1 /* XXX: Copyright/license blurb needed here */
11 #ifndef CAIRO_HAS_PNG_FUNCTIONS
12 #error This program requires cairo with PNG support
16 #include FT_FREETYPE_H
18 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
24 stdio_write (void *closure, const unsigned char *data, unsigned int length);
27 get_max_width (cairo_t *cr, char *characters);
30 get_max_height (cairo_t *cr, char *characters);
35 char outputJson = FALSE;
38 '!', '"', '#', '$', '%', '&','\'', '(',
39 ')', '*', '+', ',', '-', '.', '/', '0',
40 '1', '2', '3', '4', '5', '6', '7', '8',
41 '9', ':', ';', '<', '=', '>', '?', '@',
42 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
43 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
44 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
45 'Y', 'Z', '[','\\', ']', '^', '_', '`',
46 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
47 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
48 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
49 'y', 'z', '{', '|', '}', '~'
59 cgiFormStringNoNewlines("fontname", fontname, 20);
60 cgiFormInteger("fontsize", &fontsize, 50);
61 cgiFormStringNoNewlines("format", format, 5);
62 cgiFormStringNoNewlines("fillcolor", fillcolor, 20);
67 sscanf (fillcolor, " rgb : %d , %d , %d ", &fillcolor_red, &fillcolor_green, &fillcolor_blue);
69 if ( format[0] == 'j' && format[1] == 's' && format[2] == 'o' && format[3] == 'n' )
74 cgiHeaderContentType("application/json");
76 cgiHeaderContentType("image/png");
83 FT_UInt left_index, right_index;
86 error = FT_Init_FreeType( &library );
90 error = FT_New_Face( library,"/srv/rdworth.org/cgi-bin/Verdana.ttf",
93 if ( error == FT_Err_Unknown_File_Format )
94 printf("File opened. Font format unsupported.");
96 printf("Could not be open or read or broken.");
98 use_kerning = FT_HAS_KERNING( ft_face );
100 /* Compute max-width and max-height */
101 cairo_surface_t *surface;
103 cairo_font_face_t *cr_face;
105 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
108 cr = cairo_create (surface);
111 cairo_select_font_face (cr, fontname,
112 CAIRO_FONT_SLANT_NORMAL,
113 CAIRO_FONT_WEIGHT_NORMAL);
115 cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
116 cairo_set_font_face (cr, cr_face);
118 cairo_set_font_size (cr, fontsize);
120 cairo_set_line_width (cr, 1.0);
122 double max_width = get_max_width(cr, characters);
123 double max_height = get_max_height(cr, characters);
125 cairo_font_face_destroy (cr_face);
129 cairo_surface_destroy(surface);
132 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
133 (max_width + 8) * 10,
134 (max_height + 8) * 10);
136 cr = cairo_create (surface);
139 cairo_select_font_face (cr, fontname,
140 CAIRO_FONT_SLANT_NORMAL,
141 CAIRO_FONT_WEIGHT_NORMAL);
143 cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
144 cairo_set_font_face (cr, cr_face);
146 cairo_set_font_size (cr, fontsize);
148 cairo_text_extents_t extents;
155 cairo_translate (cr, 0, -(max_height / 2.50));
157 // cairo_translate (cr, 0, -5.0);
161 for (i = 0; i < ARRAY_SIZE(characters); i++)
168 string[0] = characters[i];
170 cairo_text_extents (cr, string, &extents);
176 printf ("u%i:{", characters[i]);
177 printf ("x:%.1f,y:%.1f,w:%.1f,h:%.1f",
179 y - (max_height * 1.15),
180 extents.width + extents.x_bearing,
183 for ( j = 0; j < ARRAY_SIZE(characters); j++ )
185 right_index = FT_Get_Char_Index( ft_face, characters[i] );
186 left_index = FT_Get_Char_Index( ft_face, characters[j] );
188 FT_Get_Kerning( ft_face, left_index, right_index,
189 FT_KERNING_UNSCALED, &kerning );
192 printf(",k%d:%ld", characters[j], kerning.x);
198 x -= extents.x_bearing;
200 cairo_move_to (cr, x, y);
201 cairo_set_source_rgb (cr, 0., 0., 0.); // black
202 if ( 0 <= fillcolor_red && fillcolor_red <= 255.0
203 && 0 <= fillcolor_green && fillcolor_green <= 255.0
204 && 0 <= fillcolor_blue && fillcolor_blue <= 255.0 )
205 cairo_set_source_rgb (cr, fillcolor_red / 255.0, fillcolor_green / 255.0, fillcolor_blue / 255.0);
206 cairo_text_path (cr, string);
209 x += extents.x_bearing;
217 for (c = 'A'; c <= 'I'; c++)
220 int spacing = ((c - 'A') * letterspacing) + 1;
225 cairo_move_to (cr, spacing, 0);
226 cairo_text_path (cr, string);
227 // cairo_set_source_rgb (cr, 0.1, 0.2, 0.2); // gray
228 cairo_set_source_rgb (cr, 0.8, 0.8, 0.85); // silver
229 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
231 cairo_push_group (cr);
232 cairo_set_line_width (cr, thick_width);
233 cairo_stroke_preserve (cr);
234 cairo_set_line_width (cr, thin_width);
235 cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
236 cairo_stroke_preserve (cr);
238 cairo_pop_group_to_source (cr);
244 cairo_move_to (cr, spacing, 0);
245 cairo_text_path (cr, string);
246 cairo_set_source_rgb (cr, 0.4, 0.45, 0.7); // blue
252 cairo_scale (cr, 1, -1);
253 cairo_push_group (cr);
256 cairo_pattern_t *gradient;
258 for (i = 0; i < 9; i++)
261 strncpy(c, STRING + i, 1);
263 int spacing = (i * letterspacing) + 1;
264 cairo_move_to (cr, spacing, -3);
265 cairo_show_text (cr, c);
268 cairo_pop_group_to_source (cr);
270 gradient = cairo_pattern_create_linear (0, 0, 0, -fontsize);
271 cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1, 1, 1, 0.5);
272 cairo_pattern_add_color_stop_rgba (gradient, 0.7, 1, 1, 1, 0.0);
274 cairo_mask (cr, gradient);
276 cairo_pattern_destroy (gradient);
282 cairo_surface_write_to_png_stream (surface, stdio_write, cgiOut);
287 cairo_surface_destroy (surface);
292 static cairo_status_t
293 stdio_write (void *closure, const unsigned char *data, unsigned int length)
295 FILE *file = closure;
296 if (fwrite (data, 1, length, file) == length)
297 return CAIRO_STATUS_SUCCESS;
299 return CAIRO_STATUS_WRITE_ERROR;
303 get_max_width(cairo_t *cr, char *characters)
306 double max_width = 0.;
309 for (i = 0; i < ARRAY_SIZE(characters); i++) {
310 cairo_text_extents_t extents;
311 string[0] = characters[i];
312 cairo_text_extents (cr, string, &extents);
313 if ((extents.width + (extents.x_bearing * 2)) > max_width)
314 max_width = extents.width + (extents.x_bearing * 2);
320 get_max_height(cairo_t *cr, char *characters)
323 double max_height = 0.;
326 for (i = 0; i < ARRAY_SIZE(characters); i++) {
327 cairo_text_extents_t extents;
328 string[0] = characters[i];
329 cairo_text_extents (cr, string, &extents);
330 // if ((extents.height - extents.y_bearing) > max_height)
331 // max_height = extents.height - extents.y_bearing;
332 if ((extents.height) > max_height)
333 max_height = extents.height;