python-pptx2 2.13.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.
- pptx2/__init__.py +152 -0
- pptx2/_color.py +75 -0
- pptx2/_slide_importer.py +597 -0
- pptx2/_svg.py +155 -0
- pptx2/_template_applier.py +292 -0
- pptx2/_textstyle.py +187 -0
- pptx2/accessibility.py +365 -0
- pptx2/action.py +270 -0
- pptx2/animation.py +2237 -0
- pptx2/api.py +49 -0
- pptx2/audit.py +258 -0
- pptx2/chart/__init__.py +0 -0
- pptx2/chart/analytics.py +381 -0
- pptx2/chart/axis.py +543 -0
- pptx2/chart/category.py +200 -0
- pptx2/chart/chart.py +670 -0
- pptx2/chart/data.py +864 -0
- pptx2/chart/datalabel.py +406 -0
- pptx2/chart/legend.py +86 -0
- pptx2/chart/marker.py +70 -0
- pptx2/chart/palettes.py +129 -0
- pptx2/chart/plot.py +462 -0
- pptx2/chart/point.py +101 -0
- pptx2/chart/quick_layouts.py +325 -0
- pptx2/chart/series.py +334 -0
- pptx2/chart/xlsx.py +272 -0
- pptx2/chart/xmlwriter.py +1845 -0
- pptx2/compose/__init__.py +28 -0
- pptx2/compose/from_spec.py +1094 -0
- pptx2/design/__init__.py +8 -0
- pptx2/design/components.py +607 -0
- pptx2/design/figures.py +389 -0
- pptx2/design/layout.py +370 -0
- pptx2/design/recipes.py +1967 -0
- pptx2/design/style.py +209 -0
- pptx2/design/tokens.py +915 -0
- pptx2/diagrams.py +754 -0
- pptx2/dml/__init__.py +0 -0
- pptx2/dml/chtfmt.py +40 -0
- pptx2/dml/color.py +496 -0
- pptx2/dml/effect.py +909 -0
- pptx2/dml/fill.py +691 -0
- pptx2/dml/line.py +287 -0
- pptx2/dml/picture.py +212 -0
- pptx2/dml/three_d.py +381 -0
- pptx2/enum/__init__.py +0 -0
- pptx2/enum/action.py +71 -0
- pptx2/enum/animation.py +31 -0
- pptx2/enum/base.py +218 -0
- pptx2/enum/chart.py +574 -0
- pptx2/enum/dml.py +740 -0
- pptx2/enum/lang.py +685 -0
- pptx2/enum/presentation.py +133 -0
- pptx2/enum/shapes.py +1029 -0
- pptx2/enum/text.py +230 -0
- pptx2/exc.py +42 -0
- pptx2/formats.py +139 -0
- pptx2/geometry.py +420 -0
- pptx2/inherit.py +109 -0
- pptx2/lint.py +2256 -0
- pptx2/math.py +177 -0
- pptx2/media.py +197 -0
- pptx2/opc/__init__.py +0 -0
- pptx2/opc/constants.py +332 -0
- pptx2/opc/oxml.py +188 -0
- pptx2/opc/package.py +762 -0
- pptx2/opc/packuri.py +109 -0
- pptx2/opc/serialized.py +296 -0
- pptx2/opc/shared.py +20 -0
- pptx2/opc/spec.py +45 -0
- pptx2/oxml/__init__.py +555 -0
- pptx2/oxml/action.py +53 -0
- pptx2/oxml/chart/__init__.py +0 -0
- pptx2/oxml/chart/axis.py +337 -0
- pptx2/oxml/chart/chart.py +481 -0
- pptx2/oxml/chart/datalabel.py +253 -0
- pptx2/oxml/chart/legend.py +72 -0
- pptx2/oxml/chart/marker.py +61 -0
- pptx2/oxml/chart/plot.py +365 -0
- pptx2/oxml/chart/series.py +425 -0
- pptx2/oxml/chart/shared.py +220 -0
- pptx2/oxml/coreprops.py +288 -0
- pptx2/oxml/dml/__init__.py +0 -0
- pptx2/oxml/dml/color.py +135 -0
- pptx2/oxml/dml/effect.py +213 -0
- pptx2/oxml/dml/fill.py +316 -0
- pptx2/oxml/dml/line.py +12 -0
- pptx2/oxml/dml/three_d.py +110 -0
- pptx2/oxml/ns.py +135 -0
- pptx2/oxml/presentation.py +313 -0
- pptx2/oxml/shapes/__init__.py +19 -0
- pptx2/oxml/shapes/autoshape.py +467 -0
- pptx2/oxml/shapes/connector.py +107 -0
- pptx2/oxml/shapes/graphfrm.py +347 -0
- pptx2/oxml/shapes/groupshape.py +329 -0
- pptx2/oxml/shapes/picture.py +270 -0
- pptx2/oxml/shapes/shared.py +577 -0
- pptx2/oxml/simpletypes.py +1027 -0
- pptx2/oxml/slide.py +563 -0
- pptx2/oxml/table.py +650 -0
- pptx2/oxml/text.py +815 -0
- pptx2/oxml/theme.py +36 -0
- pptx2/oxml/xmlchemy.py +717 -0
- pptx2/package.py +222 -0
- pptx2/parts/__init__.py +0 -0
- pptx2/parts/chart.py +95 -0
- pptx2/parts/coreprops.py +167 -0
- pptx2/parts/diagram.py +37 -0
- pptx2/parts/embeddedpackage.py +93 -0
- pptx2/parts/image.py +275 -0
- pptx2/parts/media.py +37 -0
- pptx2/parts/presentation.py +136 -0
- pptx2/parts/slide.py +371 -0
- pptx2/presentation.py +408 -0
- pptx2/py.typed +0 -0
- pptx2/render.py +586 -0
- pptx2/section.py +272 -0
- pptx2/shapes/__init__.py +26 -0
- pptx2/shapes/autoshape.py +442 -0
- pptx2/shapes/base.py +1078 -0
- pptx2/shapes/connector.py +297 -0
- pptx2/shapes/freeform.py +337 -0
- pptx2/shapes/graphfrm.py +316 -0
- pptx2/shapes/group.py +264 -0
- pptx2/shapes/picture.py +422 -0
- pptx2/shapes/placeholder.py +468 -0
- pptx2/shapes/shapetree.py +2027 -0
- pptx2/shared.py +82 -0
- pptx2/skill/SKILL.md +450 -0
- pptx2/skill/__init__.py +78 -0
- pptx2/skill/__main__.py +64 -0
- pptx2/skill/references/animations.md +189 -0
- pptx2/skill/references/basics.md +421 -0
- pptx2/skill/references/charts.md +254 -0
- pptx2/skill/references/compose.md +234 -0
- pptx2/skill/references/design.md +366 -0
- pptx2/skill/references/effects.md +249 -0
- pptx2/skill/references/end-to-end-deck.md +231 -0
- pptx2/skill/references/geometry-and-arrows.md +334 -0
- pptx2/skill/references/lint.md +275 -0
- pptx2/skill/references/math.md +86 -0
- pptx2/skill/references/picture-effects.md +129 -0
- pptx2/skill/references/render.md +151 -0
- pptx2/skill/references/smart-art.md +75 -0
- pptx2/skill/references/space-aware-authoring.md +249 -0
- pptx2/skill/references/tables.md +244 -0
- pptx2/skill/references/theme.md +127 -0
- pptx2/skill/references/three-d.md +109 -0
- pptx2/skill/references/transitions.md +100 -0
- pptx2/slide.py +1244 -0
- pptx2/smart_art.py +220 -0
- pptx2/spec.py +633 -0
- pptx2/table.py +1181 -0
- pptx2/table_styles.py +184 -0
- pptx2/templates/default.pptx +0 -0
- pptx2/templates/docx-icon.emf +0 -0
- pptx2/templates/generic-icon.emf +0 -0
- pptx2/templates/notes.xml +23 -0
- pptx2/templates/notesMaster.xml +352 -0
- pptx2/templates/pptx-icon.emf +0 -0
- pptx2/templates/theme.xml +321 -0
- pptx2/templates/xlsx-icon.emf +0 -0
- pptx2/text/__init__.py +0 -0
- pptx2/text/fonts.py +482 -0
- pptx2/text/layout.py +374 -0
- pptx2/text/text.py +1272 -0
- pptx2/theme.py +721 -0
- pptx2/types.py +36 -0
- pptx2/util.py +263 -0
- python_pptx2-2.13.0.dist-info/METADATA +351 -0
- python_pptx2-2.13.0.dist-info/RECORD +175 -0
- python_pptx2-2.13.0.dist-info/WHEEL +5 -0
- python_pptx2-2.13.0.dist-info/entry_points.txt +3 -0
- python_pptx2-2.13.0.dist-info/licenses/LICENSE +22 -0
- python_pptx2-2.13.0.dist-info/top_level.txt +1 -0
pptx2/dml/__init__.py
ADDED
|
File without changes
|
pptx2/dml/chtfmt.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""|ChartFormat| and related objects.
|
|
2
|
+
|
|
3
|
+
|ChartFormat| acts as proxy for the `spPr` element, which provides visual shape properties such as
|
|
4
|
+
line and fill for chart elements.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pptx2.dml.fill import FillFormat
|
|
10
|
+
from pptx2.dml.line import LineFormat
|
|
11
|
+
from pptx2.shared import ElementProxy
|
|
12
|
+
from pptx2.util import lazyproperty
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ChartFormat(ElementProxy):
|
|
16
|
+
"""
|
|
17
|
+
The |ChartFormat| object provides access to visual shape properties for
|
|
18
|
+
chart elements like |Axis|, |Series|, and |MajorGridlines|. It has two
|
|
19
|
+
properties, :attr:`fill` and :attr:`line`, which return a |FillFormat|
|
|
20
|
+
and |LineFormat| object respectively. The |ChartFormat| object is
|
|
21
|
+
provided by the :attr:`format` property on the target axis, series, etc.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@lazyproperty
|
|
25
|
+
def fill(self):
|
|
26
|
+
"""
|
|
27
|
+
|FillFormat| instance for this object, providing access to fill
|
|
28
|
+
properties such as fill color.
|
|
29
|
+
"""
|
|
30
|
+
spPr = self._element.get_or_add_spPr()
|
|
31
|
+
return FillFormat.from_fill_parent(spPr)
|
|
32
|
+
|
|
33
|
+
@lazyproperty
|
|
34
|
+
def line(self):
|
|
35
|
+
"""
|
|
36
|
+
The |LineFormat| object providing access to the visual properties of
|
|
37
|
+
this object, such as line color and line style.
|
|
38
|
+
"""
|
|
39
|
+
spPr = self._element.get_or_add_spPr()
|
|
40
|
+
return LineFormat(spPr)
|
pptx2/dml/color.py
ADDED
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"""DrawingML objects related to color, ColorFormat being the most prominent."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Callable
|
|
6
|
+
|
|
7
|
+
from pptx2.enum.dml import MSO_COLOR_TYPE, MSO_FILL, MSO_THEME_COLOR
|
|
8
|
+
from pptx2.oxml.dml.color import (
|
|
9
|
+
CT_HslColor,
|
|
10
|
+
CT_PresetColor,
|
|
11
|
+
CT_SchemeColor,
|
|
12
|
+
CT_ScRgbColor,
|
|
13
|
+
CT_SRgbColor,
|
|
14
|
+
CT_SystemColor,
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from pptx2.dml.fill import FillFormat
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ColorFormat(object):
|
|
22
|
+
"""
|
|
23
|
+
Provides access to color settings such as RGB color, theme color, and
|
|
24
|
+
luminance adjustments.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, eg_colorChoice_parent, color):
|
|
28
|
+
super(ColorFormat, self).__init__()
|
|
29
|
+
self._xFill = eg_colorChoice_parent
|
|
30
|
+
self._color = color
|
|
31
|
+
|
|
32
|
+
@property
|
|
33
|
+
def alpha(self):
|
|
34
|
+
"""Read/write float in [0.0, 1.0] giving the per-color alpha.
|
|
35
|
+
|
|
36
|
+
`1.0` is fully opaque (the default when no `<a:alpha>` element is
|
|
37
|
+
present); `0.0` is fully transparent. Maps to the `<a:alpha>` child of
|
|
38
|
+
the underlying color element. Assigning |None| removes any explicit
|
|
39
|
+
alpha, restoring full opacity.
|
|
40
|
+
"""
|
|
41
|
+
return self._color.alpha
|
|
42
|
+
|
|
43
|
+
@alpha.setter
|
|
44
|
+
def alpha(self, value):
|
|
45
|
+
if isinstance(self._color, _NoneColor):
|
|
46
|
+
raise ValueError(
|
|
47
|
+
"can't set alpha when color.type is None."
|
|
48
|
+
" Set color.rgb or .theme_color first."
|
|
49
|
+
)
|
|
50
|
+
if value is not None:
|
|
51
|
+
self._validate_alpha_value(value)
|
|
52
|
+
self._color.alpha = value
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def brightness(self):
|
|
56
|
+
"""
|
|
57
|
+
Read/write float value between -1.0 and 1.0 indicating the brightness
|
|
58
|
+
adjustment for this color, e.g. -0.25 is 25% darker and 0.4 is 40%
|
|
59
|
+
lighter. 0 means no brightness adjustment.
|
|
60
|
+
"""
|
|
61
|
+
return self._color.brightness
|
|
62
|
+
|
|
63
|
+
@brightness.setter
|
|
64
|
+
def brightness(self, value):
|
|
65
|
+
self._validate_brightness_value(value)
|
|
66
|
+
self._color.brightness = value
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def from_colorchoice_parent(cls, eg_colorChoice_parent):
|
|
70
|
+
xClr = eg_colorChoice_parent.eg_colorChoice
|
|
71
|
+
color = _Color(xClr)
|
|
72
|
+
color_format = cls(eg_colorChoice_parent, color)
|
|
73
|
+
return color_format
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def rgb(self):
|
|
77
|
+
"""
|
|
78
|
+
|RGBColor| value of this color, or None if no RGB color is explicitly
|
|
79
|
+
defined for this font. Setting this value to an |RGBColor| instance
|
|
80
|
+
causes its type to change to MSO_COLOR_TYPE.RGB. If the color was a
|
|
81
|
+
theme color with a brightness adjustment, the brightness adjustment
|
|
82
|
+
is removed when changing it to an RGB color.
|
|
83
|
+
"""
|
|
84
|
+
return self._color.rgb
|
|
85
|
+
|
|
86
|
+
@rgb.setter
|
|
87
|
+
def rgb(self, rgb):
|
|
88
|
+
# Accept any documented "color-like" value (RGBColor, '#RRGGBB' hex
|
|
89
|
+
# string with or without '#', or 3-tuple of ints). Historically
|
|
90
|
+
# this setter required RGBColor — leaving callers with a category
|
|
91
|
+
# of "did the wrong source surface accept hex?" footgun.
|
|
92
|
+
from pptx2._color import coerce_color
|
|
93
|
+
|
|
94
|
+
if not isinstance(rgb, RGBColor):
|
|
95
|
+
try:
|
|
96
|
+
rgb = coerce_color(rgb)
|
|
97
|
+
except (TypeError, ValueError) as exc:
|
|
98
|
+
# Preserve the historical exception type for callers that
|
|
99
|
+
# caught ValueError.
|
|
100
|
+
raise ValueError(str(exc)) from exc
|
|
101
|
+
# change to rgb color format if not already
|
|
102
|
+
if not isinstance(self._color, _SRgbColor):
|
|
103
|
+
srgbClr = self._xFill.get_or_change_to_srgbClr()
|
|
104
|
+
self._color = _SRgbColor(srgbClr)
|
|
105
|
+
# call _SRgbColor instance to do the setting
|
|
106
|
+
self._color.rgb = rgb
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def theme_color(self):
|
|
110
|
+
"""Theme color value of this color.
|
|
111
|
+
|
|
112
|
+
Value is a member of :ref:`MsoThemeColorIndex`, e.g.
|
|
113
|
+
``MSO_THEME_COLOR.ACCENT_1``. Raises AttributeError on access if the
|
|
114
|
+
color is not type ``MSO_COLOR_TYPE.SCHEME``. Assigning a member of
|
|
115
|
+
:ref:`MsoThemeColorIndex` causes the color's type to change to
|
|
116
|
+
``MSO_COLOR_TYPE.SCHEME``.
|
|
117
|
+
"""
|
|
118
|
+
return self._color.theme_color
|
|
119
|
+
|
|
120
|
+
@theme_color.setter
|
|
121
|
+
def theme_color(self, mso_theme_color_idx):
|
|
122
|
+
# change to theme color format if not already
|
|
123
|
+
if not isinstance(self._color, _SchemeColor):
|
|
124
|
+
schemeClr = self._xFill.get_or_change_to_schemeClr()
|
|
125
|
+
self._color = _SchemeColor(schemeClr)
|
|
126
|
+
self._color.theme_color = mso_theme_color_idx
|
|
127
|
+
|
|
128
|
+
@property
|
|
129
|
+
def type(self):
|
|
130
|
+
"""
|
|
131
|
+
Read-only. A value from :ref:`MsoColorType`, either RGB or SCHEME,
|
|
132
|
+
corresponding to the way this color is defined, or None if no color
|
|
133
|
+
is defined at the level of this font.
|
|
134
|
+
"""
|
|
135
|
+
return self._color.color_type
|
|
136
|
+
|
|
137
|
+
def _validate_brightness_value(self, value):
|
|
138
|
+
if value < -1.0 or value > 1.0:
|
|
139
|
+
raise ValueError("brightness must be number in range -1.0 to 1.0")
|
|
140
|
+
if isinstance(self._color, _NoneColor):
|
|
141
|
+
msg = (
|
|
142
|
+
"can't set brightness when color.type is None. Set color.rgb"
|
|
143
|
+
" or .theme_color first."
|
|
144
|
+
)
|
|
145
|
+
raise ValueError(msg)
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def _validate_alpha_value(value):
|
|
149
|
+
if value < 0.0 or value > 1.0:
|
|
150
|
+
raise ValueError("alpha must be number in range 0.0 to 1.0")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class _LazyColorFormat(ColorFormat):
|
|
154
|
+
"""Color accessor that defers solid-fill materialization until a color is assigned.
|
|
155
|
+
|
|
156
|
+
Reads (`type`, `rgb`, `theme_color`, `brightness`) on a non-solid fill return the
|
|
157
|
+
"no explicit color" sentinel without mutating the underlying XML, which preserves
|
|
158
|
+
theme inheritance. Writes to `rgb` or `theme_color` switch the fill to solid first
|
|
159
|
+
(matching the pre-fix behavior); `brightness` writes still require a color to be
|
|
160
|
+
set first and raise the original `ValueError` otherwise.
|
|
161
|
+
|
|
162
|
+
Callers supply two thunks: `peek_fill` returns the existing |FillFormat| or |None|
|
|
163
|
+
if there is none, without mutating the underlying XML; `ensure_fill` returns a
|
|
164
|
+
|FillFormat|, creating the host element if necessary (used only on write paths).
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def __init__(
|
|
168
|
+
self,
|
|
169
|
+
peek_fill: Callable[[], FillFormat | None],
|
|
170
|
+
ensure_fill: Callable[[], FillFormat],
|
|
171
|
+
):
|
|
172
|
+
# -- intentionally bypass ColorFormat.__init__: this proxy resolves the
|
|
173
|
+
# -- underlying _xFill/_color lazily through `peek_fill` / `ensure_fill`.
|
|
174
|
+
self._peek_fill = peek_fill
|
|
175
|
+
self._ensure_fill = ensure_fill
|
|
176
|
+
|
|
177
|
+
@property
|
|
178
|
+
def alpha(self) -> float:
|
|
179
|
+
cf = self._color_or_none()
|
|
180
|
+
return cf.alpha if cf is not None else 1.0
|
|
181
|
+
|
|
182
|
+
@alpha.setter
|
|
183
|
+
def alpha(self, value: float | None):
|
|
184
|
+
# -- alpha is a modifier on an existing color, not a color choice itself
|
|
185
|
+
# -- (cf. brightness). It deliberately does NOT auto-materialize a solid
|
|
186
|
+
# -- fill the way `rgb` and `theme_color` do, because "transparent
|
|
187
|
+
# -- nothing" is not a meaningful color. Set `rgb` or `theme_color` first.
|
|
188
|
+
cf = self._color_or_none()
|
|
189
|
+
if cf is None:
|
|
190
|
+
raise ValueError(
|
|
191
|
+
"can't set alpha when color.type is None."
|
|
192
|
+
" Set color.rgb or .theme_color first."
|
|
193
|
+
)
|
|
194
|
+
cf.alpha = value
|
|
195
|
+
|
|
196
|
+
@property
|
|
197
|
+
def brightness(self) -> float:
|
|
198
|
+
cf = self._color_or_none()
|
|
199
|
+
return cf.brightness if cf is not None else 0
|
|
200
|
+
|
|
201
|
+
@brightness.setter
|
|
202
|
+
def brightness(self, value: float):
|
|
203
|
+
cf = self._color_or_none()
|
|
204
|
+
if cf is None:
|
|
205
|
+
raise ValueError(
|
|
206
|
+
"can't set brightness when color.type is None."
|
|
207
|
+
" Set color.rgb or .theme_color first."
|
|
208
|
+
)
|
|
209
|
+
cf.brightness = value
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def rgb(self) -> RGBColor | None:
|
|
213
|
+
cf = self._color_or_none()
|
|
214
|
+
return cf.rgb if cf is not None else None
|
|
215
|
+
|
|
216
|
+
@rgb.setter
|
|
217
|
+
def rgb(self, value: "RGBColor | str | tuple[int, int, int]"):
|
|
218
|
+
# The downstream ColorFormat.rgb setter accepts color-like values
|
|
219
|
+
# (hex strings, 3-tuples, or RGBColor); pass through unchanged.
|
|
220
|
+
self._ensure_solid().rgb = value
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def theme_color(self) -> MSO_THEME_COLOR:
|
|
224
|
+
cf = self._color_or_none()
|
|
225
|
+
return cf.theme_color if cf is not None else MSO_THEME_COLOR.NOT_THEME_COLOR
|
|
226
|
+
|
|
227
|
+
@theme_color.setter
|
|
228
|
+
def theme_color(self, value: MSO_THEME_COLOR):
|
|
229
|
+
self._ensure_solid().theme_color = value
|
|
230
|
+
|
|
231
|
+
@property
|
|
232
|
+
def type(self) -> MSO_COLOR_TYPE | None:
|
|
233
|
+
cf = self._color_or_none()
|
|
234
|
+
return cf.type if cf is not None else None
|
|
235
|
+
|
|
236
|
+
def _color_or_none(self) -> ColorFormat | None:
|
|
237
|
+
fill = self._peek_fill()
|
|
238
|
+
if fill is None or fill.type != MSO_FILL.SOLID:
|
|
239
|
+
return None
|
|
240
|
+
return fill.fore_color
|
|
241
|
+
|
|
242
|
+
def _ensure_solid(self) -> ColorFormat:
|
|
243
|
+
fill = self._ensure_fill()
|
|
244
|
+
if fill.type != MSO_FILL.SOLID:
|
|
245
|
+
fill.solid()
|
|
246
|
+
return fill.fore_color
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
class _Color(object):
|
|
250
|
+
"""
|
|
251
|
+
Object factory for color object of the appropriate type, also the base
|
|
252
|
+
class for all color type classes such as SRgbColor.
|
|
253
|
+
"""
|
|
254
|
+
|
|
255
|
+
def __new__(cls, xClr):
|
|
256
|
+
color_cls = {
|
|
257
|
+
type(None): _NoneColor,
|
|
258
|
+
CT_HslColor: _HslColor,
|
|
259
|
+
CT_PresetColor: _PrstColor,
|
|
260
|
+
CT_SchemeColor: _SchemeColor,
|
|
261
|
+
CT_ScRgbColor: _ScRgbColor,
|
|
262
|
+
CT_SRgbColor: _SRgbColor,
|
|
263
|
+
CT_SystemColor: _SysColor,
|
|
264
|
+
}[type(xClr)]
|
|
265
|
+
return super(_Color, cls).__new__(color_cls)
|
|
266
|
+
|
|
267
|
+
def __init__(self, xClr):
|
|
268
|
+
super(_Color, self).__init__()
|
|
269
|
+
self._xClr = xClr
|
|
270
|
+
|
|
271
|
+
@property
|
|
272
|
+
def alpha(self):
|
|
273
|
+
"""Float in [0.0, 1.0]; `1.0` (fully opaque) when no `<a:alpha>` is set."""
|
|
274
|
+
alpha_elm = self._xClr.alpha
|
|
275
|
+
if alpha_elm is None:
|
|
276
|
+
return 1.0
|
|
277
|
+
return alpha_elm.val
|
|
278
|
+
|
|
279
|
+
@alpha.setter
|
|
280
|
+
def alpha(self, value):
|
|
281
|
+
self._xClr.clear_alpha()
|
|
282
|
+
if value is None or value == 1.0:
|
|
283
|
+
return
|
|
284
|
+
self._xClr.add_alpha(value)
|
|
285
|
+
|
|
286
|
+
@property
|
|
287
|
+
def brightness(self):
|
|
288
|
+
lumMod, lumOff = self._xClr.lumMod, self._xClr.lumOff
|
|
289
|
+
# a tint is lighter, a shade is darker
|
|
290
|
+
# only tints have lumOff child
|
|
291
|
+
if lumOff is not None:
|
|
292
|
+
brightness = lumOff.val
|
|
293
|
+
return brightness
|
|
294
|
+
# which leaves shades, if lumMod is present
|
|
295
|
+
if lumMod is not None:
|
|
296
|
+
brightness = lumMod.val - 1.0
|
|
297
|
+
return brightness
|
|
298
|
+
# there's no brightness adjustment if no lum{Mod|Off} elements
|
|
299
|
+
return 0
|
|
300
|
+
|
|
301
|
+
@brightness.setter
|
|
302
|
+
def brightness(self, value):
|
|
303
|
+
if value > 0:
|
|
304
|
+
self._tint(value)
|
|
305
|
+
elif value < 0:
|
|
306
|
+
self._shade(value)
|
|
307
|
+
else:
|
|
308
|
+
self._xClr.clear_lum()
|
|
309
|
+
|
|
310
|
+
@property
|
|
311
|
+
def color_type(self): # pragma: no cover
|
|
312
|
+
tmpl = ".color_type property must be implemented on %s"
|
|
313
|
+
raise NotImplementedError(tmpl % self.__class__.__name__)
|
|
314
|
+
|
|
315
|
+
@property
|
|
316
|
+
def rgb(self):
|
|
317
|
+
"""
|
|
318
|
+
Raises TypeError on access unless overridden by subclass.
|
|
319
|
+
"""
|
|
320
|
+
tmpl = "no .rgb property on color type '%s'"
|
|
321
|
+
raise AttributeError(tmpl % self.__class__.__name__)
|
|
322
|
+
|
|
323
|
+
@property
|
|
324
|
+
def theme_color(self):
|
|
325
|
+
"""
|
|
326
|
+
Raises TypeError on access unless overridden by subclass.
|
|
327
|
+
"""
|
|
328
|
+
return MSO_THEME_COLOR.NOT_THEME_COLOR
|
|
329
|
+
|
|
330
|
+
def _shade(self, value):
|
|
331
|
+
lumMod_val = 1.0 - abs(value)
|
|
332
|
+
color_elm = self._xClr.clear_lum()
|
|
333
|
+
color_elm.add_lumMod(lumMod_val)
|
|
334
|
+
|
|
335
|
+
def _tint(self, value):
|
|
336
|
+
lumOff_val = value
|
|
337
|
+
lumMod_val = 1.0 - lumOff_val
|
|
338
|
+
color_elm = self._xClr.clear_lum()
|
|
339
|
+
color_elm.add_lumMod(lumMod_val)
|
|
340
|
+
color_elm.add_lumOff(lumOff_val)
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class _HslColor(_Color):
|
|
344
|
+
@property
|
|
345
|
+
def color_type(self):
|
|
346
|
+
return MSO_COLOR_TYPE.HSL
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
class _NoneColor(_Color):
|
|
350
|
+
@property
|
|
351
|
+
def alpha(self):
|
|
352
|
+
return 1.0
|
|
353
|
+
|
|
354
|
+
@alpha.setter
|
|
355
|
+
def alpha(self, value):
|
|
356
|
+
raise AttributeError(
|
|
357
|
+
"no .alpha property on color type '%s'" % self.__class__.__name__
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
@property
|
|
361
|
+
def color_type(self):
|
|
362
|
+
return None
|
|
363
|
+
|
|
364
|
+
@property
|
|
365
|
+
def theme_color(self):
|
|
366
|
+
"""
|
|
367
|
+
Raise TypeError on attempt to access .theme_color when no color
|
|
368
|
+
choice is present.
|
|
369
|
+
"""
|
|
370
|
+
tmpl = "no .theme_color property on color type '%s'"
|
|
371
|
+
raise AttributeError(tmpl % self.__class__.__name__)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
class _PrstColor(_Color):
|
|
375
|
+
@property
|
|
376
|
+
def color_type(self):
|
|
377
|
+
return MSO_COLOR_TYPE.PRESET
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
class _SchemeColor(_Color):
|
|
381
|
+
def __init__(self, schemeClr):
|
|
382
|
+
super(_SchemeColor, self).__init__(schemeClr)
|
|
383
|
+
self._schemeClr = schemeClr
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def color_type(self):
|
|
387
|
+
return MSO_COLOR_TYPE.SCHEME
|
|
388
|
+
|
|
389
|
+
@property
|
|
390
|
+
def theme_color(self):
|
|
391
|
+
"""
|
|
392
|
+
Theme color value of this color, one of those defined in the
|
|
393
|
+
MSO_THEME_COLOR enumeration, e.g. MSO_THEME_COLOR.ACCENT_1. None if
|
|
394
|
+
no theme color is explicitly defined for this font. Setting this to a
|
|
395
|
+
value in MSO_THEME_COLOR causes the color's type to change to
|
|
396
|
+
``MSO_COLOR_TYPE.SCHEME``.
|
|
397
|
+
"""
|
|
398
|
+
return self._schemeClr.val
|
|
399
|
+
|
|
400
|
+
@theme_color.setter
|
|
401
|
+
def theme_color(self, mso_theme_color_idx):
|
|
402
|
+
self._schemeClr.val = mso_theme_color_idx
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
class _ScRgbColor(_Color):
|
|
406
|
+
@property
|
|
407
|
+
def color_type(self):
|
|
408
|
+
return MSO_COLOR_TYPE.SCRGB
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class _SRgbColor(_Color):
|
|
412
|
+
def __init__(self, srgbClr):
|
|
413
|
+
super(_SRgbColor, self).__init__(srgbClr)
|
|
414
|
+
self._srgbClr = srgbClr
|
|
415
|
+
|
|
416
|
+
@property
|
|
417
|
+
def color_type(self):
|
|
418
|
+
return MSO_COLOR_TYPE.RGB
|
|
419
|
+
|
|
420
|
+
@property
|
|
421
|
+
def rgb(self):
|
|
422
|
+
"""
|
|
423
|
+
|RGBColor| value of this color, corresponding to the value in the
|
|
424
|
+
required ``val`` attribute of the ``<a:srgbColr>`` element.
|
|
425
|
+
"""
|
|
426
|
+
return RGBColor.from_hex(self._srgbClr.val)
|
|
427
|
+
|
|
428
|
+
@rgb.setter
|
|
429
|
+
def rgb(self, rgb):
|
|
430
|
+
self._srgbClr.val = str(rgb)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
class _SysColor(_Color):
|
|
434
|
+
@property
|
|
435
|
+
def color_type(self):
|
|
436
|
+
return MSO_COLOR_TYPE.SYSTEM
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
class RGBColor(tuple):
|
|
440
|
+
"""
|
|
441
|
+
Immutable value object defining a particular RGB color.
|
|
442
|
+
"""
|
|
443
|
+
|
|
444
|
+
def __new__(cls, r, g, b):
|
|
445
|
+
msg = "RGBColor() takes three integer values 0-255"
|
|
446
|
+
for val in (r, g, b):
|
|
447
|
+
if not isinstance(val, int) or val < 0 or val > 255:
|
|
448
|
+
raise ValueError(msg)
|
|
449
|
+
return super(RGBColor, cls).__new__(cls, (r, g, b))
|
|
450
|
+
|
|
451
|
+
def __str__(self):
|
|
452
|
+
"""
|
|
453
|
+
Return a hex string rgb value, like '3C2F80'
|
|
454
|
+
"""
|
|
455
|
+
return "%02X%02X%02X" % self
|
|
456
|
+
|
|
457
|
+
@classmethod
|
|
458
|
+
def from_hex(cls, hex_str: str) -> "RGBColor":
|
|
459
|
+
"""Return a new instance from an RGB hex string, with or without a leading ``'#'``.
|
|
460
|
+
|
|
461
|
+
Accepts both ``'#3C2F80'`` and ``'3C2F80'``. Prefer this over
|
|
462
|
+
:meth:`from_string` for new code; ``from_string`` is slated for
|
|
463
|
+
removal in a future major release.
|
|
464
|
+
"""
|
|
465
|
+
if hex_str.startswith("#"):
|
|
466
|
+
hex_str = hex_str[1:]
|
|
467
|
+
# Call the underlying parser directly to avoid the
|
|
468
|
+
# ``DeprecationWarning`` emitted by ``from_string``.
|
|
469
|
+
r = int(hex_str[:2], 16)
|
|
470
|
+
g = int(hex_str[2:4], 16)
|
|
471
|
+
b = int(hex_str[4:], 16)
|
|
472
|
+
return cls(r, g, b)
|
|
473
|
+
|
|
474
|
+
@classmethod
|
|
475
|
+
def from_string(cls, rgb_hex_str):
|
|
476
|
+
"""Return a new instance from an RGB color hex string like ``'3C2F80'``.
|
|
477
|
+
|
|
478
|
+
.. deprecated::
|
|
479
|
+
Prefer :meth:`from_hex` (which accepts hex with or without a
|
|
480
|
+
leading ``'#'``) for new code. ``from_string`` will be
|
|
481
|
+
removed in a future major release; until then it emits a
|
|
482
|
+
:class:`DeprecationWarning` on call.
|
|
483
|
+
"""
|
|
484
|
+
import warnings
|
|
485
|
+
|
|
486
|
+
warnings.warn(
|
|
487
|
+
"RGBColor.from_string is deprecated and will be removed in a "
|
|
488
|
+
"future major release; use RGBColor.from_hex (which accepts "
|
|
489
|
+
"hex strings with or without a leading '#') instead.",
|
|
490
|
+
DeprecationWarning,
|
|
491
|
+
stacklevel=2,
|
|
492
|
+
)
|
|
493
|
+
r = int(rgb_hex_str[:2], 16)
|
|
494
|
+
g = int(rgb_hex_str[2:4], 16)
|
|
495
|
+
b = int(rgb_hex_str[4:], 16)
|
|
496
|
+
return cls(r, g, b)
|