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

Last change on this file since 518 was 518, checked in by Sam Hocevar, 7 years ago

imlib: refactor dirty_rect clipping coordiantes so that the upper
bound is no longer inclusive. It will make things easier in the future.

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