2 #include "chimara-glk-private.h"
5 #define BUFFER_SIZE (1024)
7 extern GPrivate *glk_data_key;
8 void on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info);
9 void on_pixbuf_closed(GdkPixbufLoader *loader, gpointer data);
11 static gboolean size_determined;
12 static gboolean image_loaded;
15 glk_image_get_info(glui32 image, glui32 *width, glui32 *height)
17 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
19 giblorb_err_t blorb_error = 0;
20 GError *pixbuf_error = NULL;
21 struct image_info *info = g_new0(struct image_info, 1);
22 info->resource_number = image;
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) );
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);
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) );
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);
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);
57 total_read += num_read;
59 giblorb_unload_chunk(glk_data->resource_map, image);
60 gdk_pixbuf_loader_close(loader, &pixbuf_error);
63 /* Determine the image dimensions */
64 g_mutex_lock(glk_data->resource_lock);
65 while(!size_determined) {
66 /* Wait for the PixbufLoader to finish reading the image size */
67 g_cond_wait(glk_data->resource_info_available, glk_data->resource_lock);
69 g_mutex_unlock(glk_data->resource_lock);
74 *height =info->height;
81 on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info)
83 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
85 g_mutex_lock(glk_data->resource_lock);
87 info->height = height;
88 size_determined = TRUE;
89 g_cond_broadcast(glk_data->resource_info_available);
90 g_mutex_unlock(glk_data->resource_lock);
94 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2)
96 VALID_WINDOW(win, return FALSE);
97 g_return_val_if_fail(win->type == wintype_Graphics, FALSE);
99 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
100 giblorb_result_t res;
101 giblorb_err_t blorb_error = 0;
102 GError *pixbuf_error = NULL;
103 struct image_info *info = g_new0(struct image_info, 1);
104 info->resource_number = image;
108 /* Lookup the proper resource */
109 blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
110 if(blorb_error != giblorb_err_None) {
111 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
115 /* Load the resource */
116 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
117 g_signal_connect( loader, "closed", G_CALLBACK(on_pixbuf_closed), NULL );
118 glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
119 buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
121 guint32 total_read = 0;
122 image_loaded = FALSE;
123 while(total_read < res.length) {
124 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
126 if( !gdk_pixbuf_loader_write(loader, buffer, MIN(BUFFER_SIZE, num_read), &pixbuf_error) ) {
127 WARNING_S("Cannot read image", pixbuf_error->message);
128 giblorb_unload_chunk(glk_data->resource_map, image);
129 gdk_pixbuf_loader_close(loader, &pixbuf_error);
134 total_read += num_read;
137 if( !gdk_pixbuf_loader_close(loader, &pixbuf_error) ) {
138 WARNING_S("Cannot read image", pixbuf_error->message);
139 giblorb_unload_chunk(glk_data->resource_map, image);
145 /* Wait for the PixbufLoader to finish loading the image */
146 g_mutex_lock(glk_data->resource_lock);
147 while(!image_loaded) {
148 g_cond_wait(glk_data->resource_loaded, glk_data->resource_lock);
150 g_mutex_unlock(glk_data->resource_lock);
153 giblorb_unload_chunk(glk_data->resource_map, image);
158 gtk_image_get_pixmap( GTK_IMAGE(win->widget), &canvas, NULL );
160 WARNING("Could not get pixmap");
164 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
166 WARNING("Could not read image");
170 gdk_draw_pixbuf( GDK_DRAWABLE(canvas), NULL, pixbuf, 0, 0, val1, val2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0 );
172 /* Update the screen */
173 gtk_widget_queue_draw(win->widget);
181 on_pixbuf_closed(GdkPixbufLoader *loader, gpointer data)
185 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
187 g_mutex_lock(glk_data->resource_lock);
189 g_cond_broadcast(glk_data->resource_loaded);
190 g_mutex_unlock(glk_data->resource_lock);
197 glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2, glui32 width, glui32 height)
199 VALID_WINDOW(win, return FALSE);
200 g_return_val_if_fail(win->type == wintype_Graphics, FALSE);
202 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
203 giblorb_result_t res;
204 giblorb_err_t blorb_error = 0;
205 GError *pixbuf_error = NULL;
206 struct image_info *info = g_new0(struct image_info, 1);
207 info->resource_number = image;
211 /* Lookup the proper resource */
212 blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
213 if(blorb_error != giblorb_err_None) {
214 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
218 /* Load the resource */
219 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
220 g_signal_connect( loader, "closed", G_CALLBACK(on_pixbuf_closed), NULL );
221 gdk_pixbuf_loader_set_size(loader, width, height);
222 glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
223 buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
225 guint32 total_read = 0;
226 image_loaded = FALSE;
227 while(total_read < res.length) {
228 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
230 if( !gdk_pixbuf_loader_write(loader, buffer, MIN(BUFFER_SIZE, num_read), &pixbuf_error) ) {
231 WARNING_S("Cannot read image", pixbuf_error->message);
232 giblorb_unload_chunk(glk_data->resource_map, image);
233 gdk_pixbuf_loader_close(loader, &pixbuf_error);
238 total_read += num_read;
241 if( !gdk_pixbuf_loader_close(loader, &pixbuf_error) ) {
242 WARNING_S("Cannot read image", pixbuf_error->message);
243 giblorb_unload_chunk(glk_data->resource_map, image);
249 /* Wait for the PixbufLoader to finish loading the image */
250 g_mutex_lock(glk_data->resource_lock);
251 while(!image_loaded) {
252 g_cond_wait(glk_data->resource_loaded, glk_data->resource_lock);
254 g_mutex_unlock(glk_data->resource_lock);
257 giblorb_unload_chunk(glk_data->resource_map, image);
262 gtk_image_get_pixmap( GTK_IMAGE(win->widget), &canvas, NULL );
264 WARNING("Could not get pixmap");
268 GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
270 WARNING("Could not read image");
274 gdk_draw_pixbuf( GDK_DRAWABLE(canvas), NULL, pixbuf, 0, 0, val1, val2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0 );
276 /* Update the screen */
277 gtk_widget_queue_draw(win->widget);
285 glk_window_set_background_color(winid_t win, glui32 color) {
286 win->background_color = color;
290 glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top, glui32 width, glui32 height)
292 VALID_WINDOW(win, return);
293 g_return_if_fail(win->type == wintype_Graphics);
299 gtk_image_get_pixmap( GTK_IMAGE(win->widget), &map, NULL );
300 gdk_draw_rectangle( GDK_DRAWABLE(map), win->widget->style->white_gc, TRUE, left, top, width, height);
301 gtk_widget_queue_draw(win->widget);
307 glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height)
309 glk_window_fill_rect(win, win->background_color, left, top, width, height);
312 void glk_window_flow_break(winid_t win)
316 /*** Called when the graphics window is resized. Resize the backing pixmap if necessary ***/
318 on_graphics_size_allocate(GtkWidget *widget, GtkAllocation *allocation, winid_t win)
321 gtk_image_get_pixmap( GTK_IMAGE(widget), &oldmap, NULL );
325 /* Determine whether a pixmap exists with the correct size */
326 gboolean needs_resize = FALSE;
330 gdk_drawable_get_size( GDK_DRAWABLE(oldmap), &oldwidth, &oldheight );
331 if(oldwidth != allocation->width || oldheight != allocation->height)
336 /* Create a new pixmap */
337 GdkPixmap *newmap = gdk_pixmap_new(widget->window, allocation->width, allocation->height, -1);
338 gdk_draw_rectangle( GDK_DRAWABLE(newmap), widget->style->white_gc, TRUE, 0, 0, allocation->width, allocation->height);
340 /* Copy the contents of the old pixmap */
342 gdk_draw_drawable( GDK_DRAWABLE(newmap), widget->style->white_gc, GDK_DRAWABLE(oldmap), 0, 0, 0, 0, oldwidth, oldheight);
344 /* Use the new pixmap */
345 gtk_image_set_from_pixmap( GTK_IMAGE(widget), newmap, NULL );
346 g_object_unref(newmap);