diff --git a/source/basic_types.cpp b/source/basic_types.cpp index f8bb0823..d02d497f 100644 --- a/source/basic_types.cpp +++ b/source/basic_types.cpp @@ -11,7 +11,11 @@ */ #include +#if defined(USE_STD_REGEX) #include +#else +#include +#endif #include namespace nana @@ -60,10 +64,46 @@ namespace nana a_ = 1.0; } +#if !defined(USE_STD_REGEX) + std::string read_number(std::string& str, std::size_t& pos) + { + pos = str.find_first_of("0123456789", pos); + if (pos == str.npos) + return{}; + + auto end = str.find_first_not_of("0123456789", pos + 1); + //integer part + if (end == str.npos) + { + pos = end; + return str.substr(pos); + } + + if (str[end] == '.') + { + auto decimal_end = str.find_first_not_of("0123456789", end + 1); + if ((decimal_end == str.npos) || (decimal_end == end + 1)) //Because of missing % + return{}; + + end = decimal_end; + } + + auto ch = str[end]; + if (ch == '%' || ch == ' ' || ch == ',' || ch == ')') + { + auto start = pos; + pos = end + (ch == '%' ? 1 : 0); + return str.substr(start, pos - start); + } + return{}; + } +#endif + //Initializes the color with a CSS-like string //contributor: BigDave(mortis2007 at hotmail co uk) //date: February 3, 2015 //maintainor: Jinhao, extended the support of CSS-spec + color::color(std::string css_color) : a_(1.0) { @@ -135,6 +175,7 @@ namespace nana has_alpha = true; } +#if defined(USE_STD_REGEX) std::regex pat; std::regex_iterator i, end; auto type_name = css_color.substr(pos, 3); @@ -222,6 +263,106 @@ namespace nana throw std::invalid_argument(excpt_what); //invalid alpha value a_ = ::nana::stod(i->str()); } +#else + auto type_name = css_color.substr(pos, 3); + pos = css_color.find_first_not_of(' ', type_end); + if (pos == css_color.npos || css_color[pos] != '(') + throw std::invalid_argument(excpt_what); + + auto str = read_number(css_color, ++pos); + if (str.empty()) + throw std::invalid_argument(excpt_what); + + if ("rgb" == type_name) + { + std::vector rgb; + + rgb.emplace_back(std::move(str)); + + const bool is_real = (rgb.back().back() == '%'); + + for (int i = 0; i < 2; ++i) + { + pos = css_color.find_first_not_of(' ', pos); + if (pos == css_color.npos || css_color[pos] != ',') + throw std::invalid_argument(excpt_what); + + str = read_number(css_color, ++pos); + if (str.empty()) + throw std::invalid_argument(excpt_what); + + rgb.emplace_back(std::move(str)); + if (rgb.size() == 3) + break; + } + + if (rgb.size() != 3) + throw std::invalid_argument(excpt_what); + + if (is_real) + { + auto pr = ::nana::stod(rgb[0].substr(0, rgb[0].size() - 1)); + r_ = (pr > 100 ? 255.0 : 2.55 * pr); + + pr = ::nana::stod(rgb[1].substr(0, rgb[1].size() - 1)); + g_ = (pr > 100 ? 255.0 : 2.55 * pr); + + pr = ::nana::stod(rgb[2].substr(0, rgb[2].size() - 1)); + b_ = (pr > 100 ? 255.0 : 2.55 * pr); + } + else + { + r_ = ::nana::stod(rgb[0]); + if (r_ > 255.0) r_ = 255; + + g_ = ::nana::stod(rgb[1]); + if (g_ > 255.0) g_ = 255; + + b_ = ::nana::stod(rgb[2]); + if (b_ > 255.0) b_ = 255; + } + } + else if ("hsl" == type_name) + { + if (str.back() == '%') + throw std::invalid_argument(excpt_what); + + auto h = ::nana::stod(str); + + pos = css_color.find_first_not_of(' ', pos); + if (pos == css_color.npos || css_color[pos] != ',') + throw std::invalid_argument(excpt_what); + + str = read_number(css_color, ++pos); + if (str.empty() || str.back() != '%') + throw std::invalid_argument(excpt_what); + + auto s = ::nana::stod(str.substr(0, str.size() - 1)); + + pos = css_color.find_first_not_of(' ', pos); + if (pos == css_color.npos || css_color[pos] != ',') + throw std::invalid_argument(excpt_what); + + str = read_number(css_color, ++pos); + if (str.empty() || str.back() != '%') + throw std::invalid_argument(excpt_what); + + auto l = ::nana::stod(str.substr(0, str.size() - 1)); + + from_hsl(h, s / 100, l / 100); + } + else + throw std::invalid_argument(excpt_what); //invalid color type + + if (has_alpha) + { + str = read_number(css_color, ++pos); + if (str.empty() || str.back() == '%') + throw std::invalid_argument(excpt_what); //invalid alpha value + + a_ = ::nana::stod(str); + } +#endif } color& color::from_rgb(unsigned red, unsigned green, unsigned blue)