// // Copyright 8-16-2007 Jonathan Westbrock // img-gen // // Permission is granted to modify and distribute this software and accompanying documentation, // provided that this complete notice appear in any and all revisions, as well as accompanying // documentation. // // No warranty shall be offered, or liability accepted by author, be these implied, expressed, or imagined. // Any damages, direct or indirect, resulting from the use of this software are hereby disclaimed. // The author makes no claim of any kind as to the sustainablity, stability, or quality of this product. // // Distributed under the terms of the GNU General Public license(GPL). // #include #include #include #include #include const char *argp_program_version = "Alpha"; const char *argp_program_bug_address = ""; const char chrValidList[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_-.<\'\'}=|/@+)]{~>[!#$%&(,?:;'\" "; struct arguments { char *args[5]; int verbose, shadow, raised, bold, italic, oblique; char *program, *font; double width, height, f1R, f1G, f1B, f1A, fS, indent, opacity, stampX, stampY; }; static struct argp_option options[] = { {"verbose", 'v', 0, 0, "Produce verbose output DEFAULT:Off"}, {"shadow", 's', 0, 0, "Font drop shadow DEFAULT:Off"}, {"bold", 'b', 0, 0, "Bold font DEFAULT:Off"}, {"italic", 'i', 0, 0, "Italic font DEFAULT:Off"}, {"oblique", 'o', 0, 0, "Oblique font DEFAULT:Off (overrides italic)"}, {"raised", 'r', 0, 0, "Raised font effect DEFAULT:Off"}, {"width", 'w', "WIDTH", 0, "Set output WIDTH DEFAULT:1280"}, {"height", 'h', "HEIGHT", 0, "Set output HEIGHT DEFAULT:1024"}, {"program", 'p', "PROGRAM", 0,"Read output from PROGRAM DEFAULT:Fortune"}, {"Red", 'R', "Font RED", 0,"Level of RED in font output DEFAULT:0.7"}, {"Green", 'G', "Font GREEN", 0,"Level of GREEN in font output DEFAULT:0.7"}, {"Blue", 'B', "Font BLUE", 0,"Level of BLUE in font output DEFAULT:0.7"}, {"Alpha", 'A', "Font ALPHA", 0,"Level of ALPHA in font output DEFAULT:0.9"}, {"Size", 'S', "Font SIZE", 0,"SIZE of font output DEFAULT:25.0"}, {"indent", 'I', "INDENT", 0,"INDENT of output text DEFAULT:10.0"}, {"opacity", 'O', "OPACITY", 0,"Output image OPACITY level DEFAULT:1.0"}, {"placex", 'x', "PLACEX", 0,"Beginning X PLACEMENT of input image on the background"}, {"placey", 'y', "PLACEY", 0,"Beginning Y PLACEMENT of input image on the background"}, {"font", 'f', "FONT", 0,"FONT of text output DEFAULT: Bitstream Vera Sans Mono"}, {0} }; static error_t parse_opt (int key, char *arg, struct argp_state *state) { struct arguments *arguments = state->input; switch (key) { case 'v': arguments->verbose = 1; break; case 's': arguments->shadow = 1; break; case 'b': arguments->bold = 1; break; case 'i': arguments->italic = 1; break; case 'o': arguments->oblique = 1; break; case 'r': arguments->raised = 1; break; case 'w': arguments->width = atof(arg); break; case 'h': arguments->height = atof(arg); break; case 'R': arguments->f1R = atof(arg); break; case 'G': arguments->f1G = atof(arg); break; case 'B': arguments->f1B = atof(arg); break; case 'A': arguments->f1A = atof(arg); break; case 'S': arguments->fS = atof(arg); break; case 'p': arguments->program = arg; break; case 'I': arguments->indent = atof(arg); break; case 'O': arguments->opacity = atof(arg); break; case 'x': arguments->stampX = atof(arg); break; case 'y': arguments->stampY = atof(arg); break; case 'f': arguments->font = arg; break; case ARGP_KEY_ARG: if (state->arg_num >= 5) { argp_usage(state); } arguments->args[state->arg_num] = arg; break; case ARGP_KEY_END: if (state->arg_num < 5) { argp_usage (state); } break; default: return ARGP_ERR_UNKNOWN; } return 0; } static char args_doc[] = "Input.png Output.png Red Green Blue"; static char doc[] = "img-gen -- A simple utility to generate images for use as backgrounds, etc."; static struct argp argp = {options, parse_opt, args_doc, doc}; int clean_string(char *udata, int verb) { char *control; if (verb > 0) printf("\nInput: %s", udata); for (control = udata; *(control += strspn(control, chrValidList)); /* */) *control = ' '; if (verb > 0) printf("\nOutput: %s", udata); return 1; } int draw_raised (cairo_t *surfus, char *strung, double pigX, double pigY, double fR, double fG, double fB, double fA, double FS, int verb) { cairo_set_font_size (surfus, FS); cairo_set_source_rgba (surfus, 0.5, 0.5, 0.5, 0.2); cairo_move_to (surfus, pigX+2, pigY+2); cairo_show_text (surfus, strung); if (verb > 0) printf("\n"); cairo_set_source_rgba (surfus, fR /2, fG /2, fB /2 , fA /2); cairo_move_to (surfus, pigX + 1, pigY + 1); cairo_show_text (surfus, strung); if (verb > 0) printf("\n"); cairo_set_source_rgba (surfus, fR, fG, fB, fA); cairo_move_to (surfus, pigX, pigY); cairo_show_text (surfus, strung); if (verb > 0) printf("\n\n"); return 1; } int draw_flat (cairo_t *surfus, char *strung, double pigX, double pigY, double fR, double fG, double fB, double fA, double FS, int verb) { cairo_set_font_size (surfus, FS); cairo_set_source_rgba (surfus, fR, fG, fB, fA); cairo_move_to (surfus, pigX, pigY); cairo_show_text (surfus, strung); if (verb > 0) printf("\n"); return 1; } int draw_shadow (cairo_t *surfus, char *strung, double pigX, double pigY, double fR, double fG, double fB, double fA, double FS, int verb) { cairo_set_font_size (surfus, FS); cairo_set_source_rgba (surfus, 0.0, 0.0, 0.0, 0.8); cairo_move_to (surfus, pigX +3, pigY +3); cairo_show_text (surfus, strung); if (verb > 0) printf("\n"); cairo_set_source_rgba (surfus, fR, fG, fB, fA); cairo_move_to (surfus, pigX, pigY); cairo_show_text (surfus, strung); if (verb > 0) printf("\n\n"); return 1; } int draw_it(cairo_t* surf, char *strung, double pigX, double pigY, double fR, double fG, double fB, double fA, double FS, int verb, int shadow, int raise) { int intByteHolder = clean_string(strung, verb); if(shadow) { if (verb > 0) printf("\n\n"); intByteHolder = draw_shadow(surf, strung, pigX, pigY, fR, fG, fB, fA, FS, verb); } if(raise) { if (verb > 0) printf("\n\n"); intByteHolder = draw_raised(surf, strung, pigX, pigY, fR, fG, fB, fA, FS, verb); } if(!raise && !shadow) { if (verb > 0) printf("\n\n"); intByteHolder = draw_flat(surf, strung, pigX, pigY, fR, fG, fB, fA, FS, verb); } return intByteHolder; } int main (int argc, char *argv[]) { struct arguments arguments; char verbage[] ="Verbose output enabled.\n"; arguments.program = "fortune"; arguments.width = 1280; arguments.height = 1024; arguments.f1R= 0.7; arguments.f1G= 0.7; arguments.f1B= 0.7; arguments.f1A= 0.9; arguments.fS= 25.0; arguments.indent= 10.0; arguments.verbose = 0; arguments.shadow = 0; arguments.bold = 0; arguments.italic = 0; arguments.oblique = 0; arguments.raised = 0; arguments.opacity = 1; arguments.stampX = 0.00000009; arguments.stampY = 0.00000009; arguments.font = "Bitstream Vera Sans Mono"; argp_parse (&argp, argc, argv, 0, 0, &arguments); if (arguments.verbose) printf (verbage); FILE *pipInput; pipInput = popen (arguments.program, "r"); if (pipInput == NULL) { return EXIT_FAILURE; } cairo_surface_t *croSurface, *croPNGSurface; cairo_t *srfOutput, *srfPNG; int intInputBytes; int intNumBytes = 100; char *strInput; cairo_font_slant_t croFontSlant; cairo_font_weight_t croFontWeight; if(arguments.italic > 0) { croFontSlant = CAIRO_FONT_SLANT_ITALIC; } else if(arguments.oblique > 0) { croFontSlant = CAIRO_FONT_SLANT_OBLIQUE; } else { croFontSlant = CAIRO_FONT_SLANT_NORMAL; } if(arguments.bold > 0) { croFontWeight = CAIRO_FONT_WEIGHT_BOLD; } else { croFontWeight = CAIRO_FONT_WEIGHT_NORMAL; } strInput = (char *) malloc (intNumBytes + 1); croPNGSurface = cairo_image_surface_create_from_png (arguments.args[0]); croSurface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, arguments.width, arguments.height); srfOutput = cairo_create (croSurface); if(arguments.opacity > 0.0) { double bgR = atof(arguments.args[2]), bgG = atof(arguments.args[3]), bgB = atof(arguments.args[4]), bgA = arguments.opacity; cairo_pattern_t *patBg; patBg = cairo_pattern_create_linear (0.0, 0.0, 0.0, arguments.height); cairo_pattern_add_color_stop_rgba (patBg, 1.0, bgR, bgG, bgB, bgA); cairo_rectangle (srfOutput, 0, 0, arguments.width, arguments.height); cairo_set_source (srfOutput, patBg); cairo_fill (srfOutput); cairo_pattern_destroy (patBg); if(arguments.verbose > 0) printf("Drew the background\n"); } else if(arguments.verbose > 0) printf("Skipping the background\n"); if(arguments.stampX > 0.00000009 || arguments.stampY > 0.00000009) { cairo_set_source_surface(srfOutput, croPNGSurface, arguments.stampX, arguments.stampY); } else { cairo_set_source_surface(srfOutput, croPNGSurface, arguments.width - cairo_image_surface_get_width (croPNGSurface), arguments.height - cairo_image_surface_get_height (croPNGSurface)); } cairo_paint (srfOutput); cairo_surface_destroy(croPNGSurface); intInputBytes = getline(&strInput, &intNumBytes, pipInput); cairo_select_font_face (srfOutput, arguments.font, croFontSlant, croFontWeight); intInputBytes = draw_it(srfOutput, strInput, arguments.indent, arguments.fS, arguments.f1R, arguments.f1G, arguments.f1B, arguments.f1A, arguments.fS, arguments.verbose, arguments.shadow, arguments.raised); double dblPosY = arguments.fS*2; while(getline (&strInput, &intNumBytes, pipInput) != -1) { intInputBytes = draw_it(srfOutput, strInput, arguments.indent, dblPosY, arguments.f1R, arguments.f1G, arguments.f1B, arguments.f1A, arguments.fS, arguments.verbose, arguments.shadow, arguments.raised); strInput = (char *) malloc (intNumBytes); dblPosY += arguments.fS; } cairo_destroy (srfOutput); cairo_surface_write_to_png (croSurface, arguments.args[1]); if(arguments.verbose > 0) printf("Wrote the Output png\n"); cairo_surface_destroy (croSurface); pclose(pipInput); return 0; }