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         count -= diff;
00478     }
00479 
00480     if (clippingArea.right <= realX + count) {
00481         int diff = (realX + count - clippingArea.right);
00482         count -= diff;
00483     }
00484 
00485     if (!count)
00486         return;
00487 
00488     int n = (count + 7) >> 3;
00489     switch (count % 8) {
00490     case 0: do {
00491                 *first++ = color; // fall through
00492     case 7:     *first++ = color; // fall through
00493     case 6:     *first++ = color; // fall through
00494     case 5:     *first++ = color; // fall through
00495     case 4:     *first++ = color; // fall through
00496     case 3:     *first++ = color; // fall through
00497     case 2:     *first++ = color; // fall through
00498     case 1:     *first++ = color;
00499             } while (--n > 0);
00500     }
00501 }
00502 
00503 
00504 VectorRenderer *createRenderer(int mode) {
00505 #ifdef DISABLE_FANCY_THEMES
00506     assert(mode == GUI::ThemeEngine::kGfxStandard);
00507 #endif
00508 
00509     PixelFormat format = g_system->getOverlayFormat();
00510     switch (mode) {
00511     case GUI::ThemeEngine::kGfxStandard:
00512         if (g_system->getOverlayFormat().bytesPerPixel == 4)
00513             return new VectorRendererSpec<uint32>(format);
00514         else if (g_system->getOverlayFormat().bytesPerPixel == 2)
00515             return new VectorRendererSpec<uint16>(format);
00516         break;
00517 #ifndef DISABLE_FANCY_THEMES
00518     case GUI::ThemeEngine::kGfxAntialias:
00519         if (g_system->getOverlayFormat().bytesPerPixel == 4)
00520             return new VectorRendererAA<uint32>(format);
00521         else if (g_system->getOverlayFormat().bytesPerPixel == 2)
00522             return new VectorRendererAA<uint16>(format);
00523         break;
00524 #endif
00525     default:
00526         break;
00527     }
00528 
00529     return 0;
00530 }
00531 
00532 template<typename PixelType>
00533 VectorRendererSpec<PixelType>::
00534 VectorRendererSpec(PixelFormat format) :
00535     _format(format),
00536     _redMask((0xFF >> format.rLoss) << format.rShift),
00537     _greenMask((0xFF >> format.gLoss) << format.gShift),
00538     _blueMask((0xFF >> format.bLoss) << format.bShift),
00539     _alphaMask((0xFF >> format.aLoss) << format.aShift) {
00540 
00541     _bitmapAlphaColor = _format.RGBToColor(255, 0, 255);
00542     _clippingArea = Common::Rect(0, 0, 32767, 32767);
00543 }
00544 
00545 /****************************
00546  * Gradient-related methods *
00547  ****************************/
00548 
00549 template<typename PixelType>
00550 void VectorRendererSpec<PixelType>::
00551 setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) {
00552     _gradientEnd = _format.RGBToColor(r2, g2, b2);
00553     _gradientStart = _format.RGBToColor(r1, g1, b1);
00554 
00555     if (sizeof(PixelType) == 4) {
00556         _gradientBytes[0] = ((_gradientEnd & _redMask) >> _format.rShift) - ((_gradientStart & _redMask) >> _format.rShift);
00557         _gradientBytes[1] = ((_gradientEnd & _greenMask) >> _format.gShift) - ((_gradientStart & _greenMask) >> _format.gShift);
00558         _gradientBytes[2] = ((_gradientEnd & _blueMask) >> _format.bShift) - ((_gradientStart & _blueMask) >> _format.bShift);
00559     } else {
00560         _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask);
00561         _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask);
00562         _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask);
00563     }
00564 }
00565 
00566 template<typename PixelType>
00567 inline PixelType VectorRendererSpec<PixelType>::
00568 calcGradient(uint32 pos, uint32 max) {
00569     PixelType output = 0;
00570     pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max;
00571 
00572     if (sizeof(PixelType) == 4) {
00573         output |= ((_gradientStart & _redMask) + (((_gradientBytes[0] * pos) >> 12) << _format.rShift)) & _redMask;
00574         output |= ((_gradientStart & _greenMask) + (((_gradientBytes[1] * pos) >> 12) << _format.gShift)) & _greenMask;
00575         output |= ((_gradientStart & _blueMask) + (((_gradientBytes[2] * pos) >> 12) << _format.bShift)) & _blueMask;
00576     } else {
00577         output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask;
00578         output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask;
00579         output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask;
00580     }
00581     output |= _alphaMask;
00582 
00583     return output;
00584 }
00585 
00586 template<typename PixelType>
00587 void VectorRendererSpec<PixelType>::
00588 precalcGradient(int h) {
00589     PixelType prevcolor = 0, color;
00590 
00591     _gradCache.resize(0);
00592     _gradIndexes.resize(0);
00593 
00594     for (int i = 0; i < h + 2; i++) {
00595         color = calcGradient(i, h);
00596         if (color != prevcolor || i == 0 || i > h - 1) {
00597             prevcolor = color;
00598             _gradCache.push_back(color);
00599             _gradIndexes.push_back(i);
00600         }
00601     }
00602 }
00603 
00604 template<typename PixelType>
00605 void VectorRendererSpec<PixelType>::
00606 gradientFill(PixelType *ptr, int width, int x, int y) {
00607     bool ox = ((y & 1) == 1);
00608     int curGrad = 0;
00609 
00610     while (_gradIndexes[curGrad + 1] <= y)
00611         curGrad++;
00612 
00613     // precalcGradient assures that _gradIndexes entries always differ in
00614     // their value. This assures stripSize is always different from zero.
00615     int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
00616 
00617     int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
00618 
00619     // Dithering:
00620     //   +--+ +--+ +--+ +--+
00621     //   |  | |  | | *| | *|
00622     //   |  | | *| |* | |**|
00623     //   +--+ +--+ +--+ +--+
00624     //     0    1    2    3
00625     if (grad == 0 ||
00626         _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
00627         stripSize < 2) { // the stip is small
00628         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
00629     } else if (grad == 3 && ox) {
00630         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
00631     } else {
00632         for (int j = x; j < x + width; j++, ptr++) {
00633             bool oy = ((j & 1) == 1);
00634 
00635             if ((ox && oy) ||
00636                 ((grad == 2 || grad == 3) && ox && !oy) ||
00637                 (grad == 3 && oy))
00638                 *ptr = _gradCache[curGrad + 1];
00639             else
00640                 *ptr = _gradCache[curGrad];
00641         }
00642     }
00643 }
00644 
00645 template<typename PixelType>
00646 void VectorRendererSpec<PixelType>::
00647 gradientFillClip(PixelType *ptr, int width, int x, int y, int realX, int realY) {
00648     if (realY < _clippingArea.top || realY >= _clippingArea.bottom) return;
00649     bool ox = ((y & 1) == 1);
00650     int curGrad = 0;
00651 
00652     while (_gradIndexes[curGrad + 1] <= y)
00653         curGrad++;
00654 
00655     // precalcGradient assures that _gradIndexes entries always differ in
00656     // their value. This assures stripSize is always different from zero.
00657     int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
00658 
00659     int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
00660 
00661     // Dithering:
00662     //   +--+ +--+ +--+ +--+
00663     //   |  | |  | | *| | *|
00664     //   |  | | *| |* | |**|
00665     //   +--+ +--+ +--+ +--+
00666     //     0    1    2    3
00667     if (grad == 0 ||
00668         _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
00669         stripSize < 2) { // the stip is small
00670         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
00671     } else if (grad == 3 && ox) {
00672         colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
00673     } else {
00674         for (int j = x; j < x + width; j++, ptr++) {
00675             if (realX + j - x < _clippingArea.left || realX + j - x >= _clippingArea.right) continue;
00676             bool oy = ((j & 1) == 1);
00677 
00678             if ((ox && oy) ||
00679                 ((grad == 2 || grad == 3) && ox && !oy) ||
00680                 (grad == 3 && oy))
00681                 *ptr = _gradCache[curGrad + 1];
00682             else
00683                 *ptr = _gradCache[curGrad];
00684         }
00685     }
00686 }
00687 
00688 template<typename PixelType>
00689 void VectorRendererSpec<PixelType>::
00690 fillSurface() {
00691     byte *ptr = (byte *)_activeSurface->getPixels();
00692 
00693     int h = _activeSurface->h;
00694     int pitch = _activeSurface->pitch;
00695 
00696     if (Base::_fillMode == kFillBackground) {
00697         colorFill<PixelType>((PixelType *)ptr, (PixelType *)(ptr + pitch * h), _bgColor);
00698     } else if (Base::_fillMode == kFillForeground) {
00699         colorFill<PixelType>((PixelType *)ptr, (PixelType *)(ptr + pitch * h), _fgColor);
00700     } else if (Base::_fillMode == kFillGradient) {
00701         precalcGradient(h);
00702 
00703         for (int i = 0; i < h; i++) {
00704             gradientFill((PixelType *)ptr, _activeSurface->w, 0, i);
00705 
00706             ptr += pitch;
00707         }
00708     }
00709 }
00710 
00711 template<typename PixelType>
00712 void VectorRendererSpec<PixelType>::
00713 fillSurfaceClip(Common::Rect clipping) {
00714     int w = _activeSurface->w;
00715     int h = _activeSurface->h;
00716     if (clipping.isEmpty() || (clipping.left == 0 && clipping.top == 0 && clipping.right == w && clipping.bottom == h)) {
00717         fillSurface();
00718         return;
00719     }
00720 
00721     byte *ptr = (byte *)_activeSurface->getPixels();
00722     int pitch = _activeSurface->pitch;
00723 
00724     if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {
00725         PixelType color = (Base::_fillMode == kFillBackground ? _bgColor : _fgColor);
00726         byte *ptrLeft = (ptr + _clippingArea.left), *ptrRight = ptr + _clippingArea.right;
00727         for (int i = 0; i < h; i++) {
00728             if (_clippingArea.top <= i && i < _clippingArea.bottom) {
00729                 colorFill<PixelType>((PixelType *)ptrLeft, (PixelType *)ptrRight, color);
00730             }
00731 
00732             ptrLeft += pitch;
00733             ptrRight += pitch;
00734         }
00735 
00736     } else if (Base::_fillMode == kFillGradient) {
00737         precalcGradient(h);
00738 
00739         for (int i = 0; i < h; i++) {
00740             if (_clippingArea.top <= i && i < _clippingArea.bottom) {
00741                 gradientFill((PixelType *)ptr + _clippingArea.left, _clippingArea.width(), 0, i);
00742             }
00743 
00744             ptr += pitch;
00745         }
00746     }
00747 }
00748 
00749 template<typename PixelType>
00750 void VectorRendererSpec<PixelType>::
00751 copyFrame(OSystem *sys, const Common::Rect &r) {
00752 
00753     sys->copyRectToOverlay(
00754         _activeSurface->getBasePtr(r.left, r.top),
00755         _activeSurface->pitch,
00756         r.left, r.top, r.width(), r.height()
00757     );
00758 }
00759 
00760 template<typename PixelType>
00761 void VectorRendererSpec<PixelType>::
00762 blitSurface(const Graphics::Surface *source, const Common::Rect &r) {
00763     assert(source->w == _activeSurface->w && source->h == _activeSurface->h);
00764 
00765     byte *dst_ptr = (byte *)_activeSurface->getBasePtr(r.left, r.top);
00766     const byte *src_ptr = (const byte *)source->getBasePtr(r.left, r.top);
00767 
00768     const int dst_pitch = _activeSurface->pitch;
00769     const int src_pitch = source->pitch;
00770 
00771     int h = r.height();
00772     const int w = r.width() * sizeof(PixelType);
00773 
00774     while (h--) {
00775         memcpy(dst_ptr, src_ptr, w);
00776         dst_ptr += dst_pitch;
00777         src_ptr += src_pitch;
00778     }
00779 }
00780 
00781 template<typename PixelType>
00782 void VectorRendererSpec<PixelType>::
00783 blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) {
00784     byte *dst_ptr = (byte *)_activeSurface->getBasePtr(r.left, r.top);
00785     const byte *src_ptr = (const byte *)source->getPixels();
00786 
00787     const int dst_pitch = _activeSurface->pitch;
00788     const int src_pitch = source->pitch;
00789 
00790     int h = r.height();
00791     const int w = r.width() * sizeof(PixelType);
00792 
00793     while (h--) {
00794         memcpy(dst_ptr, src_ptr, w);
00795         dst_ptr += dst_pitch;
00796         src_ptr += src_pitch;
00797     }
00798 }
00799 
00800 template<typename PixelType>
00801 void VectorRendererSpec<PixelType>::
00802 blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
00803     if (clipping.isEmpty() || clipping.contains(r)) {
00804         blitSubSurface(source, r);
00805         return;
00806     }
00807 
00808     int16 x = r.left;
00809     int16 y = r.top;
00810 
00811     if (r.width() > source->w)
00812         x = x + (r.width() >> 1) - (source->w >> 1);
00813 
00814     if (r.height() > source->h)
00815         y = y + (r.height() >> 1) - (source->h >> 1);
00816 
00817     int w = source->w, h = source->h;
00818     int usedW = w, usedH = h;
00819     int offsetX = 0, offsetY = 0;
00820 
00821     if (x > clipping.right || x + w < clipping.left) return;
00822     if (y > clipping.bottom || y + h < clipping.top) return;
00823     if (x < clipping.left) {
00824         offsetX = clipping.left - x;
00825         usedW -= offsetX;
00826         x = clipping.left;
00827     }
00828     if (y < clipping.top) {
00829         offsetY = clipping.top - y;
00830         usedH -= offsetY;
00831         y = clipping.top;
00832     }
00833     if (usedW > clipping.width()) usedW = clipping.width();
00834     if (usedH > clipping.height()) usedH = clipping.height();
00835 
00836     byte *dst_ptr = (byte *)_activeSurface->getBasePtr(x, y);
00837     const byte *src_ptr = (const byte *)source->getBasePtr(offsetX, offsetY);
00838 
00839     const int dst_pitch = _activeSurface->pitch;
00840     const int src_pitch = source->pitch;
00841 
00842     int lines = usedH;
00843     const int sz = usedW * sizeof(PixelType);
00844 
00845     while (lines--) {
00846         memcpy(dst_ptr, src_ptr, sz);
00847         dst_ptr += dst_pitch;
00848         src_ptr += src_pitch;
00849     }
00850 }
00851 
00852 template<typename PixelType>
00853 void VectorRendererSpec<PixelType>::
00854 blitKeyBitmap(const Graphics::Surface *source, const Common::Rect &r) {
00855     int16 x = r.left;
00856     int16 y = r.top;
00857 
00858     if (r.width() > source->w)
00859         x = x + (r.width() >> 1) - (source->w >> 1);
00860 
00861     if (r.height() > source->h)
00862         y = y + (r.height() >> 1) - (source->h >> 1);
00863 
00864     PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
00865     const PixelType *src_ptr = (const PixelType *)source->getPixels();
00866 
00867     int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
00868     int src_pitch = source->pitch / source->format.bytesPerPixel;
00869 
00870     int w, h = source->h;
00871 
00872     while (h--) {
00873         w = source->w;
00874 
00875         while (w--) {
00876             if (*src_ptr != _bitmapAlphaColor)
00877                 *dst_ptr = *src_ptr;
00878 
00879             dst_ptr++;
00880             src_ptr++;
00881         }
00882 
00883         dst_ptr = dst_ptr - source->w + dst_pitch;
00884         src_ptr = src_ptr - source->w + src_pitch;
00885     }
00886 }
00887 
00888 template<typename PixelType>
00889 void VectorRendererSpec<PixelType>::
00890 blitAlphaBitmap(Graphics::TransparentSurface *source, const Common::Rect &r, GUI::ThemeEngine::AutoScaleMode autoscale,
00891             Graphics::DrawStep::VectorAlignment xAlign, Graphics::DrawStep::VectorAlignment yAlign, int alpha) {
00892     if (autoscale == GUI::ThemeEngine::kAutoScaleStretch) {
00893         source->blit(*_activeSurface, r.left, r.top, Graphics::FLIP_NONE,
00894             nullptr, TS_ARGB(alpha, 255, 255, 255),
00895               r.width(), r.height());
00896     } else if (autoscale == GUI::ThemeEngine::kAutoScaleFit) {
00897         double ratio = (double)r.width() / source->w;
00898         double ratio2 = (double)r.height() / source->h;
00899 
00900         if (ratio2 < ratio)
00901             ratio = ratio2;
00902 
00903         int offx = 0, offy = 0;
00904         if (xAlign == Graphics::DrawStep::kVectorAlignCenter)
00905             offx = (r.width() - (int)(source->w * ratio)) >> 1;
00906 
00907         if (yAlign == Graphics::DrawStep::kVectorAlignCenter)
00908             offy = (r.height() - (int)(source->h * ratio)) >> 1;
00909 
00910         source->blit(*_activeSurface, r.left + offx, r.top + offy, Graphics::FLIP_NONE,
00911             nullptr, TS_ARGB(alpha, 255, 255, 255),
00912                       (int)(source->w * ratio), (int)(source->h * ratio));
00913 
00914     } else if (autoscale == GUI::ThemeEngine::kAutoScaleNinePatch) {
00915         Graphics::NinePatchBitmap nine(source, false);
00916         nine.blit(*_activeSurface, r.left, r.top, r.width(), r.height());
00917     } else {
00918         source->blit(*_activeSurface, r.left, r.top);
00919     }
00920 }
00921 
00922 template<typename PixelType>
00923 void VectorRendererSpec<PixelType>::
00924 blitKeyBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
00925     if (clipping.isEmpty() || clipping.contains(r)) {
00926         blitKeyBitmap(source, r);
00927         return;
00928     }
00929 
00930     int16 x = r.left;
00931     int16 y = r.top;
00932 
00933     if (r.width() > source->w)
00934         x = x + (r.width() >> 1) - (source->w >> 1);
00935 
00936     if (r.height() > source->h)
00937         y = y + (r.height() >> 1) - (source->h >> 1);
00938 
00939     Common::Rect drawRect(x, y, x + source->w, y + source->h);
00940     drawRect.clip(clipping);
00941 
00942     if (drawRect.isEmpty()) {
00943         return;
00944     }
00945 
00946     int sourceOffsetX = drawRect.left - x;
00947     int sourceOffsetY = drawRect.top - y;
00948 
00949     PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(drawRect.left, drawRect.top);
00950     const PixelType *src_ptr = (const PixelType *)source->getBasePtr(sourceOffsetX, sourceOffsetY);
00951 
00952     int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
00953     int src_pitch = source->pitch / source->format.bytesPerPixel;
00954 
00955     int w, h = drawRect.height();
00956 
00957     while (h--) {
00958         w = drawRect.width();
00959 
00960         while (w--) {
00961             if (*src_ptr != _bitmapAlphaColor)
00962                 *dst_ptr = *src_ptr;
00963 
00964             dst_ptr++;
00965             src_ptr++;
00966         }
00967 
00968         dst_ptr = dst_ptr - drawRect.width() + dst_pitch;
00969         src_ptr = src_ptr - drawRect.width() + src_pitch;
00970     }
00971 }
00972 
00973 template<typename PixelType>
00974 void VectorRendererSpec<PixelType>::
00975 applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
00976     int pixels = _activeSurface->w * _activeSurface->h;
00977     PixelType *ptr = (PixelType *)_activeSurface->getPixels();
00978     uint8 r, g, b;
00979     uint lum;
00980 
00981     // Mask to clear the last bit of every color component and all unused bits
00982     const uint32 colorMask = ~((1 << _format.rShift) | (1 << _format.gShift) | (1 << _format.bShift) // R/G/B components
00983             | (_format.aLoss == 8 ? 0 : (1 << _format.aShift)) // Alpha component
00984             | ~(_alphaMask | _redMask | _greenMask | _blueMask)); // All unused bits
00985 
00986     if (shadingStyle == GUI::ThemeEngine::kShadingDim) {
00987 
00988         // TODO: Check how this interacts with kFeatureOverlaySupportsAlpha
00989         for (int i = 0; i < pixels; ++i) {
00990             *ptr = ((*ptr & colorMask) >> 1) | _alphaMask;
00991             ++ptr;
00992         }
00993 
00994     } else if (shadingStyle == GUI::ThemeEngine::kShadingLuminance) {
00995         while (pixels--) {
00996             _format.colorToRGB(*ptr, r, g, b);
00997             lum = (r >> 2) + (g >> 1) + (b >> 3);
00998             *ptr++ = _format.RGBToColor(lum, lum, lum);
00999         }
01000     }
01001 }
01002 
01003 template<typename PixelType>
01004 inline void VectorRendererSpec<PixelType>::
01005 blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
01006     if (alpha == 0xff) {
01007         // fully opaque pixel, don't blend
01008         *ptr = color | _alphaMask;
01009     } else if (sizeof(PixelType) == 4) {
01010         const byte sR = (color & _redMask) >> _format.rShift;
01011         const byte sG = (color & _greenMask) >> _format.gShift;
01012         const byte sB = (color & _blueMask) >> _format.bShift;
01013 
01014         byte dR = (*ptr & _redMask) >> _format.rShift;
01015         byte dG = (*ptr & _greenMask) >> _format.gShift;
01016         byte dB = (*ptr & _blueMask) >> _format.bShift;
01017         byte dA = (*ptr & _alphaMask) >> _format.aShift;
01018 
01019         dR += ((sR - dR) * alpha) >> 8;
01020         dG += ((sG - dG) * alpha) >> 8;
01021         dB += ((sB - dB) * alpha) >> 8;
01022         dA += ((0xff - dA) * alpha) >> 8;
01023 
01024         *ptr = ((dR << _format.rShift) & _redMask)
01025              | ((dG << _format.gShift) & _greenMask)
01026              | ((dB << _format.bShift) & _blueMask)
01027              | ((dA << _format.aShift) & _alphaMask);
01028     } else if (sizeof(PixelType) == 2) {
01029         int idst = *ptr;
01030         int isrc = color;
01031 
01032         *ptr = (PixelType)(
01033             (_redMask & ((idst & _redMask) +
01034             ((int)(((int)(isrc & _redMask) -
01035             (int)(idst & _redMask)) * alpha) >> 8))) |
01036             (_greenMask & ((idst & _greenMask) +
01037             ((int)(((int)(isrc & _greenMask) -
01038             (int)(idst & _greenMask)) * alpha) >> 8))) |
01039             (_blueMask & ((idst & _blueMask) +
01040             ((int)(((int)(isrc & _blueMask) -
01041             (int)(idst & _blueMask)) * alpha) >> 8))) |
01042             (_alphaMask & ((idst & _alphaMask) +
01043             ((int)(((int)(_alphaMask) -
01044             (int)(idst & _alphaMask)) * alpha) >> 8))));
01045     } else {
01046         error("Unsupported BPP format: %u", (uint)sizeof(PixelType));
01047     }
01048 }
01049 
01050 template<typename PixelType>
01051 inline void VectorRendererSpec<PixelType>::
01052 blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y) {
01053     if (IS_IN_CLIP(x, y))
01054         blendPixelPtr(ptr, color, alpha);
01055 }
01056 
01057 template<typename PixelType>
01058 inline void VectorRendererSpec<PixelType>::
01059 blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) {
01060     int idst = *ptr;
01061     // This function is only used for corner pixels in rounded rectangles, so
01062     // the performance hit of this if shouldn't be too high.
01063     // We're also ignoring the cases where dst has intermediate alpha.
01064     if ((idst & _alphaMask) == 0) {
01065         // set color and alpha channels
01066         *ptr = (PixelType)(color & (_redMask | _greenMask | _blueMask)) |
01067                           ((alpha >> _format.aLoss) << _format.aShift);
01068     } else {
01069         // blend color with background
01070         blendPixelPtr(ptr, color, alpha);
01071     }
01072 }
01073 
01074 template<typename PixelType>
01075 inline void VectorRendererSpec<PixelType>::
01076 darkenFill(PixelType *ptr, PixelType *end) {
01077     PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
01078 
01079     if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
01080         // !kFeatureOverlaySupportsAlpha (but might have alpha bits)
01081 
01082         while (ptr != end) {
01083             *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
01084             ++ptr;
01085         }
01086     } else {
01087         // kFeatureOverlaySupportsAlpha
01088         // assuming at least 3 alpha bits
01089 
01090         mask |= 3 << _format.aShift;
01091         PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
01092 
01093         while (ptr != end) {
01094             // Darken the color, and increase the alpha
01095             // (0% -> 75%, 100% -> 100%)
01096             *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
01097             ++ptr;
01098         }
01099     }
01100 }
01101 
01102 template<typename PixelType>
01103 inline void VectorRendererSpec<PixelType>::
01104 darkenFillClip(PixelType *ptr, PixelType *end, int x, int y) {
01105     PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
01106 
01107     if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
01108         // !kFeatureOverlaySupportsAlpha (but might have alpha bits)
01109 
01110         while (ptr != end) {
01111             if (IS_IN_CLIP(x, y)) *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
01112             ++ptr;
01113             ++x;
01114         }
01115     } else {
01116         // kFeatureOverlaySupportsAlpha
01117         // assuming at least 3 alpha bits
01118 
01119         mask |= 3 << _format.aShift;
01120         PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
01121 
01122         while (ptr != end) {
01123             // Darken the color, and increase the alpha
01124             // (0% -> 75%, 100% -> 100%)
01125             if (IS_IN_CLIP(x, y)) *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
01126             ++ptr;
01127             ++x;
01128         }
01129     }
01130 }
01131 
01132 /********************************************************************
01133  ********************************************************************
01134  * Primitive shapes drawing - Public API calls - VectorRendererSpec *
01135  ********************************************************************
01136  ********************************************************************/
01137 template<typename PixelType>
01138 void VectorRendererSpec<PixelType>::
01139 drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area,
01140             Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis, const Common::Rect &textDrawableArea) {
01141 
01142     int offset = area.top;
01143 
01144     if (font->getFontHeight() < area.height()) {
01145         switch (alignV) {
01146         case GUI::ThemeEngine::kTextAlignVCenter:
01147             offset = area.top + ((area.height() - font->getFontHeight()) >> 1);
01148             break;
01149         case GUI::ThemeEngine::kTextAlignVBottom:
01150             offset = area.bottom - font->getFontHeight();
01151             break;
01152         default:
01153             break;
01154         }
01155     }
01156 
01157     Common::Rect drawArea;
01158     if (textDrawableArea.isEmpty()) {
01159         // In case no special area to draw to is given we only draw in the
01160         // area specified by the user.
01161         drawArea = area;
01162         // warning("there is no text drawable area. Please set this area for clipping");
01163     } else {
01164         // The area we can draw to is the intersection between the allowed
01165         // drawing area (textDrawableArea) and the area where we try to draw
01166         // the text (area).
01167         drawArea = textDrawableArea.findIntersectingRect(area);
01168     }
01169 
01170     // Better safe than sorry. We intersect with the actual surface boundaries
01171     // to avoid any ugly clipping in _activeSurface->getSubArea which messes
01172     // up the calculation of the x and y coordinates where to draw the string.
01173     drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h));
01174 
01175     if (!drawArea.isEmpty()) {
01176         Surface textAreaSurface = _activeSurface->getSubArea(drawArea);
01177         font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis);
01178     }
01179 }
01180 
01182 template<typename PixelType>
01183 void VectorRendererSpec<PixelType>::
01184 drawLine(int x1, int y1, int x2, int y2) {
01185     x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
01186     x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
01187     y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
01188     y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
01189 
01190     // we draw from top to bottom
01191     if (y2 < y1) {
01192         SWAP(x1, x2);
01193         SWAP(y1, y2);
01194     }
01195 
01196     uint dx = ABS(x2 - x1);
01197     uint dy = ABS(y2 - y1);
01198 
01199     // this is a point, not a line. stoopid.
01200     if (dy == 0 && dx == 0)
01201         return;
01202 
01203     if (Base::_strokeWidth == 0)
01204         return;
01205 
01206     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
01207     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01208     int st = Base::_strokeWidth >> 1;
01209 
01210     if (dy == 0) { // horizontal lines
01211         // these can be filled really fast with a single memset.
01212         colorFill<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor);
01213 
01214         for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
01215             colorFill<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor);
01216             colorFill<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor);
01217         }
01218 
01219     } else if (dx == 0) { // vertical lines
01220         // these ones use a static pitch increase.
01221         while (y1++ <= y2) {
01222             colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
01223             ptr += pitch;
01224         }
01225 
01226     } else if (dx == dy) { // diagonal lines
01227         // these ones also use a fixed pitch increase
01228         pitch += (x2 > x1) ? 1 : -1;
01229 
01230         while (dy--) {
01231             colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
01232             ptr += pitch;
01233         }
01234 
01235     } else { // generic lines, use the standard algorithm...
01236         drawLineAlg(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
01237     }
01238 }
01239 
01240 template<typename PixelType>
01241 void VectorRendererSpec<PixelType>::
01242 drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) {
01243     x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
01244     x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
01245     y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
01246     y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
01247 
01248     // we draw from top to bottom
01249     if (y2 < y1) {
01250         SWAP(x1, x2);
01251         SWAP(y1, y2);
01252     }
01253 
01254     uint dx = ABS(x2 - x1);
01255     uint dy = ABS(y2 - y1);
01256 
01257     // this is a point, not a line. stoopid.
01258     if (dy == 0 && dx == 0)
01259         return;
01260 
01261     if (Base::_strokeWidth == 0)
01262         return;
01263 
01264     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
01265     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01266     int st = Base::_strokeWidth >> 1;
01267 
01268     Common::Rect backup = _clippingArea;
01269     _clippingArea = clipping;
01270     bool needsClipping = !_clippingArea.isEmpty() && (!_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2));
01271     if (!needsClipping) {
01272         drawLine(x1, y1, x2, y2);
01273         _clippingArea = backup;
01274         return;
01275     }
01276 
01277     int ptr_x = x1, ptr_y = y1;
01278 
01279     if (dy == 0) { // horizontal lines
01280         colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
01281 
01282         for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
01283             colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
01284             colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
01285         }
01286 
01287     } else if (dx == 0) { // vertical lines
01288                           // these ones use a static pitch increase.
01289         while (y1++ <= y2) {
01290             colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
01291             ptr += pitch;
01292             ++ptr_y;
01293         }
01294 
01295     } else if (dx == dy) { // diagonal lines
01296                            // these ones also use a fixed pitch increase
01297         pitch += (x2 > x1) ? 1 : -1;
01298 
01299         while (dy--) {
01300             colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
01301             ptr += pitch;
01302             ++ptr_y;
01303             if (x2 > x1) ++ptr_x; else --ptr_x;
01304         }
01305 
01306     } else { // generic lines, use the standard algorithm...
01307         drawLineAlgClip(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
01308     }
01309 }
01310 
01312 template<typename PixelType>
01313 void VectorRendererSpec<PixelType>::
01314 drawCircle(int x, int y, int r) {
01315     if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h ||
01316         x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0)
01317         return;
01318 
01319     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01320         && x + r + Base::_shadowOffset < Base::_activeSurface->w
01321         && y + r + Base::_shadowOffset < Base::_activeSurface->h) {
01322         drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
01323     }
01324 
01325     switch (Base::_fillMode) {
01326     case kFillDisabled:
01327         if (Base::_strokeWidth)
01328             drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01329         break;
01330 
01331     case kFillForeground:
01332         drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01333         break;
01334 
01335     case kFillBackground:
01336         if (Base::_strokeWidth > 1) {
01337             drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01338             drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
01339         } else {
01340             drawCircleAlg(x, y, r, _bgColor, kFillBackground);
01341             drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01342         }
01343         break;
01344 
01345     case kFillGradient:
01346         break;
01347     }
01348 }
01349 
01350 template<typename PixelType>
01351 void VectorRendererSpec<PixelType>::
01352 drawCircleClip(int x, int y, int r, Common::Rect clipping) {
01353     if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h ||
01354         x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0)
01355         return;
01356 
01357     Common::Rect backup = _clippingArea;
01358     _clippingArea = clipping;
01359     bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x - r, y - r, x + r, y + r)));
01360 
01361     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01362         && x + r + Base::_shadowOffset < Base::_activeSurface->w
01363         && y + r + Base::_shadowOffset < Base::_activeSurface->h) {
01364         if (useClippingVersions)
01365             drawCircleAlgClip(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
01366         else
01367             drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
01368     }
01369 
01370     switch (Base::_fillMode) {
01371     case kFillDisabled:
01372         if (Base::_strokeWidth) {
01373             if (useClippingVersions)
01374                 drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
01375             else
01376                 drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01377         }
01378         break;
01379 
01380     case kFillForeground:
01381         if (useClippingVersions)
01382             drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
01383         else
01384             drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01385         break;
01386 
01387     case kFillBackground:
01388         if (Base::_strokeWidth > 1) {
01389             if (useClippingVersions) {
01390                 drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
01391                 drawCircleAlgClip(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
01392             } else {
01393                 drawCircleAlg(x, y, r, _fgColor, kFillForeground);
01394                 drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
01395             }
01396         } else {
01397             if (useClippingVersions) {
01398                 drawCircleAlgClip(x, y, r, _bgColor, kFillBackground);
01399                 drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
01400             } else {
01401                 drawCircleAlg(x, y, r, _bgColor, kFillBackground);
01402                 drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
01403             }
01404         }
01405         break;
01406 
01407     case kFillGradient:
01408         break;
01409     }
01410 
01411     _clippingArea = backup;
01412 }
01413 
01415 template<typename PixelType>
01416 void VectorRendererSpec<PixelType>::
01417 drawSquare(int x, int y, int w, int h) {
01418     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01419         w <= 0 || h <= 0 || x < 0 || y < 0)
01420         return;
01421 
01422     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01423         && x + w + Base::_shadowOffset < Base::_activeSurface->w
01424         && y + h + Base::_shadowOffset < Base::_activeSurface->h) {
01425         drawSquareShadow(x, y, w, h, Base::_shadowOffset);
01426     }
01427 
01428     switch (Base::_fillMode) {
01429     case kFillDisabled:
01430         if (Base::_strokeWidth)
01431             drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01432         break;
01433 
01434     case kFillForeground:
01435         drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
01436         break;
01437 
01438     case kFillBackground:
01439         drawSquareAlg(x, y, w, h, _bgColor, kFillBackground);
01440         drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01441         break;
01442 
01443     case kFillGradient:
01444         VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
01445         if (Base::_strokeWidth)
01446             drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01447         break;
01448     }
01449 }
01450 
01451 template<typename PixelType>
01452 void VectorRendererSpec<PixelType>::
01453 drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
01454     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01455         w <= 0 || h <= 0 || x < 0 || y < 0)
01456         return;
01457 
01458     Common::Rect backup = _clippingArea;
01459     _clippingArea = clipping;
01460     bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
01461 
01462     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01463         && x + w + Base::_shadowOffset < Base::_activeSurface->w
01464         && y + h + Base::_shadowOffset < Base::_activeSurface->h) {
01465         if (useClippingVersions)
01466             drawSquareShadowClip(x, y, w, h, Base::_shadowOffset);
01467         else
01468             drawSquareShadow(x, y, w, h, Base::_shadowOffset);
01469     }
01470 
01471     switch (Base::_fillMode) {
01472     case kFillDisabled:
01473         if (Base::_strokeWidth) {
01474             if (useClippingVersions)
01475                 drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01476             else
01477                 drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01478         }
01479         break;
01480 
01481     case kFillForeground:
01482         if (useClippingVersions)
01483             drawSquareAlgClip(x, y, w, h, _fgColor, kFillForeground);
01484         else
01485             drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
01486         break;
01487 
01488     case kFillBackground:
01489         if (useClippingVersions) {
01490             drawSquareAlgClip(x, y, w, h, _bgColor, kFillBackground);
01491             drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01492         } else {
01493             drawSquareAlg(x, y, w, h, _bgColor, kFillBackground);
01494             drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01495         }
01496         break;
01497 
01498     case kFillGradient:
01499         VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
01500         if (Base::_strokeWidth) {
01501             if (useClippingVersions)
01502                 drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
01503             else
01504                 drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
01505         }
01506         break;
01507     }
01508 
01509     _clippingArea = backup;
01510 }
01511 
01513 template<typename PixelType>
01514 void VectorRendererSpec<PixelType>::
01515 drawRoundedSquare(int x, int y, int r, int w, int h) {
01516     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01517         w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
01518         return;
01519 
01520     if ((r * 2) > w || (r * 2) > h)
01521         r = MIN(w /2, h / 2);
01522 
01523     if (r <= 0)
01524         return;
01525 
01526     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01527         && x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
01528         && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
01529         && h > (Base::_shadowOffset + 1) * 2) {
01530         drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
01531     }
01532 
01533     drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
01534 }
01535 
01536 template<typename PixelType>
01537 void VectorRendererSpec<PixelType>::
01538 drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
01539     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01540         w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
01541         return;
01542 
01543     if ((r * 2) > w || (r * 2) > h)
01544         r = MIN(w / 2, h / 2);
01545 
01546     if (r <= 0)
01547         return;
01548 
01549     Common::Rect backup = _clippingArea;
01550     _clippingArea = clipping;
01551     bool useOriginal = (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
01552 
01553     if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
01554         && x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
01555         && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
01556         && h > (Base::_shadowOffset + 1) * 2) {
01557         if (useOriginal) {
01558             drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
01559         } else {
01560             drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset);
01561         }
01562     }
01563 
01564     if (useOriginal) {
01565         drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
01566     } else {
01567         drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
01568     }
01569 
01570     _clippingArea = backup;
01571 }
01572 
01573 template<typename PixelType>
01574 void VectorRendererSpec<PixelType>::
01575 drawTab(int x, int y, int r, int w, int h) {
01576     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01577         w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
01578         return;
01579 
01580     if (r == 0 && Base::_bevel > 0) {
01581         drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01582         return;
01583     }
01584 
01585     if (r == 0) return;
01586 
01587     switch (Base::_fillMode) {
01588         case kFillDisabled:
01589             // FIXME: Implement this
01590             return;
01591 
01592         case kFillGradient:
01593         case kFillBackground:
01594             // FIXME: This is broken for the AA renderer.
01595             // See the rounded rect alg for how to fix it. (The border should
01596             // be drawn before the interior, both inside drawTabAlg.)
01597             drawTabShadow(x, y, w - 2, h, r);
01598             drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
01599             if (Base::_strokeWidth)
01600                 drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01601             break;
01602 
01603         case kFillForeground:
01604             drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
01605             break;
01606     }
01607 }
01608 
01609 template<typename PixelType>
01610 void VectorRendererSpec<PixelType>::
01611 drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
01612     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
01613         w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
01614         return;
01615 
01616     Common::Rect backup = _clippingArea;
01617     _clippingArea = clipping;
01618     bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
01619 
01620     if (r == 0 && Base::_bevel > 0) {
01621         if (useClippingVersions)
01622             drawBevelTabAlgClip(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01623         else
01624             drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01625         _clippingArea = backup;
01626         return;
01627     }
01628 
01629     if (r == 0) {
01630         _clippingArea = backup;
01631         return;
01632     }
01633 
01634     switch (Base::_fillMode) {
01635     case kFillDisabled:
01636         // FIXME: Implement this
01637         _clippingArea = backup;
01638         return;
01639 
01640     case kFillGradient:
01641     case kFillBackground:
01642         // FIXME: This is broken for the AA renderer.
01643         // See the rounded rect alg for how to fix it. (The border should
01644         // be drawn before the interior, both inside drawTabAlg.)
01645         if (useClippingVersions) {
01646             drawTabShadowClip(x, y, w - 2, h, r);
01647             drawTabAlgClip(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
01648             if (Base::_strokeWidth)
01649                 drawTabAlgClip(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01650         } else {
01651             drawTabShadow(x, y, w - 2, h, r);
01652             drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
01653             if (Base::_strokeWidth)
01654                 drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
01655         }
01656         break;
01657 
01658     case kFillForeground:
01659         if (useClippingVersions)
01660             drawTabAlgClip(x, y, w, h, r, _fgColor, Base::_fillMode);
01661         else
01662             drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
01663         break;
01664     }
01665 
01666     _clippingArea = backup;
01667 }
01668 
01669 template<typename PixelType>
01670 void VectorRendererSpec<PixelType>::
01671 drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
01672 
01673     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
01674         return;
01675 
01676     PixelType color = 0;
01677 
01678     if (Base::_strokeWidth <= 1) {
01679         if (Base::_fillMode == kFillForeground)
01680             color = _fgColor;
01681         else if (Base::_fillMode == kFillBackground)
01682             color = _bgColor;
01683     } else {
01684         if (Base::_fillMode == kFillDisabled)
01685             return;
01686         color = _fgColor;
01687     }
01688 
01689     if (Base::_dynamicData != 0)
01690         orient = (TriangleOrientation)Base::_dynamicData;
01691 
01692     if (w == h) {
01693         int newW = w;
01694 
01695         switch (orient) {
01696         case kTriangleUp:
01697         case kTriangleDown:
01698             //drawTriangleFast(x, y, newW, (orient == kTriangleDown), color, Base::_fillMode);
01699             drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01700             break;
01701 
01702         case kTriangleLeft:
01703         case kTriangleRight:
01704         case kTriangleAuto:
01705             break;
01706         }
01707 
01708         if (Base::_strokeWidth > 0)
01709             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01710                 //drawTriangleFast(x, y, newW, (orient == kTriangleDown), _fgColor, kFillDisabled);
01711                 drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01712             }
01713     } else {
01714         int newW = w;
01715         int newH = h;
01716 
01717         switch (orient) {
01718         case kTriangleUp:
01719         case kTriangleDown:
01720             drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
01721             break;
01722 
01723         case kTriangleLeft:
01724         case kTriangleRight:
01725         case kTriangleAuto:
01726             break;
01727         }
01728 
01729         if (Base::_strokeWidth > 0) {
01730             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01731                 drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
01732             }
01733         }
01734     }
01735 }
01736 
01737 template<typename PixelType>
01738 void VectorRendererSpec<PixelType>::
01739 drawTriangleClip(int x, int y, int w, int h, TriangleOrientation orient, Common::Rect clipping) {
01740     if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
01741         return;
01742 
01743     PixelType color = 0;
01744 
01745     if (Base::_strokeWidth <= 1) {
01746         if (Base::_fillMode == kFillForeground)
01747             color = _fgColor;
01748         else if (Base::_fillMode == kFillBackground)
01749             color = _bgColor;
01750     } else {
01751         if (Base::_fillMode == kFillDisabled)
01752             return;
01753         color = _fgColor;
01754     }
01755 
01756     if (Base::_dynamicData != 0)
01757         orient = (TriangleOrientation)Base::_dynamicData;
01758 
01759     Common::Rect backup = _clippingArea;
01760     _clippingArea = clipping;
01761     bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
01762 
01763     if (w == h) {
01764         int newW = w;
01765 
01766         switch (orient) {
01767         case kTriangleUp:
01768         case kTriangleDown:
01769             if (useClippingVersions)
01770                 drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01771             else
01772                 drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01773             break;
01774 
01775         case kTriangleLeft:
01776         case kTriangleRight:
01777         case kTriangleAuto:
01778             break;
01779         }
01780 
01781         if (Base::_strokeWidth > 0)
01782             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01783                 if (useClippingVersions)
01784                     drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01785                 else
01786                     drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
01787             }
01788     } else {
01789         int newW = w;
01790         int newH = h;
01791 
01792         switch (orient) {
01793         case kTriangleUp:
01794         case kTriangleDown:
01795             if (useClippingVersions)
01796                 drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
01797             else
01798                 drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
01799             break;
01800 
01801         case kTriangleLeft:
01802         case kTriangleRight:
01803         case kTriangleAuto:
01804             break;
01805         }
01806 
01807         if (Base::_strokeWidth > 0) {
01808             if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
01809                 if (useClippingVersions)
01810                     drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
01811                 else
01812                     drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
01813             }
01814         }
01815     }
01816 
01817     _clippingArea = backup;
01818 }
01819 
01820 
01821 /********************************************************************
01822  ********************************************************************
01823  * Aliased Primitive drawing ALGORITHMS - VectorRendererSpec
01824  ********************************************************************
01825  ********************************************************************/
01827 template<typename PixelType>
01828 void VectorRendererSpec<PixelType>::
01829 drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
01830     // Don't draw anything for empty rects.
01831     if (w <= 0 || h <= 0) {
01832         return;
01833     }
01834 
01835     int f, ddF_x, ddF_y;
01836     int x, y, px, py;
01837     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01838     int sw  = 0, sp = 0, hp = 0;
01839 
01840     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
01841     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
01842     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
01843 
01844     int real_radius = r;
01845     int short_h = h - r + 2;
01846     int long_h = h;
01847 
01848     if (fill_m == kFillDisabled) {
01849         while (sw++ < Base::_strokeWidth) {
01850             colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
01851             colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
01852             sp += pitch;
01853 
01854             BE_RESET();
01855             r--;
01856 
01857             while (x++ < y) {
01858                 BE_ALGORITHM();
01859                 BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py);
01860 
01861                 if (Base::_strokeWidth > 1)
01862                     BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py);
01863             }
01864         }
01865 
01866         ptr_fill += pitch * real_radius;
01867         while (short_h--) {
01868             colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color);
01869             colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
01870             ptr_fill += pitch;
01871         }
01872 
01873         if (baseLeft) {
01874             sw = 0;
01875             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
01876             while (sw++ < Base::_strokeWidth) {
01877                 colorFill<PixelType>(ptr_fill - baseLeft, ptr_fill, color);
01878                 ptr_fill += pitch;
01879             }
01880         }
01881 
01882         if (baseRight) {
01883             sw = 0;
01884             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
01885             while (sw++ < Base::_strokeWidth) {
01886                 colorFill<PixelType>(ptr_fill, ptr_fill + baseRight, color);
01887                 ptr_fill += pitch;
01888             }
01889         }
01890     } else {
01891         BE_RESET();
01892 
01893         precalcGradient(long_h);
01894 
01895         PixelType color1, color2;
01896         color1 = color2 = color;
01897 
01898         while (x++ < y) {
01899             BE_ALGORITHM();
01900 
01901             if (fill_m == kFillGradient) {
01902                 color1 = calcGradient(real_radius - x, long_h);
01903                 color2 = calcGradient(real_radius - y, long_h);
01904 
01905                 gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
01906                 gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
01907 
01908                 BE_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py);
01909             } else {
01910                 colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color);
01911                 colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color);
01912 
01913                 BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py);
01914             }
01915         }
01916 
01917         ptr_fill += pitch * r;
01918         while (short_h--) {
01919             if (fill_m == kFillGradient) {
01920                 gradientFill(ptr_fill, w + 1, x1, real_radius++);
01921             } else {
01922                 colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
01923             }
01924             ptr_fill += pitch;
01925         }
01926     }
01927 }
01928 
01929 template<typename PixelType>
01930 void VectorRendererSpec<PixelType>::
01931 drawTabAlgClip(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
01932     // Don't draw anything for empty rects.
01933     if (w <= 0 || h <= 0) {
01934         return;
01935     }
01936 
01937     int f, ddF_x, ddF_y;
01938     int x, y, px, py;
01939     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
01940     int sw = 0, sp = 0, hp = 0;
01941 
01942     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
01943     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
01944     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
01945     int tl_x = x1 + r, tl_y = y1 + r;
01946     int tr_x = x1 + w - r, tr_y = y1 + r;
01947     int fill_x = x1, fill_y = y1;
01948 
01949     int real_radius = r;
01950     int short_h = h - r + 2;
01951     int long_h = h;
01952 
01953     if (fill_m == kFillDisabled) {
01954         while (sw++ < Base::_strokeWidth) {
01955             colorFillClip<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, fill_x + r, fill_y + sp/pitch, _clippingArea);
01956             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);
01957             sp += pitch;
01958 
01959             BE_RESET();
01960             r--;
01961 
01962             while (x++ < y) {
01963                 BE_ALGORITHM();
01964                 BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
01965 
01966                 if (Base::_strokeWidth > 1)
01967                     BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px - pitch, py, tr_x, tr_y, tl_x, tl_y);
01968             }
01969         }
01970 
01971         ptr_fill += pitch * real_radius;
01972         fill_y += real_radius;
01973         while (short_h--) {
01974             colorFillClip<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color, fill_x, fill_y, _clippingArea);
01975             colorFillClip<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, fill_x + w - Base::_strokeWidth + 1, fill_y, _clippingArea);
01976             ptr_fill += pitch;
01977             ++fill_y;
01978         }
01979 
01980         if (baseLeft) {
01981             sw = 0;
01982             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
01983             fill_x = x1;
01984             fill_y = y1 + h + 1;
01985             while (sw++ < Base::_strokeWidth) {
01986                 colorFillClip<PixelType>(ptr_fill - baseLeft, ptr_fill, color, fill_x - baseLeft, fill_y, _clippingArea);
01987                 ptr_fill += pitch;
01988                 ++fill_y;
01989             }
01990         }
01991 
01992         if (baseRight) {
01993             sw = 0;
01994             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
01995             fill_x = x1 + w;
01996             fill_y = y1 + h + 1;
01997             while (sw++ < Base::_strokeWidth) {
01998                 colorFillClip<PixelType>(ptr_fill, ptr_fill + baseRight, color, fill_x, fill_y, _clippingArea);
01999                 ptr_fill += pitch;
02000                 ++fill_y;
02001             }
02002         }
02003     } else {
02004         BE_RESET();
02005 
02006         precalcGradient(long_h);
02007 
02008         PixelType color1, color2;
02009         color1 = color2 = color;
02010 
02011         while (x++ < y) {
02012             BE_ALGORITHM();
02013 
02014             if (fill_m == kFillGradient) {
02015                 color1 = calcGradient(real_radius - x, long_h);
02016                 color2 = calcGradient(real_radius - y, long_h);
02017 
02018                 gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y, tl_x - x, tl_y - y);
02019                 gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x, tl_x - y, tl_y - x);
02020 
02021                 BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
02022             } else {
02023                 colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color, tl_x - x, tl_y - y, _clippingArea);
02024                 colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color, tl_x - y, tl_y - x, _clippingArea);
02025 
02026                 BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
02027             }
02028         }
02029 
02030         ptr_fill += pitch * r;
02031         fill_y += r;
02032         while (short_h--) {
02033             if (fill_m == kFillGradient) {
02034                 gradientFillClip(ptr_fill, w + 1, x1, real_radius++, fill_x, fill_y);
02035             } else {
02036                 colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color, fill_x, fill_y, _clippingArea);
02037             }
02038             ptr_fill += pitch;
02039             ++fill_y;
02040         }
02041     }
02042 }
02043 
02044 template<typename PixelType>
02045 void VectorRendererSpec<PixelType>::
02046 drawTabShadow(int x1, int y1, int w, int h, int r) {
02047     int offset = 3;
02048     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02049 
02050     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
02051     uint8 expFactor = 3;
02052     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
02053 
02054     int xstart = x1;
02055     int ystart = y1;
02056     int width = w;
02057     int height = h + offset + 1;
02058 
02059     for (int i = offset; i >= 0; i--) {
02060         int f, ddF_x, ddF_y;
02061         int x, y, px, py;
02062 
02063         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
02064         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
02065         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
02066 
02067         int short_h = height - (2 * r) + 2;
02068         PixelType color = _format.RGBToColor(0, 0, 0);
02069 
02070         BE_RESET();
02071 
02072         // HACK: As we are drawing circles exploting 8-axis symmetry,
02073         // there are 4 pixels on each circle which are drawn twice.
02074         // this is ok on filled circles, but when blending on surfaces,
02075         // we cannot let it blend twice. awful.
02076         uint32 hb = 0;
02077 
02078         while (x++ < y) {
02079             BE_ALGORITHM();
02080 
02081             if (((1 << x) & hb) == 0) {
02082                 blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
02083                 hb |= (1 << x);
02084             }
02085 
02086             if (((1 << y) & hb) == 0) {
02087                 blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
02088                 hb |= (1 << y);
02089             }
02090         }
02091 
02092         ptr_fill += pitch * r;
02093         while (short_h--) {
02094             blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
02095             ptr_fill += pitch;
02096         }
02097 
02098         // Move shadow one pixel upward each iteration
02099         xstart += 1;
02100         // Multiply with expfactor
02101         alpha = (alpha * (expFactor << 8)) >> 9;
02102     }
02103 }
02104 
02105 template<typename PixelType>
02106 void VectorRendererSpec<PixelType>::
02107 drawTabShadowClip(int x1, int y1, int w, int h, int r) {
02108     int offset = 3;
02109     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02110 
02111     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
02112     uint8 expFactor = 3;
02113     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
02114 
02115     int xstart = x1;
02116     int ystart = y1;
02117     int width = w;
02118     int height = h + offset + 1;
02119 
02120     for (int i = offset; i >= 0; i--) {
02121         int f, ddF_x, ddF_y;
02122         int x, y, px, py;
02123 
02124         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
02125         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
02126         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
02127 
02128         int tl_x = xstart + r, tl_y = ystart + r;
02129         int fill_x = xstart, fill_y = ystart;
02130 
02131         int short_h = height - (2 * r) + 2;
02132         PixelType color = _format.RGBToColor(0, 0, 0);
02133 
02134         BE_RESET();
02135 
02136         // HACK: As we are drawing circles exploting 8-axis symmetry,
02137         // there are 4 pixels on each circle which are drawn twice.
02138         // this is ok on filled circles, but when blending on surfaces,
02139         // we cannot let it blend twice. awful.
02140         uint32 hb = 0;
02141 
02142         while (x++ < y) {
02143             BE_ALGORITHM();
02144 
02145             if (((1 << x) & hb) == 0) {
02146                 blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, tl_x - y, tl_y - x);
02147                 hb |= (1 << x);
02148             }
02149 
02150             if (((1 << y) & hb) == 0) {
02151                 blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, tl_x - x, tl_y - y);
02152                 hb |= (1 << y);
02153             }
02154         }
02155 
02156         ptr_fill += pitch * r;
02157         fill_y += r;
02158         while (short_h--) {
02159             blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha, fill_x, fill_y);
02160             ptr_fill += pitch;
02161             ++fill_y;
02162         }
02163 
02164         // Move shadow one pixel upward each iteration
02165         xstart += 1;
02166         // Multiply with expfactor
02167         alpha = (alpha * (expFactor << 8)) >> 9;
02168     }
02169 }
02170 
02172 template<typename PixelType>
02173 void VectorRendererSpec<PixelType>::
02174 drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
02175     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02176     int i, j;
02177 
02178     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02179 
02180     i = bevel;
02181     while (i--) {
02182         colorFill<PixelType>(ptr_left, ptr_left + w, top_color);
02183         ptr_left += pitch;
02184     }
02185 
02186     if (baseLeft > 0) {
02187         i = h - bevel;
02188         ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02189         while (i--) {
02190             colorFill<PixelType>(ptr_left, ptr_left + bevel, top_color);
02191             ptr_left += pitch;
02192         }
02193     }
02194 
02195     i = h - bevel;
02196     j = bevel - 1;
02197     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02198     while (i--) {
02199         colorFill<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color);
02200         if (j > 0) j--;
02201         ptr_left += pitch;
02202     }
02203 
02204     i = bevel;
02205     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
02206     while (i--) {
02207         colorFill<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color);
02208 
02209         if (baseLeft)
02210             colorFill<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color);
02211         ptr_left += pitch;
02212     }
02213 }
02214 
02215 template<typename PixelType>
02216 void VectorRendererSpec<PixelType>::
02217 drawBevelTabAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
02218     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02219     int i, j;
02220 
02221     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02222     int ptr_x = x, ptr_y = y;
02223 
02224     i = bevel;
02225     while (i--) {
02226         colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
02227         ptr_left += pitch;
02228         ++ptr_y;
02229     }
02230 
02231     if (baseLeft > 0) {
02232         i = h - bevel;
02233         ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02234         ptr_x = x; ptr_y = y;
02235         while (i--) {
02236             colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
02237             ptr_left += pitch;
02238             ++ptr_y;
02239         }
02240     }
02241 
02242     i = h - bevel;
02243     j = bevel - 1;
02244     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02245     ptr_x = x + w - bevel; ptr_y = y;
02246     while (i--) {
02247         colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
02248         if (j > 0) j--;
02249         ptr_left += pitch;
02250         ++ptr_y;
02251     }
02252 
02253     i = bevel;
02254     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
02255     ptr_x = x + w - bevel; ptr_y = y + h - bevel;
02256     while (i--) {
02257         colorFillClip<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color, ptr_x, ptr_y, _clippingArea);
02258 
02259         if (baseLeft)
02260             colorFillClip<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color, ptr_x - w - baseLeft + bevel, ptr_y, _clippingArea);
02261         ptr_left += pitch;
02262         ++ptr_y;
02263     }
02264 }
02265 
02267 template<typename PixelType>
02268 void VectorRendererSpec<PixelType>::
02269 drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02270     // Do not draw anything for empty rects.
02271     if (w <= 0 || h <= 0) {
02272         return;
02273     }
02274 
02275     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
02276     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02277     int max_h = h;
02278 
02279     if (fill_m != kFillDisabled) {
02280         while (h--) {
02281             if (fill_m == kFillGradient)
02282                 color = calcGradient(max_h - h, max_h);
02283 
02284             colorFill<PixelType>(ptr, ptr + w, color);
02285             ptr += pitch;
02286         }
02287     } else {
02288         int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
02289 
02290         while (sw--) {
02291             colorFill<PixelType>(ptr + sp, ptr + w + sp, color);
02292             colorFill<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color);
02293             sp += pitch;
02294         }
02295 
02296         while (h--) {
02297             colorFill<PixelType>(ptr, ptr + Base::_strokeWidth, color);
02298             colorFill<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color);
02299             ptr += pitch;
02300         }
02301     }
02302 }
02303 
02304 template<typename PixelType>
02305 void VectorRendererSpec<PixelType>::
02306 drawSquareAlgClip(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
02307     // Do not draw anything for empty rects.
02308     if (w <= 0 || h <= 0) {
02309         return;
02310     }
02311 
02312     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
02313     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02314     int max_h = h;
02315     int ptr_y = y;
02316 
02317     if (fill_m != kFillDisabled) {
02318         while (h--) {
02319             if (fill_m == kFillGradient)
02320                 color = calcGradient(max_h - h, max_h);
02321 
02322             colorFillClip<PixelType>(ptr, ptr + w, color, x, ptr_y, _clippingArea);
02323             ptr += pitch;
02324             ++ptr_y;
02325         }
02326     } else {
02327         int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
02328 
02329         while (sw--) {
02330             colorFillClip<PixelType>(ptr + sp, ptr + w + sp, color, x, ptr_y + sp/pitch, _clippingArea);
02331             colorFillClip<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color, x, ptr_y + h - sp/pitch, _clippingArea);
02332             sp += pitch;
02333         }
02334 
02335         while (h--) {
02336             colorFillClip<PixelType>(ptr, ptr + Base::_strokeWidth, color, x, ptr_y, _clippingArea);
02337             colorFillClip<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color, x + w - Base::_strokeWidth, ptr_y, _clippingArea);
02338             ptr += pitch;
02339             ptr_y += 1;
02340         }
02341     }
02342 }
02343 
02345 template<typename PixelType>
02346 void VectorRendererSpec<PixelType>::
02347 drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) {
02348     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02349     int i, j;
02350     PixelType *ptr_left;
02351 
02352     // Fill Background
02353     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02354     i = h;
02355     if (fill) {
02356         assert((_bgColor & ~_alphaMask) == 0); // only support black
02357         while (i--) {
02358             darkenFill(ptr_left, ptr_left + w);
02359             ptr_left += pitch;
02360         }
02361     }
02362 
02363     x = MAX(x - bevel, 0);
02364     y = MAX(y - bevel, 0);
02365 
02366     w = MIN(x + w + (bevel * 2), (int)_activeSurface->w) - x;
02367     h = MIN(y + h + (bevel * 2), (int)_activeSurface->h) - y;
02368 
02369     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02370     i = bevel;
02371     while (i--) {
02372         colorFill<PixelType>(ptr_left, ptr_left + w, top_color);
02373         ptr_left += pitch;
02374     }
02375 
02376     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
02377     i = h - bevel;
02378     while (i--) {
02379         colorFill<PixelType>(ptr_left, ptr_left + bevel, top_color);
02380         ptr_left += pitch;
02381     }
02382 
02383     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
02384     i = bevel;
02385     while (i--) {
02386         colorFill<PixelType>(ptr_left + i, ptr_left + w, bottom_color);
02387         ptr_left += pitch;
02388     }
02389 
02390     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02391     i = h - bevel;
02392     j = bevel - 1;
02393     while (i--) {
02394         colorFill<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color);
02395         if (j > 0) j--;
02396         ptr_left += pitch;
02397     }
02398 }
02399 
02400 template<typename PixelType>
02401 void VectorRendererSpec<PixelType>::
02402 drawBevelSquareAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) {
02403     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02404     int i, j;
02405     PixelType *ptr_left;
02406     int ptr_x, ptr_y;
02407 
02408     // Fill Background
02409     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02410     ptr_x = x; ptr_y = y;
02411     i = h;
02412     if (fill) {
02413         assert((_bgColor & ~_alphaMask) == 0); // only support black
02414         while (i--) {
02415             darkenFillClip(ptr_left, ptr_left + w, ptr_x, ptr_y);
02416             ptr_left += pitch;
02417             ++ptr_y;
02418         }
02419     }
02420 
02421     x = MAX(x - bevel, 0);
02422     y = MAX(y - bevel, 0);
02423 
02424     w = MIN(x + w + (bevel * 2), (int)_activeSurface->w) - x;
02425     h = MIN(y + h + (bevel * 2), (int)_activeSurface->h) - y;
02426 
02427     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
02428     ptr_x = x; ptr_y = y;
02429     i = bevel;
02430     while (i--) {
02431         colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
02432         ptr_left += pitch;
02433         ++ptr_y;
02434     }
02435 
02436     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
02437     ptr_x = x; ptr_y = y + bevel;
02438     i = h - bevel;
02439     while (i--) {
02440         colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
02441         ptr_left += pitch;
02442         ++ptr_y;
02443     }
02444 
02445     ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
02446     ptr_x = x; ptr_y = y + h - bevel;
02447     i = bevel;
02448     while (i--) {
02449         colorFillClip<PixelType>(ptr_left + i, ptr_left + w, bottom_color, ptr_x + i, ptr_y, _clippingArea);
02450         ptr_left += pitch;
02451         ++ptr_y;
02452     }
02453 
02454     ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
02455     ptr_x = x + w - bevel; ptr_y = y;
02456     i = h - bevel;
02457     j = bevel - 1;
02458     while (i--) {
02459         colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
02460         if (j > 0) j--;
02461         ptr_left += pitch;
02462         ++ptr_y;
02463     }
02464 }
02465 
02467 template<typename PixelType>
02468 void VectorRendererSpec<PixelType>::
02469 drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
02470     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02471     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02472     int xdir = (x2 > x1) ? 1 : -1;
02473 
02474     *ptr = (PixelType)color;
02475 
02476     if (dx > dy) {
02477         int ddy = dy * 2;
02478         int dysub = ddy - (dx * 2);
02479         int error_term = ddy - dx;
02480 
02481         while (dx--) {
02482             if (error_term >= 0) {
02483                 ptr += pitch;
02484                 error_term += dysub;
02485             } else {
02486                 error_term += ddy;
02487             }
02488 
02489             ptr += xdir;
02490             *ptr = (PixelType)color;
02491         }
02492     } else {
02493         int ddx = dx * 2;
02494         int dxsub = ddx - (dy * 2);
02495         int error_term = ddx - dy;
02496 
02497         while (dy--) {
02498             if (error_term >= 0) {
02499                 ptr += xdir;
02500                 error_term += dxsub;
02501             } else {
02502                 error_term += ddx;
02503             }
02504 
02505             ptr += pitch;
02506             *ptr = (PixelType)color;
02507         }
02508     }
02509 
02510     ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
02511     *ptr = (PixelType)color;
02512 }
02513 
02514 template<typename PixelType>
02515 void VectorRendererSpec<PixelType>::
02516 drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
02517     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02518     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02519     int xdir = (x2 > x1) ? 1 : -1;
02520     int ptr_x = x1, ptr_y = y1;
02521 
02522     if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02523 
02524     if (dx > dy) {
02525         int ddy = dy * 2;
02526         int dysub = ddy - (dx * 2);
02527         int error_term = ddy - dx;
02528 
02529         while (dx--) {
02530             if (error_term >= 0) {
02531                 ptr += pitch;
02532                 ++ptr_y;
02533                 error_term += dysub;
02534             } else {
02535                 error_term += ddy;
02536             }
02537 
02538             ptr += xdir;
02539             ptr_x += xdir;
02540             if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02541         }
02542     } else {
02543         int ddx = dx * 2;
02544         int dxsub = ddx - (dy * 2);
02545         int error_term = ddx - dy;
02546 
02547         while (dy--) {
02548             if (error_term >= 0) {
02549                 ptr += xdir;
02550                 ptr_x += xdir;
02551                 error_term += dxsub;
02552             } else {
02553                 error_term += ddx;
02554             }
02555 
02556             ptr += pitch;
02557             ++ptr_y;
02558             if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02559         }
02560     }
02561 
02562     ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
02563     ptr_x = x2; ptr_y = y2;
02564     if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
02565 }
02566 
02572 #define FIXED_POINT 1
02573 
02574 #if FIXED_POINT
02575 #define ipart(x) ((x) & ~0xFF)
02576 // This is not really correct since gradient is not percentage, but [0..255]
02577 #define rfpart(x) ((0x100 - ((x) & 0xFF)) * 100 >> 8)
02578 //#define rfpart(x) (0x100 - ((x) & 0xFF))
02579 #else
02580 #define ipart(x) ((int)x)
02581 #define round(x) (ipart(x + 0.5))
02582 #define fpart(x) (x - ipart(x))
02583 #define rfpart(x) (int)((1 - fpart(x)) * 100)
02584 #endif
02585 
02586 template<typename PixelType>
02587 void VectorRendererSpec<PixelType>::
02588 drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02589     // Don't draw anything for empty rects. This assures dy is always different
02590     // from zero.
02591     if (w <= 0 || h <= 0) {
02592         return;
02593     }
02594 
02595     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02596     int gradient_h = 0;
02597     if (!inverted) {
02598         pitch = -pitch;
02599         y1 += h;
02600     }
02601 
02602     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02603     PixelType *floor = ptr_right - 1;
02604     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
02605 
02606     int x2 = x1 + w / 2;
02607     int y2 = y1 + h;
02608 
02609 #if FIXED_POINT
02610     int dx = (x2 - x1) << 8;
02611     int dy = (y2 - y1) << 8;
02612 
02613     if (abs(dx) > abs(dy)) {
02614 #else
02615     double dx = (double)x2 - (double)x1;
02616     double dy = (double)y2 - (double)y1;
02617 
02618     if (fabs(dx) > fabs(dy)) {
02619 #endif
02620         while (floor++ != ptr_left)
02621             blendPixelPtr(floor, color, 50);
02622 
02623 #if FIXED_POINT
02624         // In this branch dx is always different from zero. This is because
02625         // abs(dx) is strictly greater than abs(dy), and abs returns zero
02626         // as minimal value.
02627         int gradient = (dy << 8) / dx;
02628         int intery = (y1 << 8) + gradient;
02629 #else
02630         double gradient = dy / dx;
02631         double intery = y1 + gradient;
02632 #endif
02633 
02634         for (int x = x1 + 1; x < x2; x++) {
02635 #if FIXED_POINT
02636             if (intery + gradient > ipart(intery) + 0x100) {
02637 #else
02638             if (intery + gradient > ipart(intery) + 1) {
02639 #endif
02640                 ptr_right++;
02641                 ptr_left--;
02642             }
02643 
02644             ptr_left += pitch;
02645             ptr_right += pitch;
02646 
02647             intery += gradient;
02648 
02649             switch (fill_m) {
02650             case kFillDisabled:
02651                 *ptr_left = *ptr_right = color;
02652                 break;
02653             case kFillForeground:
02654             case kFillBackground:
02655                 colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02656                 blendPixelPtr(ptr_right, color, rfpart(intery));
02657                 blendPixelPtr(ptr_left, color, rfpart(intery));
02658                 break;
02659             case kFillGradient:
02660                 colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02661                 blendPixelPtr(ptr_right, color, rfpart(intery));
02662                 blendPixelPtr(ptr_left, color, rfpart(intery));
02663                 break;
02664             }
02665         }
02666 
02667         return;
02668     }
02669 
02670 #if FIXED_POINT
02671     if (abs(dx) < abs(dy)) {
02672 #else
02673     if (fabs(dx) < fabs(dy)) {
02674 #endif
02675         ptr_left--;
02676         while (floor++ != ptr_left)
02677             blendPixelPtr(floor, color, 50);
02678 
02679 #if FIXED_POINT
02680         int gradient = (dx << 8) / (dy + 0x100);
02681         int interx = (x1 << 8) + gradient;
02682 #else
02683         double gradient = dx / (dy + 1);
02684         double interx = x1 + gradient;
02685 #endif
02686 
02687         for (int y = y1 + 1; y < y2; y++) {
02688 #if FIXED_POINT
02689             if (interx + gradient > ipart(interx) + 0x100) {
02690 #else
02691             if (interx + gradient > ipart(interx) + 1) {
02692 #endif
02693                 ptr_right++;
02694                 ptr_left--;
02695             }
02696 
02697             ptr_left += pitch;
02698             ptr_right += pitch;
02699 
02700             interx += gradient;
02701 
02702             switch (fill_m) {
02703             case kFillDisabled:
02704                 *ptr_left = *ptr_right = color;
02705                 break;
02706             case kFillForeground:
02707             case kFillBackground:
02708                 colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02709                 blendPixelPtr(ptr_right, color, rfpart(interx));
02710                 blendPixelPtr(ptr_left, color, rfpart(interx));
02711                 break;
02712             case kFillGradient:
02713                 colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02714                 blendPixelPtr(ptr_right, color, rfpart(interx));
02715                 blendPixelPtr(ptr_left, color, rfpart(interx));
02716                 break;
02717             }
02718         }
02719 
02720         return;
02721     }
02722 
02723     ptr_left--;
02724 
02725     while (floor++ != ptr_left)
02726         blendPixelPtr(floor, color, 50);
02727 
02728 #if FIXED_POINT
02729     int gradient = (dx / dy) << 8;
02730     int interx = (x1 << 8) + gradient;
02731 #else
02732     double gradient = dx / dy;
02733     double interx = x1 + gradient;
02734 #endif
02735 
02736     for (int y = y1 + 1; y < y2; y++) {
02737         ptr_right++;
02738         ptr_left--;
02739 
02740         ptr_left += pitch;
02741         ptr_right += pitch;
02742 
02743         interx += gradient;
02744 
02745         switch (fill_m) {
02746         case kFillDisabled:
02747             *ptr_left = *ptr_right = color;
02748             break;
02749         case kFillForeground:
02750         case kFillBackground:
02751             colorFill<PixelType>(ptr_right + 1, ptr_left, color);
02752             blendPixelPtr(ptr_right, color, rfpart(interx));
02753             blendPixelPtr(ptr_left, color, rfpart(interx));
02754             break;
02755         case kFillGradient:
02756             colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h));
02757             blendPixelPtr(ptr_right, color, rfpart(interx));
02758             blendPixelPtr(ptr_left, color, rfpart(interx));
02759             break;
02760         }
02761     }
02762 
02763 }
02764 
02766 
02767 template<typename PixelType>
02768 void VectorRendererSpec<PixelType>::
02769 drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02770     // Don't draw anything for empty rects. This assures dy is always different
02771     // from zero.
02772     if (w <= 0 || h <= 0) {
02773         return;
02774     }
02775 
02776     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02777     int gradient_h = 0;
02778     int y_pitch_sign = 1;
02779     if (!inverted) {
02780         pitch = -pitch;
02781         y1 += h;
02782         y_pitch_sign = -1;
02783     }
02784 
02785     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02786     PixelType *floor = ptr_right - 1;
02787     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
02788 
02789     int x2 = x1 + w / 2;
02790     int y2 = y1 + h;
02791     int x_right = x1;
02792     int y_right = y1;
02793     int x_left = x1 + w;
02794     int y_left = y1;
02795     int x_floor = x_right - 1;
02796     int y_floor = y_right;
02797 
02798 #if FIXED_POINT
02799     int dx = (x2 - x1) << 8;
02800     int dy = (y2 - y1) << 8;
02801 
02802     if (abs(dx) > abs(dy)) {
02803 #else
02804     double dx = (double)x2 - (double)x1;
02805     double dy = (double)y2 - (double)y1;
02806 
02807     if (fabs(dx) > fabs(dy)) {
02808 #endif
02809         while (floor++ != ptr_left)
02810             blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02811 
02812 #if FIXED_POINT
02813         // In this branch dx is always different from zero. This is because
02814         // abs(dx) is strictly greater than abs(dy), and abs returns zero
02815         // as minimal value.
02816         int gradient = (dy << 8) / dx;
02817         int intery = (y1 << 8) + gradient;
02818 #else
02819         double gradient = dy / dx;
02820         double intery = y1 + gradient;
02821 #endif
02822 
02823         for (int x = x1 + 1; x < x2; x++) {
02824 #if FIXED_POINT
02825             if (intery + gradient > ipart(intery) + 0x100) {
02826 #else
02827             if (intery + gradient > ipart(intery) + 1) {
02828 #endif
02829                 ptr_right++;
02830                 ptr_left--;
02831                 ++x_right;
02832                 --x_left;
02833             }
02834 
02835             ptr_left += pitch;
02836             ptr_right += pitch;
02837             y_right += y_pitch_sign;
02838             y_left += y_pitch_sign;
02839 
02840             intery += gradient;
02841 
02842             switch (fill_m) {
02843             case kFillDisabled:
02844                 if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02845                 if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02846                 break;
02847             case kFillForeground:
02848             case kFillBackground:
02849                 colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02850                 blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
02851                 blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
02852                 break;
02853             case kFillGradient:
02854                 colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02855                 blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
02856                 blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
02857                 break;
02858             }
02859             }
02860 
02861         return;
02862         }
02863 
02864 #if FIXED_POINT
02865     if (abs(dx) < abs(dy)) {
02866 #else
02867     if (fabs(dx) < fabs(dy)) {
02868 #endif
02869         ptr_left--;
02870         --x_left;
02871         while (floor++ != ptr_left)
02872             blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02873 
02874 #if FIXED_POINT
02875         int gradient = (dx << 8) / (dy + 0x100);
02876         int interx = (x1 << 8) + gradient;
02877 #else
02878         double gradient = dx / (dy + 1);
02879         double interx = x1 + gradient;
02880 #endif
02881 
02882         for (int y = y1 + 1; y < y2; y++) {
02883 #if FIXED_POINT
02884             if (interx + gradient > ipart(interx) + 0x100) {
02885 #else
02886             if (interx + gradient > ipart(interx) + 1) {
02887 #endif
02888                 ptr_right++;
02889                 ptr_left--;
02890                 ++x_right;
02891                 --x_left;
02892             }
02893 
02894             ptr_left += pitch;
02895             ptr_right += pitch;
02896             y_right += y_pitch_sign;
02897             y_left += y_pitch_sign;
02898 
02899             interx += gradient;
02900 
02901             switch (fill_m) {
02902             case kFillDisabled:
02903                 if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02904                 if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02905                 break;
02906             case kFillForeground:
02907             case kFillBackground:
02908                 colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02909                 blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02910                 blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02911                 break;
02912             case kFillGradient:
02913                 colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02914                 blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02915                 blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02916                 break;
02917             }
02918             }
02919 
02920         return;
02921         }
02922 
02923     ptr_left--;
02924     --x_left;
02925     while (floor++ != ptr_left)
02926         blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
02927 
02928 #if FIXED_POINT
02929     int gradient = (dx / dy) << 8;
02930     int interx = (x1 << 8) + gradient;
02931 #else
02932     double gradient = dx / dy;
02933     double interx = x1 + gradient;
02934 #endif
02935 
02936     for (int y = y1 + 1; y < y2; y++) {
02937         ptr_right++;
02938         ptr_left--;
02939         ++x_right;
02940         --x_left;
02941 
02942         ptr_left += pitch;
02943         ptr_right += pitch;
02944         y_right += y_pitch_sign;
02945         y_left += y_pitch_sign;
02946 
02947         interx += gradient;
02948 
02949         switch (fill_m) {
02950         case kFillDisabled:
02951             if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
02952             if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
02953             break;
02954         case kFillForeground:
02955         case kFillBackground:
02956             colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right + 1, y_right, _clippingArea);
02957             blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02958             blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02959             break;
02960         case kFillGradient:
02961             colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
02962             blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
02963             blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
02964             break;
02965         }
02966     }
02967 }
02968 
02970 
02972 template<typename PixelType>
02973 void VectorRendererSpec<PixelType>::
02974 drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
02975     // Do not draw anything for empty rects.
02976     if (size <= 0) {
02977         return;
02978     }
02979 
02980     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
02981 
02982     if (!inverted) {
02983         pitch = -pitch;
02984         y1 += size;
02985     }
02986 
02987     int gradient_h = 0;
02988     PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
02989     PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1);
02990     int x2 = x1 + size / 2;
02991     int y2 = y1 + size;
02992     int deltaX = abs(x2 - x1);
02993     int deltaY = abs(y2 - y1);
02994     int signX = x1 < x2 ? 1 : -1;
02995     int signY = y1 < y2 ? 1 : -1;
02996     int error = deltaX - deltaY;
02997 
02998     colorFill<PixelType>(ptr_right, ptr_left, color);
02999 
03000     while (1) {
03001         switch (fill_m) {
03002         case kFillDisabled:
03003             *ptr_left = *ptr_right = color;
03004             break;
03005         case kFillForeground:
03006         case kFillBackground:
03007             colorFill<PixelType>(ptr_right, ptr_left, color);
03008             break;
03009         case kFillGradient:
03010             colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, size));
03011             break;
03012         }
03013 
03014         if (x1 == x2 && y1 == y2)
03015             break;
03016 
03017         int error2 = error * 2;
03018 
03019         if (error2 > -deltaY) {
03020             error -= deltaY;
03021             x1 += signX;
03022             ptr_right += signX;
03023             ptr_left += -signX;
03024         }
03025 
03026         if (error2 < deltaX) {
03027             error += deltaX;
03028             y1 += signY;
03029             ptr_right += pitch;
03030             ptr_left += pitch;
03031         }
03032     }
03033 }
03034 
03036 template<typename PixelType>
03037 void VectorRendererSpec<PixelType>::
03038 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) {
03039     int f, ddF_x, ddF_y;
03040     int x, y, px, py;
03041     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03042     int sw = 0, sp = 0, hp = h * pitch;
03043 
03044     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03045     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03046     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03047     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03048     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03049 
03050     int real_radius = r;
03051     int short_h = h - (2 * r) + 2;
03052 
03053     PixelType color1 = color;
03054     PixelType color2 = color;
03055 
03056     while (sw++ < Base::_strokeWidth) {
03057         blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top
03058         blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom
03059         sp += pitch;
03060 
03061         BE_RESET();
03062         r--;
03063 
03064         int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
03065         int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
03066         int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
03067         int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
03068 
03069         // Avoid blending the last pixels twice, since we have an alpha
03070         while (x++ < (y - 2)) {
03071             BE_ALGORITHM();
03072 
03073             if (x < _clippingArea.left || x > _clippingArea.right) continue;
03074             if (y < _clippingArea.top || y > _clippingArea.bottom) continue;
03075 
03076             BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
03077             BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
03078             BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
03079             BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)));
03080 
03081             BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)));
03082             BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)));
03083             BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)));
03084             BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)));
03085 
03086             if (Base::_strokeWidth > 1) {
03087                 BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py);
03088                 BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py);
03089             }
03090         }
03091     }
03092 
03093     ptr_fill += pitch * real_radius;
03094     while (short_h--) {
03095         blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l); // left
03096         blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r); // right
03097         ptr_fill += pitch;
03098     }
03099 }
03100 
03101 template<typename PixelType>
03102 void VectorRendererSpec<PixelType>::
03103 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) {
03104     int f, ddF_x, ddF_y;
03105     int x, y, px, py;
03106     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03107     int sw = 0, sp = 0, hp = h * pitch;
03108 
03109     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03110     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03111     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03112     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03113     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03114 
03115     int real_radius = r;
03116     int short_h = h - (2 * r) + 2;
03117 
03118     PixelType color1 = color;
03119     PixelType color2 = color;
03120 
03121     while (sw++ < Base::_strokeWidth) {
03122         blendFillClip(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t,
03123             x1 + r, y1 + sp/pitch); // top
03124         blendFillClip(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b,
03125             x1 + r, y1 + (hp - sp)/ pitch); // bottom
03126         sp += pitch;
03127 
03128         BE_RESET();
03129         r--;
03130 
03131         int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
03132         int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
03133         int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
03134         int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
03135 
03136         // Avoid blending the last pixels twice, since we have an alpha
03137         while (x++ < (y - 2)) {
03138             BE_ALGORITHM();
03139 
03140             BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)), x1 + w - r, y1 + r);
03141             BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)), x1 + w - r, y1 + h - r);
03142             BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)), x1 + r, y1 + h - r);
03143             BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)), x1 + r, y1 + r);
03144 
03145             BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)), x1 + w - r, y1 + r);
03146             BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)), x1 + w - r, y1 + h - r);
03147             BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)), x1 + r, y1 + h - r);
03148             BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)), x1 + r, y1 + r);
03149 
03150             if (Base::_strokeWidth > 1) {
03151                 BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py,
03152                     x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
03153                 BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py,
03154                     x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
03155             }
03156         }
03157     }
03158 
03159     ptr_fill += pitch * real_radius;
03160     while (short_h--) {
03161         blendFillClip(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l,
03162             x1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // left
03163         blendFillClip(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r,
03164             x1 + w - Base::_strokeWidth + 1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // right
03165         ptr_fill += pitch;
03166     }
03167 }
03168 
03169 template<typename PixelType>
03170 void VectorRendererSpec<PixelType>::
03171 drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03172     // Do not draw empty space rounded squares.
03173     if (w <= 0 || h <= 0) {
03174         return;
03175     }
03176 
03177     int f, ddF_x, ddF_y;
03178     int x, y, px, py;
03179     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03180 
03181     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03182     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03183     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03184     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03185     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03186 
03187     int real_radius = r;
03188     int short_h = h - (2 * r) + 2;
03189     int long_h = h;
03190 
03191     BE_RESET();
03192 
03193     PixelType color1 = color;
03194 
03195     if (fill_m == kFillGradient) {
03196         PixelType color2, color3, color4;
03197         precalcGradient(long_h);
03198 
03199         while (x++ < y) {
03200             BE_ALGORITHM();
03201 
03202             color1 = calcGradient(real_radius - x, long_h);
03203             color2 = calcGradient(real_radius - y, long_h);
03204             color3 = calcGradient(long_h - r + x, long_h);
03205             color4 = calcGradient(long_h - r + y, long_h);
03206 
03207             gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y);
03208             gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x);
03209 
03210             gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y);
03211             gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x);
03212 
03213             BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
03214         }
03215     } else {
03216         while (x++ < y) {
03217             BE_ALGORITHM();
03218 
03219             colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1);
03220             colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1);
03221 
03222             colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1);
03223             colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1);
03224 
03225             // do not remove - messes up the drawing at lower resolutions
03226             BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
03227         }
03228     }
03229 
03230     ptr_fill += pitch * r;
03231     while (short_h--) {
03232         if (fill_m == kFillGradient) {
03233             gradientFill(ptr_fill, w + 1, x1, real_radius++);
03234         } else {
03235             colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color1);
03236         }
03237         ptr_fill += pitch;
03238     }
03239 }
03240 
03241 template<typename PixelType>
03242 void VectorRendererSpec<PixelType>::
03243 drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03244     // Do not draw empty space rounded squares.
03245     if (w <= 0 || h <= 0) {
03246         return;
03247     }
03248 
03249     int f, ddF_x, ddF_y;
03250     int x, y, px, py;
03251     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03252 
03253     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03254     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03255     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03256     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03257     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03258 
03259     int real_radius = r;
03260     int short_h = h - (2 * r) + 2;
03261     int long_h = h;
03262 
03263     BE_RESET();
03264 
03265     PixelType color1 = color;
03266 
03267     if (fill_m == kFillGradient) {
03268         PixelType color2, color3, color4;
03269         precalcGradient(long_h);
03270 
03271         while (x++ < y) {
03272             BE_ALGORITHM();
03273 
03274             color1 = calcGradient(real_radius - x, long_h);
03275             color2 = calcGradient(real_radius - y, long_h);
03276             color3 = calcGradient(long_h - r + x, long_h);
03277             color4 = calcGradient(long_h - r + y, long_h);
03278 
03279             //TL = (x1 + r, y1 + r)
03280             gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y,
03281                 x1 + r - x, y1 + r - y);
03282             gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x,
03283                 x1 + r - y, y1 + r - x);
03284 
03285             //BL = (x1 + r, y1 + h - r)
03286             gradientFillClip(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y,
03287                 x1 + r - x, y1 + h - r + y);
03288             gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x,
03289                 x1 + r - y, y1 + h - r + x);
03290 
03291             BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
03292                 x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
03293         }
03294     } else {
03295         while (x++ < y) {
03296             BE_ALGORITHM();
03297 
03298             colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1,
03299                 x1 + r - x, y1 + r - y, _clippingArea);
03300             colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1,
03301                 x1 + r - y, y1 + r - x, _clippingArea);
03302 
03303             colorFillClip<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1,
03304                 x1 + r - x, y1 + h - r + y, _clippingArea);
03305             colorFillClip<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1,
03306                 x1 + r - y, y1 + h - r + x, _clippingArea);
03307 
03308             // do not remove - messes up the drawing at lower resolutions
03309             BE_DRAWCIRCLE_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
03310                 x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
03311         }
03312     }
03313 
03314     ptr_fill += pitch * r;
03315     int short_h_orig = short_h;
03316     while (short_h--) {
03317         if (fill_m == kFillGradient) {
03318             gradientFillClip(ptr_fill, w + 1, x1, real_radius++, x1, y1 + r + short_h_orig - short_h -1);
03319         } else {
03320             colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color1, x1, y1 + r + short_h_orig - short_h - 1, _clippingArea);
03321         }
03322         ptr_fill += pitch;
03323     }
03324 }
03325 
03326 template<typename PixelType>
03327 void VectorRendererSpec<PixelType>::
03328 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03329     const uint8 borderAlpha_t = 0;
03330     const uint8 borderAlpha_r = 127;
03331     const uint8 borderAlpha_b = 255;
03332     const uint8 borderAlpha_l = 63;
03333 
03334     const uint8 bevelAlpha_t = 255;
03335     const uint8 bevelAlpha_r = 31;
03336     const uint8 bevelAlpha_b = 0;
03337     const uint8 bevelAlpha_l = 127;
03338 
03339     // If only border is visible
03340     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
03341         if (fill_m == Base::kFillBackground)
03342             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m);
03343         else
03344             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
03345     }
03346 
03347     if (Base::_strokeWidth) {
03348         if (r != 0 && _bevel > 0) {
03349             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
03350             drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
03351         } else {
03352             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
03353         }
03354     }
03355 }
03356 
03357 template<typename PixelType>
03358 void VectorRendererSpec<PixelType>::
03359 drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
03360     const uint8 borderAlpha_t = 0;
03361     const uint8 borderAlpha_r = 127;
03362     const uint8 borderAlpha_b = 255;
03363     const uint8 borderAlpha_l = 63;
03364 
03365     const uint8 bevelAlpha_t = 255;
03366     const uint8 bevelAlpha_r = 31;
03367     const uint8 bevelAlpha_b = 0;
03368     const uint8 bevelAlpha_l = 127;
03369 
03370     // If only border is visible
03371     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
03372         if (fill_m == Base::kFillBackground)
03373             drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, _bgColor, fill_m);
03374         else
03375             drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m);
03376     }
03377 
03378     //I expect these to work fine with clipping:
03379     if (Base::_strokeWidth) {
03380         if (r != 0 && _bevel > 0) {
03381             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
03382             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
03383         } else {
03384             drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
03385         }
03386     }
03387 }
03388 
03390 template<typename PixelType>
03391 void VectorRendererSpec<PixelType>::
03392 drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
03393     int f, ddF_x, ddF_y;
03394     int x, y, px, py, sw = 0;
03395     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03396     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03397 
03398     if (fill_m == kFillDisabled) {
03399         while (sw++ < Base::_strokeWidth) {
03400             BE_RESET();
03401             r--;
03402 
03403             *(ptr + y) = color;
03404             *(ptr - y) = color;
03405             *(ptr + py) = color;
03406             *(ptr - py) = color;
03407 
03408             while (x++ < y) {
03409                 BE_ALGORITHM();
03410                 BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py);
03411 
03412                 if (Base::_strokeWidth > 1) {
03413                     BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py);
03414                     BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py);
03415                 }
03416             }
03417         }
03418     } else {
03419         colorFill<PixelType>(ptr - r, ptr + r, color);
03420         BE_RESET();
03421 
03422         while (x++ < y) {
03423             BE_ALGORITHM();
03424             colorFill<PixelType>(ptr - x + py, ptr + x + py, color);
03425             colorFill<PixelType>(ptr - x - py, ptr + x - py, color);
03426             colorFill<PixelType>(ptr - y + px, ptr + y + px, color);
03427             colorFill<PixelType>(ptr - y - px, ptr + y - px, color);
03428         }
03429     }
03430 }
03431 
03432 
03433 template<typename PixelType>
03434 void VectorRendererSpec<PixelType>::
03435 drawCircleAlgClip(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
03436     int f, ddF_x, ddF_y;
03437     int x, y, px, py, sw = 0;
03438     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03439     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03440 
03441     if (fill_m == kFillDisabled) {
03442         while (sw++ < Base::_strokeWidth) {
03443             BE_RESET();
03444             r--;
03445 
03446             if (IS_IN_CLIP(x1 + y, y1)) *(ptr + y) = color;
03447             if (IS_IN_CLIP(x1 - y, y1)) *(ptr - y) = color;
03448             if (IS_IN_CLIP(x1, y1 + y)) *(ptr + py) = color;
03449             if (IS_IN_CLIP(x1, y1 - y)) *(ptr - py) = color;
03450 
03451             while (x++ < y) {
03452                 BE_ALGORITHM();
03453                 BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
03454 
03455                 if (Base::_strokeWidth > 1) {
03456                     BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x - 1, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
03457                     BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px - pitch, py, x1, y1, x1, y1, x1, y1, x1, y1);
03458                 }
03459             }
03460         }
03461     } else {
03462         colorFillClip<PixelType>(ptr - r, ptr + r, color, x1 - r, y1 + r, _clippingArea);
03463         BE_RESET();
03464 
03465         while (x++ < y) {
03466             BE_ALGORITHM();
03467             colorFillClip<PixelType>(ptr - x + py, ptr + x + py, color, x1 - x, y1 + y, _clippingArea);
03468             colorFillClip<PixelType>(ptr - x - py, ptr + x - py, color, x1 - x, y1 - y, _clippingArea);
03469             colorFillClip<PixelType>(ptr - y + px, ptr + y + px, color, x1 - y, y1 + x, _clippingArea);
03470             colorFillClip<PixelType>(ptr - y - px, ptr + y - px, color, x1 - y, y1 - x, _clippingArea);
03471         }
03472     }
03473 }
03474 
03475 
03476 /********************************************************************
03477  ********************************************************************
03478  * SHADOW drawing algorithms - VectorRendererSpec *******************
03479  ********************************************************************
03480  ********************************************************************/
03481 template<typename PixelType>
03482 void VectorRendererSpec<PixelType>::
03483 drawSquareShadow(int x, int y, int w, int h, int offset) {
03484     // Do nothing for empty rects or no shadow offset.
03485     if (w <= 0 || h <= 0 || offset <= 0) {
03486         return;
03487     }
03488 
03489     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
03490     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03491     int i, j;
03492 
03493     i = h - offset;
03494 
03495     while (i--) {
03496         j = offset;
03497         while (j--)
03498             blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset);
03499         ptr += pitch;
03500     }
03501 
03502     ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
03503 
03504     while (i++ < offset) {
03505         j = w - offset;
03506         while (j--)
03507             blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset);
03508         ptr += pitch;
03509     }
03510 
03511     ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
03512 
03513     i = 0;
03514     while (i++ < offset) {
03515         j = offset - 1;
03516         while (j--)
03517             blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset));
03518         ptr += pitch;
03519     }
03520 }
03521 
03522 template<typename PixelType>
03523 void VectorRendererSpec<PixelType>::
03524 drawSquareShadowClip(int x, int y, int w, int h, int offset) {
03525     // Do nothing for empty rects or no shadow offset.
03526     if (w <= 0 || h <= 0 || offset <= 0) {
03527         return;
03528     }
03529 
03530     PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
03531     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03532     int i, j, ptr_x = x+w-1, ptr_y = y+offset;
03533 
03534     i = h - offset;
03535 
03536     while (i--) {
03537         j = offset;
03538         while (j--)
03539             blendPixelPtrClip(ptr + j, 0, ((offset - j) << 8) / offset, ptr_x + j, ptr_y);
03540         ptr += pitch;
03541         ++ptr_y;
03542     }
03543 
03544     ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
03545     ptr_x = x + offset;
03546     ptr_y = y + h - 1;
03547 
03548     while (i++ < offset) {
03549         j = w - offset;
03550         while (j--)
03551             blendPixelPtrClip(ptr + j, 0, ((offset - i) << 8) / offset, ptr_x + j, ptr_y);
03552         ptr += pitch;
03553         ++ptr_y;
03554     }
03555 
03556     ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
03557     ptr_x = x + w;
03558     ptr_y = y + h;
03559 
03560     i = 0;
03561     while (i++ < offset) {
03562         j = offset - 1;
03563         while (j--)
03564             blendPixelPtrClip(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset), ptr_x + j, ptr_y);
03565         ptr += pitch;
03566         ++ptr_y;
03567     }
03568 }
03569 
03570 template<typename PixelType>
03571 void VectorRendererSpec<PixelType>::
03572 drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
03573     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03574 
03575     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
03576     uint8 expFactor = 3;
03577     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
03578 
03579     // These constants ensure a border of 2px on the left and of each rounded square
03580     Common::Rect shadowRect(w + offset + 2, h + offset + 1);
03581     shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
03582 
03583     // The rounded rectangle drawn on top of this shadow is guaranteed
03584     // to occlude entirely the following rect with a non-transparent color.
03585     // As an optimization, we don't draw the shadow inside of it.
03586     Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
03587     occludingRect.top    += r;
03588     occludingRect.bottom -= r;
03589 
03590     // Soft shadows are constructed by drawing increasingly
03591     // darker and smaller rectangles on top of each other.
03592     for (int i = offset; i >= 0; i--) {
03593         int f, ddF_x, ddF_y;
03594         int x, y, px, py;
03595 
03596         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.top + r);
03597         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
03598         PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.bottom - r);
03599         PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
03600 
03601         PixelType color = _format.RGBToColor(0, 0, 0);
03602 
03603         BE_RESET();
03604 
03605         // HACK: As we are drawing circles exploiting 8-axis symmetry,
03606         // there are 4 pixels on each circle which are drawn twice.
03607         // this is ok on filled circles, but when blending on surfaces,
03608         // we cannot let it blend twice. awful.
03609         uint32 hb = 0;
03610 
03611         // Draw the top and bottom parts of the shadow. Those parts have rounded corners.
03612         while (x++ < y) {
03613             BE_ALGORITHM();
03614 
03615             if (((1 << x) & hb) == 0) {
03616                 blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
03617                 blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
03618                 hb |= (1 << x);
03619             }
03620 
03621             if (((1 << y) & hb) == 0) {
03622                 blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
03623                 blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
03624                 hb |= (1 << y);
03625             }
03626         }
03627 
03628         // Draw the middle part of the shadow. This part is a rectangle with regular corners.
03629         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
03630         for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
03631 
03632             if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
03633                 if (shadowRect.left < occludingRect.left) {
03634                     blendFill(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha);
03635                 }
03636                 if (occludingRect.right < shadowRect.right + 1) {
03637                     blendFill(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
03638                 }
03639             } else {
03640                 blendFill(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha);
03641             }
03642 
03643             ptr_fill += pitch;
03644         }
03645 
03646         // Make shadow smaller each iteration
03647         shadowRect.grow(-1);
03648 
03649         if (_shadowFillMode == kShadowExponential)
03650             // Multiply with expfactor
03651             alpha = (alpha * (expFactor << 8)) >> 9;
03652     }
03653 }
03654 
03655 template<typename PixelType>
03656 void VectorRendererSpec<PixelType>::
03657 drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
03658     int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
03659 
03660     // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
03661     uint8 expFactor = 3;
03662     uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
03663 
03664     // These constants ensure a border of 2px on the left and of each rounded square
03665     Common::Rect shadowRect(w + offset + 2, h + offset + 1);
03666     shadowRect.translate((x1 > 2) ? x1 - 2 : x1, y1);
03667 
03668     // The rounded rectangle drawn on top of this shadow is guaranteed
03669     // to occlude entirely the following rect with a non-transparent color.
03670     // As an optimization, we don't draw the shadow inside of it.
03671     Common::Rect occludingRect(x1, y1, x1 + w, y1 + h);
03672     occludingRect.top    += r;
03673     occludingRect.bottom -= r;
03674 
03675     // Soft shadows are constructed by drawing increasingly
03676     // darker and smaller rectangles on top of each other.
03677     for (int i = offset; i >= 0; i--) {
03678         int f, ddF_x, ddF_y;
03679         int x, y, px, py;
03680 
03681         PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.top + r);
03682         PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.top + r);
03683         PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.left  + r, shadowRect.bottom - r);
03684         PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(shadowRect.right - r, shadowRect.bottom - r);
03685 
03686         PixelType color = _format.RGBToColor(0, 0, 0);
03687 
03688         BE_RESET();
03689 
03690         // HACK: As we are drawing circles exploiting 8-axis symmetry,
03691         // there are 4 pixels on each circle which are drawn twice.
03692         // this is ok on filled circles, but when blending on surfaces,
03693         // we cannot let it blend twice. awful.
03694         uint32 hb = 0;
03695 
03696         while (x++ < y) {
03697             BE_ALGORITHM();
03698 
03699             if (((1 << x) & hb) == 0) {
03700                 blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
03701                               shadowRect.left + r - y, shadowRect.top + r - x);
03702                 blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
03703                               shadowRect.left + r - y, shadowRect.bottom - r + x);
03704 
03705                 hb |= (1 << x);
03706             }
03707 
03708             if (((1 << y) & hb) == 0) {
03709                 blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha,
03710                               shadowRect.left + r - x, shadowRect.top + r - y);
03711                 blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha,
03712                               shadowRect.left + r - x, shadowRect.bottom - r + y);
03713 
03714                 hb |= (1 << y);
03715             }
03716         }
03717 
03718         // Draw the middle part of the shadow. This part is a rectangle with regular corners.
03719         PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(0, shadowRect.top + r);
03720         for (int y2 = shadowRect.top + r; y2 < shadowRect.bottom - r + 1; y2++) {
03721 
03722             if (occludingRect.top <= y2 && y2 < occludingRect.bottom) {
03723                 if (shadowRect.left < occludingRect.left) {
03724                     blendFillClip(ptr_fill + shadowRect.left, ptr_fill + occludingRect.left, color, (uint8)alpha,
03725                                   shadowRect.left, y2);
03726                 }
03727                 if (occludingRect.right < shadowRect.right + 1) {
03728                     blendFillClip(ptr_fill + occludingRect.right, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
03729                                   occludingRect.right, y2);
03730                 }
03731             } else {
03732                 blendFillClip(ptr_fill + shadowRect.left, ptr_fill + shadowRect.right + 1, color, (uint8)alpha,
03733                               shadowRect.left, y2);
03734             }
03735 
03736             ptr_fill += pitch;
03737         }
03738 
03739         // Make shadow smaller each iteration
03740         shadowRect.grow(-1);
03741 
03742         if (_shadowFillMode == kShadowExponential)
03743             // Multiply with expfactor
03744             alpha = (alpha * (expFactor << 8)) >> 9;
03745     }
03746 }
03747 
03748 /******************************************************************************/
03749 
03750 
03751 
03752 #ifndef DISABLE_FANCY_THEMES
03753 
03754 /********************************************************************
03755  * ANTIALIASED PRIMITIVES drawing algorithms - VectorRendererAA
03756  ********************************************************************/
03758 template<typename PixelType>
03759 void VectorRendererAA<PixelType>::
03760 drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
03761     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03762     int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03763     int xdir = (x2 > x1) ? 1 : -1;
03764     uint16 error_tmp, error_acc, gradient;
03765     uint8 alpha;
03766 
03767     *ptr = (PixelType)color;
03768 
03769     if (dx > dy) {
03770         gradient = (dy << 16) / dx;
03771         error_acc = 0;
03772 
03773         while (--dx) {
03774             error_tmp = error_acc;
03775             error_acc += gradient;
03776 
03777             if (error_acc <= error_tmp)
03778                 ptr += pitch;
03779 
03780             ptr += xdir;
03781             alpha = (error_acc >> 8);
03782 
03783             this->blendPixelPtr(ptr, color, ~alpha);
03784             this->blendPixelPtr(ptr + pitch, color, alpha);
03785         }
03786     } else if (dy != 0) {
03787         gradient = (dx << 16) / dy;
03788         error_acc = 0;
03789 
03790         while (--dy) {
03791             error_tmp = error_acc;
03792             error_acc += gradient;
03793 
03794             if (error_acc <= error_tmp)
03795                 ptr += xdir;
03796 
03797             ptr += pitch;
03798             alpha = (error_acc >> 8);
03799 
03800             this->blendPixelPtr(ptr, color, ~alpha);
03801             this->blendPixelPtr(ptr + xdir, color, alpha);
03802         }
03803     }
03804 
03805     Base::putPixel(x2, y2, color);
03806 }
03807 
03809 template<typename PixelType>
03810 void VectorRendererAA<PixelType>::
03811 drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
03812     // Don't draw anything for empty rects.
03813     if (w <= 0 || h <= 0) {
03814         return;
03815     }
03816 
03817     int x, y, px, py;
03818     int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03819     int sw = 0, sp = 0, hp = 0;
03820 
03821     frac_t T = 0, oldT;
03822     uint8 a1, a2;
03823     uint32 rsq = r*r;
03824 
03825     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03826     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03827     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03828 
03829     int real_radius = r;
03830 
03831     if (fill_m == Base::kFillDisabled) {
03832         color = 0;
03833         while (sw++ < Base::_strokeWidth) {
03834             colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color);
03835             colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color);
03836             sp += pitch;
03837 
03838             x = r - (sw - 1);
03839             y = 0;
03840             T = 0;
03841             px = pitch * x;
03842             py = 0;
03843 
03844 
03845             while (x > y++) {
03846                 WU_ALGORITHM();
03847 
03848                 // sw == 1: outside, sw = _strokeWidth: inside
03849                 if (sw != Base::_strokeWidth)
03850                     a2 = 255;
03851 
03852                 // inner arc
03853                 WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a2);
03854 
03855                 if (sw == 1) // outer arc
03856                     WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py, a1);
03857             }
03858         }
03859 
03860         int short_h = h - r + 2;
03861 
03862         ptr_fill += pitch * real_radius;
03863         while (short_h--) {
03864             colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color);
03865             colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color);
03866             ptr_fill += pitch;
03867         }
03868 
03869         if (baseLeft) {
03870             sw = 0;
03871             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
03872             while (sw++ < Base::_strokeWidth) {
03873                 colorFill<PixelType>(ptr_fill - baseLeft, ptr_fill, color);
03874                 ptr_fill += pitch;
03875             }
03876         }
03877 
03878         if (baseRight) {
03879             sw = 0;
03880             ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
03881             while (sw++ < Base::_strokeWidth) {
03882                 colorFill<PixelType>(ptr_fill, ptr_fill + baseRight, color);
03883                 ptr_fill += pitch;
03884             }
03885         }
03886     } else {
03887         PixelType color1, color2;
03888         color1 = color2 = color;
03889 
03890         int long_h = h;
03891         int short_h = h - real_radius + 2;
03892         x = real_radius;
03893         y = 0;
03894         T = 0;
03895         px = pitch * x;
03896         py = 0;
03897 
03898         Base::precalcGradient(long_h);
03899 
03900         while (x > y++) {
03901             WU_ALGORITHM();
03902 
03903             if (fill_m == Base::kFillGradient) {
03904                 color1 = Base::calcGradient(real_radius - x, long_h);
03905                 color2 = Base::calcGradient(real_radius - y, long_h);
03906 
03907                 Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, real_radius - y);
03908 
03909                 // Only fill each horizontal line once (or we destroy
03910                 // the gradient effect at the edges)
03911                 if (T < oldT || y == 1)
03912                     Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, real_radius - x);
03913 
03914                 WU_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py, a1, Base::blendPixelPtr);
03915             } else {
03916                 colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
03917                 if (T < oldT || y == 1)
03918                     colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
03919 
03920                 WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a1);
03921             }
03922         }
03923 
03924         ptr_fill += pitch * r;
03925         while (short_h--) {
03926             if (fill_m == Base::kFillGradient) {
03927                 Base::gradientFill(ptr_fill, w + 1, x1, real_radius++);
03928             } else {
03929                 colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
03930             }
03931             ptr_fill += pitch;
03932         }
03933     }
03934 }
03935 
03936 
03938 template<typename PixelType>
03939 void VectorRendererAA<PixelType>::
03940 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) {
03941     int x, y;
03942     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
03943     int px, py;
03944 
03945     uint32 rsq = r*r;
03946     frac_t T = 0, oldT;
03947     uint8 a1, a2;
03948 
03949     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
03950     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
03951     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
03952     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
03953     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
03954 
03955     int sw = 0, sp = 0;
03956     int short_h = h - 2 * r;
03957     int hp = h * pitch;
03958 
03959     int strokeWidth = Base::_strokeWidth;
03960 
03961     while (sw++ < strokeWidth) {
03962         this->blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, alpha_b); // bottom
03963         this->blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, alpha_t); // top
03964 
03965         sp += pitch;
03966 
03967         x = r - (sw - 1);
03968         y = 0;
03969         T = 0;
03970         px = pitch * x;
03971         py = 0;
03972 
03973         int alphaStep_tr = ((alpha_t - alpha_r) / (x + 1));
03974         int alphaStep_br = ((alpha_r - alpha_b) / (x + 1));
03975         int alphaStep_bl = ((alpha_b - alpha_l) / (x + 1));
03976         int alphaStep_tl = ((alpha_l - alpha_t) / (x + 1));
03977 
03978         while (x > y++) {
03979             WU_ALGORITHM();
03980 
03981             // sw == 1: outside, sw = _strokeWidth: inside
03982             // We always draw the outer edge AAed, but the inner edge
03983             // only when the inside isn't filled
03984             if (sw != strokeWidth || fill_m != Base::kFillDisabled)
03985                 a2 = 255;
03986 
03987                 // inner arc
03988                 WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16));
03989                 WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a2) >> 16));
03990                 WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a2) >> 16));
03991                 WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a2) >> 16));
03992 
03993                 WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16));
03994                 WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a2) >> 16));
03995                 WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a2) >> 16));
03996                 WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a2) >> 16));
03997 
03998                 // outer arc
03999                 if (sw == 1) {
04000                     WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a1) >> 16));
04001                     WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a1) >> 16));
04002                     WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a1) >> 16));
04003                     WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a1) >> 16));
04004 
04005                     WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16));
04006                     WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a1) >> 16));
04007                     WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a1) >> 16));
04008                     WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a1) >> 16));
04009                 }
04010             }
04011 
04012         ptr_fill += pitch * r;
04013 
04014         while (short_h-- >= -2) {
04015             this->blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color, alpha_l); // left
04016             this->blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, alpha_r); // right
04017             ptr_fill += pitch;
04018         }
04019     }
04020 }
04021 
04022 template<typename PixelType>
04023 void VectorRendererAA<PixelType>::
04024 drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
04025     w -= 2*Base::_strokeWidth;
04026     h -= 2*Base::_strokeWidth;
04027 
04028     // Do not draw empty space rounded squares.
04029     if (w <= 0 || h <= 0) {
04030         return;
04031     }
04032 
04033     int x, y;
04034     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
04035     int px, py;
04036 
04037     uint32 rsq = r*r;
04038     frac_t T = 0, oldT;
04039     uint8 a1, a2;
04040 
04041     r -= Base::_strokeWidth;
04042     x1 += Base::_strokeWidth;
04043     y1 += Base::_strokeWidth;
04044     rsq = r*r;
04045 
04046     PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);
04047     PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
04048     PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
04049     PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
04050     PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
04051 
04052     int short_h = h - 2 * r;
04053     x = r;
04054     y = 0;
04055     T = 0;
04056     px = pitch * x;
04057     py = 0;
04058 
04059     if (fill_m == Base::kFillGradient) {
04060 
04061         Base::precalcGradient(h);
04062 
04063         PixelType color1, color2, color3, color4;
04064         while (x > y++) {
04065             WU_ALGORITHM();
04066 
04067             color1 = Base::calcGradient(r - x, h);
04068             color2 = Base::calcGradient(r - y, h);
04069             color3 = Base::calcGradient(h - r + x, h);
04070             color4 = Base::calcGradient(h - r + y, h);
04071 
04072             Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y);
04073 
04074             // Only fill each horizontal line once (or we destroy
04075             // the gradient effect at the edges)
04076             if (T < oldT || y == 1)
04077                 Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x);
04078 
04079             Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y);
04080 
04081             // Only fill each horizontal line once (or we destroy
04082             // the gradient effect at the edges)
04083             if (T < oldT || y == 1)
04084                 Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x);
04085 
04086             // This shape is used for dialog backgrounds.
04087             // If we're drawing on top of an empty overlay background,
04088             // and the overlay supports alpha, we have to do AA by
04089             // setting the dest alpha channel, instead of blending with
04090             // dest color channels.
04091             if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha))
04092                 WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr);
04093             else
04094                 WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr);
04095         }
04096 
04097         ptr_fill += pitch * r;
04098         while (short_h-- >= 0) {
04099             Base::gradientFill(ptr_fill, w + 1, x1, r++);
04100             ptr_fill += pitch;
04101         }
04102 
04103     } else {
04104 
04105         while (x > 1 + y++) {
04106             WU_ALGORITHM();
04107 
04108             colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color);
04109             if (T < oldT || y == 1)
04110                 colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color);
04111 
04112             colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color);
04113             if (T < oldT || y == 1)
04114                 colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color);
04115 
04116             WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
04117         }
04118 
04119         ptr_fill += pitch * r;
04120         while (short_h-- >= 0) {
04121             colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color);
04122             ptr_fill += pitch;
04123         }
04124     }
04125 }
04126 
04127 template<typename PixelType>
04128 void VectorRendererAA<PixelType>::
04129 drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
04130     const uint8 borderAlpha_t = 0;
04131     const uint8 borderAlpha_r = 127;
04132     const uint8 borderAlpha_b = 255;
04133     const uint8 borderAlpha_l = 63;
04134 
04135     const uint8 bevelAlpha_t = 255;
04136     const uint8 bevelAlpha_r = 31;
04137     const uint8 bevelAlpha_b = 0;
04138     const uint8 bevelAlpha_l = 127;
04139 
04140     if (Base::_strokeWidth) {
04141         if (r != 0 && Base::_bevel > 0) {
04142             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
04143             drawBorderRoundedSquareAlg(x1, y1, r, w, h, Base::_bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
04144         } else {
04145             drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
04146         }
04147     }
04148 
04149     // If only border is visible
04150     if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
04151         if (fill_m == Base::kFillBackground)
04152             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, Base::_bgColor, fill_m);
04153         else
04154             drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m);
04155     }
04156 }
04157 
04159 template<typename PixelType>
04160 void VectorRendererAA<PixelType>::
04161 drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
04162     int x, y, sw = 0;
04163     const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
04164     int px, py;
04165 
04166     uint32 rsq = r*r;
04167     frac_t T = 0, oldT;
04168     uint8 a1, a2;
04169 
04170     PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
04171 
04172     if (fill_m == VectorRenderer::kFillDisabled) {
04173         while (sw++ < Base::_strokeWidth) {
04174             x = r - (sw - 1);
04175             y = 0;
04176             T = 0;
04177             px = pitch * x;
04178             py = 0;
04179 
04180             *(ptr + x) = (PixelType)color;
04181             *(ptr - x) = (PixelType)color;
04182             *(ptr + px) = (PixelType)color;
04183             *(ptr - px) = (PixelType)color;
04184 
04185             while (x > y++) {
04186                 WU_ALGORITHM();
04187 
04188                 if (sw != 1 && sw != Base::_strokeWidth)
04189                     a2 = a1 = 255;
04190 
04191                 WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - pitch), py, a2);
04192                 WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1);
04193             }
04194         }
04195     } else {
04196         colorFill<PixelType>(ptr - r, ptr + r + 1, color);
04197         x = r;
04198         y = 0;
04199         T = 0;
04200         px = pitch * x;
04201         py = 0;
04202 
04203         while (x > y++) {
04204             WU_ALGORITHM();
04205 
04206             colorFill<PixelType>(ptr - x + py, ptr + x + py, color);
04207             colorFill<PixelType>(ptr - x - py, ptr + x - py, color);
04208             colorFill<PixelType>(ptr - y + px, ptr + y + px, color);
04209             colorFill<PixelType>(ptr - y - px, ptr + y - px, color);
04210 
04211             WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1);
04212         }
04213     }
04214 }
04215 
04216 #endif
04217 
04218 }


Generated on Sat Mar 16 2019 05:02:01 for ResidualVM by doxygen 1.7.1
curved edge   curved edge