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

target_generic.cpp

Go to the documentation of this file.
00001 /*
00002         $Id: target_generic.cpp,v 1.2 2001/03/24 22:27:34 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         ------------------------------------------------------------------------
00013 
00014        the real one
00015 */
00016 
00017 #include "Core/precomp.h"
00018 
00019 #include <API/Display/Display/cliprect.h>
00020 #include <API/Display/Display/target.h>
00021 #include <API/Display/Display/pixelformat.h>
00022 #include <API/Display/Display/palette.h>
00023 #include <API/Core/System/cl_assert.h>
00024 #include <Display/Display/Generic/colormap.h>
00025 
00026 #define SGN(x) ((x)>0 ? 1 : ((x)==0 ? 0 :(-1)))
00027 #define ABS(x) ((x)>0 ? (x) : (-x))
00028 
00029 inline void fast_draw_pixel_32bpp(
00030         unsigned char *data,
00031         int x,
00032         int y,
00033         int color,
00034         unsigned int pitch);
00035 
00036 inline void fast_draw_pixel_24bpp(
00037         unsigned char *data,
00038         int x,
00039         int y,
00040         unsigned char *color,
00041         unsigned int pitch);
00042 
00043 inline void fast_draw_pixel_16bpp(
00044         unsigned char *data,
00045         int x,
00046         int y,
00047         unsigned short color,
00048         unsigned int pitch);
00049 
00050 inline void fast_draw_pixel_8bpp(
00051         unsigned char *data,
00052         int x,
00053         int y,
00054         unsigned char color,
00055         unsigned int pitch);
00056 
00057 int clip_line(int &x1,int &y1,int &x2, int &y2, int min_clip_x, int max_clip_x, int min_clip_y, int max_clip_y);
00058 
00059 void cl_fill_rect_opaque(
00060         CL_Target *target, int _x1, int _y1, int _x2, int _y2, int color);
00061 
00062 void CL_Target::push_clip_rect()
00063 {
00064         if (clip_stack.empty())
00065                 clip_stack.push(
00066                         CL_ClipRect(0, 0, get_width(), get_height()));
00067 
00068         clip_stack.push(clip_stack.top());
00069 }
00070 
00071 void CL_Target::push_clip_rect(const CL_ClipRect &rect)
00072 {
00073         push_clip_rect();
00074         clip_stack.top() = clip_stack.top().clip(rect);
00075 }
00076 
00077 CL_ClipRect CL_Target::get_clip_rect()
00078 {
00079         if (clip_stack.empty())
00080                 clip_stack.push(
00081                         CL_ClipRect(0, 0, get_width(), get_height()));
00082 
00083         return clip_stack.top();
00084 }
00085 
00086 void CL_Target::set_clip_rect(const CL_ClipRect &rect)
00087 {
00088         if (clip_stack.empty())
00089                 clip_stack.push(rect);
00090         else
00091                 clip_stack.top() = rect;
00092 }
00093 
00094 void CL_Target::pop_clip_rect()
00095 {
00096         cl_assert_debug(clip_stack.empty() == false);
00097         clip_stack.pop();
00098 }
00099 
00100 void CL_Target::push_translate_offset() 
00101 { 
00102         m_translation_stack.push(m_translation_stack.top()); 
00103 }
00104 
00105 void CL_Target::push_translate_offset(int x, int y) 
00106 { 
00107         TranslationOffset cur = m_translation_stack.top(); 
00108         m_translation_stack.push(TranslationOffset(cur.first+x, cur.second+y)); 
00109 }
00110 
00111 int  CL_Target::get_translate_offset_x() const
00112 { 
00113         return m_translation_stack.top().first; 
00114 }
00115 
00116 int  CL_Target::get_translate_offset_y() const
00117 { 
00118         return m_translation_stack.top().second; 
00119 }
00120 
00121 void CL_Target::set_translate_offset(int x, int y) 
00122 { 
00123         m_translation_stack.top().first = x; m_translation_stack.top().second = y; 
00124 }
00125 
00126 void CL_Target::pop_translate_offset() 
00127 { 
00128         m_translation_stack.pop(); if (m_translation_stack.empty()) m_translation_stack.push(TranslationOffset(0,0)); 
00129 }
00130 
00131 void CL_Target::draw_pixel(int x, int y, int color)
00132 {
00133         // Translate coords into position:
00134         int trans_x = get_translate_offset_x();
00135         int trans_y = get_translate_offset_y();
00136         x += trans_x;
00137         y += trans_y;
00138 
00139 
00140         CL_ClipRect clip = get_clip_rect();
00141         if ((x < clip.m_x1) ||
00142             (x >= clip.m_x2) ||
00143             (y < clip.m_y1) ||
00144             (y >= clip.m_y2)) return;
00145 
00146         lock();
00147 
00148         unsigned char* data = (unsigned char*) get_data();
00149         
00150         switch (get_bytes_per_pixel())
00151         {
00152                 case    1 :     
00153                         {
00154                                 unsigned char *d = data + y * get_pitch() + x;
00155                                 *d = (unsigned char) color;
00156                                 break;
00157                         }
00158                 case    2 :
00159                         {
00160                                 unsigned short *d = (unsigned short*) (data + y * get_pitch() + x*2);
00161                                 *d = (unsigned short) color;
00162                                 break;
00163                         }
00164                 case    3 :
00165                         {
00166                                 // that should do the trick - untested !!!
00167                                 unsigned char *d = data + y * get_pitch() + x*3;
00168                                 *(d++) = (unsigned char) color;
00169                                 color >>= 8;
00170                                 *(d++) = (unsigned char) color;
00171                                 color >>= 8;
00172                                 *d = (unsigned char) color;
00173                                 break;
00174                         }
00175                 case    4 :
00176                         {       
00177                                 unsigned int *d = (unsigned int*) (data + y * get_pitch() + x*4);
00178                                 *d = (unsigned int) color;
00179                                 break;
00180                         }
00181                 default:
00182                         {
00183                                 cl_assert(false);
00184                                 break;
00185                         }
00186         }
00187         unlock();
00188 }
00189 
00190 void CL_Target::flip_vertical()
00191 {
00192         lock();
00193 
00194         unsigned char* data = (unsigned char*) get_data();
00195 
00196         int byte_pp = get_bytes_per_pixel();
00197         int h = get_height();
00198         int w = get_width();
00199         int x, y, j;
00200 
00201         
00202         for (y=0; y<h; y++)
00203         {
00204                 for (x=0; x<w; x++)
00205                 {
00206                         for(j=0; j<byte_pp; j++)
00207                         {
00208                                 data[(x+y*w)*byte_pp + j] = 255; //flip data
00209                         }
00210                 }
00211         }
00212 
00213         unlock();
00214 }
00215 
00216 void CL_Target::flip_horizontal()
00217 {
00218         lock();
00219 
00220         unsigned char* data = (unsigned char*) get_data();
00221 
00222         int byte_pp = get_bytes_per_pixel();
00223         int h = get_height();
00224         int w = get_width();
00225         int x, y, j;
00226 
00227         
00228         for (y=0; y<h; y++)
00229         {
00230                 for (x=0; x<w; x++)
00231                 {
00232                         for(j=0; j<byte_pp; j++)
00233                         {
00234                                 data[(x+y*w)*byte_pp + j] = 255; //flip data
00235                         }
00236                 }
00237         }
00238 
00239         unlock();
00240 }
00241 
00242 
00243 void CL_Target::get_pixel(int x, int y, float *r, float *g, float *b, float *a)
00244 {
00245         // Translate coords into position:
00246         int trans_x = get_translate_offset_x();
00247         int trans_y = get_translate_offset_y();
00248         x += trans_x;
00249         y += trans_y;
00250 
00251 
00252         lock();
00253         unsigned char* data = (unsigned char*) get_data();
00254         int color = 0;
00255         
00256         switch (get_bytes_per_pixel())
00257         {
00258                 case    1 :     
00259                         {
00260                                 unsigned char *d = data + y * get_pitch() + x;
00261                                 color = *d;
00262                                 break;
00263                         }
00264                 case    2 :
00265                         {
00266                                 unsigned short *d = (unsigned short*) (data + y * get_pitch() + x*2);
00267                                 color = *d;
00268                                 break;
00269                         }
00270                 case    3 :
00271                         {                       
00272                                 // that should do the trick - untested !!!
00273                                 unsigned char *d = data + y * get_pitch() + x*3;
00274 #ifdef USE_BIG_ENDIAN
00275                                 color = (*d << 16) | (*(d+1) << 8) | (*(d+2));
00276 #else
00277                                 color = (*d) | (*(d+1) << 8) | (*(d+2) << 16);
00278 #endif
00279                                 break;
00280                         }
00281                 case    4 :
00282                         {       
00283                                 unsigned int *d = (unsigned int*) (data + y * get_pitch() + x*4);
00284                                 color = *d;
00285                                 break;
00286                         }
00287                 default:
00288                         {
00289                                 cl_assert(false);
00290                                 break;
00291                         }
00292         }
00293         
00294         if (is_indexed())
00295         {
00296                 *r = get_palette()->palette[color*3 +0] / 255.0f;
00297                 *g = get_palette()->palette[color*3 +1] / 255.0f;
00298                 *b = get_palette()->palette[color*3 +2] / 255.0f;
00299                 *a = 1.0f;
00300         }
00301         else
00302         {       
00303                 *r = (color & get_red_mask()) / (float (get_red_mask()));
00304                 *g = (color & get_green_mask()) / (float (get_green_mask()));
00305                 *b = (color & get_blue_mask()) / (float (get_blue_mask()));
00306                 *a = (color & get_alpha_mask()) / (float (get_alpha_mask()));
00307         }
00308         unlock();
00309 }
00310 
00311 
00312 int CL_Target::get_pixel(int x, int y)
00313 {
00314         // Translate coords into position:
00315         int trans_x = get_translate_offset_x();
00316         int trans_y = get_translate_offset_y();
00317         x += trans_x;
00318         y += trans_y;
00319 
00320 
00321         lock();
00322         unsigned char* data = (unsigned char*) get_data();
00323         int color = 0;
00324         
00325         switch (get_bytes_per_pixel())
00326         {
00327                 case    1 :     
00328                         {
00329                                 unsigned char* d = data + y * get_pitch() + x;
00330                                 color = *d;
00331                                 break;
00332                         }
00333                 case    2 :
00334                         {
00335                                 unsigned short* d = (unsigned short*) (data + y * get_pitch() + x*2);
00336                                 color = *d;
00337                                 break;
00338                         }
00339                 case    3 :
00340                         {                       
00341                                 // that should do the trick - untested !!!
00342                                 unsigned char* d = data + y * get_pitch() + x*3;
00343 #ifdef USE_BIG_ENDIAN
00344                                 color = (*d << 16) | (*(d+1) << 8) | (*(d+2));
00345 #else
00346                                 color = (*d) | (*(d+1) << 8) | (*(d+2) << 16);
00347 #endif
00348                                 break;
00349                         }
00350                 case    4 :
00351                         {       
00352                                 unsigned int* d = (unsigned int*) (data + y * get_pitch() + x*4);
00353                                 color = *d;
00354                                 break;
00355                         }
00356                 default:
00357                         {
00358                                 cl_assert(false);
00359                                 break;
00360                         }
00361         }
00362         unlock();
00363         return color;
00364 }
00365 
00366 void CL_Target::draw_rect(
00367         int x1,
00368         int y1,
00369         int x2,
00370         int y2,
00371         float r,
00372         float g,
00373         float b,
00374         float a)
00375 {
00376         if (a <= 0.01) return;
00377 
00378         // Using fill_rect is faster than draw_line because draw_line calls
00379         // fill_rect anyways if it is a straight line, which it always is.
00380         fill_rect(x1, y1, x2, y1 + 1, r, g, b, a); // Top
00381         fill_rect(x1, y1 + 1, x1 + 1, y2 - 1, r, g, b, a); // Left
00382         fill_rect(x2 - 1, y1 + 1, x2, y2 - 1, r, g, b, a); // Right
00383         fill_rect(x1, y2 - 1, x2, y2, r, g, b, a); // Bottom
00384 }
00385 
00386 void CL_Target::fill_rect(
00387         int x1,
00388         int y1,
00389         int x2,
00390         int y2,
00391         float r,
00392         float g,
00393         float b,
00394         float a)
00395 {
00396         // Translate coords into position:
00397         int trans_x = get_translate_offset_x();
00398         int trans_y = get_translate_offset_y();
00399         x1 += trans_x;
00400         y1 += trans_y;
00401         x2 += trans_x;
00402         y2 += trans_y;
00403 
00404         int color = CL_Color::get_color(this, r,g,b,a);
00405 
00406         // this could/ should get optimised, but the main focus now is to get it working again ;-)
00407 
00408         if (a == 1)
00409         {
00410                 cl_fill_rect_opaque(this, x1, y1, x2, y2, color);
00411                 return;
00412         }
00413 
00414         CL_ClipRect rect(x1, y1, x2, y2);
00415         if (get_clip_rect().test_all_clipped(rect)) return;
00416 
00417         CL_ClipRect crect = get_clip_rect().clip(rect);
00418 
00419         lock();
00420 
00421         CL_ColorMap cmap(this);
00422 
00423         unsigned int fill_color = cmap.calc_color(r, g, b, a);
00424 
00425         unsigned int red_mask = get_red_mask();
00426         unsigned int green_mask = get_green_mask();
00427         unsigned int blue_mask = get_blue_mask();
00428         unsigned int alpha_mask = get_alpha_mask();
00429         
00430         {
00431                 unsigned int rr = fill_color & red_mask;
00432                 unsigned int gg = fill_color & green_mask;
00433                 unsigned int bb = fill_color & blue_mask;
00434 
00435                 rr >>= cmap.m_red_start;
00436                 gg >>= cmap.m_green_start;
00437                 bb >>= cmap.m_blue_start;
00438         
00439                 rr = (int) (rr*a);
00440                 gg = (int) (gg*a);
00441                 bb = (int) (bb*a);
00442 
00443                 fill_color =
00444                         (rr<<cmap.m_red_start) +
00445                         (gg<<cmap.m_green_start) +
00446                         (bb<<cmap.m_blue_start);
00447         }
00448 
00449         unsigned int dest_bytes_per_pixel = (get_depth()+7)/8;
00450         unsigned int dest_pitch = get_pitch();
00451 
00452         unsigned char *dest = (unsigned char*) get_data();
00453         dest += crect.m_x1*dest_bytes_per_pixel + crect.m_y1*dest_pitch;
00454 
00455         unsigned int delta_x = crect.m_x2-crect.m_x1;
00456         unsigned int delta_y = crect.m_y2-crect.m_y1;
00457 
00458         int rr_start = cmap.m_red_start;
00459         int gg_start = cmap.m_green_start;
00460         int bb_start = cmap.m_blue_start;
00461 
00462         switch (dest_bytes_per_pixel)
00463         {
00464         case 2:
00465                 {
00466                         int i;
00467                         int rl = 1 << cmap.m_red_length;
00468                         int gl = 1 << cmap.m_green_length;
00469                         int bl = 1 << cmap.m_blue_length;
00470         
00471                         unsigned short *rr_lookup = new unsigned short[rl];
00472                         unsigned short *gg_lookup = new unsigned short[gl];
00473                         unsigned short *bb_lookup = new unsigned short[bl];
00474                                                 
00475                         for (i=0;i<rl;i++)
00476                         {
00477                                 rr_lookup[i] = (unsigned short)(i*(1-a)) << rr_start;
00478                         }
00479                         for (i=0;i<gl;i++)
00480                         {
00481                                 gg_lookup[i] = (unsigned short)(i*(1-a)) << gg_start;
00482                         }
00483                         for (i=0;i<bl;i++)
00484                         {
00485                                 bb_lookup[i] = (unsigned short)(i*(1-a)) << bb_start;
00486                         }
00487 
00488                         int skip = dest_pitch - delta_x*2;
00489                         unsigned short clear_value = (unsigned short) fill_color;
00490 
00491                         if (is_video())
00492                         {
00493                                 unsigned short *data = new unsigned short[delta_x];
00494                                 for (unsigned int yy=0; yy<delta_y; yy++)
00495                                 {
00496                                         memcpy(data, dest, delta_x*2);
00497                                         for (unsigned int xx=0;xx<delta_x;xx++)
00498                                         {
00499                                                 unsigned short dval = data[xx];
00500                                                 unsigned int rr = dval & red_mask;
00501                                                 unsigned int gg = dval & green_mask;
00502                                                 unsigned int bb = dval & blue_mask;
00503                                                 rr >>= rr_start;
00504                                                 gg >>= gg_start;
00505                                                 bb >>= bb_start;
00506                                                 dval =
00507                                                         rr_lookup[rr] +
00508                                                         gg_lookup[gg] +
00509                                                         bb_lookup[bb] +
00510                                                         clear_value;
00511 
00512                                                 data[xx] = dval;
00513                                         }
00514                                         memcpy(dest, data, delta_x*2);
00515                                         dest += delta_x*2;
00516                                         dest += skip;
00517                                 }
00518                                 delete [] data;
00519                         }
00520                         else
00521                         {
00522                                 for (unsigned int yy=0; yy<delta_y; yy++)
00523                                 {
00524                                         for (unsigned int xx=0;xx<delta_x;xx++)
00525                                         {
00526                                                 unsigned short dval = *((unsigned short *)dest+xx);
00527                                                 register unsigned int rr = dval & red_mask;
00528                                                 unsigned int gg = dval & green_mask;
00529                                                 unsigned int bb = dval & blue_mask;
00530                                                 rr >>= rr_start;
00531                                                 gg >>= gg_start;
00532                                                 bb >>= bb_start;
00533 
00534                                                 dval =
00535                                                         rr_lookup[rr] +
00536                                                         gg_lookup[gg] +
00537                                                         bb_lookup[bb] +
00538                                                         clear_value;
00539 
00540                                                 *((unsigned short *)dest+xx) = dval;
00541                                         }
00542                                         dest += delta_x*2;
00543                                         dest += skip;
00544                                 }
00545                         }
00546                         delete [] rr_lookup;
00547                         delete [] gg_lookup;
00548                         delete [] bb_lookup;
00549                 }
00550                 break;
00551 
00552         case 4:
00553                 {
00554                         int i;
00555                         int rl = 1 << cmap.m_red_length;
00556                         int gl = 1 << cmap.m_green_length;
00557                         int bl = 1 << cmap.m_blue_length;
00558         
00559                         unsigned int *rr_lookup = new unsigned int[rl];
00560                         unsigned int *gg_lookup = new unsigned int[gl];
00561                         unsigned int *bb_lookup = new unsigned int[bl];
00562 
00563                         for (i=0;i<rl;i++)
00564                         {
00565                                 rr_lookup[i] = (unsigned int)(i*(1-a)) << rr_start;
00566                         }
00567                         for (i=0;i<gl;i++)
00568                         {
00569                                 gg_lookup[i] = (unsigned int)(i*(1-a)) << gg_start;
00570                         }
00571                         for (i=0;i<bl;i++)
00572                         {
00573                                 bb_lookup[i] = (unsigned int)(i*(1-a)) << bb_start;
00574                         }
00575 
00576                         int skip = dest_pitch - delta_x*4;
00577 
00578                         if (is_video())
00579                         {
00580                                 unsigned int* data = new unsigned int[delta_x];
00581                                 for (unsigned int yy=0; yy<delta_y; yy++)
00582                                 {
00583                                         memcpy(data, dest, delta_x*4);
00584                                         for (unsigned int xx=0;xx<delta_x;xx++)
00585                                         {
00586                                                 unsigned int dval = data[xx];
00587                                                 unsigned int rr = dval & red_mask;
00588                                                 unsigned int gg = dval & green_mask;
00589                                                 unsigned int bb = dval & blue_mask;
00590                                                 unsigned int aa = dval & alpha_mask;
00591                                                 rr >>= rr_start;
00592                                                 gg >>= gg_start;
00593                                                 bb >>= bb_start;
00594 
00595                                                 dval =
00596                                                         rr_lookup[rr] +
00597                                                         gg_lookup[gg] +
00598                                                         bb_lookup[bb] +
00599                                                         fill_color;
00600 
00601                                                 data[xx] = dval | aa;
00602                                         }
00603                                         memcpy(dest, data, delta_x*4);
00604                                         dest += delta_x*4;
00605                                         dest += skip;
00606                                 }
00607                                 delete [] data;
00608                         }
00609                         else
00610                         {
00611                                 for (unsigned int yy=0; yy<delta_y; yy++)
00612                                 {
00613                                         for (unsigned int xx=0;xx<delta_x;xx++)
00614                                         {
00615                                                 unsigned int dval = *((unsigned int *) dest);
00616                                                 unsigned int rr = dval & red_mask;
00617                                                 unsigned int gg = dval & green_mask;
00618                                                 unsigned int bb = dval & blue_mask;
00619                                                 unsigned int aa = dval & alpha_mask;
00620                                                 rr >>= rr_start;
00621                                                 gg >>= gg_start;
00622                                                 bb >>= bb_start;
00623 
00624                                                 dval =
00625                                                         rr_lookup[rr] +
00626                                                         gg_lookup[gg] +
00627                                                         bb_lookup[bb] +
00628                                                         fill_color;
00629 
00630                                                 *((unsigned int *) dest) = dval | aa;
00631 
00632                                                 dest += 4;
00633                                         }
00634                                         dest += skip;
00635                                 }
00636                         }
00637                         delete [] rr_lookup;
00638                         delete [] gg_lookup;
00639                         delete [] bb_lookup;
00640                 }
00641                 break;
00642 
00643         default:
00644                 cl_assert(false); // unsupported pixel depth!
00645                 break;
00646         }
00647 
00648         unlock();
00649 }
00650 
00651 void cl_fill_rect_opaque(
00652         CL_Target *target,
00653         int _x1,
00654         int _y1,
00655         int _x2,
00656         int _y2,
00657         int color)
00658 {
00659         CL_ClipRect rect(_x1, _y1, _x2, _y2);
00660 
00661         if (target->get_clip_rect().test_all_clipped(rect)) return;
00662 
00663         CL_ClipRect crect = target->get_clip_rect().clip(rect);
00664 
00665         int x1 = crect.m_x1;
00666         int x2 = crect.m_x2;
00667         int y1 = crect.m_y1;
00668         int y2 = crect.m_y2;
00669 
00670         target->lock();
00671 
00672         unsigned int dest_pitch = target->get_pitch();
00673         unsigned int dest_bytes_per_pixel = target->get_bytes_per_pixel();
00674 
00675         register unsigned char *dest = (unsigned char*) target->get_data(); //This variable is hit hard later in the function
00676         dest += x1*dest_bytes_per_pixel + y1*dest_pitch;
00677 
00678         unsigned int delta_x = x2-x1;
00679         unsigned int delta_y = y2-y1;
00680 
00681         switch (dest_bytes_per_pixel)
00682         {
00683         case 1:
00684                 {
00685                         int skip = dest_pitch - delta_x;
00686                         if (skip == 0)
00687                         {
00688                                 memset(dest, (char) color, delta_x*delta_y);
00689                         
00690                         } else
00691                         {
00692                                 for (unsigned int y = 0; y < delta_y; y++)
00693                                 {
00694                                         memset(dest, (char) color, delta_x);
00695                                         dest += skip + delta_x;
00696                                 }
00697                         }
00698                 }
00699         
00700         case 2:
00701                 {
00702                         register unsigned short _color = (unsigned short) color;
00703                         int skip = dest_pitch - delta_x * 2;
00704                         // the blitter probes if it can perform a memset (when hi and lo byte of _color are equal)
00705                         if ((_color & 0x00FF) != (_color & 0xFF00))
00706                         {
00707                                 for (unsigned int y = 0; y < delta_y; y++)
00708                                 {
00709                                         for (unsigned int x=0; x < delta_x; x++)
00710                                         {
00711                                                 *((unsigned short *) dest) = _color;
00712                                                 dest += 2;
00713                                         }
00714                                         dest += skip;
00715                                 }
00716                         }
00717                         else
00718                         {
00719                                 char color8 = _color;
00720                                 if (skip != 0)
00721                                 {
00722                                         for (unsigned int y = 0; y < delta_y; y++)
00723                                         {
00724                                                 memset(dest, color8, 2 * delta_x);
00725                                                 dest += skip + 2 * delta_x;
00726                                         }
00727                                 }
00728                                 else // everything can be done with one single memset :-)
00729                                 {
00730                                         memset(dest, color8, 2 * delta_x * delta_y);
00731                                 }
00732                         }
00733                 }
00734                 break;
00735 
00736         case 3:
00737                 {
00738                         int skip = dest_pitch - delta_x * 3;
00739                         for (unsigned int y = 0; y < delta_y; y++)
00740                         {
00741                                 for (unsigned int x = 0; x < delta_x; x++)
00742                                 {
00743                                         *(dest++) = color & 0x0000FF;
00744                                         *(dest++) = color & 0x00FF00;
00745                                         *(dest++) = color & 0xFF0000;
00746                                 }
00747                                 dest += skip;
00748                         }
00749                 }
00750 
00751         case 4:
00752                 {
00753                         int skip = dest_pitch - delta_x * 4;
00754                         for (unsigned int y = 0; y < delta_y; y++)
00755                         {
00756                                 for (unsigned int x = 0; x < delta_x; x++)
00757                                 {
00758                                         *((unsigned int *) dest) = color;
00759                                         dest += 4;
00760                                 }
00761                                 dest += skip;
00762                         }
00763                 }
00764                 break;
00765 
00766         default:
00767                 cl_assert(false); // unsupported pixel depth!
00768                 break;
00769         }
00770 
00771         target->unlock();
00772 }
00773 
00774 // Used for draw_line function
00775 inline void fast_draw_pixel_32bpp(
00776         unsigned char *data,
00777         int x,
00778         int y,
00779         int color,
00780         unsigned int pitch)
00781 {
00782         unsigned int *d = (unsigned int*) (data + y * pitch + (x<<2));
00783         *d = (unsigned int) color;
00784         
00785         return;
00786 }
00787 
00788 // Used for draw_line function
00789 inline void fast_draw_pixel_24bpp(
00790         unsigned char *data,
00791         int x,
00792         int y,
00793         unsigned char *color,
00794         unsigned int pitch)
00795 {
00796         unsigned char *d = data + y * pitch + x*3;
00797         memcpy(d,color,3);
00798         return;
00799 }
00800 
00801 // Used for draw_line function
00802 inline void fast_draw_pixel_16bpp(
00803         unsigned char *data,
00804         int x,
00805         int y,
00806         unsigned short color,
00807         unsigned int pitch)
00808 {
00809         unsigned short *d ;
00810   d = (unsigned short*) (data + y * pitch + (x<<1));
00811         *d = color;
00812 
00813         return;
00814 }
00815 
00816 // Used for draw_line function
00817 inline void fast_draw_pixel_8bpp(
00818         unsigned char *data,
00819         int x,
00820         int y,
00821         unsigned char color,
00822         unsigned int pitch)
00823 {
00824 
00825         unsigned char *d = data + y * pitch + x;
00826   *d = color;
00827         return;
00828 }
00829 
00830 void CL_Target::draw_line(
00831         int x1,
00832         int y1,
00833         int x2,
00834         int y2,
00835         float r,
00836         float g,
00837         float b,
00838         float a)
00839 {
00840         if (y1 == y2 || x1 == x2)
00841         {
00842                 CL_Target::fill_rect(x1, y1, x2+1, y2+1, r, g, b, a);
00843                 return;
00844         }
00845 
00846         // Translate coords into position:
00847         int trans_x = get_translate_offset_x();
00848         int trans_y = get_translate_offset_y();
00849         x1 += trans_x;
00850         y1 += trans_y;
00851         x2 += trans_x;
00852         y2 += trans_y;
00853 
00854 
00855         int         color_32bpp  = CL_Color::get_color(this, r,g,b,a);
00856         CL_ClipRect clip         = get_clip_rect();
00857         int         pitch        = get_pitch();
00858 
00859         if (!clip_line(x1,y1,x2,y2,clip.m_x1,clip.m_x2-1,clip.m_y1,clip.m_y2-1))
00860         {
00861                 // line is totally out of clip area
00862                 return;
00863         }
00864         
00865         lock();
00866         
00867         unsigned char* data = (unsigned char*) get_data();
00868 
00869         int lg_delta, sh_delta, cycle, lg_step, sh_step;
00870 
00871         lg_delta = x2 - x1;
00872         sh_delta = y2 - y1;
00873         lg_step = SGN(lg_delta);
00874         lg_delta = ABS(lg_delta);
00875         sh_step = SGN(sh_delta);
00876         sh_delta = ABS(sh_delta);
00877 
00878         switch (get_bytes_per_pixel())
00879         {
00880                 //*****************************************************************
00881                 // Draw line in 8bpp mode
00882                 case    1 :     
00883                         {
00884                                 unsigned char   color_8bpp = (unsigned char) color_32bpp;
00885                                 if (sh_delta < lg_delta)
00886                                 {
00887                                         cycle = lg_delta >> 1;
00888                                         while (x1 != x2)
00889                                         {
00890                                                 fast_draw_pixel_8bpp(data,x1,y1,color_8bpp,pitch);
00891                                                 cycle += sh_delta;
00892                                                 if (cycle > lg_delta)
00893                                                 {
00894                                                         cycle -= lg_delta;
00895                                                         y1 += sh_step;
00896                                                 }
00897                                                 x1 += lg_step;
00898                                         }
00899                                         fast_draw_pixel_8bpp(data,x1,y1,color_8bpp,pitch);
00900                                 }
00901                                 cycle = sh_delta >> 1;
00902                                 while (y1 != y2)
00903                                 {
00904                                         fast_draw_pixel_8bpp(data,x1,y1,color_8bpp,pitch);
00905                                         cycle += lg_delta;
00906                                         if (cycle > sh_delta)
00907                                         {
00908                                                 cycle -= sh_delta;
00909                                                 x1 += lg_step;
00910                                         }
00911                                         y1 += sh_step;
00912                                 }
00913                                 fast_draw_pixel_8bpp(data,x1,y1,color_8bpp,pitch);
00914                                 break;
00915 
00916                         }
00917 
00918                 //*****************************************************************
00919                 // Draw line in 16bpp mode
00920                 case    2 :
00921                         {
00922                                 unsigned short color_16bpp = (unsigned short) color_32bpp;
00923                                 if (sh_delta < lg_delta)
00924                                 {
00925                                         cycle = lg_delta >> 1;
00926                                         while (x1 != x2)
00927                                         {
00928                                                 fast_draw_pixel_16bpp(data,x1,y1,color_16bpp,pitch);
00929                                                 cycle += sh_delta;
00930                                                 if (cycle > lg_delta)
00931                                                 {
00932                                                         cycle -= lg_delta;
00933                                                         y1 += sh_step;
00934                                                 }
00935                                                 x1 += lg_step;
00936                                         }
00937                                         fast_draw_pixel_16bpp(data,x1,y1,color_16bpp,pitch);
00938                                 }
00939                                 cycle = sh_delta >> 1;
00940                                 while (y1 != y2)
00941                                 {
00942                                         fast_draw_pixel_16bpp(data,x1,y1,color_16bpp,pitch);
00943                                         cycle += lg_delta;
00944                                         if (cycle > sh_delta)
00945                                         {
00946                                                 cycle -= sh_delta;
00947                                                 x1 += lg_step;
00948                                         }
00949                                         y1 += sh_step;
00950                                 }
00951                                 fast_draw_pixel_16bpp(data,x1,y1,color_16bpp,pitch);
00952                                 break;
00953                         }
00954 
00955                 //*****************************************************************
00956                 // Draw line in 24bpp mode
00957                 case    3 :
00958                         {
00959                                 unsigned char   color_24bpp[3] = {0,0,0};
00960                                 if (sh_delta < lg_delta)
00961                                 {
00962                                         cycle = lg_delta >> 1;
00963                                         while (x1 != x2)
00964                                         {
00965                                                 fast_draw_pixel_24bpp(data,x1,y1,color_24bpp,pitch);
00966                                                 cycle += sh_delta;
00967                                                 if (cycle > lg_delta)
00968                                                 {
00969                                                         cycle -= lg_delta;
00970                                                         y1 += sh_step;
00971                                                 }
00972                                                 x1 += lg_step;
00973                                         }
00974                                         fast_draw_pixel_24bpp(data,x1,y1,color_24bpp,pitch);
00975                                 }
00976                                 cycle = sh_delta >> 1;
00977                                 while (y1 != y2)
00978                                 {
00979                                         fast_draw_pixel_24bpp(data,x1,y1,color_24bpp,pitch);
00980                                         cycle += lg_delta;
00981                                         if (cycle > sh_delta)
00982                                         {
00983                                                 cycle -= sh_delta;
00984                                                 x1 += lg_step;
00985                                         }
00986                                         y1 += sh_step;
00987                                 }
00988                                 fast_draw_pixel_24bpp(data,x1,y1,color_24bpp,pitch);
00989                                 break;
00990                         }
00991                         
00992                 //*****************************************************************
00993                 // Draw line in 32bpp mode
00994                 case    4 :
00995                         {       
00996                                 if (sh_delta < lg_delta)
00997                                 {
00998                                         cycle = lg_delta >> 1;
00999                                         while (x1 != x2)
01000                                         {
01001                                                 fast_draw_pixel_32bpp(data,x1,y1,color_32bpp,pitch);
01002                                                 cycle += sh_delta;
01003                                                 if (cycle > lg_delta)
01004                                                 {
01005                                                         cycle -= lg_delta;
01006                                                         y1 += sh_step;
01007                                                 }
01008                                                 x1 += lg_step;
01009                                         }
01010                                         fast_draw_pixel_32bpp(data,x1,y1,color_32bpp,pitch);
01011                                 }
01012                                 cycle = sh_delta >> 1;
01013                                 while (y1 != y2)
01014                                 {
01015                                         fast_draw_pixel_32bpp(data,x1,y1,color_32bpp,pitch);
01016                                         cycle += lg_delta;
01017                                         if (cycle > sh_delta)
01018                                         {
01019                                                 cycle -= sh_delta;
01020                                                 x1 += lg_step;
01021                                         }
01022                                         y1 += sh_step;
01023                                 }
01024                                 fast_draw_pixel_32bpp(data,x1,y1,color_32bpp,pitch);
01025                                 break;
01026                         }
01027                 default:
01028                         {
01029                                 cl_assert(false);
01030                                 break;
01031                         }
01032         }
01033 
01034         unlock();
01035 }
01036 
01037 
01038 // This function was ripped from "Tricks of the Windows game programming gurus" 
01039 // written by Andre Lamothe ISBN:0-672-31361-8
01040 // The function was slightly adapted to work with clanlib
01041 // it returns 0 if the line is totally outside the clipping area and 1 if the
01042 // line was successfully clipped
01043 int clip_line(int &x1,int &y1,int &x2, int &y2, int min_clip_x, int max_clip_x, int min_clip_y, int max_clip_y)
01044 {
01045 
01046 // internal clipping codes
01047 #define CLIP_CODE_C  0x0000
01048 #define CLIP_CODE_N  0x0008
01049 #define CLIP_CODE_S  0x0004
01050 #define CLIP_CODE_E  0x0002
01051 #define CLIP_CODE_W  0x0001
01052 
01053 #define CLIP_CODE_NE 0x000a
01054 #define CLIP_CODE_SE 0x0006
01055 #define CLIP_CODE_NW 0x0009
01056 #define CLIP_CODE_SW 0x0005
01057 
01058         int xc1=x1;
01059         int yc1=y1;
01060         int xc2=x2;
01061         int yc2=y2;
01062 
01063         int p1_code=0;
01064         int p2_code=0;
01065 
01066         // determine codes for p1 and p2
01067         if (y1 < min_clip_y)
01068         {
01069                 p1_code|=CLIP_CODE_N;
01070         }
01071         else if (y1 > max_clip_y)
01072         {
01073                 p1_code|=CLIP_CODE_S;
01074         }
01075 
01076         if (x1 < min_clip_x)
01077         {
01078                 p1_code|=CLIP_CODE_W;
01079         }
01080         else if (x1 > max_clip_x)
01081         {
01082                 p1_code|=CLIP_CODE_E;
01083         }
01084 
01085         if (y2 < min_clip_y)
01086         {
01087                 p2_code|=CLIP_CODE_N;
01088         }
01089         else if (y2 > max_clip_y)
01090         {
01091                 p2_code|=CLIP_CODE_S;
01092         }
01093 
01094         if (x2 < min_clip_x)
01095         {
01096                 p2_code|=CLIP_CODE_W;
01097         }
01098         else if (x2 > max_clip_x)
01099         {
01100                 p2_code|=CLIP_CODE_E;
01101         }
01102 
01103         // try and trivially reject
01104         if ((p1_code & p2_code))
01105         {
01106                 return(0);
01107         }
01108 
01109         // test for totally visible, if so leave points untouched
01110         if (p1_code==0 && p2_code==0)
01111         {
01112                 return(1);
01113         }
01114 
01115         // determine end clip point for p1
01116         switch(p1_code)
01117         {
01118         case CLIP_CODE_C: 
01119                 break;
01120 
01121         case CLIP_CODE_N:
01122                 {
01123                         yc1 = (int) min_clip_y;
01124                         xc1 = (int) (x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1));
01125                 } 
01126                 break;
01127 
01128         case CLIP_CODE_S:
01129                 {
01130                         yc1 = (int) max_clip_y;
01131                         xc1 = (int) (x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1));
01132                 } 
01133                 break;
01134 
01135         case CLIP_CODE_W:
01136                 {
01137                         xc1 = (int) min_clip_x;
01138                         yc1 = (int) (y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1));
01139                 } 
01140                 break;
01141                 
01142         case CLIP_CODE_E:
01143                 {
01144                         xc1 = (int) max_clip_x;
01145                         yc1 = (int) (y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1));
01146                 } 
01147                 break;
01148 
01149         // these cases are more complex, must compute 2 intersections
01150         case CLIP_CODE_NE:
01151                 {
01152                         // north hline intersection
01153                         yc1 = (int) min_clip_y;
01154                         xc1 = (int) (x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1));
01155 
01156                         // test if intersection is valid, of so then done, else compute next
01157                         if (xc1 < min_clip_x || xc1 > max_clip_x)
01158                         {
01159                                 // east vline intersection
01160                                 xc1 = (int) max_clip_x;
01161                                 yc1 = (int) (y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1));
01162                         } // end if
01163 
01164                 } 
01165                 break;
01166         
01167         case CLIP_CODE_SE:
01168                 {
01169                         // south hline intersection
01170                         yc1 = (int) max_clip_y;
01171                         xc1 = (int) (x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1)); 
01172 
01173                         // test if intersection is valid, of so then done, else compute next
01174                         if (xc1 < min_clip_x || xc1 > max_clip_x)
01175                         {
01176                                 // east vline intersection
01177                                 xc1 = (int) max_clip_x;
01178                                 yc1 = (int) (y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1));
01179                         } // end if
01180 
01181                 } 
01182                 break;
01183         
01184         case CLIP_CODE_NW:
01185                 {
01186                         // north hline intersection
01187                         yc1 = (int) min_clip_y;
01188                         xc1 = (int) (x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1));
01189                         
01190                         // test if intersection is valid, of so then done, else compute next
01191                         if (xc1 < min_clip_x || xc1 > max_clip_x)
01192                         {
01193                                 xc1 = (int) min_clip_x;
01194                                 yc1 = (int) (y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1)); 
01195                         } // end if
01196 
01197                 } 
01198                 break;
01199                 
01200         case CLIP_CODE_SW:
01201                 {
01202                         // south hline intersection
01203                         yc1 = (int) max_clip_y;
01204                         xc1 = (int) (x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1)); 
01205 
01206                         // test if intersection is valid, of so then done, else compute next
01207                         if (xc1 < min_clip_x || xc1 > max_clip_x)
01208                         {
01209                                 xc1 = (int) min_clip_x;
01210                                 yc1 = (int) (y1 + 0.5+(min_clip_x-x1)*(y2-y1)/(x2-x1)); 
01211                         } // end if
01212                 }
01213                 break;
01214 
01215         default:
01216                 break;
01217 
01218         } // end switch
01219 
01220         // determine clip point for p2
01221         switch(p2_code)
01222         {
01223         case CLIP_CODE_C: 
01224                 break;
01225 
01226         case CLIP_CODE_N:
01227                 {
01228                         yc2 = (int) min_clip_y;
01229                         xc2 = (int) (x2 + (min_clip_y-y2)*(x1-x2)/(y1-y2));
01230                 } 
01231                 break;
01232 
01233         case CLIP_CODE_S:
01234                 {
01235                         yc2 = (int) max_clip_y;
01236                         xc2 = (int) (x2 + (max_clip_y-y2)*(x1-x2)/(y1-y2));
01237                 } 
01238                 break;
01239 
01240         case CLIP_CODE_W:
01241                 {
01242                         xc2 = (int) min_clip_x;
01243                         yc2 = (int) (y2 + (min_clip_x-x2)*(y1-y2)/(x1-x2));
01244                 } 
01245                 break;
01246 
01247         case CLIP_CODE_E:
01248                 {
01249                         xc2 = (int) max_clip_x;
01250                         yc2 = (int) (y2 + (max_clip_x-x2)*(y1-y2)/(x1-x2));
01251                 } 
01252                 break;
01253 
01254         // these cases are more complex, must compute 2 intersections
01255         case CLIP_CODE_NE:
01256                 {
01257                 // north hline intersection
01258                 yc2 = (int) min_clip_y;
01259                 xc2 = (int) (x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2));
01260 
01261                 // test if intersection is valid, of so then done, else compute next
01262                 if (xc2 < min_clip_x || xc2 > max_clip_x)
01263                 {
01264                         // east vline intersection
01265                         xc2 = (int) max_clip_x;
01266                         yc2 = (int) (y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2));
01267                 } // end if
01268 
01269                 } 
01270                 break;
01271 
01272         case CLIP_CODE_SE:
01273                 {
01274                         // south hline intersection
01275                         yc2 = (int) max_clip_y;
01276                         xc2 = (int) (x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2)); 
01277 
01278                         // test if intersection is valid, of so then done, else compute next
01279                         if (xc2 < min_clip_x || xc2 > max_clip_x)
01280                         {
01281                                 // east vline intersection
01282                                 xc2 = (int) max_clip_x;
01283                                 yc2 = (int) (y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2));
01284                         } // end if
01285                 } 
01286                 break;
01287 
01288         case CLIP_CODE_NW:
01289                 {
01290                         // north hline intersection
01291                         yc2 = (int) min_clip_y;
01292                         xc2 = (int) (x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2));
01293 
01294                         // test if intersection is valid, of so then done, else compute next
01295                         if (xc2 < min_clip_x || xc2 > max_clip_x)
01296                         {
01297                                 xc2 = (int) min_clip_x;
01298                                 yc2 = (int) (y2 + 0.5+(min_clip_x-x2)*(y1-y2)/(x1-x2)); 
01299                         } // end if
01300                 } 
01301                 break;
01302 
01303         case CLIP_CODE_SW:
01304                 {
01305                         // south hline intersection
01306                         yc2 = (int) max_clip_y;
01307                         xc2 = (int) (x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2)); 
01308 
01309                         // test if intersection is valid, of so then done, else compute next
01310                         if (xc2 < min_clip_x || xc2 > max_clip_x)
01311                         {
01312                                 xc2 = (int) min_clip_x;
01313                                 yc2 = (int) (y2 + 0.5+(min_clip_x-x2)*(y1-y2)/(x1-x2)); 
01314                         } // end if
01315 
01316                 } 
01317                 break;
01318 
01319         default:
01320                 break;
01321 
01322         } // end switch
01323 
01324         // do bounds check
01325         if ((xc1 < min_clip_x) || (xc1 > max_clip_x) ||
01326                 (yc1 < min_clip_y) || (yc1 > max_clip_y) ||
01327                 (xc2 < min_clip_x) || (xc2 > max_clip_x) ||
01328                 (yc2 < min_clip_y) || (yc2 > max_clip_y) )
01329         {
01330                         return(0);
01331         } // end if
01332 
01333         // store vars back
01334         x1 = xc1;
01335         y1 = yc1;
01336         x2 = xc2;
01337         y2 = yc2;
01338 
01339         return(1);
01340 }

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