]> git.cworth.org Git - spritext/blob - spritext.c
Initial import of Richard's spritext project
[spritext] / spritext.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <libgen.h>
5 #include <cairo.h>
6 #include <cairo-ft.h>
7 #include <cgic.h>
8 #ifndef CAIRO_HAS_PNG_FUNCTIONS
9 #error This program requires cairo with PNG support
10 #endif
11 #include <ft2build.h>
12 #include FT_FREETYPE_H
13
14 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
15
16 #define TRUE (1==1)
17 #define FALSE (!TRUE)
18
19 static cairo_status_t
20 stdio_write (void *closure, const unsigned char *data, unsigned int length);
21
22 double
23 get_max_width (cairo_t *cr, char *characters);
24
25 double
26 get_max_height (cairo_t *cr, char *characters);
27
28 void
29 out_stroke (cairo_t *cr)
30 {
31     
32 }
33
34 int
35 cgiMain ()
36 {
37     char outputJson = FALSE;
38
39     char characters[] = {
40       '!', '"', '#', '$', '%', '&','\'', '(',
41       ')', '*', '+', ',', '-', '.', '/', '0',
42       '1', '2', '3', '4', '5', '6', '7', '8',
43       '9', ':', ';', '<', '=', '>', '?', '@',
44       'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
45       'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
46       'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
47       'Y', 'Z', '[','\\', ']', '^', '_', '`',
48       'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
49       'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
50       'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
51       'y', 'z', '{', '|', '}', '~'
52     };
53
54     int i;
55
56     /* QueryString */
57     char fontname[20];
58     int fontsize;
59     char format[5];
60     char fillcolor[20];
61     cgiFormStringNoNewlines("fontname", fontname, 20);
62     cgiFormInteger("fontsize", &fontsize, 50);
63     cgiFormStringNoNewlines("format", format, 5);
64     cgiFormStringNoNewlines("fillcolor", fillcolor, 20);
65
66     int fillcolor_red;
67     int fillcolor_green;
68     int fillcolor_blue;
69     sscanf (fillcolor, " rgb : %d , %d , %d ", &fillcolor_red, &fillcolor_green, &fillcolor_blue);
70
71     if ( format[0] == 'j' && format[1] == 's' && format[2] == 'o' && format[3] == 'n' )
72       outputJson = TRUE;
73
74     if (outputJson)
75     {
76       cgiHeaderContentType("application/json");
77     } else {
78       cgiHeaderContentType("image/png");
79     }
80
81     int error;  
82     FT_Library  library;
83     FT_Face     ft_face;
84     FT_Bool     use_kerning;
85     FT_UInt     left_index, right_index;
86     FT_Vector   kerning;
87
88     error = FT_Init_FreeType( &library );
89     if ( error )
90       printf("error");
91
92     error = FT_New_Face( library,"/srv/rdworth.org/cgi-bin/Verdana.ttf",
93                          0,
94                          &ft_face );
95     if ( error == FT_Err_Unknown_File_Format )
96         printf("File opened. Font format unsupported.");
97     else if ( error )
98         printf("Could not be open or read or broken.");
99
100     use_kerning = FT_HAS_KERNING( ft_face );
101
102     /* Compute max-width and max-height */
103     cairo_surface_t *surface;
104     cairo_t *cr;
105     cairo_font_face_t *cr_face;
106
107     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
108                                           1, 1);
109
110     cr = cairo_create (surface);
111
112 /*
113     cairo_select_font_face (cr, fontname,
114                        CAIRO_FONT_SLANT_NORMAL,
115                        CAIRO_FONT_WEIGHT_NORMAL);
116 */
117     cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
118     cairo_set_font_face (cr, cr_face);
119
120     cairo_set_font_size (cr, fontsize);
121
122     cairo_set_line_width (cr, 1.0);
123
124     double max_width = get_max_width(cr, characters);
125     double max_height = get_max_height(cr, characters);
126
127     cairo_font_face_destroy (cr_face);
128
129     cairo_destroy (cr);
130
131     cairo_surface_destroy(surface);
132
133     /* Draw */
134     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
135                                          (max_width + 8) * 10,
136                                          (max_height + 8) * 10);
137
138     cr = cairo_create (surface);
139
140 /*
141     cairo_select_font_face (cr, fontname,
142                        CAIRO_FONT_SLANT_NORMAL,
143                        CAIRO_FONT_WEIGHT_NORMAL);
144 */
145     cr_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
146     cairo_set_font_face (cr, cr_face);
147
148     cairo_set_font_size (cr, fontsize);
149
150     cairo_text_extents_t extents;
151     double x = 0.0;
152     double y = 0.0;
153
154     if (outputJson)
155       printf("{");
156
157     cairo_translate (cr, 0, -(max_height / 2.50));
158
159 //    cairo_translate (cr, 0, -5.0);
160
161     char string[2];
162     string[1] = '\0';
163     for (i = 0; i < ARRAY_SIZE(characters); i++)
164     {
165       if (i % 10 == 0)
166       {
167         x = 0.;
168         y += max_height + 8;
169       }
170       string[0] = characters[i];
171
172       cairo_text_extents (cr, string, &extents);
173
174       if (outputJson)
175       {
176         if (i > 0)
177           printf (",\n");
178         printf ("u%i:{", characters[i]);
179         printf ("x:%.1f,y:%.1f,w:%.1f,h:%.1f",
180                 x,
181                 y - (max_height * 1.15),
182                 extents.width + extents.x_bearing,
183                 extents.height);
184         int j;
185         for ( j = 0; j < ARRAY_SIZE(characters); j++ )
186         {
187           right_index = FT_Get_Char_Index( ft_face, characters[i] );
188           left_index = FT_Get_Char_Index( ft_face, characters[j] );
189     
190           FT_Get_Kerning( ft_face, left_index, right_index,
191                           FT_KERNING_UNSCALED, &kerning );
192     
193           if ( kerning.x )
194             printf(",k%d:%d", characters[j], kerning.x);
195         }
196
197         printf ("}");
198       }
199
200       x -= extents.x_bearing;
201   
202       cairo_move_to (cr, x, y);
203       cairo_set_source_rgb (cr, 0., 0., 0.); // black
204       if ( 0 <= fillcolor_red && fillcolor_red <= 255.0
205         && 0 <= fillcolor_green && fillcolor_green <= 255.0
206         && 0 <= fillcolor_blue && fillcolor_blue <= 255.0 )
207         cairo_set_source_rgb (cr, fillcolor_red / 255.0, fillcolor_green / 255.0, fillcolor_blue / 255.0);
208       cairo_text_path (cr, string);
209       cairo_fill (cr);
210
211       x += extents.x_bearing;
212       x += max_width + 8;
213     }
214
215 /*
216     int thick_width = 4;
217     int thin_width = 0;
218
219     for (c = 'A'; c <= 'I'; c++)
220     {
221       string[0] = c;
222       int spacing = ((c - 'A') * letterspacing) + 1;
223
224
225       cairo_save(cr);
226
227       cairo_move_to (cr, spacing, 0);
228       cairo_text_path (cr, string);
229 //      cairo_set_source_rgb (cr, 0.1, 0.2, 0.2); // gray
230       cairo_set_source_rgb (cr, 0.8, 0.8, 0.85); // silver
231       cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
232
233       cairo_push_group (cr);
234       cairo_set_line_width (cr, thick_width);
235       cairo_stroke_preserve (cr);
236       cairo_set_line_width (cr, thin_width);
237       cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
238       cairo_stroke_preserve (cr);
239       cairo_fill (cr);
240       cairo_pop_group_to_source (cr);
241
242       cairo_paint (cr);
243
244       cairo_restore(cr);
245
246       cairo_move_to (cr, spacing, 0);
247       cairo_text_path (cr, string);
248       cairo_set_source_rgb (cr, 0.4, 0.45, 0.7); // blue
249
250       cairo_fill (cr);
251     }
252 */
253
254     cairo_scale (cr, 1, -1);
255     cairo_push_group (cr);
256 /*
257
258     cairo_pattern_t *gradient;
259
260     for (i = 0; i < 9; i++)
261     {
262       char c[2];
263       strncpy(c, STRING + i, 1);
264       c[1] = '\0';
265       int spacing = (i * letterspacing) + 1;
266       cairo_move_to (cr, spacing, -3);
267       cairo_show_text (cr, c);
268
269     }
270       cairo_pop_group_to_source (cr);
271
272       gradient = cairo_pattern_create_linear (0, 0, 0, -fontsize);
273       cairo_pattern_add_color_stop_rgba (gradient, 0.0, 1, 1, 1, 0.5);
274       cairo_pattern_add_color_stop_rgba (gradient, 0.7, 1, 1, 1, 0.0);
275
276       cairo_mask (cr, gradient);
277
278       cairo_pattern_destroy (gradient);
279 */
280     if (outputJson)
281     {
282       printf("}");
283     } else {
284       cairo_surface_write_to_png_stream (surface, stdio_write, cgiOut);
285     }
286
287     cairo_destroy (cr);
288
289     cairo_surface_destroy (surface);
290
291     return 0;
292 }
293
294 static cairo_status_t
295 stdio_write (void *closure, const unsigned char *data, unsigned int length)
296 {
297     FILE *file = closure;
298     if (fwrite (data, 1, length, file) == length)
299         return CAIRO_STATUS_SUCCESS;
300     else
301         return CAIRO_STATUS_WRITE_ERROR;
302 }
303
304 double
305 get_max_width(cairo_t *cr, char *characters)
306 {
307   int i;
308   double max_width = 0.;
309   char string[2];
310   string[1] = '\0';
311   for (i = 0; i < ARRAY_SIZE(characters); i++) {
312     cairo_text_extents_t extents;
313     string[0] = characters[i];
314     cairo_text_extents (cr, string, &extents);
315     if ((extents.width + (extents.x_bearing * 2)) > max_width)
316       max_width = extents.width + (extents.x_bearing * 2);
317   }
318   return max_width;
319 }
320
321 double
322 get_max_height(cairo_t *cr, char *characters)
323 {
324   int i;
325   double max_height = 0.;
326   char string[2];
327   string[1] = '\0';
328   for (i = 0; i < ARRAY_SIZE(characters); i++) {
329     cairo_text_extents_t extents;
330     string[0] = characters[i];
331     cairo_text_extents (cr, string, &extents);
332 //    if ((extents.height - extents.y_bearing) > max_height)
333 //      max_height = extents.height - extents.y_bearing;
334     if ((extents.height) > max_height)
335       max_height = extents.height;
336   }
337   return max_height;
338 }
339