creativity  v1.3.0
Agent-based model of creativity and piracy
style.hpp
1 #pragma once
2 #include <memory>
3 #include <ostream>
4 #include <cairomm/context.h>
5 namespace creativity { namespace data { namespace graph {
6 
8 class RGBA final {
9  public:
10  RGBA() = delete;
11 
21  constexpr RGBA(const double &r, const double &g, const double &b, const double &a = 1.0) :
22  red {r < 0 or r > 1 ? throw std::out_of_range("") : r},
23  green{g < 0 or g > 1 ? throw std::out_of_range("") : g},
24  blue {b < 0 or b > 1 ? throw std::out_of_range("") : b},
25  alpha{a < 0 or a > 1 ? throw std::out_of_range("") : a} {}
26 
32  explicit constexpr RGBA(const double &i, const double &a = 1.0) : RGBA(i,i,i,a) {}
33 
35  RGBA& operator=(const RGBA &copy) { r_(copy.red); g_(copy.green); b_(copy.blue); a_(copy.alpha); return *this; }
36 
38  constexpr bool operator==(const RGBA& other) const { return equalsRGB(other) and alpha == other.alpha; }
39 
41  constexpr bool operator!=(const RGBA& other) const { return not (*this == other); }
42 
46  constexpr bool equalsRGB(const RGBA& other) const { return red == other.red and blue == other.blue and green == other.green; }
47 
49  constexpr bool opaque() const { return alpha == 1; }
50 
52  constexpr bool transparent() const { return alpha == 0; }
53 
57  constexpr operator bool() const { return alpha > 0; }
58 
67  RGBA operator*(const RGBA& other) const { return RGBA(*this) *= other; }
68 
70  RGBA& operator*=(const RGBA& other) {
71  if (other.opaque() or transparent()) *this = other;
72  else if (not other.transparent()) {
73  double myweight = alpha - alpha*other.alpha;
74  double newalpha = other.alpha + myweight;
75  r_((myweight*red + other.alpha*other.red ) / newalpha);
76  g_((myweight*green + other.alpha*other.green) / newalpha);
77  b_((myweight*blue + other.alpha*other.blue ) / newalpha);
78  a_(newalpha);
79  }
80  return *this;
81  }
82 
84  void applyTo(Cairo::RefPtr<Cairo::Context> ctx) const { ctx->set_source_rgba(red, green, blue, alpha); }
85 
90  template <class T, typename = typename std::enable_if<
91  std::is_same<double, decltype(T::get_red())>::value and
92  std::is_same<double, decltype(T::get_green())>::value and
93  std::is_same<double, decltype(T::get_blue())>::value and
94  std::is_same<double, decltype(T::get_alpha())>::value>::type>
95  RGBA(const T& rgba) : RGBA(rgba.get_red(), rgba.get_blue(), rgba.get_green(), rgba.get_alpha()) {}
96 
97  const double red,
98  green,
99  blue,
100  alpha;
101 
105  friend std::ostream& operator<<(std::ostream &os, const RGBA &colour) {
106  os << "RGBA(" << colour.red << "," << colour.green << "," << colour.blue << "," << colour.alpha << ")";
107  return os;
108  }
109 
110  private:
111  // Private access to set new values. Values outside [0,1] are truncated.
112  void r_(double r) { const_cast<double&>(red) = r < 0 ? 0 : r > 1 ? 1 : r; }
113  void g_(double g) { const_cast<double&>(green) = g < 0 ? 0 : g > 1 ? 1 : g; }
114  void b_(double b) { const_cast<double&>(blue) = b < 0 ? 0 : b > 1 ? 1 : b; }
115  void a_(double a) { const_cast<double&>(alpha) = a < 0 ? 0 : a > 1 ? 1 : a; }
116 };
117 
118 constexpr RGBA
119  Transparent{0, 0},
120  Black{0},
121  White{1};
122 
124 class LineStyle {
125  public:
127  LineStyle(RGBA rgba, double thickness = 1.0, double length = std::numeric_limits<double>::quiet_NaN())
128  : colour{std::move(rgba)}, thickness{std::move(thickness)}, length{std::move(length)}
129  {}
130 
132  void applyTo(Cairo::RefPtr<Cairo::Context> ctx) const { colour.applyTo(ctx); ctx->set_line_width(thickness); }
136  double thickness;
141  double length;
142 };
143 
145 class FillStyle {
146  public:
149  FillStyle(RGBA fill) : FillStyle(std::move(fill), LineStyle(Transparent, 0)) {};
151  FillStyle(RGBA fill, LineStyle border) : fill_colour{std::move(fill)}, border{std::move(border)} {}
153  FillStyle(LineStyle border) : FillStyle(Transparent, border) {}
155  FillStyle(FillStyle&&) = default;
157  FillStyle(const FillStyle&) = default;
159  FillStyle& operator=(FillStyle&&) = default;
161  FillStyle& operator=(const FillStyle&) = default;
162 
165 
168 };
169 
173 class RectangleStyle : public FillStyle {
174  public:
176  using FillStyle::FillStyle;
177 
179  RectangleStyle(RectangleStyle&&) = default;
181  RectangleStyle(const RectangleStyle&) = default;
185  RectangleStyle& operator=(const RectangleStyle&) = default;
186 
189 
192  bool border_top = true, border_right = true, border_bottom = true, border_left = true;
194 
196  double borderT() const { return border_top ? border.thickness : 0; }
198  double borderR() const { return border_right ? border.thickness : 0; }
200  double borderB() const { return border_bottom ? border.thickness : 0; }
202  double borderL() const { return border_left ? border.thickness : 0; }
204  double borderLR() const { return borderL() + borderR(); }
206  double borderTB() const { return borderT() + borderB(); }
207 };
208 
209 }}}
LineStyle border
The border colour for the region.
Definition: style.hpp:167
constexpr bool operator==(const RGBA &other) const
Compares two RGBA objects: they are considered equal if all components are equal. ...
Definition: style.hpp:38
constexpr RGBA(const double &i, const double &a=1.0)
Creates a RGBA object with a gray value and optional alpha value.
Definition: style.hpp:32
FillStyle(RGBA fill)
Constructs a FillStyle using just a fill colour: the borders will be omitted (i.e.
Definition: style.hpp:149
double borderB() const
Returns the border width if the bottom border is to be drawn, 0 otherwise.
Definition: style.hpp:200
RGBA(const T &rgba)
Creates the struct from an object with get_red(), get_green(), get_blue(), and get_alpha() methods...
Definition: style.hpp:95
Primary namespace for all Creativity library code.
Definition: config.hpp:4
Style class for a filled region.
Definition: style.hpp:145
RGBA & operator*=(const RGBA &other)
Multiplies this colour by another colour.
Definition: style.hpp:70
Definition: Variable.hpp:389
friend std::ostream & operator<<(std::ostream &os, const RGBA &colour)
Sents this RGBA to an output stream in the form "RGBA(r,g,b,a)" where r, g, b, and a are replaced wit...
Definition: style.hpp:105
const double green
The green channel value.
Definition: style.hpp:97
Style class for a filled, rectangular region.
Definition: style.hpp:173
double thickness
The thickness of the line.
Definition: style.hpp:136
constexpr bool equalsRGB(const RGBA &other) const
Returns true if the red, green, and blue channels are equal.
Definition: style.hpp:46
constexpr bool transparent() const
Returns true if the object is completely transparent, that is, has alpha = 0.
Definition: style.hpp:52
double borderL() const
Returns the border width if the left border is to be drawn, 0 otherwise.
Definition: style.hpp:202
const double blue
The blue channel value.
Definition: style.hpp:97
RectangleStyle(FillStyle f)
Initialize using a FillStyle.
Definition: style.hpp:188
double borderLR() const
Returns the total drawn horizontal border width, i.e. borderR() + borderL()
Definition: style.hpp:204
void applyTo(Cairo::RefPtr< Cairo::Context > ctx) const
Applies this colour to the given Cairo::Context as the source colour.
Definition: style.hpp:84
const double red
The red channel value.
Definition: style.hpp:97
Simple class holding red, green, blue, and alpha values. Each should be a value in [0...
Definition: style.hpp:8
FillStyle(RGBA fill, LineStyle border)
Constructs a FillStyle using a fill colour and line style for the borders.
Definition: style.hpp:151
RGBA operator*(const RGBA &other) const
"Multiplies" two RGBA objects together via alpha compositing "over" filter.
Definition: style.hpp:67
double borderT() const
Returns the border width if the top border is to be drawn, 0 otherwise.
Definition: style.hpp:196
FillStyle(LineStyle border)
Constructs a FillStyle using just a LineStyle; the fill will be omitted (i.e. transparent).
Definition: style.hpp:153
RGBA & operator=(const RGBA &copy)
Copy assignment operator.
Definition: style.hpp:35
const double alpha
The alpha channel value (1 == opaque, 0 == transparent)
Definition: style.hpp:97
Style class for a drawn line.
Definition: style.hpp:124
constexpr RGBA(const double &r, const double &g, const double &b, const double &a=1.0)
Creates a RGBA colour object with a red, green, blue, and (optional) alpha value. ...
Definition: style.hpp:21
double borderR() const
Returns the border width if the right border is to be drawn, 0 otherwise.
Definition: style.hpp:198
constexpr bool opaque() const
Returns true if the object is opaque, that is, has alpha = 1.
Definition: style.hpp:49
RGBA colour
The colour of the line.
Definition: style.hpp:134
RGBA fill_colour
The fill colour for the region.
Definition: style.hpp:164
constexpr bool operator!=(const RGBA &other) const
Negation of ==.
Definition: style.hpp:41
double length
Length of the line, if applicable.
Definition: style.hpp:141
LineStyle(RGBA rgba, double thickness=1.0, double length=std::numeric_limits< double >::quiet_NaN())
Constructs a line style directly from an Gdk::RGBA object.
Definition: style.hpp:127
void applyTo(Cairo::RefPtr< Cairo::Context > ctx) const
Applies the line style to the given Cairo::Context.
Definition: style.hpp:132
double borderTB() const
Returns the total drawn vertical border width, i.e. borderT() + borderB()
Definition: style.hpp:206