Code

Fix change in revision 9947 to be consistent with rest of the codebase.
[inkscape.git] / src / sp-mask.cpp
index 456dadc5fc29d709c524c1957bf34cf800f6f388..dde91b0625280d8b1f8afa0643a7c3bd9555c38d 100644 (file)
@@ -1,24 +1,28 @@
-#define __SP_MASK_C__
-
 /*
  * SVG <mask> implementation
  *
  * Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
  * Copyright (C) 2003 authors
  *
  * 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);
@@ -100,11 +104,11 @@ sp_mask_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr
                ((SPObjectClass *) parent_class)->build (object, document, repr);
        }
 
-       sp_object_read_attr (object, "maskUnits");
-       sp_object_read_attr (object, "maskContentUnits");
+       object->readAttr( "maskUnits" );
+       object->readAttr( "maskContentUnits" );
 
        /* Register ourselves */
-       sp_document_add_resource (document, "mask", object);
+       document->addResource("mask", object);
 }
 
 static void
@@ -112,7 +116,7 @@ sp_mask_release (SPObject * object)
 {
        if (SP_OBJECT_DOCUMENT (object)) {
                /* Unregister ourselves */
-               sp_document_remove_resource (SP_OBJECT_DOCUMENT (object), "mask", object);
+               SP_OBJECT_DOCUMENT(object)->removeResource("mask", object);
        }
 
        SPMask *cp = SP_MASK (object);
@@ -176,98 +180,124 @@ sp_mask_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML
        if (SP_IS_ITEM (ochild)) {
                SPMask *cp = SP_MASK (object);
                for (SPMaskView *v = cp->display; v != NULL; v = v->next) {
-                       NRArenaItem *ac = sp_item_invoke_show (SP_ITEM (ochild),
-                                                              NR_ARENA_ITEM_ARENA (v->arenaitem),
+                       NRArenaItem *ac = SP_ITEM (ochild)->invoke_show (                                                              NR_ARENA_ITEM_ARENA (v->arenaitem),
                                                               v->key,
                                                               SP_ITEM_REFERENCE_FLAGS);
                        if (ac) {
                                nr_arena_item_add_child (v->arenaitem, ac, NULL);
-                               nr_arena_item_unref (ac);
                        }
                }
        }
 }
 
-static void
-sp_mask_update (SPObject *object, SPCtx *ctx, guint flags)
+static void sp_mask_update(SPObject *object, SPCtx *ctx, guint flags)
 {
-       if (flags & SP_OBJECT_MODIFIED_FLAG) {
-               flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
-       }
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
+    }
        
-       flags &= SP_OBJECT_MODIFIED_CASCADE;
-
-       SPObjectGroup *og = SP_OBJECTGROUP (object);
-       GSList *l = NULL;
-       for (SPObject *child = sp_object_first_child(SP_OBJECT(og)); child != NULL; child = SP_OBJECT_NEXT(child)) {
-               g_object_ref (G_OBJECT (child));
-               l = g_slist_prepend (l, child);
-       }
-       l = g_slist_reverse (l);
-       while (l) {
-               SPObject *child = SP_OBJECT (l->data);
-               l = g_slist_remove (l, child);
-               if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
-                       child->updateDisplay(ctx, flags);
-               }
-               g_object_unref (G_OBJECT (child));
-       }
-
-       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;
-                       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);
-               }
-       }
+    flags &= SP_OBJECT_MODIFIED_CASCADE;
+
+    SPObjectGroup *og = SP_OBJECTGROUP(object);
+    GSList *l = NULL;
+    for (SPObject *child = og->firstChild(); child; child = child->getNext()) {
+        g_object_ref(G_OBJECT (child));
+        l = g_slist_prepend (l, child);
+    }
+    l = g_slist_reverse (l);
+    while (l) {
+        SPObject *child = SP_OBJECT(l->data);
+        l = g_slist_remove(l, child);
+        if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+            child->updateDisplay(ctx, flags);
+        }
+        g_object_unref(G_OBJECT(child));
+    }
+
+    SPMask *mask = SP_MASK(object);
+    for (SPMaskView *v = mask->display; v != NULL; v = v->next) {
+        if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) {
+            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);
+        }
+    }
 }
 
-static void
-sp_mask_modified (SPObject *object, guint flags)
+static void sp_mask_modified(SPObject *object, guint flags)
 {
-       if (flags & SP_OBJECT_MODIFIED_FLAG) {
-               flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
-       }
+    if (flags & SP_OBJECT_MODIFIED_FLAG) {
+        flags |= SP_OBJECT_PARENT_MODIFIED_FLAG;
+    }
        
-       flags &= SP_OBJECT_MODIFIED_CASCADE;
-
-       SPObjectGroup *og = SP_OBJECTGROUP (object);
-       GSList *l = NULL;
-       for (SPObject *child = sp_object_first_child(SP_OBJECT(og)); child != NULL; child = SP_OBJECT_NEXT(child)) {
-               g_object_ref (G_OBJECT (child));
-               l = g_slist_prepend (l, child);
-       }
-       l = g_slist_reverse (l);
-       while (l) {
-               SPObject *child = SP_OBJECT (l->data);
-               l = g_slist_remove (l, child);
-               if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
-                       child->emitModified(flags);
-               }
-               g_object_unref (G_OBJECT (child));
-       }
+    flags &= SP_OBJECT_MODIFIED_CASCADE;
+
+    SPObjectGroup *og = SP_OBJECTGROUP(object);
+    GSList *l = NULL;
+    for (SPObject *child = og->firstChild(); child; child = child->getNext()) {
+        g_object_ref(G_OBJECT(child));
+        l = g_slist_prepend(l, child);
+    }
+    l = g_slist_reverse(l);
+    while (l) {
+        SPObject *child = SP_OBJECT(l->data);
+        l = g_slist_remove(l, child);
+        if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) {
+            child->emitModified(flags);
+        }
+        g_object_unref(G_OBJECT(child));
+    }
 }
 
 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;
 }
 
-NRArenaItem *
-sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key)
+// 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 = document->getReprDoc();
+    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);
+            item->doWriteTransform(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)
 {
        g_return_val_if_fail (mask != NULL, NULL);
        g_return_val_if_fail (SP_IS_MASK (mask), NULL);
@@ -277,37 +307,34 @@ sp_mask_show (SPMask *mask, NRArena *arena, unsigned int key)
        NRArenaItem *ai = NRArenaGroup::create(arena);
        mask->display = sp_mask_view_new_prepend (mask->display, key, ai);
 
-       for (SPObject *child = sp_object_first_child(SP_OBJECT(mask)) ; child != NULL; child = SP_OBJECT_NEXT(child)) {
+       for ( SPObject *child = mask->firstChild() ; child; child = child->getNext() ) {
                if (SP_IS_ITEM (child)) {
-                       NRArenaItem *ac = sp_item_invoke_show (SP_ITEM (child), arena, key, SP_ITEM_REFERENCE_FLAGS);
+                       NRArenaItem *ac = SP_ITEM (child)->invoke_show (arena, key, SP_ITEM_REFERENCE_FLAGS);
                        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);
        }
 
        return ai;
 }
 
-void
-sp_mask_hide (SPMask *cp, unsigned int key)
+void sp_mask_hide(SPMask *cp, unsigned int key)
 {
        g_return_if_fail (cp != NULL);
        g_return_if_fail (SP_IS_MASK (cp));
 
-       for (SPObject *child = sp_object_first_child(SP_OBJECT(cp)); child != NULL; child = SP_OBJECT_NEXT(child)) {
+       for ( SPObject *child = cp->firstChild(); child; child = child->getNext()) {
                if (SP_IS_ITEM (child)) {
-                       sp_item_invoke_hide (SP_ITEM (child), key);
+                       SP_ITEM(child)->invoke_hide (key);
                }
        }
 
@@ -381,4 +408,4 @@ sp_mask_view_list_remove (SPMaskView *list, SPMaskView *view)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :