source: golgotha/src/i4/image/image16.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: 12.5 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/image16.hh"
10#include "memory/malloc.hh"
11#include "palette/pal.hh"
12#include "image/context.hh"
13
14#include <string.h>
15
16inline int iabs(int val) { return val>0?val:-val; }
17
18i4_color i4_image16::get_pixel(i4_coord x, i4_coord y)
19{   
20  return i4_pal_man.convert_to_32(*paddr(x,y), pal);
21}
22 
23void i4_image16::put_pixel(i4_coord x, i4_coord y, w32 color)
24{
25  w16 *addr=paddr(x,y);
26  *addr=i4_pal_man.convert_32_to(color, &pal->source);
27}
28
29
30
31
32i4_image16::i4_image16(w16 _w, w16 _h, const i4_pal *_pal)
33{
34  w=_w;
35  h=_h;
36  bpl=_w*2;
37  set_pal(_pal);
38  data=i4_malloc(w*h*2, "");
39}
40
41i4_image16::i4_image16(w16 _w, w16 _h, const i4_pal *_pal,
42                       void *_data, int _bpl)
43{
44  data=_data;
45  bpl=_bpl;
46  pal=_pal;
47  w=_w;
48  h=_h;
49
50  dont_free_data=i4_T;
51}
52
53
54i4_image16::~i4_image16()
55{
56  if (!dont_free_data)
57    i4_free(data);
58}
59
60
61
62void i4_image16::line(i4_coord ox1, i4_coord oy1,
63                          i4_coord ox2, i4_coord oy2,
64                          i4_color color, i4_draw_context_class &context)
65{
66  i4_coord x1,y1,x2,y2;
67  i4_coord cx1,cy1,cx2,cy2;
68  i4_bool skip;
69
70  w16 tcolor=i4_pal_man.convert_32_to(color, &pal->source);
71
72  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
73  {
74    x1=ox1;
75    y1=oy1;
76    x2=ox2;
77    y2=oy2;
78    skip=i4_F;
79
80    i4_coord i,xc,yc,er,n,m,xi,yi,xcxi,ycyi,xcyi;
81    unsigned dcy,dcx;
82    // check to make sure that both endpoint are on the screen
83
84    cx1=c->x1;
85    cy1=c->y1;
86    cx2=c->x2;
87    cy2=c->y2;
88
89    // check to see if the line is completly clipped off
90    if (!((x1<cx1 && x2<cx1) || (x1>cx2 && x2>cx2) ||
91          (y1<cy1 && y2<cy1) || (y1>cy2 && y2>cy2)))
92    {
93 
94      if (x1>x2)        // make sure that x1 is to the left
95      {   
96        i=x1; x1=x2; x2=i;  // if not swap points
97        i=y1; y1=y2; y2=i;
98      } 
99
100      // clip the left side
101      if (x1<cx1)
102      { 
103        int my=(y2-y1);       
104        int mx=(x2-x1),b;
105        if (!mx) skip=i4_T;
106        if (my)
107        {
108          b=y1-(y2-y1)*x1/mx;     
109          y1=my*cx1/mx+b;
110          x1=cx1;     
111        }
112        else x1=cx1;
113      }
114
115      // clip the right side
116      if (x2>cx2)
117      { 
118        int my=(y2-y1);       
119        int mx=(x2-x1),b;
120        if (!mx) skip=i4_T;
121        else if (my)
122        {
123          b=y1-(y2-y1)*x1/mx;     
124          y2=my*cx2/mx+b;
125          x2=cx2;     
126        }
127        else x2=cx2;
128      }
129
130      if (y1>y2)        // make sure that y1 is on top
131      {   
132        i=x1; x1=x2; x2=i;  // if not swap points
133        i=y1; y1=y2; y2=i;
134      } 
135
136      // clip the bottom
137      if (y2>cy2)
138      { 
139        int mx=(x2-x1);       
140        int my=(y2-y1),b;
141        if (!my)
142          skip=i4_T;
143        else if (mx)
144        {
145          b=y1-(y2-y1)*x1/mx;     
146          x2=(cy2-b)*mx/my;
147          y2=cy2;
148        }
149        else y2=cy2;
150      }
151
152      // clip the top
153      if (y1<cy1)
154      { 
155        int mx=(x2-x1);       
156        int my=(y2-y1),b;
157        if (!my)
158          skip=i4_T;
159        else if (mx)
160        {
161          b=y1-(y2-y1)*x1/mx;     
162          x1=(cy1-b)*mx/my;
163          y1=cy1;
164        }
165        else y1=cy1;
166      }
167
168
169      // see if it got cliped into the box, out out
170      if (x1<cx1 || x2<cx1 || x1>cx2 || x2>cx2 || y1<cy1 || y2 <cy1 || y1>cy2 || y2>cy2)
171        skip=i4_T;     
172
173      if (x1>x2)
174      { xc=x2; xi=x1; }
175      else { xi=x2; xc=x1; }
176
177      if (!skip)
178      {
179        // assume y1<=y2 from above swap operation
180        yi=y2; yc=y1;
181
182        add_dirty(xc,yc,xi,yi,context);
183        dcx=x1+context.xoff; dcy=y1+context.yoff;
184        xc=(x2-x1); yc=(y2-y1);
185        if (xc<0) xi=-1; else xi=1;
186        if (yc<0) yi=-1; else yi=1;
187        n=iabs(xc); m=iabs(yc);
188        ycyi=iabs(2*yc*xi);
189        er=0;
190     
191       
192        if (n>m)
193        {
194          xcxi=iabs(2*xc*xi);
195          for (i=0;i<=n;i++)
196          {
197            *paddr(dcx, dcy)=tcolor;
198
199            if (er>0)
200            {
201              dcy+=yi;
202              er-=xcxi;
203            }
204            er+=ycyi;
205            dcx+=xi;
206          }
207        }
208        else
209        {
210          xcyi=iabs(2*xc*yi);
211          for (i=0;i<=m;i++)
212          {
213            *paddr(dcx, dcy)=tcolor;
214
215            if (er>0)
216            {
217              dcx+=xi;
218              er-=ycyi;
219            }
220            er+=xcyi;
221            dcy+=yi;
222          }
223        }
224      }
225    }
226  }
227}
228
229
230void i4_image16::put_part(i4_image_class *to,
231                              i4_coord _x,  i4_coord _y,                             
232                              i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
233                              i4_draw_context_class &context)
234{
235  const i4_pixel_format *from_format=&get_pal()->source;
236  const i4_pixel_format *to_format=&to->get_pal()->source;
237
238 
239  if ((to_format->pixel_depth!=I4_16BIT ||
240      to_format->red_mask != from_format->red_mask ||
241      to_format->green_mask != from_format->green_mask ||
242      to_format->blue_mask != from_format->blue_mask) &&
243      (from_format->alpha_mask==0 || to_format->alpha_mask))
244    // depths aren't the same do it the slow way
245    i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
246  else
247  { 
248    for (i4_rect_list_class::area_iter c=context.clip.list.begin();
249         c!=context.clip.list.end();
250         ++c)
251    {
252      i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
253
254      if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
255      if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
256      if (x2>=width())  lx2=width()-1;   else lx2=x2;
257      if (y2>=height()) ly2=height()-1;  else ly2=y2;
258 
259      if (!(lx1>lx2 || ly1>ly2))
260      {
261        if (x<c->x1)
262        { lx1+=(c->x1-x); x=c->x1; }
263
264        if (y<c->y1)
265        { ly1+=(c->y1-y); y=c->y1; }
266
267
268        if (x+lx2-lx1+1>c->x2)
269          lx2=c->x2-x+lx1;
270
271        if (y+ly2-ly1+1>c->y2)
272          ly2=c->y2-y+ly1;
273
274
275        w16 *source=paddr(lx1, ly1);
276        w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
277                                            y + context.yoff);
278       
279        int copy_width=((lx2-lx1)+1)*2;
280
281        if (!(lx1>lx2 || ly1>ly2))
282        {
283          to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
284          while (ly1<=ly2)
285          {             
286            memcpy(dest, source, copy_width);
287            dest=((w16 *)((w8 *)dest + to->bpl));
288            source=((w16 *)((w8 *)source + bpl));
289            ly1++;
290          }
291        }
292      }
293    }
294  }
295}
296
297
298
299void i4_image16::put_part_one_pixel_at_a_time(i4_image_class *to,
300                                              i4_coord _x,  i4_coord _y,
301                                              i4_coord x1, i4_coord y1,
302                                              i4_coord x2, i4_coord y2,
303                                              i4_draw_context_class &context)
304{
305  const i4_pixel_format *from_format=&get_pal()->source;
306  const i4_pixel_format *to_format=&to->get_pal()->source;
307
308 
309  if ((to_format->pixel_depth!=I4_16BIT ||
310      to_format->red_mask != from_format->red_mask ||
311      to_format->green_mask != from_format->green_mask ||
312      to_format->blue_mask != from_format->blue_mask) &&
313      (from_format->alpha_mask==0 || to_format->alpha_mask))
314    // depths aren't the same do it the slow way
315    i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
316  else
317  { 
318    for (i4_rect_list_class::area_iter c=context.clip.list.begin();
319         c!=context.clip.list.end();
320         ++c)
321    {
322      i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
323
324      if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
325      if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
326      if (x2>=width())  lx2=width()-1;   else lx2=x2;
327      if (y2>=height()) ly2=height()-1;  else ly2=y2;
328 
329      if (!(lx1>lx2 || ly1>ly2))
330      {
331        if (x<c->x1)
332        { lx1+=(c->x1-x); x=c->x1; }
333
334        if (y<c->y1)
335        { ly1+=(c->y1-y); y=c->y1; }
336
337
338        if (x+lx2-lx1+1>c->x2)
339          lx2=c->x2-x+lx1;
340
341        if (y+ly2-ly1+1>c->y2)
342          ly2=c->y2-y+ly1;
343
344
345        w16 *source=paddr(lx1, ly1);
346        w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
347                                            y + context.yoff);
348       
349        int copy_width=((lx2-lx1)+1)*2;
350
351        if (!(lx1>lx2 || ly1>ly2))
352        {
353          to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
354          while (ly1<=ly2)
355          {
356            for (int fx=0; fx<copy_width/2; fx++)
357              dest[fx]=source[fx];
358             
359            dest=((w16 *)((w8 *)dest + to->bpl));
360            source=((w16 *)((w8 *)source + bpl));
361            ly1++;
362          }
363        }
364      }
365    }
366  }
367}
368
369
370
371void i4_image16::put_part_trans(i4_image_class *to,
372                                    i4_coord _x,  i4_coord _y,                             
373                                    i4_coord x1, i4_coord y1, i4_coord x2, i4_coord y2,
374                                    i4_color trans_color,
375                                    i4_draw_context_class &context)
376{
377  const i4_pixel_format *from_format=&get_pal()->source;
378  const i4_pixel_format *to_format=&to->get_pal()->source;
379
380 
381  if ((to_format->pixel_depth!=I4_16BIT ||
382      to_format->red_mask != from_format->red_mask ||
383      to_format->green_mask != from_format->green_mask ||
384      to_format->blue_mask != from_format->blue_mask) &&
385      (from_format->alpha_mask==0 || to_format->alpha_mask))
386    // depths aren't the same do it the slow way
387    i4_image_class::put_part(to, _x, _y, x1,y1,x2,y2, context);
388  else
389  {
390    i4_color tcolor=i4_pal_man.convert_32_to(trans_color, &pal->source);
391   
392    for (i4_rect_list_class::area_iter c=context.clip.list.begin();
393         c!=context.clip.list.end();++c)
394    {
395      i4_coord lx1,ly1,lx2,ly2,x=_x,y=_y;
396
397      if (x1<0) { lx1=0; _x+=-x1; } else lx1=x1;
398      if (y1<0) { ly1=0; _y+=-y1; } else ly1=y1;
399      if (x2>=width())  lx2=width()-1;   else lx2=x2;
400      if (y2>=height()) ly2=height()-1;  else ly2=y2;
401 
402      if (!(lx1>lx2 || ly1>ly2))
403      {
404        if (x<c->x1)
405        { lx1+=(c->x1-x); x=c->x1; }
406
407        if (y<c->y1)
408        { ly1+=(c->y1-y); y=c->y1; }
409
410
411        if (x+lx2-lx1+1>c->x2)
412          lx2=c->x2-x+lx1;
413
414        if (y+ly2-ly1+1>c->y2)
415          ly2=c->y2-y+ly1;
416
417
418        if (!(lx1>lx2 || ly1>ly2))
419        {
420          to->add_dirty(x,y,x+(lx2-lx1+1),y+(ly2-ly1+1),context);
421
422          w16 *source=paddr(lx1, ly1);
423          w16 *dest=((i4_image16 *)to)->paddr(x + context.xoff,
424                                              y + context.yoff);
425          int w=(lx2-lx1+1);
426         
427          for (; ly1<=ly2; ly1++)
428          {
429            for (int j=0; j<w; j++)
430            {
431              w16 c=source[j];
432              if (c!=tcolor)
433                dest[j]=c;
434            }
435           
436            source=(w16 *)((w8 *)source + bpl);
437            dest=(w16 *)((w8 *)dest + to->bpl);
438          }
439        }
440      }
441    }
442  }
443}
444
445
446void i4_image16::bar(i4_coord x1,    i4_coord y1,
447                     i4_coord x2,    i4_coord y2,
448                     i4_color color, i4_draw_context_class &context)
449{
450  w16 tcolor=i4_pal_man.convert_32_to(color, &pal->source);
451   
452  for (i4_rect_list_class::area_iter c=context.clip.list.begin();c!=context.clip.list.end();++c)
453  {   
454    i4_coord lx1,ly1,lx2,ly2;
455
456    if (x1<c->x1) lx1=c->x1; else lx1=x1;
457    if (y1<c->y1) ly1=c->y1; else ly1=y1;
458    if (x2>c->x2) lx2=c->x2; else lx2=x2;
459    if (y2>c->y2) ly2=c->y2; else ly2=y2;
460
461    if (!(lx1>lx2 || ly1>ly2))
462    {
463      w16 *d=paddr(lx1 + context.xoff, ly1+context.yoff);
464      int count=lx2-lx1+1;
465     
466      add_dirty(lx1,ly1,lx2,ly2,context);
467      for (;ly1<=ly2; ly1++)
468      {
469        for (int x=0; x<count; x++)
470          d[x]=tcolor;
471       
472        d=(w16 *)((w8 *)d + bpl);
473      }
474    }
475  }
476}
Note: See TracBrowser for help on using the repository browser.