canvas/pixbuf scroll_region usage (odd behavior on solaris)
- From: seth_lytle yahoo com
- To: gnome-devel-list gnome org
- Subject: canvas/pixbuf scroll_region usage (odd behavior on solaris)
- Date: Tue, 7 Nov 2000 14:12:29 -0500
hello,
i have written an image viewer using gnome_canvas/gdk_pixbuf.
due to the nature of the data (very fuzzy/speckled, such that
features/artifacts show up at different scale), i would like
to be able to:
- zoom in/out
- during zoom, preserve center
- navigate through the image (both click and drag)
- be able to center any pixel in the image
- not be able to center outside the image
my initial attempts were unsuccessful (the canvas would
re-center things as i zoomed). what i ended up doing was setting
the scroll region to be the center of the image (ie, just a point),
and gtk_adjustment_value_changed to re-center.
this exposed a bug (well, i assume it is a bug), in gtklayout.
the adjustments float value is cast to guint and assigned to a
guint ([xy]offset). i don't see any guarantee that adj->value is
positive. code clipping:
gtk_layout_adjustment_changed
layout->xoffset = (gint)layout->hadjustment->value;
layout->yoffset = (gint)layout->vadjustment->value;
struct _GtkLayout
guint xoffset;
guint yoffset;
this code has disappeared in cvs, so i am hoping that i am right.
i patched my local copies, changing xoffset/yoffset to gint's,
and recompiled everything.
this works beautifully on linux. i get smooth scrolling, and
meet all my requirements. however, on solaris, i get very odd
behavior.
solaris
SunOS Release 5.5.1 Version Generic_103640-24 [UNIX(R) System V Release 4.0]
gnome-libs 1.2.7
gtk 1.2.8
gdk-pixbuf-config 0.8.0
OCCURANCE MODEL
the symptom appears to occur only if:
1. it is run and displayed on the same box
2. that box is solaris (as above)
3. it is the first gnome canvas application
actually, 3 is a little more complicated. let test be a canvas application.
./test -> invocation A
./test -> invocation B
./test -> invocation C
results in A being faulty, but B and C are fine. now
kill %1 (ie, A)
B and C are still fine. now
./test -> invocation D
B and C are still fine, but D is faulty.
THE SYMPTOM
during panning, large chunks of the image are not redrawn on adjustment_changed,
which leaves big hunks of background where the image should be (typically in the
lower right hand corner).
questions.
1. is my use of set_scroll_region (to a point), just plain old bad, and the fact
that it works on linux coincidence?
2. assuming that i need set_scroll_region to something more reasonable, any
suggestions on how to accomplish my goals (perhaps set the scroll region
very large)
for anyone who has actually made it this far into my ramble, i am attaching code
that demonstrates the problem for me. it is pretty short. the image is ugly -
just something to be visible.
button 1 and drag to scroll (a little weird the first time)
shift/button 1 to zoom in
shift/button 2 to re-center on pixel the mouse points to
shift/button 3 to zoom out
gcc -o testgn4 testgn4.c `gnome-config --cflags gnomeui` \
-lgdk_pixbuf -lm `gnome-config --libs gnomeui` `gdk-pixbuf-config --libs` \
-lglib -lgdk_pixbuf -lgnomecanvaspixbuf
LocalWords: testgn config cflags gnomeui lgdk pixbuf
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gnome.h>
#include <gdk-pixbuf/gnome-canvas-pixbuf.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
typedef struct { GnomeCanvas *canvas; GtkAdjustment *zadj; } mystuff;
static void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); }
static gint my_events (GtkWidget *w,GdkEvent *event,mystuff *z) {
GdkEventButton *bevent;
GdkEventMotion *mevent;
gint tx,ty,x, y, width, height;
int b1;
GnomeCanvas *canvas;
int m2=(GDK_CONTROL_MASK|GDK_MOD1_MASK|GDK_MOD2_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK);
int m1=(GDK_SHIFT_MASK|m2);
GtkAdjustment *adj;
int i,j;
double xo,yo;
canvas=GNOME_CANVAS(w);
gdk_window_get_size(w->window,&width,&height);
gdk_window_get_pointer (w->window, &tx, &ty, NULL);
x = (1.0*CLAMP (tx, 0, width-1));
y = (1.0*CLAMP (ty, 0, height-1));
b1=0;
if (event->type==GDK_BUTTON_PRESS) {
gtk_grab_add (w); bevent=(GdkEventButton *)event;
if (bevent->button==1 && !(bevent->state & m1)) { b1=1; }
else if (bevent->button==1 && (bevent->state & GDK_SHIFT_MASK) && !(bevent->state & m2)) { b1=2; }
else if (bevent->button==2 && (bevent->state & GDK_SHIFT_MASK) && !(bevent->state & m2)) { b1=4; }
else if (bevent->button==3 && (bevent->state & GDK_SHIFT_MASK) && !(bevent->state & m2)) { b1=3; }
}
else if (event->type==GDK_BUTTON_RELEASE) {
gtk_grab_remove(w); bevent=(GdkEventButton *)event;
if (bevent->button==1 && !(bevent->state & m1)) { b1=1; }
}
else if (event->type==GDK_MOTION_NOTIFY) {
mevent = (GdkEventMotion *) event;
if ((mevent->state & GDK_BUTTON1_MASK) && !(mevent->state & m1)) { b1=1; }
}
if (b1==1) {
double xc1,xc2,yc1,yc2;
gnome_canvas_item_get_bounds(canvas->root,&xc1,&yc1,&xc2,&yc2);
if (width>1 && height>1) gnome_canvas_w2c(canvas,xc1+(xc2-xc1)*x/(width-1),yc1+(yc2-yc1)*y/(height-1),&i,&j); else { i=0; j=0; }
}
else if (b1==2 || b1==3) {
gfloat zo,z1,z2;
i=GTK_LAYOUT(w)->hadjustment->value;
j=GTK_LAYOUT(w)->vadjustment->value;
gnome_canvas_c2w(canvas,i,j,&xo,&yo);
adj=z->zadj;
zo=adj->value;
z1=adj->lower;
z2=adj->upper;
if (b1==2) (adj->value) *= 2;
else if (b1==3) (adj->value) /= 2;
if (adj->value<z1) adj->value=z1;
if (adj->value>=z2) adj->value=z2;
if (adj->value != zo) gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas),adj->value);
gnome_canvas_w2c(canvas,xo,yo,&i,&j);
}
if (b1==4) {
gnome_canvas_window_to_world(canvas,x,y,&xo,&yo);
gnome_canvas_w2c(canvas,xo,yo,&i,&j);
}
if (b1==1 || b1==2 || b1==3 || b1==4) {
adj=GTK_LAYOUT(w)->hadjustment;
if (adj && width>0) { adj->value=i; gtk_adjustment_value_changed(adj); }
adj=GTK_LAYOUT(w)->vadjustment;
if (adj && height>0) { adj->value=j; gtk_adjustment_value_changed(adj); }
}
if (0) printf("event: %5d %5d | %d %d \n",width,height,i,j);
return(0);
}
int main( int argc, char *argv[] ) {
GtkWidget *window,*canvas;
guchar *buf3;
GnomeCanvasGroup *root;
GdkPixbuf *gpix;
mystuff *z;
int i,w=100,h=100;
buf3=calloc(w*h*3,sizeof(guchar));
for (i=0;i<w*h*3;i++) *(buf3+i)=i*i;
gpix=gdk_pixbuf_new_from_data(buf3,ART_PIX_RGB,0,8*sizeof(guchar),w,h,w*3,NULL,NULL);
gnome_init ("testGNOME", "1.2", argc, argv);
gdk_rgb_set_verbose (TRUE);
gdk_rgb_init ();
gtk_widget_set_default_colormap (gdk_rgb_get_cmap ());
gtk_widget_set_default_visual (gdk_rgb_get_visual ());
window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
gtk_signal_connect (GTK_OBJECT (window), "destroy",(GtkSignalFunc) destroy, NULL);
gtk_widget_show( window );
canvas = gnome_canvas_new ();
root = gnome_canvas_root (GNOME_CANVAS (canvas));
gnome_canvas_item_new (root,gnome_canvas_pixbuf_get_type (), "pixbuf",gpix, NULL);
z=(mystuff *)calloc(1,sizeof(mystuff));
z->canvas=GNOME_CANVAS(canvas);
z->zadj=GTK_ADJUSTMENT(gtk_adjustment_new (1.00, 0.0625,256, 0.05, 0.50, 0.50));
gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas),z->zadj->value);
gnome_canvas_set_scroll_region (GNOME_CANVAS (canvas),0.5*w,0.5*h,0.5*w,0.5*h);
gtk_container_add (GTK_CONTAINER (window), canvas);
gtk_widget_show (canvas);
gtk_signal_connect_after (GTK_OBJECT (canvas),"event",(GtkSignalFunc) my_events,z);
GTK_WIDGET_SET_FLAGS (canvas, GTK_CAN_FOCUS);
gtk_widget_grab_focus (canvas);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]