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