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

Last change on this file since 115 was 115, checked in by Sam Hocevar, 11 years ago
  • Add lock() and unlock() methods to jimage objects. They're no-ops, but the Win32/DirectX version uses them all over the place because it uses DirectDraw? surfaces. One day we may wish to merge Abuse Win32's video output, or to use the SDL blending functions. You never know.
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 *)jmalloc(size,st);
103#else
104  data=(uint8_t *)jmalloc(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.