Beginning work on graphic windows. Hopelessly broken still....
[rodin/chimara.git] / libchimara / graphics.c
1 #include "graphics.h"
2 #include "chimara-glk-private.h"
3 #include "magic.h"
4
5 #define BUFFER_SIZE (1024)
6
7 extern GPrivate *glk_data_key;
8 void on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info);
9
10 static gboolean size_determined;
11
12 glui32
13 glk_image_get_info(glui32 image, glui32 *width, glui32 *height)
14 {
15         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
16         giblorb_result_t res;
17         giblorb_err_t blorb_error = 0;
18         GError *pixbuf_error = NULL;
19         struct image_info *info = g_new0(struct image_info, 1);
20         info->resource_number = image;
21         guchar *buffer;
22
23         //printf("glk_image_get_info(%d)\n", image);
24
25         /* Lookup the proper resource */
26         blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
27         if(blorb_error != giblorb_err_None) {
28                 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
29                 return FALSE;
30         }
31
32         if(width == NULL && height == NULL) {
33                 /* No size requested, don't bother loading the image */
34                 giblorb_unload_chunk(glk_data->resource_map, image);
35                 return TRUE;
36         }
37
38         /* Load the resource */
39         GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
40         g_signal_connect( loader, "size-prepared", G_CALLBACK(on_size_prepared), info ); 
41         glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
42         buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
43
44         guint32 total_read = 0;
45         size_determined = FALSE;
46         while(total_read < res.length && !size_determined) {
47                 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
48
49                 if( !gdk_pixbuf_loader_write(loader, buffer, MIN(BUFFER_SIZE, num_read), &pixbuf_error) ) {
50                         WARNING_S("Cannot read image", pixbuf_error->message);
51                         giblorb_unload_chunk(glk_data->resource_map, image);
52                         gdk_pixbuf_loader_close(loader, &pixbuf_error);
53                         g_free(buffer);
54                         return FALSE;
55                 }
56
57                 total_read += num_read;
58         }
59         giblorb_unload_chunk(glk_data->resource_map, image);
60         gdk_pixbuf_loader_close(loader, &pixbuf_error);
61         g_free(buffer);
62
63         /* Determine the image dimensions */
64         if(!size_determined) {
65                 WARNING("Cannot read image size: file data trimmed?");
66                 g_free(info);
67                 return FALSE;
68         }
69
70         if(width != NULL)
71                 *width = info->width;
72         if(height != NULL)
73                 *height =info->height;
74         g_free(info);
75
76         //printf("size loaded: %d x %d\n", (int) *width, (int) *height);
77
78         return TRUE;
79 }
80
81 void
82 on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info)
83 {
84         info->width = width;
85         info->height = height;
86         size_determined = TRUE;
87 }
88
89 void
90 on_graphics_size_allocate(GtkWidget *widget, GtkAllocation *allocation, winid_t *win)
91 {
92         printf("size allocated: %dx%d\n", allocation->width, allocation->height);
93 }
94
95 glui32
96 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2) {
97         VALID_WINDOW(win, return FALSE);
98         g_return_val_if_fail(win->type == wintype_Graphics, FALSE);
99         printf("Drawing image %d\n", (int)image);
100
101         ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
102         giblorb_result_t res;
103         giblorb_err_t blorb_error = 0;
104         GError *pixbuf_error = NULL;
105         struct image_info *info = g_new0(struct image_info, 1);
106         info->resource_number = image;
107         guchar *buffer;
108         GdkPixmap *canvas;
109
110         //printf("glk_image_get_info(%d)\n", image);
111
112         /* Lookup the proper resource */
113         blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
114         if(blorb_error != giblorb_err_None) {
115                 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
116                 return FALSE;
117         }
118
119         /* Load the resource */
120         GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
121         glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
122         buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
123
124         guint32 total_read = 0;
125         while(total_read < res.length) {
126                 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
127
128                 if( !gdk_pixbuf_loader_write(loader, buffer, MIN(BUFFER_SIZE, num_read), &pixbuf_error) ) {
129                         WARNING_S("Cannot read image", pixbuf_error->message);
130                         giblorb_unload_chunk(glk_data->resource_map, image);
131                         gdk_pixbuf_loader_close(loader, &pixbuf_error);
132                         g_free(buffer);
133                         return FALSE;
134                 }
135
136                 total_read += num_read;
137         }
138         giblorb_unload_chunk(glk_data->resource_map, image);
139         g_free(buffer);
140
141         gtk_image_get_pixmap( GTK_IMAGE(win->widget), &canvas, NULL );
142         if(canvas == NULL) {
143                 WARNING("Could not get pixmap");
144                 gdk_pixbuf_loader_close(loader, &pixbuf_error);
145                 return FALSE;
146         }
147
148         GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
149         if(pixbuf == NULL) {
150                 WARNING("Could not read image");
151                 gdk_pixbuf_loader_close(loader, &pixbuf_error);
152                 return FALSE;
153         }
154
155         gdk_draw_pixbuf( GDK_DRAWABLE(canvas), NULL, pixbuf, 0, 0, val1, val2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0 );
156         gdk_pixbuf_loader_close(loader, &pixbuf_error);
157
158         /* Update the screen */
159         gtk_widget_queue_draw(win->widget);
160         return TRUE;
161 }
162
163 glui32
164 glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2, glui32 width, glui32 height)
165 {
166         return TRUE;
167 }
168
169 void
170 glk_window_set_background_color(winid_t win, glui32 color) {
171         win->background_color = color;
172 }
173
174 void
175 glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top, glui32 width, glui32 height)
176 {
177         VALID_WINDOW(win, return);
178         g_return_if_fail(win->type == wintype_Graphics);
179
180         GdkPixmap *map;
181         gtk_image_get_pixmap( GTK_IMAGE(win->widget), &map, NULL );
182         gdk_draw_rectangle( GDK_DRAWABLE(map), win->widget->style->white_gc, TRUE, left, top, width, height);
183         gtk_widget_queue_draw(win->widget);
184 }
185
186 void
187 glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height)
188 {
189         printf("erasing rect: %d %d %d %d\n", left, top, width, height);
190         glk_window_fill_rect(win, win->background_color, left, top, width, height);
191 }
192
193 void glk_window_flow_break(winid_t win)
194 {
195 }