The current gimp_rotate procedure does not allow for rotation around an arbitrary point even though its code is quite capable of it. It just selects the center of the image and uses that as the rotation origin. I added a gimp_rotate_around_point procedure and use it in all the scripts I'm writing. With the new procedure, you only need to select the region you wish to rotate (just like the interactive rotate tool in the toolbox). Below I've included the source code additions I made to tools_cmds.c (I don't know how to use diff and patch yet). All I really did was copy the original rotate_invoker and add X and Y center point parameters to it. Obviously, the two procedures could be written to reuse the same invoker code. -Michael /* --Added declaration */ static ProcRecord rotate_around_point_proc; /* --Added register function call */ void register_tools_procs (void) { ... procedural_db_register (&rotate_around_point_proc); ... } /* --Added new invoker --It just gets its center point from the arguments and sets --the return arguments to reference the correct PDB proc */ static Argument * rotate_around_point_invoker (Argument *args) { gboolean success = TRUE; Argument *return_args; GimpDrawable *drawable; gboolean interpolation; gdouble angle; GimpImage *gimage; TileManager *float_tiles, *new_tiles; gboolean new_layer; double cx, cy; GimpMatrix3 matrix; drawable = gimp_drawable_get_ID (args[0].value.pdb_int); if (drawable == NULL) success = FALSE; interpolation = args[1].value.pdb_int ? TRUE : FALSE; angle = args[2].value.pdb_float; if (success) { gimage = drawable_gimage (GIMP_DRAWABLE (drawable)); /* Start a transform undo group */ undo_push_group_start (gimage, TRANSFORM_CORE_UNDO); /* Cut/Copy from the specified drawable */ float_tiles = transform_core_cut (gimage, drawable, &new_layer); /* get the center from the arguments passed in */ cx = args[3].value.pdb_int; cy = args[4].value.pdb_int; #if 0 cx = float_tiles->x + float_tiles->width / 2.0; cy = float_tiles->y + float_tiles->height / 2.0; #endif /* Assemble the transformation matrix */ gimp_matrix3_identity (matrix); gimp_matrix3_translate (matrix, -cx, -cy); gimp_matrix3_rotate (matrix, angle); gimp_matrix3_translate (matrix, +cx, +cy); /* Rotate the buffer */ new_tiles = rotate_tool_rotate (gimage, drawable, NULL, angle, float_tiles, interpolation, matrix); /* Free the cut/copied buffer */ tile_manager_destroy (float_tiles); if (new_tiles) success = transform_core_paste (gimage, drawable, new_tiles, new_layer); else success = FALSE; /* Push the undo group end */ undo_push_group_end (gimage); } return_args = procedural_db_return_args (&rotate_around_point_proc, success); if (success) return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (drawable)); return return_args; } /* --It gets its own input arguments --Note: I reused the output argments since they are identical. */ static ProcArg rotate_around_point_inargs[] = { { PDB_DRAWABLE, "drawable", "The affected drawable" }, { PDB_INT32, "interpolation", "Whether to use interpolation" }, { PDB_FLOAT, "angle", "The angle of rotation (radians)" }, { PDB_INT32, "x", "the x coordinate of the point" }, { PDB_INT32, "y", "the y coordinate of the point" } }; /* --Added the procedure info */ static ProcRecord rotate_around_point_proc = { "gimp_rotate_around_point", "Rotate the specified drawable about a point through the specified angle.", "This tool rotates the specified drawable if no selection exists. If a selection exists, the portion of the drawable which lies under the selection is cut from the drawable and made into a floating selection which is then rotated by the specified amount. The interpolation parameter can be set to TRUE to indicate that either linear or cubic interpolation should be used to smooth the resulting rotated drawable. The return value is the ID of the rotated drawable. If there was no selection, this will be equal to the drawable ID supplied as input. Otherwise, this will be the newly created and rotated drawable.", "Spencer Kimball & Peter Mattis", "Spencer Kimball & Peter Mattis", "1995-1996", PDB_INTERNAL, 5, rotate_around_point_inargs, 1, rotate_outargs, { { rotate_around_point_invoker } } };