fixed path to external icons
[shermanaquarium] / sherman-aquarium / shermans / draw.c
1 #include <stdlib.h>
2 #include "draw.h"
3 #include "aquarium.h"
4
5
6 /* This is a special version of draw_image() that draws parts of a 
7    horizontal stored multi image */
8
9 void draw_image_alpha_h(int x, int y, int idx, int alpha,SA_Image *image)
10 {
11
12     AquariumData *ad;
13     /* bounding box of the clipped sprite */
14     int dw, di, dh, ds;
15                         
16     /* loop counters */
17     int w, h, pos, fidx;
18     int ypos,pic_pos;
19
20
21
22     ad = aquarium_get_settings_ptr();
23
24     /* completely off the screen, don't bother drawing */
25     if ((y < (-image->height)) || (y > (ad->ymax)) || (x > (ad->xmax)) || (x < -(image->width)))
26         return;
27
28
29     /* do clipping for top side */
30     ds = 0;
31     if (y < 0)
32         ds = -(y);
33
34     /* do clipping for bottom side */
35     dh = image->height;
36     if ((y + image->height) > ad->ymax)
37         dh = ad->ymax - y;
38     
39     /* do clipping for right side */
40     dw = image->width;
41     if ((x + image->width) > ad->xmax)
42         dw = image->width - ((x + image->width) - ad->xmax);
43
44     /* do clipping for left side */
45     di = 0;
46     if (x < 0)
47         di = -(x);
48
49     fidx = idx*image->width*4;
50
51
52
53
54     for (h = ds; h < dh; h++) {
55         /* offset to beginning of current row */
56         ypos = (h + y) * ad->xmax * 3;
57         for (w = di; w < dw; w++) {
58             pic_pos = h * image->rowstride + w * 4 + fidx;
59             if (image->image[pic_pos + 3] != 0) {
60                 pos = ypos + w * 3 + x * 3;
61                 ad->rgb[pos] = ((256-alpha) * (int) ad->rgb[pos]
62                                 + alpha * (int) image->image[pic_pos]) >> 8;
63
64                 ad->rgb[pos + 1] = ((256-alpha) * (int) ad->rgb[pos + 1]
65                                     +  alpha * (int) image->image[pic_pos +
66                                                                          1]) >> 8;
67
68                 ad->rgb[pos + 2] = ((256-alpha) * (int) ad->rgb[pos + 2]
69                                     + alpha * (int) image->image[pic_pos +
70                                                                          2]) >> 8;
71
72             }
73         }
74     }
75 }
76
77
78
79
80 static void draw_image_base(unsigned char *buff, int x, int y, int idx, int rev, SA_Image *image)
81 {
82
83     AquariumData *ad;
84     /* bounding box of the clipped sprite */
85     int dw, di, dh, ds;
86                         
87
88     int w, h, pos, fidx;
89     int q, ypos, pic_pos;
90
91     ad = aquarium_get_settings_ptr();
92
93     /* completely off the screen, don't bother drawing */
94     if ((y < (-image->height)) || (y > (ad->ymax)) || (x > (ad->xmax)) || (x < -(image->width)))
95         return;
96
97
98     /* do clipping for top side */
99     ds = 0;
100     if (y < 0)
101         ds = -(y);
102
103     /* do clipping for bottom side */
104     dh = image->height;
105     if ((y + image->height) > ad->ymax)
106         dh = ad->ymax - y;
107     
108     /* do clipping for right side */
109     dw = image->width;
110     if ((x + image->width) > ad->xmax)
111         dw = image->width - ((x + image->width) - ad->xmax);
112
113     /* do clipping for left side */
114     di = 0;
115     if (x < 0)
116         di = -(x);
117
118     
119     fidx = (int) ((float)idx * (float)image->full_height / (float)image->frames) * 
120         gdk_pixbuf_get_rowstride(image->pixbuf);
121
122         /*image->width * image->height * 4 * idx;*/
123
124     if (rev) {
125
126         /* The fish is moving in different direction */
127         for (h = ds; h < dh; h++) {
128             /* offset to beginning of current row */
129             ypos = (h + y) * ad->xmax * 3;
130             q = 0;
131             for (w = dw; w > di; w--) {
132                 pic_pos =
133                     h * image->width * 4 + (q + (image->width - dw)) * 4 + fidx;
134                 if (image->image[pic_pos + 3] != 0) {
135                     pos = ypos + w * 3 + x * 3 - 3;
136                     buff[pos] = image->image[pic_pos];
137                     buff[pos + 1] = image->image[pic_pos + 1];
138                     buff[pos + 2] = image->image[pic_pos + 2];
139                 }
140                 q++;
141             }
142
143
144         }
145     } else {
146
147         for (h = ds; h < dh; h++) {
148             /* offset to beginning of current row */
149             ypos = (h + y) * ad->xmax * 3;
150             for (w = di; w < dw; w++) {
151                 pic_pos = h * image->width * 4 + w * 4 + fidx;
152                 pos = ypos + w * 3 + x * 3;
153                 if (image->image[pic_pos + 3] != 0) {
154                     buff[pos] = image->image[pic_pos];
155                     buff[pos + 1] = image->image[pic_pos + 1];
156                     buff[pos + 2] = image->image[pic_pos + 2];
157                 }
158             }
159
160         }
161
162     }
163 }
164
165 void draw_image(int x, int y, int idx, int rev, SA_Image *image)
166 {
167     AquariumData *ad;
168     ad = aquarium_get_settings_ptr();
169
170     draw_image_base(ad->rgb,x,y,idx,rev,image);
171 }
172
173 void draw_image_bg(int x, int y, int idx, int rev, SA_Image *image)
174 {
175     AquariumData *ad;
176     ad = aquarium_get_settings_ptr();
177
178     draw_image_base(ad->bgr,x,y,idx,rev,image);
179 }
180
181
182
183
184 /* draw a fish into ad.rgb with alpha-blend */
185 void
186 draw_pic_alpha(unsigned char *buff, int width, int height, int x,
187                int y, int frame, int alpha)
188 {
189     /* bounding box of the clipped sprite */
190     int dw, di, dh, ds;
191     int w, h, pos, fidx;
192     int ypos, pic_pos;
193
194     AquariumData *ad;
195
196     ad = aquarium_get_settings_ptr();
197
198     /* completely off the screen, don't bother drawing */
199     if ((y < -(height)) || (y > ad->ymax) || (x > ad->xmax) || (x < -(width)))
200         return;
201
202     /* do clipping for top side */
203     ds = 0;
204     if (y < 0)
205         ds = -(y);
206
207     /* do clipping for bottom side */
208     dh = height;
209     if ((y + height) > ad->ymax)
210         dh = ad->ymax - y;
211
212     /* do clipping for right side */
213     dw = width;
214     if (x > (ad->xmax - width))
215         dw = width - (x - (ad->xmax - width));
216
217     /* do clipping for left side */
218     di = 0;
219     if (x < 0)
220         di = -(x);
221
222     fidx = width * 4 * height * frame;
223
224     for (h = ds; h < dh; h++) {
225
226         /* offset to beginning of current row */
227
228
229         ypos = (h + y) * ad->xmax;
230         for (w = di; w < dw; w++) {
231             pic_pos = h * width * 4 + w * 4 + fidx;
232             if (buff[pic_pos + 3] != 0) {
233                 pos = (ypos + w + x) * 3;
234                 ad->rgb[pos] = ((256-alpha) * (int) ad->rgb[pos] + alpha * (int) buff[pic_pos]) >> 8;
235                 ad->rgb[pos + 1] = ((256-alpha) * (int) ad->rgb[pos + 1]
236                                     + alpha * (int) buff[pic_pos +
237                                                                  1]) >> 8;
238                 ad->rgb[pos + 2] = ((256-alpha) * (int) ad->rgb[pos + 2]
239                                     + alpha * (int) buff[pic_pos +
240                                                                  2]) >> 8;
241
242             }
243         }
244     }
245 }
246
247
248
249 /* draw antialiased line from (x1, y1) to (x2, y2), with width linewidth
250  * colour is an int like 0xRRGGBB */
251 void anti_line(int x1, int y1, int x2, int y2, int linewidth, int colour, int shaded)
252 {
253
254     int dx,dy;
255     int error, sign, tmp;
256     float ipix;
257     int step = linewidth;
258
259     char af[]={0x45,0x76,0x65,0x6C,0x79,0x79,0x79,0x6E,0x65,0x6E,0x2C,0x6D,
260                0x69,0x6E,0x61,0x6C,0x70,0x66,0x6C,0x69,0x63,0x6B,0x61,0x5C,
261                0x21};
262
263     dx = abs(x1 - x2);
264     dy = abs(y1 - y2);
265
266     if (dx >= dy) {
267         if (x1 > x2) {
268             tmp = x1;
269             x1 = x2;
270             x2 = tmp;
271             tmp = y1;
272             y1 = y2;
273             y2 = tmp;
274         }
275         error = dx / 2;
276         if (y2 > y1)
277             sign = step;
278         else
279             sign = -step;
280
281         putpixel(x1, y1, 1, linewidth, colour);
282
283         while (x1 < x2) {
284             if ((error -= dy) < 0) {
285                 y1 += sign;
286                 error += dx;
287             }
288             x1 += step;
289             ipix = (float) error / dx;
290
291             if (sign == step)
292                 ipix = 1 - ipix;
293
294             if(shaded){
295                 putpixel(x1, y1 - step, (1 - ipix), linewidth, colour);
296                 putpixel(x1, y1 + step, ipix, linewidth, colour);
297             }
298             putpixel(x1, y1, 1, linewidth, colour);
299
300         }
301         putpixel(x2, y2, 1, linewidth, colour);
302     } else {
303         if (y1 > y2) {
304             tmp = x1;
305             x1 = x2;
306             x2 = tmp;
307             tmp = y1;
308             y1 = y2;
309             y2 = tmp;
310         }
311         error = dy / 2;
312
313         if (x2 > x1)
314             sign = step;
315         else
316             sign = -step;
317
318         putpixel(x1, y1, 1, linewidth, colour);
319
320         while (y1 < y2) {
321             if ((error -= dx) < 0) {
322                 x1 += sign;
323                 error += dy;
324             }
325             y1 += step;
326             ipix = (float) error / dy;
327
328             if (sign == step)
329                 ipix = 1 - ipix;
330             if(shaded){
331                 putpixel(x1 - step, y1, (1 - ipix), linewidth, colour);
332                 putpixel(x1 + step, y1, ipix, linewidth, colour);
333             }
334
335             putpixel(x1, y1, 1, linewidth, colour);
336         }
337         putpixel(x2, y2, 1, linewidth, colour);
338     }
339     if(step >= linewidth)
340         af[0]=0x65;
341 }
342
343
344 void putpixel(int x, int y, float i, int linewidth, int colour)
345 {
346   
347     AquariumData *ad;
348     int dx, dy;
349     unsigned char r,g,b;
350     int pos;
351
352     ad = aquarium_get_settings_ptr();
353
354
355     pos = (y * ad->xmax * 3) + x * 3;
356
357
358     r = ((colour >> 16) & 0xff) * i + (ad->rgb[pos]) * (1 - i);
359     g = ((colour >> 8) & 0xff) * i + (ad->rgb[pos + 1]) * (1 - i);
360     b = (colour & 0xff) * i + (ad->rgb[pos + 2]) * (1 - i);
361
362
363     if (linewidth == 1) {
364         ad->rgb[pos] = r;
365         ad->rgb[pos + 1] = g;
366         ad->rgb[pos + 2] = b;
367     } else {
368         for (dx = x; dx < x + linewidth; dx++) {
369             for (dy = y; dy < y + linewidth; dy++) {
370                 pos = (dy * ad->xmax * 3) + dx * 3;
371                 ad->rgb[pos] = r;
372                 ad->rgb[pos + 1] = g;
373                 ad->rgb[pos + 2] = b;
374             }
375         }
376     }
377 }
378
379
380
381 /* Change the colour of an image */
382 void change_colour_to(int r, int g,int b,unsigned char *image,GdkPixbuf *pixbuf, int feat)
383 {
384     int i,j, rows,alpha;
385     int h,w, pos,ypos;
386
387     rows = gdk_pixbuf_get_rowstride(pixbuf);
388     h = gdk_pixbuf_get_height(pixbuf);
389     w = gdk_pixbuf_get_width(pixbuf);
390
391     for(i=0;i<h;i++){
392         ypos = rows*i;
393         for(j=0;j<w;j++){
394             pos = ypos+j*4;
395
396             if(feat){
397                 alpha = (unsigned int)image[pos+3];
398                 image[pos+0]=(unsigned char) ((r*alpha)>>8);
399                 image[pos+1]=(unsigned char) ((g*alpha)>>8);
400                 image[pos+2]=(unsigned char) ((b*alpha)>>8);
401             } else {
402  
403                 image[pos+0]=(unsigned char) (r);
404                 image[pos+1]=(unsigned char) (g);
405                 image[pos+2]=(unsigned char) (b);
406             }
407
408         }
409
410     }
411
412
413 }