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


Generated on Sat Aug 1 2020 05:01:32 for ResidualVM by doxygen 1.7.1
curved edge   curved edge