static double gnome_canvas_item_invoke_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { #ifdef HACKISH_AFFINE double i2w[6], w2c[6], i2c[6], c2i[6]; ArtPoint c, i; #endif #ifdef HACKISH_AFFINE gnome_canvas_item_i2w_affine (item, i2w); gnome_canvas_w2c_affine (item->canvas, w2c); art_affine_multiply (i2c, i2w, w2c); art_affine_invert (c2i, i2c); c.x = cx; c.y = cy; art_affine_point (&i, &c, c2i); x = i.x; y = i.y; #endif return (* GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT_GET_CLASS (item))->point) ( item, x, y, cx, cy, actual_item); }
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; }