;;;; png-pixels.lisp

(defpackage png-pixels (:use cl cl-user) (:nicknames pp))
(in-package png-pixels)

(defclass surface () 
 ((path :initarg :path :accessor path)
  (pointer :initform nil :accessor pointer)))

(defmethod (setf %pixel) (vals (obj surface) row col) "
(setf (%pixel (surface row col)) (r g b a)) -> nil
"
 (ffi:c-inline ((pointer obj) row col 
                (first vals) (second vals)
                (third vals) (fourth vals))
                (:pointer-void :int :int :int :int :int :int)
  (values :int) "
SDL_Surface *sfc;
unsigned char *pixels;
int pixbytes;

sfc = (SDL_Surface *)#0;
pixels = (unsigned char *)sfc->pixels;
pixbytes = sfc->format->BytesPerPixel;

pixels[(#1 * sfc->pitch + pixbytes * #2) + 2] = #3; /*r*/
pixels[(#1 * sfc->pitch + pixbytes * #2) + 1] = #4; /*g*/
pixels[(#1 * sfc->pitch + pixbytes * #2) + 0] = #5; /*b*/
pixels[(#1 * sfc->pitch + pixbytes * #2) + 3] = #6; /*a*/
")
 (values (%pixel obj row col)))

(defmethod %pixel ((obj surface) row col) "
(%pixel (surface row col)) -> (values r g b a)
Cast to numbers.
"
 (ffi:c-inline ((pointer obj) row col) (:pointer-void :int :int)
  (values :int :int :int :int) "
SDL_Surface *sfc;
unsigned char *pixels;
int pixbytes;

sfc = (SDL_Surface *)#0;
pixels = (unsigned char *)sfc->pixels;
pixbytes = sfc->format->BytesPerPixel;

@(return 0) = pixels[(#1 * sfc->pitch + pixbytes * #2) + 2]; /*r*/
@(return 1) = pixels[(#1 * sfc->pitch + pixbytes * #2) + 1]; /*g*/
@(return 2) = pixels[(#1 * sfc->pitch + pixbytes * #2) + 0]; /*b*/
@(return 3) = pixels[(#1 * sfc->pitch + pixbytes * #2) + 3]; /*a*/
"))

(defmethod %free ((obj surface))
 (ffi:c-inline ((pointer obj)) (:pointer-void) nil
  "SDL_FreeSurface((SDL_Surface *)#0);")
 (setf (slot-value obj 'pointer) nil)
 (values))

(defmethod %load ((obj surface))
 (setf (pointer obj)
  (ffi:with-cstring (npath (path obj))
   (ffi:c-inline (npath) (:cstring) :pointer-void "
SDL_Surface *sfc;

sfc = IMG_Load(#0);
if (sfc == NULL) {
        printf(\"Failed to load png to surface\\n\");
        exit(1);
}
@(return 0)=sfc;
")))
 (values))

(defmethod %save ((obj surface))
 (ffi:with-cstring (npath (path obj))
  (ffi:c-inline ((pointer obj) npath) (:pointer-void :cstring) nil "
int result;
result = IMG_SavePNG((SDL_Surface *)#0, #1);
if (result<0) {
        printf(\"Failed to save surface as png\\n\");
        exit(1);
}"))
 (values))

(defun %start-sdl2 ()
 (ffi:clines "
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
")
 (ffi:c-inline () () nil "

if (SDL_Init(0) < 0) {
        printf(\"SDL failed to init\\n\");
        exit(1);
}
")
 (values))

(defun %stop-sdl2 ()
 (ffi:c-inline () () nil "
SDL_Quit();")
 (values))