*** 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 60
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   if (argc < 2)
41     {
42       fprintf (stderr, "Usage: gdkdraw LANGUAGE\n");
43       exit (1);
44     }
45
46   M17N_INIT ();
47   lang = msymbol (argv[1]);
48   mt = mlanguage_text (lang);
49   if (! mt)
50     {
51       fprintf (stderr, "No native name for the language \"%s\".\n", argv[1]);
52       exit (1);
53     }
54
55   nchars = mtext_len (mt);
56
57   /* Encode native language name in MT into the buffer TITLE.  */
58   merror_code = 0;
59   utf8 = msymbol ("utf-8");
60   allocated = nchars * 4;       /* Usually this is enough.  */
61   title = malloc (allocated);
62   title_len = mconv_encode_buffer (utf8, mt, title, allocated);
63   while (title_len < 0 && merror_code == MCONVERSION_RESULT_INSUFFICIENT_DST)
64     {
65       allocated += allocated;
66       title = realloc (title, allocated);
67       title_len = mconv_encode_buffer (utf8, mt, title, allocated);
68     }
69   if (title_len < 0)
70     {
71       fprintf (stderr, "Encoding of native language name failed.");
72       exit (1);
73     }
74   title[title_len] = '\0';
75
76   {
77     MPlist *param = mplist ();
78     MFace *face = mface ();
79     MFontset *fontset = mfontset ("generic");
80
81     mface_put_prop (face, Msize, (void *) (FONT_PT_SIZE * -10));
82     mface_put_prop (face, Mfontset, fontset);
83     if (argc > 2)
84       mface_put_prop (face, Mfamily, msymbol (argv[2]));
85     mplist_add (param, Mdevice, msymbol ("gd"));
86     mplist_add (param, Mface, face);
87     frame = mframe (param);
88     m17n_object_unref (fontset);
89     m17n_object_unref (face);
90     m17n_object_unref (param);
91
92     if (! frame)
93       {
94         fprintf (stderr, "Frame creation failed.  Perhaps no GD library.\n");
95         exit (1);
96       }
97   }
98
99   /* Build GD image and draw MT on it while listing up font families
100      used for drawing.  */
101   {
102     MDrawControl control;
103     MDrawGlyph *glyphs;
104     int array_size, num_glyphs;
105     MPlist *family_list;
106     int family_name_len;
107
108     memset (&control, 0, sizeof (control));
109     control.anti_alias = 1;
110     control.enable_bidi = 1;
111     mdraw_text_extents (frame, mt, 0, mtext_len (mt), &control,
112                         &metric, NULL, NULL);
113
114     image = gdImageCreateTrueColor (metric.width, metric.height);
115     bg_color = gdImageColorAllocate (image, 255, 255, 255);
116     gdImageFilledRectangle (image, 0, 0, metric.width - 1, metric.height - 1,
117                             bg_color);
118
119     array_size = nchars * 2; /* Usually this is enough. */
120     glyphs = malloc (sizeof (MDrawGlyph) * array_size);
121     if (mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
122                           &num_glyphs) < 0)
123       {
124         array_size = num_glyphs;
125         glyphs = realloc (glyphs, sizeof (MDrawGlyph) * array_size);
126         mdraw_glyph_list (frame, mt, 0, nchars, &control, glyphs, array_size,
127                           &num_glyphs);
128       }
129     
130     family_list = NULL;
131     family_name_len = 0;
132     while (num_glyphs-- > 0)
133       if (glyphs[num_glyphs].font)
134         {
135           MSymbol family = mfont_get_prop (glyphs[num_glyphs].font, Mfamily);
136
137           if (! family_list)
138             {
139               family_list = mplist ();
140               mplist_add (family_list, Msymbol, family);
141               family_name_len = strlen (msymbol_name (family));
142             }
143           else if (! mplist_find_by_value (family_list, family))
144             {
145               mplist_push (family_list, Msymbol, family);
146               family_name_len += strlen (msymbol_name (family)) + 1;
147             }
148         }
149
150     mdraw_text_with_control (frame, (MDrawWindow) image,
151                              - metric.x, - metric.y,
152                              mt, 0, mtext_len (mt), &control);
153     m17n_object_unref (frame);
154
155     if (family_list)
156       {
157         char *p = alloca (family_name_len + 1);
158         MPlist *pl = family_list;
159
160         family_names = p;
161         p += sprintf (p, "%s", msymbol_name (mplist_value (pl)));
162         for (pl = mplist_next (pl); mplist_key (pl) != Mnil;
163              pl = mplist_next (pl))
164           p += sprintf (p, ",%s", msymbol_name (mplist_value (pl)));
165       }
166     m17n_object_unref (family_list);
167   }
168
169   M17N_FINI ();
170
171   {
172     GdkPixbuf *pixbuf;
173     GtkWidget *window, *box, *text, *label;
174     int n_channels, rowstride;
175     guchar *pixels, *p;
176     int x, y;
177     PangoAttrList *attr_list;
178     PangoAttribute *attr_size;
179
180     gtk_init (&argc, &argv);
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_label_set_attributes (GTK_LABEL (label), attr_list);
218     gtk_box_pack_start (GTK_BOX (box), text, TRUE, FALSE, 0);
219     gtk_box_pack_start (GTK_BOX (box), label, TRUE, FALSE, 0);
220
221     gtk_container_add (GTK_CONTAINER (window), box);
222     gtk_signal_connect (GTK_OBJECT (window), "delete_event",
223                         GTK_SIGNAL_FUNC (delete_event), NULL);
224     gtk_signal_connect (GTK_OBJECT (window), "destroy",
225                         GTK_SIGNAL_FUNC (destroy), NULL);
226     gtk_widget_show (text);
227     gtk_widget_show (label);
228     gtk_widget_show (box);
229     gtk_widget_show (window);
230     gtk_main ();
231   }
232
233   free (title);
234
235   exit (0);
236 }