summaryrefslogtreecommitdiffstats
path: root/src/spreadsheet/styles.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/spreadsheet/styles.cpp485
1 files changed, 485 insertions, 0 deletions
diff --git a/src/spreadsheet/styles.cpp b/src/spreadsheet/styles.cpp
new file mode 100644
index 0000000..328814e
--- /dev/null
+++ b/src/spreadsheet/styles.cpp
@@ -0,0 +1,485 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "orcus/spreadsheet/styles.hpp"
+#include "orcus/string_pool.hpp"
+
+#include "ostream_utils.hpp"
+
+#include <functional>
+#include <algorithm>
+#include <cassert>
+#include <iomanip>
+#include <vector>
+#include <map>
+
+namespace orcus { namespace spreadsheet {
+
+font_t::font_t() = default;
+font_t::font_t(const font_t& other) = default;
+font_t::~font_t() = default;
+
+font_t& font_t::operator=(const font_t& other) = default;
+
+bool font_t::operator==(const font_t& other) const
+{
+ if (name != other.name)
+ return false;
+
+ if (name_asian != other.name_asian)
+ return false;
+
+ if (name_complex != other.name_complex)
+ return false;
+
+ if (size != other.size)
+ return false;
+
+ if (size_asian != other.size_asian)
+ return false;
+
+ if (size_complex != other.size_complex)
+ return false;
+
+ if (bold != other.bold)
+ return false;
+
+ if (bold_asian != other.bold_asian)
+ return false;
+
+ if (bold_complex != other.bold_complex)
+ return false;
+
+ if (italic != other.italic)
+ return false;
+
+ if (italic_asian != other.italic_asian)
+ return false;
+
+ if (italic_complex != other.italic_complex)
+ return false;
+
+ if (underline_style != other.underline_style)
+ return false;
+
+ if (underline_width != other.underline_width)
+ return false;
+
+ if (underline_mode != other.underline_mode)
+ return false;
+
+ if (underline_type != other.underline_type)
+ return false;
+
+ if (underline_color != other.underline_color)
+ return false;
+
+ if (color != other.color)
+ return false;
+
+ if (strikethrough_style != other.strikethrough_style)
+ return false;
+
+ if (strikethrough_width != other.strikethrough_width)
+ return false;
+
+ if (strikethrough_type != other.strikethrough_type)
+ return false;
+
+ if (strikethrough_text != other.strikethrough_text)
+ return false;
+
+ return true;
+}
+
+bool font_t::operator!=(const font_t& other) const
+{
+ return !operator==(other);
+}
+
+void font_t::reset()
+{
+ *this = font_t();
+}
+
+std::size_t font_t::hash::operator()(const font_t& v) const
+{
+ std::size_t hash_value = 0u;
+
+ if (v.name)
+ hash_value |= std::hash<std::string_view>{}(*v.name);
+
+ if (v.size)
+ hash_value |= std::hash<double>{}(*v.size);
+
+ if (v.bold)
+ hash_value |= std::hash<bool>{}(*v.bold);
+
+ if (v.italic)
+ hash_value |= std::hash<bool>{}(*v.italic);
+
+ return hash_value;
+}
+
+fill_t::fill_t() = default;
+
+void fill_t::reset()
+{
+ *this = fill_t();
+}
+
+border_attrs_t::border_attrs_t() = default;
+
+void border_attrs_t::reset()
+{
+ *this = border_attrs_t();
+}
+
+border_t::border_t() = default;
+
+void border_t::reset()
+{
+ *this = border_t();
+}
+
+protection_t::protection_t() = default;
+
+void protection_t::reset()
+{
+ *this = protection_t();
+}
+
+number_format_t::number_format_t() = default;
+
+void number_format_t::reset()
+{
+ *this = number_format_t();
+}
+
+bool number_format_t::operator== (const number_format_t& other) const noexcept
+{
+ return identifier == other.identifier && format_string == other.format_string;
+}
+
+bool number_format_t::operator!= (const number_format_t& other) const noexcept
+{
+ return !operator== (other);
+}
+
+cell_format_t::cell_format_t() :
+ font(0),
+ fill(0),
+ border(0),
+ protection(0),
+ number_format(0),
+ style_xf(0),
+ hor_align(hor_alignment_t::unknown),
+ ver_align(ver_alignment_t::unknown),
+ apply_num_format(false),
+ apply_font(false),
+ apply_fill(false),
+ apply_border(false),
+ apply_alignment(false),
+ apply_protection(false)
+{
+}
+
+void cell_format_t::reset()
+{
+ *this = cell_format_t();
+}
+
+cell_style_t::cell_style_t() :
+ xf(0), builtin(0)
+{
+}
+
+void cell_style_t::reset()
+{
+ *this = cell_style_t();
+}
+
+std::ostream& operator<< (std::ostream& os, const color_t& c)
+{
+ ::orcus::detail::ostream_format_guard ifs(os);
+
+ os << std::uppercase;
+
+ os << "(ARGB:"
+ << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.alpha & 0xFF)
+ << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.red & 0xFF)
+ << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.green & 0xFF)
+ << ' ' << std::hex << std::setfill('0') << std::setw(2) << int(c.blue & 0xFF)
+ << ")";
+
+ return os;
+}
+
+struct styles::impl
+{
+ std::vector<font_t> fonts;
+ std::vector<fill_t> fills;
+ std::vector<border_t> borders;
+ std::vector<protection_t> protections;
+ std::vector<number_format_t> number_formats;
+ std::vector<cell_format_t> cell_style_formats;
+ std::vector<cell_format_t> cell_formats;
+ std::vector<cell_format_t> dxf_formats;
+ std::vector<cell_style_t> cell_styles;
+ std::map<std::size_t, std::size_t> cell_styles_map; // style xf to style position in `cell_styles`
+
+ string_pool str_pool;
+};
+
+styles::styles() : mp_impl(std::make_unique<impl>()) {}
+styles::~styles() {}
+
+void styles::reserve_font_store(size_t n)
+{
+ mp_impl->fonts.reserve(n);
+}
+
+std::size_t styles::append_font(const font_t& font)
+{
+ mp_impl->fonts.emplace_back(font);
+ return mp_impl->fonts.size() - 1;
+}
+
+void styles::reserve_fill_store(size_t n)
+{
+ mp_impl->fills.reserve(n);
+}
+
+std::size_t styles::append_fill(const fill_t& fill)
+{
+ mp_impl->fills.emplace_back(fill);
+ return mp_impl->fills.size() - 1;
+}
+
+void styles::reserve_border_store(size_t n)
+{
+ mp_impl->borders.reserve(n);
+}
+
+std::size_t styles::append_border(const border_t& border)
+{
+ mp_impl->borders.emplace_back(border);
+ return mp_impl->borders.size() - 1;
+}
+
+std::size_t styles::append_protection(const protection_t& protection)
+{
+ mp_impl->protections.emplace_back(protection);
+ return mp_impl->protections.size() - 1;
+}
+
+void styles::reserve_number_format_store(size_t n)
+{
+ mp_impl->number_formats.reserve(n);
+}
+
+std::size_t styles::append_number_format(const number_format_t& nf)
+{
+ if (nf.format_string)
+ {
+ number_format_t copied = nf;
+ copied.format_string = mp_impl->str_pool.intern(*nf.format_string).first;
+ mp_impl->number_formats.emplace_back(copied);
+ }
+ else
+ mp_impl->number_formats.emplace_back(nf);
+
+ return mp_impl->number_formats.size() - 1;
+}
+
+void styles::reserve_cell_style_format_store(size_t n)
+{
+ mp_impl->cell_style_formats.reserve(n);
+}
+
+size_t styles::append_cell_style_format(const cell_format_t& cf)
+{
+ mp_impl->cell_style_formats.push_back(cf);
+ return mp_impl->cell_style_formats.size() - 1;
+}
+
+void styles::reserve_cell_format_store(size_t n)
+{
+ mp_impl->cell_formats.reserve(n);
+}
+
+size_t styles::append_cell_format(const cell_format_t& cf)
+{
+ mp_impl->cell_formats.push_back(cf);
+ return mp_impl->cell_formats.size() - 1;
+}
+
+void styles::reserve_diff_cell_format_store(size_t n)
+{
+ mp_impl->dxf_formats.reserve(n);
+}
+
+size_t styles::append_diff_cell_format(const cell_format_t& cf)
+{
+ mp_impl->dxf_formats.push_back(cf);
+ return mp_impl->dxf_formats.size() - 1;
+}
+
+void styles::reserve_cell_style_store(size_t n)
+{
+ mp_impl->cell_styles.reserve(n);
+}
+
+void styles::append_cell_style(const cell_style_t& cs)
+{
+ mp_impl->cell_styles.push_back(cs);
+}
+
+const font_t* styles::get_font(size_t index) const
+{
+ if (index >= mp_impl->fonts.size())
+ return nullptr;
+
+ return &mp_impl->fonts[index];
+}
+
+const cell_format_t* styles::get_cell_format(size_t index) const
+{
+ if (index >= mp_impl->cell_formats.size())
+ return nullptr;
+
+ return &mp_impl->cell_formats[index];
+}
+
+const fill_t* styles::get_fill(size_t index) const
+{
+ if (index >= mp_impl->fills.size())
+ return nullptr;
+
+ return &mp_impl->fills[index];
+}
+
+const border_t* styles::get_border(size_t index) const
+{
+ if (index >= mp_impl->borders.size())
+ return nullptr;
+
+ return &mp_impl->borders[index];
+}
+
+const protection_t* styles::get_protection(size_t index) const
+{
+ if (index >= mp_impl->protections.size())
+ return nullptr;
+
+ return &mp_impl->protections[index];
+}
+
+const number_format_t* styles::get_number_format(size_t index) const
+{
+ if (index >= mp_impl->number_formats.size())
+ return nullptr;
+
+ return &mp_impl->number_formats[index];
+}
+
+const cell_format_t* styles::get_cell_style_format(size_t index) const
+{
+ if (index >= mp_impl->cell_style_formats.size())
+ return nullptr;
+
+ return &mp_impl->cell_style_formats[index];
+}
+
+const cell_format_t* styles::get_dxf_format(size_t index) const
+{
+ if (index >= mp_impl->dxf_formats.size())
+ return nullptr;
+
+ return &mp_impl->dxf_formats[index];
+}
+
+const cell_style_t* styles::get_cell_style(size_t index) const
+{
+ if (index >= mp_impl->cell_styles.size())
+ return nullptr;
+
+ return &mp_impl->cell_styles[index];
+}
+
+const cell_style_t* styles::get_cell_style_by_xf(size_t xfid) const
+{
+ auto it = mp_impl->cell_styles_map.find(xfid);
+ if (it == mp_impl->cell_styles_map.end())
+ return nullptr;
+
+ auto index = it->second;
+ return &mp_impl->cell_styles[index];
+}
+
+size_t styles::get_font_count() const
+{
+ return mp_impl->fonts.size();
+}
+
+size_t styles::get_fill_count() const
+{
+ return mp_impl->fills.size();
+}
+
+size_t styles::get_border_count() const
+{
+ return mp_impl->borders.size();
+}
+
+size_t styles::get_protection_count() const
+{
+ return mp_impl->protections.size();
+}
+
+size_t styles::get_number_format_count() const
+{
+ return mp_impl->number_formats.size();
+}
+
+size_t styles::get_cell_formats_count() const
+{
+ return mp_impl->cell_formats.size();
+}
+
+size_t styles::get_cell_style_formats_count() const
+{
+ return mp_impl->cell_style_formats.size();
+}
+
+size_t styles::get_dxf_count() const
+{
+ return mp_impl->dxf_formats.size();
+}
+
+size_t styles::get_cell_styles_count() const
+{
+ return mp_impl->cell_styles.size();
+}
+
+void styles::clear()
+{
+ mp_impl = std::make_unique<impl>();
+}
+
+void styles::finalize_import()
+{
+ for (std::size_t i = 0; i < mp_impl->cell_styles.size(); ++i)
+ {
+ const auto& entry = mp_impl->cell_styles[i];
+ mp_impl->cell_styles_map.insert_or_assign(entry.xf, i);
+ }
+}
+
+}}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */