source: abuse/trunk/src/imlib/timage.cpp @ 512

Last change on this file since 512 was 512, checked in by Sam Hocevar, 12 years ago

imlib: use vec2i for image::size and unroll all necessary changes
everywhere else in the code.

File size: 25.1 KB
Line 
1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
5 *
6 *  This software was released into the Public Domain. As with most public
7 *  domain software, no warranty is made or implied by Crack dot Com or
8 *  Jonathan Clark.
9 */
10
11#include "config.h"
12
13#include "common.h"
14
15#include "timage.h"
16
17void trans_image::make_color(int c)
18{
19  uint8_t *dp=data;
20  int y,x;
21  for (y=0; y<h; y++)
22  {
23    x=0;
24    while(x<w)
25    {
26      x+=*(dp++);
27      if (x<w)
28      {
29    int run=*(dp++);
30    memset(dp,c,run);
31    x+=run;
32    dp+=run;
33      }
34    }
35  }
36}
37
38image *trans_image::make_image()
39{
40  image *im=new image(w,h);
41
42  im->lock();
43  uint8_t *d=im->scan_line(0),*dp=data,*dline;
44  int y,x;
45  for (y=0; y<h; y++)
46  {
47    x=0;
48    dline=d;
49    memset(dline,0,w);
50    while(x<w)
51    {
52      int skip=*(dp++);
53      dline+=skip;
54      x+=skip;
55      if (x<w)
56      {
57    int run=*(dp++);
58    memcpy(dline,dp,run);
59    x+=run;
60    dline+=run;
61    dp+=run;
62      }
63    }
64    d=im->next_line(y,d);
65  }
66  im->unlock();
67  return im;
68}
69
70trans_image::trans_image(image *im, char const *name)
71{
72  int size=0,x,y;
73  uint8_t *sl,*datap,*marker;
74  w=im->Size().x;
75  h=im->Size().y;
76
77  im->lock();
78
79  // first we must find out how much data to allocate
80  for (y=0; y<im->Size().y; y++)
81  {
82    sl=im->scan_line(y);
83    x=0;
84    while (x<w)
85    {
86      size++;
87      while (x<w && *sl==0) { sl++; x++; }
88
89      if (x<w)
90      {
91        size++;  // byte for the size of the run
92        while (x<w && (*sl)!=0)
93        {
94      size++;
95      x++;
96      sl++;
97    }
98      }
99    }
100  }
101
102  data=(uint8_t *)malloc(size);
103  int ww=im->Size().x,hh=im->Size().y;
104  datap=data;
105  if (!datap)
106  { printf("size = %d %d (%d)\n",im->Size().x,im->Size().y,size);  }
107  CONDITION(datap,"malloc error for trans_image::data");
108
109  for (y=0; y<hh; y++)  // now actually make the runs
110  {
111    sl=im->scan_line(y);
112    x=0;
113    while (x<ww)
114    {
115      *datap=0;  // start the skip at 0
116      while (x<im->Size().x && (*sl)==0)
117      { sl++; x++; (*datap)++; }
118      datap++;
119
120      if (x<ww)
121      {
122        marker=datap;   // let marker be the run size
123    *marker=0;
124    datap++;    // skip over this spot
125        while (x<im->Size().x && (*sl)!=0)
126        {
127          (*marker)++;
128      (*datap)=*sl;
129          datap++;
130      x++;
131      sl++;
132    }
133      }
134    }
135  }
136  im->unlock();
137}
138
139void trans_image::put_scan_line(image *screen, int x, int y, int line)   // always transparent
140{
141  int16_t x1,y1,x2,y2;
142  screen->get_clip(x1,y1,x2,y2);
143  if (y+line<y1 || y+line>y2 || x>x2 || x+w-1<x1)            // clipped off completely?
144    return;
145
146  uint8_t *datap=data;
147  int ix;
148  while (line)            // skip scan line data until we get to the line of interest
149  {
150    for (ix=0; ix<w; )
151    {
152      ix+=*datap;        // skip blank space
153      datap++;
154      if (ix<w)
155      {
156    int run_length=*datap;     // skip run
157    ix+=run_length;
158    datap+=run_length+1;
159      }
160    }
161    line--;
162    y++;
163  }
164
165
166  // now slam this list of runs to the screen
167  screen->lock();
168  uint8_t *screen_line=screen->scan_line(y)+x;
169
170  for (ix=0; ix<w; )
171  {
172    int skip=*datap;              // how much space to skip?
173    datap++;
174    screen_line+=skip;
175    ix+=skip;
176
177    if (ix<w)
178    {
179      int run_length=*datap;
180      datap++;
181
182      if (x+ix+run_length-1<x1)      // is this run clipped out totally?
183      {
184    datap+=run_length;
185    ix+=run_length;
186    screen_line+=run_length;
187      }
188      else
189      {
190    if (x+ix<x1)                 // is the run clipped partially?
191    {
192      int clip=(x1-(x+ix));
193      datap+=clip;
194      run_length-=clip;
195      screen_line+=clip;
196      ix+=clip;
197    }
198
199    if (x+ix>x2)                      // clipped totally on the right?
200        {
201          screen->unlock();
202          return ;                        // we are done, return!
203        }
204    else if (x+ix+run_length-1>x2)    // partially clipped?
205    {
206      memcpy(screen_line,datap,(x+ix+run_length-1)-x2);   // slam what we can
207          screen->unlock();
208      return ;    // and return 'cause we are done with the line
209        } else
210        {
211      memcpy(screen_line,datap,run_length);
212      screen_line+=run_length;
213        datap+=run_length;
214        ix+=run_length;
215        }
216      }
217    }
218  }
219  screen->unlock();
220}
221
222
223inline uint8_t *trans_image::clip_y(image *screen, int x1, int y1, int x2, int y2,
224                   int x, int &y, int &ysteps)
225{
226  // check to see if it is total clipped out first
227  if (y+h<=y1 || y>y2 || x>x2 || x+w<=x1)
228    return NULL;
229
230  uint8_t *datap=data;
231
232
233  ysteps=height();
234
235  if (y<y1)  // check to see if the image gets clipped at the top
236  {
237
238
239    // because data is stored in runs, we need to skip over the top clipped portion
240    int skips=(y1-y);     // how many lines do we need to skip?
241    ysteps-=skips;        // reduce h (number of lines to draw)
242    y=y1;                // start drawing here now
243    while (skips--)
244    {
245      int ix=0;
246      while (ix<w)
247      {
248        ix+=(*datap);       // skip over empty space
249        datap++;
250        if (ix<w)
251        { ix+=*datap;
252        datap+=(*datap)+1;   // skip over data
253        }
254      }
255    }
256  }
257
258  if (y+ysteps>y2)  // check to see if it gets clipped at the bottom
259    ysteps-=(y+ysteps-y2-1);
260
261  screen->add_dirty(Max(x,x1),y,Min(x+width()-1,x2),y+h-1);
262  return datap;
263}
264
265void trans_image::put_image_filled(image *screen, int x, int y,
266                   uint8_t fill_color)
267{
268 int16_t x1,y1,x2,y2;
269  int chop_length,ysteps;
270
271  screen->get_clip(x1,y1,x2,y2);
272  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
273  if (!datap) return ;     // if clip_y says nothing to draw, return
274
275  screen->lock();
276
277  screen_line=screen->scan_line(y)+x;
278  int sw=screen->Size().x-w;
279  x1-=x; x2-=x;
280  for (; ysteps>0; ysteps--)
281  {
282    int ix,slam_length;
283    for (ix=0; ix<w; )
284    {
285      int blank=(*datap);
286      memset(screen_line,fill_color,blank);
287      ix+=blank;       // skip over empty space
288      screen_line+=blank;
289
290      datap++;
291      if (ix<w)
292      {
293    slam_length=*datap;     // find the length of this run
294    datap++;
295    if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
296    {
297      datap+=slam_length;
298      ix+=slam_length;
299      screen_line+=slam_length;
300    }
301    else
302    {
303      if (ix<x1)                // the left side needs to be chopped ?
304      {
305        chop_length=(x1-ix);
306
307        if (chop_length>=slam_length)  // see if we chopped it all off
308        {                              // yes, we did
309          ix+=slam_length;             // advance everything to the end of run
310          screen_line+=slam_length;
311          datap+=slam_length;
312          slam_length=0;
313        } else
314        {
315          slam_length-=chop_length;   // else advance everything to begining of slam
316          ix+=chop_length;
317          screen_line+=chop_length;
318          datap+=chop_length;
319        }
320      }
321
322      if (slam_length)   // see if there is anything left to slam
323      {
324        if (ix+slam_length>x2) // see if right side needs to be chopped off
325          memcpy(screen_line,datap,x2-ix+1);
326        else
327          memcpy(screen_line,datap,slam_length);
328        datap+=slam_length;
329        ix+=slam_length;
330        screen_line+=slam_length;
331      }
332    }
333      }
334    }
335    screen_line+=sw;
336  }
337  screen->unlock();
338}
339
340void trans_image::put_image_offseted(image *screen, uint8_t *s_off)   // if screen x & y offset already calculated save a mul
341{
342  int ix,ysteps=height();
343  int screen_skip;
344  uint8_t skip,*datap=data;
345
346  screen->lock();
347  screen_skip = screen->Size().x - w;
348  for (; ysteps; ysteps--)
349  {
350    for (ix=0; ix<w; )
351    {
352      skip=*datap;       // skip leading blank space
353      datap++;
354      ix+=skip;
355      s_off+=skip;
356
357      if (s_off<screen->scan_line(0))
358          printf("bad write in trans_image::put_image_offseted");
359
360
361      if (ix<w)
362      {
363    skip=*datap;
364    datap++;
365    memcpy(s_off,datap,skip);
366    datap+=skip;
367    s_off+=skip;
368    ix+=skip;
369
370    if (s_off>=screen->scan_line(screen->Size().y+1))
371            printf("bad write in trans_image::put_image_offseted");
372      }
373    }
374    s_off+=screen_skip;
375  }
376  screen->unlock();
377}
378
379void trans_image::put_image(image *screen, int x, int y)
380{
381  int16_t x1,y1,x2,y2;
382  int chop_length,ysteps;
383
384  screen->get_clip(x1,y1,x2,y2);
385  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
386  if (!datap) return ;     // if clip_y says nothing to draw, return
387
388  screen->lock();
389  screen_line=screen->scan_line(y)+x;
390  int sw=screen->Size().x;
391  x1-=x; x2-=x;
392  for (; ysteps>0; ysteps--)
393  {
394    int ix,slam_length;
395    for (ix=0; ix<w; )
396    {
397      ix+=(*datap);       // skip over empty space
398      datap++;
399      if (ix<w)
400      {
401    slam_length=*datap;     // find the length of this run
402    datap++;
403    if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
404    {
405      datap+=slam_length;
406      ix+=slam_length;
407    }
408    else
409    {
410      if (ix<x1)                // the left side needs to be chopped ?
411      {
412        chop_length=(x1-ix);
413
414        if (chop_length>=slam_length)  // see if we chopped it all off
415        {                              // yes, we did
416          ix+=slam_length;             // advance everything to the end of run
417          datap+=slam_length;
418          slam_length=0;
419        } else
420        {
421          slam_length-=chop_length;   // else advance everything to begining of slam
422          ix+=chop_length;
423          datap+=chop_length;
424        }
425      }
426
427      if (slam_length)   // see if there is anything left to slam
428      {
429        if (ix+slam_length>x2) // see if right side needs to be chopped off
430          memcpy(screen_line+ix,datap,x2-ix+1);
431        else
432          memcpy(screen_line+ix,datap,slam_length);
433        datap+=slam_length;
434        ix+=slam_length;
435      }
436    }
437      }
438    }
439    screen_line+=sw;
440  }
441  screen->unlock();
442}
443
444void trans_image::put_remaped(image *screen, int x, int y, uint8_t *remap)
445{
446  int16_t x1,y1,x2,y2;
447  int chop_length,ysteps;
448
449  screen->get_clip(x1,y1,x2,y2);
450  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
451  if (!datap) return ;     // if clip_y says nothing to draw, return
452
453  screen->lock();
454  screen_line=screen->scan_line(y)+x;
455  int sw=screen->Size().x;
456  x1-=x; x2-=x;
457  for (; ysteps>0; ysteps--)
458  {
459    int ix,slam_length;
460    for (ix=0; ix<w; )
461    {
462      ix+=(*datap);       // skip over empty space
463      datap++;
464      if (ix<w)
465      {
466    slam_length=*datap;     // find the length of this run
467    datap++;
468    if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
469    {
470      datap+=slam_length;
471      ix+=slam_length;
472    }
473    else
474    {
475      if (ix<x1)                // the left side needs to be chopped ?
476      {
477        chop_length=(x1-ix);
478
479        if (chop_length>=slam_length)  // see if we chopped it all off
480        {                              // yes, we did
481          ix+=slam_length;             // advance everything to the end of run
482          datap+=slam_length;
483          slam_length=0;
484        } else
485        {
486          slam_length-=chop_length;   // else advance everything to begining of slam
487          ix+=chop_length;
488          datap+=chop_length;
489        }
490      }
491
492
493      if (slam_length)   // see if there is anything left to slam
494      {
495        int counter;
496        if (ix+slam_length>x2) // see if right side needs to be chopped off
497          counter=x2-ix+1;
498        else
499          counter=slam_length;
500
501        uint8_t *sl=screen_line+ix,*sl2=datap;
502        ix+=slam_length;
503        datap+=slam_length;
504        while (counter)
505        {
506          counter--;
507          *(sl)=remap[*(sl2)];
508          sl++;
509          sl2++;
510        }
511      }
512    }
513      }
514    }
515    screen_line+=sw;
516  }
517  screen->unlock();
518}
519
520
521
522void trans_image::put_double_remaped(image *screen, int x, int y, uint8_t *remap, uint8_t *remap2)
523{
524  int16_t x1,y1,x2,y2;
525  int chop_length,ysteps;
526
527  screen->get_clip(x1,y1,x2,y2);
528  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
529  if (!datap) return ;     // if clip_y says nothing to draw, return
530
531  screen->lock();
532  screen_line=screen->scan_line(y)+x;
533  int sw=screen->Size().x;
534  x1-=x; x2-=x;
535  for (; ysteps>0; ysteps--)
536  {
537    int ix,slam_length;
538    for (ix=0; ix<w; )
539    {
540      ix+=(*datap);       // skip over empty space
541      datap++;
542      if (ix<w)
543      {
544    slam_length=*datap;     // find the length of this run
545    datap++;
546    if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
547    {
548      datap+=slam_length;
549      ix+=slam_length;
550    }
551    else
552    {
553      if (ix<x1)                // the left side needs to be chopped ?
554      {
555        chop_length=(x1-ix);
556
557        if (chop_length>=slam_length)  // see if we chopped it all off
558        {                              // yes, we did
559          ix+=slam_length;             // advance everything to the end of run
560          datap+=slam_length;
561          slam_length=0;
562        } else
563        {
564          slam_length-=chop_length;   // else advance everything to begining of slam
565          ix+=chop_length;
566          datap+=chop_length;
567        }
568      }
569
570
571      if (slam_length)   // see if there is anything left to slam
572      {
573        int counter;
574        if (ix+slam_length>x2) // see if right side needs to be chopped off
575          counter=x2-ix+1;
576        else
577          counter=slam_length;
578
579        uint8_t *sl=screen_line+ix,*sl2=datap;
580        ix+=slam_length;
581        datap+=slam_length;
582        while (counter)
583        {
584          counter--;
585          *(sl)=remap2[remap[*(sl2)]];
586          sl++;
587          sl2++;
588        }
589      }
590    }
591      }
592    }
593    screen_line+=sw;
594  }
595  screen->unlock();
596}
597
598
599
600void trans_image::put_fade(image *screen, int x, int y,
601               int frame_on, int total_frames,
602               color_filter *f, palette *pal)
603{
604  int16_t x1,y1,x2,y2;
605  int ix,slam_length,chop_length,ysteps;
606
607  screen->get_clip(x1,y1,x2,y2);
608  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
609                *screen_line;
610  if (!datap) return ;
611
612  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
613                *caddr1,*caddr2,r_dest,g_dest,b_dest;
614
615  long fixmul=(frame_on<<16)/total_frames;
616  screen->lock();
617  for (; ysteps>0; ysteps--,y++)
618  {
619    screen_line=screen->scan_line(y);
620
621    for (ix=0; ix<w; )
622    {
623      ix+=(*datap);       // skip over empty space
624      datap++;
625      if (ix<w)
626      {
627    slam_length=*datap;     // find the length of this run
628    datap++;
629    if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
630    {
631      datap+=slam_length;
632      ix+=slam_length;
633    }
634    else
635    {
636      if (x+ix<x1)                // the left side needs to be chopped ?
637      {
638        chop_length=(x1-x-ix);
639
640        if (chop_length>=slam_length)  // see if we chopped it all off
641        {                              // yes, we did
642          ix+=slam_length;             // advance everything to the end of run
643          datap+=slam_length;
644          slam_length=0;
645        } else
646        {
647          slam_length-=chop_length;   // else advance everything to begining of slam
648          ix+=chop_length;
649          datap+=chop_length;
650        }
651      }
652
653      if (slam_length)   // see if there is anything left to slam
654      {
655        if (x+ix+slam_length>x2) // see if right side needs to be chopped off
656          chop_length=x2-x-ix;
657        else chop_length=slam_length;
658        screen_run=screen_line+x+ix;
659
660        slam_length-=chop_length;
661        ix+=chop_length;
662
663        while (chop_length--)
664        {
665          caddr1=paddr+(int)(*screen_run)*3;
666          caddr2=paddr+(int)(*datap)*3;
667
668          r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
669          caddr1++; caddr2++;
670
671          g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
672          caddr1++; caddr2++;
673
674          b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
675          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
676
677          screen_run++;
678          datap++;
679        }
680        datap+=slam_length;
681        ix+=slam_length;
682      }
683    }
684      }
685    }
686  }
687  screen->unlock();
688}
689
690
691
692
693void trans_image::put_fade_tint(image *screen, int x, int y,
694                int frame_on, int total_frames,
695                uint8_t *tint,
696                color_filter *f, palette *pal)
697{
698  int16_t x1,y1,x2,y2;
699  int ix,slam_length,chop_length,ysteps;
700
701  screen->get_clip(x1,y1,x2,y2);
702  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
703                *screen_line;
704  if (!datap) return ;
705
706  screen->lock();
707  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
708                *caddr1,*caddr2,r_dest,g_dest,b_dest;
709
710  long fixmul=(frame_on<<16)/total_frames;
711  for (; ysteps>0; ysteps--,y++)
712  {
713    screen_line=screen->scan_line(y);
714
715    for (ix=0; ix<w; )
716    {
717      ix+=(*datap);       // skip over empty space
718      datap++;
719      if (ix<w)
720      {
721    slam_length=*datap;     // find the length of this run
722    datap++;
723    if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
724    {
725      datap+=slam_length;
726      ix+=slam_length;
727    }
728    else
729    {
730      if (x+ix<x1)                // the left side needs to be chopped ?
731      {
732        chop_length=(x1-x-ix);
733
734        if (chop_length>=slam_length)  // see if we chopped it all off
735        {                              // yes, we did
736          ix+=slam_length;             // advance everything to the end of run
737          datap+=slam_length;
738          slam_length=0;
739        } else
740        {
741          slam_length-=chop_length;   // else advance everything to begining of slam
742          ix+=chop_length;
743          datap+=chop_length;
744        }
745      }
746
747      if (slam_length)   // see if there is anything left to slam
748      {
749        if (x+ix+slam_length>x2) // see if right side needs to be chopped off
750          chop_length=x2-x-ix;
751        else chop_length=slam_length;
752        screen_run=screen_line+x+ix;
753
754        slam_length-=chop_length;
755        ix+=chop_length;
756
757        while (chop_length--)
758        {
759          caddr1=paddr+(int)(*screen_run)*3;
760          caddr2=paddr+(int)(tint[*datap])*3;
761
762          r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
763          caddr1++; caddr2++;
764
765          g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
766          caddr1++; caddr2++;
767
768          b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
769          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
770
771          screen_run++;
772          datap++;
773        }
774        datap+=slam_length;
775        ix+=slam_length;
776      }
777    }
778      }
779    }
780  }
781  screen->unlock();
782}
783
784void trans_image::put_color(image *screen, int x, int y, int color)
785{
786  int16_t x1,y1,x2,y2;
787  int ix,slam_length,chop_length,ysteps;
788
789  screen->get_clip(x1,y1,x2,y2);
790  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
791                *screen_line;
792  if (!datap) return ;
793
794  screen->lock();
795  for (; ysteps>0; ysteps--,y++)
796  {
797    screen_line=screen->scan_line(y);
798
799    for (ix=0; ix<w; )
800    {
801      ix+=(*datap);       // skip over empty space
802      datap++;
803      if (ix<w)
804      {
805    slam_length=*datap;     // find the length of this run
806    datap++;
807    if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
808    {
809      datap+=slam_length;
810      ix+=slam_length;
811    }
812    else
813    {
814      if (x+ix<x1)                // the left side needs to be chopped ?
815      {
816        chop_length=(x1-x-ix);
817
818        if (chop_length>=slam_length)  // see if we chopped it all off
819        {                              // yes, we did
820          ix+=slam_length;             // advance everything to the end of run
821          datap+=slam_length;
822          slam_length=0;
823        } else
824        {
825          slam_length-=chop_length;   // else advance everything to begining of slam
826          ix+=chop_length;
827          datap+=chop_length;
828        }
829      }
830
831      if (slam_length)   // see if there is anything left to slam
832      {
833        if (x+ix+slam_length>x2) // see if right side needs to be chopped off
834          memset(screen_line+x+ix,color,x2-x-ix+1);
835        else
836          memset(screen_line+x+ix,color,slam_length);
837        datap+=slam_length;
838        ix+=slam_length;
839      }
840    }
841      }
842    }
843  }
844  screen->unlock();
845}
846
847
848// ASSUMES that the blend image completly covers this image
849void trans_image::put_blend16(image *screen, image *blend, int x, int y,
850                  int blendx, int blendy, int blend_amount, color_filter *f, palette *pal)
851
852{
853  int16_t x1,y1,x2,y2;
854  int ix,slam_length,chop_length,ysteps;
855  uint8_t *paddr=(uint8_t *)pal->addr();
856
857  screen->get_clip(x1,y1,x2,y2);
858  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),
859                *blend_line,*screen_line;
860  if (!datap) return ;
861  CONDITION(y>=blendy && y+ysteps<blendy+blend->Size().y+1,"Blend doesn't fit on trans_image");
862
863  blend_amount=16-blend_amount;
864
865  screen->lock();
866  for (; ysteps>0; ysteps--,y++)
867  {
868    screen_line=screen->scan_line(y);
869    blend_line=blend->scan_line(y-blendy);
870
871
872    for (ix=0; ix<w; )
873    {
874      ix+=(*datap);       // skip over empty space
875      datap++;
876      if (ix<w)
877      {
878    slam_length=*datap;     // find the length of this run
879    datap++;
880    if (x+ix+slam_length<x1 || x+ix>x2)  // see if this run is totally clipped
881    {
882      datap+=slam_length;
883      ix+=slam_length;
884    }
885    else
886    {
887      if (x+ix<x1)                // the left side needs to be chopped ?
888      {
889        chop_length=(x1-x-ix);
890
891        if (chop_length>=slam_length)  // see if we chopped it all off
892        {                              // yes, we did
893          ix+=slam_length;             // advance everything to the end of run
894          datap+=slam_length;
895          slam_length=0;
896        } else
897        {
898          slam_length-=chop_length;   // else advance everything to begining of slam
899          ix+=chop_length;
900          datap+=chop_length;
901        }
902      }
903
904      if (slam_length)   // see if there is anything left to slam
905      {
906
907        if (x+ix+slam_length>x2) // see if right side needs to be chopped off
908          chop_length=x2-x-ix;
909        else chop_length=slam_length;
910
911        uint8_t *screen_run=screen_line+x+ix,
912                      *blend_run=blend_line+x+ix-blendx,
913                      *caddr1,*caddr2,r_dest,g_dest,b_dest;
914
915        slam_length-=chop_length;
916        ix+=chop_length;
917
918
919        while (chop_length--)
920        {
921          caddr1=paddr+(int)(*blend_run)*3;
922          caddr2=paddr+(int)(*datap)*3;
923
924          r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
925          caddr1++; caddr2++;
926
927          g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
928          caddr1++; caddr2++;
929
930          b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
931
932          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
933
934
935          screen_run++;
936          blend_run++;
937          datap++;
938        }
939        datap+=slam_length;
940        ix+=slam_length;
941      }
942
943    }
944      }
945    }
946  }
947
948  screen->unlock();
949}
950
951void trans_image::put_predator(image *screen, int x, int y)
952{
953  int16_t x1,y1,x2,y2;
954  int chop_length,ysteps;
955
956  screen->get_clip(x1,y1,x2,y2);
957  uint8_t *datap=clip_y(screen,x1,y1,x2,y2,x,y,ysteps),*screen_line;
958  if (!datap) return ;     // if clip_y says nothing to draw, return
959
960  // see if the last scanline is clipped off
961  if (y+ysteps==y2) ysteps-=2;
962  else if (y+ysteps==y2-1) ysteps--;
963/*  {
964    for (int x=0; x<w; )
965    {
966      int skip=*datap; datap++;
967      x+=skip;
968      if (x<w)
969      {
970    int run_size=*datap;
971    datap+=run_size+1;
972    x+=run_size;
973      }
974    }
975    if (y==y2)
976      return;
977    else
978      y++;
979  }*/
980
981  screen->lock();
982  screen_line=screen->scan_line(y)+x;
983  int sw=screen->Size().x;
984  x1-=x; x2-=x;
985  for (; ysteps>0; ysteps--)
986  {
987    int ix,slam_length;
988    for (ix=0; ix<w; )
989    {
990      ix+=(*datap);       // skip over empty space
991      datap++;
992      if (ix<w)
993      {
994    slam_length=*datap;     // find the length of this run
995    datap++;
996    if (ix+slam_length<x1 || ix>x2)  // see if this run is totally clipped
997    {
998      datap+=slam_length;
999      ix+=slam_length;
1000    }
1001    else
1002    {
1003      if (ix<x1)                // the left side needs to be chopped ?
1004      {
1005        chop_length=(x1-ix);
1006
1007        if (chop_length>=slam_length)  // see if we chopped it all off
1008        {                              // yes, we did
1009          ix+=slam_length;             // advance everything to the end of run
1010          datap+=slam_length;
1011          slam_length=0;
1012        } else
1013        {
1014          slam_length-=chop_length;   // else advance everything to begining of slam
1015          ix+=chop_length;
1016          datap+=chop_length;
1017        }
1018      }
1019
1020      if (slam_length)   // see if there is anything left to slam
1021      {
1022        if (ix+slam_length>x2) // see if right side needs to be chopped off
1023          memcpy(screen_line+ix,screen_line+sw+sw+ix,x2-ix+1);
1024        else
1025          memcpy(screen_line+ix,screen_line+sw+sw+ix,slam_length);
1026        datap+=slam_length;
1027        ix+=slam_length;
1028      }
1029    }
1030      }
1031    }
1032    screen_line+=sw;
1033  }
1034  screen->unlock();
1035}
1036
1037int trans_image::size()
1038{
1039  uint8_t *d=data;
1040  int t=0;
1041  for (int y=0; y<h; y++)
1042  {
1043    int x=0;
1044    while (x<w)
1045    {
1046      x+=*d; d++; t++;
1047      if (x<w)
1048      {
1049    int s=*d; d++; t+=s+1;
1050    d+=s;
1051    x+=s;
1052      }
1053    }
1054  }
1055  return t+4+4;
1056}
Note: See TracBrowser for help on using the repository browser.