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

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