void finalize_movesel(void) { GList *list, *link; if (ui.selection->items != NULL) { prepare_new_undo(); undo->type = ITEM_MOVESEL; undo->itemlist = g_list_copy(ui.selection->items); undo->val_x = ui.selection->last_x - ui.selection->anchor_x; undo->val_y = ui.selection->last_y - ui.selection->anchor_y; undo->layer = ui.selection->layer; undo->layer2 = ui.selection->move_layer; undo->auxlist = NULL; // build auxlist = pointers to Item's just before ours (for depths) for (list = ui.selection->items; list!=NULL; list = list->next) { link = g_list_find(ui.selection->layer->items, list->data); if (link!=NULL) link = link->prev; undo->auxlist = g_list_append(undo->auxlist, ((link!=NULL) ? link->data : NULL)); } ui.selection->layer = ui.selection->move_layer; move_journal_items_by(undo->itemlist, undo->val_x, undo->val_y, undo->layer, undo->layer2, (undo->layer == undo->layer2)?undo->auxlist:NULL); } if (ui.selection->move_pageno!=ui.selection->orig_pageno) do_switch_page(ui.selection->move_pageno, FALSE, FALSE); if (ui.cur_item_type == ITEM_MOVESEL_VERT) reset_selection(); else { ui.selection->bbox.left += undo->val_x; ui.selection->bbox.right += undo->val_x; ui.selection->bbox.top += undo->val_y; ui.selection->bbox.bottom += undo->val_y; make_dashed(ui.selection->canvas_item); /* update selection box object's offset to be trivial, and its internal coordinates to agree with those of the bbox; need this since resize operations will modify the box by setting its coordinates directly */ gnome_canvas_item_affine_absolute(ui.selection->canvas_item, NULL); gnome_canvas_item_set(ui.selection->canvas_item, "x1", ui.selection->bbox.left, "x2", ui.selection->bbox.right, "y1", ui.selection->bbox.top, "y2", ui.selection->bbox.bottom, NULL); } ui.cur_item_type = ITEM_NONE; update_cursor(); }
static int affine( Tcl_Interp *interp, int objc, Tcl_Obj * const objv[], CanvasParams *param, GPtrArray *items, int type ) { GnoclOption options[] = { { "-absolute", GNOCL_BOOL, NULL }, { "-reverseOrder", GNOCL_BOOL, NULL }, { NULL } }; static const int absoluteIdx = 0; static const int reverseOrderIdx = 1; guint m; int noCoords; int absolute = 0; int reverse = 0; if( objc < 4 ) { /* canvas (affine|move|scale|rotate) tag-or-id coords ?options ? */ Tcl_WrongNumArgs( interp, 3, objv, "list-of-coordinates ?option val ...?" ); return TCL_ERROR; } if( gnoclParseOptions( interp, objc - 3, objv + 3, options ) != TCL_OK ) return TCL_ERROR; if( options[absoluteIdx].status == GNOCL_STATUS_CHANGED ) absolute = options[absoluteIdx].val.b; if( options[reverseOrderIdx].status == GNOCL_STATUS_CHANGED ) reverse = options[reverseOrderIdx].val.b; gnoclClearOptions( options ); if( absolute && reverse ) { Tcl_SetResult( interp, "Options \"-reverseOrder\" is only valid " "for relative transformations.", TCL_STATIC ); return TCL_ERROR; } if( Tcl_ListObjLength( interp, objv[3], &noCoords ) != TCL_OK ) return TCL_ERROR; for( m = 0; m < items->len; ++m ) { Gnocl_CanvasItemInfo *info = GET_INFO( items, m ); int k; double af[6]; Tcl_Obj *tp; for( k = 0; k < 6 && k < noCoords; ++k ) { if( Tcl_ListObjIndex( interp, objv[3], k, &tp ) != TCL_OK ) return TCL_ERROR; if( Tcl_GetDoubleFromObj( interp, tp, &af[k] ) != TCL_OK ) return TCL_ERROR; } /* x' = af[0] * x + af[2] * y + af[4]; y' = af[1] * x + af[3] * y + af[5]; */ switch( type ) { case Affine: if( noCoords != 6 ) { Tcl_SetResult( interp, "size of list-of-coordinates must be 6", TCL_STATIC ); return TCL_ERROR; } break; case Move: if( noCoords != 2 ) { Tcl_SetResult( interp, "size of list-of-coordinates must " "be 2 (delta-x and delta-y)", TCL_STATIC ); return TCL_ERROR; } af[4] = af[0]; af[5] = af[1]; af[0] = 1.; af[2] = 0.; af[1] = 0.; af[3] = 1.; break; case Scale: if( noCoords != 3 && noCoords != 4 ) { Tcl_SetResult( interp, "size of list-of-coordinates must " "be 3 or 4 (center, x-scale and y-scale)", TCL_STATIC ); return TCL_ERROR; } else { double x = af[0]; double y = af[1]; double scalex = af[2]; double scaley = (noCoords == 4) ? af[3] : scalex; af[0] = scalex; af[2] = .0; af[4] = x * (1. - scalex); af[1] = .0; af[3] = scaley; af[5] = y * (1. - scaley); } break; case Rotate: /* there seems to be some problems with the canvas without antialiasing and rotating (bizarre drawings) */ if( noCoords != 3 ) { Tcl_SetResult( interp, "size of list-of-coordinates must " "be 3 (center and angle)", TCL_STATIC ); return TCL_ERROR; } else { double x = af[0]; double y = af[1]; double w = af[2]; const double cw = cos( w ); const double sw = sin( w ); af[0] = cw; af[2] = -sw; af[4] = x - x * cw + y * sw; af[1] = sw; af[3] = cw; af[5] = y - x * sw - y * cw; } break; } /* printf( "\nitem: %p absolute: %d\n", info->item, absolute ); printf( "before:\n" ); { int k; double af[6]; gnome_canvas_item_i2c_affine( info->item, af ); for( k = 0; k < 6; k += 2 ) printf( "%d: %f ", k, af[k] ); printf( "\n" ); for( k = 1; k < 6; k += 2 ) printf( "%d: %f ", k, af[k] ); printf( "\n" ); } printf( "affine:\n" ); for( k = 0; k < 6; k += 2 ) printf( "%d: %f ", k, af[k] ); printf( "\n" ); for( k = 1; k < 6; k += 2 ) printf( "%d: %f ", k, af[k] ); printf( "\n" ); */ if( absolute ) gnome_canvas_item_affine_absolute( info->item, af ); else { /* Well, *I* think this is a bug in gnome: affine_relative should not be the reverse of what one would expect. Or do I have wrong expectations? */ if( reverse ) gnome_canvas_item_affine_relative( info->item, af ); else { double bf[6]; gnome_canvas_item_i2w_affine( info->item, bf ); gnome_canvas_item_affine_absolute( info->item, af ); gnome_canvas_item_affine_relative( info->item, bf ); } } } return TCL_OK; }