1 /* $Header: /home/yav/xpx/RCS/image.c,v 1.18 1996/03/26 15:39:13 yav Exp $
2 * xpx image control
3 * written by yav (UHD98984@pcvan.or.jp)
4 */
5
6 #include <X11/Xlib.h>
7 #include <X11/Xutil.h>
8 #include <X11/cursorfont.h>
9
10 #include "headers.h"
11 #include "xpx.h"
12 #include "work.h"
13 #include "scrldef.h"
14 #include "infodef.h"
15 #include "cursdef.h"
16 #include "editdef.h"
17 #define PUBLIC_IMAGE_C
18 #include "extern.h"
19
20 #ifndef IMGWINWIDTHMAX
21 #define IMGWINWIDTHMAX 1024
22 #endif
23 #ifndef IMGWINHEIGHTMAX
24 #define IMGWINHEIGHTMAX 1024
25 #endif
26
27 char rcsid_image[] = "$Id: image.c,v 1.18 1996/03/26 15:39:13 yav Exp $";
28
29 AREA area0;
30 Bool area_flag = False;
31 Bool mark_flag = False;
32
33 static AREA lastarea;
34 static AREA current_area;
35 static int mark_cnt = 0;
36 static int *mark_pts = NULL;
37
get_img_window_size()38 void get_img_window_size()
39 {
40 XWindowAttributes attr;
41
42 XGetWindowAttributes(dsp, win, &attr);
43 imgwinwidth = attr.width - imgwx - BDW*2;
44 imgwinheight = attr.height - imgwy - BDW*2;
45 if (scrollbarmode) {
46 imgwinwidth -= IMGSCRLW + BDW*3 + 3;
47 imgwinheight -= IMGSCRLW + BDW*3 + 3;
48 }
49 if (imgwinwidth > IMGWINWIDTHMAX)
50 imgwinwidth = IMGWINWIDTHMAX;
51 if (imgwinheight > IMGWINHEIGHTMAX)
52 imgwinheight = IMGWINHEIGHTMAX;
53 }
54
create_img_window()55 int create_img_window()
56 {
57 int i;
58 unsigned long mask;
59 XSetWindowAttributes attr;
60
61 mark_pts = (int *)malloc(sizeof(int)*8*(imgmaxw+imgmaxh));
62 if (mark_pts == NULL)
63 return error("create_img_window: more core!");
64 get_img_window_size();
65 imgwin = XCreateSimpleWindow(dsp, win, imgwx, imgwy,
66 imgwinwidth, imgwinheight, BDW, fg, bg);
67 attr.bit_gravity = NorthWestGravity;
68 mask = CWBitGravity;
69 if (backingstoremode) {
70 switch(backingstoremode) {
71 case 1:
72 i = WhenMapped;
73 break;
74 case 2:
75 i = Always;
76 break;
77 default:
78 i = backingstoremode;
79 break;
80 }
81 attr.backing_store = i;
82 mask |= CWBackingStore;
83 }
84 XChangeWindowAttributes(dsp, imgwin, mask, &attr);
85 XSelectInput(dsp, imgwin, ExposureMask|
86 ButtonPressMask|ButtonReleaseMask|ButtonMotionMask);
87 XMapRaised(dsp, imgwin);
88 #if 0
89 csource = XCreateBitmapFromData(dsp, win,
90 curs_bits, curs_width, curs_height);
91 cmask = XCreateBitmapFromData(dsp, win, cursmask_bits,
92 cursmask_width, cursmask_height);
93 XParseColor(dsp, DefaultColormap(dsp, scr), "Black", &cfore);
94 XParseColor(dsp, DefaultColormap(dsp, scr), "White", &cback);
95 curs = XCreatePixmapCursor(dsp, csource, cmask, &cfore, &cback,
96 curs_x_hot, curs_y_hot);
97 /* curs = XCreateFontCursor(dsp, XC_tcross); */
98 XDefineCursor(dsp, imgwin, curs);
99 #endif
100 return 0;
101 }
102
image_alloc()103 int image_alloc()
104 {
105 imgdata = (unsigned char *)malloc(imgmaxw*imgmaxh);
106 if (imgdata == NULL)
107 return 1;
108 img = XCreateImage(dsp, DefaultVisual(dsp, scr), DefaultDepth(dsp, scr),
109 ZPixmap, 0, None,
110 imgmaxw*maxzoom, imgmaxh*maxzoom,
111 32, 0);
112 if (img == NULL)
113 return 1;
114 img->data = (char *)malloc(img->bytes_per_line * img->height);
115 if (img->data == NULL)
116 return 1;
117 return 0;
118 }
119
init_image()120 void init_image()
121 {
122 if (!alloced_color)
123 get_color(color_buf+MAXCOLSET*current_pal, MAXCOLSET);
124 bzero(img->data, img->bytes_per_line * img->height);
125 }
126
resize_img_window()127 void resize_img_window()
128 {
129 get_img_window_size();
130 XResizeWindow(dsp, imgwin, imgwinwidth, imgwinheight);
131 resize_scrl();
132 resize_scroll_slider();
133 }
134
set_image_size(w,h)135 int set_image_size(w, h)
136 int w;
137 int h;
138 {
139 int r;
140
141 r = 0;
142 if (w >= 0) {
143 imgfilew = w;
144 r = 1;
145 }
146 if (h >= 0) {
147 imgfileh = h;
148 r |= 2;
149 }
150 info_imgsize_set();
151 resize_scroll_slider();
152 redraw_window(imgwin);
153 return r;
154 }
155
draw_grid(x0,y0,w0,h0)156 void draw_grid(x0, y0, w0, h0)
157 int x0;
158 int y0;
159 int w0;
160 int h0;
161 {
162 int n, x, y, w, h;
163 int ox, oy;
164
165 n = grid_size*zoomfactor;
166 ox = imgofsx + (grid_size-grid_ofsx) * zoomfactor;
167 oy = imgofsy + (grid_size-grid_ofsy) * zoomfactor;
168 w = w0;
169 x = x0;
170 if (x & 1) {
171 x++;
172 w--;
173 }
174 if (w > 0 && h0 > 0) {
175 for (y = y0; y < y0 + h0; y++) {
176 if (((oy + y)%n) == 0)
177 XDrawLine(dsp, imgwin, gridgc, x, y, x+w-1, y);
178 }
179 }
180 h = h0;
181 y = y0;
182 if (y & 1) {
183 y++;
184 h--;
185 }
186 if (w0 > 0 && h > 0) {
187 for (x = x0; x < x0 + w0; x++) {
188 if (((ox + x)%n) == 0)
189 XDrawLine(dsp, imgwin, gridgc, x, y, x, y+h-1);
190 }
191 }
192 }
193
inarea(x,w,n1,n2)194 Bool inarea(x, w, n1, n2)
195 int x;
196 int w;
197 int n1;
198 int n2;
199 {
200 if (x < n1)
201 return (x+w >= n1);
202 return x < n2;
203 }
204
calc_img_area(x,y,w,h)205 void calc_img_area(x, y, w, h)
206 int *x;
207 int *y;
208 int *w;
209 int *h;
210 {
211 *w *= zoomfactor;
212 *h *= zoomfactor;
213 *x = *x * zoomfactor - imgofsx;
214 *y = *y * zoomfactor - imgofsy;
215 }
216
little_big(p1,p2)217 void little_big(p1, p2)
218 int *p1;
219 int *p2;
220 {
221 int i;
222
223 if (*p1 > *p2) {
224 i = *p1;
225 *p1 = *p2;
226 *p2 = i;
227 }
228 }
229
calc_area(x0,y0,x1,y1)230 void calc_area(x0, y0, x1, y1)
231 int *x0;
232 int *y0;
233 int *x1;
234 int *y1;
235 {
236 little_big(x0, x1);
237 little_big(y0, y1);
238 *x1 -= *x0;
239 *y1 -= *y0;
240 calc_img_area(x0, y0, x1, y1);
241 }
242
area_expose(x0,y0,w0,h0)243 void area_expose(x0, y0, w0, h0)
244 int x0;
245 int y0;
246 int w0;
247 int h0;
248 {
249 AREA ar;
250
251 ar = current_area;
252 calc_area(&ar.x, &ar.y, &ar.w, &ar.h);
253 if ((inarea(ar.x, ar.w, x0, x0+w0) ||
254 inarea(ar.y, ar.h, y0, y0+h0)))
255 XDrawRectangle(dsp, imgwin, areagc, ar.x, ar.y, ar.w, ar.h);
256 }
257
mark_pts_on(x0,y0,w0,h0)258 void mark_pts_on(x0, y0, w0, h0)
259 int x0;
260 int y0;
261 int w0;
262 int h0;
263 {
264 int i, x, y;
265 int *p;
266
267 p = mark_pts;
268 i = mark_cnt;
269 while (i--) {
270 x = *p++ * zoomfactor - imgofsx;
271 y = *p++ * zoomfactor - imgofsy;
272 if (x0 <= x && x < x0 + w0 && y0 <= y && y < y0 + h0)
273 XDrawPoint(dsp, imgwin, areagc, x, y);
274 }
275 }
276
img_expose(x,y,w,h)277 void img_expose(x, y, w, h)
278 int x;
279 int y;
280 int w;
281 int h;
282 {
283 int i;
284 int hx, hy;
285
286 if ((imgofsx+x >= imgfilew*zoomfactor)||
287 (imgofsy+y >= imgfileh*zoomfactor)||
288 (imgofsx+x+w < 0)||
289 (imgofsy+y+h < 0)) {
290 if (x >= 0 && x+w <= imgwinwidth && y >= 0 && y+h <= imgwinheight)
291 XClearArea(dsp, imgwin, x, y, w, h, False);
292 return;
293 }
294 i = -imgofsx - x;
295 if (i > 0) {
296 XClearArea(dsp, imgwin, x, y, i, h, False);
297 x += i;
298 w -= i;
299 }
300 i = -imgofsy - y;
301 if (i > 0) {
302 XClearArea(dsp, imgwin, x, y, w, i, False);
303 y += i;
304 h -= i;
305 }
306 i = x + w - (imgfilew*zoomfactor - imgofsx);
307 if (i > 0) {
308 XClearArea(dsp, imgwin, x+w-i, y, i, h, False);
309 w -= i;
310 }
311 i = y + h - (imgfileh*zoomfactor - imgofsy);
312 if (i > 0) {
313 XClearArea(dsp, imgwin, x, y+h-i, w, i, False);
314 h -= i;
315 }
316 if (w && h) {
317 XPutImage(dsp, imgwin, gc0, img, x+imgofsx, y+imgofsy, x, y, w, h);
318 if (grid_mode)
319 draw_grid(x, y, w, h);
320 if (area_flag)
321 area_expose(x, y, w, h);
322 if (mark_flag)
323 mark_pts_on(x, y, w, h);
324 hx = hotspotx*zoomfactor-imgofsx;
325 hy = hotspoty*zoomfactor-imgofsy;
326 if (infomenu[INFOMENU_HOTSPOTCENTER].mode & MenuModeMaskOn) {
327 hx += zoomfactor/2;
328 hy += zoomfactor/2;
329 }
330 if (y <= hy && hy < y+h)
331 XDrawLine(dsp, imgwin, grid0gc, x, hy, x+w-1, hy);
332 if (x <= hx && hx < x+w)
333 XDrawLine(dsp, imgwin, grid0gc, hx, y, hx, y+h-1);
334 }
335 }
336
image_update_all_sub()337 void image_update_all_sub()
338 {
339 img_expose(0, 0, imgwinwidth, imgwinheight);
340 if (view_sw & 1)
341 redraw_window(viewwin);
342 }
343
pre_image_udpate()344 void pre_image_udpate()
345 {
346 cursor_busy();
347 make_view_image();
348 }
349
image_update_all()350 void image_update_all()
351 {
352 pre_image_udpate();
353 gen_image_sub(0, 0, imgfilew, imgfileh);
354 image_update_all_sub();
355 }
356
image_update_col()357 void image_update_col()
358 {
359 pre_image_udpate();
360 gen_image_col(0, 0, imgfilew, imgfileh);
361 image_update_all_sub();
362 }
363
color_update_all()364 void color_update_all()
365 {
366 free_color();
367 get_color(color_buf+MAXCOLSET*current_pal, MAXCOLSET);
368 if (alloced_color > alloced_private_color)
369 image_update_col();
370 }
371
img_scroll_redraw(dx,dy)372 void img_scroll_redraw(dx, dy)
373 int dx;
374 int dy;
375 {
376 if (imgwin_noexpose) {
377 XCopyArea(dsp, imgwin, imgwin, gc0,
378 (dx<0?0:dx), (dy<0?0:dy),
379 imgwinwidth-(dx<0?-dx:dx), imgwinheight-(dy<0?-dy:dy),
380 (dx<0?-dx:0), (dy<0?-dy:0));
381 imgwin_noexpose = False;
382 if (dx)
383 img_expose((dx<0?0:imgwinwidth-dx), 0, (dx<0?-dx:dx), imgwinheight);
384 if (dy)
385 img_expose(0, (dy<0?0:imgwinheight-dy), imgwinwidth, (dy<0?-dy:dy));
386 } else {
387 img_expose(0, 0, imgwinwidth, imgwinheight);
388 }
389 }
390
391 static int center_x = 0;
392 static int center_y = 0;
393
img_scroll_sub(dx,dy)394 void img_scroll_sub(dx, dy)
395 int *dx;
396 int *dy;
397 {
398 if (infomenu[INFOMENU_SCROLLSTOP].mode & MenuModeMaskOn) {
399 if (*dx) {
400 if (imgofsx + *dx + imgwinwidth >= imgfilew*zoomfactor)
401 *dx = imgfilew*zoomfactor - (imgofsx + imgwinwidth);
402 if (imgofsx + *dx < 0)
403 *dx = -imgofsx;
404 }
405 if (*dy) {
406 if (imgofsy + *dy + imgwinheight >= imgfileh*zoomfactor)
407 *dy = imgfileh*zoomfactor - (imgofsy + imgwinheight);
408 if (imgofsy + *dy < 0)
409 *dy = -imgofsy;
410 }
411 }
412 if (!*dx && !*dy)
413 return;
414 if (*dx) {
415 imgofsx += *dx;
416 move_hslider();
417 redraw_window(cursmenu[CURS_TOPX].win);
418 }
419 if (*dy) {
420 imgofsy += *dy;
421 move_vslider();
422 redraw_window(cursmenu[CURS_TOPY].win);
423 }
424 center_x = (imgofsx + imgwinwidth/2) / zoomfactor;
425 center_y = (imgofsy + imgwinheight/2) / zoomfactor;
426 }
427
img_scroll(dx,dy)428 void img_scroll(dx, dy)
429 int dx;
430 int dy;
431 {
432 img_scroll_sub(&dx, &dy);
433 img_scroll_redraw(dx, dy);
434 }
435
img_scroll_posset(newx,newy)436 void img_scroll_posset(newx, newy)
437 int newx;
438 int newy;
439 {
440 int dx, dy;
441
442 dx = newx-imgofsx;
443 dy = newy-imgofsy;
444 img_scroll_sub(&dx, &dy);
445 }
446
img_scroll_posreset()447 void img_scroll_posreset()
448 {
449 int i, x, y;
450
451 x = center_x;
452 y = center_y;
453 i = imgfilew - imgwinwidth/2/zoomfactor;
454 if (x > i)
455 x = i;
456 i = imgfileh - imgwinheight/2/zoomfactor;
457 if (y > i)
458 y = i;
459 if (x < 0)
460 x = 0;
461 if (y < 0)
462 y = 0;
463 x = (x * zoomfactor) - imgwinwidth/2;
464 y = (y * zoomfactor) - imgwinheight/2;
465 img_scroll_posset(x, y);
466 resize_scroll_slider();
467 }
468
imgscrl_background()469 void imgscrl_background()
470 {
471 int dx, dy, ax, ay;
472
473 ax = scroll_ax;
474 ay = scroll_ay;
475 /* scroll bar press? */
476 if (scrlbar[SCRLBAR_TOP].mode & MenuModeMaskOn ||
477 vslider[VSLIDER_UP].mode & MenuModeMaskOn)
478 ay = -1;
479 if (scrlbar[SCRLBAR_BOTTOM].mode & MenuModeMaskOn ||
480 vslider[VSLIDER_DOWN].mode & MenuModeMaskOn)
481 ay = 1;
482 if (scrlbar[SCRLBAR_LEFT].mode & MenuModeMaskOn ||
483 hslider[HSLIDER_LEFT].mode & MenuModeMaskOn)
484 ax = -1;
485 if (scrlbar[SCRLBAR_RIGHT].mode & MenuModeMaskOn ||
486 hslider[HSLIDER_RIGHT].mode & MenuModeMaskOn)
487 ax = 1;
488 /* set default background scroll */
489 scroll_dx += ax;
490 if (scroll_dx > scroll_speed)
491 scroll_dx = scroll_speed;
492 else if (scroll_dx < -scroll_speed)
493 scroll_dx = -scroll_speed;
494 scroll_dy += ay;
495 if (scroll_dy > scroll_speed)
496 scroll_dy = scroll_speed;
497 else if (scroll_dy < -scroll_speed)
498 scroll_dy = -scroll_speed;
499 dx = scroll_dx;
500 dy = scroll_dy;
501 if (dx || dy)
502 img_scroll(dx, dy);
503 }
504
505
norm_area(x0,y0,x1,y1)506 void norm_area(x0, y0, x1, y1)
507 int *x0;
508 int *y0;
509 int *x1;
510 int *y1;
511 {
512 little_big(x0, x1);
513 little_big(y0, y1);
514 *x1 -= *x0;
515 *y1 -= *y0;
516 }
517
area_exsub(x,y,w,h)518 void area_exsub(x, y, w, h)
519 int x;
520 int y;
521 int w;
522 int h;
523 {
524 img_expose(x, y, w+1, 1);
525 img_expose(x, y, 1, h+1);
526 img_expose(x+w, y, 1, h+1);
527 img_expose(x, y+h, w+1, 1);
528 }
529
erase_last_area()530 void erase_last_area()
531 {
532 Bool af;
533
534 af = area_flag;
535 area_flag = False;
536 calc_area(&lastarea.x, &lastarea.y, &lastarea.w, &lastarea.h);
537 area_exsub(lastarea.x, lastarea.y, lastarea.w, lastarea.h);
538 area_flag = af;
539 }
540
copy_area_expose()541 void copy_area_expose()
542 {
543 AREA ar;
544
545 if (area_flag) {
546 erase_last_area();
547 ar = lastarea = current_area = area0;
548 calc_area(&ar.x, &ar.y, &ar.w, &ar.h);
549 area_exsub(ar.x, ar.y, ar.w, ar.h);
550 }
551 }
552
max_area(rx0,ry0,rx1,ry1,n,p)553 void max_area(rx0, ry0, rx1, ry1, n, p)
554 int *rx0;
555 int *ry0;
556 int *rx1;
557 int *ry1;
558 int n;
559 int *p;
560 {
561 int x0, y0, x1, y1;
562
563 x0 = x1 = *p++;
564 y0 = y1 = *p++;
565 while (--n) {
566 if (*p < x0)
567 x0 = *p;
568 if (*p > x1)
569 x1 = *p;
570 p++;
571 if (*p < y0)
572 y0 = *p;
573 if (*p > y1)
574 y1 = *p;
575 p++;
576 }
577 *rx0 = x0;
578 *ry0 = y0;
579 *rx1 = x1;
580 *ry1 = y1;
581 }
582
mark_pts_set(n,p)583 void mark_pts_set(n, p)
584 int n;
585 int *p;
586 {
587 memcpy(mark_pts, p, n*sizeof(int)*2);
588 mark_cnt = n;
589 }
590
mark_pts_expose()591 void mark_pts_expose()
592 {
593 int xx0, xx1, yy0, yy1;
594
595 if (mark_cnt > 0) {
596 max_area(&xx0, &yy0, &xx1, &yy1, mark_cnt, mark_pts);
597 img_expose(xx0*zoomfactor-imgofsx, yy0*zoomfactor-imgofsy,
598 (xx1-xx0+1)*zoomfactor, (yy1-yy0+1)*zoomfactor);
599 }
600 }
601
602 /* End of file */
603