X-Git-Url: https://git.cworth.org/git?p=spritext;a=blobdiff_plain;f=spritext.c;h=21d77f54df6e9036cd690566c716a97751a62313;hp=a9c670bdea403a2d3067303e2dfbdfeac51fbd1a;hb=HEAD;hpb=526772356e073996f070b988e26d877abbc08835 diff --git a/spritext.c b/spritext.c index a9c670b..21d77f5 100644 --- a/spritext.c +++ b/spritext.c @@ -6,7 +6,6 @@ #include #include #include -#include #ifndef CAIRO_HAS_PNG_FUNCTIONS #error This program requires cairo with PNG support @@ -20,48 +19,71 @@ #define TRUE (1==1) #define FALSE (!TRUE) -static cairo_status_t -stdio_write (void *closure, const unsigned char *data, unsigned int length); - -double -get_max_width (cairo_t *cr, char *characters); - -double -get_max_height (cairo_t *cr, char *characters); - -void -out_stroke (cairo_t *cr) +static double +get_max_width (cairo_t *cr, const char *characters, int num_characters) { - + int i; + double max_width = 0.; + char string[2]; + string[1] = '\0'; + for (i = 0; i < num_characters; i++) { + cairo_text_extents_t extents; + string[0] = characters[i]; + cairo_text_extents (cr, string, &extents); + if ((extents.width + (extents.x_bearing * 2)) > max_width) + max_width = extents.width + (extents.x_bearing * 2); + } + return max_width; } -int -cgiMain () +static double +get_max_height (cairo_t *cr, const char *characters, int num_characters) { - char outputJson = FALSE; - - char characters[] = { - '!', '"', '#', '$', '%', '&','\'', '(', - ')', '*', '+', ',', '-', '.', '/', '0', - '1', '2', '3', '4', '5', '6', '7', '8', - '9', ':', ';', '<', '=', '>', '?', '@', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', - 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', - 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', - 'Y', 'Z', '[','\\', ']', '^', '_', '`', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '{', '|', '}', '~' - }; - int i; + double max_height = 0.; + char string[2]; + string[1] = '\0'; + for (i = 0; i < num_characters; i++) { + cairo_text_extents_t extents; + string[0] = characters[i]; + cairo_text_extents (cr, string, &extents); + if ((extents.height) > max_height) + max_height = extents.height; + } + return max_height; +} +typedef struct { + char *family; + double size; + struct { + double red; + double green; + double blue; + } color; +} args_t; + +static void +parse_args (args_t *args) +{ + /* First some defaults */ + args->family = "Vera"; + args->size = 40; + args->color.red = 0.0; + args->color.green = 0.3; + args->color.blue = 0.0; + + /* XXX: Next, we should override the defaults based on + * command-line arguments. */ + + /* XXX: Finally, we'll want to allow CGI-based arguments as + * well. */ +#if USE_CGIG /* QueryString */ - char fontname[20]; int fontsize; char format[5]; char fillcolor[20]; + char fontname[20]; cgiFormStringNoNewlines("fontname", fontname, 20); cgiFormInteger("fontsize", &fontsize, 50); cgiFormStringNoNewlines("format", format, 5); @@ -71,39 +93,48 @@ cgiMain () int fillcolor_green; int fillcolor_blue; sscanf (fillcolor, " rgb : %d , %d , %d ", &fillcolor_red, &fillcolor_green, &fillcolor_blue); - if ( format[0] == 'j' && format[1] == 's' && format[2] == 'o' && format[3] == 'n' ) outputJson = TRUE; +#endif +} - if (outputJson) - { - cgiHeaderContentType("application/json"); - } else { - cgiHeaderContentType("image/png"); - } +static FT_Face +load_ft_face_for_family (const char *family) +{ + /* XXX: Instead of a hard-coded filename here, we should really be + * taking family and using fontconfig to map that to a + * filename. */ + const char font_filename[] = "./Vera.ttf"; - int error; + int error; + FT_Face ft_face; FT_Library library; - FT_Face ft_face; - FT_Bool use_kerning; - FT_UInt left_index, right_index; - FT_Vector kerning; error = FT_Init_FreeType( &library ); - if ( error ) - printf("error"); + if ( error ) { + fprintf (stderr, "Fatal error initializing freetype.\n"); + exit (1); + } - error = FT_New_Face( library,"/srv/rdworth.org/cgi-bin/Verdana.ttf", + error = FT_New_Face( library, font_filename, 0, &ft_face ); - if ( error == FT_Err_Unknown_File_Format ) - printf("File opened. Font format unsupported."); - else if ( error ) - printf("Could not be open or read or broken."); + if ( error == FT_Err_Unknown_File_Format ) { + fprintf (stderr, "Unsupported font format: %s\n", font_filename); + exit (1); + } else if ( error ) { + fprintf (stderr, "Failed to open file: %s\n", font_filename); + exit (1); + } - use_kerning = FT_HAS_KERNING( ft_face ); + return ft_face; +} - /* Compute max-width and max-height */ +static void +get_characters_max_width_height (FT_Face ft_face, double size, + const char *characters, int num_characters, + double *max_width, double *max_height) +{ cairo_surface_t *surface; cairo_t *cr; cairo_font_face_t *cr_face; @@ -113,180 +144,124 @@ cgiMain () cr = cairo_create (surface); -/* - cairo_select_font_face (cr, fontname, - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); -*/ cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); cairo_set_font_face (cr, cr_face); - cairo_set_font_size (cr, fontsize); + cairo_set_font_size (cr, size); cairo_set_line_width (cr, 1.0); - double max_width = get_max_width(cr, characters); - double max_height = get_max_height(cr, characters); + *max_width = get_max_width(cr, characters, num_characters); + *max_height = get_max_height(cr, characters, num_characters); cairo_font_face_destroy (cr_face); cairo_destroy (cr); cairo_surface_destroy(surface); +} - /* Draw */ - surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - (max_width + 8) * 10, - (max_height + 8) * 10); - - cr = cairo_create (surface); +static void +draw_character_table (cairo_t *cr, + FT_Face ft_face, double size, + const char *characters, int num_characters, + double character_width, double character_height) +{ + cairo_font_face_t *cr_face; + int i; -/* - cairo_select_font_face (cr, fontname, - CAIRO_FONT_SLANT_NORMAL, - CAIRO_FONT_WEIGHT_NORMAL); -*/ cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); cairo_set_font_face (cr, cr_face); - cairo_set_font_size (cr, fontsize); + cairo_set_font_size (cr, size); cairo_text_extents_t extents; double x = 0.0; double y = 0.0; - if (outputJson) - printf("{"); - - cairo_translate (cr, 0, -(max_height / 2.50)); - -// cairo_translate (cr, 0, -5.0); - char string[2]; string[1] = '\0'; - for (i = 0; i < ARRAY_SIZE(characters); i++) + + cairo_set_line_width (cr, 2.0); + for (i = 0; i < num_characters; i++) { - if (i % 10 == 0) - { - x = 0.; - y += max_height + 8; - } + cairo_rectangle (cr, x, y, character_width, character_height); + cairo_stroke_preserve (cr); + cairo_save (cr); + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ + cairo_fill (cr); + cairo_restore (cr); + string[0] = characters[i]; cairo_text_extents (cr, string, &extents); - if (outputJson) + cairo_move_to (cr, x - extents.x_bearing, y - extents.y_bearing); + cairo_show_text (cr, string); + + if ((i+1) % 10 == 0) { - if (i > 0) - printf (",\n"); - printf ("u%i:{", characters[i]); - printf ("x:%.1f,y:%.1f,w:%.1f,h:%.1f", - x, - y - (max_height * 1.15), - extents.width + extents.x_bearing, - extents.height); - int j; - for ( j = 0; j < ARRAY_SIZE(characters); j++ ) - { - right_index = FT_Get_Char_Index( ft_face, characters[i] ); - left_index = FT_Get_Char_Index( ft_face, characters[j] ); - - FT_Get_Kerning( ft_face, left_index, right_index, - FT_KERNING_UNSCALED, &kerning ); - - if ( kerning.x ) - printf(",k%d:%d", characters[j], kerning.x); - } - - printf ("}"); + x = 0.; + y += character_height; + } else { + x += character_width; } - - x -= extents.x_bearing; - - cairo_move_to (cr, x, y); - cairo_set_source_rgb (cr, 0., 0., 0.); // black - if ( 0 <= fillcolor_red && fillcolor_red <= 255.0 - && 0 <= fillcolor_green && fillcolor_green <= 255.0 - && 0 <= fillcolor_blue && fillcolor_blue <= 255.0 ) - cairo_set_source_rgb (cr, fillcolor_red / 255.0, fillcolor_green / 255.0, fillcolor_blue / 255.0); - cairo_text_path (cr, string); - cairo_fill (cr); - - x += extents.x_bearing; - x += max_width + 8; } -/* - int thick_width = 4; - int thin_width = 0; - - for (c = 'A'; c <= 'I'; c++) - { - string[0] = c; - int spacing = ((c - 'A') * letterspacing) + 1; - - - cairo_save(cr); - - cairo_move_to (cr, spacing, 0); - cairo_text_path (cr, string); -// cairo_set_source_rgb (cr, 0.1, 0.2, 0.2); // gray -cairo_set_source_rgb (cr, 0.8, 0.8, 0.85); // silver -cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - -cairo_push_group (cr); -cairo_set_line_width (cr, thick_width); -cairo_stroke_preserve (cr); -cairo_set_line_width (cr, thin_width); -cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); -cairo_stroke_preserve (cr); -cairo_fill (cr); -cairo_pop_group_to_source (cr); - -cairo_paint (cr); + cairo_scale (cr, 1, -1); + cairo_push_group (cr); +} -cairo_restore(cr); +int +main (void) +{ + char characters[] = { + '!', '"', '#', '$', '%', '&','\'', '(', + ')', '*', '+', ',', '-', '.', '/', '0', + '1', '2', '3', '4', '5', '6', '7', '8', + '9', ':', ';', '<', '=', '>', '?', '@', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', '[','\\', ']', '^', '_', '`', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '{', '|', '}', '~' + }; -cairo_move_to (cr, spacing, 0); -cairo_text_path (cr, string); -cairo_set_source_rgb (cr, 0.4, 0.45, 0.7); // blue + args_t args; + FT_Face ft_face; + double max_width, max_height; + cairo_surface_t *surface; + cairo_t *cr; -cairo_fill (cr); -} -*/ + parse_args (&args); - cairo_scale (cr, 1, -1); - cairo_push_group (cr); -/* + ft_face = load_ft_face_for_family (args.family); -cairo_pattern_t *gradient; + get_characters_max_width_height (ft_face, args.size, + characters, ARRAY_SIZE (characters), + &max_width, &max_height); -for (i = 0; i < 9; i++) -{ -char c[2]; -strncpy(c, STRING + i, 1); -c[1] = '\0'; -int spacing = (i * letterspacing) + 1; -cairo_move_to (cr, spacing, -3); -cairo_show_text (cr, c); + /* Draw */ + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + max_width * 10, + max_height * 10); -} -cairo_pop_group_to_source (cr); + cr = cairo_create (surface); -gradient = cairo_pattern_create_linear (0, 0, 0, -fontsize); -cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1, 1, 1, 0.5); -cairo_pattern_add_color_stop_rgba (gradient, 0.7, 1, 1, 1, 0.0); + cairo_set_source_rgb (cr, + args.color.red, + args.color.green, + args.color.blue); -cairo_mask (cr, gradient); + draw_character_table (cr, ft_face, args.size, + characters, ARRAY_SIZE (characters), + max_width, max_height); -cairo_pattern_destroy (gradient); -*/ - if (outputJson) - { - printf("}"); - } else { - cairo_surface_write_to_png_stream (surface, stdio_write, cgiOut); - } + cairo_surface_write_to_png (surface, "spritext-output.png"); + printf ("Result written to spritext-output.png\n"); cairo_destroy (cr); @@ -294,50 +269,3 @@ cairo_pattern_destroy (gradient); return 0; } - -static cairo_status_t -stdio_write (void *closure, const unsigned char *data, unsigned int length) -{ - FILE *file = closure; - if (fwrite (data, 1, length, file) == length) - return CAIRO_STATUS_SUCCESS; - else - return CAIRO_STATUS_WRITE_ERROR; -} - -double -get_max_width(cairo_t *cr, char *characters) -{ - int i; - double max_width = 0.; - char string[2]; - string[1] = '\0'; - for (i = 0; i < ARRAY_SIZE(characters); i++) { - cairo_text_extents_t extents; - string[0] = characters[i]; - cairo_text_extents (cr, string, &extents); - if ((extents.width + (extents.x_bearing * 2)) > max_width) - max_width = extents.width + (extents.x_bearing * 2); - } - return max_width; -} - -double -get_max_height(cairo_t *cr, char *characters) -{ - int i; - double max_height = 0.; - char string[2]; - string[1] = '\0'; - for (i = 0; i < ARRAY_SIZE(characters); i++) { - cairo_text_extents_t extents; - string[0] = characters[i]; - cairo_text_extents (cr, string, &extents); -// if ((extents.height - extents.y_bearing) > max_height) -// max_height = extents.height - extents.y_bearing; - if ((extents.height) > max_height) - max_height = extents.height; - } - return max_height; -} -