Changeset 18 in projects for visualisator
- Timestamp:
- Sep 15, 2008, 4:23:39 AM (16 years ago)
- Location:
- visualisator
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
visualisator/cli.c
r9 r18 42 42 43 43 LOCHSTREIFEN *l; 44 int surface_type = 0; // 0 = PNG, 1 = SVG 44 enum _surface_type { 45 PNG_SURFACE, 46 SVG_SURFACE 47 } surface_type; 45 48 char *output_file; 46 49 int verbosity = 0; 50 int null_bytes_start = 0; 51 int null_bytes_end = 0; 52 enum { 53 SCALE_BY_LENGTH, 54 SCALE_BY_WIDTH, 55 SCALE_BY_CODE_HOLE, 56 } scale_by; 57 // scale_target == 0 implies: no scaling! 58 int scale_target = 0; 47 59 48 60 #define DPRINTF(msg...) if(verbosity!=0) fprintf(stderr,msg); 61 62 error_t parse_option (int key, char *arg, struct argp_state *state); 63 cairo_pattern_t *hex2cairo_pattern(const char *string); 49 64 50 65 const char *argp_program_version = "Punch card visualisator - CLI frontend"; … … 66 81 {"", 0, 0, OPTION_DOC, "",1}, 67 82 68 {"Empty bytes", 1, 0, OPTION_DOC, "Bytes with value=0 which are not content of files", 1},83 {"Empty bytes", 1, 0, OPTION_DOC, "Bytes with value=0x00 which are not content of files", 1}, 69 84 {"empty-start", -1, "NUM", 0, "Set number of empty bytes at beginning (default=0)", 2 }, 70 85 {"empty-end", -2, "NUM", 0, "Set number of empty bytes at end (default=0)", 2 }, … … 93 108 }; 94 109 95 char *strtolower(char *string) {96 // komisch, ich dachte echt, es gaebe dafuer eine Funktion in C...97 int x=0;98 for(;string[x];x++) string[x] = tolower(string[x]);99 100 return string; // ja, ich veraenderte den Ursprungsstring. Egal ;-)101 }102 103 cairo_pattern_t *hex2cairo_pattern(const char *string) {104 /** Kriegt aus #RRGGBBAA oder #RGBA eine Cairo-Surface */105 char buf[2]; // zum temporaeren Speichern der einzelnen umzuwandelnden Zeichen106 buf[1] = '\0'; // nur ein Ein-Zeichen-String also107 int len = strlen(string);108 unsigned char numbers[8]; // rausgefundende Ziffern109 int numbers_count; // wie viele Ziffern rausgefunden110 cairo_pattern_t *pattern;111 112 // erst mal schauen, ob ne schoene Raute da ist und auf Laenge (entsprechendes Format)113 if(string[0] != '#' || (len != 4 && len != 5 && len != 7 && len != 9)) {114 fprintf(stderr, "Bad color: %s -- colors shall have format #RGB or #RRGGBB or #RGBA or #RRGGBBAA\n", string);115 exit(1);116 }117 string++; // das "#"-Zeichen braucht keiner mehr118 119 for(numbers_count=0; numbers_count < len-1; numbers_count++) {120 buf[0] = string[numbers_count];121 numbers[numbers_count] = strtol(buf, NULL, 16);122 //printf("Read digit %s = 0x%x\n", buf, numbers[numbers_count]);123 }124 //numbers_count++; // wir zaehlen ab 1 -- komisch, tud er sowieso schon.125 126 if(numbers_count == 3 || numbers_count == 4) {127 // #RGB oder #RGBA128 pattern = cairo_pattern_create_rgba(129 (double)numbers[0] / (double)0xF,130 (double)numbers[1] / (double)0xF,131 (double)numbers[2] / (double)0xF,132 (numbers_count == 4) ? (double)numbers[3] / (double)0xF : 1133 );134 } else {135 // #RRGGBB oder #RRGGBBAA136 pattern = cairo_pattern_create_rgba(137 (double)(numbers[1] + numbers[0]*0x10) / (double)0xFF,138 (double)(numbers[3] + numbers[2]*0x10) / (double)0xFF,139 (double)(numbers[5] + numbers[4]*0x10) / (double)0xFF,140 (numbers_count == 8) ? (double)(numbers[7] + numbers[6]*0x10) / (double)0xFF : 1141 );142 }143 // Fuer Debug-Ausgaben:144 { double r,g,b,a; cairo_pattern_get_rgba(pattern, &r, &g, &b, &a);145 printf("Allocated color #%s as #%x%x%x, opacity %x\n", string, (unsigned int)(r*256), (unsigned int)(g*256), (unsigned int)(b*256), (unsigned int)(a*256)); }146 printf("Farbe fertig.\n");147 return pattern;148 }149 150 error_t parse_option (int key, char *arg, struct argp_state *state) {151 //printf("OPTION %x (%c = %i)...\n", key, key, key);152 switch(key) {153 case 'v':154 verbosity = 1;155 break;156 case 'o': case 'i':157 // Ausgabedatei setzen.158 output_file = arg;159 break;160 case 'w':161 // Breite setzen.162 lochstreifen_set_d_by_width(l, atoi(arg));163 break;164 case 'h':165 // Hoehe setzen.166 lochstreifen_set_d_by_height(l, atoi(arg));167 break;168 case 'd':169 // Durchmesser setzen170 lochstreifen_set_d(l, atoi(arg));171 break;172 case 'f':173 // Dateiformat setzen174 // keine Lust auf enums175 if(strcmp(strtolower(arg), "png") == 0) surface_type = 0;176 else if(strcmp(strtolower(arg), "svg") == 0) surface_type = 1;177 else argp_error(state, "Only PNG and SVG are supported as file formats.\n");178 break;179 case -1:180 // Emptystart-Bytes181 l->empty_start = atoi(arg);182 break;183 case -2:184 // Emptyend-Bytes185 l->empty_end = atoi(arg);186 break;187 case -3:188 // hide imagebg189 l->hintergrund = NULL;190 break;191 case -4:192 // color imagebg193 l->hintergrund = hex2cairo_pattern(arg);194 break;195 case -5:196 // hide tape197 l->streifenbg = NULL;198 break;199 case -6:200 // color tapebg201 l->streifenbg = hex2cairo_pattern(arg);202 break;203 case -7:204 // hide punched205 l->punched = NULL;206 break;207 case -8:208 // color punched209 l->punched = hex2cairo_pattern(arg);210 break;211 case -9:212 // hide notpunched213 l->notpunched = NULL;214 break;215 case -10:216 // color notpunched217 l->notpunched = hex2cairo_pattern(arg);218 break;219 case -11:220 // hide feedholes221 l->fuehrung = NULL;222 break;223 case -12:224 // color fuerhung225 l->fuehrung = hex2cairo_pattern(arg);226 break;227 case -13:228 // rotation229 if(strcmp(arg, "right") == 0) arg = "0";230 else if(strcmp(arg, "bottom") == 0) arg = "1";231 else if(strcmp(arg, "left") == 0) arg = "2";232 else if(strcmp(arg, "top") == 0) arg = "3";233 arg[1] = '\0'; // String ist jetzt auf jeden Fall nur ein zeichen lang234 lochstreifen_set_direction(l, atoi(arg), -1, -1);235 break;236 case -14:237 // horizontal spiegeln238 lochstreifen_set_direction(l, -1, 1, -1);239 break;240 case -15:241 // vertikal spiegeln242 lochstreifen_set_direction(l, -1, -1, 1);243 break;244 //case ARGP_KEY_END:245 //printf("bla...");246 default:247 return ARGP_ERR_UNKNOWN;248 } // switch249 return 0; // success250 }251 252 110 static struct argp argp = { options, parse_option, "[FILE TO READ FROM]", // Als Argument in der ersten Zeile 253 111 "This program uses cairo to draw a punched tape as a PNG or SVG file. Any binary " // Hilfe oben … … 257 115 }; // static struct argp 258 116 117 118 error_t parse_option (int key, char *arg, struct argp_state *state) { 119 //printf("OPTION %x (%c = %i)...\n", key, key, key); 120 switch(key) { 121 case 'v': 122 verbosity = 1; 123 break; 124 case 'o': case 'i': 125 // Ausgabedatei setzen. 126 output_file = arg; 127 break; 128 case 'w': 129 // set length (yeah, the legacy parameters call this width) 130 scale_by = SCALE_BY_LENGTH; 131 scale_target = atoi(arg); 132 //lochstreifen_set_scaling_by_length(l, atoi(arg)); 133 break; 134 case 'h': 135 // set width (yeah, the legacy parameters call this height) 136 scale_by = SCALE_BY_WIDTH; 137 scale_target = atoi(arg); 138 //lochstreifen_set_scaling_by_width(l, atoi(arg)); 139 break; 140 case 'd': 141 // set diameter of code holes 142 scale_by = SCALE_BY_CODE_HOLE; 143 scale_target = atoi(arg); 144 //lochstreifen_set_scaling_by_code_hole(l, atoi(arg)); 145 break; 146 case 'f': 147 // set file format 148 if(strcasecmp(arg, "png") == 0) 149 surface_type = PNG_SURFACE; 150 else if(strcasecmp(arg, "svg") == 0) 151 surface_type = SVG_SURFACE; 152 else 153 argp_error(state, "Only PNG and SVG are supported as file formats.\n"); 154 break; 155 case -1: 156 // set empty bytes at start 157 null_bytes_start = atoi(arg); 158 break; 159 case -2: 160 // set empty bytes at end 161 null_bytes_end = atoi(arg); 162 break; 163 case -3: 164 // hide imagebg 165 l->outer_background_color = NULL; 166 break; 167 case -4: 168 // color imagebg 169 l->outer_background_color = hex2cairo_pattern(arg); 170 break; 171 case -5: 172 // hide tape 173 l->papertape_background_color = NULL; 174 break; 175 case -6: 176 // color tapebg 177 l->papertape_background_color = hex2cairo_pattern(arg); 178 break; 179 case -7: 180 // hide punched 181 l->one_code_hole_color = NULL; 182 break; 183 case -8: 184 // color punched 185 l->one_code_hole_color = hex2cairo_pattern(arg); 186 break; 187 case -9: 188 // hide notpunched 189 l->zero_code_hole_color = NULL; 190 break; 191 case -10: 192 // color notpunched 193 l->zero_code_hole_color = hex2cairo_pattern(arg); 194 break; 195 case -11: 196 // hide feedholes 197 l->feed_hole_color = NULL; 198 break; 199 case -12: 200 // color fuerhung 201 l->feed_hole_color = hex2cairo_pattern(arg); 202 break; 203 case -13: 204 // rotation 205 if (strcasecmp(arg, "right" ) == 0) arg = "0"; 206 else if(strcasecmp(arg, "bottom") == 0) arg = "1"; 207 else if(strcasecmp(arg, "left" ) == 0) arg = "2"; 208 else if(strcasecmp(arg, "top" ) == 0) arg = "3"; 209 arg[1] = '\0'; // shorten string to one character 210 //lochstreifen_set_direction(l, atoi(arg)); 211 lochstreifen_set_rotation(l, atoi(arg)); 212 break; 213 case -14: 214 // horizontal spiegeln 215 //lochstreifen_set_direction(l, -1, 1, -1); 216 break; 217 case -15: 218 // vertikal spiegeln 219 //lochstreifen_set_direction(l, -1, -1, 1); 220 break; 221 //case ARGP_KEY_END: 222 //printf("bla..."); 223 default: 224 return ARGP_ERR_UNKNOWN; 225 } // switch 226 return 0; // success 227 } // function parse_option 228 229 230 /** 231 * Simple helper function to get a SOLID cairo pattern from a hex color string 232 * with formats like 233 * #RGB for example: #FF0 234 * #RGBA #A88F 235 * #RRGGBB #CD438F 236 * #RRGGBBAA #CD438FA0 237 * RGB FF0 238 * RGBA A88F 239 * RRGGBB CD438F 240 * RRGGBBAA CD438FA0 241 * 242 * If this method cannot parse the hex color string, it will print an error message 243 * at stderr and exit the complete program. 244 * 245 * @return a dynamically allocated cairo patern 246 **/ 247 cairo_pattern_t *hex2cairo_pattern(const char *string) { 248 int string_len; // length of string without "#" 249 int x, color; // iterators 250 long color_value[4]; // interpreted numbers 251 char *buf = "xy"; // Buffer for strtol <- one color value 252 253 // remove a "#" char if present 254 if(string[0] == '#') 255 string++; 256 string_len = strlen(string); 257 258 // go throught string 259 for(x=0,color=0; x < string_len && color < 5; x++,color++) { 260 // copy the current character to buffer, first position 261 buf[0] = string[x]; 262 // if short notation (shorter than AABBCC), dublicate 263 // current character to buffer second position, else 264 // copy next character to second position 265 buf[1] = string_len < 6 ? string[x] : string[++x]; 266 // parse buffer contents and save them as one color 267 color_value[color] = strtol(buf, NULL, 16); 268 } 269 270 DPRINTF("Allocating '%s' as #%x%x%x%x\n", string, 271 color_value[0], color_value[1], color_value[2], (color == 4) ? color_value[3] : 0xFF); 272 273 return cairo_pattern_create_rgba( 274 (double) color_value[0] / (double) 0xFF, 275 (double) color_value[1] / (double) 0xFF, 276 (double) color_value[2] / (double) 0xFF, 277 (color == 4) ? (double) color_value[3] / (double) 0xFF : 1 278 ); 279 } 280 281 /** 282 * Helper function: Read contents from a stream (e.g. stdin or a file) into 283 * a byte array. 284 * Expects: stream (FILE) and a pointer to a pointer (for the target array) 285 * It will allocate an array whereby you get the pointer back. 286 * @return length of data array, counting from 1 287 * 288 * I've inspired a bit from glib's g_file_get_contents because my first 289 * version was quite buggy: 290 ***** 291 * Neugeschrieben nach etwas Inspiration von der glib am 05.04.2008. 292 * Funktion get_contents_stdio, gfileutils.c im Sourcecode von glib-2.14.3. 293 * Router natürlich aus (03:11!), aber da sieht man mal wieder den Vorteil von Gentoo: 294 * Gleich alle Sourcecodes auf der Platte =) 295 ***** 296 * 297 **/ 298 int file_get_contents(FILE *stream, byte_t **content) { 299 byte_t buf[4096]; 300 size_t bytes; // gerade eben eingelesene bytes 301 byte_t *str = NULL; 302 size_t total_bytes = 0; // alle bis jetzt eingelesenen bytes 303 size_t total_allocated = 0; 304 byte_t *tmp; // fuers realloc 305 306 while(!feof(stream)) { 307 bytes = fread(buf, 1, sizeof(buf), stream); 308 309 while( (total_bytes + bytes) > total_allocated) { 310 if(str) 311 total_allocated *= 2; 312 else 313 total_allocated = bytes > sizeof(buf) ? bytes : sizeof(buf); 314 315 tmp = realloc(str, total_allocated); 316 317 if(tmp == NULL) { 318 fprintf(stderr, "*** file_get_contents ERROR*** Could not reallocate\n"); 319 //return length; // Fehler - das eingelesene zumindest zurueckgeben. 320 // nee, gar nichts zurückgeben. Das geht so nicht. 321 return 0; 322 } 323 324 str = tmp; 325 } // while innen 326 327 memcpy(str + total_bytes, buf, bytes); 328 total_bytes += bytes; 329 } // while 330 331 if(total_allocated == 0) 332 str = malloc(1); // something empty. Just to be not NULL... 333 //str[total_bytes] = '\0'; // wenns ein string wäre. 334 335 *content = str; 336 return total_bytes; 337 } 338 339 /** 340 * Helper function: A simple closure for a cairo_surface_t (PNG and SVG) to write out data 341 * either to a file or to stdout (given in first parameter) 342 **/ 259 343 cairo_status_t lochstreifen_out_closure(void *closure, unsigned char *data, unsigned int length) { 260 261 262 344 // einfach nur in das uebergebene Dateihandle schreiben 345 fwrite(data, length, 1, (FILE *)closure); 346 return CAIRO_STATUS_SUCCESS; 263 347 } 264 348 349 /** 350 * The main routine. 351 **/ 265 352 int main(int argc, char *argv[]) { 266 //unsigned char data[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; 267 /*int x; 268 unsigned char data[256]; 269 for(x=0;x<256;x++) { 270 data[x] = (unsigned char) x; 271 } 272 draw_lochstreifen(256, data); 273 return 0;*/ 274 LOCHSTREIFEN *lochstreifen; 275 cairo_t *cr; 276 cairo_surface_t *surface; 277 byte_t *data; 278 int length; // laenge des *data-Arrays 279 FILE *out; 280 int input_argc; // Index der argv-Option, wo die zu handelnden Dateien stehen. 281 l = lochstreifen_new(); 282 lochstreifen = l; 283 284 // Argumente parsen 285 argp_parse(&argp, argc, argv, 0, &input_argc, NULL); 286 287 //DPRINTF("Stop.\n"); 288 //return 0; 289 290 // Daten einlesen 291 if(input_argc < argc) { 292 FILE *fh; 293 DPRINTF("Reading from file %s\n", argv[input_argc]); 294 fh = fopen(argv[input_argc], "r"); 295 296 if(fh == NULL) { 297 perror("opening input file"); 298 exit(1); 299 } 300 301 length = file_get_contents(fh, &data); 302 fclose(fh); 303 } else { 304 DPRINTF("Reading from stdin, type [STRG]+[D] to generate paper tape from data\n"); 305 length = file_get_contents(stdin, &data); 306 } 307 DPRINTF("Read in %d bytes\n", length); 308 309 // Ausgabestream oeffnen 310 if(output_file != NULL) { 311 out = fopen(output_file, "w"); 312 313 if(out == NULL) { 314 perror("opening output file"); 315 exit(1); 316 } 317 DPRINTF("File %s successfully opened for writing\n", output_file); 318 } else { 319 DPRINTF("Writing image data to stdout\n"); 320 out = stdout; 321 } 322 323 /*int x; 324 for(x=0; x<length; x++) { 325 printf("%i von %i: 0x%x (=%c)\n", x, length, data[x], data[x]); 326 }*/ 327 328 lochstreifen_set_data(l, length, data, -1, -1); 329 330 // Surface erstellen 331 if(surface_type == 0) { // PNG 332 cairo_status_t status; 333 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 334 lochstreifen_get_width(l), 335 lochstreifen_get_height(l) 336 ); 337 cr = cairo_create(surface); 338 lochstreifen_draw(l, cr); 339 340 status = cairo_surface_write_to_png_stream(surface, (cairo_write_func_t)lochstreifen_out_closure, out); 341 DPRINTF("paper tape PNG generated: %s\n", cairo_status_to_string(status)); 342 } else if(surface_type == 1) { // SVG 343 surface = (cairo_surface_t *)cairo_svg_surface_create_for_stream( 344 (cairo_write_func_t)lochstreifen_out_closure, out, 345 (double)lochstreifen_get_width(l), 346 (double)lochstreifen_get_height(l)); 347 348 cr = cairo_create(surface); 349 lochstreifen_draw(l, cr); 350 DPRINTF("paper tape SVG generated: %s\n", cairo_status_to_string(cairo_surface_status(surface))); 351 } else { 352 fprintf(stderr, "Bad Surface Type %i", surface_type); 353 return -42; 354 } // if surface_type 355 356 return 0; 353 cairo_t *cr; ///< A cairo context, given from... 354 cairo_surface_t *surface; ///< ...this generic cairo surface 355 byte_t *data; ///< the data array, will be filled by file_get_contents 356 int length; ///< the length of that data array 357 FILE *out; ///< an output stream handle (stdout or a file) 358 int input_argc; ///< argp: index of argv argument where the filenames are stored 359 360 // now starting... 361 l = lochstreifen_new(); 362 argp_parse(&argp, argc, argv, 0, &input_argc, NULL); 363 364 // read input data to data array 365 if(input_argc < argc && argv[input_argc][0] != '-') { 366 // open a file (which name is not "-", because this shall read from STDIN) 367 FILE *fh; 368 DPRINTF("Reading from file %s\n", argv[input_argc]); 369 fh = fopen(argv[input_argc], "r"); 370 371 if(fh == NULL) { 372 perror("opening input file"); 373 exit(1); 374 } 375 376 length = file_get_contents(fh, &data); 377 fclose(fh); 378 } else { 379 DPRINTF("Reading from stdin, type [STRG]+[D] to generate paper tape from data\n"); 380 length = file_get_contents(stdin, &data); 381 } 382 383 DPRINTF("Successfully read in %d bytes to RAM\n", length); 384 385 // now after bytes are read in, we can setup the LOCHSTREIFEN 386 // correctly: 387 lochstreifen_set_data(l, length, data); 388 if(scale_target != 0) { // initialized 389 switch(scale_by) { 390 case SCALE_BY_LENGTH: 391 lochstreifen_set_scaling_by_length(l, scale_target); 392 break; 393 case SCALE_BY_WIDTH: 394 lochstreifen_set_scaling_by_width(l, scale_target); 395 break; 396 case SCALE_BY_CODE_HOLE: 397 lochstreifen_set_scaling_by_code_hole(l, scale_target); 398 } 399 } 400 // add null bytes 401 lochstreifen_add_null_bytes(l, null_bytes_start, null_bytes_end); 402 403 // open output stream 404 if(output_file != NULL) { // check if there was an argv argument 405 out = fopen(output_file, "w"); 406 407 if(out == NULL) { 408 perror("opening output file"); 409 exit(1); 410 } 411 DPRINTF("Opened file '%s' for writing\n", output_file); 412 } else { 413 DPRINTF("Writing output data to stdout\n"); 414 out = stdout; 415 } 416 417 lochstreifen_print_debug(l); 418 exit(0); 419 420 // setting up the surface and painting... 421 if(surface_type == PNG_SURFACE) { 422 cairo_status_t status; 423 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 424 lochstreifen_get_target_width(l), 425 lochstreifen_get_target_height(l) 426 ); 427 cr = cairo_create(surface); 428 lochstreifen_draw(l, cr); 429 430 status = cairo_surface_write_to_png_stream(surface, (cairo_write_func_t)lochstreifen_out_closure, out); 431 DPRINTF("PNG file generated: %s\n", cairo_status_to_string(status)); 432 return 0; 433 } else if(surface_type == SVG_SURFACE) { 434 surface = cairo_svg_surface_create_for_stream( 435 (cairo_write_func_t)lochstreifen_out_closure, out, 436 lochstreifen_get_target_width(l), 437 lochstreifen_get_target_height(l) 438 ); 439 cr = cairo_create(surface); 440 lochstreifen_draw(l, cr); 441 442 DPRINTF("SVG file generated: %s\n", cairo_status_to_string(cairo_surface_status(surface))); 443 return 0; 444 } else { 445 fprintf(stderr, "This surface is not possible, because surface_typ is an enum.\n"); 446 return -42; 447 } // if surface_type 357 448 } // main -
visualisator/lochstreifen.c
r9 r18 1 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 **/ 2 * The Paper Tape Project -- Visualisation sub project 3 * lochstreifen.c - Painting Paper Tapes according to ECMA-10, with cairographics. 4 * $Id$ 5 * 6 * This is a rewrite from the famous Cairo paper tape drawing routines. This 7 * c file implements a (simple) object called "LOCHSTREIFEN". 8 * 9 * 10 * 11 * 12 * 13 * (c) Copyright 2007, 2008 Sven Köppel 14 * 15 * This program is free software; you can redistribute 16 * it and/or modify it under the terms of the GNU General 17 * Public License as published by the Free Software 18 * Foundation; either version 3 of the License, or (at 19 * your option) any later version. 20 * 21 * This program is distributed in the hope that it will 22 * be useful, but WITHOUT ANY WARRANTY; without even the 23 * implied warranty of MERCHANTABILITY or FITNESS FOR A 24 * PARTICULAR PURPOSE. See the GNU General Public License 25 * for more details. 26 * 27 * You should have received a copy of the GNU General 28 * Public License along with this program; if not, see 29 * http://www.gnu.org/licenses/ 30 * 31 **/ 32 39 33 #include <math.h> 40 34 #include <stdio.h> 41 35 #include <stdlib.h> 42 36 #include <string.h> 43 44 37 #include "lochstreifen.h" 45 38 46 #define DEBUG 1 47 48 int 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 145 void 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 39 /** 40 * Create a new LOCHSTREIFEN object and return it. This is a quite light 41 * object system implementation, as you get a reference to the object. 42 * You are not supposed to manipulate the elements of the LOCHSTREIFEN 43 * structure directly. 44 * 45 * Btw, the german word "LOCHSTREIFEN" only means "PAPER TAPE". 46 * 47 **/ 153 48 LOCHSTREIFEN *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 179 void 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 190 void 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 196 int 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 209 int 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 218 void 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 230 int 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 235 int 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 245 int lochstreifen_get_height(LOCHSTREIFEN *l) { 246 /** Berechnet aktuelle Hoehe aus Lochstreifenkonstanten */ 247 return (l->drehung % 2 == 1) ? LOCHSTREIFEN_WIDTH : LOCHSTREIFEN_HEIGHT; 248 } 249 250 void 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 268 void 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 281 void 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 /* 324 void 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 335 void 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 350 int 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 374 int 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 49 LOCHSTREIFEN *l = malloc (sizeof(LOCHSTREIFEN)); 50 51 // set default values: 52 l->data_length = 0; 53 l->data = NULL; 54 l->highlight_region_start = 0; 55 l->highlight_region_end = 0; 56 l->highlight_region_color = NULL; 57 l->highlight_row_number = 0; 58 l->highlight_row_color = NULL; 59 l->highlight_bit_row = 0; 60 l->highlight_bit_track = 0; 61 l->highlight_bit_color = NULL; 62 l->clip = NULL; 63 l->outer_background_color = LOCHSTREIFEN_DEFAULT_OUTER_BACKGROUND_COLOR; 64 l->papertape_background_color = LOCHSTREIFEN_DEFAULT_PAPERTAPE_BACKGROUND_COLOR; 65 l->one_code_hole_color = LOCHSTREIFEN_DEFAULT_ONE_CODE_HOLE_COLOR; 66 l->zero_code_hole_color = LOCHSTREIFEN_DEFAULT_ZERO_CODE_HOLE_COLOR; 67 l->feed_hole_color = LOCHSTREIFEN_DEFAULT_FEED_HOLE_COLOR; 68 l->matrix = malloc (sizeof(cairo_matrix_t)); 69 // default matrix: 1:1 original. 70 l->matrix->xx = 1; l->matrix->yx = 0; 71 l->matrix->xy = 0; l->matrix->yy = 1; 72 l->matrix->x0 = 0; l->matrix->y0 = 0; 73 74 return l; 75 } 76 77 /** 78 * A small debug function that will print out all fields of the LOCHSTREIFEN 79 * structure well ordered to stderr. 80 * 81 **/ 82 void lochstreifen_print_debug(LOCHSTREIFEN* l) { 83 int x; 84 #define COLORP(color) if(color == NULL) fprintf(stderr, " color ist NULL.\n"); \ 85 else if(cairo_pattern_get_type(color) == CAIRO_PATTERN_TYPE_SOLID) {\ 86 double r,g,b,a; cairo_pattern_get_rgba(color, &r, &g, &b, &a); \ 87 fprintf(stderr, " SOLID: R=%f, G=%f, B=%f, A=%f\n", r, g, b, a); \ 88 } else fprintf(stderr, " NO SOLID PATTERN (special pattern)\n"); 89 #define COLORP_VERBOSE(color1, name) \ 90 fprintf(stderr, " * "name": %s\n", (color1) != NULL ? "ENABLED" : "disabled");\ 91 COLORP(color1); 92 93 94 if(l != NULL) 95 fprintf(stderr, "Debugging papertape at %x:\n", l); 96 else { 97 fprintf(stderr, "Cannot debug: Papertape is NULL!\n"); 98 return; 99 } 100 101 // 1. Point: Print out data. 102 fprintf(stderr, "1# DATA AND OUTPUT IMAGE SIZE INFORMATION\n"); 103 fprintf(stderr, " * Data: length=%i bytes", l->data_length); 104 if(l->data_length > 0 && l->data != NULL) { 105 // there are data 106 fprintf(stderr, ":\n { "); 107 for(x=0;;) { 108 fprintf(stderr, "0x%x", l->data[x]); 109 if(++x == l->data_length) { 110 fprintf(stderr, " };\n"); 111 break; 112 } else if(x == 10) { // magic number: print first 10 bytes. 113 fprintf(stderr, ", ... };\n"); 114 break; 115 } else 116 fprintf(stderr, ", "); 117 } 118 } else if(l->data == NULL) { 119 fprintf(stderr, " BUT data are NULL!\n"); 120 } else // data_length == 0. 121 fprintf(stderr, " (empty data)\n"); 122 fprintf(stderr, " * Unscaled dimensions:\n"); 123 fprintf(stderr, " width of image (length of papertape) = %f\n", lochstreifen_get_length(l)); 124 fprintf(stderr, " height of image (width of papertape) = 1\n"); 125 126 // 2. Point: Print out colors 127 fprintf(stderr, "\n2# ELEMENT COLORS\n"); 128 COLORP_VERBOSE(l->outer_background_color, "outer background"); 129 COLORP_VERBOSE(l->papertape_background_color, "papertape background"); 130 COLORP_VERBOSE(l->one_code_hole_color, "one code holes"); 131 COLORP_VERBOSE(l->zero_code_hole_color, "zero code holes"); 132 COLORP_VERBOSE(l->feed_hole_color, "feed holes"); 133 134 // 3. Point: Print out highlighted thingies 135 fprintf(stderr, "\n3# HIGHLIGHT COLORS\n"); 136 fprintf(stderr, l->highlight_region_color != NULL ? " * Highlight region: start=%i end=%i\n" 137 : " * Highlight region: disabled\n", l->highlight_region_start, l->highlight_region_end); 138 COLORP(l->highlight_region_color); 139 fprintf(stderr, l->highlight_row_color != NULL ? " * Highlight row: number=%i\n" 140 : " * Highlight row: disabled\n", l->highlight_row_number); 141 COLORP(l->highlight_row_color); 142 fprintf(stderr, l->highlight_bit_color != NULL ? " * Higlight bit: row=%i track=%i\n" 143 : " * Highlight bit: disabled\n", l->highlight_bit_row, l->highlight_bit_track); 144 COLORP(l->highlight_bit_color); 145 146 // 4. Point: Print out information about clippings 147 fprintf(stderr, "\n4# SPECIAL STRUCTURES\n"); 148 if(l->clip == NULL) 149 fprintf(stderr, " * Clipping: disabled\n"); 150 else { 151 fprintf(stderr, " * Clipping: ENABLED\n"); 152 fprintf(stderr, " x=%f, y=%f, width=%f, height=%f\n", 153 l->clip->x, l->clip->y, l->clip->width, l->clip->height); 154 } 155 156 // 5. Point: Affine Matrix 157 if(l->matrix == NULL) 158 fprintf(stderr, " * Matrix: disabled\n"); 159 else { 160 fprintf(stderr, " * Matrix: ENABLED\n"); 161 fprintf(stderr, " x_new = [xx=%f]*x + [xy=%f]*y + [x0=%f]\n", 162 l->matrix->xx, l->matrix->xy, l->matrix->x0); 163 fprintf(stderr, " y_new = [yx=%f]*x + [yy=%f]*y + [y0=%f]\n", 164 l->matrix->yx, l->matrix->yy, l->matrix->y0); 165 fprintf(stderr, " source dimensions: x_max = %f x y_max = %f\n", 166 LOCHSTREIFEN_LENGTH, LOCHSTREIFEN_WIDTH); 167 fprintf(stderr, " target dimensions: width = %i x height = %i\n", 168 lochstreifen_get_target_width(l), 169 lochstreifen_get_target_height(l)); 170 } 171 172 // 6. Point: Debugging 173 fprintf(stderr, " * Debugging: %s\n", l->debug ? "ENABLED" : "disabled"); 174 175 fprintf(stderr, "END OF LOCHSTREIFEN\n"); 176 } 177 178 /** 179 * Set the data which LOCHSTREIFEN is supposed to punch out. You shall give 180 * the LOCSTREIFEN object only a copy of your data, never give it a sensible 181 * data array. The LOCHSTREIFEN object won't write into your data, but afterwards 182 * it will free them. So it treats the data as it's own. 183 * 184 **/ 185 void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data) { 186 l->data_length = data_length; 187 if(l->data != NULL) 188 free(l->data); 189 l->data = data; 190 } 191 192 /** 193 * Adds Null Bytes (0x00) at start and/or end of the data array. This dynamically 194 * increases the data array. 195 * 196 * 197 **/ 198 void lochstreifen_add_null_bytes(LOCHSTREIFEN *l, int start, int end) { 199 byte_t *new_data; 200 201 // only to be sure realloc won't decrease the size of the array: 202 if(start < 0) start = 0; 203 if(end < 0) end = 0; 204 205 // make array bigger to contain new start/end chunks 206 new_data = realloc(l->data, l->data_length + start + end); 207 // check wheter realloc exited successfully. We don't want segfaults 208 if(new_data == NULL) 209 return; 210 // move data to the middle 211 memmove(new_data + start, new_data, l->data_length); 212 // fill new start chunk with zero bytes 213 memset(new_data, 0x00, start); 214 // fill new end chunk with zero bytes 215 memset(new_data + start + l->data_length, 0x00, end); 216 // that's it. 217 218 // fix the data link. Don't free the old data. Don't know exactly 219 // how realloc works, sorry ;-) 220 l->data = new_data; 221 } 222 223 /** 224 * Get the length of a LOCHSTREIFEN. It depends on the length of the data array 225 * and the papertape dimension constants. 226 * 227 * 228 **/ 229 double lochstreifen_get_length(LOCHSTREIFEN *l) { 230 return LOCHSTREIFEN_LENGTH; 231 } 232 233 234 /** 235 * Tell LOCHSTREIFEN to highlight a region of rows. Start counts from 0 and is already 236 * in the selection, end is no more in selection. Example with start = 2; end = 5: 237 * 238 * 0 1 2 3 4 5 6 <- rows 239 * |_________________| 240 * highlight region 241 **/ 242 void lochstreifen_set_highlight_region(LOCHSTREIFEN *l, int start, int end) { 243 l->highlight_region_start = start; 244 l->highlight_region_end = end; 245 if(l->highlight_region_color == NULL) 246 l->highlight_row_color = LOCHSTREIFEN_DEFAULT_HIGHLIGHT_REGION_COLOR; 247 } 248 249 /** 250 * Get the selection bounds of the highlighted rows. Give Links to your variables 251 * where the function stores the start/end integers. 252 * @return TRUE if there is an highlight selection, FALSE otherwiese 253 **/ 254 int lochstreifen_get_highlight_region(LOCHSTREIFEN *l, int *start, int *end) { 255 if(l->highlight_region_color == NULL) 256 return 0; 257 if(start != NULL) 258 *start = l->highlight_region_start; 259 if(end != NULL) 260 *end = l->highlight_region_end; 261 return 1; 262 } 263 264 /** 265 * Remove the highlighted region (that is, make it no more highlighted). 266 **/ 267 void lochstreifen_remove_highlight_region(LOCHSTREIFEN *l) { 268 l->highlight_region_color = NULL; 269 } 270 271 /** 272 * Tell LOCHSTREIFEN to highlight one, only one special row. Starts counting from 0. 273 * Example with start = 3: 274 * 275 * 0 1 2 3 4 5 276 * |_____| 277 * highlighted row 278 * 279 * Principally this is the same feature like lochstreifen_set_highlight_region, having 280 * (in the above example) start = 3 and end = 4. You can just use another color and 281 * use both techniques concurrently, whereby the highlighted row will ALWAYS be ABOVE 282 * the highlighted chunk of rows. An application example is e.g.: The highlighted region 283 * of rows are selected rows, the highlighted special row is the cursor position row. 284 * This would be quite usable with an implementation of the GtkEditable interface, like 285 * GtkPaperTape. 286 **/ 287 void lochstreifen_set_highlight_row(LOCHSTREIFEN *l, int number_of_row) { 288 l->highlight_row_number = number_of_row; 289 if(l->highlight_row_color == NULL) 290 l->highlight_row_color = LOCHSTREIFEN_DEFAULT_HIGHLIGHT_ROW_COLOR; 291 } 292 293 /** 294 * Get the highlighted special row. If there is no highlighted row, it will return a value 295 * less than zero (e.g. -1). 296 * @return the number of the special row, counting from zero. 297 **/ 298 int lochstreifen_get_highlight_row(LOCHSTREIFEN *l) { 299 return (l->highlight_row_color == NULL) ? -1 : l->highlight_row_number; 300 } 301 302 /** 303 * Remove the highlight at the special selected row. 304 **/ 305 void lochstreifen_remove_highlight_row(LOCHSTREIFEN *l) { 306 //l->highlight_row_color = NULL; /// nein, das ist dumm, weil es den highlight komplett entfernen würde. 307 l->highlight_row_number = -1; // das ist schlau. 308 } 309 310 /** 311 * Tell LOCHSTREIFEN to highlight one special bit on the complete papertape. To identify 312 * this bit, you give the row and track number (byte id and bit id) for this bit. E.g. 313 * with row = 3, bit = 5 you'll get something like: 314 * 315 * ------- DIRECTION OF MOVEMENT -------> 316 * track 8 8 8 8 8 8 317 * track 7 7 7 7 7 7 318 * track 6 6 6 +-----+ 6 6 319 * track 5 5 5 | 5 | 5 5 (of course the highlight won't affect any 320 * track 4 4 4 +-----+ 4 4 other bit, row 3, track 6 and track 4 321 * feed - - - - - - are not visible due to ASCII limitations 322 * track 3 3 3 3 3 3 ;-) ) 323 * track 2 2 2 2 2 2 324 * track 1 1 1 1 1 1 325 * 326 * row: 0 1 2 3 4 5 327 * ^-- this row 328 * 329 * The bit highlight will appear on top of the row highlight and region highlight. You 330 * can combine the bit highlight with row highlight (e.g. in the example above you can 331 * highlight row 3, too) and even with the region highlight (e.g. having a region from 332 * row 2 to row 5). 333 **/ 334 void lochstreifen_set_highlight_bit(LOCHSTREIFEN *l, int number_of_row, int number_of_bit) { 335 l->highlight_bit_row = number_of_row; 336 l->highlight_bit_track = number_of_bit; 337 if(l->highlight_bit_color == NULL) 338 l->highlight_bit_color = LOCHSTREIFEN_DEFAULT_HIGHLIGHT_BIT_COLOR; 339 } 340 341 /** 342 * Get the highlighted special bit. This works exactly like lochstreifen_get_highlight_region, 343 * returning FALSE (0) if there's no bit selected. 344 * 345 **/ 346 int lochstreifen_get_highlight_bit(LOCHSTREIFEN *l, int *number_of_row, int *number_of_bit) { 347 if(l->highlight_bit_color == NULL) 348 return 0; 349 if(number_of_row != NULL) 350 *number_of_row = l->highlight_bit_row; 351 if(number_of_bit != NULL) 352 *number_of_bit = l->highlight_bit_track; 353 return 1; 354 } 355 356 /** 357 * Remove the highlighting of the special bit. 358 **/ 359 void lochstreifen_remove_highlight_bit(LOCHSTREIFEN *l) { 360 l->highlight_bit_color = NULL; 361 } 362 363 /** 364 * If you want LOCHSTREIFEN only to paint a small area from the whole papertape, this 365 * is the function you can call. 366 * 367 **/ 368 void lochstreifen_set_clip(LOCHSTREIFEN *l, double x, double y, double width, double height) { 369 if(l->clip == NULL) 370 l->clip = malloc(sizeof(cairo_rectangle_t)); 371 l->clip->x = x; 372 l->clip->y = y; 373 l->clip->width = width; 374 l->clip->height = height; 375 } 376 377 /** 378 * I fyou want LOCHSTREIFEN no more to paint only a small area but the whole paper tape, 379 * simply call this function. 380 **/ 381 void lochstreifen_remove_clip(LOCHSTREIFEN *l) { 382 free(l->clip); 383 l->clip = NULL; // not neccessary, I suppose. 384 } 385 386 /** 387 * Affect the current transformation matrix so the papertape finally has a length of 388 * exactly the value given in the argument, in pixels. The length depends from the 389 * number of rows on the papertape, so the length will increase if you increase the 390 * number of rows after calling lochstreifen_set_scaling_by_length. 391 **/ 392 void lochstreifen_set_scaling_by_length(LOCHSTREIFEN *l, int length) { 393 double scale_factor = ((double)length) / LOCHSTREIFEN_LENGTH; 394 printf("Scaling to length=%i, having length=%f, getting %f as scale factor\n", 395 length, LOCHSTREIFEN_LENGTH, scale_factor); 396 cairo_matrix_scale(l->matrix, scale_factor, scale_factor); 397 } 398 399 void lochstreifen_set_scaling_by_width(LOCHSTREIFEN *l, int width) { 400 double scale_factor = ((double)width) / LOCHSTREIFEN_WIDTH; 401 cairo_matrix_scale(l->matrix, scale_factor, scale_factor); 402 } 403 404 void lochstreifen_set_scaling_by_code_hole(LOCHSTREIFEN *l, int diameter) { 405 double scale_factor = ((double)diameter)/2 / LOCHSTREIFEN_RADIUS_CODE_HOLE; 406 cairo_matrix_scale(l->matrix, scale_factor, scale_factor); 407 } 408 409 /** 410 * Get the dimensions of the paper tape in the output image. Be careful: While 411 * width/length are well defined in the LOCHSTREIFEN process, hereby width and 412 * height mean the dimensions of the rectangular surface picture. 413 * If you need only the value of one dimension, use 414 * lochstreifen_get_target_width or lochstreifen_get_target_height, respectively. 415 * 416 * The calculation of these values is quite expensive, so you do well when 417 * caching the results. 418 * @return nothing, because Call-by-Reference. 419 **/ 420 void lochstreifen_get_target_dimensions(LOCHSTREIFEN *l, int *width, int *height) { 421 int i; 422 // preset the dimensions to 0 423 if(width != NULL) *width = 0; 424 if(height != NULL) *height = 0; 425 // define the "bounding box" where the papertape resides in 426 // user space cordinates (like lochstreifen_draw paints) 427 double x[] = { 0, LOCHSTREIFEN_LENGTH, 0, LOCHSTREIFEN_LENGTH }; 428 double y[] = { 0, 0, LOCHSTREIFEN_WIDTH, LOCHSTREIFEN_WIDTH }; 429 // transform the "bounding box" throught the matrix 430 for(i=0; i < (sizeof(x) / sizeof(double)); i++) { 431 cairo_matrix_transform_point(l->matrix, &x[i], &y[i]); 432 // store biggest x/y values 433 if(width != NULL && x[i] > *width) 434 *width = x[i]; 435 if(height != NULL && y[i] > *height) 436 *height = y[i]; 437 } 438 } 439 440 /** 441 * Get width of the output picture. This is only a nicer frontend to 442 * lochstreifen_get_target_dimensions that returns the width value. 443 **/ 444 int lochstreifen_get_target_width(LOCHSTREIFEN *l) { 445 int width; 446 lochstreifen_get_target_dimensions(l, &width, NULL); 447 return width; 448 } 449 450 /** 451 * Get height of the output picture. This is only a nicer frontend to 452 * lochstreifen_get_target_dimensions that returns the height value. 453 **/ 454 int lochstreifen_get_target_height(LOCHSTREIFEN *l) { 455 int height; 456 lochstreifen_get_target_dimensions(l, NULL, &height); 457 return height; 458 } 459 460 /** 461 * Get the row number from an x/y target cordinate. That is: At first, translate 462 * the points with the current translation matrix, afterwards calculate the row 463 * number for the position. 464 * 465 * @returns Row number, counting from zero. Negative value if point not on papertape data chunk. 466 **/ 467 int lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y) { 468 // transform points 469 // zunächst ganz blöd: Matrix zur Laufzeit invertieren. 470 cairo_matrix_t invert = *l->matrix; // copy matrix 471 if(cairo_matrix_invert(&invert) != CAIRO_STATUS_SUCCESS) { // invert the copy 472 // there are some matrizes which are not invertable 473 fprintf(stderr, "lochstreifen_get_target_row_from_point: Matrix is not invertable!\n"); 474 return -1; 475 } 476 cairo_matrix_transform_point(&invert, &x, &y); // transform points 477 478 // now calculate position. 479 // check if we are on data: 480 if(y < 0 || y > LOCHSTREIFEN_WIDTH || x < LOCHSTREIFEN_TEAR_OFF_LENGTH || x > (LOCHSTREIFEN_LENGTH - LOCHSTREIFEN_TEAR_OFF_LENGTH)) 481 return -2; 482 // getting the row from the x value. This is pretty much the same algorithm 483 // like used in papertape_draw for checking up the rectangle bounding box (clipping). 484 return floor ( 485 (x - LOCHSTREIFEN_TEAR_OFF_LENGTH) / LOCHSTREIFEN_ROW_DISTANCE 486 ); 487 488 } 489 490 /** 491 * 492 * Just to be sure that there are no misunderstandings: Rotation (wiht cairo) 493 * principally works like this: 494 * 495 * | B----D 496 * | V | 497 * 180° | | V | 498 * D--------C | V | 270° 499 * |>>>>>>>>| | | V | 500 * B--------A A----C 501 * | 502 * - - - - - -+------------------------> x axis 503 * | . 504 * C----A | A------------B . 505 * | ^ | | |<<<<<<<<<<<<| . 506 * 90° | ^ | | C------------D . 507 * | ^ | | original . <- borders of the target surface 508 * | ^ | |....................+ 509 * D----B | 510 * V 511 * y axis 512 * 513 * Unfortunately every rotated box would be outside of the target surface 514 * (e.g. an 200x100px PNG image), thus we must move the matrix inside the 515 * positive x/y axis intercept. 516 * This can be performed quite simple 517 * 518 **/ 519 void lochstreifen_set_rotation(LOCHSTREIFEN *l, enum lochstreifen_direction direction) { 520 switch(direction) { 521 case LOCHSTREIFEN_MOVEMENT_TO_LEFT: 522 // standard 523 case LOCHSTREIFEN_MOVEMENT_TO_TOP: 524 //cairo_matrix_rotate(); 525 case LOCHSTREIFEN_MOVEMENT_TO_RIGHT: 526 case LOCHSTREIFEN_MOVEMENT_TO_BOTTOM: 527 case LOCHSTREIFEN_ROTATION_CLOCKWISE: 528 case LOCHSTREIFEN_ROTATION_ANTICLOCKWISE: 529 case LOCHSTREIFEN_MOVEMENT_NONE: 530 default: 531 break; 532 } 533 } 534 535 536 /** 537 * The very central main function for the LOCHSTREIFEN object: Drawing. 538 * You are supposed to create an adequate cairo context. 539 * 540 * This basic drawing function will draw relative to the width of the 541 * paper tape, like defined as 1 inch in the ECMA-10 standard. This 542 * width will have the value "1". 543 * 544 * Your cropping/... blub shall treat hereby. blabla. 545 **/ 392 546 void 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 alt 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 cairo_set_source(cr, l->fuehrung); 469 cairo_rectangle(cr, l->only_start_x, l->only_start_y, l->only_width, l->only_height); 470 //printf("Only: %d|%d, %d * %d\n", l->only_start_x, l->only_start_y, l->only_width, l->only_height); 471 cairo_paint(cr); 472 473 // Hintergrundfarbe zeichnen. 474 if(0||l->hintergrund != NULL) { 475 //l->hintergrund = cairo_pattern_create_rgb(1,1,1); 476 cairo_set_source(cr, l->hintergrund); 477 cairo_paint(cr); 478 } 479 480 // sache zeichnen 481 cairo_set_source(cr, l->streifenbg); 482 cairo_rectangle(cr, -10, -10, width+20, height+20); 483 cairo_stroke(cr); 484 if(0==1){ 485 double x,y, a,b; 486 int xx,yy,aa,bb; 487 x=0;y=0; a=width;b=height; 488 cairo_matrix_transform_point(&matrix, &x, &y); 489 cairo_matrix_transform_point(&matrix, &a, &b); 490 xx=(int)x;yy=(int)y;aa=(int)a;bb=(int)b; 491 printf("Punkt (0/0)=(%i|%i) und (%i|%i)=(%i/%i)\n", xx, yy, width, height, aa, bb); 492 } 493 494 // Lochstreifenhintergrund inklusive Abriss vorne/hinten malen 495 if(l->streifenbg != NULL) { 496 cairo_set_source(cr, l->streifenbg); 497 498 // Abriss vorne 499 cairo_move_to(cr, l->margin + l->abriss*0.8, l->margin); // oben rechts 500 cairo_line_to(cr, l->margin, l->margin + l->padding+ 3*l->d + 2*l->hspace + l->fspace/2); // genau die fspace-Mitte 501 cairo_line_to(cr, l->margin + l->abriss, height - l->margin); // unten ganz rechts 502 cairo_line_to(cr, l->margin + l->abriss, l->margin); // nach oben ganz rechts... 503 cairo_close_path(cr); // schliessen 504 // normaler Bereich 505 cairo_rectangle(cr, l->margin + l->abriss, l->margin, 506 width - 2*l->margin - 2*l->abriss, height - 2*l->margin); 507 /*printf("Zeichne Rechteck x|y = (%d|%d) width*height = %d * %d\n", 508 l->margin + l->abriss, l->margin, 509 width - 2*l->margin - 2*l->abriss, height - 2*l->margin 510 );*/ 511 // Abriss hinten... 512 cairo_move_to(cr, width - l->margin - l->abriss*0.2, l->margin); // oben mitte 513 cairo_line_to(cr, width - l->margin - l->abriss, 514 l->margin + l->padding + 3*l->d+ 2*l->hspace + l->fspace/2); // genau die fspace-Mitte 515 cairo_line_to(cr, width - l->margin, height - l->margin); // unten ganz rechts 516 cairo_line_to(cr, width - l->margin - l->abriss, height - l->margin); // unten ganz links 517 cairo_line_to(cr, width - l->margin - l->abriss, l->margin); // nach oben zum schliessen 518 cairo_close_path(cr); 519 520 cairo_fill(cr); 521 } 522 523 524 // Lochstreifenlöcher malen 525 526 /*if(l->only_start_x > 0) { 527 // nur in bestimmten Bereich zeichnen 528 int start_byte = l->empty_start + lochstreifen_byte_by_coordinate(l, l->only_start_x, l->only_start_y); // absolut inkl. empty bytes 529 530 } else byte = -l->empty_start; // leere Bytes vorne eingeschlossen 531 }*/ 532 533 // Bytes durchgehen, leere Bytes vorne/hinten mit eingeschlossen 534 for(byte = -l->empty_start, x=l->margin + l->abriss; byte < l->data_length + l->empty_end; x += l->d + l->bspace, byte++) { 535 // Clipping: Um unnoetiges Zeichnen zu ersparen, erst ab X-Koordinate zeichnen 536 if(x < l->only_start_x - (l->d + l->bspace)) continue; // - 1x Loch weniger, damit nicht ein gerade abgeschnittenes nichtgezeichnet wird 537 // und nur bis zur rechten Begrenzung zeichnen -- dannach genuegt Abbruch. 538 if(l->only_width != 0 && x > l->only_start_x + l->only_width) break; 539 540 // ggf. Byte hervorheben 541 if(byte == l->highlight_byte && l->highlight_color != NULL) { 542 cairo_set_source(cr, l->highlight_color); 543 cairo_rectangle(cr, x - l->bspace/2, l->margin, l->df*2 + l->bspace, height - 2*l->margin); 544 cairo_fill(cr); 545 } 546 547 // Bits des entsprechenden Bytes durchgehen 548 for(loch=0, y = l->margin + l->padding; loch < 8; y += l->d + l->hspace, loch++) { 549 // Clipping: Erst ab Y-Koordinate zeichnen (-1xLoch-Korrektur gegen Abschnitt) 550 if(y < l->only_start_y - (l->d - l->hspace)) continue; 551 // bis zur unteren Begrenzung -- anschliessend Abbruch 552 if(l->only_height != 0 && y > l->only_start_y + l->only_height) break; 553 554 // Ggf. Lochstreifenfuehrung zeichnen 555 if(loch==3 && l->fuehrung != NULL) { 556 // Nur vor dem 3. Loch (wenn ueberhaupt) 557 y -= l->hspace; // den Abstand vom vorherigen Loch wieder wegnehmen 558 cairo_set_source(cr, l->fuehrung); 559 cairo_arc(cr, x+l->d/2, y+l->fspace/2, l->df/2, 0., 2*M_PI); 560 cairo_fill(cr); 561 y += l->fspace; 562 } else if(loch == 3) // 3. Loch, aber keine Fuehrung zeichnen => Platz freilassen! 563 y += l->fspace - l->hspace; 564 565 // Debugausgaben machen? 566 if(l->debug != 0 && byte >= 0 && byte < l->data_length) { 567 if(loch == 0) printf("byte %3i von %3i: 0x%2x = ", byte, l->data_length, l->data[byte]); 568 fprintf(stderr, "%c", (((l->data[byte] >> loch) & 0x01) == 0x01) ? '#' : ' '); 569 if(loch == 7) printf("\n"); 570 } 571 572 if((byte < 0 || byte >= l->data_length) || // wenn ein Nullbyte gezeichnet wird 573 (((l->data[byte] >> loch) & 0x01) != 0x01) // oder das Bit an der Stelle nicht gesetzt ist 574 ) { // ist es not-Punched 575 if(l->notpunched != NULL) { // notpunched zeichnen? (muss subif sein) 576 cairo_set_source(cr, l->notpunched); 577 cairo_arc(cr, x+l->d/2, y+l->d/2, l->d/2, 0., 2*M_PI); 578 cairo_fill(cr); 579 } 580 } else if(l->punched != NULL) { // es ist Punched. Zeichnen? 581 cairo_set_source(cr, l->punched); 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 // Die Routine wegen dem Zeichnen?-Ding hervorgehoben. 586 /*cairo_set_source(cr, 587 (byte < 0 || byte >= data_length) || // wenn ein Nullbyte gezeichnet wird 588 (((data[byte] >> loch) & 0x01) != 0x01) ? // oder das Bit an der Stelle nicht gesetzt ist 589 notpunched : punched); // dann dies farbig kennzeichnen 590 cairo_arc(cr, x+d/2, y+d/2, d/2, 0., 2*M_PI); 591 cairo_fill(cr);*/ 592 593 // y+= war hier. 594 } // for bits (loecher) 595 // x += war hier. 596 } // for bytes 597 598 // Lochstreifenfuehrung im vorderen Abriss malen 599 if(l->fuehrung != NULL) { 600 cairo_set_source(cr, l->fuehrung); 601 y = l->margin + l->padding + 3*l->d + 2*l->hspace + l->fspace/2; // fspace-Mitte 602 x = l->margin + l->abriss - l->d - l->bspace; // Start-x 603 for(; x > l->margin;) { 604 cairo_arc(cr, x + l->d/2, y, l->df/2, 0., 2*M_PI); 605 x -= l->d + l->bspace; 606 } 607 cairo_fill(cr); 608 } 609 610 // fertig mit dem Lochstreifenzeichnen. 611 } // function draw_lochstreifen 547 // complete length of paper tape: 548 double length = LOCHSTREIFEN_LENGTH; 549 550 // iterators for the byte/bit loops 551 int row,track; 552 // position while iterating 553 double x,y; 554 // max positions to iterate to 555 int row_max, track_min, track_max; 556 557 // apply the matrix! 558 cairo_set_matrix(cr, l->matrix); 559 560 561 // paint outer background color. 562 if(l->outer_background_color != NULL) { 563 cairo_set_source(cr, l->outer_background_color); 564 cairo_paint(cr); 565 } 566 567 // paint the paper tape outline, including the tear-off 568 if(l->papertape_background_color != NULL) { 569 cairo_set_source(cr, l->papertape_background_color); 570 571 // tear-off at the beginning (0.5 of paper tape width) 572 cairo_move_to(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH * 0.8, 0); 573 cairo_line_to(cr, 0, 4*LOCHSTREIFEN_TRACK_DISTANCE); 574 cairo_line_to(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, LOCHSTREIFEN_WIDTH); 575 cairo_line_to(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, 0); 576 cairo_close_path(cr); 577 578 // long rectangular area over complete paper tape 579 cairo_rectangle(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, 0, 580 length - 2*LOCHSTREIFEN_TEAR_OFF_LENGTH, LOCHSTREIFEN_WIDTH); 581 582 // tear-off at the end (0.5 of paper tape width) 583 cairo_move_to(cr, length-LOCHSTREIFEN_TEAR_OFF_LENGTH, 0); 584 cairo_line_to(cr, length-LOCHSTREIFEN_TEAR_OFF_LENGTH, LOCHSTREIFEN_WIDTH); 585 cairo_line_to(cr, length, LOCHSTREIFEN_WIDTH); 586 cairo_line_to(cr, length-LOCHSTREIFEN_TEAR_OFF_LENGTH, 4*LOCHSTREIFEN_TRACK_DISTANCE); 587 cairo_line_to(cr, length-LOCHSTREIFEN_TEAR_OFF_LENGTH * 0.2, 0); 588 cairo_close_path(cr); 589 590 // paper tape background finished. 591 cairo_fill(cr); 592 } 593 594 // paint feed holes in the tear-off at the beginning 595 // only if in clipped area 596 if( ( l->clip == NULL || (l->clip->x <= LOCHSTREIFEN_TEAR_OFF_LENGTH) ) 597 && (l->feed_hole_color != NULL) ) { 598 cairo_set_source(cr, l->feed_hole_color); 599 for(y=4*LOCHSTREIFEN_TRACK_DISTANCE, 600 x=LOCHSTREIFEN_TEAR_OFF_LENGTH - LOCHSTREIFEN_ROW_DISTANCE/2; 601 x > 0; x -= LOCHSTREIFEN_ROW_DISTANCE) 602 cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_FEED_HOLE, 0., 2*M_PI); 603 cairo_fill(cr); 604 } 605 606 607 if(l->clip != NULL) { 608 // calculate clipping in dimension X (rows, bytes) 609 // calculation of first row to begin with. 610 row = floor ( 611 (l->clip->x - LOCHSTREIFEN_TEAR_OFF_LENGTH - LOCHSTREIFEN_ROW_DISTANCE / 2) 612 / LOCHSTREIFEN_ROW_DISTANCE 613 ); 614 615 // calculation of last row to end with. 616 row_max = floor( 617 (length - (l->clip->x + l->clip->width) - LOCHSTREIFEN_TEAR_OFF_LENGTH - LOCHSTREIFEN_ROW_DISTANCE/2) 618 / LOCHSTREIFEN_ROW_DISTANCE 619 ); 620 621 // calculate clipping in dimension Y (tracks, bits) 622 // calculation of first track to begin with. 623 track_min = floor( l->clip->y / LOCHSTREIFEN_TRACK_DISTANCE ); 624 625 // calculation of last track to end with. 626 track_max = 8 - floor( 627 (LOCHSTREIFEN_WIDTH - (l->clip->y + l->clip->height)) 628 / LOCHSTREIFEN_TRACK_DISTANCE 629 ); 630 } else { 631 // no clipping. Paint *everything*. 632 row = 0; 633 row_max = l->data_length; 634 635 track_min = 0; 636 track_max = 8; 637 } 638 639 // loop all the rows (bytes) 640 // x start: tear off + one half row offset + offset rows * length of row 641 for(x=LOCHSTREIFEN_TEAR_OFF_LENGTH + LOCHSTREIFEN_TRACK_DISTANCE/2 + row*LOCHSTREIFEN_TRACK_DISTANCE; 642 row < row_max; row++, x += LOCHSTREIFEN_TRACK_DISTANCE) { 643 644 // highlight region? 645 if(l->highlight_region_color != NULL && 646 (row >= l->highlight_region_start || row < l->highlight_region_end) ) { 647 cairo_set_source(cr, l->highlight_region_color); 648 // hier was schlaues schickeres als ein RECHTECK 649 // einfallen lassen. Vielleicht mit abgerundetem 650 // Rechteck? Wuerde zu den Löchern passen. 651 // http://www.cairographics.org/cookbook/roundedrectangles/ 652 cairo_rectangle(cr, x - LOCHSTREIFEN_TRACK_DISTANCE / 2, 0, 653 LOCHSTREIFEN_TRACK_DISTANCE * (l->highlight_region_end - l->highlight_region_start), 654 LOCHSTREIFEN_WIDTH); 655 cairo_fill(cr); 656 } 657 658 // highlight (only) this row? 659 if(l->highlight_row_color != NULL && row == l->highlight_row_number) { 660 cairo_set_source(cr, l->highlight_row_color); 661 // genauso abgerundetes Rechteck wie bei der region 662 // überlegen. 663 cairo_rectangle(cr, x - LOCHSTREIFEN_TRACK_DISTANCE/2, 0, 664 LOCHSTREIFEN_TRACK_DISTANCE, LOCHSTREIFEN_WIDTH); 665 cairo_fill(cr); 666 } 667 668 // loop all the tracks (bits) 669 // y start: offset tracks * width of track + one track (to get onto the papertape) 670 for(track=track_min, y = LOCHSTREIFEN_TRACK_DISTANCE*(track+1); 671 track < track_max; track++, y += LOCHSTREIFEN_TRACK_DISTANCE) { 672 if(track == 3) { 673 // the feed hole is at position 3 674 if(l->feed_hole_color != NULL) { 675 // we paint a feed hole :-) 676 cairo_set_source(cr, l->feed_hole_color); 677 cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_FEED_HOLE, 0., 2*M_PI); 678 cairo_fill(cr); 679 } 680 // jump one track, in every case. 681 y += 0.1; 682 } 683 684 if( ((l->data[row] >> track) & 0x01) != 0x01) { 685 // bit is logical ZERO (0) 686 if(l->zero_code_hole_color != NULL) { 687 // we want to paint zeros. 688 cairo_set_source(cr, l->zero_code_hole_color); 689 cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_CODE_HOLE, 0., 2*M_PI); 690 cairo_fill(cr); 691 } 692 } else if(l->one_code_hole_color != NULL) { 693 // we want to paint logical ONEs. 694 cairo_set_source(cr, l->one_code_hole_color); 695 cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_CODE_HOLE, 0., 2*M_PI); 696 cairo_fill(cr); 697 } 698 699 if(l->highlight_bit_row == row && l->highlight_bit_track == track 700 && l->highlight_bit_color != NULL) { 701 // eigentlich wollen wir hier eine Umrahmung zeichnen, 702 // damit der Zustand (0/1) nicht unsichtbar wird. Jetzt 703 // erst mal aber die Billigversion mit der dümmlichen 704 // Vollfarbe ;-) 705 cairo_set_source(cr, l->highlight_bit_color); 706 cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_CODE_HOLE, 0., 2*M_PI); 707 cairo_stroke(cr); // mal testen :-) 708 } 709 } // for tracks (bits) 710 } // for rows (bytes) 711 } // function lochstreifen_draw -
visualisator/lochstreifen.h
r9 r18 1 /*2 ** Allgemeine Headerfile fuer das3 ** Lochstreifen-Visualisieren-Projekt4 */5 1 #ifndef __LOCHSTREIFEN_H__ 6 2 #define __LOCHSTREIFEN_H__ 7 3 8 #include <cairo-svg.h> // cairo_t unten 4 // if C++ compiling... 5 #ifdef __cplusplus 6 extern "C" { 7 #endif 9 8 10 #define byte_t unsigned char 11 #define LOCHSTREIFEN struct lochstreifen 9 #include <cairo-svg.h> /* because using cairo_t */ 12 10 13 // Die Lochstreifenstruktur, die alle relevanten Daten enthaelt 11 typedef unsigned char byte_t; 12 typedef struct lochstreifen LOCHSTREIFEN; 13 14 14 struct lochstreifen { 15 /* Daten, die der Lochstreifen enthaelt: */ 16 int data_length; // Länge des Datenarrays, rechnend ab 1 (wie argc) 17 byte_t *data; // Datenarray 15 /* DATA (not supposed to be set directly) */ 16 /// Length of data array (counting from 1, like argc) 17 int data_length; 18 /// data array (the data which LOCHSTREIFEN will print) 19 byte_t *data; 18 20 19 int empty_start; // wie viele 0bytes vorne 20 int empty_end; // wie viele 0bytes hinten 21 /* COLORS / SWITCHES WHETER PARTS ARE PAINTED */ 22 cairo_pattern_t *outer_background_color; 23 cairo_pattern_t *papertape_background_color; 24 cairo_pattern_t *one_code_hole_color; 25 cairo_pattern_t *zero_code_hole_color; 26 cairo_pattern_t *feed_hole_color; 21 27 22 /* Konstanten zum Aussehen des Lochstreifens 23 Referenzeinheit ist d, daraus wird alles berechnet, 24 siehe lochstreifen_set_d 25 */ 26 int d; // Durchmesser eines Loches 27 int bspace; // Abstand der Bytes voneinander (Reihen) 28 int hspace; // Abstand der Loecher in der Bytereihe 29 int padding; // Abstand Löcher <=> Lochstreifenrand 30 int df; // Durchmesser Lochfuehrungsloch 31 int fspace; // Breite der Lochfuehrungs"nut" 32 int margin; // Abstand um Lochstreifen herum (an allen Seiten) 33 int abriss; // Länge der Abrisse an Start/Ende (halbe Höhe vom Lochstreifen) 28 /// Highlighting a (row/byte) region 29 int highlight_region_start; ///< counting from 0, already in selection 30 int highlight_region_end; ///< counting from 0, no more in selection 31 cairo_pattern_t *highlight_region_color; ///< == NULL => no selection painted 34 32 35 /* Farben, in denen der Lochstreifen gehalten ist */ 36 cairo_pattern_t *hintergrund, *streifenbg, *punched, *notpunched, *fuehrung; 37 // Farben um Lochstreifen, Lochstreifen, Loecher, Nicht-Loecher, Fuehrung 38 // siehe zum Setzen: lochstreifen_set_color oder per Cairo-Funktion fuer 39 // komplexere Loesungen. Bei NULL wird die Komponente nicht gezeichnet! 33 /// Highlight one special row 34 int highlight_row_number; ///< counting from 0 35 cairo_pattern_t *highlight_row_color; 40 36 41 /* Drehungen und co, nicht direkt veraendern, sonst stimmt die vorberechnete 42 Hoehe/Breite nicht mehr mit den realen Werten ueberein. */ 43 //cairo_matrix_t transformation; 44 // Das folgende koennte man natuerlich effizienter Speichern, aber egal. 45 int drehung; // 0-3, jeweils 45°-Schritte im Uhrzeigersinn 46 int spiegelung_hor; // horizontale Spiegelung != 0 == ja 47 int spiegelung_ver; // vertikale Spiegelung != 0 == ja 37 /// Highlight one special bit (not complete track) 38 int highlight_bit_row; ///< counting from 0 39 int highlight_bit_track; ///< counting from 0 40 cairo_pattern_t *highlight_bit_color; 48 41 49 /* Nur bestimmte rechteckige Bereiche zeichnen -- dies wird massgeblich vom 50 GTK-Interface benutzt */ 51 int only_start_x; // Die angegebenen Punkte 52 int only_start_y; // spannen ein Rechteck auf. In grober 53 int only_width; // Naeherung wird nur in diesem Bereich 54 int only_height; // gezeichnet. 42 /// Perfomant Clipping 43 cairo_rectangle_t *clip; 44 45 /// Matrix to apply for every paint process 46 cairo_matrix_t *matrix; 47 48 /*<private>*/ 49 /* The following datas are private. */ 50 51 /// Make debug output if debug != 0. 52 byte_t debug; 53 }; 54 55 /// The default color values 56 #define LOCHSTREIFEN_DEFAULT_OUTER_BACKGROUND_COLOR NULL 57 #define LOCHSTREIFEN_DEFAULT_PAPERTAPE_BACKGROUND_COLOR cairo_pattern_create_rgb(0.7, 0.7, 0.7) 58 #define LOCHSTREIFEN_DEFAULT_ONE_CODE_HOLE_COLOR cairo_pattern_create_rgb(0, 0, 0) 59 #define LOCHSTREIFEN_DEFAULT_ZERO_CODE_HOLE_COLOR NULL 60 #define LOCHSTREIFEN_DEFAULT_FEED_HOLE_COLOR cairo_pattern_create_rgb(0.5, 0.7, 1) 61 #define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_REGION_COLOR cairo_pattern_create_rgb(0.95, 1, 0) 62 #define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_ROW_COLOR cairo_pattern_create_rgb(1, 0, 0) 63 #define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_BIT_COLOR cairo_pattern_create_rgb(0.4, 0.55, 0.7) 64 65 /// dimensions of the paper tape after ECMA-10 standard 66 67 // width of paper tape, according to "PROPERTIES OF UNPUNCHED TAPE", section 1.1.2: 68 // 25.40mm = 1". This is the "base" unit in our vector drawing. 69 #define LOCHSTREIFEN_WIDTH 1.0 70 71 // length of tear-off: about the half of the width of a papertape 72 #define LOCHSTREIFEN_TEAR_OFF_LENGTH ( 0.5 * LOCHSTREIFEN_WIDTH ) 73 74 // Within a row the distance of the centres of the code holes from 75 // the centre of the feed hole shall be 2,54mm (=0.1"), where n is an integer. 76 #define LOCHSTREIFEN_TRACK_DISTANCE 0.1 77 78 // The distance between two adjacent rows shall be 2,54mm (=0.1") measured 79 // at the feed holes. 80 #define LOCHSTREIFEN_ROW_DISTANCE 0.1 81 82 // feed hole diameter: 1.170mm 83 #define LOCHSTREIFEN_RADIUS_FEED_HOLE ( (1.170 / 25.40) / 2) 84 85 // code hol diameter: 1.83mm 86 #define LOCHSTREIFEN_RADIUS_CODE_HOLE ( (1.830 / 25.40) / 2) 87 88 // length of paper tape: Tear off at start and end, data rows + 0.05" offset at start + end spacing 89 #define LOCHSTREIFEN_LENGTH ( 2 * LOCHSTREIFEN_TEAR_OFF_LENGTH + \ 90 LOCHSTREIFEN_ROW_DISTANCE * (l->data_length + 1) ) 91 92 enum lochstreifen_direction { 93 // special values for compatibility to old implementation 94 LOCHSTREIFEN_MOVEMENT_TO_LEFT = 0, 95 LOCHSTREIFEN_MOVEMENT_TO_TOP = 1, 96 LOCHSTREIFEN_MOVEMENT_TO_RIGHT = 2, 97 LOCHSTREIFEN_MOVEMENT_TO_BOTTOM = 3, 98 LOCHSTREIFEN_MOVEMENT_NONE = -1, 99 LOCHSTREIFEN_ROTATION_CLOCKWISE = 4, 100 LOCHSTREIFEN_ROTATION_ANTICLOCKWISE = 5 101 }; 55 102 56 103 57 /* Feature: Ein bestimmtes Byte hervorheben */ 58 int highlight_byte; // Nummer des Bytes (von 0) 59 cairo_pattern_t *highlight_color; // Farben => wenn NULL, kein Highlight 104 // functions 105 LOCHSTREIFEN *lochstreifen_new(); 106 void lochstreifen_print_debug(LOCHSTREIFEN* l); 107 void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data); 108 void lochstreifen_add_null_bytes(LOCHSTREIFEN *l, int start, int end); 109 double lochstreifen_get_length(LOCHSTREIFEN *l); 110 void lochstreifen_set_highlight_region(LOCHSTREIFEN *l, int start, int end); 111 int lochstreifen_get_highlight_region(LOCHSTREIFEN *l, int *start, int *end); 112 void lochstreifen_remove_highlight_region(LOCHSTREIFEN *l); 113 void lochstreifen_set_highlight_row(LOCHSTREIFEN *l, int number_of_row); 114 int lochstreifen_get_highlight_row(LOCHSTREIFEN *l); 115 void lochstreifen_remove_highlight_row(LOCHSTREIFEN *l); 116 void lochstreifen_set_highlight_bit(LOCHSTREIFEN *l, int number_of_row, int number_of_bit); 117 int lochstreifen_get_highlight_bit(LOCHSTREIFEN *l, int *number_of_row, int *number_of_bit); 118 void lochstreifen_remove_highlight_bit(LOCHSTREIFEN *l); 119 void lochstreifen_set_clip(LOCHSTREIFEN *l, double x, double y, double width, double height); 120 void lochstreifen_remove_clip(LOCHSTREIFEN *l); 121 void lochstreifen_set_scaling_by_length(LOCHSTREIFEN *l, int length); 122 void lochstreifen_set_scaling_by_width(LOCHSTREIFEN *l, int width); 123 void lochstreifen_set_scaling_by_code_hole(LOCHSTREIFEN *l, int diameter); 124 void lochstreifen_get_target_dimensions(LOCHSTREIFEN *l, int *width, int *height); 125 int lochstreifen_get_target_width(LOCHSTREIFEN *l); 126 int lochstreifen_get_target_height(LOCHSTREIFEN *l); 127 int lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y); 128 void lochstreifen_set_rotation(LOCHSTREIFEN *l, enum lochstreifen_direction direction); 129 void lochstreifen_draw(LOCHSTREIFEN *l, cairo_t *cr); 60 130 61 /* Debugausgaben machen => wenn debug != 0 ist! */ 62 byte_t debug; 63 }; 131 #ifdef __cplusplus 132 } // extern "C" 133 #endif 64 134 65 /* lochstreifen.c */66 // allgemeine Zusatzfunktion, kein Bezug67 int file_get_contents(FILE *stream, byte_t **content);68 69 // Lochstreifenfunktionen, siehe Dokumentation in c-File70 LOCHSTREIFEN *lochstreifen_new();71 void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data, int empty_start, int empty_end);72 void lochstreifen_set_d(LOCHSTREIFEN *l, int d);73 void lochstreifen_set_d_by_width(LOCHSTREIFEN *l, int width);74 void lochstreifen_set_d_by_height(LOCHSTREIFEN *l, int height);75 int lochstreifen_get_width(LOCHSTREIFEN *l);76 int lochstreifen_get_height(LOCHSTREIFEN *l);77 int lochstreifen_set_draw_only_area(LOCHSTREIFEN *l, int x, int y, int width, int height);78 int lochstreifen_flush_draw_only_area(LOCHSTREIFEN *l);79 void lochstreifen_set_color(cairo_pattern_t *color, byte_t red, byte_t green, byte_t blue, byte_t alpha);80 //void lochstreifen_rotate(LOCHSTREIFEN *l);81 //void lochstreifen_spiegel(LOCHSTREIFEN *l, byte_t horizontal);82 void lochstreifen_set_direction(LOCHSTREIFEN *l, int drehung, int spiegelung_hor, int spiegelung_ver);83 void lochstreifen_draw(LOCHSTREIFEN *l, cairo_t *cr);84 int lochstreifen_get_orientation(LOCHSTREIFEN *l);85 int lochstreifen_byte_by_coordinate(LOCHSTREIFEN *l, int x, int y);86 int lochstreifen_flush_only_start_area(LOCHSTREIFEN *l);87 void lochstreifen_set_highlight(LOCHSTREIFEN* l, int byte_number);88 int lochstreifen_coordinate_by_byte(LOCHSTREIFEN *l, int byte);89 int lochstreifen_set_only_start_area(LOCHSTREIFEN *l, int x, int y, int width, int height);90 135 91 136 #endif /* __LOCHSTREIFEN_H__ */
Note: See TracChangeset
for help on using the changeset viewer.