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 = {
89std::unordered_map<std::string, CanvasItemCtrlShape>
const ctrl_shape_map = {
114 std::cerr << loc.
line <<
':' << loc.
column <<
": " << err << std::endl;
117std::string get_string(
CRTerm const *term)
121 throw Exception{_(
"Empty or improper value, skipped")};
123 return reinterpret_cast<char *
>(cstr.get());
128 auto const str = get_string(term);
129 auto const it = ctrl_shape_map.find(str);
130 if (it == ctrl_shape_map.end()) {
131 throw Exception{Glib::ustring::compose(_(
"Unrecognized shape '%1'"), str)};
136uint32_t parse_rgb(
CRTerm const *term)
140 if (status !=
CR_OK) {
141 throw Exception{Glib::ustring::compose(_(
"Unrecognized color '%1'"), get_string(term))};
146float parse_opacity(
CRTerm const *term)
150 throw Exception{Glib::ustring::compose(_(
"Invalid opacity '%1'"), get_string(term))};
155 value =
num->
val / 100.0f;
159 throw Exception{Glib::ustring::compose(_(
"Invalid opacity units '%1'"), get_string(term))};
162 if (value > 1 || value < 0) {
163 throw Exception{Glib::ustring::compose(_(
"Opacity '%1' out of range"), get_string(term))};
169float parse_width(
CRTerm const *term)
174 throw Exception{Glib::ustring::compose(_(
"Invalid width '%1'"), get_string(term))};
179 value =
static_cast<float>(
num->val);
181 throw Exception{Glib::ustring::compose(_(
"Invalid width units '%1'"), get_string(term))};
187float parse_scale(
CRTerm const *term)
191 throw Exception{Glib::ustring::compose(_(
"Invalid scale '%1'"), get_string(term))};
196 value =
num->
val / 100.0f;
200 throw Exception{Glib::ustring::compose(_(
"Invalid scale units '%1'"), get_string(term))};
203 if (value > 100 || value < 0) {
204 throw Exception{Glib::ustring::compose(_(
"Scale '%1' out of range"), get_string(term))};
210template <auto parse, auto member>
213 auto &state = get_parsing_state(handler);
214 auto const value = parse(term);
216 (handle->*member).setProperty(value, specificity + 100000 * important);
223std::unordered_map<std::string, void(*)(
CRDocHandler *,
CRTerm const *, bool)>
const property_map = {
224 {
"shape", setter<parse_shape, &Style::shape>},
225 {
"fill", setter<parse_rgb, &Style::fill>},
226 {
"stroke", setter<parse_rgb, &Style::stroke>},
227 {
"outline", setter<parse_rgb, &Style::outline>},
228 {
"opacity", setter<parse_opacity, &Style::opacity>},
229 {
"fill-opacity", setter<parse_opacity, &Style::fill_opacity>},
230 {
"stroke-opacity", setter<parse_opacity, &Style::stroke_opacity>},
231 {
"outline-opacity", setter<parse_opacity, &Style::outline_opacity>},
232 {
"stroke-width", setter<parse_width, &Style::stroke_width>},
233 {
"outline-width", setter<parse_width, &Style::outline_width>},
234 {
"scale", setter<parse_scale, &Style::scale>},
235 {
"size-extra", setter<parse_width, &Style::size_extra>},
236 {
"stroke-scale", setter<parse_scale, &Style::stroke_scale>},
242std::optional<std::pair<TypeState, int>> configure_selector(
CRSelector *a_selector)
244 auto log_unrecognised = [&] (
char const *selector) {
245 log_error(Glib::ustring::compose(_(
"Unrecognized selector '%1'"), selector),
246 a_selector->location);
250 int specificity = a_selector->simple_sel->specificity;
253 auto const tokens = Glib::Regex::split_simple(
":", selector_str);
254 auto const type_it = tokens.empty() ? ctrl_type_map.end() : ctrl_type_map.find(tokens.front());
255 if (type_it == ctrl_type_map.end()) {
256 log_unrecognised(selector_str);
260 auto selector = TypeState{type_it->second};
262 for (
int i = 1; i < tokens.size(); i++) {
263 auto &tok = tokens[i];
266 }
else if (tok ==
"selected") {
267 selector.selected =
true;
268 }
else if (tok ==
"hover") {
270 selector.hover =
true;
271 }
else if (tok ==
"click") {
273 selector.click =
true;
275 log_unrecognised(tok.c_str());
280 return {{ selector, specificity }};
283bool fits(TypeState
const &selector, TypeState
const &handle)
290 return !((selector.selected && !handle.selected) ||
291 (selector.hover && !handle.hover) ||
292 (selector.click && !handle.click));
300 auto &state = get_parsing_state(a_handler);
302 if (
auto const ret = configure_selector(a_selector)) {
303 auto const &[selector, specificity] = *ret;
304 for (
auto &[handle, style] : state.
result.style_map) {
305 if (fits(selector, handle)) {
306 state.selected_handles.emplace_back(&style, specificity + 10000 * is_users);
310 a_selector = a_selector->next;
314template <
bool is_users>
317 set_selectors(a_handler, a_selector, is_users);
325 auto log_error_local = [&] (Glib::ustring
const &err) {
331 log_error_local(_(
"Empty or improper property, skipped."));
335 auto const it = property_map.find(property);
336 if (it == property_map.end()) {
337 log_error_local(Glib::ustring::compose(_(
"Unrecognized property '%1'"), property));
342 it->second(a_handler, a_value, a_important);
343 }
catch (Exception
const &e) {
344 log_error_local(e.msg);
353 auto &state = get_parsing_state(a_handler);
354 state.selected_handles.clear();
357uint32_t combine_rgb_a(uint32_t
rgb,
float a)
359 EXTRACT_ARGB32(
rgb, _, r, g, b)
386 for (
auto state_bits = 0; state_bits < 8; state_bits++) {
387 bool selected = state_bits & (1 << 2);
388 bool hover = state_bits & (1 << 1);
389 bool click = state_bits & (1 << 0);
394 ParsingState state{
result};
397 sac->app_data = &state;
398 sac->property = set_properties;
399 sac->end_selector = clear_selectors;
403 if (Glib::file_test(css_path, Glib::FileTest::EXISTS)) {
410 auto import = +[](CRDocHandler* a_handler, GList* a_media_list, CRString* a_uri, CRString* a_uri_default_ns, CRParsingLocation* a_location){
411 g_return_if_fail(a_handler && a_uri && a_uri->stryng && a_uri->stryng->str);
413 auto fname = a_uri->stryng->str;
415 if (Glib::file_test(css_path, Glib::FileTest::EXISTS)) {
422 sac->import_style =
import;
424 sac->start_selector = set_selectors<false>;
427 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
@ RUBBERBAND_TOUCHPATH_DESELECT
@ 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
@ RUBBERBAND_TOUCHPATH_INVERT
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.