Code

noop: dialogs/rdf.cpp: Mark a few pointers as not being written through. Make rdf_ma...
[inkscape.git] / src / dialogs / clonetiler.cpp
index 130480608413469142ab004966ed618dfd29b3f7..f6d3b030958859530d3f96b19157a2ab91df44fd 100644 (file)
@@ -149,7 +149,7 @@ on_picker_color_changed (guint rgba)
 
     Inkscape::XML::Node *repr = inkscape_get_repr(INKSCAPE, prefs_path);
     gchar c[32];
-    sp_svg_write_color(c, 32, rgba);
+    sp_svg_write_color(c, sizeof(c), rgba);
     repr->setAttribute("initial_color", c);
 
     is_updating = false;
@@ -293,9 +293,6 @@ clonetiler_get_transform (
     NR::Matrix flip_x = NR::translate(-cx, -cy) * NR::scale (-1, 1) * NR::translate(cx, cy);
     NR::Matrix flip_y = NR::translate(-cx, -cy) * NR::scale (1, -1) * NR::translate(cx, cy);
 
-    x = (int) pow ((double) x, d_per_x_exp);
-    y = (int) pow ((double) y, d_per_y_exp);
-
     switch (type) {
 
     case TILE_P1:
@@ -408,7 +405,7 @@ clonetiler_get_transform (
 
     case TILE_P4:
     {
-        NR::Matrix ori (NR::translate ((w + h) * (x/2) + dx,  (h + w) * (y/2) + dy));
+        NR::Matrix ori (NR::translate ((w + h) * pow((x/2), d_per_x_exp) + dx,  (h + w) * pow((y/2), d_per_y_exp) + dy));
         NR::Matrix dia1 (NR::translate (w/2 + h/2, -h/2 + w/2));
         NR::Matrix dia2 (NR::translate (-w/2 + h/2, h/2 + w/2));
         if (y % 2 == 0) {
@@ -430,7 +427,7 @@ clonetiler_get_transform (
     case TILE_P4M:
     {
         double max = MAX(w, h);
-        NR::Matrix ori (NR::translate ((max + max) * (x/4) + dx,  (max + max) * (y/2) + dy));
+        NR::Matrix ori (NR::translate ((max + max) * pow((x/4), d_per_x_exp) + dx,  (max + max) * pow((y/2), d_per_y_exp) + dy));
         NR::Matrix dia1 (NR::translate (w/2 - h/2, h/2 - w/2));
         NR::Matrix dia2 (NR::translate (-h/2 + w/2, w/2 - h/2));
         if (y % 2 == 0) {
@@ -460,7 +457,7 @@ clonetiler_get_transform (
     case TILE_P4G:
     {
         double max = MAX(w, h);
-        NR::Matrix ori (NR::translate ((max + max) * (x/4) + dx,  (max + max) * y + dy));
+        NR::Matrix ori (NR::translate ((max + max) * pow((x/4), d_per_x_exp) + dx,  (max + max) * pow(y, d_per_y_exp) + dy));
         NR::Matrix dia1 (NR::translate (w/2 + h/2, h/2 - w/2));
         NR::Matrix dia2 (NR::translate (-h/2 + w/2, w/2 + h/2));
         if (((x/4) + y) % 2 == 0) {
@@ -504,7 +501,7 @@ clonetiler_get_transform (
             dia1 = NR::Matrix (NR::translate (h/2 * cos30, -(h/2 * sin30)));
             dia2 = dia1 * NR::Matrix (NR::translate (0, h/2));
         }
-        NR::Matrix ori (NR::translate (width * (2*(x/3) + y%2) + dx,  (height/2) * y + dy));
+        NR::Matrix ori (NR::translate (width * pow((2*(x/3) + y%2), d_per_x_exp) + dx,  (height/2) * pow(y, d_per_y_exp) + dy));
         if (x % 3 == 0) {
             return d_s_r * ori;
         } else if (x % 3 == 1) {
@@ -523,13 +520,13 @@ clonetiler_get_transform (
         NR::Matrix dia3;
         NR::Matrix dia4;
         if (w > h) {
-            ori = NR::Matrix(NR::translate (w * (x/6) + w/2 * (y%2) + dx,  (w * cos30) * y + dy));
+            ori = NR::Matrix(NR::translate (w * pow((x/6) + 1/2 * (y%2), d_per_x_exp) + dx,  (w * cos30) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (0, h/2) * NR::translate (w/2, 0) * NR::translate (w/2 * cos60, -w/2 * sin60) * NR::translate (-h/2 * cos30, -h/2 * sin30) );
             dia2 = dia1 * NR::Matrix (NR::translate (h * cos30, h * sin30));
             dia3 = dia2 * NR::Matrix (NR::translate (0, 2 * (w/2 * sin60 - h/2 * sin30)));
             dia4 = dia3 * NR::Matrix (NR::translate (-h * cos30, h * sin30));
         } else {
-            ori  = NR::Matrix (NR::translate (2*h * cos30  * (x/6 + 0.5*(y%2)) + dx,  (2*h - h * sin30) * y + dy));
+            ori  = NR::Matrix (NR::translate (2*h * cos30  * pow((x/6 + 0.5*(y%2)), d_per_x_exp) + dx,  (2*h - h * sin30) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (0, -h/2) * NR::translate (h/2 * cos30, h/2 * sin30));
             dia2 = dia1 * NR::Matrix (NR::translate (h * cos30, h * sin30));
             dia3 = dia2 * NR::Matrix (NR::translate (0, h/2));
@@ -574,7 +571,7 @@ clonetiler_get_transform (
             dia3 = dia2 * NR::Matrix (NR::translate (0, h/2));
             dia4 = dia3 * NR::Matrix (NR::translate (-h * cos30, h * sin30));
         }
-        NR::Matrix ori (NR::translate (width * (2*(x/6) + y%2) + dx,  (height/2) * y + dy));
+        NR::Matrix ori (NR::translate (width * pow((2*(x/6) + y%2), d_per_x_exp) + dx,  (height/2) * pow(y, d_per_y_exp) + dy));
         if (x % 6 == 0) {
             return d_s_r * ori;
         } else if (x % 6 == 1) {
@@ -600,14 +597,14 @@ clonetiler_get_transform (
         NR::Matrix dia4;
         NR::Matrix dia5;
         if (w > h) {
-            ori = NR::Matrix(NR::translate (2*w * (x/6) + w * (y%2) + dx,  (2*w * sin60) * y + dy));
+            ori = NR::Matrix(NR::translate (w * pow((2*(x/6) + (y%2)), d_per_x_exp) + dx,  (2*w * sin60) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (w/2 * cos60, -w/2 * sin60));
             dia2 = dia1 * NR::Matrix (NR::translate (w/2, 0));
             dia3 = dia2 * NR::Matrix (NR::translate (w/2 * cos60, w/2 * sin60));
             dia4 = dia3 * NR::Matrix (NR::translate (-w/2 * cos60, w/2 * sin60));
             dia5 = dia4 * NR::Matrix (NR::translate (-w/2, 0));
         } else {
-            ori = NR::Matrix(NR::translate (2*h * cos30 * (x/6 + 0.5*(y%2)) + dx,  (h + h * sin30) * y + dy));
+            ori = NR::Matrix(NR::translate (2*h * cos30 * pow((x/6 + 0.5*(y%2)), d_per_x_exp) + dx,  (h + h * sin30) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (-w/2, -h/2) * NR::translate (h/2 * cos30, -h/2 * sin30) * NR::translate (w/2 * cos60, w/2 * sin60));
             dia2 = dia1 * NR::Matrix (NR::translate (-w/2 * cos60, -w/2 * sin60) * NR::translate (h/2 * cos30, -h/2 * sin30) * NR::translate (h/2 * cos30, h/2 * sin30) * NR::translate (-w/2 * cos60, w/2 * sin60));
             dia3 = dia2 * NR::Matrix (NR::translate (w/2 * cos60, -w/2 * sin60) * NR::translate (h/2 * cos30, h/2 * sin30) * NR::translate (-w/2, h/2));
@@ -636,7 +633,7 @@ clonetiler_get_transform (
         NR::Matrix ori;
         NR::Matrix dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10;
         if (w > h) {
-            ori = NR::Matrix(NR::translate (2*w * (x/12) + w * (y%2) + dx,  (2*w * sin60) * y + dy));
+            ori = NR::Matrix(NR::translate (w * pow((2*(x/12) + (y%2)), d_per_x_exp) + dx,  (2*w * sin60) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (w/2, h/2) * NR::translate (-w/2 * cos60, -w/2 * sin60) * NR::translate (-h/2 * cos30, h/2 * sin30));
             dia2 = dia1 * NR::Matrix (NR::translate (h * cos30, -h * sin30));
             dia3 = dia2 * NR::Matrix (NR::translate (-h/2 * cos30, h/2 * sin30) * NR::translate (w * cos60, 0) * NR::translate (-h/2 * cos30, -h/2 * sin30));
@@ -648,7 +645,7 @@ clonetiler_get_transform (
             dia9 = dia6 * dia3.inverse();
             dia10 = dia6 * dia4.inverse();
         } else {
-            ori = NR::Matrix(NR::translate (4*h * cos30 * (x/12 + 0.5*(y%2)) + dx,  (2*h  + 2*h * sin30) * y + dy));
+            ori = NR::Matrix(NR::translate (4*h * cos30 * pow((x/12 + 0.5*(y%2)), d_per_x_exp) + dx,  (2*h  + 2*h * sin30) * pow(y, d_per_y_exp) + dy));
             dia1 = NR::Matrix (NR::translate (-w/2, -h/2) * NR::translate (h/2 * cos30, -h/2 * sin30) * NR::translate (w/2 * cos60, w/2 * sin60));
             dia2 = dia1 * NR::Matrix (NR::translate (h * cos30, -h * sin30));
             dia3 = dia2 * NR::Matrix (NR::translate (-w/2 * cos60, -w/2 * sin60) * NR::translate (h * cos30, 0) * NR::translate (-w/2 * cos60, w/2 * sin60));
@@ -798,7 +795,7 @@ clonetiler_trace_pick (NR::Rect box)
     nr_pixblock_setup_extern( &pb, NR_PIXBLOCK_MODE_R8G8B8A8N,
                               ibox.x0, ibox.y0, ibox.x1, ibox.y1,
                               px, 4 * width, FALSE, FALSE );
-    nr_arena_item_invoke_render( trace_root, &ibox, &pb,
+    nr_arena_item_invoke_render(NULL, trace_root, &ibox, &pb,
                                  NR_ARENA_ITEM_RENDER_NO_CACHE );
 
     double R = 0, G = 0, B = 0, A = 0;
@@ -1067,37 +1064,58 @@ clonetiler_apply (GtkWidget *widget, void *)
         clonetiler_trace_setup (sp_desktop_document(desktop), 1.0, SP_ITEM (obj));
     }
 
-    NR::Point c;
+    NR::Point center;
     double w;
     double h;
+    double x0;
+    double y0;
 
     if (keepbbox &&
         obj_repr->attribute("inkscape:tile-w") &&
         obj_repr->attribute("inkscape:tile-h") &&
+        obj_repr->attribute("inkscape:tile-x0") &&
+        obj_repr->attribute("inkscape:tile-y0") &&
         obj_repr->attribute("inkscape:tile-cx") &&
         obj_repr->attribute("inkscape:tile-cy")) {
 
         double cx = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-cx", 0);
         double cy = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-cy", 0);
-
-        c = NR::Point (cx, cy);
+        center = NR::Point (cx, cy);
 
         w = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-w", 0);
         h = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-h", 0);
+        x0 = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-x0", 0);
+        y0 = sp_repr_get_double_attribute (obj_repr, "inkscape:tile-y0", 0);
     } else {
-        NR::Rect const r = SP_ITEM(obj)->invokeBbox(sp_item_i2doc_affine(SP_ITEM(obj)));
-        c = r.midpoint();
-        w = r.dimensions()[NR::X];
-        h = r.dimensions()[NR::Y];
-
-        sp_repr_set_svg_double(obj_repr, "inkscape:tile-w", w);
-        sp_repr_set_svg_double(obj_repr, "inkscape:tile-h", h);
-        sp_repr_set_svg_double(obj_repr, "inkscape:tile-cx", c[NR::X]);
-        sp_repr_set_svg_double(obj_repr, "inkscape:tile-cy", c[NR::Y]);
+        NR::Maybe<NR::Rect> r = SP_ITEM(obj)->getBounds(sp_item_i2doc_affine(SP_ITEM(obj)),
+                                                        SPItem::GEOMETRIC_BBOX);
+        /* impl: Use of GEOMETRIC_BBOX is so that the stroke of rectangles will be shared
+         * (overlapped) rather than effectively doubled in width.
+         *
+         * (If you wish to change this, then please consider discussing at bug #1722238.) */
+
+        if (r) {
+            w = r->dimensions()[NR::X];
+            h = r->dimensions()[NR::Y];
+            x0 = r->min()[NR::X];
+            y0 = r->min()[NR::Y];
+            center = desktop->dt2doc(SP_ITEM(obj)->getCenter());
+
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-cx", center[NR::X]);
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-cy", center[NR::Y]);
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-w", w);
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-h", h);
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-x0", x0);
+            sp_repr_set_svg_double(obj_repr, "inkscape:tile-y0", y0);
+        } else {
+            center = NR::Point(0, 0);
+            w = h = 0;
+            x0 = y0 = 0;
+        }
     }
 
     NR::Point cur = NR::Point (0, 0);
-    NR::Rect bbox_original = NR::Rect (NR::Point (c[NR::X] - w/2, c[NR::Y] - h/2), NR::Point (c[NR::X] + w/2, c[NR::Y] + h/2));
+    NR::Rect bbox_original = NR::Rect (NR::Point (x0, y0), NR::Point (x0 + w, y0 + h));
     double perimeter_original = (w + h)/4;
 
     for (int x = 0;
@@ -1114,14 +1132,14 @@ clonetiler_apply (GtkWidget *widget, void *)
             // Note: We create a clone at 0,0 too, right over the original, in case our clones are colored
 
             // Get transform from symmetry, shift, scale, rotation
-            NR::Matrix t = clonetiler_get_transform (type, x, y, c[NR::X], c[NR::Y], w, h,
+            NR::Matrix t = clonetiler_get_transform (type, x, y, center[NR::X], center[NR::Y], w, h,
                                                      d_x_per_x, d_y_per_x, d_x_per_y, d_y_per_y, alternate_x, alternate_y, rand_x, rand_y,
                                                      d_per_x_exp, d_per_y_exp,
                                                      d_rot_per_x, d_rot_per_y, alternate_rotx, alternate_roty, rand_rot,
                                                      d_scalex_per_x, d_scaley_per_x, d_scalex_per_y, d_scaley_per_y,
                                                      alternate_scalex, alternate_scaley, rand_scalex, rand_scaley);
 
-            cur = c * t - c;
+            cur = center * t - center;
             if (fillrect) {
                 if ((cur[NR::X] > fillwidth) || (cur[NR::Y] > fillheight)) { // off limits
                     continue;
@@ -1149,7 +1167,7 @@ clonetiler_apply (GtkWidget *widget, void *)
 
                 float rgb[3];
                 sp_color_hsl_to_rgb_floatv (rgb, hsl[0], hsl[1], hsl[2]);
-                sp_svg_write_color(color_string, 32, SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1.0));
+                sp_svg_write_color(color_string, sizeof(color_string), SP_RGBA32_F_COMPOSE(rgb[0], rgb[1], rgb[2], 1.0));
             }
 
             // Blur
@@ -1254,13 +1272,13 @@ clonetiler_apply (GtkWidget *widget, void *)
                     }
                 }
                 if (pick_to_size) {
-                    t = NR::translate(-c[NR::X], -c[NR::Y]) * NR::scale (val, val) * NR::translate(c[NR::X], c[NR::Y]) * t;
+                    t = NR::translate(-center[NR::X], -center[NR::Y]) * NR::scale (val, val) * NR::translate(center[NR::X], center[NR::Y]) * t;
                 }
                 if (pick_to_opacity) {
                     opacity *= val;
                 }
                 if (pick_to_color) {
-                    sp_svg_write_color(color_string, 32, rgba);
+                    sp_svg_write_color(color_string, sizeof(color_string), rgba);
                 }
             }
 
@@ -1286,12 +1304,9 @@ clonetiler_apply (GtkWidget *widget, void *)
                 center_set = true;
             }
 
-            gchar affinestr[80];
-            if (sp_svg_transform_write(affinestr, 79, t)) {
-                clone->setAttribute("transform", affinestr);
-            } else {
-                clone->setAttribute("transform", NULL);
-            }
+            gchar *affinestr=sp_svg_transform_write(t);
+            clone->setAttribute("transform", affinestr);
+            g_free(affinestr);
 
             if (opacity < 1.0) {
                 sp_repr_set_css_double(clone, "opacity", opacity);