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

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

lisp: implement LispList::GetLength?.

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