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

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

imlib: refactor and simplify trans_image::ClipToLine?().

File size: 25.3 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(vec2i(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  int x1, y1, x2, y2;
142  screen->GetClip(x1, y1, x2, y2);
143  if (y + line < y1 || y + line >= y2 || x >= x2 || x + w - 1 < x1)
144    return; // clipped off completely?
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 > x2)    // partially clipped?
205    {
206      memcpy(screen_line, datap, x + ix + run_length - 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
223uint8_t *trans_image::ClipToLine(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 totally clipped out first
227    if (y + h <= y1 || y >= y2 || x >= x2 || x + w <= x1)
228        return NULL;
229
230    uint8_t *parser = data;
231
232    int skiplines = Max(y1 - y, 0); // number of lines to skip
233    ysteps = Min(y2 - y, height() - skiplines); // number of lines to draw
234    y += skiplines; // first line to draw
235
236    while (skiplines--)
237    {
238        for (int ix = 0; ix < w; )
239        {
240            ix += *parser++; // skip over empty space
241
242            if (ix >= w)
243                break;
244
245            ix += *parser;
246            parser += *parser + 1; // skip over data
247        }
248    }
249
250    screen->AddDirty(Max(x, x1), y, Min(x + width(), x2), y + h);
251    return parser;
252}
253
254void trans_image::put_image_filled(image *screen, int x, int y,
255                   uint8_t fill_color)
256{
257  int x1, y1, x2, y2;
258  int chop_length,ysteps;
259
260  screen->GetClip(x1, y1, x2, y2);
261  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
262          *screen_line;
263  if (!datap)
264    return; // if ClipToLine says nothing to draw, return
265
266  screen->Lock();
267
268  screen_line=screen->scan_line(y)+x;
269  int sw=screen->Size().x-w;
270  x1 -= x; x2 -= x;
271  for (; ysteps>0; ysteps--)
272  {
273    int ix,slam_length;
274    for (ix=0; ix<w; )
275    {
276      int blank=(*datap);
277      memset(screen_line,fill_color,blank);
278      ix+=blank;       // skip over empty space
279      screen_line+=blank;
280
281      datap++;
282      if (ix<w)
283      {
284    slam_length=*datap;     // find the length of this run
285    datap++;
286    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
287    {
288      datap+=slam_length;
289      ix+=slam_length;
290      screen_line+=slam_length;
291    }
292    else
293    {
294      if (ix<x1)                // the left side needs to be chopped ?
295      {
296        chop_length=(x1-ix);
297
298        if (chop_length>=slam_length)  // see if we chopped it all off
299        {                              // yes, we did
300          ix+=slam_length;             // advance everything to the end of run
301          screen_line+=slam_length;
302          datap+=slam_length;
303          slam_length=0;
304        } else
305        {
306          slam_length-=chop_length;   // else advance everything to begining of slam
307          ix+=chop_length;
308          screen_line+=chop_length;
309          datap+=chop_length;
310        }
311      }
312
313      if (slam_length)   // see if there is anything left to slam
314      {
315        if (ix + slam_length >= x2) // see if right side needs to be chopped off
316          memcpy(screen_line, datap, x2 - ix);
317        else
318          memcpy(screen_line,datap,slam_length);
319        datap+=slam_length;
320        ix+=slam_length;
321        screen_line+=slam_length;
322      }
323    }
324      }
325    }
326    screen_line+=sw;
327  }
328  screen->Unlock();
329}
330
331void trans_image::put_image_offseted(image *screen, uint8_t *s_off)   // if screen x & y offset already calculated save a mul
332{
333  int ix,ysteps=height();
334  int screen_skip;
335  uint8_t skip,*datap=data;
336
337  screen->Lock();
338  screen_skip = screen->Size().x - w;
339  for (; ysteps; ysteps--)
340  {
341    for (ix=0; ix<w; )
342    {
343      skip=*datap;       // skip leading blank space
344      datap++;
345      ix+=skip;
346      s_off+=skip;
347
348      if (s_off<screen->scan_line(0))
349          printf("bad write in trans_image::put_image_offseted");
350
351
352      if (ix<w)
353      {
354    skip=*datap;
355    datap++;
356    memcpy(s_off,datap,skip);
357    datap+=skip;
358    s_off+=skip;
359    ix+=skip;
360
361    if (s_off>=screen->scan_line(screen->Size().y+1))
362            printf("bad write in trans_image::put_image_offseted");
363      }
364    }
365    s_off+=screen_skip;
366  }
367  screen->Unlock();
368}
369
370void trans_image::put_image(image *screen, int x, int y)
371{
372  int x1, y1, x2, y2;
373  int chop_length,ysteps;
374
375  screen->GetClip(x1, y1, x2, y2);
376  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
377          *screen_line;
378  if (!datap) return; // if ClipToLine says nothing to draw, return
379
380  screen->Lock();
381  screen_line=screen->scan_line(y)+x;
382  int sw=screen->Size().x;
383  x1 -= x; x2 -= x;
384  for (; ysteps>0; ysteps--)
385  {
386    int ix,slam_length;
387    for (ix=0; ix<w; )
388    {
389      ix+=(*datap);       // skip over empty space
390      datap++;
391      if (ix<w)
392      {
393    slam_length=*datap;     // find the length of this run
394    datap++;
395    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
396    {
397      datap+=slam_length;
398      ix+=slam_length;
399    }
400    else
401    {
402      if (ix<x1)                // the left side needs to be chopped ?
403      {
404        chop_length=(x1-ix);
405
406        if (chop_length>=slam_length)  // see if we chopped it all off
407        {                              // yes, we did
408          ix+=slam_length;             // advance everything to the end of run
409          datap+=slam_length;
410          slam_length=0;
411        } else
412        {
413          slam_length-=chop_length;   // else advance everything to begining of slam
414          ix+=chop_length;
415          datap+=chop_length;
416        }
417      }
418
419      if (slam_length)   // see if there is anything left to slam
420      {
421        if (ix + slam_length >= x2) // see if right side needs to be chopped off
422          memcpy(screen_line + ix, datap, x2 - ix);
423        else
424          memcpy(screen_line+ix,datap,slam_length);
425        datap+=slam_length;
426        ix+=slam_length;
427      }
428    }
429      }
430    }
431    screen_line+=sw;
432  }
433  screen->Unlock();
434}
435
436void trans_image::put_remaped(image *screen, int x, int y, uint8_t *remap)
437{
438  int x1, y1, x2, y2;
439  int chop_length, ysteps;
440
441  screen->GetClip(x1, y1, x2, y2);
442  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
443          *screen_line;
444  if (!datap) return; // if ClipToLine says nothing to draw, return
445
446  screen->Lock();
447  screen_line=screen->scan_line(y)+x;
448  int sw=screen->Size().x;
449  x1 -= x; x2 -= x;
450  for (; ysteps>0; ysteps--)
451  {
452    int ix,slam_length;
453    for (ix=0; ix<w; )
454    {
455      ix+=(*datap);       // skip over empty space
456      datap++;
457      if (ix<w)
458      {
459    slam_length=*datap;     // find the length of this run
460    datap++;
461    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
462    {
463      datap+=slam_length;
464      ix+=slam_length;
465    }
466    else
467    {
468      if (ix<x1)                // the left side needs to be chopped ?
469      {
470        chop_length=(x1-ix);
471
472        if (chop_length>=slam_length)  // see if we chopped it all off
473        {                              // yes, we did
474          ix+=slam_length;             // advance everything to the end of run
475          datap+=slam_length;
476          slam_length=0;
477        } else
478        {
479          slam_length-=chop_length;   // else advance everything to begining of slam
480          ix+=chop_length;
481          datap+=chop_length;
482        }
483      }
484
485
486      if (slam_length)   // see if there is anything left to slam
487      {
488        int counter;
489        if (ix + slam_length >= x2) // see if right side needs to be chopped off
490          counter = x2 - ix;
491        else
492          counter = slam_length;
493
494        uint8_t *sl=screen_line+ix,*sl2=datap;
495        ix+=slam_length;
496        datap+=slam_length;
497        while (counter)
498        {
499          counter--;
500          *(sl)=remap[*(sl2)];
501          sl++;
502          sl2++;
503        }
504      }
505    }
506      }
507    }
508    screen_line+=sw;
509  }
510  screen->Unlock();
511}
512
513
514
515void trans_image::put_double_remaped(image *screen, int x, int y, uint8_t *remap, uint8_t *remap2)
516{
517  int x1, y1, x2, y2;
518  int chop_length, ysteps;
519
520  screen->GetClip(x1, y1, x2, y2);
521  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
522          *screen_line;
523  if (!datap) return; // if ClipToLine says nothing to draw, return
524
525  screen->Lock();
526  screen_line=screen->scan_line(y)+x;
527  int sw=screen->Size().x;
528  x1 -= x; x2 -= x;
529  for (; ysteps>0; ysteps--)
530  {
531    int ix,slam_length;
532    for (ix=0; ix<w; )
533    {
534      ix+=(*datap);       // skip over empty space
535      datap++;
536      if (ix<w)
537      {
538    slam_length=*datap;     // find the length of this run
539    datap++;
540    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
541    {
542      datap+=slam_length;
543      ix+=slam_length;
544    }
545    else
546    {
547      if (ix<x1)                // the left side needs to be chopped ?
548      {
549        chop_length=(x1-ix);
550
551        if (chop_length>=slam_length)  // see if we chopped it all off
552        {                              // yes, we did
553          ix+=slam_length;             // advance everything to the end of run
554          datap+=slam_length;
555          slam_length=0;
556        } else
557        {
558          slam_length-=chop_length;   // else advance everything to begining of slam
559          ix+=chop_length;
560          datap+=chop_length;
561        }
562      }
563
564
565      if (slam_length)   // see if there is anything left to slam
566      {
567        int counter;
568        if (ix + slam_length >= x2) // see if right side needs to be chopped off
569          counter = x2 - ix;
570        else
571          counter = slam_length;
572
573        uint8_t *sl=screen_line+ix,*sl2=datap;
574        ix+=slam_length;
575        datap+=slam_length;
576        while (counter)
577        {
578          counter--;
579          *(sl)=remap2[remap[*(sl2)]];
580          sl++;
581          sl2++;
582        }
583      }
584    }
585      }
586    }
587    screen_line+=sw;
588  }
589  screen->Unlock();
590}
591
592
593
594void trans_image::put_fade(image *screen, int x, int y,
595               int frame_on, int total_frames,
596               color_filter *f, palette *pal)
597{
598  int x1, y1, x2, y2;
599  int ix,slam_length,chop_length,ysteps;
600
601  screen->GetClip(x1, y1, x2, y2);
602  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
603          *screen_line;
604  if (!datap) return;
605
606  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
607                *caddr1,*caddr2,r_dest,g_dest,b_dest;
608
609  long fixmul=(frame_on<<16)/total_frames;
610  screen->Lock();
611  for (; ysteps>0; ysteps--,y++)
612  {
613    screen_line=screen->scan_line(y);
614
615    for (ix=0; ix<w; )
616    {
617      ix+=(*datap);       // skip over empty space
618      datap++;
619      if (ix<w)
620      {
621    slam_length=*datap;     // find the length of this run
622    datap++;
623    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
624    {
625      datap+=slam_length;
626      ix+=slam_length;
627    }
628    else
629    {
630      if (x+ix<x1)                // the left side needs to be chopped ?
631      {
632        chop_length=(x1-x-ix);
633
634        if (chop_length>=slam_length)  // see if we chopped it all off
635        {                              // yes, we did
636          ix+=slam_length;             // advance everything to the end of run
637          datap+=slam_length;
638          slam_length=0;
639        } else
640        {
641          slam_length-=chop_length;   // else advance everything to begining of slam
642          ix+=chop_length;
643          datap+=chop_length;
644        }
645      }
646
647      if (slam_length)   // see if there is anything left to slam
648      {
649        if (x + ix + slam_length >= x2) // see if right side needs to be chopped off
650          chop_length = x2 - 1 - x - ix;
651        else
652          chop_length = slam_length;
653        screen_run=screen_line+x+ix;
654
655        slam_length-=chop_length;
656        ix+=chop_length;
657
658        while (chop_length--)
659        {
660          caddr1=paddr+(int)(*screen_run)*3;
661          caddr2=paddr+(int)(*datap)*3;
662
663          r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
664          caddr1++; caddr2++;
665
666          g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
667          caddr1++; caddr2++;
668
669          b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
670          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
671
672          screen_run++;
673          datap++;
674        }
675        datap+=slam_length;
676        ix+=slam_length;
677      }
678    }
679      }
680    }
681  }
682  screen->Unlock();
683}
684
685
686
687
688void trans_image::put_fade_tint(image *screen, int x, int y,
689                int frame_on, int total_frames,
690                uint8_t *tint,
691                color_filter *f, palette *pal)
692{
693  int x1, y1, x2, y2;
694  int ix,slam_length,chop_length,ysteps;
695
696  screen->GetClip(x1, y1, x2, y2);
697  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
698          *screen_line;
699  if (!datap) return;
700
701  screen->Lock();
702  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
703                *caddr1,*caddr2,r_dest,g_dest,b_dest;
704
705  long fixmul=(frame_on<<16)/total_frames;
706  for (; ysteps>0; ysteps--,y++)
707  {
708    screen_line=screen->scan_line(y);
709
710    for (ix=0; ix<w; )
711    {
712      ix+=(*datap);       // skip over empty space
713      datap++;
714      if (ix<w)
715      {
716    slam_length=*datap;     // find the length of this run
717    datap++;
718    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
719    {
720      datap+=slam_length;
721      ix+=slam_length;
722    }
723    else
724    {
725      if (x+ix<x1)                // the left side needs to be chopped ?
726      {
727        chop_length=(x1-x-ix);
728
729        if (chop_length>=slam_length)  // see if we chopped it all off
730        {                              // yes, we did
731          ix+=slam_length;             // advance everything to the end of run
732          datap+=slam_length;
733          slam_length=0;
734        } else
735        {
736          slam_length-=chop_length;   // else advance everything to begining of slam
737          ix+=chop_length;
738          datap+=chop_length;
739        }
740      }
741
742      if (slam_length)   // see if there is anything left to slam
743      {
744        if (x + ix + slam_length >= x2) // see if right side needs to be chopped off
745          chop_length = x2 - 1 - x - ix;
746        else chop_length=slam_length;
747        screen_run=screen_line+x+ix;
748
749        slam_length-=chop_length;
750        ix+=chop_length;
751
752        while (chop_length--)
753        {
754          caddr1=paddr+(int)(*screen_run)*3;
755          caddr2=paddr+(int)(tint[*datap])*3;
756
757          r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
758          caddr1++; caddr2++;
759
760          g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
761          caddr1++; caddr2++;
762
763          b_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
764          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
765
766          screen_run++;
767          datap++;
768        }
769        datap+=slam_length;
770        ix+=slam_length;
771      }
772    }
773      }
774    }
775  }
776  screen->Unlock();
777}
778
779void trans_image::put_color(image *screen, int x, int y, int color)
780{
781  int x1, y1, x2, y2;
782  int ix,slam_length,chop_length,ysteps;
783
784  screen->GetClip(x1, y1, x2, y2);
785  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
786          *screen_line;
787  if (!datap) return;
788
789  screen->Lock();
790  for (; ysteps>0; ysteps--,y++)
791  {
792    screen_line=screen->scan_line(y);
793
794    for (ix=0; ix<w; )
795    {
796      ix+=(*datap);       // skip over empty space
797      datap++;
798      if (ix<w)
799      {
800    slam_length=*datap;     // find the length of this run
801    datap++;
802    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
803    {
804      datap+=slam_length;
805      ix+=slam_length;
806    }
807    else
808    {
809      if (x+ix<x1)                // the left side needs to be chopped ?
810      {
811        chop_length=(x1-x-ix);
812
813        if (chop_length>=slam_length)  // see if we chopped it all off
814        {                              // yes, we did
815          ix+=slam_length;             // advance everything to the end of run
816          datap+=slam_length;
817          slam_length=0;
818        } else
819        {
820          slam_length-=chop_length;   // else advance everything to begining of slam
821          ix+=chop_length;
822          datap+=chop_length;
823        }
824      }
825
826      if (slam_length)   // see if there is anything left to slam
827      {
828        if (x + ix + slam_length >= x2) // see if right side needs to be chopped off
829          memset(screen_line + x + ix, color, x2 - x - ix);
830        else
831          memset(screen_line + x + ix, color, slam_length);
832        datap+=slam_length;
833        ix+=slam_length;
834      }
835    }
836      }
837    }
838  }
839  screen->Unlock();
840}
841
842
843// ASSUMES that the blend image completly covers this image
844void trans_image::put_blend16(image *screen, image *blend, int x, int y,
845                  int blendx, int blendy, int blend_amount, color_filter *f, palette *pal)
846
847{
848  int x1, y1, x2, y2;
849  int ix,slam_length,chop_length,ysteps;
850  uint8_t *paddr=(uint8_t *)pal->addr();
851
852  screen->GetClip(x1, y1, x2, y2);
853  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
854          *blend_line, *screen_line;
855  if (!datap) return;
856  CONDITION(y>=blendy && y+ysteps<blendy+blend->Size().y+1,"Blend doesn't fit on trans_image");
857
858  blend_amount=16-blend_amount;
859
860  screen->Lock();
861  for (; ysteps>0; ysteps--,y++)
862  {
863    screen_line=screen->scan_line(y);
864    blend_line=blend->scan_line(y-blendy);
865
866
867    for (ix=0; ix<w; )
868    {
869      ix+=(*datap);       // skip over empty space
870      datap++;
871      if (ix<w)
872      {
873    slam_length=*datap;     // find the length of this run
874    datap++;
875    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
876    {
877      datap+=slam_length;
878      ix+=slam_length;
879    }
880    else
881    {
882      if (x+ix<x1)                // the left side needs to be chopped ?
883      {
884        chop_length=(x1-x-ix);
885
886        if (chop_length>=slam_length)  // see if we chopped it all off
887        {                              // yes, we did
888          ix+=slam_length;             // advance everything to the end of run
889          datap+=slam_length;
890          slam_length=0;
891        } else
892        {
893          slam_length-=chop_length;   // else advance everything to begining of slam
894          ix+=chop_length;
895          datap+=chop_length;
896        }
897      }
898
899      if (slam_length)   // see if there is anything left to slam
900      {
901
902        if (x + ix + slam_length >= x2) // see if right side needs to be chopped off
903          chop_length = x2 - 1 - x - ix;
904        else
905          chop_length = slam_length;
906
907        uint8_t *screen_run=screen_line+x+ix,
908                      *blend_run=blend_line+x+ix-blendx,
909                      *caddr1,*caddr2,r_dest,g_dest,b_dest;
910
911        slam_length-=chop_length;
912        ix+=chop_length;
913
914
915        while (chop_length--)
916        {
917          caddr1=paddr+(int)(*blend_run)*3;
918          caddr2=paddr+(int)(*datap)*3;
919
920          r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
921          caddr1++; caddr2++;
922
923          g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
924          caddr1++; caddr2++;
925
926          b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
927
928          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
929
930
931          screen_run++;
932          blend_run++;
933          datap++;
934        }
935        datap+=slam_length;
936        ix+=slam_length;
937      }
938
939    }
940      }
941    }
942  }
943
944  screen->Unlock();
945}
946
947void trans_image::put_predator(image *screen, int x, int y)
948{
949  int x1, y1, x2, y2;
950  int chop_length,ysteps;
951
952  screen->GetClip(x1, y1, x2, y2);
953  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
954          *screen_line;
955  if (!datap) return; // if ClipToLine says nothing to draw, return
956
957  // see if the last scanline is clipped off
958  if (y + ysteps == y2 - 1) ysteps -= 2;
959  else if (y + ysteps == y2 - 2) 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 - 1)
973      return;
974    else
975      y++;
976  }*/
977
978  screen->Lock();
979  screen_line=screen->scan_line(y)+x;
980  int sw=screen->Size().x;
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);
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.