[1] | 1 | /** |
---|
[6] | 2 | * cli.c: An exemplar, but fully functional and highly configurable |
---|
| 3 | * command line interface (CLI) to the paper tape low level drawing |
---|
| 4 | * routines (lochstreifen.c), which uses the famous cairo graphics |
---|
| 5 | * library for drawing. |
---|
[1] | 6 | * |
---|
[6] | 7 | * See ./program --help for an overview about the self-explanatory |
---|
| 8 | * arguments. By default, the program will read in any files in |
---|
| 9 | * stdin and print the genereated PNG file on stdout. |
---|
| 10 | * |
---|
| 11 | * This program is written in english only (but the sourcecode |
---|
| 12 | * contains some german comments). See an exemplar usage of this |
---|
| 13 | * program in a PHP web program in the web-frontend subproject. |
---|
| 14 | * |
---|
| 15 | * This program uses the argp.h argument parser from the glibc. |
---|
| 16 | * Thus it unfortunately won't compile with any other libc. |
---|
| 17 | * |
---|
| 18 | * Copyright (C) 2008 Sven Köppel |
---|
| 19 | * |
---|
| 20 | * This program is free software; you can redistribute it and/or |
---|
| 21 | * modify it under the terms of the GNU General Public License as |
---|
| 22 | * published by the Free Software Foundation; either version 3 of |
---|
| 23 | * the License, or (at your option) any later version. |
---|
| 24 | * |
---|
| 25 | * This program is distributed in the hope that it will be useful, |
---|
| 26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 28 | * GNU General Public License for more details. |
---|
| 29 | * |
---|
| 30 | * You should have received a copy of the GNU General Public License |
---|
| 31 | * along with this program; if not, see |
---|
| 32 | * <http://www.gnu.org/licenses/>. |
---|
| 33 | * |
---|
[1] | 34 | **/ |
---|
| 35 | |
---|
| 36 | #include <stdio.h> |
---|
| 37 | #include <stdlib.h> |
---|
| 38 | #include <string.h> |
---|
| 39 | #include <argp.h> |
---|
| 40 | |
---|
| 41 | #include "lochstreifen.h" |
---|
| 42 | |
---|
| 43 | LOCHSTREIFEN *l; |
---|
[18] | 44 | enum _surface_type { |
---|
| 45 | PNG_SURFACE, |
---|
| 46 | SVG_SURFACE |
---|
| 47 | } surface_type; |
---|
[1] | 48 | char *output_file; |
---|
| 49 | int verbosity = 0; |
---|
[18] | 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; |
---|
[1] | 59 | |
---|
| 60 | #define DPRINTF(msg...) if(verbosity!=0) fprintf(stderr,msg); |
---|
| 61 | |
---|
[18] | 62 | error_t parse_option (int key, char *arg, struct argp_state *state); |
---|
| 63 | cairo_pattern_t *hex2cairo_pattern(const char *string); |
---|
| 64 | |
---|
[1] | 65 | const char *argp_program_version = "Punch card visualisator - CLI frontend"; |
---|
| 66 | |
---|
| 67 | static struct argp_option options[] = { |
---|
| 68 | {"verbose", 'v', 0, 0, "Produce verbose output on stderr" }, |
---|
| 69 | //{"quiet", 'q', 0, 0, "Don't produce any output" }, |
---|
| 70 | //{"silent", 's', 0, OPTION_ALIAS }, |
---|
| 71 | |
---|
| 72 | {"output", 'o', "FILE", 0, "Output to FILE (instead of standard output)" }, |
---|
| 73 | {"image", 'i', 0, OPTION_ALIAS }, |
---|
| 74 | {"format", 'f', "SVG|PNG",0, "Set desired output image format (PNG or SVG)" }, |
---|
| 75 | {"", 0, 0, OPTION_DOC, ""}, |
---|
| 76 | |
---|
| 77 | {"Dimensions", 0, 0, OPTION_DOC, "Dimensions are integers without units"}, |
---|
| 78 | {"width", 'w', "NUM", 0, "Set desired width for output image (in px or points, according to output format)", 1 }, |
---|
| 79 | {"height", 'h', "NUM", 0, "Set desired height for output image (unit like width argument)", 1 }, |
---|
| 80 | {"diameter", 'd', "NUM", 0, "Set dimensions for output image by punched hole diameter (pixel)", 1 }, |
---|
| 81 | {"", 0, 0, OPTION_DOC, "",1}, |
---|
| 82 | |
---|
[18] | 83 | {"Empty bytes", 1, 0, OPTION_DOC, "Bytes with value=0x00 which are not content of files", 1}, |
---|
[1] | 84 | {"empty-start", -1, "NUM", 0, "Set number of empty bytes at beginning (default=0)", 2 }, |
---|
| 85 | {"empty-end", -2, "NUM", 0, "Set number of empty bytes at end (default=0)", 2 }, |
---|
| 86 | {"", 0, 0, OPTION_DOC, "",2}, |
---|
| 87 | |
---|
| 88 | {"Colors", 0, 0, OPTION_DOC, "Color format: #RGB[A], #RRGGBB[AA]", 2 }, |
---|
| 89 | {"hide-imagebg", -3, 0, 0, "Make the image background (space around paper tape) transparent", 3 }, |
---|
| 90 | {"color-imagebg", -4, "#RGBA", 0, "Set image background color", 3 }, |
---|
| 91 | {"hide-tapebg", -5, 0, 0, "Hide the paper tape background", 3 }, |
---|
| 92 | {"color-tapebg", -6, "#RGBA", 0, "Set tape background color", 3 }, |
---|
| 93 | {"hide-punched", -7, 0, 0, "Hide the holes (only the punched ones)", 3 }, |
---|
| 94 | {"color-punched", -8, "#RGBA", 0, "Set color of holes (punched bits)", 3 }, |
---|
| 95 | {"hide-notpunched", -9, 0, 0, "Hide the holes which aren't punched on real tapes", 3 }, |
---|
| 96 | {"color-notpunched",-10, "#RGBA", 0, "Set color of bits with boolean value \"false\"", 3 }, |
---|
| 97 | {"hide-feedholes", -11, 0, 0, "Hide the feed holes (which means they wouldn't be punched)", 3 }, |
---|
| 98 | {"color-feedholes", -12, "#RGBA", 0, "Set color of feed holes (the small ones)", 3 }, |
---|
| 99 | {"", 0, 0, OPTION_DOC, "",3}, |
---|
| 100 | |
---|
| 101 | {"Transformations and Rotations", 0, 0, OPTION_DOC, "", 3}, |
---|
| 102 | {"rotation", -13, "right|bottom|left|top", 0, "Rotation of punched tape (alternative short notation: 0=right, 1=bottom, 2=left, 3=top)", 4 }, |
---|
| 103 | {"reflection-byte-direction", -14, 0, 0, "Enables horizontal reflecion on the data axis (inverts data direction)", 4 }, |
---|
| 104 | {"reflection-bit-direction", -15, 0, 0, "Enables vertical reflection on the other axis (inverts bit direction)", 4 }, |
---|
| 105 | {"", 0, 0, OPTION_DOC, "",-2}, |
---|
| 106 | |
---|
| 107 | { 0 } |
---|
| 108 | }; |
---|
| 109 | |
---|
[18] | 110 | static struct argp argp = { options, parse_option, "[FILE TO READ FROM]", // Als Argument in der ersten Zeile |
---|
| 111 | "This program uses cairo to draw a punched tape as a PNG or SVG file. Any binary " // Hilfe oben |
---|
| 112 | "data are accepted via stdin or read in from the file given as argument. " |
---|
| 113 | "The produced image is written into stdout or in the filename given by -o." |
---|
| 114 | // mit \v danach koennte man ausfuehrliche Hilfe unten anzeigen. |
---|
| 115 | }; // static struct argp |
---|
[1] | 116 | |
---|
| 117 | |
---|
[18] | 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 | **/ |
---|
[1] | 247 | cairo_pattern_t *hex2cairo_pattern(const char *string) { |
---|
[18] | 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 | } |
---|
[1] | 280 | |
---|
[18] | 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 |
---|
[1] | 305 | |
---|
[18] | 306 | while(!feof(stream)) { |
---|
| 307 | bytes = fread(buf, 1, sizeof(buf), stream); |
---|
[1] | 308 | |
---|
[18] | 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); |
---|
[1] | 314 | |
---|
[18] | 315 | tmp = realloc(str, total_allocated); |
---|
[1] | 316 | |
---|
[18] | 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 | } |
---|
[1] | 323 | |
---|
[18] | 324 | str = tmp; |
---|
| 325 | } // while innen |
---|
[1] | 326 | |
---|
[18] | 327 | memcpy(str + total_bytes, buf, bytes); |
---|
| 328 | total_bytes += bytes; |
---|
| 329 | } // while |
---|
[1] | 330 | |
---|
[18] | 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. |
---|
[1] | 334 | |
---|
[18] | 335 | *content = str; |
---|
| 336 | return total_bytes; |
---|
| 337 | } |
---|
[1] | 338 | |
---|
[18] | 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 | **/ |
---|
| 343 | cairo_status_t lochstreifen_out_closure(void *closure, unsigned char *data, unsigned int length) { |
---|
| 344 | // einfach nur in das uebergebene Dateihandle schreiben |
---|
| 345 | fwrite(data, length, 1, (FILE *)closure); |
---|
| 346 | return CAIRO_STATUS_SUCCESS; |
---|
| 347 | } |
---|
[1] | 348 | |
---|
[18] | 349 | /** |
---|
| 350 | * The main routine. |
---|
| 351 | **/ |
---|
| 352 | int main(int argc, char *argv[]) { |
---|
| 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"); |
---|
[1] | 370 | |
---|
[18] | 371 | if(fh == NULL) { |
---|
| 372 | perror("opening input file"); |
---|
| 373 | exit(1); |
---|
| 374 | } |
---|
[1] | 375 | |
---|
[18] | 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 | } |
---|
[1] | 382 | |
---|
[18] | 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); |
---|
[1] | 402 | |
---|
[18] | 403 | // open output stream |
---|
| 404 | if(output_file != NULL) { // check if there was an argv argument |
---|
| 405 | out = fopen(output_file, "w"); |
---|
[1] | 406 | |
---|
[18] | 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); |
---|
[1] | 419 | |
---|
[18] | 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); |
---|
[1] | 429 | |
---|
[18] | 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); |
---|
[1] | 441 | |
---|
[18] | 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 |
---|
[1] | 448 | } // main |
---|