/* Redraw the screen from the backing pixmap */ static gboolean expose_event (GtkWidget *widget, GdkEventExpose *event) { static GdkImage *image = NULL; GdkCursor *cursor; GdkPixbuf *pixbuf; if (framebuffer_allocated == FALSE) { rfbClientSetClientData (cl, gtk_init, widget); image = gdk_drawable_get_image (widget->window, 0, 0, widget->allocation.width, widget->allocation.height); cl->frameBuffer= image->mem; cl->width = widget->allocation.width; cl->height = widget->allocation.height; cl->format.bitsPerPixel = image->bits_per_pixel; cl->format.redShift = image->visual->red_shift; cl->format.greenShift = image->visual->green_shift; cl->format.blueShift = image->visual->blue_shift; cl->format.redMax = (1 << image->visual->red_prec) - 1; cl->format.greenMax = (1 << image->visual->green_prec) - 1; cl->format.blueMax = (1 << image->visual->blue_prec) - 1; #ifdef LIBVNCSERVER_CONFIG_LIBVA /* Allow libvncclient to use a more efficient way * of putting the framebuffer on the screen when * using the H.264 format. */ cl->outputWindow = GDK_WINDOW_XID(widget->window); #endif SetFormatAndEncodings (cl); framebuffer_allocated = TRUE; /* Also disable local cursor */ pixbuf = gdk_pixbuf_new_from_xpm_data(dot_cursor_xpm); cursor = gdk_cursor_new_from_pixbuf(gdk_display_get_default(), pixbuf, dot_cursor_x_hot, dot_cursor_y_hot); g_object_unref(pixbuf); gdk_window_set_cursor (gtk_widget_get_window(GTK_WIDGET(window)), cursor); gdk_cursor_unref(cursor); } #ifndef LIBVNCSERVER_CONFIG_LIBVA gdk_draw_image (GDK_DRAWABLE (widget->window), widget->style->fg_gc[gtk_widget_get_state(widget)], image, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); #endif return FALSE; }
static VALUE rg_get_image(VALUE self, VALUE x, VALUE y, VALUE w, VALUE h) { return GOBJ2RVAL(gdk_drawable_get_image(_SELF(self), NUM2INT(x), NUM2INT(y), NUM2INT(w), NUM2INT(h))); }
static void draw_light_marker (gint xpos, gint ypos) { GdkColor color; color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0x0; color.green = 0x4000; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); gdk_gc_set_function (gc, GDK_COPY); if (mapvals.lightsource.type == POINT_LIGHT) { lightx = xpos; lighty = ypos; /* Save background */ /* =============== */ backbuf.x = lightx - 7; backbuf.y = lighty - 7; backbuf.w = 14; backbuf.h = 14; /* X doesn't like images that's outside a window, make sure */ /* we get the backbuffer image from within the boundaries */ /* ======================================================== */ if (backbuf.x < 0) backbuf.x = 0; else if ((backbuf.x + backbuf.w) > PREVIEW_WIDTH) backbuf.w = (PREVIEW_WIDTH - backbuf.x); if (backbuf.y < 0) backbuf.y = 0; else if ((backbuf.y + backbuf.h) > PREVIEW_HEIGHT) backbuf.h = (PREVIEW_WIDTH - backbuf.y); backbuf.image = gdk_drawable_get_image (previewarea->window, backbuf.x, backbuf.y, backbuf.w, backbuf.h); gdk_draw_arc (previewarea->window, gc, TRUE, lightx - 7, lighty - 7, 14, 14, 0, 360 * 64); } }
/**************************************************************************** Converts a pixmap/mask sprite to a GdkPixbuf. This is just a helper function for sprite_get_pixbuf(). Most callers should use that function instead. ****************************************************************************/ static GdkPixbuf *gdk_pixbuf_new_from_pixmap_sprite(struct sprite *src) { GdkPixbuf *dst; int w, h; w = src->width; h = src->height; /* convert pixmap */ dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, src->mask != NULL, 8, w, h); gdk_pixbuf_get_from_drawable(dst, src->pixmap, NULL, 0, 0, 0, 0, w, h); /* convert mask */ if (src->mask) { GdkImage *img; int x, y, rowstride; guchar *pixels; img = gdk_drawable_get_image(src->mask, 0, 0, w, h); pixels = gdk_pixbuf_get_pixels(dst); rowstride = gdk_pixbuf_get_rowstride(dst); for (y = 0; y < h; y++) { for (x = 0; x < w; x++) { guchar *pixel = pixels + y * rowstride + x * 4 + 3; if (gdk_image_get_pixel(img, x, y)) { *pixel = 255; } else { *pixel = 0; } } } g_object_unref(img); } return dst; }
/**************************************************************************** Method returns the bounding box of a sprite. It assumes a rectangular object/mask. The bounding box contains the border (pixel which have unset pixel as neighbours) pixel. ****************************************************************************/ void sprite_get_bounding_box(struct sprite * sprite, int *start_x, int *start_y, int *end_x, int *end_y) { GdkImage *mask_image; GdkBitmap *mask = sprite_get_mask(sprite); int i, j; if (!mask) { *start_x = 0; *start_y = 0; *end_x = sprite->width - 1; *end_y = sprite->height - 1; return; } mask_image = gdk_drawable_get_image(mask, 0, 0, sprite->width, sprite->height); /* parses mask image for the first column that contains a visible pixel */ *start_x = -1; for (i = 0; i < sprite->width && *start_x == -1; i++) { for (j = 0; j < sprite->height; j++) { if (gdk_image_get_pixel(mask_image, i, j) != 0) { *start_x = i; break; } } } /* parses mask image for the last column that contains a visible pixel */ *end_x = -1; for (i = sprite->width - 1; i >= *start_x && *end_x == -1; i--) { for (j = 0; j < sprite->height; j++) { if (gdk_image_get_pixel(mask_image, i, j) != 0) { *end_x = i; break; } } } /* parses mask image for the first row that contains a visible pixel */ *start_y = -1; for (i = 0; i < sprite->height && *start_y == -1; i++) { for (j = *start_x; j <= *end_x; j++) { if (gdk_image_get_pixel(mask_image, j, i) != 0) { *start_y = i; break; } } } /* parses mask image for the last row that contains a visible pixel */ *end_y = -1; for (i = sprite->height - 1; i >= *end_y && *end_y == -1; i--) { for (j = *start_x; j <= *end_x; j++) { if (gdk_image_get_pixel(mask_image, j, i) != 0) { *end_y = i; break; } } } g_object_unref(mask_image); }
static void draw_handles (void) { gdouble dxpos, dypos; gint startx, starty, pw, ph; GimpVector3 viewpoint; GimpVector3 light_position; gint k = mapvals.light_selected; gfloat length; gfloat delta_x = 0.0; gfloat delta_y = 0.0; /* calculate handle position */ compute_preview_rectangle (&startx, &starty, &pw, &ph); switch (mapvals.lightsource[k].type) { case NO_LIGHT: return; case POINT_LIGHT: case SPOT_LIGHT: /* swap z to reverse light position */ viewpoint = mapvals.viewpoint; viewpoint.z = -viewpoint.z; light_position = mapvals.lightsource[k].position; gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos, &viewpoint, &light_position); handle_xpos = (gint) (dxpos + 0.5); handle_ypos = (gint) (dypos + 0.5); break; case DIRECTIONAL_LIGHT: light_position.x = light_position.y = 0.5; light_position.z = 0; viewpoint.z = -viewpoint.z; gimp_vector_3d_to_2d (startx, starty, pw, ph, &dxpos, &dypos, &viewpoint, &light_position); length = PREVIEW_HEIGHT / 4; delta_x = mapvals.lightsource[k].direction.x * length; delta_y = mapvals.lightsource[k].direction.y * length; handle_xpos = dxpos + delta_x; handle_ypos = dypos + delta_y; break; } gdk_gc_set_function (gc, GDK_COPY); if (mapvals.lightsource[k].type != NO_LIGHT) { GdkColor color; /* Restore background if it has been saved */ /* ======================================= */ if (backbuf.image != NULL) { gdk_gc_set_function (gc, GDK_COPY); gdk_draw_image (previewarea->window, gc, backbuf.image, 0, 0, backbuf.x, backbuf.y, backbuf.w, backbuf.h); g_object_unref (backbuf.image); backbuf.image = NULL; } /* calculate backbuffer */ switch (mapvals.lightsource[k].type) { case POINT_LIGHT: backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2; backbuf.y = handle_ypos - LIGHT_SYMBOL_SIZE / 2; backbuf.w = LIGHT_SYMBOL_SIZE; backbuf.h = LIGHT_SYMBOL_SIZE; break; case DIRECTIONAL_LIGHT: if (delta_x <= 0) backbuf.x = handle_xpos; else backbuf.x = startx + pw/2; if (delta_y <= 0) backbuf.y = handle_ypos; else backbuf.y = starty + ph/2; backbuf.x -= LIGHT_SYMBOL_SIZE/2; backbuf.y -= LIGHT_SYMBOL_SIZE/2; backbuf.w = fabs(delta_x) + LIGHT_SYMBOL_SIZE; backbuf.h = fabs(delta_y) + LIGHT_SYMBOL_SIZE; break; case SPOT_LIGHT: backbuf.x = handle_xpos - LIGHT_SYMBOL_SIZE / 2; backbuf.y = handle_ypos - LIGHT_SYMBOL_SIZE / 2; backbuf.w = LIGHT_SYMBOL_SIZE; backbuf.h = LIGHT_SYMBOL_SIZE; break; case NO_LIGHT: break; } /* Save background */ /* =============== */ if ((backbuf.x >= 0) && (backbuf.x <= PREVIEW_WIDTH) && (backbuf.y >= 0) && (backbuf.y <= PREVIEW_HEIGHT)) { /* clip coordinates to preview widget sizes */ if ((backbuf.x + backbuf.w) > PREVIEW_WIDTH) backbuf.w = (PREVIEW_WIDTH - backbuf.x); if ((backbuf.y + backbuf.h) > PREVIEW_HEIGHT) backbuf.h = (PREVIEW_HEIGHT - backbuf.y); backbuf.image = gdk_drawable_get_image (previewarea->window, backbuf.x, backbuf.y, backbuf.w, backbuf.h); } color.red = 0x0; color.green = 0x0; color.blue = 0x0; gdk_gc_set_rgb_bg_color (gc, &color); color.red = 0x0; color.green = 0x4000; color.blue = 0xFFFF; gdk_gc_set_rgb_fg_color (gc, &color); /* draw circle at light position */ switch (mapvals.lightsource[k].type) { case POINT_LIGHT: case SPOT_LIGHT: gdk_draw_arc (previewarea->window, gc, TRUE, handle_xpos - LIGHT_SYMBOL_SIZE / 2, handle_ypos - LIGHT_SYMBOL_SIZE / 2, LIGHT_SYMBOL_SIZE, LIGHT_SYMBOL_SIZE, 0, 360 * 64); break; case DIRECTIONAL_LIGHT: gdk_draw_arc (previewarea->window, gc, TRUE, handle_xpos - LIGHT_SYMBOL_SIZE / 2, handle_ypos - LIGHT_SYMBOL_SIZE / 2, LIGHT_SYMBOL_SIZE, LIGHT_SYMBOL_SIZE, 0, 360 * 64); gdk_draw_line (previewarea->window, gc, handle_xpos, handle_ypos, startx+pw/2 , starty + ph/2); break; case NO_LIGHT: break; } } }
static GdkBitmap * scale_bitmap (GdkWindow *window, GdkBitmap *bitmap, gdouble scale_x, gdouble scale_y) { GdkGC *gc; GdkVisual *visual = NULL; GdkImage *image = NULL, *new_image = NULL; GdkBitmap *new_bitmap = NULL; gint x, y, width, height, new_width, new_height; GdkColor color; if(!bitmap) return NULL; if(!window) return NULL; gc = gdk_gc_new(bitmap); gdk_window_get_size(bitmap, &width, &height); if(scale_x == 1.0 && scale_y == 1.0){ new_bitmap = gdk_pixmap_new(window, width, height, 1); color.pixel = 0; gdk_gc_set_foreground(gc, &color); gdk_draw_rectangle(new_bitmap, gc, TRUE, 0, 0, width, height); color.pixel = 1; gdk_gc_set_foreground(gc, &color); gdk_draw_pixmap(new_bitmap, gc, bitmap, 0, 0, 0, 0, width, height); gdk_gc_unref(gc); return new_bitmap; } new_width = roundint(width * scale_x); new_height = roundint(height * scale_y); /* make a client side image of the bitmap, and * scale the data into a another client side image */ visual = gdk_window_get_visual (bitmap); if(!visual) return NULL; new_image = gdk_image_new(GDK_IMAGE_FASTEST,visual,new_width,new_height); if(!new_image) return NULL; new_bitmap = gdk_pixmap_new(window, new_width, new_height, 1); image = gdk_drawable_get_image(bitmap, 0, 0, width, height); color.pixel = 0; gdk_gc_set_foreground(gc, &color); gdk_draw_rectangle(new_bitmap, gc, TRUE, 0, 0, width, height); color.pixel = 1; gdk_gc_set_foreground(gc, &color); for(x = 0; x < new_width; x++){ for(y = 0; y < new_height; y++){ gint px, py; gulong pixel; px = MIN(roundint(x / scale_x), width - 1); py = MIN(roundint(y / scale_y), height - 1); pixel = gdk_image_get_pixel(image, px, py); gdk_image_put_pixel(new_image, x, y, pixel); } } /* draw the image into a new pixmap */ gdk_draw_image(new_bitmap,gc,new_image,0,0,0,0,new_width,new_height); gdk_image_destroy(image); gdk_image_destroy(new_image); gdk_gc_unref(gc); return new_bitmap; }