{"id":13530743,"url":"https://github.com/emoon/minifb","last_synced_at":"2025-05-14T19:09:11.036Z","repository":{"id":17723867,"uuid":"20552735","full_name":"emoon/minifb","owner":"emoon","description":"MiniFB is a small cross platform library to create a frame buffer that you can draw pixels in","archived":false,"fork":false,"pushed_at":"2025-02-11T17:10:26.000Z","size":460,"stargazers_count":1057,"open_issues_count":19,"forks_count":84,"subscribers_count":30,"default_branch":"master","last_synced_at":"2025-05-14T19:09:08.168Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emoon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-06-06T05:41:52.000Z","updated_at":"2025-05-12T06:47:57.000Z","dependencies_parsed_at":"2024-01-03T04:00:12.536Z","dependency_job_id":"779d05fd-1407-46ff-a605-43ecf21e049c","html_url":"https://github.com/emoon/minifb","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fminifb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fminifb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fminifb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emoon%2Fminifb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emoon","download_url":"https://codeload.github.com/emoon/minifb/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254209859,"owners_count":22032897,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T07:00:54.491Z","updated_at":"2025-05-14T19:09:08.377Z","avatar_url":"https://github.com/emoon.png","language":"C","readme":"# MiniFB\n\nMiniFB (Mini FrameBuffer) is a small cross platform library that makes it easy to render (32-bit) pixels in a window.\n\nAn example is the best way to show how it works:\n\n```c\nstruct mfb_window *window = mfb_open_ex(\"my display\", 800, 600, WF_RESIZABLE);\nif (!window)\n    return 0;\n\nbuffer = (uint32_t *) malloc(800 * 600 * 4);\n\ndo {\n    int state;\n\n    // TODO: add some fancy rendering to the buffer of size 800 * 600\n\n    state = mfb_update_ex(window, buffer, 800, 600);\n\n    if (state \u003c 0) {\n        window = NULL;\n        break;\n    }\n} while(mfb_wait_sync(window));\n```\n\n1. First the application creates a **window** calling **mfb_open** or **mfb_open_ex**.\n2. Next it's the application responsibility to allocate a buffer to work with.\n3. Next calling **mfb_update** or **mfb_update_ex** the buffer will be copied over to the window and displayed. If this function return a value lower than 0 the window will have been destroyed internally and cannot be used anymore.\n4. Last the code waits to synchronize with the monitor calling **mfb_wait_sync**.\n\nNote that, by default, if ESC key is pressed **mfb_update** / **mfb_update_ex** will return -1 (and the window will have been destroyed internally).\n\nSee https://github.com/emoon/minifb/blob/master/tests/noise.c for a complete example.\n\n# Supported Platforms:\n\n - Windows\n - MacOS X\n - X11 (FreeBSD, Linux, *nix)\n - Wayland (Linux) [there are some issues]\n - iOS (beta)\n - Android (beta)\n - Web (WASM) (beta)\n\nMiniFB has been tested on Windows, Mac OS X, Linux, iOS, Android and web but may of course have trouble depending on your setup. Currently the code will not do any converting of data if not a proper 32-bit display can be created.\n\n# Features:\n\n - Window creation\n - Callbacks to window events\n - Get information from windows\n - Add per window data\n - Timers and target FPS\n - C and C++ interface\n\n## Callbacks to window events:\n\nYou can _add callbacks to the windows_:\n\n```c\nvoid active(struct mfb_window *window, bool isActive) {\n    ...\n}\n\nvoid resize(struct mfb_window *window, int width, int height) {\n    ...\n    // Optionally you can also change the viewport size\n    mfb_set_viewport(window, x, y, width, height);\n    // or let mfb caclculate the best fit from your original framebuffer size\n    mfb_set_viewport_best_fit(window, old_width, old_height);\n\n}\n\nbool close(struct mfb_window *window) {\n    ...\n    return true;    // true =\u003e confirm close\n                    // false =\u003e don't close\n}\n\nvoid keyboard(struct mfb_window *window, mfb_key key, mfb_key_mod mod, bool isPressed) {\n    ...\n    // Remember to close the window in some way\n    if(key == KB_KEY_ESCAPE) {\n        mfb_close(window);\n    }\n}\n\nvoid char_input(struct mfb_window *window, unsigned int charCode) {\n    ...\n}\n\nvoid mouse_btn(struct mfb_window *window, mfb_mouse_button button, mfb_key_mod mod, bool isPressed) {\n    ...\n}\n\n// Use wisely this event. It can be sent too often\nvoid mouse_move(struct mfb_window *window, int x, int y) {\n    ...\n}\n\n// Mouse wheel\nvoid mouse_scroll(struct mfb_window *window, mfb_key_mod mod, float deltaX, float deltaY) {\n    ...\n}\n\n\nint main(int argc, char argv[]) {\n\n    struct mfb_window *window = mfb_open_ex(\"my display\", 800, 600, WF_RESIZABLE);\n    if (!window)\n        return 0;\n\n    mfb_set_active_callback(window, active);\n    mfb_set_resize_callback(window, resize);\n    mfb_set_close_callback(window, close);\n    mfb_set_keyboard_callback(window, keyboard);\n    mfb_set_char_input_callback(window, char_input);\n    mfb_set_mouse_button_callback(window, mouse_btn);\n    mfb_set_mouse_move_callback(window, mouse_move);\n    mfb_set_mouse_scroll_callback(window, mouse_scroll);\n\n    ...\n}\n```\n\n### C++ event interface:\n\nIf you are using C++ you can set the callbacks to a class, or use lambda expressions:\n\n```cpp\nstruct Events {\n    void active(struct mfb_window *window, bool isActive) {\n        ...\n    }\n    ...\n}\n\nint main(int argc, char argv[]) {\n    Events e;\n\n    // Using object and pointer to member\n    mfb_set_active_callback(window, \u0026e, \u0026Events::active);\n\n    // Using std::bind\n    mfb_set_active_callback(std::bind(\u0026Events::active, \u0026e, _1, _2), window);\n\n    // Using a lambda\n    mfb_set_active_callback([](struct mfb_window *window, bool isActive) {\n        ...\n    }, window);\n\n    ...\n}\n\n```\n\n## Get information from windows (direct interface)\n\nIf you don't want to use callbacks, you can _get information about the window events directly_:\n\n```c\nbool                mfb_is_window_active(struct mfb_window *window);\n\nunsigned            mfb_get_window_width(struct mfb_window *window);\nunsigned            mfb_get_window_height(struct mfb_window *window);\n\nint                 mfb_get_mouse_x(struct mfb_window *window);             // Last mouse pos X\nint                 mfb_get_mouse_y(struct mfb_window *window);             // Last mouse pos Y\n\nfloat               mfb_get_mouse_scroll_x(struct mfb_window *window);      // Mouse wheel X as a sum. When you call this function it resets.\nfloat               mfb_get_mouse_scroll_y(struct mfb_window *window);      // Mouse wheel Y as a sum. When you call this function it resets.\n\nconst uint8_t *     mfb_get_mouse_button_buffer(struct mfb_window *window); // One byte for every button. Press (1), Release 0. (up to 8 buttons)\n\nconst uint8_t *     mfb_get_key_buffer(struct mfb_window *window);          // One byte for every key. Press (1), Release 0.\n```\n\n## Add per window data\n\nAdditionally you can _set per window data and recover it_:\n\n```c\nmfb_set_user_data(window, (void *) myData);\n...\nmyData = (someCast *) mfb_get_user_data(window);\n```\n\n## Timers and target FPS\n\nYou can create timers for your own purposes.\n\n```c\nstruct mfb_timer *  mfb_timer_create();\nvoid                mfb_timer_destroy(struct mfb_timer *tmr);\n\nvoid                mfb_timer_reset(struct mfb_timer *tmr);\ndouble              mfb_timer_now(struct mfb_timer *tmr);\ndouble              mfb_timer_delta(struct mfb_timer *tmr);\n\ndouble              mfb_timer_get_frequency();\ndouble              mfb_timer_get_resolution();\n```\n\nFurthermore you can set (and get) a target fps for the application. The default is 60 frames per second.\n\n```c\nvoid                mfb_set_target_fps(uint32_t fps);\nunsigned            mfb_get_target_fps();\n```\n\nThis avoid the problem of update too fast the window collapsing the redrawing in fast processors.\n\nNote: OpenGL and iOS have hardware support for syncing. Other systems will use software syncing. Including MacOS Metal.\n\nIn order to be able to use it you need to call the function:\n\n```c\nbool                mfb_wait_sync(struct mfb_window *window);\n```\n\nNote that if you have several windows running on the same thread it makes no sense to wait them all...\n\n.\n\n# Build instructions\n\nThe current build system is **CMake**.\n\nInitially MiniFB used tundra [https://github.com/deplinenoise/tundra](https://github.com/deplinenoise/tundra) as build system and it was required to build the code (but now is not maintained).\n\nIn any case, not many changes should be needed if you want to use MiniFB directly in your own code.\n\n## MacOS X\n\nCocoa and clang is assumed to be installed on the system (downloading latest XCode + installing the command line tools should do the trick).\n\nNote that MacOS X Mojave+ does not support Cocoa framework as expected. For that reason you can switch to Metal API.\nTo enable it just compile defining the preprocessor macro USE_METAL_API.\n\nIf you use **CMake** just enable the flag:\n\n```\nmkdir build\ncd build\ncmake .. -DUSE_METAL_API=ON\n```\n\nor if you don't want to use Metal API:\n\n```\nmkdir build\ncd build\ncmake .. -DUSE_METAL_API=OFF\n```\n\n### Coordinate system\n\nOn MacOS, the default mouse coordinate system is (0, 0) -\u003e (left, bottom). But as we want to create a multiplatform library we inverted the coordinates in such a way that now (0, 0) -\u003e (left, top), like in the other platforms.\n\nIn any case, if you want to get the default coordinate system you can use the CMake flag: USE_INVERTED_Y_ON_MACOS=ON\n\n```\nmkdir build\ncd build\ncmake .. -DUSE_INVERTED_Y_ON_MACOS=ON\n```\n\n_Note: In the future, we may use a global option so that all platforms behave in the same way. Probably: -DUSE_INVERTED_Y_\n\nif you use **tundra**:\n\n```\ntundra2 macosx-clang-debug\n```\n\nand you should be able to run the noise example (t2-output/macosx-clang-debug-default/noise).\n\n## iOS (beta)\n\nIt works with and without an UIWindow created.\nIf you want to create the UIWindow through an Story Board, remember to set the UIViewController as iOSViewController and the UIView as iOSView.\n\n**Issues:**\n\n- It seems that you have to manually set 'tvOS Deployment Target' to less than 13.\n- It seems that you have to manually set 'Launch Screen File' in project \u003e executable \u003e general to be able to get the real device height.\n- You need to manually set the 'Signing Team' and 'Bundle Identifier'.\n- No multitouch is available yet.\n- As this version uses Metal API it cannot be run in the emulator.\n\n**Functions:**\n\nSome of the MiniFB functions don't make sense on mobile.\nThe available functions for iOS are:\n\n```c\nstruct mfb_window * mfb_open(const char *title, unsigned width, unsigned height);\nstruct mfb_window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags);    // flags ignored\n\nmfb_update_state    mfb_update(struct mfb_window *window, void *buffer);\n\nvoid                mfb_close(struct mfb_window *window);\n\nvoid                mfb_set_user_data(struct mfb_window *window, void *user_data);\nvoid *              mfb_get_user_data(struct mfb_window *window);\n\nbool                mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height);\n\nbool                mfb_set_viewport_best_fit(struct mfb_window *window, unsigned old_width, unsigned old_height);\n\nvoid                mfb_set_mouse_button_callback(struct mfb_window *window, mfb_mouse_button_func callback);\nvoid                mfb_set_mouse_move_callback(struct mfb_window *window, mfb_mouse_move_func callback);\nvoid                mfb_set_resize_callback(struct mfb_window *window, mfb_resize_func callback);\nvoid                mfb_set_close_callback(struct mfb_window *window, mfb_close_func callback);\n\nunsigned            mfb_get_window_width(struct mfb_window *window);\nunsigned            mfb_get_window_height(struct mfb_window *window);\nint                 mfb_get_mouse_x(struct mfb_window *window);             // Last mouse pos X\nint                 mfb_get_mouse_y(struct mfb_window *window);             // Last mouse pos Y\nconst uint8_t *     mfb_get_mouse_button_buffer(struct mfb_window *window); // One byte for every button. Press (1), Release 0. (up to 8 buttons)\n\nvoid                mfb_get_monitor_scale(struct mfb_window *window, float *scale_x, float *scale_y)\n// [Deprecated] Use mfb_get_monitor_scale instead\nvoid                mfb_get_monitor_dpi(struct mfb_window *window, float *dpi_x, float *dpi_y)\n```\n\nTimers are also available.\n\n```c\nstruct mfb_timer *  mfb_timer_create(void);\nvoid                mfb_timer_destroy(struct mfb_timer *tmr);\nvoid                mfb_timer_reset(struct mfb_timer *tmr);\ndouble              mfb_timer_now(struct mfb_timer *tmr);\ndouble              mfb_timer_delta(struct mfb_timer *tmr);\ndouble              mfb_timer_get_frequency(void);\ndouble              mfb_timer_get_resolution(void);\n```\n\nFor now, no multitouch is available.\n\n**Example:**\n\n```objective-c\n- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n    if(g_window == 0x0) {\n        g_width  = [UIScreen mainScreen].bounds.size.width;\n        g_height = [UIScreen mainScreen].bounds.size.height;\n        g_window = mfb_open(\"noise\", g_width, g_height);\n        if(g_window != 0x0) {\n            g_buffer = malloc(g_width * g_height * 4);\n        }\n    }\n\n    return YES;\n}\n\n- (void)applicationDidBecomeActive:(UIApplication *)application {\n    mDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(OnUpdateFrame)];\n    [mDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];\n}\n\n- (void)applicationWillTerminate:(UIApplication *)application {\n    [mDisplayLink invalidate];\n    mfb_close(g_window);\n}\n\n- (void) OnUpdateFrame {\n    if(g_buffer != 0x0) {\n        // Do your wonderful rendering stuff\n    }\n\n    mfb_update_state state = mfb_update(g_window, g_buffer);\n    if (state != STATE_OK) {\n        free(g_buffer);\n        g_buffer  = 0x0;\n        g_width   = 0;\n        g_height  = 0;\n    }\n}\n```\n\n**CMake**\n\n```\nmkdir build\ncd build\ncmake -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 ..\n```\n\n## Android (beta)\n\nTake a look at the example in tests/android. You need **Android Studio** to build and run it.\n\n**Functions:**\n\nSome of the MiniFB functions don't make sense on mobile.\nThe available functions for Android are:\n\n```c\nstruct mfb_window * mfb_open(const char *title, unsigned width, unsigned height);\nstruct mfb_window * mfb_open_ex(const char *title, unsigned width, unsigned height, unsigned flags);    // flags ignored\n\nmfb_update_state    mfb_update(struct mfb_window *window, void *buffer);\n\nvoid                mfb_close(struct mfb_window *window);\n\nvoid                mfb_set_user_data(struct mfb_window *window, void *user_data);\nvoid *              mfb_get_user_data(struct mfb_window *window);\n\nbool                mfb_set_viewport(struct mfb_window *window, unsigned offset_x, unsigned offset_y, unsigned width, unsigned height);\n\nbool                mfb_set_viewport_best_fit(struct mfb_window *window, unsigned old_width, unsigned old_height);\n\nvoid                mfb_set_active_callback(struct mfb_window *window, mfb_active_func callback);\nvoid                mfb_set_mouse_button_callback(struct mfb_window *window, mfb_mouse_button_func callback);\nvoid                mfb_set_mouse_move_callback(struct mfb_window *window, mfb_mouse_move_func callback);\nvoid                mfb_set_resize_callback(struct mfb_window *window, mfb_resize_func callback);\nvoid                mfb_set_close_callback(struct mfb_window *window, mfb_close_func callback);\n\nbool                mfb_is_window_active(struct mfb_window *window);\nunsigned            mfb_get_window_width(struct mfb_window *window);\nunsigned            mfb_get_window_height(struct mfb_window *window);\nint                 mfb_get_mouse_x(struct mfb_window *window);             // Last mouse pos X\nint                 mfb_get_mouse_y(struct mfb_window *window);             // Last mouse pos Y\nconst uint8_t *     mfb_get_mouse_button_buffer(struct mfb_window *window); // One byte for every button. Press (1), Release 0. (up to 8 buttons)\n```\n\nTimers are also available.\n\n```c\nstruct mfb_timer *  mfb_timer_create(void);\nvoid                mfb_timer_destroy(struct mfb_timer *tmr);\nvoid                mfb_timer_reset(struct mfb_timer *tmr);\ndouble              mfb_timer_now(struct mfb_timer *tmr);\ndouble              mfb_timer_delta(struct mfb_timer *tmr);\ndouble              mfb_timer_get_frequency(void);\ndouble              mfb_timer_get_resolution(void);\n```\n\n## Windows\n\nIf you use **CMake** the Visual Studio project will be generated (2015, 2017 and 2019 have been tested).\n\nFurthermore you can also use **MinGW** instead of Visual Studio.\n\nif you use **tundra**:\n\nVisual Studio (ver 2012 express has been tested) tools needed (using the vcvars32.bat (for 32-bit) will set up the enviroment) to build run:\n\n```bash\ntundra2 win32-msvc-debug\n```\n\nand you should be able to run noise in t2-output/win32-msvc-debug-default/noise.exe\n\n### OpenGL API backend\n\nNow, by default, OpenGL backend is used, instead of Windows GDI, because it is faster. To maintain compatibility with old computers an OpenGL 1.5 context is created (no shaders needed).\n\nTo enable or disable OpenGL just use a CMake flag:\n\n```bash\ncmake .. -DUSE_OPENGL_API=ON\n# or\ncmake .. -DUSE_OPENGL_API=OFF\n```\n\n## X11 (FreeBSD, Linux, *nix)\n\ngcc and x11-dev libs needs to be installed.\n\nIf you use **CMake** just disable the flag:\n\n```bash\nmkdir build\ncd build\ncmake .. -DUSE_WAYLAND_API=OFF\n```\n\nIf you use **tundra**:\n\nTo build the code run:\n\n```bash\ntundra2 x11-gcc-debug\n```\n\nand you should be able to run t2-output/x11-gcc-debug-default/noise\n\n### OpenGL API backend\n\nNow, by default, OpenGL backend is used instead of X11 XImages because it is faster. To maintain compatibility with old computers an OpenGL 1.5 context is created (no shaders needed).\n\nTo enable or disable OpenGL just use a CMake flag:\n\n```bash\ncmake .. -DUSE_OPENGL_API=ON -DUSE_WAYLAND_API=OFF\n# or\ncmake .. -DUSE_OPENGL_API=OFF -DUSE_WAYLAND_API=OFF\n```\n\n## Wayland (Linux)\n\nDepends on gcc and wayland-client and wayland-cursor. Built using the wayland-gcc variants.\n\nIf you use **CMake** just enable the flag:\n\n```bash\nmkdir build\ncd build\ncmake .. -DUSE_WAYLAND_API=ON\n```\n\n## Web (WASM)\nDownload and install [Emscripten](https://emscripten.org/). When configuring your CMake build, specify the Emscripten toolchain file. Then proceed to build as usual.\n\n### Building and running the examples\n\n```bash\ncmake -DCMAKE_TOOLCHAIN_FILE=/path/to/emsdk/\u003cversion\u003e/emscripten/cmake/Modules/Platform/Emscripten.cmake -S . -B build\ncmake --build build\n```\n\n\u003e *Note*: On Windows, you will need a build tool other than Visual Studio. [Ninja](https://ninja-build.org/) is the best and easiest option. Simply download it, put the `ninja.exe` executable somewhere, and make it available on the command line via your `PATH` environment variable. Then invoke the first command above with the addition of `-G Ninja` at the end.\n\nThen open the file `build/index.html` in your browser to view the example index.\n\nThe examples are build using the Emscripten flag `-sSINGLE_FILE`, which will coalesce the `.js` and `.wasm` files into a single `.js` file. If you build your own apps without the `-sSINGLE_FILE` flag, you can not simply open the `.html` file in the browser from disk. Instead, you need an HTTP server to serve the build output. The simplest solution for that is Python's `http.server` module:\n\n```\npython3 -m http.server build/\n```\n\nYou can then open the index at [http://localhost:8000](http://localhost:8000) in your browser.\n\n### Integrating a MiniFB app in a website\nTo build an executable target for the web, you need to add a linker option specifying its module name, e.g.:\n\n```\ntarget_link_options(my_app PRIVATE \"-sEXPORT_NAME=my_app\")\n```\n\nThe Emscripten toolchain will then build a `my_app.wasm` and `my_app.js` file containing your app's WASM code and JavaScript glue code to load the WASM file and run it. To load and run your app, you need to:\n\n1. Create a `\u003ccanvas\u003e` element with an `id` attribute matching the `title` you specify when calling `mfb_open_window()` or `mfb_open_window_ex()`.\n2. Call the `\u003cmy_module_name\u003e()` in JavaScript.\n\nExample app:\n\n```c\nint main() {\n    struct mfb_window *window = mfb_open_ex(\"my_app\", 320, 240);\n    if (!window)\n        return 0;\n    uint32_t *buffer = (uint32_t *) malloc(g_width * g_height * 4);\n    mfb_update_state state;\n    do {\n        state = mfb_update_ex(window, buffer, 320, 200);\n        if (state != STATE_OK) {\n            break;\n        }\n    } while(mfb_wait_sync(window));\n    return 0;\n}\n```\n\nAssuming the build will generate `my_app.wasm` and `my_app.js`, the simplest `.html` file to load and run the app would look like this:\n\n```html\n\u003chtml\u003e\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n    \u003cmeta charset='utf-8'\u003e\n    \u003cmeta http-equiv='X-UA-Compatible' content='IE=edge'\u003e\n    \u003cmeta name='viewport' content='width=device-width, initial-scale=1'\u003e\n    \u003c!-- Load the app's .js file --\u003e\n    \u003cscript src=\"./my_app.js\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n\u003cdiv\u003e\n    \u003ccanvas id=\"Noise Test\" style=\"background: #000;\"\u003e\u003c/canvas\u003e\n\u003c/div\u003e\n\u003cscript\u003e\n    // Call the app's main() function\n    noise();\n\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Limitations \u0026 caveats\nThe web backend currently does not support the following MiniFB features:\n\n* The flags to `mfb_open_ex()` are ignored\n* `mfb_set_viewport()` (no-op)\n* `mfb_set_viewport_best_fit()` (no-op)\n* `mfb_get_monitor_dpi()` (reports a fixed value)\n* `mfb_get_monitor_scale()` (reports a fixed value)\n* `mfb_set_target_fps()` (no-op)\n* `mfb_get_target_fps()` (no-op)\n\nEverything else is supported.\n\nWhen calling `mfb_open()` or `mfb_open_ex()`, the specified title must match the `id` attribute of a `\u003ccanvas\u003e` element in the DOM. The functions will modify the `width` and `height` attribute of the `\u003ccanvas\u003e` element. If not already set, then the functions will also modify the CSS style `width` and `height` attributes of the canvas.\n\nSetting the CSS width and height of the canvas allows you to up-scale the framebuffer arbitrarily:\n\n```\n// Request a 320x240 window\nmfb_open(\"my_app\", 320, 240);\n\n// Up-scale 2x via CSS\n\u003ccanvas id=\"my_app\" style=\"width: 640px; height: 480px\"\u003e\n````\n\nIf not already set, the backend will also set a handfull of CSS styles on the canvas that are good defaults for pixel graphics.\n\n* `image-rendering: pixelated`\n* `user-select: none`\n* `border: none`\n* `outline-style: none`;\n\n# How to add it to your project\n\nFirst add this **repository as a submodule** in your dependencies folder. Something like `dependencies/`:\n\n```bash\ngit submodule add https://github.com/emoon/minifb.git dependencies/minifb\n```\n\nThen in your `CMakeLists.txt` file, include the following:\n\n```cmake\nadd_subdirectory(dependencies/minifb)\n\n# Link MiniFB to your project:\ntarget_link_libraries(${PROJECT_NAME}\n    minifb\n)\n```\n\nFill out the rest of your `CMakeLists.txt` file with your source files and dependencies.\n","funding_links":[],"categories":["Libraries"],"sub_categories":["C"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femoon%2Fminifb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femoon%2Fminifb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femoon%2Fminifb/lists"}