g_layers.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * sfnedit/g_layers.c
  3. *
  4. * Copyright (C) 2020 bzt (bztsrc@gitlab)
  5. *
  6. * Permission is hereby granted, free of charge, to any person
  7. * obtaining a copy of this software and associated documentation
  8. * files (the "Software"), to deal in the Software without
  9. * restriction, including without limitation the rights to use, copy,
  10. * modify, merge, publish, distribute, sublicense, and/or sell copies
  11. * of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be
  15. * included in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. * DEALINGS IN THE SOFTWARE.
  25. *
  26. * @brief Glyph window edit layers tool
  27. *
  28. */
  29. #include <stdint.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include "libsfn.h"
  34. #include "ui.h"
  35. #include "lang.h"
  36. extern int colorsel, mousex, mousey;
  37. int sellayers = 0, scrolllayers = 0, pagelayers = 0, isclick = 0, issel = 0, ispicker = 0, selcmd = -1, isfrc = 0, cx, cy;
  38. void ctrl_zoom_in(int idx, int mx, int my);
  39. void ctrl_zoom_out(int idx, int mx, int my);
  40. void ctrl_move(int idx, int mx, int my);
  41. void ctrl_pos(int idx, int layer, int dx, int dy);
  42. void ctrl_fliph(int idx, int layer);
  43. void ctrl_flipv(int idx, int layer);
  44. /**
  45. * Layer editor window
  46. */
  47. void view_layers(int idx)
  48. {
  49. ui_win_t *win = &wins[idx];
  50. sfncont_t *cont;
  51. int i, j, k, x = win->w - 74, w = win->zoom * ctx.glyphs[win->unicode].width, h = win->zoom * ctx.glyphs[win->unicode].height;
  52. int gx = -1, gy = -1, d;
  53. uint32_t c, *uc = (uint32_t*)&ctx.cpal;
  54. if(x < 0) x = 0;
  55. pagelayers = (win->h - 29 - 49) / 66; if(pagelayers < 1) pagelayers = 1;
  56. if(sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = ctx.glyphs[win->unicode].numlayer - 1;
  57. if(sellayers < 0) sellayers = 0;
  58. if(scrolllayers + pagelayers > ctx.glyphs[win->unicode].numlayer) scrolllayers = ctx.glyphs[win->unicode].numlayer-pagelayers;
  59. if(sellayers + 1 > scrolllayers + pagelayers - 1) scrolllayers = sellayers - pagelayers + 1;
  60. if(sellayers >= 0 && sellayers < scrolllayers) scrolllayers = sellayers;
  61. if(scrolllayers < 0) scrolllayers = 0;
  62. if(sellayers >= ctx.glyphs[win->unicode].numlayer)
  63. sellayers = 0;
  64. ssfn_dst.w = x - 6;
  65. ssfn_dst.h = win->h - 24;
  66. i = win->zoom/2; if(i < 2) i = 2;
  67. ui_box(win, 20+win->zx-i, 36, i, win->h - 36, theme[THEME_BG],theme[THEME_BG],theme[THEME_BG]);
  68. ui_box(win, 20+win->zx+w, 36, i, win->h - 36, theme[THEME_BG],theme[THEME_BG],theme[THEME_BG]);
  69. if(win->zy-i >= 0)
  70. ui_box(win, 20, 36+win->zy-i, x - 20, i, theme[THEME_BG],theme[THEME_BG],theme[THEME_BG]);
  71. if(win->zy+h < win->h)
  72. ui_box(win, 20, 36+win->zy+h, x - 20, i, theme[THEME_BG],theme[THEME_BG],theme[THEME_BG]);
  73. ui_grid(win, ctx.glyphs[win->unicode].width, ctx.glyphs[win->unicode].height);
  74. if(selcmd != -1 && issel && posx != -1 && posy != -1 && sellayers < ctx.glyphs[win->unicode].numlayer) {
  75. cont = (sfncont_t*)ctx.glyphs[win->unicode].layers[sellayers].data;
  76. for(i = 0; i < ctx.glyphs[win->unicode].layers[sellayers].len && (gx == -1 || gy == -1); i++, cont++)
  77. if(i != (selcmd >> 2)) {
  78. if(cont->px == posx) gx = posx;
  79. if(cont->py == posy) gy = posy;
  80. if(cont->type >= SSFN_CONTOUR_QUAD) {
  81. if(cont->c1x == posx) gx = posx;
  82. if(cont->c1y == posy) gy = posy;
  83. if(cont->type == SSFN_CONTOUR_CUBIC) {
  84. if(cont->c2x == posx) gx = posx;
  85. if(cont->c2y == posy) gy = posy;
  86. }
  87. }
  88. }
  89. }
  90. ui_gridbg(win, 20 + (win->zx > 0 ? win->zx : 0), 36 + (win->zy > 0 ? win->zy : 0), w, h, 1, win->data, gx, gy);
  91. ui_edit(win, 20 + win->zx, 36 + win->zy, win->unicode, sellayers);
  92. ssfn_dst.w = win->w - 1;
  93. ssfn_dst.h = win->h - 20;
  94. if(sellayers < ctx.glyphs[win->unicode].numlayer)
  95. colorsel = ctx.glyphs[win->unicode].layers[sellayers].color;
  96. else colorsel = 0xFE;
  97. c = colorsel < ctx.numcpal ? uc[colorsel] : (colorsel == 0xFF ? 0 : 0xFF000000 | theme[THEME_FG]);
  98. for(i = 0; i < 2; i++) {
  99. j = win->field == 4 + i;
  100. ui_box(win, 144 + i * 24, 1, 22, 22, theme[j ? THEME_CURSOR : (selfield == i ? THEME_DARKER : THEME_LIGHT)],
  101. theme[j ? THEME_LIGHT : THEME_BG], theme[j ? THEME_CURSOR : (selfield == i ? THEME_LIGHT : THEME_DARKER)]);
  102. ui_icon(win, 147 + i * 24, 4, ICON_ZOOMOUT + i, 0);
  103. }
  104. for(i = 0; i < 3; i++) {
  105. j = win->field == 6 + i;
  106. ui_box(win, 198 + i * 24, 1, 22, 22, theme[j ? THEME_CURSOR : (selfield==i+2 ? THEME_DARKER : THEME_LIGHT)],
  107. theme[j ? THEME_LIGHT : THEME_BG], theme[j ? THEME_CURSOR : (selfield==i+2 ? THEME_LIGHT : THEME_DARKER)]);
  108. ui_icon(win, 201 + i * 24, 4, ICON_CUT + i, 0);
  109. }
  110. for(i = 0; i < 3; i++) {
  111. j = win->field == 9 + i;
  112. ui_box(win, x + i * 24, 1, 22, 22, theme[j ? THEME_CURSOR : (selfield==i+5 ? THEME_DARKER : THEME_LIGHT)],
  113. theme[j ? THEME_LIGHT : THEME_BG], theme[j ? THEME_CURSOR : (selfield==i+5 ? THEME_LIGHT : THEME_DARKER)]);
  114. ui_icon(win, x + 3 + i * 24, 4, ICON_VECTOR + i, 0);
  115. }
  116. ui_box(win, x, win->h - 42, 22, 22, theme[win->field == 13 ? THEME_CURSOR : (selfield == 8 ? THEME_DARKER : THEME_LIGHT)],
  117. theme[win->field == 13 ? THEME_LIGHT : THEME_BG],
  118. theme[win->field == 13 ? THEME_CURSOR : (selfield == 8 ? THEME_LIGHT : THEME_DARKER)]);
  119. ui_argb(win, x + 3, win->h - 39, 16, 16, sellayers < ctx.glyphs[win->unicode].numlayer ? c : 0);
  120. ui_box(win, x+24, win->h - 42, 22, 22, theme[win->field == 14 ? THEME_CURSOR : (selfield == 9 ? THEME_DARKER : THEME_LIGHT)],
  121. theme[win->field == 14 ? THEME_LIGHT : THEME_BG],
  122. theme[win->field == 14 ? THEME_CURSOR : (selfield == 9 ? THEME_LIGHT : THEME_DARKER)]);
  123. ui_icon(win, x+27, win->h - 39, ICON_PICKER, sellayers >= ctx.glyphs[win->unicode].numlayer ||
  124. ctx.glyphs[win->unicode].layers[sellayers].type != SSFN_FRAG_PIXMAP);
  125. ui_box(win, x+48, win->h - 42, 22, 22, theme[win->field == 15 ? THEME_CURSOR : (selfield == 10 ? THEME_DARKER : THEME_LIGHT)],
  126. theme[win->field == 15 ? THEME_LIGHT : THEME_BG],
  127. theme[win->field == 15 ? THEME_CURSOR : (selfield == 10 ? THEME_LIGHT : THEME_DARKER)]);
  128. ui_icon(win, x+51, win->h - 39, ICON_DELETE, sellayers >= ctx.glyphs[win->unicode].numlayer);
  129. ui_box(win, x, 26, 70, win->h - 26 - 46, theme[win->field == 12 ? THEME_CURSOR : THEME_DARKER], theme[THEME_BG],
  130. theme[win->field == 12 ? THEME_CURSOR : THEME_LIGHT]);
  131. ssfn_dst.w = x + 68; ssfn_dst.h = win->h - 49; j = 29; x += 3;
  132. for(i = scrolllayers; i < ctx.glyphs[win->unicode].numlayer && j < ssfn_dst.h; i++, j += 66) {
  133. if(i == sellayers) {
  134. c = theme[THEME_SELBG]; d = -2;
  135. ssfn_dst.fg = theme[THEME_SELFG];
  136. } else {
  137. c = theme[THEME_DARK]; d = -1;
  138. ssfn_dst.fg = theme[THEME_FG];
  139. }
  140. ui_box(win, x, j, 64, 64, c, c, c);
  141. ui_icon(win, x, j+48, ctx.glyphs[win->unicode].layers[i].type + ICON_VECTOR, d);
  142. if(ctx.glyphs[win->unicode].layers[i].color == 0xFF) { k=1; ctx.glyphs[win->unicode].layers[i].color = 0xFE; } else k=0;
  143. ui_glyph(win, x, j, 64, win->unicode, i, 1);
  144. if(k) ctx.glyphs[win->unicode].layers[i].color = 0xFF;
  145. }
  146. ssfn_dst.fg = theme[THEME_FG];
  147. ssfn_dst.bg = 0;
  148. }
  149. /**
  150. * Add a new empty layer
  151. */
  152. void ctrl_layers_add(int idx, int t)
  153. {
  154. int l;
  155. ui_win_t *win = &wins[idx];
  156. sfnlayer_t *lyr;
  157. ctx.glyphs[win->unicode].layers = (sfnlayer_t*)realloc(ctx.glyphs[win->unicode].layers,
  158. (ctx.glyphs[win->unicode].numlayer + 1) * sizeof(sfnlayer_t));
  159. if(!ctx.glyphs[win->unicode].layers) ui_error("layers", ERR_MEM);
  160. sellayers = ctx.glyphs[win->unicode].numlayer;
  161. lyr = &ctx.glyphs[win->unicode].layers[ctx.glyphs[win->unicode].numlayer++];
  162. memset(lyr, 0, sizeof(sfnlayer_t));
  163. lyr->type = t;
  164. lyr->color = 0xFE;
  165. if(t != SSFN_FRAG_CONTOUR) {
  166. l = ctx.glyphs[win->unicode].width * ctx.glyphs[win->unicode].height;
  167. lyr->data = (unsigned char*)malloc(l);
  168. if(!lyr->data) ui_error("layers", ERR_MEM);
  169. memset(lyr->data, 0xFF, l);
  170. }
  171. modified++;
  172. }
  173. /**
  174. * Delete the last contour command from active layer
  175. */
  176. void ctrl_layers_delcmd(int idx)
  177. {
  178. ui_win_t *win = &wins[idx];
  179. if(sellayers >= 0 && sellayers < ctx.glyphs[win->unicode].numlayer &&
  180. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR && ctx.glyphs[win->unicode].layers[sellayers].len)
  181. ctx.glyphs[win->unicode].layers[sellayers].len--;
  182. }
  183. /**
  184. * Add a contour command to layer
  185. */
  186. void ctrl_layers_addcmd(int idx, int t, int x, int y)
  187. {
  188. ui_win_t *win = &wins[idx];
  189. int c1x = 0, c1y = 0, c2x = 0, c2y = 0, i, px, py;
  190. if(sellayers >= 0 && sellayers < ctx.glyphs[win->unicode].numlayer &&
  191. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR) {
  192. if(!ctx.glyphs[win->unicode].layers[sellayers].len) {
  193. t = SSFN_CONTOUR_MOVE;
  194. } else {
  195. i = ctx.glyphs[win->unicode].layers[sellayers].len - 1;
  196. px = ((sfncont_t*)ctx.glyphs[win->unicode].layers[sellayers].data)[i].px;
  197. py = ((sfncont_t*)ctx.glyphs[win->unicode].layers[sellayers].data)[i].py;
  198. if(t == SSFN_CONTOUR_QUAD) {
  199. c1x = (x - px) / 2 + px;
  200. c1y = (y - py) / 2 + py;
  201. } else if(t == SSFN_CONTOUR_CUBIC) {
  202. c1x = (x - px) / 3 + px;
  203. c1y = (y - py) / 3 + py;
  204. c2x = (x - px) * 2 / 3 + px;
  205. c2y = (y - py) * 2 / 3 + py;
  206. }
  207. }
  208. sfn_contadd(&ctx.glyphs[win->unicode].layers[sellayers], t | 0x100, x, y, c1x, c1y, c2x, c2y);
  209. }
  210. }
  211. /**
  212. * On enter handler
  213. */
  214. void ctrl_layers_onenter(int idx)
  215. {
  216. ui_win_t *win = &wins[idx];
  217. int x = win->w - 74;
  218. if(x < 0) x = 0;
  219. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  220. switch(win->field) {
  221. case 4: ctrl_zoom_out(idx, (x-20)/2 + 20, (win->h-36-24)/2 + 36); break;
  222. case 5: ctrl_zoom_in(idx, (x-20)/2 + 20, (win->h-36-24)/2 + 36); break;
  223. case 6:
  224. if(sellayers < ctx.glyphs[win->unicode].numlayer) {
  225. copypaste_start(win->unicode);
  226. copypaste_copy(win->unicode, sellayers);
  227. sfn_layerdel(win->unicode, sellayers);
  228. if(sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = ctx.glyphs[win->unicode].numlayer - 1;
  229. if(sellayers < 0) sellayers = 0;
  230. }
  231. break;
  232. case 7:
  233. if(sellayers < ctx.glyphs[win->unicode].numlayer) {
  234. copypaste_start(win->unicode); copypaste_copy(win->unicode, sellayers);
  235. }
  236. break;
  237. case 8: copypaste_paste(win->unicode, 1); break;
  238. case 9: ctrl_layers_add(idx, SSFN_FRAG_CONTOUR); break;
  239. case 10: ctrl_layers_add(idx, SSFN_FRAG_BITMAP); break;
  240. case 11: ctrl_layers_add(idx, SSFN_FRAG_PIXMAP); break;
  241. case 13:
  242. win->field = -1;
  243. if(sellayers < ctx.glyphs[win->unicode].numlayer &&
  244. ctx.glyphs[win->unicode].layers[sellayers].color == 0xFF) { colorsel = 0xFE; ctrl_colors_onenter(idx); } else
  245. win->tool = GLYPH_TOOL_COLOR;
  246. break;
  247. case 14:
  248. win->field = -1;
  249. if(sellayers < ctx.glyphs[win->unicode].numlayer &&
  250. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_PIXMAP) ispicker = 1;
  251. break;
  252. case 15:
  253. win->field = -1;
  254. if(sellayers < ctx.glyphs[win->unicode].numlayer) { sfn_layerdel(win->unicode, sellayers); modified++; }
  255. break;
  256. }
  257. }
  258. /**
  259. * On key handler
  260. */
  261. void ctrl_layers_onkey(int idx)
  262. {
  263. ui_win_t *win = &wins[idx];
  264. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  265. if(event.h & (3 << 1)) {
  266. switch(event.x) {
  267. case 'x': case 'X': win->field = 6; ctrl_layers_onenter(idx); break;
  268. case 'c': case 'C': win->field = 7; ctrl_layers_onenter(idx); break;
  269. case 'v': case 'V': win->field = 8; ctrl_layers_onenter(idx); break;
  270. }
  271. win->field = -1;
  272. } else
  273. if(event.x == 'h' || event.x == 'H') ctrl_fliph(idx, sellayers); else
  274. if(event.x == 'v' || event.x == 'V') ctrl_flipv(idx, sellayers); else
  275. if(event.x == K_BACKSPC) ctrl_layers_delcmd(idx); else
  276. if(win->field == 12) {
  277. switch(event.x) {
  278. case K_UP: if(sellayers > 0) sellayers--; break;
  279. case K_DOWN: if(sellayers < ctx.glyphs[win->unicode].numlayer - 1) sellayers++; break;
  280. }
  281. } else {
  282. switch(event.x) {
  283. case K_UP: ctrl_pos(idx, sellayers, 0, -1); break;
  284. case K_LEFT: ctrl_pos(idx, sellayers, -1, 0); break;
  285. case K_DOWN: ctrl_pos(idx, sellayers, 0, 1); break;
  286. case K_RIGHT: ctrl_pos(idx, sellayers, 1, 0); break;
  287. case K_DEL: win->field = 15; ctrl_layers_onenter(idx); break;
  288. case K_PGUP: if(sellayers > 0) sellayers--; break;
  289. case K_PGDN: if(sellayers < ctx.glyphs[win->unicode].numlayer - 1) sellayers++; break;
  290. }
  291. }
  292. ui_refreshwin(event.win, 20, 36, win->w - 20, win->h - 36 - 24);
  293. }
  294. /**
  295. * On button press handler
  296. */
  297. void ctrl_layers_onbtnpress(int idx)
  298. {
  299. ui_win_t *win = &wins[idx];
  300. int x = win->w - 74, ox = win->zx > 0 ? win->zx : 0, oy = win->zy > 0 ? win->zy : 0;
  301. if(x < 0) x = 0;
  302. selfield = win->field = mousex = mousey = -1; issel = isclick = isfrc = 0;
  303. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  304. if(event.y < 26) {
  305. if(event.x > x && event.x < x + 24) selfield = 5; else
  306. if(event.x > x + 24 && event.x < x + 48) selfield = 6; else
  307. if(event.x > x + 48 && event.x < x + 64) selfield = 7; else
  308. if(event.x > 144 && event.x < 166) selfield = 0; else
  309. if(event.x > 168 && event.x < 190) selfield = 1; else
  310. if(event.x > 198 && event.x < 220) selfield = 2; else
  311. if(event.x > 224 && event.x < 246) selfield = 3; else
  312. if(event.x > 248 && event.x < 270) selfield = 4;
  313. } else
  314. if(event.x > x) {
  315. if(event.y > 26 && event.y < win->h - 42 && event.x > x && event.x < x + 70) {
  316. if(event.w & 1) sellayers = (event.y - 28) / 64 + scrolllayers; else
  317. if(event.w & (1 << 3)) sellayers--; else
  318. if(event.w & (1 << 4)) sellayers++;
  319. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  320. } else
  321. if(event.y > win->h - 42 && event.x > x && sellayers < ctx.glyphs[win->unicode].numlayer) {
  322. if(event.x > x && event.x < x + 24) selfield = 8; else
  323. if(event.x > x + 24 && event.x < x + 48 && ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_PIXMAP)
  324. selfield = 9; else
  325. if(event.x > x + 48 && event.x < x + 72) selfield = 10;
  326. }
  327. } else
  328. if(event.y < win->h - 22) {
  329. if(event.w & (1 << 3)) ctrl_zoom_in(event.win, event.x, event.y); else
  330. if(event.w & (1 << 4)) ctrl_zoom_out(event.win, event.x, event.y); else
  331. if(event.x >= ox + 20 && event.y >= oy + 36 &&
  332. event.x <= ox + 20 + win->zoom * ctx.glyphs[win->unicode].width &&
  333. event.y <= oy + 36 + win->zoom * ctx.glyphs[win->unicode].height) {
  334. if(ispicker) {
  335. if(posx != -1 && posy != -1 && sellayers < ctx.glyphs[win->unicode].numlayer &&
  336. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_PIXMAP)
  337. ctx.glyphs[win->unicode].layers[sellayers].color =
  338. ctx.glyphs[win->unicode].layers[sellayers].data[ctx.glyphs[win->unicode].width * posy + posx];
  339. ispicker = 0;
  340. } else {
  341. if(event.h && posx != -1 && posy != -1 && sellayers < ctx.glyphs[win->unicode].numlayer &&
  342. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR) {
  343. selcmd = ctx.glyphs[win->unicode].layers[sellayers].len << 2;
  344. ctrl_layers_addcmd(idx, event.h & 1 ? SSFN_CONTOUR_LINE : (event.w & 1 ? SSFN_CONTOUR_CUBIC :
  345. SSFN_CONTOUR_QUAD), posx, posy);
  346. issel = 1;
  347. }
  348. if(selcmd == -1) { mousex = event.x; mousey = event.y; issel = 0; }
  349. else issel = 1;
  350. isclick = 1; cx = event.x; cy = event.y;
  351. isfrc = ctx.glyphs[win->unicode].layers[sellayers].type != SSFN_FRAG_CONTOUR && event.w & 1;
  352. }
  353. }
  354. }
  355. }
  356. /**
  357. * On click (button release) handler
  358. */
  359. void ctrl_layers_onclick(int idx)
  360. {
  361. ui_win_t *win = &wins[idx];
  362. uint32_t c;
  363. int x = win->w - 74, ox = win->zx > 0 ? win->zx : 0, oy = win->zy > 0 ? win->zy : 0;
  364. if(x < 0) x = 0;
  365. ispicker = 0; cursor = CURSOR_PTR;
  366. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  367. if(event.y < 26) {
  368. if(event.x > x && event.x < x + 24 && selfield == 5) { win->field = 9; ctrl_layers_onenter(idx); } else
  369. if(event.x > x + 24 && event.x < x + 48 && selfield == 6) { win->field = 10; ctrl_layers_onenter(idx); } else
  370. if(event.x > x + 48 && event.x < x + 64 && selfield == 7) { win->field = 11; ctrl_layers_onenter(idx); } else
  371. if(event.x > 144 && event.x < 166 && selfield == 0) { win->field = 4; ctrl_layers_onenter(idx); } else
  372. if(event.x > 168 && event.x < 190 && selfield == 1) { win->field = 5; ctrl_layers_onenter(idx); } else
  373. if(event.x > 198 && event.x < 220 && selfield == 2) { win->field = 6; ctrl_layers_onenter(idx); } else
  374. if(event.x > 224 && event.x < 246 && selfield == 3) { win->field = 7; ctrl_layers_onenter(idx); } else
  375. if(event.x > 248 && event.x < 270 && selfield == 4) { win->field = 8; ctrl_layers_onenter(idx); }
  376. } else
  377. if(event.x > x && event.y > win->h - 42) {
  378. if(event.x > x && event.x < x + 24 && selfield == 8) { win->field = 13; ctrl_layers_onenter(idx); } else
  379. if(event.x > x + 24 && event.x < x + 48 && selfield == 9) { win->field = 14; ctrl_layers_onenter(idx); } else
  380. if(event.x > x + 48 && event.x < x + 72 && selfield == 10) { win->field = 15; ctrl_layers_onenter(idx); }
  381. } else
  382. if(event.x >= ox + 20 && event.y >= oy + 36 &&
  383. event.x <= ox + 20 + win->zoom * ctx.glyphs[win->unicode].width &&
  384. event.y <= oy + 36 + win->zoom * ctx.glyphs[win->unicode].height && sellayers < ctx.glyphs[win->unicode].numlayer) {
  385. if(ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR && selcmd != -1) cursor = CURSOR_CROSS;
  386. if((isclick || isfrc) && !ispicker && (ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_BITMAP ||
  387. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_PIXMAP)) {
  388. cursor = CURSOR_CROSS;
  389. c = ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_BITMAP ? 0xFE :
  390. ctx.glyphs[win->unicode].layers[sellayers].color;
  391. if(ctx.glyphs[win->unicode].layers[sellayers].data[ctx.glyphs[win->unicode].width * posy + posx] == c)
  392. ctx.glyphs[win->unicode].layers[sellayers].data[ctx.glyphs[win->unicode].width * posy + posx] = 0xFF;
  393. else
  394. ctx.glyphs[win->unicode].layers[sellayers].data[ctx.glyphs[win->unicode].width * posy + posx] = c;
  395. modified++;
  396. }
  397. }
  398. isclick = issel = isfrc = 0;
  399. selfield = win->field = mousex = mousey = -1;
  400. }
  401. /**
  402. * On mouse move handler
  403. */
  404. void ctrl_layers_onmove(int idx)
  405. {
  406. ui_win_t *win = &wins[idx];
  407. sfncont_t *cont;
  408. int i, j, x = win->w - 74, ox = win->zx > 0 ? win->zx : 0, oy = win->zy > 0 ? win->zy : 0;
  409. i = event.x > cx ? event.x - cx : cx - event.x; j = event.y > cy ? event.y - cy : cy - event.y; if(j > i) i = j;
  410. if(isfrc || (isclick && i < 3)) return;
  411. if(x < 0) x = 0;
  412. posx = posy = -1; isclick = 0;
  413. if(sellayers < 0 || sellayers >= ctx.glyphs[win->unicode].numlayer) sellayers = 0;
  414. if(event.y < 26) {
  415. if(event.x > x && event.x < x + 24) status = lang[LAYERS_VECTOR]; else
  416. if(event.x > x + 24 && event.x < x + 48) status = lang[LAYERS_BITMAP]; else
  417. if(event.x > x + 48 && event.x < x + 64) status = lang[LAYERS_PIXMAP]; else
  418. if(event.x > 144 && event.x < 166) status = lang[LAYERS_ZOOMOUT]; else
  419. if(event.x > 168 && event.x < 190) status = lang[LAYERS_ZOOMIN]; else
  420. if(event.x > 198 && event.x < 220) status = lang[LAYERS_CUT]; else
  421. if(event.x > 224 && event.x < 246) status = lang[LAYERS_COPY]; else
  422. if(event.x > 248 && event.x < 270) status = lang[LAYERS_PASTE];
  423. } else
  424. if(event.x > x && event.y > win->h - 42) {
  425. if(event.x > x && event.x < x + 24) status = lang[LAYERS_FOREGROUND]; else
  426. if(event.x > x + 24 && event.x < x + 48) status = lang[LAYERS_PICKER]; else
  427. if(event.x > x + 48 && event.x < x + 72) status = lang[LAYERS_DELETE];
  428. } else
  429. if(event.x >= ox + 20 && event.y >= oy + 36 &&
  430. event.x <= ox + 20 + win->zoom * ctx.glyphs[win->unicode].width &&
  431. event.y <= oy + 36 + win->zoom * ctx.glyphs[win->unicode].height && event.y < win->h - 22) {
  432. if(sellayers < ctx.glyphs[win->unicode].numlayer &&
  433. ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR) {
  434. event.x += win->zoom/2; event.y += win->zoom/2;
  435. }
  436. posx = (event.x - ox - 20 - (win->zx < 0 ? win->zx : 0)) / win->zoom;
  437. if(posx >= ctx.glyphs[win->unicode].width) posx = -1;
  438. posy = (event.y - oy - 36 - (win->zy < 0 ? win->zy : 0)) / win->zoom;
  439. if(posy >= ctx.glyphs[win->unicode].height) posy = -1;
  440. if(!ispicker && mousex != -1 && mousey != -1) ctrl_move(event.win, event.x, event.y); else
  441. if(sellayers < ctx.glyphs[win->unicode].numlayer) {
  442. cursor = CURSOR_CROSS;
  443. if(!ispicker) {
  444. if(selcmd != -1 && issel) {
  445. /* normally we would use -1 to indicate we are off-layer, but with move we must clamp */
  446. if(posx == -1 || posx >= ctx.glyphs[win->unicode].width) posx = ctx.glyphs[win->unicode].width - 1;
  447. if(posy == -1 || posy >= ctx.glyphs[win->unicode].height) posy = ctx.glyphs[win->unicode].height - 1;
  448. cont = (sfncont_t*)ctx.glyphs[win->unicode].layers[sellayers].data;
  449. switch(selcmd & 3) {
  450. case 0: cont[selcmd >> 2].px = posx; cont[selcmd >> 2].py = posy; break;
  451. case 1: cont[selcmd >> 2].c1x = posx; cont[selcmd >> 2].c1y = posy; break;
  452. case 2: cont[selcmd >> 2].c2x = posx; cont[selcmd >> 2].c2y = posy; break;
  453. }
  454. modified++;
  455. ui_refreshwin(event.win, 20, 36, win->w - 20 - x, win->h - 36 - 24);
  456. } else
  457. if(ctx.glyphs[win->unicode].layers[sellayers].type == SSFN_FRAG_CONTOUR) {
  458. selcmd = -1;
  459. cont = (sfncont_t*)ctx.glyphs[win->unicode].layers[sellayers].data;
  460. for(i = 0; i < ctx.glyphs[win->unicode].layers[sellayers].len; i++, cont++) {
  461. if(cont->px == posx && cont->py == posy) { selcmd = i << 2; break; }
  462. if(cont->type >= SSFN_CONTOUR_QUAD && cont->c1x == posx && cont->c1y == posy)
  463. { selcmd = (i << 2)|1; break; }
  464. if(cont->type == SSFN_CONTOUR_CUBIC && cont->c2x == posx && cont->c2y == posy)
  465. { selcmd = (i << 2)|2; break; }
  466. }
  467. if(selcmd == -1) cursor = CURSOR_PTR;
  468. }
  469. } else
  470. cursor = CURSOR_GRAB;
  471. }
  472. }
  473. }