about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pptx/dml
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pptx/dml
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pptx/dml')
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/chtfmt.py40
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/color.py301
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/effect.py41
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/fill.py398
-rw-r--r--.venv/lib/python3.12/site-packages/pptx/dml/line.py100
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