Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / sp-object-repr.cpp
1 /*
2  * Object type dictionary and build frontend
3  *
4  * Authors:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *   Abhishek Sharma
7  *
8  * Copyright (C) 1999-2003 Lauris Kaplinski
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #include "sp-defs.h"
14 #include "sp-symbol.h"
15 #include "marker.h"
16 #include "sp-use.h"
17 #include "sp-root.h"
18 #include "sp-image.h"
19 #include "sp-linear-gradient-fns.h"
20 #include "sp-path.h"
21 #include "sp-radial-gradient-fns.h"
22 #include "sp-rect.h"
23 #include "box3d.h"
24 #include "box3d-side.h"
25 #include "persp3d.h"
26 #include "sp-ellipse.h"
27 #include "sp-star.h"
28 #include "sp-stop.h"
29 #include "sp-spiral.h"
30 #include "sp-offset.h"
31 #include "sp-line.h"
32 #include "sp-metadata.h"
33 #include "sp-polyline.h"
34 #include "sp-textpath.h"
35 #include "sp-tref.h"
36 #include "sp-tspan.h"
37 #include "sp-pattern.h"
38 #include "sp-clippath.h"
39 #include "sp-mask.h"
40 #include "sp-anchor.h"
41 //#include "sp-animation.h"
42 #include "sp-flowdiv.h"
43 #include "sp-flowregion.h"
44 #include "sp-flowtext.h"
45 #include "sp-script.h"
46 #include "config.h"
48 #ifdef ENABLE_SVG_FONTS
49     #include "sp-font.h"
50     #include "sp-font-face.h"
51     #include "sp-glyph.h"
52     #include "sp-missing-glyph.h"
53     #include "sp-glyph-kerning.h"
54 #endif
56 #include "sp-style-elem.h"
57 #include "sp-switch.h"
58 #include "color-profile-fns.h"
59 #include "xml/repr.h"
60 #include "sp-filter.h"
61 #include "sp-gaussian-blur.h"
62 #include "filters/blend.h"
63 #include "filters/colormatrix.h"
64 #include "filters/componenttransfer.h"
65 #include "filters/componenttransfer-funcnode.h"
66 #include "filters/composite.h"
67 #include "filters/convolvematrix.h"
68 #include "filters/diffuselighting.h"
69 #include "filters/distantlight.h"
70 #include "filters/displacementmap.h"
71 #include "filters/flood.h"
72 #include "filters/image.h"
73 #include "filters/merge.h"
74 #include "filters/morphology.h"
75 #include "filters/offset.h"
76 #include "filters/pointlight.h"
77 #include "filters/specularlighting.h"
78 #include "filters/spotlight.h"
79 #include "filters/tile.h"
80 #include "filters/turbulence.h"
81 #include "filters/mergenode.h"
82 #include "live_effects/lpeobject.h"
83 #include "sp-title.h"
84 #include "sp-desc.h"
87 enum NameType { REPR_NAME, SODIPODI_TYPE };
88 static unsigned const N_NAME_TYPES = SODIPODI_TYPE + 1;
90 static GType name_to_gtype(NameType name_type, gchar const *name);
92 /**
93  * Construct an SPRoot and all its descendents from the given repr.
94  */
95 SPObject *
96 sp_object_repr_build_tree(SPDocument *document, Inkscape::XML::Node *repr)
97 {
98     g_assert(document != NULL);
99     g_assert(repr != NULL);
101     gchar const * const name = repr->name();
102     g_assert(name != NULL);
103     GType const type = name_to_gtype(REPR_NAME, name);
104     g_assert(g_type_is_a(type, SP_TYPE_ROOT));
105     gpointer newobj = g_object_new(type, 0);
106     g_assert(newobj != NULL);
107     SPObject *const object = SP_OBJECT(newobj);
108     g_assert(object != NULL);
109     object->invoke_build(document, repr, FALSE);
111     return object;
114 GType
115 sp_repr_type_lookup(Inkscape::XML::Node *repr)
117     if ( repr->type() == Inkscape::XML::TEXT_NODE ) {
118         return SP_TYPE_STRING;
119     } else if ( repr->type() == Inkscape::XML::ELEMENT_NODE ) {
120         gchar const * const type_name = repr->attribute("sodipodi:type");
121         return ( type_name
122                  ? name_to_gtype(SODIPODI_TYPE, type_name)
123                  : name_to_gtype(REPR_NAME, repr->name()) );
124     } else {
125         return 0;
126     }
129 static GHashTable *t2dtable[N_NAME_TYPES] = {NULL};
131 static void
132 populate_dtables()
134     struct NameTypeEntry { char const *const name; GType const type_id; };
135     NameTypeEntry const repr_name_entries[] = {
136         { "svg:a", SP_TYPE_ANCHOR },
137         //{ "svg:animate", SP_TYPE_ANIMATE },
138         { "svg:circle", SP_TYPE_CIRCLE },
139         { "svg:color-profile", COLORPROFILE_TYPE },
140         { "svg:clipPath", SP_TYPE_CLIPPATH },
141         { "svg:defs", SP_TYPE_DEFS },
142         { "svg:desc", SP_TYPE_DESC },
143         { "svg:ellipse", SP_TYPE_ELLIPSE },
144         { "svg:filter", SP_TYPE_FILTER },
145         /* Note: flow* elements are proposed additions for SVG 1.2, they aren't in
146            SVG 1.1. */
147         { "svg:flowDiv", SP_TYPE_FLOWDIV },
148         { "svg:flowLine", SP_TYPE_FLOWLINE },
149         { "svg:flowPara", SP_TYPE_FLOWPARA },
150         { "svg:flowRegion", SP_TYPE_FLOWREGION },
151         { "svg:flowRegionBreak", SP_TYPE_FLOWREGIONBREAK },
152         { "svg:flowRegionExclude", SP_TYPE_FLOWREGIONEXCLUDE },
153         { "svg:flowRoot", SP_TYPE_FLOWTEXT },
154         { "svg:flowSpan", SP_TYPE_FLOWTSPAN },
155 #ifdef ENABLE_SVG_FONTS
156         { "svg:font", SP_TYPE_FONT },
157         { "svg:font-face", SP_TYPE_FONTFACE },
158         { "svg:glyph", SP_TYPE_GLYPH },
159         { "svg:missing-glyph", SP_TYPE_MISSING_GLYPH },
160         { "svg:hkern", SP_TYPE_HKERN },
161         { "svg:vkern", SP_TYPE_VKERN },
162 #endif
163         { "svg:g", SP_TYPE_GROUP },
164         { "svg:feBlend", SP_TYPE_FEBLEND },
165         { "svg:feColorMatrix", SP_TYPE_FECOLORMATRIX },
166         { "svg:feComponentTransfer", SP_TYPE_FECOMPONENTTRANSFER },
167         { "svg:feComposite", SP_TYPE_FECOMPOSITE },
168         { "svg:feConvolveMatrix", SP_TYPE_FECONVOLVEMATRIX },
169         { "svg:feDiffuseLighting", SP_TYPE_FEDIFFUSELIGHTING },
170         { "svg:feDistantLight", SP_TYPE_FEDISTANTLIGHT },
171         { "svg:feDisplacementMap", SP_TYPE_FEDISPLACEMENTMAP },
172         { "svg:feFlood", SP_TYPE_FEFLOOD },
173         { "svg:feFuncR", SP_TYPE_FEFUNCR },
174         { "svg:feFuncG", SP_TYPE_FEFUNCG },
175         { "svg:feFuncB", SP_TYPE_FEFUNCB },
176         { "svg:feFuncA", SP_TYPE_FEFUNCA },
177         { "svg:feGaussianBlur", SP_TYPE_GAUSSIANBLUR },
178         { "svg:feImage", SP_TYPE_FEIMAGE },
179         { "svg:feMerge", SP_TYPE_FEMERGE },
180         { "svg:feMorphology", SP_TYPE_FEMORPHOLOGY },
181         { "svg:feOffset", SP_TYPE_FEOFFSET },
182         { "svg:fePointLight", SP_TYPE_FEPOINTLIGHT },
183         { "svg:feSpecularLighting", SP_TYPE_FESPECULARLIGHTING },
184         { "svg:feSpotLight", SP_TYPE_FESPOTLIGHT },
185         { "svg:feTile", SP_TYPE_FETILE },
186         { "svg:feTurbulence", SP_TYPE_FETURBULENCE },
187         { "svg:feMergeNode", SP_TYPE_FEMERGENODE },
188         { "svg:image", SP_TYPE_IMAGE },
189         { "svg:line", SP_TYPE_LINE },
190         { "svg:linearGradient", SP_TYPE_LINEARGRADIENT },
191         { "svg:marker", SP_TYPE_MARKER },
192         { "svg:mask", SP_TYPE_MASK },
193         { "svg:metadata", SP_TYPE_METADATA },
194         { "svg:path", SP_TYPE_PATH },
195         { "svg:pattern", SP_TYPE_PATTERN },
196         { "svg:polygon", SP_TYPE_POLYGON },
197         { "svg:polyline", SP_TYPE_POLYLINE },
198         { "svg:radialGradient", SP_TYPE_RADIALGRADIENT },
199         { "svg:rect", SP_TYPE_RECT },
200         { "svg:stop", SP_TYPE_STOP },
201         { "svg:script", SP_TYPE_SCRIPT },
202         { "svg:svg", SP_TYPE_ROOT },
203         { "svg:style", SP_TYPE_STYLE_ELEM },
204         { "svg:switch", SP_TYPE_SWITCH },
205         { "svg:symbol", SP_TYPE_SYMBOL },
206         { "svg:text", SP_TYPE_TEXT },
207         { "svg:textPath", SP_TYPE_TEXTPATH },
208         { "svg:title", SP_TYPE_TITLE },
209         { "svg:tref", SP_TYPE_TREF },
210         { "svg:tspan", SP_TYPE_TSPAN },
211         { "svg:use", SP_TYPE_USE },
212         { "inkscape:path-effect", TYPE_LIVEPATHEFFECT }
213     };
214     NameTypeEntry const sodipodi_name_entries[] = {
215         { "arc", SP_TYPE_ARC },
216         { "inkscape:offset", SP_TYPE_OFFSET },
217         { "spiral", SP_TYPE_SPIRAL },
218         { "star", SP_TYPE_STAR },
219         { "inkscape:box3d", SP_TYPE_BOX3D },
220         { "inkscape:box3dside", SP_TYPE_BOX3D_SIDE },
221         { "inkscape:persp3d", SP_TYPE_PERSP3D }
222     };
224     NameTypeEntry const *const t2entries[] = {
225         repr_name_entries,
226         sodipodi_name_entries
227     };
228     unsigned const t2n_entries[] = {
229         G_N_ELEMENTS(repr_name_entries),
230         G_N_ELEMENTS(sodipodi_name_entries)
231     };
233     for (unsigned nt = 0; nt < N_NAME_TYPES; ++nt) {
234         NameTypeEntry const *const entries = t2entries[nt];
235         unsigned const n_entries = t2n_entries[nt];
236         GHashTable *&dtable = t2dtable[nt];
238         dtable = g_hash_table_new(g_str_hash, g_str_equal);
239         for (unsigned i = 0; i < n_entries; ++i) {
240             g_hash_table_insert(dtable,
241                                 (void *)entries[i].name,
242                                 (gpointer) entries[i].type_id);
243         }
244     }
247 static inline void
248 ensure_dtables_populated()
250     if (!*t2dtable) {
251         populate_dtables();
252     }
255 static GType
256 name_to_gtype(NameType const name_type, gchar const *name)
258     ensure_dtables_populated();
260     gpointer const data = g_hash_table_lookup(t2dtable[name_type], name);
261     return ( ( data == NULL )
262              ? SP_TYPE_OBJECT
263              : (GType) data );
266 void
267 sp_object_type_register(gchar const *name, GType const gtype)
269     GType const current = name_to_gtype(REPR_NAME, name);
270     if (current == SP_TYPE_OBJECT) {
271         g_hash_table_insert(t2dtable[REPR_NAME],
272                             const_cast<gchar *>(name),
273                             (gpointer) gtype);
274     } else {
275         /* Already registered. */
276         if (current != gtype) {
277             g_warning("repr type `%s' already registered as type #%lu, ignoring attempt to re-register as #%lu.",
278                       name, current, gtype);
279         }
280     }
283 /*
284   Local Variables:
285   mode:c++
286   c-file-style:"stroustrup"
287   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
288   indent-tabs-mode:nil
289   fill-column:99
290   End:
291 */
292 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :