Code

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