From 5817ef5cf05878f1b6919101f8c1bc14efb08722 Mon Sep 17 00:00:00 2001 From: Crzyrndm Date: Sat, 23 Jun 2018 12:15:15 +1200 Subject: [PATCH] Add serialisation of worksheet phonetic properties --- include/xlnt/worksheet/phonetic_pr.cpp | 143 +++++++++++++++ include/xlnt/worksheet/phonetic_pr.hpp | 165 ++++++++++++++++++ include/xlnt/worksheet/worksheet.hpp | 16 ++ .../detail/implementations/worksheet_impl.hpp | 5 +- source/detail/serialization/xlsx_consumer.cpp | 13 +- source/detail/serialization/xlsx_producer.cpp | 16 ++ source/worksheet/worksheet.cpp | 25 ++- 7 files changed, 375 insertions(+), 8 deletions(-) create mode 100644 include/xlnt/worksheet/phonetic_pr.cpp create mode 100644 include/xlnt/worksheet/phonetic_pr.hpp diff --git a/include/xlnt/worksheet/phonetic_pr.cpp b/include/xlnt/worksheet/phonetic_pr.cpp new file mode 100644 index 00000000..ad2c48cd --- /dev/null +++ b/include/xlnt/worksheet/phonetic_pr.cpp @@ -0,0 +1,143 @@ +// Copyright (c) 2014-2018 Thomas Fussell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#include "phonetic_pr.hpp" +#include +namespace { +// Order of elements defined by phonetic_pr::Type enum +const std::array Types{ + "fullwidthKatakana", + "halfwidthKatakana", + "Hiragana", + "noConversion"}; + +// Order of elements defined by phonetic_pr::Alignment enum +const std::array Alignments{ + "Center", + "Distributed", + "Left", + "NoControl"}; + +} // namespace + +namespace xlnt { +/// +/// out of line initialiser for static const member +/// +const std::string phonetic_pr::Serialised_ID = "phoneticPr"; + +phonetic_pr::phonetic_pr(Font_ID font) + : font_id_(font) +{ +} + +void phonetic_pr::serialise(std::ostream &output_stream) const +{ + output_stream << '<' << Serialised_ID << R"( fontID=")" << std::to_string(font_id_) << '"'; + if (has_type()) + { + output_stream << R"( type=")" << type_as_string(type_.get()) << '"'; + } + if (has_alignment()) + { + output_stream << R"( alignment=")" << alignment_as_string(alignment_.get()) << '"'; + } + output_stream << "/>"; +} + +phonetic_pr::Font_ID phonetic_pr::font_id() const +{ + return font_id_; +} + +void phonetic_pr::font_id(Font_ID font) +{ + font_id_ = font; +} + +bool phonetic_pr::has_type() const +{ + return type_.is_set(); +} + +phonetic_pr::Type phonetic_pr::type() const +{ + return type_.get(); +} + +void phonetic_pr::type(Type type) +{ + type_.set(type); +} + +bool phonetic_pr::has_alignment() const +{ + return alignment_.is_set(); +} + +phonetic_pr::Alignment phonetic_pr::alignment() const +{ + return alignment_.get(); +} + +void phonetic_pr::alignment(Alignment align) +{ + alignment_.set(align); +} + +// serialisation +const std::string &phonetic_pr::type_as_string(phonetic_pr::Type type) +{ + return Types[static_cast(type)]; +} + +phonetic_pr::Type phonetic_pr::type_from_string(const std::string &str) +{ + for (int i = 0; i < Types.size(); ++i) + { + if (str == Types[i]) + { + return static_cast(i); + } + } + return Type::No_Conversion; +} + +const std::string &phonetic_pr::alignment_as_string(Alignment type) +{ + return Alignments[static_cast(type)]; +} + +phonetic_pr::Alignment phonetic_pr::alignment_from_string(const std::string &str) +{ + for (int i = 0; i < Alignments.size(); ++i) + { + if (str == Alignments[i]) + { + return static_cast(i); + } + } + return Alignment::No_Control; +} + +} // namespace xlnt \ No newline at end of file diff --git a/include/xlnt/worksheet/phonetic_pr.hpp b/include/xlnt/worksheet/phonetic_pr.hpp new file mode 100644 index 00000000..e3929108 --- /dev/null +++ b/include/xlnt/worksheet/phonetic_pr.hpp @@ -0,0 +1,165 @@ +// Copyright (c) 2014-2018 Thomas Fussell +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE +// +// @license: http://www.opensource.org/licenses/mit-license.php +// @author: see AUTHORS file + +#pragma once + +#include +#include +#include +#include + +namespace xlnt { + +/// +/// Phonetic properties +/// Element provides a collection of properties that affect display of East Asian Languages +/// [Serialised phoneticPr] +/// +class XLNT_API phonetic_pr +{ +public: + static const std::string Serialised_ID; + + /// + /// possible values for alignment property + /// + enum class Alignment + { + Center, + Distributed, + Left, + No_Control + }; + + /// + /// possible values for type property + /// + enum class Type + { + Full_Width_Katakana, + Half_Width_Katakana, + Hiragana, + No_Conversion + }; + + /// + /// FontID represented by an unsigned 32-bit integer + /// + using Font_ID = std::uint32_t; + + /// + /// Default ctor for phonetic properties + /// + phonetic_pr() = default; + + /// + /// FontID ctor for phonetic properties + /// + explicit phonetic_pr(Font_ID font); + + /// + /// adds the xml serialised representation of this element to the stream + /// + void serialise(std::ostream& output_stream) const; + + /// + /// get the font index + /// + Font_ID font_id() const; + + /// + /// set the font index + /// + void font_id(Font_ID font); + + /// + /// is the phonetic type set + /// + bool has_type() const; + + /// + /// returns the phonetic type + /// + Type type() const; + + /// + /// sets the phonetic type + /// + void type(Type type); + + /// + /// is the alignment set + /// + bool has_alignment() const; + + /// + /// get the alignment + /// + Alignment alignment() const; + + /// + /// set the alignment + /// + void alignment(Alignment align); + + // serialisation + /// + /// string form of the type enum + /// + static const std::string &type_as_string(Type type); + + /// + /// type enum from string + /// + static Type type_from_string(const std::string &str); + + /// + /// string form of alignment enum + /// + static const std::string &alignment_as_string(xlnt::phonetic_pr::Alignment type); + + /// + /// alignment enum from string + /// + static Alignment alignment_from_string(const std::string &str); + +private: + /// + /// zero based index into style sheet font record. + /// Default: 0 + /// + Font_ID font_id_ = 0; + + /// + /// Type of characters to use. + /// Default: full width katakana + /// + xlnt::optional type_; + + /// + /// Alignment across the cell(s). + /// Default: Left + /// + xlnt::optional alignment_; +}; +} \ No newline at end of file diff --git a/include/xlnt/worksheet/worksheet.hpp b/include/xlnt/worksheet/worksheet.hpp index c38ca33b..ed460992 100644 --- a/include/xlnt/worksheet/worksheet.hpp +++ b/include/xlnt/worksheet/worksheet.hpp @@ -56,6 +56,7 @@ class relationship; class row_properties; class sheet_format_properties; class workbook; +class phonetic_pr; struct date; @@ -556,6 +557,21 @@ public: /// void reserve(std::size_t n); + /// + /// Returns true if this sheet has phonetic properties + /// + bool has_phonetic_properties() const; + + /// + /// Returns the phonetic properties of this sheet. + /// + const phonetic_pr &phonetic_properties() const; + + /// + /// Sets the phonetic properties of this sheet to phonetic_props + /// + void phonetic_properties(const phonetic_pr& phonetic_props); + /// /// Returns true if this sheet has a header/footer. /// diff --git a/source/detail/implementations/worksheet_impl.hpp b/source/detail/implementations/worksheet_impl.hpp index 7e8b407a..7bbe86cc 100644 --- a/source/detail/implementations/worksheet_impl.hpp +++ b/source/detail/implementations/worksheet_impl.hpp @@ -27,15 +27,16 @@ #include #include -#include #include #include #include +#include #include #include #include #include #include +#include namespace xlnt { @@ -72,6 +73,7 @@ struct worksheet_impl page_margins_ = other.page_margins_; merged_cells_ = other.merged_cells_; named_ranges_ = other.named_ranges_; + phonetic_properties_ = other.phonetic_properties_; header_footer_ = other.header_footer_; print_title_cols_ = other.print_title_cols_; print_title_rows_ = other.print_title_rows_; @@ -107,6 +109,7 @@ struct worksheet_impl std::vector merged_cells_; std::unordered_map named_ranges_; + optional phonetic_properties_; optional header_footer_; std::string print_title_cols_; diff --git a/source/detail/serialization/xlsx_consumer.cpp b/source/detail/serialization/xlsx_consumer.cpp index 8d6c922f..0c3ef808 100644 --- a/source/detail/serialization/xlsx_consumer.cpp +++ b/source/detail/serialization/xlsx_consumer.cpp @@ -835,7 +835,16 @@ worksheet xlsx_consumer::read_worksheet_end(const std::string &rel_id) } else if (current_worksheet_element == qn("spreadsheetml", "phoneticPr")) // CT_PhoneticPr 0-1 { - skip_remaining_content(current_worksheet_element); + phonetic_pr phonetic_properties(parser().attribute("fontId")); + if (parser().attribute_present("type")) + { + phonetic_properties.type(phonetic_pr::type_from_string(parser().attribute("type"))); + } + if (parser().attribute_present("alignment")) + { + phonetic_properties.alignment(phonetic_pr::alignment_from_string(parser().attribute("alignment"))); + } + current_worksheet_->phonetic_properties_.set(phonetic_properties); } else if (current_worksheet_element == qn("spreadsheetml", "conditionalFormatting")) // CT_ConditionalFormatting 0+ { @@ -847,7 +856,7 @@ worksheet xlsx_consumer::read_worksheet_end(const std::string &rel_id) } else if (current_worksheet_element == qn("spreadsheetml", "hyperlinks")) // CT_Hyperlinks 0-1 { - while (in_element(qn("spreadsheetml", "hyperlinks"))) + while (in_element(current_worksheet_element)) { // CT_Hyperlink expect_start_element(qn("spreadsheetml", "hyperlink"), xml::content::simple); diff --git a/source/detail/serialization/xlsx_producer.cpp b/source/detail/serialization/xlsx_producer.cpp index eeefe8c3..64937d03 100644 --- a/source/detail/serialization/xlsx_producer.cpp +++ b/source/detail/serialization/xlsx_producer.cpp @@ -2705,6 +2705,22 @@ void xlsx_producer::write_worksheet(const relationship &rel) write_end_element(xmlns, "printOptions"); } + if (ws.has_phonetic_properties()) + { + write_start_element(xmlns, phonetic_pr::Serialised_ID); + const auto &ph_props = ws.phonetic_properties(); + write_attribute("fontId", ph_props.font_id()); + if (ph_props.has_type()) + { + write_attribute("type", phonetic_pr::type_as_string(ph_props.type())); + } + if (ph_props.has_alignment()) + { + write_attribute("alignment", phonetic_pr::alignment_as_string(ph_props.alignment())); + } + write_end_element(xmlns, phonetic_pr::Serialised_ID); + } + if (ws.has_page_margins()) { write_start_element(xmlns, "pageMargins"); diff --git a/source/worksheet/worksheet.cpp b/source/worksheet/worksheet.cpp index 9907c011..9d59e895 100644 --- a/source/worksheet/worksheet.cpp +++ b/source/worksheet/worksheet.cpp @@ -26,10 +26,6 @@ #include #include -#include -#include -#include -#include #include #include #include @@ -46,6 +42,10 @@ #include #include #include +#include +#include +#include +#include namespace { @@ -1027,6 +1027,21 @@ void worksheet::register_calc_chain_in_manifest() workbook().register_workbook_part(relationship_type::calculation_chain); } +bool worksheet::has_phonetic_properties() const +{ + return d_->phonetic_properties_.is_set(); +} + +const phonetic_pr& worksheet::phonetic_properties() const +{ + return d_->phonetic_properties_.get(); +} + +void worksheet::phonetic_properties(const phonetic_pr& phonetic_props) +{ + d_->phonetic_properties_.set(phonetic_props); +} + bool worksheet::has_header_footer() const { return d_->header_footer_.is_set(); @@ -1103,7 +1118,7 @@ void worksheet::parent(xlnt::workbook &wb) conditional_format worksheet::conditional_format(const range_reference &ref, const condition &when) { - return workbook().d_->stylesheet_.get().add_conditional_format_rule(d_, ref, when); + return workbook().d_->stylesheet_.get().add_conditional_format_rule(d_, ref, when); } path worksheet::path() const