Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-18 09:42:34

0001 // This file is part of the actsvg package.
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 #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 /** Helper method to convert and @return a color into an attribute
0027  *
0028  * @param rgb_ is the r,g,b color to be represented
0029  *
0030  */
0031 std::string rgb_attr(const rgb &rgb_);
0032 
0033 /// Color specification
0034 struct color {
0035     /// The color
0036     rgb _rgb = {255, 255, 255};
0037     /// The opacity
0038     scalar _opacity = 1.;
0039     /// The highlight mode it is assumed on/off
0040     std::vector<std::string> _highlight = {};
0041     rgb _hl_rgb = {255, 0, 0};
0042 };
0043 
0044 /// Fill type specification
0045 struct fill {
0046 
0047     /// The fill color
0048     color _fc = color{{0, 0, 0}};
0049     bool _sterile = false;
0050 
0051     /// A constructor from @param fc_ color
0052     fill(const color &fc_);
0053 
0054     /// A constructor for empty
0055     fill(bool s_ = false);
0056 
0057     /** Attach this fill attribute to an object
0058      *
0059      * @tparam object_type the type of the object
0060      *
0061      * @param o_ [in,out] the object in question
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 // Define a gradient definition
0084 struct gradient {
0085 
0086     /// Define a gradient id
0087     std::string _id = "";
0088     /// The gradient direction (x1, y1, 2, y2)
0089     /// default is left to right
0090     std::array<scalar, 4> _direction = {0., 0., 1., 0.};
0091     /// The type of the gradient
0092     std::string _type = "linear";
0093 
0094     using stop = std::pair<scalar, color>;
0095 
0096     /// The gradient stops
0097     std::vector<stop> _stops = {};
0098 
0099     /// An optional label string (non-empty will trigger label rendering)
0100     std::string _label = "";
0101 
0102     /// Get a color from a scale parameter
0103     ///
0104     /// @param s_ the scale parameter for the lookup point
0105     rgb rgb_from_scale(scalar s_) const;
0106 };
0107 
0108 /// Stroke type specification
0109 struct stroke {
0110 
0111     /// The stroke color
0112     color _sc{{0, 0, 0}};
0113     /// Width definition
0114     scalar _width = 0.5;
0115     /// hl with
0116     scalar _hl_width = 0.5;
0117     /// Dashing definition
0118     std::vector<int> _dasharray = {};
0119     /// Nothing is written out
0120     bool _sterile = false;
0121 
0122     /// @brief Constructor for stroke
0123     /// @param c_ the color of the stroke
0124     /// @param w_ the with of the stroke
0125     /// @param d_ the dashed harray of the stroke
0126     stroke(const color &c_, scalar w_ = 0.5, const std::vector<int> &d_ = {});
0127 
0128     /// @brief Constructor for sterile stroke
0129     stroke(bool s_ = false);
0130 
0131     /** Attach this fill attribute to an object
0132      *
0133      * @tparam object_type the type of the object
0134      *
0135      * @param o_ [in,out] the object in question
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             // dashed array
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             // Stroke color
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             // Stroke width
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 /// Font style specification
0181 struct font {
0182     /// The font color
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     /** Attach this fill attribute to an object
0194      *
0195      * @tparam object_type the type of the object
0196      *
0197      * @param o_ [in,out] the object in question
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 /// The label struct
0213 ///
0214 struct label {
0215     /// The horizontal alignment enum
0216     enum class horizontal { left, center, right };
0217 
0218     /// The vertical alignment enum
0219     enum class vertical { top, center, bottom };
0220 
0221     /// The label text
0222     std::string _text = "";
0223 
0224     /// The label horizontal alignment
0225     horizontal _horizontal = horizontal::left;
0226 
0227     /// The vertical horizontal alignment
0228     vertical _vertical = vertical::bottom;
0229 
0230     /// The font type of the label
0231     font _font = font{};
0232 
0233     /// The position
0234     std::array<scalar, 2u> _position = {0., 0.};
0235 
0236     /// Place the label at the position - assuming a bounding box
0237     ///
0238     /// @param lhc_ the left hand corner of the bounding box
0239     /// @param ruc_ the right upper corner of the bounding box
0240     void place(const std::array<scalar, 2u> &lhc_,
0241                const std::array<scalar, 2u> &rhc_);
0242 };
0243 
0244 /// The transform struct
0245 ///
0246 /// This is a style transform, not an object transform,
0247 /// i.e. it applies to where to draw and modify the object
0248 /// while displaying
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     /** Test if it is a identity/sterile transform */
0259     bool is_identity() const;
0260 
0261     /** Apply to a point
0262      *
0263      * @param p_ the point to be transformed
0264      * @param flip is the y-axis flipped (for viewing)
0265      *
0266      * @return the transformed point
0267      **/
0268     template <typename point_type>
0269     point_type apply(const point_type &p_, bool flip = true) const {
0270         // Apply the scale and the translation
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     /** Attribute conversion
0281      *
0282      * @note that the scale is directly applied on the objects,
0283      * in order to control the viewBox boundaries
0284      **/
0285     std::string attr() const;
0286 
0287     /** Attach this fill attribute to an object
0288      *
0289      * @tparam object_type the type of the object
0290      *
0291      * @param o_ [in,out] the object in question
0292      *
0293      * @note is applies the transform to the x range
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 /// The marker struct
0309 ///
0310 /// Allowed types are:
0311 /// - none, <<, <, <|, |<, |<<, o
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 // The axis marker types
0323 template <unsigned int kDIM>
0324 using axis_markers = std::array<std::array<marker, 2u>, kDIM>;
0325 
0326 /// Some standard styles to be used as default
0327 
0328 }  // namespace style
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 }  // namespace actsvg