*** empty log message ***
[m17n/m17n-test.git] / gdkdraw.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <gd.h>
5 #include <gtk/gtk.h>
6 #include <gdk-pixbuf/gdk-pixbuf.h>
7 #include <m17n-gui.h>
8 #include <m17n-misc.h>
9
10 #define FONT_PT_SIZE 40
11
12 gint
13 delete_event (GtkWidget *widget, GdkEvent *event, gpointer data)
14 {
15   return FALSE; 
16 }
17
18 void
19 destroy (GtkWidget *widget, gpointer data)
20 {
21   gtk_main_quit ();
22 }
23
24 int
25 main (int argc, char **argv)
26 {
27   MSymbol lang;
28   MText *mt;
29   int nchars;
30   MFrame *frame;
31   MDrawMetric metric;
32   gdImagePtr image;
33   int bg_color;
34   unsigned char *title;
35   int title_len;
36   int allocated;
37   MSymbol utf8;
38   char *family_names = NULL;
39
40   gtk_init (&argc, &argv);
41
42   if (argc < 2)
43     {
44       fprintf (stderr, "Usage: gdkdraw LANGUAGE\n");
45       exit (1);
46     }
47
48   M17N_INIT ();
49   lang = msymbol (argv[1]);
50   mt = mlanguage_text (lang);
51   if (! mt)
52     {
53       fprintf (stderr, "No native name for the language \"%s\".\n", argv[1]);
54       exit (1);
55     }
56
57   nchars = mtext_len (mt);
58
59   /* Encode native language name in MT into the buffer TITLE.  */
60   merror_code = 0;
61   utf8 = msymbol ("utf-8");
62   allocated = nchars * 4;       /* Usually this is enough.  */
63   title = malloc (allocated);
64   title_len = mconv_encode_buffer (utf8, mt, title, allocated);
65   while (title_len < 0 && merror_code == MCONVERSION_RESULT_INSUFFICIENT_DST)
66     {
67       allocated += allocated;
68       title = realloc (title, allocated);
69       title_len = mconv_encode_buffer (utf8, mt, title, allocated);
70     }
71   if (title_len < 0)
72     {
73       fprintf (stderr, "Encoding of native language name failed.");
74       exit (1);
75     }
76   title[title_len] = '\0';
77
78   {
79     MPlist *param = mplist ();
80     MFace *face = mface ();
81     MFontset *fontset = mfontset ("generic");
82
83     mface_put_prop (face, Msize, (void *) (FONT_PT_SIZE * -10));
84     mface_put_prop (face, Mfontset, fontset);
85     if (argc > 2)
86       mface_put_prop (face, Mfamily, msymbol (argv[2]));
87     mplist_add (param, Mdevice, msymbol ("gd"));
88     mplist_add (param, Mface, face);
89     frame = mframe (param);
90     m17n_object_unref (fontset);
91     m17n_object_unref (face);
92     m17n_object_unref (param);
93
94     if (! frame)
95       {
96         fprintf (stderr, "Frame creation failed.  Perhaps no GD library.\n");
97         exit (1);
98       }
99   }
100
101   /* Build GD image and draw MT on it while listing up font families
102      used for drawing.  */
103   {
104     MDrawControl control;
105     MDrawGlyph *glyphs;
106     int array_size, num_glyphs;
107     MPlist *family_list;
108     int family_name_len;
109
110     memset (&control, 0, sizeof (control));
111     control.anti_alias = 1;
112     control.enable_bidi = 1;
113     mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control,
114                         &metric, NULL, NULL);
115
116     image = gdImageCreateTrueColor (metric.width, metric.height);
117     bg_color = gdImageColorAllocate (image, 255, 255, 255);
118     gdImageFilledRectangle (image, 0, 0, metric.width - 1, metric.height - 1,
119                             bg_color);
120
121     array_size = nchars * 2; /* Usually this is enough. */
122     glyphs = malloc (sizeof (MDrawGlyph) * array_size);
123     if (mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
124                           &num_glyphs) < 0)
125       {
126         array_size = num_glyphs;
127         glyphs = realloc (glyphs, sizeof (MDrawGlyph) * array_size);
128         mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
129                           &num_glyphs);
130       }
131     
132     family_list = NULL;
133     family_name_len = 0;
134     while (num_glyphs-- > 0)
135       if (glyphs[num_glyphs].font)
136         {
137           MSymbol family = mfont_get_prop (glyphs[num_glyphs].font, Mfamily);
138
139           if (! family_list)
140             {
141               family_list = mplist ();
142               mplist_add (family_list, Msymbol, family);
143               family_name_len = strlen (msymbol_name (family));
144             }
145           else if (! mplist_find_by_value (family_list, family))
146             {
147               mplist_push (family_list, Msymbol, family);
148               family_name_len += strlen (msymbol_name (family)) + 1;
149             }
150         }
151
152     mdraw_text_with_control (frame, (MDrawWindow) image,
153                              - metric.x, - metric.y,
154                              mt, 0, mtext_len (mt), &control);
155     m17n_object_unref (frame);
156
157     if (family_list)
158       {
159         char *p = alloca (family_name_len + 1);
160         MPlist *pl = family_list;
161
162         family_names = p;
163         p += sprintf (p, "%s", msymbol_name (mplist_value (pl)));
164         for (pl = mplist_next (pl); mplist_key (pl) != Mnil;
165              pl = mplist_next (pl))
166           p += sprintf (p, ",%s", msymbol_name (mplist_value (pl)));
167       }
168     m17n_object_unref (family_list);
169   }
170
171   M17N_FINI ();
172
173   {
174     GdkPixbuf *pixbuf;
175     GtkWidget *window, *box, *text, *label;
176     int n_channels, rowstride;
177     guchar *pixels, *p;
178     int x, y;
179     PangoAttrList *attr_list;
180     PangoAttribute *attr_size;
181
182     attr_list = pango_attr_list_new ();
183     attr_size = pango_attr_size_new (FONT_PT_SIZE * PANGO_SCALE);
184     attr_size->start_index = 0, attr_size->end_index = title_len;
185     pango_attr_list_insert (attr_list, attr_size);
186     if (family_names)
187       {
188         PangoAttribute *attr_family;
189
190         attr_family = pango_attr_family_new (family_names);
191         attr_family->start_index = 0, attr_family->end_index = title_len;
192         pango_attr_list_insert (attr_list, attr_family);
193       }
194
195     pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, 0, 8,
196                              metric.width, metric.height);
197     n_channels = gdk_pixbuf_get_n_channels (pixbuf);
198     rowstride = gdk_pixbuf_get_rowstride (pixbuf);
199     pixels = gdk_pixbuf_get_pixels (pixbuf);
200
201     for (y = 0; y < metric.height; y++)
202       for (x = 0; x < metric.width; x++)
203         {
204           int cid = gdImageGetPixel (image, x, y);
205           p = pixels + y * rowstride + x * n_channels;
206
207           p[0] = gdImageRed (image, cid);
208           p[1] = gdImageGreen (image, cid);
209           p[2] = gdImageBlue (image, cid);
210         }
211     gdImageDestroy (image);
212
213     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
214     box = gtk_vbox_new (FALSE, 0);
215     text = gtk_image_new_from_pixbuf (pixbuf);
216     label = gtk_label_new ((gchar *) title);
217     gtk_box_pack_start (GTK_BOX (box), text, TRUE, FALSE, 0);
218     gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 0);
219
220     gtk_container_add (GTK_CONTAINER (window), box);
221     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
222                         GTK_SIGNAL_FUNC (delete_event), NULL);
223     gtk_signal_connect (GTK_OBJECT (window), "destroy",
224                         GTK_SIGNAL_FUNC (destroy), NULL);
225     gtk_widget_show (text);
226     gtk_widget_show (label);
227     gtk_label_set_attributes (GTK_LABEL (label), attr_list);
228     gtk_widget_show (box);
229     gtk_widget_show (window);
230     gtk_main ();
231   }
232
233   free (title);
234
235   exit (0);
236 }