xlnt/source/reader/style_reader.cpp
2015-10-23 14:42:36 -04:00

505 lines
16 KiB
C++

#include <xlnt/common/zip_file.hpp>
#include <xlnt/styles/border.hpp>
#include <xlnt/styles/fill.hpp>
#include <xlnt/styles/font.hpp>
#include <xlnt/styles/named_style.hpp>
#include <xlnt/styles/number_format.hpp>
#include <xlnt/styles/style.hpp>
#include <xlnt/reader/style_reader.hpp>
#include "detail/include_pugixml.hpp"
namespace xlnt {
protection read_protection(pugi::xml_node node)
{
auto prot_type_from_string = [](const std::string &type_string)
{
if(type_string == "true") return protection::type::protected_;
else if(type_string == "inherit") return protection::type::inherit;
return protection::type::unprotected;
};
protection prot;
prot.set_locked(prot_type_from_string(node.attribute("locked").as_string()));
prot.set_hidden(prot_type_from_string(node.attribute("hidden").as_string()));
return prot;
}
alignment read_alignment(pugi::xml_node node)
{
alignment align;
align.set_wrap_text(node.attribute("wrapText").as_int() != 0);
bool has_vertical = node.attribute("vertical") != nullptr;
std::string vertical = has_vertical ? node.attribute("vertical").as_string() : "";
if(has_vertical)
{
if(vertical == "bottom")
{
align.set_vertical(alignment::vertical_alignment::bottom);
}
else if(vertical =="center")
{
align.set_vertical(alignment::vertical_alignment::center);
}
else if(vertical =="justify")
{
align.set_vertical(alignment::vertical_alignment::justify);
}
else if(vertical =="top")
{
align.set_vertical(alignment::vertical_alignment::top);
}
else
{
throw "unknown alignment";
}
}
bool has_horizontal = node.attribute("horizontal") != nullptr;
std::string horizontal = has_horizontal ? node.attribute("horizontal").as_string() : "";
if(has_horizontal)
{
if(horizontal == "left")
{
align.set_horizontal(alignment::horizontal_alignment::left);
}
else if(horizontal == "center")
{
align.set_horizontal(alignment::horizontal_alignment::center);
}
else if(horizontal == "center-continuous")
{
align.set_horizontal(alignment::horizontal_alignment::center_continuous);
}
else if(horizontal == "right")
{
align.set_horizontal(alignment::horizontal_alignment::right);
}
else if(horizontal == "justify")
{
align.set_horizontal(alignment::horizontal_alignment::justify);
}
else if(horizontal == "general")
{
align.set_horizontal(alignment::horizontal_alignment::general);
}
else
{
throw "unknown alignment";
}
}
return align;
}
style style_reader::read_style(pugi::xml_node stylesheet_node, pugi::xml_node xf_node)
{
style s;
s.apply_number_format(xf_node.attribute("applyNumberFormat").as_bool());
s.number_format_id_ = xf_node.attribute("numFmtId").as_int();
bool builtin_format = true;
for(auto num_fmt : number_formats_)
{
if(num_fmt.get_id() == s.get_number_format_id())
{
s.number_format_ = num_fmt;
builtin_format = false;
break;
}
}
if(builtin_format)
{
s.number_format_ = number_format::from_builtin_id(s.get_number_format_id());
}
s.apply_font(xf_node.attribute("applyFont").as_bool());
s.font_id_ = xf_node.attribute("fontId") != nullptr ? xf_node.attribute("fontId").as_int() : 0;
s.font_ = fonts_[s.font_id_];
s.apply_fill(xf_node.attribute("applyFill").as_bool());
s.fill_id_ = xf_node.attribute("fillId").as_int();
s.fill_ = fills_[s.fill_id_];
s.apply_border(xf_node.attribute("applyBorder").as_bool());
s.border_id_ = xf_node.attribute("borderId").as_int();
s.border_ = borders_[s.border_id_];
s.apply_protection(xf_node.attribute("protection") != nullptr);
if(s.protection_apply_)
{
auto inline_protection = read_protection(xf_node.child("protection"));
s.protection_ = inline_protection;
}
s.apply_alignment(xf_node.child("alignment") != nullptr);
if(s.alignment_apply_)
{
auto inline_alignment = read_alignment(xf_node.child("alignment"));
s.alignment_ = inline_alignment;
}
return s;
}
style_reader::style_reader(workbook &wb)
{
}
void style_reader::read_styles(zip_file &archive)
{
auto xml = archive.read("xl/styles.xml");
pugi::xml_document doc;
doc.load_string(xml.c_str());
auto root = doc.root();
auto stylesheet_node = root.child("styleSheet");
read_borders(stylesheet_node.child("borders"));
read_fills(stylesheet_node.child("fills"));
read_fonts(stylesheet_node.child("fonts"));
read_number_formats(stylesheet_node.child("numFmts"));
auto cell_xfs_node = stylesheet_node.child("cellXfs");
for(auto xf_node : cell_xfs_node.children("xf"))
{
styles_.push_back(read_style(stylesheet_node, xf_node));
styles_.back().id_ = styles_.size() - 1;
}
read_color_index();
read_dxfs();
read_cell_styles();
read_named_styles(root.child("namedStyles"));
}
void style_reader::read_number_formats(pugi::xml_node num_fmts_node)
{
for(auto num_fmt_node : num_fmts_node.children("numFmt"))
{
number_format nf;
nf.set_format_string(num_fmt_node.attribute("formatCode").as_string());
nf.set_id(num_fmt_node.attribute("numFmtId").as_int());
number_formats_.push_back(nf);
}
}
void style_reader::read_color_index()
{
}
void style_reader::read_dxfs()
{
}
void style_reader::read_fonts(pugi::xml_node fonts_node)
{
for(auto font_node : fonts_node)
{
font new_font;
new_font.set_size(font_node.child("sz").attribute("val").as_int());
new_font.set_name(font_node.child("name").attribute("val").as_string());
if(font_node.child("color").attribute("theme") != nullptr)
{
new_font.set_color(color(color::type::theme, font_node.child("color").attribute("theme").as_ullong()));
}
else if(font_node.child("color").attribute("indexed") != nullptr)
{
new_font.set_color(color(color::type::indexed, font_node.child("color").attribute("indexed").as_ullong()));
}
if(font_node.child("family") != nullptr)
{
new_font.set_family(font_node.child("family").attribute("val").as_int());
}
if(font_node.child("scheme") != nullptr)
{
new_font.set_scheme(font_node.child("scheme").attribute("val").as_string());
}
if(font_node.child("b") != nullptr)
{
new_font.set_bold(font_node.child("b").attribute("val").as_bool());
}
fonts_.push_back(new_font);
}
}
void style_reader::read_fills(pugi::xml_node fills_node)
{
auto pattern_fill_type_from_string = [](const std::string &fill_type)
{
if(fill_type == "none") return fill::pattern_type::none;
if(fill_type == "solid") return fill::pattern_type::solid;
if(fill_type == "gray125") return fill::pattern_type::gray125;
throw std::runtime_error("invalid fill type");
};
for(auto fill_node : fills_node)
{
fill new_fill;
if(fill_node.child("patternFill") != nullptr)
{
auto pattern_fill_node = fill_node.child("patternFill");
new_fill.set_type(fill::type::pattern);
std::string pattern_type_string = pattern_fill_node.attribute("patternType").as_string();
auto pattern_type = pattern_fill_type_from_string(pattern_type_string);
new_fill.set_pattern_type(pattern_type);
auto bg_color_node = pattern_fill_node.child("bgColor");
if(bg_color_node != nullptr)
{
if(bg_color_node.attribute("indexed") != nullptr)
{
new_fill.set_background_color(color(color::type::indexed, bg_color_node.attribute("indexed").as_ullong()));
}
}
auto fg_color_node = pattern_fill_node.child("fgColor");
if(fg_color_node != nullptr)
{
if(fg_color_node.attribute("indexed") != nullptr)
{
new_fill.set_foreground_color(color(color::type::indexed, fg_color_node.attribute("indexed").as_ullong()));
}
}
}
fills_.push_back(new_fill);
}
}
void style_reader::read_borders(pugi::xml_node borders_node)
{
for(auto border_node : borders_node)
{
border new_border;
if(border_node.child("left") != nullptr)
{
new_border.left_assigned = true;
auto left_node = border_node.child("left");
if(left_node.attribute("style") != nullptr)
{
if(left_node.attribute("style").as_string() == std::string("thin"))
{
new_border.left.set_border_style(border_style::thin);
}
else
{
throw std::runtime_error("unknown border style");
}
}
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;
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);
}
}
void style_reader::read_named_styles(pugi::xml_node named_styles_node)
{
}
void style_reader::read_style_names()
{
}
void style_reader::read_cell_styles()
{
}
void style_reader::read_xfs()
{
}
void style_reader::read_style_table()
{
}
} // namespace xlnt