SDL_gfx
2.0.25
|
00001 /* 00002 00003 SDL_gfxPrimitives.c: graphics primitives for SDL surfaces 00004 00005 Copyright (C) 2001-2012 Andreas Schiffler 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for any damages 00009 arising from the use of this software. 00010 00011 Permission is granted to anyone to use this software for any purpose, 00012 including commercial applications, and to alter it and redistribute it 00013 freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must not 00016 claim that you wrote the original software. If you use this software 00017 in a product, an acknowledgment in the product documentation would be 00018 appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must not be 00021 misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any source 00024 distribution. 00025 00026 Andreas Schiffler -- aschiffler at ferzkopp dot net 00027 00028 */ 00029 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <math.h> 00033 #include <string.h> 00034 00035 #include "SDL_gfxPrimitives.h" 00036 #include "SDL_rotozoom.h" 00037 #include "SDL_gfxPrimitives_font.h" 00038 #include "SDL_gfxBlitFunc.h" 00039 00040 /* -===================- */ 00041 00042 #define DEFAULT_ALPHA_PIXEL_ROUTINE 00043 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00044 #define ALPHA_PIXEL_ADDITIVE_BLEND 00045 00046 /* ---- Structures */ 00047 00051 typedef struct { 00052 Sint16 x, y; 00053 int dx, dy, s1, s2, swapdir, error; 00054 Uint32 count; 00055 } SDL_gfxBresenhamIterator; 00056 00060 typedef struct { 00061 Uint32 color; 00062 SDL_Surface *dst; 00063 int u, v; /* delta x , delta y */ 00064 int ku, kt, kv, kd; /* loop constants */ 00065 int oct2; 00066 int quad4; 00067 Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy; 00068 } SDL_gfxMurphyIterator; 00069 00070 /* ----- Defines for pixel clipping tests */ 00071 00072 #define clip_xmin(surface) surface->clip_rect.x 00073 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1 00074 #define clip_ymin(surface) surface->clip_rect.y 00075 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1 00076 00087 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00088 { 00089 int bpp; 00090 Uint8 *p; 00091 00092 /* 00093 * Honor clipping setup at pixel level 00094 */ 00095 if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) { 00096 00097 /* 00098 * Get destination format 00099 */ 00100 bpp = dst->format->BytesPerPixel; 00101 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00102 switch (bpp) { 00103 case 1: 00104 *p = color; 00105 break; 00106 case 2: 00107 *(Uint16 *) p = color; 00108 break; 00109 case 3: 00110 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 00111 p[0] = (color >> 16) & 0xff; 00112 p[1] = (color >> 8) & 0xff; 00113 p[2] = color & 0xff; 00114 } else { 00115 p[0] = color & 0xff; 00116 p[1] = (color >> 8) & 0xff; 00117 p[2] = (color >> 16) & 0xff; 00118 } 00119 break; 00120 case 4: 00121 *(Uint32 *) p = color; 00122 break; 00123 } /* switch */ 00124 00125 00126 } 00127 00128 return (0); 00129 } 00130 00144 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00145 { 00146 int bpp; 00147 Uint8 *p; 00148 00149 /* 00150 * Get destination format 00151 */ 00152 bpp = dst->format->BytesPerPixel; 00153 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00154 switch (bpp) { 00155 case 1: 00156 *p = color; 00157 break; 00158 case 2: 00159 *(Uint16 *) p = color; 00160 break; 00161 case 3: 00162 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 00163 p[0] = (color >> 16) & 0xff; 00164 p[1] = (color >> 8) & 0xff; 00165 p[2] = color & 0xff; 00166 } else { 00167 p[0] = color & 0xff; 00168 p[1] = (color >> 8) & 0xff; 00169 p[2] = (color >> 16) & 0xff; 00170 } 00171 break; 00172 case 4: 00173 *(Uint32 *) p = color; 00174 break; 00175 } /* switch */ 00176 00177 return (0); 00178 } 00179 00190 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00191 { 00192 int result; 00193 00194 /* 00195 * Lock the surface 00196 */ 00197 if (SDL_MUSTLOCK(dst)) { 00198 if (SDL_LockSurface(dst) < 0) { 00199 return (-1); 00200 } 00201 } 00202 00203 result = fastPixelColorNolock(dst, x, y, color); 00204 00205 /* 00206 * Unlock surface 00207 */ 00208 if (SDL_MUSTLOCK(dst)) { 00209 SDL_UnlockSurface(dst); 00210 } 00211 00212 return (result); 00213 } 00214 00228 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 00229 { 00230 Uint32 color; 00231 00232 /* 00233 * Setup color 00234 */ 00235 color = SDL_MapRGBA(dst->format, r, g, b, a); 00236 00237 /* 00238 * Draw 00239 */ 00240 return (fastPixelColor(dst, x, y, color)); 00241 } 00242 00256 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 00257 { 00258 Uint32 color; 00259 00260 /* 00261 * Setup color 00262 */ 00263 color = SDL_MapRGBA(dst->format, r, g, b, a); 00264 00265 /* 00266 * Draw 00267 */ 00268 return (fastPixelColorNolock(dst, x, y, color)); 00269 } 00270 00286 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) 00287 { 00288 SDL_PixelFormat *format; 00289 Uint32 Rmask, Gmask, Bmask, Amask; 00290 Uint32 Rshift, Gshift, Bshift, Ashift; 00291 Uint32 sR, sG, sB; 00292 Uint32 dR, dG, dB, dA; 00293 00294 if (dst == NULL) 00295 { 00296 return (-1); 00297 } 00298 00299 if (x >= clip_xmin(dst) && x <= clip_xmax(dst) && 00300 y >= clip_ymin(dst) && y <= clip_ymax(dst)) 00301 { 00302 00303 format = dst->format; 00304 00305 switch (format->BytesPerPixel) { 00306 case 1: 00307 { /* Assuming 8-bpp */ 00308 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x; 00309 if (alpha == 255) { 00310 *pixel = color; 00311 } else { 00312 Uint8 R, G, B; 00313 SDL_Palette *palette = format->palette; 00314 SDL_Color *colors = palette->colors; 00315 SDL_Color dColor = colors[*pixel]; 00316 SDL_Color sColor = colors[color]; 00317 dR = dColor.r; 00318 dG = dColor.g; 00319 dB = dColor.b; 00320 sR = sColor.r; 00321 sG = sColor.g; 00322 sB = sColor.b; 00323 00324 R = dR + ((sR - dR) * alpha >> 8); 00325 G = dG + ((sG - dG) * alpha >> 8); 00326 B = dB + ((sB - dB) * alpha >> 8); 00327 00328 *pixel = SDL_MapRGB(format, R, G, B); 00329 } 00330 } 00331 break; 00332 00333 case 2: 00334 { /* Probably 15-bpp or 16-bpp */ 00335 Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x; 00336 if (alpha == 255) { 00337 *pixel = color; 00338 } else { 00339 Uint16 R, G, B, A; 00340 Uint16 dc = *pixel; 00341 00342 Rmask = format->Rmask; 00343 Gmask = format->Gmask; 00344 Bmask = format->Bmask; 00345 Amask = format->Amask; 00346 00347 dR = (dc & Rmask); 00348 dG = (dc & Gmask); 00349 dB = (dc & Bmask); 00350 00351 R = (dR + (((color & Rmask) - dR) * alpha >> 8)) & Rmask; 00352 G = (dG + (((color & Gmask) - dG) * alpha >> 8)) & Gmask; 00353 B = (dB + (((color & Bmask) - dB) * alpha >> 8)) & Bmask; 00354 *pixel = R | G | B; 00355 if (Amask!=0) { 00356 dA = (dc & Amask); 00357 A = (dA + (((color & Amask) - dA) * alpha >> 8)) & Amask; 00358 *pixel |= A; 00359 } 00360 } 00361 } 00362 break; 00363 00364 case 3: 00365 { /* Slow 24-bpp mode, usually not used */ 00366 Uint8 R, G, B; 00367 Uint8 Rshift8, Gshift8, Bshift8; 00368 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3; 00369 00370 Rshift = format->Rshift; 00371 Gshift = format->Gshift; 00372 Bshift = format->Bshift; 00373 00374 Rshift8 = Rshift >> 3; 00375 Gshift8 = Gshift >> 3; 00376 Bshift8 = Bshift >> 3; 00377 00378 sR = (color >> Rshift) & 0xFF; 00379 sG = (color >> Gshift) & 0xFF; 00380 sB = (color >> Bshift) & 0xFF; 00381 00382 if (alpha == 255) { 00383 *(pixel + Rshift8) = sR; 00384 *(pixel + Gshift8) = sG; 00385 *(pixel + Bshift8) = sB; 00386 } else { 00387 dR = *((pixel) + Rshift8); 00388 dG = *((pixel) + Gshift8); 00389 dB = *((pixel) + Bshift8); 00390 00391 R = dR + ((sR - dR) * alpha >> 8); 00392 G = dG + ((sG - dG) * alpha >> 8); 00393 B = dB + ((sB - dB) * alpha >> 8); 00394 00395 *((pixel) + Rshift8) = R; 00396 *((pixel) + Gshift8) = G; 00397 *((pixel) + Bshift8) = B; 00398 } 00399 } 00400 break; 00401 00402 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE 00403 00404 case 4: 00405 { /* Probably :-) 32-bpp */ 00406 Uint32 R, G, B, A; 00407 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; 00408 if (alpha == 255) { 00409 *pixel = color; 00410 } else { 00411 Uint32 dc = *pixel; 00412 00413 Rmask = format->Rmask; 00414 Gmask = format->Gmask; 00415 Bmask = format->Bmask; 00416 Amask = format->Amask; 00417 00418 Rshift = format->Rshift; 00419 Gshift = format->Gshift; 00420 Bshift = format->Bshift; 00421 Ashift = format->Ashift; 00422 00423 dR = (dc & Rmask) >> Rshift; 00424 dG = (dc & Gmask) >> Gshift; 00425 dB = (dc & Bmask) >> Bshift; 00426 00427 00428 R = ((dR + ((((color & Rmask) >> Rshift) - dR) * alpha >> 8)) << Rshift) & Rmask; 00429 G = ((dG + ((((color & Gmask) >> Gshift) - dG) * alpha >> 8)) << Gshift) & Gmask; 00430 B = ((dB + ((((color & Bmask) >> Bshift) - dB) * alpha >> 8)) << Bshift) & Bmask; 00431 *pixel = R | G | B; 00432 if (Amask!=0) { 00433 dA = (dc & Amask) >> Ashift; 00434 00435 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND 00436 A = (dA | GFX_ALPHA_ADJUST_ARRAY[alpha & 255]) << Ashift; // make destination less transparent... 00437 #else 00438 A = ((dA + ((((color & Amask) >> Ashift) - dA) * alpha >> 8)) << Ashift) & Amask; 00439 #endif 00440 *pixel |= A; 00441 } 00442 } 00443 } 00444 break; 00445 #endif 00446 00447 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00448 00449 case 4:{ /* Probably :-) 32-bpp */ 00450 if (alpha == 255) { 00451 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color; 00452 } else { 00453 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; 00454 Uint32 dR, dG, dB, dA; 00455 Uint32 dc = *pixel; 00456 00457 Uint32 surfaceAlpha, preMultR, preMultG, preMultB; 00458 Uint32 aTmp; 00459 00460 Rmask = format->Rmask; 00461 Gmask = format->Gmask; 00462 Bmask = format->Bmask; 00463 Amask = format->Amask; 00464 00465 dR = (color & Rmask); 00466 dG = (color & Gmask); 00467 dB = (color & Bmask); 00468 dA = (color & Amask); 00469 00470 Rshift = format->Rshift; 00471 Gshift = format->Gshift; 00472 Bshift = format->Bshift; 00473 Ashift = format->Ashift; 00474 00475 preMultR = (alpha * (dR >> Rshift)); 00476 preMultG = (alpha * (dG >> Gshift)); 00477 preMultB = (alpha * (dB >> Bshift)); 00478 00479 surfaceAlpha = ((dc & Amask) >> Ashift); 00480 aTmp = (255 - alpha); 00481 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { 00482 aTmp *= surfaceAlpha; 00483 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; 00484 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; 00485 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; 00486 } 00487 *pixel = R | G | B | (A << Ashift & Amask); 00488 00489 } 00490 } 00491 break; 00492 #endif 00493 } 00494 } 00495 00496 return (0); 00497 } 00498 00509 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00510 { 00511 Uint8 alpha; 00512 Uint32 mcolor; 00513 int result = 0; 00514 00515 /* 00516 * Lock the surface 00517 */ 00518 if (SDL_MUSTLOCK(dst)) { 00519 if (SDL_LockSurface(dst) < 0) { 00520 return (-1); 00521 } 00522 } 00523 00524 /* 00525 * Setup color 00526 */ 00527 alpha = color & 0x000000ff; 00528 mcolor = 00529 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00530 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00531 00532 /* 00533 * Draw 00534 */ 00535 result = _putPixelAlpha(dst, x, y, mcolor, alpha); 00536 00537 /* 00538 * Unlock the surface 00539 */ 00540 if (SDL_MUSTLOCK(dst)) { 00541 SDL_UnlockSurface(dst); 00542 } 00543 00544 return (result); 00545 } 00546 00557 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00558 { 00559 Uint8 alpha; 00560 Uint32 mcolor; 00561 int result = 0; 00562 00563 /* 00564 * Setup color 00565 */ 00566 alpha = color & 0x000000ff; 00567 mcolor = 00568 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00569 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00570 00571 /* 00572 * Draw 00573 */ 00574 result = _putPixelAlpha(dst, x, y, mcolor, alpha); 00575 00576 return (result); 00577 } 00578 00579 00595 int _filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha) 00596 { 00597 SDL_PixelFormat *format; 00598 Uint32 Rmask, Gmask, Bmask, Amask; 00599 Uint32 Rshift, Gshift, Bshift, Ashift; 00600 Uint32 sR, sG, sB, sA; 00601 Uint32 dR, dG, dB, dA; 00602 Sint16 x, y; 00603 00604 if (dst == NULL) { 00605 return (-1); 00606 } 00607 00608 format = dst->format; 00609 switch (format->BytesPerPixel) { 00610 case 1: 00611 { /* Assuming 8-bpp */ 00612 Uint8 *row, *pixel; 00613 Uint8 R, G, B; 00614 SDL_Color *colors = format->palette->colors; 00615 SDL_Color dColor; 00616 SDL_Color sColor = colors[color]; 00617 sR = sColor.r; 00618 sG = sColor.g; 00619 sB = sColor.b; 00620 00621 for (y = y1; y <= y2; y++) { 00622 row = (Uint8 *) dst->pixels + y * dst->pitch; 00623 for (x = x1; x <= x2; x++) { 00624 if (alpha == 255) { 00625 *(row + x) = color; 00626 } else { 00627 pixel = row + x; 00628 00629 dColor = colors[*pixel]; 00630 dR = dColor.r; 00631 dG = dColor.g; 00632 dB = dColor.b; 00633 00634 R = dR + ((sR - dR) * alpha >> 8); 00635 G = dG + ((sG - dG) * alpha >> 8); 00636 B = dB + ((sB - dB) * alpha >> 8); 00637 00638 *pixel = SDL_MapRGB(format, R, G, B); 00639 } 00640 } 00641 } 00642 } 00643 break; 00644 00645 case 2: 00646 { /* Probably 15-bpp or 16-bpp */ 00647 Uint16 *row, *pixel; 00648 Uint16 R, G, B, A; 00649 Uint16 dc; 00650 Rmask = format->Rmask; 00651 Gmask = format->Gmask; 00652 Bmask = format->Bmask; 00653 Amask = format->Amask; 00654 00655 sR = (color & Rmask); 00656 sG = (color & Gmask); 00657 sB = (color & Bmask); 00658 sA = (color & Amask); 00659 00660 for (y = y1; y <= y2; y++) { 00661 row = (Uint16 *) dst->pixels + y * dst->pitch / 2; 00662 for (x = x1; x <= x2; x++) { 00663 if (alpha == 255) { 00664 *(row + x) = color; 00665 } else { 00666 pixel = row + x; 00667 dc = *pixel; 00668 00669 dR = (dc & Rmask); 00670 dG = (dc & Gmask); 00671 dB = (dc & Bmask); 00672 00673 R = (dR + ((sR - dR) * alpha >> 8)) & Rmask; 00674 G = (dG + ((sG - dG) * alpha >> 8)) & Gmask; 00675 B = (dB + ((sB - dB) * alpha >> 8)) & Bmask; 00676 *pixel = R | G | B; 00677 if (Amask!=0) { 00678 dA = (dc & Amask); 00679 A = (dA + ((sA - dA) * alpha >> 8)) & Amask; 00680 *pixel |= A; 00681 } 00682 } 00683 } 00684 } 00685 } 00686 break; 00687 00688 case 3: 00689 { /* Slow 24-bpp mode, usually not used */ 00690 Uint8 *row, *pixel; 00691 Uint8 R, G, B; 00692 Uint8 Rshift8, Gshift8, Bshift8; 00693 00694 Rshift = format->Rshift; 00695 Gshift = format->Gshift; 00696 Bshift = format->Bshift; 00697 00698 Rshift8 = Rshift >> 3; 00699 Gshift8 = Gshift >> 3; 00700 Bshift8 = Bshift >> 3; 00701 00702 sR = (color >> Rshift) & 0xff; 00703 sG = (color >> Gshift) & 0xff; 00704 sB = (color >> Bshift) & 0xff; 00705 00706 for (y = y1; y <= y2; y++) { 00707 row = (Uint8 *) dst->pixels + y * dst->pitch; 00708 for (x = x1; x <= x2; x++) { 00709 pixel = row + x * 3; 00710 00711 if (alpha == 255) { 00712 *(pixel + Rshift8) = sR; 00713 *(pixel + Gshift8) = sG; 00714 *(pixel + Bshift8) = sB; 00715 } else { 00716 dR = *((pixel) + Rshift8); 00717 dG = *((pixel) + Gshift8); 00718 dB = *((pixel) + Bshift8); 00719 00720 R = dR + ((sR - dR) * alpha >> 8); 00721 G = dG + ((sG - dG) * alpha >> 8); 00722 B = dB + ((sB - dB) * alpha >> 8); 00723 00724 *((pixel) + Rshift8) = R; 00725 *((pixel) + Gshift8) = G; 00726 *((pixel) + Bshift8) = B; 00727 } 00728 } 00729 } 00730 } 00731 break; 00732 00733 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE 00734 case 4: 00735 { /* Probably :-) 32-bpp */ 00736 Uint32 *row, *pixel; 00737 Uint32 R, G, B, A; 00738 Uint32 dc; 00739 Rmask = format->Rmask; 00740 Gmask = format->Gmask; 00741 Bmask = format->Bmask; 00742 Amask = format->Amask; 00743 00744 Rshift = format->Rshift; 00745 Gshift = format->Gshift; 00746 Bshift = format->Bshift; 00747 Ashift = format->Ashift; 00748 00749 sR = (color & Rmask) >> Rshift; 00750 sG = (color & Gmask) >> Gshift; 00751 sB = (color & Bmask) >> Bshift; 00752 sA = (color & Amask) >> Ashift; 00753 00754 for (y = y1; y <= y2; y++) { 00755 row = (Uint32 *) dst->pixels + y * dst->pitch / 4; 00756 for (x = x1; x <= x2; x++) { 00757 if (alpha == 255) { 00758 *(row + x) = color; 00759 } else { 00760 pixel = row + x; 00761 dc = *pixel; 00762 00763 dR = (dc & Rmask) >> Rshift; 00764 dG = (dc & Gmask) >> Gshift; 00765 dB = (dc & Bmask) >> Bshift; 00766 00767 R = ((dR + ((sR - dR) * alpha >> 8)) << Rshift) & Rmask; 00768 G = ((dG + ((sG - dG) * alpha >> 8)) << Gshift) & Gmask; 00769 B = ((dB + ((sB - dB) * alpha >> 8)) << Bshift) & Bmask; 00770 *pixel = R | G | B; 00771 if (Amask!=0) { 00772 dA = (dc & Amask) >> Ashift; 00773 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND 00774 A = (dA | GFX_ALPHA_ADJUST_ARRAY[sA & 255]) << Ashift; // make destination less transparent... 00775 #else 00776 A = ((dA + ((sA - dA) * alpha >> 8)) << Ashift) & Amask; 00777 #endif 00778 *pixel |= A; 00779 } 00780 } 00781 } 00782 } 00783 } 00784 break; 00785 #endif 00786 00787 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00788 case 4:{ /* Probably :-) 32-bpp */ 00789 Uint32 *row, *pixel; 00790 Uint32 dR, dG, dB, dA; 00791 Uint32 dc; 00792 Uint32 surfaceAlpha, preMultR, preMultG, preMultB; 00793 Uint32 aTmp; 00794 00795 Rmask = format->Rmask; 00796 Gmask = format->Gmask; 00797 Bmask = format->Bmask; 00798 Amask = format->Amask; 00799 00800 dR = (color & Rmask); 00801 dG = (color & Gmask); 00802 dB = (color & Bmask); 00803 dA = (color & Amask); 00804 00805 Rshift = format->Rshift; 00806 Gshift = format->Gshift; 00807 Bshift = format->Bshift; 00808 Ashift = format->Ashift; 00809 00810 preMultR = (alpha * (dR >> Rshift)); 00811 preMultG = (alpha * (dG >> Gshift)); 00812 preMultB = (alpha * (dB >> Bshift)); 00813 00814 for (y = y1; y <= y2; y++) { 00815 row = (Uint32 *) dst->pixels + y * dst->pitch / 4; 00816 for (x = x1; x <= x2; x++) { 00817 if (alpha == 255) { 00818 *(row + x) = color; 00819 } else { 00820 pixel = row + x; 00821 dc = *pixel; 00822 00823 surfaceAlpha = ((dc & Amask) >> Ashift); 00824 aTmp = (255 - alpha); 00825 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { 00826 aTmp *= surfaceAlpha; 00827 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; 00828 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; 00829 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; 00830 } 00831 *pixel = R | G | B | (A << Ashift & Amask); 00832 } 00833 } 00834 } 00835 } 00836 break; 00837 #endif 00838 00839 } 00840 00841 return (0); 00842 } 00843 00856 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) 00857 { 00858 Uint8 alpha; 00859 Uint32 mcolor; 00860 int result = 0; 00861 00862 /* 00863 * Lock the surface 00864 */ 00865 if (SDL_MUSTLOCK(dst)) { 00866 if (SDL_LockSurface(dst) < 0) { 00867 return (-1); 00868 } 00869 } 00870 00871 /* 00872 * Setup color 00873 */ 00874 alpha = color & 0x000000ff; 00875 mcolor = 00876 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00877 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00878 00879 /* 00880 * Draw 00881 */ 00882 result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha); 00883 00884 /* 00885 * Unlock the surface 00886 */ 00887 if (SDL_MUSTLOCK(dst)) { 00888 SDL_UnlockSurface(dst); 00889 } 00890 00891 return (result); 00892 } 00893 00905 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 00906 { 00907 return (filledRectAlpha(dst, x1, y, x2, y, color)); 00908 } 00909 00921 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) 00922 { 00923 return (filledRectAlpha(dst, x, y1, x, y2, color)); 00924 } 00925 00937 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) 00938 { 00939 Uint32 a; 00940 00941 /* 00942 * Get alpha 00943 */ 00944 a = (color & (Uint32) 0x000000ff); 00945 00946 /* 00947 * Modify Alpha by weight 00948 */ 00949 a = ((a * weight) >> 8); 00950 00951 return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a)); 00952 } 00953 00965 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) 00966 { 00967 Uint32 a; 00968 00969 /* 00970 * Get alpha 00971 */ 00972 a = (color & (Uint32) 0x000000ff); 00973 00974 /* 00975 * Modify Alpha by weight 00976 */ 00977 a = ((a * weight) >> 8); 00978 00979 return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a)); 00980 } 00981 00995 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 00996 { 00997 Uint32 color; 00998 00999 /* 01000 * Check Alpha 01001 */ 01002 if (a == 255) { 01003 /* 01004 * No alpha blending required 01005 */ 01006 /* 01007 * Setup color 01008 */ 01009 color = SDL_MapRGBA(dst->format, r, g, b, a); 01010 /* 01011 * Draw 01012 */ 01013 return (fastPixelColor(dst, x, y, color)); 01014 } else { 01015 /* 01016 * Alpha blending required 01017 */ 01018 /* 01019 * Draw 01020 */ 01021 return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01022 } 01023 } 01024 01025 01041 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 01042 { 01043 Sint16 left, right, top, bottom; 01044 Uint8 *pixel, *pixellast; 01045 int dx; 01046 int pixx, pixy; 01047 Sint16 w; 01048 Sint16 xtmp; 01049 int result = -1; 01050 01051 /* 01052 * Check visibility of clipping rectangle 01053 */ 01054 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01055 return(0); 01056 } 01057 01058 /* 01059 * Swap x1, x2 if required to ensure x1<=x2 01060 */ 01061 if (x1 > x2) { 01062 xtmp = x1; 01063 x1 = x2; 01064 x2 = xtmp; 01065 } 01066 01067 /* 01068 * Get clipping boundary and 01069 * check visibility of hline 01070 */ 01071 left = dst->clip_rect.x; 01072 if (x2<left) { 01073 return(0); 01074 } 01075 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01076 if (x1>right) { 01077 return(0); 01078 } 01079 top = dst->clip_rect.y; 01080 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01081 if ((y<top) || (y>bottom)) { 01082 return (0); 01083 } 01084 01085 /* 01086 * Clip x 01087 */ 01088 if (x1 < left) { 01089 x1 = left; 01090 } 01091 if (x2 > right) { 01092 x2 = right; 01093 } 01094 01095 /* 01096 * Calculate width 01097 */ 01098 w = x2 - x1; 01099 01100 /* 01101 * Lock the surface 01102 */ 01103 if (SDL_MUSTLOCK(dst)) { 01104 if (SDL_LockSurface(dst) < 0) { 01105 return (-1); 01106 } 01107 } 01108 01109 /* 01110 * More variable setup 01111 */ 01112 dx = w; 01113 pixx = dst->format->BytesPerPixel; 01114 pixy = dst->pitch; 01115 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; 01116 01117 /* 01118 * Draw 01119 */ 01120 switch (dst->format->BytesPerPixel) { 01121 case 1: 01122 memset(pixel, color, dx+1); 01123 break; 01124 case 2: 01125 pixellast = pixel + dx + dx; 01126 for (; pixel <= pixellast; pixel += pixx) { 01127 *(Uint16 *) pixel = color; 01128 } 01129 break; 01130 case 3: 01131 pixellast = pixel + dx + dx + dx; 01132 for (; pixel <= pixellast; pixel += pixx) { 01133 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01134 pixel[0] = (color >> 16) & 0xff; 01135 pixel[1] = (color >> 8) & 0xff; 01136 pixel[2] = color & 0xff; 01137 } else { 01138 pixel[0] = color & 0xff; 01139 pixel[1] = (color >> 8) & 0xff; 01140 pixel[2] = (color >> 16) & 0xff; 01141 } 01142 } 01143 break; 01144 default: /* case 4 */ 01145 dx = dx + dx; 01146 pixellast = pixel + dx + dx; 01147 for (; pixel <= pixellast; pixel += pixx) { 01148 *(Uint32 *) pixel = color; 01149 } 01150 break; 01151 } 01152 01153 /* 01154 * Unlock surface 01155 */ 01156 if (SDL_MUSTLOCK(dst)) { 01157 SDL_UnlockSurface(dst); 01158 } 01159 01160 /* 01161 * Set result code 01162 */ 01163 result = 0; 01164 01165 return (result); 01166 } 01167 01185 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01186 { 01187 /* 01188 * Draw 01189 */ 01190 return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01191 } 01192 01204 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 01205 { 01206 Sint16 left, right, top, bottom; 01207 Uint8 *pixel, *pixellast; 01208 int dx; 01209 int pixx, pixy; 01210 Sint16 xtmp; 01211 int result = -1; 01212 Uint8 *colorptr; 01213 Uint8 color3[3]; 01214 01215 /* 01216 * Check visibility of clipping rectangle 01217 */ 01218 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01219 return(0); 01220 } 01221 01222 /* 01223 * Swap x1, x2 if required to ensure x1<=x2 01224 */ 01225 if (x1 > x2) { 01226 xtmp = x1; 01227 x1 = x2; 01228 x2 = xtmp; 01229 } 01230 01231 /* 01232 * Get clipping boundary and 01233 * check visibility of hline 01234 */ 01235 left = dst->clip_rect.x; 01236 if (x2<left) { 01237 return(0); 01238 } 01239 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01240 if (x1>right) { 01241 return(0); 01242 } 01243 top = dst->clip_rect.y; 01244 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01245 if ((y<top) || (y>bottom)) { 01246 return (0); 01247 } 01248 01249 /* 01250 * Clip x 01251 */ 01252 if (x1 < left) { 01253 x1 = left; 01254 } 01255 if (x2 > right) { 01256 x2 = right; 01257 } 01258 01259 /* 01260 * Calculate width difference 01261 */ 01262 dx = x2 - x1; 01263 01264 /* 01265 * Alpha check 01266 */ 01267 if ((color & 255) == 255) { 01268 01269 /* 01270 * No alpha-blending required 01271 */ 01272 01273 /* 01274 * Setup color 01275 */ 01276 colorptr = (Uint8 *) & color; 01277 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01278 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 01279 } else { 01280 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 01281 } 01282 01283 /* 01284 * Lock the surface 01285 */ 01286 if (SDL_MUSTLOCK(dst)) { 01287 if (SDL_LockSurface(dst) < 0) { 01288 return (-1); 01289 } 01290 } 01291 01292 /* 01293 * More variable setup 01294 */ 01295 pixx = dst->format->BytesPerPixel; 01296 pixy = dst->pitch; 01297 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; 01298 01299 /* 01300 * Draw 01301 */ 01302 switch (dst->format->BytesPerPixel) { 01303 case 1: 01304 memset(pixel, color, dx + 1); 01305 break; 01306 case 2: 01307 pixellast = pixel + dx + dx; 01308 for (; pixel <= pixellast; pixel += pixx) { 01309 *(Uint16 *) pixel = color; 01310 } 01311 break; 01312 case 3: 01313 pixellast = pixel + dx + dx + dx; 01314 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01315 color3[0] = (color >> 16) & 0xff; 01316 color3[1] = (color >> 8) & 0xff; 01317 color3[2] = color & 0xff; 01318 } else { 01319 color3[0] = color & 0xff; 01320 color3[1] = (color >> 8) & 0xff; 01321 color3[2] = (color >> 16) & 0xff; 01322 } 01323 for (; pixel <= pixellast; pixel += pixx) { 01324 memcpy(pixel, color3, 3); 01325 } 01326 break; 01327 default: /* case 4 */ 01328 dx = dx + dx; 01329 pixellast = pixel + dx + dx; 01330 for (; pixel <= pixellast; pixel += pixx) { 01331 *(Uint32 *) pixel = color; 01332 } 01333 break; 01334 } 01335 01336 /* 01337 * Unlock surface 01338 */ 01339 if (SDL_MUSTLOCK(dst)) { 01340 SDL_UnlockSurface(dst); 01341 } 01342 01343 /* 01344 * Set result code 01345 */ 01346 result = 0; 01347 01348 } else { 01349 01350 /* 01351 * Alpha blending blit 01352 */ 01353 result = _HLineAlpha(dst, x1, x1 + dx, y, color); 01354 } 01355 01356 return (result); 01357 } 01358 01373 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01374 { 01375 /* 01376 * Draw 01377 */ 01378 return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01379 } 01380 01392 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color) 01393 { 01394 Sint16 left, right, top, bottom; 01395 Uint8 *pixel, *pixellast; 01396 int dy; 01397 int pixx, pixy; 01398 Sint16 h; 01399 Sint16 ytmp; 01400 int result = -1; 01401 Uint8 *colorptr; 01402 01403 /* 01404 * Check visibility of clipping rectangle 01405 */ 01406 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01407 return(0); 01408 } 01409 01410 /* 01411 * Swap y1, y2 if required to ensure y1<=y2 01412 */ 01413 if (y1 > y2) { 01414 ytmp = y1; 01415 y1 = y2; 01416 y2 = ytmp; 01417 } 01418 01419 /* 01420 * Get clipping boundary and 01421 * check visibility of vline 01422 */ 01423 left = dst->clip_rect.x; 01424 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01425 if ((x<left) || (x>right)) { 01426 return (0); 01427 } 01428 top = dst->clip_rect.y; 01429 if (y2<top) { 01430 return(0); 01431 } 01432 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01433 if (y1>bottom) { 01434 return(0); 01435 } 01436 01437 /* 01438 * Clip x 01439 */ 01440 if (y1 < top) { 01441 y1 = top; 01442 } 01443 if (y2 > bottom) { 01444 y2 = bottom; 01445 } 01446 01447 /* 01448 * Calculate height 01449 */ 01450 h = y2 - y1; 01451 01452 /* 01453 * Alpha check 01454 */ 01455 if ((color & 255) == 255) { 01456 01457 /* 01458 * No alpha-blending required 01459 */ 01460 01461 /* 01462 * Setup color 01463 */ 01464 colorptr = (Uint8 *) & color; 01465 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01466 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 01467 } else { 01468 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 01469 } 01470 01471 /* 01472 * Lock the surface 01473 */ 01474 if (SDL_MUSTLOCK(dst)) { 01475 if (SDL_LockSurface(dst) < 0) { 01476 return (-1); 01477 } 01478 } 01479 01480 /* 01481 * More variable setup 01482 */ 01483 dy = h; 01484 pixx = dst->format->BytesPerPixel; 01485 pixy = dst->pitch; 01486 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1; 01487 pixellast = pixel + pixy * dy; 01488 01489 /* 01490 * Draw 01491 */ 01492 switch (dst->format->BytesPerPixel) { 01493 case 1: 01494 for (; pixel <= pixellast; pixel += pixy) { 01495 *(Uint8 *) pixel = color; 01496 } 01497 break; 01498 case 2: 01499 for (; pixel <= pixellast; pixel += pixy) { 01500 *(Uint16 *) pixel = color; 01501 } 01502 break; 01503 case 3: 01504 for (; pixel <= pixellast; pixel += pixy) { 01505 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01506 pixel[0] = (color >> 16) & 0xff; 01507 pixel[1] = (color >> 8) & 0xff; 01508 pixel[2] = color & 0xff; 01509 } else { 01510 pixel[0] = color & 0xff; 01511 pixel[1] = (color >> 8) & 0xff; 01512 pixel[2] = (color >> 16) & 0xff; 01513 } 01514 } 01515 break; 01516 default: /* case 4 */ 01517 for (; pixel <= pixellast; pixel += pixy) { 01518 *(Uint32 *) pixel = color; 01519 } 01520 break; 01521 } 01522 01523 /* Unlock surface */ 01524 if (SDL_MUSTLOCK(dst)) { 01525 SDL_UnlockSurface(dst); 01526 } 01527 01528 /* 01529 * Set result code 01530 */ 01531 result = 0; 01532 01533 } else { 01534 01535 /* 01536 * Alpha blending blit 01537 */ 01538 01539 result = _VLineAlpha(dst, x, y1, y1 + h, color); 01540 01541 } 01542 01543 return (result); 01544 } 01545 01560 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01561 { 01562 /* 01563 * Draw 01564 */ 01565 return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01566 } 01567 01580 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) 01581 { 01582 int result; 01583 Sint16 tmp; 01584 01585 /* Check destination surface */ 01586 if (dst == NULL) 01587 { 01588 return -1; 01589 } 01590 01591 /* 01592 * Check visibility of clipping rectangle 01593 */ 01594 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01595 return 0; 01596 } 01597 01598 /* 01599 * Test for special cases of straight lines or single point 01600 */ 01601 if (x1 == x2) { 01602 if (y1 == y2) { 01603 return (pixelColor(dst, x1, y1, color)); 01604 } else { 01605 return (vlineColor(dst, x1, y1, y2, color)); 01606 } 01607 } else { 01608 if (y1 == y2) { 01609 return (hlineColor(dst, x1, x2, y1, color)); 01610 } 01611 } 01612 01613 /* 01614 * Swap x1, x2 if required 01615 */ 01616 if (x1 > x2) { 01617 tmp = x1; 01618 x1 = x2; 01619 x2 = tmp; 01620 } 01621 01622 /* 01623 * Swap y1, y2 if required 01624 */ 01625 if (y1 > y2) { 01626 tmp = y1; 01627 y1 = y2; 01628 y2 = tmp; 01629 } 01630 01631 /* 01632 * Draw rectangle 01633 */ 01634 result = 0; 01635 result |= hlineColor(dst, x1, x2, y1, color); 01636 result |= hlineColor(dst, x1, x2, y2, color); 01637 y1 += 1; 01638 y2 -= 1; 01639 if (y1 <= y2) { 01640 result |= vlineColor(dst, x1, y1, y2, color); 01641 result |= vlineColor(dst, x2, y1, y2, color); 01642 } 01643 01644 return (result); 01645 01646 } 01647 01663 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01664 { 01665 /* 01666 * Draw 01667 */ 01668 return (rectangleColor 01669 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01670 } 01671 01685 int roundedRectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) 01686 { 01687 int result; 01688 Sint16 w, h, tmp; 01689 Sint16 xx1, xx2, yy1, yy2; 01690 01691 /* 01692 * Check destination surface 01693 */ 01694 if (dst == NULL) 01695 { 01696 return -1; 01697 } 01698 01699 /* 01700 * Check radius vor valid range 01701 */ 01702 if (rad < 0) { 01703 return -1; 01704 } 01705 01706 /* 01707 * Special case - no rounding 01708 */ 01709 if (rad == 0) { 01710 return rectangleColor(dst, x1, y1, x2, y2, color); 01711 } 01712 01713 /* 01714 * Check visibility of clipping rectangle 01715 */ 01716 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01717 return 0; 01718 } 01719 01720 /* 01721 * Test for special cases of straight lines or single point 01722 */ 01723 if (x1 == x2) { 01724 if (y1 == y2) { 01725 return (pixelColor(dst, x1, y1, color)); 01726 } else { 01727 return (vlineColor(dst, x1, y1, y2, color)); 01728 } 01729 } else { 01730 if (y1 == y2) { 01731 return (hlineColor(dst, x1, x2, y1, color)); 01732 } 01733 } 01734 01735 /* 01736 * Swap x1, x2 if required 01737 */ 01738 if (x1 > x2) { 01739 tmp = x1; 01740 x1 = x2; 01741 x2 = tmp; 01742 } 01743 01744 /* 01745 * Swap y1, y2 if required 01746 */ 01747 if (y1 > y2) { 01748 tmp = y1; 01749 y1 = y2; 01750 y2 = tmp; 01751 } 01752 01753 /* 01754 * Calculate width&height 01755 */ 01756 w = x2 - x1; 01757 h = y2 - y1; 01758 01759 /* 01760 * Maybe adjust radius 01761 */ 01762 if ((rad * 2) > w) 01763 { 01764 rad = w / 2; 01765 } 01766 if ((rad * 2) > h) 01767 { 01768 rad = h / 2; 01769 } 01770 01771 /* 01772 * Draw corners 01773 */ 01774 result = 0; 01775 xx1 = x1 + rad; 01776 xx2 = x2 - rad; 01777 yy1 = y1 + rad; 01778 yy2 = y2 - rad; 01779 result |= arcColor(dst, xx1, yy1, rad, 180, 270, color); 01780 result |= arcColor(dst, xx2, yy1, rad, 270, 360, color); 01781 result |= arcColor(dst, xx1, yy2, rad, 90, 180, color); 01782 result |= arcColor(dst, xx2, yy2, rad, 0, 90, color); 01783 01784 /* 01785 * Draw lines 01786 */ 01787 if (xx1 <= xx2) { 01788 result |= hlineColor(dst, xx1, xx2, y1, color); 01789 result |= hlineColor(dst, xx1, xx2, y2, color); 01790 } 01791 if (yy1 <= yy2) { 01792 result |= vlineColor(dst, x1, yy1, yy2, color); 01793 result |= vlineColor(dst, x2, yy1, yy2, color); 01794 } 01795 01796 return result; 01797 } 01798 01815 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01816 { 01817 /* 01818 * Draw 01819 */ 01820 return (roundedRectangleColor 01821 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01822 } 01823 01837 int roundedBoxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) 01838 { 01839 int result; 01840 Sint16 w, h, tmp; 01841 Sint16 xx1, xx2, yy1, yy2; 01842 01843 /* 01844 * Check destination surface 01845 */ 01846 if (dst == NULL) 01847 { 01848 return -1; 01849 } 01850 01851 /* 01852 * Check radius vor valid range 01853 */ 01854 if (rad < 0) { 01855 return -1; 01856 } 01857 01858 /* 01859 * Special case - no rounding 01860 */ 01861 if (rad == 0) { 01862 return rectangleColor(dst, x1, y1, x2, y2, color); 01863 } 01864 01865 /* 01866 * Check visibility of clipping rectangle 01867 */ 01868 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01869 return 0; 01870 } 01871 01872 /* 01873 * Test for special cases of straight lines or single point 01874 */ 01875 if (x1 == x2) { 01876 if (y1 == y2) { 01877 return (pixelColor(dst, x1, y1, color)); 01878 } else { 01879 return (vlineColor(dst, x1, y1, y2, color)); 01880 } 01881 } else { 01882 if (y1 == y2) { 01883 return (hlineColor(dst, x1, x2, y1, color)); 01884 } 01885 } 01886 01887 /* 01888 * Swap x1, x2 if required 01889 */ 01890 if (x1 > x2) { 01891 tmp = x1; 01892 x1 = x2; 01893 x2 = tmp; 01894 } 01895 01896 /* 01897 * Swap y1, y2 if required 01898 */ 01899 if (y1 > y2) { 01900 tmp = y1; 01901 y1 = y2; 01902 y2 = tmp; 01903 } 01904 01905 /* 01906 * Calculate width&height 01907 */ 01908 w = x2 - x1; 01909 h = y2 - y1; 01910 01911 /* 01912 * Maybe adjust radius 01913 */ 01914 if ((rad * 2) > w) 01915 { 01916 rad = w / 2; 01917 } 01918 if ((rad * 2) > h) 01919 { 01920 rad = h / 2; 01921 } 01922 01923 /* 01924 * Draw corners 01925 */ 01926 result = 0; 01927 xx1 = x1 + rad; 01928 xx2 = x2 - rad; 01929 yy1 = y1 + rad; 01930 yy2 = y2 - rad; 01931 result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color); 01932 result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color); 01933 result |= filledPieColor(dst, xx1, yy2, rad, 90, 180, color); 01934 result |= filledPieColor(dst, xx2, yy2, rad, 0, 90, color); 01935 01936 /* 01937 * Draw body 01938 */ 01939 xx1++; 01940 xx2--; 01941 yy1++; 01942 yy2--; 01943 if (xx1 <= xx2) { 01944 result |= boxColor(dst, xx1, y1, xx2, y2, color); 01945 } 01946 if (yy1 <= yy2) { 01947 result |= boxColor(dst, x1, yy1, xx1-1, yy2, color); 01948 result |= boxColor(dst, xx2+1, yy1, x2, yy2, color); 01949 } 01950 01951 return result; 01952 } 01953 01970 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, 01971 Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01972 { 01973 /* 01974 * Draw 01975 */ 01976 return (roundedBoxColor 01977 (dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01978 } 01979 01980 /* --------- Clipping routines for line */ 01981 01982 /* Clipping based heavily on code from */ 01983 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */ 01984 01985 #define CLIP_LEFT_EDGE 0x1 01986 #define CLIP_RIGHT_EDGE 0x2 01987 #define CLIP_BOTTOM_EDGE 0x4 01988 #define CLIP_TOP_EDGE 0x8 01989 #define CLIP_INSIDE(a) (!a) 01990 #define CLIP_REJECT(a,b) (a&b) 01991 #define CLIP_ACCEPT(a,b) (!(a|b)) 01992 02005 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) 02006 { 02007 int code = 0; 02008 02009 if (x < left) { 02010 code |= CLIP_LEFT_EDGE; 02011 } else if (x > right) { 02012 code |= CLIP_RIGHT_EDGE; 02013 } 02014 if (y < top) { 02015 code |= CLIP_TOP_EDGE; 02016 } else if (y > bottom) { 02017 code |= CLIP_BOTTOM_EDGE; 02018 } 02019 return code; 02020 } 02021 02031 static int _clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2) 02032 { 02033 Sint16 left, right, top, bottom; 02034 int code1, code2; 02035 int draw = 0; 02036 Sint16 swaptmp; 02037 float m; 02038 02039 /* 02040 * Get clipping boundary 02041 */ 02042 left = dst->clip_rect.x; 02043 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02044 top = dst->clip_rect.y; 02045 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02046 02047 while (1) { 02048 code1 = _clipEncode(*x1, *y1, left, top, right, bottom); 02049 code2 = _clipEncode(*x2, *y2, left, top, right, bottom); 02050 if (CLIP_ACCEPT(code1, code2)) { 02051 draw = 1; 02052 break; 02053 } else if (CLIP_REJECT(code1, code2)) 02054 break; 02055 else { 02056 if (CLIP_INSIDE(code1)) { 02057 swaptmp = *x2; 02058 *x2 = *x1; 02059 *x1 = swaptmp; 02060 swaptmp = *y2; 02061 *y2 = *y1; 02062 *y1 = swaptmp; 02063 swaptmp = code2; 02064 code2 = code1; 02065 code1 = swaptmp; 02066 } 02067 if (*x2 != *x1) { 02068 m = (float)(*y2 - *y1) / (float)(*x2 - *x1); 02069 } else { 02070 m = 1.0f; 02071 } 02072 if (code1 & CLIP_LEFT_EDGE) { 02073 *y1 += (Sint16) ((left - *x1) * m); 02074 *x1 = left; 02075 } else if (code1 & CLIP_RIGHT_EDGE) { 02076 *y1 += (Sint16) ((right - *x1) * m); 02077 *x1 = right; 02078 } else if (code1 & CLIP_BOTTOM_EDGE) { 02079 if (*x2 != *x1) { 02080 *x1 += (Sint16) ((bottom - *y1) / m); 02081 } 02082 *y1 = bottom; 02083 } else if (code1 & CLIP_TOP_EDGE) { 02084 if (*x2 != *x1) { 02085 *x1 += (Sint16) ((top - *y1) / m); 02086 } 02087 *y1 = top; 02088 } 02089 } 02090 } 02091 02092 return draw; 02093 } 02094 02107 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) 02108 { 02109 Sint16 left, right, top, bottom; 02110 Uint8 *pixel, *pixellast; 02111 int x, dx; 02112 int dy; 02113 int pixx, pixy; 02114 Sint16 w, h, tmp; 02115 int result; 02116 Uint8 *colorptr; 02117 02118 /* 02119 * Check visibility of clipping rectangle 02120 */ 02121 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02122 return(0); 02123 } 02124 02125 /* 02126 * Order coordinates to ensure that 02127 * x1<=x2 and y1<=y2 02128 */ 02129 if (x1 > x2) { 02130 tmp = x1; 02131 x1 = x2; 02132 x2 = tmp; 02133 } 02134 if (y1 > y2) { 02135 tmp = y1; 02136 y1 = y2; 02137 y2 = tmp; 02138 } 02139 02140 /* 02141 * Get clipping boundary and 02142 * check visibility 02143 */ 02144 left = dst->clip_rect.x; 02145 if (x2<left) { 02146 return(0); 02147 } 02148 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02149 if (x1>right) { 02150 return(0); 02151 } 02152 top = dst->clip_rect.y; 02153 if (y2<top) { 02154 return(0); 02155 } 02156 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02157 if (y1>bottom) { 02158 return(0); 02159 } 02160 02161 /* Clip all points */ 02162 if (x1<left) { 02163 x1=left; 02164 } else if (x1>right) { 02165 x1=right; 02166 } 02167 if (x2<left) { 02168 x2=left; 02169 } else if (x2>right) { 02170 x2=right; 02171 } 02172 if (y1<top) { 02173 y1=top; 02174 } else if (y1>bottom) { 02175 y1=bottom; 02176 } 02177 if (y2<top) { 02178 y2=top; 02179 } else if (y2>bottom) { 02180 y2=bottom; 02181 } 02182 02183 /* 02184 * Test for special cases of straight line or single point 02185 */ 02186 if (x1 == x2) { 02187 if (y1 == y2) { 02188 return (pixelColor(dst, x1, y1, color)); 02189 } else { 02190 return (vlineColor(dst, x1, y1, y2, color)); 02191 } 02192 } 02193 if (y1 == y2) { 02194 return (hlineColor(dst, x1, x2, y1, color)); 02195 } 02196 02197 /* 02198 * Calculate width&height 02199 */ 02200 w = x2 - x1; 02201 h = y2 - y1; 02202 02203 /* 02204 * Alpha check 02205 */ 02206 if ((color & 255) == 255) { 02207 02208 /* 02209 * No alpha-blending required 02210 */ 02211 02212 /* 02213 * Setup color 02214 */ 02215 colorptr = (Uint8 *) & color; 02216 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02217 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 02218 } else { 02219 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 02220 } 02221 02222 /* 02223 * Lock the surface 02224 */ 02225 if (SDL_MUSTLOCK(dst)) { 02226 if (SDL_LockSurface(dst) < 0) { 02227 return (-1); 02228 } 02229 } 02230 02231 /* 02232 * More variable setup 02233 */ 02234 dx = w; 02235 dy = h; 02236 pixx = dst->format->BytesPerPixel; 02237 pixy = dst->pitch; 02238 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1; 02239 pixellast = pixel + pixx * dx + pixy * dy; 02240 dx++; 02241 02242 /* 02243 * Draw 02244 */ 02245 switch (dst->format->BytesPerPixel) { 02246 case 1: 02247 for (; pixel <= pixellast; pixel += pixy) { 02248 memset(pixel, (Uint8) color, dx); 02249 } 02250 break; 02251 case 2: 02252 pixy -= (pixx * dx); 02253 for (; pixel <= pixellast; pixel += pixy) { 02254 for (x = 0; x < dx; x++) { 02255 *(Uint16*) pixel = color; 02256 pixel += pixx; 02257 } 02258 } 02259 break; 02260 case 3: 02261 pixy -= (pixx * dx); 02262 for (; pixel <= pixellast; pixel += pixy) { 02263 for (x = 0; x < dx; x++) { 02264 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02265 pixel[0] = (color >> 16) & 0xff; 02266 pixel[1] = (color >> 8) & 0xff; 02267 pixel[2] = color & 0xff; 02268 } else { 02269 pixel[0] = color & 0xff; 02270 pixel[1] = (color >> 8) & 0xff; 02271 pixel[2] = (color >> 16) & 0xff; 02272 } 02273 pixel += pixx; 02274 } 02275 } 02276 break; 02277 default: /* case 4 */ 02278 pixy -= (pixx * dx); 02279 for (; pixel <= pixellast; pixel += pixy) { 02280 for (x = 0; x < dx; x++) { 02281 *(Uint32 *) pixel = color; 02282 pixel += pixx; 02283 } 02284 } 02285 break; 02286 } 02287 02288 /* Unlock surface */ 02289 if (SDL_MUSTLOCK(dst)) { 02290 SDL_UnlockSurface(dst); 02291 } 02292 02293 result = 0; 02294 02295 } else { 02296 02297 result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color); 02298 02299 } 02300 02301 return (result); 02302 } 02303 02319 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02320 { 02321 /* 02322 * Draw 02323 */ 02324 return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 02325 } 02326 02327 /* ----- Line */ 02328 02329 /* Non-alpha line drawing code adapted from routine */ 02330 /* by Pete Shinners, pete@shinners.org */ 02331 /* Originally from pygame, http://pygame.seul.org */ 02332 02333 #define ABS(a) (((a)<0) ? -(a) : (a)) 02334 02347 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) 02348 { 02349 int pixx, pixy; 02350 int x, y; 02351 int dx, dy; 02352 int ax, ay; 02353 int sx, sy; 02354 int swaptmp; 02355 Uint8 *pixel; 02356 Uint8 *colorptr; 02357 02358 /* 02359 * Clip line and test if we have to draw 02360 */ 02361 if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) { 02362 return (0); 02363 } 02364 02365 /* 02366 * Test for special cases of straight lines or single point 02367 */ 02368 if (x1 == x2) { 02369 if (y1 < y2) { 02370 return (vlineColor(dst, x1, y1, y2, color)); 02371 } else if (y1 > y2) { 02372 return (vlineColor(dst, x1, y2, y1, color)); 02373 } else { 02374 return (pixelColor(dst, x1, y1, color)); 02375 } 02376 } 02377 if (y1 == y2) { 02378 if (x1 < x2) { 02379 return (hlineColor(dst, x1, x2, y1, color)); 02380 } else if (x1 > x2) { 02381 return (hlineColor(dst, x2, x1, y1, color)); 02382 } 02383 } 02384 02385 /* 02386 * Variable setup 02387 */ 02388 dx = x2 - x1; 02389 dy = y2 - y1; 02390 sx = (dx >= 0) ? 1 : -1; 02391 sy = (dy >= 0) ? 1 : -1; 02392 02393 /* Lock surface */ 02394 if (SDL_MUSTLOCK(dst)) { 02395 if (SDL_LockSurface(dst) < 0) { 02396 return (-1); 02397 } 02398 } 02399 02400 /* 02401 * Check for alpha blending 02402 */ 02403 if ((color & 255) == 255) { 02404 02405 /* 02406 * No alpha blending - use fast pixel routines 02407 */ 02408 02409 /* 02410 * Setup color 02411 */ 02412 colorptr = (Uint8 *) & color; 02413 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02414 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 02415 } else { 02416 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 02417 } 02418 02419 /* 02420 * More variable setup 02421 */ 02422 dx = sx * dx + 1; 02423 dy = sy * dy + 1; 02424 pixx = dst->format->BytesPerPixel; 02425 pixy = dst->pitch; 02426 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1; 02427 pixx *= sx; 02428 pixy *= sy; 02429 if (dx < dy) { 02430 swaptmp = dx; 02431 dx = dy; 02432 dy = swaptmp; 02433 swaptmp = pixx; 02434 pixx = pixy; 02435 pixy = swaptmp; 02436 } 02437 02438 /* 02439 * Draw 02440 */ 02441 x = 0; 02442 y = 0; 02443 switch (dst->format->BytesPerPixel) { 02444 case 1: 02445 for (; x < dx; x++, pixel += pixx) { 02446 *pixel = color; 02447 y += dy; 02448 if (y >= dx) { 02449 y -= dx; 02450 pixel += pixy; 02451 } 02452 } 02453 break; 02454 case 2: 02455 for (; x < dx; x++, pixel += pixx) { 02456 *(Uint16 *) pixel = color; 02457 y += dy; 02458 if (y >= dx) { 02459 y -= dx; 02460 pixel += pixy; 02461 } 02462 } 02463 break; 02464 case 3: 02465 for (; x < dx; x++, pixel += pixx) { 02466 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02467 pixel[0] = (color >> 16) & 0xff; 02468 pixel[1] = (color >> 8) & 0xff; 02469 pixel[2] = color & 0xff; 02470 } else { 02471 pixel[0] = color & 0xff; 02472 pixel[1] = (color >> 8) & 0xff; 02473 pixel[2] = (color >> 16) & 0xff; 02474 } 02475 y += dy; 02476 if (y >= dx) { 02477 y -= dx; 02478 pixel += pixy; 02479 } 02480 } 02481 break; 02482 default: /* case 4 */ 02483 for (; x < dx; x++, pixel += pixx) { 02484 *(Uint32 *) pixel = color; 02485 y += dy; 02486 if (y >= dx) { 02487 y -= dx; 02488 pixel += pixy; 02489 } 02490 } 02491 break; 02492 } 02493 02494 } else { 02495 02496 /* 02497 * Alpha blending required - use single-pixel blits 02498 */ 02499 02500 ax = ABS(dx) << 1; 02501 ay = ABS(dy) << 1; 02502 x = x1; 02503 y = y1; 02504 if (ax > ay) { 02505 int d = ay - (ax >> 1); 02506 02507 while (x != x2) { 02508 pixelColorNolock (dst, x, y, color); 02509 if (d > 0 || (d == 0 && sx == 1)) { 02510 y += sy; 02511 d -= ax; 02512 } 02513 x += sx; 02514 d += ay; 02515 } 02516 } else { 02517 int d = ax - (ay >> 1); 02518 02519 while (y != y2) { 02520 pixelColorNolock (dst, x, y, color); 02521 if (d > 0 || ((d == 0) && (sy == 1))) { 02522 x += sx; 02523 d -= ay; 02524 } 02525 y += sy; 02526 d += ax; 02527 } 02528 } 02529 pixelColorNolock (dst, x, y, color); 02530 02531 } 02532 02533 /* Unlock surface */ 02534 if (SDL_MUSTLOCK(dst)) { 02535 SDL_UnlockSurface(dst); 02536 } 02537 02538 return (0); 02539 } 02540 02556 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02557 { 02558 /* 02559 * Draw 02560 */ 02561 return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 02562 } 02563 02564 /* AA Line */ 02565 02566 #define AAlevels 256 02567 #define AAbits 8 02568 02589 int _aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint) 02590 { 02591 Sint32 xx0, yy0, xx1, yy1; 02592 int result; 02593 Uint32 intshift, erracc, erradj; 02594 Uint32 erracctmp, wgt, wgtcompmask; 02595 int dx, dy, tmp, xdir, y0p1, x0pxdir; 02596 02597 /* 02598 * Check visibility of clipping rectangle 02599 */ 02600 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02601 return(0); 02602 } 02603 02604 /* 02605 * Clip line and test if we have to draw 02606 */ 02607 if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) { 02608 return (0); 02609 } 02610 02611 /* 02612 * Keep on working with 32bit numbers 02613 */ 02614 xx0 = x1; 02615 yy0 = y1; 02616 xx1 = x2; 02617 yy1 = y2; 02618 02619 /* 02620 * Reorder points if required 02621 */ 02622 if (yy0 > yy1) { 02623 tmp = yy0; 02624 yy0 = yy1; 02625 yy1 = tmp; 02626 tmp = xx0; 02627 xx0 = xx1; 02628 xx1 = tmp; 02629 } 02630 02631 /* 02632 * Calculate distance 02633 */ 02634 dx = xx1 - xx0; 02635 dy = yy1 - yy0; 02636 02637 /* 02638 * Check for special cases 02639 */ 02640 if (dx == 0) { 02641 /* 02642 * Vertical line 02643 */ 02644 if (draw_endpoint) 02645 { 02646 return (vlineColor(dst, x1, y1, y2, color)); 02647 } else { 02648 if (dy>0) { 02649 return (vlineColor(dst, x1, yy0, yy0+dy, color)); 02650 } else { 02651 return (pixelColor(dst, x1, y1, color)); 02652 } 02653 } 02654 } else if (dy == 0) { 02655 /* 02656 * Horizontal line 02657 */ 02658 if (draw_endpoint) 02659 { 02660 return (hlineColor(dst, x1, x2, y1, color)); 02661 } else { 02662 if (dx!=0) { 02663 return (hlineColor(dst, xx0, xx0+dx, y1, color)); 02664 } else { 02665 return (pixelColor(dst, x1, y1, color)); 02666 } 02667 } 02668 } else if ((dx == dy) && (draw_endpoint)) { 02669 /* 02670 * Diagonal line (with endpoint) 02671 */ 02672 return (lineColor(dst, x1, y1, x2, y2, color)); 02673 } 02674 02675 /* 02676 * Adjust for negative dx and set xdir 02677 */ 02678 if (dx >= 0) { 02679 xdir = 1; 02680 } else { 02681 xdir = -1; 02682 dx = (-dx); 02683 } 02684 02685 /* 02686 * Line is not horizontal, vertical or diagonal (with endpoint) 02687 */ 02688 result = 0; 02689 02690 /* 02691 * Zero accumulator 02692 */ 02693 erracc = 0; 02694 02695 /* 02696 * # of bits by which to shift erracc to get intensity level 02697 */ 02698 intshift = 32 - AAbits; 02699 02700 /* 02701 * Mask used to flip all bits in an intensity weighting 02702 */ 02703 wgtcompmask = AAlevels - 1; 02704 02705 /* Lock surface */ 02706 if (SDL_MUSTLOCK(dst)) { 02707 if (SDL_LockSurface(dst) < 0) { 02708 return (-1); 02709 } 02710 } 02711 02712 /* 02713 * Draw the initial pixel in the foreground color 02714 */ 02715 result |= pixelColorNolock(dst, x1, y1, color); 02716 02717 /* 02718 * x-major or y-major? 02719 */ 02720 if (dy > dx) { 02721 02722 /* 02723 * y-major. Calculate 16-bit fixed point fractional part of a pixel that 02724 * X advances every time Y advances 1 pixel, truncating the result so that 02725 * we won't overrun the endpoint along the X axis 02726 */ 02727 /* 02728 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; 02729 */ 02730 erradj = ((dx << 16) / dy) << 16; 02731 02732 /* 02733 * draw all pixels other than the first and last 02734 */ 02735 x0pxdir = xx0 + xdir; 02736 while (--dy) { 02737 erracctmp = erracc; 02738 erracc += erradj; 02739 if (erracc <= erracctmp) { 02740 /* 02741 * rollover in error accumulator, x coord advances 02742 */ 02743 xx0 = x0pxdir; 02744 x0pxdir += xdir; 02745 } 02746 yy0++; /* y-major so always advance Y */ 02747 02748 /* 02749 * the AAbits most significant bits of erracc give us the intensity 02750 * weighting for this pixel, and the complement of the weighting for 02751 * the paired pixel. 02752 */ 02753 wgt = (erracc >> intshift) & 255; 02754 result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); 02755 result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt); 02756 } 02757 02758 } else { 02759 02760 /* 02761 * x-major line. Calculate 16-bit fixed-point fractional part of a pixel 02762 * that Y advances each time X advances 1 pixel, truncating the result so 02763 * that we won't overrun the endpoint along the X axis. 02764 */ 02765 /* 02766 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; 02767 */ 02768 erradj = ((dy << 16) / dx) << 16; 02769 02770 /* 02771 * draw all pixels other than the first and last 02772 */ 02773 y0p1 = yy0 + 1; 02774 while (--dx) { 02775 02776 erracctmp = erracc; 02777 erracc += erradj; 02778 if (erracc <= erracctmp) { 02779 /* 02780 * Accumulator turned over, advance y 02781 */ 02782 yy0 = y0p1; 02783 y0p1++; 02784 } 02785 xx0 += xdir; /* x-major so always advance X */ 02786 /* 02787 * the AAbits most significant bits of erracc give us the intensity 02788 * weighting for this pixel, and the complement of the weighting for 02789 * the paired pixel. 02790 */ 02791 wgt = (erracc >> intshift) & 255; 02792 result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); 02793 result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt); 02794 } 02795 } 02796 02797 /* 02798 * Do we have to draw the endpoint 02799 */ 02800 if (draw_endpoint) { 02801 /* 02802 * Draw final pixel, always exactly intersected by the line and doesn't 02803 * need to be weighted. 02804 */ 02805 result |= pixelColorNolock (dst, x2, y2, color); 02806 } 02807 02808 /* Unlock surface */ 02809 if (SDL_MUSTLOCK(dst)) { 02810 SDL_UnlockSurface(dst); 02811 } 02812 02813 return (result); 02814 } 02815 02828 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color) 02829 { 02830 return (_aalineColor(dst, x1, y1, x2, y2, color, 1)); 02831 } 02832 02848 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02849 { 02850 return (_aalineColor 02851 (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1)); 02852 } 02853 02854 02855 /* ----- Circle */ 02856 02872 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 02873 { 02874 Sint16 left, right, top, bottom; 02875 int result; 02876 Sint16 x1, y1, x2, y2; 02877 Sint16 cx = 0; 02878 Sint16 cy = rad; 02879 Sint16 df = 1 - rad; 02880 Sint16 d_e = 3; 02881 Sint16 d_se = -2 * rad + 5; 02882 Sint16 xpcx, xmcx, xpcy, xmcy; 02883 Sint16 ypcy, ymcy, ypcx, ymcx; 02884 Uint8 *colorptr; 02885 02886 /* 02887 * Check visibility of clipping rectangle 02888 */ 02889 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02890 return(0); 02891 } 02892 02893 /* 02894 * Sanity check radius 02895 */ 02896 if (rad < 0) { 02897 return (-1); 02898 } 02899 02900 /* 02901 * Special case for rad=0 - draw a point 02902 */ 02903 if (rad == 0) { 02904 return (pixelColor(dst, x, y, color)); 02905 } 02906 02907 /* 02908 * Get circle and clipping boundary and 02909 * test if bounding box of circle is visible 02910 */ 02911 x2 = x + rad; 02912 left = dst->clip_rect.x; 02913 if (x2<left) { 02914 return(0); 02915 } 02916 x1 = x - rad; 02917 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02918 if (x1>right) { 02919 return(0); 02920 } 02921 y2 = y + rad; 02922 top = dst->clip_rect.y; 02923 if (y2<top) { 02924 return(0); 02925 } 02926 y1 = y - rad; 02927 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02928 if (y1>bottom) { 02929 return(0); 02930 } 02931 02932 /* 02933 * Draw circle 02934 */ 02935 result = 0; 02936 02937 /* Lock surface */ 02938 if (SDL_MUSTLOCK(dst)) { 02939 if (SDL_LockSurface(dst) < 0) { 02940 return (-1); 02941 } 02942 } 02943 02944 /* 02945 * Alpha Check 02946 */ 02947 if ((color & 255) == 255) { 02948 02949 /* 02950 * No Alpha - direct memory writes 02951 */ 02952 02953 /* 02954 * Setup color 02955 */ 02956 colorptr = (Uint8 *) & color; 02957 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02958 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 02959 } else { 02960 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 02961 } 02962 02963 /* 02964 * Draw 02965 */ 02966 do { 02967 ypcy = y + cy; 02968 ymcy = y - cy; 02969 if (cx > 0) { 02970 xpcx = x + cx; 02971 xmcx = x - cx; 02972 result |= fastPixelColorNolock(dst, xmcx, ypcy, color); 02973 result |= fastPixelColorNolock(dst, xpcx, ypcy, color); 02974 result |= fastPixelColorNolock(dst, xmcx, ymcy, color); 02975 result |= fastPixelColorNolock(dst, xpcx, ymcy, color); 02976 } else { 02977 result |= fastPixelColorNolock(dst, x, ymcy, color); 02978 result |= fastPixelColorNolock(dst, x, ypcy, color); 02979 } 02980 xpcy = x + cy; 02981 xmcy = x - cy; 02982 if ((cx > 0) && (cx != cy)) { 02983 ypcx = y + cx; 02984 ymcx = y - cx; 02985 result |= fastPixelColorNolock(dst, xmcy, ypcx, color); 02986 result |= fastPixelColorNolock(dst, xpcy, ypcx, color); 02987 result |= fastPixelColorNolock(dst, xmcy, ymcx, color); 02988 result |= fastPixelColorNolock(dst, xpcy, ymcx, color); 02989 } else if (cx == 0) { 02990 result |= fastPixelColorNolock(dst, xmcy, y, color); 02991 result |= fastPixelColorNolock(dst, xpcy, y, color); 02992 } 02993 /* 02994 * Update 02995 */ 02996 if (df < 0) { 02997 df += d_e; 02998 d_e += 2; 02999 d_se += 2; 03000 } else { 03001 df += d_se; 03002 d_e += 2; 03003 d_se += 4; 03004 cy--; 03005 } 03006 cx++; 03007 } while (cx <= cy); 03008 03009 /* 03010 * Unlock surface 03011 */ 03012 SDL_UnlockSurface(dst); 03013 03014 } else { 03015 03016 /* 03017 * Using Alpha - blended pixel blits 03018 */ 03019 03020 do { 03021 /* 03022 * Draw 03023 */ 03024 ypcy = y + cy; 03025 ymcy = y - cy; 03026 if (cx > 0) { 03027 xpcx = x + cx; 03028 xmcx = x - cx; 03029 result |= pixelColorNolock (dst, xmcx, ypcy, color); 03030 result |= pixelColorNolock (dst, xpcx, ypcy, color); 03031 result |= pixelColorNolock (dst, xmcx, ymcy, color); 03032 result |= pixelColorNolock (dst, xpcx, ymcy, color); 03033 } else { 03034 result |= pixelColorNolock (dst, x, ymcy, color); 03035 result |= pixelColorNolock (dst, x, ypcy, color); 03036 } 03037 xpcy = x + cy; 03038 xmcy = x - cy; 03039 if ((cx > 0) && (cx != cy)) { 03040 ypcx = y + cx; 03041 ymcx = y - cx; 03042 result |= pixelColorNolock (dst, xmcy, ypcx, color); 03043 result |= pixelColorNolock (dst, xpcy, ypcx, color); 03044 result |= pixelColorNolock (dst, xmcy, ymcx, color); 03045 result |= pixelColorNolock (dst, xpcy, ymcx, color); 03046 } else if (cx == 0) { 03047 result |= pixelColorNolock (dst, xmcy, y, color); 03048 result |= pixelColorNolock (dst, xpcy, y, color); 03049 } 03050 /* 03051 * Update 03052 */ 03053 if (df < 0) { 03054 df += d_e; 03055 d_e += 2; 03056 d_se += 2; 03057 } else { 03058 df += d_se; 03059 d_e += 2; 03060 d_se += 4; 03061 cy--; 03062 } 03063 cx++; 03064 } while (cx <= cy); 03065 03066 } /* Alpha check */ 03067 03068 /* Unlock surface */ 03069 if (SDL_MUSTLOCK(dst)) { 03070 SDL_UnlockSurface(dst); 03071 } 03072 03073 return (result); 03074 } 03075 03090 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03091 { 03092 /* 03093 * Draw 03094 */ 03095 return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03096 } 03097 03098 /* ----- Arc */ 03099 03117 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) 03118 { 03119 Sint16 left, right, top, bottom; 03120 int result; 03121 Sint16 x1, y1, x2, y2; 03122 Sint16 cx = 0; 03123 Sint16 cy = rad; 03124 Sint16 df = 1 - rad; 03125 Sint16 d_e = 3; 03126 Sint16 d_se = -2 * rad + 5; 03127 Sint16 xpcx, xmcx, xpcy, xmcy; 03128 Sint16 ypcy, ymcy, ypcx, ymcx; 03129 Uint8 *colorptr; 03130 Uint8 drawoct; 03131 int startoct, endoct, oct, stopval_start = 0, stopval_end = 0; 03132 double dstart, dend, temp = 0.; 03133 03134 /* 03135 * Check visibility of clipping rectangle 03136 */ 03137 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03138 return(0); 03139 } 03140 03141 /* 03142 * Sanity check radius 03143 */ 03144 if (rad < 0) { 03145 return (-1); 03146 } 03147 03148 /* 03149 * Special case for rad=0 - draw a point 03150 */ 03151 if (rad == 0) { 03152 return (pixelColor(dst, x, y, color)); 03153 } 03154 03155 /* 03156 * Get arc's circle and clipping boundary and 03157 * test if bounding box of circle is visible 03158 */ 03159 x2 = x + rad; 03160 left = dst->clip_rect.x; 03161 if (x2<left) { 03162 return(0); 03163 } 03164 x1 = x - rad; 03165 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03166 if (x1>right) { 03167 return(0); 03168 } 03169 y2 = y + rad; 03170 top = dst->clip_rect.y; 03171 if (y2<top) { 03172 return(0); 03173 } 03174 y1 = y - rad; 03175 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03176 if (y1>bottom) { 03177 return(0); 03178 } 03179 03180 // Octant labelling 03181 // 03182 // \ 5 | 6 / 03183 // \ | / 03184 // 4 \ | / 7 03185 // \|/ 03186 //------+------ +x 03187 // /|\ 03188 // 3 / | \ 0 03189 // / | \ 03190 // / 2 | 1 \ 03191 // +y 03192 03193 // Initially reset bitmask to 0x00000000 03194 // the set whether or not to keep drawing a given octant. 03195 // For example: 0x00111100 means we're drawing in octants 2-5 03196 drawoct = 0; 03197 03198 /* 03199 * Fixup angles 03200 */ 03201 start %= 360; 03202 end %= 360; 03203 // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. 03204 while (start < 0) start += 360; 03205 while (end < 0) end += 360; 03206 start %= 360; 03207 end %= 360; 03208 03209 // now, we find which octants we're drawing in. 03210 startoct = start / 45; 03211 endoct = end / 45; 03212 oct = startoct - 1; // we increment as first step in loop 03213 03214 // stopval_start, stopval_end; 03215 // what values of cx to stop at. 03216 do { 03217 oct = (oct + 1) % 8; 03218 03219 if (oct == startoct) { 03220 // need to compute stopval_start for this octant. Look at picture above if this is unclear 03221 dstart = (double)start; 03222 switch (oct) 03223 { 03224 case 0: 03225 case 3: 03226 temp = sin(dstart * M_PI / 180.); 03227 break; 03228 case 1: 03229 case 6: 03230 temp = cos(dstart * M_PI / 180.); 03231 break; 03232 case 2: 03233 case 5: 03234 temp = -cos(dstart * M_PI / 180.); 03235 break; 03236 case 4: 03237 case 7: 03238 temp = -sin(dstart * M_PI / 180.); 03239 break; 03240 } 03241 temp *= rad; 03242 stopval_start = (int)temp; // always round down. 03243 // This isn't arbitrary, but requires graph paper to explain well. 03244 // The basic idea is that we're always changing drawoct after we draw, so we 03245 // stop immediately after we render the last sensible pixel at x = ((int)temp). 03246 03247 // and whether to draw in this octant initially 03248 if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array 03249 else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false 03250 } 03251 if (oct == endoct) { 03252 // need to compute stopval_end for this octant 03253 dend = (double)end; 03254 switch (oct) 03255 { 03256 case 0: 03257 case 3: 03258 temp = sin(dend * M_PI / 180); 03259 break; 03260 case 1: 03261 case 6: 03262 temp = cos(dend * M_PI / 180); 03263 break; 03264 case 2: 03265 case 5: 03266 temp = -cos(dend * M_PI / 180); 03267 break; 03268 case 4: 03269 case 7: 03270 temp = -sin(dend * M_PI / 180); 03271 break; 03272 } 03273 temp *= rad; 03274 stopval_end = (int)temp; 03275 03276 // and whether to draw in this octant initially 03277 if (startoct == endoct) { 03278 // note: we start drawing, stop, then start again in this case 03279 // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true 03280 if (start > end) { 03281 // unfortunately, if we're in the same octant and need to draw over the whole circle, 03282 // we need to set the rest to true, because the while loop will end at the bottom. 03283 drawoct = 255; 03284 } else { 03285 drawoct &= 255 - (1 << oct); 03286 } 03287 } 03288 else if (oct % 2) drawoct &= 255 - (1 << oct); 03289 else drawoct |= (1 << oct); 03290 } else if (oct != startoct) { // already verified that it's != endoct 03291 drawoct |= (1 << oct); // draw this entire segment 03292 } 03293 } while (oct != endoct); 03294 03295 // so now we have what octants to draw and when to draw them. all that's left is the actual raster code. 03296 03297 /* Lock surface */ 03298 if (SDL_MUSTLOCK(dst)) { 03299 if (SDL_LockSurface(dst) < 0) { 03300 return (-1); 03301 } 03302 } 03303 03304 /* 03305 * Draw arc 03306 */ 03307 result = 0; 03308 03309 /* 03310 * Alpha Check 03311 */ 03312 if ((color & 255) == 255) { 03313 03314 /* 03315 * No Alpha - direct memory writes 03316 */ 03317 03318 /* 03319 * Setup color 03320 */ 03321 colorptr = (Uint8 *) & color; 03322 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 03323 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 03324 } else { 03325 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 03326 } 03327 03328 /* 03329 * Draw 03330 */ 03331 do { 03332 ypcy = y + cy; 03333 ymcy = y - cy; 03334 if (cx > 0) { 03335 xpcx = x + cx; 03336 xmcx = x - cx; 03337 // always check if we're drawing a certain octant before adding a pixel to that octant. 03338 if (drawoct & 4) result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2] 03339 if (drawoct & 2) result |= fastPixelColorNolock(dst, xpcx, ypcy, color); 03340 if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color); 03341 if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color); 03342 } else { 03343 if (drawoct & 6) result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1] 03344 if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64 03345 } 03346 03347 xpcy = x + cy; 03348 xmcy = x - cy; 03349 if (cx > 0 && cx != cy) { 03350 ypcx = y + cx; 03351 ymcx = y - cx; 03352 if (drawoct & 8) result |= fastPixelColorNolock(dst, xmcy, ypcx, color); 03353 if (drawoct & 1) result |= fastPixelColorNolock(dst, xpcy, ypcx, color); 03354 if (drawoct & 16) result |= fastPixelColorNolock(dst, xmcy, ymcx, color); 03355 if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color); 03356 } else if (cx == 0) { 03357 if (drawoct & 24) result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16 03358 if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128 03359 } 03360 03361 /* 03362 * Update whether we're drawing an octant 03363 */ 03364 if (stopval_start == cx) { 03365 // works like an on-off switch because start & end may be in the same octant. 03366 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct); 03367 else drawoct |= (1 << startoct); 03368 } 03369 if (stopval_end == cx) { 03370 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct); 03371 else drawoct |= (1 << endoct); 03372 } 03373 03374 /* 03375 * Update pixels 03376 */ 03377 if (df < 0) { 03378 df += d_e; 03379 d_e += 2; 03380 d_se += 2; 03381 } else { 03382 df += d_se; 03383 d_e += 2; 03384 d_se += 4; 03385 cy--; 03386 } 03387 cx++; 03388 } while (cx <= cy); 03389 03390 /* 03391 * Unlock surface 03392 */ 03393 SDL_UnlockSurface(dst); 03394 03395 } else { 03396 03397 /* 03398 * Using Alpha - blended pixel blits 03399 */ 03400 03401 do { 03402 ypcy = y + cy; 03403 ymcy = y - cy; 03404 if (cx > 0) { 03405 xpcx = x + cx; 03406 xmcx = x - cx; 03407 03408 // always check if we're drawing a certain octant before adding a pixel to that octant. 03409 if (drawoct & 4) result |= pixelColorNolock(dst, xmcx, ypcy, color); 03410 if (drawoct & 2) result |= pixelColorNolock(dst, xpcx, ypcy, color); 03411 if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color); 03412 if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color); 03413 } else { 03414 if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color); 03415 if (drawoct & 6) result |= pixelColorNolock(dst, x, ypcy, color); 03416 } 03417 03418 xpcy = x + cy; 03419 xmcy = x - cy; 03420 if (cx > 0 && cx != cy) { 03421 ypcx = y + cx; 03422 ymcx = y - cx; 03423 if (drawoct & 8) result |= pixelColorNolock(dst, xmcy, ypcx, color); 03424 if (drawoct & 1) result |= pixelColorNolock(dst, xpcy, ypcx, color); 03425 if (drawoct & 16) result |= pixelColorNolock(dst, xmcy, ymcx, color); 03426 if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color); 03427 } else if (cx == 0) { 03428 if (drawoct & 24) result |= pixelColorNolock(dst, xmcy, y, color); 03429 if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color); 03430 } 03431 03432 /* 03433 * Update whether we're drawing an octant 03434 */ 03435 if (stopval_start == cx) { 03436 // works like an on-off switch. 03437 // This is just in case start & end are in the same octant. 03438 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct); 03439 else drawoct |= (1 << startoct); 03440 } 03441 if (stopval_end == cx) { 03442 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct); 03443 else drawoct |= (1 << endoct); 03444 } 03445 03446 /* 03447 * Update pixels 03448 */ 03449 if (df < 0) { 03450 df += d_e; 03451 d_e += 2; 03452 d_se += 2; 03453 } else { 03454 df += d_se; 03455 d_e += 2; 03456 d_se += 4; 03457 cy--; 03458 } 03459 cx++; 03460 } while (cx <= cy); 03461 03462 } /* Alpha check */ 03463 03464 /* Unlock surface */ 03465 if (SDL_MUSTLOCK(dst)) { 03466 SDL_UnlockSurface(dst); 03467 } 03468 03469 return (result); 03470 } 03471 03488 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03489 { 03490 /* 03491 * Draw 03492 */ 03493 return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03494 } 03495 03496 /* ----- AA Circle */ 03497 03498 03512 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 03513 { 03514 return (aaellipseColor(dst, x, y, rad, rad, color)); 03515 } 03516 03531 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03532 { 03533 /* 03534 * Draw 03535 */ 03536 return (aaellipseColor 03537 (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03538 } 03539 03540 /* ----- Filled Circle */ 03541 03556 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 03557 { 03558 Sint16 left, right, top, bottom; 03559 int result; 03560 Sint16 x1, y1, x2, y2; 03561 Sint16 cx = 0; 03562 Sint16 cy = rad; 03563 Sint16 ocx = (Sint16) 0xffff; 03564 Sint16 ocy = (Sint16) 0xffff; 03565 Sint16 df = 1 - rad; 03566 Sint16 d_e = 3; 03567 Sint16 d_se = -2 * rad + 5; 03568 Sint16 xpcx, xmcx, xpcy, xmcy; 03569 Sint16 ypcy, ymcy, ypcx, ymcx; 03570 03571 /* 03572 * Check visibility of clipping rectangle 03573 */ 03574 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03575 return(0); 03576 } 03577 03578 /* 03579 * Sanity check radius 03580 */ 03581 if (rad < 0) { 03582 return (-1); 03583 } 03584 03585 /* 03586 * Special case for rad=0 - draw a point 03587 */ 03588 if (rad == 0) { 03589 return (pixelColor(dst, x, y, color)); 03590 } 03591 03592 /* 03593 * Get circle and clipping boundary and 03594 * test if bounding box of circle is visible 03595 */ 03596 x2 = x + rad; 03597 left = dst->clip_rect.x; 03598 if (x2<left) { 03599 return(0); 03600 } 03601 x1 = x - rad; 03602 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03603 if (x1>right) { 03604 return(0); 03605 } 03606 y2 = y + rad; 03607 top = dst->clip_rect.y; 03608 if (y2<top) { 03609 return(0); 03610 } 03611 y1 = y - rad; 03612 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03613 if (y1>bottom) { 03614 return(0); 03615 } 03616 03617 /* 03618 * Draw 03619 */ 03620 result = 0; 03621 do { 03622 xpcx = x + cx; 03623 xmcx = x - cx; 03624 xpcy = x + cy; 03625 xmcy = x - cy; 03626 if (ocy != cy) { 03627 if (cy > 0) { 03628 ypcy = y + cy; 03629 ymcy = y - cy; 03630 result |= hlineColor(dst, xmcx, xpcx, ypcy, color); 03631 result |= hlineColor(dst, xmcx, xpcx, ymcy, color); 03632 } else { 03633 result |= hlineColor(dst, xmcx, xpcx, y, color); 03634 } 03635 ocy = cy; 03636 } 03637 if (ocx != cx) { 03638 if (cx != cy) { 03639 if (cx > 0) { 03640 ypcx = y + cx; 03641 ymcx = y - cx; 03642 result |= hlineColor(dst, xmcy, xpcy, ymcx, color); 03643 result |= hlineColor(dst, xmcy, xpcy, ypcx, color); 03644 } else { 03645 result |= hlineColor(dst, xmcy, xpcy, y, color); 03646 } 03647 } 03648 ocx = cx; 03649 } 03650 /* 03651 * Update 03652 */ 03653 if (df < 0) { 03654 df += d_e; 03655 d_e += 2; 03656 d_se += 2; 03657 } else { 03658 df += d_se; 03659 d_e += 2; 03660 d_se += 4; 03661 cy--; 03662 } 03663 cx++; 03664 } while (cx <= cy); 03665 03666 return (result); 03667 } 03668 03683 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03684 { 03685 /* 03686 * Draw 03687 */ 03688 return (filledCircleColor 03689 (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03690 } 03691 03692 /* ----- Ellipse */ 03693 03709 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 03710 { 03711 Sint16 left, right, top, bottom; 03712 int result; 03713 Sint16 x1, y1, x2, y2; 03714 int ix, iy; 03715 int h, i, j, k; 03716 int oh, oi, oj, ok; 03717 int xmh, xph, ypk, ymk; 03718 int xmi, xpi, ymj, ypj; 03719 int xmj, xpj, ymi, ypi; 03720 int xmk, xpk, ymh, yph; 03721 Uint8 *colorptr; 03722 03723 /* 03724 * Check visibility of clipping rectangle 03725 */ 03726 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03727 return(0); 03728 } 03729 03730 /* 03731 * Sanity check radii 03732 */ 03733 if ((rx < 0) || (ry < 0)) { 03734 return (-1); 03735 } 03736 03737 /* 03738 * Special case for rx=0 - draw a vline 03739 */ 03740 if (rx == 0) { 03741 return (vlineColor(dst, x, y - ry, y + ry, color)); 03742 } 03743 /* 03744 * Special case for ry=0 - draw a hline 03745 */ 03746 if (ry == 0) { 03747 return (hlineColor(dst, x - rx, x + rx, y, color)); 03748 } 03749 03750 /* 03751 * Get circle and clipping boundary and 03752 * test if bounding box of circle is visible 03753 */ 03754 x2 = x + rx; 03755 left = dst->clip_rect.x; 03756 if (x2<left) { 03757 return(0); 03758 } 03759 x1 = x - rx; 03760 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03761 if (x1>right) { 03762 return(0); 03763 } 03764 y2 = y + ry; 03765 top = dst->clip_rect.y; 03766 if (y2<top) { 03767 return(0); 03768 } 03769 y1 = y - ry; 03770 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03771 if (y1>bottom) { 03772 return(0); 03773 } 03774 03775 /* 03776 * Init vars 03777 */ 03778 oh = oi = oj = ok = 0xFFFF; 03779 03780 /* 03781 * Draw 03782 */ 03783 result = 0; 03784 03785 /* Lock surface */ 03786 if (SDL_MUSTLOCK(dst)) { 03787 if (SDL_LockSurface(dst) < 0) { 03788 return (-1); 03789 } 03790 } 03791 03792 /* 03793 * Check alpha 03794 */ 03795 if ((color & 255) == 255) { 03796 03797 /* 03798 * No Alpha - direct memory writes 03799 */ 03800 03801 /* 03802 * Setup color 03803 */ 03804 colorptr = (Uint8 *) & color; 03805 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 03806 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 03807 } else { 03808 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 03809 } 03810 03811 03812 if (rx > ry) { 03813 ix = 0; 03814 iy = rx * 64; 03815 03816 do { 03817 h = (ix + 32) >> 6; 03818 i = (iy + 32) >> 6; 03819 j = (h * ry) / rx; 03820 k = (i * ry) / rx; 03821 03822 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) { 03823 xph = x + h; 03824 xmh = x - h; 03825 if (k > 0) { 03826 ypk = y + k; 03827 ymk = y - k; 03828 result |= fastPixelColorNolock(dst, xmh, ypk, color); 03829 result |= fastPixelColorNolock(dst, xph, ypk, color); 03830 result |= fastPixelColorNolock(dst, xmh, ymk, color); 03831 result |= fastPixelColorNolock(dst, xph, ymk, color); 03832 } else { 03833 result |= fastPixelColorNolock(dst, xmh, y, color); 03834 result |= fastPixelColorNolock(dst, xph, y, color); 03835 } 03836 ok = k; 03837 xpi = x + i; 03838 xmi = x - i; 03839 if (j > 0) { 03840 ypj = y + j; 03841 ymj = y - j; 03842 result |= fastPixelColorNolock(dst, xmi, ypj, color); 03843 result |= fastPixelColorNolock(dst, xpi, ypj, color); 03844 result |= fastPixelColorNolock(dst, xmi, ymj, color); 03845 result |= fastPixelColorNolock(dst, xpi, ymj, color); 03846 } else { 03847 result |= fastPixelColorNolock(dst, xmi, y, color); 03848 result |= fastPixelColorNolock(dst, xpi, y, color); 03849 } 03850 oj = j; 03851 } 03852 03853 ix = ix + iy / rx; 03854 iy = iy - ix / rx; 03855 03856 } while (i > h); 03857 } else { 03858 ix = 0; 03859 iy = ry * 64; 03860 03861 do { 03862 h = (ix + 32) >> 6; 03863 i = (iy + 32) >> 6; 03864 j = (h * rx) / ry; 03865 k = (i * rx) / ry; 03866 03867 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) { 03868 xmj = x - j; 03869 xpj = x + j; 03870 if (i > 0) { 03871 ypi = y + i; 03872 ymi = y - i; 03873 result |= fastPixelColorNolock(dst, xmj, ypi, color); 03874 result |= fastPixelColorNolock(dst, xpj, ypi, color); 03875 result |= fastPixelColorNolock(dst, xmj, ymi, color); 03876 result |= fastPixelColorNolock(dst, xpj, ymi, color); 03877 } else { 03878 result |= fastPixelColorNolock(dst, xmj, y, color); 03879 result |= fastPixelColorNolock(dst, xpj, y, color); 03880 } 03881 oi = i; 03882 xmk = x - k; 03883 xpk = x + k; 03884 if (h > 0) { 03885 yph = y + h; 03886 ymh = y - h; 03887 result |= fastPixelColorNolock(dst, xmk, yph, color); 03888 result |= fastPixelColorNolock(dst, xpk, yph, color); 03889 result |= fastPixelColorNolock(dst, xmk, ymh, color); 03890 result |= fastPixelColorNolock(dst, xpk, ymh, color); 03891 } else { 03892 result |= fastPixelColorNolock(dst, xmk, y, color); 03893 result |= fastPixelColorNolock(dst, xpk, y, color); 03894 } 03895 oh = h; 03896 } 03897 03898 ix = ix + iy / ry; 03899 iy = iy - ix / ry; 03900 03901 } while (i > h); 03902 } 03903 03904 } else { 03905 03906 if (rx > ry) { 03907 ix = 0; 03908 iy = rx * 64; 03909 03910 do { 03911 h = (ix + 32) >> 6; 03912 i = (iy + 32) >> 6; 03913 j = (h * ry) / rx; 03914 k = (i * ry) / rx; 03915 03916 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) { 03917 xph = x + h; 03918 xmh = x - h; 03919 if (k > 0) { 03920 ypk = y + k; 03921 ymk = y - k; 03922 result |= pixelColorNolock (dst, xmh, ypk, color); 03923 result |= pixelColorNolock (dst, xph, ypk, color); 03924 result |= pixelColorNolock (dst, xmh, ymk, color); 03925 result |= pixelColorNolock (dst, xph, ymk, color); 03926 } else { 03927 result |= pixelColorNolock (dst, xmh, y, color); 03928 result |= pixelColorNolock (dst, xph, y, color); 03929 } 03930 ok = k; 03931 xpi = x + i; 03932 xmi = x - i; 03933 if (j > 0) { 03934 ypj = y + j; 03935 ymj = y - j; 03936 result |= pixelColorNolock (dst, xmi, ypj, color); 03937 result |= pixelColorNolock (dst, xpi, ypj, color); 03938 result |= pixelColorNolock (dst, xmi, ymj, color); 03939 result |= pixelColor(dst, xpi, ymj, color); 03940 } else { 03941 result |= pixelColorNolock (dst, xmi, y, color); 03942 result |= pixelColorNolock (dst, xpi, y, color); 03943 } 03944 oj = j; 03945 } 03946 03947 ix = ix + iy / rx; 03948 iy = iy - ix / rx; 03949 03950 } while (i > h); 03951 } else { 03952 ix = 0; 03953 iy = ry * 64; 03954 03955 do { 03956 h = (ix + 32) >> 6; 03957 i = (iy + 32) >> 6; 03958 j = (h * rx) / ry; 03959 k = (i * rx) / ry; 03960 03961 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) { 03962 xmj = x - j; 03963 xpj = x + j; 03964 if (i > 0) { 03965 ypi = y + i; 03966 ymi = y - i; 03967 result |= pixelColorNolock (dst, xmj, ypi, color); 03968 result |= pixelColorNolock (dst, xpj, ypi, color); 03969 result |= pixelColorNolock (dst, xmj, ymi, color); 03970 result |= pixelColorNolock (dst, xpj, ymi, color); 03971 } else { 03972 result |= pixelColorNolock (dst, xmj, y, color); 03973 result |= pixelColorNolock (dst, xpj, y, color); 03974 } 03975 oi = i; 03976 xmk = x - k; 03977 xpk = x + k; 03978 if (h > 0) { 03979 yph = y + h; 03980 ymh = y - h; 03981 result |= pixelColorNolock (dst, xmk, yph, color); 03982 result |= pixelColorNolock (dst, xpk, yph, color); 03983 result |= pixelColorNolock (dst, xmk, ymh, color); 03984 result |= pixelColorNolock (dst, xpk, ymh, color); 03985 } else { 03986 result |= pixelColorNolock (dst, xmk, y, color); 03987 result |= pixelColorNolock (dst, xpk, y, color); 03988 } 03989 oh = h; 03990 } 03991 03992 ix = ix + iy / ry; 03993 iy = iy - ix / ry; 03994 03995 } while (i > h); 03996 } 03997 03998 } /* Alpha check */ 03999 04000 /* Unlock surface */ 04001 if (SDL_MUSTLOCK(dst)) { 04002 SDL_UnlockSurface(dst); 04003 } 04004 04005 return (result); 04006 } 04007 04023 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04024 { 04025 /* 04026 * Draw 04027 */ 04028 return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04029 } 04030 04031 /* ----- AA Ellipse */ 04032 04033 /* Windows targets do not have lrint, so provide a local inline version */ 04034 #if defined(_MSC_VER) 04035 /* Detect 64bit and use intrinsic version */ 04036 #ifdef _M_X64 04037 #include <emmintrin.h> 04038 static __inline long 04039 lrint(float f) 04040 { 04041 return _mm_cvtss_si32(_mm_load_ss(&f)); 04042 } 04043 #elif defined(_M_IX86) 04044 __inline long int 04045 lrint (double flt) 04046 { 04047 int intgr; 04048 _asm 04049 { 04050 fld flt 04051 fistp intgr 04052 }; 04053 return intgr; 04054 } 04055 #elif defined(_M_ARM) 04056 #include <armintr.h> 04057 #pragma warning(push) 04058 #pragma warning(disable: 4716) 04059 __declspec(naked) long int 04060 lrint (double flt) 04061 { 04062 __emit(0xEC410B10); // fmdrr d0, r0, r1 04063 __emit(0xEEBD0B40); // ftosid s0, d0 04064 __emit(0xEE100A10); // fmrs r0, s0 04065 __emit(0xE12FFF1E); // bx lr 04066 } 04067 #pragma warning(pop) 04068 #else 04069 #error lrint needed for MSVC on non X86/AMD64/ARM targets. 04070 #endif 04071 #endif 04072 04088 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 04089 { 04090 Sint16 left, right, top, bottom; 04091 Sint16 x1,y1,x2,y2; 04092 int i; 04093 int a2, b2, ds, dt, dxt, t, s, d; 04094 Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2; 04095 float cp; 04096 double sab; 04097 Uint8 weight, iweight; 04098 int result; 04099 04100 /* 04101 * Check visibility of clipping rectangle 04102 */ 04103 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04104 return(0); 04105 } 04106 04107 /* 04108 * Sanity check radii 04109 */ 04110 if ((rx < 0) || (ry < 0)) { 04111 return (-1); 04112 } 04113 04114 /* 04115 * Special case for rx=0 - draw a vline 04116 */ 04117 if (rx == 0) { 04118 return (vlineColor(dst, x, y - ry, y + ry, color)); 04119 } 04120 /* 04121 * Special case for ry=0 - draw an hline 04122 */ 04123 if (ry == 0) { 04124 return (hlineColor(dst, x - rx, x + rx, y, color)); 04125 } 04126 04127 /* 04128 * Get circle and clipping boundary and 04129 * test if bounding box of circle is visible 04130 */ 04131 x2 = x + rx; 04132 left = dst->clip_rect.x; 04133 if (x2<left) { 04134 return(0); 04135 } 04136 x1 = x - rx; 04137 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04138 if (x1>right) { 04139 return(0); 04140 } 04141 y2 = y + ry; 04142 top = dst->clip_rect.y; 04143 if (y2<top) { 04144 return(0); 04145 } 04146 y1 = y - ry; 04147 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04148 if (y1>bottom) { 04149 return(0); 04150 } 04151 04152 /* Variable setup */ 04153 a2 = rx * rx; 04154 b2 = ry * ry; 04155 04156 ds = 2 * a2; 04157 dt = 2 * b2; 04158 04159 xc2 = 2 * x; 04160 yc2 = 2 * y; 04161 04162 sab = sqrt((double)(a2 + b2)); 04163 od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */ 04164 dxt = (Sint16)lrint((double)a2 / sab) + od; 04165 04166 t = 0; 04167 s = -2 * a2 * ry; 04168 d = 0; 04169 04170 xp = x; 04171 yp = y - ry; 04172 04173 /* Lock surface */ 04174 if (SDL_MUSTLOCK(dst)) { 04175 if (SDL_LockSurface(dst) < 0) { 04176 return (-1); 04177 } 04178 } 04179 04180 /* Draw */ 04181 result = 0; 04182 04183 /* "End points" */ 04184 result |= pixelColorNolock(dst, xp, yp, color); 04185 result |= pixelColorNolock(dst, xc2 - xp, yp, color); 04186 result |= pixelColorNolock(dst, xp, yc2 - yp, color); 04187 result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color); 04188 04189 for (i = 1; i <= dxt; i++) { 04190 xp--; 04191 d += t - b2; 04192 04193 if (d >= 0) 04194 ys = yp - 1; 04195 else if ((d - s - a2) > 0) { 04196 if ((2 * d - s - a2) >= 0) 04197 ys = yp + 1; 04198 else { 04199 ys = yp; 04200 yp++; 04201 d -= s + a2; 04202 s += ds; 04203 } 04204 } else { 04205 yp++; 04206 ys = yp + 1; 04207 d -= s + a2; 04208 s += ds; 04209 } 04210 04211 t -= dt; 04212 04213 /* Calculate alpha */ 04214 if (s != 0) { 04215 cp = (float) abs(d) / (float) abs(s); 04216 if (cp > 1.0) { 04217 cp = 1.0; 04218 } 04219 } else { 04220 cp = 1.0; 04221 } 04222 04223 /* Calculate weights */ 04224 weight = (Uint8) (cp * 255); 04225 iweight = 255 - weight; 04226 04227 /* Upper half */ 04228 xx = xc2 - xp; 04229 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight); 04230 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight); 04231 04232 result |= pixelColorWeightNolock(dst, xp, ys, color, weight); 04233 result |= pixelColorWeightNolock(dst, xx, ys, color, weight); 04234 04235 /* Lower half */ 04236 yy = yc2 - yp; 04237 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight); 04238 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight); 04239 04240 yy = yc2 - ys; 04241 result |= pixelColorWeightNolock(dst, xp, yy, color, weight); 04242 result |= pixelColorWeightNolock(dst, xx, yy, color, weight); 04243 } 04244 04245 /* Replaces original approximation code dyt = abs(yp - yc); */ 04246 dyt = (Sint16)lrint((double)b2 / sab ) + od; 04247 04248 for (i = 1; i <= dyt; i++) { 04249 yp++; 04250 d -= s + a2; 04251 04252 if (d <= 0) 04253 xs = xp + 1; 04254 else if ((d + t - b2) < 0) { 04255 if ((2 * d + t - b2) <= 0) 04256 xs = xp - 1; 04257 else { 04258 xs = xp; 04259 xp--; 04260 d += t - b2; 04261 t -= dt; 04262 } 04263 } else { 04264 xp--; 04265 xs = xp - 1; 04266 d += t - b2; 04267 t -= dt; 04268 } 04269 04270 s += ds; 04271 04272 /* Calculate alpha */ 04273 if (t != 0) { 04274 cp = (float) abs(d) / (float) abs(t); 04275 if (cp > 1.0) { 04276 cp = 1.0; 04277 } 04278 } else { 04279 cp = 1.0; 04280 } 04281 04282 /* Calculate weight */ 04283 weight = (Uint8) (cp * 255); 04284 iweight = 255 - weight; 04285 04286 /* Left half */ 04287 xx = xc2 - xp; 04288 yy = yc2 - yp; 04289 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight); 04290 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight); 04291 04292 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight); 04293 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight); 04294 04295 /* Right half */ 04296 xx = xc2 - xs; 04297 result |= pixelColorWeightNolock(dst, xs, yp, color, weight); 04298 result |= pixelColorWeightNolock(dst, xx, yp, color, weight); 04299 04300 result |= pixelColorWeightNolock(dst, xs, yy, color, weight); 04301 result |= pixelColorWeightNolock(dst, xx, yy, color, weight); 04302 04303 } 04304 04305 /* Unlock surface */ 04306 if (SDL_MUSTLOCK(dst)) { 04307 SDL_UnlockSurface(dst); 04308 } 04309 04310 return (result); 04311 } 04312 04328 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04329 { 04330 /* 04331 * Draw 04332 */ 04333 return (aaellipseColor 04334 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04335 } 04336 04337 /* ---- Filled Ellipse */ 04338 04339 /* Note: */ 04340 /* Based on algorithm from sge library with multiple-hline draw removal */ 04341 /* and other speedup changes. */ 04342 04358 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 04359 { 04360 Sint16 left, right, top, bottom; 04361 int result; 04362 Sint16 x1, y1, x2, y2; 04363 int ix, iy; 04364 int h, i, j, k; 04365 int oh, oi, oj, ok; 04366 int xmh, xph; 04367 int xmi, xpi; 04368 int xmj, xpj; 04369 int xmk, xpk; 04370 04371 /* 04372 * Check visibility of clipping rectangle 04373 */ 04374 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04375 return(0); 04376 } 04377 04378 /* 04379 * Sanity check radii 04380 */ 04381 if ((rx < 0) || (ry < 0)) { 04382 return (-1); 04383 } 04384 04385 /* 04386 * Special case for rx=0 - draw a vline 04387 */ 04388 if (rx == 0) { 04389 return (vlineColor(dst, x, y - ry, y + ry, color)); 04390 } 04391 /* 04392 * Special case for ry=0 - draw a hline 04393 */ 04394 if (ry == 0) { 04395 return (hlineColor(dst, x - rx, x + rx, y, color)); 04396 } 04397 04398 /* 04399 * Get circle and clipping boundary and 04400 * test if bounding box of circle is visible 04401 */ 04402 x2 = x + rx; 04403 left = dst->clip_rect.x; 04404 if (x2<left) { 04405 return(0); 04406 } 04407 x1 = x - rx; 04408 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04409 if (x1>right) { 04410 return(0); 04411 } 04412 y2 = y + ry; 04413 top = dst->clip_rect.y; 04414 if (y2<top) { 04415 return(0); 04416 } 04417 y1 = y - ry; 04418 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04419 if (y1>bottom) { 04420 return(0); 04421 } 04422 04423 /* 04424 * Init vars 04425 */ 04426 oh = oi = oj = ok = 0xFFFF; 04427 04428 /* 04429 * Draw 04430 */ 04431 result = 0; 04432 if (rx > ry) { 04433 ix = 0; 04434 iy = rx * 64; 04435 04436 do { 04437 h = (ix + 32) >> 6; 04438 i = (iy + 32) >> 6; 04439 j = (h * ry) / rx; 04440 k = (i * ry) / rx; 04441 04442 if ((ok != k) && (oj != k)) { 04443 xph = x + h; 04444 xmh = x - h; 04445 if (k > 0) { 04446 result |= hlineColor(dst, xmh, xph, y + k, color); 04447 result |= hlineColor(dst, xmh, xph, y - k, color); 04448 } else { 04449 result |= hlineColor(dst, xmh, xph, y, color); 04450 } 04451 ok = k; 04452 } 04453 if ((oj != j) && (ok != j) && (k != j)) { 04454 xmi = x - i; 04455 xpi = x + i; 04456 if (j > 0) { 04457 result |= hlineColor(dst, xmi, xpi, y + j, color); 04458 result |= hlineColor(dst, xmi, xpi, y - j, color); 04459 } else { 04460 result |= hlineColor(dst, xmi, xpi, y, color); 04461 } 04462 oj = j; 04463 } 04464 04465 ix = ix + iy / rx; 04466 iy = iy - ix / rx; 04467 04468 } while (i > h); 04469 } else { 04470 ix = 0; 04471 iy = ry * 64; 04472 04473 do { 04474 h = (ix + 32) >> 6; 04475 i = (iy + 32) >> 6; 04476 j = (h * rx) / ry; 04477 k = (i * rx) / ry; 04478 04479 if ((oi != i) && (oh != i)) { 04480 xmj = x - j; 04481 xpj = x + j; 04482 if (i > 0) { 04483 result |= hlineColor(dst, xmj, xpj, y + i, color); 04484 result |= hlineColor(dst, xmj, xpj, y - i, color); 04485 } else { 04486 result |= hlineColor(dst, xmj, xpj, y, color); 04487 } 04488 oi = i; 04489 } 04490 if ((oh != h) && (oi != h) && (i != h)) { 04491 xmk = x - k; 04492 xpk = x + k; 04493 if (h > 0) { 04494 result |= hlineColor(dst, xmk, xpk, y + h, color); 04495 result |= hlineColor(dst, xmk, xpk, y - h, color); 04496 } else { 04497 result |= hlineColor(dst, xmk, xpk, y, color); 04498 } 04499 oh = h; 04500 } 04501 04502 ix = ix + iy / ry; 04503 iy = iy - ix / ry; 04504 04505 } while (i > h); 04506 } 04507 04508 return (result); 04509 } 04510 04526 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04527 { 04528 /* 04529 * Draw 04530 */ 04531 return (filledEllipseColor 04532 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04533 } 04534 04535 /* ----- pie */ 04536 04553 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled) 04554 { 04555 Sint16 left, right, top, bottom; 04556 Sint16 x1, y1, x2, y2; 04557 int result; 04558 double angle, start_angle, end_angle; 04559 double deltaAngle; 04560 double dr; 04561 int numpoints, i; 04562 Sint16 *vx, *vy; 04563 04564 /* 04565 * Check visibility of clipping rectangle 04566 */ 04567 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04568 return(0); 04569 } 04570 04571 /* 04572 * Sanity check radii 04573 */ 04574 if (rad < 0) { 04575 return (-1); 04576 } 04577 04578 /* 04579 * Fixup angles 04580 */ 04581 start = start % 360; 04582 end = end % 360; 04583 04584 /* 04585 * Special case for rad=0 - draw a point 04586 */ 04587 if (rad == 0) { 04588 return (pixelColor(dst, x, y, color)); 04589 } 04590 04591 /* 04592 * Clip against circle, not pie (not 100% optimal). 04593 * Get pie's circle and clipping boundary and 04594 * test if bounding box of circle is visible 04595 */ 04596 x2 = x + rad; 04597 left = dst->clip_rect.x; 04598 if (x2<left) { 04599 return(0); 04600 } 04601 x1 = x - rad; 04602 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04603 if (x1>right) { 04604 return(0); 04605 } 04606 y2 = y + rad; 04607 top = dst->clip_rect.y; 04608 if (y2<top) { 04609 return(0); 04610 } 04611 y1 = y - rad; 04612 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04613 if (y1>bottom) { 04614 return(0); 04615 } 04616 04617 /* 04618 * Variable setup 04619 */ 04620 dr = (double) rad; 04621 deltaAngle = 3.0 / dr; 04622 start_angle = (double) start *(2.0 * M_PI / 360.0); 04623 end_angle = (double) end *(2.0 * M_PI / 360.0); 04624 if (start > end) { 04625 end_angle += (2.0 * M_PI); 04626 } 04627 04628 /* We will always have at least 2 points */ 04629 numpoints = 2; 04630 04631 /* Count points (rather than calculating it) */ 04632 angle = start_angle; 04633 while (angle < end_angle) { 04634 angle += deltaAngle; 04635 numpoints++; 04636 } 04637 04638 /* Allocate combined vertex array */ 04639 vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints); 04640 if (vx == NULL) { 04641 return (-1); 04642 } 04643 04644 /* Update point to start of vy */ 04645 vy += numpoints; 04646 04647 /* Center */ 04648 vx[0] = x; 04649 vy[0] = y; 04650 04651 /* First vertex */ 04652 angle = start_angle; 04653 vx[1] = x + (int) (dr * cos(angle)); 04654 vy[1] = y + (int) (dr * sin(angle)); 04655 04656 if (numpoints<3) 04657 { 04658 result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color); 04659 } 04660 else 04661 { 04662 /* Calculate other vertices */ 04663 i = 2; 04664 angle = start_angle; 04665 while (angle < end_angle) { 04666 angle += deltaAngle; 04667 if (angle>end_angle) 04668 { 04669 angle = end_angle; 04670 } 04671 vx[i] = x + (int) (dr * cos(angle)); 04672 vy[i] = y + (int) (dr * sin(angle)); 04673 i++; 04674 } 04675 04676 /* Draw */ 04677 if (filled) { 04678 result = filledPolygonColor(dst, vx, vy, numpoints, color); 04679 } else { 04680 result = polygonColor(dst, vx, vy, numpoints, color); 04681 } 04682 } 04683 04684 /* Free combined vertex array */ 04685 free(vx); 04686 04687 return (result); 04688 } 04689 04703 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04704 Sint16 start, Sint16 end, Uint32 color) 04705 { 04706 return (_pieColor(dst, x, y, rad, start, end, color, 0)); 04707 04708 } 04709 04726 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04727 Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04728 { 04729 return (_pieColor(dst, x, y, rad, start, end, 04730 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0)); 04731 04732 } 04733 04747 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) 04748 { 04749 return (_pieColor(dst, x, y, rad, start, end, color, 1)); 04750 } 04751 04768 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04769 Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04770 { 04771 return (_pieColor(dst, x, y, rad, start, end, 04772 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1)); 04773 } 04774 04775 /* ------ Trigon */ 04776 04793 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04794 { 04795 Sint16 vx[3]; 04796 Sint16 vy[3]; 04797 04798 vx[0]=x1; 04799 vx[1]=x2; 04800 vx[2]=x3; 04801 vy[0]=y1; 04802 vy[1]=y2; 04803 vy[2]=y3; 04804 04805 return(polygonColor(dst,vx,vy,3,color)); 04806 } 04807 04825 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04826 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04827 { 04828 Sint16 vx[3]; 04829 Sint16 vy[3]; 04830 04831 vx[0]=x1; 04832 vx[1]=x2; 04833 vx[2]=x3; 04834 vy[0]=y1; 04835 vy[1]=y2; 04836 vy[2]=y3; 04837 04838 return(polygonRGBA(dst,vx,vy,3,r,g,b,a)); 04839 } 04840 04841 /* ------ AA-Trigon */ 04842 04859 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04860 { 04861 Sint16 vx[3]; 04862 Sint16 vy[3]; 04863 04864 vx[0]=x1; 04865 vx[1]=x2; 04866 vx[2]=x3; 04867 vy[0]=y1; 04868 vy[1]=y2; 04869 vy[2]=y3; 04870 04871 return(aapolygonColor(dst,vx,vy,3,color)); 04872 } 04873 04891 int aatrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04892 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04893 { 04894 Sint16 vx[3]; 04895 Sint16 vy[3]; 04896 04897 vx[0]=x1; 04898 vx[1]=x2; 04899 vx[2]=x3; 04900 vy[0]=y1; 04901 vy[1]=y2; 04902 vy[2]=y3; 04903 04904 return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a)); 04905 } 04906 04907 /* ------ Filled Trigon */ 04908 04925 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04926 { 04927 Sint16 vx[3]; 04928 Sint16 vy[3]; 04929 04930 vx[0]=x1; 04931 vx[1]=x2; 04932 vx[2]=x3; 04933 vy[0]=y1; 04934 vy[1]=y2; 04935 vy[2]=y3; 04936 04937 return(filledPolygonColor(dst,vx,vy,3,color)); 04938 } 04939 04959 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04960 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04961 { 04962 Sint16 vx[3]; 04963 Sint16 vy[3]; 04964 04965 vx[0]=x1; 04966 vx[1]=x2; 04967 vx[2]=x3; 04968 vy[0]=y1; 04969 vy[1]=y2; 04970 vy[2]=y3; 04971 04972 return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a)); 04973 } 04974 04975 /* ---- Polygon */ 04976 04988 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 04989 { 04990 int result; 04991 int i; 04992 const Sint16 *x1, *y1, *x2, *y2; 04993 04994 /* 04995 * Check visibility of clipping rectangle 04996 */ 04997 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04998 return(0); 04999 } 05000 05001 /* 05002 * Vertex array NULL check 05003 */ 05004 if (vx == NULL) { 05005 return (-1); 05006 } 05007 if (vy == NULL) { 05008 return (-1); 05009 } 05010 05011 /* 05012 * Sanity check 05013 */ 05014 if (n < 3) { 05015 return (-1); 05016 } 05017 05018 /* 05019 * Pointer setup 05020 */ 05021 x1 = x2 = vx; 05022 y1 = y2 = vy; 05023 x2++; 05024 y2++; 05025 05026 /* 05027 * Draw 05028 */ 05029 result = 0; 05030 for (i = 1; i < n; i++) { 05031 result |= lineColor(dst, *x1, *y1, *x2, *y2, color); 05032 x1 = x2; 05033 y1 = y2; 05034 x2++; 05035 y2++; 05036 } 05037 result |= lineColor(dst, *x1, *y1, *vx, *vy, color); 05038 05039 return (result); 05040 } 05041 05056 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05057 { 05058 /* 05059 * Draw 05060 */ 05061 return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 05062 } 05063 05064 /* ---- AA-Polygon */ 05065 05077 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 05078 { 05079 int result; 05080 int i; 05081 const Sint16 *x1, *y1, *x2, *y2; 05082 05083 /* 05084 * Check visibility of clipping rectangle 05085 */ 05086 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05087 return(0); 05088 } 05089 05090 /* 05091 * Vertex array NULL check 05092 */ 05093 if (vx == NULL) { 05094 return (-1); 05095 } 05096 if (vy == NULL) { 05097 return (-1); 05098 } 05099 05100 /* 05101 * Sanity check 05102 */ 05103 if (n < 3) { 05104 return (-1); 05105 } 05106 05107 /* 05108 * Pointer setup 05109 */ 05110 x1 = x2 = vx; 05111 y1 = y2 = vy; 05112 x2++; 05113 y2++; 05114 05115 /* 05116 * Draw 05117 */ 05118 result = 0; 05119 for (i = 1; i < n; i++) { 05120 result |= _aalineColor(dst, *x1, *y1, *x2, *y2, color, 0); 05121 x1 = x2; 05122 y1 = y2; 05123 x2++; 05124 y2++; 05125 } 05126 result |= _aalineColor(dst, *x1, *y1, *vx, *vy, color, 0); 05127 05128 return (result); 05129 } 05130 05145 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05146 { 05147 /* 05148 * Draw 05149 */ 05150 return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 05151 } 05152 05153 /* ---- Filled Polygon */ 05154 05163 int _gfxPrimitivesCompareInt(const void *a, const void *b) 05164 { 05165 return (*(const int *) a) - (*(const int *) b); 05166 } 05167 05173 static int *gfxPrimitivesPolyIntsGlobal = NULL; 05174 05180 static int gfxPrimitivesPolyAllocatedGlobal = 0; 05181 05197 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated) 05198 { 05199 int result; 05200 int i; 05201 int y, xa, xb; 05202 int miny, maxy; 05203 int x1, y1; 05204 int x2, y2; 05205 int ind1, ind2; 05206 int ints; 05207 int *gfxPrimitivesPolyInts = NULL; 05208 int *gfxPrimitivesPolyIntsNew = NULL; 05209 int gfxPrimitivesPolyAllocated = 0; 05210 05211 /* 05212 * Check visibility of clipping rectangle 05213 */ 05214 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05215 return(0); 05216 } 05217 05218 /* 05219 * Vertex array NULL check 05220 */ 05221 if (vx == NULL) { 05222 return (-1); 05223 } 05224 if (vy == NULL) { 05225 return (-1); 05226 } 05227 05228 /* 05229 * Sanity check number of edges 05230 */ 05231 if (n < 3) { 05232 return -1; 05233 } 05234 05235 /* 05236 * Map polygon cache 05237 */ 05238 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05239 /* Use global cache */ 05240 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; 05241 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; 05242 } else { 05243 /* Use local cache */ 05244 gfxPrimitivesPolyInts = *polyInts; 05245 gfxPrimitivesPolyAllocated = *polyAllocated; 05246 } 05247 05248 /* 05249 * Allocate temp array, only grow array 05250 */ 05251 if (!gfxPrimitivesPolyAllocated) { 05252 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); 05253 gfxPrimitivesPolyAllocated = n; 05254 } else { 05255 if (gfxPrimitivesPolyAllocated < n) { 05256 gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); 05257 if (!gfxPrimitivesPolyIntsNew) { 05258 if (!gfxPrimitivesPolyInts) { 05259 free(gfxPrimitivesPolyInts); 05260 gfxPrimitivesPolyInts = NULL; 05261 } 05262 gfxPrimitivesPolyAllocated = 0; 05263 } else { 05264 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew; 05265 gfxPrimitivesPolyAllocated = n; 05266 } 05267 } 05268 } 05269 05270 /* 05271 * Check temp array 05272 */ 05273 if (gfxPrimitivesPolyInts==NULL) { 05274 gfxPrimitivesPolyAllocated = 0; 05275 } 05276 05277 /* 05278 * Update cache variables 05279 */ 05280 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05281 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; 05282 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; 05283 } else { 05284 *polyInts = gfxPrimitivesPolyInts; 05285 *polyAllocated = gfxPrimitivesPolyAllocated; 05286 } 05287 05288 /* 05289 * Check temp array again 05290 */ 05291 if (gfxPrimitivesPolyInts==NULL) { 05292 return(-1); 05293 } 05294 05295 /* 05296 * Determine Y maxima 05297 */ 05298 miny = vy[0]; 05299 maxy = vy[0]; 05300 for (i = 1; (i < n); i++) { 05301 if (vy[i] < miny) { 05302 miny = vy[i]; 05303 } else if (vy[i] > maxy) { 05304 maxy = vy[i]; 05305 } 05306 } 05307 05308 /* 05309 * Draw, scanning y 05310 */ 05311 result = 0; 05312 for (y = miny; (y <= maxy); y++) { 05313 ints = 0; 05314 for (i = 0; (i < n); i++) { 05315 if (!i) { 05316 ind1 = n - 1; 05317 ind2 = 0; 05318 } else { 05319 ind1 = i - 1; 05320 ind2 = i; 05321 } 05322 y1 = vy[ind1]; 05323 y2 = vy[ind2]; 05324 if (y1 < y2) { 05325 x1 = vx[ind1]; 05326 x2 = vx[ind2]; 05327 } else if (y1 > y2) { 05328 y2 = vy[ind1]; 05329 y1 = vy[ind2]; 05330 x2 = vx[ind1]; 05331 x1 = vx[ind2]; 05332 } else { 05333 continue; 05334 } 05335 if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) { 05336 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); 05337 } 05338 } 05339 05340 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt); 05341 05342 for (i = 0; (i < ints); i += 2) { 05343 xa = gfxPrimitivesPolyInts[i] + 1; 05344 xa = (xa >> 16) + ((xa & 32768) >> 15); 05345 xb = gfxPrimitivesPolyInts[i+1] - 1; 05346 xb = (xb >> 16) + ((xb & 32768) >> 15); 05347 result |= hlineColor(dst, xa, xb, y, color); 05348 } 05349 } 05350 05351 return (result); 05352 } 05353 05372 int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated) 05373 { 05374 /* 05375 * Draw 05376 */ 05377 return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated)); 05378 } 05379 05394 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 05395 { 05396 /* 05397 * Draw 05398 */ 05399 return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL)); 05400 } 05401 05416 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05417 { 05418 /* 05419 * Draw 05420 */ 05421 return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL)); 05422 } 05423 05437 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy) 05438 { 05439 Sint16 left, right, top, bottom; 05440 Sint16 w; 05441 Sint16 xtmp; 05442 int result = 0; 05443 int texture_x_walker; 05444 int texture_y_start; 05445 SDL_Rect source_rect,dst_rect; 05446 int pixels_written,write_width; 05447 05448 /* 05449 * Check visibility of clipping rectangle 05450 */ 05451 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05452 return(0); 05453 } 05454 05455 /* 05456 * Swap x1, x2 if required to ensure x1<=x2 05457 */ 05458 if (x1 > x2) { 05459 xtmp = x1; 05460 x1 = x2; 05461 x2 = xtmp; 05462 } 05463 05464 /* 05465 * Get clipping boundary and 05466 * check visibility of hline 05467 */ 05468 left = dst->clip_rect.x; 05469 if (x2<left) { 05470 return(0); 05471 } 05472 right = dst->clip_rect.x + dst->clip_rect.w - 1; 05473 if (x1>right) { 05474 return(0); 05475 } 05476 top = dst->clip_rect.y; 05477 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 05478 if ((y<top) || (y>bottom)) { 05479 return (0); 05480 } 05481 05482 /* 05483 * Clip x 05484 */ 05485 if (x1 < left) { 05486 x1 = left; 05487 } 05488 if (x2 > right) { 05489 x2 = right; 05490 } 05491 05492 /* 05493 * Calculate width to draw 05494 */ 05495 w = x2 - x1 + 1; 05496 05497 /* 05498 * Determine where in the texture we start drawing 05499 */ 05500 texture_x_walker = (x1 - texture_dx) % texture->w; 05501 if (texture_x_walker < 0){ 05502 texture_x_walker = texture->w + texture_x_walker ; 05503 } 05504 05505 texture_y_start = (y + texture_dy) % texture->h; 05506 if (texture_y_start < 0){ 05507 texture_y_start = texture->h + texture_y_start; 05508 } 05509 05510 // setup the source rectangle; we are only drawing one horizontal line 05511 source_rect.y = texture_y_start; 05512 source_rect.x = texture_x_walker; 05513 source_rect.h = 1; 05514 05515 // we will draw to the current y 05516 dst_rect.y = y; 05517 05518 // if there are enough pixels left in the current row of the texture 05519 // draw it all at once 05520 if (w <= texture->w -texture_x_walker){ 05521 source_rect.w = w; 05522 source_rect.x = texture_x_walker; 05523 dst_rect.x= x1; 05524 result = (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0); 05525 } else { // we need to draw multiple times 05526 // draw the first segment 05527 pixels_written = texture->w - texture_x_walker; 05528 source_rect.w = pixels_written; 05529 source_rect.x = texture_x_walker; 05530 dst_rect.x= x1; 05531 result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0); 05532 write_width = texture->w; 05533 05534 // now draw the rest 05535 // set the source x to 0 05536 source_rect.x = 0; 05537 while (pixels_written < w){ 05538 if (write_width >= w - pixels_written) { 05539 write_width = w - pixels_written; 05540 } 05541 source_rect.w = write_width; 05542 dst_rect.x = x1 + pixels_written; 05543 result |= (SDL_BlitSurface (texture,&source_rect , dst, &dst_rect) == 0); 05544 pixels_written += write_width; 05545 } 05546 } 05547 05548 return result; 05549 } 05550 05574 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, 05575 SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated) 05576 { 05577 int result; 05578 int i; 05579 int y, xa, xb; 05580 int minx,maxx,miny, maxy; 05581 int x1, y1; 05582 int x2, y2; 05583 int ind1, ind2; 05584 int ints; 05585 int *gfxPrimitivesPolyInts = NULL; 05586 int gfxPrimitivesPolyAllocated = 0; 05587 05588 /* 05589 * Check visibility of clipping rectangle 05590 */ 05591 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05592 return(0); 05593 } 05594 05595 /* 05596 * Sanity check number of edges 05597 */ 05598 if (n < 3) { 05599 return -1; 05600 } 05601 05602 /* 05603 * Map polygon cache 05604 */ 05605 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05606 /* Use global cache */ 05607 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; 05608 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; 05609 } else { 05610 /* Use local cache */ 05611 gfxPrimitivesPolyInts = *polyInts; 05612 gfxPrimitivesPolyAllocated = *polyAllocated; 05613 } 05614 05615 /* 05616 * Allocate temp array, only grow array 05617 */ 05618 if (!gfxPrimitivesPolyAllocated) { 05619 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); 05620 gfxPrimitivesPolyAllocated = n; 05621 } else { 05622 if (gfxPrimitivesPolyAllocated < n) { 05623 gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); 05624 gfxPrimitivesPolyAllocated = n; 05625 } 05626 } 05627 05628 /* 05629 * Check temp array 05630 */ 05631 if (gfxPrimitivesPolyInts==NULL) { 05632 gfxPrimitivesPolyAllocated = 0; 05633 } 05634 05635 /* 05636 * Update cache variables 05637 */ 05638 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05639 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; 05640 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; 05641 } else { 05642 *polyInts = gfxPrimitivesPolyInts; 05643 *polyAllocated = gfxPrimitivesPolyAllocated; 05644 } 05645 05646 /* 05647 * Check temp array again 05648 */ 05649 if (gfxPrimitivesPolyInts==NULL) { 05650 return(-1); 05651 } 05652 05653 /* 05654 * Determine X,Y minima,maxima 05655 */ 05656 miny = vy[0]; 05657 maxy = vy[0]; 05658 minx = vx[0]; 05659 maxx = vx[0]; 05660 for (i = 1; (i < n); i++) { 05661 if (vy[i] < miny) { 05662 miny = vy[i]; 05663 } else if (vy[i] > maxy) { 05664 maxy = vy[i]; 05665 } 05666 if (vx[i] < minx) { 05667 minx = vx[i]; 05668 } else if (vx[i] > maxx) { 05669 maxx = vx[i]; 05670 } 05671 } 05672 if (maxx <0 || minx > dst->w){ 05673 return -1; 05674 } 05675 if (maxy <0 || miny > dst->h){ 05676 return -1; 05677 } 05678 05679 /* 05680 * Draw, scanning y 05681 */ 05682 result = 0; 05683 for (y = miny; (y <= maxy); y++) { 05684 ints = 0; 05685 for (i = 0; (i < n); i++) { 05686 if (!i) { 05687 ind1 = n - 1; 05688 ind2 = 0; 05689 } else { 05690 ind1 = i - 1; 05691 ind2 = i; 05692 } 05693 y1 = vy[ind1]; 05694 y2 = vy[ind2]; 05695 if (y1 < y2) { 05696 x1 = vx[ind1]; 05697 x2 = vx[ind2]; 05698 } else if (y1 > y2) { 05699 y2 = vy[ind1]; 05700 y1 = vy[ind2]; 05701 x2 = vx[ind1]; 05702 x1 = vx[ind2]; 05703 } else { 05704 continue; 05705 } 05706 if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) { 05707 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1); 05708 } 05709 } 05710 05711 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt); 05712 05713 for (i = 0; (i < ints); i += 2) { 05714 xa = gfxPrimitivesPolyInts[i] + 1; 05715 xa = (xa >> 16) + ((xa & 32768) >> 15); 05716 xb = gfxPrimitivesPolyInts[i+1] - 1; 05717 xb = (xb >> 16) + ((xb & 32768) >> 15); 05718 result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy); 05719 } 05720 } 05721 05722 return (result); 05723 } 05724 05741 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy) 05742 { 05743 /* 05744 * Draw 05745 */ 05746 return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL)); 05747 } 05748 05749 05750 /* ---- Character */ 05751 05755 static SDL_Surface *gfxPrimitivesFont[256]; 05756 05760 static Uint32 gfxPrimitivesFontColor[256]; 05761 05765 static const unsigned char *currentFontdata = gfxPrimitivesFontdata; 05766 05770 static Uint32 charWidth = 8; 05771 05775 static Uint32 charHeight = 8; 05776 05780 static Uint32 charWidthLocal = 8; 05781 05785 static Uint32 charHeightLocal = 8; 05786 05790 static Uint32 charPitch = 1; 05791 05795 static Uint32 charRotation = 0; 05796 05800 static Uint32 charSize = 8; 05801 05815 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch) 05816 { 05817 int i; 05818 05819 if ((fontdata) && (cw) && (ch)) { 05820 currentFontdata = fontdata; 05821 charWidth = cw; 05822 charHeight = ch; 05823 } else { 05824 currentFontdata = gfxPrimitivesFontdata; 05825 charWidth = 8; 05826 charHeight = 8; 05827 } 05828 05829 charPitch = (charWidth+7)/8; 05830 charSize = charPitch * charHeight; 05831 05832 /* Maybe flip width/height for rendering */ 05833 if ((charRotation==1) || (charRotation==3)) 05834 { 05835 charWidthLocal = charHeight; 05836 charHeightLocal = charWidth; 05837 } 05838 else 05839 { 05840 charWidthLocal = charWidth; 05841 charHeightLocal = charHeight; 05842 } 05843 05844 /* Clear character cache */ 05845 for (i = 0; i < 256; i++) { 05846 if (gfxPrimitivesFont[i]) { 05847 SDL_FreeSurface(gfxPrimitivesFont[i]); 05848 gfxPrimitivesFont[i] = NULL; 05849 } 05850 } 05851 } 05852 05861 void gfxPrimitivesSetFontRotation(Uint32 rotation) 05862 { 05863 int i; 05864 05865 rotation = rotation & 3; 05866 if (charRotation != rotation) 05867 { 05868 /* Store rotation */ 05869 charRotation = rotation; 05870 05871 /* Maybe flip width/height for rendering */ 05872 if ((charRotation==1) || (charRotation==3)) 05873 { 05874 charWidthLocal = charHeight; 05875 charHeightLocal = charWidth; 05876 } 05877 else 05878 { 05879 charWidthLocal = charWidth; 05880 charHeightLocal = charHeight; 05881 } 05882 05883 /* Clear character cache */ 05884 for (i = 0; i < 256; i++) { 05885 if (gfxPrimitivesFont[i]) { 05886 SDL_FreeSurface(gfxPrimitivesFont[i]); 05887 gfxPrimitivesFont[i] = NULL; 05888 } 05889 } 05890 } 05891 } 05892 05908 int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color) 05909 { 05910 Sint16 left, right, top, bottom; 05911 Sint16 x1, y1, x2, y2; 05912 SDL_Rect srect; 05913 SDL_Rect drect; 05914 int result; 05915 Uint32 ix, iy; 05916 const unsigned char *charpos; 05917 Uint8 *curpos; 05918 int forced_redraw; 05919 Uint8 patt, mask; 05920 Uint8 *linepos; 05921 Uint32 pitch; 05922 SDL_Surface *rotatedCharacter; 05923 Uint32 ci; 05924 05925 /* 05926 * Check visibility of clipping rectangle 05927 */ 05928 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05929 return(0); 05930 } 05931 05932 /* 05933 * Get text and clipping boundary and 05934 * test if bounding box of character is visible 05935 */ 05936 05937 left = dst->clip_rect.x; 05938 x2 = x + charWidthLocal; 05939 if (x2<left) { 05940 return(0); 05941 } 05942 right = dst->clip_rect.x + dst->clip_rect.w - 1; 05943 x1 = x; 05944 if (x1>right) { 05945 return(0); 05946 } 05947 top = dst->clip_rect.y; 05948 y2 = y + charHeightLocal; 05949 if (y2<top) { 05950 return(0); 05951 } 05952 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 05953 y1 = y; 05954 if (y1>bottom) { 05955 return(0); 05956 } 05957 05958 /* 05959 * Setup source rectangle 05960 */ 05961 srect.x = 0; 05962 srect.y = 0; 05963 srect.w = charWidthLocal; 05964 srect.h = charHeightLocal; 05965 05966 /* 05967 * Setup destination rectangle 05968 */ 05969 drect.x = x; 05970 drect.y = y; 05971 drect.w = charWidthLocal; 05972 drect.h = charHeightLocal; 05973 05974 /* Character index in cache */ 05975 ci = (unsigned char) c; 05976 05977 /* 05978 * Create new charWidth x charHeight bitmap surface if not already present. 05979 * Might get rotated later. 05980 */ 05981 if (gfxPrimitivesFont[ci] == NULL) { 05982 gfxPrimitivesFont[ci] = 05983 SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 05984 charWidth, charHeight, 32, 05985 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF); 05986 /* 05987 * Check pointer 05988 */ 05989 if (gfxPrimitivesFont[ci] == NULL) { 05990 return (-1); 05991 } 05992 /* 05993 * Definitely redraw 05994 */ 05995 forced_redraw = 1; 05996 } else { 05997 forced_redraw = 0; 05998 } 05999 06000 /* 06001 * Check if color has changed 06002 */ 06003 if ((gfxPrimitivesFontColor[ci] != color) || (forced_redraw)) { 06004 /* 06005 * Redraw character 06006 */ 06007 SDL_SetAlpha(gfxPrimitivesFont[ci], SDL_SRCALPHA, 255); 06008 gfxPrimitivesFontColor[ci] = color; 06009 06010 /* Lock font-surface */ 06011 if (SDL_LockSurface(gfxPrimitivesFont[ci]) != 0) 06012 return (-1); 06013 06014 /* 06015 * Variable setup 06016 */ 06017 charpos = currentFontdata + ci * charSize; 06018 linepos = (Uint8 *) gfxPrimitivesFont[ci]->pixels; 06019 pitch = gfxPrimitivesFont[ci]->pitch; 06020 06021 /* 06022 * Drawing loop 06023 */ 06024 patt = 0; 06025 for (iy = 0; iy < charHeight; iy++) { 06026 mask = 0x00; 06027 curpos = linepos; 06028 for (ix = 0; ix < charWidth; ix++) { 06029 if (!(mask >>= 1)) { 06030 patt = *charpos++; 06031 mask = 0x80; 06032 } 06033 06034 if (patt & mask) 06035 *(Uint32 *)curpos = color; 06036 else 06037 *(Uint32 *)curpos = 0; 06038 curpos += 4; 06039 } 06040 linepos += pitch; 06041 } 06042 06043 /* Unlock font-surface */ 06044 SDL_UnlockSurface(gfxPrimitivesFont[ci]); 06045 06046 /* Maybe rotate and replace cached image */ 06047 if (charRotation>0) 06048 { 06049 rotatedCharacter = rotateSurface90Degrees(gfxPrimitivesFont[ci], charRotation); 06050 SDL_FreeSurface(gfxPrimitivesFont[ci]); 06051 gfxPrimitivesFont[ci] = rotatedCharacter; 06052 } 06053 } 06054 06055 /* 06056 * Draw bitmap onto destination surface 06057 */ 06058 result = SDL_BlitSurface(gfxPrimitivesFont[ci], &srect, dst, &drect); 06059 06060 return (result); 06061 } 06062 06077 int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 06078 { 06079 /* 06080 * Draw 06081 */ 06082 return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 06083 } 06084 06099 int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color) 06100 { 06101 int result = 0; 06102 Sint16 curx = x; 06103 Sint16 cury = y; 06104 const char *curchar = s; 06105 06106 while (*curchar && !result) { 06107 result |= characterColor(dst, curx, cury, *curchar, color); 06108 switch (charRotation) 06109 { 06110 case 0: 06111 curx += charWidthLocal; 06112 break; 06113 case 2: 06114 curx -= charWidthLocal; 06115 break; 06116 case 1: 06117 cury += charHeightLocal; 06118 break; 06119 case 3: 06120 cury -= charHeightLocal; 06121 break; 06122 } 06123 curchar++; 06124 } 06125 06126 return (result); 06127 } 06128 06143 int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 06144 { 06145 /* 06146 * Draw 06147 */ 06148 return (stringColor(dst, x, y, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 06149 } 06150 06151 /* ---- Bezier curve */ 06152 06162 double _evaluateBezier (double *data, int ndata, double t) 06163 { 06164 double mu, result; 06165 int n,k,kn,nn,nkn; 06166 double blend,muk,munk; 06167 06168 /* Sanity check bounds */ 06169 if (t<0.0) { 06170 return(data[0]); 06171 } 06172 if (t>=(double)ndata) { 06173 return(data[ndata-1]); 06174 } 06175 06176 /* Adjust t to the range 0.0 to 1.0 */ 06177 mu=t/(double)ndata; 06178 06179 /* Calculate interpolate */ 06180 n=ndata-1; 06181 result=0.0; 06182 muk = 1; 06183 munk = pow(1-mu,(double)n); 06184 for (k=0;k<=n;k++) { 06185 nn = n; 06186 kn = k; 06187 nkn = n - k; 06188 blend = muk * munk; 06189 muk *= mu; 06190 munk /= (1-mu); 06191 while (nn >= 1) { 06192 blend *= nn; 06193 nn--; 06194 if (kn > 1) { 06195 blend /= (double)kn; 06196 kn--; 06197 } 06198 if (nkn > 1) { 06199 blend /= (double)nkn; 06200 nkn--; 06201 } 06202 } 06203 result += data[k] * blend; 06204 } 06205 06206 return (result); 06207 } 06208 06221 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color) 06222 { 06223 int result; 06224 int i; 06225 double *x, *y, t, stepsize; 06226 Sint16 x1, y1, x2, y2; 06227 06228 /* 06229 * Sanity check 06230 */ 06231 if (n < 3) { 06232 return (-1); 06233 } 06234 if (s < 2) { 06235 return (-1); 06236 } 06237 06238 /* 06239 * Variable setup 06240 */ 06241 stepsize=(double)1.0/(double)s; 06242 06243 /* Transfer vertices into float arrays */ 06244 if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) { 06245 return(-1); 06246 } 06247 if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) { 06248 free(x); 06249 return(-1); 06250 } 06251 for (i=0; i<n; i++) { 06252 x[i]=(double)vx[i]; 06253 y[i]=(double)vy[i]; 06254 } 06255 x[n]=(double)vx[0]; 06256 y[n]=(double)vy[0]; 06257 06258 /* 06259 * Draw 06260 */ 06261 result = 0; 06262 t=0.0; 06263 x1=(Sint16)lrint(_evaluateBezier(x,n+1,t)); 06264 y1=(Sint16)lrint(_evaluateBezier(y,n+1,t)); 06265 for (i = 0; i <= (n*s); i++) { 06266 t += stepsize; 06267 x2=(Sint16)_evaluateBezier(x,n,t); 06268 y2=(Sint16)_evaluateBezier(y,n,t); 06269 result |= lineColor(dst, x1, y1, x2, y2, color); 06270 x1 = x2; 06271 y1 = y2; 06272 } 06273 06274 /* Clean up temporary array */ 06275 free(x); 06276 free(y); 06277 06278 return (result); 06279 } 06280 06296 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 06297 { 06298 /* 06299 * Draw 06300 */ 06301 return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 06302 } 06303 06304 06323 int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2) 06324 { 06325 int temp; 06326 06327 if (b==NULL) { 06328 return(-1); 06329 } 06330 06331 b->x = x1; 06332 b->y = y1; 06333 06334 /* dx = abs(x2-x1), s1 = sign(x2-x1) */ 06335 if ((b->dx = x2 - x1) != 0) { 06336 if (b->dx < 0) { 06337 b->dx = -b->dx; 06338 b->s1 = -1; 06339 } else { 06340 b->s1 = 1; 06341 } 06342 } else { 06343 b->s1 = 0; 06344 } 06345 06346 /* dy = abs(y2-y1), s2 = sign(y2-y1) */ 06347 if ((b->dy = y2 - y1) != 0) { 06348 if (b->dy < 0) { 06349 b->dy = -b->dy; 06350 b->s2 = -1; 06351 } else { 06352 b->s2 = 1; 06353 } 06354 } else { 06355 b->s2 = 0; 06356 } 06357 06358 if (b->dy > b->dx) { 06359 temp = b->dx; 06360 b->dx = b->dy; 06361 b->dy = temp; 06362 b->swapdir = 1; 06363 } else { 06364 b->swapdir = 0; 06365 } 06366 06367 b->count = (b->dx<0) ? 0 : (unsigned int)b->dx; 06368 b->dy <<= 1; 06369 b->error = b->dy - b->dx; 06370 b->dx <<= 1; 06371 06372 return(0); 06373 } 06374 06375 06385 int _bresenhamIterate(SDL_gfxBresenhamIterator *b) 06386 { 06387 if (b==NULL) { 06388 return (-1); 06389 } 06390 06391 /* last point check */ 06392 if (b->count==0) { 06393 return (2); 06394 } 06395 06396 while (b->error >= 0) { 06397 if (b->swapdir) { 06398 b->x += b->s1; 06399 } else { 06400 b->y += b->s2; 06401 } 06402 06403 b->error -= b->dx; 06404 } 06405 06406 if (b->swapdir) { 06407 b->y += b->s2; 06408 } else { 06409 b->x += b->s1; 06410 } 06411 06412 b->error += b->dy; 06413 b->count--; 06414 06415 /* count==0 indicates "end-of-line" */ 06416 return ((b->count) ? 0 : 1); 06417 } 06418 06419 06428 void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1) 06429 { 06430 int p; 06431 d1 = -d1; 06432 06433 /* 06434 * Lock the surface 06435 */ 06436 if (SDL_MUSTLOCK(m->dst)) { 06437 SDL_LockSurface(m->dst); 06438 } 06439 06440 for (p = 0; p <= m->u; p++) { 06441 06442 pixelColorNolock(m->dst, x, y, m->color); 06443 06444 if (d1 <= m->kt) { 06445 if (m->oct2 == 0) { 06446 x++; 06447 } else { 06448 if (m->quad4 == 0) { 06449 y++; 06450 } else { 06451 y--; 06452 } 06453 } 06454 d1 += m->kv; 06455 } else { 06456 x++; 06457 if (m->quad4 == 0) { 06458 y++; 06459 } else { 06460 y--; 06461 } 06462 d1 += m->kd; 06463 } 06464 } 06465 06466 /* Unlock surface */ 06467 if (SDL_MUSTLOCK(m->dst)) { 06468 SDL_UnlockSurface(m->dst); 06469 } 06470 06471 m->tempx = x; 06472 m->tempy = y; 06473 } 06474 06490 void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter, 06491 Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by, 06492 Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y) 06493 { 06494 int atemp1, atemp2; 06495 int ftmp1, ftmp2; 06496 Uint16 m1x, m1y, m2x, m2y; 06497 Uint16 fix, fiy, lax, lay, curx, cury; 06498 Uint16 px[4], py[4]; 06499 SDL_gfxBresenhamIterator b; 06500 06501 if (miter > 1) { 06502 if (m->first1x != -32768) { 06503 fix = (m->first1x + m->first2x) / 2; 06504 fiy = (m->first1y + m->first2y) / 2; 06505 lax = (m->last1x + m->last2x) / 2; 06506 lay = (m->last1y + m->last2y) / 2; 06507 curx = (ml1x + ml2x) / 2; 06508 cury = (ml1y + ml2y) / 2; 06509 06510 atemp1 = (fix - curx); 06511 atemp2 = (fiy - cury); 06512 ftmp1 = atemp1 * atemp1 + atemp2 * atemp2; 06513 atemp1 = (lax - curx); 06514 atemp2 = (lay - cury); 06515 ftmp2 = atemp1 * atemp1 + atemp2 * atemp2; 06516 06517 if (ftmp1 <= ftmp2) { 06518 m1x = m->first1x; 06519 m1y = m->first1y; 06520 m2x = m->first2x; 06521 m2y = m->first2y; 06522 } else { 06523 m1x = m->last1x; 06524 m1y = m->last1y; 06525 m2x = m->last2x; 06526 m2y = m->last2y; 06527 } 06528 06529 atemp1 = (m2x - ml2x); 06530 atemp2 = (m2y - ml2y); 06531 ftmp1 = atemp1 * atemp1 + atemp2 * atemp2; 06532 atemp1 = (m2x - ml2bx); 06533 atemp2 = (m2y - ml2by); 06534 ftmp2 = atemp1 * atemp1 + atemp2 * atemp2; 06535 06536 if (ftmp2 >= ftmp1) { 06537 ftmp1 = ml2bx; 06538 ftmp2 = ml2by; 06539 ml2bx = ml2x; 06540 ml2by = ml2y; 06541 ml2x = ftmp1; 06542 ml2y = ftmp2; 06543 ftmp1 = ml1bx; 06544 ftmp2 = ml1by; 06545 ml1bx = ml1x; 06546 ml1by = ml1y; 06547 ml1x = ftmp1; 06548 ml1y = ftmp2; 06549 } 06550 06551 /* 06552 * Lock the surface 06553 */ 06554 if (SDL_MUSTLOCK(m->dst)) { 06555 SDL_LockSurface(m->dst); 06556 } 06557 06558 _bresenhamInitialize(&b, m2x, m2y, m1x, m1y); 06559 do { 06560 pixelColorNolock(m->dst, b.x, b.y, m->color); 06561 } while (_bresenhamIterate(&b)==0); 06562 06563 _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by); 06564 do { 06565 pixelColorNolock(m->dst, b.x, b.y, m->color); 06566 } while (_bresenhamIterate(&b)==0); 06567 06568 _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by); 06569 do { 06570 pixelColorNolock(m->dst, b.x, b.y, m->color); 06571 } while (_bresenhamIterate(&b)==0); 06572 06573 _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y); 06574 do { 06575 pixelColorNolock(m->dst, b.x, b.y, m->color); 06576 } while (_bresenhamIterate(&b)==0); 06577 06578 /* Unlock surface */ 06579 if (SDL_MUSTLOCK(m->dst)) { 06580 SDL_UnlockSurface(m->dst); 06581 } 06582 06583 px[0] = m1x; 06584 px[1] = m2x; 06585 px[2] = ml1bx; 06586 px[3] = ml2bx; 06587 py[0] = m1y; 06588 py[1] = m2y; 06589 py[2] = ml1by; 06590 py[3] = ml2by; 06591 polygonColor(m->dst, px, py, 4, m->color); 06592 } 06593 } 06594 06595 m->last1x = ml1x; 06596 m->last1y = ml1y; 06597 m->last2x = ml2x; 06598 m->last2y = ml2y; 06599 m->first1x = ml1bx; 06600 m->first1y = ml1by; 06601 m->first2x = ml2bx; 06602 m->first2y = ml2by; 06603 } 06604 06605 06606 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y)) 06607 06622 void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter) 06623 { 06624 float offset = (float)width / 2.f; 06625 06626 Sint16 temp; 06627 Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by; 06628 06629 int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */ 06630 06631 int q; /* pel counter,q=perpendicular to line */ 06632 int tmp; 06633 06634 int dd; /* distance along line */ 06635 int tk; /* thickness threshold */ 06636 double ang; /* angle for initial point calculation */ 06637 double sang, cang; 06638 06639 /* Initialisation */ 06640 m->u = x2 - x1; /* delta x */ 06641 m->v = y2 - y1; /* delta y */ 06642 06643 if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */ 06644 temp = x1; 06645 x1 = x2; 06646 x2 = temp; 06647 temp = y1; 06648 y1 = y2; 06649 y2 = temp; 06650 m->u *= -1; 06651 m->v *= -1; 06652 } 06653 06654 if (m->v < 0) { /* swap to 1st quadrant and flag */ 06655 m->v *= -1; 06656 m->quad4 = 1; 06657 } else { 06658 m->quad4 = 0; 06659 } 06660 06661 if (m->v > m->u) { /* swap things if in 2 octant */ 06662 tmp = m->u; 06663 m->u = m->v; 06664 m->v = tmp; 06665 m->oct2 = 1; 06666 } else { 06667 m->oct2 = 0; 06668 } 06669 06670 m->ku = m->u + m->u; /* change in l for square shift */ 06671 m->kv = m->v + m->v; /* change in d for square shift */ 06672 m->kd = m->kv - m->ku; /* change in d for diagonal shift */ 06673 m->kt = m->u - m->kv; /* diag/square decision threshold */ 06674 06675 d0 = 0; 06676 d1 = 0; 06677 dd = 0; 06678 06679 ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */ 06680 sang = sin(ang); 06681 cang = cos(ang); 06682 06683 if (m->oct2 == 0) { 06684 ptx = x1 + (Sint16)lrint(offset * sang); 06685 if (m->quad4 == 0) { 06686 pty = y1 - (Sint16)lrint(offset * cang); 06687 } else { 06688 pty = y1 + (Sint16)lrint(offset * cang); 06689 } 06690 } else { 06691 ptx = x1 - (Sint16)lrint(offset * cang); 06692 if (m->quad4 == 0) { 06693 pty = y1 + (Sint16)lrint(offset * sang); 06694 } else { 06695 pty = y1 - (Sint16)lrint(offset * sang); 06696 } 06697 } 06698 06699 /* used here for constant thickness line */ 06700 tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v)); 06701 06702 if (miter == 0) { 06703 m->first1x = -32768; 06704 m->first1y = -32768; 06705 m->first2x = -32768; 06706 m->first2y = -32768; 06707 m->last1x = -32768; 06708 m->last1y = -32768; 06709 m->last2x = -32768; 06710 m->last2y = -32768; 06711 } 06712 ptxx = ptx; 06713 ptxy = pty; 06714 06715 for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */ 06716 06717 _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */ 06718 if (q == 0) { 06719 ml1x = ptx; 06720 ml1y = pty; 06721 ml1bx = m->tempx; 06722 ml1by = m->tempy; 06723 } else { 06724 ml2x = ptx; 06725 ml2y = pty; 06726 ml2bx = m->tempx; 06727 ml2by = m->tempy; 06728 } 06729 if (d0 < m->kt) { /* square move */ 06730 if (m->oct2 == 0) { 06731 if (m->quad4 == 0) { 06732 pty++; 06733 } else { 06734 pty--; 06735 } 06736 } else { 06737 ptx++; 06738 } 06739 } else { /* diagonal move */ 06740 dd += m->kv; 06741 d0 -= m->ku; 06742 if (d1 < m->kt) { /* normal diagonal */ 06743 if (m->oct2 == 0) { 06744 ptx--; 06745 if (m->quad4 == 0) { 06746 pty++; 06747 } else { 06748 pty--; 06749 } 06750 } else { 06751 ptx++; 06752 if (m->quad4 == 0) { 06753 pty--; 06754 } else { 06755 pty++; 06756 } 06757 } 06758 d1 += m->kv; 06759 } else { /* double square move, extra parallel line */ 06760 if (m->oct2 == 0) { 06761 ptx--; 06762 } else { 06763 if (m->quad4 == 0) { 06764 pty--; 06765 } else { 06766 pty++; 06767 } 06768 } 06769 d1 += m->kd; 06770 if (dd > tk) { 06771 _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y); 06772 return; /* breakout on the extra line */ 06773 } 06774 _murphyParaline(m, ptx, pty, d1); 06775 if (m->oct2 == 0) { 06776 if (m->quad4 == 0) { 06777 pty++; 06778 } else { 06779 06780 pty--; 06781 } 06782 } else { 06783 ptx++; 06784 } 06785 } 06786 } 06787 dd += m->ku; 06788 d0 += m->kv; 06789 } 06790 06791 _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y); 06792 } 06793 06794 06808 int thickLineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color) 06809 { 06810 int wh; 06811 SDL_gfxMurphyIterator m; 06812 06813 if (dst == NULL) return -1; 06814 if (width < 1) return -1; 06815 06816 /* Special case: thick "point" */ 06817 if ((x1 == x2) && (y1 == y2)) { 06818 wh = width / 2; 06819 return boxColor(dst, x1 - wh, y1 - wh, x2 + width, y2 + width, color); 06820 } 06821 06822 m.dst = dst; 06823 m.color = color; 06824 06825 _murphyWideline(&m, x1, y1, x2, y2, width, 0); 06826 _murphyWideline(&m, x1, y1, x2, y2, width, 1); 06827 06828 return(0); 06829 } 06830 06847 int thickLineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 06848 { 06849 return (thickLineColor(dst, x1, y1, x2, y2, width, 06850 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 06851 }