Integrating GfxLib with Gtk

Linux specific questions.
Post Reply
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Integrating GfxLib with Gtk

Post by caseih »

forum admins, feel free to move this post to another forum if it's more appropriate there. This is a linux-based thing (should work on win32 with gtk though), but whatever.

I've written a quick and dirty demonstration, a la the win32 demo in the language reference, on painting the ScreenPtr to a GtkDrawingArea widget. Now it sort of works, but currently the byte ordering of the ScreenPtr is not what the GdkPixbuf wrapper is expecting, so while you can see the letters on the screen that where PRINTed there, drawing lines and stuff is funky. And there's no real provision for redrawing the screen other than on an expose. But here's the code. It has no real purpose, but others may enjoy it. The window starts off with a DrawingArea that's 0 pixels, so you'll have to resize the window.

Here's the glade file:

Code: Select all

<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">

<glade-interface>

<widget class="GtkWindow" id="window">
  <property name="visible">True</property>
  <property name="title" translatable="yes">FreeBASIC and GTK and GfxLib</property>
  <property name="type">GTK_WINDOW_TOPLEVEL</property>
  <property name="window_position">GTK_WIN_POS_NONE</property>
  <property name="modal">False</property>
  <property name="resizable">True</property>
  <property name="destroy_with_parent">False</property>
  <property name="decorated">True</property>
  <property name="skip_taskbar_hint">False</property>
  <property name="skip_pager_hint">False</property>
  <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
  <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
  <property name="focus_on_map">True</property>
  <property name="urgency_hint">False</property>
  <signal name="delete_event" handler="on_window_delete_event" last_modification_time="Mon, 26 Feb 2007 06:16:11 GMT"/>

  <child>
    <widget class="GtkVBox" id="vbox1">
      <property name="border_width">11</property>
      <property name="visible">True</property>
      <property name="homogeneous">False</property>
      <property name="spacing">5</property>

      <child>
	<widget class="GtkDrawingArea" id="drawingarea1">
	  <property name="visible">True</property>
	  <signal name="configure_event" handler="on_drawingarea_configure_event" last_modification_time="Mon, 26 Feb 2007 05:55:48 GMT"/>
	  <signal name="expose_event" handler="on_drawingarea_expose_event" last_modification_time="Mon, 26 Feb 2007 05:55:56 GMT"/>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">True</property>
	  <property name="fill">True</property>
	</packing>
      </child>

      <child>
	<widget class="GtkHBox" id="hbox1">
	  <property name="border_width">10</property>
	  <property name="visible">True</property>
	  <property name="homogeneous">False</property>
	  <property name="spacing">0</property>

	  <child>
	    <widget class="GtkButton" id="quit_button">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="label">gtk-quit</property>
	      <property name="use_stock">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_quit_button_clicked" last_modification_time="Mon, 26 Feb 2007 05:58:55 GMT"/>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">False</property>
	      <property name="fill">False</property>
	      <property name="pack_type">GTK_PACK_END</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkButton" id="button2">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="label" translatable="yes">button2</property>
	      <property name="use_underline">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_button2_clicked" last_modification_time="Mon, 26 Feb 2007 05:58:42 GMT"/>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">False</property>
	      <property name="fill">False</property>
	      <property name="pack_type">GTK_PACK_END</property>
	    </packing>
	  </child>

	  <child>
	    <widget class="GtkButton" id="button3">
	      <property name="visible">True</property>
	      <property name="can_focus">True</property>
	      <property name="label" translatable="yes">button3</property>
	      <property name="use_underline">True</property>
	      <property name="relief">GTK_RELIEF_NORMAL</property>
	      <property name="focus_on_click">True</property>
	      <signal name="clicked" handler="on_button3_clicked" last_modification_time="Mon, 26 Feb 2007 05:58:48 GMT"/>
	    </widget>
	    <packing>
	      <property name="padding">0</property>
	      <property name="expand">False</property>
	      <property name="fill">False</property>
	      <property name="pack_type">GTK_PACK_END</property>
	    </packing>
	  </child>
	</widget>
	<packing>
	  <property name="padding">0</property>
	  <property name="expand">False</property>
	  <property name="fill">False</property>
	</packing>
      </child>
    </widget>
  </child>
</widget>

</glade-interface>
Here's the bas file:

Code: Select all

option explicit 'no idea what this does
defint a-z

#include "gtk/gtk.bi"
#include "gtk/libglade/glade-xml.bi"
#include "fbgfx.bi"

#define NULL 0
dim shared w,h
dim shared xml as GladeXML Ptr


declare sub on_window_delete_event cdecl alias _
           "on_window_delete_event" ( byval object as GtkObject Ptr, _
	                              byval user_data as gpointer )
declare sub on_drawingarea_configure_event cdecl alias _
           "on_drawingarea_configure_event" ( byval object as GtkObject Ptr, _
                                       byval event as GdkEventConfigure Ptr, _
	                                      byval user_data as gpointer )
declare sub on_drawingarea_expose_event cdecl alias _
           "on_drawingarea_expose_event" ( byval object as GtkObject Ptr, _
                                           byval expose as GdkEventExpose Ptr, _
	                                   byval user_data as gpointer )
declare sub on_quit_button_clicked cdecl alias _
           "on_quit_button_clicked" ( byval object as GtkObject Ptr, _
	                              byval user_data as gpointer )
declare sub on_button2_clicked cdecl alias _
           "on_button2_clicked" ( byval object as GtkObject Ptr, _
	                          byval user_data as gpointer )
declare sub on_button3_clicked cdecl alias _
           "on_button3_clicked" ( byval object as GtkObject Ptr, _
	                          byval user_data as gpointer )

sub redraw () 
	dim widget as GtkWidget Ptr

	widget=glade_xml_get_widget(xml,"drawingarea")
	gtk_widget_queue_draw_area(widget,0,0,w,h)
end sub

sub on_window_delete_event cdecl ( byval object as GtkObject Ptr, _
	                            byval user_data as gpointer )
	on_quit_button_clicked(object,user_data)
end sub

sub on_quit_button_clicked cdecl ( byval object as GtkObject Ptr, _
	                           byval user_data as gpointer ) export
	print "Quit Button clicked."
	gtk_main_quit()
end sub

sub on_button3_clicked cdecl ( byval object as GtkObject Ptr, _
	                       byval user_data as gpointer )

	print "Button 3 clicked"
	line (40,40)-(139,499),55
	redraw
end sub

sub on_drawingarea_configure_event cdecl ( byval object as GtkObject Ptr, _
                                       byval event as GdkEventConfigure Ptr, _
	                                   byval user_data as gpointer )

	w=event->width
	h=event->height
	
	print "New dimensions are ";w;",";h
	if h < 16 or w < 16 then print "too small" : return
	ScreenRes w,h,24,1,GFX_NULL
	width ,25
	color ,0
	cls
	print "Drawing area (re)configured."
	print "New dimensions are ";w;",";h

	'here we resize the screen buffer


end sub

sub on_drawingarea_expose_event cdecl ( byval object as GtkObject Ptr, _
                                        byval expose as GdkEventExpose Ptr, _
	                                byval user_data as gpointer )

	dim pixbuf as GdkPixbuf Ptr
	dim gc as GdkGC Ptr

	if h < 16 or w < 16 then print "too small; no drawing" : return 'no valid graphics mode yet

	pixbuf=gdk_pixbuf_new_from_data(ScreenPtr, _
	                                GDK_COLORSPACE_RGB, _
					0, _
					8, _
					w, _
					h, _
					w*4, _
					NULL, _
					NULL)
	gc = gdk_gc_new (expose->window)

	gdk_pixbuf_render_to_drawable (pixbuf, _
	                               expose->window, _
				       gc, _
				       0,0,0,0, _
				       w,h, _
				       GDK_RGB_DITHER_NORMAL, _
				       0,0)

	gdk_pixbuf_unref(pixbuf)
	gdk_gc_unref(gc)
end sub

dim window_widget as GtkWidget Ptr

gtk_init( NULL, NULL)
xml = glade_xml_new("gtkgfxlib.glade",NULL,NULL)

window_widget=glade_xml_get_widget( xml, "window")
gtk_widget_show_all( window_widget)
gtk_widget_set_size_request (glade_xml_get_widget(xml,"drawingarea"), 640, 480)
glade_xml_signal_autoconnect(xml)
gtk_main()

end 0
tunginobi
Posts: 655
Joined: Jan 10, 2006 0:44
Contact:

Post by tunginobi »

Very nice! Got it working after a few tweaks:

1. The forum [ code ] tags have changed SYSTEM into System and name= to Name in the Glade XML file.
2. In two places in the source, you refer to "drawingarea", but the widget is named "drawingarea1".
3. You haven't written the implementation of on_button2_clicked().
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

it doesn't appear to work on windows(2k), i get this dumped out to a console:
(thing.exe:792): Gtk-CRITICAL **: gtk_widget_set_size_request: assertion `GTK_IS_WIDGET (widget)' failed

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_button2_clicked'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_window_delete_event'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_drawingarea_configure_event'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_button3_clicked'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_drawingarea_expose_event'.
looks lkie this when running:

Image

that isn't correct, is it?
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

cha0s wrote:it doesn't appear to work on windows(2k), i get this dumped out to a console:
(thing.exe:792): Gtk-CRITICAL **: gtk_widget_set_size_request: assertion `GTK_IS_WIDGET (widget)' failed

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_button2_clicked'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_window_delete_event'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_drawingarea_configure_event'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_button3_clicked'.

(thing.exe:792): libglade-WARNING **: could not find signal handler 'on_drawingarea_expose_event'.

As for the first warning, I was having a problem getting the drawing area to have an initial size. I never did solve that one, hence the warning, which can be ignored in this case.

The auto signal connect subroutine likely does not work on windows. It relies on features of the gnu linker that are only available on elf binaries. Signals would have to be connected by hand. To do this you would extract a pointer to each widget and connect that widget's appropriate signal to the signal handler.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

tunginobi wrote:Very nice! Got it working after a few tweaks:

1. The forum [ code ] tags have changed SYSTEM into System and name= to Name in the Glade XML file.
2. In two places in the source, you refer to "drawingarea", but the widget is named "drawingarea1".
3. You haven't written the implementation of on_button2_clicked().

Hmm. My code was running, so maybe I changed the glade file sometime after I built the exe the first time.

As for the other handler, this is true. I figured I would make it draw circles at some point or something. The Gtk warning about not finding the handler is harmless. That's the nice thing about signals. They can be emitted to their hearts content even if no one is around to listen to them.

You are seeing the color problems, right? The order of the bytes in the screen buffer still need to be worked out. Maybe it would be nice if ScreenRes could allow you to tweak the byte order, say to just make it RRRRGGGGBBBB, instead of some 4-byte thing that the 24-bit screen defaults too.
tunginobi
Posts: 655
Joined: Jan 10, 2006 0:44
Contact:

Post by tunginobi »

caseih wrote:You are seeing the color problems, right? The order of the bytes in the screen buffer still need to be worked out. Maybe it would be nice if ScreenRes could allow you to tweak the byte order, say to just make it RRRRGGGGBBBB, instead of some 4-byte thing that the 24-bit screen defaults too.
Yeah, I noticed when I started using the rgb() macro to draw circles and such.

FB's GTK headers only include the one byte order:

Code: Select all

Enum GdkColorspace
	GDK_COLORSPACE_RGB
end Enum
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

EDIT: Fixed the expose handler. Apparently the bytes were in RGBA order

I added a hack to adjust the bytes so GTK is happy. It proves this works anyway. Button2 and button3 now do things like drawing random stuff.

Note that since ScreenPtr is painted manually, or when the window is exposed, you can't just do things like "input a$" without gtk freezing up while you are doing it (and you won't see anything!)

To really make this usable, we'd have to do complicated threading to make sure that "input a$" wouldn't block the gui AND update stuff. This is complicated by the fact that GTK wants to be in charge of events and all that so any basic code is likely run from within a GTK call-back. But as long as you don't want to do any BASIC-style input, this could be useful to someone.

Code: Select all

option explicit 'no idea what this does
defint a-z

#include "gtk/gtk.bi"
#include "gtk/libglade/glade-xml.bi"
#include "fbgfx.bi"

#define NULL 0
dim shared w,h
dim shared xml as GladeXML Ptr
dim shared gtkbuffer as zstring ptr

gtkbuffer = NULL

declare sub on_window_delete_event cdecl alias _
           "on_window_delete_event" ( byval object as GtkObject Ptr, _
	                              byval user_data as gpointer )
declare sub on_drawingarea_configure_event cdecl alias _
           "on_drawingarea_configure_event" ( byval object as GtkObject Ptr, _
                                       byval event as GdkEventConfigure Ptr, _
	                                      byval user_data as gpointer )
declare sub on_drawingarea_expose_event cdecl alias _
           "on_drawingarea_expose_event" ( byval object as GtkObject Ptr, _
                                           byval expose as GdkEventExpose Ptr, _
	                                   byval user_data as gpointer )
declare sub on_quit_button_clicked cdecl alias _
           "on_quit_button_clicked" ( byval object as GtkObject Ptr, _
	                              byval user_data as gpointer )
declare sub on_button2_clicked cdecl alias _
           "on_button2_clicked" ( byval object as GtkObject Ptr, _
	                          byval user_data as gpointer )
declare sub on_button3_clicked cdecl alias _
           "on_button3_clicked" ( byval object as GtkObject Ptr, _
	                          byval user_data as gpointer )

sub redraw () 
	dim widget as GtkWidget Ptr

	widget=glade_xml_get_widget(xml,"drawingarea1")
	gtk_widget_queue_draw_area(widget,0,0,w,h)
end sub

sub on_window_delete_event cdecl ( byval object as GtkObject Ptr, _
	                            byval user_data as gpointer )
	on_quit_button_clicked(object,user_data)
end sub

sub on_quit_button_clicked cdecl ( byval object as GtkObject Ptr, _
	                           byval user_data as gpointer ) export
	print "Quit Button clicked."
	redraw
	gtk_main_quit()
end sub

sub on_button2_clicked cdecl ( byval object as GtkObject Ptr, _
	                       byval user_data as gpointer )

	color ,rnd(1)*&hffffff
	print "Button 2 clicked"

	dim x,y,c,r,f
	x=rnd(1)*w
	y=rnd(1)*h
	r=rnd(1)*(w+h)/3
	c=rnd(1)*&hffffff
	f=rnd(1)*10

	if f>5 then
		circle (x,y),r,c
	else
		circle (x,y),r,c,,,,F
	end if
	redraw
end sub


sub on_button3_clicked cdecl ( byval object as GtkObject Ptr, _
	                       byval user_data as gpointer )

	color ,rnd(1)*&hffffff
	print "Button 3 clicked"

	dim x,y,a,b,c,f
	x=rnd(1)*w
	y=rnd(1)*h
	a=rnd(1)*w
	b=rnd(1)*h
	c=rnd(1)*&hffffff
	f=rnd(1)*10

	if f>5 then
		line (x,y)-(a,b),c
	else
		line (x,y)-(a,b),c,bf
	end if
	redraw
end sub

sub on_drawingarea_configure_event cdecl ( byval object as GtkObject Ptr, _
                                       byval event as GdkEventConfigure Ptr, _
	                                   byval user_data as gpointer )

	w=event->width
	h=event->height
	
	if gtkbuffer <> NULL then deallocate(gtkbuffer):gtkbuffer=NULL

	print "New dimensions are ";w;",";h
	if h < 16 or w < 16 then print "too small" : return
	ScreenRes w,h,24,1,GFX_NULL
	gtkbuffer = allocate(w*h*3)
	width ,25
	color ,0
	cls
	print "Drawing area (re)configured."
	print "New dimensions are ";w;",";h

	'here we resize the screen buffer


end sub

sub on_drawingarea_expose_event cdecl ( byval object as GtkObject Ptr, _
                                        byval expose as GdkEventExpose Ptr, _
	                                byval user_data as gpointer )

	dim pixbuf as GdkPixbuf Ptr
	dim gc as GdkGC Ptr
	dim c as zstring ptr
	dim d as zstring ptr
	dim x

	if h < 16 or w < 16 then print "too small; no drawing" : return 'no valid graphics mode yet

	c = ScreenPtr
	d = gtkbuffer

	for x=0 to h*w-1
		*d=*c
		c = c + 1
		d = d + 1
		*d=*c
		c = c + 1
		d = d + 1
		*d=*c
		c = c + 1
		d = d + 1
		c = c + 1
	next
		

	pixbuf=gdk_pixbuf_new_from_data(gtkbuffer, _
	                                GDK_COLORSPACE_RGB, _
					0, _
					8, _
					w, _
					h, _
					w*3, _
					NULL, _
					NULL)
	gc = gdk_gc_new (expose->window)

	gdk_pixbuf_render_to_drawable (pixbuf, _
	                               expose->window, _
				       gc, _
				       0,0,0,0, _
				       w,h, _
				       GDK_RGB_DITHER_NORMAL, _
				       0,0)

	gdk_pixbuf_unref(pixbuf)
	gdk_gc_unref(gc)
end sub

dim window_widget as GtkWidget Ptr

randomize

gtk_init( NULL, NULL)
xml = glade_xml_new("gtkgfxlib.glade",NULL,NULL)

window_widget=glade_xml_get_widget( xml, "window")
gtk_widget_show_all( window_widget)
gtk_widget_set_size_request (glade_xml_get_widget(xml,"drawingarea1"), 640, 480)
glade_xml_signal_autoconnect(xml)
gtk_main()

end 0

Last edited by caseih on Feb 28, 2007 5:39, edited 1 time in total.
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

Can you show me how to make this work the "right" way, so that it's crossplatform?
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

First add

Code: Select all

#include "gtk/glib.bi"
Then you'll have to replace the xml autoconnect lines with:

Code: Select all

g_signal_connect(glade_xml_get_widget(xml,"window"), "delete-event", @on_window_delete_event,NULL)

g_signal_connect(glade_xml_get_widget(xml,"drawingarea1"), "configure-event", @on_drawingarea_configure_event,NULL)

g_signal_connect(glade_xml_get_widget(xml,"drawingarea1"), "expose-event", @on_drawingarea_expose_event,NULL)

g_signal_connect(glade_xml_get_widget(xml,"quit_button"), "clicked", @on_quit_button_clicked,NULL)

g_signal_connect(glade_xml_get_widget(xml,"button2_button"), "clicked", @on_button2_button_clicked,NULL)

g_signal_connect(glade_xml_get_widget(xml,"button3_button"), "clicked", @on_button3_button_clicked,NULL)

I think that does it. I still am having byte order problems. I think GTK and FB must be opposite each other or something.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

For linux, the proper byte copying code from the expose handler is:

Code: Select all

	for x=0 to h*w-1
		*d=*(c+2)
		c = c + 1
		d = d + 1
		*d=*c
		c = c + 1
		d = d + 1
		*d=*(c-2)
		c = c + 1
		d = d + 1
		c = c + 1
	next
cha0s
Site Admin
Posts: 5319
Joined: May 27, 2005 6:42
Location: USA
Contact:

Post by cha0s »

Nice, I got it to work, I had to change these lines:

Code: Select all

g_signal_connect(glade_xml_get_widget(xml,"button2"), "clicked", @on_button2_clicked,NULL)
g_signal_connect(glade_xml_get_widget(xml,"button3"), "clicked", @on_button3_clicked,NULL)
i got a lot of warnings though, i followed it back:

#define g_signal_connect(i,s,h,d) g_signal_connect_data(i,s,h,d,0,0)
declare function g_signal_connect_data (byval instance as gpointer, byval detailed_signal as zstring ptr, byval c_handler as GCallback, byval data as gpointer, byval destroy_data as GClosureNotify, byval connect_flags as GConnectFlags) as gulong
#define G_CALLBACK(f) (cast(GCallback,f))
type GCallback as sub cdecl()

so... it's expecting a cdecl sub with no parameters... i wonder if that's wrong...
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Post by caseih »

I'm really good about posting code with "some assembly required" aren't I? :)

Yes the function pointer should be wrapped in the G_CALLBACK casting macro. It's okay that it expects a cdecl with no parameters. That's because each signal has a different signature, or number of parameters to pass to a callback. Being cdecl, it just won't matter. Hence the macro which casts everything to a cdecl with no params.
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: Integrating GfxLib with Gtk

Post by owen »

How does this work?
Does the for next loop affect gtkbuffer?
Only thing I can tell is it affect C and D which are not used in any of the code below the for next loop.
gtkbuffer appears to be unchanged and the image is the same.
I can not compile and test this as I am having a hard time getting GTK2 and Glade to work.
i have FB 1.05 and GTK 3.8.2 up and running but this was written for gtk2 i think.
if anybody can compile and let me know if it works please let me know.

Code: Select all

   c = ScreenPtr
   d = gtkbuffer

   for x=0 to h*w-1
      *d=*c
      c = c + 1
      d = d + 1
      *d=*c
      c = c + 1
      d = d + 1
      *d=*c
      c = c + 1
      d = d + 1
      c = c + 1
   next
      

   pixbuf=gdk_pixbuf_new_from_data(gtkbuffer, _
                                   GDK_COLORSPACE_RGB, _
               0, _
               8, _
               w, _
               h, _
               w*3, _
               NULL, _
               NULL)
   gc = gdk_gc_new (expose->window)

   gdk_pixbuf_render_to_drawable (pixbuf
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: Integrating GfxLib with Gtk

Post by owen »

i use gtk image new from file to load a bit map
i wonder if there's a way to create a gtk image without having to load it from an file, data, pixbub etc ?
myimage = gtk_image_new_from_file("580x580-black.bmp")
myimage = gtk_blank_image(width,height)

any how this is how i have managed to make fb graphics (fbgfx) work in gtk3
sure wish there was a way to not have to iterate through each pixel
For i = 0 To mywidth*myheight-1
*(mygetpixels+i*3)=myrgb.r
*(mygetpixels+i*3+1)=myrgb.g
*(mygetpixels+i*3+2)=myrgb.b
Next
wish instead i could just say something like *(mygetpixels = *modifiedscreenptr


Code: Select all

'fbcad drawarea width and height = 581 (0 to 580)
'screenres 581,581
'using widths and heights not multiples of 4 does'nt work
'use 580x580

Declare Sub myfbgfxtogtkimg()
Declare Sub mymain()
Declare Sub mygfxcolors()
Declare Sub moreballs()
Declare Sub lessballs()
Declare Sub myrgbcol(pc As UByte)


#include "fbgfx.bi"
#DEFINE __USE_GTK3__
#include once "gtk/gtk.bi"
#LIBPATH "c:/gtk3/lib"

#Define NULL 0

Dim Shared As GtkWidget Ptr win
Dim Shared As GtkWidget Ptr fixed
Dim As GtkWidget Ptr button1
Dim As GtkWidget Ptr button2
Dim Shared As GtkWidget Ptr myimage
Dim Shared mypixbuf as GdkPixbuf Ptr
Dim Shared mygetpixels As UByte Ptr
Dim Shared mywidth As Integer
Dim Shared myheight As Integer

Type myclr
    r As UByte
    g As UByte
    b As UByte
End Type
Dim Shared myrgb As myclr


Dim Shared ballc As Integer


gtk_init(NULL, NULL)

win = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(GTK_WINDOW(win), "FBgfx and GTK3image by Owen")
gtk_widget_set_size_request(win, 700, 700)


fixed = gtk_fixed_new()
gtk_container_add(GTK_CONTAINER(win), fixed)
 
button1 = gtk_button_new_with_label("More balls")
gtk_widget_set_size_request(button1, 80, 35)
gtk_fixed_put(GTK_FIXED(fixed), button1, 10, 50)
g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK (@moreballs), NULL)

button2 = gtk_button_new_with_label("Less balls")
gtk_widget_set_size_request(button2, 80, 35)
gtk_fixed_put(GTK_FIXED(fixed), button2, 10, 100)
g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK (@lessballs), NULL)

g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK (@gtk_main_quit), NULL)

'for fbgfx---------
myimage = gtk_image_new_from_file("580x580-black.bmp")
mypixbuf=gtk_image_get_pixbuf(myimage)
mygetpixels=gdk_pixbuf_get_pixels (mypixbuf)
mywidth = gdk_pixbuf_get_width (mypixbuf)
myheight = gdk_pixbuf_get_height (mypixbuf)
'gtk image to display fbgfx
gtk_fixed_put(fixed, myimage, 100, 50)


'when gtk is idle - draw the ball
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, @mymain, NULL, NULL)

'ScreenRes 581,581,,1,fb.GFX_NULL
ScreenRes mywidth,myheight,,1',fb.GFX_NULL

ballc=2
Dim Shared As Integer ball(4096,4)'x,y,direction,color
Dim As Integer i
For i = 1 To 4096
	ball(i,1)=Int(Rnd*(mywidth-11))+11
	ball(i,2)=Int(Rnd*(myheight-11))+11
	ball(i,3)=Int(Rnd*7)+1
	ball(i,4)=Int(Rnd*14)+1
Next



gtk_widget_show_all(win)

gtk_main()

End

Sub mymain()
	Sleep 1
	Dim As Integer i
	Cls
	For i = 1 To ballc
		Circle(ball(i,1),ball(i,2)),10,ball(i,4)
		Select Case ball(i,3)
			Case 1'up
				ball(i,2)=ball(i,2)-1
				If ball(i,2)=9 Then
					ball(i,2)=10
					ball(i,3)=2
				EndIf
			Case 2'down
				ball(i,2)=ball(i,2)+1
				If ball(i,2)=myheight-9 Then
					ball(i,2)=myheight-10
					ball(i,3)=1
				EndIf
			Case 3'left
				ball(i,1)=ball(i,1)-1
				If ball(i,1)=9 Then
					ball(i,1)=10
					ball(i,3)=4
				EndIf
			Case 4'right
				ball(i,1)=ball(i,1)+1
				If ball(i,1)=mywidth-9 Then
					ball(i,1)=mywidth-10
					ball(i,3)=3
				EndIf
			Case 5'up-left
				ball(i,2)=ball(i,2)-1
				If ball(i,2)=9 Then
					ball(i,2)=10
					ball(i,3)=7
				EndIf
				ball(i,1)=ball(i,1)-1
				If ball(i,1)=9 Then
					ball(i,1)=10
					If ball(i,3)=7 Then ball(i,3)=8 Else ball(i,3)=6
				EndIf
			Case 6'up-right
				ball(i,2)=ball(i,2)-1
				If ball(i,2)=9 Then
					ball(i,2)=10
					ball(i,3)=8
				EndIf
				ball(i,1)=ball(i,1)+1
				If ball(i,1)=mywidth-9 Then
					ball(i,1)=mywidth-10
					If ball(i,3)=8 Then ball(i,3)=7 Else ball(i,3)=5
				EndIf
			Case 7'down-left
				ball(i,2)=ball(i,2)+1
				If ball(i,2)=myheight-9 Then
					ball(i,2)=myheight-10
					ball(i,3)=5
				EndIf
				ball(i,1)=ball(i,1)-1
				If ball(i,1)=9 Then
					ball(i,1)=10
					If ball(i,3)=6 Then ball(i,3)=7 Else ball(i,3)=8
				EndIf
			Case 8'down-right
				ball(i,2)=ball(i,2)+1
				If ball(i,2)=myheight-9 Then
					ball(i,2)=myheight-10
					ball(i,3)=6
				EndIf
				ball(i,1)=ball(i,1)+1
				If ball(i,1)=mywidth-9 Then
					ball(i,1)=mywidth-10
					If ball(i,3)=6 Then ball(i,3)=5 Else ball(i,3)=7
				EndIf
		End Select
	Next
	Locate 1,1
	Print ballc
	myfbgfxtogtkimg
End Sub


Sub moreballs()
	ballc=ballc*2
	If ballc>4096 Then ballc=4096
End Sub

Sub lessballs()
	ballc=ballc/2
	If ballc<2 Then ballc=2
End Sub

Sub myfbgfxtogtkimg()
	gtk_widget_hide(myimage)
	Dim As Integer i
	Dim As UByte pixcolor,r,g,b
	Dim as ubyte ptr myfbgfx = ScreenPtr
	For i = 0 To mywidth*myheight-1
		pixcolor=*(myfbgfx+i)
		myrgbcol(pixcolor)
		*(mygetpixels+i*3)=myrgb.r
		*(mygetpixels+i*3+1)=myrgb.g
		*(mygetpixels+i*3+2)=myrgb.b
	Next
	gtk_widget_show(myimage)
End Sub

Sub myrgbcol(pc As UByte)
	Dim As UByte r,g,b
	Select Case pc
		Case 0 'black
			r=0
			g=0
			b=0
		Case 1 'blue
			r=0
			g=0
			b=255
		Case 2 'green
			r=0
			g=255
			b=0
		Case 3 'cyan
			r=0
			g=255
			b=255
		Case 4 'red
			r=255
			g=0
			b=0
		Case 5 'pink
			r=255
			g=192
			b=203
		Case 6 'yellow
			r=255
			g=255
			b=0
		Case 7 'grey
			r=128
			g=128
			b=128
		Case 8 'dark grey
			r=105
			g=105
			b=105
		Case 9 'bright blue
			r=132
			g=112
			b=255
		Case 10 'bright green
			r=127
			g=255
			b=0
		Case 11 'bright cyan
			r=105
			g=255
			b=255
		Case 12 'bright red
			r=255
			g=105
			b=105
		Case 13 'bright pink
			r=255
			g=222
			b=233
		Case 14 'bright yellow
			r=255
			g=255
			b=128
		Case 15 'white
			r=255
			g=255
			b=255
	End Select
	
	myrgb.r=r
	myrgb.g=g
	myrgb.b=b

End Sub
owen
Posts: 555
Joined: Apr 19, 2006 10:55
Location: Kissimmee, FL
Contact:

Re: Integrating GfxLib with Gtk

Post by owen »

draw lines and circles example

Code: Select all

'fbcad drawarea width and height = 581 (0 to 580)
'screenres 581,581
'using widths and heights not multiples of 4 does'nt work
'use 580x580

#include "fbgfx.bi"
#DEFINE __USE_GTK3__
#include once "gtk/gtk.bi"
#LIBPATH "c:/gtk3/lib"

#Define NULL 0

Declare Function motion_notify_event Cdecl ( Byval widget As GtkWidget Ptr, Byval event As GdkEventMotion Ptr ) As Integer
Declare Function calcd(cd1 as Double,cd2 as Double,cd3 as Double,cd4 as Double,cd5 as Double,cd6 as Double) as double


Declare Sub myfbgfxtogtkimg()
Declare Sub mymain()
Declare Sub mygfxcolors()
Declare Sub myrgbcol(pc As UByte)
Declare Sub mouse_button_down()
Declare Sub mouse_button_released()
Declare Sub button_draw_line()
Declare Sub button_draw_circle()
Declare Sub drawlines
Declare Sub drawcircles



Dim Shared As GtkWidget Ptr win
Dim Shared As GtkWidget Ptr fixed
Dim As GtkWidget Ptr button1
Dim As GtkWidget Ptr button2
Dim Shared As GtkWidget Ptr myimage
Dim Shared mypixbuf as GdkPixbuf Ptr
Dim Shared mygetpixels As UByte Ptr
Dim Shared mywidth As Integer
Dim Shared myheight As Integer
Dim Shared As GtkWidget Ptr ebox
Dim Shared As Integer mygtkimage_mouse_x, mygtkimage_mouse_y
Dim Shared As BOOLEAN mousebuttondown, mousebuttonup
Dim Shared As BOOLEAN drawingline=FALSE, drawingcircle=FALSE
Dim Shared As Integer linec,circlec
Dim Shared As Double lines(100,4), circles(100,3)
Dim Shared As String drawing_entity
drawing_entity="line"

Type myclr
    r As UByte
    g As UByte
    b As UByte
End Type
Dim Shared myrgb As myclr


Dim Shared ballc As Integer


gtk_init(NULL, NULL)

win = gtk_window_new(GTK_WINDOW_TOPLEVEL)
gtk_window_set_title(GTK_WINDOW(win), "FBgfx and GTK3image by Owen")
gtk_widget_set_size_request(win, 700, 700)


fixed = gtk_fixed_new()
gtk_container_add(GTK_CONTAINER(win), fixed)
 
button1 = gtk_button_new_with_label("Draw Lines")
gtk_widget_set_size_request(button1, 80, 35)
gtk_fixed_put(GTK_FIXED(fixed), button1, 10, 50)
g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK (@button_draw_line), NULL)

button2 = gtk_button_new_with_label("Draw Circles")
gtk_widget_set_size_request(button2, 80, 35)
gtk_fixed_put(GTK_FIXED(fixed), button2, 10, 100)
g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK (@button_draw_circle), NULL)

g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK (@gtk_main_quit), NULL)

'for fbgfx---------
myimage = gtk_image_new_from_file("580x580-black.bmp")
mypixbuf=gtk_image_get_pixbuf(myimage)
mygetpixels=gdk_pixbuf_get_pixels (mypixbuf)
mywidth = gdk_pixbuf_get_width (mypixbuf)
myheight = gdk_pixbuf_get_height (mypixbuf)
'gtk image to display fbgfx
'gtk_fixed_put(fixed, myimage, 100, 50)
ebox = gtk_event_box_new()
gtk_container_add(GTK_CONTAINER(ebox), myimage)
gtk_fixed_put(GTK_FIXED(fixed), ebox, 100,50)

g_signal_connect(G_OBJECT(ebox), "button_press_event", G_CALLBACK(@mouse_button_down), NULL)
g_signal_connect(G_OBJECT(ebox), "button_release_event", G_CALLBACK(@mouse_button_released), NULL)
gtk_widget_set_events(G_OBJECT(ebox), GDK_POINTER_MOTION_MASK)
g_signal_connect(G_OBJECT(ebox), "motion-notify-event", G_CALLBACK(@motion_notify_event), NULL)
'gtk_widget_set_events(ebox, GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK)




'when gtk is idle - draw the ball
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, @mymain, NULL, NULL)


'show the fb graphics screen
'ScreenRes mywidth,myheight
'hide the fb graphics screen
ScreenRes mywidth,myheight,,,fb.GFX_NULL


ballc=2
Dim Shared As Integer ball(4096,4)'x,y,direction,color
Dim As Integer i
For i = 1 To 4096
	ball(i,1)=Int(Rnd*(mywidth-11))+11
	ball(i,2)=Int(Rnd*(myheight-11))+11
	ball(i,3)=Int(Rnd*7)+1
	ball(i,4)=Int(Rnd*14)+1
Next

gtk_widget_show_all(win)

gtk_main()

End



Function motion_notify_event Cdecl ( Byval widget As GtkWidget Ptr, Byval event As GdkEventMotion Ptr ) As Integer
	mygtkimage_mouse_x = event->x
	mygtkimage_mouse_y = event->y
End Function

Function calcd(cd1 as Double,cd2 As Double,cd3 as Double,cd4 as Double,cd5 as Double,cd6 as Double) as double
	calcd = sqr((cd1-cd4)^2 + (cd2-cd5)^2 + (cd3-cd6)^2)
end function


Sub mymain()
	Sleep 1
	Dim As Integer i
	Cls
	'do not use any FB keyboard commands like input, inkey, get key
	'as it will cause a conflict with GTK
	
	'getmouse works when the FBGFX window is ACTIVE
	'but since the FBGFX window will be hidden GetMouse function will not be used
	'rather we will use GTK's mouse functions while mouse is over drawing area
	'also we will be using GTK's keyboard functions as well.
'	Dim As Integer mousex,mousey
'	GetMouse(mousex,mousey)
	'mousex and mousey will be -1 if mouse is not over the "ACTIVE" Fb graphics window
'	Print "FBGFX mouse x =";mousex, "mouse y =";mousey
	'USE GTK Keyboard and Mouse functions
	'Print "GTK mouse x =";mygtkimage_mouse_x, "mouse y =";mygtkimage_mouse_y
	If mousebuttondown=TRUE Then
		mousebuttondown=FALSE
		Select Case drawing_entity
			Case "line"
				If drawingline=FALSE Then
					drawingline=TRUE
					linec=linec+1
					lines(linec,1)=mygtkimage_mouse_x
					lines(linec,2)=mygtkimage_mouse_y
				EndIf
			Case "circle"
				If drawingcircle=FALSE Then
					drawingcircle=TRUE
					circlec=circlec+1
					circles(circlec,1)=mygtkimage_mouse_x
					circles(circlec,2)=mygtkimage_mouse_y
				EndIf				
		End Select
		'if this is the first time the mouse button is press down then begin drawing a line
	EndIf
	
	Select Case drawing_entity
		Case "line"
			If drawingline=TRUE Then Line(lines(linec,1),lines(linec,2))-(mygtkimage_mouse_x,mygtkimage_mouse_y)
		Case "circle"
			Dim r As Double
			r=calcd( circles(circlec,1) , circles(circlec,2) ,0, CDbl(mygtkimage_mouse_x), CDbl(mygtkimage_mouse_y),0)
			If drawingcircle=TRUE Then Circle( circles(circlec,1),circles(circlec,2) ),r
	End Select
	
	
	
	If mousebuttonup=TRUE Then
		mousebuttonup=FALSE
		Select Case drawing_entity
			Case "line"
				If drawingline=TRUE Then
					drawingline=FALSE
					lines(linec,3)=mygtkimage_mouse_x
					lines(linec,4)=mygtkimage_mouse_y
				EndIf			
			Case "circle"
				If drawingcircle=TRUE Then
					drawingcircle=FALSE
					Dim r As Double
					r=calcd( circles(circlec,1) , circles(circlec,2) ,0, CDbl(mygtkimage_mouse_x), CDbl(mygtkimage_mouse_y),0)
					circles(circlec,3)=r
				EndIf			
		End Select
	EndIf
	
	drawlines
	drawcircles
	myfbgfxtogtkimg
	
End Sub


Sub drawlines
	Dim As Integer i
	For i = 1 To linec
		If i=linec And drawingline=TRUE Then Exit For
		Line(lines(i,1),lines(i,2))-(lines(i,3),lines(i,4))
	Next
End Sub

Sub drawcircles
	Dim As Integer i
	For i = 1 To circlec
		If i=circlec And drawingcircle=TRUE Then Exit For
		circle(circles(i,1),circles(i,2)),circles(i,3)
	Next
End Sub



Sub button_draw_line()
	drawing_entity="line"
End Sub

Sub button_draw_circle()
	drawing_entity="circle"
End Sub


Sub mouse_button_down()
	mousebuttondown=TRUE
End Sub
Sub mouse_button_released()
	mousebuttonup=TRUE
End Sub

Sub myfbgfxtogtkimg()
	gtk_widget_hide(myimage)
	Dim As Integer i
	Dim As UByte pixcolor,r,g,b
	Dim as ubyte ptr myfbgfx = ScreenPtr
	For i = 0 To mywidth*myheight-1
		pixcolor=*(myfbgfx+i)
		myrgbcol(pixcolor)
		*(mygetpixels+i*3)=myrgb.r
		*(mygetpixels+i*3+1)=myrgb.g
		*(mygetpixels+i*3+2)=myrgb.b
	Next
	gtk_widget_show(myimage)
End Sub

Sub myrgbcol(pc As UByte)
	Dim As UByte r,g,b
	Select Case pc
		Case 0 'black
			r=0
			g=0
			b=0
		Case 1 'blue
			r=0
			g=0
			b=255
		Case 2 'green
			r=0
			g=255
			b=0
		Case 3 'cyan
			r=0
			g=255
			b=255
		Case 4 'red
			r=255
			g=0
			b=0
		Case 5 'pink
			r=255
			g=192
			b=203
		Case 6 'yellow
			r=255
			g=255
			b=0
		Case 7 'grey
			r=128
			g=128
			b=128
		Case 8 'dark grey
			r=105
			g=105
			b=105
		Case 9 'bright blue
			r=132
			g=112
			b=255
		Case 10 'bright green
			r=127
			g=255
			b=0
		Case 11 'bright cyan
			r=105
			g=255
			b=255
		Case 12 'bright red
			r=255
			g=105
			b=105
		Case 13 'bright pink
			r=255
			g=222
			b=233
		Case 14 'bright yellow
			r=255
			g=255
			b=128
		Case 15 'white
			r=255
			g=255
			b=255
	End Select
	
	myrgb.r=r
	myrgb.g=g
	myrgb.b=b

End Sub
Post Reply