Giter Club home page Giter Club logo

Comments (14)

bohonghuang avatar bohonghuang commented on July 19, 2024 1

Okay, previously there were no bindings generated for GdkPixbuf because I thought it had fewer use cases. Now, I have added it in commit 6ab0131. Please upgrade to use it.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024

I suspect that your pathname contains a ~ that cannot be expanded by GTK. To address this, you need to use (namestring (truename (cu/display u))) to expand it on the Lisp side.

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

That didn't help either, and when I (format t "~a" (cu/display u)), I get the full path /Users/jonathanbennett/.roswell/lisp/quicklisp/local-projects/megastrike/data/images/units/vehicles/Pumapat.png

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024

Can you load cl-gdk4 and try this in your application?

(let ((texture (gdk:make-texture :path "/path/to/your/image/file")))
  (format t "WIDTH: ~A HEIGHT: ~A~%" (gdk:texture-width texture) (gdk:texture-height texture)))

The function gdk:make-texture should signal an error when it fails to open the file. Once the texture is loaded successfully, you can create a picture with (gtk:make-picture :paintable texture).

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

the above snippet accurately reports the size of the image (84x72 px), but the image is still not rendering. It is a png file, is the a possible reason for the error?

EDIT: Using gtk:make-image once more renders it (when using a texture or a file). This makes me wonder if I need to do something to set the size of the image when using a picture, but I do not see anything that I could change to set the picture size.

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024

Have you tried a minimal example like this?

(define-application (:name picture-test
                     :id "org.bohonghuang.gtk4.issue-33")
  (define-main-window (window (make-application-window :application *application*))
    (setf (window-title window) "Picture Test"
          (window-child window) (make-picture :filename "/path/to/your/image/file"))
    (unless (widget-visible-p window)
      (window-present window))))

The snippet is tested to run on both Windows and GNU/Linux, and the size of the picture defaults to the dimensions of the image file.

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

The minimum example you just posted works on MacOS as well (just tested it now). Is it possible that you can't have a picture inside a box or inside a ListBoxChild?

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024

The minimum size of Picture defaults to zeros, so you could use (setf (widget-size-request picture) '(100 100)) to set the size manually after creating a picture.

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

Ok, I've got that working. I'm struggling to figure out how I could draw the picture in a drawing area.

EDIT: Ok, here is the code that has gotten me the closest to managing to draw the images on the screen.

(let ((unit (function-that-returns-nil-or-the-occupant-of-a-hex)))
    (when unit
      (with-gdk-rgba (color "#000000")
        (gdk:cairo-set-source-rgba cr color)
        (gdk:cairo-set-source-pixbuf cr
                                     (gdk:pixbuf-get-from-texture (cu/display unit)) ;; cu/display unit returns a GDK:Texture
                                     (point-x (nth 5 hex-points))
                                     (point-y (nth 5 hex-points))))
      cairo:stroke)))

In the screenshot attached, there should be an image inside the top-left hex (the one that would be labeled 0101, but instead it is completely empty. It put something there, because the text telling you the hex number is gone from that hex, but whatever is there is invisible.

Screenshot 2023-10-10 at 8 12 15

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

I have rewritten this down to the smallest possible code I can envision might do this:

(defun draw-test-window ()
  (let ((window (gtk:make-application-window :application gtk:*application*))
        (picture (gtk:make-drawing-area)))
    (setf (gtk:window-child window) picture
          (gtk:drawing-area-content-width picture) 500
          (gtk:drawing-area-content-height picture) 500
          (gtk:drawing-area-draw-func picture) (list (cffi:callback %draw-func)
                                                    (cffi:null-pointer)
                                                    (cffi:null-pointer)))
    (unless (gtk:widget-visible-p window)
      (gtk:window-present window))))

(defun draw-func (area cr width height)
  (declare (ignore area)
           (optimize (speed 3)
                     (debug 0)
                     (safety 0)))
  (with-gdk-rgba (color "#000000")
    (let ((texture (gdk:make-texture :path (namestring (merge-pathnames "images/units/mechs/Akuma.png" *data-folder*)))))
      (gdk:cairo-set-source-pixbuf cr
                                   (gdk:pixbuf-get-from-texture texture)
                                   (coerce (the fixnum 100) 'double-float)
                                   (coerce (the fixnum 100) 'double-float))
      (cairo:fill-path))))

Having (cairo:stroke) as the final line also does not draw anything on the screen. In both cases, I get a blank white screen which is 500 by 500 pixels. I expected the image to be displayed 100 pixel down from the top and over from the left.

EDIT:

Sorry, I forgot to include the callback function, but this was copy/pasted from your Cairo demo so I suspect you're familiar with it.

(cffi:defcallback %draw-func :void ((area :pointer)
                                    (cr :pointer)
                                    (width :int)
                                    (height :int)
                                    (data :pointer))
  (declare (ignore data))
  (let ((cairo:*context* (make-instance 'cairo:context
                                        :pointer cr
                                        :width width
                                        :height height
                                        :pixel-based-p nil)))
    (draw-func (make-instance 'gir::object-instance
                              :class (gir:nget gtk:*ns* "DrawingArea")
                              :this area)
               (make-instance 'gir::struct-instance
                              :class (gir:nget megastrike::*ns* "Context")
                              :this cr)
               width height)))

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024

Having (cairo:stroke) as the final line also does not draw anything on the screen. In both cases, I get a blank white screen which is 500 by 500 pixels. I expected the image to be displayed 100 pixel down from the top and over from the left.

You haven't set a path using functions like cairo:rectangle, so there won't be anything drawn. The following code can help you draw your image in the center of the canvas.

(defun draw-func (area cr canvas-width canvas-height)
    (declare (ignore area)
             (optimize (speed 3)
                       (debug 0)
                       (safety 0)))
  (let ((texture (gdk:make-texture :path (namestring (truename (merge-pathnames "images/units/mechs/Akuma.png" *data-folder*))))))
    (let* ((canvas-width (coerce (the fixnum canvas-width) 'single-float))
           (canvas-height (coerce (the fixnum canvas-height) 'single-float))
           (width (coerce (the fixnum (gdk:texture-width texture)) 'single-float))
           (height (coerce (the fixnum (gdk:texture-height texture)) 'single-float))
           (x (/ (- canvas-width width) 2.0))
           (y (/ (- canvas-height width) 2.0)))
      (cairo:rectangle x y width height)
      (gdk:cairo-set-source-pixbuf cr (gdk:pixbuf-get-from-texture texture) (coerce x 'double-float) (coerce y 'double-float))
      (cairo:fill-path)
      (with-gdk-rgba (color "#FF0000")
        (cairo:rectangle x y width height)
        (gdk:cairo-set-source-rgba cr color)
        (cairo:set-line-width 3.0)
        (cairo:stroke)))))

where x and y are the coordinates of the top-left corner of the image, you can change them to position the image wherever you want it to be drawn.

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

Ok, got that part working within my program. The problem now is a matter of scaling. Based on reading the GDK Documentation and a few examples in Python, it appears I need to use GdkPixbuf.Pixbuf.scale_simple, but I can't find it in GDK4. If I use (cairo:scale), it scales all the coordinates (obviously), meaning the x and y origin for the image shifts.

from cl-gtk4.

jonathanabennett avatar jonathanabennett commented on July 19, 2024

Next question. The images I have are all black and white. I'd like to mark which team they are on by painting the unit the team's color (which I've got in the format returned by gdk:rgba-to-string). I looked at GdkPixbuf.Pixbuf.composite-color-simple, but it wants a GUINT32 rather than an RGBA color structure. Should I be controlling this in Cairo?

from cl-gtk4.

bohonghuang avatar bohonghuang commented on July 19, 2024
  1. You can directly provide the color value in the format #xRRGGBBAA.
  2. If you are familiar with cffi, the conversion between GdkRGBA and the RGBA8888 should not be difficult:
(cffi:defcstruct gdk-rgba
  (red :float)
  (green :float)
  (blue :float)
  (alpha :float))

(cffi:defcstruct rgba8888
  (red :uint8)
  (green :uint8)
  (blue :uint8)
  (alpha :uint8))

(defun rgba-color-value (rgba)
  (cffi:with-foreign-slots (((r1 red) (g1 green) (b1 blue) (a1 alpha)) (gobj:object-pointer rgba) (:struct gdk-rgba))
    (cffi:with-foreign-object (pointer '(:struct rgba8888))
      (cffi:with-foreign-slots (((r2 red) (g2 green) (b2 blue) (a2 alpha)) pointer (:struct rgba8888))
        (setf r2 (round (* r1 #xFF))
              g2 (round (* g1 #xFF))
              b2 (round (* b1 #xFF))
              a2 (round (* a1 #xFF))))
      (cffi:mem-ref pointer :uint32))))

(with-gdk-rgba (rgba "#FF0000FF")
  (assert (= (rgba-color-value rgba) #xFF0000FF)))

from cl-gtk4.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.