#ifndef WDL_NO_DEFINE_MINMAX #define WDL_NO_DEFINE_MINMAX #endif #include "lice.h" #include "lice_combine.h" #include #define _PI 3.141592653589793238f #define IGNORE_SCALING(mode) ((mode)&LICE_BLIT_IGNORE_SCALING) template inline void _SWAP(T& a, T& b) { T tmp = a; a = b; b = tmp; } #define A(x) ((LICE_pixel_chan)((x)*255.0+0.5)) #define AF(x) (255) #define DEF_ALPHAS(dim) \ static const LICE_pixel_chan alphas_unfill[] = { __ALPHAS__(A) }; \ static const LICE_pixel_chan alphas_fill[] = { __ALPHAS__(AF) }; \ const LICE_pixel_chan * const alphas = fill ? alphas_fill : alphas_unfill; \ ((void)sizeof(char[1 - 2*(sizeof(alphas_unfill) != dim*dim)])); \ ((void)sizeof(char[1 - 2*(sizeof(alphas_fill) != dim*dim)])); static bool CachedCircle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa, bool fill) { // fast draw for some small circles if (r == 1.5f) { if (aa) { #define __ALPHAS__(B) \ A(0.31), A(1.00), A(1.00), A(0.31), \ A(1.00), B(0.06), B(0.06), A(1.00), \ A(1.00), B(0.06), B(0.06), A(1.00), \ A(0.31), A(1.00), A(1.00), A(0.31), DEF_ALPHAS(4) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 4, 4, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(1.00), A(1.00), A(0.00), \ A(1.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), A(1.00), \ A(0.00), A(1.00), A(1.00), A(0.00), DEF_ALPHAS(4) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 4, 4, alpha, mode); } return true; } else if (r == 2.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.06), A(0.75), A(1.00), A(0.75), A(0.06), \ A(0.75), A(0.82), B(0.31), A(0.82), A(0.75), \ A(1.00), B(0.31), B(0.00), B(0.31), A(1.00), \ A(0.75), A(0.82), B(0.31), A(0.82), A(0.75), \ A(0.06), A(0.75), A(1.00), A(0.75), A(0.06) DEF_ALPHAS(5) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 5, 5, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), B(0.00), A(1.00), A(0.00), \ A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.00), A(1.00), B(0.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), A(0.00), A(0.00) DEF_ALPHAS(5) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 5, 5, alpha, mode); } return true; } else if (r == 2.5f) { if (aa) { #define __ALPHAS__(B) \ A(0.06), A(0.75), A(1.00), A(1.00), A(0.75), A(0.06), \ A(0.75), A(0.82), B(0.31), B(0.31), A(0.82), A(0.75), \ A(1.00), B(0.31), B(0.00), B(0.00), B(0.31), A(1.00), \ A(1.00), B(0.31), B(0.00), B(0.00), B(0.31), A(1.00), \ A(0.75), A(0.82), B(0.31), B(0.31), A(0.82), A(0.75), \ A(0.06), A(0.75), A(1.00), A(1.00), A(0.75), A(0.06) DEF_ALPHAS(6) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 6, 6, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(1.00), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.00), A(1.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), A(1.00), A(0.00), A(0.00) DEF_ALPHAS(6) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 6, 6, alpha, mode); } return true; } else if (r == 3.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.56), A(1.00), A(1.00), A(1.00), A(0.56), A(0.00), \ A(0.56), A(1.00), B(0.38), B(0.25), B(0.38), A(1.00), A(0.56), \ A(1.00), B(0.44), B(0.00), B(0.00), B(0.00), B(0.44), A(1.00), \ A(1.00), B(0.19), B(0.00), B(0.00), B(0.00), B(0.19), A(1.00), \ A(1.00), B(0.44), B(0.00), B(0.00), B(0.00), B(0.44), A(1.00), \ A(0.56), A(1.00), B(0.38), B(0.25), B(0.38), A(1.00), A(0.56), \ A(0.00), A(0.56), A(1.00), A(1.00), A(1.00), A(0.56), A(0.00) DEF_ALPHAS(7) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 7, 7, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00) DEF_ALPHAS(7) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 7, 7, alpha, mode); } return true; } else if (r == 3.5f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.31), A(0.87), A(1.00), A(1.00), A(0.87), A(0.31), A(0.00), \ A(0.31), A(1.00), A(0.69), B(0.25), B(0.25), A(0.69), A(1.00), A(0.31), \ A(0.87), A(0.69), B(0.00), B(0.00), B(0.00), B(0.00), A(0.69), A(0.87), \ A(1.00), B(0.25), B(0.00), B(0.00), B(0.00), B(0.00), B(0.25), A(1.00), \ A(1.00), B(0.25), B(0.00), B(0.00), B(0.00), B(0.00), B(0.25), A(1.00), \ A(0.87), A(0.69), B(0.00), B(0.00), B(0.00), B(0.00), A(0.69), A(0.87), \ A(0.31), A(1.00), A(0.69), B(0.25), B(0.25), A(0.69), A(1.00), A(0.31), \ A(0.00), A(0.31), A(0.87), A(1.00), A(1.00), A(0.87), A(0.31), A(0.00) DEF_ALPHAS(8) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 8, 8, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \ A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \ A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00) DEF_ALPHAS(8) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 8, 8, alpha, mode); } return true; } else if (r == 4.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.12), A(0.69), A(1.00), A(1.00), A(1.00), A(0.69), A(0.12), A(0.00), \ A(0.12), A(0.94), A(0.82), B(0.31), B(0.25), B(0.31), A(0.82), A(0.94), A(0.12), \ A(0.69), A(0.82), B(0.06), B(0.00), B(0.00), B(0.00), B(0.06), A(0.82), A(0.69), \ A(1.00), B(0.31), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.31), A(1.00), \ A(1.00), B(0.19), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.19), A(1.00), \ A(1.00), B(0.31), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.31), A(1.00), \ A(0.69), A(0.82), B(0.06), B(0.00), B(0.00), B(0.00), B(0.06), A(0.82), A(0.69), \ A(0.12), A(0.94), A(0.82), B(0.31), B(0.25), B(0.31), A(0.82), A(0.94), A(0.12), \ A(0.00), A(0.12), A(0.69), A(1.00), A(1.00), A(1.00), A(0.69), A(0.12), A(0.00) DEF_ALPHAS(9) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 9, 9, alpha, mode); } else { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \ A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), \ A(0.00), A(1.00), A(1.00), B(0.00), B(0.00), B(0.00), A(1.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), A(1.00), A(1.00), A(1.00), A(1.00), A(0.00), A(0.00) DEF_ALPHAS(9) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 9, 9, alpha, mode); } return true; } else if (r == 5.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(0.00), A(0.58), A(0.90), A(1.00), A(0.90), A(0.58), A(0.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(1.00), B(0.42), B(0.10), B(0.00), B(0.10), B(0.42), A(1.00), A(0.00), A(0.00), \ A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(0.58), B(0.42), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.42), A(0.58), \ A(0.90), B(0.10), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.10), A(0.90), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.90), B(0.10), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.10), A(0.90), \ A(0.58), B(0.42), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.42), A(0.58), \ A(0.00), A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), A(0.00), \ A(0.00), A(0.00), A(1.00), B(0.42), B(0.10), B(0.00), B(0.10), B(0.42), A(1.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.00), A(0.58), A(0.90), A(1.00), A(0.90), A(0.58), A(0.00), A(0.00), A(0.00) DEF_ALPHAS(11) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 11, 11, alpha, mode); return true; } } else if (r == 6.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(0.00), A(0.20), A(0.66), A(0.92), A(1.00), A(0.92), A(0.66), A(0.20), A(0.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.47), A(0.81), B(0.35), B(0.09), B(0.00), B(0.09), B(0.35), A(0.81), A(0.47), A(0.00), A(0.00), \ A(0.00), A(0.47), B(0.53), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.53), A(0.47), A(0.00), \ A(0.20), A(0.81), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.81), A(0.20), \ A(0.66), B(0.35), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.35), A(0.66), \ A(0.92), B(0.09), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.09), A(0.92), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.92), B(0.09), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.09), A(0.92), \ A(0.66), B(0.35), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.35), A(0.66), \ A(0.20), A(0.81), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.81), A(0.20), \ A(0.00), A(0.47), B(0.53), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.53), A(0.47), A(0.00), \ A(0.00), A(0.00), A(0.47), A(0.81), B(0.35), B(0.09), B(0.00), B(0.09), B(0.35), A(0.81), A(0.47), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.00), A(0.20), A(0.66), A(0.92), A(1.00), A(0.92), A(0.66), A(0.20), A(0.00), A(0.00), A(0.00), DEF_ALPHAS(13) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 13, 13, alpha, mode); return true; } } else if (r == 7.0f) { if (aa) { #define __ALPHAS__(B) \ A(0.00), A(0.00), A(0.00), A(0.00), A(0.33), A(0.71), A(0.93), A(1.00), A(0.93), A(0.71), A(0.33), A(0.00), A(0.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.00), A(0.75), A(0.68), B(0.29), B(0.07), B(0.00), B(0.07), B(0.29), A(0.68), A(0.75), A(0.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.90), B(0.26), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.34), A(0.90), A(0.00), A(0.00), \ A(0.00), A(0.75), B(0.34), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.26), A(0.75), A(0.00), \ A(0.33), A(0.68), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.68), A(0.33), \ A(0.71), B(0.29), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.29), A(0.71), \ A(0.93), B(0.07), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.07), A(0.93), \ A(1.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(1.00), \ A(0.93), B(0.07), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.07), A(0.93), \ A(0.71), B(0.29), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.29), A(0.71), \ A(0.33), A(0.68), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), A(0.68), A(0.33), \ A(0.00), A(0.75), B(0.34), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.26), A(0.75), A(0.00), \ A(0.00), A(0.00), A(0.90), B(0.26), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.00), B(0.34), A(0.90), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.00), A(0.75), A(0.68), B(0.29), B(0.07), B(0.00), B(0.07), B(0.29), A(0.68), A(0.75), A(0.00), A(0.00), A(0.00), \ A(0.00), A(0.00), A(0.00), A(0.00), A(0.33), A(0.71), A(0.93), A(1.00), A(0.93), A(0.71), A(0.33), A(0.00), A(0.00), A(0.00), A(0.00), DEF_ALPHAS(15) #undef __ALPHAS__ LICE_DrawGlyph(dest, cx-r, cy-r, color, alphas, 15, 15, alpha, mode); return true; } } return false; } template class _LICE_CircleDrawer { public: static void DrawClippedPt(LICE_IBitmap* dest, int x, int y, const int *clip, int r, int g, int b, int a, int alpha, bool doclip) { if (doclip && (x < clip[0] || x >= clip[2] || y < clip[1] || y >= clip[3])) return; LICE_pixel* px = dest->getBits()+y*dest->getRowSpan()+x; COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha); } static void DrawClippedHorzLine(LICE_IBitmap* dest, int y, int xlo, int xhi, const int *clip, int r, int g, int b, int a, int alpha, bool doclip) { if (doclip) { if (y < clip[1] || y >= clip[3]) return; xlo = lice_max(xlo, clip[0]); xhi = lice_min(xhi, clip[2]-1); } LICE_pixel* px = dest->getBits()+y*dest->getRowSpan()+xlo; while (xlo <= xhi) { COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha); ++px; ++xlo; } } static void DrawClippedVertLine(LICE_IBitmap* dest, int x, int ylo, int yhi, const int *clip, int r, int g, int b, int a, int alpha, bool doclip) { if (doclip) { if (x < clip[0] || x >= clip[2]) return; ylo = lice_max(ylo, clip[1]); yhi = lice_min(yhi, clip[3]-1); } int span=dest->getRowSpan(); LICE_pixel* px = dest->getBits()+ylo*span+x; while (ylo <= yhi) { COMBFUNC::doPix((LICE_pixel_chan*)px, r, g, b, a, alpha); px += span; ++ylo; } } static void DrawClippedCircleAA(LICE_IBitmap* dest, float cx, float cy, float rad, const int *clip, LICE_pixel color, int ai, bool filled, bool doclip) { int r = LICE_GETR(color), g = LICE_GETG(color), b = LICE_GETB(color), a = LICE_GETA(color); const int cx0=(int)floor(cx+0.5f); const int cy0=(int)floor(cy+0.5f); int y=(int)rad; double w=rad-floor(rad); int wa=(int)((double)ai*w); DrawClippedPt(dest, cx0, cy0-y-1, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0, cy0+y+1, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0-y-1, cy0, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0+y+1, cy0, clip, r, g, b, a, wa, doclip); if (filled) { DrawClippedVertLine(dest, cx0, cy0-y, cy0-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0, cy0+1, cy0+y, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0, cx0-y, cx0+y, clip, r, g, b, a, ai, doclip); } else { int iwa=ai-wa; DrawClippedPt(dest, cx0, cy0-y, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0+y, cy0, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0, cy0+y, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0-y, cy0, clip, r, g, b, a, iwa, doclip); } double r2=rad*rad; double yf=sqrt(r2-1.0); int yl=(int)(yf+0.5); int x=1; while (x <= yl) { y=(int)yf; w=yf-floor(yf); wa=(int)((double)ai*w); DrawClippedPt(dest, cx0-x, cy0-y-1, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0-x, cy0+y+1, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0+x, cy0-y-1, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0+x, cy0+y+1, clip, r, g, b, a, wa, doclip); if (x != yl) { DrawClippedPt(dest, cx0-y-1, cy0-x, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0+y+1, cy0-x, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0-y-1, cy0+x, clip, r, g, b, a, wa, doclip); DrawClippedPt(dest, cx0+y+1, cy0+x, clip, r, g, b, a, wa, doclip); } if (filled) { DrawClippedVertLine(dest, cx0-x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0-x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0-x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0-x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0+x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0+x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0+x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0+x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip); } else { int iwa=ai-wa; DrawClippedPt(dest, cx0-y, cy0-x, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0+y, cy0-x, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0-x, cy0+y, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0+x, cy0+y, clip, r, g, b, a, iwa, doclip); if (x != yl) { DrawClippedPt(dest, cx0-x, cy0-y, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0+x, cy0-y, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0-y, cy0+x, clip, r, g, b, a, iwa, doclip); DrawClippedPt(dest, cx0+y, cy0+x, clip, r, g, b, a, iwa, doclip); } } ++x; yf=sqrt(r2-(double)(x*x)); yl=(int)(yf+0.5); } } static void DrawClippedCircle(LICE_IBitmap* dest, float cx, float cy, float rad, const int *clip, LICE_pixel color, int ai, bool filled, bool doclip) { const int r = LICE_GETR(color), g = LICE_GETG(color), b = LICE_GETB(color), a = LICE_GETA(color); const int cx0=(int)floor(cx+0.5f); const int cy0=(int)floor(cy+0.5f); const int r0=(int)(rad+0.5f); if (filled) { DrawClippedVertLine(dest, cx0, cy0-r0, cy0-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0, cy0+1, cy0+r0, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0, cx0-r0, cx0+r0, clip, r, g, b, a, ai, doclip); } else { DrawClippedPt(dest, cx0, cy0-r0, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0+r0, cy0, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0, cy0+r0, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0-r0, cy0, clip, r, g, b, a, ai, doclip); } int x=0; int y=r0; int e=-r0; while (++x < y) { if (e < 0) { e += 2*x+1; } else { --y; e += 2*(x-y)+1; } if (filled) { DrawClippedVertLine(dest, cx0-x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0-x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0-x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0-x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0+x, cx0-y, cx0-x, clip, r, g, b, a, ai, doclip); DrawClippedHorzLine(dest, cy0+x, cx0+x, cx0+y, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0+x, cy0-y, cy0-x-1, clip, r, g, b, a, ai, doclip); DrawClippedVertLine(dest, cx0+ x, cy0+x+1, cy0+y, clip, r, g, b, a, ai, doclip); } else { DrawClippedPt(dest, cx0-x, cy0-y, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0-x, cy0+y, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0+x, cy0-y, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0+x, cy0+y, clip, r, g, b, a, ai, doclip); if (x != y) { DrawClippedPt(dest, cx0-y, cy0-x, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0-y, cy0+x, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0+y, cy0-x, clip, r, g, b, a, ai, doclip); DrawClippedPt(dest, cx0+y, cy0+x, clip, r, g, b, a, ai, doclip); } } } } }; static void __DrawCircleClipped(LICE_IBitmap* dest, float cx, float cy, float rad, LICE_pixel color, int ia, bool aa, bool filled, int mode, const int *clip, bool doclip) { // todo: more clipped/filled versions (to optimize constants out?) if (aa) { #define __LICE__ACTION(COMBFUNC) _LICE_CircleDrawer::DrawClippedCircleAA(dest, cx, cy, rad, clip, color, ia, filled, doclip) __LICE_ACTION_NOSRCALPHA(mode, ia,false) #undef __LICE__ACTION } else { #define __LICE__ACTION(COMBFUNC) _LICE_CircleDrawer::DrawClippedCircle(dest, cx, cy, rad, clip, color, ia, filled, doclip) __LICE_ACTION_CONSTANTALPHA(mode,ia,false) #undef __LICE__ACTION } } static void __DrawArc(int w, int h, LICE_IBitmap* dest, float cx, float cy, float rad, double anglo, double anghi, LICE_pixel color, int ialpha, bool aa, int mode) { const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL); if (__sc>0) { __LICE_SCU(w); __LICE_SCU(h); if (!IGNORE_SCALING(mode)) { __LICE_SC(cx); __LICE_SC(cy); __LICE_SC(rad); } } // -2PI <= anglo <= anghi <= 2PI anglo += 2.0*_PI; anghi += 2.0*_PI; // 0 <= anglo <= anghi <= 4PI double next_ang = anglo - fmod(anglo,0.5*_PI); int ly = (int)floor(cy - rad*cos(anglo) + 0.5); int lx = (int)floor(cx + rad*sin(anglo) + 0.5); while (anglo < anghi) { next_ang += 0.5*_PI; if (next_ang > anghi) next_ang = anghi; int yhi = (int) floor(cy-rad*cos(next_ang)+0.5); int xhi = (int) floor(cx+rad*sin(next_ang)+0.5); int ylo = ly; int xlo = lx; ly = yhi; lx = xhi; if (yhi < ylo) { int tmp = ylo; ylo = yhi; yhi=tmp; } if (xhi < xlo) { int tmp = xlo; xlo = xhi; xhi=tmp; } anglo = next_ang; if (xhi != cx) xhi++; if (yhi != cy) yhi++; const int clip[4]={lice_max(xlo,0),lice_max(0, ylo),lice_min(w,xhi+1),lice_min(h, yhi+1)}; __DrawCircleClipped(dest,cx,cy,rad,color,ialpha,aa,false,mode,clip,true); } } void LICE_Arc(LICE_IBitmap* dest, float cx, float cy, float r, float minAngle, float maxAngle, LICE_pixel color, float alpha, int mode, bool aa) { if (!dest) return; if (dest->isFlipped()) { cy=dest->getHeight()-1-cy; minAngle=_PI-minAngle; maxAngle=_PI-maxAngle; } if (maxAngle < minAngle) { float tmp=maxAngle; maxAngle=minAngle; minAngle=tmp; } if (maxAngle - minAngle >= 2.0f*_PI) { LICE_Circle(dest,cx,cy,r,color,alpha,mode,aa); return; } if (maxAngle >= 2.0f*_PI) { float tmp = fmod(maxAngle,2.0f*_PI); minAngle -= maxAngle - tmp; // reduce by factors of 2PI maxAngle = tmp; } else if (minAngle <= -2.0f*_PI) { float tmp = fmod(minAngle,2.0f*_PI); maxAngle -= minAngle - tmp; // toward zero by factors of 2pi minAngle = tmp; } // -2PI <= minAngle <= maxAngle <= 2PI int ia = (int) (alpha*256.0f); if (!ia) return; __DrawArc(dest->getWidth(),dest->getHeight(),dest,cx,cy,r,minAngle,maxAngle,color,ia,aa,mode); } void LICE_Circle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa) { if (!dest) return; int w = dest->getWidth(), h = dest->getHeight(); const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL); if (__sc>0) { __LICE_SCU(w); __LICE_SCU(h); if (!IGNORE_SCALING(mode)) { __LICE_SC(cx); __LICE_SC(cy); __LICE_SC(r); } } const int clip[4] = { 0, 0, w, h }; if (w < 1 || h <1 || r<0 || (int)cx+(int)r < -2 || (int)cy + (int)r < - 2 || (int)cx-(int)r > w + 2 || (int)cy - (int)r > h + 2 ) return; int ia = (int) (alpha*256.0f); if (!ia) return; if (CachedCircle(dest, cx, cy, r, color, alpha, mode|LICE_BLIT_IGNORE_SCALING, aa, false)) return; if (dest->isFlipped()) cy=h-1-cy; const bool doclip = !(cx-r-2 >= 0 && cy-r-2 >= 0 && cx+r+2 < w && cy+r+2 < h); __DrawCircleClipped(dest,cx,cy,r,color,ia,aa,false,mode,clip,doclip); } void LICE_FillCircle(LICE_IBitmap* dest, float cx, float cy, float r, LICE_pixel color, float alpha, int mode, bool aa) { if (!dest) return; int w = dest->getWidth(), h = dest->getHeight(); const int __sc = (int)dest->Extended(LICE_EXT_GET_SCALING,NULL); if (__sc>0) { __LICE_SCU(w); __LICE_SCU(h); if (!IGNORE_SCALING(mode)) { __LICE_SC(cx); __LICE_SC(cy); __LICE_SC(r); } } if (w < 1 || h < 1 || r < 0.0 || (int)cx+(int)r < -2 || (int)cy + (int)r < - 2 || (int)cx-(int)r > w + 2 || (int)cy - (int)r > h + 2 ) return; const int ia = (int) (alpha*256.0f); if (!ia) return; if (CachedCircle(dest, cx, cy, r, color, alpha, mode|LICE_BLIT_IGNORE_SCALING, aa, true)) return; if (dest->isFlipped()) cy=h-1-cy; const int clip[4] = { 0, 0, w, h }; const bool doclip = !(cx-r-2 >= 0 && cy-r-2 >= 0 && cx+r+2 < w && cy+r+2 < h); __DrawCircleClipped(dest,cx,cy,r,color,ia,aa,true,mode,clip,doclip); } void LICE_RoundRect(LICE_IBitmap *drawbm, float xpos, float ypos, float w, float h, int cornerradius, LICE_pixel col, float alpha, int mode, bool aa) { xpos = floor(xpos+0.5); ypos = floor(ypos+0.5); w = floor(w+0.5); h = floor(h+0.5); if (cornerradius>0) { float cr=cornerradius; if (cr > w*0.5) cr=w*0.5; if (cr > h*0.5) cr=h*0.5; cr=floor(cr); if (cr>=2) { double adj = 0.0; const int __sc = IGNORE_SCALING(mode) ? 0 : drawbm ? (int)drawbm->Extended(LICE_EXT_GET_SCALING,NULL) : 0; if (__sc>0) { adj = 1.0 - 256.0/__sc; LICE_FLine(drawbm,xpos+cr+adj,ypos+adj,xpos+w-cr,ypos+adj,col,alpha,mode,true); LICE_FLine(drawbm,xpos+cr-1+adj,ypos+h-adj,xpos+w-cr-adj,ypos+h-adj,col,alpha,mode,true); LICE_FLine(drawbm,xpos+w-adj,ypos+cr+adj,xpos+w-adj,ypos+h-cr-adj,col,alpha,mode,true); LICE_FLine(drawbm,xpos+adj,ypos+cr-1+adj,xpos+adj,ypos+h-cr-adj,col,alpha,mode,true); // aa=true; } else { LICE_Line(drawbm,xpos+cr,ypos,xpos+w-cr,ypos,col,alpha,mode,aa); LICE_Line(drawbm,xpos+cr-1,ypos+h,xpos+w-cr,ypos+h,col,alpha,mode,aa); LICE_Line(drawbm,xpos+w,ypos+cr,xpos+w,ypos+h-cr,col,alpha,mode,aa); LICE_Line(drawbm,xpos,ypos+cr-1,xpos,ypos+h-cr,col,alpha,mode,aa); } LICE_Arc(drawbm,xpos+cr+adj,ypos+cr+adj,cr,-_PI*0.5f,0,col,alpha,mode,aa); LICE_Arc(drawbm,xpos+w-cr-adj,ypos+cr+adj,cr,0,_PI*0.5f,col,alpha,mode,aa); LICE_Arc(drawbm,xpos+w-cr-adj,ypos+h-cr-adj,cr,_PI*0.5f,_PI,col,alpha,mode,aa); LICE_Arc(drawbm,xpos+cr+adj,ypos+h-cr-adj,cr,_PI,_PI*1.5f,col,alpha,mode,aa); return; } } LICE_DrawRect(drawbm, (int)xpos, (int)ypos, (int)w, (int)h, col, alpha, mode); }