graphics.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* $XConsortium: graphics.c /main/4 1995/11/02 14:05:07 rswiston $ */
  24. /*********************************************************************
  25. * (c) Copyright 1993, 1994 Hewlett-Packard Company
  26. * (c) Copyright 1993, 1994 International Business Machines Corp.
  27. * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  28. * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
  29. * Novell, Inc.
  30. **********************************************************************/
  31. /******************************************************************************
  32. ** Program: dticon
  33. **
  34. ** Description: X11-based multi-color icon editor
  35. **
  36. ** File: graphics.c, which contains the following subroutines or
  37. ** functions:
  38. ** Flicker_Arc()
  39. ** Circle_Box()
  40. ** Set_HotBox_Coords()
  41. ** Start_HotBox()
  42. ** Do_HotBox()
  43. ** Stop_HotBox()
  44. **
  45. ******************************************************************************
  46. **
  47. ** Copyright Hewlett-Packard Company, 1990, 1991, 1992.
  48. ** All rights are reserved. Copying or reproduction of this program,
  49. ** except for archival purposes, is prohibited without prior written
  50. ** consent of Hewlett-Packard Company.
  51. **
  52. ** Hewlett-Packard makes no representations about the suitibility of this
  53. ** software for any purpose. It is provided "as is" without express or
  54. ** implied warranty.
  55. **
  56. ******************************************************************************/
  57. #include <stdlib.h>
  58. #include <math.h>
  59. #include <Xm/Xm.h>
  60. #include "externals.h"
  61. #include "utils.h"
  62. #include "process.h"
  63. extern GC scratch_gc;
  64. extern Widget editMenu_cut_pb;
  65. extern Widget editMenu_copy_pb;
  66. extern Widget editMenu_rotate_pb;
  67. extern Widget editMenu_flip_pb;
  68. extern Widget editMenu_scale_pb;
  69. extern void Stop_HotBox(void);
  70. /***************************************************************************
  71. * *
  72. * Routine: Flicker_Arc *
  73. * *
  74. * Purpose: Given 2 points (top-left and bottom-right), draw an *
  75. * invertable ellipse around the box they form. *
  76. * *
  77. *X11***********************************************************************/
  78. void
  79. Flicker_Arc(
  80. Window win,
  81. int x1,
  82. int y1,
  83. int x2,
  84. int y2 )
  85. {
  86. int x, y, width, height;
  87. x = min(x1, x2);
  88. y = min(y1, y2);
  89. width = abs(x1 - x2);
  90. height = abs(y1 - y2);
  91. #ifdef DEBUG
  92. if (debug)
  93. stat_out("Doing Flicker_Arc: x=%d, y=%d, width=%d, height=%d\n",
  94. x, y, width, height);
  95. #endif
  96. if ((width > 0) && (height > 0))
  97. XDrawArc(dpy, win, Flicker_gc, x, y, width, height, 0, 360*64);
  98. }
  99. /***************************************************************************
  100. * *
  101. * Routine: Circle_Box *
  102. * *
  103. * Purpose: Given 2 points (the center and radius of a circle) *
  104. * generate a box which would exactly enclose this circle, *
  105. * and then draw a flickering circle that matches the box. *
  106. * WARNING: [x1,y1] are always assumed to be the centerpoint *
  107. * and this routine will generate bogus results if this is *
  108. * not TRUE. *
  109. * *
  110. *X11***********************************************************************/
  111. void
  112. Circle_Box(
  113. Window win,
  114. int x1,
  115. int y1,
  116. int x2,
  117. int y2,
  118. XRectangle *box )
  119. {
  120. int radius, top_x, top_y, bottom_x, bottom_y, width, height;
  121. double size;
  122. #ifdef DEBUG
  123. if (debug)
  124. stat_out("Entering Circle_Box\n");
  125. #endif
  126. width = mag(x1, x2);
  127. height = mag(y1, y2);
  128. size = (double) ((width * width) + (height * height));
  129. radius = (int) sqrt(size);
  130. top_x = x1 - radius;
  131. top_y = y1 - radius;
  132. bottom_x = x1 + radius;
  133. bottom_y = y1 + radius;
  134. #ifdef DEBUG
  135. if (debug)
  136. stat_out(" Circle_Box values: tx=%d, ty=%d, bx=%d, by=%d\n",
  137. top_x, top_y, bottom_x, bottom_x);
  138. #endif
  139. Flicker_Arc(win, top_x, top_y, bottom_x, bottom_y);
  140. box->x = top_x;
  141. box->y = top_y;
  142. box->width = bottom_x - top_x + 1;
  143. box->height = bottom_y - top_y + 1;
  144. #ifdef DEBUG
  145. if (debug)
  146. stat_out("Leaving Circle_Box\n");
  147. #endif
  148. }
  149. /***************************************************************************
  150. * *
  151. * Routine: Set_HotBox_Coords *
  152. * *
  153. * Purpose: A SELECT operation has just occurred. Initiate a timer *
  154. * calculate the area to enclose. *
  155. * not TRUE. *
  156. * *
  157. *X11***********************************************************************/
  158. #define FLASH_INTERVAL 300
  159. static Boolean FlashState=False;
  160. static int flash_x, flash_y, flash_width, flash_height;
  161. static int box_x1, box_y1, box_x2, box_y2;
  162. static XtIntervalId selectTimerID;
  163. static void Do_HotBox();
  164. void
  165. Set_HotBox_Coords( void )
  166. {
  167. int min_x, min_y, max_x, max_y, tmp_x, tmp_y;
  168. min_x = min(ix, last_ix);
  169. min_y = min(iy, last_iy);
  170. max_x = max(ix, last_ix);
  171. max_y = max(iy, last_iy);
  172. /*** make sure all four points are on the tablet ***/
  173. if (min_x < 0)
  174. min_x = 0;
  175. if (min_y < 0)
  176. min_y = 0;
  177. if ((max_x) >= icon_width)
  178. max_x = icon_width-1;
  179. if ((max_y) >= icon_height)
  180. max_y = icon_height-1;
  181. select_box.x = min_x;
  182. select_box.y = min_y;
  183. select_box.width = max_x - min_x + 1;
  184. select_box.height = max_y - min_y + 1;
  185. box_x1 = min_x;
  186. box_y1 = min_y;
  187. box_x2 = max_x+1;
  188. box_y2 = max_y+1;
  189. Tablet_Coords(min_x, min_y, &flash_x, &flash_y);
  190. Tablet_Coords(max_x+1, max_y+1, &tmp_x, &tmp_y);
  191. flash_width = tmp_x - flash_x;
  192. flash_height = tmp_y - flash_y;
  193. #ifdef DEBUG
  194. if (debug) {
  195. stat_out(" select_box: x=%d, y=%d, width=%d, height=%d\n",
  196. select_box.x, select_box.y,
  197. select_box.width, select_box.height);
  198. stat_out(" flash box: x=%d, y=%d, width=%d, height=%d\n",
  199. flash_x, flash_y, flash_width, flash_height);
  200. }
  201. #endif
  202. }
  203. /***************************************************************************
  204. * *
  205. * Routine: Start_HotBox *
  206. * *
  207. * Purpose: A SELECT operation has just occurred. Initiate a timer *
  208. * which flashes a 1-pixel wide box around the perimeter of *
  209. * the selected rectangle every FLASH_INTERVAL milliseconds. *
  210. * Use the global variables ix, iy, last_ix, last_iy to *
  211. * calculate the area to enclose. *
  212. * *
  213. *X11***********************************************************************/
  214. void
  215. Start_HotBox(
  216. int flag )
  217. {
  218. #ifdef DEBUG
  219. if (debug)
  220. stat_out("Entering Start_HotBox\n");
  221. #endif
  222. Selected = True;
  223. /* turn on stuff that uses the selected area */
  224. XtSetSensitive( editMenu_cut_pb, True);
  225. XtSetSensitive( editMenu_copy_pb, True);
  226. XtSetSensitive(editMenu_rotate_pb, True);
  227. XtSetSensitive(editMenu_flip_pb, True);
  228. XtSetSensitive(editMenu_scale_pb, True);
  229. XSync(dpy, 0);
  230. if (flag == INITIAL)
  231. Set_HotBox_Coords();
  232. selectTimerID = XtAppAddTimeOut(AppContext,
  233. FLASH_INTERVAL,
  234. (XtTimerCallbackProc) Do_HotBox,
  235. NULL);
  236. #ifdef DEBUG
  237. if (debug)
  238. stat_out("Leaving Start_HotBox - TimerID=%d\n", selectTimerID);
  239. #endif
  240. }
  241. /***************************************************************************
  242. * *
  243. * Routine: Do_HotBox *
  244. * *
  245. * Purpose: Flash one alternating pulse around the selected area, and *
  246. * then re-set itself to activate again in FLASH_INTERVAL *
  247. * milliseconds. *
  248. * *
  249. * note: Check selectTimerID so that timeouts added for previous selects *
  250. * are ignored. ex: if new select is started before previous select *
  251. * timeout is serviced, "Selected" will already be set to true again *
  252. * (for new select) when timeout from old selection is called... so *
  253. * now Stop_HotBox is called immediately (before HotBox Coords are *
  254. * set for new select), and last timeout is ignored. *
  255. * *
  256. *X11***********************************************************************/
  257. static void
  258. Do_HotBox(
  259. XtPointer *client_data,
  260. XtIntervalId *local_id )
  261. {
  262. #ifdef DEBUG
  263. if (debug)
  264. stat_out(". ");
  265. #endif
  266. if (GraphicsOp != SELECT)
  267. Selected = False;
  268. if (*local_id == selectTimerID)
  269. {
  270. if (Selected)
  271. {
  272. if (FlashState) {
  273. FlashState = False;
  274. XSetForeground(dpy, scratch_gc, black_pixel);
  275. }
  276. else
  277. {
  278. FlashState = True;
  279. XSetForeground(dpy, scratch_gc, white_pixel);
  280. }
  281. XSetLineAttributes(dpy, scratch_gc, 1, LineSolid, CapButt, JoinMiter);
  282. XDrawRectangle(dpy, tablet_win, scratch_gc,
  283. flash_x, flash_y, flash_width, flash_height);
  284. selectTimerID=XtAppAddTimeOut(AppContext,
  285. FLASH_INTERVAL,
  286. (XtTimerCallbackProc) Do_HotBox,
  287. NULL);
  288. }
  289. else
  290. Stop_HotBox();
  291. }
  292. }
  293. /***************************************************************************
  294. * *
  295. * Routine: Stop_HotBox *
  296. * *
  297. * Purpose: Undo the last Selected border operation. *
  298. * *
  299. *X11***********************************************************************/
  300. void
  301. Stop_HotBox( void )
  302. {
  303. int min_x, min_y, max_x, max_y, tmp_x, tmp_y;
  304. static int tmp_ix, tmp_iy;
  305. static Boolean Rotate_Move=False;
  306. #ifdef DEBUG
  307. if (debug)
  308. stat_out("Entering Stop_HotBox\n");
  309. #endif
  310. if (GridEnabled) {
  311. XDrawLine(dpy, tablet_win, Grid_gc,
  312. flash_x, flash_y, (flash_x+flash_width), flash_y);
  313. XDrawLine(dpy, tablet_win, Grid_gc,
  314. flash_x, (flash_y+flash_height), (flash_x+flash_width),
  315. (flash_y+flash_height));
  316. XDrawLine(dpy, tablet_win, Grid_gc,
  317. flash_x, flash_y, flash_x, (flash_y+flash_height));
  318. XDrawLine(dpy, tablet_win, Grid_gc,
  319. (flash_x+flash_width), flash_y, (flash_x+flash_width),
  320. (flash_y+flash_height));
  321. }
  322. else {
  323. /* since Rotate left and right moves ix and iy revert to tmp_ix, tmp_iy */
  324. if (Rotate_Move) { Rotate_Move = False;
  325. ix = tmp_ix;
  326. iy = tmp_iy; }
  327. min_x = min(ix, last_ix);
  328. min_y = min(iy, last_iy);
  329. max_x = max(ix, last_ix);
  330. max_y = max(iy, last_iy);
  331. if (++max_x >= icon_width) max_x--;
  332. if (++max_y >= icon_height) max_y--;
  333. Transfer_Back_Image(min_x, min_y, max_x, max_y, HOLLOW);
  334. /* if it is a Rotate Op. then keep ix, iy */
  335. if(GraphicsOp == S_ROTATE) { Rotate_Move = True;
  336. tmp_ix = ix;
  337. tmp_iy = iy; }
  338. }
  339. #ifdef DEBUG
  340. if (debug)
  341. stat_out("Leaving Stop_HotBox\n");
  342. #endif
  343. }