Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:32:37

0001 // This file is part of the actsvg packge.
0002 //
0003 // Copyright (C) 2022 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
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 /** Helper method to convert and @return a color into an attribute
0025  *
0026  * @param rgb_ is the r,g,b color to be represented
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 /// Color specification
0040 struct color {
0041     /// The color
0042     rgb _rgb = {255, 255, 255};
0043     /// The opacity
0044     scalar _opacity = 1.;
0045     /// The highlight mode it is assumed on/off
0046     std::vector<std::string> _highlight = {};
0047     rgb _hl_rgb = {255, 0, 0};
0048 };
0049 
0050 /// Fill type specification
0051 struct fill {
0052 
0053     /// The fill color
0054     color _fc = color{{0, 0, 0}};
0055     bool _sterile = false;
0056 
0057     /// A constructor from @param fc_ color
0058     fill(const color &fc_) : _fc(fc_) {}
0059 
0060     /// A constructor for empty
0061     fill(bool s_ = false) : _sterile(s_) {
0062         _fc = color();
0063         _fc._opacity = 0.;
0064     }
0065 
0066     /** Attach this fill attribute to an object
0067      *
0068      * @tparam object_type the type of the object
0069      *
0070      * @param o_ [in,out] the object in question
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 /// Stroke type speficiation
0093 struct stroke {
0094 
0095     /// The stroke color
0096     color _sc{{0, 0, 0}};
0097     /// Width definition
0098     scalar _width = 0.5;
0099     /// hl with
0100     scalar _hl_width = 0.5;
0101     /// Dashing definition
0102     std::vector<int> _dasharray = {};
0103     /// Nothing is written out
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     /** Attach this fill attribute to an object
0112      *
0113      * @tparam object_type the type of the object
0114      *
0115      * @param o_ [in,out] the object in question
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             // dashed array
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             // Stroke color
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             // Stroke width
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 /// Font sytle specification
0161 struct font {
0162     /// The font color
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     /** Attach this fill attribute to an object
0174      *
0175      * @tparam object_type the type of the object
0176      *
0177      * @param o_ [in,out] the object in question
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 /// The transform struct
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     /** Attrribute conversion
0203      *
0204      * @note that the scale is directly applied on the objects,
0205      * in order to control the viewBox boundaries
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     /** Attach this fill attribute to an object
0240      *
0241      * @tparam object_type the type of the object
0242      *
0243      * @param o_ [in,out] the object in question
0244      *
0245      * @note is applies the transform to the x range
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 /// The marker struct
0261 ///
0262 /// Allowed types are:
0263 /// - none, <<, <, <|, |<, |<<, o
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 // The axis marker types
0275 template <unsigned int kDIM>
0276 using axis_markers = std::array<std::array<marker, 2u>, kDIM>;
0277 
0278 /// Some standard styles to be used as default
0279 
0280 }  // namespace style
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 }  // namespace actsvg