diff --git a/vendor/raylib/raylib.flan b/vendor/raylib/raylib.flan index 5b0bb55..a84dc2b 100644 --- a/vendor/raylib/raylib.flan +++ b/vendor/raylib/raylib.flan @@ -1,19 +1,35 @@ ;;;; raylib, declared for Flan. The directory is the package (plan.org, ;;;; Modules), and (import rl "vendor:raylib") qualifies all of it as rl/… ;;;; -;;;; Nothing here names a raylib symbol. Every `declare` names a wrapper in -;;;; shim.c, and that is the whole design decision: raylib passes Color by -;;;; value and returns Vector2 by value, and how a small aggregate is passed -;;;; differs between x86-64, arm64 and wasm32. Written in C, clang classifies -;;;; each one correctly per target for free; written in emit.ml it would be -;;;; three calling conventions to reimplement and then maintain forever. This -;;;; is "one narrow host ABI, implemented twice" (plan.org, Targets), and it -;;;; is why the checker rejects an aggregate in a `declare` signature at all. +;;;; Every binding here is one `declare-c` line naming raylib's own function +;;;; in raylib's own signature — Color by value, Vector2 returned by value — +;;;; and the compiler writes the C that flattens it. There is no shim.c in +;;;; this directory any more, and no hand-written wrapper at all. ;;;; -;;;; So each struct that crosses does it through a pointer, and the `-raw` -;;;; declaration is wrapped by an ordinary Flan function just below it. The -;;;; `-raw` names are visible as rl/…-raw because there is no visibility rule -;;;; yet; they are not meant to be called. +;;;; The shim itself did not go away, only the typing of it. A small +;;;; aggregate's calling convention is a per-target classification rather than +;;;; part of its layout: x86-64 hands Vector2 over as <2 x float> and returns +;;;; Rectangle as {i64,i64}, and arm64 and wasm32 each do something else. +;;;; Written in C, clang classifies every one of them correctly for whichever +;;;; target the build is for; written in emit.ml it would be three calling +;;;; conventions to reimplement and then keep correct forever, and a mistake +;;;; would read as a field full of garbage rather than as a link error. This +;;;; is "one narrow host ABI, implemented twice" (plan.org, Targets). See +;;;; lib/shim.ml. +;;;; +;;;; What that means for reading this file: the `defstruct`s below are the +;;;; only statement anywhere about raylib's layouts, and the generated C +;;;; typedefs are made from them. No raylib header is consulted — a build +;;;; needs libraylib linkable, not raylib-devel — so a wrong field order here +;;;; is wrong everywhere and nothing but a test can catch it. The acceptance +;;;; cases pin the layouts by making raylib *compute* with the fields, and +;;;; they go red when a struct below is permuted. Likewise a scalar's width: +;;;; f64 where raylib says float now emits `double` in the generated +;;;; prototype, and raylib reads garbage. +;;;; +;;;; Two bindings keep a hand-written Flan wrapper, both because their Flan +;;;; face is deliberately not raylib's: collision-point-poly? takes a slice, +;;;; and collision-lines answers with an Option. Both wrappers are Flan. ;; Layouts are C's — no object headers anywhere — so these are exactly ;; raylib's structs and nothing marshals. @@ -46,31 +62,27 @@ ;; ── Window ────────────────────────────────────────────────────────── -(declare init-window [width i32 height i32 title string] "flan_rl_init_window") -(declare close-window [] "flan_rl_close_window") -(declare window-should-close? [] bool "flan_rl_window_should_close") -(declare set-target-fps [fps i32] "flan_rl_set_target_fps") -(declare set-trace-log-level [level TraceLogLevel] "flan_rl_set_trace_log_level") +(declare-c init-window [width i32 height i32 title string] "InitWindow") +(declare-c close-window [] "CloseWindow") +(declare-c window-should-close? [] bool "WindowShouldClose") +(declare-c set-target-fps [fps i32] "SetTargetFPS") +(declare-c set-trace-log-level [level TraceLogLevel] "SetTraceLogLevel") ;; ── Input ─────────────────────────────────────────────────────────── -(declare key-pressed? [key Key] bool "flan_rl_is_key_pressed") -(declare key-down? [key Key] bool "flan_rl_is_key_down") -(declare key-released? [key Key] bool "flan_rl_is_key_released") +(declare-c key-pressed? [key Key] bool "IsKeyPressed") +(declare-c key-down? [key Key] bool "IsKeyDown") +(declare-c key-released? [key Key] bool "IsKeyReleased") -(declare mouse-button-pressed? [button MouseButton] bool - "flan_rl_is_mouse_button_pressed") -(declare mouse-button-down? [button MouseButton] bool - "flan_rl_is_mouse_button_down") -(declare mouse-button-released? [button MouseButton] bool - "flan_rl_is_mouse_button_released") +(declare-c mouse-button-pressed? + [button MouseButton] bool + "IsMouseButtonPressed") +(declare-c mouse-button-down? [button MouseButton] bool "IsMouseButtonDown") +(declare-c mouse-button-released? + [button MouseButton] bool + "IsMouseButtonReleased") -(declare get-mouse-position-raw [out (Ptr Vector2)] "flan_rl_get_mouse_position") - -(defn get-mouse-position [] Vector2 - (let [v (Vector2 {})] - (get-mouse-position-raw (addr v)) - v)) +(declare-c get-mouse-position [] Vector2 "GetMousePosition") ;; ── Colours ───────────────────────────────────────────────────────── ;; @@ -78,37 +90,22 @@ ;; reading of the packed 0xRRGGBBAA integer — that is why get-color is a real ;; call and not a reinterpretation. -(declare get-color-raw [hex u32 out (Ptr Color)] "flan_rl_get_color") - -(defn get-color [hex u32] Color - (let [c (Color {})] - (get-color-raw hex (addr c)) - c)) +(declare-c get-color [hex u32] Color "GetColor") (defconst black (Color {:r 0 :g 0 :b 0 :a 255})) (defconst white (Color {:r 255 :g 255 :b 255 :a 255})) ;; ── Drawing ───────────────────────────────────────────────────────── -(declare begin-drawing [] "flan_rl_begin_drawing") -(declare end-drawing [] "flan_rl_end_drawing") -(declare draw-fps [x i32 y i32] "flan_rl_draw_fps") +(declare-c begin-drawing [] "BeginDrawing") +(declare-c end-drawing [] "EndDrawing") +(declare-c draw-fps [x i32 y i32] "DrawFPS") -(declare clear-background-raw [color (Ptr Color)] "flan_rl_clear_background") +(declare-c clear-background [color Color] "ClearBackground") -(defn clear-background [color Color] - ;; The copy is not ceremony: a parameter is not an assignable place - ;; (spec-memory.md), so there is no address to take without one. - (let [c color] - (clear-background-raw (addr c)))) - -(declare draw-rectangle-raw - [x i32 y i32 width i32 height i32 color (Ptr Color)] - "flan_rl_draw_rectangle") - -(defn draw-rectangle [x i32 y i32 width i32 height i32 color Color] - (let [c color] - (draw-rectangle-raw x y width height (addr c)))) +(declare-c draw-rectangle + [x i32 y i32 width i32 height i32 color Color] + "DrawRectangle") ;; ── Shapes texture ────────────────────────────────────────────────── ;; @@ -122,29 +119,15 @@ ;; source's width or height is not positive, so a caller — and the test — ;; should keep clear of those values if it wants its own back. -(declare set-shapes-texture-raw - [texture (Ptr Texture2D) source (Ptr Rectangle)] - "flan_rl_set_shapes_texture") +(declare-c set-shapes-texture + [texture Texture2D source Rectangle] + "SetShapesTexture") -(defn set-shapes-texture [texture Texture2D source Rectangle] - (let [t texture - r source] - (set-shapes-texture-raw (addr t) (addr r)))) +(declare-c get-shapes-texture [] Texture2D "GetShapesTexture") -(declare get-shapes-texture-raw [out (Ptr Texture2D)] "flan_rl_get_shapes_texture") - -(defn get-shapes-texture [] Texture2D - (let [t (Texture2D {})] - (get-shapes-texture-raw (addr t)) - t)) - -(declare get-shapes-texture-rectangle-raw - [out (Ptr Rectangle)] "flan_rl_get_shapes_texture_rectangle") - -(defn get-shapes-texture-rectangle [] Rectangle - (let [r (Rectangle {})] - (get-shapes-texture-rectangle-raw (addr r)) - r)) +(declare-c get-shapes-texture-rectangle + [] Rectangle + "GetShapesTextureRectangle") ;; ── Camera2D ──────────────────────────────────────────────────────── ;; @@ -160,13 +143,9 @@ (defstruct Camera2D [offset Vector2 target Vector2 rotation f32 zoom f32]) -(declare begin-mode-2d-raw [camera (Ptr Camera2D)] "flan_rl_begin_mode_2d") +(declare-c begin-mode-2d [camera Camera2D] "BeginMode2D") -(defn begin-mode-2d [camera Camera2D] - (let [c camera] - (begin-mode-2d-raw (addr c)))) - -(declare end-mode-2d [] "flan_rl_end_mode_2d") +(declare-c end-mode-2d [] "EndMode2D") ;; The two conversions are pure arithmetic over every field of the camera, so ;; unlike the rest of the camera they run with no window and no GL context. @@ -174,27 +153,13 @@ ;; a rotated camera, which is the only call here that mixes x into y — it is ;; also the only thing that pins Vector2's two fields against each other. -(declare get-screen-to-world-2d-raw - [position (Ptr Vector2) camera (Ptr Camera2D) out (Ptr Vector2)] - "flan_rl_get_screen_to_world_2d") +(declare-c get-screen-to-world-2d + [position Vector2 camera Camera2D] Vector2 + "GetScreenToWorld2D") -(defn get-screen-to-world-2d [position Vector2 camera Camera2D] Vector2 - (let [p position - c camera - out (Vector2 {})] - (get-screen-to-world-2d-raw (addr p) (addr c) (addr out)) - out)) - -(declare get-world-to-screen-2d-raw - [position (Ptr Vector2) camera (Ptr Camera2D) out (Ptr Vector2)] - "flan_rl_get_world_to_screen_2d") - -(defn get-world-to-screen-2d [position Vector2 camera Camera2D] Vector2 - (let [p position - c camera - out (Vector2 {})] - (get-world-to-screen-2d-raw (addr p) (addr c) (addr out)) - out)) +(declare-c get-world-to-screen-2d + [position Vector2 camera Camera2D] Vector2 + "GetWorldToScreen2D") ;; ── Shapes ────────────────────────────────────────────────────────── ;; @@ -203,16 +168,9 @@ ;; also how the acceptance table pins the layout: a store-and-return check is ;; symmetric and a permuted layout survives it untouched. -(declare get-collision-rec-raw - [a (Ptr Rectangle) b (Ptr Rectangle) out (Ptr Rectangle)] - "flan_rl_get_collision_rec") - -(defn get-collision-rec [a Rectangle b Rectangle] Rectangle - (let [x a - y b - out (Rectangle {})] - (get-collision-rec-raw (addr x) (addr y) (addr out)) - out)) +(declare-c get-collision-rec + [a Rectangle b Rectangle] Rectangle + "GetCollisionRec") ;; ── Collision ─────────────────────────────────────────────────────── ;; @@ -220,103 +178,75 @@ ;; makes them the other half of what the acceptance table can assert, and the ;; only part of the 2D surface that is tested as thoroughly as it is bound. ;; -;; Each takes its aggregates through pointers for the usual reason, and each -;; wrapper copies its parameters into locals first — a parameter is not an -;; assignable place (spec-memory.md), so there is no address to take. +;; Each is declared exactly as raylib declares it. The pointers and the copies +;; the crossing needs — a parameter is not an assignable place +;; (spec-memory.md), so a struct argument has no address to take without one — +;; are in the generated halves and not here. -(declare collision-recs?-raw [a (Ptr Rectangle) b (Ptr Rectangle)] bool - "flan_rl_check_collision_recs") +(declare-c collision-recs? + [a Rectangle b Rectangle] bool + "CheckCollisionRecs") -(defn collision-recs? [a Rectangle b Rectangle] bool - (let [x a y b] - (collision-recs?-raw (addr x) (addr y)))) +(declare-c collision-circles? + [c1 Vector2 r1 f32 c2 Vector2 r2 f32] bool + "CheckCollisionCircles") -(declare collision-circles?-raw - [c1 (Ptr Vector2) r1 f32 c2 (Ptr Vector2) r2 f32] bool - "flan_rl_check_collision_circles") +(declare-c collision-circle-rec? + [center Vector2 radius f32 rec Rectangle] bool + "CheckCollisionCircleRec") -(defn collision-circles? [c1 Vector2 r1 f32 c2 Vector2 r2 f32] bool - (let [a c1 b c2] - (collision-circles?-raw (addr a) r1 (addr b) r2))) +(declare-c collision-circle-line? [center Vector2 radius f32 + p1 Vector2 p2 Vector2] bool "CheckCollisionCircleLine") -(declare collision-circle-rec?-raw - [center (Ptr Vector2) radius f32 rec (Ptr Rectangle)] bool - "flan_rl_check_collision_circle_rec") +(declare-c collision-point-rec? + [point Vector2 rec Rectangle] bool + "CheckCollisionPointRec") -(defn collision-circle-rec? [center Vector2 radius f32 rec Rectangle] bool - (let [c center r rec] - (collision-circle-rec?-raw (addr c) radius (addr r)))) +(declare-c collision-point-circle? + [point Vector2 center Vector2 radius f32] bool + "CheckCollisionPointCircle") -(declare collision-circle-line?-raw - [center (Ptr Vector2) radius f32 p1 (Ptr Vector2) p2 (Ptr Vector2)] bool - "flan_rl_check_collision_circle_line") - -(defn collision-circle-line? [center Vector2 radius f32 - p1 Vector2 p2 Vector2] bool - (let [c center a p1 b p2] - (collision-circle-line?-raw (addr c) radius (addr a) (addr b)))) - -(declare collision-point-rec?-raw [point (Ptr Vector2) rec (Ptr Rectangle)] bool - "flan_rl_check_collision_point_rec") - -(defn collision-point-rec? [point Vector2 rec Rectangle] bool - (let [p point r rec] - (collision-point-rec?-raw (addr p) (addr r)))) - -(declare collision-point-circle?-raw - [point (Ptr Vector2) center (Ptr Vector2) radius f32] bool - "flan_rl_check_collision_point_circle") - -(defn collision-point-circle? [point Vector2 center Vector2 radius f32] bool - (let [p point c center] - (collision-point-circle?-raw (addr p) (addr c) radius))) - -(declare collision-point-triangle?-raw - [point (Ptr Vector2) a (Ptr Vector2) b (Ptr Vector2) c (Ptr Vector2)] bool - "flan_rl_check_collision_point_triangle") - -(defn collision-point-triangle? [point Vector2 a Vector2 b Vector2 - c Vector2] bool - (let [p point x a y b z c] - (collision-point-triangle?-raw (addr p) (addr x) (addr y) (addr z)))) +(declare-c collision-point-triangle? [point Vector2 a Vector2 b Vector2 + c Vector2] bool "CheckCollisionPointTriangle") ;; `threshold` is in pixels, and it is not optional in practice: raylib's test ;; is a distance comparison in floats, so a point exactly on the line fails at ;; a threshold of 0. 1 is the useful smallest value. -(declare collision-point-line?-raw - [point (Ptr Vector2) p1 (Ptr Vector2) p2 (Ptr Vector2) threshold i32] bool - "flan_rl_check_collision_point_line") +(declare-c collision-point-line? [point Vector2 p1 Vector2 p2 Vector2 + threshold i32] bool "CheckCollisionPointLine") -(defn collision-point-line? [point Vector2 p1 Vector2 p2 Vector2 - threshold i32] bool - (let [p point a p1 b p2] - (collision-point-line?-raw (addr p) (addr a) (addr b) threshold))) - -;; A slice crosses as ptr+len, which is exactly what raylib wants here, so -;; this is the one collision call that needs no per-element copying. The -;; polygon is not closed explicitly — raylib joins the last point to the -;; first. -(declare collision-point-poly?-raw [point (Ptr Vector2) points [Vector2]] bool - "flan_rl_check_collision_point_poly") +;; The one binding whose Flan face is not raylib's, and one of only two in +;; this file with a hand-written wrapper on top. A Flan slice crosses as +;; ptr+len with an i64 length; raylib wants a pointer and an `int` count, and +;; the generator refuses to guess what integer type a C count parameter is — +;; so the declaration says (Ptr Vector2) and a count, and the wrapper takes +;; the slice apart. The polygon is not closed explicitly; raylib joins the +;; last point to the first. +;; +;; Empty is answered here rather than passed on: (at points 0) would be an +;; out-of-bounds read, and raylib answers false for a polygon with no points +;; anyway. +(declare-c collision-point-poly?-raw + [point Vector2 points (Ptr Vector2) count i32] bool + "CheckCollisionPointPoly") (defn collision-point-poly? [point Vector2 points [Vector2]] bool - (let [p point] - (collision-point-poly?-raw (addr p) points))) + (if (= (len points) 0) + false + (collision-point-poly?-raw point (addr (at points 0)) (len points)))) ;; The one that answers with more than yes or no: where the two segments meet. ;; None is "they do not", so the point cannot be read when there isn't one — ;; raylib's own signature leaves the out-parameter untouched in that case and ;; a caller that forgets reads whatever was there. -(declare collision-lines-raw - [a1 (Ptr Vector2) a2 (Ptr Vector2) b1 (Ptr Vector2) b2 (Ptr Vector2) - out (Ptr Vector2)] bool - "flan_rl_check_collision_lines") +(declare-c collision-lines-raw + [a1 Vector2 a2 Vector2 b1 Vector2 b2 Vector2 out (Ptr Vector2)] bool + "CheckCollisionLines") (defn collision-lines [a1 Vector2 a2 Vector2 b1 Vector2 b2 Vector2] (Option Vector2) - (let [p a1 q a2 r b1 s b2 - out (Vector2 {})] - (if (collision-lines-raw (addr p) (addr q) (addr r) (addr s) (addr out)) + (let [out (Vector2 {})] + (if (collision-lines-raw a1 a2 b1 b2 (addr out)) (Some out) None))) @@ -328,70 +258,27 @@ ;; only in the log; raylib 5.5 spells it IsTextureValid, and IsTextureReady, ;; which older code calls, does not exist in this version. -(declare load-texture-raw [path string out (Ptr Texture2D)] "flan_rl_load_texture") +(declare-c load-texture [path string] Texture2D "LoadTexture") -(defn load-texture [path string] Texture2D - (let [t (Texture2D {})] - (load-texture-raw path (addr t)) - t)) +(declare-c texture-valid? [texture Texture2D] bool "IsTextureValid") -(declare texture-valid?-raw [texture (Ptr Texture2D)] bool "flan_rl_is_texture_valid") +(declare-c unload-texture [texture Texture2D] "UnloadTexture") -(defn texture-valid? [texture Texture2D] bool - (let [t texture] - (texture-valid?-raw (addr t)))) +(declare-c draw-texture + [texture Texture2D x i32 y i32 tint Color] + "DrawTexture") -(declare unload-texture-raw [texture (Ptr Texture2D)] "flan_rl_unload_texture") +(declare-c draw-texture-v + [texture Texture2D position Vector2 tint Color] + "DrawTextureV") -(defn unload-texture [texture Texture2D] - (let [t texture] - (unload-texture-raw (addr t)))) - -(declare draw-texture-raw - [texture (Ptr Texture2D) x i32 y i32 tint (Ptr Color)] - "flan_rl_draw_texture") - -(defn draw-texture [texture Texture2D x i32 y i32 tint Color] - (let [t texture - c tint] - (draw-texture-raw (addr t) x y (addr c)))) - -(declare draw-texture-v-raw - [texture (Ptr Texture2D) position (Ptr Vector2) tint (Ptr Color)] - "flan_rl_draw_texture_v") - -(defn draw-texture-v [texture Texture2D position Vector2 tint Color] - (let [t texture - p position - c tint] - (draw-texture-v-raw (addr t) (addr p) (addr c)))) - -(declare draw-texture-ex-raw - [texture (Ptr Texture2D) position (Ptr Vector2) rotation f32 scale f32 - tint (Ptr Color)] - "flan_rl_draw_texture_ex") - -(defn draw-texture-ex [texture Texture2D position Vector2 rotation f32 - scale f32 tint Color] - (let [t texture - p position - c tint] - (draw-texture-ex-raw (addr t) (addr p) rotation scale (addr c)))) +(declare-c draw-texture-ex [texture Texture2D position Vector2 rotation f32 + scale f32 tint Color] "DrawTextureEx") ;; A negative source width or height flips the sprite, which is how a sheet is ;; drawn facing the other way without a second image. -(declare draw-texture-rec-raw - [texture (Ptr Texture2D) source (Ptr Rectangle) position (Ptr Vector2) - tint (Ptr Color)] - "flan_rl_draw_texture_rec") - -(defn draw-texture-rec [texture Texture2D source Rectangle position Vector2 - tint Color] - (let [t texture - s source - p position - c tint] - (draw-texture-rec-raw (addr t) (addr s) (addr p) (addr c)))) +(declare-c draw-texture-rec [texture Texture2D source Rectangle position Vector2 + tint Color] "DrawTextureRec") ;; ── Images ────────────────────────────────────────────────────────── ;; @@ -410,101 +297,55 @@ ;; level too, so a caller can see which ones change what they are given. (defstruct Image [data (Ptr u8) width i32 height i32 mipmaps i32 format i32]) -(declare load-image-raw [path string out (Ptr Image)] "flan_rl_load_image") - -(defn load-image [path string] Image - (let [i (Image {})] - (load-image-raw path (addr i)) - i)) +(declare-c load-image [path string] Image "LoadImage") ;; raylib 5.5 spells this IsImageValid. IsImageReady, which older code calls, ;; does not exist here — the same rename that took IsTextureReady. -(declare image-valid?-raw [image (Ptr Image)] bool "flan_rl_is_image_valid") - -(defn image-valid? [image Image] bool - (let [i image] - (image-valid?-raw (addr i)))) +(declare-c image-valid? [image Image] bool "IsImageValid") ;; By value, as raylib has it. The caller's copy is dangling afterwards — ;; `data` pointed at the buffer this just freed — so an Image is used or ;; unloaded, never both. -(declare unload-image-raw [image (Ptr Image)] "flan_rl_unload_image") - -(defn unload-image [image Image] - (let [i image] - (unload-image-raw (addr i)))) +(declare-c unload-image [image Image] "UnloadImage") ;; The format is taken from the path's extension, so ".png" writes a PNG. ;; False means it could not be written. -(declare export-image-raw [image (Ptr Image) path string] bool - "flan_rl_export_image") +(declare-c export-image [image Image path string] bool "ExportImage") -(defn export-image [image Image path string] bool - (let [i image] - (export-image-raw (addr i) path))) - -(declare gen-image-color-raw - [width i32 height i32 color (Ptr Color) out (Ptr Image)] - "flan_rl_gen_image_color") - -(defn gen-image-color [width i32 height i32 color Color] Image - (let [c color - i (Image {})] - (gen-image-color-raw width height (addr c) (addr i)) - i)) +(declare-c gen-image-color + [width i32 height i32 color Color] Image + "GenImageColor") ;; Bicubic, so the pixels that come out are interpolated and only the new ;; width and height are exactly predictable. image-resize-nn is the ;; nearest-neighbour one, and it is the one to reach for when the colours ;; have to survive. -(declare image-resize [image (Ptr Image) width i32 height i32] - "flan_rl_image_resize") -(declare image-resize-nn [image (Ptr Image) width i32 height i32] - "flan_rl_image_resize_nn") +(declare-c image-resize + [image (Ptr Image) width i32 height i32] + "ImageResize") +(declare-c image-resize-nn + [image (Ptr Image) width i32 height i32] + "ImageResizeNN") -(declare image-crop-raw [image (Ptr Image) crop (Ptr Rectangle)] - "flan_rl_image_crop") +(declare-c image-crop [image (Ptr Image) crop Rectangle] "ImageCrop") -(defn image-crop [image (Ptr Image) crop Rectangle] - (let [r crop] - (image-crop-raw image (addr r)))) +(declare-c image-flip-horizontal [image (Ptr Image)] "ImageFlipHorizontal") +(declare-c image-flip-vertical [image (Ptr Image)] "ImageFlipVertical") -(declare image-flip-horizontal [image (Ptr Image)] - "flan_rl_image_flip_horizontal") -(declare image-flip-vertical [image (Ptr Image)] - "flan_rl_image_flip_vertical") - -(declare image-draw-pixel-raw - [image (Ptr Image) x i32 y i32 color (Ptr Color)] - "flan_rl_image_draw_pixel") - -(defn image-draw-pixel [image (Ptr Image) x i32 y i32 color Color] - (let [c color] - (image-draw-pixel-raw image x y (addr c)))) +(declare-c image-draw-pixel + [image (Ptr Image) x i32 y i32 color Color] + "ImageDrawPixel") ;; Out of bounds is not an error: raylib logs a warning and hands back a ;; transparent black, so a caller that is off by one gets zeroes rather than ;; somebody else's memory. -(declare get-image-color-raw - [image (Ptr Image) x i32 y i32 out (Ptr Color)] - "flan_rl_get_image_color") - -(defn get-image-color [image Image x i32 y i32] Color - (let [i image - c (Color {})] - (get-image-color-raw (addr i) x y (addr c)) - c)) +(declare-c get-image-color [image Image x i32 y i32] Color "GetImageColor") ;; The one call in this section that does need a GL context — it uploads. An ;; image loaded and edited on the CPU becomes something draw-texture can use. -(declare load-texture-from-image-raw [image (Ptr Image) out (Ptr Texture2D)] - "flan_rl_load_texture_from_image") - -(defn load-texture-from-image [image Image] Texture2D - (let [i image - t (Texture2D {})] - (load-texture-from-image-raw (addr i) (addr t)) - t)) +(declare-c load-texture-from-image + [image Image] Texture2D + "LoadTextureFromImage") ;; ── Shapes ────────────────────────────────────────────────────────── ;; @@ -522,185 +363,92 @@ ;; and draws nonsense, so this was read off the library with nm rather than ;; remembered. -(declare draw-pixel-raw [x i32 y i32 color (Ptr Color)] "flan_rl_draw_pixel") +(declare-c draw-pixel [x i32 y i32 color Color] "DrawPixel") -(defn draw-pixel [x i32 y i32 color Color] - (let [c color] (draw-pixel-raw x y (addr c)))) +(declare-c draw-pixel-v [position Vector2 color Color] "DrawPixelV") -(declare draw-pixel-v-raw [position (Ptr Vector2) color (Ptr Color)] - "flan_rl_draw_pixel_v") +(declare-c draw-line [x1 i32 y1 i32 x2 i32 y2 i32 color Color] "DrawLine") -(defn draw-pixel-v [position Vector2 color Color] - (let [p position c color] (draw-pixel-v-raw (addr p) (addr c)))) - -(declare draw-line-raw [x1 i32 y1 i32 x2 i32 y2 i32 color (Ptr Color)] - "flan_rl_draw_line") - -(defn draw-line [x1 i32 y1 i32 x2 i32 y2 i32 color Color] - (let [c color] (draw-line-raw x1 y1 x2 y2 (addr c)))) - -(declare draw-line-v-raw - [start (Ptr Vector2) end (Ptr Vector2) color (Ptr Color)] - "flan_rl_draw_line_v") - -(defn draw-line-v [start Vector2 end Vector2 color Color] - (let [a start b end c color] (draw-line-v-raw (addr a) (addr b) (addr c)))) +(declare-c draw-line-v [start Vector2 end Vector2 color Color] "DrawLineV") ;; The thick one is built from triangles rather than GL lines, which is why it ;; is a separate call and not a parameter on the one above. -(declare draw-line-ex-raw - [start (Ptr Vector2) end (Ptr Vector2) thick f32 color (Ptr Color)] - "flan_rl_draw_line_ex") +(declare-c draw-line-ex + [start Vector2 end Vector2 thick f32 color Color] + "DrawLineEx") -(defn draw-line-ex [start Vector2 end Vector2 thick f32 color Color] - (let [a start b end c color] - (draw-line-ex-raw (addr a) (addr b) thick (addr c)))) +(declare-c draw-circle [x i32 y i32 radius f32 color Color] "DrawCircle") -(declare draw-circle-raw [x i32 y i32 radius f32 color (Ptr Color)] - "flan_rl_draw_circle") +(declare-c draw-circle-v + [center Vector2 radius f32 color Color] + "DrawCircleV") -(defn draw-circle [x i32 y i32 radius f32 color Color] - (let [c color] (draw-circle-raw x y radius (addr c)))) +(declare-c draw-circle-lines + [x i32 y i32 radius f32 color Color] + "DrawCircleLines") -(declare draw-circle-v-raw - [center (Ptr Vector2) radius f32 color (Ptr Color)] "flan_rl_draw_circle_v") - -(defn draw-circle-v [center Vector2 radius f32 color Color] - (let [p center c color] (draw-circle-v-raw (addr p) radius (addr c)))) - -(declare draw-circle-lines-raw [x i32 y i32 radius f32 color (Ptr Color)] - "flan_rl_draw_circle_lines") - -(defn draw-circle-lines [x i32 y i32 radius f32 color Color] - (let [c color] (draw-circle-lines-raw x y radius (addr c)))) - -(declare draw-circle-lines-v-raw - [center (Ptr Vector2) radius f32 color (Ptr Color)] - "flan_rl_draw_circle_lines_v") - -(defn draw-circle-lines-v [center Vector2 radius f32 color Color] - (let [p center c color] (draw-circle-lines-v-raw (addr p) radius (addr c)))) +(declare-c draw-circle-lines-v + [center Vector2 radius f32 color Color] + "DrawCircleLinesV") ;; Two radii, horizontal then vertical. Equal radii is a circle, so a wrapper ;; that exchanged them would be invisible unless they differ — which is why ;; sand.flan's ellipse is deliberately wider than it is tall. -(declare draw-ellipse-raw - [x i32 y i32 radius-h f32 radius-v f32 color (Ptr Color)] - "flan_rl_draw_ellipse") +(declare-c draw-ellipse + [x i32 y i32 radius-h f32 radius-v f32 color Color] + "DrawEllipse") -(defn draw-ellipse [x i32 y i32 radius-h f32 radius-v f32 color Color] - (let [c color] (draw-ellipse-raw x y radius-h radius-v (addr c)))) - -(declare draw-ellipse-lines-raw - [x i32 y i32 radius-h f32 radius-v f32 color (Ptr Color)] - "flan_rl_draw_ellipse_lines") - -(defn draw-ellipse-lines [x i32 y i32 radius-h f32 radius-v f32 color Color] - (let [c color] (draw-ellipse-lines-raw x y radius-h radius-v (addr c)))) +(declare-c draw-ellipse-lines + [x i32 y i32 radius-h f32 radius-v f32 color Color] + "DrawEllipseLines") ;; Angles are degrees, clockwise from the +x axis, and `segments` is how many ;; straight pieces the arc is made of — 0 lets raylib pick from the radius. -(declare draw-ring-raw - [center (Ptr Vector2) inner f32 outer f32 start f32 end f32 - segments i32 color (Ptr Color)] - "flan_rl_draw_ring") +(declare-c draw-ring [center Vector2 inner f32 outer f32 start f32 end f32 + segments i32 color Color] "DrawRing") -(defn draw-ring [center Vector2 inner f32 outer f32 start f32 end f32 - segments i32 color Color] - (let [p center c color] - (draw-ring-raw (addr p) inner outer start end segments (addr c)))) - -(declare draw-ring-lines-raw - [center (Ptr Vector2) inner f32 outer f32 start f32 end f32 - segments i32 color (Ptr Color)] - "flan_rl_draw_ring_lines") - -(defn draw-ring-lines [center Vector2 inner f32 outer f32 start f32 end f32 - segments i32 color Color] - (let [p center c color] - (draw-ring-lines-raw (addr p) inner outer start end segments (addr c)))) +(declare-c draw-ring-lines [center Vector2 inner f32 outer f32 start f32 end f32 + segments i32 color Color] "DrawRingLines") ;; Counter-clockwise, and raylib means it: the clockwise winding is culled and ;; draws nothing at all, which looks exactly like a broken binding. -(declare draw-triangle-raw - [v1 (Ptr Vector2) v2 (Ptr Vector2) v3 (Ptr Vector2) color (Ptr Color)] - "flan_rl_draw_triangle") +(declare-c draw-triangle + [v1 Vector2 v2 Vector2 v3 Vector2 color Color] + "DrawTriangle") -(defn draw-triangle [v1 Vector2 v2 Vector2 v3 Vector2 color Color] - (let [a v1 b v2 d v3 c color] - (draw-triangle-raw (addr a) (addr b) (addr d) (addr c)))) +(declare-c draw-triangle-lines + [v1 Vector2 v2 Vector2 v3 Vector2 color Color] + "DrawTriangleLines") -(declare draw-triangle-lines-raw - [v1 (Ptr Vector2) v2 (Ptr Vector2) v3 (Ptr Vector2) color (Ptr Color)] - "flan_rl_draw_triangle_lines") +(declare-c draw-rectangle-v + [position Vector2 size Vector2 color Color] + "DrawRectangleV") -(defn draw-triangle-lines [v1 Vector2 v2 Vector2 v3 Vector2 color Color] - (let [a v1 b v2 d v3 c color] - (draw-triangle-lines-raw (addr a) (addr b) (addr d) (addr c)))) +(declare-c draw-rectangle-rec [rec Rectangle color Color] "DrawRectangleRec") -(declare draw-rectangle-v-raw - [position (Ptr Vector2) size (Ptr Vector2) color (Ptr Color)] - "flan_rl_draw_rectangle_v") - -(defn draw-rectangle-v [position Vector2 size Vector2 color Color] - (let [p position s size c color] - (draw-rectangle-v-raw (addr p) (addr s) (addr c)))) - -(declare draw-rectangle-rec-raw [rec (Ptr Rectangle) color (Ptr Color)] - "flan_rl_draw_rectangle_rec") - -(defn draw-rectangle-rec [rec Rectangle color Color] - (let [r rec c color] (draw-rectangle-rec-raw (addr r) (addr c)))) - -(declare draw-rectangle-lines-raw - [x i32 y i32 width i32 height i32 color (Ptr Color)] - "flan_rl_draw_rectangle_lines") - -(defn draw-rectangle-lines [x i32 y i32 width i32 height i32 color Color] - (let [c color] (draw-rectangle-lines-raw x y width height (addr c)))) +(declare-c draw-rectangle-lines + [x i32 y i32 width i32 height i32 color Color] + "DrawRectangleLines") ;; The one-pixel outline above is drawn with GL lines and sits *on* the ;; rectangle's edge; this one is drawn with quads and sits inside it, so the ;; two do not agree at thickness 1 and that is raylib's doing, not a bug here. -(declare draw-rectangle-lines-ex-raw - [rec (Ptr Rectangle) thick f32 color (Ptr Color)] - "flan_rl_draw_rectangle_lines_ex") - -(defn draw-rectangle-lines-ex [rec Rectangle thick f32 color Color] - (let [r rec c color] (draw-rectangle-lines-ex-raw (addr r) thick (addr c)))) +(declare-c draw-rectangle-lines-ex + [rec Rectangle thick f32 color Color] + "DrawRectangleLinesEx") ;; `roundness` is 0 to 1 as a fraction of the shorter side, so 0 is a plain ;; rectangle and 1 is a stadium. -(declare draw-rectangle-rounded-raw - [rec (Ptr Rectangle) roundness f32 segments i32 color (Ptr Color)] - "flan_rl_draw_rectangle_rounded") - -(defn draw-rectangle-rounded [rec Rectangle roundness f32 segments i32 - color Color] - (let [r rec c color] - (draw-rectangle-rounded-raw (addr r) roundness segments (addr c)))) +(declare-c draw-rectangle-rounded [rec Rectangle roundness f32 segments i32 + color Color] "DrawRectangleRounded") ;; No thickness here — see the section note. The `-ex` form below is the one ;; that takes it. -(declare draw-rectangle-rounded-lines-raw - [rec (Ptr Rectangle) roundness f32 segments i32 color (Ptr Color)] - "flan_rl_draw_rectangle_rounded_lines") +(declare-c draw-rectangle-rounded-lines [rec Rectangle roundness f32 segments i32 + color Color] "DrawRectangleRoundedLines") -(defn draw-rectangle-rounded-lines [rec Rectangle roundness f32 segments i32 - color Color] - (let [r rec c color] - (draw-rectangle-rounded-lines-raw (addr r) roundness segments (addr c)))) - -(declare draw-rectangle-rounded-lines-ex-raw - [rec (Ptr Rectangle) roundness f32 segments i32 thick f32 - color (Ptr Color)] - "flan_rl_draw_rectangle_rounded_lines_ex") - -(defn draw-rectangle-rounded-lines-ex [rec Rectangle roundness f32 - segments i32 thick f32 color Color] - (let [r rec c color] - (draw-rectangle-rounded-lines-ex-raw (addr r) roundness segments thick - (addr c)))) +(declare-c draw-rectangle-rounded-lines-ex [rec Rectangle roundness f32 + segments i32 thick f32 color Color] "DrawRectangleRoundedLinesEx") ;; ── Text ──────────────────────────────────────────────────────────── ;; @@ -718,14 +466,11 @@ ;; load-font, load-font-ex, unload-font, get-font-default, draw-text-ex and ;; measure-text-ex are all absent rather than half-done. -(declare draw-text-raw - [text string x i32 y i32 font-size i32 color (Ptr Color)] - "flan_rl_draw_text") +(declare-c draw-text + [text string x i32 y i32 font-size i32 color Color] + "DrawText") -(defn draw-text [text string x i32 y i32 font-size i32 color Color] - (let [c color] (draw-text-raw text x y font-size (addr c)))) - -(declare measure-text [text string font-size i32] i32 "flan_rl_measure_text") +(declare-c measure-text [text string font-size i32] i32 "MeasureText") ;; ── Timing and window state ───────────────────────────────────────── ;; @@ -734,7 +479,7 @@ ;; delta the last frame took, in seconds, which is what a simulation should ;; scale by instead of assuming the target fps was met. -(declare get-frame-time [] f32 "flan_rl_get_frame_time") -(declare get-time [] f64 "flan_rl_get_time") -(declare get-screen-width [] i32 "flan_rl_get_screen_width") -(declare get-screen-height [] i32 "flan_rl_get_screen_height") +(declare-c get-frame-time [] f32 "GetFrameTime") +(declare-c get-time [] f64 "GetTime") +(declare-c get-screen-width [] i32 "GetScreenWidth") +(declare-c get-screen-height [] i32 "GetScreenHeight") diff --git a/vendor/raylib/shim.c b/vendor/raylib/shim.c deleted file mode 100644 index b9f9e1e..0000000 --- a/vendor/raylib/shim.c +++ /dev/null @@ -1,476 +0,0 @@ -/* The C half of the raylib binding: one wrapper per `declare` in raylib.flan. - * - * The wrappers exist so that no aggregate is ever passed or returned across - * the Flan/C boundary. raylib takes Color by value and returns Vector2 by - * value, and a small aggregate is passed differently on x86-64 (<2 x float>, - * i32), on arm64, and on wasm32. Here, clang classifies each one correctly for - * whichever target the build is for; in the Flan backend it would be three - * conventions to reimplement. Everything below therefore trades in scalars and - * pointers only — see raylib.flan. - * - * raylib's own headers are not needed and not used: these prototypes are the - * declarations, so the build has no dependency on raylib-devel being - * installed, only on the shared library being linkable. - */ - -#include -#include -#include -#include - -typedef struct { float x, y; } Vector2; -typedef struct { unsigned char r, g, b, a; } Color; -typedef struct { unsigned int id; int width, height, mipmaps, format; } Texture2D; -typedef struct { float x, y, width, height; } Rectangle; -typedef struct { Vector2 offset, target; float rotation, zoom; } Camera2D; - -extern void InitWindow(int width, int height, const char *title); -extern void CloseWindow(void); -extern bool WindowShouldClose(void); -extern void SetTargetFPS(int fps); -extern void SetTraceLogLevel(int level); -extern bool IsKeyPressed(int key); -extern bool IsKeyDown(int key); -extern bool IsKeyReleased(int key); -extern bool IsMouseButtonPressed(int button); -extern bool IsMouseButtonDown(int button); -extern bool IsMouseButtonReleased(int button); -extern Vector2 GetMousePosition(void); -extern Color GetColor(unsigned int hex); -extern void BeginDrawing(void); -extern void EndDrawing(void); -extern void DrawFPS(int x, int y); -extern void ClearBackground(Color color); -extern void DrawRectangle(int x, int y, int width, int height, Color color); -extern void SetShapesTexture(Texture2D texture, Rectangle source); -extern Texture2D GetShapesTexture(void); -extern Rectangle GetShapesTextureRectangle(void); -extern Rectangle GetCollisionRec(Rectangle a, Rectangle b); -extern Texture2D LoadTexture(const char *fileName); -extern bool IsTextureValid(Texture2D texture); -extern void UnloadTexture(Texture2D texture); -extern void DrawTexture(Texture2D texture, int posX, int posY, Color tint); -extern void DrawTextureV(Texture2D texture, Vector2 position, Color tint); -extern void DrawTextureEx(Texture2D texture, Vector2 position, float rotation, - float scale, Color tint); -extern void DrawTextureRec(Texture2D texture, Rectangle source, - Vector2 position, Color tint); -extern void BeginMode2D(Camera2D camera); -extern void EndMode2D(void); -extern Vector2 GetScreenToWorld2D(Vector2 position, Camera2D camera); -extern Vector2 GetWorldToScreen2D(Vector2 position, Camera2D camera); -extern bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2); -extern bool CheckCollisionCircles(Vector2 c1, float r1, Vector2 c2, float r2); -extern bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec); -extern bool CheckCollisionCircleLine(Vector2 center, float radius, - Vector2 p1, Vector2 p2); -extern bool CheckCollisionPointRec(Vector2 point, Rectangle rec); -extern bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius); -extern bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, - Vector2 p3); -extern bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, - int threshold); -extern bool CheckCollisionPointPoly(Vector2 point, const Vector2 *points, - int pointCount); -extern bool CheckCollisionLines(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, - Vector2 *collisionPoint); - -/* A Flan string arrives as ptr+len and is not NUL-terminated, so a C API that - * wants a C string needs a copy. Two callers want one: the window title and a - * texture's file path. Each passes a buffer big enough for what it is — 256 - * for a title, PATH_MAX for a path — and truncating is better than reading - * past the end. A truncated path fails to open and LoadTexture returns an id - * of 0, which is what texture-valid? is for. */ -static const char *cstr(const char *p, long long n, char *buf, size_t cap) { - size_t k = (size_t)n < cap - 1 ? (size_t)n : cap - 1; - memcpy(buf, p, k); - buf[k] = '\0'; - return buf; -} - -void flan_rl_init_window(int width, int height, const char *title, long long n) { - char buf[256]; - InitWindow(width, height, cstr(title, n, buf, sizeof buf)); -} - -void flan_rl_close_window(void) { CloseWindow(); } -bool flan_rl_window_should_close(void) { return WindowShouldClose(); } -void flan_rl_set_target_fps(int fps) { SetTargetFPS(fps); } -void flan_rl_set_trace_log_level(int l) { SetTraceLogLevel(l); } - -bool flan_rl_is_key_pressed(int key) { return IsKeyPressed(key); } -bool flan_rl_is_key_down(int key) { return IsKeyDown(key); } -bool flan_rl_is_key_released(int key) { return IsKeyReleased(key); } - -bool flan_rl_is_mouse_button_pressed(int b) { return IsMouseButtonPressed(b); } -bool flan_rl_is_mouse_button_down(int b) { return IsMouseButtonDown(b); } -bool flan_rl_is_mouse_button_released(int b) { return IsMouseButtonReleased(b); } - -void flan_rl_get_mouse_position(Vector2 *out) { *out = GetMousePosition(); } - -void flan_rl_get_color(unsigned int hex, Color *out) { *out = GetColor(hex); } - -void flan_rl_begin_drawing(void) { BeginDrawing(); } -void flan_rl_end_drawing(void) { EndDrawing(); } -void flan_rl_draw_fps(int x, int y) { DrawFPS(x, y); } - -void flan_rl_clear_background(const Color *color) { ClearBackground(*color); } - -void flan_rl_draw_rectangle(int x, int y, int width, int height, - const Color *color) { - DrawRectangle(x, y, width, height, *color); -} - -void flan_rl_set_shapes_texture(const Texture2D *texture, const Rectangle *source) { - SetShapesTexture(*texture, *source); -} - -void flan_rl_get_shapes_texture(Texture2D *out) { *out = GetShapesTexture(); } - -void flan_rl_get_shapes_texture_rectangle(Rectangle *out) { - *out = GetShapesTextureRectangle(); -} - -void flan_rl_get_collision_rec(const Rectangle *a, const Rectangle *b, - Rectangle *out) { - *out = GetCollisionRec(*a, *b); -} - -void flan_rl_load_texture(const char *path, long long n, Texture2D *out) { - char buf[PATH_MAX]; - *out = LoadTexture(cstr(path, n, buf, sizeof buf)); -} - -bool flan_rl_is_texture_valid(const Texture2D *texture) { - return IsTextureValid(*texture); -} - -void flan_rl_unload_texture(const Texture2D *texture) { UnloadTexture(*texture); } - -void flan_rl_draw_texture(const Texture2D *texture, int x, int y, - const Color *tint) { - DrawTexture(*texture, x, y, *tint); -} - -void flan_rl_draw_texture_v(const Texture2D *texture, const Vector2 *position, - const Color *tint) { - DrawTextureV(*texture, *position, *tint); -} - -void flan_rl_draw_texture_ex(const Texture2D *texture, const Vector2 *position, - float rotation, float scale, const Color *tint) { - DrawTextureEx(*texture, *position, rotation, scale, *tint); -} - -void flan_rl_draw_texture_rec(const Texture2D *texture, const Rectangle *source, - const Vector2 *position, const Color *tint) { - DrawTextureRec(*texture, *source, *position, *tint); -} - -void flan_rl_begin_mode_2d(const Camera2D *camera) { BeginMode2D(*camera); } -void flan_rl_end_mode_2d(void) { EndMode2D(); } - -void flan_rl_get_screen_to_world_2d(const Vector2 *position, - const Camera2D *camera, Vector2 *out) { - *out = GetScreenToWorld2D(*position, *camera); -} - -void flan_rl_get_world_to_screen_2d(const Vector2 *position, - const Camera2D *camera, Vector2 *out) { - *out = GetWorldToScreen2D(*position, *camera); -} - -bool flan_rl_check_collision_recs(const Rectangle *a, const Rectangle *b) { - return CheckCollisionRecs(*a, *b); -} - -bool flan_rl_check_collision_circles(const Vector2 *c1, float r1, - const Vector2 *c2, float r2) { - return CheckCollisionCircles(*c1, r1, *c2, r2); -} - -bool flan_rl_check_collision_circle_rec(const Vector2 *center, float radius, - const Rectangle *rec) { - return CheckCollisionCircleRec(*center, radius, *rec); -} - -bool flan_rl_check_collision_circle_line(const Vector2 *center, float radius, - const Vector2 *p1, const Vector2 *p2) { - return CheckCollisionCircleLine(*center, radius, *p1, *p2); -} - -bool flan_rl_check_collision_point_rec(const Vector2 *point, const Rectangle *rec) { - return CheckCollisionPointRec(*point, *rec); -} - -bool flan_rl_check_collision_point_circle(const Vector2 *point, - const Vector2 *center, float radius) { - return CheckCollisionPointCircle(*point, *center, radius); -} - -bool flan_rl_check_collision_point_triangle(const Vector2 *point, const Vector2 *a, - const Vector2 *b, const Vector2 *c) { - return CheckCollisionPointTriangle(*point, *a, *b, *c); -} - -bool flan_rl_check_collision_point_line(const Vector2 *point, const Vector2 *p1, - const Vector2 *p2, int threshold) { - return CheckCollisionPointLine(*point, *p1, *p2, threshold); -} - -/* A Flan slice arrives as ptr+len, the same shape a string does. raylib wants - * an int count, and a polygon with more than INT_MAX points is not a thing - * that happens; the clamp is there so the conversion is not silent. */ -bool flan_rl_check_collision_point_poly(const Vector2 *point, - const Vector2 *points, long long n) { - if (n > INT_MAX) n = INT_MAX; - return CheckCollisionPointPoly(*point, points, (int)n); -} - -bool flan_rl_check_collision_lines(const Vector2 *a1, const Vector2 *a2, - const Vector2 *b1, const Vector2 *b2, - Vector2 *out) { - return CheckCollisionLines(*a1, *a2, *b1, *b2, out); -} - -/* ── Images ───────────────────────────────────────────────────────── - * - * An Image is pixels in RAM, so all of this runs with no window and no GL - * context — which is why it is the part of the package that a headless test - * can actually assert rather than merely link. `data` is the pixel buffer - * raylib owns; `format` is a PixelFormat enum and GenImageColor makes 7 - * (uncompressed R8G8B8A8). - * - * raylib 5.5 spells the predicate IsImageValid. IsImageReady, which the 5.1 - * header still had, is gone — checked with nm -D, not remembered. - */ -typedef struct { void *data; int width, height, mipmaps, format; } Image; - -extern Image LoadImage(const char *fileName); -extern bool IsImageValid(Image image); -extern void UnloadImage(Image image); -extern bool ExportImage(Image image, const char *fileName); -extern Image GenImageColor(int width, int height, Color color); -extern void ImageResize(Image *image, int newWidth, int newHeight); -extern void ImageResizeNN(Image *image, int newWidth, int newHeight); -extern void ImageCrop(Image *image, Rectangle crop); -extern void ImageFlipHorizontal(Image *image); -extern void ImageFlipVertical(Image *image); -extern void ImageDrawPixel(Image *dst, int posX, int posY, Color color); -extern Color GetImageColor(Image image, int x, int y); -extern Texture2D LoadTextureFromImage(Image image); - -void flan_rl_load_image(const char *path, long long n, Image *out) { - char buf[PATH_MAX]; - *out = LoadImage(cstr(path, n, buf, sizeof buf)); -} - -bool flan_rl_is_image_valid(const Image *image) { return IsImageValid(*image); } -void flan_rl_unload_image(const Image *image) { UnloadImage(*image); } - -bool flan_rl_export_image(const Image *image, const char *path, long long n) { - char buf[PATH_MAX]; - return ExportImage(*image, cstr(path, n, buf, sizeof buf)); -} - -void flan_rl_gen_image_color(int width, int height, const Color *color, - Image *out) { - *out = GenImageColor(width, height, *color); -} - -void flan_rl_image_resize(Image *image, int w, int h) { ImageResize(image, w, h); } -void flan_rl_image_resize_nn(Image *image, int w, int h) { ImageResizeNN(image, w, h); } - -void flan_rl_image_crop(Image *image, const Rectangle *crop) { - ImageCrop(image, *crop); -} - -void flan_rl_image_flip_horizontal(Image *image) { ImageFlipHorizontal(image); } -void flan_rl_image_flip_vertical(Image *image) { ImageFlipVertical(image); } - -void flan_rl_image_draw_pixel(Image *dst, int x, int y, const Color *color) { - ImageDrawPixel(dst, x, y, *color); -} - -void flan_rl_get_image_color(const Image *image, int x, int y, Color *out) { - *out = GetImageColor(*image, x, y); -} - -void flan_rl_load_texture_from_image(const Image *image, Texture2D *out) { - *out = LoadTextureFromImage(*image); -} - -/* ── Shapes, text and timing ───────────────────────────────────────── - * - * All of the drawing below needs a GL context and therefore a window, so none - * of it can be in the acceptance table — it is exercised by running sand.flan - * and looking. The three prototypes most likely to be remembered wrong were - * checked against nm -D on libraylib.so.550 rather than against a header: - * raylib 5.5 moved the line thickness off DrawRectangleRoundedLines onto - * DrawRectangleRoundedLinesEx, so the four-argument form here is the 5.5 one - * and not the 5.1 one. - * - * MeasureText, GetFrameTime, GetTime and GetScreenWidth/Height need no GL - * context but do need InitWindow: the first reads the default font, which - * only InitWindow loads, and the others read window state. Headless they all - * answer 0 — measured, not assumed — so they are no more assertable than the - * drawing is. - */ - -extern void DrawPixel(int posX, int posY, Color color); -extern void DrawPixelV(Vector2 position, Color color); -extern void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, - Color color); -extern void DrawLineV(Vector2 startPos, Vector2 endPos, Color color); -extern void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color); -extern void DrawCircle(int centerX, int centerY, float radius, Color color); -extern void DrawCircleV(Vector2 center, float radius, Color color); -extern void DrawCircleLines(int centerX, int centerY, float radius, Color color); -extern void DrawCircleLinesV(Vector2 center, float radius, Color color); -extern void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, - Color color); -extern void DrawEllipseLines(int centerX, int centerY, float radiusH, - float radiusV, Color color); -extern void DrawRing(Vector2 center, float innerRadius, float outerRadius, - float startAngle, float endAngle, int segments, Color color); -extern void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, - float startAngle, float endAngle, int segments, - Color color); -extern void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color); -extern void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color); -extern void DrawRectangleV(Vector2 position, Vector2 size, Color color); -extern void DrawRectangleRec(Rectangle rec, Color color); -extern void DrawRectangleLines(int posX, int posY, int width, int height, - Color color); -extern void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color); -extern void DrawRectangleRounded(Rectangle rec, float roundness, int segments, - Color color); -extern void DrawRectangleRoundedLines(Rectangle rec, float roundness, - int segments, Color color); -extern void DrawRectangleRoundedLinesEx(Rectangle rec, float roundness, - int segments, float lineThick, - Color color); -extern void DrawText(const char *text, int posX, int posY, int fontSize, - Color color); -extern int MeasureText(const char *text, int fontSize); -extern float GetFrameTime(void); -extern double GetTime(void); -extern int GetScreenWidth(void); -extern int GetScreenHeight(void); - -void flan_rl_draw_pixel(int x, int y, const Color *c) { DrawPixel(x, y, *c); } - -void flan_rl_draw_pixel_v(const Vector2 *p, const Color *c) { - DrawPixelV(*p, *c); -} - -void flan_rl_draw_line(int x1, int y1, int x2, int y2, const Color *c) { - DrawLine(x1, y1, x2, y2, *c); -} - -void flan_rl_draw_line_v(const Vector2 *a, const Vector2 *b, const Color *c) { - DrawLineV(*a, *b, *c); -} - -void flan_rl_draw_line_ex(const Vector2 *a, const Vector2 *b, float thick, - const Color *c) { - DrawLineEx(*a, *b, thick, *c); -} - -void flan_rl_draw_circle(int x, int y, float radius, const Color *c) { - DrawCircle(x, y, radius, *c); -} - -void flan_rl_draw_circle_v(const Vector2 *center, float radius, const Color *c) { - DrawCircleV(*center, radius, *c); -} - -void flan_rl_draw_circle_lines(int x, int y, float radius, const Color *c) { - DrawCircleLines(x, y, radius, *c); -} - -void flan_rl_draw_circle_lines_v(const Vector2 *center, float radius, - const Color *c) { - DrawCircleLinesV(*center, radius, *c); -} - -void flan_rl_draw_ellipse(int x, int y, float rh, float rv, const Color *c) { - DrawEllipse(x, y, rh, rv, *c); -} - -void flan_rl_draw_ellipse_lines(int x, int y, float rh, float rv, const Color *c) { - DrawEllipseLines(x, y, rh, rv, *c); -} - -void flan_rl_draw_ring(const Vector2 *center, float inner, float outer, - float start, float end, int segments, const Color *c) { - DrawRing(*center, inner, outer, start, end, segments, *c); -} - -void flan_rl_draw_ring_lines(const Vector2 *center, float inner, float outer, - float start, float end, int segments, - const Color *c) { - DrawRingLines(*center, inner, outer, start, end, segments, *c); -} - -void flan_rl_draw_triangle(const Vector2 *a, const Vector2 *b, const Vector2 *d, - const Color *c) { - DrawTriangle(*a, *b, *d, *c); -} - -void flan_rl_draw_triangle_lines(const Vector2 *a, const Vector2 *b, - const Vector2 *d, const Color *c) { - DrawTriangleLines(*a, *b, *d, *c); -} - -void flan_rl_draw_rectangle_v(const Vector2 *position, const Vector2 *size, - const Color *c) { - DrawRectangleV(*position, *size, *c); -} - -void flan_rl_draw_rectangle_rec(const Rectangle *rec, const Color *c) { - DrawRectangleRec(*rec, *c); -} - -void flan_rl_draw_rectangle_lines(int x, int y, int w, int h, const Color *c) { - DrawRectangleLines(x, y, w, h, *c); -} - -void flan_rl_draw_rectangle_lines_ex(const Rectangle *rec, float thick, - const Color *c) { - DrawRectangleLinesEx(*rec, thick, *c); -} - -void flan_rl_draw_rectangle_rounded(const Rectangle *rec, float roundness, - int segments, const Color *c) { - DrawRectangleRounded(*rec, roundness, segments, *c); -} - -/* Four arguments, not five: 5.5's DrawRectangleRoundedLines has no thickness - * and the Ex variant below is where it went. Getting this wrong links fine. */ -void flan_rl_draw_rectangle_rounded_lines(const Rectangle *rec, float roundness, - int segments, const Color *c) { - DrawRectangleRoundedLines(*rec, roundness, segments, *c); -} - -void flan_rl_draw_rectangle_rounded_lines_ex(const Rectangle *rec, - float roundness, int segments, - float thick, const Color *c) { - DrawRectangleRoundedLinesEx(*rec, roundness, segments, thick, *c); -} - -void flan_rl_draw_text(const char *text, long long n, int x, int y, - int font_size, const Color *c) { - char buf[512]; - DrawText(cstr(text, n, buf, sizeof buf), x, y, font_size, *c); -} - -int flan_rl_measure_text(const char *text, long long n, int font_size) { - char buf[512]; - return MeasureText(cstr(text, n, buf, sizeof buf), font_size); -} - -float flan_rl_get_frame_time(void) { return GetFrameTime(); } -double flan_rl_get_time(void) { return GetTime(); } -int flan_rl_get_screen_width(void) { return GetScreenWidth(); } -int flan_rl_get_screen_height(void) { return GetScreenHeight(); }