123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- // Copyright (c) 2014-2021 Thomas Fussell
- // Copyright (c) 2010-2015 openpyxl
- //
- // 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, ARISING 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 <cmath>
- #include <cstdlib>
- #include <xlnt/styles/color.hpp>
- #include <xlnt/utils/exceptions.hpp>
- namespace {
- std::array<std::uint8_t, 4> decode_hex_string(const std::string &hex_string)
- {
- auto x = std::strtoul(hex_string.c_str(), nullptr, 16);
- auto a = static_cast<std::uint8_t>(x >> 24);
- auto r = static_cast<std::uint8_t>((x >> 16) & 0xff);
- auto g = static_cast<std::uint8_t>((x >> 8) & 0xff);
- auto b = static_cast<std::uint8_t>(x & 0xff);
- return {{r, g, b, a}};
- }
- } // namespace
- namespace xlnt {
- // indexed_color implementation
- indexed_color::indexed_color(std::size_t index)
- : index_(index)
- {
- }
- std::size_t indexed_color::index() const
- {
- return index_;
- }
- void indexed_color::index(std::size_t index)
- {
- index_ = index;
- }
- // theme_color implementation
- theme_color::theme_color(std::size_t index)
- : index_(index)
- {
- }
- std::size_t theme_color::index() const
- {
- return index_;
- }
- void theme_color::index(std::size_t index)
- {
- index_ = index;
- }
- // rgb_color implementation
- std::string rgb_color::hex_string() const
- {
- static const char *digits = "0123456789ABCDEF";
- std::string hex_string(8, '0');
- auto out_iter = hex_string.begin();
- for (auto byte : {rgba_[3], rgba_[0], rgba_[1], rgba_[2]})
- {
- for (auto i = 0; i < 2; ++i)
- {
- auto nibble = byte >> (4 * (1 - i)) & 0xf;
- *(out_iter++) = digits[nibble];
- }
- }
- return hex_string;
- }
- rgb_color::rgb_color(const std::string &hex_string)
- : rgba_(decode_hex_string(hex_string))
- {
- }
- rgb_color::rgb_color(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a)
- : rgba_({{r, g, b, a}})
- {
- }
- std::uint8_t rgb_color::red() const
- {
- return rgba_[0];
- }
- std::uint8_t rgb_color::green() const
- {
- return rgba_[1];
- }
- std::uint8_t rgb_color::blue() const
- {
- return rgba_[2];
- }
- std::uint8_t rgb_color::alpha() const
- {
- return rgba_[3];
- }
- std::array<std::uint8_t, 3> rgb_color::rgb() const
- {
- return {{red(), green(), blue()}};
- }
- std::array<std::uint8_t, 4> rgb_color::rgba() const
- {
- return rgba_;
- }
- // color implementation
- const color color::black()
- {
- return color(rgb_color("ff000000"));
- }
- const color color::white()
- {
- return color(rgb_color("ffffffff"));
- }
- const color color::red()
- {
- return color(rgb_color("ffff0000"));
- }
- const color color::darkred()
- {
- return color(rgb_color("ff8b0000"));
- }
- const color color::blue()
- {
- return color(rgb_color("ff0000ff"));
- }
- const color color::darkblue()
- {
- return color(rgb_color("ff00008b"));
- }
- const color color::green()
- {
- return color(rgb_color("ff00ff00"));
- }
- const color color::darkgreen()
- {
- return color(rgb_color("ff008b00"));
- }
- const color color::yellow()
- {
- return color(rgb_color("ffffff00"));
- }
- const color color::darkyellow()
- {
- return color(rgb_color("ffcccc00"));
- }
- color::color()
- : color(indexed_color(0))
- {
- }
- color::color(const rgb_color &rgb)
- : type_(color_type::rgb),
- rgb_(rgb),
- indexed_(0),
- theme_(0)
- {
- }
- color::color(const indexed_color &indexed)
- : type_(color_type::indexed),
- rgb_(rgb_color(0, 0, 0, 0)),
- indexed_(indexed),
- theme_(0)
- {
- }
- color::color(const theme_color &theme)
- : type_(color_type::theme),
- rgb_(rgb_color(0, 0, 0, 0)),
- indexed_(0),
- theme_(theme)
- {
- }
- color_type color::type() const
- {
- return type_;
- }
- bool color::auto_() const
- {
- return auto_color;
- }
- void color::auto_(bool value)
- {
- auto_color = value;
- }
- const indexed_color &color::indexed() const
- {
- assert_type(color_type::indexed);
- return indexed_;
- }
- indexed_color &color::indexed()
- {
- assert_type(color_type::indexed);
- return indexed_;
- }
- const theme_color &color::theme() const
- {
- assert_type(color_type::theme);
- return theme_;
- }
- theme_color &color::theme()
- {
- assert_type(color_type::theme);
- return theme_;
- }
- const rgb_color &color::rgb() const
- {
- assert_type(color_type::rgb);
- return rgb_;
- }
- rgb_color &color::rgb()
- {
- assert_type(color_type::rgb);
- return rgb_;
- }
- bool color::has_tint() const
- {
- return tint_.is_set();
- }
- void color::tint(double tint)
- {
- tint_ = tint;
- }
- double color::tint() const
- {
- return tint_.is_set() ? tint_.get() : 0.0;
- }
- void color::assert_type(color_type t) const
- {
- if (t != type_)
- {
- throw invalid_attribute();
- }
- }
- bool color::operator==(const xlnt::color &other) const
- {
- if (type_ != other.type_ || auto_color != other.auto_color)
- {
- return false;
- }
- if (tint_.is_set() != other.tint_.is_set() || (tint_.is_set() && std::fabs(tint_.get() - other.tint_.get()) != 0.0))
- {
- return false;
- }
- switch (type_)
- {
- case color_type::indexed:
- return indexed_.index() == other.indexed_.index();
- case color_type::theme:
- return theme_.index() == other.theme_.index();
- case color_type::rgb:
- return rgb_.rgba() == other.rgb_.rgba();
- }
- return false;
- }
- bool color::operator!=(const color &other) const
- {
- return !(*this == other);
- }
- } // namespace xlnt
|