ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

VectorRendererSpec.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/util.h"
00024 #include "common/system.h"
00025 #include "common/frac.h"
00026 
00027 #include "graphics/surface.h"
00028 #include "graphics/transparent_surface.h"
00029 #include "graphics/nine_patch.h"
00030 #include "graphics/colormasks.h"
00031 
00032 #include "gui/ThemeEngine.h"
00033 #include "graphics/VectorRenderer.h"
00034 #include "graphics/VectorRendererSpec.h"
00035 
00036 #define VECTOR_RENDERER_FAST_TRIANGLES
00037 
00039 inline frac_t fp_sqroot(uint32 x) {
00040 #if 0
00041     // Use the FPU to compute the square root and then convert it to fixed
00042     // point data. On systems with a fast FPU, this can be a lot faster than
00043     // the integer based code below - on my system roughly 50x! However, on
00044     // systems without an FPU, the converse might be true.
00045     // For now, we only use the integer based code.
00046     return doubleToFrac(sqrt((double)x));
00047 #else
00048     // The code below wants to use a lot of registers, which is not good on
00049     // x86 processors. By taking advantage of the fact the the input value is
00050     // an integer, it might be possible to improve this. Furthermore, we could
00051     // take advantage of the fact that we call this function several times on
00052     // decreasing values. By feeding it the sqrt of the previous old x, as well
00053     // as the old x, it should be possible to compute the correct sqrt with far
00054     // fewer than 23 iterations.
00055     uint32 root, remHI, remLO, testDIV, count;
00056 
00057     root = 0;
00058     remHI = 0;
00059     remLO = x << 16;
00060     count = 23;
00061 
00062     do {
00063         remHI = (remHI << 2) | (remLO >> 30);
00064         remLO <<= 2;
00065         root <<= 1;
00066         testDIV = (root << 1) + 1;
00067 
00068         if (remHI >= testDIV) {
00069             remHI -= testDIV;
00070             root++;
00071         }
00072     } while (count--);
00073 
00074     return root;
00075 #endif
00076 }
00077 
00078 /*
00079     HELPER MACROS for Bresenham's circle drawing algorithm
00080     Note the proper spelling on this header.
00081 */
00082 #define BE_ALGORITHM() do { \
00083     if (f >= 0) { \
00084         y--; \
00085         ddF_y += 2; \
00086         f += ddF_y; \
00087         py -= pitch; \
00088     } \
00089     px += pitch; \
00090     ddF_x += 2; \
00091     f += ddF_x + 1; \
00092 } while(0)
00093 
00094 #define BE_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py) do { \
00095     *(ptr1 + (y) - (px)) = color; \
00096     *(ptr1 + (x) - (py)) = color; \
00097     *(ptr2 - (x) - (py)) = color; \
00098     *(ptr2 - (y) - (px)) = color; \
00099 } while (0)
00100 
00101 #define BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py) do { \
00102     *(ptr3 - (y) + (px)) = color; \
00103     *(ptr3 - (x) + (py)) = color; \
00104     *(ptr4 + (x) + (py)) = color; \
00105     *(ptr4 + (y) + (px)) = color; \
00106 } while (0)
00107 
00108 #define BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \
00109     BE_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py); \
00110     BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py); \
00111 } while (0)
00112 
00113 #define BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
00114     if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
00115         *(ptr1 + (y) - (px)) = color; \
00116     if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
00117         *(ptr1 + (x) - (py)) = color; \
00118     if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
00119         *(ptr2 - (x) - (py)) = color; \
00120     if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
00121         *(ptr2 - (y) - (px)) = color; \
00122 } while (0)
00123 
00124 #define BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
00125     if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
00126         *(ptr3 - (y) + (px)) = color; \
00127     if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
00128         *(ptr3 - (x) + (py)) = color; \
00129     if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
00130         *(ptr4 + (x) + (py)) = color; \
00131     if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
00132         *(ptr4 + (y) + (px)) = color; \
00133 } while (0)
00134 
00135 #define BE_DRAWCIRCLE_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
00136     BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
00137     BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
00138 } while (0)
00139 
00140 #define BE_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \
00141     *(ptr1 + (y) - (px)) = color1; \
00142     *(ptr1 + (x) - (py)) = color1; \
00143     *(ptr2 - (x) - (py)) = color1; \
00144     *(ptr2 - (y) - (px)) = color1; \
00145     *(ptr3 - (y) + (px)) = color1; \
00146     *(ptr3 - (x) + (py)) = color1; \
00147     *(ptr4 + (x) + (py)) = color2; \
00148     *(ptr4 + (y) + (px)) = color2; \
00149 } while (0)
00150 
00151 #define BE_DRAWCIRCLE_BCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
00152     if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
00153         *(ptr1 + (y) - (px)) = color1; \
00154     if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
00155         *(ptr1 + (x) - (py)) = color1; \
00156     if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
00157         *(ptr2 - (x) - (py)) = color1; \
00158     if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
00159         *(ptr2 - (y) - (px)) = color1; \
00160     if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
00161         *(ptr3 - (y) + (px)) = color1; \
00162     if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
00163         *(ptr3 - (x) + (py)) = color1; \
00164     if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
00165         *(ptr4 + (x) + (py)) = color2; \
00166     if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
00167         *(ptr4 + (y) + (px)) = color2; \
00168 } while (0)
00169 
00170 #define BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
00171     this->blendPixelPtr(ptr + (y) - (px), color, a); \
00172 } while (0)
00173 
00174 #define BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \
00175     this->blendPixelPtr(ptr + (x) - (py), color, a); \
00176 } while (0)
00177 
00178 #define BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00179     if (IS_IN_CLIP((realX) + (y), (realY) - (x))) \
00180         this->blendPixelPtr(ptr + (y) - (px), color, a); \
00181 } while (0)
00182 
00183 #define BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00184     if (IS_IN_CLIP((realX) + (x), (realY) - (y))) \
00185         this->blendPixelPtr(ptr + (x) - (py), color, a); \
00186 } while (0)
00187 
00188 #define BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
00189     this->blendPixelPtr(ptr - (x) - (py), color, a); \
00190 } while (0)
00191 
00192 #define BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \
00193     this->blendPixelPtr(ptr - (y) - (px), color, a); \
00194 } while (0)
00195 
00196 #define BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00197     if (IS_IN_CLIP((realX) - (x), (realY) - (y))) \
00198         this->blendPixelPtr(ptr - (x) - (py), color, a); \
00199 } while (0)
00200 
00201 #define BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00202     if (IS_IN_CLIP((realX) - (y), (realY) - (x))) \
00203         this->blendPixelPtr(ptr - (y) - (px), color, a); \
00204 } while (0)
00205 
00206 #define BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
00207     this->blendPixelPtr(ptr - (y) + (px), color, a); \
00208 } while (0)
00209 
00210 #define BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \
00211     this->blendPixelPtr(ptr - (x) + (py), color, a); \
00212 } while (0)
00213 
00214 #define BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00215     if (IS_IN_CLIP((realX) - (y), (realY) + (x))) \
00216         this->blendPixelPtr(ptr - (y) + (px), color, a); \
00217 } while (0)
00218 
00219 #define BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00220     if (IS_IN_CLIP((realX) - (x), (realY) + (y))) \
00221         this->blendPixelPtr(ptr - (x) + (py), color, a); \
00222 } while (0)
00223 
00224 #define BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
00225     this->blendPixelPtr(ptr + (x) + (py), color, a); \
00226 } while (0)
00227 
00228 #define BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \
00229     this->blendPixelPtr(ptr + (y) + (px), color, a); \
00230 } while (0)
00231 
00232 #define BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00233     if (IS_IN_CLIP((realX) + (x), (realY) + (y))) \
00234         this->blendPixelPtr(ptr + (x) + (py), color, a); \
00235 } while (0)
00236 
00237 #define BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
00238     if (IS_IN_CLIP((realX) + (y), (realY) + (x))) \
00239         this->blendPixelPtr(ptr + (y) + (px), color, a); \
00240 } while (0)
00241 
00242 #define BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py) do { \
00243     *(ptr1 + (y) - (px)) = color1; \
00244     *(ptr1 + (x) - (py)) = color2; \
00245     *(ptr2 - (x) - (py)) = color2; \
00246     *(ptr2 - (y) - (px)) = color1; \
00247 } while (0)
00248 
00249 #define BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py) do { \
00250     *(ptr3 - (y) + (px)) = color3; \
00251     *(ptr3 - (x) + (py)) = color4; \
00252     *(ptr4 + (x) + (py)) = color4; \
00253     *(ptr4 + (y) + (px)) = color3; \
00254 } while (0)
00255 
00256 #define BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \
00257     BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py); \
00258     BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py); \
00259 } while (0)
00260 
00261 #define IS_IN_CLIP(x,y) (_clippingArea.left <= (x) && (x) < _clippingArea.right \
00262     && _clippingArea.top <= (y) && (y) < _clippingArea.bottom)
00263 
00264 #define BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
00265     if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
00266         *(ptr1 + (y) - (px)) = color1; \
00267 \
00268     if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
00269         *(ptr1 + (x) - (py)) = color2; \
00270 \
00271     if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
00272         *(ptr2 - (x) - (py)) = color2; \
00273 \
00274     if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
00275         *(ptr2 - (y) - (px)) = color1; \
00276 } while (0)
00277 
00278 #define BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
00279     if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
00280         *(ptr3 - (y) + (px)) = color3; \
00281 \
00282     if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
00283         *(ptr3 - (x) + (py)) = color4; \
00284 \
00285     if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
00286         *(ptr4 + (x) + (py)) = color4; \
00287 \
00288     if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
00289         *(ptr4 + (y) + (px)) = color3; \
00290 } while (0)
00291 
00292 #define BE_DRAWCIRCLE_XCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
00293     BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
00294     BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
00295 } while (0)
00296 
00297 
00298 #define BE_RESET() do { \
00299     f = 1 - r; \
00300     ddF_x = 0; ddF_y = -2 * r; \
00301     x = 0; y = r; px = 0; py = pitch * r; \
00302 } while (0)
00303 
00304 #define TRIANGLE_MAINX() \
00305         if (error_term >= 0) { \
00306             ptr_right += pitch; \
00307             ptr_left += pitch; \
00308             error_term += dysub; \
00309         } else { \
00310             error_term += ddy; \
00311         } \
00312         ptr_right++; \
00313         ptr_left--;
00314 
00315 #define TRIANGLE_MAINY() \
00316         if (error_term >= 0) { \
00317             ptr_right++; \
00318             ptr_left--; \
00319             error_term += dxsub; \
00320         } else { \
00321             error_term += ddx; \
00322         } \
00323         ptr_right += pitch; \
00324         ptr_left += pitch;
00325 
00327 #define WU_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py,a) do { \
00328     this->blendPixelPtr(ptr1 + (y) - (px), color, a); \
00329     this->blendPixelPtr(ptr1 + (x) - (py), color, a); \
00330     this->blendPixelPtr(ptr2 - (x) - (py), color, a); \
00331     this->blendPixelPtr(ptr2 - (y) - (px), color, a); \
00332 } while (0)
00333 
00334 #define WU_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py,a) do { \
00335     this->blendPixelPtr(ptr3 - (y) + (px), color, a); \
00336     this->blendPixelPtr(ptr3 - (x) + (py), color, a); \
00337     this->blendPixelPtr(ptr4 + (x) + (py), color, a); \
00338     this->blendPixelPtr(ptr4 + (y) + (px), color, a); \
00339 } while (0)
00340 
00341 #define WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) do { \
00342     WU_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py,a); \
00343     WU_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py,a); \
00344 } while (0)
00345 
00346 
00347 // Color depending on y
00348 // Note: this is only for the outer pixels
00349 #define WU_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py,a,func) do { \
00350     this->func(ptr1 + (y) - (px), color1, a); \
00351     this->func(ptr1 + (x) - (py), color2, a); \
00352     this->func(ptr2 - (x) - (py), color2, a); \
00353     this->func(ptr2 - (y) - (px), color1, a); \
00354 } while (0)
00355 
00356 #define WU_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py,a,func) do { \
00357     this->func(ptr3 - (y) + (px), color3, a); \
00358     this->func(ptr3 - (x) + (py), color4, a); \
00359     this->func(ptr4 + (x) + (py), color4, a); \
00360     this->func(ptr4 + (y) + (px), color3, a); \
00361 } while (0)
00362 
00363 #define WU_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a,func) do { \
00364     WU_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py,a,func); \
00365     WU_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py,a,func); \
00366 } while (0)
00367 
00368 // Color depending on corner (tl,tr,bl: color1, br: color2)
00369 // Note: this is only for the outer pixels
00370 #define WU_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) do { \
00371     this->blendPixelPtr(ptr1 + (y) - (px), color1, a); \
00372     this->blendPixelPtr(ptr1 + (x) - (py), color1, a); \
00373     this->blendPixelPtr(ptr2 - (x) - (py), color1, a); \
00374     this->blendPixelPtr(ptr2 - (y) - (px), color1, a); \
00375     this->blendPixelPtr(ptr3 - (y) + (px), color1, a); \
00376     this->blendPixelPtr(ptr3 - (x) + (py), color1, a); \
00377     this->blendPixelPtr(ptr4 + (x) + (py), color2, a); \
00378     this->blendPixelPtr(ptr4 + (y) + (px), color2, a); \
00379 } while (0)
00380 
00381 #define WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
00382     this->blendPixelPtr(ptr + (y) - (px), color, a); \
00383 } while (0)
00384 
00385 #define WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \
00386     this->blendPixelPtr(ptr + (x) - (py), color, a); \
00387 } while (0)
00388 
00389 #define WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
00390     this->blendPixelPtr(ptr - (x) - (py), color, a); \
00391 } while (0)
00392 
00393 #define WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \
00394     this->blendPixelPtr(ptr - (y) - (px), color, a); \
00395 } while (0)
00396 
00397 #define WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
00398     this->blendPixelPtr(ptr - (y) + (px), color, a); \
00399 } while (0)
00400 
00401 #define WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \
00402     this->blendPixelPtr(ptr - (x) + (py), color, a); \
00403 } while (0)
00404 
00405 #define WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
00406     this->blendPixelPtr(ptr + (x) + (py), color, a); \
00407 } while (0)
00408 
00409 #define WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \
00410     this->blendPixelPtr(ptr + (y) + (px), color, a); \
00411 } while (0)
00412 
00413 // optimized Wu's algorithm
00414 #define WU_ALGORITHM() do { \
00415     oldT = T; \
00416     T = fp_sqroot(rsq - y*y) ^ 0xFFFF; \
00417     py += pitch; \
00418     if (T < oldT) { \
00419         x--; px -= pitch; \
00420     } \
00421     a2 = (T >> 8); \
00422     a1 = ~a2; \
00423 } while (0)
00424 
00425 
00426 namespace Graphics {
00427 
00444 template<typename PixelType>
00445 void colorFill(PixelType *first, PixelType *last, PixelType color) {
00446     int count = (last - first);
00447     if (!count)
00448         return;
00449     int n = (count + 7) >> 3;
00450     switch (count % 8) {
00451     case 0: do {
00452                 *first++ = color; // fall through
00453     case 7:     *first++ = color; // fall through
00454     case 6:     *first++ = color; // fall through
00455     case 5:     *first++ = color; // fall through
00456     case 4:     *first++ = color; // fall through
00457     case 3:     *first++ = color; // fall through
00458     case 2:     *first++ = color; // fall through
00459     case 1:     *first++ = color;
00460             } while (--n > 0);
00461     }
00462 }
00463 
00464 template<typename PixelType>
00465 void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX, int realY, Common::Rect &clippingArea) {
00466     if (realY < clippingArea.top || realY >= clippingArea.bottom)
00467         return;
00468 
00469     int count = (last - first);
00470 
00471     if (realX > clippingArea.right || realX + count < clippingArea.left)
00472         return;
00473 
00474     if (realX < clippingArea.left) {
00475         int diff = (clippingArea.left - realX);
00476         realX += diff;
00477         first += diff;
00478         count -= diff;
00479     }
00480 
00481     if (clippingArea.right <= realX + count) {
00482         int diff = (realX + count - clippingArea.right);
00483         count -= diff;
00484     }
00485 
00486     if (!count)
00487         return;
00488 
00489     int n = (count + 7) >> 3;
00490     switch (count % 8) {
00491     case 0: do {
00492                 *first++ = color; // fall through
00493     case 7:     *first++ = color; // fall through
00494     case 6:     *first++ = color; // fall through
00495     case 5:     *first++ = color; // fall through
00496     case 4:     *first++ = color; // fall through
00497     case 3:     *first++ = color; // fall through
00498     case 2:     *first++ = color; // fall through
00499     case 1:     *first++ = color;
00500             } while (--n > 0);
00501     }
00502 }
00503 
00504 
00505 VectorRenderer *createRenderer(int mode) {
00506 #ifdef DISABLE_FANCY_THEMES
00507     assert(mode == GUI::ThemeEngine::kGfxStandard);
00508 #endif
00509 
00510     PixelFormat format = g_system->getOverlayFormat();
00511     switch (mode) {
00512     case GUI::ThemeEngine::kGfxStandard:
00513         if (g_system->getOverlayFormat().bytesPerPixel == 4)
00514             return new VectorRendererSpec<uint32>(format);
00515         else if (g_system->getOverlayFormat().bytesPerPixel == 2)
00516             return new VectorRendererSpec<uint16>(format);
00517         break;
00518 #ifndef DISABLE_FANCY_THEMES
00519     case GUI::ThemeEngine::kGfxAntialias:
00520         if (g_system->getOverlayFormat().bytesPerPixel == 4)
00521             return new VectorRendererAA<uint32>(format);
00522         else if (g_system->getOverlayFormat().bytesPerPixel == 2)
00523             return new VectorRendererAA<uint16>(format);
00524         break;
00525 #endif
00526     default:
00527         break;
00528     }
00529 
00530     return 0;
00531 }
00532 
00533 template<typename PixelType>
00534 VectorRendererSpec<PixelType>::
00535 VectorRendererSpec(PixelFormat format) :
00536     _format(format),
00537     _redMask((0xFF >> format.rLoss) << format.rShift),
00538     _greenMask((0xFF >> format.gLoss) << format.gShift),
00539     _blueMask((0xFF >> format.bLoss) << format.bShift),
00540     _alphaMask((0xFF >> format.aLoss) << format.aShift) {
00541 
00542     _bitmapAlphaColor = _format.RGBToColor(255, 0, 255);
00543     _clippingArea = Common::Rect(0, 0, 32767, 32767);
00544 }
00545 
00546 /****************************
00547  * Gradient-related methods *
00548  ****************************/
00549 
00550 template<typename PixelType>
00551 void VectorRendererSpec<PixelType>::
00552 setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) {
00553     _gradientEnd = _format.RGBToColor(r2, g2, b2);
00554     _gradientStart = _format.RGBToColor(r1, g1, b1);
00555 
00556     if (sizeof(PixelType) == 4) {
00557         _gradientBytes[0] = ((_gradientEnd & _redMask) >> _format.rShift) - ((_gradientStart & _redMask) >> _format.rShift);
00558         _gradientBytes[1] = ((_gradientEnd & _greenMask) >> _format.gShift) - ((_gradientStart & _greenMask) >> _format.gShift);
00559         _gradientBytes[2] = ((_gradientEnd & _blueMask) >> _format.bShift) - ((_gradientStart & _blueMask) >> _format.bShift);
00560     } else {
00561         _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask);
00562         _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask);
00563         _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask);
00564     }
00565 }
00566 
00567 template<typename PixelType>
00568 inline PixelType VectorRendererSpec<PixelType>::
00569 calcGradient(uint32 pos, uint32 max) {
00570     PixelType output = 0;
00571     pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max;
00572 
00573     if (sizeof(PixelType) == 4) {
00574         output |= ((_gradientStart & _redMask) + (((_gradientBytes[0] * pos) >> 12) << _format.rShift)) & _redMask;
00575         output |= ((_gradientStart & _greenMask) + (((_gradientBytes[1] * pos) >> 12) << _format.gShift)) & _greenMask;
00576         output |= ((_gradientStart & _blueMask) + (((_gradientBytes[2] * pos) >> 12) << _format.bShift)) & _blueMask;
00577     } else {
00578         output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask;
00579         output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask;
00580         output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask;
00581     }
00582     output |= _alphaMask;
00583 
00584     return output;
00585 }
00586 
00587 template<typename PixelType>
00588 void VectorRendererSpec<PixelType>::
00589 precalcGradient(int h) {
00590     PixelType prevcolor = 0, color;
00591 
00592     _gradCache.resize(0);
00593     _gradIndexes.resize(0);
00594 
00595     for (int i = 0; i < h + 2; i++) {
00596         color = calcGradient(i, h);
00597         if (color != prevcolor || i == 0 || i > h - 1) {
00598             prevcolor = color;
00599             _gradCache.push_back(color);
00600             _gradIndexes.push_back(i);
00601         }
00602     }
00603 }
00604 
00605 template<typename PixelType>
00606 void VectorRendererSpec<PixelType>::
00607 gradientFill(PixelType *ptr, int width, int x, int y) {
00608     bool ox = ((y & 1) == 1);
00609     int curGrad = 0;
00610 
00611     while (_gradIndexes[curGrad + 1] <= y)
00612         curGrad++;
00613 
00614     // precalcGradient assures that _gradIndexes entries always differ in
00615     // their value. This assures stripSize is always different from zero.
00616     int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
00617 
00618     int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
00619 
00620     // Dithering:
00621     //   +--+ +--+ +--+ +--+
00622     //   |  | |  | | *| | *|
00623     //   |  | | *| |* | |**|
00624     //   +--+ +--+ +--+ +--+
00625     //     0    1    2    3
00626     if (grad == 0 ||
00627         _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
00628         stripSize < 2) { // the stip is small
00629         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
00630     } else if (grad == 3 && ox) {
00631         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
00632     } else {
00633         for (int j = x; j < x + width; j++, ptr++) {
00634             bool oy = ((j & 1) == 1);
00635 
00636             if ((ox && oy) ||
00637                 ((grad == 2 || grad == 3) && ox && !oy) ||
00638                 (grad == 3 && oy))
00639                 *ptr = _gradCache[curGrad + 1];
00640             else
00641                 *ptr = _gradCache[curGrad];
00642         }
00643     }
00644 }
00645 
00646 template<typename PixelType>
00647 void VectorRendererSpec<PixelType>::
00648 gradientFillClip(PixelType *ptr, int width, int x, int y, int realX, int realY) {
00649     if (realY < _clippingArea.top || realY >= _clippingArea.bottom) return;
00650     bool ox = ((y & 1) == 1);
00651     int curGrad = 0;
00652 
00653     while (_gradIndexes[curGrad + 1] <= y)
00654         curGrad++;
00655 
00656     // precalcGradient assures that _gradIndexes entries always differ in
00657     // their value. This assures stripSize is always different from zero.
00658     int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
00659 
00660     int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
00661 
00662     // Dithering:
00663     //   +--+ +--+ +--+ +--+
00664     //   |  | |  | | *| | *|
00665     //   |  | | *| |* | |**|
00666     //   +--+ +--+ +--+ +--+
00667     //     0    1    2    3
00668     if (grad == 0 ||
00669         _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
00670         stripSize < 2) { // the stip is small
00671         colorFillClip<PixelType>(ptr, ptr + width, _gradCache[curGrad], realX, realY, _clippingArea);
00672     } else if (grad == 3 && ox) {
00673         colorFillClip<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1], realX, realY, _clippingArea);
00674     } else {
00675         for (int j = x; j < x + width; j++, ptr++) {
00676             if (realX + j - x < _clippingArea.left || realX + j - x >= _clippingArea.right) continue;
00677             bool oy = ((j & 1) == 1);
00678 
00679             if ((ox && oy) ||
00680                 ((grad == 2 || grad == 3) && ox && !oy) ||
00681                 (grad == 3 && oy))
00682                 *ptr = _gradCache[curGrad + 1];
00683             else
00684                 *ptr = _gradCache[curGrad];
00685         }
00686     }
00687 }
00688 
00689 template<typename PixelType>
00690 void VectorRendererSpec<PixelType>::
00691 fillSurface() {
00692     Common::Rect drawRect(0, 0, _activeSurface->w, _activeSurface->h);
00693     drawRect.clip(_clippingArea);
00694 
00695     if (drawRect.isEmpty()) {
00696         return;
00697     }
00698 
00699     int h = _activeSurface->h;
00700     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
00701 
00702     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, drawRect.top);
00703 
00704     if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {
00705         PixelType color = (Base::_fillMode == kFillBackground ? _bgColor : _fgColor);
00706         PixelType *ptrLeft = (ptr + drawRect.left), *ptrRight = ptr + drawRect.right;
00707         for (int i = drawRect.top; i < drawRect.bottom; i++) {
00708             colorFill<PixelType>(ptrLeft, ptrRight, color);
00709 
00710             ptrLeft += pitch;
00711             ptrRight += pitch;
00712         }
00713 
00714     } else if (Base::_fillMode == kFillGradient) {
00715         precalcGradient(h);
00716 
00717         for (int i = drawRect.top; i < drawRect.bottom; i++) {
00718             gradientFill(ptr + drawRect.left, drawRect.width(), 0, i);
00719 
00720             ptr += pitch;
00721         }
00722     }
00723 }
00724 
00725 template<typename PixelType>
00726 void VectorRendererSpec<PixelType>::
00727 copyFrame(OSystem *sys, const Common::Rect &r) {
00728 
00729     sys->copyRectToOverlay(
00730         _activeSurface->getBasePtr(r.left, r.top),
00731         _activeSurface->pitch,
00732         r.left, r.top, r.width(), r.height()
00733     );
00734 }
00735 
00736 template<typename PixelType>
00737 void VectorRendererSpec<PixelType>::
00738 blitSurface(const Graphics::Surface *source, const Common::Rect &r) {
00739     assert(source->w == _activeSurface->w && source->h == _activeSurface->h);
00740 
00741     byte *dst_ptr = (byte *)_activeSurface->getBasePtr(r.left, r.top);
00742     const byte *src_ptr = (const byte *)source->getBasePtr(r.left, r.top);
00743 
00744     const int dst_pitch = _activeSurface->pitch;
00745     const int src_pitch = source->pitch;
00746 
00747     int h = r.height();
00748     const int w = r.width() * sizeof(PixelType);
00749 
00750     while (h--) {
00751         memcpy(dst_ptr, src_ptr, w);
00752         dst_ptr += dst_pitch;
00753         src_ptr += src_pitch;
00754     }
00755 }
00756 
00757 template<typename PixelType>
00758 void VectorRendererSpec<PixelType>::
00759 blitSubSurface(const Graphics::Surface *source, const Common::Point &p) {
00760     Common::Rect drawRect(p.x, p.y, p.x + source->w, p.y + source->h);
00761     drawRect.clip(_clippingArea);
00762 
00763     if (drawRect.isEmpty()) {
00764         return;
00765     }
00766 
00767     int sourceOffsetX = drawRect.left - p.x;
00768     int sourceOffsetY = drawRect.top - p.y;
00769 
00770     byte *dst_ptr = (byte *)_activeSurface->getBasePtr(drawRect.left, drawRect.top);
00771     const byte *src_ptr = (const byte *)source->getBasePtr(sourceOffsetX, sourceOffsetY);
00772 
00773     const int dst_pitch = _activeSurface->pitch;
00774     const int src_pitch = source->pitch;
00775 
00776     int lines = drawRect.height();
00777     const int sz = drawRect.width() * sizeof(PixelType);
00778 
00779     while (lines--) {
00780         memcpy(dst_ptr, src_ptr, sz);
00781         dst_ptr += dst_pitch;
00782         src_ptr += src_pitch;
00783     }
00784 }
00785 
00786 template<typename PixelType>
00787 void VectorRendererSpec<PixelType>::
00788 blitKeyBitmap(const Graphics::Surface *source, const Common::Point &p) {
00789     Common::Rect drawRect(p.x, p.y, p.x + source->w, p.y + source->h);
00790     drawRect.clip(_clippingArea);
00791 
00792     if (drawRect.isEmpty()) {
00793         return;
00794     }
00795 
00796     int sourceOffsetX = drawRect.left - p.x;
00797     int sourceOffsetY = drawRect.top - p.y;
00798 
00799     PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(drawRect.left, drawRect.top);
00800     const PixelType *src_ptr = (const PixelType *)source->getBasePtr(sourceOffsetX, sourceOffsetY);
00801 
00802     int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
00803     int src_pitch = source->pitch / source->format.bytesPerPixel;
00804 
00805     int w, h = drawRect.height();
00806 
00807     while (h--) {
00808         w = drawRect.width();
00809 
00810         while (w--) {
00811             if (*src_ptr != _bitmapAlphaColor)
00812                 *dst_ptr = *src_ptr;
00813 
00814             dst_ptr++;
00815             src_ptr++;
00816         }
00817 
00818         dst_ptr = dst_ptr - drawRect.width() + dst_pitch;
00819         src_ptr = src_ptr - drawRect.width() + src_pitch;
00820     }
00821 }
00822 
00823 template<typename PixelType>
00824 void VectorRendererSpec<PixelType>::
00825 blitAlphaBitmap(Graphics::TransparentSurface *source, const Common::Rect &r, GUI::ThemeEngine::AutoScaleMode autoscale,
00826             Graphics::DrawStep::VectorAlignment xAlign, Graphics::DrawStep::VectorAlignment yAlign, int alpha) {
00827     if (autoscale == GUI::ThemeEngine::kAutoScaleStretch) {
00828         source->blit(*_activeSurface, r.left, r.top, Graphics::FLIP_NONE,
00829             nullptr, TS_ARGB(alpha, 255, 255, 255),
00830               r.width(), r.height());
00831     } else if (autoscale == GUI::ThemeEngine::kAutoScaleFit) {
00832         double ratio = (double)r.width() / source->w;
00833         double ratio2 = (double)r.height() / source->h;
00834 
00835         if (ratio2 < ratio)
00836             ratio = ratio2;
00837 
00838         int offx = 0, offy = 0;
00839         if (xAlign == Graphics::DrawStep::kVectorAlignCenter)
00840             offx = (r.width() - (int)(source->w * ratio)) >> 1;
00841 
00842         if (yAlign == Graphics::DrawStep::kVectorAlignCenter)
00843             offy = (r.height() - (int)(source->h * ratio)) >> 1;
00844 
00845         source->blit(*_activeSurface, r.left + offx, r.top + offy, Graphics::FLIP_NONE,
00846             nullptr, TS_ARGB(alpha, 255, 255, 255),
00847                       (int)(source->w * ratio), (int)(source->h * ratio));
00848 
00849     } else if (autoscale == GUI::ThemeEngine::kAutoScaleNinePatch) {
00850         Graphics::NinePatchBitmap nine(source, false);
00851         nine.blit(*_activeSurface, r.left, r.top, r.width(), r.height());
00852     } else {
00853         source->blit(*_activeSurface, r.left, r.top);
00854     }
00855 }
00856 
00857 template<typename PixelType>
00858 void VectorRendererSpec<PixelType>::
00859 applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
00860     int pixels = _activeSurface->w * _activeSurface->h;
00861     PixelType *ptr = (PixelType *)_activeSurface->getPixels();
00862     uint8 r, g, b;
00863     uint lum;
00864 
00865     // Mask to clear the last bit of every color component and all unused bits
00866     const uint32 colorMask = ~((1 << _format.rShift) | (1 << _format.gShift) | (1 << _format.bShift) // R/G/B components
00867             | (_format.aLoss == 8 ? 0 : (1 << _format.aShift)) // Alpha component
00868             | ~(_alphaMask | _redMask | _greenMask | _blueMask)); // All unused bits
00869 
00870     if (shadingStyle == GUI::ThemeEngine::kShadingDim) {
00871 
00872         // TODO: Check how this interacts with kFeatureOverlaySupportsAlpha
00873         for (int i = 0; i < pixels; ++i) {
00874             *ptr = ((*ptr & colorMask) >> 1) | _alphaMask;
00875             ++ptr;
00876         }
00877 
00878     } else if (shadingStyle == GUI::ThemeEngine::kShadingLuminance) {
00879         while (pixels--) {
00880             _format.colorToRGB(*ptr, r, g, b);
00881             lum = (r >> 2) + (g >> 1) + (b >> 3);
00882             *ptr++ = _format.RGBToColor(lum, lum, lum);
00883         }
00884     }
00885 }
00886 
00887 template<typename PixelType>
00888 inline void VectorRendererSpec<PixelType>::
00889 blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
00890     if (alpha == 0xff) {
00891         // fully opaque pixel, don't blend
00892         *ptr = color | _alphaMask;
00893     } else if (sizeof(PixelType) == 4) {
00894         const byte sR = (color & _redMask) >> _format.rShift;
00895         const byte sG = (color & _greenMask) >> _format.gShift;
00896         const byte sB = (color & _blueMask) >> _format.bShift;
00897 
00898         byte dR = (*ptr & _redMask) >> _format.rShift;
00899         byte dG = (*ptr & _greenMask) >> _format.gShift;
00900         byte dB = (*ptr & _blueMask) >> _format.bShift;
00901         byte dA = (*ptr & _alphaMask) >> _format.aShift;
00902 
00903         dR += ((sR - dR) * alpha) >> 8;
00904         dG += ((sG - dG) * alpha) >> 8;
00905         dB += ((sB - dB) * alpha) >> 8;
00906         dA += ((0xff - dA) * alpha) >> 8;
00907 
00908         *ptr = ((dR << _format.rShift) & _redMask)
00909              | ((dG << _format.gShift) & _greenMask)
00910              | ((dB << _format.bShift) & _blueMask)
00911              | ((dA << _format.aShift) & _alphaMask);
00912     } else if (sizeof(PixelType) == 2) {
00913         int idst = *ptr;
00914         int isrc = color;
00915 
00916         *ptr = (PixelType)(
00917             (_redMask & ((idst & _redMask) +
00918             ((int)(((int)(isrc & _redMask) -
00919             (int)(idst & _redMask)) * alpha) >> 8))) |
00920             (_greenMask & ((idst & _greenMask) +
00921             ((int)(((int)(isrc & _greenMask) -
00922             (int)(idst & _greenMask)) * alpha) >> 8))) |
00923             (_blueMask & ((idst & _blueMask) +
00924             ((int)(((int)(isrc & _blueMask) -
00925             (int)(idst & _blueMask)) * alpha) >> 8))) |
00926             (_alphaMask & ((idst & _alphaMask) +
00927             ((int)(((int)(_alphaMask) -
00928             (int)(idst & _alphaMask)) * alpha) >> 8))));
00929     } else {
00930         error("Unsupported BPP format: %u", (uint)sizeof(PixelType));
00931     }
00932 }
00933 
00934 template<typename PixelType>
00935 inline void VectorRendererSpec<PixelType>::
00936 blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y) {
00937     if (IS_IN_CLIP(x, y))
00938         blendPixelPtr(ptr, color, alpha);
00939 }
00940 
00941 template<typename PixelType>
00942 inline void VectorRendererSpec<PixelType>::
00943 blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) {
00944     int idst = *ptr;
00945     // This function is only used for corner pixels in rounded rectangles, so
00946     // the performance hit of this if shouldn't be too high.
00947     // We're also ignoring the cases where dst has intermediate alpha.
00948     if ((idst & _alphaMask) == 0) {
00949         // set color and alpha channels
00950         *ptr = (PixelType)(color & (_redMask | _greenMask | _blueMask)) |
00951                           ((alpha >> _format.aLoss) << _format.aShift);
00952     } else {
00953         // blend color with background
00954         blendPixelPtr(ptr, color, alpha);
00955     }
00956 }
00957 
00958 template<typename PixelType>
00959 inline void VectorRendererSpec<PixelType>::
00960 darkenFill(PixelType *ptr, PixelType *end) {
00961     PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
00962 
00963     if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
00964         // !kFeatureOverlaySupportsAlpha (but might have alpha bits)
00965 
00966         while (ptr != end) {
00967             *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
00968             ++ptr;
00969         }
00970     } else {
00971         // kFeatureOverlaySupportsAlpha
00972         // assuming at least 3 alpha bits
00973 
00974         mask |= 3 << _format.aShift;
00975         PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
00976 
00977         while (ptr != end) {
00978             // Darken the color, and increase the alpha
00979             // (0% -> 75%, 100% -> 100%)
00980             *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
00981             ++ptr;
00982         }
00983     }
00984 }
00985 
00986 template<typename PixelType>
00987 inline void VectorRendererSpec<PixelType>::
00988 darkenFillClip(PixelType *ptr, PixelType *end, int x, int y) {
00989     PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
00990 
00991     if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
00992         // !kFeatureOverlaySupportsAlpha (but might have alpha bits)
00993 
00994         while (ptr != end) {
00995             if (IS_IN_CLIP(x, y)) *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
00996             ++ptr;
00997             ++x;
00998         }
00999     } else {
01000         // kFeatureOverlaySupportsAlpha
01001         // assuming at least 3 alpha bits
01002 
01003         mask |= 3 << _format.aShift;
01004         PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
01005 
01006         while (ptr != end) {
01007             // Darken the color, and increase the alpha
01008             // (0% -> 75%, 100% -> 100%)
01009             if (IS_IN_CLIP(x, y)) *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
01010             ++ptr;
01011             ++x;
01012         }
01013     }
01014 }
01015 
01016 /********************************************************************
01017  ********************************************************************
01018  * Primitive shapes drawing - Public API calls - VectorRendererSpec *
01019  ********************************************************************
01020  ********************************************************************/
01021 template<typename PixelType>
01022 void VectorRendererSpec<PixelType>::
01023 drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area,
01024             Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis, const Common::Rect &textDrawableArea) {
01025 
01026     int offset = area.top;
01027 
01028     if (font->getFontHeight() < area.height()) {
01029         switch (alignV) {
01030         case GUI::ThemeEngine::kTextAlignVCenter:
01031             offset = area.top + ((area.height() - font->getFontHeight()) >> 1);
01032             break;
01033         case GUI::ThemeEngine::kTextAlignVBottom:
01034             offset = area.bottom - font->getFontHeight();
01035             break;
01036         default:
01037             break;
01038         }
01039     }
01040 
01041     Common::Rect drawArea;
01042     if (textDrawableArea.isEmpty()) {
01043         // In case no special area to draw to is given we only draw in the
01044         // area specified by the user.
01045         drawArea = area;
01046         // warning("there is no text drawable area. Please set this area for clipping");
01047     } else {
01048         // The area we can draw to is the intersection between the allowed
01049         // drawing area (textDrawableArea) and the area where we try to draw
01050         // the text (area).
01051         drawArea = textDrawableArea.findIntersectingRect(area);
01052     }
01053 
01054     // Better safe than sorry. We intersect with the actual surface boundaries
01055     // to avoid any ugly clipping in _activeSurface->getSubArea which messes
01056     // up the calculation of the x and y coordinates where to draw the string.
01057     drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h));
01058 
01059     if (!drawArea.isEmpty()) {
01060         Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
01061         font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
01062     }
01063 }
01064 
01065 template<typename PixelType>
01066 void VectorRendererSpec<PixelType>::
01067 drawLine(int x1, int y1, int x2, int y2) {
01068     x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
01069     x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
01070     y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
01071     y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
01072 
01073     // we draw from top to bottom
01074     if (y2 < y1) {
01075         SWAP(x1, x2);
01076         SWAP(y1, y2);
01077     }
01078 
01079     uint dx = ABS(x2 - x1);
01080     uint dy = ABS(y2 - y1);
01081 
01082     // this is a point, not a line. stoopid.
01083     if (dy == 0 && dx == 0)
01084         return;
01085 
01086     if (Base::_strokeWidth == 0)
01087         return;
01088 
01089     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
01090     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01091     int st = Base::_strokeWidth >> 1;
01092 
01093     bool useClippingVersions = !_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2);
01094 
01095     int ptr_x = x1, ptr_y = y1;
01096 
01097     if (dy == 0) { // horizontal lines
01098         if (useClippingVersions) {
01099             colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
01100         } else {
01101             colorFill<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor);
01102         }
01103 
01104         for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
01105             if (useClippingVersions) {
01106                 colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
01107                 colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
01108             } else {
01109                 colorFill<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor);
01110                 colorFill<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor);
01111             }
01112         }
01113 
01114     } else if (dx == 0) { // vertical lines
01115                           // these ones use a static pitch increase.
01116         while (y1++ <= y2) {
01117             if (useClippingVersions) {
01118                 colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
01119             } else {
01120                 colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
01121             }
01122             ptr += pitch;
01123             ++ptr_y;
01124         }
01125 
01126     } else if (dx == dy) { // diagonal lines
01127                            // these ones also use a fixed pitch increase
01128         pitch += (x2 > x1) ? 1 : -1;
01129 
01130         while (dy--) {
01131             if (useClippingVersions) {
01132                 colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
01133             } else {
01134                 colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
01135             }
01136             ptr += pitch;
01137             ++ptr_y;
01138             if (x2 > x1) ++ptr_x; else --ptr_x;
01139         }
01140 
01141     } else { // generic lines, use the standard algorithm...
01142         if (useClippingVersions) {
01143             drawLineAlgClip(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
01144         } else {
01145             drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
01146         }
01147     }
01148 }
01149 
01151 template<typename PixelType>
01152 void VectorRendererSpec<PixelType>::
01153 drawCircle(int x, int y, int r) {
01154     if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h ||
01155         x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0)
01156         return;
01157 
01158     bool useClippingVersions = !_clippingArea.contains(Common::Rect(x - r, y - r, x + r, y + r));
01159 
01160     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01161         && x + r + Base::_shadowOffset < Base::_activeSurface->w
01162         && y + r + Base::_shadowOffset < Base::_activeSurface->h) {
01163         if (useClippingVersions)
01164             drawCircleAlgClip(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
01165         else
01166             drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
01167     }
01168 
01169     switch (Base::_fillMode) {
01170     case kFillDisabled:
01171         if (Base::_strokeWidth) {
01172             if (useClippingVersions)
01173                 drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
01174             else
01175                 drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01176         }
01177         break;
01178 
01179     case kFillForeground:
01180         if (useClippingVersions)
01181             drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
01182         else
01183             drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01184         break;
01185 
01186     case kFillBackground:
01187         if (Base::_strokeWidth > 1) {
01188             if (useClippingVersions) {
01189                 drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
01190                 drawCircleAlgClip(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
01191             } else {
01192                 drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01193                 drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
01194             }
01195         } else {
01196             if (useClippingVersions) {
01197                 drawCircleAlgClip(x, y, r, _bgColor, kFillBackground);
01198                 drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
01199             } else {
01200                 drawCircleAlg(x, y, r, _bgColor, kFillBackground);
01201                 drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01202             }
01203         }
01204         break;
01205 
01206     case kFillGradient:
01207         break;
01208     }
01209 }
01210 
01212 template<typename PixelType>
01213 void VectorRendererSpec<PixelType>::
01214 drawSquare(int x, int y, int w, int h) {
01215     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01216         w <= 0 || h <= 0 || x < 0 || y < 0)
01217         return;
01218 
01219     bool useClippingVersions = !_clippingArea.contains(Common::Rect(x, y, x + w, y + h));
01220 
01221     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01222         && x + w + Base::_shadowOffset < Base::_activeSurface->w
01223         && y + h + Base::_shadowOffset < Base::_activeSurface->h) {
01224         if (useClippingVersions)
01225             drawSquareShadowClip(x, y, w, h, Base::_shadowOffset);
01226         else
01227             drawSquareShadow(x, y, w, h, Base::_shadowOffset);
01228     }
01229 
01230     switch (Base::_fillMode) {
01231     case kFillDisabled:
01232         if (Base::_strokeWidth) {
01233             if (useClippingVersions)
01234                 drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01235             else
01236                 drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01237         }
01238         break;
01239 
01240     case kFillForeground:
01241         if (useClippingVersions)
01242             drawSquareAlgClip(x, y, w, h, _fgColor, kFillForeground);
01243         else
01244             drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
01245         break;
01246 
01247     case kFillBackground:
01248         if (useClippingVersions) {
01249             drawSquareAlgClip(x, y, w, h, _bgColor, kFillBackground);
01250             drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01251         } else {
01252             drawSquareAlg(x, y, w, h, _bgColor, kFillBackground);
01253             drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01254         }
01255         break;
01256 
01257     case kFillGradient:
01258         VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
01259         if (Base::_strokeWidth) {
01260             if (useClippingVersions)
01261                 drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01262             else
01263                 drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01264         }
01265         break;
01266     }
01267 }
01268 
01270 template<typename PixelType>
01271 void VectorRendererSpec<PixelType>::
01272 drawRoundedSquare(int x, int y, int r, int w, int h) {
01273     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01274         w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
01275         return;
01276 
01277     if ((r * 2) > w || (r * 2) > h)
01278         r = MIN(w / 2, h / 2);
01279 
01280     if (r <= 0)
01281         return;
01282 
01283     bool useOriginal = _clippingArea.contains(Common::Rect(x, y, x + w, y + h));
01284 
01285     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01286         && x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
01287         && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
01288         && h > (Base::_shadowOffset + 1) * 2) {
01289         if (useOriginal) {
01290             drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
01291         } else {
01292             drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset);
01293         }
01294     }
01295 
01296     if (useOriginal) {
01297         drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
01298     } else {
01299         drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
01300     }
01301 }
01302 
01303 template<typename PixelType>
01304 void VectorRendererSpec<PixelType>::
01305 drawTab(int x, int y, int r, int w, int h) {
01306     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01307         w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
01308         return;
01309 
01310     bool useClippingVersions = !_clippingArea.contains(Common::Rect(x, y, x + w, y + h));
01311 
01312     if (r == 0 && Base::_bevel > 0) {
01313         if (useClippingVersions)
01314             drawBevelTabAlgClip(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01315         else
01316             drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01317         return;
01318     }
01319 
01320     if (r == 0) {
01321         return;
01322     }
01323 
01324     switch (Base::_fillMode) {
01325     case kFillDisabled:
01326         // FIXME: Implement this
01327         return;
01328 
01329     case kFillGradient:
01330     case kFillBackground:
01331         // FIXME: This is broken for the AA renderer.
01332         // See the rounded rect alg for how to fix it. (The border should
01333         // be drawn before the interior, both inside drawTabAlg.)
01334         if (useClippingVersions) {
01335             drawTabShadowClip(x, y, w - 2, h, r);
01336             drawTabAlgClip(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
01337             if (Base::_strokeWidth)
01338                 drawTabAlgClip(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01339         } else {
01340             drawTabShadow(x, y, w - 2, h, r);
01341             drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
01342             if (Base::_strokeWidth)
01343                 drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01344         }
01345         break;
01346 
01347     case kFillForeground:
01348         if (useClippingVersions)
01349             drawTabAlgClip(x, y, w, h, r, _fgColor, Base::_fillMode);
01350         else
01351             drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
01352         break;
01353     }
01354 }
01355 
01356 template<typename PixelType>
01357 void VectorRendererSpec<PixelType>::
01358 drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
01359     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
01360         return;
01361 
01362     PixelType color = 0;
01363 
01364     if (Base::_strokeWidth <= 1) {
01365         if (Base::_fillMode == kFillForeground)
01366             color = _fgColor;
01367         else if (Base::_fillMode == kFillBackground)
01368             color = _bgColor;
01369     } else {
01370         if (Base::_fillMode == kFillDisabled)
01371             return;
01372         color = _fgColor;
01373     }
01374 
01375     if (Base::_dynamicData != 0)
01376         orient = (TriangleOrientation)Base::_dynamicData;
01377 
01378     bool useClippingVersions = !_clippingArea.contains(Common::Rect(x, y, x + w, y + h));
01379 
01380     if (w == h) {
01381         int newW = w;
01382 
01383         switch (orient) {
01384         case kTriangleUp:
01385         case kTriangleDown:
01386             if (useClippingVersions)
01387                 drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01388             else
01389                 drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01390             break;
01391 
01392         case kTriangleLeft:
01393         case kTriangleRight:
01394         case kTriangleAuto:
01395             break;
01396         }
01397 
01398         if (Base::_strokeWidth > 0)
01399             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01400                 if (useClippingVersions)
01401                     drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01402                 else
01403                     drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01404             }
01405     } else {
01406         int newW = w;
01407         int newH = h;
01408 
01409         switch (orient) {
01410         case kTriangleUp:
01411         case kTriangleDown:
01412             if (useClippingVersions)
01413                 drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
01414             else
01415                 drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
01416             break;
01417 
01418         case kTriangleLeft:
01419         case kTriangleRight:
01420         case kTriangleAuto:
01421             break;
01422         }
01423 
01424         if (Base::_strokeWidth > 0) {
01425             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01426                 if (useClippingVersions)
01427                     drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
01428                 else
01429                     drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
01430             }
01431         }
01432     }
01433 }
01434 
01435 
01436 /********************************************************************
01437  ********************************************************************
01438  * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec
01439  ********************************************************************
01440  ********************************************************************/
01442 template<typename PixelType>
01443 void VectorRendererSpec<PixelType>::
01444 drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
01445     // Don't draw anything for empty rects.
01446     if (w <= 0 || h <= 0) {
01447         return;
01448     }
01449 
01450     int f, ddF_x, ddF_y;
01451     int x, y, px, py;
01452     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01453     int sw  = 0, sp = 0, hp = 0;
01454 
01455     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
01456     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
01457     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
01458 
01459     int real_radius = r;
01460     int short_h = h - r;
01461     int long_h = h;
01462 
01463     if (fill_m == kFillDisabled) {
01464         while (sw++ < Base::_strokeWidth) {
01465             colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
01466             colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
01467             sp += pitch;
01468 
01469             BE_RESET();
01470             r--;
01471 
01472             while (x++ < y) {
01473                 BE_ALGORITHM();
01474                 BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py);
01475 
01476                 if (Base::_strokeWidth > 1)
01477                     BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py);
01478             }
01479         }
01480 
01481         ptr_fill += pitch * real_radius;
01482         while (short_h--) {
01483             colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color);
01484             colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
01485             ptr_fill += pitch;
01486         }
01487 
01488         if (baseLeft) {
01489             sw = 0;
01490             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
01491             while (sw++ < Base::_strokeWidth) {
01492                 colorFill<PixelType>(ptr_fill - baseLeft, ptr_fill, color);
01493                 ptr_fill += pitch;
01494             }
01495         }
01496 
01497         if (baseRight) {
01498             sw = 0;
01499             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
01500             while (sw++ < Base::_strokeWidth) {
01501                 colorFill<PixelType>(ptr_fill, ptr_fill + baseRight, color);
01502                 ptr_fill += pitch;
01503             }
01504         }
01505     } else {
01506         BE_RESET();
01507 
01508         precalcGradient(long_h);
01509 
01510         PixelType color1, color2;
01511         color1 = color2 = color;
01512 
01513         while (x++ < y) {
01514             BE_ALGORITHM();
01515 
01516             if (fill_m == kFillGradient) {
01517                 color1 = calcGradient(real_radius - x, long_h);
01518                 color2 = calcGradient(real_radius - y, long_h);
01519 
01520                 gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
01521                 gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
01522 
01523                 BE_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py);
01524             } else {
01525                 colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color);
01526                 colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color);
01527 
01528                 BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py);
01529             }
01530         }
01531 
01532         ptr_fill += pitch * r;
01533         while (short_h--) {
01534             if (fill_m == kFillGradient) {
01535                 gradientFill(ptr_fill, w + 1, x1, real_radius++);
01536             } else {
01537                 colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
01538             }
01539             ptr_fill += pitch;
01540         }
01541     }
01542 }
01543 
01544 template<typename PixelType>
01545 void VectorRendererSpec<PixelType>::
01546 drawTabAlgClip(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
01547     // Don't draw anything for empty rects.
01548     if (w <= 0 || h <= 0) {
01549         return;
01550     }
01551 
01552     int f, ddF_x, ddF_y;
01553     int x, y, px, py;
01554     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01555     int sw = 0, sp = 0, hp = 0;
01556 
01557     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
01558     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
01559     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
01560     int tl_x = x1 + r, tl_y = y1 + r;
01561     int tr_x = x1 + w - r, tr_y = y1 + r;
01562     int fill_x = x1, fill_y = y1;
01563 
01564     int real_radius = r;
01565     int short_h = h - r;
01566     int long_h = h;
01567 
01568     if (fill_m == kFillDisabled) {
01569         while (sw++ < Base::_strokeWidth) {
01570             colorFillClip<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, fill_x + r, fill_y + sp/pitch, _clippingArea);
01571             colorFillClip<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, fill_x + r, fill_y + hp / pitch - sp / pitch, _clippingArea);
01572             sp += pitch;
01573 
01574             BE_RESET();
01575             r--;
01576 
01577             while (x++ < y) {
01578                 BE_ALGORITHM();
01579                 BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
01580 
01581                 if (Base::_strokeWidth > 1)
01582                     BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px - pitch, py, tr_x, tr_y, tl_x, tl_y);
01583             }
01584         }
01585 
01586         ptr_fill += pitch * real_radius;
01587         fill_y += real_radius;
01588         while (short_h--) {
01589             colorFillClip<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color, fill_x, fill_y, _clippingArea);
01590             colorFillClip<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, fill_x + w - Base::_strokeWidth + 1, fill_y, _clippingArea);
01591             ptr_fill += pitch;
01592             ++fill_y;
01593         }
01594 
01595         if (baseLeft) {
01596             sw = 0;
01597             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
01598             fill_x = x1;
01599             fill_y = y1 + h + 1;
01600             while (sw++ < Base::_strokeWidth) {
01601                 colorFillClip<PixelType>(ptr_fill - baseLeft, ptr_fill, color, fill_x - baseLeft, fill_y, _clippingArea);
01602                 ptr_fill += pitch;
01603                 ++fill_y;
01604             }
01605         }
01606 
01607         if (baseRight) {
01608             sw = 0;
01609             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
01610             fill_x = x1 + w;
01611             fill_y = y1 + h + 1;
01612             while (sw++ < Base::_strokeWidth) {
01613                 colorFillClip<PixelType>(ptr_fill, ptr_fill + baseRight, color, fill_x, fill_y, _clippingArea);
01614                 ptr_fill += pitch;
01615                 ++fill_y;
01616             }
01617         }
01618     } else {
01619         BE_RESET();
01620 
01621         precalcGradient(long_h);
01622 
01623         PixelType color1, color2;
01624         color1 = color2 = color;
01625 
01626         while (x++ < y) {
01627             BE_ALGORITHM();
01628 
01629             if (fill_m == kFillGradient) {
01630                 color1 = calcGradient(real_radius - x, long_h);
01631                 color2 = calcGradient(real_radius - y, long_h);
01632 
01633                 gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y, tl_x - x, tl_y - y);
01634                 gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x, tl_x - y, tl_y - x);
01635 
01636                 BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
01637             } else {
01638                 colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color, tl_x - x, tl_y - y, _clippingArea);
01639                 colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color, tl_x - y, tl_y - x, _clippingArea);
01640 
01641                 BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
01642             }
01643         }
01644 
01645         ptr_fill += pitch * r;
01646         fill_y += r;
01647         while (short_h--) {
01648             if (fill_m == kFillGradient) {
01649                 gradientFillClip(ptr_fill, w + 1, x1, real_radius++, fill_x, fill_y);
01650             } else {
01651                 colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color, fill_x, fill_y, _clippingArea);
01652             }
01653             ptr_fill += pitch;
01654             ++fill_y;
01655         }
01656     }
01657 }
01658 
01659 template<typename PixelType>
01660 void VectorRendererSpec<PixelType>::
01661 drawTabShadow(int x1, int y1, int w, int h, int r) {
01662     int offset = 3;
01663     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01664 
01665     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
01666     uint8 expFactor = 3;
01667     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
01668 
01669     int xstart = x1;
01670     int ystart = y1;
01671     int width = w;
01672     int height = h + offset + 1;
01673 
01674     for (int i = offset; i >= 0; i--) {
01675         int f, ddF_x, ddF_y;
01676         int x, y, px, py;
01677 
01678         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
01679         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
01680         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
01681 
01682         int short_h = height - (2 * r);
01683         PixelType color = _format.RGBToColor(0, 0, 0);
01684 
01685         BE_RESET();
01686 
01687         // HACK: As we are drawing circles exploting 8-axis symmetry,
01688         // there are 4 pixels on each circle which are drawn twice.
01689         // this is ok on filled circles, but when blending on surfaces,
01690         // we cannot let it blend twice. awful.
01691         uint32 hb = 0;
01692 
01693         while (x++ < y) {
01694             BE_ALGORITHM();
01695 
01696             if (((1 << x) & hb) == 0) {
01697                 blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
01698                 hb |= (1 << x);
01699             }
01700 
01701             if (((1 << y) & hb) == 0) {
01702                 blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
01703                 hb |= (1 << y);
01704             }
01705         }
01706 
01707         ptr_fill += pitch * r;
01708         while (short_h--) {
01709             blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
01710             ptr_fill += pitch;
01711         }
01712 
01713         // Move shadow one pixel upward each iteration
01714         xstart += 1;
01715         // Multiply with expfactor
01716         alpha = (alpha * (expFactor << 8)) >> 9;
01717     }
01718 }
01719 
01720 template<typename PixelType>
01721 void VectorRendererSpec<PixelType>::
01722 drawTabShadowClip(int x1, int y1, int w, int h, int r) {
01723     int offset = 3;
01724     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01725 
01726     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
01727     uint8 expFactor = 3;
01728     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
01729 
01730     int xstart = x1;
01731     int ystart = y1;
01732     int width = w;
01733     int height = h + offset + 1;
01734 
01735     for (int i = offset; i >= 0; i--) {
01736         int f, ddF_x, ddF_y;
01737         int x, y, px, py;
01738 
01739         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
01740         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
01741         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
01742 
01743         int tl_x = xstart + r, tl_y = ystart + r;
01744         int fill_x = xstart, fill_y = ystart;
01745 
01746         int short_h = height - (2 * r);
01747         PixelType color = _format.RGBToColor(0, 0, 0);
01748 
01749         BE_RESET();
01750 
01751         // HACK: As we are drawing circles exploting 8-axis symmetry,
01752         // there are 4 pixels on each circle which are drawn twice.
01753         // this is ok on filled circles, but when blending on surfaces,
01754         // we cannot let it blend twice. awful.
01755         uint32 hb = 0;
01756 
01757         while (x++ < y) {
01758             BE_ALGORITHM();
01759 
01760             if (((1 << x) & hb) == 0) {
01761                 blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, tl_x - y, tl_y - x);
01762                 hb |= (1 << x);
01763             }
01764 
01765             if (((1 << y) & hb) == 0) {
01766                 blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, tl_x - x, tl_y - y);
01767                 hb |= (1 << y);
01768             }
01769         }
01770 
01771         ptr_fill += pitch * r;
01772         fill_y += r;
01773         while (short_h--) {
01774             blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha, fill_x, fill_y);
01775             ptr_fill += pitch;
01776             ++fill_y;
01777         }
01778 
01779         // Move shadow one pixel upward each iteration
01780         xstart += 1;
01781         // Multiply with expfactor
01782         alpha = (alpha * (expFactor << 8)) >> 9;
01783     }
01784 }
01785 
01787 template<typename PixelType>
01788 void VectorRendererSpec<PixelType>::
01789 drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
01790     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01791     int i, j;
01792 
01793     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01794 
01795     i = bevel;
01796     while (i--) {
01797         colorFill<PixelType>(ptr_left, ptr_left + w, top_color);
01798         ptr_left += pitch;
01799     }
01800 
01801     if (baseLeft > 0) {
01802         i = h - bevel;
01803         ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01804         while (i--) {
01805             colorFill<PixelType>(ptr_left, ptr_left + bevel, top_color);
01806             ptr_left += pitch;
01807         }
01808     }
01809 
01810     i = h - bevel;
01811     j = bevel - 1;
01812     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
01813     while (i--) {
01814         colorFill<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color);
01815         if (j > 0) j--;
01816         ptr_left += pitch;
01817     }
01818 
01819     i = bevel;
01820     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
01821     while (i--) {
01822         colorFill<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color);
01823 
01824         if (baseLeft)
01825             colorFill<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color);
01826         ptr_left += pitch;
01827     }
01828 }
01829 
01830 template<typename PixelType>
01831 void VectorRendererSpec<PixelType>::
01832 drawBevelTabAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
01833     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01834     int i, j;
01835 
01836     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01837     int ptr_x = x, ptr_y = y;
01838 
01839     i = bevel;
01840     while (i--) {
01841         colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
01842         ptr_left += pitch;
01843         ++ptr_y;
01844     }
01845 
01846     if (baseLeft > 0) {
01847         i = h - bevel;
01848         ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01849         ptr_x = x; ptr_y = y;
01850         while (i--) {
01851             colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
01852             ptr_left += pitch;
01853             ++ptr_y;
01854         }
01855     }
01856 
01857     i = h - bevel;
01858     j = bevel - 1;
01859     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
01860     ptr_x = x + w - bevel; ptr_y = y;
01861     while (i--) {
01862         colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
01863         if (j > 0) j--;
01864         ptr_left += pitch;
01865         ++ptr_y;
01866     }
01867 
01868     i = bevel;
01869     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
01870     ptr_x = x + w - bevel; ptr_y = y + h - bevel;
01871     while (i--) {
01872         colorFillClip<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color, ptr_x, ptr_y, _clippingArea);
01873 
01874         if (baseLeft)
01875             colorFillClip<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color, ptr_x - w - baseLeft + bevel, ptr_y, _clippingArea);
01876         ptr_left += pitch;
01877         ++ptr_y;
01878     }
01879 }
01880 
01882 template<typename PixelType>
01883 void VectorRendererSpec<PixelType>::
01884 drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
01885     // Do not draw anything for empty rects.
01886     if (w <= 0 || h <= 0) {
01887         return;
01888     }
01889 
01890     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
01891     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01892     int max_h = h;
01893 
01894     if (fill_m != kFillDisabled) {
01895         while (h--) {
01896             if (fill_m == kFillGradient)
01897                 color = calcGradient(max_h - h, max_h);
01898 
01899             colorFill<PixelType>(ptr, ptr + w, color);
01900             ptr += pitch;
01901         }
01902     } else {
01903         int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
01904 
01905         while (sw--) {
01906             colorFill<PixelType>(ptr + sp, ptr + w + sp, color);
01907             colorFill<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color);
01908             sp += pitch;
01909         }
01910 
01911         while (h--) {
01912             colorFill<PixelType>(ptr, ptr + Base::_strokeWidth, color);
01913             colorFill<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color);
01914             ptr += pitch;
01915         }
01916     }
01917 }
01918 
01919 template<typename PixelType>
01920 void VectorRendererSpec<PixelType>::
01921 drawSquareAlgClip(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
01922     // Do not draw anything for empty rects.
01923     if (w <= 0 || h <= 0) {
01924         return;
01925     }
01926 
01927     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
01928     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01929     int max_h = h;
01930     int ptr_y = y;
01931 
01932     if (fill_m != kFillDisabled) {
01933         while (h--) {
01934             if (fill_m == kFillGradient)
01935                 color = calcGradient(max_h - h, max_h);
01936 
01937             colorFillClip<PixelType>(ptr, ptr + w, color, x, ptr_y, _clippingArea);
01938             ptr += pitch;
01939             ++ptr_y;
01940         }
01941     } else {
01942         int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
01943 
01944         while (sw--) {
01945             colorFillClip<PixelType>(ptr + sp, ptr + w + sp, color, x, ptr_y + sp/pitch, _clippingArea);
01946             colorFillClip<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color, x, ptr_y + h - sp/pitch, _clippingArea);
01947             sp += pitch;
01948         }
01949 
01950         while (h--) {
01951             colorFillClip<PixelType>(ptr, ptr + Base::_strokeWidth, color, x, ptr_y, _clippingArea);
01952             colorFillClip<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color, x + w - Base::_strokeWidth, ptr_y, _clippingArea);
01953             ptr += pitch;
01954             ptr_y += 1;
01955         }
01956     }
01957 }
01958 
01960 template<typename PixelType>
01961 void VectorRendererSpec<PixelType>::
01962 drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color) {
01963     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01964     int i, j;
01965     PixelType *ptr_left;
01966 
01967     // Fill Background
01968     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01969     i = h;
01970     // Optimize rendering in case the background color is black
01971     if ((_bgColor & ~_alphaMask) == 0) {
01972         while (i--) {
01973             darkenFill(ptr_left, ptr_left + w);
01974             ptr_left += pitch;
01975         }
01976     } else {
01977         while (i--) {
01978             blendFill(ptr_left, ptr_left + w, _bgColor, 200);
01979             ptr_left += pitch;
01980         }
01981     }
01982 
01983     x = MAX(x - bevel, 0);
01984     y = MAX(y - bevel, 0);
01985 
01986     w = MIN(x + w + (bevel * 2), (int)_activeSurface->w) - x;
01987     h = MIN(y + h + (bevel * 2), (int)_activeSurface->h) - y;
01988 
01989     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
01990     i = bevel;
01991     while (i--) {
01992         colorFill<PixelType>(ptr_left, ptr_left + w, top_color);
01993         ptr_left += pitch;
01994     }
01995 
01996     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
01997     i = h - bevel;
01998     while (i--) {
01999         colorFill<PixelType>(ptr_left, ptr_left + bevel, top_color);
02000         ptr_left += pitch;
02001     }
02002 
02003     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
02004     i = bevel;
02005     while (i--) {
02006         colorFill<PixelType>(ptr_left + i, ptr_left + w, bottom_color);
02007         ptr_left += pitch;
02008     }
02009 
02010     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02011     i = h - bevel;
02012     j = bevel - 1;
02013     while (i--) {
02014         colorFill<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color);
02015         if (j > 0) j--;
02016         ptr_left += pitch;
02017     }
02018 }
02019 
02020 template<typename PixelType>
02021 void VectorRendererSpec<PixelType>::
02022 drawBevelSquareAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color) {
02023     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02024     int i, j;
02025     PixelType *ptr_left;
02026     int ptr_x, ptr_y;
02027 
02028     // Fill Background
02029     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02030     ptr_x = x; ptr_y = y;
02031     i = h;
02032     // Optimize rendering in case the background color is black
02033     if ((_bgColor & ~_alphaMask) == 0) {
02034         while (i--) {
02035             darkenFillClip(ptr_left, ptr_left + w, ptr_x, ptr_y);
02036             ptr_left += pitch;
02037             ++ptr_y;
02038         }
02039     } else {
02040         while (i-- ) {
02041             blendFillClip(ptr_left, ptr_left + w, ptr_x, ptr_y, _bgColor, 200);
02042             ptr_left += pitch;
02043         }
02044     }
02045 
02046     x = MAX(x - bevel, 0);
02047     y = MAX(y - bevel, 0);
02048 
02049     w = MIN(x + w + (bevel * 2), (int)_activeSurface->w) - x;
02050     h = MIN(y + h + (bevel * 2), (int)_activeSurface->h) - y;
02051 
02052     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02053     ptr_x = x; ptr_y = y;
02054     i = bevel;
02055     while (i--) {
02056         colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
02057         ptr_left += pitch;
02058         ++ptr_y;
02059     }
02060 
02061     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
02062     ptr_x = x; ptr_y = y + bevel;
02063     i = h - bevel;
02064     while (i--) {
02065         colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
02066         ptr_left += pitch;
02067         ++ptr_y;
02068     }
02069 
02070     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
02071     ptr_x = x; ptr_y = y + h - bevel;
02072     i = bevel;
02073     while (i--) {
02074         colorFillClip<PixelType>(ptr_left + i, ptr_left + w, bottom_color, ptr_x + i, ptr_y, _clippingArea);
02075         ptr_left += pitch;
02076         ++ptr_y;
02077     }
02078 
02079     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02080     ptr_x = x + w - bevel; ptr_y = y;
02081     i = h - bevel;
02082     j = bevel - 1;
02083     while (i--) {
02084         colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
02085         if (j > 0) j--;
02086         ptr_left += pitch;
02087         ++ptr_y;
02088     }
02089 }
02090 
02092 template<typename PixelType>
02093 void VectorRendererSpec<PixelType>::
02094 drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
02095     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02096     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02097     int xdir = (x2 > x1) ? 1 : -1;
02098 
02099     *ptr = (PixelType)color;
02100 
02101     if (dx > dy) {
02102         int ddy = dy * 2;
02103         int dysub = ddy - (dx * 2);
02104         int error_term = ddy - dx;
02105 
02106         while (dx--) {
02107             if (error_term >= 0) {
02108                 ptr += pitch;
02109                 error_term += dysub;
02110             } else {
02111                 error_term += ddy;
02112             }
02113 
02114             ptr += xdir;
02115             *ptr = (PixelType)color;
02116         }
02117     } else {
02118         int ddx = dx * 2;
02119         int dxsub = ddx - (dy * 2);
02120         int error_term = ddx - dy;
02121 
02122         while (dy--) {
02123             if (error_term >= 0) {
02124                 ptr += xdir;
02125                 error_term += dxsub;
02126             } else {
02127                 error_term += ddx;
02128             }
02129 
02130             ptr += pitch;
02131             *ptr = (PixelType)color;
02132         }
02133     }
02134 
02135     ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
02136     *ptr = (PixelType)color;
02137 }
02138 
02139 template<typename PixelType>
02140 void VectorRendererSpec<PixelType>::
02141 drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
02142     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02143     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02144     int xdir = (x2 > x1) ? 1 : -1;
02145     int ptr_x = x1, ptr_y = y1;
02146 
02147     if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02148 
02149     if (dx > dy) {
02150         int ddy = dy * 2;
02151         int dysub = ddy - (dx * 2);
02152         int error_term = ddy - dx;
02153 
02154         while (dx--) {
02155             if (error_term >= 0) {
02156                 ptr += pitch;
02157                 ++ptr_y;
02158                 error_term += dysub;
02159             } else {
02160                 error_term += ddy;
02161             }
02162 
02163             ptr += xdir;
02164             ptr_x += xdir;
02165             if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02166         }
02167     } else {
02168         int ddx = dx * 2;
02169         int dxsub = ddx - (dy * 2);
02170         int error_term = ddx - dy;
02171 
02172         while (dy--) {
02173             if (error_term >= 0) {
02174                 ptr += xdir;
02175                 ptr_x += xdir;
02176                 error_term += dxsub;
02177             } else {
02178                 error_term += ddx;
02179             }
02180 
02181             ptr += pitch;
02182             ++ptr_y;
02183             if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02184         }
02185     }
02186 
02187     ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
02188     ptr_x = x2; ptr_y = y2;
02189     if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02190 }
02191 
02197 #define FIXED_POINT 1
02198 
02199 #if FIXED_POINT
02200 #define ipart(x) ((x) & ~0xFF)
02201 // This is not really correct since gradient is not percentage, but [0..255]
02202 #define rfpart(x) ((0x100 - ((x) & 0xFF)) * 100 >> 8)
02203 //#define rfpart(x) (0x100 - ((x) & 0xFF))
02204 #else
02205 #define ipart(x) ((int)x)
02206 #define round(x) (ipart(x + 0.5))
02207 #define fpart(x) (x - ipart(x))
02208 #define rfpart(x) (int)((1 - fpart(x)) * 100)
02209 #endif
02210 
02211 template<typename PixelType>
02212 void VectorRendererSpec<PixelType>::
02213 drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02214     // Don't draw anything for empty rects. This assures dy is always different
02215     // from zero.
02216     if (w <= 0 || h <= 0) {
02217         return;
02218     }
02219 
02220     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02221     int gradient_h = 0;
02222     if (!inverted) {
02223         pitch = -pitch;
02224         y1 += h;
02225     }
02226 
02227     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02228     PixelType *floor = ptr_right - 1;
02229     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
02230 
02231     int x2 = x1 + w / 2;
02232     int y2 = y1 + h;
02233 
02234 #if FIXED_POINT
02235     int dx = (x2 - x1) << 8;
02236     int dy = (y2 - y1) << 8;
02237 
02238     if (abs(dx) > abs(dy)) {
02239 #else
02240     double dx = (double)x2 - (double)x1;
02241     double dy = (double)y2 - (double)y1;
02242 
02243     if (fabs(dx) > fabs(dy)) {
02244 #endif
02245         while (floor++ != ptr_left)
02246             blendPixelPtr(floor, color, 50);
02247 
02248 #if FIXED_POINT
02249         // In this branch dx is always different from zero. This is because
02250         // abs(dx) is strictly greater than abs(dy), and abs returns zero
02251         // as minimal value.
02252         int gradient = (dy << 8) / dx;
02253         int intery = (y1 << 8) + gradient;
02254 #else
02255         double gradient = dy / dx;
02256         double intery = y1 + gradient;
02257 #endif
02258 
02259         for (int x = x1 + 1; x < x2; x++) {
02260 #if FIXED_POINT
02261             if (intery + gradient > ipart(intery) + 0x100) {
02262 #else
02263             if (intery + gradient > ipart(intery) + 1) {
02264 #endif
02265                 ptr_right++;
02266                 ptr_left--;
02267             }
02268 
02269             ptr_left += pitch;
02270             ptr_right += pitch;
02271 
02272             intery += gradient;
02273 
02274             switch (fill_m) {
02275             case kFillDisabled:
02276                 *ptr_left = *ptr_right = color;
02277                 break;
02278             case kFillForeground:
02279             case kFillBackground:
02280                 colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02281                 blendPixelPtr(ptr_right, color, rfpart(intery));
02282                 blendPixelPtr(ptr_left, color, rfpart(intery));
02283                 break;
02284             case kFillGradient:
02285                 colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02286                 blendPixelPtr(ptr_right, color, rfpart(intery));
02287                 blendPixelPtr(ptr_left, color, rfpart(intery));
02288                 break;
02289             }
02290         }
02291 
02292         return;
02293     }
02294 
02295 #if FIXED_POINT
02296     if (abs(dx) < abs(dy)) {
02297 #else
02298     if (fabs(dx) < fabs(dy)) {
02299 #endif
02300         ptr_left--;
02301         while (floor++ != ptr_left)
02302             blendPixelPtr(floor, color, 50);
02303 
02304 #if FIXED_POINT
02305         int gradient = (dx << 8) / (dy + 0x100);
02306         int interx = (x1 << 8) + gradient;
02307 #else
02308         double gradient = dx / (dy + 1);
02309         double interx = x1 + gradient;
02310 #endif
02311 
02312         for (int y = y1 + 1; y < y2; y++) {
02313 #if FIXED_POINT
02314             if (interx + gradient > ipart(interx) + 0x100) {
02315 #else
02316             if (interx + gradient > ipart(interx) + 1) {
02317 #endif
02318                 ptr_right++;
02319                 ptr_left--;
02320             }
02321 
02322             ptr_left += pitch;
02323             ptr_right += pitch;
02324 
02325             interx += gradient;
02326 
02327             switch (fill_m) {
02328             case kFillDisabled:
02329                 *ptr_left = *ptr_right = color;
02330                 break;
02331             case kFillForeground:
02332             case kFillBackground:
02333                 colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02334                 blendPixelPtr(ptr_right, color, rfpart(interx));
02335                 blendPixelPtr(ptr_left, color, rfpart(interx));
02336                 break;
02337             case kFillGradient:
02338                 colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02339                 blendPixelPtr(ptr_right, color, rfpart(interx));
02340                 blendPixelPtr(ptr_left, color, rfpart(interx));
02341                 break;
02342             }
02343         }
02344 
02345         return;
02346     }
02347 
02348     ptr_left--;
02349 
02350     while (floor++ != ptr_left)
02351         blendPixelPtr(floor, color, 50);
02352 
02353 #if FIXED_POINT
02354     int gradient = (dx / dy) << 8;
02355     int interx = (x1 << 8) + gradient;
02356 #else
02357     double gradient = dx / dy;
02358     double interx = x1 + gradient;
02359 #endif
02360 
02361     for (int y = y1 + 1; y < y2; y++) {
02362         ptr_right++;
02363         ptr_left--;
02364 
02365         ptr_left += pitch;
02366         ptr_right += pitch;
02367 
02368         interx += gradient;
02369 
02370         switch (fill_m) {
02371         case kFillDisabled:
02372             *ptr_left = *ptr_right = color;
02373             break;
02374         case kFillForeground:
02375         case kFillBackground:
02376             colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02377             blendPixelPtr(ptr_right, color, rfpart(interx));
02378             blendPixelPtr(ptr_left, color, rfpart(interx));
02379             break;
02380         case kFillGradient:
02381             colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02382             blendPixelPtr(ptr_right, color, rfpart(interx));
02383             blendPixelPtr(ptr_left, color, rfpart(interx));
02384             break;
02385         }
02386     }
02387 
02388 }
02389 
02391 
02392 template<typename PixelType>
02393 void VectorRendererSpec<PixelType>::
02394 drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02395     // Don't draw anything for empty rects. This assures dy is always different
02396     // from zero.
02397     if (w <= 0 || h <= 0) {
02398         return;
02399     }
02400 
02401     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02402     int gradient_h = 0;
02403     int y_pitch_sign = 1;
02404     if (!inverted) {
02405         pitch = -pitch;
02406         y1 += h;
02407         y_pitch_sign = -1;
02408     }
02409 
02410     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02411     PixelType *floor = ptr_right - 1;
02412     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
02413 
02414     int x2 = x1 + w / 2;
02415     int y2 = y1 + h;
02416     int x_right = x1;
02417     int y_right = y1;
02418     int x_left = x1 + w;
02419     int y_left = y1;
02420     int x_floor = x_right - 1;
02421     int y_floor = y_right;
02422 
02423 #if FIXED_POINT
02424     int dx = (x2 - x1) << 8;
02425     int dy = (y2 - y1) << 8;
02426 
02427     if (abs(dx) > abs(dy)) {
02428 #else
02429     double dx = (double)x2 - (double)x1;
02430     double dy = (double)y2 - (double)y1;
02431 
02432     if (fabs(dx) > fabs(dy)) {
02433 #endif
02434         while (floor++ != ptr_left)
02435             blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02436 
02437 #if FIXED_POINT
02438         // In this branch dx is always different from zero. This is because
02439         // abs(dx) is strictly greater than abs(dy), and abs returns zero
02440         // as minimal value.
02441         int gradient = (dy << 8) / dx;
02442         int intery = (y1 << 8) + gradient;
02443 #else
02444         double gradient = dy / dx;
02445         double intery = y1 + gradient;
02446 #endif
02447 
02448         for (int x = x1 + 1; x < x2; x++) {
02449 #if FIXED_POINT
02450             if (intery + gradient > ipart(intery) + 0x100) {
02451 #else
02452             if (intery + gradient > ipart(intery) + 1) {
02453 #endif
02454                 ptr_right++;
02455                 ptr_left--;
02456                 ++x_right;
02457                 --x_left;
02458             }
02459 
02460             ptr_left += pitch;
02461             ptr_right += pitch;
02462             y_right += y_pitch_sign;
02463             y_left += y_pitch_sign;
02464 
02465             intery += gradient;
02466 
02467             switch (fill_m) {
02468             case kFillDisabled:
02469                 if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02470                 if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02471                 break;
02472             case kFillForeground:
02473             case kFillBackground:
02474                 colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02475                 blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
02476                 blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
02477                 break;
02478             case kFillGradient:
02479                 colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02480                 blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
02481                 blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
02482                 break;
02483             }
02484             }
02485 
02486         return;
02487         }
02488 
02489 #if FIXED_POINT
02490     if (abs(dx) < abs(dy)) {
02491 #else
02492     if (fabs(dx) < fabs(dy)) {
02493 #endif
02494         ptr_left--;
02495         --x_left;
02496         while (floor++ != ptr_left)
02497             blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02498 
02499 #if FIXED_POINT
02500         int gradient = (dx << 8) / (dy + 0x100);
02501         int interx = (x1 << 8) + gradient;
02502 #else
02503         double gradient = dx / (dy + 1);
02504         double interx = x1 + gradient;
02505 #endif
02506 
02507         for (int y = y1 + 1; y < y2; y++) {
02508 #if FIXED_POINT
02509             if (interx + gradient > ipart(interx) + 0x100) {
02510 #else
02511             if (interx + gradient > ipart(interx) + 1) {
02512 #endif
02513                 ptr_right++;
02514                 ptr_left--;
02515                 ++x_right;
02516                 --x_left;
02517             }
02518 
02519             ptr_left += pitch;
02520             ptr_right += pitch;
02521             y_right += y_pitch_sign;
02522             y_left += y_pitch_sign;
02523 
02524             interx += gradient;
02525 
02526             switch (fill_m) {
02527             case kFillDisabled:
02528                 if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02529                 if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02530                 break;
02531             case kFillForeground:
02532             case kFillBackground:
02533                 colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02534                 blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02535                 blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02536                 break;
02537             case kFillGradient:
02538                 colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02539                 blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02540                 blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02541                 break;
02542             }
02543             }
02544 
02545         return;
02546         }
02547 
02548     ptr_left--;
02549     --x_left;
02550     while (floor++ != ptr_left)
02551         blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02552 
02553 #if FIXED_POINT
02554     int gradient = (dx / dy) << 8;
02555     int interx = (x1 << 8) + gradient;
02556 #else
02557     double gradient = dx / dy;
02558     double interx = x1 + gradient;
02559 #endif
02560 
02561     for (int y = y1 + 1; y < y2; y++) {
02562         ptr_right++;
02563         ptr_left--;
02564         ++x_right;
02565         --x_left;
02566 
02567         ptr_left += pitch;
02568         ptr_right += pitch;
02569         y_right += y_pitch_sign;
02570         y_left += y_pitch_sign;
02571 
02572         interx += gradient;
02573 
02574         switch (fill_m) {
02575         case kFillDisabled:
02576             if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02577             if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02578             break;
02579         case kFillForeground:
02580         case kFillBackground:
02581             colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02582             blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02583             blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02584             break;
02585         case kFillGradient:
02586             colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02587             blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02588             blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02589             break;
02590         }
02591     }
02592 }
02593 
02595 
02597 template<typename PixelType>
02598 void VectorRendererSpec<PixelType>::
02599 drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02600     // Do not draw anything for empty rects.
02601     if (size <= 0) {
02602         return;
02603     }
02604 
02605     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02606 
02607     if (!inverted) {
02608         pitch = -pitch;
02609         y1 += size;
02610     }
02611 
02612     int gradient_h = 0;
02613     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02614     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1);
02615     int x2 = x1 + size / 2;
02616     int y2 = y1 + size;
02617     int deltaX = abs(x2 - x1);
02618     int deltaY = abs(y2 - y1);
02619     int signX = x1 < x2 ? 1 : -1;
02620     int signY = y1 < y2 ? 1 : -1;
02621     int error = deltaX - deltaY;
02622 
02623     colorFill<PixelType>(ptr_right, ptr_left, color);
02624 
02625     while (1) {
02626         switch (fill_m) {
02627         case kFillDisabled:
02628             *ptr_left = *ptr_right = color;
02629             break;
02630         case kFillForeground:
02631         case kFillBackground:
02632             colorFill<PixelType>(ptr_right, ptr_left, color);
02633             break;
02634         case kFillGradient:
02635             colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, size));
02636             break;
02637         }
02638 
02639         if (x1 == x2 && y1 == y2)
02640             break;
02641 
02642         int error2 = error * 2;
02643 
02644         if (error2 > -deltaY) {
02645             error -= deltaY;
02646             x1 += signX;
02647             ptr_right += signX;
02648             ptr_left += -signX;
02649         }
02650 
02651         if (error2 < deltaX) {
02652             error += deltaX;
02653             y1 += signY;
02654             ptr_right += pitch;
02655             ptr_left += pitch;
02656         }
02657     }
02658 }
02659 
02661 template<typename PixelType>
02662 void VectorRendererSpec<PixelType>::
02663 drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
02664     int f, ddF_x, ddF_y;
02665     int x, y, px, py;
02666     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02667     int sw = 0, sp = 0, hp = h * pitch;
02668 
02669     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
02670     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
02671     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
02672     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
02673     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
02674 
02675     int real_radius = r;
02676     int short_h = h - (2 * r) + 2;
02677 
02678     PixelType color1 = color;
02679     PixelType color2 = color;
02680 
02681     while (sw++ < Base::_strokeWidth) {
02682         blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top
02683         blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom
02684         sp += pitch;
02685 
02686         BE_RESET();
02687         r--;
02688 
02689         int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
02690         int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
02691         int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
02692         int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
02693 
02694         // Avoid blending the last pixels twice, since we have an alpha
02695         while (x++ < (y - 2)) {
02696             BE_ALGORITHM();
02697 
02698             BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
02699             BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
02700             BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
02701             BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)));
02702 
02703             BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)));
02704             BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)));
02705             BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)));
02706             BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)));
02707 
02708             if (Base::_strokeWidth > 1) {
02709                 BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
02710                 BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
02711             }
02712         }
02713     }
02714 
02715     ptr_fill += pitch * real_radius;
02716     while (short_h--) {
02717         blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l); // left
02718         blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r); // right
02719         ptr_fill += pitch;
02720     }
02721 }
02722 
02723 template<typename PixelType>
02724 void VectorRendererSpec<PixelType>::
02725 drawBorderRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
02726     int f, ddF_x, ddF_y;
02727     int x, y, px, py;
02728     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02729     int sw = 0, sp = 0, hp = h * pitch;
02730 
02731     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
02732     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
02733     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
02734     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
02735     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
02736 
02737     int real_radius = r;
02738     int short_h = h - (2 * r) + 2;
02739 
02740     PixelType color1 = color;
02741     PixelType color2 = color;
02742 
02743     while (sw++ < Base::_strokeWidth) {
02744         blendFillClip(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t,
02745             x1 + r, y1 + sp/pitch); // top
02746         blendFillClip(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b,
02747             x1 + r, y1 + (hp - sp)/ pitch); // bottom
02748         sp += pitch;
02749 
02750         BE_RESET();
02751         r--;
02752 
02753         int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
02754         int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
02755         int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
02756         int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
02757 
02758         // Avoid blending the last pixels twice, since we have an alpha
02759         while (x++ < (y - 2)) {
02760             BE_ALGORITHM();
02761 
02762             BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)), x1 + w - r, y1 + r);
02763             BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)), x1 + w - r, y1 + h - r);
02764             BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)), x1 + r, y1 + h - r);
02765             BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)), x1 + r, y1 + r);
02766 
02767             BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)), x1 + w - r, y1 + r);
02768             BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)), x1 + w - r, y1 + h - r);
02769             BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)), x1 + r, y1 + h - r);
02770             BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)), x1 + r, y1 + r);
02771 
02772             if (Base::_strokeWidth > 1) {
02773                 BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py,
02774                     x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
02775                 BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py,
02776                     x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
02777             }
02778         }
02779     }
02780 
02781     ptr_fill += pitch * real_radius;
02782     while (short_h--) {
02783         blendFillClip(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l,
02784             x1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // left
02785         blendFillClip(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r,
02786             x1 + w - Base::_strokeWidth + 1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // right
02787         ptr_fill += pitch;
02788     }
02789 }
02790 
02791 template<typename PixelType>
02792 void VectorRendererSpec<PixelType>::
02793 drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02794     // Do not draw empty space rounded squares.
02795     if (w <= 0 || h <= 0) {
02796         return;
02797     }
02798 
02799     int f, ddF_x, ddF_y;
02800     int x, y, px, py;
02801     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02802 
02803     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
02804     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
02805     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
02806     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
02807     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
02808 
02809     int real_radius = r;
02810     int short_h = h - (2 * r) + 2;
02811     int long_h = h;
02812 
02813     BE_RESET();
02814 
02815     PixelType color1 = color;
02816 
02817     if (fill_m == kFillGradient) {
02818         PixelType color2, color3, color4;
02819         precalcGradient(long_h);
02820 
02821         while (x++ < y) {
02822             BE_ALGORITHM();
02823 
02824             color1 = calcGradient(real_radius - x, long_h);
02825             color2 = calcGradient(real_radius - y, long_h);
02826             color3 = calcGradient(long_h - r + x, long_h);
02827             color4 = calcGradient(long_h - r + y, long_h);
02828 
02829             gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
02830             gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
02831 
02832             gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y);
02833             gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x);
02834 
02835             BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
02836         }
02837     } else {
02838         while (x++ < y) {
02839             BE_ALGORITHM();
02840 
02841             colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1);
02842             colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1);
02843 
02844             colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1);
02845             colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1);
02846 
02847             // do not remove - messes up the drawing at lower resolutions
02848             BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
02849         }
02850     }
02851 
02852     ptr_fill += pitch * r;
02853     while (short_h--) {
02854         if (fill_m == kFillGradient) {
02855             gradientFill(ptr_fill, w + 1, x1, real_radius++);
02856         } else {
02857             colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color1);
02858         }
02859         ptr_fill += pitch;
02860     }
02861 }
02862 
02863 template<typename PixelType>
02864 void VectorRendererSpec<PixelType>::
02865 drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02866     // Do not draw empty space rounded squares.
02867     if (w <= 0 || h <= 0) {
02868         return;
02869     }
02870 
02871     int f, ddF_x, ddF_y;
02872     int x, y, px, py;
02873     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02874 
02875     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
02876     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
02877     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
02878     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
02879     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
02880 
02881     int real_radius = r;
02882     int short_h = h - (2 * r) + 2;
02883     int long_h = h;
02884 
02885     BE_RESET();
02886 
02887     PixelType color1 = color;
02888 
02889     if (fill_m == kFillGradient) {
02890         PixelType color2, color3, color4;
02891         precalcGradient(long_h);
02892 
02893         while (x++ < y) {
02894             BE_ALGORITHM();
02895 
02896             color1 = calcGradient(real_radius - x, long_h);
02897             color2 = calcGradient(real_radius - y, long_h);
02898             color3 = calcGradient(long_h - r + x, long_h);
02899             color4 = calcGradient(long_h - r + y, long_h);
02900 
02901             //TL = (x1 + r, y1 + r)
02902             gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y,
02903                 x1 + r - x, y1 + r - y);
02904             gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x,
02905                 x1 + r - y, y1 + r - x);
02906 
02907             //BL = (x1 + r, y1 + h - r)
02908             gradientFillClip(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y,
02909                 x1 + r - x, y1 + h - r + y);
02910             gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x,
02911                 x1 + r - y, y1 + h - r + x);
02912 
02913             BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
02914                 x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
02915         }
02916     } else {
02917         while (x++ < y) {
02918             BE_ALGORITHM();
02919 
02920             colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1,
02921                 x1 + r - x, y1 + r - y, _clippingArea);
02922             colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1,
02923                 x1 + r - y, y1 + r - x, _clippingArea);
02924 
02925             colorFillClip<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1,
02926                 x1 + r - x, y1 + h - r + y, _clippingArea);
02927             colorFillClip<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1,
02928                 x1 + r - y, y1 + h - r + x, _clippingArea);
02929 
02930             // do not remove - messes up the drawing at lower resolutions
02931             BE_DRAWCIRCLE_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
02932                 x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
02933         }
02934     }
02935 
02936     ptr_fill += pitch * r;
02937     int short_h_orig = short_h;
02938     while (short_h--) {
02939         if (fill_m == kFillGradient) {
02940             gradientFillClip(ptr_fill, w + 1, x1, real_radius++, x1, y1 + r + short_h_orig - short_h -1);
02941         } else {
02942             colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color1, x1, y1 + r + short_h_orig - short_h - 1, _clippingArea);
02943         }
02944         ptr_fill += pitch;
02945     }
02946 }
02947 
02948 template<typename PixelType>
02949 void VectorRendererSpec<PixelType>::
02950 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02951     const uint8 borderAlpha_t = 0;
02952     const uint8 borderAlpha_r = 127;
02953     const uint8 borderAlpha_b = 255;
02954     const uint8 borderAlpha_l = 63;
02955 
02956     const uint8 bevelAlpha_t = 255;
02957     const uint8 bevelAlpha_r = 31;
02958     const uint8 bevelAlpha_b = 0;
02959     const uint8 bevelAlpha_l = 127;
02960 
02961     // If only border is visible
02962     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
02963         if (fill_m == Base::kFillBackground)
02964             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m);
02965         else
02966             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
02967     }
02968 
02969     if (Base::_strokeWidth) {
02970         if (r != 0 && _bevel > 0) {
02971             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
02972             drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
02973         } else {
02974             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
02975         }
02976     }
02977 }
02978 
02979 template<typename PixelType>
02980 void VectorRendererSpec<PixelType>::
02981 drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02982     const uint8 borderAlpha_t = 0;
02983     const uint8 borderAlpha_r = 127;
02984     const uint8 borderAlpha_b = 255;
02985     const uint8 borderAlpha_l = 63;
02986 
02987     const uint8 bevelAlpha_t = 255;
02988     const uint8 bevelAlpha_r = 31;
02989     const uint8 bevelAlpha_b = 0;
02990     const uint8 bevelAlpha_l = 127;
02991 
02992     // If only border is visible
02993     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
02994         if (fill_m == Base::kFillBackground)
02995             drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, _bgColor, fill_m);
02996         else
02997             drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m);
02998     }
02999 
03000     //I expect these to work fine with clipping:
03001     if (Base::_strokeWidth) {
03002         if (r != 0 && _bevel > 0) {
03003             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
03004             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
03005         } else {
03006             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
03007         }
03008     }
03009 }
03010 
03012 template<typename PixelType>
03013 void VectorRendererSpec<PixelType>::
03014 drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
03015     int f, ddF_x, ddF_y;
03016     int x, y, px, py, sw = 0;
03017     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03018     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03019 
03020     if (fill_m == kFillDisabled) {
03021         while (sw++ < Base::_strokeWidth) {
03022             BE_RESET();
03023             r--;
03024 
03025             *(ptr + y) = color;
03026             *(ptr - y) = color;
03027             *(ptr + py) = color;
03028             *(ptr - py) = color;
03029 
03030             while (x++ < y) {
03031                 BE_ALGORITHM();
03032                 BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py);
03033 
03034                 if (Base::_strokeWidth > 1) {
03035                     BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py);
03036                     BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py);
03037                 }
03038             }
03039         }
03040     } else {
03041         colorFill<PixelType>(ptr - r, ptr + r, color);
03042         BE_RESET();
03043 
03044         while (x++ < y) {
03045             BE_ALGORITHM();
03046             colorFill<PixelType>(ptr - x + py, ptr + x + py, color);
03047             colorFill<PixelType>(ptr - x - py, ptr + x - py, color);
03048             colorFill<PixelType>(ptr - y + px, ptr + y + px, color);
03049             colorFill<PixelType>(ptr - y - px, ptr + y - px, color);
03050         }
03051     }
03052 }
03053 
03054 
03055 template<typename PixelType>
03056 void VectorRendererSpec<PixelType>::
03057 drawCircleAlgClip(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
03058     int f, ddF_x, ddF_y;
03059     int x, y, px, py, sw = 0;
03060     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03061     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03062 
03063     if (fill_m == kFillDisabled) {
03064         while (sw++ < Base::_strokeWidth) {
03065             BE_RESET();
03066             r--;
03067 
03068             if (IS_IN_CLIP(x1 + y, y1)) *(ptr + y) = color;
03069             if (IS_IN_CLIP(x1 - y, y1)) *(ptr - y) = color;
03070             if (IS_IN_CLIP(x1, y1 + y)) *(ptr + py) = color;
03071             if (IS_IN_CLIP(x1, y1 - y)) *(ptr - py) = color;
03072 
03073             while (x++ < y) {
03074                 BE_ALGORITHM();
03075                 BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
03076 
03077                 if (Base::_strokeWidth > 1) {
03078                     BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x - 1, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
03079                     BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px - pitch, py, x1, y1, x1, y1, x1, y1, x1, y1);
03080                 }
03081             }
03082         }
03083     } else {
03084         colorFillClip<PixelType>(ptr - r, ptr + r, color, x1 - r, y1 + r, _clippingArea);
03085         BE_RESET();
03086 
03087         while (x++ < y) {
03088             BE_ALGORITHM();
03089             colorFillClip<PixelType>(ptr - x + py, ptr + x + py, color, x1 - x, y1 + y, _clippingArea);
03090             colorFillClip<PixelType>(ptr - x - py, ptr + x - py, color, x1 - x, y1 - y, _clippingArea);
03091             colorFillClip<PixelType>(ptr - y + px, ptr + y + px, color, x1 - y, y1 + x, _clippingArea);
03092             colorFillClip<PixelType>(ptr - y - px, ptr + y - px, color, x1 - y, y1 - x, _clippingArea);
03093         }
03094     }
03095 }
03096 
03097 
03098 /********************************************************************
03099  ********************************************************************
03100  * SHADOW drawing algorithms - VectorRendererSpec *******************
03101  ********************************************************************
03102  ********************************************************************/
03103 template<typename PixelType>
03104 void VectorRendererSpec<PixelType>::
03105 drawSquareShadow(int x, int y, int w, int h, int offset) {
03106     // Do nothing for empty rects or no shadow offset.
03107     if (w <= 0 || h <= 0 || offset <= 0) {
03108         return;
03109     }
03110 
03111     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
03112     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03113     int i, j;
03114 
03115     i = h - offset;
03116 
03117     while (i--) {
03118         j = offset;
03119         while (j--)
03120             blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset);
03121         ptr += pitch;
03122     }
03123 
03124     ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
03125 
03126     while (i++ < offset) {
03127         j = w - offset;
03128         while (j--)
03129             blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset);
03130         ptr += pitch;
03131     }
03132 
03133     ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
03134 
03135     i = 0;
03136     while (i++ < offset) {
03137         j = offset - 1;
03138         while (j--)
03139             blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset));
03140         ptr += pitch;
03141     }
03142 }
03143 
03144 template<typename PixelType>
03145 void VectorRendererSpec<PixelType>::
03146 drawSquareShadowClip(int x, int y, int w, int h, int offset) {
03147     // Do nothing for empty rects or no shadow offset.
03148     if (w <= 0 || h <= 0 || offset <= 0) {
03149         return;
03150     }
03151 
03152     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
03153     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03154     int i, j, ptr_x = x+w-1, ptr_y = y+offset;
03155 
03156     i = h - offset;
03157 
03158     while (i--) {
03159         j = offset;
03160         while (j--)
03161             blendPixelPtrClip(ptr + j, 0, ((offset - j) << 8) / offset, ptr_x + j, ptr_y);
03162         ptr += pitch;
03163         ++ptr_y;
03164     }
03165 
03166     ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
03167     ptr_x = x + offset;
03168     ptr_y = y + h - 1;
03169 
03170     while (i++ < offset) {
03171         j = w - offset;
03172         while (j--)
03173             blendPixelPtrClip(ptr + j, 0, ((offset - i) << 8) / offset, ptr_x + j, ptr_y);
03174         ptr += pitch;
03175         ++ptr_y;
03176     }
03177 
03178     ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
03179     ptr_x = x + w;
03180     ptr_y = y + h;
03181 
03182     i = 0;
03183     while (i++ < offset) {
03184         j = offset - 1;
03185         while (j--)
03186             blendPixelPtrClip(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset), ptr_x + j, ptr_y);
03187         ptr += pitch;
03188         ++ptr_y;
03189     }
03190 }
03191 
03192 template<typename PixelType>
03193 void VectorRendererSpec<PixelType>::
03194 drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
03195     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03196 
03197     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
03198     uint8 expFactor = 3;
03199     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
03200 
03201     // These constants ensure a border of 2px on the left and of each rounded square
03202     Common::Rect shadowRect(w + offset + 2, h + offset + 1);
03203     shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
03204 
03205     // The rounded rectangle drawn on top of this shadow is guaranteed
03206     // to occlude entirely the following rect with a non-transparent color.
03207     // As an optimization, we don't draw the shadow inside of it.
03208     Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
03209     occludingRect.top    += r;
03210     occludingRect.bottom -= r;
03211 
03212     // Soft shadows are constructed by drawing increasingly
03213     // darker and smaller rectangles on top of each other.
03214     for (int i = offset; i >= 0; i--) {
03215         int f, ddF_x, ddF_y;
03216         int x, y, px, py;
03217 
03218         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.top + r);
03219         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
03220         PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.bottom - r);
03221         PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
03222 
03223         PixelType color = _format.RGBToColor(0, 0, 0);
03224 
03225         BE_RESET();
03226 
03227         // HACK: As we are drawing circles exploiting 8-axis symmetry,
03228         // there are 4 pixels on each circle which are drawn twice.
03229         // this is ok on filled circles, but when blending on surfaces,
03230         // we cannot let it blend twice. awful.
03231         uint32 hb = 0;
03232 
03233         // Draw the top and bottom parts of the shadow. Those parts have rounded corners.
03234         while (x++ < y) {
03235             BE_ALGORITHM();
03236 
03237             if (((1 << x) & hb) == 0) {
03238                 blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
03239                 blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
03240                 hb |= (1 << x);
03241             }
03242 
03243             if (((1 << y) & hb) == 0) {
03244                 blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
03245                 blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
03246                 hb |= (1 << y);
03247             }
03248         }
03249 
03250         // Draw the middle part of the shadow. This part is a rectangle with regular corners.
03251         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
03252         for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
03253 
03254             if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
03255                 if (shadowRect.left < occludingRect.left) {
03256                     blendFill(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha);
03257                 }
03258                 if (occludingRect.right < shadowRect.right + 1) {
03259                     blendFill(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
03260                 }
03261             } else {
03262                 blendFill(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
03263             }
03264 
03265             ptr_fill += pitch;
03266         }
03267 
03268         // Make shadow smaller each iteration
03269         shadowRect.grow(-1);
03270 
03271         if (_shadowFillMode == kShadowExponential)
03272             // Multiply with expfactor
03273             alpha = (alpha * (expFactor << 8)) >> 9;
03274     }
03275 }
03276 
03277 template<typename PixelType>
03278 void VectorRendererSpec<PixelType>::
03279 drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
03280     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03281 
03282     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
03283     uint8 expFactor = 3;
03284     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
03285 
03286     // These constants ensure a border of 2px on the left and of each rounded square
03287     Common::Rect shadowRect(w + offset + 2, h + offset + 1);
03288     shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
03289 
03290     // The rounded rectangle drawn on top of this shadow is guaranteed
03291     // to occlude entirely the following rect with a non-transparent color.
03292     // As an optimization, we don't draw the shadow inside of it.
03293     Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
03294     occludingRect.top    += r;
03295     occludingRect.bottom -= r;
03296 
03297     // Soft shadows are constructed by drawing increasingly
03298     // darker and smaller rectangles on top of each other.
03299     for (int i = offset; i >= 0; i--) {
03300         int f, ddF_x, ddF_y;
03301         int x, y, px, py;
03302 
03303         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.top + r);
03304         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
03305         PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.bottom - r);
03306         PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
03307 
03308         PixelType color = _format.RGBToColor(0, 0, 0);
03309 
03310         BE_RESET();
03311 
03312         // HACK: As we are drawing circles exploiting 8-axis symmetry,
03313         // there are 4 pixels on each circle which are drawn twice.
03314         // this is ok on filled circles, but when blending on surfaces,
03315         // we cannot let it blend twice. awful.
03316         uint32 hb = 0;
03317 
03318         while (x++ < y) {
03319             BE_ALGORITHM();
03320 
03321             if (((1 << x) & hb) == 0) {
03322                 blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
03323                               shadowRect.left + r - y, shadowRect.top + r - x);
03324                 blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
03325                               shadowRect.left + r - y, shadowRect.bottom - r + x);
03326 
03327                 hb |= (1 << x);
03328             }
03329 
03330             if (((1 << y) & hb) == 0) {
03331                 blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha,
03332                               shadowRect.left + r - x, shadowRect.top + r - y);
03333                 blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha,
03334                               shadowRect.left + r - x, shadowRect.bottom - r + y);
03335 
03336                 hb |= (1 << y);
03337             }
03338         }
03339 
03340         // Draw the middle part of the shadow. This part is a rectangle with regular corners.
03341         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
03342         for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
03343 
03344             if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
03345                 if (shadowRect.left < occludingRect.left) {
03346                     blendFillClip(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha,
03347                                   shadowRect.left, y2);
03348                 }
03349                 if (occludingRect.right < shadowRect.right + 1) {
03350                     blendFillClip(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
03351                                   occludingRect.right, y2);
03352                 }
03353             } else {
03354                 blendFillClip(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
03355                               shadowRect.left, y2);
03356             }
03357 
03358             ptr_fill += pitch;
03359         }
03360 
03361         // Make shadow smaller each iteration
03362         shadowRect.grow(-1);
03363 
03364         if (_shadowFillMode == kShadowExponential)
03365             // Multiply with expfactor
03366             alpha = (alpha * (expFactor << 8)) >> 9;
03367     }
03368 }
03369 
03370 /******************************************************************************/
03371 
03372 
03373 
03374 #ifndef DISABLE_FANCY_THEMES
03375 
03376 /********************************************************************
03377  * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA
03378  ********************************************************************/
03380 template<typename PixelType>
03381 void VectorRendererAA<PixelType>::
03382 drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
03383     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03384     int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03385     int xdir = (x2 > x1) ? 1 : -1;
03386     uint16 error_tmp, error_acc, gradient;
03387     uint8 alpha;
03388 
03389     *ptr = (PixelType)color;
03390 
03391     if (dx > dy) {
03392         gradient = (dy << 16) / dx;
03393         error_acc = 0;
03394 
03395         while (--dx) {
03396             error_tmp = error_acc;
03397             error_acc += gradient;
03398 
03399             if (error_acc <= error_tmp)
03400                 ptr += pitch;
03401 
03402             ptr += xdir;
03403             alpha = (error_acc >> 8);
03404 
03405             this->blendPixelPtr(ptr, color, ~alpha);
03406             this->blendPixelPtr(ptr + pitch, color, alpha);
03407         }
03408     } else if (dy != 0) {
03409         gradient = (dx << 16) / dy;
03410         error_acc = 0;
03411 
03412         while (--dy) {
03413             error_tmp = error_acc;
03414             error_acc += gradient;
03415 
03416             if (error_acc <= error_tmp)
03417                 ptr += xdir;
03418 
03419             ptr += pitch;
03420             alpha = (error_acc >> 8);
03421 
03422             this->blendPixelPtr(ptr, color, ~alpha);
03423             this->blendPixelPtr(ptr + xdir, color, alpha);
03424         }
03425     }
03426 
03427     Base::putPixel(x2, y2, color);
03428 }
03429 
03431 template<typename PixelType>
03432 void VectorRendererAA<PixelType>::
03433 drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
03434     // Don't draw anything for empty rects.
03435     if (w <= 0 || h <= 0) {
03436         return;
03437     }
03438 
03439     int x, y, px, py;
03440     int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03441     int sw = 0, sp = 0, hp = 0;
03442 
03443     frac_t T = 0, oldT;
03444     uint8 a1, a2;
03445     uint32 rsq = r*r;
03446 
03447     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03448     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03449     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03450 
03451     int real_radius = r;
03452 
03453     if (fill_m == Base::kFillDisabled) {
03454         color = 0;
03455         while (sw++ < Base::_strokeWidth) {
03456             colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
03457             colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
03458             sp += pitch;
03459 
03460             x = r - (sw - 1);
03461             y = 0;
03462             T = 0;
03463             px = pitch * x;
03464             py = 0;
03465 
03466 
03467             while (x > y++) {
03468                 WU_ALGORITHM();
03469 
03470                 // sw == 1: outside, sw = _strokeWidth: inside
03471                 if (sw != Base::_strokeWidth)
03472                     a2 = 255;
03473 
03474                 // inner arc
03475                 WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a2);
03476 
03477                 if (sw == 1) // outer arc
03478                     WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py, a1);
03479             }
03480         }
03481 
03482         int short_h = h - r;
03483 
03484         ptr_fill += pitch * real_radius;
03485         while (short_h--) {
03486             colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color);
03487             colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
03488             ptr_fill += pitch;
03489         }
03490 
03491         if (baseLeft) {
03492             sw = 0;
03493             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
03494             while (sw++ < Base::_strokeWidth) {
03495                 colorFill<PixelType>(ptr_fill - baseLeft, ptr_fill, color);
03496                 ptr_fill += pitch;
03497             }
03498         }
03499 
03500         if (baseRight) {
03501             sw = 0;
03502             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
03503             while (sw++ < Base::_strokeWidth) {
03504                 colorFill<PixelType>(ptr_fill, ptr_fill + baseRight, color);
03505                 ptr_fill += pitch;
03506             }
03507         }
03508     } else {
03509         PixelType color1, color2;
03510         color1 = color2 = color;
03511 
03512         int long_h = h;
03513         int short_h = h - real_radius;
03514         x = real_radius;
03515         y = 0;
03516         T = 0;
03517         px = pitch * x;
03518         py = 0;
03519 
03520         Base::precalcGradient(long_h);
03521 
03522         while (x > y++) {
03523             WU_ALGORITHM();
03524 
03525             if (fill_m == Base::kFillGradient) {
03526                 color1 = Base::calcGradient(real_radius - x, long_h);
03527                 color2 = Base::calcGradient(real_radius - y, long_h);
03528 
03529                 Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, real_radius - y);
03530 
03531                 // Only fill each horizontal line once (or we destroy
03532                 // the gradient effect at the edges)
03533                 if (T < oldT || y == 1)
03534                     Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, real_radius - x);
03535 
03536                 WU_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py, a1, Base::blendPixelPtr);
03537             } else {
03538                 colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
03539                 if (T < oldT || y == 1)
03540                     colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
03541 
03542                 WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a1);
03543             }
03544         }
03545 
03546         ptr_fill += pitch * r;
03547         while (short_h--) {
03548             if (fill_m == Base::kFillGradient) {
03549                 Base::gradientFill(ptr_fill, w + 1, x1, real_radius++);
03550             } else {
03551                 colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
03552             }
03553             ptr_fill += pitch;
03554         }
03555     }
03556 }
03557 
03558 
03560 template<typename PixelType>
03561 void VectorRendererAA<PixelType>::
03562 drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
03563     int x, y;
03564     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03565     int px, py;
03566 
03567     uint32 rsq = r*r;
03568     frac_t T = 0, oldT;
03569     uint8 a1, a2;
03570 
03571     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03572     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03573     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03574     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03575     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03576 
03577     int sw = 0, sp = 0;
03578     int short_h = h - 2 * r;
03579     int hp = h * pitch;
03580 
03581     int strokeWidth = Base::_strokeWidth;
03582 
03583     while (sw++ < strokeWidth) {
03584         this->blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, alpha_b); // bottom
03585         this->blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, alpha_t); // top
03586 
03587         sp += pitch;
03588 
03589         x = r - (sw - 1);
03590         y = 0;
03591         T = 0;
03592         px = pitch * x;
03593         py = 0;
03594 
03595         int alphaStep_tr = ((alpha_t - alpha_r) / (x + 1));
03596         int alphaStep_br = ((alpha_r - alpha_b) / (x + 1));
03597         int alphaStep_bl = ((alpha_b - alpha_l) / (x + 1));
03598         int alphaStep_tl = ((alpha_l - alpha_t) / (x + 1));
03599 
03600         while (x > y++) {
03601             WU_ALGORITHM();
03602 
03603             // sw == 1: outside, sw = _strokeWidth: inside
03604             // We always draw the outer edge AAed, but the inner edge
03605             // only when the inside isn't filled
03606             if (sw != strokeWidth || fill_m != Base::kFillDisabled)
03607                 a2 = 255;
03608 
03609                 // inner arc
03610                 WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16));
03611                 WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a2) >> 16));
03612                 WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a2) >> 16));
03613                 WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a2) >> 16));
03614 
03615                 WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16));
03616                 WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a2) >> 16));
03617                 WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a2) >> 16));
03618                 WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a2) >> 16));
03619 
03620                 // outer arc
03621                 if (sw == 1) {
03622                     WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a1) >> 16));
03623                     WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a1) >> 16));
03624                     WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a1) >> 16));
03625                     WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a1) >> 16));
03626 
03627                     WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16));
03628                     WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a1) >> 16));
03629                     WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a1) >> 16));
03630                     WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a1) >> 16));
03631                 }
03632             }
03633 
03634         ptr_fill += pitch * r;
03635 
03636         while (short_h-- >= -2) {
03637             this->blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color, alpha_l); // left
03638             this->blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, alpha_r); // right
03639             ptr_fill += pitch;
03640         }
03641     }
03642 }
03643 
03644 template<typename PixelType>
03645 void VectorRendererAA<PixelType>::
03646 drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03647     w -= 2*Base::_strokeWidth;
03648     h -= 2*Base::_strokeWidth;
03649 
03650     // Do not draw empty space rounded squares.
03651     if (w <= 0 || h <= 0) {
03652         return;
03653     }
03654 
03655     int x, y;
03656     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03657     int px, py;
03658 
03659     uint32 rsq = r*r;
03660     frac_t T = 0, oldT;
03661     uint8 a1, a2;
03662 
03663     r -= Base::_strokeWidth;
03664     x1 += Base::_strokeWidth;
03665     y1 += Base::_strokeWidth;
03666     rsq = r*r;
03667 
03668     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03669     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03670     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03671     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03672     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03673 
03674     int short_h = h - 2 * r;
03675     x = r;
03676     y = 0;
03677     T = 0;
03678     px = pitch * x;
03679     py = 0;
03680 
03681     if (fill_m == Base::kFillGradient) {
03682 
03683         Base::precalcGradient(h);
03684 
03685         PixelType color1, color2, color3, color4;
03686         while (x > y++) {
03687             WU_ALGORITHM();
03688 
03689             color1 = Base::calcGradient(r - x, h);
03690             color2 = Base::calcGradient(r - y, h);
03691             color3 = Base::calcGradient(h - r + x, h);
03692             color4 = Base::calcGradient(h - r + y, h);
03693 
03694             Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y);
03695 
03696             // Only fill each horizontal line once (or we destroy
03697             // the gradient effect at the edges)
03698             if (T < oldT || y == 1)
03699                 Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x);
03700 
03701             Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y);
03702 
03703             // Only fill each horizontal line once (or we destroy
03704             // the gradient effect at the edges)
03705             if (T < oldT || y == 1)
03706                 Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x);
03707 
03708             // This shape is used for dialog backgrounds.
03709             // If we're drawing on top of an empty overlay background,
03710             // and the overlay supports alpha, we have to do AA by
03711             // setting the dest alpha channel, instead of blending with
03712             // dest color channels.
03713             if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha))
03714                 WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr);
03715             else
03716                 WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr);
03717         }
03718 
03719         ptr_fill += pitch * r;
03720         while (short_h-- >= 0) {
03721             Base::gradientFill(ptr_fill, w + 1, x1, r++);
03722             ptr_fill += pitch;
03723         }
03724 
03725     } else {
03726 
03727         while (x > 1 + y++) {
03728             WU_ALGORITHM();
03729 
03730             colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
03731             if (T < oldT || y == 1)
03732                 colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
03733 
03734             colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color);
03735             if (T < oldT || y == 1)
03736                 colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color);
03737 
03738             WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
03739         }
03740 
03741         ptr_fill += pitch * r;
03742         while (short_h-- >= 0) {
03743             colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
03744             ptr_fill += pitch;
03745         }
03746     }
03747 }
03748 
03749 template<typename PixelType>
03750 void VectorRendererAA<PixelType>::
03751 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03752     const uint8 borderAlpha_t = 0;
03753     const uint8 borderAlpha_r = 127;
03754     const uint8 borderAlpha_b = 255;
03755     const uint8 borderAlpha_l = 63;
03756 
03757     const uint8 bevelAlpha_t = 255;
03758     const uint8 bevelAlpha_r = 31;
03759     const uint8 bevelAlpha_b = 0;
03760     const uint8 bevelAlpha_l = 127;
03761 
03762     if (Base::_strokeWidth) {
03763         if (r != 0 && Base::_bevel > 0) {
03764             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
03765             drawBorderRoundedSquareAlg(x1, y1, r, w, h, Base::_bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
03766         } else {
03767             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
03768         }
03769     }
03770 
03771     // If only border is visible
03772     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
03773         if (fill_m == Base::kFillBackground)
03774             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, Base::_bgColor, fill_m);
03775         else
03776             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
03777     }
03778 }
03779 
03781 template<typename PixelType>
03782 void VectorRendererAA<PixelType>::
03783 drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
03784     int x, y, sw = 0;
03785     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03786     int px, py;
03787 
03788     uint32 rsq = r*r;
03789     frac_t T = 0, oldT;
03790     uint8 a1, a2;
03791 
03792     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03793 
03794     if (fill_m == VectorRenderer::kFillDisabled) {
03795         while (sw++ < Base::_strokeWidth) {
03796             x = r - (sw - 1);
03797             y = 0;
03798             T = 0;
03799             px = pitch * x;
03800             py = 0;
03801 
03802             *(ptr + x) = (PixelType)color;
03803             *(ptr - x) = (PixelType)color;
03804             *(ptr + px) = (PixelType)color;
03805             *(ptr - px) = (PixelType)color;
03806 
03807             while (x > y++) {
03808                 WU_ALGORITHM();
03809 
03810                 if (sw != 1 && sw != Base::_strokeWidth)
03811                     a2 = a1 = 255;
03812 
03813                 WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - pitch), py, a2);
03814                 WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1);
03815             }
03816         }
03817     } else {
03818         colorFill<PixelType>(ptr - r, ptr + r + 1, color);
03819         x = r;
03820         y = 0;
03821         T = 0;
03822         px = pitch * x;
03823         py = 0;
03824 
03825         while (x > y++) {
03826             WU_ALGORITHM();
03827 
03828             colorFill<PixelType>(ptr - x + py, ptr + x + py, color);
03829             colorFill<PixelType>(ptr - x - py, ptr + x - py, color);
03830             colorFill<PixelType>(ptr - y + px, ptr + y + px, color);
03831             colorFill<PixelType>(ptr - y - px, ptr + y - px, color);
03832 
03833             WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1);
03834         }
03835     }
03836 }
03837 
03838 #endif
03839 
03840 }


Generated on Sat Apr 4 2020 05:00:35 for ResidualVM by doxygen 1.7.1
curved edge   curved edge