Code

Avoid crash by uninitialized perspectives.
[inkscape.git] / src / sp-mask.cpp
index 1f2d531b788d445fd2373fc0194417fc12c1bd7a..20cb38297c126fd07e93a27c1e6687accfc21575 100644 (file)
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
+#include <cstring>
+#include <string>
 
 #include "display/nr-arena.h"
 #include "display/nr-arena-group.h"
+#include "libnr/nr-matrix-ops.h"
 #include <xml/repr.h>
 
 #include "enums.h"
 #include "attributes.h"
 #include "document.h"
+#include "document-private.h"
 #include "sp-item.h"
 
 #include "sp-mask.h"
@@ -39,7 +43,7 @@ static void sp_mask_set (SPObject *object, unsigned int key, const gchar *value)
 static void sp_mask_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref);
 static void sp_mask_update (SPObject *object, SPCtx *ctx, guint flags);
 static void sp_mask_modified (SPObject *object, guint flags);
-static Inkscape::XML::Node *sp_mask_write (SPObject *object, Inkscape::XML::Node *repr, guint flags);
+static Inkscape::XML::Node *sp_mask_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
 
 SPMaskView *sp_mask_view_new_prepend (SPMaskView *list, unsigned int key, NRArenaItem *arenaitem);
 SPMaskView *sp_mask_view_list_remove (SPMaskView *list, SPMaskView *view);
@@ -87,8 +91,8 @@ sp_mask_init (SPMask *mask)
        mask->maskUnits_set = FALSE;
        mask->maskUnits = SP_CONTENT_UNITS_OBJECTBOUNDINGBOX;
 
-       mask->maskUnits_set = FALSE;
-       mask->maskUnits = SP_CONTENT_UNITS_USERSPACEONUSE;
+       mask->maskContentUnits_set = FALSE;
+       mask->maskContentUnits = SP_CONTENT_UNITS_USERSPACEONUSE;
 
        mask->display = NULL;
 }
@@ -117,7 +121,7 @@ sp_mask_release (SPObject * object)
 
        SPMask *cp = SP_MASK (object);
        while (cp->display) {
-               /* We simply unref and let item to manage this in handler */
+               /* We simply unref and let item manage this in handler */
                cp->display = sp_mask_view_list_remove (cp->display, cp->display);
        }
 
@@ -182,7 +186,6 @@ sp_mask_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML
                                                               SP_ITEM_REFERENCE_FLAGS);
                        if (ac) {
                                nr_arena_item_add_child (v->arenaitem, ac, NULL);
-                               nr_arena_item_unref (ac);
                        }
                }
        }
@@ -216,10 +219,9 @@ sp_mask_update (SPObject *object, SPCtx *ctx, guint flags)
        SPMask *mask = SP_MASK (object);
        for (SPMaskView *v = mask->display; v != NULL; v = v->next) {
                if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
-                       NRMatrix t;
-                       nr_matrix_set_scale (&t, v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0);
-                       t.c[4] = v->bbox.x0;
-                       t.c[5] = v->bbox.y0;
+            Geom::Matrix t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0));
+                       t[4] = v->bbox.x0;
+                       t[5] = v->bbox.y0;
                        nr_arena_group_set_child_transform (NR_ARENA_GROUP (v->arenaitem), &t);
                } else {
                        nr_arena_group_set_child_transform (NR_ARENA_GROUP (v->arenaitem), NULL);
@@ -254,18 +256,50 @@ sp_mask_modified (SPObject *object, guint flags)
 }
 
 static Inkscape::XML::Node *
-sp_mask_write (SPObject *object, Inkscape::XML::Node *repr, guint flags)
+sp_mask_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
 {
        if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
-               repr = sp_repr_new ("svg:mask");
+               repr = xml_doc->createElement("svg:mask");
        }
 
        if (((SPObjectClass *) (parent_class))->write)
-               ((SPObjectClass *) (parent_class))->write (object, repr, flags);
+               ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags);
 
        return repr;
 }
 
+// Create a mask element (using passed elements), add it to <defs>
+const gchar *
+sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform)
+{
+    Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document));
+
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:mask");
+    repr->setAttribute("maskUnits", "userSpaceOnUse");
+    
+    defsrepr->appendChild(repr);
+    const gchar *mask_id = repr->attribute("id");
+    SPObject *mask_object = document->getObjectById(mask_id);
+    
+    for (GSList *it = reprs; it != NULL; it = it->next) {
+        Inkscape::XML::Node *node = (Inkscape::XML::Node *)(it->data);
+        SPItem *item = SP_ITEM(mask_object->appendChildRepr(node));
+        
+        if (NULL != applyTransform) {
+            Geom::Matrix transform (item->transform);
+            transform *= (*applyTransform);
+            sp_item_write_transform(item, SP_OBJECT_REPR(item), transform);
+        }
+    }
+
+    if (repr != defsrepr->lastChild())
+        defsrepr->changeOrder(repr, defsrepr->lastChild()); // workaround for bug 989084
+    
+    Inkscape::GC::release(repr);
+    return mask_id;
+}
+
 NRArenaItem *
 sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key)
 {
@@ -283,16 +317,14 @@ sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key)
                        if (ac) {
                                /* The order is not important in mask */
                                nr_arena_item_add_child (ai, ac, NULL);
-                               nr_arena_item_unref (ac);
                        }
                }
        }
 
        if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
-               NRMatrix t;
-               nr_matrix_set_scale (&t, mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0);
-               t.c[4] = mask->display->bbox.x0;
-               t.c[5] = mask->display->bbox.y0;
+        Geom::Matrix t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0));
+               t[4] = mask->display->bbox.x0;
+               t[5] = mask->display->bbox.y0;
                nr_arena_group_set_child_transform (NR_ARENA_GROUP (ai), &t);
        }
 
@@ -332,7 +364,6 @@ sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox)
                            !NR_DF_TEST_CLOSE (v->bbox.x1, bbox->x1, NR_EPSILON) ||
                            !NR_DF_TEST_CLOSE (v->bbox.y1, bbox->y1, NR_EPSILON)) {
                                v->bbox = *bbox;
-                               SP_OBJECT(mask)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
                        }
                        break;
                }
@@ -373,3 +404,13 @@ sp_mask_view_list_remove (SPMaskView *list, SPMaskView *view)
        return list;
 }
 
+/*
+  Local Variables:
+  mode:c++
+  c-file-style:"stroustrup"
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+  indent-tabs-mode:nil
+  fill-column:99
+  End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :