1 #define __SP_CONDITIONS_CPP__
3 /*
4 * SVG conditional attribute evaluation
5 *
6 * Authors:
7 * Andrius R. <knutux@gmail.com>
8 *
9 * Copyright (C) 2006 authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
18 #include <set>
19 #include <glibmm/ustring.h>
20 #include "conditions.h"
21 #include "xml/repr.h"
22 #include "dialogs/rdf.h"
24 typedef bool (* condition_evaluator)(SPItem const *item, gchar const *value);
26 struct Condition {
27 gchar const *attribute;
28 condition_evaluator evaluator;
29 };
31 static bool evaluateSystemLanguage(SPItem const *item, gchar const *value);
32 static bool evaluateRequiredFeatures(SPItem const *item, gchar const *value);
33 static bool evaluateRequiredExtensions(SPItem const *item, gchar const *value);
35 /* define any conditional attributes and their handler functions in this array */
36 static Condition _condition_handlers[] = {
37 { "systemLanguage", evaluateSystemLanguage },
38 { "requiredFeatures", evaluateRequiredFeatures },
39 { "requiredExtensions", evaluateRequiredExtensions },
40 };
42 /* function which evaluates if item should be displayed */
43 bool sp_item_evaluate(SPItem const *item) {
44 Inkscape::XML::Node *grepr = SP_OBJECT_REPR (item);
46 for ( unsigned int i = 0 ; i < sizeof(_condition_handlers)/sizeof(_condition_handlers[0]) ; i++ ) {
47 gchar const *value = grepr->attribute(_condition_handlers[i].attribute);
48 if ( NULL == value )
49 continue;
51 if (!_condition_handlers[i].evaluator(item, value))
52 return false;
53 }
55 return true;
56 }
58 #define ISALNUM(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || ((c) >= '0' && (c) <= '9'))
60 static gchar *preprocessLanguageCode(gchar *lngcode) {
61 if ( NULL == lngcode )
62 return NULL;
64 lngcode = g_strstrip(lngcode);
65 if ( 0 == *lngcode )
66 return lngcode;
67 for ( unsigned int i = 0 ; i < strlen(lngcode) ; i++ ) {
68 if ( lngcode[i] >= 'A' && lngcode[i] <= 'Z' ) {
69 lngcode[i] = g_ascii_tolower(lngcode[i]);
70 } else if ( '_' == lngcode[i] ) {
71 lngcode[i] = '-';
72 } else if ( !ISALNUM(lngcode[i]) && '-' != lngcode[i] ) {
73 // only alpha numeric characters and '-' may be contained in language code
74 lngcode[0] = 0;
75 break;
76 }
77 }
79 return lngcode;
80 }
82 static bool evaluateSystemLanguage(SPItem const *item, gchar const *value) {
83 if ( NULL == value )
84 return true;
86 std::set<Glib::ustring> language_codes;
87 gchar *str = NULL;
88 gchar **strlist = g_strsplit( value, ",", 0);
90 for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
91 gchar *lngcode = preprocessLanguageCode(str);
92 if ( 0 == *lngcode )
93 continue;
94 language_codes.insert(lngcode);
96 gchar *pos = strchr (lngcode, '-');
97 if (pos)
98 {
99 // if subtag is used, primary tag is still a perfect match
100 *pos = 0;
101 if ( language_codes.find(lngcode) == language_codes.end() ) {
102 language_codes.insert(lngcode);
103 }
104 }
105 }
106 g_strfreev(strlist);
108 if (language_codes.empty())
109 return false;
111 SPDocument *document = SP_OBJECT_DOCUMENT(item);
112 Glib::ustring document_language = document->getLanguage();
114 if (document_language.size() == 0)
115 return false;
117 bool match = true;
118 strlist = g_strsplit( document_language.c_str(), ",", 0);
119 for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
120 gchar *lngcode = preprocessLanguageCode(str);
121 if ( 0 == *lngcode )
122 continue;
123 if ( language_codes.find(lngcode) != language_codes.end() ) {
124 match = true;
125 break;
126 }
127 match = false;
128 }
129 g_strfreev(strlist);
130 return match;
131 }
133 static std::vector<Glib::ustring> splitByWhitespace(gchar const *value) {
134 std::vector<Glib::ustring> parts;
135 gchar *str = NULL;
136 gchar **strlist = g_strsplit( value, ",", 0);
138 for ( int i = 0 ; (str = strlist[i]) ; i++ ) {
139 gchar *part = g_strstrip(str);
140 if ( 0 == *part )
141 continue;
142 parts.push_back(part);
143 }
144 g_strfreev(strlist);
145 return parts;
146 }
148 #define SVG11FEATURE "http://www.w3.org/TR/SVG11/feature#"
149 #define SVG10FEATURE "org.w3c."
151 static bool evaluateSVG11Feature(gchar const *feature) {
152 static gchar const *_supported_features[] = {
153 "SVG", // incomplete "SVG-static" - missing support for "Filter"
154 /* SVG - user agent supports at least one of the following:
155 "SVG-static", "SVG-animation", "SVG-dynamic" or "SVGDOM" */
156 // "SVGDOM", // not sure
157 /* SVGDOM - user agent supports at least one of the following:
158 "SVGDOM-static", "SVGDOM-animation" or "SVGDOM-dynamic" */
159 "SVG-static", // incomplete - missing support for "Filter"
160 /* SVG-static - user agent supports the following features:
161 "CoreAttribute", "Structure", "ContainerAttribute",
162 "ConditionalProcessing", "Image", "Style", "ViewportAttribute",
163 "Shape", "Text", "PaintAttribute", "OpacityAttribute",
164 "GraphicsAttribute", "Marker", "ColorProfile",
165 "Gradient", "Pattern", "Clip", "Mask", "Filter",
166 "XlinkAttribute", "Font", "Extensibility" */
167 // "SVGDOM-static", // not sure
168 /* SVGDOM-static - All of the DOM interfaces and methods
169 that correspond to SVG-static */
170 // "SVG-animation", // no support
171 /* SVG-animation - All of the language features from "SVG-static"
172 plus the feature "feature#Animation" */
173 // "SVGDOM-animation", // no support
174 /* SVGDOM-animation - All of the DOM interfaces and methods
175 that correspond to SVG-animation */
176 // "SVG-dynamic", // no support
177 /* SVG-dynamic - user agent supports all "SVG-animation" and the following features:
178 "Hyperlinking", "Scripting", "View", "Cursor",
179 "GraphicalEventsAttribute", "DocumentEventsAttribute", "AnimationEventsAttribute" */
180 // "SVGDOM-dynamic", // no support
181 /* SVGDOM-dynamic - All of the DOM interfaces and methods
182 that correspond to SVG-dynamic */
183 "CoreAttribute",
184 "Structure",
185 "BasicStructure",
186 "ContainerAttribute",
187 "ConditionalProcessing",
188 "Image",
189 "Style",
190 "ViewportAttribute", // not sure
191 "Shape",
192 "Text",
193 "BasicText",
194 "PaintAttribute",
195 "BasicPaintAttribute",
196 "OpacityAttribute",
197 "GraphicsAttribute",
198 "BasicGraphicsAttribute",
199 "Marker",
200 "ColorProfile",
201 "Gradient",
202 "Pattern",
203 "Clip",
204 "BasicClip",
205 "Mask",
206 // "Filter",
207 // "BasicFilter",
208 // "DocumentEventsAttribute",
209 // "GraphicalEventsAttribute",
210 // "AnimationEventsAttribute",
211 // "Cursor", // not sure
212 "Hyperlinking", // not sure
213 "XlinkAttribute", // not sure
214 "ExternalResourcesRequired", // not sure
215 "View",
216 // "Script",
217 // "Animation",
218 "Font",
219 "BasicFont",
220 "Extensibility", // not sure
221 };
223 for ( unsigned int i = 0 ; i < sizeof(_supported_features)/sizeof(_supported_features[0]); i++ ) {
224 if ( 0 == strcasecmp(feature, _supported_features[0]) )
225 return true;
226 }
227 return false;
228 }
230 static bool evaluateSVG10Feature(gchar const *feature) {
231 static gchar const *_supported_features[] = {
232 "svg.static", // incomplete - no filter effects
233 "dom.svg.static", // not sure
234 // "svg.animation",
235 // "dom.svg.animation",
236 // "svg.dynamic",
237 // "dom.svg.dynamic"
238 // "svg.all",
239 // "dom.svg.all"
240 };
241 for ( unsigned int i = 0 ; i < sizeof(_supported_features)/sizeof(_supported_features[0]); i++ ) {
242 if ( 0 == strcasecmp(feature, _supported_features[0]) )
243 return true;
244 }
245 return false;
246 }
248 static bool evaluateSingleFeature(gchar const *value) {
249 if ( NULL == value )
250 return false;
251 gchar const *found;
252 found = strstr(value, SVG11FEATURE);
253 if ( value == found )
254 return evaluateSVG11Feature(found + strlen(SVG11FEATURE));
255 found = strstr(value, SVG10FEATURE);
256 if ( value == found )
257 return evaluateSVG10Feature(found + strlen(SVG10FEATURE));
258 return false;
259 }
261 static bool evaluateRequiredFeatures(SPItem const */*item*/, gchar const *value) {
262 if ( NULL == value )
263 return true;
265 std::vector<Glib::ustring> parts = splitByWhitespace(value);
266 if ( 0 == parts.size() )
267 return false;
269 for ( unsigned int i = 0 ; i < parts.size() ; i++ ) {
270 if (!evaluateSingleFeature(parts[i].c_str())) {
271 return false;
272 }
273 }
275 return true;
276 }
278 static bool evaluateRequiredExtensions(SPItem const */*item*/, gchar const *value) {
279 if ( NULL == value )
280 return true;
281 return false;
282 }
284 /*
285 * Language codes and names:
286 aa Afar
287 ab Abkhazian
288 af Afrikaans
289 am Amharic
290 ar Arabic
291 as Assamese
292 ay Aymara
293 az Azerbaijani
295 ba Bashkir
296 be Byelorussian
297 bg Bulgarian
298 bh Bihari
299 bi Bislama
300 bn Bengali; Bangla
301 bo Tibetan
302 br Breton
304 ca Catalan
305 co Corsican
306 cs Czech
307 cy Welsh
309 da Danish
310 de German
311 dz Bhutani
313 el Greek
314 en English
315 eo Esperanto
316 es Spanish
317 et Estonian
318 eu Basque
320 fa Persian
321 fi Finnish
322 fj Fiji
323 fo Faroese
324 fr French
325 fy Frisian
327 ga Irish
328 gd Scots Gaelic
329 gl Galician
330 gn Guarani
331 gu Gujarati
333 ha Hausa
334 he Hebrew (formerly iw)
335 hi Hindi
336 hr Croatian
337 hu Hungarian
338 hy Armenian
340 ia Interlingua
341 id Indonesian (formerly in)
342 ie Interlingue
343 ik Inupiak
344 is Icelandic
345 it Italian
346 iu Inuktitut
348 ja Japanese
349 jw Javanese
351 ka Georgian
352 kk Kazakh
353 kl Greenlandic
354 km Cambodian
355 kn Kannada
356 ko Korean
357 ks Kashmiri
358 ku Kurdish
359 ky Kirghiz
361 la Latin
362 ln Lingala
363 lo Laothian
364 lt Lithuanian
365 lv Latvian, Lettish
367 mg Malagasy
368 mi Maori
369 mk Macedonian
370 ml Malayalam
371 mn Mongolian
372 mo Moldavian
373 mr Marathi
374 ms Malay
375 mt Maltese
376 my Burmese
378 na Nauru
379 ne Nepali
380 nl Dutch
381 no Norwegian
383 oc Occitan
384 om (Afan) Oromo
385 or Oriya
387 pa Punjabi
388 pl Polish
389 ps Pashto, Pushto
390 pt Portuguese
392 qu Quechua
394 rm Rhaeto-Romance
395 rn Kirundi
396 ro Romanian
397 ru Russian
398 rw Kinyarwanda
400 sa Sanskrit
401 sd Sindhi
402 sg Sangho
403 sh Serbo-Croatian
404 si Sinhalese
405 sk Slovak
406 sl Slovenian
407 sm Samoan
408 sn Shona
409 so Somali
410 sq Albanian
411 sr Serbian
412 ss Siswati
413 st Sesotho
414 su Sundanese
415 sv Swedish
416 sw Swahili
418 ta Tamil
419 te Telugu
420 tg Tajik
421 th Thai
422 ti Tigrinya
423 tk Turkmen
424 tl Tagalog
425 tn Setswana
426 to Tonga
427 tr Turkish
428 ts Tsonga
429 tt Tatar
430 tw Twi
432 ug Uighur
433 uk Ukrainian
434 ur Urdu
435 uz Uzbek
437 vi Vietnamese
438 vo Volapuk
440 wo Wolof
442 xh Xhosa
444 yi Yiddish (formerly ji)
445 yo Yoruba
447 za Zhuang
448 zh Chinese
449 zu Zulu
450 */
453 /*
454 Local Variables:
455 mode:c++
456 c-file-style:"stroustrup"
457 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
458 indent-tabs-mode:nil
459 fill-column:99
460 End:
461 */
462 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :