improve fill and style serialization test coverage

This commit is contained in:
Thomas Fussell 2016-07-14 22:09:57 -04:00
parent 64c95aa7c5
commit 25b995bc78
7 changed files with 625 additions and 325 deletions

View File

@ -23,69 +23,47 @@
// @author: see AUTHORS file // @author: see AUTHORS file
#pragma once #pragma once
#include <unordered_map>
#include <xlnt/xlnt_config.hpp> #include <xlnt/xlnt_config.hpp>
#include <xlnt/styles/color.hpp> #include <xlnt/styles/color.hpp>
#include <xlnt/utils/optional.hpp> #include <xlnt/utils/optional.hpp>
namespace xlnt { namespace xlnt {
/// <summary> class pattern_fill : public hashable
/// Describes the fill style of a particular cell.
/// </summary>
class XLNT_CLASS fill : public hashable
{ {
public: public:
enum class type enum class type
{ {
none, none,
solid, solid,
gradient,
pattern
};
enum class gradient_type
{
none,
linear,
path
};
enum class pattern_type
{
none,
solid,
darkdown,
darkgray,
darkgrid,
darkhorizontal,
darktrellis,
darkup,
darkvertical,
gray0625,
gray125,
lightdown,
lightgray,
lightgrid,
lighthorizontal,
lighttrellis,
lightup,
lightvertical,
mediumgray, mediumgray,
darkgray,
lightgray,
darkhorizontal,
darkvertical,
darkdown,
darkup,
darkgrid,
darktrellis,
lighthorizontal,
lightvertical,
lightdown,
lightup,
lightgrid,
lighttrellis,
gray125,
gray0625
}; };
fill(); pattern_fill();
pattern_fill(type pattern_type);
type get_type() const; type get_type() const;
void set_type(type t); void set_type(type pattern_type);
pattern_type get_pattern_type() const;
void set_pattern_type(pattern_type t);
gradient_type get_gradient_type() const;
void set_gradient_type(gradient_type t);
void set_foreground_color(const color &c); void set_foreground_color(const color &c);
@ -99,49 +77,110 @@ public:
const std::experimental::optional<color> &get_background_color() const; const std::experimental::optional<color> &get_background_color() const;
void set_start_color(const color &c); protected:
std::string to_hash_string() const override;
std::experimental::optional<color> &get_start_color(); private:
type type_ = type::none;
const std::experimental::optional<color> &get_start_color() const; std::experimental::optional<color> foreground_color_;
std::experimental::optional<color> background_color_;
};
void set_end_color(const color &c); class gradient_fill : public hashable
{
public:
enum class type
{
linear,
path
};
std::experimental::optional<color> &get_end_color(); gradient_fill();
const std::experimental::optional<color> &get_end_color() const; gradient_fill(type gradient_type);
void set_rotation(double rotation); type get_type() const;
double get_rotation() const; void set_type(type gradient_type);
void set_degree(double degree);
double get_degree() const;
double get_gradient_left() const; double get_gradient_left() const;
void set_gradient_left(double value);
double get_gradient_right() const; double get_gradient_right() const;
void set_gradient_right(double value);
double get_gradient_top() const; double get_gradient_top() const;
void set_gradient_top(double value);
double get_gradient_bottom() const; double get_gradient_bottom() const;
void set_gradient_bottom(double value);
void add_stop(double position, color stop_color);
void delete_stop(double position);
void clear_stops();
const std::unordered_map<double, color> &get_stops() const;
protected: protected:
std::string to_hash_string() const override; std::string to_hash_string() const override;
private: private:
type type_; type type_ = type::linear;
pattern_type pattern_type_;
gradient_type gradient_type_; std::unordered_map<double, color> stops_;
double rotation_; double degree_ = 0;
std::experimental::optional<color> foreground_color_; double left_ = 0;
std::experimental::optional<color> background_color_; double right_ = 0;
std::experimental::optional<color> start_color_; double top_ = 0;
std::experimental::optional<color> end_color_; double bottom_ = 0;
};
double gradient_path_left_;
double gradient_path_right_; /// <summary>
double gradient_path_top_; /// Describes the fill style of a particular cell.
double gradient_path_bottom_; /// </summary>
class XLNT_CLASS fill : public hashable
{
public:
enum class type
{
pattern,
gradient
};
static fill gradient(gradient_fill::type gradient_type);
static fill pattern(pattern_fill::type pattern_type);
type get_type() const;
gradient_fill &get_gradient_fill();
const gradient_fill &get_gradient_fill() const;
pattern_fill &get_pattern_fill();
const pattern_fill &get_pattern_fill() const;
protected:
std::string to_hash_string() const override;
private:
type type_ = type::pattern;
gradient_fill gradient_;
pattern_fill pattern_;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -360,9 +360,8 @@ public:
auto ws = wb.create_sheet(); auto ws = wb.create_sheet();
auto cell = ws.get_cell("A1"); auto cell = ws.get_cell("A1");
xlnt::fill f; xlnt::fill f = xlnt::fill::pattern(xlnt::pattern_fill::type::solid);
f.set_pattern_type(xlnt::fill::pattern_type::solid); f.get_pattern_fill().set_foreground_color(xlnt::color::red());
f.set_foreground_color(xlnt::color(xlnt::color::type::rgb, "FF0000"));
cell.set_fill(f); cell.set_fill(f);

View File

@ -144,46 +144,46 @@ std::string underline_style_to_string(xlnt::font::underline_style underline_styl
// fill::pattern_type serialization // fill::pattern_type serialization
const std::unordered_map<std::string, xlnt::fill::pattern_type> &get_string_pattern_fill_type_map() const std::unordered_map<std::string, xlnt::pattern_fill::type> &get_string_pattern_fill_type_map()
{ {
static std::unordered_map<std::string, xlnt::fill::pattern_type> *map = nullptr; static std::unordered_map<std::string, xlnt::pattern_fill::type> *map = nullptr;
if (map == nullptr) if (map == nullptr)
{ {
map = new std::unordered_map<std::string, xlnt::fill::pattern_type> map = new std::unordered_map<std::string, xlnt::pattern_fill::type>
{ {
{ "darkdown", xlnt::fill::pattern_type::darkdown }, { "darkdown", xlnt::pattern_fill::type::darkdown },
{ "darkgray", xlnt::fill::pattern_type::darkgray }, { "darkgray", xlnt::pattern_fill::type::darkgray },
{ "darkgrid", xlnt::fill::pattern_type::darkgrid }, { "darkgrid", xlnt::pattern_fill::type::darkgrid },
{ "darkhorizontal", xlnt::fill::pattern_type::darkhorizontal }, { "darkhorizontal", xlnt::pattern_fill::type::darkhorizontal },
{ "darktrellis", xlnt::fill::pattern_type::darktrellis }, { "darktrellis", xlnt::pattern_fill::type::darktrellis },
{ "darkup", xlnt::fill::pattern_type::darkup }, { "darkup", xlnt::pattern_fill::type::darkup },
{ "darkvertical", xlnt::fill::pattern_type::darkvertical }, { "darkvertical", xlnt::pattern_fill::type::darkvertical },
{ "gray0625", xlnt::fill::pattern_type::gray0625 }, { "gray0625", xlnt::pattern_fill::type::gray0625 },
{ "gray125", xlnt::fill::pattern_type::gray125 }, { "gray125", xlnt::pattern_fill::type::gray125 },
{ "lightdown", xlnt::fill::pattern_type::lightdown }, { "lightdown", xlnt::pattern_fill::type::lightdown },
{ "lightgray", xlnt::fill::pattern_type::lightgray }, { "lightgray", xlnt::pattern_fill::type::lightgray },
{ "lightgrid", xlnt::fill::pattern_type::lightgrid }, { "lightgrid", xlnt::pattern_fill::type::lightgrid },
{ "lighthorizontal", xlnt::fill::pattern_type::lighthorizontal }, { "lighthorizontal", xlnt::pattern_fill::type::lighthorizontal },
{ "lighttrellis", xlnt::fill::pattern_type::lighttrellis }, { "lighttrellis", xlnt::pattern_fill::type::lighttrellis },
{ "lightup", xlnt::fill::pattern_type::lightup }, { "lightup", xlnt::pattern_fill::type::lightup },
{ "lightvertical", xlnt::fill::pattern_type::lightvertical }, { "lightvertical", xlnt::pattern_fill::type::lightvertical },
{ "mediumgray", xlnt::fill::pattern_type::mediumgray }, { "mediumgray", xlnt::pattern_fill::type::mediumgray },
{ "none", xlnt::fill::pattern_type::none }, { "none", xlnt::pattern_fill::type::none },
{ "solid", xlnt::fill::pattern_type::solid } { "solid", xlnt::pattern_fill::type::solid }
}; };
} }
return *map; return *map;
} }
const std::unordered_map<xlnt::fill::pattern_type, std::string, EnumClassHash> &get_pattern_fill_type_string_map() const std::unordered_map<xlnt::pattern_fill::type, std::string, EnumClassHash> &get_pattern_fill_type_string_map()
{ {
static std::unordered_map<xlnt::fill::pattern_type, std::string, EnumClassHash> *map = nullptr; static std::unordered_map<xlnt::pattern_fill::type, std::string, EnumClassHash> *map = nullptr;
if (map == nullptr) if (map == nullptr)
{ {
map = new std::unordered_map<xlnt::fill::pattern_type, std::string, EnumClassHash>; map = new std::unordered_map<xlnt::pattern_fill::type, std::string, EnumClassHash>;
for (auto pair : get_string_pattern_fill_type_map()) for (auto pair : get_string_pattern_fill_type_map())
{ {
@ -194,16 +194,61 @@ const std::unordered_map<xlnt::fill::pattern_type, std::string, EnumClassHash> &
return *map; return *map;
} }
xlnt::fill::pattern_type pattern_fill_type_from_string(const std::string &fill_type) xlnt::pattern_fill::type pattern_fill_type_from_string(const std::string &fill_type)
{ {
return get_string_pattern_fill_type_map().at(string_lower(fill_type)); return get_string_pattern_fill_type_map().at(string_lower(fill_type));
}; };
std::string pattern_fill_type_to_string(xlnt::fill::pattern_type fill_type) std::string pattern_fill_type_to_string(xlnt::pattern_fill::type fill_type)
{ {
return get_pattern_fill_type_string_map().at(fill_type); return get_pattern_fill_type_string_map().at(fill_type);
} }
// fill::gradient_type serialization
const std::unordered_map<std::string, xlnt::gradient_fill::type> &get_string_gradient_fill_type_map()
{
static std::unordered_map<std::string, xlnt::gradient_fill::type> *map = nullptr;
if (map == nullptr)
{
map = new std::unordered_map<std::string, xlnt::gradient_fill::type>
{
{ "linear", xlnt::gradient_fill::type::linear },
{ "path", xlnt::gradient_fill::type::path }
};
}
return *map;
}
const std::unordered_map<xlnt::gradient_fill::type, std::string, EnumClassHash> &get_gradient_fill_type_string_map()
{
static std::unordered_map<xlnt::gradient_fill::type, std::string, EnumClassHash> *map = nullptr;
if (map == nullptr)
{
map = new std::unordered_map<xlnt::gradient_fill::type, std::string, EnumClassHash>;
for (auto pair : get_string_gradient_fill_type_map())
{
map->emplace(pair.second, pair.first);
}
}
return *map;
}
xlnt::gradient_fill::type gradient_fill_type_from_string(const std::string &fill_type)
{
return get_string_gradient_fill_type_map().at(string_lower(fill_type));
};
std::string gradient_fill_type_to_string(xlnt::gradient_fill::type fill_type)
{
return get_gradient_fill_type_string_map().at(fill_type);
}
// border_style serialization // border_style serialization
@ -563,25 +608,41 @@ xlnt::fill read_fill(const pugi::xml_node &fill_node)
if (fill_node.child("patternFill")) if (fill_node.child("patternFill"))
{ {
new_fill.set_type(xlnt::fill::type::pattern);
auto pattern_fill_node = fill_node.child("patternFill"); auto pattern_fill_node = fill_node.child("patternFill");
std::string pattern_fill_type_string = pattern_fill_node.attribute("patternType").value(); std::string pattern_fill_type_string = pattern_fill_node.attribute("patternType").value();
if (!pattern_fill_type_string.empty()) if (!pattern_fill_type_string.empty())
{ {
new_fill.set_pattern_type(pattern_fill_type_from_string(pattern_fill_type_string)); new_fill = xlnt::fill::pattern(pattern_fill_type_from_string(pattern_fill_type_string));
if (pattern_fill_node.child("bgColor")) if (pattern_fill_node.child("bgColor"))
{ {
new_fill.get_background_color() = read_color(pattern_fill_node.child("bgColor")); new_fill.get_pattern_fill().get_background_color() = read_color(pattern_fill_node.child("bgColor"));
} }
if (pattern_fill_node.child("fgColor")) if (pattern_fill_node.child("fgColor"))
{ {
new_fill.get_foreground_color() = read_color(pattern_fill_node.child("fgColor")); new_fill.get_pattern_fill().get_foreground_color() = read_color(pattern_fill_node.child("fgColor"));
} }
} }
else
{
new_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::none);
}
}
else if (fill_node.child("gradientFill"))
{
auto gradient_fill_node = fill_node.child("gradientFill");
std::string gradient_fill_type_string = gradient_fill_node.attribute("gradientType").value();
if (!gradient_fill_type_string.empty())
{
new_fill = xlnt::fill::gradient(gradient_fill_type_from_string(gradient_fill_type_string));
}
else
{
new_fill = xlnt::fill::gradient(xlnt::gradient_fill::type::linear);
}
} }
return new_fill; return new_fill;
@ -895,46 +956,59 @@ bool write_fills(const std::vector<xlnt::fill> &fills, pugi::xml_node &fills_nod
if (fill_.get_type() == xlnt::fill::type::pattern) if (fill_.get_type() == xlnt::fill::type::pattern)
{ {
const auto &pattern = fill_.get_pattern_fill();
auto pattern_fill_node = fill_node.append_child("patternFill"); auto pattern_fill_node = fill_node.append_child("patternFill");
pattern_fill_node.append_attribute("patternType").set_value(pattern_fill_type_to_string(fill_.get_pattern_type()).c_str()); pattern_fill_node.append_attribute("patternType").set_value(pattern_fill_type_to_string(pattern.get_type()).c_str());
if (fill_.get_pattern_type() != xlnt::fill::pattern_type::solid) continue;
if (fill_.get_foreground_color()) if (pattern.get_foreground_color())
{ {
write_color(*fill_.get_foreground_color(), pattern_fill_node.append_child("fgColor")); write_color(*pattern.get_foreground_color(), pattern_fill_node.append_child("fgColor"));
} }
if (fill_.get_background_color()) if (pattern.get_background_color())
{ {
write_color(*fill_.get_background_color(), pattern_fill_node.append_child("bgColor")); write_color(*pattern.get_background_color(), pattern_fill_node.append_child("bgColor"));
} }
} }
else if (fill_.get_type() == xlnt::fill::type::solid)
{
auto solid_fill_node = fill_node.append_child("solidFill");
solid_fill_node.append_child("color");
}
else if (fill_.get_type() == xlnt::fill::type::gradient) else if (fill_.get_type() == xlnt::fill::type::gradient)
{ {
const auto &gradient = fill_.get_gradient_fill();
auto gradient_fill_node = fill_node.append_child("gradientFill"); auto gradient_fill_node = fill_node.append_child("gradientFill");
auto gradient_fill_type_string = gradient_fill_type_to_string(gradient.get_type());
gradient_fill_node.append_attribute("gradientType").set_value(gradient_fill_type_string.c_str());
if (fill_.get_gradient_type() == xlnt::fill::gradient_type::linear) if (gradient.get_degree() != 0)
{ {
gradient_fill_node.append_attribute("degree").set_value(std::to_string(fill_.get_rotation()).c_str()); gradient_fill_node.append_attribute("degree").set_value(gradient.get_degree());
} }
else if (fill_.get_gradient_type() == xlnt::fill::gradient_type::path)
if (gradient.get_gradient_left() != 0)
{ {
gradient_fill_node.append_attribute("left").set_value(std::to_string(fill_.get_gradient_left()).c_str()); gradient_fill_node.append_attribute("left").set_value(gradient.get_gradient_left());
gradient_fill_node.append_attribute("right").set_value(std::to_string(fill_.get_gradient_right()).c_str()); }
gradient_fill_node.append_attribute("top").set_value(std::to_string(fill_.get_gradient_top()).c_str());
gradient_fill_node.append_attribute("bottom").set_value(std::to_string(fill_.get_gradient_bottom()).c_str());
auto start_node = gradient_fill_node.append_child("stop"); if (gradient.get_gradient_right() != 0)
start_node.append_attribute("position").set_value("0"); {
gradient_fill_node.append_attribute("right").set_value(gradient.get_gradient_right());
}
auto end_node = gradient_fill_node.append_child("stop"); if (gradient.get_gradient_top() != 0)
end_node.append_attribute("position").set_value("1"); {
gradient_fill_node.append_attribute("top").set_value(gradient.get_gradient_top());
}
if (gradient.get_gradient_bottom() != 0)
{
gradient_fill_node.append_attribute("bottom").set_value(gradient.get_gradient_bottom());
}
for (const auto &stop : gradient.get_stops())
{
auto stop_node = gradient_fill_node.append_child("stop");
stop_node.append_attribute("position").set_value(stop.first);
write_color(stop.second, stop_node.append_child("color"));
} }
} }
} }
@ -989,6 +1063,41 @@ bool write_borders(const std::vector<xlnt::border> &borders, pugi::xml_node &bor
return true; return true;
} }
bool write_alignment(const xlnt::alignment &a, pugi::xml_node alignment_node)
{
if (a.has_vertical())
{
auto vertical = vertical_alignment_to_string(a.get_vertical());
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
}
if (a.has_horizontal())
{
auto horizontal = horizontal_alignment_to_string(a.get_horizontal());
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
}
if (a.get_wrap_text())
{
alignment_node.append_attribute("wrapText").set_value("1");
}
if (a.get_shrink_to_fit())
{
alignment_node.append_attribute("shrinkToFit").set_value("1");
}
return true;
}
bool write_protection(const xlnt::protection &p, pugi::xml_node protection_node)
{
protection_node.append_attribute("locked").set_value(p.get_locked() ? "1" : "0");
protection_node.append_attribute("hidden").set_value(p.get_hidden() ? "1" : "0");
return true;
}
bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, pugi::xml_node xf_node) bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::stylesheet &stylesheet, pugi::xml_node xf_node)
{ {
xf_node.append_attribute("numFmtId").set_value(std::to_string(xf.get_number_format().get_id()).c_str()); xf_node.append_attribute("numFmtId").set_value(std::to_string(xf.get_number_format().get_id()).c_str());
@ -1006,41 +1115,17 @@ bool write_base_format(const xlnt::base_format &xf, const xlnt::detail::styleshe
if(xf.fill_applied()) xf_node.append_attribute("applyFill").set_value("1"); if(xf.fill_applied()) xf_node.append_attribute("applyFill").set_value("1");
if(xf.font_applied()) xf_node.append_attribute("applyFont").set_value("1"); if(xf.font_applied()) xf_node.append_attribute("applyFont").set_value("1");
if(xf.border_applied()) xf_node.append_attribute("applyBorder").set_value("1"); if(xf.border_applied()) xf_node.append_attribute("applyBorder").set_value("1");
if(xf.alignment_applied()) xf_node.append_attribute("applyAlignment").set_value("1");
if(xf.protection_applied()) xf_node.append_attribute("applyProtection").set_value("1");
if (xf.alignment_applied()) if(xf.alignment_applied())
{ {
auto alignment_node = xf_node.append_child("alignment"); xf_node.append_attribute("applyAlignment").set_value("1");
write_alignment(xf.get_alignment(), xf_node.append_child("alignment"));
if (xf.get_alignment().has_vertical())
{
auto vertical = vertical_alignment_to_string(xf.get_alignment().get_vertical());
alignment_node.append_attribute("vertical").set_value(vertical.c_str());
}
if (xf.get_alignment().has_horizontal())
{
auto horizontal = horizontal_alignment_to_string(xf.get_alignment().get_horizontal());
alignment_node.append_attribute("horizontal").set_value(horizontal.c_str());
}
if (xf.get_alignment().get_wrap_text())
{
alignment_node.append_attribute("wrapText").set_value("1");
}
if (xf.get_alignment().get_shrink_to_fit())
{
alignment_node.append_attribute("shrinkToFit").set_value("1");
}
} }
if (xf.protection_applied()) if (xf.protection_applied())
{ {
auto protection_node = xf_node.append_child("protection"); xf_node.append_attribute("applyProtection").set_value("1");
protection_node.append_attribute("locked").set_value(xf.get_protection().get_locked() ? "1" : "0"); write_protection(xf.get_protection(), xf_node.append_child("protection"));
protection_node.append_attribute("hidden").set_value(xf.get_protection().get_hidden() ? "1" : "0");
} }
return true; return true;

View File

@ -26,103 +26,105 @@
namespace xlnt { namespace xlnt {
fill::fill()
: type_(type::pattern),
pattern_type_(pattern_type::none),
gradient_type_(gradient_type::none),
rotation_(0),
gradient_path_left_(0),
gradient_path_right_(0),
gradient_path_top_(0),
gradient_path_bottom_(0)
{
}
fill::type fill::get_type() const fill::type fill::get_type() const
{ {
return type_; return type_;
} }
void fill::set_type(type t) pattern_fill::type pattern_fill::get_type() const
{
return type_;
}
void pattern_fill::set_type(pattern_fill::type t)
{ {
type_ = t; type_ = t;
} }
fill::pattern_type fill::get_pattern_type() const gradient_fill::type gradient_fill::get_type() const
{ {
return pattern_type_; return type_;
} }
void fill::set_pattern_type(pattern_type t) void gradient_fill::set_type(gradient_fill::type t)
{ {
type_ = type::pattern; type_ = t;
pattern_type_ = t;
} }
fill::gradient_type fill::get_gradient_type() const void pattern_fill::set_foreground_color(const color &c)
{
return gradient_type_;
}
void fill::set_gradient_type(gradient_type t)
{
type_ = type::gradient;
gradient_type_ = t;
}
void fill::set_foreground_color(const color &c)
{ {
foreground_color_ = c; foreground_color_ = c;
} }
std::experimental::optional<color> &fill::get_foreground_color() std::experimental::optional<color> &pattern_fill::get_foreground_color()
{ {
return foreground_color_; return foreground_color_;
} }
const std::experimental::optional<color> &fill::get_foreground_color() const const std::experimental::optional<color> &pattern_fill::get_foreground_color() const
{ {
return foreground_color_; return foreground_color_;
} }
std::experimental::optional<color> &fill::get_background_color() void pattern_fill::set_background_color(const color &c)
{
background_color_ = c;
}
std::experimental::optional<color> &pattern_fill::get_background_color()
{ {
return background_color_; return background_color_;
} }
const std::experimental::optional<color> &fill::get_background_color() const const std::experimental::optional<color> &pattern_fill::get_background_color() const
{ {
return background_color_; return background_color_;
} }
std::experimental::optional<color> &fill::get_start_color() void gradient_fill::set_degree(double degree)
{ {
return start_color_; degree_ = degree;
} }
const std::experimental::optional<color> &fill::get_start_color() const double gradient_fill::get_degree() const
{ {
return start_color_; return degree_;
} }
std::experimental::optional<color> &fill::get_end_color() std::string pattern_fill::to_hash_string() const
{ {
return end_color_; std::string hash_string = "pattern_fill";
hash_string.append(background_color_ ? "1" : "0");
if (background_color_)
{
hash_string.append(std::to_string(background_color_->hash()));
}
hash_string.append(background_color_ ? "1" : "0");
if (background_color_)
{
hash_string.append(std::to_string(background_color_->hash()));
}
return hash_string;
} }
const std::experimental::optional<color> &fill::get_end_color() const std::string gradient_fill::to_hash_string() const
{ {
return end_color_; std::string hash_string = "gradient_fill";
}
void fill::set_rotation(double rotation) hash_string.append(std::to_string(static_cast<std::size_t>(type_)));
{ hash_string.append(std::to_string(stops_.size()));
rotation_ = rotation; hash_string.append(std::to_string(degree_));
} hash_string.append(std::to_string(left_));
hash_string.append(std::to_string(right_));
double fill::get_rotation() const hash_string.append(std::to_string(top_));
{ hash_string.append(std::to_string(bottom_));
return rotation_;
return hash_string;
} }
std::string fill::to_hash_string() const std::string fill::to_hash_string() const
@ -134,99 +136,154 @@ std::string fill::to_hash_string() const
switch (type_) switch (type_)
{ {
case type::pattern: case type::pattern:
{ hash_string.append(std::to_string(pattern_.hash()));
hash_string.append(std::to_string(static_cast<std::size_t>(pattern_type_)));
hash_string.append(background_color_ ? "1" : "0");
if (background_color_)
{
hash_string.append(std::to_string(background_color_->hash()));
}
hash_string.append(background_color_ ? "1" : "0");
if (background_color_)
{
hash_string.append(std::to_string(background_color_->hash()));
}
break; break;
}
case type::gradient: case type::gradient:
{ hash_string.append(std::to_string(gradient_.hash()));
hash_string.append(std::to_string(static_cast<std::size_t>(gradient_type_)));
if (gradient_type_ == gradient_type::path)
{
hash_string.append(std::to_string(gradient_path_left_));
hash_string.append(std::to_string(gradient_path_right_));
hash_string.append(std::to_string(gradient_path_top_));
hash_string.append(std::to_string(gradient_path_bottom_));
}
else if (gradient_type_ == gradient_type::linear)
{
hash_string.append(std::to_string(rotation_));
}
hash_string.append(start_color_ ? "1" : "0");
if (start_color_)
{
hash_string.append(std::to_string(start_color_->hash()));
}
hash_string.append(end_color_ ? "1" : "0");
if (end_color_)
{
hash_string.append(std::to_string(end_color_->hash()));
}
break; break;
}
default: default:
{
break; break;
}
} // switch (type_) } // switch (type_)
return hash_string; return hash_string;
} }
double fill::get_gradient_left() const double gradient_fill::get_gradient_left() const
{ {
return gradient_path_left_; return left_;
} }
double fill::get_gradient_right() const void gradient_fill::set_gradient_left(double value)
{ {
return gradient_path_right_; left_ = value;
} }
double fill::get_gradient_top() const double gradient_fill::get_gradient_right() const
{ {
return gradient_path_top_; return right_;
} }
double fill::get_gradient_bottom() const void gradient_fill::set_gradient_right(double value)
{ {
return gradient_path_bottom_; right_ = value;
} }
void fill::set_background_color(const color &c) double gradient_fill::get_gradient_top() const
{ {
background_color_ = c; return top_;
} }
void fill::set_start_color(const color &c) void gradient_fill::set_gradient_top(double value)
{ {
start_color_ = c; top_ = value;
} }
void fill::set_end_color(const color &c) double gradient_fill::get_gradient_bottom() const
{ {
end_color_ = c; return bottom_;
}
void gradient_fill::set_gradient_bottom(double value)
{
bottom_ = value;
}
fill fill::pattern(pattern_fill::type pattern_type)
{
fill f;
f.type_ = type::pattern;
f.pattern_ = pattern_fill(pattern_type);
return f;
}
fill fill::gradient(gradient_fill::type gradient_type)
{
fill f;
f.type_ = type::gradient;
f.gradient_ = gradient_fill(gradient_type);
return f;
}
pattern_fill::pattern_fill(type pattern_type) : type_(pattern_type)
{
}
pattern_fill::pattern_fill() : pattern_fill(type::none)
{
}
gradient_fill::gradient_fill(type gradient_type) : type_(gradient_type)
{
}
gradient_fill::gradient_fill() : gradient_fill(type::linear)
{
}
gradient_fill &fill::get_gradient_fill()
{
if (type_ != fill::type::gradient)
{
throw std::runtime_error("not gradient");
}
return gradient_;
}
const gradient_fill &fill::get_gradient_fill() const
{
if (type_ != fill::type::gradient)
{
throw std::runtime_error("not gradient");
}
return gradient_;
}
pattern_fill &fill::get_pattern_fill()
{
if (type_ != fill::type::pattern)
{
throw std::runtime_error("not pattern");
}
return pattern_;
}
const pattern_fill &fill::get_pattern_fill() const
{
if (type_ != fill::type::pattern)
{
throw std::runtime_error("not pattern");
}
return pattern_;
}
void gradient_fill::add_stop(double position, color stop_color)
{
stops_[position] = stop_color;
}
void gradient_fill::delete_stop(double position)
{
stops_.erase(stops_.find(position));
}
void gradient_fill::clear_stops()
{
stops_.clear();
}
const std::unordered_map<double, color> &gradient_fill::get_stops() const
{
return stops_;
} }
} // namespace xlnt } // namespace xlnt

View File

@ -12,66 +12,45 @@ public:
{ {
xlnt::fill fill; xlnt::fill fill;
TS_ASSERT_EQUALS(fill.get_gradient_type(), xlnt::fill::gradient_type::none); TS_ASSERT_EQUALS(fill.get_type(), xlnt::fill::type::pattern);
fill.set_gradient_type(xlnt::fill::gradient_type::linear); fill = xlnt::fill::gradient(xlnt::gradient_fill::type::linear);
TS_ASSERT_EQUALS(fill.get_gradient_type(), xlnt::fill::gradient_type::linear); TS_ASSERT_EQUALS(fill.get_type(), xlnt::fill::type::gradient);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_type(), xlnt::gradient_fill::type::linear);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_left(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_right(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_top(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_gradient_bottom(), 0);
TS_ASSERT_THROWS(fill.get_pattern_fill(), std::runtime_error);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_degree(), 0);
fill.get_gradient_fill().set_degree(1);
TS_ASSERT_EQUALS(fill.get_gradient_fill().get_degree(), 1);
fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid);
fill.get_pattern_fill().set_foreground_color(xlnt::color::black());
TS_ASSERT(fill.get_pattern_fill().get_foreground_color());
TS_ASSERT_EQUALS(*fill.get_pattern_fill().get_foreground_color(), xlnt::color::black());
TS_ASSERT(!fill.get_foreground_color()); fill.get_pattern_fill().set_background_color(xlnt::color::green());
fill.set_foreground_color(xlnt::color::black()); TS_ASSERT(fill.get_pattern_fill().get_background_color());
TS_ASSERT(fill.get_foreground_color()); TS_ASSERT_EQUALS(*fill.get_pattern_fill().get_background_color(), xlnt::color::green());
TS_ASSERT(!fill.get_background_color());
fill.set_background_color(xlnt::color::black());
TS_ASSERT(fill.get_background_color());
TS_ASSERT(!fill.get_start_color());
fill.set_start_color(xlnt::color::black());
TS_ASSERT(fill.get_start_color());
TS_ASSERT(!fill.get_end_color());
fill.set_end_color(xlnt::color::black());
TS_ASSERT(fill.get_end_color());
TS_ASSERT_EQUALS(fill.get_rotation(), 0);
fill.set_rotation(1);
TS_ASSERT_EQUALS(fill.get_rotation(), 1);
TS_ASSERT_EQUALS(fill.get_gradient_bottom(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_left(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_top(), 0);
TS_ASSERT_EQUALS(fill.get_gradient_right(), 0);
const auto &const_fill = fill; const auto &const_fill = fill;
TS_ASSERT(const_fill.get_foreground_color()); TS_ASSERT(const_fill.get_pattern_fill().get_foreground_color());
TS_ASSERT(const_fill.get_background_color()); TS_ASSERT(const_fill.get_pattern_fill().get_background_color());
TS_ASSERT(const_fill.get_start_color());
TS_ASSERT(const_fill.get_end_color());
} }
void test_hash() void test_hash()
{ {
xlnt::fill none_fill; xlnt::fill pattern_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid);
xlnt::fill gradient_fill_linear = xlnt::fill::gradient(xlnt::gradient_fill::type::linear);
xlnt::fill gradient_fill_path = xlnt::fill::gradient(xlnt::gradient_fill::type::path);
xlnt::fill solid_fill;
solid_fill.set_type(xlnt::fill::type::solid);
xlnt::fill pattern_fill;
pattern_fill.set_type(xlnt::fill::type::pattern);
xlnt::fill gradient_fill_linear;
gradient_fill_linear.set_type(xlnt::fill::type::gradient);
gradient_fill_linear.set_gradient_type(xlnt::fill::gradient_type::linear);
xlnt::fill gradient_fill_path;
gradient_fill_path.set_type(xlnt::fill::type::gradient);
gradient_fill_path.set_gradient_type(xlnt::fill::gradient_type::path);
gradient_fill_path.set_start_color(xlnt::color::red());
gradient_fill_path.set_end_color(xlnt::color::green());
TS_ASSERT_DIFFERS(none_fill.hash(), solid_fill.hash());
TS_ASSERT_DIFFERS(solid_fill.hash(), pattern_fill.hash());
TS_ASSERT_DIFFERS(pattern_fill.hash(), gradient_fill_linear.hash()); TS_ASSERT_DIFFERS(pattern_fill.hash(), gradient_fill_linear.hash());
TS_ASSERT_DIFFERS(gradient_fill_linear.hash(), gradient_fill_path.hash()); TS_ASSERT_DIFFERS(gradient_fill_linear.hash(), gradient_fill_path.hash());
TS_ASSERT_DIFFERS(gradient_fill_path.hash(), none_fill.hash()); TS_ASSERT_DIFFERS(gradient_fill_path.hash(), pattern_fill.hash());
} }
}; };

View File

@ -214,4 +214,147 @@ public:
TS_ASSERT(style_xml_matches(expected, wb)); TS_ASSERT(style_xml_matches(expected, wb));
} }
void test_alignment()
{
xlnt::workbook wb;
xlnt::alignment a;
a.set_horizontal(xlnt::horizontal_alignment::center_continuous);
a.set_vertical(xlnt::vertical_alignment::justify);
a.set_wrap_text(true);
a.set_shrink_to_fit(true);
wb.get_active_sheet().get_cell("A1").set_alignment(a);
std::string expected =
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">"
" <fonts count=\"1\">"
" <font>"
" <sz val=\"12\"/>"
" <color theme=\"1\"/>"
" <name val=\"Calibri\"/>"
" <family val=\"2\"/>"
" <scheme val=\"minor\"/>"
" </font>"
" </fonts>"
" <fills count=\"2\">"
" <fill>"
" <patternFill patternType=\"none\"/>"
" </fill>"
" <fill>"
" <patternFill patternType=\"gray125\"/>"
" </fill>"
" </fills>"
" <borders count=\"1\">"
" <border>"
" <left/>"
" <right/>"
" <top/>"
" <bottom/>"
" <diagonal/>"
" </border>"
" </borders>"
" <cellStyleXfs count=\"1\">"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>"
" </cellStyleXfs>"
" <cellXfs count=\"2\">"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\">"
" <alignment vertical=\"justify\" horizontal=\"center-continuous\" wrapText=\"1\" shrinkToFit=\"1\"/>"
" </xf>"
" </cellXfs>"
" <cellStyles count=\"1\">"
" <cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>"
" </cellStyles>"
" <dxfs count=\"0\"/>"
" <tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\" defaultPivotStyle=\"PivotStyleMedium7\"/>"
"</styleSheet>";
TS_ASSERT(style_xml_matches(expected, wb));
}
void test_fill()
{
xlnt::workbook wb;
xlnt::fill pattern_fill = xlnt::fill::pattern(xlnt::pattern_fill::type::solid);
pattern_fill.get_pattern_fill().set_foreground_color(xlnt::color::red());
pattern_fill.get_pattern_fill().set_background_color(xlnt::color::blue());
wb.get_active_sheet().get_cell("A1").set_fill(pattern_fill);
xlnt::fill gradient_fill_linear = xlnt::fill::gradient(xlnt::gradient_fill::type::linear);
gradient_fill_linear.get_gradient_fill().set_degree(90);
wb.get_active_sheet().get_cell("A1").set_fill(gradient_fill_linear);
xlnt::fill gradient_fill_path = xlnt::fill::gradient(xlnt::gradient_fill::type::path);
gradient_fill_path.get_gradient_fill().set_gradient_left(1);
gradient_fill_path.get_gradient_fill().set_gradient_right(2);
gradient_fill_path.get_gradient_fill().set_gradient_top(3);
gradient_fill_path.get_gradient_fill().set_gradient_bottom(4);
gradient_fill_path.get_gradient_fill().add_stop(0, xlnt::color::red());
gradient_fill_path.get_gradient_fill().add_stop(1, xlnt::color::blue());
wb.get_active_sheet().get_cell("A1").set_fill(gradient_fill_path);
std::string expected =
"<styleSheet xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\" xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\" xmlns:x14ac=\"http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac\" mc:Ignorable=\"x14ac\">"
" <fonts count=\"1\">"
" <font>"
" <sz val=\"12\"/>"
" <color theme=\"1\"/>"
" <name val=\"Calibri\"/>"
" <family val=\"2\"/>"
" <scheme val=\"minor\"/>"
" </font>"
" </fonts>"
" <fills count=\"5\">"
" <fill>"
" <patternFill patternType=\"none\"/>"
" </fill>"
" <fill>"
" <patternFill patternType=\"gray125\"/>"
" </fill>"
" <fill>"
" <patternFill patternType=\"solid\">"
" <fgColor rgb=\"ffff0000\"/>"
" <bgColor rgb=\"ff0000ff\"/>"
" </patternFill>"
" </fill>"
" <fill>"
" <gradientFill gradientType=\"linear\" degree=\"90\"/>"
" </fill>"
" <fill>"
" <gradientFill gradientType=\"path\" left=\"1\" right=\"2\" top=\"3\" bottom=\"4\">"
" <stop position=\"0\">"
" <color rgb=\"ff00ff00\"/>"
" </stop>"
" <stop position=\"1\">"
" <color rgb=\"ffffff00\"/>"
" </stop>"
" </gradientFill>"
" </fill>"
" </fills>"
" <borders count=\"1\">"
" <border>"
" <left/>"
" <right/>"
" <top/>"
" <bottom/>"
" <diagonal/>"
" </border>"
" </borders>"
" <cellStyleXfs count=\"1\">"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\"/>"
" </cellStyleXfs>"
" <cellXfs count=\"2\">"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"0\" borderId=\"0\" xfId=\"0\"/>"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"2\" borderId=\"0\" xfId=\"0\"/>"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"3\" borderId=\"0\" xfId=\"0\"/>"
" <xf numFmtId=\"0\" fontId=\"0\" fillId=\"4\" borderId=\"0\" xfId=\"0\"/>"
" </cellXfs>"
" <cellStyles count=\"1\">"
" <cellStyle name=\"Normal\" xfId=\"0\" builtinId=\"0\"/>"
" </cellStyles>"
" <dxfs count=\"0\"/>"
" <tableStyles count=\"0\" defaultTableStyle=\"TableStyleMedium9\" defaultPivotStyle=\"PivotStyleMedium7\"/>"
"</styleSheet>";
TS_ASSERT(style_xml_matches(expected, wb));
}
}; };

View File

@ -92,9 +92,7 @@ workbook::workbook() : d_(new detail::workbook_impl())
create_style("Normal"); create_style("Normal");
d_->stylesheet_.format_styles.front() = "Normal"; d_->stylesheet_.format_styles.front() = "Normal";
xlnt::fill gray125; xlnt::fill gray125 = xlnt::fill::pattern(xlnt::pattern_fill::type::gray125);
gray125.set_type(xlnt::fill::type::pattern);
gray125.set_pattern_type(xlnt::fill::pattern_type::gray125);
d_->stylesheet_.fills.push_back(gray125); d_->stylesheet_.fills.push_back(gray125);
} }