|
Atrinik Client 2.5
|
00001 /* 00002 00003 SDL_gfxPrimitives - Graphics primitives for SDL surfaces 00004 00005 LGPL (c) A. Schiffler 00006 00007 */ 00008 00009 #include <global.h> 00010 00011 /* -===================- */ 00012 00013 #define DEFAULT_ALPHA_PIXEL_ROUTINE 00014 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00015 00016 /* ---- Structures */ 00017 00021 typedef struct { 00022 Sint16 x, y; 00023 int dx, dy, s1, s2, swapdir, error; 00024 Uint32 count; 00025 } SDL_gfxBresenhamIterator; 00026 00030 typedef struct { 00031 Uint32 color; 00032 SDL_Surface *dst; 00033 int u, v; /* delta x , delta y */ 00034 int ku, kt, kv, kd; /* loop constants */ 00035 int oct2; 00036 int quad4; 00037 Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy; 00038 } SDL_gfxMurphyIterator; 00039 00040 /* ----- Defines for pixel clipping tests */ 00041 00042 00061 static int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2) 00062 { 00063 int temp; 00064 00065 if (b==NULL) { 00066 return(-1); 00067 } 00068 00069 b->x = x; 00070 b->y = y; 00071 00072 /* dx = abs(x2-x1), s1 = sign(x2-x1) */ 00073 if ((b->dx = x2 - x) != 0) { 00074 if (b->dx < 0) { 00075 b->dx = -b->dx; 00076 b->s1 = -1; 00077 } else { 00078 b->s1 = 1; 00079 } 00080 } else { 00081 b->s1 = 0; 00082 } 00083 00084 /* dy = abs(y2-y1), s2 = sign(y2-y1) */ 00085 if ((b->dy = y2 - y) != 0) { 00086 if (b->dy < 0) { 00087 b->dy = -b->dy; 00088 b->s2 = -1; 00089 } else { 00090 b->s2 = 1; 00091 } 00092 } else { 00093 b->s2 = 0; 00094 } 00095 00096 if (b->dy > b->dx) { 00097 temp = b->dx; 00098 b->dx = b->dy; 00099 b->dy = temp; 00100 b->swapdir = 1; 00101 } else { 00102 b->swapdir = 0; 00103 } 00104 00105 b->count = b->dx; 00106 b->dy <<= 1; 00107 b->error = b->dy - b->dx; 00108 b->dx <<= 1; 00109 00110 return(0); 00111 } 00112 00113 00123 static int _bresenhamIterate(SDL_gfxBresenhamIterator *b) 00124 { 00125 if (b==NULL) { 00126 return (-1); 00127 } 00128 00129 /* last point check */ 00130 if (b->count <= 0) { 00131 return (2); 00132 } 00133 00134 while (b->error >= 0) { 00135 if (b->swapdir) { 00136 b->x += b->s1; 00137 } else { 00138 b->y += b->s2; 00139 } 00140 00141 b->error -= b->dx; 00142 } 00143 00144 if (b->swapdir) { 00145 b->y += b->s2; 00146 } else { 00147 b->x += b->s1; 00148 } 00149 00150 b->error += b->dy; 00151 b->count--; 00152 00153 /* count==0 indicates "end-of-line" */ 00154 return ((b->count) ? 0 : 1); 00155 } 00156 00157 00167 #define clip_xmin(surface) surface->clip_rect.x 00168 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1 00169 #define clip_ymin(surface) surface->clip_rect.y 00170 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1 00171 00182 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00183 { 00184 int bpp; 00185 Uint8 *p; 00186 00187 /* 00188 * Honor clipping setup at pixel level 00189 */ 00190 if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) { 00191 00192 /* 00193 * Get destination format 00194 */ 00195 bpp = dst->format->BytesPerPixel; 00196 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00197 switch (bpp) { 00198 case 1: 00199 *p = color; 00200 break; 00201 case 2: 00202 *(Uint16 *) p = color; 00203 break; 00204 case 3: 00205 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 00206 p[0] = (color >> 16) & 0xff; 00207 p[1] = (color >> 8) & 0xff; 00208 p[2] = color & 0xff; 00209 } else { 00210 p[0] = color & 0xff; 00211 p[1] = (color >> 8) & 0xff; 00212 p[2] = (color >> 16) & 0xff; 00213 } 00214 break; 00215 case 4: 00216 *(Uint32 *) p = color; 00217 break; 00218 } /* switch */ 00219 00220 00221 } 00222 00223 return (0); 00224 } 00225 00239 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00240 { 00241 int bpp; 00242 Uint8 *p; 00243 00244 /* 00245 * Get destination format 00246 */ 00247 bpp = dst->format->BytesPerPixel; 00248 p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; 00249 switch (bpp) { 00250 case 1: 00251 *p = color; 00252 break; 00253 case 2: 00254 *(Uint16 *) p = color; 00255 break; 00256 case 3: 00257 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 00258 p[0] = (color >> 16) & 0xff; 00259 p[1] = (color >> 8) & 0xff; 00260 p[2] = color & 0xff; 00261 } else { 00262 p[0] = color & 0xff; 00263 p[1] = (color >> 8) & 0xff; 00264 p[2] = (color >> 16) & 0xff; 00265 } 00266 break; 00267 case 4: 00268 *(Uint32 *) p = color; 00269 break; 00270 } /* switch */ 00271 00272 return (0); 00273 } 00274 00285 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00286 { 00287 int result; 00288 00289 /* 00290 * Lock the surface 00291 */ 00292 if (SDL_MUSTLOCK(dst)) { 00293 if (SDL_LockSurface(dst) < 0) { 00294 return (-1); 00295 } 00296 } 00297 00298 result = fastPixelColorNolock(dst, x, y, color); 00299 00300 /* 00301 * Unlock surface 00302 */ 00303 if (SDL_MUSTLOCK(dst)) { 00304 SDL_UnlockSurface(dst); 00305 } 00306 00307 return (result); 00308 } 00309 00323 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 00324 { 00325 Uint32 color; 00326 00327 /* 00328 * Setup color 00329 */ 00330 color = SDL_MapRGBA(dst->format, r, g, b, a); 00331 00332 /* 00333 * Draw 00334 */ 00335 return (fastPixelColor(dst, x, y, color)); 00336 } 00337 00351 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 00352 { 00353 Uint32 color; 00354 00355 /* 00356 * Setup color 00357 */ 00358 color = SDL_MapRGBA(dst->format, r, g, b, a); 00359 00360 /* 00361 * Draw 00362 */ 00363 return (fastPixelColorNolock(dst, x, y, color)); 00364 } 00365 00381 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha) 00382 { 00383 SDL_PixelFormat *format; 00384 Uint32 Rmask, Gmask, Bmask, Amask; 00385 Uint32 Rshift, Gshift, Bshift, Ashift; 00386 Uint32 R, G, B, A; 00387 00388 if (dst == NULL) 00389 { 00390 return (-1); 00391 } 00392 00393 if (x >= clip_xmin(dst) && x <= clip_xmax(dst) && 00394 y >= clip_ymin(dst) && y <= clip_ymax(dst)) 00395 { 00396 00397 format = dst->format; 00398 00399 switch (format->BytesPerPixel) { 00400 case 1: 00401 { /* Assuming 8-bpp */ 00402 if (alpha == 255) { 00403 *((Uint8 *) dst->pixels + y * dst->pitch + x) = color; 00404 } else { 00405 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x; 00406 SDL_Palette *palette = format->palette; 00407 SDL_Color *colors = palette->colors; 00408 SDL_Color dColor = colors[*pixel]; 00409 SDL_Color sColor = colors[color]; 00410 Uint8 dR = dColor.r; 00411 Uint8 dG = dColor.g; 00412 Uint8 dB = dColor.b; 00413 Uint8 sR = sColor.r; 00414 Uint8 sG = sColor.g; 00415 Uint8 sB = sColor.b; 00416 00417 dR = dR + ((sR - dR) * alpha >> 8); 00418 dG = dG + ((sG - dG) * alpha >> 8); 00419 dB = dB + ((sB - dB) * alpha >> 8); 00420 00421 *pixel = SDL_MapRGB(format, dR, dG, dB); 00422 } 00423 } 00424 break; 00425 00426 case 2: 00427 { /* Probably 15-bpp or 16-bpp */ 00428 if (alpha == 255) { 00429 *((Uint16 *) dst->pixels + y * dst->pitch / 2 + x) = color; 00430 } else { 00431 Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x; 00432 Uint32 dc = *pixel; 00433 00434 Rmask = format->Rmask; 00435 Gmask = format->Gmask; 00436 Bmask = format->Bmask; 00437 Amask = format->Amask; 00438 R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask; 00439 G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask; 00440 B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask; 00441 A = 255; 00442 if (Amask) { 00443 A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask; 00444 } 00445 *pixel = R | G | B | A; 00446 } 00447 } 00448 break; 00449 00450 case 3: 00451 { /* Slow 24-bpp mode, usually not used */ 00452 Uint8 Rshift8, Gshift8, Bshift8, Ashift8; 00453 Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3; 00454 00455 Rshift = format->Rshift; 00456 Gshift = format->Gshift; 00457 Bshift = format->Bshift; 00458 Ashift = format->Ashift; 00459 00460 Rshift8 = Rshift / 8; 00461 Gshift8 = Gshift / 8; 00462 Bshift8 = Bshift / 8; 00463 Ashift8 = Ashift / 8; 00464 00465 if (alpha == 255) { 00466 *(pixel + Rshift8) = color >> Rshift; 00467 *(pixel + Gshift8) = color >> Gshift; 00468 *(pixel + Bshift8) = color >> Bshift; 00469 *(pixel + Ashift8) = color >> Ashift; 00470 } else { 00471 Uint8 dR, dG, dB, dA = 0; 00472 Uint8 sR, sG, sB, sA = 0; 00473 00474 dR = *((pixel) + Rshift8); 00475 dG = *((pixel) + Gshift8); 00476 dB = *((pixel) + Bshift8); 00477 dA = *((pixel) + Ashift8); 00478 00479 sR = (color >> Rshift) & 0xff; 00480 sG = (color >> Gshift) & 0xff; 00481 sB = (color >> Bshift) & 0xff; 00482 sA = (color >> Ashift) & 0xff; 00483 00484 dR = dR + ((sR - dR) * alpha >> 8); 00485 dG = dG + ((sG - dG) * alpha >> 8); 00486 dB = dB + ((sB - dB) * alpha >> 8); 00487 dA = dA + ((sA - dA) * alpha >> 8); 00488 00489 *((pixel) + Rshift8) = dR; 00490 *((pixel) + Gshift8) = dG; 00491 *((pixel) + Bshift8) = dB; 00492 *((pixel) + Ashift8) = dA; 00493 } 00494 } 00495 break; 00496 00497 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE 00498 00499 case 4: 00500 { /* Probably :-) 32-bpp */ 00501 if (alpha == 255) { 00502 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color; 00503 } else { 00504 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; 00505 Uint32 dc = *pixel; 00506 00507 Rmask = format->Rmask; 00508 Gmask = format->Gmask; 00509 Bmask = format->Bmask; 00510 Amask = format->Amask; 00511 00512 Rshift = format->Rshift; 00513 Gshift = format->Gshift; 00514 Bshift = format->Bshift; 00515 Ashift = format->Ashift; 00516 00517 A = 0; 00518 R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask; 00519 G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask; 00520 B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask; 00521 if (Amask) { 00522 A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask; 00523 } 00524 *pixel = R | G | B | A; 00525 } 00526 } 00527 break; 00528 #endif 00529 00530 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00531 00532 case 4:{ /* Probably :-) 32-bpp */ 00533 if (alpha == 255) { 00534 *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color; 00535 } else { 00536 Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x; 00537 Uint32 dR, dG, dB, dA; 00538 Uint32 dc = *pixel; 00539 00540 Uint32 surfaceAlpha, preMultR, preMultG, preMultB; 00541 Uint32 aTmp; 00542 00543 Rmask = format->Rmask; 00544 Gmask = format->Gmask; 00545 Bmask = format->Bmask; 00546 Amask = format->Amask; 00547 00548 dR = (color & Rmask); 00549 dG = (color & Gmask); 00550 dB = (color & Bmask); 00551 dA = (color & Amask); 00552 00553 Rshift = format->Rshift; 00554 Gshift = format->Gshift; 00555 Bshift = format->Bshift; 00556 Ashift = format->Ashift; 00557 00558 preMultR = (alpha * (dR >> Rshift)); 00559 preMultG = (alpha * (dG >> Gshift)); 00560 preMultB = (alpha * (dB >> Bshift)); 00561 00562 surfaceAlpha = ((dc & Amask) >> Ashift); 00563 aTmp = (255 - alpha); 00564 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { 00565 aTmp *= surfaceAlpha; 00566 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; 00567 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; 00568 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; 00569 } 00570 *pixel = R | G | B | (A << Ashift & Amask); 00571 00572 } 00573 } 00574 break; 00575 #endif 00576 } 00577 } 00578 00579 return (0); 00580 } 00581 00592 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00593 { 00594 Uint8 alpha; 00595 Uint32 mcolor; 00596 int result = 0; 00597 00598 /* 00599 * Lock the surface 00600 */ 00601 if (SDL_MUSTLOCK(dst)) { 00602 if (SDL_LockSurface(dst) < 0) { 00603 return (-1); 00604 } 00605 } 00606 00607 /* 00608 * Setup color 00609 */ 00610 alpha = color & 0x000000ff; 00611 mcolor = 00612 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00613 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00614 00615 /* 00616 * Draw 00617 */ 00618 result = _putPixelAlpha(dst, x, y, mcolor, alpha); 00619 00620 /* 00621 * Unlock the surface 00622 */ 00623 if (SDL_MUSTLOCK(dst)) { 00624 SDL_UnlockSurface(dst); 00625 } 00626 00627 return (result); 00628 } 00629 00640 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color) 00641 { 00642 Uint8 alpha; 00643 Uint32 mcolor; 00644 int result = 0; 00645 00646 /* 00647 * Setup color 00648 */ 00649 alpha = color & 0x000000ff; 00650 mcolor = 00651 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00652 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00653 00654 /* 00655 * Draw 00656 */ 00657 result = _putPixelAlpha(dst, x, y, mcolor, alpha); 00658 00659 return (result); 00660 } 00661 00662 00678 int _filledRectAlpha(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha) 00679 { 00680 SDL_PixelFormat *format; 00681 Uint32 Rmask, Bmask, Gmask, Amask; 00682 Uint32 Rshift, Bshift, Gshift, Ashift; 00683 Uint8 sR, sG, sB, sA; 00684 Uint32 R, G, B, A; 00685 Sint16 x, y; 00686 00687 format = dst->format; 00688 switch (format->BytesPerPixel) { 00689 case 1: 00690 { /* Assuming 8-bpp */ 00691 Uint8 *row, *pixel; 00692 Uint8 dR, dG, dB; 00693 SDL_Palette *palette = format->palette; 00694 SDL_Color *colors = palette->colors; 00695 sR = colors[color].r; 00696 sG = colors[color].g; 00697 sB = colors[color].b; 00698 00699 for (y = yy; y <= y2; y++) { 00700 row = (Uint8 *) dst->pixels + y * dst->pitch; 00701 for (x = xx; x <= x2; x++) { 00702 pixel = row + x; 00703 00704 dR = colors[*pixel].r; 00705 dG = colors[*pixel].g; 00706 dB = colors[*pixel].b; 00707 00708 dR = dR + ((sR - dR) * alpha >> 8); 00709 dG = dG + ((sG - dG) * alpha >> 8); 00710 dB = dB + ((sB - dB) * alpha >> 8); 00711 00712 *pixel = SDL_MapRGB(format, dR, dG, dB); 00713 } 00714 } 00715 } 00716 break; 00717 00718 case 2: 00719 { /* Probably 15-bpp or 16-bpp */ 00720 Uint16 *row, *pixel; 00721 Uint32 dR, dG, dB, dA; 00722 Rmask = format->Rmask; 00723 Gmask = format->Gmask; 00724 Bmask = format->Bmask; 00725 Amask = format->Amask; 00726 00727 dR = (color & Rmask); 00728 dG = (color & Gmask); 00729 dB = (color & Bmask); 00730 dA = (color & Amask); 00731 00732 A = 0; 00733 00734 for (y = yy; y <= y2; y++) { 00735 row = (Uint16 *) dst->pixels + y * dst->pitch / 2; 00736 for (x = xx; x <= x2; x++) { 00737 pixel = row + x; 00738 00739 R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask; 00740 G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask; 00741 B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask; 00742 if (Amask) 00743 { 00744 A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask; 00745 *pixel = R | G | B | A; 00746 } else { 00747 *pixel = R | G | B; 00748 } 00749 } 00750 } 00751 } 00752 break; 00753 00754 case 3: 00755 { /* Slow 24-bpp mode, usually not used */ 00756 Uint8 *row, *pix; 00757 Uint8 dR, dG, dB, dA; 00758 Uint8 Rshift8, Gshift8, Bshift8, Ashift8; 00759 00760 Rshift = format->Rshift; 00761 Gshift = format->Gshift; 00762 Bshift = format->Bshift; 00763 Ashift = format->Ashift; 00764 00765 Rshift8 = Rshift / 8; 00766 Gshift8 = Gshift / 8; 00767 Bshift8 = Bshift / 8; 00768 Ashift8 = Ashift / 8; 00769 00770 sR = (color >> Rshift) & 0xff; 00771 sG = (color >> Gshift) & 0xff; 00772 sB = (color >> Bshift) & 0xff; 00773 sA = (color >> Ashift) & 0xff; 00774 00775 for (y = yy; y <= y2; y++) { 00776 row = (Uint8 *) dst->pixels + y * dst->pitch; 00777 for (x = xx; x <= x2; x++) { 00778 pix = row + x * 3; 00779 00780 dR = *((pix) + Rshift8); 00781 dG = *((pix) + Gshift8); 00782 dB = *((pix) + Bshift8); 00783 dA = *((pix) + Ashift8); 00784 00785 dR = dR + ((sR - dR) * alpha >> 8); 00786 dG = dG + ((sG - dG) * alpha >> 8); 00787 dB = dB + ((sB - dB) * alpha >> 8); 00788 dA = dA + ((sA - dA) * alpha >> 8); 00789 00790 *((pix) + Rshift8) = dR; 00791 *((pix) + Gshift8) = dG; 00792 *((pix) + Bshift8) = dB; 00793 *((pix) + Ashift8) = dA; 00794 } 00795 } 00796 } 00797 break; 00798 00799 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE 00800 case 4: 00801 { /* Probably :-) 32-bpp */ 00802 Uint32 *row, *pixel; 00803 Uint32 dR, dG, dB, dA; 00804 00805 Rmask = format->Rmask; 00806 Gmask = format->Gmask; 00807 Bmask = format->Bmask; 00808 Amask = format->Amask; 00809 00810 Rshift = format->Rshift; 00811 Gshift = format->Gshift; 00812 Bshift = format->Bshift; 00813 Ashift = format->Ashift; 00814 00815 dR = (color & Rmask); 00816 dG = (color & Gmask); 00817 dB = (color & Bmask); 00818 dA = (color & Amask); 00819 00820 for (y = yy; y <= y2; y++) { 00821 row = (Uint32 *) dst->pixels + y * dst->pitch / 4; 00822 for (x = xx; x <= x2; x++) { 00823 pixel = row + x; 00824 00825 R = ((*pixel & Rmask) + ((((dR - (*pixel & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask; 00826 G = ((*pixel & Gmask) + ((((dG - (*pixel & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask; 00827 B = ((*pixel & Bmask) + ((((dB - (*pixel & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask; 00828 if (Amask) 00829 { 00830 A = ((*pixel & Amask) + ((((dA - (*pixel & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask; 00831 *pixel = R | G | B | A; 00832 } else { 00833 *pixel = R | G | B; 00834 } 00835 } 00836 } 00837 } 00838 break; 00839 #endif 00840 00841 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE 00842 case 4:{ /* Probably :-) 32-bpp */ 00843 Uint32 *row, *pixel; 00844 Uint32 dR, dG, dB, dA; 00845 Uint32 dc; 00846 Uint32 surfaceAlpha, preMultR, preMultG, preMultB; 00847 Uint32 aTmp; 00848 00849 Rmask = format->Rmask; 00850 Gmask = format->Gmask; 00851 Bmask = format->Bmask; 00852 Amask = format->Amask; 00853 00854 dR = (color & Rmask); 00855 dG = (color & Gmask); 00856 dB = (color & Bmask); 00857 dA = (color & Amask); 00858 00859 Rshift = format->Rshift; 00860 Gshift = format->Gshift; 00861 Bshift = format->Bshift; 00862 Ashift = format->Ashift; 00863 00864 preMultR = (alpha * (dR >> Rshift)); 00865 preMultG = (alpha * (dG >> Gshift)); 00866 preMultB = (alpha * (dB >> Bshift)); 00867 00868 for (y = y1; y <= y2; y++) { 00869 row = (Uint32 *) dst->pixels + y * dst->pitch / 4; 00870 for (x = x1; x <= x2; x++) { 00871 pixel = row + x; 00872 dc = *pixel; 00873 00874 surfaceAlpha = ((dc & Amask) >> Ashift); 00875 aTmp = (255 - alpha); 00876 if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) { 00877 aTmp *= surfaceAlpha; 00878 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask; 00879 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask; 00880 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask; 00881 } 00882 *pixel = R | G | B | (A << Ashift & Amask); 00883 00884 } 00885 } 00886 } 00887 break; 00888 #endif 00889 00890 } 00891 00892 return (0); 00893 } 00894 00907 int filledRectAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color) 00908 { 00909 Uint8 alpha; 00910 Uint32 mcolor; 00911 int result = 0; 00912 00913 /* 00914 * Lock the surface 00915 */ 00916 if (SDL_MUSTLOCK(dst)) { 00917 if (SDL_LockSurface(dst) < 0) { 00918 return (-1); 00919 } 00920 } 00921 00922 /* 00923 * Setup color 00924 */ 00925 alpha = color & 0x000000ff; 00926 mcolor = 00927 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24, 00928 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha); 00929 00930 /* 00931 * Draw 00932 */ 00933 result = _filledRectAlpha(dst, x, y, x2, y2, mcolor, alpha); 00934 00935 /* 00936 * Unlock the surface 00937 */ 00938 if (SDL_MUSTLOCK(dst)) { 00939 SDL_UnlockSurface(dst); 00940 } 00941 00942 return (result); 00943 } 00944 00956 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 00957 { 00958 return (filledRectAlpha(dst, x1, y, x2, y, color)); 00959 } 00960 00972 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color) 00973 { 00974 return (filledRectAlpha(dst, x, y, x, y2, color)); 00975 } 00976 00988 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) 00989 { 00990 Uint32 a; 00991 00992 /* 00993 * Get alpha 00994 */ 00995 a = (color & (Uint32) 0x000000ff); 00996 00997 /* 00998 * Modify Alpha by weight 00999 */ 01000 a = ((a * weight) >> 8); 01001 01002 return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a)); 01003 } 01004 01016 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight) 01017 { 01018 Uint32 a; 01019 01020 /* 01021 * Get alpha 01022 */ 01023 a = (color & (Uint32) 0x000000ff); 01024 01025 /* 01026 * Modify Alpha by weight 01027 */ 01028 a = ((a * weight) >> 8); 01029 01030 return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a)); 01031 } 01032 01046 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01047 { 01048 Uint32 color; 01049 01050 /* 01051 * Check Alpha 01052 */ 01053 if (a == 255) { 01054 /* 01055 * No alpha blending required 01056 */ 01057 /* 01058 * Setup color 01059 */ 01060 color = SDL_MapRGBA(dst->format, r, g, b, a); 01061 /* 01062 * Draw 01063 */ 01064 return (fastPixelColor(dst, x, y, color)); 01065 } else { 01066 /* 01067 * Alpha blending required 01068 */ 01069 /* 01070 * Draw 01071 */ 01072 return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01073 } 01074 } 01075 01076 01092 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 01093 { 01094 Sint16 left, right, top, bottom; 01095 Uint8 *pixel, *pixellast; 01096 int dx; 01097 int pixx, pixy; 01098 Sint16 w; 01099 Sint16 xtmp; 01100 int result = -1; 01101 01102 /* 01103 * Check visibility of clipping rectangle 01104 */ 01105 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01106 return(0); 01107 } 01108 01109 /* 01110 * Swap x1, x2 if required to ensure x1<=x2 01111 */ 01112 if (x1 > x2) { 01113 xtmp = x1; 01114 x1 = x2; 01115 x2 = xtmp; 01116 } 01117 01118 /* 01119 * Get clipping boundary and 01120 * check visibility of hline 01121 */ 01122 left = dst->clip_rect.x; 01123 if (x2<left) { 01124 return(0); 01125 } 01126 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01127 if (x1>right) { 01128 return(0); 01129 } 01130 top = dst->clip_rect.y; 01131 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01132 if ((y<top) || (y>bottom)) { 01133 return (0); 01134 } 01135 01136 /* 01137 * Clip x 01138 */ 01139 if (x1 < left) { 01140 x1 = left; 01141 } 01142 if (x2 > right) { 01143 x2 = right; 01144 } 01145 01146 /* 01147 * Calculate width 01148 */ 01149 w = x2 - x1; 01150 01151 /* 01152 * Lock the surface 01153 */ 01154 if (SDL_MUSTLOCK(dst)) { 01155 if (SDL_LockSurface(dst) < 0) { 01156 return (-1); 01157 } 01158 } 01159 01160 /* 01161 * More variable setup 01162 */ 01163 dx = w; 01164 pixx = dst->format->BytesPerPixel; 01165 pixy = dst->pitch; 01166 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; 01167 01168 /* 01169 * Draw 01170 */ 01171 switch (dst->format->BytesPerPixel) { 01172 case 1: 01173 memset(pixel, color, dx+1); 01174 break; 01175 case 2: 01176 pixellast = pixel + dx + dx; 01177 for (; pixel <= pixellast; pixel += pixx) { 01178 *(Uint16 *) pixel = color; 01179 } 01180 break; 01181 case 3: 01182 pixellast = pixel + dx + dx + dx; 01183 for (; pixel <= pixellast; pixel += pixx) { 01184 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01185 pixel[0] = (color >> 16) & 0xff; 01186 pixel[1] = (color >> 8) & 0xff; 01187 pixel[2] = color & 0xff; 01188 } else { 01189 pixel[0] = color & 0xff; 01190 pixel[1] = (color >> 8) & 0xff; 01191 pixel[2] = (color >> 16) & 0xff; 01192 } 01193 } 01194 break; 01195 default: /* case 4 */ 01196 dx = dx + dx; 01197 pixellast = pixel + dx + dx; 01198 for (; pixel <= pixellast; pixel += pixx) { 01199 *(Uint32 *) pixel = color; 01200 } 01201 break; 01202 } 01203 01204 /* 01205 * Unlock surface 01206 */ 01207 if (SDL_MUSTLOCK(dst)) { 01208 SDL_UnlockSurface(dst); 01209 } 01210 01211 /* 01212 * Set result code 01213 */ 01214 result = 0; 01215 01216 return (result); 01217 } 01218 01236 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01237 { 01238 /* 01239 * Draw 01240 */ 01241 return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01242 } 01243 01255 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color) 01256 { 01257 Sint16 left, right, top, bottom; 01258 Uint8 *pixel, *pixellast; 01259 int dx; 01260 int pixx, pixy; 01261 Sint16 xtmp; 01262 int result = -1; 01263 Uint8 *colorptr; 01264 Uint8 color3[3]; 01265 01266 /* 01267 * Check visibility of clipping rectangle 01268 */ 01269 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01270 return(0); 01271 } 01272 01273 /* 01274 * Swap x1, x2 if required to ensure x1<=x2 01275 */ 01276 if (x1 > x2) { 01277 xtmp = x1; 01278 x1 = x2; 01279 x2 = xtmp; 01280 } 01281 01282 /* 01283 * Get clipping boundary and 01284 * check visibility of hline 01285 */ 01286 left = dst->clip_rect.x; 01287 if (x2<left) { 01288 return(0); 01289 } 01290 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01291 if (x1>right) { 01292 return(0); 01293 } 01294 top = dst->clip_rect.y; 01295 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01296 if ((y<top) || (y>bottom)) { 01297 return (0); 01298 } 01299 01300 /* 01301 * Clip x 01302 */ 01303 if (x1 < left) { 01304 x1 = left; 01305 } 01306 if (x2 > right) { 01307 x2 = right; 01308 } 01309 01310 /* 01311 * Calculate width difference 01312 */ 01313 dx = x2 - x1; 01314 01315 /* 01316 * Alpha check 01317 */ 01318 if ((color & 255) == 255) { 01319 01320 /* 01321 * No alpha-blending required 01322 */ 01323 01324 /* 01325 * Setup color 01326 */ 01327 colorptr = (Uint8 *) & color; 01328 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01329 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 01330 } else { 01331 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 01332 } 01333 01334 /* 01335 * Lock the surface 01336 */ 01337 if (SDL_MUSTLOCK(dst)) { 01338 if (SDL_LockSurface(dst) < 0) { 01339 return (-1); 01340 } 01341 } 01342 01343 /* 01344 * More variable setup 01345 */ 01346 pixx = dst->format->BytesPerPixel; 01347 pixy = dst->pitch; 01348 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y; 01349 01350 /* 01351 * Draw 01352 */ 01353 switch (dst->format->BytesPerPixel) { 01354 case 1: 01355 memset(pixel, color, dx + 1); 01356 break; 01357 case 2: 01358 pixellast = pixel + dx + dx; 01359 for (; pixel <= pixellast; pixel += pixx) { 01360 *(Uint16 *) pixel = color; 01361 } 01362 break; 01363 case 3: 01364 pixellast = pixel + dx + dx + dx; 01365 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01366 color3[0] = (color >> 16) & 0xff; 01367 color3[1] = (color >> 8) & 0xff; 01368 color3[2] = color & 0xff; 01369 } else { 01370 color3[0] = color & 0xff; 01371 color3[1] = (color >> 8) & 0xff; 01372 color3[2] = (color >> 16) & 0xff; 01373 } 01374 for (; pixel <= pixellast; pixel += pixx) { 01375 memcpy(pixel, color3, 3); 01376 } 01377 break; 01378 default: /* case 4 */ 01379 dx = dx + dx; 01380 pixellast = pixel + dx + dx; 01381 for (; pixel <= pixellast; pixel += pixx) { 01382 *(Uint32 *) pixel = color; 01383 } 01384 break; 01385 } 01386 01387 /* 01388 * Unlock surface 01389 */ 01390 if (SDL_MUSTLOCK(dst)) { 01391 SDL_UnlockSurface(dst); 01392 } 01393 01394 /* 01395 * Set result code 01396 */ 01397 result = 0; 01398 01399 } else { 01400 01401 /* 01402 * Alpha blending blit 01403 */ 01404 result = _HLineAlpha(dst, x1, x1 + dx, y, color); 01405 } 01406 01407 return (result); 01408 } 01409 01424 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01425 { 01426 /* 01427 * Draw 01428 */ 01429 return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01430 } 01431 01443 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color) 01444 { 01445 Sint16 left, right, top, bottom; 01446 Uint8 *pixel, *pixellast; 01447 int dy; 01448 int pixx, pixy; 01449 Sint16 h; 01450 Sint16 ytmp; 01451 int result = -1; 01452 Uint8 *colorptr; 01453 01454 /* 01455 * Check visibility of clipping rectangle 01456 */ 01457 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01458 return(0); 01459 } 01460 01461 /* 01462 * Swap y1, y2 if required to ensure y1<=y2 01463 */ 01464 if (y > y2) { 01465 ytmp = y; 01466 y = y2; 01467 y2 = ytmp; 01468 } 01469 01470 /* 01471 * Get clipping boundary and 01472 * check visibility of vline 01473 */ 01474 left = dst->clip_rect.x; 01475 right = dst->clip_rect.x + dst->clip_rect.w - 1; 01476 if ((x<left) || (x>right)) { 01477 return (0); 01478 } 01479 top = dst->clip_rect.y; 01480 if (y2<top) { 01481 return(0); 01482 } 01483 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 01484 if (y>bottom) { 01485 return(0); 01486 } 01487 01488 /* 01489 * Clip x 01490 */ 01491 if (y < top) { 01492 y = top; 01493 } 01494 if (y2 > bottom) { 01495 y2 = bottom; 01496 } 01497 01498 /* 01499 * Calculate height 01500 */ 01501 h = y2 - y; 01502 01503 /* 01504 * Alpha check 01505 */ 01506 if ((color & 255) == 255) { 01507 01508 /* 01509 * No alpha-blending required 01510 */ 01511 01512 /* 01513 * Setup color 01514 */ 01515 colorptr = (Uint8 *) & color; 01516 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01517 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 01518 } else { 01519 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 01520 } 01521 01522 /* 01523 * Lock the surface 01524 */ 01525 if (SDL_MUSTLOCK(dst)) { 01526 if (SDL_LockSurface(dst) < 0) { 01527 return (-1); 01528 } 01529 } 01530 01531 /* 01532 * More variable setup 01533 */ 01534 dy = h; 01535 pixx = dst->format->BytesPerPixel; 01536 pixy = dst->pitch; 01537 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y; 01538 pixellast = pixel + pixy * dy; 01539 01540 /* 01541 * Draw 01542 */ 01543 switch (dst->format->BytesPerPixel) { 01544 case 1: 01545 for (; pixel <= pixellast; pixel += pixy) { 01546 *(Uint8 *) pixel = color; 01547 } 01548 break; 01549 case 2: 01550 for (; pixel <= pixellast; pixel += pixy) { 01551 *(Uint16 *) pixel = color; 01552 } 01553 break; 01554 case 3: 01555 for (; pixel <= pixellast; pixel += pixy) { 01556 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 01557 pixel[0] = (color >> 16) & 0xff; 01558 pixel[1] = (color >> 8) & 0xff; 01559 pixel[2] = color & 0xff; 01560 } else { 01561 pixel[0] = color & 0xff; 01562 pixel[1] = (color >> 8) & 0xff; 01563 pixel[2] = (color >> 16) & 0xff; 01564 } 01565 } 01566 break; 01567 default: /* case 4 */ 01568 for (; pixel <= pixellast; pixel += pixy) { 01569 *(Uint32 *) pixel = color; 01570 } 01571 break; 01572 } 01573 01574 /* Unlock surface */ 01575 if (SDL_MUSTLOCK(dst)) { 01576 SDL_UnlockSurface(dst); 01577 } 01578 01579 /* 01580 * Set result code 01581 */ 01582 result = 0; 01583 01584 } else { 01585 01586 /* 01587 * Alpha blending blit 01588 */ 01589 01590 result = _VLineAlpha(dst, x, y, y + h, color); 01591 01592 } 01593 01594 return (result); 01595 } 01596 01611 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01612 { 01613 /* 01614 * Draw 01615 */ 01616 return (vlineColor(dst, x, y, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01617 } 01618 01631 int rectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color) 01632 { 01633 int result; 01634 Sint16 tmp; 01635 01636 /* Check destination surface */ 01637 if (dst == NULL) 01638 { 01639 return -1; 01640 } 01641 01642 /* 01643 * Check visibility of clipping rectangle 01644 */ 01645 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01646 return 0; 01647 } 01648 01649 /* 01650 * Test for special cases of straight lines or single point 01651 */ 01652 if (x == x2) { 01653 if (y == y2) { 01654 return (pixelColor(dst, x, y, color)); 01655 } else { 01656 return (vlineColor(dst, x, y, y2, color)); 01657 } 01658 } else { 01659 if (y == y2) { 01660 return (hlineColor(dst, x, x2, y, color)); 01661 } 01662 } 01663 01664 /* 01665 * Swap x1, x2 if required 01666 */ 01667 if (x > x2) { 01668 tmp = x; 01669 x = x2; 01670 x2 = tmp; 01671 } 01672 01673 /* 01674 * Swap y1, y2 if required 01675 */ 01676 if (y > y2) { 01677 tmp = y; 01678 y = y2; 01679 y2 = tmp; 01680 } 01681 01682 /* 01683 * Draw rectangle 01684 */ 01685 result = 0; 01686 result |= hlineColor(dst, x, x2, y, color); 01687 result |= hlineColor(dst, x, x2, y2, color); 01688 y += 1; 01689 y2 -= 1; 01690 if (y <= y2) { 01691 result |= vlineColor(dst, x, y, y2, color); 01692 result |= vlineColor(dst, x2, y, y2, color); 01693 } 01694 01695 return (result); 01696 01697 } 01698 01714 int rectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01715 { 01716 /* 01717 * Draw 01718 */ 01719 return (rectangleColor 01720 (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01721 } 01722 01736 int roundedRectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) 01737 { 01738 int result; 01739 Sint16 w, h, tmp; 01740 Sint16 xx1, xx2, yy1, yy2; 01741 01742 /* 01743 * Check destination surface 01744 */ 01745 if (dst == NULL) 01746 { 01747 return -1; 01748 } 01749 01750 /* 01751 * Check radius vor valid range 01752 */ 01753 if (rad < 0) { 01754 return -1; 01755 } 01756 01757 /* 01758 * Special case - no rounding 01759 */ 01760 if (rad == 0) { 01761 return rectangleColor(dst, x, y, x2, y2, color); 01762 } 01763 01764 /* 01765 * Check visibility of clipping rectangle 01766 */ 01767 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01768 return 0; 01769 } 01770 01771 /* 01772 * Test for special cases of straight lines or single point 01773 */ 01774 if (x == x2) { 01775 if (y == y2) { 01776 return (pixelColor(dst, x, y, color)); 01777 } else { 01778 return (vlineColor(dst, x, y, y2, color)); 01779 } 01780 } else { 01781 if (y == y2) { 01782 return (hlineColor(dst, x, x2, y, color)); 01783 } 01784 } 01785 01786 /* 01787 * Swap x1, x2 if required 01788 */ 01789 if (x > x2) { 01790 tmp = x; 01791 x = x2; 01792 x2 = tmp; 01793 } 01794 01795 /* 01796 * Swap y1, y2 if required 01797 */ 01798 if (y > y2) { 01799 tmp = y; 01800 y = y2; 01801 y2 = tmp; 01802 } 01803 01804 /* 01805 * Calculate width&height 01806 */ 01807 w = x2 - x; 01808 h = y2 - y; 01809 01810 /* 01811 * Maybe adjust radius 01812 */ 01813 if ((rad * 2) > w) 01814 { 01815 rad = w / 2; 01816 } 01817 if ((rad * 2) > h) 01818 { 01819 rad = h / 2; 01820 } 01821 01822 /* 01823 * Draw corners 01824 */ 01825 result = 0; 01826 xx1 = x + rad; 01827 xx2 = x2 - rad; 01828 yy1 = y + rad; 01829 yy2 = y2 - rad; 01830 result |= arcColor(dst, xx1, yy1, rad, 180, 270, color); 01831 result |= arcColor(dst, xx2, yy1, rad, 270, 360, color); 01832 result |= arcColor(dst, xx1, yy2, rad, 90, 180, color); 01833 result |= arcColor(dst, xx2, yy2, rad, 0, 90, color); 01834 01835 /* 01836 * Draw lines 01837 */ 01838 if (xx1 <= xx2) { 01839 result |= hlineColor(dst, xx1, xx2, y, color); 01840 result |= hlineColor(dst, xx1, xx2, y2, color); 01841 } 01842 if (yy1 <= yy2) { 01843 result |= vlineColor(dst, x, yy1, yy2, color); 01844 result |= vlineColor(dst, x2, yy1, yy2, color); 01845 } 01846 01847 return result; 01848 } 01849 01866 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 01867 { 01868 /* 01869 * Draw 01870 */ 01871 return (roundedRectangleColor 01872 (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 01873 } 01874 01888 int roundedBoxColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color) 01889 { 01890 int result; 01891 Sint16 w, h, tmp; 01892 Sint16 xx1, xx2, yy1, yy2; 01893 01894 /* 01895 * Check destination surface 01896 */ 01897 if (dst == NULL) 01898 { 01899 return -1; 01900 } 01901 01902 /* 01903 * Check radius vor valid range 01904 */ 01905 if (rad < 0) { 01906 return -1; 01907 } 01908 01909 /* 01910 * Special case - no rounding 01911 */ 01912 if (rad == 0) { 01913 return rectangleColor(dst, x, y, x2, y2, color); 01914 } 01915 01916 /* 01917 * Check visibility of clipping rectangle 01918 */ 01919 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 01920 return 0; 01921 } 01922 01923 /* 01924 * Test for special cases of straight lines or single point 01925 */ 01926 if (x == x2) { 01927 if (y == y2) { 01928 return (pixelColor(dst, x, y, color)); 01929 } else { 01930 return (vlineColor(dst, x, y, y2, color)); 01931 } 01932 } else { 01933 if (y == y2) { 01934 return (hlineColor(dst, x, x2, y, color)); 01935 } 01936 } 01937 01938 /* 01939 * Swap x1, x2 if required 01940 */ 01941 if (x > x2) { 01942 tmp = x; 01943 x = x2; 01944 x2 = tmp; 01945 } 01946 01947 /* 01948 * Swap y1, y2 if required 01949 */ 01950 if (y > y2) { 01951 tmp = y; 01952 y = y2; 01953 y2 = tmp; 01954 } 01955 01956 /* 01957 * Calculate width&height 01958 */ 01959 w = x2 - x; 01960 h = y2 - y; 01961 01962 /* 01963 * Maybe adjust radius 01964 */ 01965 if ((rad * 2) > w) 01966 { 01967 rad = w / 2; 01968 } 01969 if ((rad * 2) > h) 01970 { 01971 rad = h / 2; 01972 } 01973 01974 /* 01975 * Draw corners 01976 */ 01977 result = 0; 01978 xx1 = x + rad; 01979 xx2 = x2 - rad; 01980 yy1 = y + rad; 01981 yy2 = y2 - rad; 01982 result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color); 01983 result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color); 01984 result |= filledPieColor(dst, xx1, yy2, rad, 90, 180, color); 01985 result |= filledPieColor(dst, xx2, yy2, rad, 0, 90, color); 01986 01987 /* 01988 * Draw body 01989 */ 01990 xx1++; 01991 xx2--; 01992 yy1++; 01993 yy2--; 01994 if (xx1 <= xx2) { 01995 result |= boxColor(dst, xx1, y, xx2, y2, color); 01996 } 01997 if (yy1 <= yy2) { 01998 result |= boxColor(dst, x, yy1, xx1-1, yy2, color); 01999 result |= boxColor(dst, xx2+1, yy1, x2, yy2, color); 02000 } 02001 02002 return result; 02003 } 02004 02021 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, 02022 Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02023 { 02024 /* 02025 * Draw 02026 */ 02027 return (roundedBoxColor 02028 (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 02029 } 02030 02031 /* --------- Clipping routines for line */ 02032 02033 /* Clipping based heavily on code from */ 02034 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */ 02035 02036 #define CLIP_LEFT_EDGE 0x1 02037 #define CLIP_RIGHT_EDGE 0x2 02038 #define CLIP_BOTTOM_EDGE 0x4 02039 #define CLIP_TOP_EDGE 0x8 02040 #define CLIP_INSIDE(a) (!a) 02041 #define CLIP_REJECT(a,b) (a&b) 02042 #define CLIP_ACCEPT(a,b) (!(a|b)) 02043 02056 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom) 02057 { 02058 int code = 0; 02059 02060 if (x < left) { 02061 code |= CLIP_LEFT_EDGE; 02062 } else if (x > right) { 02063 code |= CLIP_RIGHT_EDGE; 02064 } 02065 if (y < top) { 02066 code |= CLIP_TOP_EDGE; 02067 } else if (y > bottom) { 02068 code |= CLIP_BOTTOM_EDGE; 02069 } 02070 return code; 02071 } 02072 02082 static int _clipLine(SDL_Surface * dst, Sint16 * x, Sint16 * y, Sint16 * x2, Sint16 * y2) 02083 { 02084 Sint16 left, right, top, bottom; 02085 int code1, code2; 02086 int draw = 0; 02087 Sint16 swaptmp; 02088 float m; 02089 02090 /* 02091 * Get clipping boundary 02092 */ 02093 left = dst->clip_rect.x; 02094 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02095 top = dst->clip_rect.y; 02096 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02097 02098 while (1) { 02099 code1 = _clipEncode(*x, *y, left, top, right, bottom); 02100 code2 = _clipEncode(*x2, *y2, left, top, right, bottom); 02101 if (CLIP_ACCEPT(code1, code2)) { 02102 draw = 1; 02103 break; 02104 } else if (CLIP_REJECT(code1, code2)) 02105 break; 02106 else { 02107 if (CLIP_INSIDE(code1)) { 02108 swaptmp = *x2; 02109 *x2 = *x; 02110 *x = swaptmp; 02111 swaptmp = *y2; 02112 *y2 = *y; 02113 *y = swaptmp; 02114 swaptmp = code2; 02115 code2 = code1; 02116 code1 = swaptmp; 02117 } 02118 if (*x2 != *x) { 02119 m = (*y2 - *y) / (float) (*x2 - *x); 02120 } else { 02121 m = 1.0f; 02122 } 02123 if (code1 & CLIP_LEFT_EDGE) { 02124 *y += (Sint16) ((left - *x) * m); 02125 *x = left; 02126 } else if (code1 & CLIP_RIGHT_EDGE) { 02127 *y += (Sint16) ((right - *x) * m); 02128 *x = right; 02129 } else if (code1 & CLIP_BOTTOM_EDGE) { 02130 if (*x2 != *x) { 02131 *x += (Sint16) ((bottom - *y) / m); 02132 } 02133 *y = bottom; 02134 } else if (code1 & CLIP_TOP_EDGE) { 02135 if (*x2 != *x) { 02136 *x += (Sint16) ((top - *y) / m); 02137 } 02138 *y = top; 02139 } 02140 } 02141 } 02142 02143 return draw; 02144 } 02145 02158 int boxColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color) 02159 { 02160 Sint16 left, right, top, bottom; 02161 Uint8 *pixel, *pixellast; 02162 int x, dx; 02163 int dy; 02164 int pixx, pixy; 02165 Sint16 w, h, tmp; 02166 int result; 02167 Uint8 *colorptr; 02168 02169 /* 02170 * Check visibility of clipping rectangle 02171 */ 02172 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02173 return(0); 02174 } 02175 02176 /* 02177 * Order coordinates to ensure that 02178 * x1<=x2 and y1<=y2 02179 */ 02180 if (xx > x2) { 02181 tmp = xx; 02182 xx = x2; 02183 x2 = tmp; 02184 } 02185 if (yy > y2) { 02186 tmp = yy; 02187 yy = y2; 02188 y2 = tmp; 02189 } 02190 02191 /* 02192 * Get clipping boundary and 02193 * check visibility 02194 */ 02195 left = dst->clip_rect.x; 02196 if (x2<left) { 02197 return(0); 02198 } 02199 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02200 if (xx>right) { 02201 return(0); 02202 } 02203 top = dst->clip_rect.y; 02204 if (y2<top) { 02205 return(0); 02206 } 02207 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02208 if (yy>bottom) { 02209 return(0); 02210 } 02211 02212 /* Clip all points */ 02213 if (xx<left) { 02214 xx=left; 02215 } else if (xx>right) { 02216 xx=right; 02217 } 02218 if (x2<left) { 02219 x2=left; 02220 } else if (x2>right) { 02221 x2=right; 02222 } 02223 if (yy<top) { 02224 yy=top; 02225 } else if (yy>bottom) { 02226 yy=bottom; 02227 } 02228 if (y2<top) { 02229 y2=top; 02230 } else if (y2>bottom) { 02231 y2=bottom; 02232 } 02233 02234 /* 02235 * Test for special cases of straight line or single point 02236 */ 02237 if (xx == x2) { 02238 if (yy == y2) { 02239 return (pixelColor(dst, xx, yy, color)); 02240 } else { 02241 return (vlineColor(dst, xx, yy, y2, color)); 02242 } 02243 } 02244 if (yy == y2) { 02245 return (hlineColor(dst, xx, x2, yy, color)); 02246 } 02247 02248 /* 02249 * Calculate width&height 02250 */ 02251 w = x2 - xx; 02252 h = y2 - yy; 02253 02254 /* 02255 * Alpha check 02256 */ 02257 if ((color & 255) == 255) { 02258 02259 /* 02260 * No alpha-blending required 02261 */ 02262 02263 /* 02264 * Setup color 02265 */ 02266 colorptr = (Uint8 *) & color; 02267 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02268 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 02269 } else { 02270 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 02271 } 02272 02273 /* 02274 * Lock the surface 02275 */ 02276 if (SDL_MUSTLOCK(dst)) { 02277 if (SDL_LockSurface(dst) < 0) { 02278 return (-1); 02279 } 02280 } 02281 02282 /* 02283 * More variable setup 02284 */ 02285 dx = w; 02286 dy = h; 02287 pixx = dst->format->BytesPerPixel; 02288 pixy = dst->pitch; 02289 pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy; 02290 pixellast = pixel + pixx * dx + pixy * dy; 02291 dx++; 02292 02293 /* 02294 * Draw 02295 */ 02296 switch (dst->format->BytesPerPixel) { 02297 case 1: 02298 for (; pixel <= pixellast; pixel += pixy) { 02299 memset(pixel, (Uint8) color, dx); 02300 } 02301 break; 02302 case 2: 02303 pixy -= (pixx * dx); 02304 for (; pixel <= pixellast; pixel += pixy) { 02305 for (x = 0; x < dx; x++) { 02306 *(Uint16*) pixel = color; 02307 pixel += pixx; 02308 } 02309 } 02310 break; 02311 case 3: 02312 pixy -= (pixx * dx); 02313 for (; pixel <= pixellast; pixel += pixy) { 02314 for (x = 0; x < dx; x++) { 02315 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02316 pixel[0] = (color >> 16) & 0xff; 02317 pixel[1] = (color >> 8) & 0xff; 02318 pixel[2] = color & 0xff; 02319 } else { 02320 pixel[0] = color & 0xff; 02321 pixel[1] = (color >> 8) & 0xff; 02322 pixel[2] = (color >> 16) & 0xff; 02323 } 02324 pixel += pixx; 02325 } 02326 } 02327 break; 02328 default: /* case 4 */ 02329 pixy -= (pixx * dx); 02330 for (; pixel <= pixellast; pixel += pixy) { 02331 for (x = 0; x < dx; x++) { 02332 *(Uint32 *) pixel = color; 02333 pixel += pixx; 02334 } 02335 } 02336 break; 02337 } 02338 02339 /* Unlock surface */ 02340 if (SDL_MUSTLOCK(dst)) { 02341 SDL_UnlockSurface(dst); 02342 } 02343 02344 result = 0; 02345 02346 } else { 02347 02348 result = filledRectAlpha(dst, xx, yy, xx + w, yy + h, color); 02349 02350 } 02351 02352 return (result); 02353 } 02354 02370 int boxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02371 { 02372 /* 02373 * Draw 02374 */ 02375 return (boxColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 02376 } 02377 02378 /* ----- Line */ 02379 02380 /* Non-alpha line drawing code adapted from routine */ 02381 /* by Pete Shinners, pete@shinners.org */ 02382 /* Originally from pygame, http://pygame.seul.org */ 02383 02384 #define ABS(a) (((a)<0) ? -(a) : (a)) 02385 02398 int lineColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color) 02399 { 02400 int pixx, pixy; 02401 int x, y; 02402 int dx, dy; 02403 int ax, ay; 02404 int sx, sy; 02405 int swaptmp; 02406 Uint8 *pixel; 02407 Uint8 *colorptr; 02408 02409 /* 02410 * Clip line and test if we have to draw 02411 */ 02412 if (!(_clipLine(dst, &xx, &yy, &x2, &y2))) { 02413 return (0); 02414 } 02415 02416 /* 02417 * Test for special cases of straight lines or single point 02418 */ 02419 if (xx == x2) { 02420 if (yy < y2) { 02421 return (vlineColor(dst, xx, yy, y2, color)); 02422 } else if (yy > y2) { 02423 return (vlineColor(dst, xx, y2, yy, color)); 02424 } else { 02425 return (pixelColor(dst, xx, yy, color)); 02426 } 02427 } 02428 if (yy == y2) { 02429 if (xx < x2) { 02430 return (hlineColor(dst, xx, x2, yy, color)); 02431 } else if (xx > x2) { 02432 return (hlineColor(dst, x2, xx, yy, color)); 02433 } 02434 } 02435 02436 /* 02437 * Variable setup 02438 */ 02439 dx = x2 - xx; 02440 dy = y2 - yy; 02441 sx = (dx >= 0) ? 1 : -1; 02442 sy = (dy >= 0) ? 1 : -1; 02443 02444 /* Lock surface */ 02445 if (SDL_MUSTLOCK(dst)) { 02446 if (SDL_LockSurface(dst) < 0) { 02447 return (-1); 02448 } 02449 } 02450 02451 /* 02452 * Check for alpha blending 02453 */ 02454 if ((color & 255) == 255) { 02455 02456 /* 02457 * No alpha blending - use fast pixel routines 02458 */ 02459 02460 /* 02461 * Setup color 02462 */ 02463 colorptr = (Uint8 *) & color; 02464 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02465 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 02466 } else { 02467 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 02468 } 02469 02470 /* 02471 * More variable setup 02472 */ 02473 dx = sx * dx + 1; 02474 dy = sy * dy + 1; 02475 pixx = dst->format->BytesPerPixel; 02476 pixy = dst->pitch; 02477 pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy; 02478 pixx *= sx; 02479 pixy *= sy; 02480 if (dx < dy) { 02481 swaptmp = dx; 02482 dx = dy; 02483 dy = swaptmp; 02484 swaptmp = pixx; 02485 pixx = pixy; 02486 pixy = swaptmp; 02487 } 02488 02489 /* 02490 * Draw 02491 */ 02492 x = 0; 02493 y = 0; 02494 switch (dst->format->BytesPerPixel) { 02495 case 1: 02496 for (; x < dx; x++, pixel += pixx) { 02497 *pixel = color; 02498 y += dy; 02499 if (y >= dx) { 02500 y -= dx; 02501 pixel += pixy; 02502 } 02503 } 02504 break; 02505 case 2: 02506 for (; x < dx; x++, pixel += pixx) { 02507 *(Uint16 *) pixel = color; 02508 y += dy; 02509 if (y >= dx) { 02510 y -= dx; 02511 pixel += pixy; 02512 } 02513 } 02514 break; 02515 case 3: 02516 for (; x < dx; x++, pixel += pixx) { 02517 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 02518 pixel[0] = (color >> 16) & 0xff; 02519 pixel[1] = (color >> 8) & 0xff; 02520 pixel[2] = color & 0xff; 02521 } else { 02522 pixel[0] = color & 0xff; 02523 pixel[1] = (color >> 8) & 0xff; 02524 pixel[2] = (color >> 16) & 0xff; 02525 } 02526 y += dy; 02527 if (y >= dx) { 02528 y -= dx; 02529 pixel += pixy; 02530 } 02531 } 02532 break; 02533 default: /* case 4 */ 02534 for (; x < dx; x++, pixel += pixx) { 02535 *(Uint32 *) pixel = color; 02536 y += dy; 02537 if (y >= dx) { 02538 y -= dx; 02539 pixel += pixy; 02540 } 02541 } 02542 break; 02543 } 02544 02545 } else { 02546 02547 /* 02548 * Alpha blending required - use single-pixel blits 02549 */ 02550 02551 ax = ABS(dx) << 1; 02552 ay = ABS(dy) << 1; 02553 x = xx; 02554 y = yy; 02555 if (ax > ay) { 02556 int d = ay - (ax >> 1); 02557 02558 while (x != x2) { 02559 pixelColorNolock (dst, x, y, color); 02560 if (d > 0 || (d == 0 && sx == 1)) { 02561 y += sy; 02562 d -= ax; 02563 } 02564 x += sx; 02565 d += ay; 02566 } 02567 } else { 02568 int d = ax - (ay >> 1); 02569 02570 while (y != y2) { 02571 pixelColorNolock (dst, x, y, color); 02572 if (d > 0 || ((d == 0) && (sy == 1))) { 02573 x += sx; 02574 d -= ay; 02575 } 02576 y += sy; 02577 d += ax; 02578 } 02579 } 02580 pixelColorNolock (dst, x, y, color); 02581 02582 } 02583 02584 /* Unlock surface */ 02585 if (SDL_MUSTLOCK(dst)) { 02586 SDL_UnlockSurface(dst); 02587 } 02588 02589 return (0); 02590 } 02591 02607 int lineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02608 { 02609 /* 02610 * Draw 02611 */ 02612 return (lineColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 02613 } 02614 02615 /* AA Line */ 02616 02617 #define AAlevels 256 02618 #define AAbits 8 02619 02640 int _aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint) 02641 { 02642 Sint32 xx0, yy0, xx1, yy1; 02643 int result; 02644 Uint32 intshift, erracc, erradj; 02645 Uint32 erracctmp, wgt; 02646 int dx, dy, tmp, xdir, y0p1, x0pxdir; 02647 02648 /* 02649 * Check visibility of clipping rectangle 02650 */ 02651 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02652 return(0); 02653 } 02654 02655 /* 02656 * Clip line and test if we have to draw 02657 */ 02658 if (!(_clipLine(dst, &x, &y, &x2, &y2))) { 02659 return (0); 02660 } 02661 02662 /* 02663 * Keep on working with 32bit numbers 02664 */ 02665 xx0 = x; 02666 yy0 = y; 02667 xx1 = x2; 02668 yy1 = y2; 02669 02670 /* 02671 * Reorder points if required 02672 */ 02673 if (yy0 > yy1) { 02674 tmp = yy0; 02675 yy0 = yy1; 02676 yy1 = tmp; 02677 tmp = xx0; 02678 xx0 = xx1; 02679 xx1 = tmp; 02680 } 02681 02682 /* 02683 * Calculate distance 02684 */ 02685 dx = xx1 - xx0; 02686 dy = yy1 - yy0; 02687 02688 /* 02689 * Check for special cases 02690 */ 02691 if (dx == 0) { 02692 /* 02693 * Vertical line 02694 */ 02695 if (draw_endpoint) 02696 { 02697 return (vlineColor(dst, x, y, y2, color)); 02698 } else { 02699 if (dy>0) { 02700 return (vlineColor(dst, x, yy0, yy0+dy, color)); 02701 } else { 02702 return (pixelColor(dst, x, y, color)); 02703 } 02704 } 02705 } else if (dy == 0) { 02706 /* 02707 * Horizontal line 02708 */ 02709 if (draw_endpoint) 02710 { 02711 return (hlineColor(dst, x, x2, y, color)); 02712 } else { 02713 if (dx>0) { 02714 return (hlineColor(dst, xx0, xx0+dx, y, color)); 02715 } else { 02716 return (pixelColor(dst, x, y, color)); 02717 } 02718 } 02719 } else if ((dx == dy) && (draw_endpoint)) { 02720 /* 02721 * Diagonal line (with endpoint) 02722 */ 02723 return (lineColor(dst, x, y, x2, y2, color)); 02724 } 02725 02726 /* 02727 * Adjust for negative dx and set xdir 02728 */ 02729 if (dx >= 0) { 02730 xdir = 1; 02731 } else { 02732 xdir = -1; 02733 dx = (-dx); 02734 } 02735 02736 /* 02737 * Line is not horizontal, vertical or diagonal (with endpoint) 02738 */ 02739 result = 0; 02740 02741 /* 02742 * Zero accumulator 02743 */ 02744 erracc = 0; 02745 02746 /* 02747 * # of bits by which to shift erracc to get intensity level 02748 */ 02749 intshift = 32 - AAbits; 02750 02751 /* Lock surface */ 02752 if (SDL_MUSTLOCK(dst)) { 02753 if (SDL_LockSurface(dst) < 0) { 02754 return (-1); 02755 } 02756 } 02757 02758 /* 02759 * Draw the initial pixel in the foreground color 02760 */ 02761 result |= pixelColorNolock(dst, x, y, color); 02762 02763 /* 02764 * x-major or y-major? 02765 */ 02766 if (dy > dx) { 02767 02768 /* 02769 * y-major. Calculate 16-bit fixed point fractional part of a pixel that 02770 * X advances every time Y advances 1 pixel, truncating the result so that 02771 * we won't overrun the endpoint along the X axis 02772 */ 02773 /* 02774 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy; 02775 */ 02776 erradj = ((dx << 16) / dy) << 16; 02777 02778 /* 02779 * draw all pixels other than the first and last 02780 */ 02781 x0pxdir = xx0 + xdir; 02782 while (--dy) { 02783 erracctmp = erracc; 02784 erracc += erradj; 02785 if (erracc <= erracctmp) { 02786 /* 02787 * rollover in error accumulator, x coord advances 02788 */ 02789 xx0 = x0pxdir; 02790 x0pxdir += xdir; 02791 } 02792 yy0++; /* y-major so always advance Y */ 02793 02794 /* 02795 * the AAbits most significant bits of erracc give us the intensity 02796 * weighting for this pixel, and the complement of the weighting for 02797 * the paired pixel. 02798 */ 02799 wgt = (erracc >> intshift) & 255; 02800 result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); 02801 result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt); 02802 } 02803 02804 } else { 02805 02806 /* 02807 * x-major line. Calculate 16-bit fixed-point fractional part of a pixel 02808 * that Y advances each time X advances 1 pixel, truncating the result so 02809 * that we won't overrun the endpoint along the X axis. 02810 */ 02811 /* 02812 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx; 02813 */ 02814 erradj = ((dy << 16) / dx) << 16; 02815 02816 /* 02817 * draw all pixels other than the first and last 02818 */ 02819 y0p1 = yy0 + 1; 02820 while (--dx) { 02821 02822 erracctmp = erracc; 02823 erracc += erradj; 02824 if (erracc <= erracctmp) { 02825 /* 02826 * Accumulator turned over, advance y 02827 */ 02828 yy0 = y0p1; 02829 y0p1++; 02830 } 02831 xx0 += xdir; /* x-major so always advance X */ 02832 /* 02833 * the AAbits most significant bits of erracc give us the intensity 02834 * weighting for this pixel, and the complement of the weighting for 02835 * the paired pixel. 02836 */ 02837 wgt = (erracc >> intshift) & 255; 02838 result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt); 02839 result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt); 02840 } 02841 } 02842 02843 /* 02844 * Do we have to draw the endpoint 02845 */ 02846 if (draw_endpoint) { 02847 /* 02848 * Draw final pixel, always exactly intersected by the line and doesn't 02849 * need to be weighted. 02850 */ 02851 result |= pixelColorNolock (dst, x2, y2, color); 02852 } 02853 02854 /* Unlock surface */ 02855 if (SDL_MUSTLOCK(dst)) { 02856 SDL_UnlockSurface(dst); 02857 } 02858 02859 return (result); 02860 } 02861 02874 int aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color) 02875 { 02876 return (_aalineColor(dst, x, y, x2, y2, color, 1)); 02877 } 02878 02894 int aalineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 02895 { 02896 return (_aalineColor 02897 (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1)); 02898 } 02899 02900 02901 /* ----- Circle */ 02902 02918 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 02919 { 02920 Sint16 left, right, top, bottom; 02921 int result; 02922 Sint16 xx, yy, x2, y2; 02923 Sint16 cx = 0; 02924 Sint16 cy = rad; 02925 Sint16 df = 1 - rad; 02926 Sint16 d_e = 3; 02927 Sint16 d_se = -2 * rad + 5; 02928 Sint16 xpcx, xmcx, xpcy, xmcy; 02929 Sint16 ypcy, ymcy, ypcx, ymcx; 02930 Uint8 *colorptr; 02931 02932 /* 02933 * Check visibility of clipping rectangle 02934 */ 02935 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 02936 return(0); 02937 } 02938 02939 /* 02940 * Sanity check radius 02941 */ 02942 if (rad < 0) { 02943 return (-1); 02944 } 02945 02946 /* 02947 * Special case for rad=0 - draw a point 02948 */ 02949 if (rad == 0) { 02950 return (pixelColor(dst, x, y, color)); 02951 } 02952 02953 /* 02954 * Get circle and clipping boundary and 02955 * test if bounding box of circle is visible 02956 */ 02957 x2 = x + rad; 02958 left = dst->clip_rect.x; 02959 if (x2<left) { 02960 return(0); 02961 } 02962 xx = x - rad; 02963 right = dst->clip_rect.x + dst->clip_rect.w - 1; 02964 if (xx>right) { 02965 return(0); 02966 } 02967 y2 = y + rad; 02968 top = dst->clip_rect.y; 02969 if (y2<top) { 02970 return(0); 02971 } 02972 yy = y - rad; 02973 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 02974 if (yy>bottom) { 02975 return(0); 02976 } 02977 02978 /* 02979 * Draw circle 02980 */ 02981 result = 0; 02982 02983 /* Lock surface */ 02984 if (SDL_MUSTLOCK(dst)) { 02985 if (SDL_LockSurface(dst) < 0) { 02986 return (-1); 02987 } 02988 } 02989 02990 /* 02991 * Alpha Check 02992 */ 02993 if ((color & 255) == 255) { 02994 02995 /* 02996 * No Alpha - direct memory writes 02997 */ 02998 02999 /* 03000 * Setup color 03001 */ 03002 colorptr = (Uint8 *) & color; 03003 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 03004 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 03005 } else { 03006 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 03007 } 03008 03009 /* 03010 * Draw 03011 */ 03012 do { 03013 ypcy = y + cy; 03014 ymcy = y - cy; 03015 if (cx > 0) { 03016 xpcx = x + cx; 03017 xmcx = x - cx; 03018 result |= fastPixelColorNolock(dst, xmcx, ypcy, color); 03019 result |= fastPixelColorNolock(dst, xpcx, ypcy, color); 03020 result |= fastPixelColorNolock(dst, xmcx, ymcy, color); 03021 result |= fastPixelColorNolock(dst, xpcx, ymcy, color); 03022 } else { 03023 result |= fastPixelColorNolock(dst, x, ymcy, color); 03024 result |= fastPixelColorNolock(dst, x, ypcy, color); 03025 } 03026 xpcy = x + cy; 03027 xmcy = x - cy; 03028 if ((cx > 0) && (cx != cy)) { 03029 ypcx = y + cx; 03030 ymcx = y - cx; 03031 result |= fastPixelColorNolock(dst, xmcy, ypcx, color); 03032 result |= fastPixelColorNolock(dst, xpcy, ypcx, color); 03033 result |= fastPixelColorNolock(dst, xmcy, ymcx, color); 03034 result |= fastPixelColorNolock(dst, xpcy, ymcx, color); 03035 } else if (cx == 0) { 03036 result |= fastPixelColorNolock(dst, xmcy, y, color); 03037 result |= fastPixelColorNolock(dst, xpcy, y, color); 03038 } 03039 /* 03040 * Update 03041 */ 03042 if (df < 0) { 03043 df += d_e; 03044 d_e += 2; 03045 d_se += 2; 03046 } else { 03047 df += d_se; 03048 d_e += 2; 03049 d_se += 4; 03050 cy--; 03051 } 03052 cx++; 03053 } while (cx <= cy); 03054 03055 /* 03056 * Unlock surface 03057 */ 03058 SDL_UnlockSurface(dst); 03059 03060 } else { 03061 03062 /* 03063 * Using Alpha - blended pixel blits 03064 */ 03065 03066 do { 03067 /* 03068 * Draw 03069 */ 03070 ypcy = y + cy; 03071 ymcy = y - cy; 03072 if (cx > 0) { 03073 xpcx = x + cx; 03074 xmcx = x - cx; 03075 result |= pixelColorNolock (dst, xmcx, ypcy, color); 03076 result |= pixelColorNolock (dst, xpcx, ypcy, color); 03077 result |= pixelColorNolock (dst, xmcx, ymcy, color); 03078 result |= pixelColorNolock (dst, xpcx, ymcy, color); 03079 } else { 03080 result |= pixelColorNolock (dst, x, ymcy, color); 03081 result |= pixelColorNolock (dst, x, ypcy, color); 03082 } 03083 xpcy = x + cy; 03084 xmcy = x - cy; 03085 if ((cx > 0) && (cx != cy)) { 03086 ypcx = y + cx; 03087 ymcx = y - cx; 03088 result |= pixelColorNolock (dst, xmcy, ypcx, color); 03089 result |= pixelColorNolock (dst, xpcy, ypcx, color); 03090 result |= pixelColorNolock (dst, xmcy, ymcx, color); 03091 result |= pixelColorNolock (dst, xpcy, ymcx, color); 03092 } else if (cx == 0) { 03093 result |= pixelColorNolock (dst, xmcy, y, color); 03094 result |= pixelColorNolock (dst, xpcy, y, color); 03095 } 03096 /* 03097 * Update 03098 */ 03099 if (df < 0) { 03100 df += d_e; 03101 d_e += 2; 03102 d_se += 2; 03103 } else { 03104 df += d_se; 03105 d_e += 2; 03106 d_se += 4; 03107 cy--; 03108 } 03109 cx++; 03110 } while (cx <= cy); 03111 03112 } /* Alpha check */ 03113 03114 /* Unlock surface */ 03115 if (SDL_MUSTLOCK(dst)) { 03116 SDL_UnlockSurface(dst); 03117 } 03118 03119 return (result); 03120 } 03121 03136 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03137 { 03138 /* 03139 * Draw 03140 */ 03141 return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03142 } 03143 03144 /* ----- Arc */ 03145 03163 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) 03164 { 03165 Sint16 left, right, top, bottom; 03166 int result; 03167 Sint16 xx, yy, x2, y2; 03168 Sint16 cx = 0; 03169 Sint16 cy = rad; 03170 Sint16 df = 1 - rad; 03171 Sint16 d_e = 3; 03172 Sint16 d_se = -2 * rad + 5; 03173 Sint16 xpcx, xmcx, xpcy, xmcy; 03174 Sint16 ypcy, ymcy, ypcx, ymcx; 03175 Uint8 *colorptr; 03176 Uint8 drawoct; 03177 int startoct, endoct, oct, stopval_start = 0, stopval_end; 03178 double temp = 0; 03179 03180 /* 03181 * Check visibility of clipping rectangle 03182 */ 03183 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03184 return(0); 03185 } 03186 03187 /* 03188 * Sanity check radius 03189 */ 03190 if (rad < 0) { 03191 return (-1); 03192 } 03193 03194 /* 03195 * Special case for rad=0 - draw a point 03196 */ 03197 if (rad == 0) { 03198 return (pixelColor(dst, x, y, color)); 03199 } 03200 03201 /* 03202 * Get arc's circle and clipping boundary and 03203 * test if bounding box of circle is visible 03204 */ 03205 x2 = x + rad; 03206 left = dst->clip_rect.x; 03207 if (x2<left) { 03208 return(0); 03209 } 03210 xx = x - rad; 03211 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03212 if (xx>right) { 03213 return(0); 03214 } 03215 y2 = y + rad; 03216 top = dst->clip_rect.y; 03217 if (y2<top) { 03218 return(0); 03219 } 03220 yy = y - rad; 03221 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03222 if (yy>bottom) { 03223 return(0); 03224 } 03225 03226 /* Octant labelling 03227 // \ 5 | 6 / 03228 // \ | / 03229 // 4 \ | / 7 03230 // \|/ 03231 //------+------ +x 03232 // /|\ 03233 // 3 / | \ 0 03234 // / | \ 03235 // / 2 | 1 \ 03236 // +y */ 03237 03238 /* Initially reset bitmask to 0x00000000 03239 * the set whether or not to keep drawing a given octant. 03240 * For example: 0x00111100 means we're drawing in octants 2-5 */ 03241 drawoct = 0; 03242 03243 /* 03244 * Fixup angles 03245 */ 03246 start %= 360; 03247 end %= 360; 03248 /* 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. */ 03249 while (start < 0) start += 360; 03250 while (end < 0) end += 360; 03251 start %= 360; 03252 end %= 360; 03253 03254 /* now, we find which octants we're drawing in. */ 03255 startoct = start / 45; 03256 endoct = end / 45; 03257 oct = startoct - 1; /* we increment as first step in loop */ 03258 03259 /* stopval_start, stopval_end; */ 03260 /* what values of cx to stop at. */ 03261 do { 03262 oct = (oct + 1) % 8; 03263 03264 if (oct == startoct) { 03265 /* need to compute stopval_start for this octant. Look at picture above if this is unclear */ 03266 switch (oct) 03267 { 03268 case 0: 03269 case 3: 03270 temp = sin(start * M_PI / 180); 03271 break; 03272 case 1: 03273 case 6: 03274 temp = cos(start * M_PI / 180); 03275 break; 03276 case 2: 03277 case 5: 03278 temp = -cos(start * M_PI / 180); 03279 break; 03280 case 4: 03281 case 7: 03282 temp = -sin(start * M_PI / 180); 03283 break; 03284 } 03285 temp *= rad; 03286 stopval_start = (int)temp; /* always round down. */ 03287 /* This isn't arbitrary, but requires graph paper to explain well. */ 03288 /* The basic idea is that we're always changing drawoct after we draw, so we */ 03289 /* stop immediately after we render the last sensible pixel at x = ((int)temp). */ 03290 03291 /* and whether to draw in this octant initially */ 03292 if (oct % 2) drawoct |= (1 << oct); /* this is basically like saying drawoct[oct] = true, if drawoct were a bool array */ 03293 else drawoct &= 255 - (1 << oct); /* this is basically like saying drawoct[oct] = false */ 03294 } 03295 if (oct == endoct) { 03296 /* need to compute stopval_end for this octant */ 03297 switch (oct) 03298 { 03299 case 0: 03300 case 3: 03301 temp = sin(end * M_PI / 180); 03302 break; 03303 case 1: 03304 case 6: 03305 temp = cos(end * M_PI / 180); 03306 break; 03307 case 2: 03308 case 5: 03309 temp = -cos(end * M_PI / 180); 03310 break; 03311 case 4: 03312 case 7: 03313 temp = -sin(end * M_PI / 180); 03314 break; 03315 } 03316 temp *= rad; 03317 stopval_end = (int)temp; 03318 03319 /* and whether to draw in this octant initially */ 03320 if (startoct == endoct) { 03321 /* note: we start drawing, stop, then start again in this case */ 03322 /* otherwise: we only draw in this octant, so initialize it to false, it will get set back to true */ 03323 if (start > end) { 03324 /* unfortunately, if we're in the same octant and need to draw over the whole circle, */ 03325 /* we need to set the rest to true, because the while loop will end at the bottom. */ 03326 drawoct = 255; 03327 } else { 03328 drawoct &= 255 - (1 << oct); 03329 } 03330 } 03331 else if (oct % 2) drawoct &= 255 - (1 << oct); 03332 else drawoct |= (1 << oct); 03333 } else if (oct != startoct) { /* already verified that it's != endoct */ 03334 drawoct |= (1 << oct); /* draw this entire segment */ 03335 } 03336 } while (oct != endoct); 03337 03338 /* so now we have what octants to draw and when to draw them. all that's left is the actual raster code. */ 03339 03340 /* Lock surface */ 03341 if (SDL_MUSTLOCK(dst)) { 03342 if (SDL_LockSurface(dst) < 0) { 03343 return (-1); 03344 } 03345 } 03346 03347 /* 03348 * Draw arc 03349 */ 03350 result = 0; 03351 03352 /* 03353 * Alpha Check 03354 */ 03355 if ((color & 255) == 255) { 03356 03357 /* 03358 * No Alpha - direct memory writes 03359 */ 03360 03361 /* 03362 * Setup color 03363 */ 03364 colorptr = (Uint8 *) & color; 03365 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 03366 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 03367 } else { 03368 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 03369 } 03370 03371 /* 03372 * Draw 03373 */ 03374 do { 03375 ypcy = y + cy; 03376 ymcy = y - cy; 03377 if (cx > 0) { 03378 xpcx = x + cx; 03379 xmcx = x - cx; 03380 if (drawoct & 4) result |= fastPixelColorNolock(dst, xmcx, ypcy, color); 03381 if (drawoct & 2) result |= fastPixelColorNolock(dst, xpcx, ypcy, color); 03382 if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color); 03383 if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color); 03384 } else { 03385 if (drawoct & 6) result |= fastPixelColorNolock(dst, x, ypcy, color); 03386 if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); 03387 } 03388 03389 xpcy = x + cy; 03390 xmcy = x - cy; 03391 if (cx > 0 && cx != cy) { 03392 ypcx = y + cx; 03393 ymcx = y - cx; 03394 if (drawoct & 8) result |= fastPixelColorNolock(dst, xmcy, ypcx, color); 03395 if (drawoct & 1) result |= fastPixelColorNolock(dst, xpcy, ypcx, color); 03396 if (drawoct & 16) result |= fastPixelColorNolock(dst, xmcy, ymcx, color); 03397 if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color); 03398 } else if (cx == 0) { 03399 if (drawoct & 24) result |= fastPixelColorNolock(dst, xmcy, y, color); 03400 if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); 03401 } 03402 03403 /* 03404 * Update whether we're drawing an octant 03405 */ 03406 if (stopval_start == cx) { 03407 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct); 03408 else drawoct |= (1 << startoct); 03409 } 03410 if (stopval_end == cx) { 03411 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct); 03412 else drawoct |= (1 << endoct); 03413 } 03414 03415 /* 03416 * Update pixels 03417 */ 03418 if (df < 0) { 03419 df += d_e; 03420 d_e += 2; 03421 d_se += 2; 03422 } else { 03423 df += d_se; 03424 d_e += 2; 03425 d_se += 4; 03426 cy--; 03427 } 03428 cx++; 03429 } while (cx <= cy); 03430 03431 /* 03432 * Unlock surface 03433 */ 03434 SDL_UnlockSurface(dst); 03435 03436 } else { 03437 03438 /* 03439 * Using Alpha - blended pixel blits 03440 */ 03441 03442 do { 03443 ypcy = y + cy; 03444 ymcy = y - cy; 03445 if (cx > 0) { 03446 xpcx = x + cx; 03447 xmcx = x - cx; 03448 03449 if (drawoct & 4) result |= pixelColorNolock(dst, xmcx, ypcy, color); 03450 if (drawoct & 2) result |= pixelColorNolock(dst, xpcx, ypcy, color); 03451 if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color); 03452 if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color); 03453 } else { 03454 if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color); 03455 if (drawoct & 6) result |= pixelColorNolock(dst, x, ypcy, color); 03456 } 03457 03458 xpcy = x + cy; 03459 xmcy = x - cy; 03460 if (cx > 0 && cx != cy) { 03461 ypcx = y + cx; 03462 ymcx = y - cx; 03463 if (drawoct & 8) result |= pixelColorNolock(dst, xmcy, ypcx, color); 03464 if (drawoct & 1) result |= pixelColorNolock(dst, xpcy, ypcx, color); 03465 if (drawoct & 16) result |= pixelColorNolock(dst, xmcy, ymcx, color); 03466 if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color); 03467 } else if (cx == 0) { 03468 if (drawoct & 24) result |= pixelColorNolock(dst, xmcy, y, color); 03469 if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color); 03470 } 03471 03472 /* 03473 * Update whether we're drawing an octant 03474 */ 03475 if (stopval_start == cx) { 03476 if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct); 03477 else drawoct |= (1 << startoct); 03478 } 03479 if (stopval_end == cx) { 03480 if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct); 03481 else drawoct |= (1 << endoct); 03482 } 03483 03484 /* 03485 * Update pixels 03486 */ 03487 if (df < 0) { 03488 df += d_e; 03489 d_e += 2; 03490 d_se += 2; 03491 } else { 03492 df += d_se; 03493 d_e += 2; 03494 d_se += 4; 03495 cy--; 03496 } 03497 cx++; 03498 } while (cx <= cy); 03499 03500 } /* Alpha check */ 03501 03502 /* Unlock surface */ 03503 if (SDL_MUSTLOCK(dst)) { 03504 SDL_UnlockSurface(dst); 03505 } 03506 03507 return (result); 03508 } 03509 03526 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03527 { 03528 /* 03529 * Draw 03530 */ 03531 return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03532 } 03533 03534 /* ----- AA Circle */ 03535 03536 03550 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 03551 { 03552 return (aaellipseColor(dst, x, y, rad, rad, color)); 03553 } 03554 03569 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03570 { 03571 /* 03572 * Draw 03573 */ 03574 return (aaellipseColor 03575 (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03576 } 03577 03578 /* ----- Filled Circle */ 03579 03594 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color) 03595 { 03596 Sint16 left, right, top, bottom; 03597 int result; 03598 Sint16 xx, yy, x2, y2; 03599 Sint16 cx = 0; 03600 Sint16 cy = rad; 03601 Sint16 ocx = (Sint16) 0xffff; 03602 Sint16 ocy = (Sint16) 0xffff; 03603 Sint16 df = 1 - rad; 03604 Sint16 d_e = 3; 03605 Sint16 d_se = -2 * rad + 5; 03606 Sint16 xpcx, xmcx, xpcy, xmcy; 03607 Sint16 ypcy, ymcy, ypcx, ymcx; 03608 03609 /* 03610 * Check visibility of clipping rectangle 03611 */ 03612 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03613 return(0); 03614 } 03615 03616 /* 03617 * Sanity check radius 03618 */ 03619 if (rad < 0) { 03620 return (-1); 03621 } 03622 03623 /* 03624 * Special case for rad=0 - draw a point 03625 */ 03626 if (rad == 0) { 03627 return (pixelColor(dst, x, y, color)); 03628 } 03629 03630 /* 03631 * Get circle and clipping boundary and 03632 * test if bounding box of circle is visible 03633 */ 03634 x2 = x + rad; 03635 left = dst->clip_rect.x; 03636 if (x2<left) { 03637 return(0); 03638 } 03639 xx = x - rad; 03640 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03641 if (xx>right) { 03642 return(0); 03643 } 03644 y2 = y + rad; 03645 top = dst->clip_rect.y; 03646 if (y2<top) { 03647 return(0); 03648 } 03649 yy = y - rad; 03650 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03651 if (yy>bottom) { 03652 return(0); 03653 } 03654 03655 /* 03656 * Draw 03657 */ 03658 result = 0; 03659 do { 03660 xpcx = x + cx; 03661 xmcx = x - cx; 03662 xpcy = x + cy; 03663 xmcy = x - cy; 03664 if (ocy != cy) { 03665 if (cy > 0) { 03666 ypcy = y + cy; 03667 ymcy = y - cy; 03668 result |= hlineColor(dst, xmcx, xpcx, ypcy, color); 03669 result |= hlineColor(dst, xmcx, xpcx, ymcy, color); 03670 } else { 03671 result |= hlineColor(dst, xmcx, xpcx, y, color); 03672 } 03673 ocy = cy; 03674 } 03675 if (ocx != cx) { 03676 if (cx != cy) { 03677 if (cx > 0) { 03678 ypcx = y + cx; 03679 ymcx = y - cx; 03680 result |= hlineColor(dst, xmcy, xpcy, ymcx, color); 03681 result |= hlineColor(dst, xmcy, xpcy, ypcx, color); 03682 } else { 03683 result |= hlineColor(dst, xmcy, xpcy, y, color); 03684 } 03685 } 03686 ocx = cx; 03687 } 03688 /* 03689 * Update 03690 */ 03691 if (df < 0) { 03692 df += d_e; 03693 d_e += 2; 03694 d_se += 2; 03695 } else { 03696 df += d_se; 03697 d_e += 2; 03698 d_se += 4; 03699 cy--; 03700 } 03701 cx++; 03702 } while (cx <= cy); 03703 03704 return (result); 03705 } 03706 03721 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 03722 { 03723 /* 03724 * Draw 03725 */ 03726 return (filledCircleColor 03727 (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 03728 } 03729 03730 /* ----- Ellipse */ 03731 03747 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 03748 { 03749 Sint16 left, right, top, bottom; 03750 int result; 03751 Sint16 xx, yy, x2, y2; 03752 int ix, iy; 03753 int h, i, j, k; 03754 int oh, oi, oj, ok; 03755 int xmh, xph, ypk, ymk; 03756 int xmi, xpi, ymj, ypj; 03757 int xmj, xpj, ymi, ypi; 03758 int xmk, xpk, ymh, yph; 03759 Uint8 *colorptr; 03760 03761 /* 03762 * Check visibility of clipping rectangle 03763 */ 03764 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 03765 return(0); 03766 } 03767 03768 /* 03769 * Sanity check radii 03770 */ 03771 if ((rx < 0) || (ry < 0)) { 03772 return (-1); 03773 } 03774 03775 /* 03776 * Special case for rx=0 - draw a vline 03777 */ 03778 if (rx == 0) { 03779 return (vlineColor(dst, x, y - ry, y + ry, color)); 03780 } 03781 /* 03782 * Special case for ry=0 - draw a hline 03783 */ 03784 if (ry == 0) { 03785 return (hlineColor(dst, x - rx, x + rx, y, color)); 03786 } 03787 03788 /* 03789 * Get circle and clipping boundary and 03790 * test if bounding box of circle is visible 03791 */ 03792 x2 = x + rx; 03793 left = dst->clip_rect.x; 03794 if (x2<left) { 03795 return(0); 03796 } 03797 xx = x - rx; 03798 right = dst->clip_rect.x + dst->clip_rect.w - 1; 03799 if (xx>right) { 03800 return(0); 03801 } 03802 y2 = y + ry; 03803 top = dst->clip_rect.y; 03804 if (y2<top) { 03805 return(0); 03806 } 03807 yy = y - ry; 03808 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 03809 if (yy>bottom) { 03810 return(0); 03811 } 03812 03813 /* 03814 * Init vars 03815 */ 03816 oh = oi = oj = ok = 0xFFFF; 03817 03818 /* 03819 * Draw 03820 */ 03821 result = 0; 03822 03823 /* Lock surface */ 03824 if (SDL_MUSTLOCK(dst)) { 03825 if (SDL_LockSurface(dst) < 0) { 03826 return (-1); 03827 } 03828 } 03829 03830 /* 03831 * Check alpha 03832 */ 03833 if ((color & 255) == 255) { 03834 03835 /* 03836 * No Alpha - direct memory writes 03837 */ 03838 03839 /* 03840 * Setup color 03841 */ 03842 colorptr = (Uint8 *) & color; 03843 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) { 03844 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]); 03845 } else { 03846 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]); 03847 } 03848 03849 03850 if (rx > ry) { 03851 ix = 0; 03852 iy = rx * 64; 03853 03854 do { 03855 h = (ix + 32) >> 6; 03856 i = (iy + 32) >> 6; 03857 j = (h * ry) / rx; 03858 k = (i * ry) / rx; 03859 03860 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) { 03861 xph = x + h; 03862 xmh = x - h; 03863 if (k > 0) { 03864 ypk = y + k; 03865 ymk = y - k; 03866 result |= fastPixelColorNolock(dst, xmh, ypk, color); 03867 result |= fastPixelColorNolock(dst, xph, ypk, color); 03868 result |= fastPixelColorNolock(dst, xmh, ymk, color); 03869 result |= fastPixelColorNolock(dst, xph, ymk, color); 03870 } else { 03871 result |= fastPixelColorNolock(dst, xmh, y, color); 03872 result |= fastPixelColorNolock(dst, xph, y, color); 03873 } 03874 ok = k; 03875 xpi = x + i; 03876 xmi = x - i; 03877 if (j > 0) { 03878 ypj = y + j; 03879 ymj = y - j; 03880 result |= fastPixelColorNolock(dst, xmi, ypj, color); 03881 result |= fastPixelColorNolock(dst, xpi, ypj, color); 03882 result |= fastPixelColorNolock(dst, xmi, ymj, color); 03883 result |= fastPixelColorNolock(dst, xpi, ymj, color); 03884 } else { 03885 result |= fastPixelColorNolock(dst, xmi, y, color); 03886 result |= fastPixelColorNolock(dst, xpi, y, color); 03887 } 03888 oj = j; 03889 } 03890 03891 ix = ix + iy / rx; 03892 iy = iy - ix / rx; 03893 03894 } while (i > h); 03895 } else { 03896 ix = 0; 03897 iy = ry * 64; 03898 03899 do { 03900 h = (ix + 32) >> 6; 03901 i = (iy + 32) >> 6; 03902 j = (h * rx) / ry; 03903 k = (i * rx) / ry; 03904 03905 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) { 03906 xmj = x - j; 03907 xpj = x + j; 03908 if (i > 0) { 03909 ypi = y + i; 03910 ymi = y - i; 03911 result |= fastPixelColorNolock(dst, xmj, ypi, color); 03912 result |= fastPixelColorNolock(dst, xpj, ypi, color); 03913 result |= fastPixelColorNolock(dst, xmj, ymi, color); 03914 result |= fastPixelColorNolock(dst, xpj, ymi, color); 03915 } else { 03916 result |= fastPixelColorNolock(dst, xmj, y, color); 03917 result |= fastPixelColorNolock(dst, xpj, y, color); 03918 } 03919 oi = i; 03920 xmk = x - k; 03921 xpk = x + k; 03922 if (h > 0) { 03923 yph = y + h; 03924 ymh = y - h; 03925 result |= fastPixelColorNolock(dst, xmk, yph, color); 03926 result |= fastPixelColorNolock(dst, xpk, yph, color); 03927 result |= fastPixelColorNolock(dst, xmk, ymh, color); 03928 result |= fastPixelColorNolock(dst, xpk, ymh, color); 03929 } else { 03930 result |= fastPixelColorNolock(dst, xmk, y, color); 03931 result |= fastPixelColorNolock(dst, xpk, y, color); 03932 } 03933 oh = h; 03934 } 03935 03936 ix = ix + iy / ry; 03937 iy = iy - ix / ry; 03938 03939 } while (i > h); 03940 } 03941 03942 } else { 03943 03944 if (rx > ry) { 03945 ix = 0; 03946 iy = rx * 64; 03947 03948 do { 03949 h = (ix + 32) >> 6; 03950 i = (iy + 32) >> 6; 03951 j = (h * ry) / rx; 03952 k = (i * ry) / rx; 03953 03954 if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) { 03955 xph = x + h; 03956 xmh = x - h; 03957 if (k > 0) { 03958 ypk = y + k; 03959 ymk = y - k; 03960 result |= pixelColorNolock (dst, xmh, ypk, color); 03961 result |= pixelColorNolock (dst, xph, ypk, color); 03962 result |= pixelColorNolock (dst, xmh, ymk, color); 03963 result |= pixelColorNolock (dst, xph, ymk, color); 03964 } else { 03965 result |= pixelColorNolock (dst, xmh, y, color); 03966 result |= pixelColorNolock (dst, xph, y, color); 03967 } 03968 ok = k; 03969 xpi = x + i; 03970 xmi = x - i; 03971 if (j > 0) { 03972 ypj = y + j; 03973 ymj = y - j; 03974 result |= pixelColorNolock (dst, xmi, ypj, color); 03975 result |= pixelColorNolock (dst, xpi, ypj, color); 03976 result |= pixelColorNolock (dst, xmi, ymj, color); 03977 result |= pixelColor(dst, xpi, ymj, color); 03978 } else { 03979 result |= pixelColorNolock (dst, xmi, y, color); 03980 result |= pixelColorNolock (dst, xpi, y, color); 03981 } 03982 oj = j; 03983 } 03984 03985 ix = ix + iy / rx; 03986 iy = iy - ix / rx; 03987 03988 } while (i > h); 03989 } else { 03990 ix = 0; 03991 iy = ry * 64; 03992 03993 do { 03994 h = (ix + 32) >> 6; 03995 i = (iy + 32) >> 6; 03996 j = (h * rx) / ry; 03997 k = (i * rx) / ry; 03998 03999 if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) { 04000 xmj = x - j; 04001 xpj = x + j; 04002 if (i > 0) { 04003 ypi = y + i; 04004 ymi = y - i; 04005 result |= pixelColorNolock (dst, xmj, ypi, color); 04006 result |= pixelColorNolock (dst, xpj, ypi, color); 04007 result |= pixelColorNolock (dst, xmj, ymi, color); 04008 result |= pixelColorNolock (dst, xpj, ymi, color); 04009 } else { 04010 result |= pixelColorNolock (dst, xmj, y, color); 04011 result |= pixelColorNolock (dst, xpj, y, color); 04012 } 04013 oi = i; 04014 xmk = x - k; 04015 xpk = x + k; 04016 if (h > 0) { 04017 yph = y + h; 04018 ymh = y - h; 04019 result |= pixelColorNolock (dst, xmk, yph, color); 04020 result |= pixelColorNolock (dst, xpk, yph, color); 04021 result |= pixelColorNolock (dst, xmk, ymh, color); 04022 result |= pixelColorNolock (dst, xpk, ymh, color); 04023 } else { 04024 result |= pixelColorNolock (dst, xmk, y, color); 04025 result |= pixelColorNolock (dst, xpk, y, color); 04026 } 04027 oh = h; 04028 } 04029 04030 ix = ix + iy / ry; 04031 iy = iy - ix / ry; 04032 04033 } while (i > h); 04034 } 04035 04036 } /* Alpha check */ 04037 04038 /* Unlock surface */ 04039 if (SDL_MUSTLOCK(dst)) { 04040 SDL_UnlockSurface(dst); 04041 } 04042 04043 return (result); 04044 } 04045 04061 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04062 { 04063 /* 04064 * Draw 04065 */ 04066 return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04067 } 04068 04069 /* ----- AA Ellipse */ 04070 04086 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 04087 { 04088 Sint16 left, right, top, bottom; 04089 Sint16 xx1, yy1, x2, y2; 04090 int i; 04091 int a2, b2, ds, dt, dxt, t, s, d; 04092 Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2; 04093 float cp; 04094 double sab; 04095 Uint8 weight, iweight; 04096 int result; 04097 04098 /* 04099 * Check visibility of clipping rectangle 04100 */ 04101 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04102 return(0); 04103 } 04104 04105 /* 04106 * Sanity check radii 04107 */ 04108 if ((rx < 0) || (ry < 0)) { 04109 return (-1); 04110 } 04111 04112 /* 04113 * Special case for rx=0 - draw a vline 04114 */ 04115 if (rx == 0) { 04116 return (vlineColor(dst, x, y - ry, y + ry, color)); 04117 } 04118 /* 04119 * Special case for ry=0 - draw an hline 04120 */ 04121 if (ry == 0) { 04122 return (hlineColor(dst, x - rx, x + rx, y, color)); 04123 } 04124 04125 /* 04126 * Get circle and clipping boundary and 04127 * test if bounding box of circle is visible 04128 */ 04129 x2 = x + rx; 04130 left = dst->clip_rect.x; 04131 if (x2<left) { 04132 return(0); 04133 } 04134 xx1 = x - rx; 04135 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04136 if (xx1>right) { 04137 return(0); 04138 } 04139 y2 = y + ry; 04140 top = dst->clip_rect.y; 04141 if (y2<top) { 04142 return(0); 04143 } 04144 yy1 = y - ry; 04145 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04146 if (yy1>bottom) { 04147 return(0); 04148 } 04149 04150 /* Variable setup */ 04151 a2 = rx * rx; 04152 b2 = ry * ry; 04153 04154 ds = 2 * a2; 04155 dt = 2 * b2; 04156 04157 xc2 = 2 * x; 04158 yc2 = 2 * y; 04159 04160 sab = sqrt(a2 + b2); 04161 od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */ 04162 dxt = (Sint16)lrint((double)a2 / sab) + od; 04163 04164 t = 0; 04165 s = -2 * a2 * ry; 04166 d = 0; 04167 04168 xp = x; 04169 yp = y - ry; 04170 04171 /* Lock surface */ 04172 if (SDL_MUSTLOCK(dst)) { 04173 if (SDL_LockSurface(dst) < 0) { 04174 return (-1); 04175 } 04176 } 04177 04178 /* Draw */ 04179 result = 0; 04180 04181 /* "End points" */ 04182 result |= pixelColorNolock(dst, xp, yp, color); 04183 result |= pixelColorNolock(dst, xc2 - xp, yp, color); 04184 result |= pixelColorNolock(dst, xp, yc2 - yp, color); 04185 result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color); 04186 04187 for (i = 1; i <= dxt; i++) { 04188 xp--; 04189 d += t - b2; 04190 04191 if (d >= 0) 04192 ys = yp - 1; 04193 else if ((d - s - a2) > 0) { 04194 if ((2 * d - s - a2) >= 0) 04195 ys = yp + 1; 04196 else { 04197 ys = yp; 04198 yp++; 04199 d -= s + a2; 04200 s += ds; 04201 } 04202 } else { 04203 yp++; 04204 ys = yp + 1; 04205 d -= s + a2; 04206 s += ds; 04207 } 04208 04209 t -= dt; 04210 04211 /* Calculate alpha */ 04212 if (s != 0.0) { 04213 cp = abs(d) / abs(s); 04214 if (cp > 1.0) { 04215 cp = 1.0; 04216 } 04217 } else { 04218 cp = 1.0; 04219 } 04220 04221 /* Calculate weights */ 04222 weight = (Uint8) (cp * 255); 04223 iweight = 255 - weight; 04224 04225 /* Upper half */ 04226 xx = xc2 - xp; 04227 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight); 04228 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight); 04229 04230 result |= pixelColorWeightNolock(dst, xp, ys, color, weight); 04231 result |= pixelColorWeightNolock(dst, xx, ys, color, weight); 04232 04233 /* Lower half */ 04234 yy = yc2 - yp; 04235 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight); 04236 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight); 04237 04238 yy = yc2 - ys; 04239 result |= pixelColorWeightNolock(dst, xp, yy, color, weight); 04240 result |= pixelColorWeightNolock(dst, xx, yy, color, weight); 04241 } 04242 04243 /* Replaces original approximation code dyt = abs(yp - yc); */ 04244 dyt = (Sint16)lrint((double)b2 / sab ) + od; 04245 04246 for (i = 1; i <= dyt; i++) { 04247 yp++; 04248 d -= s + a2; 04249 04250 if (d <= 0) 04251 xs = xp + 1; 04252 else if ((d + t - b2) < 0) { 04253 if ((2 * d + t - b2) <= 0) 04254 xs = xp - 1; 04255 else { 04256 xs = xp; 04257 xp--; 04258 d += t - b2; 04259 t -= dt; 04260 } 04261 } else { 04262 xp--; 04263 xs = xp - 1; 04264 d += t - b2; 04265 t -= dt; 04266 } 04267 04268 s += ds; 04269 04270 /* Calculate alpha */ 04271 if (t != 0.0) { 04272 cp = abs(d) / abs(t); 04273 if (cp > 1.0) { 04274 cp = 1.0; 04275 } 04276 } else { 04277 cp = 1.0; 04278 } 04279 04280 /* Calculate weight */ 04281 weight = (Uint8) (cp * 255); 04282 iweight = 255 - weight; 04283 04284 /* Left half */ 04285 xx = xc2 - xp; 04286 yy = yc2 - yp; 04287 result |= pixelColorWeightNolock(dst, xp, yp, color, iweight); 04288 result |= pixelColorWeightNolock(dst, xx, yp, color, iweight); 04289 04290 result |= pixelColorWeightNolock(dst, xp, yy, color, iweight); 04291 result |= pixelColorWeightNolock(dst, xx, yy, color, iweight); 04292 04293 /* Right half */ 04294 xx = xc2 - xs; 04295 result |= pixelColorWeightNolock(dst, xs, yp, color, weight); 04296 result |= pixelColorWeightNolock(dst, xx, yp, color, weight); 04297 04298 result |= pixelColorWeightNolock(dst, xs, yy, color, weight); 04299 result |= pixelColorWeightNolock(dst, xx, yy, color, weight); 04300 04301 } 04302 04303 /* Unlock surface */ 04304 if (SDL_MUSTLOCK(dst)) { 04305 SDL_UnlockSurface(dst); 04306 } 04307 04308 return (result); 04309 } 04310 04326 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04327 { 04328 /* 04329 * Draw 04330 */ 04331 return (aaellipseColor 04332 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04333 } 04334 04335 /* ---- Filled Ellipse */ 04336 04337 /* Note: */ 04338 /* Based on algorithm from sge library with multiple-hline draw removal */ 04339 /* and other speedup changes. */ 04340 04356 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color) 04357 { 04358 Sint16 left, right, top, bottom; 04359 int result; 04360 Sint16 xx, yy, x2, y2; 04361 int ix, iy; 04362 int h, i, j, k; 04363 int oh, oi, oj, ok; 04364 int xmh, xph; 04365 int xmi, xpi; 04366 int xmj, xpj; 04367 int xmk, xpk; 04368 04369 /* 04370 * Check visibility of clipping rectangle 04371 */ 04372 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04373 return(0); 04374 } 04375 04376 /* 04377 * Sanity check radii 04378 */ 04379 if ((rx < 0) || (ry < 0)) { 04380 return (-1); 04381 } 04382 04383 /* 04384 * Special case for rx=0 - draw a vline 04385 */ 04386 if (rx == 0) { 04387 return (vlineColor(dst, x, y - ry, y + ry, color)); 04388 } 04389 /* 04390 * Special case for ry=0 - draw a hline 04391 */ 04392 if (ry == 0) { 04393 return (hlineColor(dst, x - rx, x + rx, y, color)); 04394 } 04395 04396 /* 04397 * Get circle and clipping boundary and 04398 * test if bounding box of circle is visible 04399 */ 04400 x2 = x + rx; 04401 left = dst->clip_rect.x; 04402 if (x2<left) { 04403 return(0); 04404 } 04405 xx = x - rx; 04406 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04407 if (xx>right) { 04408 return(0); 04409 } 04410 y2 = y + ry; 04411 top = dst->clip_rect.y; 04412 if (y2<top) { 04413 return(0); 04414 } 04415 yy = y - ry; 04416 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04417 if (yy>bottom) { 04418 return(0); 04419 } 04420 04421 /* 04422 * Init vars 04423 */ 04424 oh = oi = oj = ok = 0xFFFF; 04425 04426 /* 04427 * Draw 04428 */ 04429 result = 0; 04430 if (rx > ry) { 04431 ix = 0; 04432 iy = rx * 64; 04433 04434 do { 04435 h = (ix + 32) >> 6; 04436 i = (iy + 32) >> 6; 04437 j = (h * ry) / rx; 04438 k = (i * ry) / rx; 04439 04440 if ((ok != k) && (oj != k)) { 04441 xph = x + h; 04442 xmh = x - h; 04443 if (k > 0) { 04444 result |= hlineColor(dst, xmh, xph, y + k, color); 04445 result |= hlineColor(dst, xmh, xph, y - k, color); 04446 } else { 04447 result |= hlineColor(dst, xmh, xph, y, color); 04448 } 04449 ok = k; 04450 } 04451 if ((oj != j) && (ok != j) && (k != j)) { 04452 xmi = x - i; 04453 xpi = x + i; 04454 if (j > 0) { 04455 result |= hlineColor(dst, xmi, xpi, y + j, color); 04456 result |= hlineColor(dst, xmi, xpi, y - j, color); 04457 } else { 04458 result |= hlineColor(dst, xmi, xpi, y, color); 04459 } 04460 oj = j; 04461 } 04462 04463 ix = ix + iy / rx; 04464 iy = iy - ix / rx; 04465 04466 } while (i > h); 04467 } else { 04468 ix = 0; 04469 iy = ry * 64; 04470 04471 do { 04472 h = (ix + 32) >> 6; 04473 i = (iy + 32) >> 6; 04474 j = (h * rx) / ry; 04475 k = (i * rx) / ry; 04476 04477 if ((oi != i) && (oh != i)) { 04478 xmj = x - j; 04479 xpj = x + j; 04480 if (i > 0) { 04481 result |= hlineColor(dst, xmj, xpj, y + i, color); 04482 result |= hlineColor(dst, xmj, xpj, y - i, color); 04483 } else { 04484 result |= hlineColor(dst, xmj, xpj, y, color); 04485 } 04486 oi = i; 04487 } 04488 if ((oh != h) && (oi != h) && (i != h)) { 04489 xmk = x - k; 04490 xpk = x + k; 04491 if (h > 0) { 04492 result |= hlineColor(dst, xmk, xpk, y + h, color); 04493 result |= hlineColor(dst, xmk, xpk, y - h, color); 04494 } else { 04495 result |= hlineColor(dst, xmk, xpk, y, color); 04496 } 04497 oh = h; 04498 } 04499 04500 ix = ix + iy / ry; 04501 iy = iy - ix / ry; 04502 04503 } while (i > h); 04504 } 04505 04506 return (result); 04507 } 04508 04524 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04525 { 04526 /* 04527 * Draw 04528 */ 04529 return (filledEllipseColor 04530 (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 04531 } 04532 04533 /* ----- pie */ 04534 04551 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled) 04552 { 04553 Sint16 left, right, top, bottom; 04554 Sint16 xx, yy, x2, y2; 04555 int result; 04556 double angle, start_angle, end_angle; 04557 double deltaAngle; 04558 double dr; 04559 int numpoints, i; 04560 Sint16 *vx, *vy; 04561 04562 /* 04563 * Check visibility of clipping rectangle 04564 */ 04565 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04566 return(0); 04567 } 04568 04569 /* 04570 * Sanity check radii 04571 */ 04572 if (rad < 0) { 04573 return (-1); 04574 } 04575 04576 /* 04577 * Fixup angles 04578 */ 04579 start = start % 360; 04580 end = end % 360; 04581 04582 /* 04583 * Special case for rad=0 - draw a point 04584 */ 04585 if (rad == 0) { 04586 return (pixelColor(dst, x, y, color)); 04587 } 04588 04589 /* 04590 * Clip against circle, not pie (not 100% optimal). 04591 * Get pie's circle and clipping boundary and 04592 * test if bounding box of circle is visible 04593 */ 04594 x2 = x + rad; 04595 left = dst->clip_rect.x; 04596 if (x2<left) { 04597 return(0); 04598 } 04599 xx = x - rad; 04600 right = dst->clip_rect.x + dst->clip_rect.w - 1; 04601 if (xx>right) { 04602 return(0); 04603 } 04604 y2 = y + rad; 04605 top = dst->clip_rect.y; 04606 if (y2<top) { 04607 return(0); 04608 } 04609 yy = y - rad; 04610 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 04611 if (yy>bottom) { 04612 return(0); 04613 } 04614 04615 /* 04616 * Variable setup 04617 */ 04618 dr = (double) rad; 04619 deltaAngle = 3.0 / dr; 04620 start_angle = (double) start *(2.0 * M_PI / 360.0); 04621 end_angle = (double) end *(2.0 * M_PI / 360.0); 04622 if (start > end) { 04623 end_angle += (2.0 * M_PI); 04624 } 04625 04626 /* We will always have at least 2 points */ 04627 numpoints = 2; 04628 04629 /* Count points (rather than calculating it) */ 04630 angle = start_angle; 04631 while (angle < end_angle) { 04632 angle += deltaAngle; 04633 numpoints++; 04634 } 04635 04636 /* Allocate combined vertex array */ 04637 vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints); 04638 if (vx == NULL) { 04639 return (-1); 04640 } 04641 04642 /* Update point to start of vy */ 04643 vy += numpoints; 04644 04645 /* Center */ 04646 vx[0] = x; 04647 vy[0] = y; 04648 04649 /* First vertex */ 04650 angle = start_angle; 04651 vx[1] = x + (int) (dr * cos(angle)); 04652 vy[1] = y + (int) (dr * sin(angle)); 04653 04654 if (numpoints<3) 04655 { 04656 result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color); 04657 } 04658 else 04659 { 04660 /* Calculate other vertices */ 04661 i = 2; 04662 angle = start_angle; 04663 while (angle < end_angle) { 04664 angle += deltaAngle; 04665 if (angle>end_angle) 04666 { 04667 angle = end_angle; 04668 } 04669 vx[i] = x + (int) (dr * cos(angle)); 04670 vy[i] = y + (int) (dr * sin(angle)); 04671 i++; 04672 } 04673 04674 /* Draw */ 04675 if (filled) { 04676 result = filledPolygonColor(dst, vx, vy, numpoints, color); 04677 } else { 04678 result = polygonColor(dst, vx, vy, numpoints, color); 04679 } 04680 } 04681 04682 /* Free combined vertex array */ 04683 free(vx); 04684 04685 return (result); 04686 } 04687 04701 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04702 Sint16 start, Sint16 end, Uint32 color) 04703 { 04704 return (_pieColor(dst, x, y, rad, start, end, color, 0)); 04705 04706 } 04707 04724 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04725 Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04726 { 04727 return (_pieColor(dst, x, y, rad, start, end, 04728 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0)); 04729 04730 } 04731 04745 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color) 04746 { 04747 return (_pieColor(dst, x, y, rad, start, end, color, 1)); 04748 } 04749 04766 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, 04767 Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04768 { 04769 return (_pieColor(dst, x, y, rad, start, end, 04770 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1)); 04771 } 04772 04773 /* ------ Trigon */ 04774 04791 int trigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04792 { 04793 Sint16 vx[3]; 04794 Sint16 vy[3]; 04795 04796 vx[0]=x; 04797 vx[1]=x2; 04798 vx[2]=x3; 04799 vy[0]=y; 04800 vy[1]=y2; 04801 vy[2]=y3; 04802 04803 return(polygonColor(dst,vx,vy,3,color)); 04804 } 04805 04823 int trigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04824 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04825 { 04826 Sint16 vx[3]; 04827 Sint16 vy[3]; 04828 04829 vx[0]=x; 04830 vx[1]=x2; 04831 vx[2]=x3; 04832 vy[0]=y; 04833 vy[1]=y2; 04834 vy[2]=y3; 04835 04836 return(polygonRGBA(dst,vx,vy,3,r,g,b,a)); 04837 } 04838 04839 /* ------ AA-Trigon */ 04840 04857 int aatrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04858 { 04859 Sint16 vx[3]; 04860 Sint16 vy[3]; 04861 04862 vx[0]=x; 04863 vx[1]=x2; 04864 vx[2]=x3; 04865 vy[0]=y; 04866 vy[1]=y2; 04867 vy[2]=y3; 04868 04869 return(aapolygonColor(dst,vx,vy,3,color)); 04870 } 04871 04889 int aatrigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04890 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04891 { 04892 Sint16 vx[3]; 04893 Sint16 vy[3]; 04894 04895 vx[0]=x; 04896 vx[1]=x2; 04897 vx[2]=x3; 04898 vy[0]=y; 04899 vy[1]=y2; 04900 vy[2]=y3; 04901 04902 return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a)); 04903 } 04904 04905 /* ------ Filled Trigon */ 04906 04923 int filledTrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color) 04924 { 04925 Sint16 vx[3]; 04926 Sint16 vy[3]; 04927 04928 vx[0]=x; 04929 vx[1]=x2; 04930 vx[2]=x3; 04931 vy[0]=y; 04932 vy[1]=y2; 04933 vy[2]=y3; 04934 04935 return(filledPolygonColor(dst,vx,vy,3,color)); 04936 } 04937 04957 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, 04958 Uint8 r, Uint8 g, Uint8 b, Uint8 a) 04959 { 04960 Sint16 vx[3]; 04961 Sint16 vy[3]; 04962 04963 vx[0]=x; 04964 vx[1]=x2; 04965 vx[2]=x3; 04966 vy[0]=y; 04967 vy[1]=y2; 04968 vy[2]=y3; 04969 04970 return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a)); 04971 } 04972 04973 /* ---- Polygon */ 04974 04986 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 04987 { 04988 int result; 04989 int i; 04990 const Sint16 *x, *y, *x2, *y2; 04991 04992 /* 04993 * Check visibility of clipping rectangle 04994 */ 04995 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 04996 return(0); 04997 } 04998 04999 /* 05000 * Vertex array NULL check 05001 */ 05002 if (vx == NULL) { 05003 return (-1); 05004 } 05005 if (vy == NULL) { 05006 return (-1); 05007 } 05008 05009 /* 05010 * Sanity check 05011 */ 05012 if (n < 3) { 05013 return (-1); 05014 } 05015 05016 /* 05017 * Pointer setup 05018 */ 05019 x = x2 = vx; 05020 y = y2 = vy; 05021 x2++; 05022 y2++; 05023 05024 /* 05025 * Draw 05026 */ 05027 result = 0; 05028 for (i = 1; i < n; i++) { 05029 result |= lineColor(dst, *x, *y, *x2, *y2, color); 05030 x = x2; 05031 y = y2; 05032 x2++; 05033 y2++; 05034 } 05035 result |= lineColor(dst, *x, *y, *vx, *vy, color); 05036 05037 return (result); 05038 } 05039 05054 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05055 { 05056 /* 05057 * Draw 05058 */ 05059 return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 05060 } 05061 05062 /* ---- AA-Polygon */ 05063 05075 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 05076 { 05077 int result; 05078 int i; 05079 const Sint16 *x, *y, *x2, *y2; 05080 05081 /* 05082 * Check visibility of clipping rectangle 05083 */ 05084 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05085 return(0); 05086 } 05087 05088 /* 05089 * Vertex array NULL check 05090 */ 05091 if (vx == NULL) { 05092 return (-1); 05093 } 05094 if (vy == NULL) { 05095 return (-1); 05096 } 05097 05098 /* 05099 * Sanity check 05100 */ 05101 if (n < 3) { 05102 return (-1); 05103 } 05104 05105 /* 05106 * Pointer setup 05107 */ 05108 x = x2 = vx; 05109 y = y2 = vy; 05110 x2++; 05111 y2++; 05112 05113 /* 05114 * Draw 05115 */ 05116 result = 0; 05117 for (i = 1; i < n; i++) { 05118 result |= _aalineColor(dst, *x, *y, *x2, *y2, color, 0); 05119 x = x2; 05120 y = y2; 05121 x2++; 05122 y2++; 05123 } 05124 result |= _aalineColor(dst, *x, *y, *vx, *vy, color, 0); 05125 05126 return (result); 05127 } 05128 05143 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05144 { 05145 /* 05146 * Draw 05147 */ 05148 return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 05149 } 05150 05151 /* ---- Filled Polygon */ 05152 05161 int _gfxPrimitivesCompareInt(const void *a, const void *b) 05162 { 05163 return (*(const int *) a) - (*(const int *) b); 05164 } 05165 05171 static int *gfxPrimitivesPolyIntsGlobal = NULL; 05172 05178 static int gfxPrimitivesPolyAllocatedGlobal = 0; 05179 05195 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated) 05196 { 05197 int result; 05198 int i; 05199 int y, xa, xb; 05200 int miny, maxy; 05201 int xx, yy; 05202 int x2, y2; 05203 int ind1, ind2; 05204 int ints; 05205 int *gfxPrimitivesPolyInts = NULL; 05206 int gfxPrimitivesPolyAllocated = 0; 05207 05208 /* 05209 * Check visibility of clipping rectangle 05210 */ 05211 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05212 return(0); 05213 } 05214 05215 /* 05216 * Vertex array NULL check 05217 */ 05218 if (vx == NULL) { 05219 return (-1); 05220 } 05221 if (vy == NULL) { 05222 return (-1); 05223 } 05224 05225 /* 05226 * Sanity check number of edges 05227 */ 05228 if (n < 3) { 05229 return -1; 05230 } 05231 05232 /* 05233 * Map polygon cache 05234 */ 05235 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05236 /* Use global cache */ 05237 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; 05238 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; 05239 } else { 05240 /* Use local cache */ 05241 gfxPrimitivesPolyInts = *polyInts; 05242 gfxPrimitivesPolyAllocated = *polyAllocated; 05243 } 05244 05245 /* 05246 * Allocate temp array, only grow array 05247 */ 05248 if (!gfxPrimitivesPolyAllocated) { 05249 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); 05250 gfxPrimitivesPolyAllocated = n; 05251 } else { 05252 if (gfxPrimitivesPolyAllocated < n) { 05253 gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); 05254 gfxPrimitivesPolyAllocated = n; 05255 } 05256 } 05257 05258 /* 05259 * Check temp array 05260 */ 05261 if (gfxPrimitivesPolyInts==NULL) { 05262 gfxPrimitivesPolyAllocated = 0; 05263 } 05264 05265 /* 05266 * Update cache variables 05267 */ 05268 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05269 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; 05270 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; 05271 } else { 05272 *polyInts = gfxPrimitivesPolyInts; 05273 *polyAllocated = gfxPrimitivesPolyAllocated; 05274 } 05275 05276 /* 05277 * Check temp array again 05278 */ 05279 if (gfxPrimitivesPolyInts==NULL) { 05280 return(-1); 05281 } 05282 05283 /* 05284 * Determine Y maxima 05285 */ 05286 miny = vy[0]; 05287 maxy = vy[0]; 05288 for (i = 1; (i < n); i++) { 05289 if (vy[i] < miny) { 05290 miny = vy[i]; 05291 } else if (vy[i] > maxy) { 05292 maxy = vy[i]; 05293 } 05294 } 05295 05296 /* 05297 * Draw, scanning y 05298 */ 05299 result = 0; 05300 for (y = miny; (y <= maxy); y++) { 05301 ints = 0; 05302 for (i = 0; (i < n); i++) { 05303 if (!i) { 05304 ind1 = n - 1; 05305 ind2 = 0; 05306 } else { 05307 ind1 = i - 1; 05308 ind2 = i; 05309 } 05310 yy = vy[ind1]; 05311 y2 = vy[ind2]; 05312 if (yy < y2) { 05313 xx = vx[ind1]; 05314 x2 = vx[ind2]; 05315 } else if (yy > y2) { 05316 y2 = vy[ind1]; 05317 yy = vy[ind2]; 05318 x2 = vx[ind1]; 05319 xx = vx[ind2]; 05320 } else { 05321 continue; 05322 } 05323 if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) { 05324 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx); 05325 } 05326 } 05327 05328 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt); 05329 05330 for (i = 0; (i < ints); i += 2) { 05331 xa = gfxPrimitivesPolyInts[i] + 1; 05332 xa = (xa >> 16) + ((xa & 32768) >> 15); 05333 xb = gfxPrimitivesPolyInts[i+1] - 1; 05334 xb = (xb >> 16) + ((xb & 32768) >> 15); 05335 result |= hlineColor(dst, xa, xb, y, color); 05336 } 05337 } 05338 05339 return (result); 05340 } 05341 05360 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) 05361 { 05362 /* 05363 * Draw 05364 */ 05365 return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated)); 05366 } 05367 05382 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color) 05383 { 05384 /* 05385 * Draw 05386 */ 05387 return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL)); 05388 } 05389 05404 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05405 { 05406 /* 05407 * Draw 05408 */ 05409 return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL)); 05410 } 05411 05425 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy) 05426 { 05427 Sint16 left, right, top, bottom; 05428 Sint16 w; 05429 Sint16 xtmp; 05430 int result = 0; 05431 int texture_x_walker; 05432 int texture_y_start; 05433 SDL_Rect source_rect,dst_rect; 05434 int pixels_written,write_width; 05435 05436 /* 05437 * Check visibility of clipping rectangle 05438 */ 05439 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05440 return(0); 05441 } 05442 05443 /* 05444 * Swap x1, x2 if required to ensure x1<=x2 05445 */ 05446 if (x1 > x2) { 05447 xtmp = x1; 05448 x1 = x2; 05449 x2 = xtmp; 05450 } 05451 05452 /* 05453 * Get clipping boundary and 05454 * check visibility of hline 05455 */ 05456 left = dst->clip_rect.x; 05457 if (x2<left) { 05458 return(0); 05459 } 05460 right = dst->clip_rect.x + dst->clip_rect.w - 1; 05461 if (x1>right) { 05462 return(0); 05463 } 05464 top = dst->clip_rect.y; 05465 bottom = dst->clip_rect.y + dst->clip_rect.h - 1; 05466 if ((y<top) || (y>bottom)) { 05467 return (0); 05468 } 05469 05470 /* 05471 * Clip x 05472 */ 05473 if (x1 < left) { 05474 x1 = left; 05475 } 05476 if (x2 > right) { 05477 x2 = right; 05478 } 05479 05480 /* 05481 * Calculate width to draw 05482 */ 05483 w = x2 - x1 + 1; 05484 05485 /* 05486 * Determine where in the texture we start drawing 05487 */ 05488 texture_x_walker = (x1 - texture_dx) % texture->w; 05489 if (texture_x_walker < 0){ 05490 texture_x_walker = texture->w + texture_x_walker ; 05491 } 05492 05493 texture_y_start = (y + texture_dy) % texture->h; 05494 if (texture_y_start < 0){ 05495 texture_y_start = texture->h + texture_y_start; 05496 } 05497 05498 source_rect.y = texture_y_start; 05499 source_rect.x = texture_x_walker; 05500 source_rect.h = 1; 05501 05502 dst_rect.y = y; 05503 05504 if (w <= texture->w -texture_x_walker){ 05505 source_rect.w = w; 05506 source_rect.x = texture_x_walker; 05507 dst_rect.x= x1; 05508 result = (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0); 05509 } else { 05510 pixels_written = texture->w - texture_x_walker; 05511 source_rect.w = pixels_written; 05512 source_rect.x = texture_x_walker; 05513 dst_rect.x= x1; 05514 result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0); 05515 write_width = texture->w; 05516 05517 source_rect.x = 0; 05518 while (pixels_written < w){ 05519 if (write_width >= w - pixels_written) { 05520 write_width = w - pixels_written; 05521 } 05522 source_rect.w = write_width; 05523 dst_rect.x = x1 + pixels_written; 05524 result |= (SDL_BlitSurface (texture,&source_rect , dst, &dst_rect) == 0); 05525 pixels_written += write_width; 05526 } 05527 } 05528 05529 return result; 05530 } 05531 05555 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, 05556 SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated) 05557 { 05558 int result; 05559 int i; 05560 int y, xa, xb; 05561 int minx,maxx,miny, maxy; 05562 int xx, yy; 05563 int x2, y2; 05564 int ind1, ind2; 05565 int ints; 05566 int *gfxPrimitivesPolyInts = NULL; 05567 int gfxPrimitivesPolyAllocated = 0; 05568 05569 /* 05570 * Check visibility of clipping rectangle 05571 */ 05572 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) { 05573 return(0); 05574 } 05575 05576 /* 05577 * Sanity check number of edges 05578 */ 05579 if (n < 3) { 05580 return -1; 05581 } 05582 05583 /* 05584 * Map polygon cache 05585 */ 05586 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05587 /* Use global cache */ 05588 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal; 05589 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal; 05590 } else { 05591 /* Use local cache */ 05592 gfxPrimitivesPolyInts = *polyInts; 05593 gfxPrimitivesPolyAllocated = *polyAllocated; 05594 } 05595 05596 /* 05597 * Allocate temp array, only grow array 05598 */ 05599 if (!gfxPrimitivesPolyAllocated) { 05600 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n); 05601 gfxPrimitivesPolyAllocated = n; 05602 } else { 05603 if (gfxPrimitivesPolyAllocated < n) { 05604 gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n); 05605 gfxPrimitivesPolyAllocated = n; 05606 } 05607 } 05608 05609 /* 05610 * Check temp array 05611 */ 05612 if (gfxPrimitivesPolyInts==NULL) { 05613 gfxPrimitivesPolyAllocated = 0; 05614 } 05615 05616 /* 05617 * Update cache variables 05618 */ 05619 if ((polyInts==NULL) || (polyAllocated==NULL)) { 05620 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts; 05621 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated; 05622 } else { 05623 *polyInts = gfxPrimitivesPolyInts; 05624 *polyAllocated = gfxPrimitivesPolyAllocated; 05625 } 05626 05627 /* 05628 * Check temp array again 05629 */ 05630 if (gfxPrimitivesPolyInts==NULL) { 05631 return(-1); 05632 } 05633 05634 /* 05635 * Determine X,Y minima,maxima 05636 */ 05637 miny = vy[0]; 05638 maxy = vy[0]; 05639 minx = vx[0]; 05640 maxx = vx[0]; 05641 for (i = 1; (i < n); i++) { 05642 if (vy[i] < miny) { 05643 miny = vy[i]; 05644 } else if (vy[i] > maxy) { 05645 maxy = vy[i]; 05646 } 05647 if (vx[i] < minx) { 05648 minx = vx[i]; 05649 } else if (vx[i] > maxx) { 05650 maxx = vx[i]; 05651 } 05652 } 05653 if (maxx <0 || minx > dst->w){ 05654 return -1; 05655 } 05656 if (maxy <0 || miny > dst->h){ 05657 return -1; 05658 } 05659 05660 /* 05661 * Draw, scanning y 05662 */ 05663 result = 0; 05664 for (y = miny; (y <= maxy); y++) { 05665 ints = 0; 05666 for (i = 0; (i < n); i++) { 05667 if (!i) { 05668 ind1 = n - 1; 05669 ind2 = 0; 05670 } else { 05671 ind1 = i - 1; 05672 ind2 = i; 05673 } 05674 yy = vy[ind1]; 05675 y2 = vy[ind2]; 05676 if (yy < y2) { 05677 xx = vx[ind1]; 05678 x2 = vx[ind2]; 05679 } else if (yy > y2) { 05680 y2 = vy[ind1]; 05681 yy = vy[ind2]; 05682 x2 = vx[ind1]; 05683 xx = vx[ind2]; 05684 } else { 05685 continue; 05686 } 05687 if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) { 05688 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx); 05689 } 05690 } 05691 05692 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt); 05693 05694 for (i = 0; (i < ints); i += 2) { 05695 xa = gfxPrimitivesPolyInts[i] + 1; 05696 xa = (xa >> 16) + ((xa & 32768) >> 15); 05697 xb = gfxPrimitivesPolyInts[i+1] - 1; 05698 xb = (xb >> 16) + ((xb & 32768) >> 15); 05699 result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy); 05700 } 05701 } 05702 05703 return (result); 05704 } 05705 05722 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy) 05723 { 05724 /* 05725 * Draw 05726 */ 05727 return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL)); 05728 } 05729 05730 05740 double _evaluateBezier (double *data, int ndata, double t) 05741 { 05742 double mu, result; 05743 int n,k,kn,nn,nkn; 05744 double blend,muk,munk; 05745 05746 /* Sanity check bounds */ 05747 if (t<0.0) { 05748 return(data[0]); 05749 } 05750 if (t>=(double)ndata) { 05751 return(data[ndata-1]); 05752 } 05753 05754 /* Adjust t to the range 0.0 to 1.0 */ 05755 mu=t/(double)ndata; 05756 05757 /* Calculate interpolate */ 05758 n=ndata-1; 05759 result=0.0; 05760 muk = 1; 05761 munk = pow(1-mu,(double)n); 05762 for (k=0;k<=n;k++) { 05763 nn = n; 05764 kn = k; 05765 nkn = n - k; 05766 blend = muk * munk; 05767 muk *= mu; 05768 munk /= (1-mu); 05769 while (nn >= 1) { 05770 blend *= nn; 05771 nn--; 05772 if (kn > 1) { 05773 blend /= (double)kn; 05774 kn--; 05775 } 05776 if (nkn > 1) { 05777 blend /= (double)nkn; 05778 nkn--; 05779 } 05780 } 05781 result += data[k] * blend; 05782 } 05783 05784 return (result); 05785 } 05786 05799 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color) 05800 { 05801 int result; 05802 int i; 05803 double *x, *y, t, stepsize; 05804 Sint16 xx, yy, x2, y2; 05805 05806 /* 05807 * Sanity check 05808 */ 05809 if (n < 3) { 05810 return (-1); 05811 } 05812 if (s < 2) { 05813 return (-1); 05814 } 05815 05816 /* 05817 * Variable setup 05818 */ 05819 stepsize=(double)1.0/(double)s; 05820 05821 /* Transfer vertices into float arrays */ 05822 if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) { 05823 return(-1); 05824 } 05825 if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) { 05826 free(x); 05827 return(-1); 05828 } 05829 for (i=0; i<n; i++) { 05830 x[i]=vx[i]; 05831 y[i]=vy[i]; 05832 } 05833 x[n]=vx[0]; 05834 y[n]=vy[0]; 05835 05836 /* 05837 * Draw 05838 */ 05839 result = 0; 05840 t=0.0; 05841 xx=(Sint16)lrint(_evaluateBezier(x,n+1,t)); 05842 yy=(Sint16)lrint(_evaluateBezier(y,n+1,t)); 05843 for (i = 0; i <= (n*s); i++) { 05844 t += stepsize; 05845 x2=_evaluateBezier(x,n,t); 05846 y2=_evaluateBezier(y,n,t); 05847 result |= lineColor(dst, xx, yy, x2, y2, color); 05848 xx = x2; 05849 yy = y2; 05850 } 05851 05852 /* Clean up temporary array */ 05853 free(x); 05854 free(y); 05855 05856 return (result); 05857 } 05858 05874 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 05875 { 05876 /* 05877 * Draw 05878 */ 05879 return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 05880 } 05881 static void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1) 05882 { 05883 int p; 05884 d1 = -d1; 05885 05886 /* 05887 * Lock the surface 05888 */ 05889 if (SDL_MUSTLOCK(m->dst)) { 05890 SDL_LockSurface(m->dst); 05891 } 05892 05893 for (p = 0; p <= m->u; p++) { 05894 05895 pixelColorNolock(m->dst, x, y, m->color); 05896 05897 if (d1 <= m->kt) { 05898 if (m->oct2 == 0) { 05899 x++; 05900 } else { 05901 if (m->quad4 == 0) { 05902 y++; 05903 } else { 05904 y--; 05905 } 05906 } 05907 d1 += m->kv; 05908 } else { 05909 x++; 05910 if (m->quad4 == 0) { 05911 y++; 05912 } else { 05913 y--; 05914 } 05915 d1 += m->kd; 05916 } 05917 } 05918 05919 /* Unlock surface */ 05920 if (SDL_MUSTLOCK(m->dst)) { 05921 SDL_UnlockSurface(m->dst); 05922 } 05923 05924 m->tempx = x; 05925 m->tempy = y; 05926 } 05927 05943 static void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter, 05944 Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by, 05945 Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y) 05946 { 05947 int atemp1, atemp2; 05948 int ftmp1, ftmp2; 05949 Uint16 m1x, m1y, m2x, m2y; 05950 Uint16 fix, fiy, lax, lay, curx, cury; 05951 Uint16 px[4], py[4]; 05952 SDL_gfxBresenhamIterator b; 05953 05954 if (miter > 1) { 05955 if (m->first1x != -32768) { 05956 fix = (m->first1x + m->first2x) / 2; 05957 fiy = (m->first1y + m->first2y) / 2; 05958 lax = (m->last1x + m->last2x) / 2; 05959 lay = (m->last1y + m->last2y) / 2; 05960 curx = (ml1x + ml2x) / 2; 05961 cury = (ml1y + ml2y) / 2; 05962 05963 atemp1 = (fix - curx); 05964 atemp2 = (fiy - cury); 05965 ftmp1 = atemp1 * atemp1 + atemp2 * atemp2; 05966 atemp1 = (lax - curx); 05967 atemp2 = (lay - cury); 05968 ftmp2 = atemp1 * atemp1 + atemp2 * atemp2; 05969 05970 if (ftmp1 <= ftmp2) { 05971 m1x = m->first1x; 05972 m1y = m->first1y; 05973 m2x = m->first2x; 05974 m2y = m->first2y; 05975 } else { 05976 m1x = m->last1x; 05977 m1y = m->last1y; 05978 m2x = m->last2x; 05979 m2y = m->last2y; 05980 } 05981 05982 atemp1 = (m2x - ml2x); 05983 atemp2 = (m2y - ml2y); 05984 ftmp1 = atemp1 * atemp1 + atemp2 * atemp2; 05985 atemp1 = (m2x - ml2bx); 05986 atemp2 = (m2y - ml2by); 05987 ftmp2 = atemp1 * atemp1 + atemp2 * atemp2; 05988 05989 if (ftmp2 >= ftmp1) { 05990 ftmp1 = ml2bx; 05991 ftmp2 = ml2by; 05992 ml2bx = ml2x; 05993 ml2by = ml2y; 05994 ml2x = ftmp1; 05995 ml2y = ftmp2; 05996 ftmp1 = ml1bx; 05997 ftmp2 = ml1by; 05998 ml1bx = ml1x; 05999 ml1by = ml1y; 06000 ml1x = ftmp1; 06001 ml1y = ftmp2; 06002 } 06003 06004 /* 06005 * Lock the surface 06006 */ 06007 if (SDL_MUSTLOCK(m->dst)) { 06008 SDL_LockSurface(m->dst); 06009 } 06010 06011 _bresenhamInitialize(&b, m2x, m2y, m1x, m1y); 06012 do { 06013 pixelColorNolock(m->dst, b.x, b.y, m->color); 06014 } while (_bresenhamIterate(&b)==0); 06015 06016 _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by); 06017 do { 06018 pixelColorNolock(m->dst, b.x, b.y, m->color); 06019 } while (_bresenhamIterate(&b)==0); 06020 06021 _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by); 06022 do { 06023 pixelColorNolock(m->dst, b.x, b.y, m->color); 06024 } while (_bresenhamIterate(&b)==0); 06025 06026 _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y); 06027 do { 06028 pixelColorNolock(m->dst, b.x, b.y, m->color); 06029 } while (_bresenhamIterate(&b)==0); 06030 06031 /* Unlock surface */ 06032 if (SDL_MUSTLOCK(m->dst)) { 06033 SDL_UnlockSurface(m->dst); 06034 } 06035 06036 px[0] = m1x; 06037 px[1] = m2x; 06038 px[2] = ml1bx; 06039 px[3] = ml2bx; 06040 py[0] = m1y; 06041 py[1] = m2y; 06042 py[2] = ml1by; 06043 py[3] = ml2by; 06044 polygonColor(m->dst, (const Sint16 *) px, (const Sint16 *) py, 4, m->color); 06045 } 06046 } 06047 06048 m->last1x = ml1x; 06049 m->last1y = ml1y; 06050 m->last2x = ml2x; 06051 m->last2y = ml2y; 06052 m->first1x = ml1bx; 06053 m->first1y = ml1by; 06054 m->first2x = ml2bx; 06055 m->first2y = ml2by; 06056 } 06057 06058 06059 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y)) 06060 06075 static void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter) 06076 { 06077 float offset = width / 2.f; 06078 06079 Sint16 temp; 06080 Sint16 ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by; 06081 06082 int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */ 06083 06084 int q; /* pel counter,q=perpendicular to line */ 06085 int tmp; 06086 06087 int dd; /* distance along line */ 06088 int tk; /* thickness threshold */ 06089 double ang; /* angle for initial point calculation */ 06090 double sang, cang; 06091 06092 ml2by = ml2bx = ml1by = ml1bx = ml2y = ml2x = ml1y = ml1x = 0; 06093 06094 /* Initialisation */ 06095 m->u = x2 - x; /* delta x */ 06096 m->v = y2 - y; /* delta y */ 06097 06098 if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */ 06099 temp = x; 06100 x = x2; 06101 x2 = temp; 06102 temp = y; 06103 y = y2; 06104 y = temp; 06105 m->u *= -1; 06106 m->v *= -1; 06107 } 06108 06109 if (m->v < 0) { /* swap to 1st quadrant and flag */ 06110 m->v *= -1; 06111 m->quad4 = 1; 06112 } else { 06113 m->quad4 = 0; 06114 } 06115 06116 if (m->v > m->u) { /* swap things if in 2 octant */ 06117 tmp = m->u; 06118 m->u = m->v; 06119 m->v = tmp; 06120 m->oct2 = 1; 06121 } else { 06122 m->oct2 = 0; 06123 } 06124 06125 m->ku = m->u + m->u; /* change in l for square shift */ 06126 m->kv = m->v + m->v; /* change in d for square shift */ 06127 m->kd = m->kv - m->ku; /* change in d for diagonal shift */ 06128 m->kt = m->u - m->kv; /* diag/square decision threshold */ 06129 06130 d0 = 0; 06131 d1 = 0; 06132 dd = 0; 06133 06134 ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */ 06135 sang = sin(ang); 06136 cang = cos(ang); 06137 06138 if (m->oct2 == 0) { 06139 ptx = x + (Sint16)lrint(offset * sang); 06140 if (m->quad4 == 0) { 06141 pty = y - (Sint16)lrint(offset * cang); 06142 } else { 06143 pty = y + (Sint16)lrint(offset * cang); 06144 } 06145 } else { 06146 ptx = x - (Sint16)lrint(offset * cang); 06147 if (m->quad4 == 0) { 06148 pty = y + (Sint16)lrint(offset * sang); 06149 } else { 06150 pty = y - (Sint16)lrint(offset * sang); 06151 } 06152 } 06153 06154 /* used here for constant thickness line */ 06155 tk = (int) (4. * HYPOT(ptx - x, pty - y) * HYPOT(m->u, m->v)); 06156 06157 if (miter == 0) { 06158 m->first1x = -32768; 06159 m->first1y = -32768; 06160 m->first2x = -32768; 06161 m->first2y = -32768; 06162 m->last1x = -32768; 06163 m->last1y = -32768; 06164 m->last2x = -32768; 06165 m->last2y = -32768; 06166 } 06167 06168 for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */ 06169 06170 _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */ 06171 if (q == 0) { 06172 ml1x = ptx; 06173 ml1y = pty; 06174 ml1bx = m->tempx; 06175 ml1by = m->tempy; 06176 } else { 06177 ml2x = ptx; 06178 ml2y = pty; 06179 ml2bx = m->tempx; 06180 ml2by = m->tempy; 06181 } 06182 if (d0 < m->kt) { /* square move */ 06183 if (m->oct2 == 0) { 06184 if (m->quad4 == 0) { 06185 pty++; 06186 } else { 06187 pty--; 06188 } 06189 } else { 06190 ptx++; 06191 } 06192 } else { /* diagonal move */ 06193 dd += m->kv; 06194 d0 -= m->ku; 06195 if (d1 < m->kt) { /* normal diagonal */ 06196 if (m->oct2 == 0) { 06197 ptx--; 06198 if (m->quad4 == 0) { 06199 pty++; 06200 } else { 06201 pty--; 06202 } 06203 } else { 06204 ptx++; 06205 if (m->quad4 == 0) { 06206 pty--; 06207 } else { 06208 pty++; 06209 } 06210 } 06211 d1 += m->kv; 06212 } else { /* double square move, extra parallel line */ 06213 if (m->oct2 == 0) { 06214 ptx--; 06215 } else { 06216 if (m->quad4 == 0) { 06217 pty--; 06218 } else { 06219 pty++; 06220 } 06221 } 06222 d1 += m->kd; 06223 if (dd > tk) { 06224 _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y); 06225 return; /* breakout on the extra line */ 06226 } 06227 _murphyParaline(m, ptx, pty, d1); 06228 if (m->oct2 == 0) { 06229 if (m->quad4 == 0) { 06230 pty++; 06231 } else { 06232 06233 pty--; 06234 } 06235 } else { 06236 ptx++; 06237 } 06238 } 06239 } 06240 dd += m->ku; 06241 d0 += m->kv; 06242 } 06243 06244 _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y); 06245 } 06246 06247 06261 int thickLineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color) 06262 { 06263 SDL_gfxMurphyIterator m; 06264 06265 if (dst == NULL) return -1; 06266 if (width < 1) return -1; 06267 06268 m.dst = dst; 06269 m.color = color; 06270 06271 _murphyWideline(&m, x, y, x2, y2, width, 0); 06272 _murphyWideline(&m, x, y, x2, y2, width, 1); 06273 06274 return(0); 06275 } 06276 06293 int thickLineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 06294 { 06295 return (thickLineColor(dst, x, y, x2, y2, width, 06296 ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a)); 06297 }
1.7.4