boring boring documentation

This commit is contained in:
Thomas Fussell 2017-03-25 11:22:21 -04:00
parent e040a1c4ab
commit 1121bcbe15
8 changed files with 338 additions and 254 deletions

View File

@ -30,7 +30,7 @@
namespace xlnt {
/// <summary>
/// Text can be aligned horizontally in these enumerated ways.
/// Text can be aligned horizontally within a cell in these enumerated ways.
/// </summary>
enum class XLNT_API horizontal_alignment
{
@ -45,7 +45,7 @@ enum class XLNT_API horizontal_alignment
};
/// <summary>
/// Text can be aligned vertically in these enumerated ways.
/// Text can be aligned vertically within a cell in these enumerated ways.
/// </summary>
enum class XLNT_API vertical_alignment
{
@ -57,68 +57,69 @@ enum class XLNT_API vertical_alignment
};
/// <summary>
/// Alignment options for use in cell formats.
/// Alignment options that determine how text should be displayed within a cell.
/// </summary>
class XLNT_API alignment
{
public:
/// <summary>
///
/// Returns true if shrink-to-fit has been enabled.
/// </summary>
bool shrink() const;
/// <summary>
///
/// Sets whether the font size should be reduced until all of the text fits in a cell without wrapping.
/// </summary>
alignment &shrink(bool shrink_to_fit);
/// <summary>
///
/// Returns true if text-wrapping has been enabled.
/// </summary>
bool wrap() const;
/// <summary>
///
/// Sets whether text in a cell should continue to multiple lines if it doesn't fit in one line.
/// </summary>
alignment &wrap(bool wrap_text);
/// <summary>
///
/// Returns the optional value of indentation width in number of spaces.
/// </summary>
optional<int> indent() const;
/// <summary>
///
/// Sets the indent size in number of spaces from the side of the cell. This will only
/// take effect when left or right horizontal alignment has also been set.
/// </summary>
alignment &indent(int indent_size);
/// <summary>
///
/// Returns the optional value of rotation for text in the cell in degrees.
/// </summary>
optional<int> rotation() const;
/// <summary>
///
/// Sets the rotation for text in the cell in degrees.
/// </summary>
alignment &rotation(int text_rotation);
/// <summary>
///
/// Returns the optional horizontal alignment.
/// </summary>
optional<horizontal_alignment> horizontal() const;
/// <summary>
///
/// Sets the horizontal alignment.
/// </summary>
alignment &horizontal(horizontal_alignment horizontal);
/// <summary>
///
/// Returns the optional vertical alignment.
/// </summary>
optional<vertical_alignment> vertical() const;
/// <summary>
///
/// Sets the vertical alignment.
/// </summary>
alignment &vertical(vertical_alignment vertical);
@ -133,11 +134,34 @@ public:
bool operator!=(const alignment &other) const;
private:
bool shrink_to_fit_ = false;
bool wrap_text_ = false;
optional<int> indent_;
/// <summary>
/// Whether or not to shrink font size until it fits on one line
/// </summary>
bool shrink_to_fit_ = false;
/// <summary>
/// Whether or not to wrap text to the next line
/// </summary>
bool wrap_text_ = false;
/// <summary>
/// The indent in number of spaces from the side
/// </summary>
optional<int> indent_;
/// <summary>
/// The text roation in degrees
/// </summary>
optional<int> text_rotation_;
/// <summary>
/// The horizontal alignment
/// </summary>
optional<horizontal_alignment> horizontal_;
/// <summary>
/// The vertical alignment
/// </summary>
optional<vertical_alignment> vertical_;
};

View File

@ -50,7 +50,7 @@ enum class XLNT_API border_side
};
/// <summary>
///
/// Enumerates the pattern of the border lines on a particular side.
/// </summary>
enum class XLNT_API border_style
{

View File

@ -32,7 +32,7 @@
namespace xlnt {
/// <summary>
///
/// An indexed color encapsulates a simple index to a color in the indexedColors of the stylesheet.
/// </summary>
class XLNT_API indexed_color
{
@ -60,7 +60,7 @@ private:
};
/// <summary>
///
/// A theme color encapsulates a color derived from the theme.
/// </summary>
class XLNT_API theme_color
{
@ -88,64 +88,60 @@ private:
};
/// <summary>
///
/// An RGB color describes a color in terms of its red, green, blue, and alpha components.
/// </summary>
class XLNT_API rgb_color
{
public:
/// <summary>
///
/// Constructs an RGB color from a string in the form #[aa]rrggbb
/// </summary>
rgb_color(const std::string &hex_string);
/// <summary>
///
/// Constructs an RGB color from red, green, and blue values in the range 0 to 255
/// plus an optional alpha which defaults to fully opaque.
/// </summary>
rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a = 255);
/// <summary>
///
/// Returns a string representation of this color in the form #aarrggbb
/// </summary>
std::string hex_string() const;
/// <summary>
///
/// Returns a byte representing the red component of this color
/// </summary>
std::uint8_t red() const;
/// <summary>
///
/// Returns a byte representing the red component of this color
/// </summary>
std::uint8_t green() const;
/// <summary>
///
/// Returns a byte representing the blue component of this color
/// </summary>
std::uint8_t blue() const;
/// <summary>
///
/// Returns a byte representing the alpha component of this color
/// </summary>
std::uint8_t alpha() const;
/// <summary>
///
/// Returns the red, green, and blue components of this color separately in an array in that order.
/// </summary>
std::array<std::uint8_t, 3> rgb() const;
/// <summary>
///
/// Returns the red, green, blue, and alpha components of this color separately in an array in that order.
/// </summary>
std::array<std::uint8_t, 4> rgba() const;
private:
/// <summary>
///
/// </summary>
static std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string);
/// <summary>
///
/// The four bytes of this color
/// </summary>
std::array<std::uint8_t, 4> rgba_;
};
@ -167,163 +163,163 @@ class XLNT_API color
{
public:
/// <summary>
///
/// Returns the color #000000
/// </summary>
static const color black();
/// <summary>
///
/// Returns the color #ffffff
/// </summary>
static const color white();
/// <summary>
///
/// Returns the color #ff0000
/// </summary>
static const color red();
/// <summary>
///
/// Returns the color #8b0000
/// </summary>
static const color darkred();
/// <summary>
///
/// Returns the color #00ff00
/// </summary>
static const color blue();
/// <summary>
///
/// Returns the color #008b00
/// </summary>
static const color darkblue();
/// <summary>
///
/// Returns the color #0000ff
/// </summary>
static const color green();
/// <summary>
///
/// Returns the color #00008b
/// </summary>
static const color darkgreen();
/// <summary>
///
/// Returns the color #ffff00
/// </summary>
static const color yellow();
/// <summary>
///
/// Returns the color #cccc00
/// </summary>
static const color darkyellow();
/// <summary>
///
/// Constructs a default color
/// </summary>
color();
/// <summary>
///
/// Constructs a color from a given RGB color
/// </summary>
color(const rgb_color &rgb);
/// <summary>
///
/// Constructs a color from a given indexed color
/// </summary>
color(const indexed_color &indexed);
/// <summary>
///
/// Constructs a color from a given theme color
/// </summary>
color(const theme_color &theme);
/// <summary>
///
/// Returns the type of this color
/// </summary>
color_type type() const;
/// <summary>
///
/// Returns true if this color has been set to auto
/// </summary>
bool is_auto() const;
bool auto_() const;
/// <summary>
///
/// Sets the auto property of this color to value
/// </summary>
void auto_(bool value);
/// <summary>
///
/// Returns the internal indexed color representing this color. If this is not an RGB color,
/// an invalid_attribute exception will be thrown.
/// </summary>
const rgb_color &rgb() const;
rgb_color rgb() const;
/// <summary>
///
/// Returns the internal indexed color representing this color. If this is not an indexed color,
/// an invalid_attribute exception will be thrown.
/// </summary>
const indexed_color &indexed() const;
indexed_color indexed() const;
/// <summary>
///
/// Returns the internal indexed color representing this color. If this is not a theme color,
/// an invalid_attribute exception will be thrown.
/// </summary>
const theme_color &theme() const;
theme_color theme() const;
/// <summary>
///
/// Returns the tint of this color.
/// </summary>
double tint() const;
/// <summary>
///
/// Sets the tint of this color to tint. Tints lighten or darken an existing color by multiplying the color with the tint.
/// </summary>
void tint(double tint);
/// <summary>
///
/// Returns true if this color is equivalent to other
/// </summary>
bool operator==(const color &other) const;
/// <summary>
///
/// Returns true if this color is not equivalent to other
/// </summary>
bool operator!=(const color &other) const
{
return !(*this == other);
}
bool operator!=(const color &other) const;
private:
/// <summary>
///
/// Throws an invalid_attribute exception if the given type is different from this color's type
/// </summary>
void assert_type(color_type t) const;
/// <summary>
///
/// The type of this color
/// </summary>
color_type type_;
/// <summary>
///
/// The internal RGB color. Only valid when this color has a type of rgb
/// </summary>
rgb_color rgb_;
/// <summary>
///
/// The internal RGB color. Only valid when this color has a type of indexed
/// </summary>
indexed_color indexed_;
/// <summary>
///
/// The internal RGB color. Only valid when this color has a type of theme
/// </summary>
theme_color theme_;
/// <summary>
///
/// The tint of this color
/// </summary>
double tint_;
double tint_ = 0.0;
/// <summary>
///
/// Whether or not this is an auto color
/// </summary>
bool auto__;
bool auto__ = false;
};
} // namespace xlnt

View File

@ -33,7 +33,7 @@
namespace xlnt {
/// <summary>
///
/// The pattern of pixels upon which the corresponding pattern fill will be displayed
/// </summary>
enum class XLNT_API pattern_fill_type
{
@ -59,58 +59,56 @@ enum class XLNT_API pattern_fill_type
};
/// <summary>
///
/// Represents a fill which colors the cell based on a foreground and
/// background color and a pattern.
/// </summary>
class XLNT_API pattern_fill
{
public:
/// <summary>
///
/// Constructs a default pattern fill with a none pattern and no colors.
/// </summary>
pattern_fill();
/// <summary>
///
/// Returns the pattern used by this fill
/// </summary>
pattern_fill_type type() const;
/// <summary>
///
/// Sets the pattern of this fill and returns a reference to it.
/// </summary>
pattern_fill &type(pattern_fill_type new_type);
/// <summary>
///
/// Returns the optional foreground color of this fill
/// </summary>
optional<color> foreground() const;
/// <summary>
///
/// Sets the foreground color and returns a reference to this pattern.
/// </summary>
pattern_fill &foreground(const color &foreground);
/// <summary>
///
/// Returns the optional background color of this fill
/// </summary>
optional<color> background() const;
/// <summary>
///
/// Sets the foreground color and returns a reference to this pattern.
/// </summary>
pattern_fill &background(const color &background);
/// <summary>
/// Returns true if left is exactly equal to right.
/// Returns true if this pattern fill is equivalent to other.
/// </summary>
XLNT_API friend bool operator==(const pattern_fill &left, const pattern_fill &right);
bool operator==(const pattern_fill &other) const;
/// <summary>
/// Returns true if left is not exactly equal to right.
/// Returns true if this pattern fill is not equivalent to other.
/// </summary>
XLNT_API friend bool operator!=(const pattern_fill &left, const pattern_fill &right)
{
return !(left == right);
}
bool operator!=(const pattern_fill &other) const;
private:
/// <summary>
@ -139,37 +137,37 @@ enum class XLNT_API gradient_fill_type
};
/// <summary>
///
/// Encapsulates a fill which transitions between colors at particular "stops".
/// </summary>
class XLNT_API gradient_fill
{
public:
/// <summary>
///
/// Constructs a default linear fill
/// </summary>
gradient_fill();
/// <summary>
///
/// Returns the type of this gradient fill
/// </summary>
gradient_fill_type type() const;
// Type
/// <summary>
///
/// Sets the type of this gradient fill
/// </summary>
gradient_fill &type(gradient_fill_type new_type);
// Degree
/// <summary>
///
/// Sets the angle of the gradient in degrees
/// </summary>
gradient_fill &degree(double degree);
/// <summary>
///
/// Returns the angle of the gradient
/// </summary>
double degree() const;
@ -241,15 +239,12 @@ public:
/// <summary>
/// Returns true if left is exactly equal to right.
/// </summary>
XLNT_API friend bool operator==(const gradient_fill &left, const gradient_fill &right);
bool operator==(const gradient_fill &other) const;
/// <summary>
/// Returns true if left is not exactly equal to right.
/// </summary>
XLNT_API friend bool operator!=(const gradient_fill &left, const gradient_fill &right)
{
return !(left == right);
}
bool operator!=(const gradient_fill &right) const;
private:
/// <summary>
@ -347,29 +342,26 @@ public:
/// <summary>
/// Returns true if left is exactly equal to right.
/// </summary>
XLNT_API friend bool operator==(const fill &left, const fill &right);
bool operator==(const fill &other) const;
/// <summary>
/// Returns true if left is not exactly equal to right.
/// </summary>
XLNT_API friend bool operator!=(const fill &left, const fill &right)
{
return !(left == right);
}
bool operator!=(const fill &other) const;
private:
/// <summary>
///
/// The type of this fill
/// </summary>
fill_type type_ = fill_type::pattern;
/// <summary>
///
/// The internal gradient fill if this is a gradient fill type
/// </summary>
xlnt::gradient_fill gradient_;
/// <summary>
///
/// The internal pattern fill if this is a pattern fill type
/// </summary>
xlnt::pattern_fill pattern_;
};

View File

@ -2950,7 +2950,7 @@ void xlsx_producer::write_relationships(const std::vector<xlnt::relationship> &r
void xlsx_producer::write_color(const xlnt::color &color)
{
if (color.is_auto())
if (color.auto_())
{
write_attribute("auto", write_bool(true));
return;

View File

@ -28,114 +28,47 @@
#include <xlnt/styles/color.hpp>
#include <xlnt/utils/exceptions.hpp>
namespace {
std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string)
{
auto x = std::strtoul(hex_string.c_str(), NULL, 16);
auto a = static_cast<std::uint8_t>(x >> 24);
auto r = static_cast<std::uint8_t>((x >> 16) & 0xff);
auto g = static_cast<std::uint8_t>((x >> 8) & 0xff);
auto b = static_cast<std::uint8_t>(x & 0xff);
return { { r, g, b, a } };
}
} // namespace
namespace xlnt {
indexed_color::indexed_color(std::size_t index)
: index_(index)
// indexed_color implementation
indexed_color::indexed_color(std::size_t index) : index_(index)
{
}
theme_color::theme_color(std::size_t index)
: index_(index)
std::size_t indexed_color::index() const
{
return index_;
}
// theme_color implementation
theme_color::theme_color(std::size_t index) : index_(index)
{
}
const color color::black()
std::size_t theme_color::index() const
{
return color(rgb_color("ff000000"));
return index_;
}
const color color::white()
{
return color(rgb_color("ffffffff"));
}
const color color::red()
{
return color(rgb_color("ffff0000"));
}
const color color::darkred()
{
return color(rgb_color("ff8b0000"));
}
const color color::blue()
{
return color(rgb_color("ff0000ff"));
}
const color color::darkblue()
{
return color(rgb_color("ff00008b"));
}
const color color::green()
{
return color(rgb_color("ff00ff00"));
}
const color color::darkgreen()
{
return color(rgb_color("ff008b00"));
}
const color color::yellow()
{
return color(rgb_color("ffffff00"));
}
const color color::darkyellow()
{
return color(rgb_color("ffcccc00"));
}
color::color()
: type_(color_type::indexed), rgb_(rgb_color(0, 0, 0, 0)), indexed_(0), theme_(0), tint_(0), auto__(false)
{
}
color::color(const rgb_color &rgb)
: type_(color_type::rgb), rgb_(rgb), indexed_(0), theme_(0), tint_(0), auto__(false)
{
}
color::color(const indexed_color &indexed)
: type_(color_type::indexed), rgb_(rgb_color(0, 0, 0, 0)), indexed_(indexed), theme_(0), tint_(0), auto__(false)
{
}
color::color(const theme_color &theme)
: type_(color_type::theme), rgb_(rgb_color(0, 0, 0, 0)), indexed_(0), theme_(theme), tint_(0), auto__(false)
{
}
color_type color::type() const
{
return type_;
}
bool color::is_auto() const
{
return auto__;
}
void color::auto_(bool value)
{
auto__ = value;
}
const indexed_color &color::indexed() const
{
assert_type(color_type::indexed);
return indexed_;
}
const theme_color &color::theme() const
{
assert_type(color_type::theme);
return theme_;
}
// rgb_color implementation
std::string rgb_color::hex_string() const
{
@ -155,18 +88,6 @@ std::string rgb_color::hex_string() const
return hex_string;
}
std::array<std::uint8_t, 4> rgb_color::decode_hex_string(const std::string &hex_string)
{
auto x = std::strtoul(hex_string.c_str(), NULL, 16);
auto a = static_cast<std::uint8_t>(x >> 24);
auto r = static_cast<std::uint8_t>((x >> 16) & 0xff);
auto g = static_cast<std::uint8_t>((x >> 8) & 0xff);
auto b = static_cast<std::uint8_t>(x & 0xff);
return {{r, g, b, a}};
}
rgb_color::rgb_color(const std::string &hex_string)
: rgba_(decode_hex_string(hex_string))
{
@ -177,17 +98,144 @@ rgb_color::rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_
{
}
std::size_t indexed_color::index() const
std::uint8_t rgb_color::red() const
{
return index_;
return rgba_[0];
}
std::size_t theme_color::index() const
std::uint8_t rgb_color::green() const
{
return index_;
return rgba_[1];
}
const rgb_color &color::rgb() const
std::uint8_t rgb_color::blue() const
{
return rgba_[2];
}
std::uint8_t rgb_color::alpha() const
{
return rgba_[3];
}
std::array<std::uint8_t, 3> rgb_color::rgb() const
{
return { red(), green(), blue() };
}
std::array<std::uint8_t, 4> rgb_color::rgba() const
{
return rgba_;
}
// color implementation
const color color::black()
{
return color(rgb_color("ff000000"));
}
const color color::white()
{
return color(rgb_color("ffffffff"));
}
const color color::red()
{
return color(rgb_color("ffff0000"));
}
const color color::darkred()
{
return color(rgb_color("ff8b0000"));
}
const color color::blue()
{
return color(rgb_color("ff0000ff"));
}
const color color::darkblue()
{
return color(rgb_color("ff00008b"));
}
const color color::green()
{
return color(rgb_color("ff00ff00"));
}
const color color::darkgreen()
{
return color(rgb_color("ff008b00"));
}
const color color::yellow()
{
return color(rgb_color("ffffff00"));
}
const color color::darkyellow()
{
return color(rgb_color("ffcccc00"));
}
color::color() : color(indexed_color(0))
{
}
color::color(const rgb_color &rgb)
: type_(color_type::rgb),
rgb_(rgb),
indexed_(0),
theme_(0)
{
}
color::color(const indexed_color &indexed)
: type_(color_type::indexed),
rgb_(rgb_color(0, 0, 0, 0)),
indexed_(indexed),
theme_(0)
{
}
color::color(const theme_color &theme)
: type_(color_type::theme),
rgb_(rgb_color(0, 0, 0, 0)),
indexed_(0),
theme_(theme)
{
}
color_type color::type() const
{
return type_;
}
bool color::auto_() const
{
return auto__;
}
void color::auto_(bool value)
{
auto__ = value;
}
indexed_color color::indexed() const
{
assert_type(color_type::indexed);
return indexed_;
}
theme_color color::theme() const
{
assert_type(color_type::theme);
return theme_;
}
rgb_color color::rgb() const
{
assert_type(color_type::rgb);
return rgb_;
@ -198,6 +246,11 @@ void color::tint(double tint)
tint_ = tint;
}
double color::tint() const
{
return tint_;
}
void color::assert_type(color_type t) const
{
if (t != type_)
@ -206,7 +259,7 @@ void color::assert_type(color_type t) const
}
}
XLNT_API bool color::operator==(const xlnt::color &other) const
bool color::operator==(const xlnt::color &other) const
{
if (type_ != other.type_ || std::fabs(tint_ - other.tint_) != 0.0 || auto__ != other.auto__)
{
@ -226,4 +279,9 @@ XLNT_API bool color::operator==(const xlnt::color &other) const
return false;
}
bool color::operator!=(const color &other) const
{
return !(*this == other);
}
} // namespace xlnt

View File

@ -73,35 +73,35 @@ pattern_fill &pattern_fill::background(const color &new_background)
return *this;
}
XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right)
bool pattern_fill::operator==(const pattern_fill &other) const
{
if (left.background().is_set() != right.background().is_set())
if (background().is_set() != other.background().is_set())
{
return false;
}
if (left.background().is_set())
if (background().is_set())
{
if (left.background().get() != right.background().get())
if (background().get() != other.background().get())
{
return false;
}
}
if (left.foreground().is_set() != right.foreground().is_set())
if (foreground().is_set() != other.foreground().is_set())
{
return false;
}
if (left.foreground().is_set())
if (foreground().is_set())
{
if (left.foreground().get() != right.foreground().get())
if (foreground().get() != other.foreground().get())
{
return false;
}
}
if (left.type() != right.type())
if (type() != other.type())
{
return false;
}
@ -109,10 +109,14 @@ XLNT_API bool operator==(const pattern_fill &left, const pattern_fill &right)
return true;
}
bool pattern_fill::operator!=(const pattern_fill &other) const
{
return !(*this == other);
}
// gradient_fill
gradient_fill::gradient_fill()
: type_(gradient_fill_type::linear)
gradient_fill::gradient_fill() : type_(gradient_fill_type::linear)
{
}
@ -199,39 +203,39 @@ std::unordered_map<double, color> gradient_fill::stops() const
return stops_;
}
XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right)
bool gradient_fill::operator==(const gradient_fill &other) const
{
if (left.type() != right.type())
if (type() != other.type())
{
return false;
}
if (std::fabs(left.degree() - right.degree()) != 0.)
if (std::fabs(degree() - other.degree()) != 0.)
{
return false;
}
if (std::fabs(left.bottom() - right.bottom()) != 0.)
if (std::fabs(bottom() - other.bottom()) != 0.)
{
return false;
}
if (std::fabs(left.right() - right.right()) != 0.)
if (std::fabs(right() - other.right()) != 0.)
{
return false;
}
if (std::fabs(left.top() - right.top()) != 0.)
if (std::fabs(top() - other.top()) != 0.)
{
return false;
}
if (std::fabs(left.left() - right.left()) != 0.)
if (std::fabs(left() - other.left()) != 0.)
{
return false;
}
if (left.stops() != right.stops())
if (stops() != other.stops())
{
return false;
}
@ -239,6 +243,11 @@ XLNT_API bool operator==(const gradient_fill &left, const gradient_fill &right)
return true;
}
bool gradient_fill::operator!=(const gradient_fill &other) const
{
return !(*this == other);
}
// fill
fill fill::solid(const color &fill_color)
@ -287,19 +296,24 @@ pattern_fill fill::pattern_fill() const
return pattern_;
}
XLNT_API bool operator==(const fill &left, const fill &right)
bool fill::operator==(const fill &other) const
{
if (left.type() != right.type())
if (type() != other.type())
{
return false;
}
if (left.type() == fill_type::gradient)
if (type() == fill_type::gradient)
{
return left.gradient_fill() == right.gradient_fill();
return gradient_fill() == other.gradient_fill();
}
return left.pattern_fill() == right.pattern_fill();
return pattern_fill() == other.pattern_fill();
}
bool fill::operator!=(const fill &other) const
{
return !(*this == other);
}
} // namespace xlnt

View File

@ -33,13 +33,13 @@ public:
void test_non_rgb_colors()
{
xlnt::color indexed = xlnt::indexed_color(1);
TS_ASSERT(!indexed.is_auto());
TS_ASSERT(!indexed.auto_());
TS_ASSERT_EQUALS(indexed.indexed().index(), 1);
TS_ASSERT_THROWS(indexed.theme(), xlnt::invalid_attribute);
TS_ASSERT_THROWS(indexed.rgb(), xlnt::invalid_attribute);
xlnt::color theme = xlnt::theme_color(3);
TS_ASSERT(!theme.is_auto());
TS_ASSERT(!theme.auto_());
TS_ASSERT_EQUALS(theme.theme().index(), 3);
TS_ASSERT_THROWS(theme.indexed(), xlnt::invalid_attribute);
TS_ASSERT_THROWS(theme.rgb(), xlnt::invalid_attribute);