1 /* XXX: Copyright/license blurb needed here */
10 #ifndef CAIRO_HAS_PNG_FUNCTIONS
11 #error This program requires cairo with PNG support
15 #include FT_FREETYPE_H
17 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
24 stdio_write (void *closure, const unsigned char *data, unsigned int length);
28 get_max_width (cairo_t *cr, const char *characters, int num_characters)
31 double max_width = 0.;
34 for (i = 0; i < num_characters; i++) {
35 cairo_text_extents_t extents;
36 string[0] = characters[i];
37 cairo_text_extents (cr, string, &extents);
38 if ((extents.width + (extents.x_bearing * 2)) > max_width)
39 max_width = extents.width + (extents.x_bearing * 2);
45 get_max_height (cairo_t *cr, const char *characters, int num_characters)
48 double max_height = 0.;
51 for (i = 0; i < num_characters; i++) {
52 cairo_text_extents_t extents;
53 string[0] = characters[i];
54 cairo_text_extents (cr, string, &extents);
55 // if ((extents.height - extents.y_bearing) > max_height)
56 // max_height = extents.height - extents.y_bearing;
57 if ((extents.height) > max_height)
58 max_height = extents.height;
74 parse_args (args_t *args)
76 /* First some defaults */
77 args->family = "Vera";
79 args->color.red = 0.0;
80 args->color.green = 0.0;
81 args->color.blue = 0.0;
83 /* XXX: Next, we should override the defaults based on
84 * command-line arguments. */
86 /* XXX: Finally, we'll want to allow CGI-based arguments as
94 cgiFormStringNoNewlines("fontname", fontname, 20);
95 cgiFormInteger("fontsize", &fontsize, 50);
96 cgiFormStringNoNewlines("format", format, 5);
97 cgiFormStringNoNewlines("fillcolor", fillcolor, 20);
102 sscanf (fillcolor, " rgb : %d , %d , %d ", &fillcolor_red, &fillcolor_green, &fillcolor_blue);
103 if ( format[0] == 'j' && format[1] == 's' && format[2] == 'o' && format[3] == 'n' )
109 load_ft_face_for_family (const char *family)
111 /* XXX: Instead of a hard-coded filename here, we should really be
112 * taking family and using fontconfig to map that to a
114 const char font_filename[] = "./Vera.ttf";
120 error = FT_Init_FreeType( &library );
122 fprintf (stderr, "Fatal error initializing freetype.\n");
126 error = FT_New_Face( library, font_filename,
129 if ( error == FT_Err_Unknown_File_Format ) {
130 fprintf (stderr, "Unsupported font format: %s\n", font_filename);
132 } else if ( error ) {
133 fprintf (stderr, "Failed to open file: %s\n", font_filename);
141 get_characters_max_width_height (FT_Face ft_face, double size,
142 const char *characters, int num_characters,
143 double *max_width, double *max_height)
145 cairo_surface_t *surface;
147 cairo_font_face_t *cr_face;
149 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
152 cr = cairo_create (surface);
155 cairo_select_font_face (cr, fontname,
156 CAIRO_FONT_SLANT_NORMAL,
157 CAIRO_FONT_WEIGHT_NORMAL);
159 cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
160 cairo_set_font_face (cr, cr_face);
162 cairo_set_font_size (cr, size);
164 cairo_set_line_width (cr, 1.0);
166 *max_width = get_max_width(cr, characters, num_characters);
167 *max_height = get_max_height(cr, characters, num_characters);
169 cairo_font_face_destroy (cr_face);
173 cairo_surface_destroy(surface);
177 draw_character_table (cairo_t *cr,
178 FT_Face ft_face, double size,
179 const char *characters, int num_characters,
180 double character_width, double character_height)
182 cairo_font_face_t *cr_face;
186 cairo_select_font_face (cr, fontname,
187 CAIRO_FONT_SLANT_NORMAL,
188 CAIRO_FONT_WEIGHT_NORMAL);
190 cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
191 cairo_set_font_face (cr, cr_face);
193 cairo_set_font_size (cr, size);
195 cairo_text_extents_t extents;
199 cairo_translate (cr, 0, -(character_height / 2.50));
201 // cairo_translate (cr, 0, -5.0);
205 for (i = 0; i < num_characters; i++)
210 y += character_height + 8;
212 string[0] = characters[i];
214 cairo_text_extents (cr, string, &extents);
216 x -= extents.x_bearing;
218 cairo_move_to (cr, x, y);
219 cairo_text_path (cr, string);
222 x += extents.x_bearing;
223 x += character_width + 8;
230 for (c = 'A'; c <= 'I'; c++)
233 int spacing = ((c - 'A') * letterspacing) + 1;
238 cairo_move_to (cr, spacing, 0);
239 cairo_text_path (cr, string);
240 // cairo_set_source_rgb (cr, 0.1, 0.2, 0.2); // gray
241 cairo_set_source_rgb (cr, 0.8, 0.8, 0.85); // silver
242 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
244 cairo_push_group (cr);
245 cairo_set_line_width (cr, thick_width);
246 cairo_stroke_preserve (cr);
247 cairo_set_line_width (cr, thin_width);
248 cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
249 cairo_stroke_preserve (cr);
251 cairo_pop_group_to_source (cr);
257 cairo_move_to (cr, spacing, 0);
258 cairo_text_path (cr, string);
259 cairo_set_source_rgb (cr, 0.4, 0.45, 0.7); // blue
265 cairo_scale (cr, 1, -1);
266 cairo_push_group (cr);
269 cairo_pattern_t *gradient;
271 for (i = 0; i < 9; i++)
274 strncpy(c, STRING + i, 1);
276 int spacing = (i * letterspacing) + 1;
277 cairo_move_to (cr, spacing, -3);
278 cairo_show_text (cr, c);
281 cairo_pop_group_to_source (cr);
283 gradient = cairo_pattern_create_linear (0, 0, 0, -fontsize);
284 cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1, 1, 1, 0.5);
285 cairo_pattern_add_color_stop_rgba (gradient, 0.7, 1, 1, 1, 0.0);
287 cairo_mask (cr, gradient);
289 cairo_pattern_destroy (gradient);
296 char characters[] = {
297 '!', '"', '#', '$', '%', '&','\'', '(',
298 ')', '*', '+', ',', '-', '.', '/', '0',
299 '1', '2', '3', '4', '5', '6', '7', '8',
300 '9', ':', ';', '<', '=', '>', '?', '@',
301 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
302 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
303 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
304 'Y', 'Z', '[','\\', ']', '^', '_', '`',
305 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
306 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
307 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
308 'y', 'z', '{', '|', '}', '~'
313 double max_width, max_height;
314 cairo_surface_t *surface;
322 cgiHeaderContentType("application/json");
324 cgiHeaderContentType("image/png");
328 ft_face = load_ft_face_for_family (args.family);
330 get_characters_max_width_height (ft_face, args.size,
331 characters, ARRAY_SIZE (characters),
332 &max_width, &max_height);
335 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
336 (max_width + 8) * 10,
337 (max_height + 8) * 10);
339 cr = cairo_create (surface);
341 cairo_set_source_rgb (cr,
346 draw_character_table (cr, ft_face, args.size,
347 characters, ARRAY_SIZE (characters),
348 max_width, max_height);
355 cairo_surface_write_to_png_stream (surface, stdio_write, cgiOut);
359 cairo_surface_write_to_png (surface, "spritext-output.png");
360 printf ("Result written to spritext-output.png\n");
364 cairo_surface_destroy (surface);
370 static cairo_status_t
371 stdio_write (void *closure, const unsigned char *data, unsigned int length)
373 FILE *file = closure;
374 if (fwrite (data, 1, length, file) == length)
375 return CAIRO_STATUS_SUCCESS;
377 return CAIRO_STATUS_WRITE_ERROR;