00001
00043 #include "gfx.h"
00044 #include "gfx_p.h"
00045
00046 #include "cfg/cfg_gfx.h"
00047 #include <cfg/debug.h>
00048 #include <cfg/macros.h>
00049
00050
00051 #if !defined(CONFIG_GFX_CLIPPING) || (CONFIG_GFX_CLIPPING != 0 && CONFIG_GFX_CLIPPING != 1)
00052 #error CONFIG_GFX_CLIPPING must be defined to either 0 or 1
00053 #endif
00054 #if !defined(CONFIG_GFX_VCOORDS) || (CONFIG_GFX_VCOORDS != 0 && CONFIG_GFX_VCOORDS != 1)
00055 #error CONFIG_GFX_VCOORDS must be defined to either 0 or 1
00056 #endif
00057
00071 static void gfx_lineUnclipped(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
00072 {
00073 int x, y, e, len, adx, ady, signx, signy;
00074
00075 if (x2 > x1)
00076 {
00077
00078 signx = +1;
00079 adx = x2 - x1;
00080 }
00081 else
00082 {
00083
00084 signx = -1;
00085 adx = x1 - x2;
00086 }
00087
00088 if (y2 > y1)
00089 {
00090
00091 signy = +1;
00092 ady = y2 - y1;
00093 }
00094 else
00095 {
00096
00097 signy = -1;
00098 ady = y1 - y2;
00099 }
00100
00101 x = x1;
00102 y = y1;
00103
00104 if (adx > ady)
00105 {
00106
00107
00108 len = adx;
00109 e = -adx;
00110 while (len--)
00111 {
00112
00113 ASSERT((x >= 0) && (x < bm->width) && (y >= 0) && (y < bm->height));
00114 BM_PLOT(bm, x, y);
00115 x += signx;
00116 e += ady;
00117 if (e >= 0)
00118 {
00119 y += signy;
00120 e -= adx;
00121 }
00122 }
00123 }
00124 else
00125 {
00126
00127
00128 len = ady;
00129 e = -ady;
00130 while (len--)
00131 {
00132
00133 ASSERT ((x >= 0) && (x < bm->width) && (y >= 0) && (y < bm->height));
00134 BM_PLOT(bm, x, y);
00135 y += signy;
00136 e += adx;
00137 if (e >= 0)
00138 {
00139 x += signx;
00140 e -= ady;
00141 }
00142 }
00143 }
00144 }
00145
00146 #if CONFIG_GFX_CLIPPING
00147
00149 static int gfx_findRegion(int x, int y, Rect *cr)
00150 {
00151 int code = 0;
00152
00153 if (y >= cr->ymax)
00154 code |= 1;
00155 else if (y < cr->ymin)
00156 code |= 2;
00157
00158 if (x >= cr->xmax)
00159 code |= 4;
00160 else if (x < cr->xmin)
00161 code |= 8;
00162
00163 return code;
00164 }
00165
00166 #endif
00167
00184 void gfx_line(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
00185 {
00186 #if CONFIG_GFX_CLIPPING
00187 int clip1 = gfx_findRegion(x1, y1, &bm->cr);
00188 int clip2 = gfx_findRegion(x2, y2, &bm->cr);
00189
00190
00191 while (clip1 | clip2)
00192 {
00193
00194 if (clip1 & clip2)
00195 return;
00196
00197 int c = clip1 ? clip1 : clip2;
00198 int x, y;
00199
00200 if (c & 1)
00201 {
00202 x = x1 + (x2 - x1) * (bm->cr.ymax - y1) / (y2 - y1);
00203 y = bm->cr.ymax - 1;
00204 }
00205 else if (c & 2)
00206 {
00207 x = x1 + (x2 - x1) * (bm->cr.ymin - y1) / (y2 - y1);
00208 y = bm->cr.ymin;
00209 }
00210 else if (c & 4)
00211 {
00212 y = y1 + (y2 - y1) * (bm->cr.xmax - x1) / (x2 - x1);
00213 x = bm->cr.xmax - 1;
00214 }
00215 else
00216 {
00217 y = y1 + (y2 - y1) * (bm->cr.xmin - x1) / (x2 - x1);
00218 x = bm->cr.xmin;
00219 }
00220
00221 if (c == clip1)
00222 {
00223
00224
00225
00226
00227
00228 x1 = x;
00229 y1 = y;
00230 clip1 = gfx_findRegion(x1, y1, &bm->cr);
00231 }
00232 else
00233 {
00234 x2 = x;
00235 y2 = y;
00236 clip2 = gfx_findRegion(x2, y2, &bm->cr);
00237 }
00238 }
00239 #endif
00240
00241 gfx_lineUnclipped(bm, x1, y1, x2, y2);
00242 }
00243
00250 void gfx_moveTo(Bitmap *bm, coord_t x, coord_t y)
00251 {
00252 bm->penX = x;
00253 bm->penY = y;
00254 }
00255
00264 void gfx_lineTo(Bitmap *bm, coord_t x, coord_t y)
00265 {
00266 gfx_line(bm, bm->penX, bm->penY, x, y);
00267 gfx_moveTo(bm, x, y);
00268 }
00269
00270
00277 void gfx_rectDraw(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
00278 {
00279
00280 if (x1 > x2) SWAP(x1, x2);
00281 if (y1 > y2) SWAP(y1, y2);
00282
00283
00284 gfx_line(bm, x1, y1, x2-1, y1);
00285 gfx_line(bm, x2-1, y1, x2-1, y2-1);
00286 gfx_line(bm, x2-1, y2-1, x1, y2-1);
00287 gfx_line(bm, x1, y2-1, x1, y1);
00288 }
00289
00290
00298 void gfx_rectFillC(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2, uint8_t color)
00299 {
00300 coord_t x, y;
00301
00302
00303 if (x1 > x2) SWAP(x1, x2);
00304 if (y1 > y2) SWAP(y1, y2);
00305
00306 #if CONFIG_GFX_CLIPPING
00307
00308 if (x1 < bm->cr.xmin) x1 = bm->cr.xmin;
00309 if (x2 < bm->cr.xmin) x2 = bm->cr.xmin;
00310 if (x1 > bm->cr.xmax) x1 = bm->cr.xmax;
00311 if (x2 > bm->cr.xmax) x2 = bm->cr.xmax;
00312 if (y1 < bm->cr.ymin) y1 = bm->cr.ymin;
00313 if (y2 < bm->cr.ymin) y2 = bm->cr.ymin;
00314 if (y1 > bm->cr.ymax) y1 = bm->cr.ymax;
00315 if (y2 > bm->cr.ymax) y2 = bm->cr.ymax;
00316 #endif
00317
00318
00319 if (color)
00320 {
00321 for (x = x1; x < x2; x++)
00322 for (y = y1; y < y2; y++)
00323 BM_PLOT(bm, x, y);
00324 }
00325 else
00326 {
00327 for (x = x1; x < x2; x++)
00328 for (y = y1; y < y2; y++)
00329 BM_CLEAR(bm, x, y);
00330 }
00331 }
00332
00333
00341 void gfx_rectFill(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
00342 {
00343 gfx_rectFillC(bm, x1, y1, x2, y2, 0xFF);
00344 }
00345
00346
00354 void gfx_rectClear(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
00355 {
00356 gfx_rectFillC(bm, x1, y1, x2, y2, 0x00);
00357 }
00358
00359
00360 #if CONFIG_GFX_VCOORDS
00361
00365 void gfx_setViewRect(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2)
00366 {
00367 ASSERT(x1 != x2);
00368 ASSERT(y1 != y2);
00369
00370 bm->orgX = x1;
00371 bm->orgY = y1;
00372 bm->scaleX = (vcoord_t)(bm->cr.xmax - bm->cr.xmin - 1) / (vcoord_t)(x2 - x1);
00373 bm->scaleY = (vcoord_t)(bm->cr.ymax - bm->cr.ymin - 1) / (vcoord_t)(y2 - y1);
00374
00375
00376
00377
00378 }
00379
00380
00385 coord_t gfx_transformX(Bitmap *bm, vcoord_t x)
00386 {
00387 return bm->cr.xmin + (coord_t)((x - bm->orgX) * bm->scaleX);
00388 }
00389
00394 coord_t gfx_transformY(Bitmap *bm, vcoord_t y)
00395 {
00396 return bm->cr.ymin + (coord_t)((y - bm->orgY) * bm->scaleY);
00397 }
00398
00399
00403 void gfx_vline(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2)
00404 {
00405 gfx_line(bm,
00406 gfx_transformX(bm, x1), gfx_transformY(bm, y1),
00407 gfx_transformY(bm, x2), gfx_transformY(bm, y2));
00408 }
00409 #endif