source: abuse/tags/pd/macabuse/imlib/timage.c @ 57

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