rendered paste body//
// Copyright 8-16-2007 Jonathan Westbrock <dulljon@yahoo.com>
// 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 <cairo.h>
#include <stdio.h>
#include <stdlib.h>
#include <argp.h>
#include <string.h>
const char *argp_program_version = "Alpha";
const char *argp_program_bug_address = "<dulljon@yahoo.com>";
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("<Drew text>\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("<Drew text>\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("<Drew text>\n<Raise complete>\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("<Drew text>\n<Default flat draw complete\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("<Drew text>\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("<Drew text>\n<Shadow complete>\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<Shadow initiated>\n");
intByteHolder = draw_shadow(surf, strung, pigX, pigY, fR, fG, fB, fA, FS, verb);
}
if(raise)
{
if (verb > 0)
printf("\n<Raise initiated>\n");
intByteHolder = draw_raised(surf, strung, pigX, pigY, fR, fG, fB, fA, FS, verb);
}
if(!raise && !shadow)
{
if (verb > 0)
printf("\n<Default flat draw initiated>\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;
}