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