# encoding: utf-8
"""
DrawingML objects related to color, ColorFormat being the most prominent.
"""
from __future__ import absolute_import, print_function, unicode_literals
from ..enum.dml import MSO_COLOR_TYPE, MSO_THEME_COLOR
from ..oxml.dml.color import (
CT_HslColor,
CT_PresetColor,
CT_SchemeColor,
CT_ScRgbColor,
CT_SRgbColor,
CT_SystemColor,
)
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)