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

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

imlib: some cleaning up in trans_image before I templatise half of it.

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