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