clean up style reading and writing, add travis config

This commit is contained in:
Thomas Fussell 2015-10-26 15:57:37 -04:00
parent dfe9b1e013
commit de48eeb2eb
9 changed files with 269 additions and 388 deletions

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
bin/ bin/
lib/ lib/
build/premake/*/ build/genie/*/
build/cmake/build/
docs/_*/ docs/_*/
docs/doxyxml/ docs/doxyxml/
*.obj *.obj

8
.travis.yml Normal file
View File

@ -0,0 +1,8 @@
language: C++
compiler:
- clang
- gcc
script:
- mkdir build/cmake/build && cd build/cmake/build && cmake .. && make && cd ../../../bin && xlnt.test
install: ./build/install-dependencies.sh

3
build/install-dependencies.sh Executable file
View File

@ -0,0 +1,3 @@
cd ..
git submodule init
git submodule update

View File

@ -70,6 +70,7 @@ public:
type get_type() const { return type_; } type get_type() const { return type_; }
void set_type(type t) { type_ = t; } void set_type(type t) { type_ = t; }
std::string get_pattern_type_string() const std::string get_pattern_type_string() const
{ {
if(type_ != type::pattern) if(type_ != type::pattern)
@ -101,12 +102,50 @@ public:
default: throw std::runtime_error("invalid type"); default: throw std::runtime_error("invalid type");
} }
} }
std::string get_gradient_type_string() const
{
if(type_ != type::gradient)
{
throw std::runtime_error("not gradient fill");
}
switch(gradient_type_)
{
case gradient_type::linear: return "linear";
case gradient_type::path: return "path";
default: throw std::runtime_error("invalid type");
}
}
pattern_type get_pattern_type() const pattern_type get_pattern_type() const
{ {
return pattern_type_; return pattern_type_;
} }
void set_pattern_type(pattern_type t) { pattern_type_ = t; }
void set_gradient_type(gradient_type t) { gradient_type_ = t; } void set_pattern_type(pattern_type t)
{
type_ = type::pattern;
pattern_type_ = t;
}
void set_gradient_type(gradient_type t)
{
type_ = type::gradient;
gradient_type_ = t;
}
void set_start_color(const color &c)
{
start_color_ = c;
start_color_assigned_ = true;
}
void set_end_color(const color &c)
{
end_color_ = c;
end_color_assigned_ = true;
}
void set_foreground_color(const color &c) void set_foreground_color(const color &c)
{ {
@ -145,6 +184,16 @@ public:
return hash() == other.hash(); return hash() == other.hash();
} }
void set_rotation(double rotation)
{
rotation_ = rotation;
}
double get_rotation() const
{
return rotation_;
}
std::size_t hash() const std::size_t hash() const
{ {
auto seed = static_cast<std::size_t>(type_); auto seed = static_cast<std::size_t>(type_);
@ -157,17 +206,28 @@ public:
return seed; return seed;
} }
double get_gradient_left() const { return gradient_path_left_; }
double get_gradient_right() const { return gradient_path_right_; }
double get_gradient_top() const { return gradient_path_top_; }
double get_gradient_bottom() const { return gradient_path_bottom_; }
private: private:
type type_ = type::none; type type_ = type::none;
pattern_type pattern_type_; pattern_type pattern_type_;
gradient_type gradient_type_; gradient_type gradient_type_;
int rotation_ = 0; double rotation_ = 0;
bool foreground_color_assigned_ = false; bool foreground_color_assigned_ = false;
color foreground_color_ = color::black; color foreground_color_ = color::black;
bool background_color_assigned_ = false; bool background_color_assigned_ = false;
color background_color_ = color::white; color background_color_ = color::white;
bool start_color_assigned_ = false;
color start_color_ = color::white; color start_color_ = color::white;
bool end_color_assigned_ = false;
color end_color_ = color::black; color end_color_ = color::black;
double gradient_path_left_ = 0;
double gradient_path_right_ = 0;
double gradient_path_top_ = 0;
double gradient_path_bottom_ = 0;
}; };
} // namespace xlnt } // namespace xlnt

View File

@ -305,21 +305,6 @@ const std::unordered_map<int, std::string> known_locales =
{0x3801, "Arabic - United Arab Emirates"}, {0x3801, "Arabic - United Arab Emirates"},
{0x4001, "Arabic - Qatar"} {0x4001, "Arabic - Qatar"}
}; };
std::string get_currency_symbol(const std::string &locale_string)
{
if(locale_string.substr(1, 1) == "$")
{
return "$";
}
else if(locale_string.substr(1, 3) == "")
{
return "";
}
// auto code_page = std::stoi(locale_string.substr(3), nullptr, 16);
throw std::runtime_error("locale specific characters aren't supported yet");
}
bool is_valid_locale(const std::string &locale_string) bool is_valid_locale(const std::string &locale_string)
{ {

View File

@ -296,6 +296,99 @@ void style_reader::read_fills(pugi::xml_node fills_node)
fills_.push_back(new_fill); fills_.push_back(new_fill);
} }
} }
void read_side(pugi::xml_node side_node, side &side, bool &assigned)
{
if(side_node != nullptr)
{
assigned = true;
if(side_node.attribute("style") != nullptr)
{
std::string border_style_string = side_node.attribute("style").as_string();
if(border_style_string == "none")
{
side.set_border_style(border_style::none);
}
else if(border_style_string == "dashdot")
{
side.set_border_style(border_style::dashdot);
}
else if(border_style_string == "dashdotdot")
{
side.set_border_style(border_style::dashdotdot);
}
else if(border_style_string == "dashed")
{
side.set_border_style(border_style::dashed);
}
else if(border_style_string == "dotted")
{
side.set_border_style(border_style::dotted);
}
else if(border_style_string == "double")
{
side.set_border_style(border_style::double_);
}
else if(border_style_string == "hair")
{
side.set_border_style(border_style::hair);
}
else if(border_style_string == "medium")
{
side.set_border_style(border_style::medium);
}
else if(border_style_string == "mediumdashdot")
{
side.set_border_style(border_style::mediumdashdot);
}
else if(border_style_string == "mediumdashdotdot")
{
side.set_border_style(border_style::mediumdashdotdot);
}
else if(border_style_string == "mediumdashed")
{
side.set_border_style(border_style::mediumdashed);
}
else if(border_style_string == "slantdashdot")
{
side.set_border_style(border_style::slantdashdot);
}
else if(border_style_string == "thick")
{
side.set_border_style(border_style::thick);
}
else if(border_style_string == "thin")
{
side.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
auto color_node = side_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
side.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
side.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
}
void style_reader::read_borders(pugi::xml_node borders_node) void style_reader::read_borders(pugi::xml_node borders_node)
{ {
@ -303,180 +396,22 @@ void style_reader::read_borders(pugi::xml_node borders_node)
{ {
border new_border; border new_border;
if(border_node.child("left") != nullptr) const std::vector<std::tuple<std::string, side &, bool &>> sides =
{ {
new_border.left_assigned = true; {"start", new_border.start, new_border.start_assigned},
auto left_node = border_node.child("left"); {"end", new_border.end, new_border.end_assigned},
{"left", new_border.left, new_border.left_assigned},
if(left_node.attribute("style") != nullptr) {"right", new_border.right, new_border.right_assigned},
{ {"top", new_border.top, new_border.top_assigned},
if(left_node.attribute("style").as_string() == std::string("thin")) {"bottom", new_border.bottom, new_border.bottom_assigned},
{ {"diagonal", new_border.diagonal, new_border.diagonal_assigned},
new_border.left.set_border_style(border_style::thin); {"vertical", new_border.vertical, new_border.vertical_assigned},
} {"horizontal", new_border.horizontal, new_border.horizontal_assigned}
else };
{
throw std::runtime_error("unknown border style"); for(const auto &side : sides)
}
}
auto color_node = left_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
new_border.left.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
new_border.left.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_node.child("right") != nullptr)
{ {
new_border.right_assigned = true; read_side(border_node.child(std::get<0>(side).c_str()), std::get<1>(side), std::get<2>(side));
auto right_node = border_node.child("right");
if(right_node.attribute("style") != nullptr)
{
if(right_node.attribute("style").as_string() == std::string("thin"))
{
new_border.right.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
auto color_node = right_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
new_border.right.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
new_border.right.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_node.child("top") != nullptr)
{
new_border.top_assigned = true;
auto top_node = border_node.child("top");
if(top_node.attribute("style") != nullptr)
{
if(top_node.attribute("style").as_string() == std::string("thin"))
{
new_border.top.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
auto color_node = top_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
new_border.top.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
new_border.top.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_node.child("bottom") != nullptr)
{
new_border.bottom_assigned = true;
auto bottom_node = border_node.child("bottom");
if(bottom_node.attribute("style") != nullptr)
{
if(bottom_node.attribute("style").as_string() == std::string("thin"))
{
new_border.bottom.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
auto color_node = bottom_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
new_border.bottom.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
new_border.bottom.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_node.child("diagonal") != nullptr)
{
new_border.diagonal_assigned = true;
auto diagonal_node = border_node.child("diagonal");
if(diagonal_node.attribute("style") != nullptr)
{
if(diagonal_node.attribute("style").as_string() == std::string("thin"))
{
new_border.diagonal.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
auto color_node = diagonal_node.child("color");
if(color_node != nullptr)
{
if(color_node.attribute("indexed") != nullptr)
{
new_border.diagonal.set_color(side::color_type::indexed, color_node.attribute("indexed").as_int());
}
else if(color_node.attribute("theme") != nullptr)
{
new_border.diagonal.set_color(side::color_type::theme, color_node.attribute("theme").as_int());
}
else
{
throw std::runtime_error("invalid color type");
}
}
} }
borders_.push_back(new_border); borders_.push_back(new_border);

View File

@ -39,22 +39,22 @@ style::style() :
style::style(const style &other) : style::style(const style &other) :
id_(other.id_), id_(other.id_),
alignment_(other.alignment_),
alignment_apply_(other.alignment_apply_), alignment_apply_(other.alignment_apply_),
border_(other.border_), alignment_(other.alignment_),
border_apply_(other.border_apply_), border_apply_(other.border_apply_),
border_id_(other.border_id_), border_id_(other.border_id_),
fill_(other.fill_), border_(other.border_),
fill_apply_(other.fill_apply_), fill_apply_(other.fill_apply_),
fill_id_(other.fill_id_), fill_id_(other.fill_id_),
font_(other.font_), fill_(other.fill_),
font_apply_(other.font_apply_), font_apply_(other.font_apply_),
font_id_(other.font_id_), font_id_(other.font_id_),
number_format_(other.number_format_), font_(other.font_),
number_format_apply_(other.number_format_apply_), number_format_apply_(other.number_format_apply_),
number_format_id_(other.number_format_id_), number_format_id_(other.number_format_id_),
protection_(other.protection_), number_format_(other.number_format_),
protection_apply_(other.protection_apply_), protection_apply_(other.protection_apply_),
protection_(other.protection_),
pivot_button_(other.pivot_button_), pivot_button_(other.pivot_button_),
quote_prefix_(other.quote_prefix_) quote_prefix_(other.quote_prefix_)
{ {

View File

@ -31,37 +31,6 @@
#include "detail/workbook_impl.hpp" #include "detail/workbook_impl.hpp"
#include "detail/worksheet_impl.hpp" #include "detail/worksheet_impl.hpp"
namespace {
static std::string create_temporary_filename()
{
#ifdef _WIN32
std::array<TCHAR, MAX_PATH> buffer;
DWORD result = GetTempPath(static_cast<DWORD>(buffer.size()), buffer.data());
if(result > MAX_PATH)
{
throw std::runtime_error("buffer is too small");
}
if(result == 0)
{
throw std::runtime_error("GetTempPath failed");
}
std::string directory(buffer.begin(), buffer.begin() + result);
return directory + "xlnt.xlsx";
#else
return "/tmp/xlsx.xlnt";
#endif
}
template <class T>
void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}
} // namespace
namespace xlnt { namespace xlnt {
namespace detail { namespace detail {

View File

@ -129,6 +129,33 @@ std::string style_writer::write_table() const
} }
} }
} }
else if(fill_.get_type() == fill::type::solid)
{
auto solid_fill_node = fill_node.append_child("solidFill");
solid_fill_node.append_child("color");
}
else if(fill_.get_type() == fill::type::gradient)
{
auto gradient_fill_node = fill_node.append_child("gradientFill");
if(fill_.get_gradient_type_string() == "linear")
{
gradient_fill_node.append_attribute("degree").set_value(fill_.get_rotation());
}
else if(fill_.get_gradient_type_string() == "path")
{
gradient_fill_node.append_attribute("left").set_value(fill_.get_gradient_left());
gradient_fill_node.append_attribute("right").set_value(fill_.get_gradient_right());
gradient_fill_node.append_attribute("top").set_value(fill_.get_gradient_top());
gradient_fill_node.append_attribute("bottom").set_value(fill_.get_gradient_bottom());
auto start_node = gradient_fill_node.append_child("stop");
start_node.append_attribute("position").set_value(0);
auto end_node = gradient_fill_node.append_child("stop");
end_node.append_attribute("position").set_value(1);
}
}
} }
auto borders_node = style_sheet_node.append_child("borders"); auto borders_node = style_sheet_node.append_child("borders");
@ -139,176 +166,69 @@ std::string style_writer::write_table() const
{ {
auto border_node = borders_node.append_child("border"); auto border_node = borders_node.append_child("border");
if(border_.left_assigned) const std::vector<std::tuple<std::string, const side &, bool>> sides =
{ {
auto left_node = border_node.append_child("left"); {"start", border_.start, border_.start_assigned},
{"end", border_.end, border_.end_assigned},
if(border_.left.is_style_assigned()) {"left", border_.left, border_.left_assigned},
{ {"right", border_.right, border_.right_assigned},
auto style_attribute = left_node.append_attribute("style"); {"top", border_.top, border_.top_assigned},
{"bottom", border_.bottom, border_.bottom_assigned},
switch(border_.left.get_style()) {"diagonal", border_.diagonal, border_.diagonal_assigned},
{ {"vertical", border_.vertical, border_.vertical_assigned},
case border_style::none: style_attribute.set_value("none"); break; {"horizontal", border_.horizontal, border_.horizontal_assigned}
case border_style::thin: style_attribute.set_value("thin"); break; };
default: throw std::runtime_error("invalid style");
}
}
if(border_.left.is_color_assigned())
{
auto color_node = left_node.append_child("color");
if(border_.left.get_color_type() == side::color_type::indexed)
{
color_node.append_attribute("indexed").set_value((int)border_.left.get_color());
}
else if(border_.diagonal.get_color_type() == side::color_type::theme)
{
color_node.append_attribute("indexed").set_value((int)border_.left.get_color());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_.right_assigned) for(const auto &side_tuple : sides)
{ {
auto right_node = border_node.append_child("right"); std::string name = std::get<0>(side_tuple);
const side &side_ = std::get<1>(side_tuple);
bool assigned = std::get<2>(side_tuple);
if(border_.right.is_style_assigned()) if(assigned)
{ {
auto style_attribute = right_node.append_attribute("style"); auto side_node = border_node.append_child(name.c_str());
switch(border_.right.get_style()) if(side_.is_style_assigned())
{ {
case border_style::none: style_attribute.set_value("none"); break; auto style_attribute = side_node.append_attribute("style");
case border_style::thin: style_attribute.set_value("thin"); break;
default: throw std::runtime_error("invalid style"); switch(side_.get_style())
{
case border_style::none: style_attribute.set_value("none"); break;
case border_style::dashdot : style_attribute.set_value("dashdot"); break;
case border_style::dashdotdot : style_attribute.set_value("dashdotdot"); break;
case border_style::dashed : style_attribute.set_value("dashed"); break;
case border_style::dotted : style_attribute.set_value("dotted"); break;
case border_style::double_ : style_attribute.set_value("double"); break;
case border_style::hair : style_attribute.set_value("hair"); break;
case border_style::medium : style_attribute.set_value("thin"); break;
case border_style::mediumdashdot: style_attribute.set_value("mediumdashdot"); break;
case border_style::mediumdashdotdot: style_attribute.set_value("mediumdashdotdot"); break;
case border_style::mediumdashed: style_attribute.set_value("mediumdashed"); break;
case border_style::slantdashdot: style_attribute.set_value("slantdashdot"); break;
case border_style::thick: style_attribute.set_value("thick"); break;
case border_style::thin: style_attribute.set_value("thin"); break;
default: throw std::runtime_error("invalid style");
}
} }
}
if(border_.right.is_color_assigned())
{
auto color_node = right_node.append_child("color");
if(border_.right.get_color_type() == side::color_type::indexed) if(side_.is_color_assigned())
{ {
color_node.append_attribute("indexed").set_value((int)border_.right.get_color()); auto color_node = side_node.append_child("color");
}
else if(border_.diagonal.get_color_type() == side::color_type::theme) if(side_.get_color_type() == side::color_type::indexed)
{ {
color_node.append_attribute("indexed").set_value((int)border_.right.get_color()); color_node.append_attribute("indexed").set_value((int)side_.get_color());
} }
else else if(side_.get_color_type() == side::color_type::theme)
{ {
throw std::runtime_error("invalid color type"); color_node.append_attribute("indexed").set_value((int)side_.get_color());
} }
} else
} {
throw std::runtime_error("invalid color type");
if(border_.top_assigned) }
{
auto top_node = border_node.append_child("top");
if(border_.top.is_style_assigned())
{
auto style_attribute = top_node.append_attribute("style");
switch(border_.top.get_style())
{
case border_style::none: style_attribute.set_value("none"); break;
case border_style::thin: style_attribute.set_value("thin"); break;
default: throw std::runtime_error("invalid style");
}
}
if(border_.top.is_color_assigned())
{
auto color_node = top_node.append_child("color");
if(border_.top.get_color_type() == side::color_type::indexed)
{
color_node.append_attribute("indexed").set_value((int)border_.top.get_color());
}
else if(border_.diagonal.get_color_type() == side::color_type::theme)
{
color_node.append_attribute("indexed").set_value((int)border_.top.get_color());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_.bottom_assigned)
{
auto bottom_node = border_node.append_child("bottom");
if(border_.bottom.is_style_assigned())
{
auto style_attribute = bottom_node.append_attribute("style");
switch(border_.bottom.get_style())
{
case border_style::none: style_attribute.set_value("none"); break;
case border_style::thin: style_attribute.set_value("thin"); break;
default: throw std::runtime_error("invalid style");
}
}
if(border_.bottom.is_color_assigned())
{
auto color_node = bottom_node.append_child("color");
if(border_.bottom.get_color_type() == side::color_type::indexed)
{
color_node.append_attribute("indexed").set_value((int)border_.bottom.get_color());
}
else if(border_.diagonal.get_color_type() == side::color_type::theme)
{
color_node.append_attribute("indexed").set_value((int)border_.bottom.get_color());
}
else
{
throw std::runtime_error("invalid color type");
}
}
}
if(border_.diagonal_assigned)
{
auto diagonal_node = border_node.append_child("diagonal");
if(border_.diagonal.is_style_assigned())
{
auto style_attribute = diagonal_node.append_attribute("style");
switch(border_.diagonal.get_style())
{
case border_style::none: style_attribute.set_value("none"); break;
case border_style::thin: style_attribute.set_value("thin"); break;
default: throw std::runtime_error("invalid style");
}
}
if(border_.diagonal.is_color_assigned())
{
auto color_node = diagonal_node.append_child("color");
if(border_.diagonal.get_color_type() == side::color_type::indexed)
{
color_node.append_attribute("indexed").set_value((int)border_.diagonal.get_color());
}
else if(border_.diagonal.get_color_type() == side::color_type::theme)
{
color_node.append_attribute("indexed").set_value((int)border_.diagonal.get_color());
}
else
{
throw std::runtime_error("invalid color type");
} }
} }
} }