source: golgotha/src/i4/image/image.cc @ 608

Last change on this file since 608 was 80, checked in by Sam Hocevar, 15 years ago
  • Adding the Golgotha source code. Not sure what's going to be interesting in there, but since it's all public domain, there's certainly stuff to pick up.
File size: 13.0 KB
Line 
1/********************************************************************** <BR>
2  This file is part of Crack dot Com's free source code release of
3  Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
4  information about compiling & licensing issues visit this URL</a>
5  <PRE> If that doesn't help, contact Jonathan Clark at
6  golgotha_source@usa.net (Subject should have "GOLG" in it)
7***********************************************************************/
8
9#include "image/image.hh"
10#include "error/error.hh"
11#include "image/image32.hh"
12#include "image/image16.hh"
13#include "image/image8.hh"
14#include "palette/pal.hh"
15#include "area/rectlist.hh"
16#include "image/context.hh"
17
18
19#ifndef abs
20#define abs(x) ((x)<0 ? -(x) : (x))
21#endif
22
23
24// void i4_image_class::widget(i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2, i4_color bright, i4_color med, i4_color dark, i4_draw_context_class &context)
25// {
26//   add_dirty(x1,y1,x2,y2,context);      // to keep from creating a dirty for each operation below
27
28//   bar(x1,y1,x2,y1,bright,context);
29//   bar(x1,y1+1,x1,y2,bright,context);
30//   bar(x2,y1+1,x2,y2,dark,context);
31//   bar(x1+1,y2,x2-1,y2,dark,context);
32//   bar(x1+1,y1+1,x2-1,y2-1,med,context);
33// }
34
35void i4_image_class::put_pixel(i4_coord x, i4_coord y, w32 color, i4_draw_context_class &context)
36{
37  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
38  {     
39    if (x>=c->x1 && x<=c->x2 && y>=c->y1 && y<=c->y2)
40      put_pixel(x + context.xoff, y + context.yoff, color);
41  }
42}
43
44
45w32 i4_image_class::get_pixel(i4_coord x, i4_coord y,  i4_draw_context_class &context)
46{
47  return get_pixel(x + context.xoff, y + context.yoff);
48}
49
50 
51void i4_image_class::xor_bar(i4_coord x1,    i4_coord y1,
52                             i4_coord x2,    i4_coord y2,
53                             i4_color color, i4_draw_context_class &context)
54{
55  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
56  {
57    i4_coord lx1,ly1,lx2,ly2;
58
59    if (x1<c->x1) lx1=c->x1; else lx1=x1;
60    if (y1<c->y1) ly1=c->y1; else ly1=y1;
61    if (x2>c->x2) lx2=c->x2; else lx2=x2;
62    if (y2>c->y2) ly2=c->y2; else ly2=y2;
63
64    if (!(lx1>lx2 || ly1>ly2))
65    {
66      add_dirty(lx1,ly1,lx2,ly2,context);
67      for (;ly1<=ly2; ly1++)
68        for (int x=lx1; x<=lx2; x++)
69          put_pixel(x + context.xoff, ly1 + context.yoff, get_pixel(x,ly1)^0xffffff);
70
71    }
72  }
73}
74
75
76
77void i4_image_class::bar(i4_coord x1,    i4_coord y1,
78                         i4_coord x2,    i4_coord y2,
79                         i4_color color, i4_draw_context_class &context)
80{
81  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
82  {   
83    i4_coord lx1,ly1,lx2,ly2;
84
85    if (x1<c->x1) lx1=c->x1; else lx1=x1;
86    if (y1<c->y1) ly1=c->y1; else ly1=y1;
87    if (x2>c->x2) lx2=c->x2; else lx2=x2;
88    if (y2>c->y2) ly2=c->y2; else ly2=y2;
89
90    if (!(lx1>lx2 || ly1>ly2))
91    {
92      add_dirty(lx1,ly1,lx2,ly2,context);
93      for (;ly1<=ly2; ly1++)
94        for (int x=lx1; x<=lx2; x++)
95          put_pixel(x+ context.xoff, ly1+ context.yoff, color);
96
97    }
98  }
99}
100
101void i4_image_class::line(i4_coord ox1, i4_coord oy1,
102                          i4_coord ox2, i4_coord oy2,
103                          i4_color color, i4_draw_context_class &context)
104{
105  i4_coord x1,y1,x2,y2;
106  i4_coord cx1,cy1,cx2,cy2;
107  i4_bool skip;
108
109  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
110  {
111    x1=ox1;
112    y1=oy1;
113    x2=ox2;
114    y2=oy2;
115    skip=i4_F;
116
117    i4_coord i,xc,yc,er,n,m,xi,yi,xcxi,ycyi,xcyi;
118    unsigned dcy,dcx;
119    // check to make sure that both endpoint are on the screen
120
121    cx1=c->x1;
122    cy1=c->y1;
123    cx2=c->x2;
124    cy2=c->y2;
125
126    // check to see if the line is completly clipped off
127    if (!((x1<cx1 && x2<cx1) || (x1>cx2 && x2>cx2) ||
128          (y1<cy1 && y2<cy1) || (y1>cy2 && y2>cy2)))
129    {
130 
131      if (x1>x2)        // make sure that x1 is to the left
132      {   
133        i=x1; x1=x2; x2=i;  // if not swap points
134        i=y1; y1=y2; y2=i;
135      } 
136
137      // clip the left side
138      if (x1<cx1)
139      { 
140        int my=(y2-y1);       
141        int mx=(x2-x1),b;
142        if (!mx) skip=i4_T;
143        if (my)
144        {
145          b=y1-(y2-y1)*x1/mx;     
146          y1=my*cx1/mx+b;
147          x1=cx1;     
148        }
149        else x1=cx1;
150      }
151
152      // clip the right side
153      if (x2>cx2)
154      { 
155        int my=(y2-y1);       
156        int mx=(x2-x1),b;
157        if (!mx) skip=i4_T;
158        else if (my)
159        {
160          b=y1-(y2-y1)*x1/mx;     
161          y2=my*cx2/mx+b;
162          x2=cx2;     
163        }
164        else x2=cx2;
165      }
166
167      if (y1>y2)        // make sure that y1 is on top
168      {   
169        i=x1; x1=x2; x2=i;  // if not swap points
170        i=y1; y1=y2; y2=i;
171      } 
172
173      // clip the bottom
174      if (y2>cy2)
175      { 
176        int mx=(x2-x1);       
177        int my=(y2-y1),b;
178        if (!my)
179          skip=i4_T;
180        else if (mx)
181        {
182          b=y1-(y2-y1)*x1/mx;     
183          x2=(cy2-b)*mx/my;
184          y2=cy2;
185        }
186        else y2=cy2;
187      }
188
189      // clip the top
190      if (y1<cy1)
191      { 
192        int mx=(x2-x1);       
193        int my=(y2-y1),b;
194        if (!my)
195          skip=i4_T;
196        else if (mx)
197        {
198          b=y1-(y2-y1)*x1/mx;     
199          x1=(cy1-b)*mx/my;
200          y1=cy1;
201        }
202        else y1=cy1;
203      }
204
205
206      // see if it got cliped into the box, out out
207      if (x1<cx1 || x2<cx1 || x1>cx2 || x2>cx2 || y1<cy1 || y2 <cy1 || y1>cy2 || y2>cy2)
208        skip=i4_T;     
209
210      if (x1>x2)
211      { xc=x2; xi=x1; }
212      else { xi=x2; xc=x1; }
213
214      if (!skip)
215      {
216        // assume y1<=y2 from above swap operation
217        yi=y2; yc=y1;
218
219        add_dirty(xc,yc,xi,yi,context);
220        dcx=x1+context.xoff; dcy=y1+context.yoff;
221        xc=(x2-x1); yc=(y2-y1);
222        if (xc<0) xi=-1; else xi=1;
223        if (yc<0) yi=-1; else yi=1;
224        n=abs(xc); m=abs(yc);
225        ycyi=abs(2*yc*xi);
226        er=0;
227     
228       
229        if (n>m)
230        {
231          xcxi=abs(2*xc*xi);
232          for (i=0;i<=n;i++)
233          {
234            put_pixel(dcx, dcy, color);
235
236            if (er>0)
237            {
238              dcy+=yi;
239              er-=xcxi;
240            }
241            er+=ycyi;
242            dcx+=xi;
243          }
244        }
245        else
246        {
247          xcyi=abs(2*xc*yi);
248          for (i=0;i<=m;i++)
249          {
250            put_pixel(dcx, dcy, color);
251
252            if (er>0)
253            {
254              dcx+=xi;
255              er-=ycyi;
256            }
257            er+=xcyi;
258            dcy+=yi;
259          }
260        }
261      }
262    }
263  }
264}
265
266
267void i4_image_class::put_part(i4_image_class *to,
268                              i4_coord _x,  i4_coord _y,                             
269                              i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
270                              i4_draw_context_class &context)
271{
272  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
273  {
274    i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
275
276    if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
277    if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
278    if (x2>=width())  lx2=width()-1;   else lx2=x2;
279    if (y2>=height()) ly2=height()-1;  else ly2=y2;
280 
281    if (!(lx1>lx2 || ly1>ly2))
282    {
283      if (x<c->x1)
284      { lx1+=(c->x1-x); x=c->x1; }
285
286      if (y<c->y1)
287      { ly1+=(c->y1-y); y=c->y1; }
288
289
290      if (x+lx2-lx1+1>c->x2)
291        lx2=c->x2-x+lx1;
292
293      if (y+ly2-ly1+1>c->y2)
294        ly2=c->y2-y+ly1;
295
296
297      const i4_pixel_format *from_format=&get_pal()->source;
298      const i4_pixel_format *to_format=&to->get_pal()->source;
299      if (from_format->alpha_mask==0 || to_format->alpha_mask)
300      {
301        if (!(lx1>lx2 || ly1>ly2))
302        {
303          to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
304          while (ly1<=ly2)
305          {
306            int tx=x;
307            for (int fx=lx1;fx<=lx2; fx++, tx++)
308            {     
309              w32 c=get_pixel(fx, ly1);         
310              to->put_pixel(tx+ context.xoff, y+ context.yoff, c);
311            }
312            ly1++;
313            y++;
314          }
315        }
316      }
317      else
318      {
319        if (!(lx1>lx2 || ly1>ly2))
320        {
321          to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
322          while (ly1<=ly2)
323          {
324            int tx=x;
325            for (int fx=lx1;fx<=lx2; fx++, tx++)
326            {     
327              w32 c=get_pixel(fx, ly1);
328              float a=c>>24;
329              if (a)
330              {
331                a/=255.0;
332
333                int r=(c>>16)&0xff, g=(c>>8)&0xff, b=c&0xff;
334                w32 tc=to->get_pixel(tx, y, context);
335                int tr=(tc>>16)&0xff, tg=(tc>>8)&0xff, tb=tc&0xff;
336               
337                r=(int)((r-tr)*a + tr);
338                g=(int)((g-tg)*a + tg);
339                b=(int)((b-tb)*a + tb);
340
341                to->put_pixel(tx+ context.xoff, y+ context.yoff, (r<<16) | (g<<8) | b);
342              }
343            }
344            ly1++;
345            y++;
346          }
347        }
348      }
349    }
350  }
351}
352
353
354
355void i4_image_class::put_part_trans(i4_image_class *to,
356                                    i4_coord _x,  i4_coord _y,                             
357                                    i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
358                                    i4_color trans_color,
359                                    i4_draw_context_class &context)
360{
361  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
362  {
363    i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
364
365    if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
366    if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
367    if (x2>=width())  lx2=width()-1;   else lx2=x2;
368    if (y2>=height()) ly2=height()-1;  else ly2=y2;
369 
370    if (!(lx1>lx2 || ly1>ly2))
371    {
372      if (x<c->x1)
373      { lx1+=(c->x1-x); x=c->x1; }
374
375      if (y<c->y1)
376      { ly1+=(c->y1-y); y=c->y1; }
377
378
379      if (x+lx2-lx1+1>c->x2)
380        lx2=c->x2-x+lx1;
381
382      if (y+ly2-ly1+1>c->y2)
383        ly2=c->y2-y+ly1;
384
385
386      const i4_pixel_format *from_format=&get_pal()->source;
387      const i4_pixel_format *to_format=&to->get_pal()->source;
388
389      if (!(lx1>lx2 || ly1>ly2))
390      {
391        to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
392        while (ly1<=ly2)
393        {
394          int tx=x;
395          for (int fx=lx1;fx<=lx2; fx++, tx++)
396          {     
397            w32 c=get_pixel(fx, ly1);
398            if (c!=trans_color)
399              to->put_pixel(tx+context.xoff, y+ context.yoff, c);
400          }
401          ly1++;
402          y++;
403        }
404      }
405    }
406  }
407}
408
409
410
411i4_image_class *i4_create_image(int width, int height, const i4_pal *pal)
412{
413  switch (pal->source.pixel_depth)
414  {
415    case I4_32BIT :
416      return new i4_image32(width, height, pal);
417      break;
418
419    case I4_16BIT :
420      return new i4_image16(width, height, pal);
421      break;
422     
423     
424    case I4_8BIT :
425      return new i4_image8(width, height, pal);
426      break;
427     
428    default:     
429      i4_error("don't know how");     
430  }
431 
432
433
434  return 0;
435}
436
437i4_image_class *i4_create_image(int width, int height,
438                                const i4_pal *pal,
439                                void *data,
440                                int bpl)
441{
442  switch (pal->source.pixel_depth)
443  {
444    case I4_32BIT :
445      return new i4_image32(width, height, pal, data, bpl);
446      break;
447
448    case I4_16BIT :
449      return new i4_image16(width, height, pal, data, bpl);
450      break;
451     
452    case I4_8BIT :
453      return new i4_image8(width, height, pal, data, bpl);
454      break;
455     
456    default:     
457      i4_error("don't know how");     
458  }
459  return 0;
460}
461
462i4_image_class *i4_image_class::copy()
463{
464  i4_image_class *im=i4_create_image(width(), height(), pal);
465
466  for (int y=0; y<h; y++)
467    for (int x=0; x<w; x++)
468      im->put_pixel(x,y, get_pixel(x,y));
469
470  return im;
471}
472
473
474void i4_image_class::add_single_dirty(i4_coord x1, i4_coord y1, i4_coord x2,
475                                      i4_coord y2, i4_draw_context_class &context)
476{
477  context.add_single_dirty(x1+context.xoff,y1+context.yoff,
478                           x2+context.xoff,y2+context.yoff);
479}
480 
481void i4_image_class::add_dirty(i4_coord x1, i4_coord y1, i4_coord x2,
482                               i4_coord y2, i4_draw_context_class &context)
483{
484  context.add_both_dirty(x1+context.xoff,y1+context.yoff,
485                         x2+context.xoff,y2+context.yoff);
486}
487
488void i4_image_class::rectangle(i4_coord x1, i4_coord y1,
489                               i4_coord x2, i4_coord y2, i4_color color,
490                               i4_draw_context_class &context)
491{
492  bar(x1,y1,x1,y2,color,context);
493  bar(x2,y1,x2,y2,color,context);
494  bar(x1+1,y1,x2-1,y1,color,context);
495  bar(x1+1,y2,x2-1,y2,color,context);
496}
Note: See TracBrowser for help on using the repository browser.