diff --git a/README.org b/README.org index ee0a1c0..b773813 100644 --- a/README.org +++ b/README.org @@ -11,38 +11,36 @@ on Linux and macOS. ** API +High-level API: +- ~F _display width‿height~ creates a window of the given dimensions + and displays its left operand. ~F~ should be a function returning a + color as an RGB triplet in the (0,1) range, and taking a list of two + elements ~x‿y~, where ~x~ and ~y~ are the pixel coordinates. + +Low-level API: - ~OpenWindow w‿h‿t~ opens a window of width ~w~ and height ~h~, with title ~t~. Returns a window handle. - ~CloseWindow w~ closes a window given its handle ~w~. - ~F _render w~ runs the function ~F~ at each coordinate of the window - ~w~ and set the corresponding pixel color. ~F~ should be a function - returning a color as an RGB triplet in the (0,1) range, and taking a - list of three elements ~x‿y‿t~, where ~x~ and ~y~ are the pixel - coordinates and ~t~ is the time. + ~w~ and set the corresponding pixel color. ~F~ is a function with + the same arguments as for ~_display~. ** Example See [[./example.bqn][example.bqn]]. #+begin_src bqn -f←•Import "fenster.bqn" +f←•Import"fenster.bqn" size←500 -w←f.OpenWindow size‿size‿"bqn-fenster example" - -Rainbow←{𝕊x‿y‿t: +Rainbow←{𝕊x‿y: x‿y↩x‿y÷size - t↩(100|t)÷100 h←(x+y)÷2 f.HSVtoRGB⟨360×h,1,1⟩ } -Rainbow f._render w - -•Delay 3 - -f.CloseWindow w +Rainbow f._display size‿size #+end_src [[./example.png]] diff --git a/example.bqn b/example.bqn index 75d75e2..dfeedd1 100644 --- a/example.bqn +++ b/example.bqn @@ -2,17 +2,10 @@ f←•Import"fenster.bqn" size←500 -w←f.OpenWindow size‿size‿"bqn-fenster example" - -Rainbow←{𝕊x‿y‿t: +Rainbow←{𝕊x‿y: x‿y↩x‿y÷size - t↩(100|t)÷100 h←(x+y)÷2 f.HSVtoRGB⟨360×h,1,1⟩ } -Rainbow f._render w - -•Delay 3 - -f.CloseWindow w +Rainbow f._display size‿size diff --git a/example.png b/example.png index b788c74..7361a87 100644 Binary files a/example.png and b/example.png differ diff --git a/fenster.bqn b/fenster.bqn index 168578c..7580bf6 100644 --- a/fenster.bqn +++ b/fenster.bqn @@ -1,7 +1,10 @@ ⟨ + FensterLoop, OpenWindow, CloseWindow, _render, + RenderArray + _display, Black, White, Gray, @@ -11,6 +14,8 @@ HSVtoRGB ⟩⇐ +## FFI functions + FensterFFI←"lib.so"⊸•FFI fensterOpen←FensterFFI"i8"‿"fenster_open"‿">*:i8" @@ -24,7 +29,12 @@ fensterGetWidth←FensterFFI"u32"‿"fenster_get_width"‿">*:i8" fensterGetHeight←FensterFFI"u32"‿"fenster_get_height"‿">*:i8" fensterGetPixel←FensterFFI"u32"‿"fenster_get_pixel"‿"*:i8"‿"u32"‿"u32" fensterSetPixel←FensterFFI""‿"fenster_set_pixel"‿"*:i8"‿"u32"‿"u32"‿"u32" +fensterSetArray←FensterFFI""‿"fenster_set_array"‿"*:i8"‿"u32"‿"u32"‿"u32"‿"u32"‿"*u32" +## Low-level functions + +# Open a window with given width, height, and title +# Returns the window's handle. OpenWindow←{𝕊w‿h‿t: f←FensterInit⟨w,h,1+≠t,t∾@⟩ FensterOpen f @@ -32,17 +42,19 @@ OpenWindow←{𝕊w‿h‿t: f } +# Close a window. CloseWindow←{𝕊f: FensterClose f FensterLoop f } +# Render a function in the window. +# The function should take a list x‿y of coordinates and return an r‿𝕘‿b color. _render←{Func _𝕣 f: w←FensterGetWidth f h←FensterGetHeight f - t←FensterTime⟨⟩ {𝕊x‿y: - r‿g‿b←Func x‿y‿t + r‿g‿b←Func x‿y c←+´(⌽256⋆↕3)×⌊r‿g‿b×255 FensterSetPixel f‿x‿y‿c }¨⥊(↕w)⋈⌜↕h @@ -50,6 +62,24 @@ _render←{Func _𝕣 f: f } +# Render an array directly. +RenderArray←{buf𝕊f: + bufw‿bufh←≢buf + FensterSetArray⟨f,0,0,bufw,bufh,buf⟩ +} + +## High-level function + +# Open a window, render a function in it, and wait for the user to close it. +_display←{Func _𝕣 w‿h: + win←OpenWindow w‿h‿"bqn-fenster" + Func _render win + ⊢•_while_(¬FensterLoop)win + CloseWindow win +} + +## Utilities + Black←0‿0‿0˙ White←1‿1‿1˙ Gray←{𝕩‿𝕩‿𝕩} diff --git a/lib.c b/lib.c index dc668dd..6c6cea6 100644 --- a/lib.c +++ b/lib.c @@ -29,3 +29,16 @@ uint32_t fenster_get_pixel(struct fenster *f, int i, int j) { void fenster_set_pixel(struct fenster *f, int i, int j, uint32_t color) { fenster_pixel(f, i, j) = color; } + +void fenster_set_array(struct fenster *f, int start_i, int start_j, + int bufwidth, int bufheight, + uint32_t buf[bufwidth * bufheight]) { + int max_i = start_i + bufwidth < f->width ? bufwidth : f->width - start_i; + int max_j = start_j + bufheight < f->height ? bufheight : f->height - start_j; + for (int i = 0; i < max_i; i++) { + for (int j = 0; j < max_j; j++) { + fenster_pixel(f, start_i + i, start_j + j) = buf[j * bufwidth + i]; + } + } + fenster_loop(f); +}