X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdialogs%2Fclonetiler.cpp;h=f6d3b030958859530d3f96b19157a2ab91df44fd;hb=6d7d846dbf27d17b82110d99015a85cff809a789;hp=2bed7b3993d0fa53695018d41e6894bdc9d207d7;hpb=2c020c360b11fbe8c3709322558ddc592e5e9ca3;p=inkscape.git diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp index 2bed7b399..f6d3b0309 100644 --- a/src/dialogs/clonetiler.cpp +++ b/src/dialogs/clonetiler.cpp @@ -4,9 +4,10 @@ * Clone tiling dialog * * Authors: - * bulia byak + * bulia byak + * Johan Engelen * - * Copyright (C) 2004-2005 Authors + * Copyright (C) 2004-2006 Authors * Released under GNU GPL */ @@ -60,6 +61,8 @@ #include "../sp-filter.h" #include "../filter-chemistry.h" +#define MIN_ONSCREEN_DISTANCE 50 + static GtkWidget *dlg = NULL; static win_data wd; @@ -146,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; @@ -290,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: @@ -405,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) { @@ -427,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) { @@ -457,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) { @@ -501,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) { @@ -520,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)); @@ -571,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) { @@ -597,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)); @@ -633,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)); @@ -645,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)); @@ -783,6 +783,11 @@ clonetiler_trace_pick (NR::Rect box) /* Set up pixblock */ guchar *px = g_new(guchar, 4 * width * height); + + if (px == NULL) { + return 0; // buffer is too big or too small, cannot pick, so return 0 + } + memset(px, 0x00, 4 * width * height); /* Render */ @@ -790,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; @@ -1042,8 +1047,8 @@ clonetiler_apply (GtkWidget *widget, void *) int ymax = prefs_get_int_attribute (prefs_path, "ymax", 2); int fillrect = prefs_get_int_attribute (prefs_path, "fillrect", 0); - double fillwidth = prefs_get_double_attribute_limited (prefs_path, "fillwidth", 50, 0, 6000); - double fillheight = prefs_get_double_attribute_limited (prefs_path, "fillheight", 50, 0, 6000); + double fillwidth = prefs_get_double_attribute_limited (prefs_path, "fillwidth", 50, 0, 1e6); + double fillheight = prefs_get_double_attribute_limited (prefs_path, "fillheight", 50, 0, 1e6); int dotrace = prefs_get_int_attribute (prefs_path, "dotrace", 0); int pick = prefs_get_int_attribute (prefs_path, "pick", 0); @@ -1059,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 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; @@ -1106,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; @@ -1141,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 @@ -1246,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); } } @@ -1265,7 +1291,7 @@ clonetiler_apply (GtkWidget *widget, void *) } // Create the clone - Inkscape::XML::Node *clone = sp_repr_new("svg:use"); + Inkscape::XML::Node *clone = obj_repr->document()->createElement("svg:use"); clone->setAttribute("x", "0"); clone->setAttribute("y", "0"); clone->setAttribute("inkscape:tiled-clone-of", id_href); @@ -1278,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); @@ -1304,7 +1327,7 @@ clonetiler_apply (GtkWidget *widget, void *) // it's hard to figure out exact width/height of the tile without having an object // that we can take bbox of; however here we only need a lower bound so that blur // margins are not too small, and the perimeter should work - SPFilter *constructed = new_filter_gaussian_blur(sp_desktop_document(desktop), radius, t.expansion(), perimeter, perimeter); + SPFilter *constructed = new_filter_gaussian_blur(sp_desktop_document(desktop), radius, t.expansion(), t.expansionX(), t.expansionY(), perimeter, perimeter); sp_style_set_property_url (clone_object, "filter", SP_OBJECT(constructed), false); } @@ -1629,8 +1652,8 @@ clonetiler_dialog (void) dlg = sp_window_new (title, TRUE); if (x == -1000 || y == -1000) { - x = prefs_get_int_attribute (prefs_path, "x", 0); - y = prefs_get_int_attribute (prefs_path, "y", 0); + x = prefs_get_int_attribute (prefs_path, "x", -1000); + y = prefs_get_int_attribute (prefs_path, "y", -1000); } if (w ==0 || h == 0) { @@ -1638,19 +1661,19 @@ clonetiler_dialog (void) h = prefs_get_int_attribute (prefs_path, "h", 0); } - if (x<0) x=0; - if (y<0) y=0; +// if (x<0) x=0; +// if (y<0) y=0; - if (x != 0 || y != 0) { + if (w && h) { + gtk_window_resize ((GtkWindow *) dlg, w, h); + } + if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE))) { gtk_window_move ((GtkWindow *) dlg, x, y); } else { gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER); } - if (w && h) { - gtk_window_resize ((GtkWindow *) dlg, w, h); - } sp_transientize (dlg); wd.win = dlg; @@ -2517,7 +2540,7 @@ clonetiler_dialog (void) { // Width spinbutton - GtkObject *a = gtk_adjustment_new (0.0, -SP_DESKTOP_SCROLL_LIMIT, SP_DESKTOP_SCROLL_LIMIT, 1.0, 10.0, 10.0); + GtkObject *a = gtk_adjustment_new (0.0, -1e6, 1e6, 1.0, 10.0, 10.0); sp_unit_selector_add_adjustment (SP_UNIT_SELECTOR (u), GTK_ADJUSTMENT (a)); double value = prefs_get_double_attribute (prefs_path, "fillwidth", 50); @@ -2541,7 +2564,7 @@ clonetiler_dialog (void) { // Height spinbutton - GtkObject *a = gtk_adjustment_new (0.0, -SP_DESKTOP_SCROLL_LIMIT, SP_DESKTOP_SCROLL_LIMIT, 1.0, 10.0, 10.0); + GtkObject *a = gtk_adjustment_new (0.0, -1e6, 1e6, 1.0, 10.0, 10.0); sp_unit_selector_add_adjustment (SP_UNIT_SELECTOR (u), GTK_ADJUSTMENT (a)); double value = prefs_get_double_attribute (prefs_path, "fillheight", 50);