Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
sp-style-elem.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
/*
5 * Authors: see git history
6 *
7 * Copyright (C) 2018 Authors
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10#include "sp-style-elem.h"
11
12// For external style sheets
13#include <iostream>
14
16
17#include "attributes.h"
18#include "document.h"
19#include "sp-root.h"
20#include "style.h"
21
22#include "io/resource.h"
23#include "libnrtype/font-factory.h" // For font-rule
24#include "xml/document.h" // for Document
25#include "xml/node.h" // for Node, NodeType
26
29{
30 auto styleelem = static_cast<SPStyleElem *>(this);
31 styleelem->read_content();
32 styleelem->document->getRoot()->emitModified(SP_OBJECT_MODIFIED_CASCADE);
33}
34
36{
37 auto styleelem = static_cast<SPStyleElem *>(this);
38
40 child.addObserver(styleelem->textNodeObserver());
41 }
42
43 styleelem->read_content();
44}
45
47{
48 auto styleelem = static_cast<SPStyleElem *>(this);
49
50 child.removeObserver(styleelem->textNodeObserver());
51 styleelem->read_content();
52}
53
60
65
67
68void SPStyleElem::set(SPAttr key, char const *value)
69{
70 switch (key) {
71 case SPAttr::TYPE: {
72 if (!value) {
73 /* TODO: `type' attribute is required. Give error message as per
74 http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. */
75 is_css = false;
76 } else {
77 /* fixme: determine what whitespace is allowed. Will probably need to ask on SVG
78 list; though the relevant RFC may give info on its lexer. */
79 is_css = ( g_ascii_strncasecmp(value, "text/css", 8) == 0
80 && ( value[8] == '\0' ||
81 value[8] == ';' ) );
82 }
83 break;
84 }
85
86#if 0 /* unfinished */
87 case SPAttr::MEDIA: {
88 parse_media(style_elem, value);
89 break;
90 }
91#endif
92
93 /* title is ignored. */
94 default: {
95 SPObject::set(key, value);
96 break;
97 }
98 }
99}
100
102 if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
103 repr = xml_doc->createElement("svg:style");
104 }
105
106 if (flags & SP_OBJECT_WRITE_BUILD) {
107 g_warning("nyi: Forming <style> content for SP_OBJECT_WRITE_BUILD.");
108 /* fixme: Consider having the CRStyleSheet be a member of SPStyleElem, and then
109 pretty-print to a string s, then repr->addChild(xml_doc->createTextNode(s), NULL). */
110 }
111 if (is_css) {
112 repr->setAttribute("type", "text/css");
113 }
114 /* todo: media */
115
116 SPObject::write(xml_doc, repr, flags);
117
118 return repr;
119}
120
121
123static Glib::ustring
125{
126 Glib::ustring ret;
127 // effic: Initialising ret to a reasonable starting size could speed things up.
128 for (Inkscape::XML::Node const *rch = repr.firstChild(); rch != nullptr; rch = rch->next()) {
129 if ( rch->type() == Inkscape::XML::NodeType::TEXT_NODE ) {
130 ret += rch->content();
131 }
132 }
133 return ret;
134}
135
136
137
138/* Callbacks for SAC-style libcroco parser. */
139
141
145struct ParseTmp
146{
147private:
148 static constexpr unsigned ParseTmp_magic = 0x23474397; // from /dev/urandom
149 unsigned const magic = ParseTmp_magic;
150
151public:
152 CRParser *const parser;
153 CRStyleSheet *const stylesheet;
154 SPDocument *const document; // Need file location for '@import'
155
156 // Current statement
157 StmtType stmtType = NO_STMT;
158 CRStatement *currStmt = nullptr;
159
160 ParseTmp() = delete;
161 ParseTmp(ParseTmp const &) = delete;
162 ParseTmp(CRStyleSheet *const stylesheet, SPDocument *const document);
163 ~ParseTmp() { cr_parser_destroy(parser); }
164
168 static ParseTmp *cast(CRDocHandler *a_handler)
169 {
170 assert(a_handler && a_handler->app_data);
171 auto self = static_cast<ParseTmp *>(a_handler->app_data);
172 assert(self->magic == ParseTmp_magic);
173 return self;
174 }
175};
176
177static void
179 GList *a_media_list,
180 CRString *a_uri,
181 CRString *a_uri_default_ns,
182 CRParsingLocation *a_location)
183{
184 /* a_uri_default_ns is set to NULL and is unused by libcroco */
185
186 // Get document
187 g_return_if_fail(a_handler && a_uri);
188 auto &parse_tmp = *ParseTmp::cast(a_handler);
189
190 SPDocument* document = parse_tmp.document;
191 if (!document) {
192 std::cerr << "import_style_cb: No document!" << std::endl;
193 return;
194 }
195 if (!document->getDocumentFilename()) {
196 std::cerr << "import_style_cb: Document filename is NULL" << std::endl;
197 return;
198 }
199
200 // Get file
201 auto import_file =
202 Inkscape::IO::Resource::get_filename (document->getDocumentFilename(), a_uri->stryng->str);
203
204 // Parse file
205 CRStyleSheet *stylesheet = cr_stylesheet_new (nullptr);
206 ParseTmp parse_new(stylesheet, document);
207 CRStatus const parse_status =
208 cr_parser_parse_file(parse_new.parser, reinterpret_cast<const guchar *>(import_file.c_str()), CR_UTF_8);
209 if (parse_status == CR_OK) {
210 g_assert(parse_tmp.stylesheet);
211 g_assert(parse_tmp.stylesheet != stylesheet);
212 stylesheet->origin = ORIGIN_AUTHOR;
213 // Append import statement
214 CRStatement *ruleset =
215 cr_statement_new_at_import_rule(parse_tmp.stylesheet, cr_string_dup(a_uri), nullptr, stylesheet);
216 parse_tmp.stylesheet->statements = cr_statement_append(parse_tmp.stylesheet->statements, ruleset);
217 } else {
218 std::cerr << "import_style_cb: Could not parse: " << import_file << std::endl;
219 cr_stylesheet_destroy (stylesheet);
220 }
221};
222
223static void
225 CRSelector *a_sel_list)
226{
227 g_return_if_fail(a_handler && a_sel_list);
228 auto &parse_tmp = *ParseTmp::cast(a_handler);
229
230 if ( (parse_tmp.currStmt != nullptr)
231 || (parse_tmp.stmtType != NO_STMT) ) {
232 g_warning("Expecting currStmt==NULL and stmtType==0 (NO_STMT) at start of ruleset, but found currStmt=%p, stmtType=%u",
233 static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType));
234 // fixme: Check whether we need to unref currStmt if non-NULL.
235 }
236 CRStatement *ruleset = cr_statement_new_ruleset(parse_tmp.stylesheet, a_sel_list, nullptr, nullptr);
237 g_return_if_fail(ruleset && ruleset->type == RULESET_STMT);
238 parse_tmp.stmtType = NORMAL_RULESET_STMT;
239 parse_tmp.currStmt = ruleset;
240}
241
242static void
244 CRSelector *a_sel_list)
245{
246 g_return_if_fail(a_handler && a_sel_list);
247 auto &parse_tmp = *ParseTmp::cast(a_handler);
248
249 CRStatement *const ruleset = parse_tmp.currStmt;
250 if (parse_tmp.stmtType == NORMAL_RULESET_STMT
251 && ruleset
252 && ruleset->type == RULESET_STMT
253 && ruleset->kind.ruleset->sel_list == a_sel_list)
254 {
255 parse_tmp.stylesheet->statements = cr_statement_append(parse_tmp.stylesheet->statements,
256 ruleset);
257 } else {
258 g_warning("Found stmtType=%u, stmt=%p, stmt.type=%u, ruleset.sel_list=%p, a_sel_list=%p.",
259 unsigned(parse_tmp.stmtType),
260 ruleset,
261 unsigned(ruleset->type),
262 ruleset->kind.ruleset->sel_list,
263 a_sel_list);
264 }
265 parse_tmp.currStmt = nullptr;
266 parse_tmp.stmtType = NO_STMT;
267}
268
269static void
272{
273 auto &parse_tmp = *ParseTmp::cast(a_handler);
274
275 if (parse_tmp.stmtType != NO_STMT || parse_tmp.currStmt != nullptr) {
276 g_warning("Expecting currStmt==NULL and stmtType==0 (NO_STMT) at start of @font-face, but found currStmt=%p, stmtType=%u",
277 static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType));
278 // fixme: Check whether we need to unref currStmt if non-NULL.
279 }
280 CRStatement *font_face_rule = cr_statement_new_at_font_face_rule (parse_tmp.stylesheet, nullptr);
281 g_return_if_fail(font_face_rule && font_face_rule->type == AT_FONT_FACE_RULE_STMT);
282 parse_tmp.stmtType = FONT_FACE_STMT;
283 parse_tmp.currStmt = font_face_rule;
284}
285
286static void
288{
289 auto &parse_tmp = *ParseTmp::cast(a_handler);
290
291 CRStatement *const font_face_rule = parse_tmp.currStmt;
292 if (parse_tmp.stmtType == FONT_FACE_STMT
293 && font_face_rule
294 && font_face_rule->type == AT_FONT_FACE_RULE_STMT)
295 {
296 parse_tmp.stylesheet->statements = cr_statement_append(parse_tmp.stylesheet->statements,
297 font_face_rule);
298 } else {
299 g_warning("Found stmtType=%u, stmt=%p, stmt.type=%u.",
300 unsigned(parse_tmp.stmtType),
301 font_face_rule,
302 unsigned(font_face_rule->type));
303 }
304
305 g_warning("end_font_face_cb: font face rule limited support.");
306 cr_declaration_dump(font_face_rule->kind.font_face_rule->decl_list, stderr, 2, TRUE);
307 std::cerr << std::endl;
308
309 // Get document
310 SPDocument* document = parse_tmp.document;
311 if (!document) {
312 std::cerr << "end_font_face_cb: No document!" << std::endl;
313 return;
314 }
315 if (!document->getDocumentFilename()) {
316 std::cerr << "end_font_face_cb: Document filename is NULL" << std::endl;
317 return;
318 }
319
320 // Add ttf or otf fonts.
321 CRDeclaration const *cur = nullptr;
322 for (cur = font_face_rule->kind.font_face_rule->decl_list; cur; cur = cur->next) {
323 if (cur->property &&
324 cur->property->stryng &&
325 cur->property->stryng->str &&
326 strcmp(cur->property->stryng->str, "src") == 0 ) {
327
328 if (cur->value &&
329 cur->value->content.str &&
330 cur->value->content.str->stryng &&
331 cur->value->content.str->stryng->str) {
332
333 Glib::ustring value = cur->value->content.str->stryng->str;
334
335 if (value.rfind("ttf") == (value.length() - 3) ||
336 value.rfind("otf") == (value.length() - 3)) {
337
338 // Get file
339 Glib::ustring ttf_file =
341
342 if (!ttf_file.empty()) {
343 FontFactory::get().AddFontFile(ttf_file.c_str());
344 g_info("end_font_face_cb: Added font: %s", ttf_file.c_str());
345
346 // FIX ME: Need to refresh font list.
347 } else {
348 g_warning("end_font_face_cb: Failed to add: %s", value.c_str());
349 }
350 }
351 }
352 }
353 }
354
355 parse_tmp.currStmt = nullptr;
356 parse_tmp.stmtType = NO_STMT;
357
358}
359
360static void
361property_cb(CRDocHandler *const a_handler,
362 CRString *const a_name,
363 CRTerm *const a_value, gboolean const a_important)
364{
365 // std::cerr << "property_cb: Entrance: " << a_name->stryng->str << ": " << cr_term_to_string(a_value) << std::endl;
366 g_return_if_fail(a_handler && a_name);
367 auto &parse_tmp = *ParseTmp::cast(a_handler);
368
369 CRStatement *const ruleset = parse_tmp.currStmt;
370 g_return_if_fail(ruleset);
371
372 CRDeclaration *const decl = cr_declaration_new (ruleset, cr_string_dup(a_name), a_value);
373 g_return_if_fail(decl);
374 decl->important = a_important;
375
376 switch (parse_tmp.stmtType) {
377
378 case NORMAL_RULESET_STMT: {
379 g_return_if_fail (ruleset->type == RULESET_STMT);
380 CRStatus const append_status = cr_statement_ruleset_append_decl (ruleset, decl);
381 g_return_if_fail (append_status == CR_OK);
382 break;
383 }
384 case FONT_FACE_STMT: {
385 g_return_if_fail (ruleset->type == AT_FONT_FACE_RULE_STMT);
386 CRDeclaration *new_decls = cr_declaration_append (ruleset->kind.font_face_rule->decl_list, decl);
387 g_return_if_fail (new_decls);
388 ruleset->kind.font_face_rule->decl_list = new_decls;
389 break;
390 }
391 default:
392 g_warning ("property_cb: Unhandled stmtType: %u", parse_tmp.stmtType);
393 return;
394 }
395}
396
397ParseTmp::ParseTmp(CRStyleSheet *const stylesheet, SPDocument *const document)
398 : parser(cr_parser_new(nullptr))
399 , stylesheet(stylesheet)
400 , document(document)
401{
402 CRDocHandler *sac_handler = cr_doc_handler_new();
403 sac_handler->app_data = this;
404 sac_handler->import_style = import_style_cb;
405 sac_handler->start_selector = start_selector_cb;
406 sac_handler->end_selector = end_selector_cb;
407 sac_handler->start_font_face = start_font_face_cb;
408 sac_handler->end_font_face = end_font_face_cb;
409 sac_handler->property = property_cb;
410 cr_parser_set_sac_handler(parser, sac_handler);
411 cr_doc_handler_unref(sac_handler);
412}
413
418std::vector<std::unique_ptr<SPStyle>> SPStyleElem::get_styles() const
419{
420 std::vector<std::unique_ptr<SPStyle>> styles;
421
422 if (style_sheet) {
424 for (int x = 0; x < count; ++x) {
426 styles.emplace_back(new SPStyle(document));
427 styles.back()->mergeStatement(statement);
428 }
429 }
430
431 return styles;
432}
433
439{
440 if (!self.style_sheet) {
441 return;
442 }
443
444 auto *next = self.style_sheet->next;
445 auto *cascade = self.document->getStyleCascade();
446 auto *topsheet = cr_cascade_get_sheet(cascade, ORIGIN_AUTHOR);
447
449
450 if (topsheet == self.style_sheet) {
451 // will unref style_sheet
452 cr_cascade_set_sheet(cascade, next, ORIGIN_AUTHOR);
453 } else if (!topsheet) {
455 }
456
457 self.style_sheet = nullptr;
458}
459
461 // TODO On modification (observer callbacks), clearing and re-appending to
462 // the cascade can change the position of a stylesheet relative to other
463 // sheets in the document. We need a better way to update a style sheet
464 // which preserves the position.
465 clear_style_sheet(*this);
466
467 // First, create the style-sheet object and track it in this
468 // element so that it can be edited. It'll be combined with
469 // the document's style sheet later.
470 style_sheet = cr_stylesheet_new (nullptr);
471
472 ParseTmp parse_tmp(style_sheet, document);
473
474 //XML Tree being used directly here while it shouldn't be.
475 Glib::ustring const text = concat_children(*getRepr());
476 if (!(text.find_first_not_of(" \t\r\n") != std::string::npos)) {
477 return;
478 }
479 CRStatus const parse_status =
480 cr_parser_parse_buf(parse_tmp.parser, reinterpret_cast<const guchar *>(text.c_str()), text.bytes(), CR_UTF_8);
481
482 if (parse_status == CR_OK) {
483 auto *cascade = document->getStyleCascade();
484 auto *topsheet = cr_cascade_get_sheet(cascade, ORIGIN_AUTHOR);
485 if (!topsheet) {
486 // if the style is the first style sheet that we've seen, set the document's
487 // first style sheet to this style and create a cascade object with it.
489 // unref style sheet; it's been refed by adding to cascade
491 } else {
492 // If not the first, then chain up this style_sheet
494 }
495 } else {
497 style_sheet = nullptr;
498 if (parse_status != CR_PARSING_ERROR) {
499 g_printerr("parsing error code=%u\n", unsigned(parse_status));
500 }
501 }
502 // If style sheet has changed, we need to cascade the entire object tree, top down
503 // Get root, read style, loop through children
504 document->getRoot()->requestDisplayUpdate(SP_OBJECT_STYLESHEET_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
505 SP_OBJECT_MODIFIED_FLAG);
506}
507
509 read_content();
510
512#if 0
513 readAttr( "media" );
514#endif
515
517 for (auto child = repr->firstChild(); child; child = child->next()) {
519 child->addObserver(textNodeObserver());
520 }
521 }
522
524}
525
528 for (auto child = getRepr()->firstChild(); child; child = child->next()) {
529 child->removeObserver(textNodeObserver());
530 }
531
532 clear_style_sheet(*this);
533
535}
536
537
538/*
539 Local Variables:
540 mode:c++
541 c-file-style:"stroustrup"
542 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
543 indent-tabs-mode:nil
544 fill-column:99
545 End:
546*/
547// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Lookup dictionary for attributes/properties.
SPAttr
Definition attributes.h:27
constexpr auto cast
Equivalent to dynamic_cast<T [const] *>(...) where the const is deduced.
Definition cast.h:84
void AddFontFile(char const *utf8file)
Add a an additional font.
static FontFactory & get(Args &&... args)
Definition statics.h:153
Interface for refcounted XML nodes.
Definition node.h:80
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual Node * firstChild()=0
Get the first child of this node.
virtual char const * content() const =0
Get the content of a text or comment node.
virtual void addObserver(NodeObserver &observer)=0
Add an object that will be notified of the changes to this node.
virtual void removeObserver(NodeObserver &observer)=0
Remove an object from the list of observers.
Typed SVG document implementation.
Definition document.h:101
SPRoot * getRoot()
Returns our SPRoot.
Definition document.h:200
char const * getDocumentFilename() const
Definition document.h:229
CRCascade * getStyleCascade()
Definition document.h:223
Inkscape::XML::Node * repr
Definition sp-object.h:193
SPDocument * document
Definition sp-object.h:188
virtual void set(SPAttr key, const char *value)
SPObject * firstChild()
Definition sp-object.h:315
virtual Inkscape::XML::Node * write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags)
virtual void release()
void readAttr(char const *key)
Read value of key attribute from XML node into object.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
virtual void build(SPDocument *doc, Inkscape::XML::Node *repr)
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
void notifyChildRemoved(Inkscape::XML::Node &, Inkscape::XML::Node &, Inkscape::XML::Node *) final
Child removal callback.
void notifyChildAdded(Inkscape::XML::Node &, Inkscape::XML::Node &, Inkscape::XML::Node *) final
Child addition callback.
void notifyChildOrderChanged(Inkscape::XML::Node &, Inkscape::XML::Node &, Inkscape::XML::Node *, Inkscape::XML::Node *) final
Child order change callback.
void notifyContentChanged(Inkscape::XML::Node &, Inkscape::Util::ptr_shared, Inkscape::Util::ptr_shared) final
Content change callback.
SPStyleElemNodeObserver & nodeObserver()
CRStyleSheet * style_sheet
void release() override
void build(SPDocument *doc, Inkscape::XML::Node *repr) override
~SPStyleElem() override
SPStyleElemTextNodeObserver & textNodeObserver()
void read_content() override
Inkscape::XML::Node * write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags) override
std::vector< std::unique_ptr< SPStyle > > get_styles() const
Get the list of styles.
void set(SPAttr key, char const *value) override
An SVG style object.
Definition style.h:45
enum CRStatus cr_cascade_set_sheet(CRCascade *a_this, CRStyleSheet *a_sheet, enum CRStyleOrigin a_origin)
CRStyleSheet * cr_cascade_get_sheet(CRCascade *a_this, enum CRStyleOrigin a_origin)
CRDeclaration * cr_declaration_append(CRDeclaration *a_this, CRDeclaration *a_new)
void cr_declaration_dump(CRDeclaration const *a_this, FILE *a_fp, glong a_indent, gboolean a_one_per_line)
CRDeclaration * cr_declaration_new(CRStatement *a_statement, CRString *a_property, CRTerm *a_value)
CRDocHandler * cr_doc_handler_new(void)
typedefG_BEGIN_DECLS struct _CRDocHandler CRDocHandler
gboolean cr_doc_handler_unref(CRDocHandler *a_this)
The declaration file of the CRParser class.
enum CRStatus cr_parser_parse_file(CRParser *a_this, const guchar *a_file_uri, enum CREncoding a_enc)
enum CRStatus cr_parser_parse_buf(CRParser *a_this, const guchar *a_buf, gulong a_len, enum CREncoding a_enc)
void cr_parser_destroy(CRParser *a_this)
CRParser * cr_parser_new(CRTknzr *a_tknzr)
enum CRStatus cr_parser_set_sac_handler(CRParser *a_this, CRDocHandler *a_handler)
typedefG_BEGIN_DECLS struct _CRSelector CRSelector
Definition cr-selector.h:40
CRStatement * cr_statement_new_at_font_face_rule(CRStyleSheet *a_sheet, CRDeclaration *a_font_decls)
CRStatement * cr_statement_new_ruleset(CRStyleSheet *a_sheet, CRSelector *a_sel_list, CRDeclaration *a_decl_list, CRStatement *a_media_rule)
@ RULESET_STMT
@ AT_FONT_FACE_RULE_STMT
A css2 font face rule.
CRStatement * cr_statement_new_at_import_rule(CRStyleSheet *a_container_sheet, CRString *a_url, GList *a_media_list, CRStyleSheet *a_imported_sheet)
CRStatement * cr_statement_append(CRStatement *a_this, CRStatement *a_new)
enum CRStatus cr_statement_ruleset_append_decl(CRStatement *a_this, CRDeclaration *a_decl)
typedefG_BEGIN_DECLS struct _CRString CRString
Definition cr-string.h:37
CRString * cr_string_dup(CRString const *a_this)
CRStyleSheet * cr_stylesheet_unlink(CRStyleSheet *a_this)
@ ORIGIN_AUTHOR
CRStatement * cr_stylesheet_statement_get_from_list(CRStyleSheet *a_this, int itemnr)
gint cr_stylesheet_nr_rules(CRStyleSheet const *a_this)
void cr_stylesheet_destroy(CRStyleSheet *a_this)
CRStyleSheet * cr_stylesheet_append_stylesheet(CRStyleSheet *a_this, CRStyleSheet *a_new_stylesheet)
gboolean cr_stylesheet_unref(CRStyleSheet *a_this)
CRStyleSheet * cr_stylesheet_new(CRStatement *a_stmts)
CRStatus
The status type returned by the methods of the croco library.
Definition cr-utils.h:42
@ CR_OK
Definition cr-utils.h:43
@ CR_PARSING_ERROR
Definition cr-utils.h:58
@ CR_UTF_8
Definition cr-utils.h:89
TODO: insert short description here.
void media_set_all(Media &media)
Definition media.cpp:20
std::string get_filename(Type type, char const *filename, bool localized, bool silent)
Definition resource.cpp:170
@ TEXT_NODE
Text node, e.g. "Some text" in <group>Some text</group> is represented by a text node.
static cairo_user_data_key_t key
Ocnode * child[8]
Definition quantize.cpp:33
Inkscape::IO::Resource - simple resource API.
SPRoot: SVG <svg> implementation.
static void property_cb(CRDocHandler *const a_handler, CRString *const a_name, CRTerm *const a_value, gboolean const a_important)
static void import_style_cb(CRDocHandler *a_handler, GList *a_media_list, CRString *a_uri, CRString *a_uri_default_ns, CRParsingLocation *a_location)
static Glib::ustring concat_children(Inkscape::XML::Node const &repr)
Returns the concatenation of the content of the text children of the specified object.
static void start_selector_cb(CRDocHandler *a_handler, CRSelector *a_sel_list)
static void clear_style_sheet(SPStyleElem &self)
Remove style_sheet from the document style cascade and destroy it.
@ FONT_FACE_STMT
@ NO_STMT
@ NORMAL_RULESET_STMT
static void start_font_face_cb(CRDocHandler *a_handler, CRParsingLocation *)
static void end_selector_cb(CRDocHandler *a_handler, CRSelector *a_sel_list)
static void end_font_face_cb(CRDocHandler *a_handler)
TODO: insert short description here.
Interface for XML documents.
Definition document.h:43
virtual Node * createElement(char const *name)=0
CRDeclaration * decl_list
CRString *CRTerm * value
The property.
CRDeclaration * next
The implementation of the SAC parser.
Definition cr-parser.h:51
CRSelector * sel_list
A list of instances of #CRSimpeSel.
The abstraction of css statement as defined in the chapter 4 and appendix D.1 of the css2 spec.
CRAtFontFaceRule * font_face_rule
union _CRStatement::@6 kind
enum CRStatementType type
The type of the statement.
CRRuleSet * ruleset
An abstraction of a css stylesheet as defined by the css2 spec in chapter 4.
enum CRStyleOrigin origin
CRStyleSheet * next
A link to the next stylesheet.
An abstraction of a css2 term as defined in the CSS2 spec in appendix D.1: term ::= [ NUMBER S* | PER...
Definition cr-term.h:83
CRString * str
Definition cr-term.h:109
union _CRTerm::@7 content
The content of the term.
SPStyle - a style object for SPItem objects.
Interface for XML documents.
Interface for XML nodes.