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