OK, here's my first cut at a PDB general 2d transform. It provides
rotation, scaling (with separate x and y factors), and translation.
General enough to be useful, but still easier to use than a full
perspective operation.

Sorry, not in patch format; but it all goes in tool_cmds.c,
declaration and registration near the top, everything else pasted
at the end of the file.

-- 
David Hodson  --  [EMAIL PROTECTED]  --  this night wounds time


/*
--Added declaration
*/

static ProcRecord transform_2d_proc;


/*
--Added register function call
*/

void
register_tools_procs (void)
{
  ...
  
  procedural_db_register (&transform_2d_proc);
  
  ...
}




/*
--Added new invoker
--zoom and rotate about point (source_x, source_y)
--then move (source_x, source_y) to (dest_x, dest_y)
*/

static Argument *
transform_2d_invoker (Argument *args)
{
  gboolean success = TRUE;
  Argument *return_args;
  GimpDrawable *drawable;
  gboolean interpolation;
  gdouble source_x, source_y;
  gdouble angle;
  gdouble scale_x, scale_y;
  gdouble dest_x, dest_y;
  GimpImage *gimage;
  TileManager *float_tiles, *new_tiles;
  Layer* layer;
  gboolean new_layer;
  GimpMatrix matrix;

  drawable = gimp_drawable_get_ID (args[0].value.pdb_int);
  if (drawable == NULL)
    success = FALSE;

  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);

      interpolation = args[1].value.pdb_int ? TRUE : FALSE;

      /* transform centre */
      source_x = args[2].value.pdb_float;
      source_y = args[3].value.pdb_float;

      /* transform scale */
      scale_x = args[4].value.pdb_float;
      scale_y = args[5].value.pdb_float;

      /* angle (radians) */
      angle = args[6].value.pdb_float;

      /* transform destination */
      dest_x = args[7].value.pdb_float;
      dest_y = args[8].value.pdb_float;

      /* Assemble the transformation matrix */
      gimp_matrix_identity  (matrix);
      gimp_matrix_translate (matrix, -source_x, -source_y);
      gimp_matrix_scale     (matrix, scale_x, scale_y);
      gimp_matrix_rotate    (matrix, angle);
      gimp_matrix_translate (matrix, dest_x, dest_y);
    
      /* Transform the buffer */
      new_tiles = transform_core_do (gimage, drawable, float_tiles,
                                      interpolation, matrix, NULL, NULL);
    
      /* Free the cut/copied buffer */
      tile_manager_destroy (float_tiles);
    
      if (new_tiles)
        {
          layer = transform_core_paste (gimage, drawable, new_tiles, new_layer);
          success = layer != NULL;
        }
      else
        success = FALSE;
    
      /* Push the undo group end */
      undo_push_group_end (gimage);
    }

  return_args = procedural_db_return_args (&transform_2d_proc, success);

  if (success)
    return_args[1].value.pdb_int = drawable_ID (GIMP_DRAWABLE (drawable));

  return return_args;
}




/*
--It gets its own input arguments
*/

static ProcArg transform_2d_inargs[] =
{
  {
    PDB_DRAWABLE,
    "drawable",
    "The affected drawable"
  },
  {
    PDB_INT32,
    "interpolation",
    "Whether to use interpolation"
  },
  {
    PDB_FLOAT,
    "source_x",
    "X coordinate of the transform centre"
  },
  {
    PDB_FLOAT,
    "source_y",
    "Y coordinate of the transform centre"
  },
  {
    PDB_FLOAT,
    "x_scale",
    "Amount to scale in x"
  },
  {
    PDB_FLOAT,
    "y_scale",
    "Amount to scale in y"
  },
  {
    PDB_FLOAT,
    "angle",
    "The angle of rotation (radians)"
  },
  {
    PDB_FLOAT,
    "dest_x",
    "X coordinate of where the centre goes"
  },
  {
    PDB_FLOAT,
    "dest_y",
    "Y coordinate of where the centre goes"
  }
};


static ProcArg transform_2d_outargs[] =
{
  {
    PDB_DRAWABLE,
    "drawable",
    "The transformed drawable"
  }
};



/*
--Added the procedure info
*/

static ProcRecord transform_2d_proc =
{
  "gimp_transform_2d",
  "Transform the specified drawable in 2d",
  "This tool transforms 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 transformed. The 
interpolation
parameter can be set to TRUE to indicate that either linear or cubic interpolation
should be used to smooth the resulting drawable. The transformation is done by scaling
the image by the x and y scale factors about the point (source_x, source_y), then
rotating around the same point, then translating that point to the new position
(dest_x, dest_y). 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 transformed drawable.",
  "Spencer Kimball & Peter Mattis, David Hodson",
  "Spencer Kimball & Peter Mattis, David Hodson",
  "1995-2000",
  PDB_INTERNAL,
  9,
  transform_2d_inargs,
  1,
  transform_2d_outargs,
  { { transform_2d_invoker } }
};


Reply via email to