[Linux] Cursor_From_PNG

Share your advanced PureBasic knowledge/code with the community.
GBeebe
Enthusiast
Enthusiast
Posts: 263
Joined: Sat Oct 09, 2004 6:52 pm
Location: Franklin, PA - USA
Contact:

[Linux] Cursor_From_PNG

Post by GBeebe »

To make it easier to have custom cursors in a Linux game I'm working on, I decided to write my own Procedure which does so from a PNG file.

sample image:
Image

The PNG file needs to be square (equal width and height), I think it also has to be 16*16, 32*32, 64*64 etc, only. Any transparent pixels in the PNG will be transparent in the cursor, also only black and white colors are allowed.

Code: Select all

Procedure.i Cursor_From_PNG(pngfile.s, hx, hy)
;hx and hy are the "hot spot" for the pointer.
png = LoadImage(#PB_Any, pngfile.s)
w = ImageWidth(png)
h = ImageHeight(png)

*pngsrc = AllocateMemory(w*h/8)   ;the source (1 bit per pixel, 1 byte for 8 pixels)
*pngmsk = AllocateMemory(w*h/8)   ;image mask for the source

StartDrawing(ImageOutput(png))
DrawingMode(#PB_2DDrawing_AlphaBlend)   ;we need the alpha chanel to make the mask.
For a = 1 To w * h Step 8
    srcbyte.s = "" ;reset the binary strings
    mskbyte.s = ""
    
    For b = 0 To 7  ; 8 pixels
        x = (a + b) % w : If x = 0 : x = w : EndIf      ;calculate x
        y = (a + b) / w : If x <> w : y + 1 : EndIf     ;calculate y
        c.l = Point(x-1, y-1)
        If Alpha(c) <> 0    ;this is solid?
            ;we are assuming that this image is only black and white, so we'll use the red value to check color.
            If Red(c) <> 0
                srcbyte.s + "1"
            Else
                srcbyte.s + "0"
            EndIf
            mskbyte.s + "1"
        Else
            srcbyte + "0"
            mskbyte + "0"
        EndIf                       
    Next
    ;fix endian problem
    srcbyte.s = ReverseString(srcbyte.s)
    mskbyte.s = ReverseString(mskbyte.s)
    ;byte = binary string
    sbyte.b = Val("%" + srcbyte.s) 
    mbyte.b = Val("%" + mskbyte.s)
    ;write the byte to the pointer
    PokeB(*pngsrc + (a / 8), sbyte.b)
    PokeB(*pngmsk + (a / 8), mbyte.b)
Next
StopDrawing()

fg.GdkColor ;white color
fg\red = 65535
fg\green = 65535
fg\blue = 65535
bg.GdkColor ;black color

src = gdk_bitmap_create_from_data_(#Null, *pngsrc, w, h)
msk = gdk_bitmap_create_from_data_(#Null, *pngmsk, w, h)
*mycursor = gdk_cursor_new_from_pixmap_(src, msk, @fg, @bg, hx, hy)
ProcedureReturn *mycursor
EndProcedure


Main_Window = OpenWindow(#PB_Any, 50, 50, 512, 512, "Cursor Test")

;create a Gdk Pointer to the Widget\Window
        *Widget.GtkWidget = WindowID(Main_Window)
        *GdkWindow = *Widget\Window
        *cur_sword = Cursor_From_PNG("sword.png", 0, 0)
;set the cursor        
        gdk_window_set_cursor_(*GdkWindow , *cur_sword) 

Repeat
    WE = WaitWindowEvent()
Delay(10)
Until WE = #PB_Event_CloseWindow

Feel free to post any alterations you feel may be beneficial to the Linux PB community.
User avatar
Erlend
Enthusiast
Enthusiast
Posts: 115
Joined: Mon Apr 19, 2004 8:22 pm
Location: NORWAY

Re: [Linux] Cursor_From_PNG

Post by Erlend »

Another way to create custom gdk cursor from PNG file or just draw like here...

Code: Select all

Procedure CreateCursor(Image,x,y)
   ProcedureReturn gdk_cursor_new_from_pixbuf_(gdk_display_get_default_(),ImageID(image),x,y)
EndProcedure
Procedure SetCursor(Handle,Cursor)
  *widget.gtkwidget=Handle
  gdk_window_set_cursor_(*widget\window,Cursor)    
EndProcedure

OpenWindow(0,0,0,300,300,"Cursor Test Gdk/Gtk")
CreateImage(0,32,32,32)
StartDrawing(ImageOutput(0))
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0,0,32,32,0)
DrawingMode(#PB_2DDrawing_AlphaBlend)
LineXY(16,0,16,32,RGBA(0,255,0,155))
LineXY(0,16,32,16,RGBA(0,255,0,155))
StopDrawing()

result=createcursor(0,16,16)
Setcursor(WindowID(0),result)
ButtonGadget(0,0,0,100,30,"TEST") 

Repeat
Until WaitWindowEvent()=#PB_Event_CloseWindow
GBeebe
Enthusiast
Enthusiast
Posts: 263
Joined: Sat Oct 09, 2004 6:52 pm
Location: Franklin, PA - USA
Contact:

Re: [Linux] Cursor_From_PNG

Post by GBeebe »

:) Ok, you win. Thank you though. I knew it was possible to have multi color cursors, with different alpha levels, but hadn't gotten to figuring out gdk_cursor_new_from_pixbuf_() because I thought images in PB were pixmaps. Thank you again.
User avatar
Erlend
Enthusiast
Enthusiast
Posts: 115
Joined: Mon Apr 19, 2004 8:22 pm
Location: NORWAY

Re: [Linux] Cursor_From_PNG

Post by Erlend »

You are right but the PB Team changed PBImage in 4.40 from pixmaps to pixbufs under linux...
Post Reply