flip_tool.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /* The GIMP -- an image manipulation program
  2. * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "config.h"
  19. #include <stdlib.h>
  20. #include <gtk/gtk.h>
  21. #include <gdk/gdkkeysyms.h>
  22. #include "apptypes.h"
  23. #include "appenv.h"
  24. #include "cursorutil.h"
  25. #include "drawable.h"
  26. #include "flip_tool.h"
  27. #include "gdisplay.h"
  28. #include "gimage_mask.h"
  29. #include "gimpui.h"
  30. #include "path_transform.h"
  31. #include "tile_manager_pvt.h" /* ick. */
  32. #include "libgimp/gimpintl.h"
  33. #define FLIP_INFO 0
  34. /* the flip structures */
  35. typedef struct _FlipOptions FlipOptions;
  36. struct _FlipOptions
  37. {
  38. ToolOptions tool_options;
  39. InternalOrientationType type;
  40. InternalOrientationType type_d;
  41. GtkWidget *type_w[2];
  42. };
  43. static FlipOptions *flip_options = NULL;
  44. /* functions */
  45. /* FIXME: Lame - 1 hacks abound since the code assumes certain values for
  46. * the ORIENTATION_FOO constants.
  47. */
  48. static void
  49. flip_options_reset (void)
  50. {
  51. FlipOptions *options = flip_options;
  52. gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (options->type_w[options->type_d - 1]), TRUE);
  53. }
  54. static FlipOptions *
  55. flip_options_new (void)
  56. {
  57. FlipOptions *options;
  58. GtkWidget *vbox;
  59. GtkWidget *frame;
  60. /* the new flip tool options structure */
  61. options = g_new (FlipOptions, 1);
  62. tool_options_init ((ToolOptions *) options,
  63. _("Flip Tool"),
  64. flip_options_reset);
  65. options->type = options->type_d = ORIENTATION_HORIZONTAL;
  66. /* the main vbox */
  67. vbox = options->tool_options.main_vbox;
  68. /* tool toggle */
  69. frame =
  70. gimp_radio_group_new2 (TRUE, _("Tool Toggle"),
  71. gimp_radio_button_update,
  72. &options->type, (gpointer) options->type,
  73. _("Horizontal"), (gpointer) ORIENTATION_HORIZONTAL,
  74. &options->type_w[0],
  75. _("Vertical"), (gpointer) ORIENTATION_VERTICAL,
  76. &options->type_w[1],
  77. NULL);
  78. gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
  79. gtk_widget_show (frame);
  80. return options;
  81. }
  82. static void
  83. flip_modifier_key_func (Tool *tool,
  84. GdkEventKey *kevent,
  85. gpointer gdisp_ptr)
  86. {
  87. switch (kevent->keyval)
  88. {
  89. case GDK_Alt_L: case GDK_Alt_R:
  90. break;
  91. case GDK_Shift_L: case GDK_Shift_R:
  92. break;
  93. case GDK_Control_L: case GDK_Control_R:
  94. if (flip_options->type == ORIENTATION_HORIZONTAL)
  95. {
  96. gtk_toggle_button_set_active
  97. (GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_VERTICAL - 1]), TRUE);
  98. }
  99. else
  100. {
  101. gtk_toggle_button_set_active
  102. (GTK_TOGGLE_BUTTON (flip_options->type_w[ORIENTATION_HORIZONTAL - 1]), TRUE);
  103. }
  104. break;
  105. }
  106. }
  107. TileManager *
  108. flip_tool_transform (Tool *tool,
  109. gpointer gdisp_ptr,
  110. TransformState state)
  111. {
  112. TransformCore *transform_core;
  113. GDisplay *gdisp;
  114. transform_core = (TransformCore *) tool->private;
  115. gdisp = (GDisplay *) gdisp_ptr;
  116. switch (state)
  117. {
  118. case INIT:
  119. transform_info = NULL;
  120. break;
  121. case MOTION:
  122. break;
  123. case RECALC:
  124. break;
  125. case FINISH:
  126. /* transform_core->trans_info[FLIP] *= -1.0;*/
  127. return flip_tool_flip (gdisp->gimage,
  128. gimage_active_drawable (gdisp->gimage),
  129. transform_core->original,
  130. (int) transform_core->trans_info[FLIP_INFO],
  131. flip_options->type);
  132. break;
  133. }
  134. return NULL;
  135. }
  136. static void
  137. flip_cursor_update (Tool *tool,
  138. GdkEventMotion *mevent,
  139. gpointer gdisp_ptr)
  140. {
  141. GDisplay *gdisp;
  142. GimpDrawable *drawable;
  143. GdkCursorType ctype = GIMP_BAD_CURSOR;
  144. gdisp = (GDisplay *) gdisp_ptr;
  145. if ((drawable = gimage_active_drawable (gdisp->gimage)))
  146. {
  147. gint x, y;
  148. gint off_x, off_y;
  149. drawable_offsets (drawable, &off_x, &off_y);
  150. gdisplay_untransform_coords (gdisp,
  151. (double) mevent->x, (double) mevent->y,
  152. &x, &y, TRUE, FALSE);
  153. if (x >= off_x && y >= off_y &&
  154. x < (off_x + drawable_width (drawable)) &&
  155. y < (off_y + drawable_height (drawable)))
  156. {
  157. /* Is there a selected region? If so, is cursor inside? */
  158. if (gimage_mask_is_empty (gdisp->gimage) ||
  159. gimage_mask_value (gdisp->gimage, x, y))
  160. {
  161. if (flip_options->type == ORIENTATION_HORIZONTAL)
  162. ctype = GDK_SB_H_DOUBLE_ARROW;
  163. else
  164. ctype = GDK_SB_V_DOUBLE_ARROW;
  165. }
  166. }
  167. }
  168. gdisplay_install_tool_cursor (gdisp, ctype,
  169. FLIP,
  170. CURSOR_MODIFIER_NONE,
  171. ctype == GDK_SB_V_DOUBLE_ARROW);
  172. }
  173. Tool *
  174. tools_new_flip (void)
  175. {
  176. Tool *tool;
  177. TransformCore *private;
  178. /* The tool options */
  179. if (! flip_options)
  180. {
  181. flip_options = flip_options_new ();
  182. tools_register (FLIP, (ToolOptions *) flip_options);
  183. }
  184. tool = transform_core_new (FLIP, FALSE);
  185. private = tool->private;
  186. private->trans_func = flip_tool_transform;
  187. private->trans_info[FLIP_INFO] = -1.0;
  188. tool->modifier_key_func = flip_modifier_key_func;
  189. tool->cursor_update_func = flip_cursor_update;
  190. return tool;
  191. }
  192. void
  193. tools_free_flip_tool (Tool *tool)
  194. {
  195. transform_core_free (tool);
  196. }
  197. TileManager *
  198. flip_tool_flip (GimpImage *gimage,
  199. GimpDrawable *drawable,
  200. TileManager *orig,
  201. gint flip,
  202. InternalOrientationType type)
  203. {
  204. TileManager *new;
  205. PixelRegion srcPR, destPR;
  206. gint i;
  207. if (!orig)
  208. return NULL;
  209. if (flip > 0)
  210. {
  211. new = tile_manager_new (orig->width, orig->height, orig->bpp);
  212. pixel_region_init (&srcPR, orig, 0, 0, orig->width, orig->height, FALSE);
  213. pixel_region_init (&destPR, new, 0, 0, orig->width, orig->height, TRUE);
  214. copy_region (&srcPR, &destPR);
  215. new->x = orig->x;
  216. new->y = orig->y;
  217. }
  218. else
  219. {
  220. new = tile_manager_new (orig->width, orig->height, orig->bpp);
  221. new->x = orig->x;
  222. new->y = orig->y;
  223. if (type == ORIENTATION_HORIZONTAL)
  224. for (i = 0; i < orig->width; i++)
  225. {
  226. pixel_region_init (&srcPR, orig, i, 0, 1, orig->height, FALSE);
  227. pixel_region_init (&destPR, new,
  228. (orig->width - i - 1), 0, 1, orig->height, TRUE);
  229. copy_region (&srcPR, &destPR);
  230. }
  231. else
  232. for (i = 0; i < orig->height; i++)
  233. {
  234. pixel_region_init (&srcPR, orig, 0, i, orig->width, 1, FALSE);
  235. pixel_region_init (&destPR, new,
  236. 0, (orig->height - i - 1), orig->width, 1, TRUE);
  237. copy_region (&srcPR, &destPR);
  238. }
  239. /* flip locked paths */
  240. /* Note that the undo structures etc are setup before we enter this
  241. * function.
  242. */
  243. if (type == ORIENTATION_HORIZONTAL)
  244. path_transform_flip_horz (gimage);
  245. else
  246. path_transform_flip_vert (gimage);
  247. }
  248. return new;
  249. }