00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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;
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;
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
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
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
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
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
00379
00380 fill_rect(x1, y1, x2, y1 + 1, r, g, b, a);
00381 fill_rect(x1, y1 + 1, x1 + 1, y2 - 1, r, g, b, a);
00382 fill_rect(x2 - 1, y1 + 1, x2, y2 - 1, r, g, b, a);
00383 fill_rect(x1, y2 - 1, x2, y2, r, g, b, a);
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
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
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);
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();
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
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
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);
00768 break;
00769 }
00770
00771 target->unlock();
00772 }
00773
00774
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
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
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
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
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
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
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
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
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
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
01039
01040
01041
01042
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
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
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
01104 if ((p1_code & p2_code))
01105 {
01106 return(0);
01107 }
01108
01109
01110 if (p1_code==0 && p2_code==0)
01111 {
01112 return(1);
01113 }
01114
01115
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
01150 case CLIP_CODE_NE:
01151 {
01152
01153 yc1 = (int) min_clip_y;
01154 xc1 = (int) (x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1));
01155
01156
01157 if (xc1 < min_clip_x || xc1 > max_clip_x)
01158 {
01159
01160 xc1 = (int) max_clip_x;
01161 yc1 = (int) (y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1));
01162 }
01163
01164 }
01165 break;
01166
01167 case CLIP_CODE_SE:
01168 {
01169
01170 yc1 = (int) max_clip_y;
01171 xc1 = (int) (x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1));
01172
01173
01174 if (xc1 < min_clip_x || xc1 > max_clip_x)
01175 {
01176
01177 xc1 = (int) max_clip_x;
01178 yc1 = (int) (y1 + 0.5+(max_clip_x-x1)*(y2-y1)/(x2-x1));
01179 }
01180
01181 }
01182 break;
01183
01184 case CLIP_CODE_NW:
01185 {
01186
01187 yc1 = (int) min_clip_y;
01188 xc1 = (int) (x1 + 0.5+(min_clip_y-y1)*(x2-x1)/(y2-y1));
01189
01190
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 }
01196
01197 }
01198 break;
01199
01200 case CLIP_CODE_SW:
01201 {
01202
01203 yc1 = (int) max_clip_y;
01204 xc1 = (int) (x1 + 0.5+(max_clip_y-y1)*(x2-x1)/(y2-y1));
01205
01206
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 }
01212 }
01213 break;
01214
01215 default:
01216 break;
01217
01218 }
01219
01220
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
01255 case CLIP_CODE_NE:
01256 {
01257
01258 yc2 = (int) min_clip_y;
01259 xc2 = (int) (x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2));
01260
01261
01262 if (xc2 < min_clip_x || xc2 > max_clip_x)
01263 {
01264
01265 xc2 = (int) max_clip_x;
01266 yc2 = (int) (y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2));
01267 }
01268
01269 }
01270 break;
01271
01272 case CLIP_CODE_SE:
01273 {
01274
01275 yc2 = (int) max_clip_y;
01276 xc2 = (int) (x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2));
01277
01278
01279 if (xc2 < min_clip_x || xc2 > max_clip_x)
01280 {
01281
01282 xc2 = (int) max_clip_x;
01283 yc2 = (int) (y2 + 0.5+(max_clip_x-x2)*(y1-y2)/(x1-x2));
01284 }
01285 }
01286 break;
01287
01288 case CLIP_CODE_NW:
01289 {
01290
01291 yc2 = (int) min_clip_y;
01292 xc2 = (int) (x2 + 0.5+(min_clip_y-y2)*(x1-x2)/(y1-y2));
01293
01294
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 }
01300 }
01301 break;
01302
01303 case CLIP_CODE_SW:
01304 {
01305
01306 yc2 = (int) max_clip_y;
01307 xc2 = (int) (x2 + 0.5+(max_clip_y-y2)*(x1-x2)/(y1-y2));
01308
01309
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 }
01315
01316 }
01317 break;
01318
01319 default:
01320 break;
01321
01322 }
01323
01324
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 }
01332
01333
01334 x1 = xc1;
01335 y1 = yc1;
01336 x2 = xc2;
01337 y2 = yc2;
01338
01339 return(1);
01340 }