5#include <boost/functional/hash.hpp>
6#include <glibmm/fileutils.h>
7#include <glibmm/i18n.h>
8#include <glibmm/regex.h>
41 return *
reinterpret_cast<ParsingState *
>(a_handler->app_data);
47std::unordered_map<std::string, CanvasItemCtrlType>
const ctrl_type_map = {
85std::unordered_map<std::string, CanvasItemCtrlShape>
const ctrl_shape_map = {
110 std::cerr << loc.
line <<
':' << loc.
column <<
": " << err << std::endl;
113std::string get_string(
CRTerm const *term)
117 throw Exception{_(
"Empty or improper value, skipped")};
119 return reinterpret_cast<char *
>(cstr.get());
124 auto const str = get_string(term);
125 auto const it = ctrl_shape_map.find(str);
126 if (it == ctrl_shape_map.end()) {
127 throw Exception{Glib::ustring::compose(_(
"Unrecognized shape '%1'"), str)};
132uint32_t parse_rgb(
CRTerm const *term)
136 if (status !=
CR_OK) {
137 throw Exception{Glib::ustring::compose(_(
"Unrecognized color '%1'"), get_string(term))};
142float parse_opacity(
CRTerm const *term)
146 throw Exception{Glib::ustring::compose(_(
"Invalid opacity '%1'"), get_string(term))};
151 value =
num->
val / 100.0f;
155 throw Exception{Glib::ustring::compose(_(
"Invalid opacity units '%1'"), get_string(term))};
158 if (value > 1 || value < 0) {
159 throw Exception{Glib::ustring::compose(_(
"Opacity '%1' out of range"), get_string(term))};
165float parse_width(
CRTerm const *term)
170 throw Exception{Glib::ustring::compose(_(
"Invalid width '%1'"), get_string(term))};
175 value =
static_cast<float>(
num->val);
177 throw Exception{Glib::ustring::compose(_(
"Invalid width units '%1'"), get_string(term))};
183float parse_scale(
CRTerm const *term)
187 throw Exception{Glib::ustring::compose(_(
"Invalid scale '%1'"), get_string(term))};
192 value =
num->
val / 100.0f;
196 throw Exception{Glib::ustring::compose(_(
"Invalid scale units '%1'"), get_string(term))};
199 if (value > 100 || value < 0) {
200 throw Exception{Glib::ustring::compose(_(
"Scale '%1' out of range"), get_string(term))};
206template <auto parse, auto member>
209 auto &state = get_parsing_state(handler);
210 auto const value = parse(term);
212 (handle->*member).setProperty(value, specificity + 100000 * important);
219std::unordered_map<std::string, void(*)(
CRDocHandler *,
CRTerm const *, bool)>
const property_map = {
220 {
"shape", setter<parse_shape, &Style::shape>},
221 {
"fill", setter<parse_rgb, &Style::fill>},
222 {
"stroke", setter<parse_rgb, &Style::stroke>},
223 {
"outline", setter<parse_rgb, &Style::outline>},
224 {
"opacity", setter<parse_opacity, &Style::opacity>},
225 {
"fill-opacity", setter<parse_opacity, &Style::fill_opacity>},
226 {
"stroke-opacity", setter<parse_opacity, &Style::stroke_opacity>},
227 {
"outline-opacity", setter<parse_opacity, &Style::outline_opacity>},
228 {
"stroke-width", setter<parse_width, &Style::stroke_width>},
229 {
"outline-width", setter<parse_width, &Style::outline_width>},
230 {
"scale", setter<parse_scale, &Style::scale>},
231 {
"size-extra", setter<parse_width, &Style::size_extra>},
232 {
"stroke-scale", setter<parse_scale, &Style::stroke_scale>},
238std::optional<std::pair<TypeState, int>> configure_selector(
CRSelector *a_selector)
240 auto log_unrecognised = [&] (
char const *selector) {
241 log_error(Glib::ustring::compose(_(
"Unrecognized selector '%1'"), selector),
242 a_selector->location);
246 int specificity = a_selector->simple_sel->specificity;
249 auto const tokens = Glib::Regex::split_simple(
":", selector_str);
250 auto const type_it = tokens.empty() ? ctrl_type_map.end() : ctrl_type_map.find(tokens.front());
251 if (type_it == ctrl_type_map.end()) {
252 log_unrecognised(selector_str);
256 auto selector = TypeState{type_it->second};
258 for (
int i = 1; i < tokens.size(); i++) {
259 auto &tok = tokens[i];
262 }
else if (tok ==
"selected") {
263 selector.selected =
true;
264 }
else if (tok ==
"hover") {
266 selector.hover =
true;
267 }
else if (tok ==
"click") {
269 selector.click =
true;
271 log_unrecognised(tok.c_str());
276 return {{ selector, specificity }};
279bool fits(TypeState
const &selector, TypeState
const &handle)
286 return !((selector.selected && !handle.selected) ||
287 (selector.hover && !handle.hover) ||
288 (selector.click && !handle.click));
296 auto &state = get_parsing_state(a_handler);
298 if (
auto const ret = configure_selector(a_selector)) {
299 auto const &[selector, specificity] = *ret;
300 for (
auto &[handle, style] : state.
result.style_map) {
301 if (fits(selector, handle)) {
302 state.selected_handles.emplace_back(&style, specificity + 10000 * is_users);
306 a_selector = a_selector->next;
310template <
bool is_users>
313 set_selectors(a_handler, a_selector, is_users);
321 auto log_error_local = [&] (Glib::ustring
const &err) {
327 log_error_local(_(
"Empty or improper property, skipped."));
331 auto const it = property_map.find(property);
332 if (it == property_map.end()) {
333 log_error_local(Glib::ustring::compose(_(
"Unrecognized property '%1'"), property));
338 it->second(a_handler, a_value, a_important);
339 }
catch (Exception
const &e) {
340 log_error_local(e.msg);
349 auto &state = get_parsing_state(a_handler);
350 state.selected_handles.clear();
353uint32_t combine_rgb_a(uint32_t
rgb,
float a)
355 EXTRACT_ARGB32(
rgb, _, r, g, b)
382 for (
auto state_bits = 0; state_bits < 8; state_bits++) {
383 bool selected = state_bits & (1 << 2);
384 bool hover = state_bits & (1 << 1);
385 bool click = state_bits & (1 << 0);
390 ParsingState state{
result};
393 sac->app_data = &state;
394 sac->property = set_properties;
395 sac->end_selector = clear_selectors;
399 if (Glib::file_test(css_path, Glib::FileTest::EXISTS)) {
406 auto import = +[](CRDocHandler* a_handler, GList* a_media_list, CRString* a_uri, CRString* a_uri_default_ns, CRParsingLocation* a_location){
407 g_return_if_fail(a_handler && a_uri && a_uri->stryng && a_uri->stryng->str);
409 auto fname = a_uri->stryng->str;
411 if (Glib::file_test(css_path, Glib::FileTest::EXISTS)) {
418 sac->import_style =
import;
420 sac->start_selector = set_selectors<false>;
423 sac->start_selector = set_selectors<true>;
Cairo integration helpers.
The declaration of the #CRDocumentHandler class.
CRDocHandler * cr_doc_handler_new(void)
typedefG_BEGIN_DECLS struct _CRDocHandler CRDocHandler
The declaration file of the CRParser class.
CRParser * cr_parser_new_from_file(const guchar *a_file_uri, enum CREncoding a_enc)
enum CRStatus cr_parser_parse(CRParser *a_this)
enum CRStatus cr_parser_set_sac_handler(CRParser *a_this, CRDocHandler *a_handler)
enum CRStatus cr_rgb_set_from_term(CRRgb *a_this, const struct _CRTerm *a_value)
The declaration file of the CRSelector file.
typedefG_BEGIN_DECLS struct _CRSelector CRSelector
guchar * cr_simple_sel_one_to_string(CRSimpleSel const *a_this)
enum CRStatus cr_simple_sel_compute_specificity(CRSimpleSel *a_this)
Declaration file of the CRString class.
typedefG_BEGIN_DECLS struct _CRString CRString
const gchar * cr_string_peek_raw_str(CRString const *a_this)
Declaration of the CRTerm class.
guchar * cr_term_to_string(CRTerm const *a_this)
The Croco library basic types definitions And global definitions.
std::vector< std::pair< Style *, int > > selected_handles
Ad-hoc smart pointer useful when interfacing with C code.
guint AssembleARGB32(guint32 a, guint32 r, guint32 g, guint32 b)
Classes related to control handle styling.
Css parse_css(const std::string &css_file_name)
std::string get_path_string(Domain domain, Type type, char const *filename, char const *extra)
auto delete_with(T *p)
Wrap a raw pointer in a std::unique_ptr with a custom function as the deleter.
@ CANVAS_ITEM_CTRL_SHAPE_SQUARE
@ CANVAS_ITEM_CTRL_SHAPE_TRIANGLE
@ CANVAS_ITEM_CTRL_SHAPE_PLUS
@ CANVAS_ITEM_CTRL_SHAPE_CROSS
@ CANVAS_ITEM_CTRL_SHAPE_CARROW
@ CANVAS_ITEM_CTRL_SHAPE_SALIGN
@ CANVAS_ITEM_CTRL_SHAPE_CALIGN
@ CANVAS_ITEM_CTRL_SHAPE_TRIANGLE_ANGLED
@ CANVAS_ITEM_CTRL_SHAPE_PIVOT
@ CANVAS_ITEM_CTRL_SHAPE_DIAMOND
@ CANVAS_ITEM_CTRL_SHAPE_DARROW
@ CANVAS_ITEM_CTRL_SHAPE_SARROW
@ CANVAS_ITEM_CTRL_SHAPE_CIRCLE
@ CANVAS_ITEM_CTRL_SHAPE_MALIGN
@ CANVAS_ITEM_CTRL_TYPE_ANCHOR
@ CANVAS_ITEM_CTRL_TYPE_CENTER
@ CANVAS_ITEM_CTRL_TYPE_GUIDE_HANDLE
@ CANVAS_ITEM_CTRL_TYPE_POINTER
@ CANVAS_ITEM_CTRL_TYPE_NODE_AUTO
@ CANVAS_ITEM_CTRL_TYPE_ADJ_ROTATE
@ CANVAS_ITEM_CTRL_TYPE_POINT
@ CANVAS_ITEM_CTRL_TYPE_NODE_CUSP
@ RUBBERBAND_TOUCHPATH_SELECT
@ CANVAS_ITEM_CTRL_TYPE_MARGIN
@ CANVAS_ITEM_CTRL_TYPE_ADJ_HANDLE
@ CANVAS_ITEM_CTRL_TYPE_SIZER
@ CANVAS_ITEM_CTRL_TYPE_MARKER
@ CANVAS_ITEM_CTRL_TYPE_NODE_SMOOTH
@ CANVAS_ITEM_CTRL_TYPE_INVISIPOINT
@ CANVAS_ITEM_CTRL_TYPE_ADJ_SALIGN
@ CANVAS_ITEM_CTRL_TYPE_NODE_SYMMETRICAL
@ CANVAS_ITEM_CTRL_TYPE_ADJ_CALIGN
@ CANVAS_ITEM_CTRL_TYPE_SHAPER
@ CANVAS_ITEM_CTRL_TYPE_MOVE
@ RUBBERBAND_TOUCHPATH_FLOOD
@ RUBBERBAND_TOUCHPATH_ERASER
@ CANVAS_ITEM_CTRL_TYPE_MESH
@ CANVAS_ITEM_CTRL_TYPE_ADJ_SKEW
@ CANVAS_ITEM_CTRL_TYPE_LPE
@ CANVAS_ITEM_CTRL_TYPE_ROTATE
@ CANVAS_ITEM_CTRL_TYPE_ADJ_MALIGN
@ CANVAS_ITEM_CTRL_TYPE_ADJ_CENTER
@ LAST_ITEM_CANVAS_ITEM_CTRL_TYPE
@ CANVAS_ITEM_CTRL_TYPE_DEFAULT
Inkscape::IO::Resource - simple resource API.
The result of parsing the handle styling CSS files, containing all information needed to style a give...
std::unordered_map< TypeState, Style > style_map
Property< float > opacity
Property< uint32_t > stroke
uint32_t getOutline() const
Property< float > outline_opacity
Property< float > stroke_opacity
Property< uint32_t > outline
Property< float > fill_opacity
uint32_t getStroke() const
Property< uint32_t > fill
Struct to manage type and state.
An abstraction of a css2 term as defined in the CSS2 spec in appendix D.1: term ::= [ NUMBER S* | PER...
CRParsingLocation location
union _CRTerm::@7 content
The content of the term.