Source code for fastpyxl.drawing.fill

# Copyright (c) 2010-2024 fastpyxl

from fastpyxl.descriptors.excel import ExtensionList as OfficeArtExtensionList
from fastpyxl.typed_serialisable.base import Serialisable
from fastpyxl.typed_serialisable.errors import FieldValidationError
from fastpyxl.typed_serialisable.fields import AliasField, Field
from fastpyxl.xml.constants import DRAWING_NS, REL_NS

from .colors import (
    PRESET_COLORS,
    ColorChoice,
    HSLColor,
    RGBPercent,
    SchemeColor,
    SystemColor,
)
from .effect import (
    AlphaBiLevelEffect,
    AlphaCeilingEffect,
    AlphaFloorEffect,
    AlphaInverseEffect,
    AlphaModulateEffect,
    AlphaModulateFixedEffect,
    AlphaReplaceEffect,
    BiLevelEffect,
    BlurEffect,
    ColorChangeEffect,
    ColorReplaceEffect,
    DuotoneEffect,
    FillOverlayEffect,
    GrayscaleEffect,
    HSLEffect,
    LuminanceEffect,
    TintEffect,
)

"""
Fill elements from drawing main schema
"""


def _enum_converter(value, allowed_values, field_name: str):
    if value is None:
        return None
    if value not in allowed_values:
        raise FieldValidationError(f"{field_name} rejected value {value!r}")
    return value


def _range_converter(value, minimum: int, maximum: int, field_name: str):
    if value is None:
        return None
    try:
        numeric = int(value)
    except (TypeError, ValueError) as exc:
        raise FieldValidationError(f"{field_name} rejected value {value!r}") from exc
    if not minimum <= numeric <= maximum:
        raise FieldValidationError(f"{field_name} rejected value {value!r}")
    return numeric


[docs] class PatternFillProperties(Serialisable): tagname = "pattFill" namespace = DRAWING_NS prst: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter( v, ( "pct5", "pct10", "pct20", "pct25", "pct30", "pct40", "pct50", "pct60", "pct70", "pct75", "pct80", "pct90", "horz", "vert", "ltHorz", "ltVert", "dkHorz", "dkVert", "narHorz", "narVert", "dashHorz", "dashVert", "cross", "dnDiag", "upDiag", "ltDnDiag", "ltUpDiag", "dkDnDiag", "dkUpDiag", "wdDnDiag", "wdUpDiag", "dashDnDiag", "dashUpDiag", "diagCross", "smCheck", "lgCheck", "smGrid", "lgGrid", "dotGrid", "smConfetti", "lgConfetti", "horzBrick", "diagBrick", "solidDmnd", "openDmnd", "dotDmnd", "plaid", "sphere", "weave", "divot", "shingle", "wave", "trellis", "zigZag", ), "prst", ), default=None, ) preset = AliasField("prst", default=None) fgClr: ColorChoice | None = Field.element(expected_type=ColorChoice, allow_none=True, default=None) foreground = AliasField("fgClr", default=None) bgClr: ColorChoice | None = Field.element(expected_type=ColorChoice, allow_none=True, default=None) background = AliasField("bgClr", default=None) xml_order = ("fgClr", "bgClr") def __init__(self, prst=None, fgClr=None, bgClr=None): self.prst = prst self.fgClr = fgClr self.bgClr = bgClr
[docs] class RelativeRect(Serialisable): tagname = "rect" namespace = DRAWING_NS l: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) # noqa: E741 left = AliasField("l", default=None) t: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) top = AliasField("t", default=None) r: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) right = AliasField("r", default=None) b: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) bottom = AliasField("b", default=None) def __init__(self, l=None, t=None, r=None, b=None): # noqa: E741 self.l = l # noqa: E741 self.t = t self.r = r self.b = b
[docs] class StretchInfoProperties(Serialisable): tagname = "stretch" namespace = DRAWING_NS fillRect: RelativeRect | None = Field.element(expected_type=RelativeRect, allow_none=True, default=None) def __init__(self, fillRect=RelativeRect()): self.fillRect = fillRect
[docs] class GradientStop(Serialisable): tagname = "gs" namespace = DRAWING_NS pos: int | None = Field.attribute( expected_type=int, allow_none=True, converter=lambda v: _range_converter(v, 0, 100000, "pos"), default=None, ) scrgbClr: RGBPercent | None = Field.element(expected_type=RGBPercent, allow_none=True, default=None) RGBPercent = AliasField("scrgbClr", default=None) srgbClr: str | None = Field.nested_value(expected_type=str, allow_none=True, default=None) RGB = AliasField("srgbClr", default=None) hslClr: HSLColor | None = Field.element(expected_type=HSLColor, allow_none=True, default=None) sysClr: SystemColor | None = Field.element(expected_type=SystemColor, allow_none=True, default=None) schemeClr: SchemeColor | None = Field.element(expected_type=SchemeColor, allow_none=True, default=None) prstClr: str | None = Field.nested_value( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, PRESET_COLORS, "prstClr"), default=None, ) xml_order = ("scrgbClr", "srgbClr", "hslClr", "sysClr", "schemeClr", "prstClr") def __init__(self, pos=None, scrgbClr=None, srgbClr=None, hslClr=None, sysClr=None, schemeClr=None, prstClr=None): if pos is None: pos = 0 self.pos = pos self.scrgbClr = scrgbClr self.srgbClr = srgbClr self.hslClr = hslClr self.sysClr = sysClr self.schemeClr = schemeClr self.prstClr = prstClr
[docs] class LinearShadeProperties(Serialisable): tagname = "lin" namespace = DRAWING_NS ang: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) scaled: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) def __init__(self, ang=None, scaled=None): self.ang = ang self.scaled = scaled
[docs] class PathShadeProperties(Serialisable): tagname = "path" namespace = DRAWING_NS path: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, ("shape", "circle", "rect"), "path"), default=None, ) fillToRect: RelativeRect | None = Field.element(expected_type=RelativeRect, allow_none=True, default=None) def __init__(self, path=None, fillToRect=None): self.path = path self.fillToRect = fillToRect
[docs] class GradientFillProperties(Serialisable): tagname = "gradFill" namespace = DRAWING_NS flip: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, ("x", "y", "xy"), "flip"), default=None, ) rotWithShape: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) gsLst: list[GradientStop] = Field.nested_sequence(expected_type=GradientStop, count=False, default=list) stop_list = AliasField("gsLst", default=None) lin: LinearShadeProperties | None = Field.element(expected_type=LinearShadeProperties, allow_none=True, default=None) linear = AliasField("lin", default=None) path: PathShadeProperties | None = Field.element(expected_type=PathShadeProperties, allow_none=True, default=None) tileRect: RelativeRect | None = Field.element(expected_type=RelativeRect, allow_none=True, default=None) xml_order = ("gsLst", "lin", "path", "tileRect") def __init__(self, flip=None, rotWithShape=None, gsLst=(), lin=None, path=None, tileRect=None): self.flip = flip self.rotWithShape = rotWithShape self.gsLst = list(gsLst) self.lin = lin self.path = path self.tileRect = tileRect
[docs] class SolidColorFillProperties(Serialisable): tagname = "solidFill" scrgbClr: RGBPercent | None = Field.element(expected_type=RGBPercent, allow_none=True, default=None) RGBPercent = AliasField("scrgbClr", default=None) srgbClr: str | None = Field.nested_value(expected_type=str, allow_none=True, default=None) RGB = AliasField("srgbClr", default=None) hslClr: HSLColor | None = Field.element(expected_type=HSLColor, allow_none=True, default=None) sysClr: SystemColor | None = Field.element(expected_type=SystemColor, allow_none=True, default=None) schemeClr: SchemeColor | None = Field.element(expected_type=SchemeColor, allow_none=True, default=None) prstClr: str | None = Field.nested_value( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, PRESET_COLORS, "prstClr"), default=None, ) xml_order = ("scrgbClr", "srgbClr", "hslClr", "sysClr", "schemeClr", "prstClr") def __init__(self, scrgbClr=None, srgbClr=None, hslClr=None, sysClr=None, schemeClr=None, prstClr=None): self.scrgbClr = scrgbClr self.srgbClr = srgbClr self.hslClr = hslClr self.sysClr = sysClr self.schemeClr = schemeClr self.prstClr = prstClr
[docs] class Blip(Serialisable): tagname = "blip" namespace = DRAWING_NS cstate: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, ("email", "screen", "print", "hqprint"), "cstate"), default=None, ) embed: str | None = Field.attribute(expected_type=str, allow_none=True, namespace=REL_NS, default=None) link: str | None = Field.attribute(expected_type=str, allow_none=True, namespace=REL_NS, default=None) noGrp: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noSelect: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noRot: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noChangeAspect: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noMove: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noResize: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noEditPoints: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noAdjustHandles: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noChangeArrowheads: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) noChangeShapeType: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) extLst: OfficeArtExtensionList | None = Field.element(expected_type=OfficeArtExtensionList, allow_none=True, default=None) alphaBiLevel: AlphaBiLevelEffect | None = Field.element(expected_type=AlphaBiLevelEffect, allow_none=True, default=None) alphaCeiling: AlphaCeilingEffect | None = Field.element(expected_type=AlphaCeilingEffect, allow_none=True, default=None) alphaFloor: AlphaFloorEffect | None = Field.element(expected_type=AlphaFloorEffect, allow_none=True, default=None) alphaInv: AlphaInverseEffect | None = Field.element(expected_type=AlphaInverseEffect, allow_none=True, default=None) alphaMod: AlphaModulateEffect | None = Field.element(expected_type=AlphaModulateEffect, allow_none=True, default=None) alphaModFix: AlphaModulateFixedEffect | None = Field.element(expected_type=AlphaModulateFixedEffect, allow_none=True, default=None) alphaRepl: AlphaReplaceEffect | None = Field.element(expected_type=AlphaReplaceEffect, allow_none=True, default=None) biLevel: BiLevelEffect | None = Field.element(expected_type=BiLevelEffect, allow_none=True, default=None) blur: BlurEffect | None = Field.element(expected_type=BlurEffect, allow_none=True, default=None) clrChange: ColorChangeEffect | None = Field.element(expected_type=ColorChangeEffect, allow_none=True, default=None) clrRepl: ColorReplaceEffect | None = Field.element(expected_type=ColorReplaceEffect, allow_none=True, default=None) duotone: DuotoneEffect | None = Field.element(expected_type=DuotoneEffect, allow_none=True, default=None) fillOverlay: FillOverlayEffect | None = Field.element(expected_type=FillOverlayEffect, allow_none=True, default=None) grayscl: GrayscaleEffect | None = Field.element(expected_type=GrayscaleEffect, allow_none=True, default=None) hsl: HSLEffect | None = Field.element(expected_type=HSLEffect, allow_none=True, default=None) lum: LuminanceEffect | None = Field.element(expected_type=LuminanceEffect, allow_none=True, default=None) tint: TintEffect | None = Field.element(expected_type=TintEffect, allow_none=True, default=None) xml_order = ( "alphaBiLevel", "alphaCeiling", "alphaFloor", "alphaInv", "alphaMod", "alphaModFix", "alphaRepl", "biLevel", "blur", "clrChange", "clrRepl", "duotone", "fillOverlay", "grayscl", "hsl", "lum", "tint", ) def __init__( self, cstate=None, embed=None, link=None, noGrp=None, noSelect=None, noRot=None, noChangeAspect=None, noMove=None, noResize=None, noEditPoints=None, noAdjustHandles=None, noChangeArrowheads=None, noChangeShapeType=None, extLst=None, alphaBiLevel=None, alphaCeiling=None, alphaFloor=None, alphaInv=None, alphaMod=None, alphaModFix=None, alphaRepl=None, biLevel=None, blur=None, clrChange=None, clrRepl=None, duotone=None, fillOverlay=None, grayscl=None, hsl=None, lum=None, tint=None, ): self.cstate = cstate self.embed = embed self.link = link self.noGrp = noGrp self.noSelect = noSelect self.noRot = noRot self.noChangeAspect = noChangeAspect self.noMove = noMove self.noResize = noResize self.noEditPoints = noEditPoints self.noAdjustHandles = noAdjustHandles self.noChangeArrowheads = noChangeArrowheads self.noChangeShapeType = noChangeShapeType self.extLst = extLst self.alphaBiLevel = alphaBiLevel self.alphaCeiling = alphaCeiling self.alphaFloor = alphaFloor self.alphaInv = alphaInv self.alphaMod = alphaMod self.alphaModFix = alphaModFix self.alphaRepl = alphaRepl self.biLevel = biLevel self.blur = blur self.clrChange = clrChange self.clrRepl = clrRepl self.duotone = duotone self.fillOverlay = fillOverlay self.grayscl = grayscl self.hsl = hsl self.lum = lum self.tint = tint
[docs] class TileInfoProperties(Serialisable): tx: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) ty: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) sx: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) sy: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) flip: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, ("x", "y", "xy"), "flip"), default=None, ) algn: str | None = Field.attribute( expected_type=str, allow_none=True, converter=lambda v: _enum_converter(v, ("tl", "t", "tr", "l", "ctr", "r", "bl", "b", "br"), "algn"), default=None, ) def __init__(self, tx=None, ty=None, sx=None, sy=None, flip=None, algn=None): self.tx = tx self.ty = ty self.sx = sx self.sy = sy self.flip = flip self.algn = algn
[docs] class BlipFillProperties(Serialisable): tagname = "blipFill" dpi: int | None = Field.attribute(expected_type=int, allow_none=True, default=None) rotWithShape: bool | None = Field.attribute(expected_type=bool, allow_none=True, default=None) blip: Blip | None = Field.element(expected_type=Blip, allow_none=True, default=None) srcRect: RelativeRect | None = Field.element(expected_type=RelativeRect, allow_none=True, default=None) tile: TileInfoProperties | None = Field.element(expected_type=TileInfoProperties, allow_none=True, default=None) stretch: StretchInfoProperties | None = Field.element(expected_type=StretchInfoProperties, allow_none=True, default=None) xml_order = ("blip", "srcRect", "tile", "stretch") def __init__(self, dpi=None, rotWithShape=None, blip=None, tile=None, stretch=StretchInfoProperties(), srcRect=None): self.dpi = dpi self.rotWithShape = rotWithShape self.blip = blip self.tile = tile self.stretch = stretch self.srcRect = srcRect