package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.graphics_core/Framebuffer.ml.html
Source file Framebuffer.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (*****************************************************************************) (* Types *) (*****************************************************************************) type pixels = (int32, Bigarray.int32_elt, Bigarray.c_layout) Bigarray.Array2.t type t = { width : int; height : int; pixels : pixels } (*****************************************************************************) (* Colors *) (*****************************************************************************) (* 0xRRGGBB -> 0xFFRRGGBB, the opaque pixel value stored in memory *) let pixel_of_rgb (rgb : int) : int32 = Int32.of_int (0xFF000000 lor rgb) (* 0xAARRGGBB -> 0xRRGGBB (dropping the alpha byte) *) let rgb_of_pixel (pixel : int32) : int = Int32.to_int pixel land 0xFFFFFF let red rgb = (rgb lsr 16) land 0xFF let green rgb = (rgb lsr 8) land 0xFF let blue rgb = rgb land 0xFF let blend ~(src : int) ~(dst : int) ~(alpha : float) : int = (* each channel is a weighted average of the two colors, e.g. with * alpha = 0.25, a quarter of src and three quarters of dst *) let mix s d = int_of_float ((float s *. alpha) +. (float d *. (1. -. alpha)) +. 0.5) in (mix (red src) (red dst) lsl 16) lor (mix (green src) (green dst) lsl 8) lor mix (blue src) (blue dst) (*****************************************************************************) (* Creation *) (*****************************************************************************) let of_pixels (pixels : pixels) : t = { width = Bigarray.Array2.dim2 pixels; height = Bigarray.Array2.dim1 pixels; pixels } let create ~width ~height : t = let pixels = Bigarray.Array2.create Bigarray.int32 Bigarray.c_layout height width in Bigarray.Array2.fill pixels (pixel_of_rgb 0xFFFFFF); of_pixels pixels let clear (fb : t) ~rgb = Bigarray.Array2.fill fb.pixels (pixel_of_rgb rgb) let get_rgb (fb : t) ~x ~y = rgb_of_pixel fb.pixels.{y, x} (*****************************************************************************) (* Spans *) (*****************************************************************************) let fill_span (fb : t) ~y ~x0 ~x1 ~rgb ~alpha = (* clipping: keep only the part of the span that is inside the * framebuffer; e.g. on a 1000-pixel-wide framebuffer, the span * [-20, 30) becomes [0, 30), and [990, 1200) becomes [990, 1000) *) let x0 = max x0 0 and x1 = min x1 fb.width in if y >= 0 && y < fb.height && x0 < x1 && alpha > 0. then if alpha >= 1. then (* opaque: no need to look at what's there, just overwrite; this * is by far the most common case, so it gets a fast path, filling * the whole run at once *) let row = Bigarray.Array2.slice_left fb.pixels y in Bigarray.Array1.fill (Bigarray.Array1.sub row x0 (x1 - x0)) (pixel_of_rgb rgb) else for x = x0 to x1 - 1 do let dst = rgb_of_pixel fb.pixels.{y, x} in fb.pixels.{y, x} <- pixel_of_rgb (blend ~src:rgb ~dst ~alpha) done (* The original, simple version: a span of length 1 *) let plot_simple (fb : t) ~x ~y ~rgb ~alpha = fill_span fb ~y ~x0:x ~x1:(x + 1) ~rgb ~alpha (* claude: optimization (Opti.enabled): fill_span's fast path allocates * two Bigarray views (slice_left, sub) per call; for a single pixel * that's most of the cost, and images, Wu lines, and antialiased edges * plot many single pixels. So write the pixel directly. *) let plot (fb : t) ~x ~y ~rgb ~alpha = if not !Opti.enabled then plot_simple fb ~x ~y ~rgb ~alpha else if x >= 0 && x < fb.width && y >= 0 && y < fb.height && alpha > 0. then fb.pixels.{y, x} <- (if alpha >= 1. then pixel_of_rgb rgb else pixel_of_rgb (blend ~src:rgb ~dst:(rgb_of_pixel fb.pixels.{y, x}) ~alpha))
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>