File indexing completed on 2025-01-30 09:32:37
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include <array>
0012 #include <sstream>
0013 #include <string>
0014
0015 #include "defs.hpp"
0016 #include "utils.hpp"
0017
0018 namespace actsvg {
0019
0020 namespace style {
0021
0022 using rgb = std::array<int, 3>;
0023
0024
0025
0026
0027
0028
0029 static std::string rgb_attr(const rgb &rgb_) {
0030 if (rgb_ == rgb{-1, -1, -1}) {
0031 return "none";
0032 }
0033
0034 return std::string("rgb(") + std::to_string(rgb_[0]) + __c +
0035 std::to_string(rgb_[1]) + __c + std::to_string(rgb_[2]) +
0036 std::string(")");
0037 }
0038
0039
0040 struct color {
0041
0042 rgb _rgb = {255, 255, 255};
0043
0044 scalar _opacity = 1.;
0045
0046 std::vector<std::string> _highlight = {};
0047 rgb _hl_rgb = {255, 0, 0};
0048 };
0049
0050
0051 struct fill {
0052
0053
0054 color _fc = color{{0, 0, 0}};
0055 bool _sterile = false;
0056
0057
0058 fill(const color &fc_) : _fc(fc_) {}
0059
0060
0061 fill(bool s_ = false) : _sterile(s_) {
0062 _fc = color();
0063 _fc._opacity = 0.;
0064 }
0065
0066
0067
0068
0069
0070
0071
0072 template <typename object_type>
0073 void attach_attributes(object_type &o_) const {
0074
0075 if (not _sterile) {
0076 o_._attribute_map["fill"] = rgb_attr(_fc._rgb);
0077 o_._attribute_map["fill-opacity"] = utils::to_string(_fc._opacity);
0078 }
0079
0080 if (_fc._highlight.size() == 2u) {
0081 object_type on_off;
0082 on_off._tag = "set";
0083 on_off._attribute_map["attributeName"] = "fill";
0084 on_off._attribute_map["begin"] = _fc._highlight[0];
0085 on_off._attribute_map["end"] = _fc._highlight[1];
0086 on_off._attribute_map["to"] = rgb_attr(_fc._hl_rgb);
0087 o_.add_object(on_off);
0088 }
0089 }
0090 };
0091
0092
0093 struct stroke {
0094
0095
0096 color _sc{{0, 0, 0}};
0097
0098 scalar _width = 0.5;
0099
0100 scalar _hl_width = 0.5;
0101
0102 std::vector<int> _dasharray = {};
0103
0104 bool _sterile = false;
0105
0106 stroke(const color &c_, scalar w_ = 0.5, const std::vector<int> &d_ = {})
0107 : _sc(c_), _width(w_), _dasharray(d_) {}
0108
0109 stroke(bool s_ = false) : _sterile(s_) {}
0110
0111
0112
0113
0114
0115
0116
0117 template <typename object_type>
0118 void attach_attributes(object_type &o_) const {
0119
0120 if (not _sterile) {
0121 o_._attribute_map["stroke"] = rgb_attr(_sc._rgb);
0122 o_._attribute_map["stroke-opacity"] =
0123 utils::to_string(_sc._opacity);
0124 o_._attribute_map["stroke-width"] = utils::to_string(_width);
0125
0126 if (not _dasharray.empty()) {
0127 std::string da_str;
0128 for (auto [i, d] : utils::enumerate(_dasharray)) {
0129 da_str += std::to_string(d);
0130 if (i + 1 < _dasharray.size()) {
0131 da_str += __blk;
0132 }
0133 }
0134 o_._attribute_map["stroke-dasharray"] = da_str;
0135 }
0136
0137 if (_sc._highlight.size() == 2u) {
0138 object_type on_off;
0139 on_off._tag = "set";
0140 on_off._attribute_map["attributeName"] = "stroke";
0141 on_off._attribute_map["begin"] = _sc._highlight[0];
0142 on_off._attribute_map["end"] = _sc._highlight[1];
0143 on_off._attribute_map["to"] = rgb_attr(_sc._hl_rgb);
0144 o_.add_object(on_off);
0145 }
0146
0147 if (_width != _hl_width) {
0148 object_type on_off;
0149 on_off._tag = "set";
0150 on_off._attribute_map["attributeName"] = "stroke-width";
0151 on_off._attribute_map["begin"] = "mouseover";
0152 on_off._attribute_map["end"] = "mouseout";
0153 on_off._attribute_map["to"] = utils::to_string(_hl_width);
0154 o_.add_object(on_off);
0155 }
0156 }
0157 }
0158 };
0159
0160
0161 struct font {
0162
0163 color _fc{{0, 0, 0}};
0164
0165 std::string _family = "Andale Mono";
0166
0167 unsigned int _size = 12;
0168
0169 scalar _line_spacing = 1.4;
0170
0171 std::string _style = "";
0172
0173
0174
0175
0176
0177
0178
0179 template <typename object_type>
0180 void attach_attributes(object_type &o_) const {
0181 o_._attribute_map["fill"] = rgb_attr(_fc._rgb);
0182 o_._attribute_map["font-size"] = utils::to_string(_size);
0183 if (not _family.empty()) {
0184 o_._attribute_map["font-family"] = _family;
0185 }
0186 if (not _style.empty()) {
0187 o_._attribute_map["font-style"] = _style;
0188 }
0189 }
0190 };
0191
0192
0193 struct transform {
0194
0195 std::array<scalar, 3> _tr = {0., 0.};
0196 std::array<scalar, 3> _rot = {0., 0., 0.};
0197 std::array<scalar, 2> _skew = {0., 0.};
0198 std::array<scalar, 2> _scale = {1., 1.};
0199
0200 bool _sterile = false;
0201
0202
0203
0204
0205
0206
0207 std::string attr() const {
0208 bool translate = (_tr[0] != 0. or _tr[1] != 0.);
0209 bool rotate = (_rot[0] != 0.);
0210 bool scale = (_scale[0] != 1. or _scale[1] != 1.);
0211 bool skew = (_skew[0] != 0. or _skew[1] != 0.);
0212 std::stringstream tr_str;
0213 if (translate) {
0214 tr_str << "translate(" << utils::to_string(_scale[0] * _tr[0])
0215 << __c << utils::to_string(-_scale[0] * _tr[1]) << ")";
0216 if (rotate or scale or skew) {
0217 tr_str << __blk;
0218 }
0219 }
0220 if (rotate) {
0221 tr_str << "rotate(" << utils::to_string(-_rot[0]) << __c
0222 << utils::to_string(_rot[1]) << __c
0223 << utils::to_string(-_rot[2]) << ")";
0224 if (scale or skew) {
0225 tr_str << __blk;
0226 }
0227 }
0228 if (skew) {
0229 tr_str << "skewX(" << utils::to_string(_skew[0]) << ") skewY("
0230 << utils::to_string(_skew[1]) << ")";
0231 }
0232 if (scale) {
0233 tr_str << "scale(" << utils::to_string(_scale[0]) << ","
0234 << utils::to_string(_scale[1]) << ")";
0235 }
0236 return tr_str.str();
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 template <typename object_type>
0248 void attach_attributes(object_type &o_) const {
0249 auto transform_attribute = attr();
0250 if (not transform_attribute.empty()) {
0251 o_._attribute_map["transform"] = transform_attribute;
0252 scalar tx = _tr[0];
0253 scalar ty = _tr[1];
0254 o_._x_range = {o_._x_range[0] + tx, o_._x_range[1] + tx};
0255 o_._y_range = {o_._y_range[0] + ty, o_._y_range[1] + ty};
0256 }
0257 }
0258 };
0259
0260
0261
0262
0263
0264 struct marker {
0265 std::string _type = "";
0266
0267 scalar _size = 4.;
0268
0269 fill _fill = fill{{{0, 0, 0}}};
0270
0271 stroke _stroke = stroke();
0272 };
0273
0274
0275 template <unsigned int kDIM>
0276 using axis_markers = std::array<std::array<marker, 2u>, kDIM>;
0277
0278
0279
0280 }
0281
0282 static style::marker __no_marker = style::marker();
0283 static style::marker __standard_marker = style::marker{{"<<"}};
0284 static std::array<style::marker, 2u> __standard_axis_markers = {
0285 __no_marker, __standard_marker};
0286
0287 }