source: projects/paper-tape/userspace-driver/old implementation/lochstreifen.c @ 29

Last change on this file since 29 was 29, checked in by sven, 11 years ago

I think that was the some kind of

  • Property svn:executable set to *
File size: 26.7 KB
Line 
1/**
2 * Lochstreifen mit Cairo zeichnen
3 *
4 * Diese Datei stellt ein Objekt (LOCHSTREIFEN) zur Verfuegung,
5 * welches mit Cairo Lochstreifen auf vielfaeltige Weise rendern
6 * kann. Ueber die zahlreichen Funktionen koennen die Variablen
7 * eingestellt werden.
8 *
9 * Diese Lochstreifenroutinen sind bewusst nur mit Cairo programmiert
10 * worden (kompilieren mit `pkg-config --cflags --libs cairo`), sie
11 * benoetigen kein installiertes GTK oder Glib.
12 *
13 * Die Variationsmoeglichkeiten fuer die gezeichneten Lochstreifen
14 * sind sehr vielfaeltig und koennen einzeln voellig frei miteinander
15 * kombiniert werden. So kann man saemtliche geometrischen Abstaende
16 * aendern (Abstand der Lochreihen, Lochspalten, Fuehrungloecher,
17 * Durchmesser der unterschiedlichen Loecher, Abstaende in und um
18 * den Lochstreifen, usw.) oder verhaeltnissmaessig angeben.
19 * Ausserdem laesst sich der Lochstreifen sehr leicht in 45°-Schritten
20 * drehen oder um beide Achsen spiegeln. Saemtliche Farben sind frei
21 * einstellbar, einzelne Objekte koennen auf Wunsch auch nicht
22 * gezeichnet werden.
23 *
24 * Anzumerken sei auch, dass diese Routinen nur die Zeichenarbeit
25 * uebernehmen -- das Cairoobjekt muss das Programm stellen. Damit sind
26 * voellige Freiheiten zur Wahl der Cairo-Surface gegeben (SVG, PNG,
27 * PDF, ... -- alles moeglich, Cairo eben). Da man bei der Erstellung
28 * einer Cairosurface ueblicherweise Groessenangaben braucht, kriegt
29 * man diese aus den aktuellen Parametern berechnet mit
30 * lochstreifen_get_width und lochstreifen_get_height.
31 *
32 * Fuer die Bedeutung der einzelnen Felder der LOCHSTREIFEN-Struktur
33 * siehe Header-File, fuer genauere Erklaerungen zu den Funktionen
34 * siehe direkt bei deren Implementierungen (diese Datei).
35 *
36 * sven, im November 2007.
37 *
38 **/
39#include <math.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43
44#include "lochstreifen.h"
45
46#define DEBUG 1
47
48int file_get_contents(FILE *stream, byte_t **content) {
49    /**
50    * Kleine Behelfsfunktion, die den stream (z.B. stdin, eine Datei) als Bytes
51    * komplett einliest.
52    * Erwartet: Stream, Zeiger auf Zeiger (für Array)
53    * Gibt zurück:  Return-value:      Laenge von content, rechnend ab 1
54    *               Call-by-reference: Content wird alloziiert als Array mit Inhalt
55    *
56    * Erzeugt seltsamerweise manchmal komische Fehler,
57    * g_file_get_contents von Glib funktioniert zuverlaessiger.
58    **/
59    // das war meine Version, bevor ich mir alles von g_file_get_contents
60    // abgeschaut habe. Einen Fehler hab ich zumindest gerade entdeckt:
61    // realloc gibt ggf. einen neuen Pointer zurück. Das würde erklären, warum auch
62    // das ganze *mal* ging und *mal* nicht. Offensichtlich kopiert realloc dann auch
63    // die Daten, wenn es entscheidet, sie woanders auf dem heap abzusieldeln...
64    /*
65    // um wie viel Zeichen das dynamische Array jeweils erhoeht werden soll
66    // ein Kompromiss zwischen Platzverschwendung (zuviel allokatierter aber ungenutzter
67    // Speicher) und Perfomance beim Einlesen (zu oft das Array erweitern)
68    #define FILE_GET_CONTENT_STEPSIZE 20
69
70    int length;
71    int extended = 1; // wie oft bereits erweitert
72    *content = (byte_t*) malloc(sizeof(byte_t) * FILE_GET_CONTENT_STEPSIZE);
73    if(*content == NULL) return 0; // schlecht.
74
75    for(length=0;;) {
76        (*content)[length] = (byte_t)fgetc(stream);
77        if(feof(stream) != 0) break; // EOF vor dem Einlesen!
78        printf("%03d. Zeichen eingelesen: 0x%02X (=%c)\n", length+1, (*content)[length], (*content)[length]);
79        if(extended*FILE_GET_CONTENT_STEPSIZE == ++length) {// Speicherende erreicht?
80             printf("=> Bereits %d mal den %d-Puffer verwendet, erweitere auf %d...\n", extended, FILE_GET_CONTENT_STEPSIZE, (extended+1)*FILE_GET_CONTENT_STEPSIZE);
81             if(realloc(*content, sizeof(byte_t)*(++extended)*FILE_GET_CONTENT_STEPSIZE) == NULL) // Speicher vergroessern
82                 return length; // Fehler - das eingelesene zumindest zurueckgeben.
83        }
84    }
85
86    return length; // wir wollen ab 1 zaehlen, das wurde indirekt durch den letzten unnoetigen ++inkrement gemacht
87    }
88    int file_get_contents(FILE *stream, byte_t **content) {
89    */
90    /**
91     * Neugeschrieben nach etwas Inspiration von der glib am 05.04.2008.
92     * Funktion get_contents_stdio, gfileutils.c im Sourcecode von glib-2.14.3.
93     * Router natürlich aus (03:11!), aber da sieht man mal wieder den Vorteil von Gentoo:
94     * Gleich alle Sourcecodes auf der Platte =)
95     *
96     *
97     *
98     **/
99     // *stream = *f
100     // *content = **contents
101     // gsize *length
102
103     byte_t buf[4096];
104     size_t bytes; // gerade eben eingelesene bytes
105     byte_t *str = NULL;
106     size_t total_bytes = 0;     // alle bis jetzt eingelesenen bytes
107     size_t total_allocated = 0;
108     byte_t *tmp; // fuers realloc
109
110     while(!feof(stream)) {
111         bytes = fread(buf, 1, sizeof(buf), stream);
112
113         while( (total_bytes + bytes) > total_allocated) {
114             if(str)
115                 total_allocated *= 2;
116             else
117                 total_allocated = bytes > sizeof(buf) ? bytes : sizeof(buf);
118
119             tmp = realloc(str, total_allocated);
120
121             if(tmp == NULL) {
122                 fprintf(stderr, "*** file_get_contents ERROR*** Could not reallocate\n");
123                 //return length; // Fehler - das eingelesene zumindest zurueckgeben.
124                 // nee, gar nichts zurückgeben. Das geht so nicht.
125                 return 0;
126             }
127
128             str = tmp;
129        } // while innen
130
131        memcpy(str + total_bytes, buf, bytes);
132        total_bytes += bytes;
133     } // while
134
135     if(total_allocated == 0)
136         str = malloc(1); // ein leerer String halt.
137
138     //str[total_bytes] = '\0'; // wenns ein string wäre.
139
140     *content = str; // WAS: *content = str.
141
142     return total_bytes;
143}
144
145void lochstreifen_set_color(cairo_pattern_t *color, byte_t red, byte_t green, byte_t blue, byte_t alpha) {
146    /** Kleine Befehlsfunktion, die ein Cairopattern erzeugt. Farbwerte zwischen 0 und 255.
147        alpha = 255 ist unnoetig => einfach das Patternobjekt auf NULL setzen und die Zeichenfunktion
148        wird es nicht zeichnen. */
149    color = cairo_pattern_create_rgba(red/255, green/255, blue/255, alpha/255);
150}
151
152
153LOCHSTREIFEN *lochstreifen_new() {
154    /** Neues Lochstreifenobjekt erzeugen */
155    LOCHSTREIFEN *l = malloc(sizeof(LOCHSTREIFEN));
156    // Defaultwerte setzen:
157    l->d = 10;
158    l->data_length = 0;
159    l->data = NULL;
160    l->empty_start = 0;
161    l->empty_end = 0;
162    l->debug = 0;
163    l->hintergrund = NULL; // nicht zeichnen
164    l->streifenbg = cairo_pattern_create_rgb(0.7,0.7,0.7);
165    l->punched = cairo_pattern_create_rgb(0,0,0);
166    l->notpunched = cairo_pattern_create_rgb(0.827, 0.827, 0.827); //220/255, 220/255, 220/255);
167    l->fuehrung = cairo_pattern_create_rgb(143/255, 175/255, 255/255);
168    //cairo_matrix_init_identity(&(l->transformation));
169        //, 1, 0, 0, 1, 0, 0); // Standardmatrix einrichten (keine Drehung)
170    l->drehung = 0;
171    l->spiegelung_hor = 0;
172    l->spiegelung_ver = 0;
173    l->highlight_byte = 0;
174    l->highlight_color = NULL;
175    lochstreifen_flush_only_start_area(l);
176    return l;
177}
178
179void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data, int empty_start, int empty_end) {
180    /** Zu druckende Daten eingeben, Anzahl gewuenschter Leerbytes vorne/hinten eingeben,
181        ist empty_start/empty_end < 0, wird das entsprechende nicht gesetzt */
182    l->data_length = data_length;
183    if(l->data != NULL) // unbenutzten Speicher freigeben!
184        free(l->data);
185    l->data = data;
186    if(empty_start >= 0) l->empty_start = empty_start;
187    if(empty_end >= 0) l->empty_end = empty_end;
188}
189
190void lochstreifen_set_highlight(LOCHSTREIFEN* l, int byte_number) {
191    l->highlight_byte = byte_number;
192    if(l->highlight_color == NULL)
193        l->highlight_color = cairo_pattern_create_rgb(242/255, 255/255, 0);
194}
195
196int lochstreifen_set_only_start_area(LOCHSTREIFEN *l, int x, int y, int width, int height) {
197    /** Clipping-Rechteck setzen. Damit wird beim naechsten Zeichnen nur in diesem
198        Bereich gezeichnet. Es handelt sich jedoch um kein exiplites ordentliches
199        cairo_clipping, sondern eine grobe Naehrung zwecks Perfomance.
200        Die Koordinaten beziehen sich auf die entgueltige Form (inkl. Drehung, ...)
201    */
202    l->only_start_x = x;
203    l->only_start_y = y;
204    l->only_width = width;
205    l->only_height = height;
206    return 0; // could make void.
207}
208
209int lochstreifen_flush_only_start_area(LOCHSTREIFEN *l) {
210    /** Clipping-Rechteck loeschen -- beim naechsten Zeichnen alles zeichnen */
211    l->only_start_x = 0;
212    l->only_start_y = 0;
213    l->only_width = 0;
214    l->only_height = 0;
215    return 0; // yeah, void would be correct.
216}
217
218void lochstreifen_set_d(LOCHSTREIFEN *l, int d) {
219    /** Durchmesser eines Loches uebergeben (allgemeine Referenzeinheit fuer Dimensionen) */
220    l->d = d;
221    l->bspace = d*0.7/1.9;  // Abstand der Bytes voneinander (Reihen)
222    l->hspace = d/2;  // Abstand der Loecher in der Bytereihe
223    l->padding = d; // Abstand Löcher <=> Lochstreifenrand
224    l->df = d/2; // Durchmesser Lochfuehrungsloch
225    l->fspace = 1.1*(d+ l->hspace); // Breite der Lochfuehrungs"nut"
226    l->margin = d*2; // Abstand um Lochstreifen herum (an allen Seiten)
227    l->abriss = (8*d+6* l->hspace + l->fspace)/2; // Länge der Abrisse an Start/Ende (halbe Höhe vom Lochstreifen)
228}
229
230int lochstreifen_get_orientation(LOCHSTREIFEN *l) {
231    /** Gibt die Orientierung des Lochstreifens zurueck; 1 = horizontal, 0 = vertikal */
232    return (l->drehung % 2 == 0) ? 1 : 0;
233}
234
235int lochstreifen_get_width(LOCHSTREIFEN *l) {
236    /** Berechnet aktuelle Breite aus Lochstreifenkonstanten */
237    // interne Ersetzungen...
238    #define LOCHSTREIFEN_WIDTH  2*l->abriss + 2*l->margin + \
239        (l->data_length + l->empty_start + l->empty_end) * (l->d + l->bspace) - l->bspace // ein bspace zuviel am Ende
240    #define LOCHSTREIFEN_HEIGHT 8*l->d + 6*l->hspace + l->fspace + l->margin*2 + l->padding*2 \
241                                     //  ^ weil letztes hspace + hspace über fspace unnötig
242    return (l->drehung % 2 == 0) ? LOCHSTREIFEN_WIDTH : LOCHSTREIFEN_HEIGHT;
243}
244
245int lochstreifen_get_height(LOCHSTREIFEN *l) {
246    /** Berechnet aktuelle Hoehe aus Lochstreifenkonstanten */
247    return (l->drehung % 2 == 1) ? LOCHSTREIFEN_WIDTH : LOCHSTREIFEN_HEIGHT;
248}
249
250void lochstreifen_set_d_by_width(LOCHSTREIFEN *l, int width) {
251    /**
252     * Umkehrfunktion zu set_d (dort wird die Breite/Hoehe durch d berechnet),
253     * hier wird d durch die vorgegebene Breite berechnet. Die Hoehe ergibt
254     * sich dann natuerlich auch automatisch.
255     * Evventuelle Drehungen werden miteinberechnet, d.h. wenn der Lochstreifen
256     * z.B. nach oben/unten zeigt, bezieht sich width auf die "echte" Hoehe.
257     **/
258    // Gleichung zum Berechnen von LOCHSTREIFEN_WIDTH nach
259    // d aufgeloest mit MuPad Pro 3.2 ( ;-) )
260    #define LOCHSTREIFEN_INV_WIDTH  (double) (1 / (6187./380. + 26./19. * (double)(l->data_length + l->empty_start + l->empty_end)))
261    #define LOCHSTREIFEN_INV_HEIGHT  (double) (1 * 20./373.)
262    lochstreifen_set_d(l,
263        (int)rint((double)width * ((l->drehung % 2 == 0) ? LOCHSTREIFEN_INV_WIDTH : LOCHSTREIFEN_INV_HEIGHT))
264    );
265    //printf("Width soll %d ==> %d | %d\n", width, lochstreifen_get_width(l), lochstreifen_get_height(l));
266}
267
268void lochstreifen_set_d_by_height(LOCHSTREIFEN *l, int height) {
269    /**
270     * Siehe set_d_by_width, nur wird hier d abhaengig von der gewuenschten Hoehe
271     * berechnet.
272     **/
273    lochstreifen_set_d(l,
274        (int)rint((double) height * LOCHSTREIFEN_INV_HEIGHT) //((l->drehung % 2 == 0) ? LOCHSTREIFEN_INV_WIDTH : LOCHSTREIFEN_INV_HEIGHT))
275    );
276    //printf("Height soll %03d ==> d=%02d | %f, w/h = %03d | %03d\n", height, l->d,
277    //    (double)height*LOCHSTREIFEN_INV_HEIGHT
278    //    , lochstreifen_get_width(l), lochstreifen_get_height(l));
279}
280
281void lochstreifen_set_direction(LOCHSTREIFEN *l, int drehung, int spiegelung_hor, int spiegelung_ver) {
282    /**
283     * Transformationen der Lochstreifenausrichtung
284     * drehung: 0 = Kopf nach links
285     *          1 = oben
286     *          2 = rechts
287     *          3 = unten
288     *         -1 = nicht aendern
289     *          4 = um 90° im Uhrzeigersinn drehen
290     *          5 = um 90° gegen Uhrzeigersinn drehen
291     * Spiegelung horizontal/vertikal: 0 = nein
292     *                                 1 = ja
293     *                                 2 = vertauschen
294     *                                -1 = nicht aendern
295     **/
296     if(drehung >= 0) {
297         // Das "Ausprobieren" zwecks "Autodrehung" mit Aufruf wie
298         // lochstreifen_set_direction(l, l->drehung++, -1, -1);
299         //if(drehung > 4) drehung -= 4; // bei zu grossen Werten mal ausprobieren
300         //if(drehung < 0) drehung += 4; // bei zu kleinen Werten mal ausprobieren
301         //if(drehung % 4 == 0) drehung = 0; // quasi keine Drehung
302         if(drehung >= 4) {
303             if(drehung == 4) l->drehung++;
304             else if(drehung == 5) l->drehung--;
305             if(l->drehung >= 4) l->drehung -= 4; // bei zu grossen Werten
306             if(l->drehung < 0) l->drehung += 4; // bei zu kleinen Werten
307         } else {
308             //if(drehung > 0 && drehung < 4) // gute Werte
309             // normale Drehung mit festem Zielwert
310             l->drehung = drehung;
311         }
312     }
313     if(spiegelung_hor > -1) {
314         if(spiegelung_hor == 2) l->spiegelung_hor = l->spiegelung_hor == 0 ? 1 : 0; // negotieren
315         else l->spiegelung_hor = spiegelung_hor; // normal
316     }
317     if(spiegelung_ver > -1) {
318         if(spiegelung_ver == 2) l->spiegelung_ver = l->spiegelung_ver == 0 ? 1 : 0; // negotieren
319         else l->spiegelung_ver = spiegelung_ver; // normal
320     }
321}
322
323/*
324void lochstreifen_rotate(LOCHSTREIFEN *l) {
325    **
326     * Wird den Lochstreifen beim naechsten Zeichnen um 45° mit dem
327     * Uhrzeigersinn rotiert anzeigen. Nur mit diesen Funktionen wird
328     * die Hoehen/Breitenberechnung im Vorhinein noch funktionieren!
329     **
330     cairo_matrix_rotate(&(l->transformation), M_PI);
331     cairo_matrix_translate((&l->transformation), lochstreifen_get_width(l), 0),
332     l->drehung++; // ...
333}
334
335void lochstreifen_spiegel(LOCHSTREIFEN *l, byte_t horizontal) {
336    **
337     * Spiegelt den Lochstreifen, ist horizontal = 1 dann horizontal,
338     * sonst vertikal (oder so aehnlich)
339     **
340     if(horizontal != 0) { // vertikal
341         cairo_matrix_scale(&(l->transformation), -1, 1);
342         cairo_matrix_translate((&l->transformation), 0, lochstreifen_get_height(l));
343     } else {
344         cairo_matrix_scale(&(l->transformation), 1, -1);
345         cairo_matrix_translate((&l->transformation), lochstreifen_get_width(l), 0);
346     }
347}
348*/
349
350int lochstreifen_byte_by_coordinate(LOCHSTREIFEN *l, int x, int y) {
351     /**
352      * Anhand der Koordinaten (x|y) wird der Index des Bytes (fuers Datenarray, ab 1 zaehlend),
353      * welches damit "erfasst" wird, zurueckgegeben.
354      * Befindet sich (x|y) nicht im Bereich eines Bytes, dann wird je nach Fall zurueckgegeben:
355      *    0 = ausserhalb Lochstreifens
356      *   -1 = in Emptystart/Emptyend-Bytes (die nicht in der Datei existieren)
357      *        oder in Abrissbereichen
358      **/
359    int byte;
360    // BETRACHTUNG HORIZONTALE AUSRICHTUNG
361
362    if(y <= l->margin || y >= LOCHSTREIFEN_HEIGHT - l->margin) return 0; // ueber/unter Lochstreifen
363    x -= l->margin; // erst mal Rand abziehen
364    if(x <= 0) return 0; // links neben dem Lochstreifen.
365    x -= l->abriss + (l->empty_start)*(l->d + l->bspace); // Emptystart+Abrissbereich
366    if(x <= 0) return -1; // in diesem Bereich gewesen
367    // jetzt sind wir im Bytebereich
368    byte = (int) (x / (l->d + l->bspace)) + 1; // Abrunden: Auf welchem Byte man ist + ab 1 zaehlen.
369    if(byte > l->data_length + l->empty_start) return 0; // komplett ausserhalb Lochstreifens
370    else if(byte > l->data_length) return -1; // im Emptyendbereich
371    else return byte; // im gueltigen Bereich -- Byte gefunden!
372}
373
374int lochstreifen_coordinate_by_byte(LOCHSTREIFEN *l, int byte) {
375    /**
376     * Anhang eines Bytes (fuers Datenarray, ab 0 zaehlend) wird -- abhaengig nach aktueller
377     * Ausrichtung des Lochstreifens -- die Koordinate des Bytes in der Dimension der
378     * Ausrichtung des Lochstreifens zurueckgegeben..
379     * Liegt der Lochstreifen horizontal, so wird die x-Koordinate zurueckgegeben. Liegt er
380     * vertikal, dann die y-Koordinate.
381     *
382     **/
383     int xy;
384     //if(lochstreifen_get_orientation(l)) { // horizontal = 1 | vertical = 0
385        xy = l->margin + l->abriss + (l->d + l->bspace) * (byte + l->empty_start);
386     //}
387
388     return xy;
389     // TODO! Richtige implementierung!
390}
391
392void lochstreifen_draw(LOCHSTREIFEN *l, cairo_t *cr) {
393    /**
394     * Den Lochstreifen auf das uebergebene Cairoobjekt zeichnen.
395     * Die Funktion zeichnet nach den aktuellen Lochstreifenobjekt-Angaben
396     * (Groesse/Breite) -- wenn die cairo_image_surface nicht diesen Dimensionen
397     * entspricht, ist das halt schlecht.
398     *
399     **/
400    int byte,loch,x,y; // temp fuer Schleifen
401    int height = lochstreifen_get_height(l);
402    int width = lochstreifen_get_width(l);
403    // 4 Eckpunkte des Zeichenbereichs bestimmen...
404    int x1,x2,y1,y2;
405    x1 = l->only_start_x; y1 = l->only_start_y;
406    x2 = x1 + width;      y2 = y1 + height;
407
408    /*int x1,y1,x2,y2,x3,y3,x4,y4;
409    x1 = l->only_start_x; y1 = l->only_start_y;
410    x2 = x1+width; y2 = y1;
411    x3 = x2; y3 = y2+height;
412    x4 = x1; y4 = y3;*/
413
414    // Verschiebungsmatrix erst hier berechnen, weil Verschiebungen vorher unklar
415    // wunderbare affine Abbildungen ;-)
416    cairo_matrix_t matrix, temp; // temp: Temporaere Matrix zur Matrizenmulitiplikation
417    cairo_matrix_init_identity(&matrix);
418    if(l->drehung > 0) {
419        if(l->drehung == 1) {
420            cairo_matrix_init(&temp, 0, -1, 1, 0, 0, height);
421            x = width; width = height; height = x;                // Breiten und Hoehen
422            x = l->only_width; l->only_width = l->only_height; l->only_height = x; // gerade vertauschen
423        } else if(l->drehung == 2) {
424            cairo_matrix_init(&temp, -1, 0, 0, -1, width, height);
425        } else if(l->drehung == 3) {
426            cairo_matrix_init(&temp, 0, 1, -1, 0, width, 0);
427            x = width; width = height; height = x;                // Breiten und Hoehen
428            x = l->only_width; l->only_width = l->only_height; l->only_height = x; // gerade vertauschen
429        }
430        cairo_matrix_multiply(&matrix, &matrix, &temp);
431    }
432
433    if(l->spiegelung_hor != 0) {
434         cairo_matrix_init(&temp, -1, 0, 0, 1,
435             l->drehung % 2 == 0 ? width : height, // Default bei Nicht-Drehung: width
436             0);
437         cairo_matrix_multiply(&matrix, &matrix, &temp);
438    }
439    if(l->spiegelung_ver != 0) {
440         cairo_matrix_init(&temp, 1, 0, 0, -1, 0,
441             l->drehung % 2 == 0 ? height: width); // Default bei Nicht-Drehung: height
442         cairo_matrix_multiply(&matrix, &matrix, &temp);
443    }
444
445    //if(l->drehung > 0) {
446        /*cairo_matrix_rotate(&matrix, l->drehung/2 *M_PI);
447        if(l->drehung == 1) { // 90°, im III. Sektor
448            //x = width; width = height; height = x;
449            //cairo_matrix_translate(&matrix, 0, 0);
450        } else if(l->drehung == 2) { // 180°, im IV Sektor
451            cairo_matrix_translate(&matrix, width, height);
452        } else if(l->drehung == 3) { // 270°, im I. Sektor
453            //x = width; width = height; height = x;
454            cairo_matrix_translate(&matrix, width, height);
455        }*/
456        // 4. Sektor kommt nicht vor
457    //}
458    cairo_set_matrix(cr, &matrix);
459    // -1, 0, 0, 1, width, 0 = spiegelung x-achse
460
461    //cairo_device_to_user(cr, (double*)&(l->only_start_x), (double*)&(l->only_start_y));
462    cairo_device_to_user(cr, (double*)&(x1), (double*)&(y1));
463    cairo_device_to_user(cr, (double*)&(x2), (double*)&(y2));
464
465    l->only_start_x = x2 < x1 ? x2 : x1;
466    l->only_start_y = y2 < y1 ? y2 : y1;
467
468    // wozu die folgenden 4 Zeilen?
469    //cairo_set_source(cr, l->fuehrung);
470    //cairo_rectangle(cr, l->only_start_x, l->only_start_y, l->only_width, l->only_height);
471    //printf("Only: %d|%d, %d * %d\n", l->only_start_x, l->only_start_y, l->only_width, l->only_height);
472    //cairo_paint(cr);
473
474    // Hintergrundfarbe zeichnen.
475    if(l->hintergrund != NULL) {
476        //l->hintergrund = cairo_pattern_create_rgb(1,1,1);
477        cairo_set_source(cr, l->hintergrund);
478        cairo_paint(cr);
479    }
480
481    // sache zeichnen
482    // welche Sache? Ausgeklammert.
483    /*cairo_set_source(cr, l->streifenbg);
484    cairo_rectangle(cr, -10, -10, width+20, height+20);
485    cairo_stroke(cr);
486    if(0==1){
487        double x,y, a,b;
488        int xx,yy,aa,bb;
489        x=0;y=0; a=width;b=height;
490        cairo_matrix_transform_point(&matrix, &x, &y);
491        cairo_matrix_transform_point(&matrix, &a, &b);
492        xx=(int)x;yy=(int)y;aa=(int)a;bb=(int)b;
493        printf("Punkt (0/0)=(%i|%i) und (%i|%i)=(%i/%i)\n", xx, yy, width, height, aa, bb);
494    }*/
495
496    // erst mal klären. Alles.
497    cairo_reset_clip(cr); // falls es da was gab.
498
499    // Lochstreifenhintergrund inklusive Abriss vorne/hinten malen
500    if(l->streifenbg != NULL) {
501        cairo_set_source(cr, l->streifenbg);
502
503        // Abriss vorne
504        cairo_move_to(cr, l->margin + l->abriss*0.8, l->margin); // oben rechts
505        cairo_line_to(cr, l->margin, l->margin + l->padding+ 3*l->d + 2*l->hspace + l->fspace/2); // genau die fspace-Mitte
506        cairo_line_to(cr, l->margin + l->abriss, height - l->margin); // unten ganz rechts
507        cairo_line_to(cr, l->margin + l->abriss, l->margin); // nach oben ganz rechts...
508        cairo_close_path(cr); // schliessen
509        // normaler Bereich
510        cairo_rectangle(cr, l->margin + l->abriss, l->margin,
511            width - 2*l->margin - 2*l->abriss, height - 2*l->margin);
512        /*printf("Zeichne Rechteck x|y = (%d|%d) width*height = %d * %d\n",
513            l->margin + l->abriss, l->margin,
514            width - 2*l->margin - 2*l->abriss, height - 2*l->margin
515        );*/
516        // Abriss hinten...
517        cairo_move_to(cr, width - l->margin - l->abriss*0.2, l->margin); // oben mitte
518        cairo_line_to(cr, width - l->margin - l->abriss,
519            l->margin + l->padding + 3*l->d+ 2*l->hspace + l->fspace/2); // genau die fspace-Mitte
520        cairo_line_to(cr, width - l->margin, height - l->margin); // unten ganz rechts
521        cairo_line_to(cr, width - l->margin - l->abriss, height - l->margin); // unten ganz links
522        cairo_line_to(cr, width - l->margin - l->abriss, l->margin); // nach oben zum schliessen
523        cairo_close_path(cr);
524
525        cairo_fill(cr);
526    }
527
528
529    // Lochstreifenlöcher malen
530
531    /*if(l->only_start_x > 0) {
532        // nur in bestimmten Bereich zeichnen
533        int start_byte = l->empty_start + lochstreifen_byte_by_coordinate(l, l->only_start_x, l->only_start_y); // absolut inkl. empty bytes
534
535    } else byte = -l->empty_start; // leere Bytes vorne eingeschlossen
536    }*/
537
538    // Bytes durchgehen, leere Bytes vorne/hinten mit eingeschlossen
539    for(byte = -l->empty_start, x=l->margin + l->abriss; byte < l->data_length + l->empty_end; x += l->d + l->bspace, byte++) {
540        // Clipping: Um unnoetiges Zeichnen zu ersparen, erst ab X-Koordinate zeichnen
541        if(x < l->only_start_x - (l->d + l->bspace)) continue; // - 1x Loch weniger, damit nicht ein gerade abgeschnittenes nichtgezeichnet wird
542        // und nur bis zur rechten Begrenzung zeichnen -- dannach genuegt Abbruch.
543        if(l->only_width != 0 && x > l->only_start_x + l->only_width) break;
544
545        // ggf. Byte hervorheben
546        if(byte == l->highlight_byte && l->highlight_color != NULL) {
547            cairo_set_source(cr, l->highlight_color);
548            cairo_rectangle(cr, x - l->bspace/2, l->margin, l->df*2 + l->bspace, height - 2*l->margin);
549            cairo_fill(cr);
550        }
551
552        // Bits des entsprechenden Bytes durchgehen
553        for(loch=0, y = l->margin + l->padding; loch < 8; y += l->d + l->hspace, loch++) {
554            // Clipping: Erst ab Y-Koordinate zeichnen (-1xLoch-Korrektur gegen Abschnitt)
555            if(y < l->only_start_y - (l->d - l->hspace)) continue;
556            // bis zur unteren Begrenzung -- anschliessend Abbruch
557            if(l->only_height != 0 && y > l->only_start_y + l->only_height) break;
558
559            // Ggf. Lochstreifenfuehrung zeichnen
560            if(loch==3 && l->fuehrung != NULL) {
561                // Nur vor dem 3. Loch (wenn ueberhaupt)
562                y -= l->hspace; // den Abstand vom vorherigen Loch wieder wegnehmen
563                cairo_set_source(cr, l->fuehrung);
564                cairo_arc(cr, x+l->d/2, y+l->fspace/2, l->df/2, 0., 2*M_PI);
565                cairo_fill(cr);
566                y += l->fspace;
567            } else if(loch == 3) // 3. Loch, aber keine Fuehrung zeichnen => Platz freilassen!
568                y += l->fspace - l->hspace;
569
570            // Debugausgaben machen?
571            if(l->debug != 0 && byte >= 0 && byte < l->data_length) {
572                if(loch == 0) printf("byte %3i von %3i: 0x%2x = ", byte, l->data_length, l->data[byte]);
573                fprintf(stderr, "%c", (((l->data[byte] >> loch) & 0x01) == 0x01) ? '#' : ' ');
574                if(loch == 7) printf("\n");
575            }
576
577            if((byte < 0 || byte >= l->data_length) ||    // wenn ein Nullbyte gezeichnet wird
578               (((l->data[byte] >> loch) & 0x01) != 0x01) // oder das Bit an der Stelle nicht gesetzt ist
579               ) {                                        // ist es not-Punched
580                if(l->notpunched != NULL) { // notpunched zeichnen? (muss subif sein)
581                    cairo_set_source(cr, l->notpunched);
582                    cairo_arc(cr, x+l->d/2, y+l->d/2, l->d/2, 0., 2*M_PI);
583                    cairo_fill(cr);
584                }
585            } else if(l->punched != NULL) { // es ist Punched. Zeichnen?
586                cairo_set_source(cr, l->punched);
587                cairo_arc(cr, x+l->d/2, y+l->d/2, l->d/2, 0., 2*M_PI);
588                cairo_fill(cr);
589            }
590            // Die Routine wegen dem Zeichnen?-Ding hervorgehoben.
591            /*cairo_set_source(cr,
592                 (byte < 0 || byte >= data_length) ||      // wenn ein Nullbyte gezeichnet wird
593                 (((data[byte] >> loch) & 0x01) != 0x01) ? // oder das Bit an der Stelle nicht gesetzt ist
594                 notpunched : punched);                    // dann dies farbig kennzeichnen
595            cairo_arc(cr, x+d/2, y+d/2, d/2, 0., 2*M_PI);
596            cairo_fill(cr);*/
597
598            // y+= war hier.
599        } // for bits (loecher)
600        // x += war hier.
601    } // for bytes
602
603    // Lochstreifenfuehrung im vorderen Abriss malen
604    if(l->fuehrung != NULL) {
605        cairo_set_source(cr, l->fuehrung);
606        y = l->margin + l->padding + 3*l->d + 2*l->hspace + l->fspace/2; // fspace-Mitte
607        x = l->margin + l->abriss - l->d - l->bspace; // Start-x
608        for(; x > l->margin;) {
609            cairo_arc(cr, x + l->d/2, y, l->df/2, 0., 2*M_PI);
610            x -= l->d + l->bspace;
611        }
612        cairo_fill(cr);
613    }
614
615    // fertig mit dem Lochstreifenzeichnen.
616} // function draw_lochstreifen
Note: See TracBrowser for help on using the repository browser.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License