Main Page | Data Structures | File List | Data Fields | Globals

line.c

00001 /*=========================================================================
00002 
00003 GFX - a small graphics library
00004 
00005 Copyright (C) 2004  Rafael de Oliveira Jannone
00006 
00007 This library is free software; you can redistribute it and/or
00008 modify it under the terms of the GNU Lesser General Public
00009 License as published by the Free Software Foundation; either
00010 version 2.1 of the License, or (at your option) any later version.
00011 
00012 This library 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 GNU
00015 Lesser General Public License for more details.
00016 
00017 You should have received a copy of the GNU Lesser General Public
00018 License along with this library; if not, write to the Free Software
00019 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 
00021 Contact the author:
00022         by e-mail : rafael AT jannone DOT org
00023         homepage  : http://jannone.org/gfxlib
00024         ICQ UIN   : 10115284
00025 
00026 See the License at http://www.gnu.org/copyleft/lesser.txt
00027 
00028 =========================================================================*/
00029 
00030 // LINE.C : line drawing functions
00031 
00032 /* === WARNING ==
00033 
00034         This is a work-in-progress, meaning that most of this code is unstable
00035         and it's subject to future changes.  Also, most of it is very hackish,
00036         not properly cleaned up nor tested.
00037 
00038    === WARNING == */
00039 
00040 #include "line.h"
00041 
00042 #define LINE_T_MEMBERS \
00043         int dinc1, dinc2;       \
00044         char xinc1, xinc2;      \
00045         char yinc1, yinc2;      \
00046         int numpixels;          \
00047         int d
00048 
00049 typedef struct {
00050         LINE_T_MEMBERS;
00051 } line_t;
00052 
00053 /*
00054         ok, what follows is quite an evil hack. lemme explain.
00055 
00056         we are using a kludge here, using local variables
00057         as if they were inside a struct.
00058         normally, you would do something like (line_t*)&dinc1 to
00059         accomplish that, however the HT compiler actually maps
00060         the variables backwards, meaning that we should point
00061         to the last local variable as if it were the first member
00062         of the struct.
00063 
00064         that's why we need REVERSE_LINE_T_MEMBERS and all this
00065         crap
00066 */
00067 
00068 #define LINE_T_FIRST    dinc1
00069 
00070 #define REVERSE_LINE_T_MEMBERS \
00071         int d;                  \
00072         int numpixels;          \
00073         char yinc2, yinc1;      \
00074         char xinc2, xinc1;      \
00075         int dinc2, dinc1
00076 
00077 
00078 // this macro is probably deprecated by now
00079 /*
00080 #define COPY_FROM_LINE_T(name)  \
00081         dinc1 = name.dinc1;     \
00082         dinc2 = name.dinc2;     \
00083         xinc1 = name.xinc1;     \
00084         xinc2 = name.xinc2;     \
00085         yinc1 = name.yinc1;     \
00086         yinc2 = name.yinc2;     \
00087         numpixels = name.numpixels;     \
00088         d = name.d
00089 */
00090 
00091 void compute_line(int x1, int y1, int x2, int y2, line_t *r) {
00092         int deltax, deltay;
00093 
00094         deltax = (x2 - x1); if (deltax<0) deltax=-deltax;
00095         deltay = (y2 - y1); if (deltay<0) deltay=-deltay;
00096 
00097         if (deltax >= deltay) {
00098                 r->numpixels = deltax + 1;
00099                 r->d = (2 * deltay) - deltax;
00100                 r->dinc1 = deltay << 1;
00101                 r->dinc2 = (deltay - deltax) << 1;
00102                 
00103                 r->xinc1 = 1;
00104                 r->xinc2 = 1;
00105                 
00106                 r->yinc1 = 0;
00107                 r->yinc2 = 1;
00108         } else {
00109                 r->numpixels = deltay + 1;
00110                 r->d = (2 * deltax) - deltay;
00111                 r->dinc1 = deltax << 1;
00112                 r->dinc2 = (deltax - deltay) << 1;
00113                 
00114                 r->xinc1 = 0;
00115                 r->xinc2 = 1;
00116                 
00117                 r->yinc1 = 1;
00118                 r->yinc2 = 1;
00119         }
00120 
00121         if (x1 > x2) {
00122                 r->xinc1 = -(r->xinc1);
00123                 r->xinc2 = -(r->xinc2);
00124         }
00125         if (y1 > y2) {
00126                 r->yinc1 = -(r->yinc1);
00127                 r->yinc2 = -(r->yinc2);
00128         }
00129 }
00130 
00131 void line(int x1, int y1, int x2, int y2)
00132 {
00133         REVERSE_LINE_T_MEMBERS;
00134 
00135         int i;
00136         u_int addr, last;
00137         u_char bit, value;
00138 
00139         compute_line(x1, y1, x2, y2, (line_t*)&LINE_T_FIRST);
00140 
00141         addr = map_pixel(x1, y1);
00142         bit = map_subpixel(x1);
00143         value = vpeek(addr);
00144         last = addr;
00145 
00146         for (i=0; i < numpixels; i++) {
00147                 value |= bit;
00148 
00149                 if (d<0) {
00150                         d += dinc1;
00151                         if (xinc1) {
00152                                 if (xinc1 > 0) {
00153                                         bit >>= 1;
00154                                         if (!bit) {
00155                                                 addr += 8;
00156                                                 bit = 128;
00157                                         }
00158                                 } else {
00159                                         bit <<= 1;
00160                                         if (!bit) {
00161                                                 addr -=8;
00162                                                 bit = 1;
00163                                         }
00164                                 }
00165                         }
00166                         if (yinc1) {
00167                                 if (yinc1 > 0) {
00168                                         addr += 1;
00169                                         if (!(addr & 7))
00170                                                 addr += 256 - 8;
00171                                 } else {
00172                                         addr -= 1;
00173                                         if ((addr & 7) == 7)
00174                                                 addr -= 256 - 8;
00175                                 }
00176                         }
00177                 }
00178                 else
00179                 {
00180                         d += dinc2;
00181                         if (xinc2) {
00182                                 if (xinc2 > 0) {
00183                                         bit >>= 1;
00184                                         if (!bit) {
00185                                                 addr += 8;
00186                                                 bit = 128;
00187                                         }
00188                                 } else {
00189                                         bit <<= 1;
00190                                         if (!bit) {
00191                                                 addr -=8;
00192                                                 bit = 1;
00193                                         }
00194                                 }
00195                         }
00196                         if (yinc2) {
00197                                 if (yinc2 > 0) {
00198                                         addr += 1;
00199                                         if (!(addr & 7))
00200                                                 addr += 256 - 8;
00201                                 } else {
00202                                         addr -= 1;
00203                                         if ((addr & 7) == 7)
00204                                                 addr -= 256 - 8;
00205                                 }
00206                         }
00207                 }
00208                 if (last != addr) {
00209                         vpoke(last, value);
00210                         value = vpeek(addr);
00211                         last = addr;
00212                 }
00213         }
00214         vpoke(addr, value);
00215 }
00216 
00217 void line_slow(int x1, int y1, int x2, int y2)
00218 {
00219         REVERSE_LINE_T_MEMBERS;
00220 
00221         int i, x, y;
00222         u_int addr, last;
00223         u_char value;
00224 
00225         compute_line(x1, y1, x2, y2, (line_t*)&LINE_T_FIRST);
00226 
00227         x = x1;
00228         y = y1;
00229         addr = map_pixel(x, y);
00230         last = addr;
00231         value = vpeek(addr);
00232 
00233         for (i=0; i < numpixels; i++) {
00234                 value |= map_subpixel(x);
00235                 if (d<0) {
00236                         d += dinc1;
00237                         x += xinc1;
00238                         y += yinc1;
00239                 }
00240                 else
00241                 {
00242                         d += dinc2;
00243                         x += xinc2;
00244                         y += yinc2;
00245                 }
00246                 addr = map_pixel(x, y);
00247                 if (last != addr) {
00248                         vpoke(last, value);
00249                         value = vpeek(addr);
00250                         last = addr;
00251                 }
00252         }
00253         vpoke(addr, value);
00254 }
00255 
00256 void surface_line(surface_t* s, int x1, int y1, int x2, int y2) {
00257         REVERSE_LINE_T_MEMBERS;
00258 
00259         int i;
00260         u_int addr;
00261         u_char* data, bit;
00262 
00263         compute_line(x1, y1, x2, y2, (line_t*)&LINE_T_FIRST);
00264 
00265         data = s->data.ram;
00266         addr = map_pixel(x1, y1);
00267         bit = map_subpixel(x1);
00268 
00269         i = numpixels;
00270         while (i--) {
00271                 data[addr] |= bit;
00272 
00273                 if (d<0) {
00274                         d += dinc1;
00275                         if (xinc1) {
00276                                 if (xinc1 > 0) {
00277                                         bit >>= 1;
00278                                         if (!bit) {
00279                                                 addr += 8;
00280                                                 bit = 128;
00281                                         }
00282                                 } else {
00283                                         bit <<= 1;
00284                                         if (!bit) {
00285                                                 addr -=8;
00286                                                 bit = 1;
00287                                         }
00288                                 }
00289                         }
00290                         if (yinc1) {
00291                                 if (yinc1 > 0) {
00292                                         addr += 1;
00293                                         if (!(addr & 7))
00294                                                 addr += 256 - 8;
00295                                 } else {
00296                                         addr -= 1;
00297                                         if ((addr & 7) == 7)
00298                                                 addr -= 256 - 8;
00299                                 }
00300                         }
00301                 }
00302                 else
00303                 {
00304                         d += dinc2;
00305                         if (xinc2) {
00306                                 if (xinc2 > 0) {
00307                                         bit >>= 1;
00308                                         if (!bit) {
00309                                                 addr += 8;
00310                                                 bit = 128;
00311                                         }
00312                                 } else {
00313                                         bit <<= 1;
00314                                         if (!bit) {
00315                                                 addr -=8;
00316                                                 bit = 1;
00317                                         }
00318                                 }
00319                         }
00320                         if (yinc2) {
00321                                 if (yinc2 > 0) {
00322                                         addr += 1;
00323                                         if (!(addr & 7))
00324                                                 addr += 256 - 8;
00325                                 } else {
00326                                         addr -= 1;
00327                                         if ((addr & 7) == 7)
00328                                                 addr -= 256 - 8;
00329                                 }
00330                         }
00331                 }
00332         }
00333 }
00334 
00335 #define MAX(a, b) (((a) > (b)) ? (a) : (b))
00336 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
00337 
00338 void calculate_side(int x1, int y1, int x2, int y2, int low[], int high[]) {
00339         int step;
00340         int lines;
00341         int ly, hy, ux;
00342         int *pl, *ph;
00343 
00344         if (y2 < y1) {
00345                 int t;
00346                 t = x2; x2 = x1; x1 = t;
00347                 t = y2; y2 = y1; y1 = t;                
00348         }
00349         lines = y2 - y1;
00350 
00351         pl = low + y1;
00352         ph = high + y1;
00353 
00354         if (!lines) {
00355                 ly = *pl; hy = *ph;
00356                 if (x1 < x2) {
00357                         low[y1] = MIN(ly, x1); high[y1] = MAX(hy, x2);
00358                 } else {
00359                         low[y1] = MIN(ly, x2); high[y1] = MAX(hy, x1);
00360                 }
00361                 return;
00362         }
00363 
00364         step = i2f(x2 - x1);
00365         step /= lines;
00366         x1 = i2f(x1);
00367 
00368         while (lines--) {
00369                 ly = *pl; hy = *ph;
00370                 ux = f2i(x1);
00371                 *pl++ = MIN(ly, ux); *ph++ = MAX(hy, ux);
00372                 x1 += step;
00373         }
00374 }
00375 
00376 void surface_hline(surface_t* s, int x1, int y1, int x2, u_char value) {
00377         int bi, bf;
00378         u_char di, df, c;
00379         u_char *data;
00380 
00381         if (x1 > x2)
00382                 return;
00383 
00384         data = s->data.ram + map_pixel(x1, y1);
00385 
00386         bi = x1 >> 3;
00387         bf = x2 >> 3;
00388         di = x1 & 7;
00389         if (bi == bf) {
00390                 c = ~(u_char)(255 >> (u_char)(x2 - x1 + 1)) >> di;
00391                 *data = (c & value) | (*data & ~c);
00392                 return;
00393         }
00394         df = x2 & 7;
00395         if (di > 0) {
00396                 c = 255 >> di;
00397                 *data = (c & value) | (*data & ~c);
00398                 data += 8;
00399                 ++bi;
00400         }
00401         if (df < 7) {
00402                 --bf;
00403         }
00404         while (bi <= bf) {
00405                 *data = value;
00406                 data += 8;
00407                 bi++;
00408         }
00409         if (df < 7) {
00410                 c = ~(255 >> df);
00411                 *data = (c & value) | (*data & ~c);
00412         }
00413 }
00414 
00415 void hline(int x1, int y1, int x2, u_char value) {
00416         int bi, bf;
00417         u_char di, df, c;
00418         int data;
00419 
00420         if (x1 > x2)
00421                 return;
00422 
00423         data = map_pixel(x1, y1);
00424 
00425         bi = x1 >> 3;
00426         bf = x2 >> 3;
00427         di = x1 & 7;
00428         if (bi == bf) {
00429                 c = ~(u_char)(255 >> (u_char)(x2 - x1 + 1)) >> di;
00430                 vpoke(data, (c & value) | (vpeek(data) & ~c));
00431                 return;
00432         }
00433         df = x2 & 7;
00434         if (di > 0) {
00435                 c = 255 >> di;
00436                 vpoke(data, (c & value) | (vpeek(data) & ~c));
00437                 data += 8;
00438                 ++bi;
00439         }
00440         if (df < 7) {
00441                 --bf;
00442         }
00443         while (bi <= bf) {
00444                 vpoke(data, value);
00445                 data += 8;
00446                 bi++;
00447         }
00448         if (df < 7) {
00449                 c = ~(255 >> df);
00450                 vpoke(data, (c & value) | (vpeek(data) & ~c));
00451         }
00452 }
00453 
00454 #asm
00455 psect data
00456 
00457 global _dithpat
00458 _dithpat:
00459         defb    00000000B
00460         defb    00000000B
00461 
00462         defb    00000000B
00463         defb    10101010B
00464 
00465         defb    01010101B
00466         defb    10101010B
00467 
00468         defb    11111111B
00469         defb    10101010B
00470 
00471         defb    11111111B
00472         defb    11111111B
00473 #endasm

Generated on Thu Mar 3 19:55:02 2005 for GFX lib by  doxygen 1.4.1