izzi
SVG SUBSET C++ API
Loading...
Searching...
No Matches
a60-svg-base-types.h
Go to the documentation of this file.
1// svg base -*- mode: C++ -*-
2
3// Copyright (C) 2014-2024 Benjamin De Kosnik <b.dekosnik@gmail.com>
4
5// This file is part of the alpha60-MiL SVG library. This library is
6// free software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the Free
8// Software Foundation; either version 3, or (at your option) any
9// later version.
10
11// This library is distributed in the hope that it will be useful, but
12// WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15
16#ifndef MiL_SVG_BASE_TYPES_H
17#define MiL_SVG_BASE_TYPES_H 1
18
19
20#include <map>
21#include <ostream>
22#include <fstream>
23#include <cstdint>
24//#include <compare>
25
26
27namespace svg {
28
29/// Measurement abstraction for absolute (not relative) measurements.
30enum class unit
31 {
32 meter, m, ///< Meter
33 centimeter, cm, ///< Centimeter
34 millimeter, mm, ///< Milliimeter
35 inch, in, ///< Inch
36 pixel, px, ///< Pixel where 1 pixel x 96 PPI = .26 mm
37 point, pt ///< Point where 1 pixel x 1/72 dpi x 96 PPI = .26 mm
38 };
39
40const string
42{
43 using enum_map_type = std::map<unit, std::string>;
44
45 static enum_map_type enum_map;
46 if (enum_map.empty())
47 {
48 enum_map[unit::meter] = "m";
49 enum_map[unit::m] = "m";
50 enum_map[unit::centimeter] = "cm";
51 enum_map[unit::cm] = "cm";
52 enum_map[unit::millimeter] = "mm";
53 enum_map[unit::mm] = "mm";
54 enum_map[unit::inch] = "in";
55 enum_map[unit::in] = "in";
56 enum_map[unit::pixel] = "px";
57 enum_map[unit::px] = "px";
58 enum_map[unit::point] = "pt";
59 enum_map[unit::pt] = "pt";
60 }
61 return enum_map[e];
62}
63
64
65/**
66 Area/Page/Canvas/Drawing area description.
67 Size, origin location in 2D (x,y), heigh, width
68
69 ANSI Letter mm == (unit::millimeter, 215.9, 279.4);
70 ANSI Letter pixels == (unit::pixel, 765, 990);
71
72 ISO A4 mm == (unit::millimeter, 210, 297);
73 ISO A4 pixels == (unit::pixel, 744.09, 1052.36);
74
75 720p pixels == (unit::pixel, 1280, 720);
76 1080p pixels == (unit::pixel, 1920, 1080);
77
78 SVG coordinate system is (0,0) is top leftmost.
79*/
80template<typename T1 = svg::space_type>
81struct area
82{
83 using atype = T1;
84 using unit = svg::unit;
85
88
89 /// Given @param rdenom scaling factor and SVG canvas area by @obj,
90 /// compute max effective segment size given number of segments @rdenom.
91 /// NB: if rdenom is two then this is a max radius value centered
92 /// on the page/frame.
93 inline constexpr double
94 max_segment_size_n(const uint rdenom = 2) const
95 {
96 double leastside = std::min(_M_height, _M_width);
97 return leastside / rdenom;
98 }
99
100 /// Convenience function for finding center.
101 inline constexpr point_2t
103 { return std::make_tuple(_M_width / 2, _M_height / 2); }
104
105 /// Landscape, aka largest side is horizontal.
106 area
108 {
109 atype lg = 0, sm = 0;
110 if (_M_width >= _M_height)
111 {
112 lg = _M_width;
113 sm = _M_height;
114 }
115 else
116 {
117 lg = _M_height;
118 sm = _M_width;
119 }
120 atype twidth = lg;
121 atype theight = sm;
122 return area(twidth, theight);
123 }
124
125 /// Portrait, aka largest side is vertical.
126 area
128 {
129 atype lg = 0, sm = 0;
130 if (_M_width >= _M_height)
131 {
132 lg = _M_width;
133 sm = _M_height;
134 }
135 else
136 {
137 lg = _M_height;
138 sm = _M_width;
139 }
140 atype twidth = sm;
141 atype theight = lg;
142 return area(twidth, theight);
143 }
144};
145
146
147/// Datum consolidating style preferences.
148struct style
149{
152
156
157 // auto operator<=>(const style&) const = default;
158
159 /// Convenience function to set all colors at once.
160 void
162 {
163 _M_fill_color = klr;
164 _M_stroke_color = klr;
165 }
166};
167
168
169/// Additional path/line/polyline stroke styles.
170// NB: https://yuanchuan.dev/fun-with-stroke-dasharray
172{
173 // marker-start, marker-mid, marker-end
175
176 // https://developer.mozilla.org/en-US/docs/Web/CSS/stroke-dasharray
177 string dasharray;
178
179 // https://developer.mozilla.org/en-US/docs/Web/CSS/stroke-dashoffset
181
182 // https://developer.mozilla.org/en-US/docs/Web/CSS/stroke-linecap
183 string linecap; // butt, round, square
184
186};
187
188
189const string
191{
192 const string space("; ");
193 std::ostringstream stream;
194 stream << k::space;
195 stream << "style=" << k::quote;
196 stream << "fill:" << color_qi::to_string(s._M_fill_color) << space;
197 stream << "fill-opacity:" << s._M_fill_opacity << space;
198 stream << "stroke:" << color_qi::to_string(s._M_stroke_color) << space;
199 stream << "stroke-opacity:" << s._M_stroke_opacity << space;
200 stream << "stroke-width:" << s._M_stroke_size << k::quote;
201 return stream.str();
202}
203
204
205/// Datum consolidating transform possibilities.
206/// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/transform
208{
209 static string
210 matrix(double a, double b, double c, double d, double e, double f)
211 {
212 std::ostringstream stream;
213 stream << "matrix(" << a << k::comma << b << k::comma << c << k::comma
214 << d << k::comma << e << k::comma << f << k::comma << ")";
215 return stream.str();
216 }
217
218 static string
219 rotate(int deg)
220 {
221 std::ostringstream stream;
222 stream << "rotate(" << deg << ")";
223 return stream.str();
224 }
225
226 static string
227 rotate(int deg, int x, int y)
228 {
229 std::ostringstream stream;
230 stream << "rotate(" << deg << k::comma << x << k::comma << y << ")";
231 return stream.str();
232 }
233
234 static string
235 scale(double factor)
236 {
237 std::ostringstream stream;
238 stream << "scale(" << factor << ")";
239 return stream.str();
240 }
241
242 static string
243 scale(double factor1, double factor2)
244 {
245 std::ostringstream stream;
246 stream << "scale(" << factor1 << k::comma << factor2 << ")";
247 return stream.str();
248 }
249
250 static string
251 skew_x(double factor)
252 {
253 std::ostringstream stream;
254 stream << "skewX(" << factor << ")";
255 return stream.str();
256 }
257
258 static string
259 skew_y(double factor)
260 {
261 std::ostringstream stream;
262 stream << "skewY(" << factor << ")";
263 return stream.str();
264 }
265
266 static string
267 translate(int x, int y)
268 {
269 std::ostringstream stream;
270 stream << "translate(" << x << k::comma << y << ")";
271 return stream.str();
272 }
273};
274
275
276/**
277 Character rendering, type, fonts, styles.
278
279 Expect to keep changing the output, so use this abstraction to set
280 styling defaults, so that one can just assign types instead of doing
281 a bunch of search-and-replace operations when changing type
282 characteristics.
283
284 SVG Fonts
285 https://developer.mozilla.org/docs/Web/SVG/Tutorial/SVG_fonts
286*/
288{
289 /// Text alignment.
290 enum class align
291 {
292 left, ///< Left-most part of text block
293 center, ///< Center part of text block
294 right, ///< Right part of text block
303 };
304
305 /// How to align text to a given point.
306 enum class anchor
307 {
308 start, ///< Start the text block at point.
309 middle, ///< Center the middle of the text block at point.
310 end, ///< End the text block at point.
311 inherit ///< Enclosing object or group
312 };
313
314 /// How to align text to the dominant-baseline.
315 /// https://developer.mozilla.org/docs/Web/SVG/Attribute/dominant-baseline
330
331 /// Weight as per CSS property.
332 enum class weight
333 {
335 light, ///< CSS 300
336 normal, ///< CSS 400
337 medium, ///< CSS 500
340 };
341
342 /// Face style variant.
343 /// https://developer.mozilla.org/docs/Web/CSS/font-style
344 enum class property
345 {
346 normal, ///< Book
347 italic ///< Italic
348 };
349
350 // Find all installed fonts on linux with `fc-list`
351 std::string _M_face; // System font name
352 space_type _M_size; // Display size
354
355 // Style attributes for text
356 // font-weight, transform,
357 // https://developer.mozilla.org/en-US/docs/Web/SVG/Element/font-face
362 property _M_p;
363
364 // Compile time expression.
366 use_style(const style s) const
367 { return { _M_face, _M_size, s, _M_anchor, _M_align, _M_baseline, _M_w, _M_p }; }
368
369 const std::string
370 to_string(const align a) const
371 {
372 using enum_map_type = std::map<align, std::string>;
373
374 static enum_map_type enum_map;
375 if (enum_map.empty())
376 {
377 enum_map[align::left] = "left";
378 enum_map[align::center] = "center";
379 enum_map[align::right] = "right";
380 enum_map[align::justify] = "justify";
381 enum_map[align::justifyall] = "justify-all";
382 enum_map[align::start] = "start";
383 enum_map[align::end] = "end";
384 enum_map[align::inherit] = "inherit";
385 enum_map[align::matchparent] = "match-parent";
386 enum_map[align::initial] = "initial";
387 enum_map[align::unset] = "unset";
388 }
389 return enum_map[a];
390 }
391
392 const std::string
393 to_string(const anchor a) const
394 {
395 using enum_map_type = std::map<anchor, std::string>;
396
397 static enum_map_type enum_map;
398 if (enum_map.empty())
399 {
400 enum_map[anchor::start] = "start";
401 enum_map[anchor::middle] = "middle";
402 enum_map[anchor::end] = "end";
403 enum_map[anchor::inherit] = "inherit";
404 }
405 return enum_map[a];
406 }
407
408 const std::string
409 to_string(const weight w) const
410 {
411 using enum_map_type = std::map<weight, std::string>;
412
413 static enum_map_type enum_map;
414 if (enum_map.empty())
415 {
416 enum_map[weight::xlight] = "200";
417 enum_map[weight::light] = "300";
418 enum_map[weight::normal] = "400";
419 enum_map[weight::medium] = "500";
420 enum_map[weight::bold] = "600";
421 enum_map[weight::xbold] = "700";
422 }
423 return enum_map[w];
424 }
425
426 const std::string
427 to_string(const baseline b) const
428 {
429 using enum_map_type = std::map<baseline, std::string>;
430
431 static enum_map_type enum_map;
432 if (enum_map.empty())
433 {
434 enum_map[baseline::none] = "";
435 enum_map[baseline::automatic] = "auto";
436 enum_map[baseline::ideographic] = "ideographic";
437 enum_map[baseline::alphabetic] = "alphabetic";
438 enum_map[baseline::hanging] = "hanging";
439 enum_map[baseline::mathematical] = "mathematical";
440 enum_map[baseline::central] = "central";
441 enum_map[baseline::middle] = "middle";
442 enum_map[baseline::text_after_edge] = "text-after-edge";
443 enum_map[baseline::text_before_edge] = "text-before-edge";
444 enum_map[baseline::text_top] = "text-top";
445 }
446 return enum_map[b];
447 }
448
449 const std::string
450 to_string(const property p) const
451 {
452 using enum_map_type = std::map<property, std::string>;
453
454 static enum_map_type enum_map;
455 if (enum_map.empty())
456 {
457 enum_map[property::normal] = "normal";
458 enum_map[property::italic] = "italic";
459 }
460 return enum_map[p];
461 }
462
463 const std::string
465 {
466 const string name("__name");
467 const string size("__size");
468 const string anchor("__anchor");
469 const string align("__align");
470 const string len("__lentype");
471
472 std::string strip1 = \
473 R"(font-family="__name" font-size="__size__lentype" text-anchor="__anchor" text-align="__align" )";
474
475 string_replace(strip1, name, _M_face);
476 string_replace(strip1, size, std::to_string(_M_size));
479 string_replace(strip1, len, svg::to_string(utype));
480
481 const std::string weight("__weight");
482 const std::string property("__prop");
483
484 std::string strip2 = \
485 R"(font-weight="__weight" font-style="__prop")";
486
489
490 // Add dominant baseline only if necessary.
491 string stripb;
493 {
494 stripb += "dominant-baseline=";
495 stripb += k::quote;
496 stripb += to_string(_M_baseline);
497 stripb += k::quote;
498 stripb += k::space;
499 }
500 return strip1 + stripb + strip2;
501 }
502};
503
504} // namespace svg
505
506#endif
color
Color enumerated as types.
unit
Measurement abstraction for absolute (not relative) measurements.
@ px
Pixel where 1 pixel x 96 PPI = .26 mm.
@ cm
Centimeter.
@ mm
Milliimeter.
@ pt
Point where 1 pixel x 1/72 dpi x 96 PPI = .26 mm.
const string to_string(const unit e)
void string_replace(std::string &target, const std::string &match, const std::string &replace)
Definition a60-svg.h:43
double space_type
Base floating point type.
Definition a60-svg.h:62
unsigned int uint
Definition a60-svg.h:57
std::tuple< space_type, space_type > point_2t
Point (x,y) in 2D space.
Definition a60-svg.h:65
constexpr point_2t center_point() const
Convenience function for finding center.
area to_portrait() const
Portrait, aka largest side is vertical.
area to_landscape() const
Landscape, aka largest side is horizontal.
constexpr double max_segment_size_n(const uint rdenom=2) const
Given.
Color quantified as integral RGB components in the range [0,255]. aka like Scalar in OpenCV.
static string to_string(color_qi s)
Additional path/line/polyline stroke styles.
Datum consolidating style preferences.
color_qi _M_fill_color
color_qi _M_stroke_color
void set_colors(const svg::color &klr)
Convenience function to set all colors at once.
Datum consolidating transform possibilities. https://developer.mozilla.org/en-US/docs/Web/SVG/Attribu...
static string translate(int x, int y)
static string matrix(double a, double b, double c, double d, double e, double f)
static string skew_y(double factor)
static string rotate(int deg, int x, int y)
static string skew_x(double factor)
static string scale(double factor)
static string rotate(int deg)
static string scale(double factor1, double factor2)
const std::string to_string(const baseline b) const
baseline
How to align text to the dominant-baseline. https://developer.mozilla.org/docs/Web/SVG/Attribute/domi...
@ none
Ignore this attribute.
const std::string to_string(const align a) const
const std::string to_string(const anchor a) const
const std::string to_string(const property p) const
align
Text alignment.
@ right
Right part of text block.
@ left
Left-most part of text block.
@ center
Center part of text block.
const std::string to_string(const weight w) const
anchor
How to align text to a given point.
@ middle
Center the middle of the text block at point.
@ inherit
Enclosing object or group.
@ end
End the text block at point.
@ start
Start the text block at point.
property
Face style variant. https://developer.mozilla.org/docs/Web/CSS/font-style.
weight
Weight as per CSS property.
typography use_style(const style s) const
const std::string add_attribute(const svg::unit utype=svg::unit::pixel) const