diff options
| author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
|---|---|---|
| committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
| commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
| tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pptx/dml | |
| parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
| download | gn-ai-master.tar.gz | |
Diffstat (limited to '.venv/lib/python3.12/site-packages/pptx/dml')
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/__init__.py | 0 | ||||
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/chtfmt.py | 40 | ||||
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/color.py | 301 | ||||
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/effect.py | 41 | ||||
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/fill.py | 398 | ||||
| -rw-r--r-- | .venv/lib/python3.12/site-packages/pptx/dml/line.py | 100 |
6 files changed, 880 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/__init__.py b/.venv/lib/python3.12/site-packages/pptx/dml/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/__init__.py diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/chtfmt.py b/.venv/lib/python3.12/site-packages/pptx/dml/chtfmt.py new file mode 100644 index 00000000..c37e4844 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/chtfmt.py @@ -0,0 +1,40 @@ +"""|ChartFormat| and related objects. + +|ChartFormat| acts as proxy for the `spPr` element, which provides visual shape properties such as +line and fill for chart elements. +""" + +from __future__ import annotations + +from pptx.dml.fill import FillFormat +from pptx.dml.line import LineFormat +from pptx.shared import ElementProxy +from pptx.util import lazyproperty + + +class ChartFormat(ElementProxy): + """ + The |ChartFormat| object provides access to visual shape properties for + chart elements like |Axis|, |Series|, and |MajorGridlines|. It has two + properties, :attr:`fill` and :attr:`line`, which return a |FillFormat| + and |LineFormat| object respectively. The |ChartFormat| object is + provided by the :attr:`format` property on the target axis, series, etc. + """ + + @lazyproperty + def fill(self): + """ + |FillFormat| instance for this object, providing access to fill + properties such as fill color. + """ + spPr = self._element.get_or_add_spPr() + return FillFormat.from_fill_parent(spPr) + + @lazyproperty + def line(self): + """ + The |LineFormat| object providing access to the visual properties of + this object, such as line color and line style. + """ + spPr = self._element.get_or_add_spPr() + return LineFormat(spPr) diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/color.py b/.venv/lib/python3.12/site-packages/pptx/dml/color.py new file mode 100644 index 00000000..54155823 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/color.py @@ -0,0 +1,301 @@ +"""DrawingML objects related to color, ColorFormat being the most prominent.""" + +from __future__ import annotations + +from pptx.enum.dml import MSO_COLOR_TYPE, MSO_THEME_COLOR +from pptx.oxml.dml.color import ( + CT_HslColor, + CT_PresetColor, + CT_SchemeColor, + CT_ScRgbColor, + CT_SRgbColor, + CT_SystemColor, +) + + +class ColorFormat(object): + """ + Provides access to color settings such as RGB color, theme color, and + luminance adjustments. + """ + + def __init__(self, eg_colorChoice_parent, color): + super(ColorFormat, self).__init__() + self._xFill = eg_colorChoice_parent + self._color = color + + @property + def brightness(self): + """ + Read/write float value between -1.0 and 1.0 indicating the brightness + adjustment for this color, e.g. -0.25 is 25% darker and 0.4 is 40% + lighter. 0 means no brightness adjustment. + """ + return self._color.brightness + + @brightness.setter + def brightness(self, value): + self._validate_brightness_value(value) + self._color.brightness = value + + @classmethod + def from_colorchoice_parent(cls, eg_colorChoice_parent): + xClr = eg_colorChoice_parent.eg_colorChoice + color = _Color(xClr) + color_format = cls(eg_colorChoice_parent, color) + return color_format + + @property + def rgb(self): + """ + |RGBColor| value of this color, or None if no RGB color is explicitly + defined for this font. Setting this value to an |RGBColor| instance + causes its type to change to MSO_COLOR_TYPE.RGB. If the color was a + theme color with a brightness adjustment, the brightness adjustment + is removed when changing it to an RGB color. + """ + return self._color.rgb + + @rgb.setter + def rgb(self, rgb): + if not isinstance(rgb, RGBColor): + raise ValueError("assigned value must be type RGBColor") + # change to rgb color format if not already + if not isinstance(self._color, _SRgbColor): + srgbClr = self._xFill.get_or_change_to_srgbClr() + self._color = _SRgbColor(srgbClr) + # call _SRgbColor instance to do the setting + self._color.rgb = rgb + + @property + def theme_color(self): + """Theme color value of this color. + + Value is a member of :ref:`MsoThemeColorIndex`, e.g. + ``MSO_THEME_COLOR.ACCENT_1``. Raises AttributeError on access if the + color is not type ``MSO_COLOR_TYPE.SCHEME``. Assigning a member of + :ref:`MsoThemeColorIndex` causes the color's type to change to + ``MSO_COLOR_TYPE.SCHEME``. + """ + return self._color.theme_color + + @theme_color.setter + def theme_color(self, mso_theme_color_idx): + # change to theme color format if not already + if not isinstance(self._color, _SchemeColor): + schemeClr = self._xFill.get_or_change_to_schemeClr() + self._color = _SchemeColor(schemeClr) + self._color.theme_color = mso_theme_color_idx + + @property + def type(self): + """ + Read-only. A value from :ref:`MsoColorType`, either RGB or SCHEME, + corresponding to the way this color is defined, or None if no color + is defined at the level of this font. + """ + return self._color.color_type + + def _validate_brightness_value(self, value): + if value < -1.0 or value > 1.0: + raise ValueError("brightness must be number in range -1.0 to 1.0") + if isinstance(self._color, _NoneColor): + msg = ( + "can't set brightness when color.type is None. Set color.rgb" + " or .theme_color first." + ) + raise ValueError(msg) + + +class _Color(object): + """ + Object factory for color object of the appropriate type, also the base + class for all color type classes such as SRgbColor. + """ + + def __new__(cls, xClr): + color_cls = { + type(None): _NoneColor, + CT_HslColor: _HslColor, + CT_PresetColor: _PrstColor, + CT_SchemeColor: _SchemeColor, + CT_ScRgbColor: _ScRgbColor, + CT_SRgbColor: _SRgbColor, + CT_SystemColor: _SysColor, + }[type(xClr)] + return super(_Color, cls).__new__(color_cls) + + def __init__(self, xClr): + super(_Color, self).__init__() + self._xClr = xClr + + @property + def brightness(self): + lumMod, lumOff = self._xClr.lumMod, self._xClr.lumOff + # a tint is lighter, a shade is darker + # only tints have lumOff child + if lumOff is not None: + brightness = lumOff.val + return brightness + # which leaves shades, if lumMod is present + if lumMod is not None: + brightness = lumMod.val - 1.0 + return brightness + # there's no brightness adjustment if no lum{Mod|Off} elements + return 0 + + @brightness.setter + def brightness(self, value): + if value > 0: + self._tint(value) + elif value < 0: + self._shade(value) + else: + self._xClr.clear_lum() + + @property + def color_type(self): # pragma: no cover + tmpl = ".color_type property must be implemented on %s" + raise NotImplementedError(tmpl % self.__class__.__name__) + + @property + def rgb(self): + """ + Raises TypeError on access unless overridden by subclass. + """ + tmpl = "no .rgb property on color type '%s'" + raise AttributeError(tmpl % self.__class__.__name__) + + @property + def theme_color(self): + """ + Raises TypeError on access unless overridden by subclass. + """ + return MSO_THEME_COLOR.NOT_THEME_COLOR + + def _shade(self, value): + lumMod_val = 1.0 - abs(value) + color_elm = self._xClr.clear_lum() + color_elm.add_lumMod(lumMod_val) + + def _tint(self, value): + lumOff_val = value + lumMod_val = 1.0 - lumOff_val + color_elm = self._xClr.clear_lum() + color_elm.add_lumMod(lumMod_val) + color_elm.add_lumOff(lumOff_val) + + +class _HslColor(_Color): + @property + def color_type(self): + return MSO_COLOR_TYPE.HSL + + +class _NoneColor(_Color): + @property + def color_type(self): + return None + + @property + def theme_color(self): + """ + Raise TypeError on attempt to access .theme_color when no color + choice is present. + """ + tmpl = "no .theme_color property on color type '%s'" + raise AttributeError(tmpl % self.__class__.__name__) + + +class _PrstColor(_Color): + @property + def color_type(self): + return MSO_COLOR_TYPE.PRESET + + +class _SchemeColor(_Color): + def __init__(self, schemeClr): + super(_SchemeColor, self).__init__(schemeClr) + self._schemeClr = schemeClr + + @property + def color_type(self): + return MSO_COLOR_TYPE.SCHEME + + @property + def theme_color(self): + """ + Theme color value of this color, one of those defined in the + MSO_THEME_COLOR enumeration, e.g. MSO_THEME_COLOR.ACCENT_1. None if + no theme color is explicitly defined for this font. Setting this to a + value in MSO_THEME_COLOR causes the color's type to change to + ``MSO_COLOR_TYPE.SCHEME``. + """ + return self._schemeClr.val + + @theme_color.setter + def theme_color(self, mso_theme_color_idx): + self._schemeClr.val = mso_theme_color_idx + + +class _ScRgbColor(_Color): + @property + def color_type(self): + return MSO_COLOR_TYPE.SCRGB + + +class _SRgbColor(_Color): + def __init__(self, srgbClr): + super(_SRgbColor, self).__init__(srgbClr) + self._srgbClr = srgbClr + + @property + def color_type(self): + return MSO_COLOR_TYPE.RGB + + @property + def rgb(self): + """ + |RGBColor| value of this color, corresponding to the value in the + required ``val`` attribute of the ``<a:srgbColr>`` element. + """ + return RGBColor.from_string(self._srgbClr.val) + + @rgb.setter + def rgb(self, rgb): + self._srgbClr.val = str(rgb) + + +class _SysColor(_Color): + @property + def color_type(self): + return MSO_COLOR_TYPE.SYSTEM + + +class RGBColor(tuple): + """ + Immutable value object defining a particular RGB color. + """ + + def __new__(cls, r, g, b): + msg = "RGBColor() takes three integer values 0-255" + for val in (r, g, b): + if not isinstance(val, int) or val < 0 or val > 255: + raise ValueError(msg) + return super(RGBColor, cls).__new__(cls, (r, g, b)) + + def __str__(self): + """ + Return a hex string rgb value, like '3C2F80' + """ + return "%02X%02X%02X" % self + + @classmethod + def from_string(cls, rgb_hex_str): + """ + Return a new instance from an RGB color hex string like ``'3C2F80'``. + """ + r = int(rgb_hex_str[:2], 16) + g = int(rgb_hex_str[2:4], 16) + b = int(rgb_hex_str[4:], 16) + return cls(r, g, b) diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/effect.py b/.venv/lib/python3.12/site-packages/pptx/dml/effect.py new file mode 100644 index 00000000..9df69ce4 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/effect.py @@ -0,0 +1,41 @@ +"""Visual effects on a shape such as shadow, glow, and reflection.""" + +from __future__ import annotations + + +class ShadowFormat(object): + """Provides access to shadow effect on a shape.""" + + def __init__(self, spPr): + # ---spPr may also be a grpSpPr; both have a:effectLst child--- + self._element = spPr + + @property + def inherit(self): + """True if shape inherits shadow settings. + + Read/write. An explicitly-defined shadow setting on a shape causes + this property to return |False|. A shape with no explicitly-defined + shadow setting inherits its shadow settings from the style hierarchy + (and so returns |True|). + + Assigning |True| causes any explicitly-defined shadow setting to be + removed and inheritance is restored. Note this has the side-effect of + removing **all** explicitly-defined effects, such as glow and + reflection, and restoring inheritance for all effects on the shape. + Assigning |False| causes the inheritance link to be broken and **no** + effects to appear on the shape. + """ + if self._element.effectLst is None: + return True + return False + + @inherit.setter + def inherit(self, value): + inherit = bool(value) + if inherit: + # ---remove any explicitly-defined effects + self._element._remove_effectLst() + else: + # ---ensure at least the effectLst element is present + self._element.get_or_add_effectLst() diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/fill.py b/.venv/lib/python3.12/site-packages/pptx/dml/fill.py new file mode 100644 index 00000000..8212af9e --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/fill.py @@ -0,0 +1,398 @@ +"""DrawingML objects related to fill.""" + +from __future__ import annotations + +from collections.abc import Sequence +from typing import TYPE_CHECKING + +from pptx.dml.color import ColorFormat +from pptx.enum.dml import MSO_FILL +from pptx.oxml.dml.fill import ( + CT_BlipFillProperties, + CT_GradientFillProperties, + CT_GroupFillProperties, + CT_NoFillProperties, + CT_PatternFillProperties, + CT_SolidColorFillProperties, +) +from pptx.oxml.xmlchemy import BaseOxmlElement +from pptx.shared import ElementProxy +from pptx.util import lazyproperty + +if TYPE_CHECKING: + from pptx.enum.dml import MSO_FILL_TYPE + from pptx.oxml.xmlchemy import BaseOxmlElement + + +class FillFormat(object): + """Provides access to the current fill properties. + + Also provides methods to change the fill type. + """ + + def __init__(self, eg_fill_properties_parent: BaseOxmlElement, fill_obj: _Fill): + super(FillFormat, self).__init__() + self._xPr = eg_fill_properties_parent + self._fill = fill_obj + + @classmethod + def from_fill_parent(cls, eg_fillProperties_parent: BaseOxmlElement) -> FillFormat: + """ + Return a |FillFormat| instance initialized to the settings contained + in *eg_fillProperties_parent*, which must be an element having + EG_FillProperties in its child element sequence in the XML schema. + """ + fill_elm = eg_fillProperties_parent.eg_fillProperties + fill = _Fill(fill_elm) + fill_format = cls(eg_fillProperties_parent, fill) + return fill_format + + @property + def back_color(self): + """Return a |ColorFormat| object representing background color. + + This property is only applicable to pattern fills and lines. + """ + return self._fill.back_color + + def background(self): + """ + Sets the fill type to noFill, i.e. transparent. + """ + noFill = self._xPr.get_or_change_to_noFill() + self._fill = _NoFill(noFill) + + @property + def fore_color(self): + """ + Return a |ColorFormat| instance representing the foreground color of + this fill. + """ + return self._fill.fore_color + + def gradient(self): + """Sets the fill type to gradient. + + If the fill is not already a gradient, a default gradient is added. + The default gradient corresponds to the default in the built-in + PowerPoint "White" template. This gradient is linear at angle + 90-degrees (upward), with two stops. The first stop is Accent-1 with + tint 100%, shade 100%, and satMod 130%. The second stop is Accent-1 + with tint 50%, shade 100%, and satMod 350%. + """ + gradFill = self._xPr.get_or_change_to_gradFill() + self._fill = _GradFill(gradFill) + + @property + def gradient_angle(self): + """Angle in float degrees of line of a linear gradient. + + Read/Write. May be |None|, indicating the angle should be inherited + from the style hierarchy. An angle of 0.0 corresponds to + a left-to-right gradient. Increasing angles represent + counter-clockwise rotation of the line, for example 90.0 represents + a bottom-to-top gradient. Raises |TypeError| when the fill type is + not MSO_FILL_TYPE.GRADIENT. Raises |ValueError| for a non-linear + gradient (e.g. a radial gradient). + """ + if self.type != MSO_FILL.GRADIENT: + raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT") + return self._fill.gradient_angle + + @gradient_angle.setter + def gradient_angle(self, value): + if self.type != MSO_FILL.GRADIENT: + raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT") + self._fill.gradient_angle = value + + @property + def gradient_stops(self): + """|GradientStops| object providing access to stops of this gradient. + + Raises |TypeError| when fill is not gradient (call `fill.gradient()` + first). Each stop represents a color between which the gradient + smoothly transitions. + """ + if self.type != MSO_FILL.GRADIENT: + raise TypeError("Fill is not of type MSO_FILL_TYPE.GRADIENT") + return self._fill.gradient_stops + + @property + def pattern(self): + """Return member of :ref:`MsoPatternType` indicating fill pattern. + + Raises |TypeError| when fill is not patterned (call + `fill.patterned()` first). Returns |None| if no pattern has been set; + PowerPoint may display the default `PERCENT_5` pattern in this case. + Assigning |None| will remove any explicit pattern setting, although + relying on the default behavior is discouraged and may produce + rendering differences across client applications. + """ + return self._fill.pattern + + @pattern.setter + def pattern(self, pattern_type): + self._fill.pattern = pattern_type + + def patterned(self): + """Selects the pattern fill type. + + Note that calling this method does not by itself set a foreground or + background color of the pattern. Rather it enables subsequent + assignments to properties like fore_color to set the pattern and + colors. + """ + pattFill = self._xPr.get_or_change_to_pattFill() + self._fill = _PattFill(pattFill) + + def solid(self): + """ + Sets the fill type to solid, i.e. a solid color. Note that calling + this method does not set a color or by itself cause the shape to + appear with a solid color fill; rather it enables subsequent + assignments to properties like fore_color to set the color. + """ + solidFill = self._xPr.get_or_change_to_solidFill() + self._fill = _SolidFill(solidFill) + + @property + def type(self) -> MSO_FILL_TYPE: + """The type of this fill, e.g. `MSO_FILL_TYPE.SOLID`.""" + return self._fill.type + + +class _Fill(object): + """ + Object factory for fill object of class matching fill element, such as + _SolidFill for ``<a:solidFill>``; also serves as the base class for all + fill classes + """ + + def __new__(cls, xFill): + if xFill is None: + fill_cls = _NoneFill + elif isinstance(xFill, CT_BlipFillProperties): + fill_cls = _BlipFill + elif isinstance(xFill, CT_GradientFillProperties): + fill_cls = _GradFill + elif isinstance(xFill, CT_GroupFillProperties): + fill_cls = _GrpFill + elif isinstance(xFill, CT_NoFillProperties): + fill_cls = _NoFill + elif isinstance(xFill, CT_PatternFillProperties): + fill_cls = _PattFill + elif isinstance(xFill, CT_SolidColorFillProperties): + fill_cls = _SolidFill + else: + fill_cls = _Fill + return super(_Fill, cls).__new__(fill_cls) + + @property + def back_color(self): + """Raise TypeError for types that do not override this property.""" + tmpl = "fill type %s has no background color, call .patterned() first" + raise TypeError(tmpl % self.__class__.__name__) + + @property + def fore_color(self): + """Raise TypeError for types that do not override this property.""" + tmpl = "fill type %s has no foreground color, call .solid() or .pattern" "ed() first" + raise TypeError(tmpl % self.__class__.__name__) + + @property + def pattern(self): + """Raise TypeError for fills that do not override this property.""" + tmpl = "fill type %s has no pattern, call .patterned() first" + raise TypeError(tmpl % self.__class__.__name__) + + @property + def type(self) -> MSO_FILL_TYPE: # pragma: no cover + raise NotImplementedError( + f".type property must be implemented on {self.__class__.__name__}" + ) + + +class _BlipFill(_Fill): + @property + def type(self): + return MSO_FILL.PICTURE + + +class _GradFill(_Fill): + """Proxies an `a:gradFill` element.""" + + def __init__(self, gradFill): + self._element = self._gradFill = gradFill + + @property + def gradient_angle(self): + """Angle in float degrees of line of a linear gradient. + + Read/Write. May be |None|, indicating the angle is inherited from the + style hierarchy. An angle of 0.0 corresponds to a left-to-right + gradient. Increasing angles represent clockwise rotation of the line, + for example 90.0 represents a top-to-bottom gradient. Raises + |TypeError| when the fill type is not MSO_FILL_TYPE.GRADIENT. Raises + |ValueError| for a non-linear gradient (e.g. a radial gradient). + """ + # ---case 1: gradient path is explicit, but not linear--- + path = self._gradFill.path + if path is not None: + raise ValueError("not a linear gradient") + + # ---case 2: gradient path is inherited (no a:lin OR a:path)--- + lin = self._gradFill.lin + if lin is None: + return None + + # ---case 3: gradient path is explicitly linear--- + # angle is stored in XML as a clockwise angle, whereas the UI + # reports it as counter-clockwise from horizontal-pointing-right. + # Since the UI is consistent with trigonometry conventions, we + # respect that in the API. + clockwise_angle = lin.ang + counter_clockwise_angle = 0.0 if clockwise_angle == 0.0 else (360.0 - clockwise_angle) + return counter_clockwise_angle + + @gradient_angle.setter + def gradient_angle(self, value): + lin = self._gradFill.lin + if lin is None: + raise ValueError("not a linear gradient") + lin.ang = 360.0 - value + + @lazyproperty + def gradient_stops(self): + """|_GradientStops| object providing access to gradient colors. + + Each stop represents a color between which the gradient smoothly + transitions. + """ + return _GradientStops(self._gradFill.get_or_add_gsLst()) + + @property + def type(self): + return MSO_FILL.GRADIENT + + +class _GrpFill(_Fill): + @property + def type(self): + return MSO_FILL.GROUP + + +class _NoFill(_Fill): + @property + def type(self): + return MSO_FILL.BACKGROUND + + +class _NoneFill(_Fill): + @property + def type(self): + return None + + +class _PattFill(_Fill): + """Provides access to patterned fill properties.""" + + def __init__(self, pattFill): + super(_PattFill, self).__init__() + self._element = self._pattFill = pattFill + + @lazyproperty + def back_color(self): + """Return |ColorFormat| object that controls background color.""" + bgClr = self._pattFill.get_or_add_bgClr() + return ColorFormat.from_colorchoice_parent(bgClr) + + @lazyproperty + def fore_color(self): + """Return |ColorFormat| object that controls foreground color.""" + fgClr = self._pattFill.get_or_add_fgClr() + return ColorFormat.from_colorchoice_parent(fgClr) + + @property + def pattern(self): + """Return member of :ref:`MsoPatternType` indicating fill pattern. + + Returns |None| if no pattern has been set; PowerPoint may display the + default `PERCENT_5` pattern in this case. Assigning |None| will + remove any explicit pattern setting. + """ + return self._pattFill.prst + + @pattern.setter + def pattern(self, pattern_type): + self._pattFill.prst = pattern_type + + @property + def type(self): + return MSO_FILL.PATTERNED + + +class _SolidFill(_Fill): + """Provides access to fill properties such as color for solid fills.""" + + def __init__(self, solidFill): + super(_SolidFill, self).__init__() + self._solidFill = solidFill + + @lazyproperty + def fore_color(self): + """Return |ColorFormat| object controlling fill color.""" + return ColorFormat.from_colorchoice_parent(self._solidFill) + + @property + def type(self): + return MSO_FILL.SOLID + + +class _GradientStops(Sequence): + """Collection of |GradientStop| objects defining gradient colors. + + A gradient must have a minimum of two stops, but can have as many more + than that as required to achieve the desired effect (three is perhaps + most common). Stops are sequenced in the order they are transitioned + through. + """ + + def __init__(self, gsLst): + self._gsLst = gsLst + + def __getitem__(self, idx): + return _GradientStop(self._gsLst[idx]) + + def __len__(self): + return len(self._gsLst) + + +class _GradientStop(ElementProxy): + """A single gradient stop. + + A gradient stop defines a color and a position. + """ + + def __init__(self, gs): + super(_GradientStop, self).__init__(gs) + self._gs = gs + + @lazyproperty + def color(self): + """Return |ColorFormat| object controlling stop color.""" + return ColorFormat.from_colorchoice_parent(self._gs) + + @property + def position(self): + """Location of stop in gradient path as float between 0.0 and 1.0. + + The value represents a percentage, where 0.0 (0%) represents the + start of the path and 1.0 (100%) represents the end of the path. For + a linear gradient, these would represent opposing extents of the + filled area. + """ + return self._gs.pos + + @position.setter + def position(self, value): + self._gs.pos = float(value) diff --git a/.venv/lib/python3.12/site-packages/pptx/dml/line.py b/.venv/lib/python3.12/site-packages/pptx/dml/line.py new file mode 100644 index 00000000..82be47a4 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/pptx/dml/line.py @@ -0,0 +1,100 @@ +"""DrawingML objects related to line formatting.""" + +from __future__ import annotations + +from pptx.dml.fill import FillFormat +from pptx.enum.dml import MSO_FILL +from pptx.util import Emu, lazyproperty + + +class LineFormat(object): + """Provides access to line properties such as color, style, and width. + + A LineFormat object is typically accessed via the ``.line`` property of + a shape such as |Shape| or |Picture|. + """ + + def __init__(self, parent): + super(LineFormat, self).__init__() + self._parent = parent + + @lazyproperty + def color(self): + """ + The |ColorFormat| instance that provides access to the color settings + for this line. Essentially a shortcut for ``line.fill.fore_color``. + As a side-effect, accessing this property causes the line fill type + to be set to ``MSO_FILL.SOLID``. If this sounds risky for your use + case, use ``line.fill.type`` to non-destructively discover the + existing fill type. + """ + if self.fill.type != MSO_FILL.SOLID: + self.fill.solid() + return self.fill.fore_color + + @property + def dash_style(self): + """Return value indicating line style. + + Returns a member of :ref:`MsoLineDashStyle` indicating line style, or + |None| if no explicit value has been set. When no explicit value has + been set, the line dash style is inherited from the style hierarchy. + + Assigning |None| removes any existing explicitly-defined dash style. + """ + ln = self._ln + if ln is None: + return None + return ln.prstDash_val + + @dash_style.setter + def dash_style(self, dash_style): + if dash_style is None: + ln = self._ln + if ln is None: + return + ln._remove_prstDash() + ln._remove_custDash() + return + ln = self._get_or_add_ln() + ln.prstDash_val = dash_style + + @lazyproperty + def fill(self): + """ + |FillFormat| instance for this line, providing access to fill + properties such as foreground color. + """ + ln = self._get_or_add_ln() + return FillFormat.from_fill_parent(ln) + + @property + def width(self): + """ + The width of the line expressed as an integer number of :ref:`English + Metric Units <EMU>`. The returned value is an instance of |Length|, + a value class having properties such as `.inches`, `.cm`, and `.pt` + for converting the value into convenient units. + """ + ln = self._ln + if ln is None: + return Emu(0) + return ln.w + + @width.setter + def width(self, emu): + if emu is None: + emu = 0 + ln = self._get_or_add_ln() + ln.w = emu + + def _get_or_add_ln(self): + """ + Return the ``<a:ln>`` element containing the line format properties + in the XML. + """ + return self._parent.get_or_add_ln() + + @property + def _ln(self): + return self._parent.ln |
