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.
Files changed (117) hide show
  1. pptx/__init__.py +84 -0
  2. pptx/action.py +270 -0
  3. pptx/api.py +49 -0
  4. pptx/chart/__init__.py +0 -0
  5. pptx/chart/axis.py +523 -0
  6. pptx/chart/category.py +200 -0
  7. pptx/chart/chart.py +280 -0
  8. pptx/chart/data.py +864 -0
  9. pptx/chart/datalabel.py +288 -0
  10. pptx/chart/legend.py +79 -0
  11. pptx/chart/marker.py +70 -0
  12. pptx/chart/plot.py +412 -0
  13. pptx/chart/point.py +101 -0
  14. pptx/chart/series.py +258 -0
  15. pptx/chart/xlsx.py +272 -0
  16. pptx/chart/xmlwriter.py +1840 -0
  17. pptx/dml/__init__.py +0 -0
  18. pptx/dml/chtfmt.py +40 -0
  19. pptx/dml/color.py +301 -0
  20. pptx/dml/effect.py +41 -0
  21. pptx/dml/fill.py +468 -0
  22. pptx/dml/line.py +100 -0
  23. pptx/enum/__init__.py +0 -0
  24. pptx/enum/action.py +71 -0
  25. pptx/enum/base.py +175 -0
  26. pptx/enum/chart.py +492 -0
  27. pptx/enum/dml.py +405 -0
  28. pptx/enum/lang.py +685 -0
  29. pptx/enum/shapes.py +1029 -0
  30. pptx/enum/text.py +371 -0
  31. pptx/exc.py +23 -0
  32. pptx/media.py +197 -0
  33. pptx/opc/__init__.py +0 -0
  34. pptx/opc/constants.py +331 -0
  35. pptx/opc/oxml.py +188 -0
  36. pptx/opc/package.py +762 -0
  37. pptx/opc/packuri.py +109 -0
  38. pptx/opc/serialized.py +296 -0
  39. pptx/opc/shared.py +20 -0
  40. pptx/opc/spec.py +44 -0
  41. pptx/oxml/__init__.py +492 -0
  42. pptx/oxml/action.py +53 -0
  43. pptx/oxml/chart/__init__.py +0 -0
  44. pptx/oxml/chart/axis.py +297 -0
  45. pptx/oxml/chart/chart.py +282 -0
  46. pptx/oxml/chart/datalabel.py +252 -0
  47. pptx/oxml/chart/legend.py +72 -0
  48. pptx/oxml/chart/marker.py +61 -0
  49. pptx/oxml/chart/plot.py +345 -0
  50. pptx/oxml/chart/series.py +254 -0
  51. pptx/oxml/chart/shared.py +219 -0
  52. pptx/oxml/coreprops.py +288 -0
  53. pptx/oxml/dml/__init__.py +0 -0
  54. pptx/oxml/dml/color.py +111 -0
  55. pptx/oxml/dml/fill.py +197 -0
  56. pptx/oxml/dml/line.py +12 -0
  57. pptx/oxml/ns.py +129 -0
  58. pptx/oxml/presentation.py +130 -0
  59. pptx/oxml/shapes/__init__.py +19 -0
  60. pptx/oxml/shapes/autoshape.py +455 -0
  61. pptx/oxml/shapes/connector.py +107 -0
  62. pptx/oxml/shapes/graphfrm.py +342 -0
  63. pptx/oxml/shapes/groupshape.py +280 -0
  64. pptx/oxml/shapes/picture.py +270 -0
  65. pptx/oxml/shapes/shared.py +523 -0
  66. pptx/oxml/simpletypes.py +740 -0
  67. pptx/oxml/slide.py +347 -0
  68. pptx/oxml/table.py +588 -0
  69. pptx/oxml/text.py +748 -0
  70. pptx/oxml/theme.py +29 -0
  71. pptx/oxml/xmlchemy.py +717 -0
  72. pptx/package.py +222 -0
  73. pptx/parts/__init__.py +0 -0
  74. pptx/parts/chart.py +95 -0
  75. pptx/parts/coreprops.py +167 -0
  76. pptx/parts/embeddedpackage.py +93 -0
  77. pptx/parts/image.py +275 -0
  78. pptx/parts/media.py +37 -0
  79. pptx/parts/presentation.py +126 -0
  80. pptx/parts/slide.py +297 -0
  81. pptx/parts/theme.py +13 -0
  82. pptx/presentation.py +113 -0
  83. pptx/py.typed +0 -0
  84. pptx/shapes/__init__.py +26 -0
  85. pptx/shapes/autoshape.py +355 -0
  86. pptx/shapes/base.py +293 -0
  87. pptx/shapes/connector.py +297 -0
  88. pptx/shapes/freeform.py +337 -0
  89. pptx/shapes/graphfrm.py +166 -0
  90. pptx/shapes/group.py +69 -0
  91. pptx/shapes/picture.py +203 -0
  92. pptx/shapes/placeholder.py +407 -0
  93. pptx/shapes/shapetree.py +1190 -0
  94. pptx/shared.py +82 -0
  95. pptx/slide.py +577 -0
  96. pptx/spec.py +632 -0
  97. pptx/table.py +520 -0
  98. pptx/templates/default.pptx +0 -0
  99. pptx/templates/docx-icon.emf +0 -0
  100. pptx/templates/generic-icon.emf +0 -0
  101. pptx/templates/notes.xml +23 -0
  102. pptx/templates/notesMaster.xml +352 -0
  103. pptx/templates/pptx-icon.emf +0 -0
  104. pptx/templates/theme.xml +321 -0
  105. pptx/templates/xlsx-icon.emf +0 -0
  106. pptx/text/__init__.py +0 -0
  107. pptx/text/fonts.py +399 -0
  108. pptx/text/layout.py +325 -0
  109. pptx/text/text.py +770 -0
  110. pptx/theme.py +135 -0
  111. pptx/types.py +36 -0
  112. pptx/util.py +284 -0
  113. ps_python_pptx-1.1.0.dist-info/METADATA +75 -0
  114. ps_python_pptx-1.1.0.dist-info/RECORD +117 -0
  115. ps_python_pptx-1.1.0.dist-info/WHEEL +5 -0
  116. ps_python_pptx-1.1.0.dist-info/licenses/LICENSE +20 -0
  117. ps_python_pptx-1.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,523 @@
1
+ """Common shape-related oxml objects."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Callable
6
+
7
+ from pptx.dml.fill import CT_GradientFillProperties
8
+ from pptx.enum.shapes import PP_PLACEHOLDER
9
+ from pptx.oxml.ns import qn
10
+ from pptx.oxml.simpletypes import (
11
+ ST_Angle,
12
+ ST_Coordinate,
13
+ ST_Direction,
14
+ ST_DrawingElementId,
15
+ ST_LineWidth,
16
+ ST_PlaceholderSize,
17
+ ST_PositiveCoordinate,
18
+ XsdBoolean,
19
+ XsdString,
20
+ XsdUnsignedInt,
21
+ )
22
+ from pptx.oxml.xmlchemy import (
23
+ BaseOxmlElement,
24
+ Choice,
25
+ OptionalAttribute,
26
+ OxmlElement,
27
+ RequiredAttribute,
28
+ ZeroOrOne,
29
+ ZeroOrOneChoice,
30
+ )
31
+ from pptx.util import Emu
32
+
33
+ if TYPE_CHECKING:
34
+ from pptx.oxml.action import CT_Hyperlink
35
+ from pptx.oxml.shapes.autoshape import CT_CustomGeometry2D, CT_PresetGeometry2D
36
+ from pptx.util import Length
37
+
38
+
39
+ class BaseShapeElement(BaseOxmlElement):
40
+ """Provides common behavior for shape element classes like CT_Shape, CT_Picture, etc."""
41
+
42
+ spPr: CT_ShapeProperties
43
+
44
+ @property
45
+ def cx(self) -> Length:
46
+ return self._get_xfrm_attr("cx")
47
+
48
+ @cx.setter
49
+ def cx(self, value):
50
+ self._set_xfrm_attr("cx", value)
51
+
52
+ @property
53
+ def cy(self) -> Length:
54
+ return self._get_xfrm_attr("cy")
55
+
56
+ @cy.setter
57
+ def cy(self, value):
58
+ self._set_xfrm_attr("cy", value)
59
+
60
+ @property
61
+ def flipH(self):
62
+ return bool(self._get_xfrm_attr("flipH"))
63
+
64
+ @flipH.setter
65
+ def flipH(self, value):
66
+ self._set_xfrm_attr("flipH", value)
67
+
68
+ @property
69
+ def flipV(self):
70
+ return bool(self._get_xfrm_attr("flipV"))
71
+
72
+ @flipV.setter
73
+ def flipV(self, value):
74
+ self._set_xfrm_attr("flipV", value)
75
+
76
+ def get_or_add_xfrm(self):
77
+ """Return the `a:xfrm` grandchild element, newly-added if not present.
78
+
79
+ This version works for `p:sp`, `p:cxnSp`, and `p:pic` elements, others will need to
80
+ override.
81
+ """
82
+ return self.spPr.get_or_add_xfrm()
83
+
84
+ @property
85
+ def has_ph_elm(self):
86
+ """
87
+ True if this shape element has a `p:ph` descendant, indicating it
88
+ is a placeholder shape. False otherwise.
89
+ """
90
+ return self.ph is not None
91
+
92
+ @property
93
+ def ph(self) -> CT_Placeholder | None:
94
+ """The `p:ph` descendant element if there is one, None otherwise."""
95
+ ph_elms = self.xpath("./*[1]/p:nvPr/p:ph")
96
+ if len(ph_elms) == 0:
97
+ return None
98
+ return ph_elms[0]
99
+
100
+ @property
101
+ def ph_idx(self) -> int:
102
+ """Integer value of placeholder idx attribute.
103
+
104
+ Raises |ValueError| if shape is not a placeholder.
105
+ """
106
+ ph = self.ph
107
+ if ph is None:
108
+ raise ValueError("not a placeholder shape")
109
+ return ph.idx
110
+
111
+ @property
112
+ def ph_orient(self) -> str:
113
+ """Placeholder orientation, e.g. 'vert'.
114
+
115
+ Raises |ValueError| if shape is not a placeholder.
116
+ """
117
+ ph = self.ph
118
+ if ph is None:
119
+ raise ValueError("not a placeholder shape")
120
+ return ph.orient
121
+
122
+ @property
123
+ def ph_sz(self) -> str:
124
+ """Placeholder size, e.g. ST_PlaceholderSize.HALF.
125
+
126
+ Raises `ValueError` if shape is not a placeholder.
127
+ """
128
+ ph = self.ph
129
+ if ph is None:
130
+ raise ValueError("not a placeholder shape")
131
+ return ph.sz
132
+
133
+ @property
134
+ def ph_type(self):
135
+ """Placeholder type, e.g. ST_PlaceholderType.TITLE ('title').
136
+
137
+ Raises `ValueError` if shape is not a placeholder.
138
+ """
139
+ ph = self.ph
140
+ if ph is None:
141
+ raise ValueError("not a placeholder shape")
142
+ return ph.type
143
+
144
+ @property
145
+ def rot(self) -> float:
146
+ """Float representing degrees this shape is rotated clockwise."""
147
+ xfrm = self.xfrm
148
+ if xfrm is None or xfrm.rot is None:
149
+ return 0.0
150
+ return xfrm.rot
151
+
152
+ @rot.setter
153
+ def rot(self, value: float):
154
+ self.get_or_add_xfrm().rot = value
155
+
156
+ @property
157
+ def shape_id(self):
158
+ """
159
+ Integer id of this shape
160
+ """
161
+ return self._nvXxPr.cNvPr.id
162
+
163
+ @property
164
+ def shape_name(self):
165
+ """
166
+ Name of this shape
167
+ """
168
+ return self._nvXxPr.cNvPr.name
169
+
170
+ @property
171
+ def txBody(self):
172
+ """Child `p:txBody` element, None if not present."""
173
+ return self.find(qn("p:txBody"))
174
+
175
+ @property
176
+ def x(self) -> Length:
177
+ return self._get_xfrm_attr("x")
178
+
179
+ @x.setter
180
+ def x(self, value):
181
+ self._set_xfrm_attr("x", value)
182
+
183
+ @property
184
+ def xfrm(self):
185
+ """The `a:xfrm` grandchild element or |None| if not found.
186
+
187
+ This version works for `p:sp`, `p:cxnSp`, and `p:pic` elements, others will need to
188
+ override.
189
+ """
190
+ return self.spPr.xfrm
191
+
192
+ @property
193
+ def y(self) -> Length:
194
+ return self._get_xfrm_attr("y")
195
+
196
+ @y.setter
197
+ def y(self, value):
198
+ self._set_xfrm_attr("y", value)
199
+
200
+ @property
201
+ def _nvXxPr(self):
202
+ """
203
+ Required non-visual shape properties element for this shape. Actual
204
+ name depends on the shape type, e.g. `p:nvPicPr` for picture
205
+ shape.
206
+ """
207
+ return self.xpath("./*[1]")[0]
208
+
209
+ def _get_xfrm_attr(self, name: str) -> Length | None:
210
+ xfrm = self.xfrm
211
+ if xfrm is None:
212
+ return None
213
+ return getattr(xfrm, name)
214
+
215
+ def _set_xfrm_attr(self, name, value):
216
+ xfrm = self.get_or_add_xfrm()
217
+ setattr(xfrm, name, value)
218
+
219
+
220
+ class CT_ApplicationNonVisualDrawingProps(BaseOxmlElement):
221
+ """`p:nvPr` element."""
222
+
223
+ get_or_add_ph: Callable[[], CT_Placeholder]
224
+
225
+ ph = ZeroOrOne(
226
+ "p:ph",
227
+ successors=(
228
+ "a:audioCd",
229
+ "a:wavAudioFile",
230
+ "a:audioFile",
231
+ "a:videoFile",
232
+ "a:quickTimeFile",
233
+ "p:custDataLst",
234
+ "p:extLst",
235
+ ),
236
+ )
237
+
238
+
239
+ class CT_LineProperties(BaseOxmlElement):
240
+ """Custom element class for <a:ln> element"""
241
+
242
+ _tag_seq = (
243
+ "a:noFill",
244
+ "a:solidFill",
245
+ "a:gradFill",
246
+ "a:pattFill",
247
+ "a:prstDash",
248
+ "a:custDash",
249
+ "a:round",
250
+ "a:bevel",
251
+ "a:miter",
252
+ "a:headEnd",
253
+ "a:tailEnd",
254
+ "a:extLst",
255
+ )
256
+ eg_lineFillProperties = ZeroOrOneChoice(
257
+ (
258
+ Choice("a:noFill"),
259
+ Choice("a:solidFill"),
260
+ Choice("a:gradFill"),
261
+ Choice("a:pattFill"),
262
+ ),
263
+ successors=_tag_seq[4:],
264
+ )
265
+ prstDash = ZeroOrOne("a:prstDash", successors=_tag_seq[5:])
266
+ custDash = ZeroOrOne("a:custDash", successors=_tag_seq[6:])
267
+ del _tag_seq
268
+ w = OptionalAttribute("w", ST_LineWidth, default=Emu(0))
269
+
270
+ @property
271
+ def eg_fillProperties(self):
272
+ """
273
+ Required to fulfill the interface used by dml.fill.
274
+ """
275
+ return self.eg_lineFillProperties
276
+
277
+ @property
278
+ def prstDash_val(self):
279
+ """Return value of `val` attribute of `a:prstDash` child.
280
+
281
+ Return |None| if not present.
282
+ """
283
+ prstDash = self.prstDash
284
+ if prstDash is None:
285
+ return None
286
+ return prstDash.val
287
+
288
+ @prstDash_val.setter
289
+ def prstDash_val(self, val):
290
+ self._remove_custDash()
291
+ prstDash = self.get_or_add_prstDash()
292
+ prstDash.val = val
293
+
294
+
295
+ class CT_NonVisualDrawingProps(BaseOxmlElement):
296
+ """`p:cNvPr` custom element class."""
297
+
298
+ get_or_add_hlinkClick: Callable[[], CT_Hyperlink]
299
+ get_or_add_hlinkHover: Callable[[], CT_Hyperlink]
300
+
301
+ _tag_seq = ("a:hlinkClick", "a:hlinkHover", "a:extLst")
302
+ hlinkClick: CT_Hyperlink | None = ZeroOrOne("a:hlinkClick", successors=_tag_seq[1:])
303
+ hlinkHover: CT_Hyperlink | None = ZeroOrOne("a:hlinkHover", successors=_tag_seq[2:])
304
+ id = RequiredAttribute("id", ST_DrawingElementId)
305
+ name = RequiredAttribute("name", XsdString)
306
+ del _tag_seq
307
+
308
+
309
+ class CT_Placeholder(BaseOxmlElement):
310
+ """`p:ph` custom element class."""
311
+
312
+ type: PP_PLACEHOLDER = OptionalAttribute( # pyright: ignore[reportAssignmentType]
313
+ "type", PP_PLACEHOLDER, default=PP_PLACEHOLDER.OBJECT
314
+ )
315
+ orient: str = OptionalAttribute( # pyright: ignore[reportAssignmentType]
316
+ "orient", ST_Direction, default=ST_Direction.HORZ
317
+ )
318
+ sz: str = OptionalAttribute( # pyright: ignore[reportAssignmentType]
319
+ "sz", ST_PlaceholderSize, default=ST_PlaceholderSize.FULL
320
+ )
321
+ idx: int = OptionalAttribute( # pyright: ignore[reportAssignmentType]
322
+ "idx", XsdUnsignedInt, default=0
323
+ )
324
+
325
+
326
+ class CT_Point2D(BaseOxmlElement):
327
+ """
328
+ Custom element class for <a:off> element.
329
+ """
330
+
331
+ x: Length = RequiredAttribute("x", ST_Coordinate) # pyright: ignore[reportAssignmentType]
332
+ y: Length = RequiredAttribute("y", ST_Coordinate) # pyright: ignore[reportAssignmentType]
333
+
334
+
335
+ class CT_PositiveSize2D(BaseOxmlElement):
336
+ """
337
+ Custom element class for <a:ext> element.
338
+ """
339
+
340
+ cx = RequiredAttribute("cx", ST_PositiveCoordinate)
341
+ cy = RequiredAttribute("cy", ST_PositiveCoordinate)
342
+
343
+
344
+ class CT_ShapeProperties(BaseOxmlElement):
345
+ """Custom element class for `p:spPr` element.
346
+
347
+ Shared by `p:sp`, `p:cxnSp`, and `p:pic` elements as well as a few more obscure ones.
348
+ """
349
+
350
+ get_or_add_xfrm: Callable[[], CT_Transform2D]
351
+ get_or_add_ln: Callable[[], CT_LineProperties]
352
+ _add_prstGeom: Callable[[], CT_PresetGeometry2D]
353
+ _remove_custGeom: Callable[[], None]
354
+
355
+ _tag_seq = (
356
+ "a:xfrm",
357
+ "a:custGeom",
358
+ "a:prstGeom",
359
+ "a:noFill",
360
+ "a:solidFill",
361
+ "a:gradFill",
362
+ "a:blipFill",
363
+ "a:pattFill",
364
+ "a:grpFill",
365
+ "a:ln",
366
+ "a:effectLst",
367
+ "a:effectDag",
368
+ "a:scene3d",
369
+ "a:sp3d",
370
+ "a:extLst",
371
+ )
372
+ xfrm: CT_Transform2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
373
+ "a:xfrm", successors=_tag_seq[1:]
374
+ )
375
+ custGeom: CT_CustomGeometry2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
376
+ "a:custGeom", successors=_tag_seq[2:]
377
+ )
378
+ prstGeom: CT_PresetGeometry2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
379
+ "a:prstGeom", successors=_tag_seq[3:]
380
+ )
381
+ eg_fillProperties = ZeroOrOneChoice(
382
+ (
383
+ Choice("a:noFill"),
384
+ Choice("a:solidFill"),
385
+ Choice("a:gradFill"),
386
+ Choice("a:blipFill"),
387
+ Choice("a:pattFill"),
388
+ Choice("a:grpFill"),
389
+ ),
390
+ successors=_tag_seq[9:],
391
+ )
392
+ ln: CT_LineProperties | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
393
+ "a:ln", successors=_tag_seq[10:]
394
+ )
395
+ effectLst = ZeroOrOne("a:effectLst", successors=_tag_seq[11:])
396
+ del _tag_seq
397
+
398
+ @property
399
+ def cx(self):
400
+ """
401
+ Shape width as an instance of Emu, or None if not present.
402
+ """
403
+ cx_str_lst = self.xpath("./a:xfrm/a:ext/@cx")
404
+ if not cx_str_lst:
405
+ return None
406
+ return Emu(cx_str_lst[0])
407
+
408
+ @property
409
+ def cy(self):
410
+ """
411
+ Shape height as an instance of Emu, or None if not present.
412
+ """
413
+ cy_str_lst = self.xpath("./a:xfrm/a:ext/@cy")
414
+ if not cy_str_lst:
415
+ return None
416
+ return Emu(cy_str_lst[0])
417
+
418
+ @property
419
+ def x(self) -> Length | None:
420
+ """Distance between the left edge of the slide and left edge of the shape.
421
+
422
+ 0 if not present.
423
+ """
424
+ x_str_lst = self.xpath("./a:xfrm/a:off/@x")
425
+ if not x_str_lst:
426
+ return None
427
+ return Emu(x_str_lst[0])
428
+
429
+ @property
430
+ def y(self):
431
+ """
432
+ The offset of the top of the shape from the top of the slide, as an
433
+ instance of Emu. None if not present.
434
+ """
435
+ y_str_lst = self.xpath("./a:xfrm/a:off/@y")
436
+ if not y_str_lst:
437
+ return None
438
+ return Emu(y_str_lst[0])
439
+
440
+ def _new_gradFill(self):
441
+ return CT_GradientFillProperties.new_gradFill()
442
+
443
+
444
+ class CT_Transform2D(BaseOxmlElement):
445
+ """`a:xfrm` custom element class.
446
+
447
+ NOTE: this is a composite including CT_GroupTransform2D, which appears
448
+ with the `a:xfrm` tag in a group shape (including a slide `p:spTree`).
449
+ """
450
+
451
+ _tag_seq = ("a:off", "a:ext", "a:chOff", "a:chExt")
452
+ off: CT_Point2D | None = ZeroOrOne( # pyright: ignore[reportAssignmentType]
453
+ "a:off", successors=_tag_seq[1:]
454
+ )
455
+ ext = ZeroOrOne("a:ext", successors=_tag_seq[2:])
456
+ chOff = ZeroOrOne("a:chOff", successors=_tag_seq[3:])
457
+ chExt = ZeroOrOne("a:chExt", successors=_tag_seq[4:])
458
+ del _tag_seq
459
+ rot: float | None = OptionalAttribute( # pyright: ignore[reportAssignmentType]
460
+ "rot", ST_Angle, default=0.0
461
+ )
462
+ flipH = OptionalAttribute("flipH", XsdBoolean, default=False)
463
+ flipV = OptionalAttribute("flipV", XsdBoolean, default=False)
464
+
465
+ @property
466
+ def x(self):
467
+ off = self.off
468
+ if off is None:
469
+ return None
470
+ return off.x
471
+
472
+ @x.setter
473
+ def x(self, value):
474
+ off = self.get_or_add_off()
475
+ off.x = value
476
+
477
+ @property
478
+ def y(self):
479
+ off = self.off
480
+ if off is None:
481
+ return None
482
+ return off.y
483
+
484
+ @y.setter
485
+ def y(self, value):
486
+ off = self.get_or_add_off()
487
+ off.y = value
488
+
489
+ @property
490
+ def cx(self):
491
+ ext = self.ext
492
+ if ext is None:
493
+ return None
494
+ return ext.cx
495
+
496
+ @cx.setter
497
+ def cx(self, value):
498
+ ext = self.get_or_add_ext()
499
+ ext.cx = value
500
+
501
+ @property
502
+ def cy(self):
503
+ ext = self.ext
504
+ if ext is None:
505
+ return None
506
+ return ext.cy
507
+
508
+ @cy.setter
509
+ def cy(self, value):
510
+ ext = self.get_or_add_ext()
511
+ ext.cy = value
512
+
513
+ def _new_ext(self):
514
+ ext = OxmlElement("a:ext")
515
+ ext.cx = 0
516
+ ext.cy = 0
517
+ return ext
518
+
519
+ def _new_off(self):
520
+ off = OxmlElement("a:off")
521
+ off.x = 0
522
+ off.y = 0
523
+ return off