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