diff --git a/include/orcus/spreadsheet/import_interface.hpp b/include/orcus/spreadsheet/import_interface.hpp index cc83e5a518aea73c6b204bf65445667b7651516e..ede5b64a03bc10f1f5a3c3e2032ef1542650d77c 100644 --- a/include/orcus/spreadsheet/import_interface.hpp +++ b/include/orcus/spreadsheet/import_interface.hpp @@ -90,6 +90,10 @@ public: virtual void set_font_name(const char* s, size_t n) = 0; virtual void set_font_size(double point) = 0; virtual void set_font_underline(orcus::spreadsheet::underline_t e) = 0; + virtual void set_font_underline_width(underline_width_t e) = 0; + virtual void set_font_underline_mode(underline_mode_t e) = 0; + virtual void set_font_underline_type(underline_type_t e) = 0; + virtual void set_font_underline_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) = 0; virtual void set_font_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) = 0; virtual size_t commit_font() = 0; diff --git a/include/orcus/spreadsheet/styles.hpp b/include/orcus/spreadsheet/styles.hpp index 3cf019e739368d723bfcb9b7b0eb558224a93bc3..c17e5a43f03c0a7fae767dfc9763869d00e8e507 100644 --- a/include/orcus/spreadsheet/styles.hpp +++ b/include/orcus/spreadsheet/styles.hpp @@ -39,7 +39,11 @@ struct ORCUS_SPM_DLLPUBLIC font_t double size; bool bold:1; bool italic:1; - underline_t underline; + underline_t underline_style; + underline_width_t underline_width; + underline_mode_t underline_mode; + underline_type_t underline_type; + color_t underline_color; color_t color; font_t(); @@ -146,6 +150,10 @@ public: virtual void set_font_name(const char* s, size_t n); virtual void set_font_size(double point); virtual void set_font_underline(underline_t e); + virtual void set_font_underline_width(underline_width_t e); + virtual void set_font_underline_mode(underline_mode_t e); + virtual void set_font_underline_type(underline_type_t e); + virtual void set_font_underline_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue); virtual void set_font_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue); virtual size_t commit_font(); diff --git a/include/orcus/spreadsheet/types.hpp b/include/orcus/spreadsheet/types.hpp index 9b4987f111c336e02e0f46026c406ccbe6eb50c3..394e4b2625740fe100a99c020794d21184bf1a64 100644 --- a/include/orcus/spreadsheet/types.hpp +++ b/include/orcus/spreadsheet/types.hpp @@ -81,7 +81,48 @@ enum class underline_t single_line, single_accounting, // unique to xlsx double_line, - double_accounting // unique to xlsx + double_accounting, // unique to xlsx + solid, + dotted, + dash, + long_dash, + dot_dash, + dot_dot_dot_dash, + wave +}; + +enum class underline_width_t +{ + none = 0, + normal, + bold, + thin, + medium, + thick, + positive_integer, + percent, + positive_length +}; + +enum class underline_mode_t +{ + continuos = 0, + skip_white_space +}; + +enum class underline_type_t +{ + none = 0, + single, + double_type //necessary to not call it "double", since it is a reserved word +}; + +struct underline_attrs_t +{ + underline_t underline_style; + underline_width_t underline_width; + underline_mode_t underline_mode; + underline_type_t underline_type; }; enum class hor_alignment_t diff --git a/src/liborcus/odf_helper.cpp b/src/liborcus/odf_helper.cpp index 3e4cd6d102e4eff56f3d4d32fd1598994459b155..7ebbe6c503ba922b238bf2c5e901565eab72fa12 100644 --- a/src/liborcus/odf_helper.cpp +++ b/src/liborcus/odf_helper.cpp @@ -40,6 +40,34 @@ odf_border_style_map::entry odf_border_style_entries[] = { MDDS_ASCII("thin"), spreadsheet::border_style_t::thin} }; +typedef mdds::sorted_string_map odf_underline_width_map; + +odf_underline_width_map::entry odf_underline_width_entries[] = +{ + { MDDS_ASCII("bold"), spreadsheet::underline_width_t::bold}, + { MDDS_ASCII("medium"), spreadsheet::underline_width_t::medium}, + { MDDS_ASCII("none"), spreadsheet::underline_width_t::none}, + { MDDS_ASCII("normal"), spreadsheet::underline_width_t::normal}, + { MDDS_ASCII("percent"), spreadsheet::underline_width_t::percent}, + { MDDS_ASCII("positiveInteger"), spreadsheet::underline_width_t::positive_integer}, + { MDDS_ASCII("positiveLength"), spreadsheet::underline_width_t::positive_length}, + { MDDS_ASCII("thick"), spreadsheet::underline_width_t::thick}, + { MDDS_ASCII("thin"), spreadsheet::underline_width_t::thin}, +}; + +typedef mdds::sorted_string_map odf_underline_style_map; + +odf_underline_style_map::entry odf_underline_style_entries[] = +{ + { MDDS_ASCII("dash"), spreadsheet::underline_t::dash}, + { MDDS_ASCII("dot-dash"), spreadsheet::underline_t::dot_dash}, + { MDDS_ASCII("dot-dot-dot-dash"), spreadsheet::underline_t::dot_dot_dot_dash}, + { MDDS_ASCII("dotted"), spreadsheet::underline_t::dotted}, + { MDDS_ASCII("long-dash"), spreadsheet::underline_t::long_dash}, + { MDDS_ASCII("none"), spreadsheet::underline_t::none}, + { MDDS_ASCII("solid"), spreadsheet::underline_t::solid}, + { MDDS_ASCII("wave"), spreadsheet::underline_t::wave} +}; bool is_valid_hex_digit(const char& character, orcus::spreadsheet::color_elem_t& val) { @@ -118,6 +146,27 @@ orcus::odf_helper::odf_border_details odf_helper::extract_border_details(const o } return border_details; } + +orcus::spreadsheet::underline_width_t odf_helper::extract_underline_width(const orcus::pstring& value) +{ + orcus::spreadsheet::underline_width_t underline_width; + + odf_underline_width_map underline_width_map(odf_underline_width_entries, ORCUS_N_ELEMENTS(odf_underline_width_entries), spreadsheet::underline_width_t::none); + underline_width = underline_width_map.find(value.get(), value.size()); + + return underline_width; +} + +orcus::spreadsheet::underline_t odf_helper::extract_underline_style(const orcus::pstring& value) +{ + spreadsheet::underline_t underline_style; + + odf_underline_style_map underline_style_map(odf_underline_style_entries, ORCUS_N_ELEMENTS(odf_underline_style_entries), spreadsheet::underline_t::none); + underline_style = underline_style_map.find(value.get(), value.size()); + + return underline_style; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/liborcus/odf_helper.hpp b/src/liborcus/odf_helper.hpp index f8a22b730a0a3e753d725ff94afdd8efeda6f82e..e022412e0b0b994092ebf62705f49f146aeabc97 100644 --- a/src/liborcus/odf_helper.hpp +++ b/src/liborcus/odf_helper.hpp @@ -37,6 +37,9 @@ public: **/ static orcus::odf_helper::odf_border_details extract_border_details(const orcus::pstring& value); + static orcus::spreadsheet::underline_width_t extract_underline_width(const orcus::pstring& value); + + static orcus::spreadsheet::underline_t extract_underline_style(const orcus::pstring& value); }; } diff --git a/src/liborcus/odf_styles_context.cpp b/src/liborcus/odf_styles_context.cpp index b62edfc154ad1a7e8820c7a57482c3a73f4f1bdd..72c34321351ab01a9f6c8d16ac306cbcd15d06ac 100644 --- a/src/liborcus/odf_styles_context.cpp +++ b/src/liborcus/odf_styles_context.cpp @@ -107,8 +107,25 @@ class text_prop_attr_parser : std::unary_function spreadsheet::color_elem_t m_green; spreadsheet::color_elem_t m_blue; + bool m_underline_is_text_color; + bool m_underline; + + spreadsheet::color_elem_t m_underline_red; + spreadsheet::color_elem_t m_underline_green; + spreadsheet::color_elem_t m_underline_blue; + + spreadsheet::underline_mode_t m_underline_mode; + spreadsheet::underline_width_t m_underline_width; + spreadsheet::underline_t m_underline_style; + spreadsheet::underline_type_t m_underline_type; + public: - text_prop_attr_parser() : m_bold(false), m_italic(false), m_color(false) {} + text_prop_attr_parser() : m_bold(false), m_italic(false), m_color(false), + m_underline_is_text_color(false), m_underline(false), + m_underline_mode(spreadsheet::underline_mode_t::continuos), + m_underline_width(spreadsheet::underline_width_t::none), + m_underline_style(spreadsheet::underline_t::none), + m_underline_type(spreadsheet::underline_type_t::none) {} void operator() (const xml_token_attr_t& attr) { @@ -119,6 +136,43 @@ public: case XML_font_name: m_font_name = attr.value; break; + case XML_text_underline_color: + if (!odf_helper::convert_fo_color(attr.value, m_underline_red, m_underline_green, m_underline_blue)) + { + m_underline = true; + m_underline_is_text_color = true; + } + break; + case XML_text_underline_mode: + m_underline = true; + if (attr.value == "skip-white-space") + m_underline_mode = spreadsheet::underline_mode_t::skip_white_space; + else + m_underline_mode = spreadsheet::underline_mode_t::continuos; + break; + case XML_text_underline_width: + { + m_underline = true; + m_underline_width = odf_helper::extract_underline_width(attr.value); + } + break; + case XML_text_underline_style: + { + m_underline = true; + m_underline_style = odf_helper::extract_underline_style(attr.value); + } + break; + case XML_text_underline_type: + { + m_underline = true; + if (attr.value == "none") + m_underline_type = spreadsheet::underline_type_t::none; + if (attr.value == "single") + m_underline_type = spreadsheet::underline_type_t::single; + if (attr.value == "double") + m_underline_type = spreadsheet::underline_type_t::double_type; + } + break; default: ; } @@ -158,6 +212,19 @@ public: green = m_green; blue = m_blue; } + bool has_underline() const { return m_underline; } + bool underline_is_text_color() const { return m_underline_is_text_color; } + const spreadsheet::underline_width_t get_underline_width() const { return m_underline_width; } + const spreadsheet::underline_mode_t get_underline_mode() const { return m_underline_mode; } + const spreadsheet::underline_type_t get_underline_type() const { return m_underline_type; } + const spreadsheet::underline_t get_underline_style() const { return m_underline_style; } + void get_underline_color(spreadsheet::color_elem_t& red, spreadsheet::color_elem_t& green, + spreadsheet::color_elem_t& blue) + { + red = m_underline_red; + green = m_underline_green; + blue = m_underline_blue; + } }; class cell_prop_attr_parser : std::unary_function @@ -414,6 +481,33 @@ void styles_context::start_element(xmlns_id_t ns, xml_token_t name, const std::v mp_styles->set_font_color(0, red, green, blue); } + if (func.has_underline()) + { + if (func.underline_is_text_color() && func.has_color()) + { + spreadsheet::color_elem_t red, green, blue; + func.get_color(red, green, blue); + mp_styles->set_font_underline_color(0, red, green, blue); + } + else + { + spreadsheet::color_elem_t red, green, blue; + func.get_underline_color(red, green, blue); + mp_styles->set_font_underline_color(0, red, green, blue); + } + spreadsheet::underline_width_t width = func.get_underline_width(); + mp_styles->set_font_underline_width(width); + + spreadsheet::underline_t style = func.get_underline_style(); + mp_styles->set_font_underline(style); + + spreadsheet::underline_type_t type = func.get_underline_type(); + mp_styles->set_font_underline_type(type); + + spreadsheet::underline_mode_t mode = func.get_underline_mode(); + mp_styles->set_font_underline_mode(mode); + } + size_t font_id = mp_styles->commit_font(); switch (m_current_style->family) diff --git a/src/liborcus/odf_styles_context_test.cpp b/src/liborcus/odf_styles_context_test.cpp index 838bf2d55e9cbee863553863d371c54f6fb0ec9d..d037b18ebedf8372994949d7708b00d71ede567d 100644 --- a/src/liborcus/odf_styles_context_test.cpp +++ b/src/liborcus/odf_styles_context_test.cpp @@ -112,5 +112,46 @@ int main() assert(cell_border->diagonal_tl_br.border_color.green == 0x00); assert(cell_border->diagonal_tl_br.border_width.value == 0.74); +/* Test for Font and underline + ================================================== +*/ + style = find_cell_style_by_name("Name8", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + size_t font = cell_format->font; + assert(cell_format); + + const orcus::spreadsheet::font_t* cell_font = styles.get_font(font); + assert(cell_font->name == "Liberation Sans"); + assert(cell_font->size == 24); + assert(cell_font->bold == true); + assert(cell_font->italic == true); + assert(cell_font->underline_style == orcus::spreadsheet::underline_t::solid); + assert(cell_font->underline_width == orcus::spreadsheet::underline_width_t::thick); + assert(cell_font->underline_mode == orcus::spreadsheet::underline_mode_t::continuos); + assert(cell_font->underline_type == orcus::spreadsheet::underline_type_t::none); + assert(cell_font->underline_color.red == (int)0x80); + assert(cell_font->underline_color.green == (int)0x80); + assert(cell_font->underline_color.blue == (int)0x80); + + style = find_cell_style_by_name("Name9", &styles); + xf = style->xf; + cell_format = styles.get_cell_style_format(xf); + font = cell_format->font; + assert(cell_format); + + cell_font = styles.get_font(font); + assert(cell_font->name == "Tahoma"); + assert(cell_font->size == 00); + assert(cell_font->bold == true); + assert(cell_font->italic == false); + assert(cell_font->underline_style == orcus::spreadsheet::underline_t::dash); + assert(cell_font->underline_width == orcus::spreadsheet::underline_width_t::bold); + assert(cell_font->underline_mode == orcus::spreadsheet::underline_mode_t::continuos); + assert(cell_font->underline_type == orcus::spreadsheet::underline_type_t::none); + assert(cell_font->underline_color.red == (int)0x18); + assert(cell_font->underline_color.green == (int)0x56); + assert(cell_font->underline_color.blue == (int)0xff); + return 0; } diff --git a/src/spreadsheet/styles.cpp b/src/spreadsheet/styles.cpp index 9e62c0c6c7e7c577df739576f870658ac8515060..e1795d80acf808294556912c50055bcf766aef65 100644 --- a/src/spreadsheet/styles.cpp +++ b/src/spreadsheet/styles.cpp @@ -15,7 +15,10 @@ namespace orcus { namespace spreadsheet { font_t::font_t() : size(0.0), bold(false), - italic(false), underline(underline_t::none), + italic(false), underline_style(underline_t::none), + underline_width(underline_width_t::none), + underline_mode(underline_mode_t::continuos), + underline_type(underline_type_t::none), color() { } @@ -154,7 +157,27 @@ void import_styles::set_font_size(double point) void import_styles::set_font_underline(underline_t e) { - m_cur_font.underline = e; + m_cur_font.underline_style = e; +} + +void import_styles::set_font_underline_width(underline_width_t e) +{ + m_cur_font.underline_width = e; +} + +void import_styles::set_font_underline_mode(underline_mode_t e) +{ + m_cur_font.underline_mode = e; +} + +void import_styles::set_font_underline_type(underline_type_t e) +{ + m_cur_font.underline_type = e; +} + +void import_styles::set_font_underline_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) +{ + m_cur_font.underline_color = color_t(alpha, red, green, blue); } void import_styles::set_font_color(color_elem_t alpha, color_elem_t red, color_elem_t green, color_elem_t blue) diff --git a/test/ods/styles/cell-styles.xml b/test/ods/styles/cell-styles.xml index e9b944d1a1845d3d19bf70bd1fbe46a572c142a7..81b2a45caef66b49c7b7fd314f72e5bf3b64f640 100644 --- a/test/ods/styles/cell-styles.xml +++ b/test/ods/styles/cell-styles.xml @@ -12,4 +12,10 @@ + + + + + +