int drw_aktx = 0; int drw_akty = 0; uint16_t drw_color = 0xffff; // Koordinaten, um die die Ausgabe einer Turtlegrafik "verschoben" werden kann int drw_xofs = 0; int drw_yofs = 0; /* ------------------------------------------------------------- drw_putpixel zeichnet einen einzelnen Bildpunkt auf das Display x, y : Koordinate, an der ein Bildpunkt gesetzt wird col : Farbe des Bildpunktes ------------------------------------------------------------- */ void drw_putpixel(int x, int y, uint16_t col) { putpixel(x + drw_xofs, y + drw_yofs, col); } /* ------------------------------------------------------------- drw_line Zeichnet eine Linie von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird Linienalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_line(int x0, int y0, int x1, int y1, uint16_t color) { // Linienalgorithmus nach Bresenham (www.wikipedia.org) int dx = abs(x1-x0), sx = x0 dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */ if (e2 < dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */ } } /* ------------------------------------------------------------- drw_ellipse Zeichnet eine Ellipse mit Mittelpunt an der Koordinate xm,ym mit den Hoehen- Breitenverhaeltnis a:b mit der angegebenen Farbe xm,ym : Koordinate des Mittelpunktes der Ellipse a,b : Hoehen- Breitenverhaeltnis color : Farbwert, der gezeichnet wird Ellipsenalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_ellipse(int xm, int ym, int a, int b, uint16_t color ) { // Algorithmus nach Bresenham (www.wikipedia.org) int dx = 0, dy = b; // im I. Quadranten von links oben nach rechts unten long a2 = a*a, b2 = b*b; long err = b2-(2*b-1)*a2, e2; // Fehler im 1. Schritt */ do { drw_putpixel(xm+dx, ym+dy,color); // I. Quadrant drw_putpixel(xm-dx, ym+dy,color); // II. Quadrant drw_putpixel(xm-dx, ym-dy,color); // III. Quadrant drw_putpixel(xm+dx, ym-dy,color); // IV. Quadrant e2 = 2*err; if (e2 < (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; } if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; } } while (dy >= 0); while (dx++ < a) // fehlerhafter Abbruch bei flachen Ellipsen (b=1) { drw_putpixel(xm+dx, ym,color); drw_putpixel(xm-dx, ym,color); } } /* ---------------------------------------------------------- drw_fastxline zeichnet eine Linie in X-Achse mit den X Punkten x1 und x2 auf der Y-Achse y1 x1, x2 : Start-, Endpunkt der Linie y1 : Y-Koordinate der Linie color : 16 - Bit RGB565 Farbwert der gezeichnet werden soll ---------------------------------------------------------- */ void drw_fastxline(int x1, int y1, int x2, uint16_t color) { int x; if (x2 < x1) { x = x1; x1 = x2; x2 = x; } for (x= x1; x< (x2+1); x++) { drw_putpixel(x,y1, color); } } /* ------------------------------------------------------------- drw_rectangle Zeichnet ein Rechteck von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_rectangle(int x1, int y1, int x2, int y2, uint16_t color) { if (x2 < x1) { int t = x1; x1 = x2; x2 = t; } if (y2 < y1) { int t = y1; y1 = y2; y2 = t; } drw_line(x1,y1,x2,y1, color); drw_line(x2,y1,x2,y2, color); drw_line(x1,y2,x2,y2, color); drw_line(x1,y1,x1,y2, color); } /* ------------------------------------------------------------- drw_fillrectangle Zeichnet ein gefuelltes Rechteck von den Koordinaten x0,y0 zu x1,y1 mit der angegebenen Farbe x0,y0 : Koordinate linke obere Ecke x1,y1 : Koordinate rechte untere Ecke color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_fillrectangle(int x1, int y1, int x2, int y2, uint16_t color) { if (x2 < x1) { int t = x1; x1 = x2; x2 = t; } if (y2 < y1) { int t = y1; y1 = y2; y2 = t; } int y; for (y = y1; y <= y2; y++) { drw_fastxline(x1, y, x2, color); } } /* ------------------------------------------------------------- drw_circle Zeichnet einen Kreis mit Mittelpunt an der Koordinate xm,ym und dem Radius r mit der angegebenen Farbe x ,y : Koordinate des Mittelpunktes der Ellipse r : Radius des Kreises color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_circle(int x, int y, int r, uint16_t color ) { drw_ellipse(x,y,r,r,color); } /* ------------------------------------------------------------- drw_fillellipse Zeichnet eine ausgefuellte Ellipse mit Mittelpunt an der Koordinate xm,ym mit den Hoehen- Breitenverhaeltnis a:b mit der angegebenen Farbe xm,ym : Koordinate des Mittelpunktes der Ellipse a,b : Hoehen- Breitenverhaeltnis color : Farbwert, der gezeichnet wird Ellipsenalgorithmus nach Bresenham (www.wikipedia.org) ------------------------------------------------------------- */ void drw_fillellipse(int xm, int ym, int a, int b, uint16_t color ) { // Algorithmus nach Bresenham (www.wikipedia.org) int dx = 0, dy = b; // im I. Quadranten von links oben nach rechts unten long a2 = a*a, b2 = b*b; long err = b2-(2*b-1)*a2, e2; // Fehler im 1. Schritt */ do { drw_fastxline(xm+dx, ym+dy,xm-dx, color); // I. und II. Quadrant drw_fastxline(xm-dx, ym-dy,xm+dx, color); // III. und IV. Quadrant e2 = 2*err; if (e2 < (2*dx+1)*b2) { dx++; err += (2*dx+1)*b2; } if (e2 > -(2*dy-1)*a2) { dy--; err -= (2*dy-1)*a2; } } while (dy >= 0); while (dx++ < a) // fehlerhafter Abbruch bei flachen Ellipsen (b=1) { drw_putpixel(xm+dx, ym,color); drw_putpixel(xm-dx, ym,color); } } /* ------------------------------------------------------------- drw_fillcircle Zeichnet einen ausgefuellten Kreis mit Mittelpunt an der Koordinate xm,ym und dem Radius r mit der angegebenen Farbe x,y : Koordinate des Mittelpunktes der Ellipse r : Radius des Kreises color : Farbwert, der gezeichnet wird ------------------------------------------------------------- */ void drw_fillcircle(int x, int y, int r, uint16_t color ) { drw_fillellipse(x,y,r,r,color); } /* ------------------------------------------------------------- cmd_getonearg liest einen Parameter als Integer ab der Stringposition 0 und gibt als Funktionsargument einen Zeiger auf den dem Argument folgenden String zurueck. *str : Zeiger auf String *value : Zeiger Speicherplatz, der den im String ent- haltenen Wert als Integer aufnimmt Rueckgabe : Zeiger auf den String, der dem Parameter folgt ------------------------------------------------------------- */ const char *cmd_getonearg(const char *str, int *value) { char ch, negativesign; char loop; int v; loop= 1; v= 0; negativesign= 0; while(*str && loop) { ch= *str; if (ch == '-') { negativesign= 1; str++; ch= *str; } if ((ch >= '0') && (ch <= '9')) { v = v*10; v += ch-'0'; str++; } else { loop= 0; } } *value= v; if (negativesign) { *value= *value * (-1); } return str; } /* ------------------------------------------------------------- cmd_parse Interpretiert einen String als Anweisungen fuer einen Zeichenstift Kommandos innerhalb des Strings: P : bewegt den Zeichenstift auf eine absolue Koordinatenposition ohne etwas zu zeicnen p : zeichnet eine Line zur angegebenen absoluten Koordinatenposition M : bewegt den Zeichenstift auf eine relative Koordinatenposition ohne etwas zu zeicnen m : zeichnet eine Line zur angegebenen relative Koordinatenposition r : zeichnet eine Linie nach rechts mit einer ange- gebenen Anzahl Pixel (right) l : zeichnet eine Linie nach links mit einer ange- gebenen Anzahl Pixel (left) u : zeichnet eine Linie nach oben mit einer ange- gebenen Anzahl Pixel (up) d : zeichnet eine Linie nach unten mit einer ange- gebenen Anzahl Pixel (down) k : zeichnet einen Kreis mit einem angegebenen Radius K : zeichnet einen gefuellten Kreis mit einem angegebenen Radius t : zeichnet ein Recheck von der aktuellen Zeichen- position mit angegebener Pixelbreite und Pixel- hoehe T : zeichnet ein gefuelltes Recheck von der aktuellen Zeichenposition mit angegebener Pixelbreite und Pixelhoehe c : setzt die Zeichenfarbe mit der Farbe in der EGA-Palette (1 Argument) C : setzt die Zeichenfarbe mit Werten fuer rot, gruen, blau ------------------------------------------------------------- */ void cmd_parse(const char *str) { char ch; int arg1, arg2, arg3; while(*str) { ch= *str; str++; switch(ch) { // ---------------------------------------------- // EGA-Farbwahl // ---------------------------------------------- case 'c' : { str= cmd_getonearg(str, &arg1); drw_color= rgbfromega(arg1); break; } // ---------------------------------------------- // VGA-Farbwahl // ---------------------------------------------- case 'C' : { str= cmd_getonearg(str, &arg1); if(*str == ',') str++; str= cmd_getonearg(str, &arg2); if(*str == ',') str++; str= cmd_getonearg(str, &arg3); drw_color= rgbfromvalue(arg1, arg2, arg3); break; } // ---------------------------------------------- // zeichne nach rechts / right draw // ---------------------------------------------- case 'r' : { str= cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx+arg1, drw_akty, drw_color); drw_aktx += arg1; break; } // ---------------------------------------------- // zeichne nach links / left draw // ---------------------------------------------- case 'l' : { str= cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx-arg1, drw_akty, drw_color); drw_aktx -= arg1; break; } // ---------------------------------------------- // zeichne nach oben / up draw // ---------------------------------------------- case 'u' : { str= cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx, drw_akty-arg1, drw_color); drw_akty -= arg1; break; } // ---------------------------------------------- // zeichne nach unten / down draw // ---------------------------------------------- case 'd' : { str= cmd_getonearg(str, &arg1); drw_line(drw_aktx, drw_akty, drw_aktx, drw_akty+arg1, drw_color); drw_akty += arg1; break; } // ---------------------------------------------- // zeichne Kreis / circle draw // ---------------------------------------------- case 'k' : { str= cmd_getonearg(str, &arg1); drw_circle(drw_aktx, drw_akty, arg1, drw_color); break; } // ---------------------------------------------- // zeichne ausgefuellten Kreis / filled // circle draw // ---------------------------------------------- case 'K' : { str= cmd_getonearg(str, &arg1); drw_fillcircle(drw_aktx, drw_akty, arg1, drw_color); break; } // ---------------------------------------------- // zeichne Rechteck / recTangle draw // aktuelle Position ist linkes oberes Eck, // Argument 1 entspricht Breite, Argument 2 // entspricht Hoehe // ---------------------------------------------- case 't' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_rectangle(drw_aktx, drw_akty, drw_aktx+arg1, drw_akty+arg2, drw_color); break; } // ---------------------------------------------- // zeichne ausgefuelltes Rechteck / filled // rectangle draw. Akuelle Position ist // linkes oberes Eck, Argument 1 entspricht // Breite, Argument 2 entspricht Hoehe // ---------------------------------------------- case 'T' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_fillrectangle(drw_aktx, drw_akty, drw_aktx+arg1, drw_akty+arg2, drw_color); break; } // ---------------------------------------------- // postioniert Zeichenstift zu einer absoluten // Koordinate ohne zu zeichnen // ---------------------------------------------- case 'P' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_aktx= arg1; drw_akty= arg2; break; } // ---------------------------------------------- // zeichnet eine Linie zu einer absoluten // Koordinate // ---------------------------------------------- case 'p' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_line(drw_aktx, drw_akty, arg1, arg2, drw_color); drw_aktx= arg1; drw_akty= arg2; break; } // ---------------------------------------------- // positioniert den Zeichenstift zu einer // relativen Koordinate ohne zu zeichnen // ---------------------------------------------- case 'M' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_aktx += arg1; drw_akty += arg2; break; } // ---------------------------------------------- // zeichnet eine Linie zu einer relativen // Koordinate // ---------------------------------------------- case 'm' : { str= cmd_getonearg(str, &arg1); str++; str= cmd_getonearg(str, &arg2); drw_line(drw_aktx, drw_akty, drw_aktx + arg1, drw_akty + arg2, drw_color); drw_aktx += arg1; drw_akty += arg2; break; } default : break; } } }