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 //printf("glk_image_get_info(%d)\n", image);
27 /* Lookup the proper resource */
28 blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
29 if(blorb_error != giblorb_err_None) {
30 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
34 if(width == NULL && height == NULL) {
35 /* No size requested, don't bother loading the image */
36 giblorb_unload_chunk(glk_data->resource_map, image);
40 /* Load the resource */
41 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
42 g_signal_connect( loader, "size-prepared", G_CALLBACK(on_size_prepared), info );
43 glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
44 buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
46 guint32 total_read = 0;
47 size_determined = FALSE;
48 while(total_read < res.length && !size_determined) {
49 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
51 if( !gdk_pixbuf_loader_write(loader, buffer, MIN(BUFFER_SIZE, num_read), &pixbuf_error) ) {
52 WARNING_S("Cannot read image", pixbuf_error->message);
53 giblorb_unload_chunk(glk_data->resource_map, image);
54 gdk_pixbuf_loader_close(loader, &pixbuf_error);
59 total_read += num_read;
61 giblorb_unload_chunk(glk_data->resource_map, image);
62 gdk_pixbuf_loader_close(loader, &pixbuf_error);
65 /* Determine the image dimensions */
66 g_mutex_lock(glk_data->resource_lock);
67 while(!size_determined) {
68 /* Wait for the PixbufLoader to finish reading the image size */
69 g_cond_wait(glk_data->resource_info_available, glk_data->resource_lock);
71 g_mutex_unlock(glk_data->resource_lock);
76 *height =info->height;
83 on_size_prepared(GdkPixbufLoader *loader, gint width, gint height, struct image_info *info)
85 ChimaraGlkPrivate *glk_data = g_private_get(glk_data_key);
87 g_mutex_lock(glk_data->resource_lock);
89 info->height = height;
90 size_determined = TRUE;
91 g_cond_broadcast(glk_data->resource_info_available);
92 g_mutex_unlock(glk_data->resource_lock);
96 glk_image_draw(winid_t win, glui32 image, glsi32 val1, glsi32 val2)
98 VALID_WINDOW(win, return FALSE);
99 g_return_val_if_fail(win->type == wintype_Graphics, FALSE);
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;
110 /* Lookup the proper resource */
111 blorb_error = giblorb_load_resource(glk_data->resource_map, giblorb_method_FilePos, &res, giblorb_ID_Pict, image);
112 if(blorb_error != giblorb_err_None) {
113 WARNING_S( "Error loading resource", giblorb_get_error_message(blorb_error) );
117 /* Load the resource */
118 GdkPixbufLoader *loader = gdk_pixbuf_loader_new();
119 g_signal_connect( loader, "closed", G_CALLBACK(on_pixbuf_closed), NULL );
120 glk_stream_set_position(glk_data->resource_file, res.data.startpos, seekmode_Start);
121 buffer = g_malloc( BUFFER_SIZE * sizeof(guchar) );
123 guint32 total_read = 0;
124 image_loaded = FALSE;
125 while(total_read < res.length) {
126 guint32 num_read = glk_get_buffer_stream(glk_data->resource_file, (char *) buffer, BUFFER_SIZE);
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);
136 total_read += num_read;
139 if( !gdk_pixbuf_loader_close(loader, &pixbuf_error) ) {
140 WARNING_S("Cannot read image", pixbuf_error->message);
141 giblorb_unload_chunk(glk_data->resource_map, image);
147 /* Wait for the PixbufLoader to finish loading the image */
148 g_mutex_lock(glk_data->resource_lock);
149 while(!image_loaded) {
150 g_cond_wait(glk_data->resource_loaded, glk_data->resource_lock);
152 g_mutex_unlock(glk_data->resource_lock);
155 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 printf("Drawing image %d\n", (int)image);
173 gdk_draw_pixbuf( GDK_DRAWABLE(canvas), NULL, pixbuf, 0, 0, val1, val2, -1, -1, GDK_RGB_DITHER_NONE, 0, 0 );
175 /* Update the screen */
176 gtk_widget_queue_draw(win->widget);
182 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);
195 glk_image_draw_scaled(winid_t win, glui32 image, glsi32 val1, glsi32 val2, glui32 width, glui32 height)
201 glk_window_set_background_color(winid_t win, glui32 color) {
202 win->background_color = color;
206 glk_window_fill_rect(winid_t win, glui32 color, glsi32 left, glsi32 top, glui32 width, glui32 height)
208 VALID_WINDOW(win, return);
209 g_return_if_fail(win->type == wintype_Graphics);
212 gtk_image_get_pixmap( GTK_IMAGE(win->widget), &map, NULL );
213 gdk_draw_rectangle( GDK_DRAWABLE(map), win->widget->style->white_gc, TRUE, left, top, width, height);
214 gtk_widget_queue_draw(win->widget);
218 glk_window_erase_rect(winid_t win, glsi32 left, glsi32 top, glui32 width, glui32 height)
220 printf("erasing rect: %d %d %d %d\n", left, top, width, height);
221 glk_window_fill_rect(win, win->background_color, left, top, width, height);
224 void glk_window_flow_break(winid_t win)
228 /*** Called when the graphics window is resized. Resize the backing pixmap if necessary ***/
230 on_graphics_size_allocate(GtkWidget *widget, GtkAllocation *allocation, winid_t win)
232 printf("allocate to: %dx%d\n", allocation->width, allocation->height);
234 gtk_image_get_pixmap( GTK_IMAGE(widget), &oldmap, NULL );
238 /* Determine whether a pixmap exists with the correct size */
239 gboolean needs_resize = FALSE;
243 gdk_drawable_get_size( GDK_DRAWABLE(oldmap), &oldwidth, &oldheight );
244 if(oldwidth != allocation->width || oldheight != allocation->height)
249 printf("needs resize\n");
250 /* Create a new pixmap */
251 GdkPixmap *newmap = gdk_pixmap_new(widget->window, allocation->width, allocation->height, -1);
252 gdk_draw_rectangle( GDK_DRAWABLE(newmap), widget->style->white_gc, TRUE, 0, 0, allocation->width, allocation->height);
254 /* Copy the contents of the old pixmap */
256 gdk_draw_drawable( GDK_DRAWABLE(newmap), widget->style->white_gc, GDK_DRAWABLE(oldmap), 0, 0, 0, 0, oldwidth, oldheight);
258 /* Use the new pixmap */
259 gtk_image_set_from_pixmap( GTK_IMAGE(widget), newmap, NULL );
260 g_object_unref(newmap);