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

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

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

File size: 25.3 KB
RevLine 
[56]1/*
2 *  Abuse - dark 2D side-scrolling platform game
3 *  Copyright (c) 1995 Crack dot Com
[494]4 *  Copyright (c) 2005-2011 Sam Hocevar <sam@hocevar.net>
[56]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
[512]13#include "common.h"
14
[481]15#include "timage.h"
[2]16
17void trans_image::make_color(int c)
18{
[17]19  uint8_t *dp=data;
[2]20  int y,x;
[494]21  for (y=0; y<h; y++)
[2]22  {
23    x=0;
24    while(x<w)
25    {
26      x+=*(dp++);
27      if (x<w)
[115]28      {
29    int run=*(dp++);
30    memset(dp,c,run);
31    x+=run;
32    dp+=run;
[2]33      }
34    }
35  }
36}
37
38image *trans_image::make_image()
39{
[513]40  image *im=new image(vec2i(w,h));
[115]41
[515]42  im->Lock();
[17]43  uint8_t *d=im->scan_line(0),*dp=data,*dline;
[2]44  int y,x;
[494]45  for (y=0; y<h; y++)
[2]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)
[115]56      {
57    int run=*(dp++);
58    memcpy(dline,dp,run);
59    x+=run;
60    dline+=run;
61    dp+=run;
[2]62      }
63    }
64    d=im->next_line(y,d);
65  }
[515]66  im->Unlock();
[2]67  return im;
68}
69
[39]70trans_image::trans_image(image *im, char const *name)
[2]71{
72  int size=0,x,y;
[115]73  uint8_t *sl,*datap,*marker;
[512]74  w=im->Size().x;
75  h=im->Size().y;
[115]76
[515]77  im->Lock();
[115]78
[2]79  // first we must find out how much data to allocate
[512]80  for (y=0; y<im->Size().y; y++)
[2]81  {
82    sl=im->scan_line(y);
[115]83    x=0;
[2]84    while (x<w)
[115]85    {
86      size++;
87      while (x<w && *sl==0) { sl++; x++; }
88
[2]89      if (x<w)
90      {
[115]91        size++;  // byte for the size of the run
[2]92        while (x<w && (*sl)!=0)
93        {
[115]94      size++;
95      x++;
96      sl++;
97    }
[2]98      }
[115]99    }
100  }
[2]101
[129]102  data=(uint8_t *)malloc(size);
[512]103  int ww=im->Size().x,hh=im->Size().y;
[2]104  datap=data;
105  if (!datap)
[512]106  { printf("size = %d %d (%d)\n",im->Size().x,im->Size().y,size);  }
[2]107  CONDITION(datap,"malloc error for trans_image::data");
[115]108
[494]109  for (y=0; y<hh; y++)  // now actually make the runs
[2]110  {
111    sl=im->scan_line(y);
[115]112    x=0;
[2]113    while (x<ww)
[115]114    {
115      *datap=0;  // start the skip at 0
[512]116      while (x<im->Size().x && (*sl)==0)
[115]117      { sl++; x++; (*datap)++; }
118      datap++;
119
[2]120      if (x<ww)
121      {
122        marker=datap;   // let marker be the run size
[115]123    *marker=0;
124    datap++;    // skip over this spot
[512]125        while (x<im->Size().x && (*sl)!=0)
[115]126        {
127          (*marker)++;
128      (*datap)=*sl;
129          datap++;
130      x++;
131      sl++;
132    }
[2]133      }
[115]134    }
135  }
[515]136  im->Unlock();
[2]137}
138
[115]139void trans_image::put_scan_line(image *screen, int x, int y, int line)   // always transparent
[2]140{
[518]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?
[2]145
[17]146  uint8_t *datap=data;
[115]147  int ix;
[2]148  while (line)            // skip scan line data until we get to the line of interest
149  {
[494]150    for (ix=0; ix<w; )
[115]151    {
[2]152      ix+=*datap;        // skip blank space
153      datap++;
[115]154      if (ix<w)
155      {
156    int run_length=*datap;     // skip run
157    ix+=run_length;
158    datap+=run_length+1;
159      }
[2]160    }
[115]161    line--;
162    y++;
[2]163  }
[115]164
165
[2]166  // now slam this list of runs to the screen
[515]167  screen->Lock();
[17]168  uint8_t *screen_line=screen->scan_line(y)+x;
[115]169
[494]170  for (ix=0; ix<w; )
[115]171  {
[2]172    int skip=*datap;              // how much space to skip?
173    datap++;
174    screen_line+=skip;
[115]175    ix+=skip;
176
[2]177    if (ix<w)
[115]178    {
[2]179      int run_length=*datap;
180      datap++;
181
182      if (x+ix+run_length-1<x1)      // is this run clipped out totally?
183      {
[115]184    datap+=run_length;
185    ix+=run_length;
186    screen_line+=run_length;
[2]187      }
188      else
[115]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    }
[2]198
[518]199    if (x + ix >= x2)                      // clipped totally on the right?
[115]200        {
[515]201          screen->Unlock();
[2]202          return ;                        // we are done, return!
[115]203        }
[518]204    else if (x + ix + run_length > x2)    // partially clipped?
[115]205    {
[518]206      memcpy(screen_line, datap, x + ix + run_length - x2); // slam what we can
207      screen->Unlock();
[115]208      return ;    // and return 'cause we are done with the line
[2]209        } else
210        {
[115]211      memcpy(screen_line,datap,run_length);
212      screen_line+=run_length;
213        datap+=run_length;
214        ix+=run_length;
215        }
216      }
[2]217    }
218  }
[515]219  screen->Unlock();
[2]220}
221
222
[520]223uint8_t *trans_image::ClipToLine(image *screen, int x1, int y1, int x2, int y2,
224                                 int x, int &y, int &ysteps)
[2]225{
[520]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;
[2]229
[520]230    uint8_t *parser = data;
[2]231
[520]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
[2]235
[520]236    while (skiplines--)
237    {
238        for (int ix = 0; ix < w; )
239        {
240            ix += *parser++; // skip over empty space
[115]241
[520]242            if (ix >= w)
243                break;
[2]244
[520]245            ix += *parser;
246            parser += *parser + 1; // skip over data
[115]247        }
[2]248    }
[115]249
[520]250    screen->AddDirty(Max(x, x1), y, Min(x + width(), x2), y + h);
251    return parser;
[115]252}
[2]253
[115]254void trans_image::put_image_filled(image *screen, int x, int y,
255                   uint8_t fill_color)
[2]256{
[518]257  int x1, y1, x2, y2;
[2]258  int chop_length,ysteps;
259
[518]260  screen->GetClip(x1, y1, x2, y2);
[520]261  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]262          *screen_line;
[520]263  if (!datap)
264    return; // if ClipToLine says nothing to draw, return
[115]265
[515]266  screen->Lock();
[115]267
268  screen_line=screen->scan_line(y)+x;
[512]269  int sw=screen->Size().x-w;
[518]270  x1 -= x; x2 -= x;
[494]271  for (; ysteps>0; ysteps--)
[115]272  {
273    int ix,slam_length;
[494]274    for (ix=0; ix<w; )
[2]275    {
276      int blank=(*datap);
277      memset(screen_line,fill_color,blank);
278      ix+=blank;       // skip over empty space
279      screen_line+=blank;
280
[115]281      datap++;
282      if (ix<w)
283      {
284    slam_length=*datap;     // find the length of this run
285    datap++;
[518]286    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
[115]287    {
288      datap+=slam_length;
289      ix+=slam_length;
290      screen_line+=slam_length;
[2]291    }
[115]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      {
[518]315        if (ix + slam_length >= x2) // see if right side needs to be chopped off
316          memcpy(screen_line, datap, x2 - ix);
[115]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    }
[2]326    screen_line+=sw;
[115]327  }
[515]328  screen->Unlock();
[2]329}
330
[17]331void trans_image::put_image_offseted(image *screen, uint8_t *s_off)   // if screen x & y offset already calculated save a mul
[2]332{
333  int ix,ysteps=height();
[115]334  int screen_skip;
[17]335  uint8_t skip,*datap=data;
[115]336
[515]337  screen->Lock();
[512]338  screen_skip = screen->Size().x - w;
[494]339  for (; ysteps; ysteps--)
[2]340  {
[494]341    for (ix=0; ix<w; )
[2]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))
[115]349          printf("bad write in trans_image::put_image_offseted");
[2]350
351
352      if (ix<w)
353      {
[115]354    skip=*datap;
355    datap++;
356    memcpy(s_off,datap,skip);
357    datap+=skip;
358    s_off+=skip;
359    ix+=skip;
[2]360
[512]361    if (s_off>=screen->scan_line(screen->Size().y+1))
[115]362            printf("bad write in trans_image::put_image_offseted");
[2]363      }
364    }
365    s_off+=screen_skip;
366  }
[515]367  screen->Unlock();
[2]368}
369
[115]370void trans_image::put_image(image *screen, int x, int y)
[2]371{
[518]372  int x1, y1, x2, y2;
[2]373  int chop_length,ysteps;
374
[518]375  screen->GetClip(x1, y1, x2, y2);
[520]376  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]377          *screen_line;
[520]378  if (!datap) return; // if ClipToLine says nothing to draw, return
[115]379
[515]380  screen->Lock();
[115]381  screen_line=screen->scan_line(y)+x;
[512]382  int sw=screen->Size().x;
[518]383  x1 -= x; x2 -= x;
[494]384  for (; ysteps>0; ysteps--)
[115]385  {
386    int ix,slam_length;
[494]387    for (ix=0; ix<w; )
[2]388    {
389      ix+=(*datap);       // skip over empty space
[115]390      datap++;
391      if (ix<w)
392      {
393    slam_length=*datap;     // find the length of this run
394    datap++;
[518]395    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
[115]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);
[2]405
[115]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      {
[518]421        if (ix + slam_length >= x2) // see if right side needs to be chopped off
422          memcpy(screen_line + ix, datap, x2 - ix);
[115]423        else
424          memcpy(screen_line+ix,datap,slam_length);
425        datap+=slam_length;
426        ix+=slam_length;
427      }
[2]428    }
[115]429      }
430    }
[2]431    screen_line+=sw;
[115]432  }
[515]433  screen->Unlock();
[2]434}
435
[115]436void trans_image::put_remaped(image *screen, int x, int y, uint8_t *remap)
[2]437{
[518]438  int x1, y1, x2, y2;
439  int chop_length, ysteps;
[2]440
[518]441  screen->GetClip(x1, y1, x2, y2);
[520]442  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]443          *screen_line;
[520]444  if (!datap) return; // if ClipToLine says nothing to draw, return
[115]445
[515]446  screen->Lock();
[115]447  screen_line=screen->scan_line(y)+x;
[512]448  int sw=screen->Size().x;
[518]449  x1 -= x; x2 -= x;
[494]450  for (; ysteps>0; ysteps--)
[115]451  {
452    int ix,slam_length;
[494]453    for (ix=0; ix<w; )
[2]454    {
455      ix+=(*datap);       // skip over empty space
[115]456      datap++;
457      if (ix<w)
458      {
459    slam_length=*datap;     // find the length of this run
460    datap++;
[518]461    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
[115]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);
[2]471
[115]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      }
[2]484
485
[115]486      if (slam_length)   // see if there is anything left to slam
487      {
488        int counter;
[518]489        if (ix + slam_length >= x2) // see if right side needs to be chopped off
490          counter = x2 - ix;
[115]491        else
[518]492          counter = slam_length;
[115]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      }
[2]505    }
[115]506      }
507    }
[2]508    screen_line+=sw;
[115]509  }
[515]510  screen->Unlock();
[2]511}
512
513
514
[115]515void trans_image::put_double_remaped(image *screen, int x, int y, uint8_t *remap, uint8_t *remap2)
[2]516{
[518]517  int x1, y1, x2, y2;
518  int chop_length, ysteps;
[2]519
[518]520  screen->GetClip(x1, y1, x2, y2);
[520]521  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]522          *screen_line;
[520]523  if (!datap) return; // if ClipToLine says nothing to draw, return
[115]524
[515]525  screen->Lock();
[115]526  screen_line=screen->scan_line(y)+x;
[512]527  int sw=screen->Size().x;
[518]528  x1 -= x; x2 -= x;
[494]529  for (; ysteps>0; ysteps--)
[115]530  {
531    int ix,slam_length;
[494]532    for (ix=0; ix<w; )
[2]533    {
534      ix+=(*datap);       // skip over empty space
[115]535      datap++;
536      if (ix<w)
537      {
538    slam_length=*datap;     // find the length of this run
539    datap++;
[518]540    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
[115]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);
[2]550
[115]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      }
[2]563
564
[115]565      if (slam_length)   // see if there is anything left to slam
566      {
567        int counter;
[518]568        if (ix + slam_length >= x2) // see if right side needs to be chopped off
569          counter = x2 - ix;
[115]570        else
[518]571          counter = slam_length;
[115]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      }
[2]584    }
[115]585      }
586    }
[2]587    screen_line+=sw;
[115]588  }
[515]589  screen->Unlock();
[2]590}
591
592
593
594void trans_image::put_fade(image *screen, int x, int y,
[115]595               int frame_on, int total_frames,
596               color_filter *f, palette *pal)
[2]597{
[518]598  int x1, y1, x2, y2;
[2]599  int ix,slam_length,chop_length,ysteps;
600
[518]601  screen->GetClip(x1, y1, x2, y2);
[520]602  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]603          *screen_line;
[520]604  if (!datap) return;
[2]605
[17]606  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
[2]607                *caddr1,*caddr2,r_dest,g_dest,b_dest;
608
609  long fixmul=(frame_on<<16)/total_frames;
[515]610  screen->Lock();
[494]611  for (; ysteps>0; ysteps--,y++)
[115]612  {
[2]613    screen_line=screen->scan_line(y);
[115]614
[494]615    for (ix=0; ix<w; )
[2]616    {
617      ix+=(*datap);       // skip over empty space
[115]618      datap++;
619      if (ix<w)
620      {
621    slam_length=*datap;     // find the length of this run
622    datap++;
[518]623    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
[115]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);
[2]633
[115]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      }
[2]646
[115]647      if (slam_length)   // see if there is anything left to slam
648      {
[518]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;
[115]653        screen_run=screen_line+x+ix;
[2]654
[115]655        slam_length-=chop_length;
656        ix+=chop_length;
[2]657
[115]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  }
[515]682  screen->Unlock();
[2]683}
684
685
686
687
688void trans_image::put_fade_tint(image *screen, int x, int y,
[115]689                int frame_on, int total_frames,
690                uint8_t *tint,
691                color_filter *f, palette *pal)
[2]692{
[518]693  int x1, y1, x2, y2;
[2]694  int ix,slam_length,chop_length,ysteps;
695
[518]696  screen->GetClip(x1, y1, x2, y2);
[520]697  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]698          *screen_line;
[520]699  if (!datap) return;
[2]700
[515]701  screen->Lock();
[17]702  uint8_t *screen_run,*paddr=(uint8_t *)pal->addr(),
[2]703                *caddr1,*caddr2,r_dest,g_dest,b_dest;
704
705  long fixmul=(frame_on<<16)/total_frames;
[494]706  for (; ysteps>0; ysteps--,y++)
[115]707  {
[2]708    screen_line=screen->scan_line(y);
[115]709
[494]710    for (ix=0; ix<w; )
[2]711    {
712      ix+=(*datap);       // skip over empty space
[115]713      datap++;
714      if (ix<w)
715      {
716    slam_length=*datap;     // find the length of this run
717    datap++;
[518]718    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
[115]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);
[2]728
[115]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      }
[2]741
[115]742      if (slam_length)   // see if there is anything left to slam
743      {
[518]744        if (x + ix + slam_length >= x2) // see if right side needs to be chopped off
745          chop_length = x2 - 1 - x - ix;
[115]746        else chop_length=slam_length;
747        screen_run=screen_line+x+ix;
[2]748
[115]749        slam_length-=chop_length;
750        ix+=chop_length;
[2]751
[115]752        while (chop_length--)
753        {
754          caddr1=paddr+(int)(*screen_run)*3;
755          caddr2=paddr+(int)(tint[*datap])*3;
[2]756
[115]757          r_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
758          caddr1++; caddr2++;
[2]759
[115]760          g_dest=((((int)(*caddr1)-(int)(*caddr2))*fixmul)>>16)+(int)(*caddr2);
761          caddr1++; caddr2++;
[2]762
[115]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);
[2]765
[115]766          screen_run++;
767          datap++;
768        }
769        datap+=slam_length;
770        ix+=slam_length;
771      }
772    }
773      }
774    }
775  }
[515]776  screen->Unlock();
[115]777}
[2]778
[115]779void trans_image::put_color(image *screen, int x, int y, int color)
[2]780{
[518]781  int x1, y1, x2, y2;
[2]782  int ix,slam_length,chop_length,ysteps;
[115]783
[518]784  screen->GetClip(x1, y1, x2, y2);
[520]785  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]786          *screen_line;
[520]787  if (!datap) return;
[115]788
[515]789  screen->Lock();
[494]790  for (; ysteps>0; ysteps--,y++)
[115]791  {
[2]792    screen_line=screen->scan_line(y);
[115]793
[494]794    for (ix=0; ix<w; )
[2]795    {
796      ix+=(*datap);       // skip over empty space
[115]797      datap++;
798      if (ix<w)
799      {
800    slam_length=*datap;     // find the length of this run
801    datap++;
[518]802    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
[115]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);
[2]812
[115]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      {
[518]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);
[115]830        else
[518]831          memset(screen_line + x + ix, color, slam_length);
[115]832        datap+=slam_length;
833        ix+=slam_length;
834      }
835    }
836      }
837    }
838  }
[515]839  screen->Unlock();
[2]840}
841
842
843// ASSUMES that the blend image completly covers this image
[115]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)
[2]846
847{
[518]848  int x1, y1, x2, y2;
[2]849  int ix,slam_length,chop_length,ysteps;
[115]850  uint8_t *paddr=(uint8_t *)pal->addr();
851
[518]852  screen->GetClip(x1, y1, x2, y2);
[520]853  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]854          *blend_line, *screen_line;
[520]855  if (!datap) return;
[512]856  CONDITION(y>=blendy && y+ysteps<blendy+blend->Size().y+1,"Blend doesn't fit on trans_image");
[115]857
[2]858  blend_amount=16-blend_amount;
[115]859
[515]860  screen->Lock();
[494]861  for (; ysteps>0; ysteps--,y++)
[115]862  {
[2]863    screen_line=screen->scan_line(y);
864    blend_line=blend->scan_line(y-blendy);
[115]865
866
[494]867    for (ix=0; ix<w; )
[2]868    {
869      ix+=(*datap);       // skip over empty space
[115]870      datap++;
871      if (ix<w)
872      {
873    slam_length=*datap;     // find the length of this run
874    datap++;
[518]875    if (x + ix + slam_length < x1 || x + ix >= x2)  // see if this run is totally clipped
[115]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);
[2]885
[115]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      }
[2]898
[115]899      if (slam_length)   // see if there is anything left to slam
900      {
[2]901
[518]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;
[2]906
[115]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;
[2]910
[115]911        slam_length-=chop_length;
912        ix+=chop_length;
[2]913
914
[115]915        while (chop_length--)
916        {
917          caddr1=paddr+(int)(*blend_run)*3;
918          caddr2=paddr+(int)(*datap)*3;
[2]919
[115]920          r_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
921          caddr1++; caddr2++;
[2]922
[115]923          g_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
924          caddr1++; caddr2++;
[2]925
[115]926          b_dest=((int)(*caddr1)-(int)(*caddr2))*blend_amount/16+(int)(*caddr2);
[2]927
[115]928          *screen_run=f->lookup_color(r_dest>>3,g_dest>>3,b_dest>>3);
[2]929
[115]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
[515]944  screen->Unlock();
[2]945}
946
[115]947void trans_image::put_predator(image *screen, int x, int y)
[2]948{
[518]949  int x1, y1, x2, y2;
[2]950  int chop_length,ysteps;
951
[518]952  screen->GetClip(x1, y1, x2, y2);
[520]953  uint8_t *datap = ClipToLine(screen, x1, y1, x2, y2, x, y, ysteps),
[518]954          *screen_line;
[520]955  if (!datap) return; // if ClipToLine says nothing to draw, return
[2]956
957  // see if the last scanline is clipped off
[518]958  if (y + ysteps == y2 - 1) ysteps -= 2;
959  else if (y + ysteps == y2 - 2) ysteps--;
[2]960/*  {
[494]961    for (int x=0; x<w; )
[2]962    {
963      int skip=*datap; datap++;
964      x+=skip;
965      if (x<w)
966      {
[115]967    int run_size=*datap;
968    datap+=run_size+1;
969    x+=run_size;
[2]970      }
971    }
[518]972    if (y==y2 - 1)
[2]973      return;
974    else
[115]975      y++;
[2]976  }*/
[115]977
[515]978  screen->Lock();
[115]979  screen_line=screen->scan_line(y)+x;
[512]980  int sw=screen->Size().x;
[518]981  x1 -= x; x2 -= x;
[494]982  for (; ysteps>0; ysteps--)
[115]983  {
984    int ix,slam_length;
[494]985    for (ix=0; ix<w; )
[2]986    {
987      ix+=(*datap);       // skip over empty space
[115]988      datap++;
989      if (ix<w)
990      {
991    slam_length=*datap;     // find the length of this run
992    datap++;
[518]993    if (ix + slam_length < x1 || ix >= x2)  // see if this run is totally clipped
[115]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);
[2]1003
[115]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      {
[518]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);
[115]1021        else
[518]1022          memcpy(screen_line + ix, screen_line + sw + sw + ix, slam_length);
[115]1023        datap+=slam_length;
1024        ix+=slam_length;
1025      }
[2]1026    }
[115]1027      }
1028    }
[2]1029    screen_line+=sw;
[115]1030  }
[515]1031  screen->Unlock();
[2]1032}
1033
1034int trans_image::size()
1035{
[17]1036  uint8_t *d=data;
[2]1037  int t=0;
[494]1038  for (int y=0; y<h; y++)
[2]1039  {
1040    int x=0;
1041    while (x<w)
1042    {
1043      x+=*d; d++; t++;
1044      if (x<w)
1045      {
[115]1046    int s=*d; d++; t+=s+1;
1047    d+=s;
1048    x+=s;
1049      }
[2]1050    }
1051  }
1052  return t+4+4;
1053}
Note: See TracBrowser for help on using the repository browser.