From 26cb7af8b81dc1123ce04343bb2f371f5647e73c Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Fri, 27 May 2016 14:42:28 +0530 Subject: [PATCH 1/7] Add facility to extract border details out of xml attributes --- src/liborcus/odf_helper.cpp | 56 ++++++++++++++++++++++++++++++++++++- src/liborcus/odf_helper.hpp | 16 +++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/liborcus/odf_helper.cpp b/src/liborcus/odf_helper.cpp index fc3f61e5b..73b2375e4 100644 --- a/src/liborcus/odf_helper.cpp +++ b/src/liborcus/odf_helper.cpp @@ -6,11 +6,39 @@ */ #include "odf_helper.hpp" +#include "string_helper.hpp" +#include +#include +#include +#include +#include namespace orcus { namespace { +typedef mdds::sorted_string_map odf_border_style_map; + +odf_border_style_map::entry odf_border_style_entries[] = +{ + { MDDS_ASCII("unknown") , spreadsheet::border_style_t::unknown}, + { MDDS_ASCII("none") , spreadsheet::border_style_t::none}, + { MDDS_ASCII("dash_dot") , spreadsheet::border_style_t::dash_dot}, + { MDDS_ASCII("dash_dot_dot") , spreadsheet::border_style_t::dash_dot_dot}, + { MDDS_ASCII("dashed") , spreadsheet::border_style_t::dashed}, + { MDDS_ASCII("dotted") , spreadsheet::border_style_t::dotted}, + { MDDS_ASCII("double_border") , spreadsheet::border_style_t::double_border}, + { MDDS_ASCII("hair") , spreadsheet::border_style_t::hair}, + { MDDS_ASCII("medium") , spreadsheet::border_style_t::medium}, + { MDDS_ASCII("medium_dash_dot") , spreadsheet::border_style_t::medium_dash_dot}, + { MDDS_ASCII("medium_dash_dot_dot") , spreadsheet::border_style_t::medium_dash_dot_dot}, + { MDDS_ASCII("medium_dashed") , spreadsheet::border_style_t::medium_dashed}, + { MDDS_ASCII("slant_dash_dot") , spreadsheet::border_style_t::slant_dash_dot}, + { MDDS_ASCII("thick") , spreadsheet::border_style_t::thick}, + { MDDS_ASCII("thin") , spreadsheet::border_style_t::thin} +}; + + bool is_valid_hex_digit(const char& character, orcus::spreadsheet::color_elem_t& val) { if ('0' <= character && character <= '9') @@ -66,7 +94,33 @@ bool odf_helper::convert_fo_color(const pstring& value, orcus::spreadsheet::colo return convert_color_digits(value, blue, 5); } - + +orcus::odf_helper::odf_border_details odf_helper::extract_border_details(const orcus::pstring &value) +{ + orcus::pstring color_code; + orcus::pstring width; + orcus::pstring style; + orcus::odf_helper::odf_border_details border_details; + + std::vector detail = orcus::string_helper::split_string(value,' '); + + for(auto& sub_detail : detail) + { + if(sub_detail[0] == '#') + convert_fo_color(sub_detail,border_details.red , border_details.green , border_details.blue); + + else if(sub_detail[0] >= '0' && sub_detail[0] <='9') + border_details.border_width = orcus::to_length(sub_detail); + + else // This has to be a style + { + odf_border_style_map border_style_map(odf_border_style_entries , ORCUS_N_ELEMENTS(odf_border_style_entries) , spreadsheet::border_style_t::none); + border_details.border_style = border_style_map.find(sub_detail.get() , sub_detail.size()); + } + + } + return border_details; +} } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/liborcus/odf_helper.hpp b/src/liborcus/odf_helper.hpp index 6880914c5..d8b3aee88 100644 --- a/src/liborcus/odf_helper.hpp +++ b/src/liborcus/odf_helper.hpp @@ -10,15 +10,31 @@ #include #include +#include namespace orcus { class odf_helper { public: + struct odf_border_details + { + + orcus::spreadsheet::border_style_t border_style; + + spreadsheet::color_elem_t red; + spreadsheet::color_elem_t green; + spreadsheet::color_elem_t blue; + + length_t border_width; + }; + static bool convert_fo_color(const orcus::pstring& value, orcus::spreadsheet::color_elem_t& red, orcus::spreadsheet::color_elem_t& green, orcus::spreadsheet::color_elem_t& blue); + /* extracts border style,width and colors out of the pstring provided to it */ + static orcus::odf_helper::odf_border_details extract_border_details(const orcus::pstring& value); + }; } -- GitLab From 080e4473789fc03a6f73f5f28e77925a6730cd4b Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Fri, 27 May 2016 14:48:50 +0530 Subject: [PATCH 2/7] Add facility to read Border style - solid --- include/orcus/spreadsheet/types.hpp | 1 + src/liborcus/odf_helper.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/orcus/spreadsheet/types.hpp b/include/orcus/spreadsheet/types.hpp index 46949539f..14f9ebc0a 100644 --- a/include/orcus/spreadsheet/types.hpp +++ b/include/orcus/spreadsheet/types.hpp @@ -40,6 +40,7 @@ enum class border_style_t { unknown = 0, none, + solid, dash_dot, dash_dot_dot, dashed, diff --git a/src/liborcus/odf_helper.cpp b/src/liborcus/odf_helper.cpp index 73b2375e4..ec4235003 100644 --- a/src/liborcus/odf_helper.cpp +++ b/src/liborcus/odf_helper.cpp @@ -23,6 +23,7 @@ odf_border_style_map::entry odf_border_style_entries[] = { { MDDS_ASCII("unknown") , spreadsheet::border_style_t::unknown}, { MDDS_ASCII("none") , spreadsheet::border_style_t::none}, + { MDDS_ASCII("solid") ,spreadsheet::border_style_t::solid}, { MDDS_ASCII("dash_dot") , spreadsheet::border_style_t::dash_dot}, { MDDS_ASCII("dash_dot_dot") , spreadsheet::border_style_t::dash_dot_dot}, { MDDS_ASCII("dashed") , spreadsheet::border_style_t::dashed}, @@ -107,7 +108,7 @@ orcus::odf_helper::odf_border_details odf_helper::extract_border_details(const o for(auto& sub_detail : detail) { if(sub_detail[0] == '#') - convert_fo_color(sub_detail,border_details.red , border_details.green , border_details.blue); + convert_fo_color(sub_detail , border_details.red , border_details.green , border_details.blue); else if(sub_detail[0] >= '0' && sub_detail[0] <='9') border_details.border_width = orcus::to_length(sub_detail); -- GitLab From 850a2a6125593f2ab6a2f793b037479c4d602504 Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Fri, 27 May 2016 15:20:12 +0530 Subject: [PATCH 3/7] Add facility to set border width --- include/orcus/spreadsheet/import_interface.hpp | 2 ++ include/orcus/spreadsheet/styles.hpp | 6 +++++- src/spreadsheet/styles.cpp | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/orcus/spreadsheet/import_interface.hpp b/include/orcus/spreadsheet/import_interface.hpp index 66da60aae..0ff96f8c8 100644 --- a/include/orcus/spreadsheet/import_interface.hpp +++ b/include/orcus/spreadsheet/import_interface.hpp @@ -13,6 +13,7 @@ #include "types.hpp" #include "orcus/types.hpp" #include "orcus/env.hpp" +#include // NB: This header must not depend on ixion, as it needs to be usable for // those clients that provide their own formula engine. Other headers in @@ -110,6 +111,7 @@ public: virtual void set_border_style(orcus::spreadsheet::border_direction_t dir, border_style_t style) = 0; virtual void set_border_color( orcus::spreadsheet::border_direction_t dir, color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) = 0; + virtual void set_border_width(border_direction_t dir, length_t width) = 0; virtual size_t commit_border() = 0; // cell protection diff --git a/include/orcus/spreadsheet/styles.hpp b/include/orcus/spreadsheet/styles.hpp index 8ce834cf0..3cf019e73 100644 --- a/include/orcus/spreadsheet/styles.hpp +++ b/include/orcus/spreadsheet/styles.hpp @@ -11,7 +11,7 @@ #include "orcus/spreadsheet/import_interface.hpp" #include "orcus/pstring.hpp" #include "orcus/env.hpp" - +#include #include namespace orcus { @@ -60,6 +60,7 @@ struct ORCUS_SPM_DLLPUBLIC border_attrs_t { border_style_t style; color_t border_color; + length_t border_width; border_attrs_t(); void reset(); @@ -72,6 +73,8 @@ struct ORCUS_SPM_DLLPUBLIC border_t border_attrs_t left; border_attrs_t right; border_attrs_t diagonal; + border_attrs_t diagonal_bl_tr; + border_attrs_t diagonal_tl_br; border_t(); void reset(); @@ -157,6 +160,7 @@ public: virtual void set_border_style(border_direction_t dir, border_style_t style); virtual void set_border_color( border_direction_t dir, color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue); + virtual void set_border_width(border_direction_t dir,length_t length); virtual size_t commit_border(); virtual void set_cell_hidden(bool b); diff --git a/src/spreadsheet/styles.cpp b/src/spreadsheet/styles.cpp index 699dbcc41..7ab5bfa1a 100644 --- a/src/spreadsheet/styles.cpp +++ b/src/spreadsheet/styles.cpp @@ -252,6 +252,13 @@ void import_styles::set_border_color( p->border_color = color_t(alpha, red, green, blue); } +void import_styles::set_border_width(border_direction_t dir , length_t width) +{ + border_attrs_t* p = get_border_attrs(m_cur_border ,dir); + if(p) + p->border_width = width; +} + size_t import_styles::commit_border() { m_borders.push_back(m_cur_border); -- GitLab From 41d0273e75211441444f48fe744d6c1a688f2ab6 Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Fri, 27 May 2016 16:21:51 +0530 Subject: [PATCH 4/7] Implement facility to parse and commit border --- src/liborcus/odf_helper.cpp | 1 + src/liborcus/odf_helper.hpp | 1 + src/liborcus/odf_styles_context.cpp | 71 +++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/src/liborcus/odf_helper.cpp b/src/liborcus/odf_helper.cpp index ec4235003..b21ecbb51 100644 --- a/src/liborcus/odf_helper.cpp +++ b/src/liborcus/odf_helper.cpp @@ -12,6 +12,7 @@ #include #include #include +#include namespace orcus { diff --git a/src/liborcus/odf_helper.hpp b/src/liborcus/odf_helper.hpp index d8b3aee88..a3273b437 100644 --- a/src/liborcus/odf_helper.hpp +++ b/src/liborcus/odf_helper.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace orcus { diff --git a/src/liborcus/odf_styles_context.cpp b/src/liborcus/odf_styles_context.cpp index 6cf726982..a19d348b0 100644 --- a/src/liborcus/odf_styles_context.cpp +++ b/src/liborcus/odf_styles_context.cpp @@ -9,7 +9,6 @@ #include "odf_namespace_types.hpp" #include "odf_token_constants.hpp" #include "odf_helper.hpp" - #include "orcus/measurement.hpp" #include "orcus/spreadsheet/import_interface.hpp" @@ -163,12 +162,19 @@ public: class cell_prop_attr_parser : std::unary_function { +public: + typedef std::map border_map_t; + odf_helper::odf_border_details border_details; +private: spreadsheet::color_elem_t m_background_red; spreadsheet::color_elem_t m_background_green; spreadsheet::color_elem_t m_background_blue; + bool m_background_color; + border_map_t m_border_style_dir_pair; + public: void operator() (const xml_token_attr_t& attr) @@ -181,6 +187,36 @@ public: m_background_color = odf_helper::convert_fo_color(attr.value, m_background_red, m_background_green, m_background_blue); break; + + case XML_border: + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::top , border_details)); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::bottom , border_details)); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::left , border_details)); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::right , border_details)); + break; + + case XML_border_top: + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::top , border_details)); + break; + + case XML_border_bottom: + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::bottom , border_details)); + break; + + case XML_border_left: + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::left , border_details)); + break; + + case XML_border_right: + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::right , border_details)); + break; + + default: ; } @@ -188,6 +224,7 @@ public: } bool has_background_color() { return m_background_color; } + void get_background_color(spreadsheet::color_elem_t& red, spreadsheet::color_elem_t& green, spreadsheet::color_elem_t& blue) { @@ -195,6 +232,14 @@ public: green = m_background_green; blue = m_background_blue; } + + bool has_border() { return !m_border_style_dir_pair.empty(); } + + border_map_t& get_border_attrib() + { + return m_border_style_dir_pair; + } + }; } @@ -370,9 +415,9 @@ void styles_context::start_element(xmlns_id_t ns, xml_token_t name, const std::v m_current_style->cell_data->automatic_style = m_automatic_styles; if (mp_styles) { + cell_prop_attr_parser func; func = std::for_each(attrs.begin(), attrs.end(), func); - if (func.has_background_color()) { spreadsheet::color_elem_t red, green, blue; @@ -380,15 +425,33 @@ void styles_context::start_element(xmlns_id_t ns, xml_token_t name, const std::v mp_styles->set_fill_bg_color(0, red, green, blue); } - size_t fill = mp_styles->commit_fill(); + size_t fill_id = mp_styles->commit_fill(); + + if(func.has_border()) + { + const cell_prop_attr_parser::border_map_t& border_map = func.get_border_attrib(); + for (cell_prop_attr_parser::border_map_t::const_iterator itr = border_map.begin(); itr != border_map.end(); ++itr) + { + mp_styles->set_border_color(itr->first , 0, itr->second.red, itr->second.green, itr->second.blue); + mp_styles->set_border_style(itr->first , itr->second.border_style); + mp_styles->set_border_width(itr->first , itr->second.border_width); + + } + + } + + size_t border_id = mp_styles->commit_border(); switch (m_current_style->family) { case style_family_table_cell: { odf_style::cell* data = m_current_style->cell_data; - data->fill = fill; + data->fill = fill_id; + data->border=border_id; } + break; + default: ; } -- GitLab From 133c28373c96ec13abb220602a53e8cdce3045fb Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Fri, 27 May 2016 13:41:14 +0530 Subject: [PATCH 5/7] Add test for border import --- src/liborcus/odf_styles_context_test.cpp | 53 +++++++++++++++++++++++- test/ods/styles/cell-styles.xml | 14 ++++++- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/src/liborcus/odf_styles_context_test.cpp b/src/liborcus/odf_styles_context_test.cpp index 7aa5bfe7c..5fa055c5d 100644 --- a/src/liborcus/odf_styles_context_test.cpp +++ b/src/liborcus/odf_styles_context_test.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include namespace { @@ -34,13 +36,16 @@ int main() orcus::spreadsheet::import_styles styles(string_pool); orcus::import_ods::read_styles(content.c_str(), content.size(), &styles); - - const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Note", &styles); +/* Test for Cell Fill + ===================================================== +*/ + const orcus::spreadsheet::cell_style_t* style = find_cell_style_by_name("Name1", &styles); assert(style->parent_name == "Text"); size_t xf = style->xf; std::cerr << std::hex << (int)xf; const orcus::spreadsheet::cell_format_t* cell_format = styles.get_cell_style_format(xf); assert(cell_format); + size_t fill = cell_format->fill; std::cerr << std::hex << (int)fill; const orcus::spreadsheet::fill_t* cell_fill = styles.get_fill(fill); @@ -49,5 +54,49 @@ int main() assert(cell_fill->bg_color.red == 0xfe); assert(cell_fill->bg_color.green == 0xff); assert(cell_fill->bg_color.blue == 0xcc); + +/* Test for Border Styles + ===================================================== +*/ + assert(styles.get_border_count()==5); + + /* Test that border style applies to all the sides when not specified */ + style = find_cell_style_by_name("Name1", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + size_t border = cell_format->border; + assert(cell_format); + + const orcus::spreadsheet::border_t* cell_border = styles.get_border(border); + assert(cell_border->top.style == orcus::spreadsheet::border_style_t::thick); + assert(cell_border->bottom.style == orcus::spreadsheet::border_style_t::thick); + assert(cell_border->left.style == orcus::spreadsheet::border_style_t::thick); + assert(cell_border->right.style == orcus::spreadsheet::border_style_t::thick); + assert(cell_border->top.border_color.red == 0xff); + assert(cell_border->bottom.border_color.green == 0xcc); + assert(cell_border->left.border_color.blue == 0x12); + assert(cell_border->right.border_width.value == 0.06); + assert(cell_border->top.border_width.value == 0.06); + + /*Test that border applies to only specified sides*/ + style = find_cell_style_by_name("Name2", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + border = cell_format->border; + assert(cell_format); + + cell_border = styles.get_border(border); + assert(cell_border->top.style == orcus::spreadsheet::border_style_t::dashed); + assert(cell_border->bottom.style == orcus::spreadsheet::border_style_t::thin); + assert(cell_border->left.style == orcus::spreadsheet::border_style_t::none); + assert(cell_border->right.style == orcus::spreadsheet::border_style_t::thin); + assert(cell_border->top.border_color.red == 0xff); + assert(cell_border->bottom.border_color.green == 0xee); + assert(cell_border->left.border_color.blue == 0x11); + assert(cell_border->right.border_width.value == 0.22); + assert(cell_border->bottom.border_width.value == 1.74); + + //TODO : These border styles dont work :- solid,dash_dot,dash_dot_dot ...and some others + return 0; } diff --git a/test/ods/styles/cell-styles.xml b/test/ods/styles/cell-styles.xml index 6ccf9baae..37dac7fc9 100644 --- a/test/ods/styles/cell-styles.xml +++ b/test/ods/styles/cell-styles.xml @@ -1,6 +1,16 @@ - - + + + + + + + + + + + + -- GitLab From 964c3f59fc12de60347515d1bc4efb553ff0cd4d Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Sun, 29 May 2016 00:13:00 +0530 Subject: [PATCH 6/7] Add facility to read diagonal border --- include/orcus/spreadsheet/types.hpp | 4 +++- src/liborcus/odf_styles_context.cpp | 12 +++++++++++- src/spreadsheet/styles.cpp | 6 ++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/orcus/spreadsheet/types.hpp b/include/orcus/spreadsheet/types.hpp index 14f9ebc0a..9b4987f11 100644 --- a/include/orcus/spreadsheet/types.hpp +++ b/include/orcus/spreadsheet/types.hpp @@ -33,7 +33,9 @@ enum class border_direction_t bottom, left, right, - diagonal + diagonal, + diagonal_bl_tr, + diagonal_tl_br }; enum class border_style_t diff --git a/src/liborcus/odf_styles_context.cpp b/src/liborcus/odf_styles_context.cpp index a19d348b0..2ee518829 100644 --- a/src/liborcus/odf_styles_context.cpp +++ b/src/liborcus/odf_styles_context.cpp @@ -215,7 +215,17 @@ public: border_details = odf_helper::extract_border_details(attr.value); m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::right , border_details)); break; - + case XML_diagonal_bl_tr: + { + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::diagonal_bl_tr , border_details)); + } + break; + case XML_diagonal_tl_br: + { + border_details = odf_helper::extract_border_details(attr.value); + m_border_style_dir_pair.insert(std::make_pair(spreadsheet::border_direction_t::diagonal_tl_br , border_details)); + } default: ; diff --git a/src/spreadsheet/styles.cpp b/src/spreadsheet/styles.cpp index 7ab5bfa1a..6639d7adc 100644 --- a/src/spreadsheet/styles.cpp +++ b/src/spreadsheet/styles.cpp @@ -218,6 +218,12 @@ border_attrs_t* get_border_attrs(border_t& cur_border, border_direction_t dir) case border_direction_t::diagonal: p = &cur_border.diagonal; break; + case border_direction_t::diagonal_bl_tr: + p = &cur_border.diagonal_bl_tr; + break; + case border_direction_t::diagonal_tl_br: + p = &cur_border.diagonal_tl_br; + break; default: ; } -- GitLab From d5ee9395de9593a5d0dd843b56e0efab0d0b15e2 Mon Sep 17 00:00:00 2001 From: Jaskaran Date: Sun, 29 May 2016 01:01:38 +0530 Subject: [PATCH 7/7] Add test for diagonal border --- src/liborcus/odf_styles_context_test.cpp | 14 ++++++++++++++ test/ods/styles/cell-styles.xml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/liborcus/odf_styles_context_test.cpp b/src/liborcus/odf_styles_context_test.cpp index 5fa055c5d..b4277fe8f 100644 --- a/src/liborcus/odf_styles_context_test.cpp +++ b/src/liborcus/odf_styles_context_test.cpp @@ -98,5 +98,19 @@ int main() //TODO : These border styles dont work :- solid,dash_dot,dash_dot_dot ...and some others + /*Test that border applies to the diagonal*/ + style = find_cell_style_by_name("Name3", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + border = cell_format->border; + assert(cell_format); + + cell_border = styles.get_border(border); + assert(cell_border->diagonal_bl_tr.style == orcus::spreadsheet::border_style_t::thick); + assert(cell_border->diagonal_tl_br.style == orcus::spreadsheet::border_style_t::thin); + assert(cell_border->diagonal_bl_tr.border_color.red == 0xff); + assert(cell_border->diagonal_tl_br.border_color.green == 0x00); + assert(cell_border->diagonal_tl_br.border_width.value == 0.74); + return 0; } diff --git a/test/ods/styles/cell-styles.xml b/test/ods/styles/cell-styles.xml index 37dac7fc9..a948157c4 100644 --- a/test/ods/styles/cell-styles.xml +++ b/test/ods/styles/cell-styles.xml @@ -7,7 +7,7 @@ - + -- GitLab