Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / sp-flowregion.cpp
1 /*
2  */
4 #ifdef HAVE_CONFIG_H
5 # include "config.h"
6 #endif
7 #include <glibmm/i18n.h>
9 #include <xml/repr.h>
10 #include "display/curve.h"
11 #include "sp-shape.h"
12 #include "sp-text.h"
13 #include "sp-use.h"
14 #include "style.h"
15 #include "document.h"
16 #include "sp-title.h"
17 #include "sp-desc.h"
19 #include "sp-flowregion.h"
21 #include "display/canvas-bpath.h"
24 #include "livarot/Path.h"
25 #include "livarot/Shape.h"
27 static void sp_flowregion_class_init (SPFlowregionClass *klass);
28 static void sp_flowregion_init (SPFlowregion *group);
29 static void sp_flowregion_dispose (GObject *object);
31 static void sp_flowregion_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
32 static void sp_flowregion_remove_child (SPObject * object, Inkscape::XML::Node * child);
33 static void sp_flowregion_update (SPObject *object, SPCtx *ctx, guint flags);
34 static void sp_flowregion_modified (SPObject *object, guint flags);
35 static Inkscape::XML::Node *sp_flowregion_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
37 static gchar * sp_flowregion_description (SPItem * item);
39 static SPItemClass * flowregion_parent_class;
41 static void sp_flowregionexclude_class_init (SPFlowregionExcludeClass *klass);
42 static void sp_flowregionexclude_init (SPFlowregionExclude *group);
43 static void sp_flowregionexclude_dispose (GObject *object);
45 static void sp_flowregionexclude_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
46 static void sp_flowregionexclude_remove_child (SPObject * object, Inkscape::XML::Node * child);
47 static void sp_flowregionexclude_update (SPObject *object, SPCtx *ctx, guint flags);
48 static void sp_flowregionexclude_modified (SPObject *object, guint flags);
49 static Inkscape::XML::Node *sp_flowregionexclude_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
51 static gchar * sp_flowregionexclude_description (SPItem * item);
53 static SPItemClass * flowregionexclude_parent_class;
56 static void         GetDest(SPObject* child,Shape **computed);
58 GType
59 sp_flowregion_get_type (void)
60 {
61         static GType group_type = 0;
62         if (!group_type) {
63                 GTypeInfo group_info = {
64                         sizeof (SPFlowregionClass),
65                         NULL,   /* base_init */
66                         NULL,   /* base_finalize */
67                         (GClassInitFunc) sp_flowregion_class_init,
68                         NULL,   /* class_finalize */
69                         NULL,   /* class_data */
70                         sizeof (SPFlowregion),
71                         16,     /* n_preallocs */
72                         (GInstanceInitFunc) sp_flowregion_init,
73                         NULL,   /* value_table */
74                 };
75                 group_type = g_type_register_static (SP_TYPE_ITEM, "SPFlowregion", &group_info, (GTypeFlags)0);
76         }
77         return group_type;
78 }
80 static void
81 sp_flowregion_class_init (SPFlowregionClass *klass)
82 {
83         GObjectClass * object_class;
84         SPObjectClass * sp_object_class;
85         SPItemClass * item_class;
87         object_class = (GObjectClass *) klass;
88         sp_object_class = (SPObjectClass *) klass;
89         item_class = (SPItemClass *) klass;
91         flowregion_parent_class = (SPItemClass *)g_type_class_ref (SP_TYPE_ITEM);
93         object_class->dispose = sp_flowregion_dispose;
95         sp_object_class->child_added = sp_flowregion_child_added;
96         sp_object_class->remove_child = sp_flowregion_remove_child;
97         sp_object_class->update = sp_flowregion_update;
98         sp_object_class->modified = sp_flowregion_modified;
99         sp_object_class->write = sp_flowregion_write;
101         item_class->description = sp_flowregion_description;
104 static void
105 sp_flowregion_init (SPFlowregion *group)
107         new (&group->computed) std::vector<Shape*>;
110 static void
111 sp_flowregion_dispose(GObject *object)
113         SPFlowregion *group=(SPFlowregion *)object;
114     for (std::vector<Shape*>::iterator it = group->computed.begin() ; it != group->computed.end() ; it++)
115         delete *it;
116     group->computed.~vector<Shape*>();
119 static void
120 sp_flowregion_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
122         SPItem *item;
124         item = SP_ITEM (object);
126         if (((SPObjectClass *) (flowregion_parent_class))->child_added)
127                 (* ((SPObjectClass *) (flowregion_parent_class))->child_added) (object, child, ref);
129         object->requestModified(SP_OBJECT_MODIFIED_FLAG);
132 /* fixme: hide (Lauris) */
134 static void
135 sp_flowregion_remove_child (SPObject * object, Inkscape::XML::Node * child)
137         if (((SPObjectClass *) (flowregion_parent_class))->remove_child)
138                 (* ((SPObjectClass *) (flowregion_parent_class))->remove_child) (object, child);
140         object->requestModified(SP_OBJECT_MODIFIED_FLAG);
144 static void sp_flowregion_update(SPObject *object, SPCtx *ctx, unsigned int flags)
146     SPFlowregion *group = SP_FLOWREGION(object);
148     SPItemCtx *ictx = reinterpret_cast<SPItemCtx *>(ctx);
149     SPItemCtx cctx = *ictx;
151     if (((SPObjectClass *) (flowregion_parent_class))->update) {
152         ((SPObjectClass *) (flowregion_parent_class))->update (object, ctx, flags);
153     }
155     if (flags & SP_OBJECT_MODIFIED_FLAG) {
156         flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
157     }
158     flags &= SP_OBJECT_MODIFIED_CASCADE;
160     GSList *l = NULL;
161     for ( SPObject *child = object->firstChild() ; child ; child = child->getNext() ) {
162         g_object_ref( G_OBJECT(child) );
163         l = g_slist_prepend(l, child);
164     }
165     l = g_slist_reverse(l);
166     while (l) {
167         SPObject *child = SP_OBJECT(l->data);
168         l = g_slist_remove(l, child);
169         if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
170             if (SP_IS_ITEM (child)) {
171                 SPItem const &chi = *SP_ITEM(child);
172                 cctx.i2doc = chi.transform * ictx->i2doc;
173                 cctx.i2vp = chi.transform * ictx->i2vp;
174                 child->updateDisplay((SPCtx *)&cctx, flags);
175             } else {
176                 child->updateDisplay(ctx, flags);
177             }
178         }
179         g_object_unref (G_OBJECT(child));
180     }
182     group->UpdateComputed();
185 void SPFlowregion::UpdateComputed(void)
187     for (std::vector<Shape*>::iterator it = computed.begin() ; it != computed.end() ; it++) {
188         delete *it;
189     }
190     computed.clear();
192     for (SPObject* child = firstChild() ; child ; child = child->getNext() ) {
193         Shape *shape = 0;
194         GetDest(child, &shape);
195         computed.push_back(shape);
196     }
199 static void sp_flowregion_modified(SPObject *object, guint flags)
201     SP_FLOWREGION(object); // ensure it is the proper type.
203     if (flags & SP_OBJECT_MODIFIED_FLAG) {
204         flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
205     }
206     flags &= SP_OBJECT_MODIFIED_CASCADE;
208     GSList *l = NULL;
209     for ( SPObject *child = object->firstChild() ; child ; child = child->getNext() ) {
210         g_object_ref( G_OBJECT(child) );
211         l = g_slist_prepend(l, child);
212     }
213     l = g_slist_reverse(l);
214     while (l) {
215         SPObject *child = SP_OBJECT(l->data);
216         l = g_slist_remove(l, child);
217         if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
218             child->emitModified(flags);
219         }
220         g_object_unref( G_OBJECT(child) );
221     }
224 static Inkscape::XML::Node *sp_flowregion_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
226     if (flags & SP_OBJECT_WRITE_BUILD) {
227         if ( repr == NULL ) {
228             repr = xml_doc->createElement("svg:flowRegion");
229         }
231         GSList *l = NULL;
232         for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) {
233             if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
234                 Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
235                 if (crepr) {
236                     l = g_slist_prepend(l, crepr);
237                 }
238             }
239         }
241         while (l) {
242             repr->addChild((Inkscape::XML::Node *) l->data, NULL);
243             Inkscape::GC::release((Inkscape::XML::Node *) l->data);
244             l = g_slist_remove(l, l->data);
245         }
247     } else {
248         for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) {
249             if ( !SP_IS_TITLE(child) && !SP_IS_DESC(child) ) {
250                 child->updateRepr(flags);
251             }
252         }
253     }
255     if (((SPObjectClass *) (flowregion_parent_class))->write) {
256         ((SPObjectClass *) (flowregion_parent_class))->write (object, xml_doc, repr, flags);
257     }
259     return repr;
263 static gchar *sp_flowregion_description(SPItem */*item*/)
265         // TRANSLATORS: "Flow region" is an area where text is allowed to flow
266         return g_strdup_printf(_("Flow region"));
269 /*
270  *
271  */
273 GType
274 sp_flowregionexclude_get_type (void)
276         static GType group_type = 0;
277         if (!group_type) {
278                 GTypeInfo group_info = {
279                         sizeof (SPFlowregionExcludeClass),
280                         NULL,   /* base_init */
281                         NULL,   /* base_finalize */
282                         (GClassInitFunc) sp_flowregionexclude_class_init,
283                         NULL,   /* class_finalize */
284                         NULL,   /* class_data */
285                         sizeof (SPFlowregionExclude),
286                         16,     /* n_preallocs */
287                         (GInstanceInitFunc) sp_flowregionexclude_init,
288                         NULL,   /* value_table */
289                 };
290                 group_type = g_type_register_static (SP_TYPE_ITEM, "SPFlowregionExclude", &group_info, (GTypeFlags)0);
291         }
292         return group_type;
295 static void
296 sp_flowregionexclude_class_init (SPFlowregionExcludeClass *klass)
298         GObjectClass * object_class;
299         SPObjectClass * sp_object_class;
300         SPItemClass * item_class;
302         object_class = (GObjectClass *) klass;
303         sp_object_class = (SPObjectClass *) klass;
304         item_class = (SPItemClass *) klass;
306         flowregionexclude_parent_class = (SPItemClass *)g_type_class_ref (SP_TYPE_ITEM);
308         object_class->dispose = sp_flowregionexclude_dispose;
310         sp_object_class->child_added = sp_flowregionexclude_child_added;
311         sp_object_class->remove_child = sp_flowregionexclude_remove_child;
312         sp_object_class->update = sp_flowregionexclude_update;
313         sp_object_class->modified = sp_flowregionexclude_modified;
314         sp_object_class->write = sp_flowregionexclude_write;
316         item_class->description = sp_flowregionexclude_description;
319 static void
320 sp_flowregionexclude_init (SPFlowregionExclude *group)
322         group->computed = NULL;
325 static void
326 sp_flowregionexclude_dispose(GObject *object)
328         SPFlowregionExclude *group=(SPFlowregionExclude *)object;
329     if (group->computed) {
330         delete group->computed;
331         group->computed = NULL;
332     }
335 static void
336 sp_flowregionexclude_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
338         SPItem *item;
340         item = SP_ITEM (object);
342         if (((SPObjectClass *) (flowregionexclude_parent_class))->child_added)
343                 (* ((SPObjectClass *) (flowregionexclude_parent_class))->child_added) (object, child, ref);
345         object->requestModified(SP_OBJECT_MODIFIED_FLAG);
348 /* fixme: hide (Lauris) */
350 static void
351 sp_flowregionexclude_remove_child (SPObject * object, Inkscape::XML::Node * child)
353         if (((SPObjectClass *) (flowregionexclude_parent_class))->remove_child)
354                 (* ((SPObjectClass *) (flowregionexclude_parent_class))->remove_child) (object, child);
356         object->requestModified(SP_OBJECT_MODIFIED_FLAG);
360 static void sp_flowregionexclude_update(SPObject *object, SPCtx *ctx, unsigned int flags)
362     SPFlowregionExclude *group = SP_FLOWREGIONEXCLUDE (object);
364     SPItemCtx *ictx = reinterpret_cast<SPItemCtx *>(ctx);
365     SPItemCtx cctx = *ictx;
367     if (((SPObjectClass *) (flowregionexclude_parent_class))->update) {
368         ((SPObjectClass *) (flowregionexclude_parent_class))->update (object, ctx, flags);
369     }
371     if (flags & SP_OBJECT_MODIFIED_FLAG) {
372         flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
373     }
374     flags &= SP_OBJECT_MODIFIED_CASCADE;
376     GSList *l = NULL;
377     for ( SPObject *child = object->firstChild() ; child ; child = child->getNext() ) {
378         g_object_ref( G_OBJECT(child) );
379         l = g_slist_prepend(l, child);
380     }
381     l = g_slist_reverse (l);
382     while (l) {
383         SPObject *child = SP_OBJECT(l->data);
384         l = g_slist_remove(l, child);
385         if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
386             if (SP_IS_ITEM (child)) {
387                 SPItem const &chi = *SP_ITEM(child);
388                 cctx.i2doc = chi.transform * ictx->i2doc;
389                 cctx.i2vp = chi.transform * ictx->i2vp;
390                 child->updateDisplay((SPCtx *)&cctx, flags);
391             } else {
392                 child->updateDisplay(ctx, flags);
393             }
394         }
395         g_object_unref( G_OBJECT(child) );
396     }
398     group->UpdateComputed();
401 void SPFlowregionExclude::UpdateComputed(void)
403     if (computed) {
404         delete computed;
405         computed = NULL;
406     }
408     for ( SPObject* child = firstChild() ; child ; child = child->getNext() ) {
409         GetDest(child, &computed);
410     }
413 static void sp_flowregionexclude_modified(SPObject *object, guint flags)
415     SP_FLOWREGIONEXCLUDE(object); // Ensure it is the proper type
417     if (flags & SP_OBJECT_MODIFIED_FLAG) {
418         flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
419     }
420     flags &= SP_OBJECT_MODIFIED_CASCADE;
422     GSList *l = NULL;
423     for ( SPObject *child = object->firstChild() ; child ; child = child->getNext() ) {
424         g_object_ref( G_OBJECT(child) );
425         l = g_slist_prepend(l, child);
426     }
427     l = g_slist_reverse (l);
428     while (l) {
429         SPObject *child = SP_OBJECT(l->data);
430         l = g_slist_remove(l, child);
431         if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
432             child->emitModified(flags);
433         }
434         g_object_unref( G_OBJECT(child) );
435     }
438 static Inkscape::XML::Node *sp_flowregionexclude_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
440     if (flags & SP_OBJECT_WRITE_BUILD) {
441         if ( repr == NULL ) {
442             repr = xml_doc->createElement("svg:flowRegionExclude");
443         }
445         GSList *l = NULL;
446         for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) {
447             Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
448             if (crepr) {
449                 l = g_slist_prepend(l, crepr);
450             }
451         }
453         while (l) {
454             repr->addChild((Inkscape::XML::Node *) l->data, NULL);
455             Inkscape::GC::release((Inkscape::XML::Node *) l->data);
456             l = g_slist_remove(l, l->data);
457         }
459     } else {
460         for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) {
461             child->updateRepr(flags);
462         }
463     }
465     if (((SPObjectClass *) (flowregionexclude_parent_class))->write) {
466         ((SPObjectClass *) (flowregionexclude_parent_class))->write (object, xml_doc, repr, flags);
467     }
469     return repr;
473 static gchar *sp_flowregionexclude_description(SPItem */*item*/)
475         /* TRANSLATORS: A region "cut out of" a flow region; text is not allowed to flow inside the
476          * flow excluded region.  flowRegionExclude in SVG 1.2: see
477          * http://www.w3.org/TR/2004/WD-SVG12-20041027/flow.html#flowRegion-elem and
478          * http://www.w3.org/TR/2004/WD-SVG12-20041027/flow.html#flowRegionExclude-elem. */
479         return g_strdup_printf(_("Flow excluded region"));
482 /*
483  *
484  */
486 static void         UnionShape(Shape **base_shape, Shape const *add_shape)
488     if (*base_shape == NULL)
489         *base_shape = new Shape;
490         if ( (*base_shape)->hasEdges() == false ) {
491                 (*base_shape)->Copy(const_cast<Shape*>(add_shape));
492         } else if ( add_shape->hasEdges() ) {
493                 Shape* temp=new Shape;
494                 temp->Booleen(const_cast<Shape*>(add_shape), *base_shape, bool_op_union);
495                 delete *base_shape;
496                 *base_shape = temp;
497         }
500 static void         GetDest(SPObject* child,Shape **computed)
502         if ( child == NULL ) return;
504         SPCurve *curve=NULL;
505         Geom::Matrix tr_mat;
507         SPObject* u_child=child;
508         if ( SP_IS_USE(u_child) ) {
509                 u_child=SP_USE(u_child)->child;
510                 tr_mat = SP_ITEM(u_child)->getRelativeTransform(SP_OBJECT_PARENT(child));
511         } else {
512                 tr_mat = SP_ITEM(u_child)->transform;
513         }
514         if ( SP_IS_SHAPE (u_child) ) {
515                 curve = SP_SHAPE (u_child)->getCurve ();
516         } else if ( SP_IS_TEXT (u_child) ) {
517         curve = SP_TEXT (u_child)->getNormalizedBpath ();
518         }
520         if ( curve ) {
521                 Path*   temp=new Path;
522         temp->LoadPathVector(curve->get_pathvector(), tr_mat, true);
523                 Shape*  n_shp=new Shape;
524                 temp->Convert(0.25);
525                 temp->Fill(n_shp,0);
526                 Shape*  uncross=new Shape;
527                 SPStyle* style=SP_OBJECT_STYLE(u_child);
528                 if ( style && style->fill_rule.computed == SP_WIND_RULE_EVENODD ) {
529                         uncross->ConvertToShape(n_shp,fill_oddEven);
530                 } else {
531                         uncross->ConvertToShape(n_shp,fill_nonZero);
532                 }
533                 UnionShape(computed, uncross);
534                 delete uncross;
535                 delete n_shp;
536                 delete temp;
537                 curve->unref();
538         } else {
539 //              printf("no curve\n");
540         }
543 /*
544   Local Variables:
545   mode:c++
546   c-file-style:"stroustrup"
547   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
548   indent-tabs-mode:nil
549   fill-column:99
550   End:
551 */
552 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :