Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

blit_transparent.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: blit_transparent.cpp,v 1.2 2001/03/27 02:31:53 plasmoid Exp $
00003 
00004         ------------------------------------------------------------------------
00005         ClanLib, the platform independent game SDK.
00006 
00007         This library is distributed under the GNU LIBRARY GENERAL PUBLIC LICENSE
00008         version 2. See COPYING for details.
00009 
00010         For a total list of contributers see CREDITS.
00011 
00012         Alpha-only blitter.
00013         This file by Martin Starch (starch@dark.x.dtu.dk) 3/99
00014         ------------------------------------------------------------------------
00015 */
00016 
00017 #include "Core/precomp.h"
00018 #include <Display/Display/Generic/blit_alphamask_rle.h>
00019 #include <Display/Display/Generic/blit_transparent.h>
00020 #include <Display/Display/Generic/displaycard_generic.h>
00021 #include <Display/Display/Generic/pixeldata.h>
00022 
00023 #ifndef WIN32
00024 #include "Core/System/Generic/string_asm.h"
00025 #else
00026 #define fast_memmove memcpy
00027 #endif
00028 
00029 #undef USE_I386_ASSEMBLER
00030 
00031 #if !defined(WIN32) || defined(USE_TASM)
00032 
00033         /* assembler acceleration -- mbn 03/99 */
00034 
00035         extern "C"
00036         {
00037                 void blit_transparent_noclip_asm_16bpp(
00038                         unsigned char *src,
00039                         unsigned short *dest,
00040                         unsigned int width);
00041 
00042                 void blit_transparent_noclip_asm_32bpp(
00043                         unsigned char *src,
00044                         unsigned int *dest,
00045                         unsigned int width);
00046 
00047                 void blit_transparent_clip_asm_16bpp(
00048                         unsigned char *src,
00049                         unsigned short *dest,
00050                         unsigned int width);
00051 
00052                 void blit_transparent_clip_asm_32bpp(
00053                         unsigned char *src,
00054                         unsigned int *dest,
00055                         unsigned int width);
00056         }
00057 
00058 #endif
00059 
00060 
00061 CL_Blit_Transparent::CL_Blit_Transparent(
00062         CL_DisplayCard_Generic *card,
00063         CL_SurfaceProvider *provider)
00064 {
00065         m_card = card;
00066         m_provider = provider;
00067 
00068         m_contained_alpha_blitter = NULL;
00069         m_lines = NULL;
00070         m_num_lines = 0;
00071 }
00072 
00073 CL_Blit_Transparent::~CL_Blit_Transparent()
00074 {
00075         if (m_lines != NULL)
00076         {
00077                 for (unsigned int i=0;i<m_num_lines;i++) 
00078                 {
00079                         if (m_lines[i]) delete[] m_lines[i];
00080                 }
00081         }
00082         delete[] m_lines;
00083         delete m_contained_alpha_blitter;
00084 }
00085 
00086 bool CL_Blit_Transparent::init_surface(CL_Blitters *blitters)
00087 {
00088         CL_PixelData alpha(
00089                 0,
00090                 0,
00091                 0,
00092                 255,
00093                 m_provider,
00094                 1);
00095 
00096         m_num_lines = m_provider->get_height()*m_provider->get_num_frames();
00097 
00098         int bytes_pr_line = alpha.get_bytes_pr_line();
00099         unsigned char *alpha_data = new unsigned char[m_num_lines*bytes_pr_line];
00100 
00101         bool has_alpha = false;
00102         bool transparent = false;
00103 
00104         int alpha_width = alpha.get_width();
00105 
00106         unsigned int y;
00107         for (y=0;y<m_num_lines;y++)
00108         {
00109                 unsigned char *l = &alpha_data[y*bytes_pr_line];
00110                 alpha.get_line_pixel_to_dest(y, l);
00111                 
00112                 for (int x=0;x<alpha_width;x++)
00113                 {
00114                         if (l[x] == 0) transparent = true;
00115                         if (l[x] != 0 && l[x] != 255) 
00116                         {
00117 //                              std::cout << "how can this happen" << std::endl;
00118                                 transparent = true;
00119                                 has_alpha = true;
00120                                 break;
00121                         }
00122                 }
00123         }
00124 
00125         if (!transparent)
00126         {
00127                 // This blitter will handle surfaces containing transparency/alpha only
00128                 delete[] alpha_data;
00129                 return false;
00130         }
00131 
00132         CL_PixelData input(
00133                 m_card->get_target()->get_red_mask(),
00134                 m_card->get_target()->get_green_mask(),
00135                 m_card->get_target()->get_blue_mask(),
00136                 m_card->get_target()->get_alpha_mask(),
00137                 m_provider,
00138                 (m_card->get_target()->get_depth()+7)/8);
00139 
00140         m_width = m_provider->get_width();
00141         m_height = m_provider->get_height();
00142 
00143         m_lines = new unsigned char*[m_num_lines];
00144         int input_bytes_pr_line = input.get_bytes_pr_line();
00145         unsigned char *image_data = new unsigned char[m_num_lines*input_bytes_pr_line];
00146 
00147         for (y=0;y<m_num_lines;y++) 
00148         {
00149                 m_lines[y] = NULL;
00150 
00151                 unsigned char *line_dest = &image_data[y*input_bytes_pr_line];
00152 //              memset(line_dest, 0, input_bytes_pr_line); // <- debug - is memory valid?
00153                 input.get_line_pixel_to_dest(y, line_dest);
00154                 
00155                 make_line(
00156                         m_card->get_target(),
00157                         m_provider, 
00158                         y,
00159                         line_dest,
00160                         &alpha_data[y*bytes_pr_line]);
00161         }
00162 
00163         if (has_alpha)
00164         {
00165                 m_contained_alpha_blitter = new CL_Blit_AlphaMask_RLE(
00166                         m_card,
00167                         m_provider,
00168                         image_data,
00169                         input_bytes_pr_line,
00170                         alpha_data,
00171                         bytes_pr_line);
00172         }
00173 
00174         delete[] alpha_data;
00175         delete[] image_data;
00176 
00177         if (!blitters->test_clip()) blitters->set_clip(this);
00178         if (!blitters->test_noclip()) blitters->set_noclip(this);
00179         if (!blitters->test_scale_noclip()) blitters->set_scale_noclip(this);
00180         if (!blitters->test_scale_clip()) blitters->set_scale_clip(this);
00181 
00182         return true;
00183 }
00184 
00185 void CL_Blit_Transparent::make_line(
00186         CL_Target *target,
00187         CL_SurfaceProvider *provider,
00188         int line_num,
00189         unsigned char *input_data,
00190         unsigned char *alpha_data)
00191 {
00192         int dest_bytes_pr_pixel = target->get_depth()/8;
00193         cl_assert((dest_bytes_pr_pixel == 2) || (dest_bytes_pr_pixel == 4));
00194 
00195         unsigned char *data = new unsigned char[dest_bytes_pr_pixel*m_width*4];
00196 
00197         int cur_state = CL_Blit_Transparent::cmd_skip;
00198         int cmd_pos = 0;
00199         int cmd_start = 0;
00200         unsigned short *cmd_set_size = NULL;
00201 
00202         bool line_has_data = true;
00203 
00204         for (unsigned int x=0;x<m_width;x++)
00205         {
00206                 if (alpha_data[x] == 255)
00207                 {
00208                         if (cur_state == CL_Blit_Transparent::cmd_skip)
00209                         {
00210                                 unsigned short *data_ptr = (unsigned short *) (&data[cmd_pos]);
00211                                 *data_ptr = x-cmd_start;
00212                                 cmd_pos += 2;
00213 
00214                                 cmd_start = x;
00215 
00216                                 cmd_set_size = (unsigned short *) (&data[cmd_pos]);
00217                                 cmd_pos += 2;
00218 
00219                                 cur_state = CL_Blit_Transparent::cmd_copy;
00220                         }
00221 
00222                         if (dest_bytes_pr_pixel == 2)
00223                         {
00224                                 *((unsigned short *) &data[cmd_pos]) = ((unsigned short *) input_data)[x];
00225                                 cmd_pos += sizeof(unsigned short);
00226                         }
00227                         else
00228                         {
00229                                 *((unsigned int *) &data[cmd_pos]) = ((int *) input_data)[x];
00230                                 cmd_pos += sizeof(unsigned int);
00231                         }
00232                 }
00233                 else
00234                 {
00235                         if (cur_state == CL_Blit_Transparent::cmd_copy)
00236                         {
00237                                 *cmd_set_size = x - cmd_start;
00238                                 cmd_start = x;
00239 
00240                                 cur_state = CL_Blit_Transparent::cmd_skip;
00241                         }
00242                 }
00243         }
00244         if (cur_state == CL_Blit_Transparent::cmd_skip)
00245         {
00246                 if (cmd_start == 0) line_has_data = false;
00247 
00248                 unsigned short *data_ptr = (unsigned short *) &data[cmd_pos];
00249                 *data_ptr = m_width-cmd_start;
00250                 cmd_pos += 2;
00251         }
00252         else
00253         {
00254                 *cmd_set_size = m_width - cmd_start;
00255         }
00256 
00257         if (line_has_data)
00258         {
00259                 m_lines[line_num] = new unsigned char[cmd_pos];
00260                 fast_memmove((char *) (m_lines[line_num]), (char *) data, cmd_pos);
00261         }
00262         else
00263         {
00264                 m_lines[line_num] = NULL;
00265         }
00266 
00267         delete[] data;
00268 }
00269 
00270 template <class T>
00271 void SubBlitter_Transparent<T>::blt_noclip(
00272         CL_Blit_Transparent *parent,
00273         CL_Target *target,
00274         int x,
00275         int y,
00276         int spr_no)
00277 {
00278         unsigned int dest_pitch = target->get_pitch();
00279 
00280         unsigned char *dest = (unsigned char *) target->get_data();
00281         dest += x*sizeof(T) + (y-1)*dest_pitch;
00282 
00283 //      T *dd;
00284         
00285         int cur_line = parent->m_height*spr_no;
00286         for (unsigned int yy=0; yy<parent->m_height; yy++)
00287         {
00288                 dest += dest_pitch;
00289                 
00290                 unsigned char *line_data = parent->m_lines[cur_line+yy];
00291                 if (line_data == NULL) continue;
00292 
00293                 T *dd = (T *) dest;
00294                 int cur_state = CL_Blit_Transparent::cmd_copy;
00295                 
00296                 unsigned int x = *((unsigned short *) (&line_data[0]));
00297                 int lpos = 2;
00298 
00299                 /* assembler acceleration -- mbn 03/99 */
00300                 
00301 #if !defined(WIN32) || defined(USE_TASM)
00302 #ifdef USE_I386_ASSEMBLER
00303                 switch (sizeof(T))
00304                 {
00305                 case 2:
00306                         blit_transparent_noclip_asm_16bpp(
00307                                 line_data+lpos,
00308                                 (unsigned short *) (&dd[x]),
00309                                 parent->m_width-x);
00310 
00311                         break;
00312 
00313                 case 4:
00314                         blit_transparent_noclip_asm_32bpp(
00315                                 line_data+lpos,
00316                                 (unsigned int *) (&dd[x]),
00317                                 parent->m_width-x);
00318 
00319                         break;
00320 
00321                 default:
00322 #endif
00323 #endif
00324                         while (x<parent->m_width)
00325                         {
00326                                 if (cur_state == CL_Blit_Transparent::cmd_copy)
00327                                 {
00328                                         unsigned short rep = *((unsigned short *) &line_data[lpos]);
00329                                         lpos += 2;
00330 
00331                                         BltRLERow_Transparent<T>::show_row(
00332                                                 (T *) &(line_data[lpos]),
00333                                                 &dd[x],
00334                                                 rep);
00335 
00336                                         x += rep;
00337                                         lpos += sizeof(T)*rep;
00338 
00339                                         cur_state = CL_Blit_Transparent::cmd_skip;
00340                                 }
00341                                 else
00342                                 {
00343                                         unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00344                                         unsigned short skip = *skip_pos;
00345                                         x += skip;
00346                                         lpos += 2;
00347                                         cur_state = CL_Blit_Transparent::cmd_copy;
00348                                 }
00349                         }
00350 #if !defined(WIN32) || defined(USE_TASM)
00351 #ifdef USE_I386_ASSEMBLER
00352                 }
00353 #endif
00354 #endif
00355         }
00356 }
00357 
00358 void CL_Blit_Transparent::blt_noclip(
00359         CL_Target *target,
00360         int x,
00361         int y,
00362         int spr_no)
00363 {
00364         target->lock();
00365         
00366         unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00367         switch (dest_bytes_per_pixel)
00368         {
00369         case 2:
00370                 SubBlitter_Transparent<unsigned short>::blt_noclip(this, target, x, y, spr_no);
00371                 break;
00372         case 4:
00373                 SubBlitter_Transparent<unsigned int>::blt_noclip(this, target, x, y, spr_no);
00374                 break;
00375         default:
00376                 cl_assert(false);
00377                 break;
00378         }
00379 
00380         target->unlock();
00381 
00382         if (m_contained_alpha_blitter != NULL)
00383         {
00384                 m_contained_alpha_blitter->blt_noclip(target, x, y, spr_no);
00385         }
00386 }
00387 
00388 template <class T>
00389 void SubBlitter_Transparent<T>::blt_clip(
00390         CL_Blit_Transparent *parent,
00391         CL_Target *target,
00392         int x,
00393         int y,
00394         int spr_no, 
00395         const CL_ClipRect &clip)
00396 {
00397         CL_ClipRect dest_clip(x, y, x+parent->m_width, y+parent->m_height);
00398         CL_ClipRect clipped = clip.clip(dest_clip);
00399         
00400         if (clipped.m_x1 >= clipped.m_x2 ||
00401             clipped.m_y1 >= clipped.m_y2) return;
00402 
00403         target->lock();
00404 
00405         unsigned int dest_pitch = target->get_pitch();
00406 
00407         unsigned char *dest = (unsigned char *) target->get_data();
00408         dest += clipped.m_x1*sizeof(T) + clipped.m_y1*dest_pitch;
00409 
00410         int src_delta_x = clipped.m_x1-dest_clip.m_x1;
00411         int src_delta_y = clipped.m_y1-dest_clip.m_y1;
00412 
00413         unsigned int size_x = clipped.m_x2-clipped.m_x1;
00414         unsigned int size_y = clipped.m_y2-clipped.m_y1;
00415 
00416         int offset_line = parent->m_height*spr_no + src_delta_y;
00417 
00418         for (unsigned int yy=0; yy<size_y; yy++)
00419         {
00420                 unsigned char *line_data = parent->m_lines[offset_line+yy];
00421                 if (line_data == NULL) continue;
00422 
00423                 T       *dd = (T *) (dest+yy*dest_pitch);
00424 
00425                 unsigned short src_pos = *((unsigned short *) (&line_data[0]));
00426                 int cur_state = CL_Blit_Transparent::cmd_copy;
00427                 int lpos = 2;
00428 
00429                 while (src_pos < src_delta_x)
00430                 {
00431                         if (cur_state == CL_Blit_Transparent::cmd_copy)
00432                         {
00433                                 unsigned short rep = *((unsigned short *) &line_data[lpos]);
00434                                 lpos += 2;
00435 
00436                                 if (src_pos+rep >= src_delta_x)
00437                                 {
00438                                         unsigned short skip = src_delta_x-src_pos;
00439                                         unsigned short clip_rep = rep - skip;
00440 
00441                                         if (int(src_pos+rep) >= int(size_x+src_delta_x))
00442                                         {
00443                                                 clip_rep -= (src_pos+rep)-(size_x+src_delta_x);
00444                                         }
00445 
00446                                         if (clip_rep > 0)
00447                                         {
00448                                                 BltRLERow_Transparent<T>::show_row(
00449                                                         (T *) &(line_data[lpos+sizeof(T)*skip]),
00450                                                         dd,
00451                                                         clip_rep);
00452                                         }
00453                                 }
00454 
00455                                 src_pos += rep;
00456                                 lpos += sizeof(T)*rep;
00457 
00458                                 cur_state = CL_Blit_Transparent::cmd_skip;
00459                         }
00460                         else
00461                         {
00462                                 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00463                                 unsigned short skip = *skip_pos;
00464                                 src_pos += skip;
00465                                 lpos += 2;
00466                                 cur_state = CL_Blit_Transparent::cmd_copy;
00467                         }
00468                 }
00469 
00470                 unsigned int x = src_pos - src_delta_x;
00471 
00472 #if !defined(WIN32) || defined(USE_TASM)
00473 #ifdef USE_I386_ASSEMBLER
00474                 switch (sizeof(T))
00475                 {
00476                 case 2:
00477                         if (cur_state == CL_Blit_Transparent::cmd_skip)
00478                         {
00479                                 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00480                                 unsigned short skip = *skip_pos;
00481                                 x += skip;
00482                                 lpos += 2;
00483                         }
00484                         if (x<parent->m_width)
00485                                 blit_transparent_clip_asm_16bpp(
00486                                         line_data+lpos,
00487                                         (unsigned short *) (&dd[x]),
00488                                         size_x-x);
00489 
00490                         break;
00491 
00492                 case 4:
00493                         if (cur_state == CL_Blit_Transparent::cmd_skip)
00494                         {
00495                                 unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00496                                 unsigned short skip = *skip_pos;
00497                                 x += skip;
00498                                 lpos += 2;
00499                         }
00500                         if (x<parent->m_width)
00501                                 blit_transparent_clip_asm_32bpp(
00502                                         line_data+lpos,
00503                                         (unsigned int *) (&dd[x]),
00504                                         size_x-x);
00505 
00506                         break;
00507 
00508                 default:
00509 #endif
00510 #endif
00511                         while (x<size_x)
00512                         {
00513                                 if (cur_state == CL_Blit_Transparent::cmd_copy)
00514                                 {
00515                                         unsigned short rep = *((unsigned short *) &line_data[lpos]);
00516                                         lpos += 2;
00517 
00518                                         unsigned short clip_rep = rep;
00519 
00520                                         if (x+rep >= size_x)
00521                                         {
00522                                                 clip_rep = size_x - x;
00523                                         }
00524 
00525                                         if (clip_rep > 0)
00526                                         {
00527                                                 BltRLERow_Transparent<T>::show_row(
00528                                                         (T *) &(line_data[lpos]),
00529                                                         &dd[x],
00530                                                         clip_rep);
00531                                         }
00532 
00533                                         x += rep;
00534                                         lpos += sizeof(T)*rep;
00535 
00536                                         cur_state = CL_Blit_Transparent::cmd_skip;
00537                                 }
00538                                 else
00539                                 {
00540                                         unsigned short *skip_pos = (unsigned short *) (&line_data[lpos]);
00541                                         unsigned short skip = *skip_pos;
00542                                         x += skip;
00543                                         lpos += 2;
00544                                         cur_state = CL_Blit_Transparent::cmd_copy;
00545                                 }
00546                         }
00547 #if !defined(WIN32) || defined(USE_TASM)
00548 #ifdef USE_I386_ASSEMBLER
00549                 }
00550 #endif
00551 #endif
00552         }
00553 
00554         target->unlock();
00555 }
00556 
00557 void CL_Blit_Transparent::blt_clip(
00558         CL_Target *target,
00559         int x,
00560         int y,
00561         int spr_no,
00562         const CL_ClipRect &clip)
00563 {
00564         unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00565         switch (dest_bytes_per_pixel)
00566         {
00567         case 2:
00568                 SubBlitter_Transparent<unsigned short>::blt_clip(this, target, x, y, spr_no, clip);
00569                 break;
00570         case 4:
00571                 SubBlitter_Transparent<unsigned int>::blt_clip(this, target, x, y, spr_no, clip);
00572                 break;
00573         }
00574         if (m_contained_alpha_blitter != NULL)
00575         {
00576                 m_contained_alpha_blitter->blt_clip(target, x, y, spr_no, clip);
00577         }
00578 }
00579 
00580 template <class T>
00581 void SubBlitter_Transparent<T>::unpack_line(
00582         T *dest,
00583         unsigned char *transparent_dest,
00584         unsigned char *source_data,
00585         int num_pixels)
00586 {
00587         int cur_state = CL_Blit_Transparent::cmd_skip;
00588         int x = 0;
00589         int lpos = 0;
00590         while (x < num_pixels)
00591         {
00592                 if (cur_state == CL_Blit_Transparent::cmd_copy)
00593                 {
00594                         unsigned short rep = *((unsigned short *) &source_data[lpos]);
00595                         lpos += 2;
00596 
00597                         memset(&transparent_dest[x], 0, rep);
00598 
00599                         for (;rep>0;rep--)
00600                         {
00601                                 dest[x++] = *((T *) &source_data[lpos]);
00602                                 lpos += sizeof(T);
00603                         }
00604 
00605                         cur_state = CL_Blit_Transparent::cmd_skip;
00606                 }
00607                 else
00608                 {
00609                         unsigned short *skip_pos = (unsigned short *) (&source_data[lpos]);
00610                         unsigned short skip = *skip_pos;
00611                         memset(&transparent_dest[x], 1, skip);
00612                         x += skip;
00613                         lpos += 2;
00614                         cur_state = CL_Blit_Transparent::cmd_copy;
00615                 }
00616         }
00617 }
00618 
00619 template <class T>
00620 void SubBlitter_Transparent<T>::blt_scale_noclip(
00621         CL_Blit_Transparent *parent,
00622         CL_Target *target,
00623         int x,
00624         int y,
00625         int dest_width,
00626         int dest_height,
00627         int spr_no)
00628 {
00629         if (dest_width <= 0 || dest_height <= 0) return;
00630         target->lock();
00631 
00632         unsigned int dest_pitch = target->get_pitch();
00633 
00634         unsigned char *dest = (unsigned char*) target->get_data();
00635         dest += x*sizeof(T) + y*dest_pitch;
00636 
00637         unsigned int stepX = (parent->m_width<<16) / dest_width;
00638         unsigned int stepY = (parent->m_height<<16) / dest_height;
00639         unsigned int posX = 0;
00640         unsigned int posY = (spr_no*parent->m_height)<<16;
00641 
00642         T *unpacked_line = new T[parent->m_width];
00643         unsigned char *is_transparent = new unsigned char[parent->m_width];
00644 
00645         for (int yy=0; yy<dest_height; yy++)
00646         {
00647                 unsigned char *line_data = parent->m_lines[posY>>16];
00648                 if (line_data != NULL) 
00649                 {
00650                         unpack_line(unpacked_line, is_transparent, line_data, parent->m_width);
00651 
00652                         T *dd = (T *) (dest+yy*dest_pitch);
00653 
00654                         posX = 0;
00655                         for (int xx=0;xx<dest_width;xx++)
00656                         {
00657                                 int ix = (posX>>16);
00658                                 if (!is_transparent[ix]) 
00659                                 {
00660                                         BltRLERow_Transparent<T>::show_row(
00661                                                 &unpacked_line[ix],
00662                                                 &dd[xx],
00663                                                 1);
00664                                 }
00665                                 posX += stepX;
00666                         }
00667                 }
00668                 posY+=stepY;
00669         }
00670 
00671         delete[] unpacked_line;
00672         delete[] is_transparent;
00673 
00674         target->unlock();
00675 }
00676 
00677 void CL_Blit_Transparent::blt_scale_noclip(
00678         CL_Target *target,
00679         int x,
00680         int y,
00681         int dest_width,
00682         int dest_height,
00683         int spr_no)
00684 {
00685         unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00686         switch (dest_bytes_per_pixel)
00687         {
00688         case 2:
00689                         SubBlitter_Transparent<unsigned short>::blt_scale_noclip(
00690                                 this,
00691                                 target,
00692                                 x,
00693                                 y,
00694                                 dest_width,
00695                                 dest_height,
00696                                 spr_no);
00697                 break;
00698         case 4:
00699                         SubBlitter_Transparent<unsigned int>::blt_scale_noclip(
00700                                 this,
00701                                 target,
00702                                 x,
00703                                 y,
00704                                 dest_width,
00705                                 dest_height,
00706                                 spr_no);
00707                 break;
00708         }
00709         if (m_contained_alpha_blitter != NULL)
00710         {
00711                 m_contained_alpha_blitter->blt_scale_noclip(target, x, y, dest_width, dest_height, spr_no);
00712         }
00713 }
00714 
00715 template <class T>
00716 void SubBlitter_Transparent<T>::blt_scale_clip(
00717         CL_Blit_Transparent *parent,
00718         CL_Target *target,
00719         int x,
00720         int y,
00721         int dest_width,
00722         int dest_height,
00723         int spr_no,
00724         const CL_ClipRect &clip)
00725 {
00726         if (dest_width <= 0 || dest_height <= 0) return;
00727 
00728         CL_ClipRect dest_clip(x, y, x+dest_width, y+dest_height);
00729         CL_ClipRect clipped = clip.clip(dest_clip);
00730         
00731         if (clipped.m_x1 >= clipped.m_x2 ||
00732             clipped.m_y1 >= clipped.m_y2) return;
00733         target->lock();
00734 
00735         unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00736         unsigned int dest_pitch = target->get_pitch();
00737 
00738         unsigned char *dest = (unsigned char*) target->get_data();
00739         dest += clipped.m_x1*dest_bytes_per_pixel + clipped.m_y1*dest_pitch;
00740 
00741         unsigned int stepX = (parent->m_width<<16) / dest_width;
00742         unsigned int stepY = (parent->m_height<<16) / dest_height;
00743 
00744         unsigned int clipX = stepX*(clipped.m_x1-x);
00745         unsigned int clipY = stepY*(clipped.m_y1-y);
00746 
00747         unsigned int posX = clipX;
00748         unsigned int posY = clipY + ((spr_no*parent->m_height) << 16);
00749 
00750         dest_width = clipped.m_x2-clipped.m_x1;
00751         dest_height = clipped.m_y2-clipped.m_y1;
00752 
00753         T *unpacked_line = new T[parent->m_width];
00754         unsigned char *is_transparent = new unsigned char[parent->m_width];
00755 
00756         for (int yy=0; yy<dest_height; yy++)
00757         {
00758                 unsigned char *line_data = parent->m_lines[posY>>16];
00759                 if (line_data != NULL) 
00760                 {
00761                         unpack_line(unpacked_line, is_transparent, line_data, parent->m_width);
00762 
00763                         T *dd = (T *) (dest+yy*dest_pitch);
00764 
00765                         posX = clipX;
00766                         for (int xx=0;xx<dest_width;xx++)
00767                         {
00768                                 int ix = (posX>>16);
00769                                 if (!is_transparent[ix]) 
00770                                 {
00771                                         BltRLERow_Transparent<T>::show_row(
00772                                                 &unpacked_line[ix],
00773                                                 &dd[xx],
00774                                                 1);
00775                                 }
00776                                 posX += stepX;
00777                         }
00778                 }
00779                 posY+=stepY;
00780         }
00781 
00782         delete[] unpacked_line;
00783         delete[] is_transparent;
00784 
00785         target->unlock();
00786 }
00787 
00788 void CL_Blit_Transparent::blt_scale_clip(
00789         CL_Target *target,
00790         int x,
00791         int y,
00792         int dest_width,
00793         int dest_height,
00794         int spr_no,
00795         const CL_ClipRect &clip)
00796 {
00797         unsigned int dest_bytes_per_pixel = (target->get_depth()+7)/8;
00798         switch (dest_bytes_per_pixel)
00799         {
00800         case 2:
00801                         SubBlitter_Transparent<unsigned short>::blt_scale_clip(
00802                                 this,
00803                                 target,
00804                                 x,
00805                                 y,
00806                                 dest_width,
00807                                 dest_height,
00808                                 spr_no,
00809                                 clip);
00810                 break;
00811         case 4:
00812                         SubBlitter_Transparent<unsigned int>::blt_scale_clip(
00813                                 this,
00814                                 target,
00815                                 x,
00816                                 y,
00817                                 dest_width,
00818                                 dest_height,
00819                                 spr_no,
00820                                 clip);
00821                 break;
00822         }
00823         if (m_contained_alpha_blitter != NULL)
00824         {
00825                 m_contained_alpha_blitter->blt_scale_clip(target, x, y, dest_width, dest_height, spr_no, clip);
00826         }
00827 }

Generated at Wed Apr 4 19:53:59 2001 for ClanLib by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001