Compare commits

...

551 Commits

Author SHA1 Message Date
Martin Fouilleul 82e4d0e08b Moving repo to github 2023-10-09 17:23:54 +02:00
Martin Fouilleul ef79405805 Licensing changes 2023-10-08 18:29:58 +02:00
Martin Fouilleul a1b48b2b2f add github sponsor yml file 2023-10-08 18:27:43 +02:00
Ilia Demianenko 5e62a5d2e7 Make intensity FPS-independent 2023-10-03 21:31:22 -07:00
Ilia Demianenko c05223f91c Make the fluid sample do a splat on startup 2023-10-03 21:19:36 -07:00
Reuben Dunnington 6e4943c2fa
make scancode -> keycode conversion consistent with header definitions 2023-09-29 22:09:31 -04:00
Martin Fouilleul 90dd12a69f Aligned arena allocation 2023-09-29 10:53:48 +02:00
Martin Fouilleul 549e640102 making binding generator output explicit void for functions with no parameters. Fix oc_surface_canvas/oc_surface_gles to take explicit void 2023-09-28 21:29:03 +02:00
Martin Fouilleul d5bd7ea2bb fix order of file vs function in logging function arguments 2023-09-28 21:28:18 +02:00
Martin Fouilleul c4a1ad52a0 fix duplicate declarations in .clang-format 2023-09-28 10:04:32 +02:00
Reuben Dunnington 9448104f41
macos: separate building orca core from samples 2023-09-25 22:36:02 -04:00
Reuben Dunnington aac74b0533
win32: separate building orca core from samples 2023-09-25 22:28:01 -04:00
Ben Visness 4f0738fe64 Check for Xcode command-line tools 2023-09-25 11:28:52 +00:00
Ben Visness 1cc8778982 Do clang checks on Mac 2023-09-25 11:28:52 +00:00
Ben Visness 75c4f6f94d Revamp Clang checks for Windows; still need to do the same for Mac 2023-09-25 11:28:52 +00:00
Martin Fouilleul fb18d3240a Fix handling of wasm memory growing. Properly account for wasm3 header size, align on page boundary and return the previous size, asserting that there's enough memory for the requested chunk size. 2023-09-25 11:59:11 +02:00
Martin Fouilleul 388b059643 adding exp/expf 2023-09-24 18:44:32 +02:00
Martin Fouilleul b4aedb3ecc adding __math_xflowf 2023-09-24 11:15:08 +02:00
Ben Visness 34127134d5 Bypass dumb powershell execution policy problems 2023-09-21 06:54:13 +00:00
Ben Visness 24d61aaeab Detect MSVC version and architecture via preprocessor 2023-09-21 06:53:35 +00:00
Reuben Dunnington 37c00bd42f fix compile errors with pow/powf 2023-09-21 06:52:14 +00:00
Martin Fouilleul 94ce88e272 [macos] use libtool instead of ar when building wasm3 lib, and pass -no_warning_for_no_symbols because translation units in wasm3 don't have symbols 2023-09-19 11:48:42 +02:00
Martin Fouilleul 647565e285 Put offset curve sample check count in an enum to silence -Wgnu-folding-constant 2023-09-19 11:47:27 +02:00
Martin Fouilleul ecf89fa6b2 [macos build]
- Remove the need for -maes, silence warning about ignored option on ARM macs
- Set -mmacos-version-min when building wasm3 to match that of the platform layer and runtime
2023-09-19 09:56:46 +02:00
Martin Fouilleul 715ab0f6e3 put mtl renderer constants in an enum to silence -Wgnu-folding-constant warnings 2023-09-19 09:24:23 +02:00
Martin Fouilleul 370482a3e0 remove wrong alignment attribute of IM3Operation wasm3 2023-09-19 09:15:36 +02:00
Martin Fouilleul 827db17e14 update image atlas alloc functions to match image/font create functions 2023-09-19 09:10:06 +02:00
Martin Fouilleul 01565324c5 add extern C to libc-shim string.h in C++ mode 2023-09-19 08:57:23 +02:00
Reuben Dunnington ea74114693 windows: fix vsync logspam when window is minimized 2023-09-19 06:42:58 +00:00
Reuben Dunnington 4b30bd70d0 fix gl error spam when window is resized to 0 width/height 2023-09-19 06:37:46 +00:00
Ben Visness 43273cc170 Switch from `python3` to `python` on Windows
and just make other things nicer I dunno
2023-09-19 06:36:05 +00:00
Ben Visness ab3280ed4e Add extra checks for MSVC 2023-09-19 06:36:05 +00:00
Reuben Dunnington 0d839a9767
call oc_on_mouse_wheel() when getting a wheel event 2023-09-18 19:17:31 -07:00
Martin Fouilleul 762d2d9d10 small fixes in cheatsheets 2023-09-18 21:21:54 +02:00
Martin Fouilleul 34303edd4e expose malloc/free to apps through libc-shim stdlib.h 2023-09-18 21:13:06 +02:00
Reuben Dunnington e85d774245 Bring over more math functions from musl
* asin
* asinf
* acosf
* tan
* tanf
* atan
* atan2
* atan2f
* atanf
* cbrt
* cbrtf
* log
* logf
* log2
* log2f
2023-09-18 10:21:49 +00:00
Martin Fouilleul 116e614ab6 Keep log format as "function() in file:line: msg", but pass the arguments in consistent order between the host and guest app. 2023-09-18 10:19:13 +00:00
Reuben Dunnington 44477782d8 logging: move parens to be in front of function 2023-09-18 10:19:13 +00:00
Ben Visness d2e8430c49 Check if the runtime is up to date on dev install 2023-09-18 10:04:59 +00:00
Ben Visness 45c615bfa9 Add cool image to README 2023-09-18 10:02:42 +00:00
Ben Visness 17beaef0e0 Slightly improve MSVC documentation and error messages 2023-09-18 10:01:44 +00:00
Reuben Dunnington 37655abbf5 wrap some paths to handle spaces on windows 2023-09-18 10:01:11 +00:00
Ben Visness a77d6a07cd Use the HTTPS URL in the docs
SSH doesn't work unless you have a public key on your Gitea account. Obviously we don't even expect most of our users to even create a Gitea account.
2023-09-17 10:41:40 -05:00
Ben Visness 0b273f1e43 Fix links in quick start 2023-09-16 17:53:49 -05:00
Ben Visness bd780b20f3 Print help when running `orca source` 2023-09-16 15:46:00 -05:00
Reuben Dunnington 5b7e27f9fd
running orca with no args should print help instead of throw an error 2023-09-16 10:00:07 -07:00
Martin Fouilleul 00555dc03f Fix mistake I did when resolving conflicts in dev.py between #79 and #89 2023-09-16 18:55:25 +02:00
martinfouilleul 4865e2142d scripts/bundle.py: fix ext path in windows_make_app 2023-09-16 18:05:18 +02:00
Ben Visness f05adac120 Update the README and quick start for launch 2023-09-16 15:56:48 +00:00
Ben Visness 29cb9f50e4 Add commands to deal with Orca source code:
- Add a vendor commands
- Add a command that helps you set up a C compiler
- Move ext into the src folder
- Update Mac build scripts for consistency
- Update Windows batch scripts
2023-09-16 17:54:56 +02:00
Ben Visness 731b1c7334 Add uninstall command 2023-09-16 15:46:43 +00:00
Martin Fouilleul 7d3f29e43b [ui layout]
- implement ui box min size, + small fixes in layout code of ui sample
- quick workaround for background showing on resize: clear to current theme's bg0 color
- precompute minsize based on children to avoid upward fixup step
- fix scrollable panel
- Simplify color overrides, override more things to counteract the light theme
- Change dragging to active for after #106 is merged
- when clamping box to minsize during shrinking, redistribute excess to siblings that still have some slack
- wrap demo in a scrollable panel

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Co-authored-by: Martin Fouilleul <martinfouilleul@gmail.com>
2023-09-16 16:59:45 +02:00
Ilia Demianenko 33078fd9dc UI demo with styling 2023-09-16 16:59:45 +02:00
Martin Fouilleul 300d5aeab4 add a OC_UI_HOT style selector and use that to style radio buttons when the button's label is hovered 2023-09-16 16:33:08 +02:00
Martin Fouilleul d58643eb52 fix button & checkbox to return to normal styling when active but _not_ hovered 2023-09-16 16:18:23 +02:00
Ilia Demianenko efeac65a96 Only highlight the widgets on mouse down when they are also hovered 2023-09-15 15:00:33 -07:00
Martin Fouilleul 7ca40f8cac minor Readme.md additions 2023-09-14 17:42:01 +02:00
Martin Fouilleul 09cf30cf45 Consistency/intent
- pass arenas as first parameters (exception being texbox widget, where we always pass tag as first parameter)
- pass lists by value when there's no modification (eg oc_list_for etc...)
- fix sketches, use oc_arena_scope as value.
2023-09-14 11:54:38 +02:00
Martin Fouilleul 47dc052508 Minor consistency things:
- oc_window_style could be enum
- clikCount in oc_key_event to u8
- return of oc_input_key_press -> u8
- rename oc_key_pressed/released/repeated to oc_key_press/release/repeat_count to reflect meaning of return value
2023-09-14 10:47:10 +02:00
Martin Fouilleul 0e680c989b consistency: use _proc everywhere instead of _function or _callback in procedure typedefs. Also remove unused oc_live_resize_callback 2023-09-14 10:31:12 +02:00
Ilia Demianenko 73717b5dd8 Document palette colors 2023-09-14 07:42:09 +00:00
Ilia Demianenko d44ac5a1fb Use color + bgColor for selected radio instead of bgColor + borderColor 2023-09-13 14:02:50 -07:00
Ilia Demianenko 82aefaf758 Radio button group 2023-09-13 14:02:50 -07:00
Martin Fouilleul 8cd571f923 Remove oc_scratch()/oc_scratch_next() in favour of safer oc_scratch_begin()/oc_scratch_end() 2023-09-13 18:10:47 +02:00
Martin Fouilleul a0f9ab5f85 Allow building apps in C++ mode 2023-09-13 15:18:15 +00:00
Martin Fouilleul 0f3f7b5052 oc_runtime_clipboard_get_string() pushes to an arena, so to maintain oc_str8 conventions, we push an implicit null terminator after it 2023-09-13 17:05:15 +02:00
Ilia Demianenko a5567da82c Clipboard handling 2023-09-13 16:59:26 +02:00
Martin Fouilleul 7026919b38 pass both scancode and keycode to oc_on_key_up()/oc_on_key_down() 2023-09-13 16:33:28 +02:00
Martin Fouilleul a1ffcd3ddc [ui] macOS text edit shortcuts 2023-09-13 16:25:18 +02:00
Martin Fouilleul d53c688810 Keyboard layout support:
- Convey both fixed scancodes and keyboard-layout dependent keycodes in key events.
- Update scancode to keycode mapping when keyboard layout changes
- Allow querying key input state using either keycodes or scancodes
2023-09-13 16:22:33 +02:00
Martin Fouilleul db36158e7a check return pointer sizes in binding stubs 2023-09-12 17:06:01 +02:00
Martin Fouilleul d90c11db58 Save return pointer before calling native function in binding stubs 2023-09-12 15:03:56 +02:00
Martin Fouilleul b9232b796c Fix hang on quit. Closes #91 2023-09-12 09:36:32 +02:00
Martin Fouilleul ce752713f6 oc_matrix_push() -> oc_matrix_multiply_push(), and add oc_matrix_push() to push a matrix on the stack as is 2023-09-11 20:02:46 +02:00
Martin Fouilleul 313f2e0ad4 Fix quit by sending an event to wakeup the main loop when calling oc_request_quit() 2023-09-11 18:36:40 +02:00
martinfouilleul ab4abd28d7 Fix broken build on MSVC due to size_t being considered equivalent to u64 in _Generic associations 2023-09-11 18:09:47 +02:00
Martin Fouilleul 3e2f550b68 switch order of designated enums in strings, to make it easier to compile in c++ mode 2023-09-11 14:15:35 +02:00
Martin Fouilleul dc837a6a6d change len of strings to size_t 2023-09-11 12:53:15 +02:00
Martin Fouilleul 8d346eca90 flip order of len and ptr in oc_str8/16/32 structs, to make bindings easier 2023-09-11 12:53:15 +02:00
Ilia Demianenko afbb4329f5 Fix scrolling 2023-09-11 09:43:58 +00:00
Martin Fouilleul 06a7642055 Licensing and copyright information 2023-09-11 11:09:47 +02:00
Ilia Demianenko bb39bc7a13 Make arrow keys always move the cursor to the edge of the selection first 2023-09-11 09:08:47 +00:00
Ben Visness 748617d9b0 Remove unnecessary hr 2023-09-10 16:55:18 -05:00
Ben Visness 5394e8f301 Update README 2023-09-10 16:46:32 -05:00
Martin Fouilleul 5cdded57b3 Replace confusing oc_text_bounding_box() with oc_font_text_metrics(), which returns both the logical metrics and ink bounding box of text 2023-09-10 19:25:41 +02:00
Martin Fouilleul e6a3ac7694 oc_render uses currently selected surface 2023-09-10 15:21:11 +02:00
Martin Fouilleul b223abcd5b add current features to Readme 2023-09-10 15:00:58 +02:00
Martin Fouilleul 4b2580f510 Documentation and some API cleaning
- Fleshing out Readme
- Renaming pong to breakout
- Renaming triangleGLES to triangle
- Move cheatsheets to their own directory
- Cleanup clock example to use in QuickStart
- QuickStart.md
- Some API cleaning:
    - oc_font_create_from_file()/oc_font_create_from_path()
    - oc_image_create_from_file/oc_image_create_from_path
    - oc_canvas_set_current() -> oc_canvas_select()
    - some matrix helpers
2023-09-10 12:29:40 +02:00
martinfouilleul 9aad2c0ec8 Fix debug overlay vsync on windows 2023-09-10 12:28:53 +02:00
Martin Fouilleul 565bef5896 #if guard vsync API from Orca apps 2023-09-09 15:33:59 +02:00
Ilia Demianenko 18dff15cf1 Support double and triple click text selection
Higher order click processing courtesy of https://devblogs.microsoft.com/oldnewthing/20041018-00/?p=37543
2023-09-09 14:57:51 +02:00
Martin Fouilleul 5a7182a3b9 make vsync differences between win32 and macos explicit in runtime.c 2023-09-09 14:34:20 +02:00
Reuben Dunnington 6ae129022e
rework vsync to be manual wait for win32 2023-09-08 21:35:13 -07:00
Reuben Dunnington d9703519b9
osx vsync notification 2023-09-08 20:58:14 -07:00
Reuben Dunnington aa1c5ef915
cleanup dead code 2023-09-08 20:58:14 -07:00
Reuben Dunnington be5b6aea30
vblank notification: win32 2023-09-08 20:58:11 -07:00
Martin Fouilleul 8fbfeab261 fix clock sample oc_runtime_window_set_size() -> oc_window_set_size() 2023-09-08 15:04:40 +02:00
Ilia Demianenko 3bcbc76662 Make tooltip disappear on mouse leave 2023-09-08 14:35:42 +02:00
Ilia Demianenko b4797dcd2d Light UI theme 2023-09-08 12:22:03 +00:00
Martin Fouilleul 907f33bc27 [osx] quickfix for frame pacing on osx, keep swap interval to 1 for all surfaces 2023-09-08 10:32:59 +02:00
martinfouilleul 3effde949e Fix file date on windows 2023-09-08 10:18:22 +02:00
Martin Fouilleul 8f413fdb46 fix auto-scrolling in debug UI (due to change in how oc_ui_panel() is structured) 2023-09-08 10:11:51 +02:00
Martin Fouilleul a275b3da28 adding file timestamps to file_status 2023-09-07 10:09:26 +02:00
Reuben Dunnington 15a8e2ae22 wasm bindings: enforce pointer length
* bindgen.py: print an error when a pointer argument doesn't have an annotated length
* ensure all bindings with pointers have length annotations
* add a couple helper functions for dealing with length annotations
2023-09-07 07:51:23 +00:00
MartinFouilleul 9b3a71a5c8 Merge pull request 'Make UI look nicer' (#80) from ilidemi/orca:ui-redesign into main
Reviewed-on: #80
2023-09-07 07:42:23 +00:00
Ilia Demianenko 15bc29d703 Merge branch 'main' of git.handmade.network:hmn/orca into ui-redesign 2023-09-06 22:31:03 -07:00
Ilia Demianenko aff03630da Make UI look nicer
Design system by semi.design: https://semi.design/en-US/start/overview

SVG icon workflow:
- Find the SVG with devtools
- Copy curve path to https://yqnn.github.io/svg-path-editor/
- Scale X and Y by 1/size (usually 1/24)
- In `ui.c`, do offset and scale with a matrix transform, then the draw commands can use the exact numbers from the normalized SVG
2023-09-06 22:24:00 -07:00
Martin Fouilleul 425d9b3448 - Added basic cheatsheets
- Minor cleanups:
    - Hiding some native-only path APIs
    - Re-formatting ui.h
2023-09-06 08:58:43 +02:00
Martin Fouilleul bd35b75f4b Minor API cleanup:
- Removing unused remote/host surfaces for now
- Complete canvas attributes getters
- Separate surface creation APIs accessible by host and guest
- added oc_get_matrix(), removed oc_viewport()
- oc_get_clip -> oc_clip_top, oc_get_matrix -> oc_matrix_top
2023-09-06 08:58:04 +02:00
Martin Fouilleul fbb03d27a3 Helpers for manipulating orca structs living in wasm memory:
- convert between wasm memory and native pointers, asserting on out-of-bounds
- oc_wasm_list helpers
- oc_wasm_str8 helpers
- pushing things to arenas in wasm memory
2023-09-02 18:07:57 +02:00
Martin Fouilleul 0205d90941 - Added oc_file_open_with_request() to request new file capability for a given path. This presents user with a message box allowing them to accept or deny the request.
- Added oc_file_open_with_dialog() to ask user to grant new file capabilities through an open/save dialog.
2023-09-02 11:00:28 +02:00
Martin Fouilleul 0db1589dc6 [canvas] remove degenerate point lines when encoding strokes 2023-09-01 19:40:37 +02:00
Martin Fouilleul fe25476305 remove stale comments in samples 2023-08-30 15:35:28 +02:00
martinfouilleul 19ce7447aa use app->quit on main thread instead of oc_should_quit(), to ensure that runloop_thread always exits its event loop before main thread 2023-08-30 12:06:32 +02:00
Martin Fouilleul 1907663cdc Skip drawing ui box when it's rect + boders are fully outside current clip 2023-08-29 18:43:25 +02:00
martinfouilleul 46ef9ee7e8 don't hide debug overlay, paint it transparent instead, brought to you by Windows stuttering and crashing on close if you call SwapBuffer on a hidden window :*) 2023-08-29 16:14:20 +00:00
Martin Fouilleul f268f031af Set user-created surfaces to non-blocking and use the debug overlay surface to block on vsync. 2023-08-29 16:14:20 +00:00
Martin Fouilleul 07414af087 [mtl canvas] Fix nTilesX/nTilesY computation in oc_mtl_canvas_render (don't multiply twice by scale) 2023-08-29 18:13:01 +02:00
Martin Fouilleul 9164e66cc6 [mtl canvas] fixed bug were order of mtl_segment_setup arguments tileOpMax and segmentMax were interverted, which would cull tile ops based on max number of segments, causing weird artifacts for some lengths of the segment buffer 2023-08-29 17:36:30 +02:00
martinfouilleul d86d0f8074 replace cp with copy in sketches build.bat scripts 2023-08-29 07:56:28 +00:00
martinfouilleul ec97c6d9ca win32 implementation of oc_surface_bring_to_front/send_to_back 2023-08-28 17:04:55 +02:00
Martin Fouilleul 02bfe30672 Expose oc_surface_bring_to_front/send_to_back() to orca apps, and always bring debug layer to front when displaying it 2023-08-28 16:11:55 +02:00
Martin Fouilleul b5034d3c81 [osx] implement oc_surface_bring_to_front() and oc_surface_send_to_back() 2023-08-28 15:48:24 +02:00
Reuben Dunnington 416044ea76 Makes sketches compile and run with changes introduced by renaming pass.
This is a combination of 19 commits:

- fix atlas
- fix canvas
- fix image
- add OpenSansLatinSubset to resources
- fix multi_surface
- fix perf_text
- fix polygon
- fix render_thread
- fix simpleWindow
- fix smooth_resize
- fix surface_sharing
- fixed tiger
- fix triangleGL
- fix triangleGLES (note rendering doesn't work)
- fix ui
- fix all on osx
- Fix sketch triangleGLES
- Make transparent rectangle clearer in sketches polygon
- Add proper error message in sketch/triangleGL on macOS
2023-08-28 12:37:33 +02:00
Reuben Dunnington ceb4a3a95d [osx canvas] Early out when eltCount or pathCount == 0, which avoid encoding empty passes and firing metal asserts when running in debug mode from xcode. 2023-08-28 12:16:31 +02:00
Martin Fouilleul 4b1ab4db97 expose oc_surface_contents_scaling() to get dpi scaling from a surface 2023-08-28 12:10:29 +02:00
MartinFouilleul 0727466f48 Merge pull request 'Support move/select/delete word with keyboard in textbox' (#63) from ilidemi/orca:text-box-words into main
Reviewed-on: #63
2023-08-25 13:50:14 +00:00
Ilia Demianenko 3c199dce34 minor 2023-08-25 15:46:11 +02:00
Ilia Demianenko 53cf85db53 Support move/select/delete word with keyboard in textbox 2023-08-25 15:46:04 +02:00
Reuben Dunnington 1917085990 win32: initialize clock in oc_init() 2023-08-25 13:39:04 +00:00
Ilia Demianenko 396d52edcd Clamp rounded rect radius 2023-08-25 13:33:49 +00:00
MartinFouilleul 5c89f1d103 Merge pull request 'window_size_title_api' (#61) from window_size_title_api into main
Reviewed-on: #61
2023-08-25 13:29:27 +00:00
Reuben Dunnington fad375c403
macos window title/size
* add macOS implmentation for oc_window_set_title()
* move implementation of oc_window_set_content_size() to a block that
  is guaranteed to run on the main thread
2023-08-24 11:57:41 -07:00
Reuben Dunnington 9ed636e018
update samples for oc_window_set_content_size oc_vec2 change 2023-08-24 11:42:28 -07:00
Reuben Dunnington bfd4c2a450
update oc_window_set_content_size to use oc_vec2 for consistency 2023-08-24 11:42:27 -07:00
Reuben Dunnington 81712c14c1
update samples with title/window size 2023-08-24 11:42:27 -07:00
Reuben Dunnington d4cb93c61a
oc_runtime_window_set_title and oc_runtime_window_set_size 2023-08-24 11:42:27 -07:00
Reuben Dunnington e4ac212408
wip window title and size API 2023-08-24 11:42:26 -07:00
Reuben Dunnington 72209200b5
format app.h 2023-08-24 11:42:26 -07:00
Reuben Dunnington b9e843f4bb
fix some crashes in metal implementation when pathCount and etlCount are 0 2023-08-24 11:33:21 -07:00
MartinFouilleul d3e27df818 Merge pull request 'Fix leak in canvas code and samples' (#60) from fix_canvas_leak into main
Reviewed-on: #60
2023-08-23 14:33:22 +00:00
Martin Fouilleul 42738195b5 Don't assume oc_scratch() is cleared at the frame boundary. Use oc_scratch_begin()/oc_scratch_end() instead 2023-08-23 16:24:13 +02:00
Martin Fouilleul 98f131cb30 Fix leak in metal surface: command buffer must not be committed if there is no surface to present it to, or it will result in a huge leak in metal resources. Also wrap oc_mtl_surface_acquire_command_buffer() in an @autoreleasepool to fix a smaller leak 2023-08-23 15:09:06 +02:00
Martin Fouilleul 86b1121fbe allow enabling/disabling metal frame capture when bundling a macos app 2023-08-23 15:06:35 +02:00
Martin Fouilleul 232c5f4f4c Fix exec permission on samples/clock/build.sh 2023-08-23 12:21:02 +02:00
Reuben Dunnington 4bde491a36 clock sample app 2023-08-23 12:16:32 +02:00
Martin Fouilleul edaffcb649 implement oc_window_is_minimized on macos 2023-08-23 12:16:01 +02:00
Reuben Dunnington 7b48c20c26 remove stray declaration 2023-08-22 21:32:13 +00:00
Reuben Dunnington 9ca7e82c82 flatten oc_request_quit() binding 2023-08-22 21:32:13 +00:00
Reuben Dunnington f4a82cd381 pong: demo oc_request_quit() and oc_on_terminate()
* gamestate now records your score (total blocks destroyed)
* when all blocks are destroyed, quit
* print a message when the app is terminated
2023-08-22 21:32:13 +00:00
Reuben Dunnington 0973e26150 expose oc_request_quit() to wasm runtime 2023-08-22 21:32:13 +00:00
Reuben Dunnington 9d1d8e5306
add win32 impl for oc_clock_time() 2023-08-22 13:42:01 -07:00
Reuben Dunnington 5a4fba96fa clang-format: use custom brace/indent style 2023-08-22 20:18:04 +00:00
Ilia Demianenko 2c07c9b665 Bring back the main modifier, get rid of _impl 2023-08-22 20:15:21 +00:00
Ilia Demianenko a6f81a1320 Use textbox shortcuts from the host platform 2023-08-22 20:15:21 +00:00
Reuben Dunnington 7755827485 ensure focus remains on main window when creating child windows 2023-08-22 20:10:57 +00:00
Reuben Dunnington c27e1c6b62
don't attempt to draw when the window is minimized 2023-08-22 07:43:22 -07:00
Reuben Dunnington 513bdacf64
disable include sorting - we rely on include order in some places 2023-08-21 14:39:09 -07:00
Reuben Dunnington 464a25c55d
fixes for a couple compile errors 2023-08-21 11:50:42 -07:00
Martin Fouilleul 94b9cb2bbf Auto-formatting with clang-format 2023-08-19 15:52:11 +02:00
MartinFouilleul 0d920670a2 Merge pull request 'Small textbox fixes' (#41) from ilidemi/orca:textbox-fixes into main
Reviewed-on: #41
2023-08-18 16:31:20 +00:00
Ilia Demianenko 40887a9a2d Small textbox fixes
Lose focus on mouse click outside
Update selection while dragging outside the box
Stop trying to flip the selection on drag, keep shift+click
2023-08-18 18:15:39 +02:00
MartinFouilleul e0db03b51c Merge pull request 'clang-format' (#39) from clang-format into main
Reviewed-on: #39
2023-08-18 15:59:40 +00:00
Reuben Dunnington a931f08067
Merge branch 'main' into clang-format 2023-08-18 08:31:35 -07:00
Reuben Dunnington 9a125361d6 forward sys keys to default window proc to get alt+f4 handling 2023-08-18 17:22:08 +02:00
MartinFouilleul 78e09b3373 Merge pull request 'Python tooling improvements' (#44) from python-improvements into main
Reviewed-on: #44
2023-08-18 14:50:32 +00:00
Ben Visness 18069fbc58 Detect Orca source from anywhere and make scripts work from anywhere 2023-08-18 16:44:28 +02:00
Ben Visness 4ae8bc3bfa Put gles_gen.log in the build folder 2023-08-18 16:44:28 +02:00
Ben Visness 50f6ed8bec Automatically add Orca to the PATH on Windows 2023-08-18 16:44:28 +02:00
Ben Visness 570a33a0e1 Dodge AppData problems on Windows (#32) 2023-08-18 16:44:28 +02:00
Martin Fouilleul 75621d85a5 Big renaming and consistency pass, including:
- "Namespacing" the Orca APIs by adding the oc_ prefix everywhere
- Naming consistency tweaks, eg create_from_memory vs. create_from_data
- Adhering to a more consistent convention when pairing functions defining entities lifetime, eg. create/destroy, push/clear, alloc/recycle, init/cleanup
- Preferring oc_str8 to const char*, except when we expect lots of C string literals (e.g. when tagging UI widgets) or when it would be annoying to systematically wrap data we want to read/write into a string
- Reorganize macros for asserts/logging, and properly exposing them to the apps with non conflicting names
- Generally rearrange some bits and pruning unused stuff to make things more navigable
2023-08-18 16:30:55 +02:00
Reuben Dunnington c8dc466449
pong: restore NOTE/TODO comment formatting 2023-08-15 11:57:00 -07:00
Reuben Dunnington 55347f315c
clang-format tweaks
* enforce unix-style line endings
* don't format comment leading spaces
* don't sort includes
2023-08-15 07:11:34 -07:00
Reuben Dunnington c99217920f
collapse some weird if formatting 2023-08-14 14:09:22 -07:00
Reuben Dunnington 69860792df
tweak pong main.c to keep matrix formatting 2023-08-14 11:53:12 -07:00
Reuben Dunnington aa09da6f20
add .clang-format 2023-08-14 11:52:41 -07:00
Martin Fouilleul 9ae9562ca7 remove .gitmodule 2023-08-13 15:38:48 +02:00
Martin Fouilleul cf88ba6290 This commit restructures the codebase to melt the milepost platform layer into the main orca codebase.
Here's a list of commits squashed in this update:

- move angle files to ext/ and pull includes/libs from there when needed
- remove milepost/ext/angle_headers
- Collapsed milepost/ext into ext
- Collapse milepost/scripts into scripts/
- collapse milepost/resources into resources/. WARN: this temporarily breaks milepost's native examples
- collapse milepost/test into test/
- renamed test/ to tests/
- build milepost directly into build/bin
- remove unused GLES and KHR folders from sdk/
- reorganizing milepost directory tree into app, graphics, platfrom, ui, util
- collapse milepost/src to src/
- Move all native examples to sketches/ and remove milepost repo
- Moving sketches resources into their own shared folder separate from the runtime's resource folder
- Moving all binding code to src/wasmbind
- Moving all binding code to src/wasmbind
- pong: fix typo in error log
- fixing log parameter order
- add error logs to mg_image_create_*
- Fix build scripts on windows
- fixed include mistake after rebase
- collapsing milepost.{h|c|m} to orca.{h|c|m} and moving from sdk/ to src/
- rename orca_app.h/main.c to runtime.h/c
- collapsed sdk/ to src/
- put old sdk files into their respective dirs
- renamed canvas_api.json to surface_api.json
- moved all stb headers in ext/stb/
- remove unused OpenSansLatinSubset.ttf font
- moving cstdlib to src/wasmlibc and removing some duplicates with src/platform
- move libc stdarg and string functions from platform/ to wasmlibc/
- rename wasmlibc to libc-shim to reflect non-completeness
- Expose abort/assert variadic functions and macros to orca apps, and forward libc-shim abort/assert to these
- move Orca API runtime implementations to runtime_xxx
- fix missing math constants when including math.h with msvc in graphics_common.c
- Change name of runtime to orca_runtime. When bundling on Windows, change name of runtime executable to the name of the app.
2023-08-13 15:28:57 +02:00
martinfouilleul 72bb238d08 [canvas] fix canvas max tile queue count. Off-by-one was causing some paths to be culled in segment setup shader's bounds check 2023-08-13 14:51:27 +02:00
martinfouilleul 39010f5365 untrack generated samples\fluid\src\glsl_shaders.h 2023-08-11 11:19:25 +02:00
Ilia Demianenko 9da38506ff Fix slider dragging 2023-08-11 08:44:19 +00:00
Ilia Demianenko aee51e62e3 Fix windows build scripts 2023-08-09 15:15:22 -07:00
Martin Fouilleul 4d11ed1be7 [doc] update readme to the new build tools and remove refs to milepost submodule 2023-08-09 12:18:52 +02:00
Martin Fouilleul e0662f3387 Merge remote-tracking branch 'milepost-origin/prepare_orca_submodule_merge' into main
This brings the old milepost submodule tree, along with its history, into the Orca repository, so we don't have to deal with git submodule issues anymore.
2023-08-09 11:42:07 +02:00
Martin Fouilleul c2fe529243 Preparing milepost submodule merge. Remove milepost submodule. 2023-08-09 11:39:45 +02:00
Martin Fouilleul 6d33ee45dd Preparing milepost submodule merge. Moving all files into milepost folder 2023-08-09 11:36:16 +02:00
Martin Fouilleul eb9db393ba Merge branch 'gl_texture_fetch_barrier_bit' into main 2023-08-09 10:56:18 +02:00
MartinFouilleul b6462ca5f8 Merge pull request '[win32] Use wheel scroll lines system setting to determine how much to scroll' (#7) from ilidemi/milepost:win32-scroll-lines into main
Reviewed-on: MartinFouilleul/milepost#7
2023-08-09 08:22:45 +00:00
Ilia Demianenko 60083c1f2e [win32] Use wheel scroll lines system setting to determine how much to scroll 2023-08-08 20:46:48 -07:00
Martin Fouilleul e4d9955e83 [gles] expose GLES surface and GLES API to orca apps.
- Allow orca app to request either Canvas or GLES surfaces
- Add bounds check specifications to the json bindings spec format and to the bindings generator scripts.
- Generate GLES API json bindings spec from gl.xml
- Remove APIs that can't be bound with current wasm memory model (ie buffer mapping)
- Manually link remaining APIs, except glGetString
- Add fluid simulation sample
- Add abort messages for wasm loading and runtime fatal errors
- Adapt orca build tool to generate GLES json spec from gl.xml
- Adapt glesTriangle and fluid samples build scripts to new orca build tool
2023-08-08 22:54:29 +02:00
Martin Fouilleul d01dc832fb [gles] Support for exposing GLES surfaces to orca apps
- update gles surface example
- add mp_dispatch_on_main_thread_sync() to osx threads
- add /experimental:c11atomics to glesTriangle build.bat
- mp_dispatch_on_main_thread_sync: win32 impl
- move mp_dispatch_on_main_thread_sync() on app layer
- configure dlmalloc to not assume contiguity. This allows us to reserve blocks on our end without trashing malloc-owned zones. This way we can add a block to store GL static strings when needed.
- implement deselect interface
- Log an error when an OpenGL function is called while no OpenGL API is selected, or if that function is not part of the selected API
- avoid dispatching calls to image or canvas API if surface is not selected. However, we could later allow it and temporarily select the surface _on behalf of the user_.
- Adding support for format string and optional parameters in assert macros
2023-08-08 22:15:53 +02:00
bvisness 3fae3252a1 Convert build scripts to Python (#31)
All the tooling has been built into a new command-line tool, `orca`. To use it, just run `orca -h`.

To build the samples, you must first install the orca tooling by running `orca dev install`. This simulates what it will be like to actually use the orca tooling as an end user, without the source checked out. Mostly. (I don't yet have it downloading pre-built copies of the Orca runtime libraries and `orca.exe`.)
Co-authored-by: Ben Visness <ben@bvisness.me>
Co-authored-by: Ben Visness <bvisness@gmail.com>
Co-authored-by: Martin Fouilleul <martinfouilleul@gmail.com>
Reviewed-on: #31
Co-authored-by: bvisness <ben@handmade.network>
Co-committed-by: bvisness <ben@handmade.network>
2023-08-08 09:38:43 +00:00
MartinFouilleul c103c001f7 Merge pull request 'Python build script updates' (#6) from build-python into main
Reviewed-on: MartinFouilleul/milepost#6
2023-08-08 09:32:41 +00:00
Ben Visness e20a743605 Delete build scripts in favor of parent orca scripts 2023-08-07 23:00:27 -05:00
MartinFouilleul 6221370aa0 Merge pull request 'mp_thread' (#3) from mp_thread into main
Reviewed-on: MartinFouilleul/milepost#3
2023-07-31 18:06:54 +00:00
Reuben Dunnington 32ac59cd7e
fix compile error on macos 2023-07-31 09:46:18 -07:00
Reuben Dunnington 6ec113b708
examples: replace pthread with mp_thread 2023-07-30 21:21:25 -07:00
Reuben Dunnington 003af621a0
expose platform_thread.h to users of milepost 2023-07-30 21:08:29 -07:00
Reuben Dunnington ff5e6e6039
add win32 platform_thread.h implementation 2023-07-30 20:59:00 -07:00
Reuben Dunnington 58210d1884
reworking thread exit code API to make it easier on win32 2023-07-30 20:58:10 -07:00
Reuben Dunnington baab4036c4
platform thread naming pass 2023-07-30 19:28:15 -07:00
martinfouilleul a4763d2da8 [gl canvas] add texture memory barrier between raster pass and blit pass 2023-07-29 12:36:55 +02:00
Martin Fouilleul 442d86386e Merge branch 'batch_multi_image' into main
This allows the renderer to use multiple source textures per batch, and thus create less batches (and less draw calls). It also doesn't create a separate batch for non-image fills/strokes. This greatly improves perf especially when interleaving images and solid color commands. When using lots of images though, it is still recommended to use an atlas, which ensures everything fits in a single batch.
2023-07-28 10:48:52 +02:00
martinfouilleul b05caf984c [gl canvas] allow multiple textures per batch 2023-07-27 20:07:07 +02:00
Martin Fouilleul c983c39f44 [canvas] removed old begin/end/renderBatch function pointers 2023-07-27 18:11:34 +02:00
Martin Fouilleul 203adfd470 [mtl canvas] allow using multiple textures per batch 2023-07-27 16:46:10 +02:00
Martin Fouilleul 0c8e698b6e [mtl canvas] don't trigger a new batch when setting the current image to nil (avoids creating a lot of batches when we just alternate between the same image and no image, eg painting multiple instances of the same image with a stroked border) 2023-07-27 16:10:30 +02:00
martinfouilleul 392bd3a756 Merge branch 'new_gl_canvas' 2023-07-27 15:38:55 +02:00
martinfouilleul b300cc4d7d [gl canvas] balance dispatch of raster shader along 2 dimensions to avoid hitting the max workgroup count per dimension 2023-07-27 15:24:20 +02:00
martinfouilleul 3c103eeb65 [canvas, gl] compute intermediate glsl structs' sizes according to std430 2023-07-27 14:38:12 +02:00
martinfouilleul ae862b39ba [win32, gl canvas] grow intermediate gl buffers as needed 2023-07-27 12:40:52 +02:00
martinfouilleul a35f0b82b2 [win32, gl canvas] bound check intermediate buffers in canvas shaders 2023-07-27 12:11:30 +02:00
martinfouilleul 680deb35b0 [win32, gl canvas] grow path and element input buffers as needed 2023-07-27 11:37:39 +02:00
martinfouilleul 0caeccd3fb Merge branch 'autoresize_surfaces' 2023-07-26 17:41:50 +02:00
martinfouilleul 0785b6b637 [win32]
- Take drop shadown into account when calling SetWindowPos (milepost window frame _excludes_ the drop shadow)
- Fix mp_window_center()
2023-07-26 17:35:58 +02:00
martinfouilleul 2c0d3268e7 [win32] update window rect API 2023-07-26 16:50:45 +02:00
Martin Fouilleul 1fd9d17e82 [osx] settle on consistent API for getting/setting window rect 2023-07-26 15:54:01 +02:00
Martin Fouilleul 06b5d30dc6 [osx] correctly pass move/resize contents and frame rect relative to top-left instead of bottom left 2023-07-25 18:05:55 +02:00
Martin Fouilleul e7cce5e36f [osx, surface] use autoresizeMask to resize surfaces to the parent window's client area 2023-07-25 17:02:11 +02:00
martinfouilleul a4ae1cf214 [win32, surface] Fix auto-selecting surface when first creating one ; checking why smooth resize still doesn't work even though we receive events and draw in a separate thread 2023-07-25 15:55:09 +02:00
martinfouilleul 3816e85592 [win32, surface] always resize surface to parent window's client area 2023-07-25 14:18:02 +02:00
martinfouilleul 985aed852a [app] change mp_move_event to mp_mouse_event and mp_frame_event to mp_move_event. Transmit both window frame and contents rect in move/resize events 2023-07-25 13:40:25 +02:00
martinfouilleul 2a4e90cf9a [win32, canvas] Fix padding of mg_gl_screen_tile 2023-07-16 17:12:34 +02:00
Martin Fouilleul 8c885223d3 [osx, canvas] revert to 16 pixel wide tiles. 32 gives some benefit for a few large paths, but degrades too much for higher segment counts 2023-07-15 17:32:18 +02:00
martinfouilleul bff9a3618f [win32, canvas] use glBindBufferBase() and explicit uniform offset to avoid glBindBufferRange() implementation-specific alignment issues 2023-07-15 15:29:45 +02:00
Martin Fouilleul 6a3cb83932 Merge branch 'ilidemi-orca_ui' into main 2023-07-15 11:42:48 +02:00
Ilia Demianenko e7982b7786 Just use MP_KEYMOD_MAIN_MODIFIER instead of OS_COPY_PASTE_MOD 2023-07-15 00:54:57 -07:00
Ilia Demianenko e6c271c3f5 minor 2023-07-15 00:35:02 -07:00
ilidemi 2214974804 Merge branch 'main' into orca_ui 2023-07-15 07:21:41 +00:00
Ilia Demianenko 445325d45f Merge branch 'orca_ui' of git.handmade.network:ilidemi/milepost into orca_ui 2023-07-15 00:17:53 -07:00
Ilia Demianenko 40906bb852 Feedback 2023-07-15 00:15:12 -07:00
martinfouilleul 782b7f54ae [win32, canvas] only dispatch raster shader for tiles touched by paths 2023-07-14 18:58:18 +02:00
martinfouilleul 1c244c2a00 [win32, canvas] only sample coverage at 8x and source textures at 2x, and accumulate in a single color value per pixel 2023-07-14 17:37:33 +02:00
Martin Fouilleul ec0f22a9d8 [osx, canvas] keep op buffer size to 4<<20 for now 2023-07-14 16:28:45 +02:00
ilidemi ff1460e629 Merge branch 'main' into orca_ui 2023-07-14 04:57:45 +00:00
Ilia Demianenko 8bfbabd877 Orca UI support 2023-07-13 21:36:31 -07:00
martinfouilleul 660ad33ddc [win32, gl canvas] persistently map input buffers 2023-07-12 15:54:02 +02:00
martinfouilleul 6944325014 [win32, canvas] rolling input buffers 2023-07-12 15:52:48 +02:00
martinfouilleul 684543ec15 [gl canvas] fix implicit boolean conversion error on some drivers 2023-07-12 15:46:52 +02:00
Martin Fouilleul 025ebd91d5 [osx, canvas]
- Pass buffer lengths to kernels and bound check when allocating from buffers
- Dynamically compute/guess size of intermediate buffers and grow if needed
2023-07-11 20:03:17 +02:00
Martin Fouilleul 98a516ff0a [osx, canvas] start with small input buffers and grow them as needed 2023-07-11 17:00:17 +02:00
Martin Fouilleul fc07a0d018 [osx, canvas] use 32 pixels-wide tiles 2023-07-11 14:27:15 +02:00
Martin Fouilleul 9e8a0f5f69 [osx, canvas] Only dispatch raster shader for tiles that are overlapped by at least one path. 2023-07-10 20:20:18 +02:00
Martin Fouilleul bfc7530bcf [osx, canvas]
- Only super sample coverage at 8x rate, and accumulate pixel color in a single color value
- Super sample images at lower 2x rate
- Cull tiles outside clip
- Bypass coverage for fully covered tiles
2023-07-10 17:52:34 +02:00
Martin Fouilleul a65b0cc1bb [osx, surface] Query list of available metal devices, and select a discrete GPU if available. This way we avoid calling MTLCreateSystemDefaultDevice() which messes with Discord's screen sharing, while also being able to take GPU frame captures in XCode (which was broken by 9bfae2c4e8) 2023-07-10 11:28:49 +02:00
Martin Fouilleul 7573c40c56 [mtl, canvas] remove unused hull matrix 2023-07-07 16:44:32 +02:00
martinfouilleul 59fdc27ac6 [gl, canvas]
- Haul path color and texture sampling outside of per-sample loop
- Pack gl input structs a bit
- Set correct hint flags for glBufferData()
2023-07-07 15:45:06 +02:00
Martin Fouilleul 9bfae2c4e8 [osx, metal] Set metal layer's device to layer.preferredDevice instead of calling MTLCreateDefaultSystemDevice(). This fixes issue 15 so we can use Discord's screen sharing while using Orca. This will need to be revisited when we want to actually use a different metal device. 2023-07-07 10:41:17 +02:00
martinfouilleul 806f00417e [win32, canvas] Fix random crash by correctly setting wgl_surface deselect function pointer to mg_wgl_deselect(). Forgot to do it in 18c793db, dumb me. 2023-07-06 11:29:57 +02:00
martinfouilleul 1e34c3406f fixing conflict in gl_canvas 2023-07-05 18:07:37 +02:00
Ben Visness ff5a57fb92 Add some convenient rectangle accessors 2023-07-04 16:13:28 -05:00
martinfouilleul bdb9ddf888 [win32, canvas] added back texture atlasing and fixed incorrect culling of solid tiles when using a source texture 2023-07-04 17:24:41 +02:00
martinfouilleul 5c4c8ce505 [wip, win32, canvas] adding back textures 2023-07-04 15:59:45 +02:00
martinfouilleul 311cef65e8 [wip, win32, canvas] dispatch path setup, segment setup and backprop in batches of GL_MAX_COMPUTE_WORK_GROUP_COUNT elements 2023-07-03 16:16:39 +02:00
martinfouilleul e24a872fad [wip, win32, canvas] encode strokes 2023-07-03 15:16:27 +02:00
martinfouilleul d00024b515 [wip, win32, canvas] added MSAA to new canvas renderer 2023-07-03 15:00:40 +02:00
martinfouilleul 0e6d67f636 [wip, win32, canvas] Cubics segment setup 2023-07-03 14:21:53 +02:00
martinfouilleul 01aa4f838f [wip, win32, canvas] quadratics 2023-07-03 12:14:21 +02:00
martinfouilleul 899ad4c030 [wip, win32, canvas] Correctly setup path index in segment_setup.glsl 2023-07-03 11:02:04 +02:00
martinfouilleul 36c75a55dd [win32] Fix first image not being rendered in win32 canvas renderer 2023-07-02 12:49:45 +02:00
martinfouilleul b61d8868d3 [wip, win32, canvas] wip trying to fix multiple shapes 2023-07-02 12:26:54 +02:00
martinfouilleul 7628138cee [wip, win32, canvas] tiling in per-path tile queues, then merge (no backprop for now) 2023-06-30 16:53:36 +02:00
martinfouilleul f0b7cf32a9 [wip, win32, canvas] winding backprop and right crossing segments 2023-06-30 15:30:05 +02:00
martinfouilleul 0870097262 [wip, win32, canvas] bin segments to screen tile queues 2023-06-30 15:18:37 +02:00
martinfouilleul 15c54b9385 [wip, win32, canvas] segment setup, non tiled 2023-06-29 16:43:38 +02:00
martinfouilleul f76ff94c28 [wip, win32, canvas] raster elements directly per pixel 2023-06-29 15:48:52 +02:00
Ben Visness 23984e8370 Enable font stuff in Orca 2023-06-28 20:44:13 -05:00
martinfouilleul b797f187dc [wip, win32, canvas] porting new canvas renderer to opengl 2023-06-27 18:53:09 +02:00
Martin Fouilleul 21aa1bef68 [win32] honor timeout value in mp_pump_events 2023-06-26 19:59:34 +02:00
Martin Fouilleul 0d65d19436 str8_to_cstring forwards to str8_push_copy(), which null-terminates the copy 2023-06-26 16:24:12 +02:00
Martin Fouilleul ffb900d872 String functions that return str8/16/32 allocated on an arena implicitly zero-terminate strings, so we can avoid one copy when passing to C stdlib APIs 2023-06-26 16:06:26 +02:00
Martin Fouilleul 4b491ee94a - Defined mp_thread_local to nothing for Orca platforms (since this requires atomics, which we don't have yet). This allows use to enable bulk-memory without getting clang backend errors about missing tls and atomics.
- Replaced memory copy/fill routines with builtins
2023-06-25 20:29:50 +02:00
Martin Fouilleul 98a67cef72 #define MORECORE to orca_mem_grow. Removed builtin memory routine that don't seem to be supported by wasm3 (TODO: investigate that later) 2023-06-25 20:29:50 +02:00
Ben Visness bcf84e0b80 Graphics and memory stuff for stb_image 2023-06-25 20:29:50 +02:00
Martin Fouilleul bc03887148 Added ORCA_IMPORT to mark symbols imported from the runtime 2023-06-25 20:17:01 +02:00
Martin Fouilleul 28e0a6c88e Add tag to io_op enum, for debugging convenience 2023-06-23 17:24:18 +02:00
Martin Fouilleul 18c793dbb4 When we call mg_surface_prepare() on a surface, select it in a per-thread handle. Automatically call deselect on the selected handle when preparing another surface. Also have a way to deselect whichever surface is currently selected. This is needed for some backend that explicitly need to be 'unbound' before using them from another thread 2023-06-23 15:32:32 +02:00
martinfouilleul 83f128fb55 [win32, graphics] adding example to test rendering in a secondary thread 2023-06-21 19:14:56 +02:00
martinfouilleul 0366e3d724 [win32, graphics] experiments with multisurface with transparent top-level windows 2023-06-21 15:48:26 +02:00
martinfouilleul ae7a60b942 [win32, graphics, wip] working on multi surface, currently using top-level transparent window and moving them to cover the 'parent' window area... 2023-06-21 12:36:05 +02:00
Martin Fouilleul c357da97f6 add multi surface skeleton example 2023-06-20 11:47:02 +02:00
Martin Fouilleul 26a1af344c Fix rpath in examples 2023-06-20 11:45:59 +02:00
martinfouilleul d9a9215fa8 Fixed bug in mem_arena_alloc when selecting chunk from which to allocate 2023-06-19 17:09:31 +02:00
martinfouilleul 2fe683b79d fixed include directives to avoid having to pass to much include paths in usage scripts 2023-06-19 16:16:54 +02:00
martinfouilleul d2c4acf6e2 [wip] adding missing impl for win32 version of orca 2023-06-17 20:09:25 +02:00
martinfouilleul e93bf76adc [win32] silence warning about WIN32_LEAN_AND_MEAN redefinitions 2023-06-16 20:06:02 +02:00
martinfouilleul 6499bcd2a2 [win32] fixing include directives to avoid having to pass all include dirs to compiler 2023-06-16 19:48:33 +02:00
martinfouilleul debcffce2a [win32, io] win32 passes files io test with new common io_open_at implementation 2023-06-16 15:30:48 +02:00
Martin Fouilleul a64c86ca4e [io, test] Added more file io tests 2023-06-16 11:57:53 +02:00
Martin Fouilleul ec53cd5416 [io, osx] Reorganize to first compute flags/do checks etc., then enter next path element at a single callsite 2023-06-15 20:01:52 +02:00
Martin Fouilleul d363c8b607 [wip, osx, io] reorganizing io_open_restrict, fix opening last element with the correct flags 2023-06-15 18:27:33 +02:00
martinfouilleul c71da9e761 [io, win32] separate 'raw io' primitives from the io_open_restrict() implementation 2023-06-14 19:41:51 +02:00
martinfouilleul 49643520ee [win32, io] adding context struct for use in io_open_path_restrict() 2023-06-14 18:35:33 +02:00
martinfouilleul 5d2bf9eab9 [wip, win32, io] win32 file io passing tests (still work to do though) 2023-06-14 17:21:31 +02:00
martinfouilleul 0fa6dcd2ea [win32, io]
- Added str16 functions for dealing with win32 wide char strings
- Added io_open_relative to open a path relative to an already opened handle (with no escape checking)
2023-06-14 12:03:50 +02:00
Martin Fouilleul 529a13867c fix git handling of symlink 2023-06-13 20:06:20 +02:00
martinfouilleul 9954b69eda [win32, io] implement IO_OP_OPEN_AT with non-null base directory handle 2023-06-13 19:53:06 +02:00
Martin Fouilleul 0bd985efbc [io] restrict rights of files open with file_open_at to the rights of the directory handle 2023-06-13 15:56:19 +02:00
Martin Fouilleul b147aed85c - Added tests for sandboxing file io with file_open_at() and FILE_OPEN_RESTRICT
- Fixed bug in io_open_restrict() that closed the dir file descriptor, making it impossible to use it in subsequent calls.
2023-06-12 18:04:59 +02:00
Martin Fouilleul b2d2d2a587 [io] implementing IO_OP_OPEN_AT with FILE_OPEN_RESTRICT flag for sandboxing file access 2023-06-11 18:20:21 +02:00
Martin Fouilleul c041b212ab [io] removed IO_OP_POS, wrap IO_OP_SEEK with offset 0 and flag FILE_SEEK_CURRENT instead 2023-05-31 11:38:17 +02:00
martinfouilleul a1b3195ddf [win32, io, wip] add fstat operation (type/size/perms for now, TODO: times) 2023-05-26 18:01:44 +02:00
martinfouilleul 3667ab30e0 [win32, io, wip] add win32 io impl. for open/close/seek/read/write 2023-05-26 16:03:23 +02:00
Martin Fouilleul 41b6128a35 [io] testing abstracted io 2023-05-26 11:40:00 +02:00
Martin Fouilleul c75661cfc9 [io] abstract file io API, using a request/completion model ala io_uring (w/ only synchronous completion for now), and per-platform backend 2023-05-25 20:08:38 +02:00
Martin Fouilleul debffac5c0 [path] use new mem_scratch_begin_next() API in path functions, to handle the case where passed-in result arena is itself a scratch arena 2023-05-24 20:36:05 +02:00
Martin Fouilleul ba125ae860 [mem] change scratch arena API to allow using independant scratch for temporary computations and results 2023-05-24 20:17:03 +02:00
Martin Fouilleul 02bfe587c8 [path] adding platform path functions 2023-05-24 16:27:39 +02:00
Martin Fouilleul 43c23627e2 Merge branch 'win32' into orca 2023-05-24 15:11:32 +02:00
martinfouilleul db0dadd128 [win32] allow specifying start folder in open/save dialogs 2023-05-23 17:24:38 +02:00
martinfouilleul ed45d88cfd [win32] add file type filters to open/save dialogs 2023-05-23 16:43:57 +02:00
martinfouilleul 49de9d0290 [win32] added basic mp_save_dialogue() implementation using COM IFileSaveDialog 2023-05-23 16:04:49 +02:00
martinfouilleul e24500e18d [win32] added basic mp_open_dialog() implementation using COM IFileOpenDialog 2023-05-23 15:59:29 +02:00
martinfouilleul a54c8b4f4b [win32] alert popup using TaskDialogIndirect(): automatically handles icons, dpi, and text/buttons layout (but requires Vista or higher) 2023-05-23 14:50:31 +02:00
martinfouilleul f1d8dd1ca9 [win32] crappy message box with custom button text. Not DPI aware, doesn't show message box image (eg exclamation/information mark), and has very crude layout... 2023-05-23 12:55:57 +02:00
Martin Fouilleul 83aea67305 [perf_text example] track CMUSerif-Roman.ttf 2023-05-22 10:13:52 +02:00
Martin Fouilleul 259d381e56 [perf_text example] track CMUSerif-Roman.ttf 2023-05-22 10:10:08 +02:00
martinfouilleul a6a37c874e [win32] adding prototypes for open/save/alert dialogs in win32_app.c 2023-05-17 16:50:07 +02:00
martinfouilleul 2a01cba026 [ui] Fix ui scrolling 2023-05-17 15:48:25 +02:00
martinfouilleul 9f7cfd985c [win32] re-introduced perf_text, tiger, and ui examples 2023-05-17 15:14:14 +02:00
martinfouilleul 2bec7a633a [win32] reflected changes to canvas surface interface on GL backend. But implementation still uses the (slower) Loop-Blinn + triangle fan method. 2023-05-16 18:06:22 +02:00
martinfouilleul b6db5107a3 [win32, wip] simple GL triangle example 2023-05-12 16:50:14 +02:00
martinfouilleul 52538248d9 [win32, wip] compile and run simple window example 2023-05-12 16:46:13 +02:00
martinfouilleul 62b8b3323e [win32, wip] Remove input state from win32_app code 2023-05-12 11:42:35 +02:00
martinfouilleul 2bf6a4f007 Fixed void pointer arithmetic in hash.c to avoid pedantic error on msvc 2023-05-12 11:13:55 +02:00
Martin Fouilleul 9b29e681fe Merge commit 'e426319' into orca (integrate fix to mg_image_size(), which doesn't need a current canvas anymore) 2023-05-10 11:20:30 +02:00
Martin Fouilleul e426319723 Fix mg_image_size() (doesn't need a current canvas anymore) 2023-05-10 11:18:36 +02:00
Martin Fouilleul 3f1447f729 Always put arena pointer in mem_arena_marker, to avoid possible DEBUG value discrepancy between lib and client code 2023-05-09 18:29:32 +02:00
Martin Fouilleul 1ab1d70df2 Fix image data not storing surface handle in mg_image_create() 2023-05-08 13:01:45 +02:00
Martin Fouilleul 39e96e0739 Added xxhash64 hash function and use that instead of x64-specific aes hash, until we get an arm version 2023-04-29 19:25:40 +02:00
Martin Fouilleul f69a6b31ae update angle install notes 2023-04-26 15:58:42 +02:00
Martin Fouilleul b27dc615d1 Finish separating graphics_common and graphics_surface + add platform_math, so that we can compile graphics_common to wasm in orca 2023-04-26 14:56:02 +02:00
Martin Fouilleul ca1caf8537 splitting graphics_surface and graphics_common in order to isolate surface dispatch stuff from orca apps 2023-04-25 22:15:56 +02:00
Martin Fouilleul 346979a21a [canvas] change surface/canvas APIs to treat canvas a 'just another kind of surface', and split canvas implementation (managed by surface) from canvas _command buffer_ and implicit context (represented by mg_canvas) 2023-04-25 19:13:15 +02:00
Martin Fouilleul 32d7d91893 [wip] changed ui_begin_frame() to take explicit canvas size 2023-04-25 15:10:05 +02:00
Martin Fouilleul 3769b70753 [wip] changing backend enum to api enum, and adding canvas api in here 2023-04-25 14:54:52 +02:00
Martin Fouilleul 7c273f494b [ui, logging]
- Changed workings of ui_panel() and scrolling to make it easier for usage code to control scrolling.
- Renamed logging functions
2023-04-20 15:40:00 +02:00
Martin Fouilleul bb6b68ad73 [event system] allocate events and additional payload (e.g. file paths) directly in ring buffer, and copy them to user-supplied arena in mp_next_event() 2023-04-19 16:16:36 +02:00
Martin Fouilleul ab150f94f2 separating input state from app, so that it can be used in different threads that main thread. E.g. ui context uses its own input state that can be fed events in a second thread 2023-04-19 11:28:20 +02:00
Martin Fouilleul f1d6e0f15c remove unnecessary platform headers from utf8 files 2023-04-18 18:42:48 +02:00
Martin Fouilleul ff4dddc0b7 moved assert to platform layer 2023-04-18 18:36:06 +02:00
Martin Fouilleul 794f47b141 abstracting logging for orca 2023-04-18 18:05:54 +02:00
Martin Fouilleul 86a16d3775 modifications to log system to support orca env where stdio is not defined 2023-04-18 14:33:27 +02:00
Martin Fouilleul 0d6fb197fb adding vargs and asserts for orca 2023-04-18 10:43:52 +02:00
Martin Fouilleul e9e9ab68c2 base memory allocator and chunked arenas for orca 2023-04-17 18:12:21 +02:00
Martin Fouilleul f36e144bc0 start integrating milepost components to orca 2023-04-17 10:55:19 +02:00
Martin Fouilleul c347e10577 Put all dependency libraries and shaders in bin directory 2023-04-12 16:12:26 +02:00
Martin Fouilleul f35e91a38c [mtl renderer] fixed clipping 2023-04-11 14:51:58 +02:00
Martin Fouilleul b7f5b84123 [mtl canvas] remove old metal canvas stuff 2023-04-11 11:19:29 +02:00
Martin Fouilleul 03b5802529 [canvas] replace simple shape helpers with normal paths operations instead of having dedicated primitives for rounded rects/ellipses and so on 2023-04-11 11:16:23 +02:00
Martin Fouilleul c6e89c1869 [wip] adding smooth live-resizing example 2023-04-11 10:50:14 +02:00
Martin Fouilleul 551d5e084e [mtl renderer] re-introduced texturing 2023-04-09 19:24:32 +02:00
Martin Fouilleul ee3e55dadd [mtl renderer] fix msaa sample positions 2023-04-08 12:11:38 +02:00
Martin Fouilleul effd8f1dd0 [mtl canvas] use same ccw test for testing against diagonal and testing against hull 2023-04-08 10:04:17 +02:00
Martin Fouilleul 2b7aadf180 [mtl canvas] multi-sampling 2023-04-07 18:18:50 +02:00
Martin Fouilleul 65b5a4b52a [mtl renderer] Fixed curve slicing which used matrix operation and re-parameterization, which could create gaps in path. Now use blossoms, which ensure endpoints of subcurves match 2023-04-07 17:17:55 +02:00
Martin Fouilleul d1fab449bc [mtl canvas] Fixed loop implicit matrix 2023-04-07 10:15:37 +02:00
Martin Fouilleul c4e866d9d4 [mtl canvas] Fix shader contents scaling 2023-04-05 10:31:50 +02:00
Martin Fouilleul 4c4f27066b [mtl renderer] re-introduced end caps 2023-04-05 10:25:48 +02:00
Martin Fouilleul e999af6bd3 [mtl canvas] make diagonal checks inclusive in mtl_side_of_segment() 2023-04-05 10:19:25 +02:00
Martin Fouilleul 53946a5710 [mtl canvas] fix end joint not generated for paths with only 2 elements 2023-04-05 09:52:12 +02:00
Martin Fouilleul 2484cdf7b3 [mtl canvas, wip] re-introducing joints 2023-04-04 20:35:48 +02:00
Martin Fouilleul 8d7fdf3b1a [mtl canvas, wip] Fixing inclusive/exclusive bound checks during curve side tests / shortcut / rasterization 2023-04-04 19:02:53 +02:00
Martin Fouilleul 9322db8201 [mtl canvas, wip] cubic bézier implicitization 2023-04-01 19:46:35 +02:00
Martin Fouilleul 767841f9c6 [mtl canvas, wip] Fixed wrong backdrop when segment ended right on tile's bottom boundary 2023-03-30 16:41:41 +02:00
Martin Fouilleul 93998852bb [mtl canvas, wip] Re-introducing quadratics implicitization 2023-03-30 15:58:46 +02:00
Martin Fouilleul eee158ff85 [mtl canvas] tmp fix of clear color (revisit one we re-introduce texturing) 2023-03-29 16:30:16 +02:00
Martin Fouilleul 8af4e4eddc [mtl canvas, wip] Collate queues in a per-tile op list and prune occluded shapes 2023-03-29 16:21:28 +02:00
Martin Fouilleul a6c53649bd [mtl canvas, wip] implemented backprop 2023-03-29 14:27:05 +02:00
Martin Fouilleul c4415aaeea [mtl canvas, wip] binning segments to tile queues 2023-03-28 17:58:23 +02:00
Martin Fouilleul c71bc5be98 [mtl canvas] segment setup pass 2023-03-28 15:10:05 +02:00
Martin Fouilleul f6a992e5f4 [mtl canvas] very first draft of new canvas backend based on edge-counting instead of triangle overlap 2023-03-28 13:09:48 +02:00
Martin Fouilleul c20758f6a2 [mtl canvas] cull tiles queues outside viewport 2023-03-22 17:28:11 +01:00
Martin Fouilleul faf024a63a [mtl canvas] reorganizing the loop in render kernel to allow different commands 2023-03-22 16:40:43 +01:00
Martin Fouilleul e9ecd9d521 [mtl canvas] Fix artifacts on tiger that was due to epsilon comparison for cubics equation in draw kernel. Removed that (now do <= 0), but then we need to weed out false negatives for solid triangles. So we compute if the triangle is solid in the triangle kernel and store it in the mg_triangle_data struct for now. 2023-03-22 15:02:04 +01:00
Martin Fouilleul b0be21795e [mtl canvas] prevent tiles entirely covered by textured shapes to be treated as solid (as the texture could be non-uniformly transparent) 2023-03-22 12:02:13 +01:00
Martin Fouilleul 26f669f3c1 [mtl canvas] adding a color command for fully covered, solid color tiles. This is not much of an improvement for now because the tile array just got bigger, but maybe we can use the same scheme and compact it into an int 2023-03-22 10:46:56 +01:00
Martin Fouilleul 90b00979ed [mtl canvas] detecting full covered/uncovered tiles 2023-03-22 09:23:22 +01:00
Martin Fouilleul 0d8bc824a2 [mtl canvas] bucket triangles into per-shape tile queues, then gather into tile arrays. This somewhat improves perf for perf_text test and avoids an awful degradation due to sorting in tiger test (tiger now runs at ~20fps, which is still much slower than it could be, but the triangle coverage method we're using just incurs too much cross product computations...) 2023-03-21 10:22:37 +01:00
Martin Fouilleul a4ef58f2d8 [mtl canvas] Tiling per rectangles into per-shape tile queues (linked lists of triangle indices) to avoid sorting 2023-03-20 16:46:12 +01:00
Martin Fouilleul 11113f597c [mtl canvas, exp] try tiling per tile and avoiding sorting pass (worse on simple shapes and text, but degrades slower with complex scenes (eg tiger). Not great though) 2023-03-20 10:08:17 +01:00
Martin Fouilleul 92f4909d63 [mtl canvas] testing the metal canvas rendering the ghostscript tiger, and acknowledging it's painfully slow 2023-03-18 14:35:51 +01:00
Martin Fouilleul 1d36088302 [mtl canvas] render to an intermediate texture and acquire the drawable and blit to it only at the end of all compute passes 2023-03-16 10:25:56 +01:00
Martin Fouilleul f14f397c99 [mtl surface] don't re-acquire drawable if there's already a valid one acquired 2023-03-15 18:51:50 +01:00
Martin Fouilleul bd8e31c535 [mtl canvas] triple buffer vertex/index/shape buffers 2023-03-15 17:48:39 +01:00
Martin Fouilleul 0c74e997ae [mtl surface] fix crash on exit when metal GPU frame capture is enabled. Apparently, if we release resources (on exit) before all GPU work is completed, libMetalCapture crashes on bad access. To work around that, in mg_mtl_surface_destroy(), we enqueue a last (empty) command buffer and call waitUntilCompleted on it, to ensure all previous command buffers are also completed 2023-03-15 13:02:18 +01:00
Martin Fouilleul 5ce53001e2 [canvas, mtl] clear resets command count and stores clear color. Ccanvas' backend begin proc now takes a clearColor parameter and clears final surface to that color before drawing any batch 2023-03-15 11:09:42 +01:00
Martin Fouilleul 98bac9744f [mtl canvas] rearranged bounding box computations in tiling shader 2023-03-15 10:19:04 +01:00
Martin Fouilleul f2cb96826c [mtl canvas] fix bias computation for clockwise triangles 2023-03-15 10:04:51 +01:00
Martin Fouilleul 5c1a220f1f [mtl canvas] don't reorder point to make clockwise triangles. Instead, store triangle orientation in triangle struct and multiply orientation in raster test 2023-03-14 15:08:39 +01:00
Martin Fouilleul 221fcbeb6b [mtl canvas] store uv transform and color in triangle data (don't pass vertex or shape buffer to draw kernel) 2023-03-14 12:20:39 +01:00
Martin Fouilleul c9a5b3d52d [mtl canvas] rearranged triangle data for better packing 2023-03-14 09:42:17 +01:00
Martin Fouilleul 1b3583cc6d [mtl canvas] remove box array, cache box in triangle struct 2023-03-14 09:42:12 +01:00
Martin Fouilleul 6536f4ac64 [mtl canvas] fused boxing and tiling, cache cubics in triangle data 2023-03-14 09:40:11 +01:00
Martin Fouilleul ee4a667258 [mtl canvas] trying fused boxing/tiling passes 2023-03-14 09:25:20 +01:00
Martin Fouilleul fd5a4d4cd8 [wip] trying to simplify metal shader 2023-03-14 09:25:09 +01:00
Martin Fouilleul cee294d8ad [mtl canvas] fixed setBuffer that was being called on the wrong encoder 2023-03-14 09:20:51 +01:00
Martin Fouilleul e9d64166a3 [mtl canvas] fixed bug where tiles left and below screen where all bucketed to the first row/column (same as gl version, see 4a8c77f02) 2023-03-13 16:53:12 +01:00
Martin Fouilleul 6da2494c81 [canvas example] fixed movement 2023-03-13 15:53:35 +01:00
Martin Fouilleul 13f025ab21 [mtl canvas] convert triangle rasterization to fixed point 2023-03-13 15:18:18 +01:00
Martin Fouilleul 7c58145524 [mtl surface] Allow setting swap interval to 0. Note however that vsync needs to be turned off at the OS level for that to work smoothly. Otherwise, we get jittery frame rate with stalls when we run off of drawables (I suppose? should investigate some more).
This can be done with Quart Debugger in Additional Tools for XCode.
2023-03-13 12:21:33 +01:00
Martin Fouilleul 716bdc53d4 [ui] draw drop-down button with correct roundness 2023-03-13 10:53:21 +01:00
Martin Fouilleul 5455c2a52b [ui] Allow styling overlay boxes (e.g. menu and drop-down list panels) locally.
- Added an UI_FLAG_OVERLAY flag. When we make a box with that flag set, it is added the an overlayList in the ui context.
- After styling and static size pass, we reparent boxes in the overlayList to an overlay node just below the root node.
- Layout and drawing works uniformly on the whole tree. Overlay boxes get drawn last and steal mouse hover from boxes underneath them.
2023-03-13 10:26:39 +01:00
Martin Fouilleul 9e41d2b6fc [ui] first version of select popup menu 2023-03-12 19:06:09 +01:00
Martin Fouilleul 09951afa53 [ui] added ui_checkbox() helper 2023-03-11 19:06:05 +01:00
Martin Fouilleul b907578eb4 Fix clipping one pixel short 2023-03-11 16:55:30 +01:00
Martin Fouilleul 009fe8e3e8 [ui, styling]Fix order of adding after rules to running list in rule-matching pass 2023-03-11 16:43:58 +01:00
Martin Fouilleul bf92a6f307 Merge branch 'master' of ssh://git.forkingpaths.dev/martinfouilleul/milepost 2023-03-11 16:27:52 +01:00
Martin Fouilleul da7e0f402b [ui, layout] Add UI_FLAG_ALLOW_OVERFLOW_X/Y 2023-03-11 16:27:21 +01:00
martinfouilleul 137a75540b [win32] implemented string clipboard functions 2023-03-09 19:44:55 +01:00
martinfouilleul 359e08b0a8 [ui] set text box cursor to the same color as text 2023-03-09 18:09:04 +01:00
martinfouilleul cae8666561 [ui, win32] Fixed char input and modifier keys 2023-03-09 18:03:27 +01:00
martinfouilleul 9accf4c666 [ui, win32]
- change coord system of gl canvas to match ui
- change mouse coordinate system to match ui
- fix mouse delta
2023-03-09 17:38:41 +01:00
Martin Fouilleul c7d5cf113e [ui] reintroducing tooltip 2023-03-09 16:08:42 +01:00
Martin Fouilleul c362751c23 [ui] menus widgets first draft 2023-03-09 16:02:46 +01:00
Martin Fouilleul feca7d1026 [ui] moved ui_panel() into ui.c 2023-03-09 14:27:46 +01:00
Martin Fouilleul d2f4f5083b [ui, layout] solving layout constraints 2023-03-09 13:13:13 +01:00
Martin Fouilleul 56874c99d6 [ui, layout] layout constraint solving, first draft 2023-03-09 12:36:38 +01:00
Martin Fouilleul a569454df5 [ui, wip] scrolling / scrolling panels 2023-03-08 19:53:28 +01:00
Martin Fouilleul 873d4ab6db [ui, canvas]
- Allow querying the size of the canvas's underlying surface
- Set size of ui root to canvas' size
2023-03-08 15:03:35 +01:00
Martin Fouilleul 1212d714d5 [platform/canvas]
- Changed canvas coordinate system to match UI coord system (origin at top left, y axis down)
- Changed mouse coordinate system to match UI and canvas
- No need to pass width/height to ui_begin_frame() anymore
2023-03-08 13:19:18 +01:00
Martin Fouilleul 7b2ef080e8 [util, formatting] shorten list loop names to for_list_xxx 2023-03-08 12:03:33 +01:00
Martin Fouilleul 3682605f97 [util, formatting] changed list api to snakecase for consistency with the rest of the codebase 2023-03-08 12:00:10 +01:00
Martin Fouilleul bfc19665ce [util]
- shorten str8_lit macro to STR8
- use strlen() in STR8 and remove str8_from_cstring(). Usage with string literal seem to always be optimized by compile-time constant, so there's little need for a confusing macro that only works with literals and breaks with pointers.
- replaced str8_unbox() with str8_lp/str8_ip
2023-03-08 11:40:40 +01:00
Martin Fouilleul f07f56948d [ui] shorten ui styling api names 2023-03-08 11:13:32 +01:00
Martin Fouilleul 8b06cb31ba [ui, styling]
- Put all styling calls _before_ the styled box.
- Renamed full pattern matching API to ui_style_match_next_before/after
- Helper to style next box only (ui_style_next())
2023-03-08 11:09:28 +01:00
Martin Fouilleul c551135933 [ui] remove the need to pass a default style to ui_frame() 2023-03-07 19:44:22 +01:00
Martin Fouilleul 2466241b1e [ui, styling] finished first pass on core layout/styling system 2023-03-07 19:27:01 +01:00
Martin Fouilleul 8032c7340b [ui, styling] revisiting layout/sizing 2023-03-07 19:06:04 +01:00
Martin Fouilleul d3a8a651e5 [ui, styling] make layout and floating properties part of styling system 2023-03-07 10:33:22 +01:00
Martin Fouilleul 7b10a99a8c [ui, styling] First draft of rule-based styling to replace old stack-based system 2023-03-06 19:33:01 +01:00
Martin Fouilleul b52a35c753 [ui, textbox] Fixed selection background rectangle 2023-03-05 17:03:00 +01:00
Martin Fouilleul 1af132352a [ui, textbox] Scroll text inside text box to always show edit cursor. 2023-03-05 16:35:55 +01:00
Martin Fouilleul 592f4cdecd end of line renormalization 2023-03-05 16:05:43 +01:00
Martin Fouilleul 4359bdaa3c [ui, textbox] position cursor at mouse position / extend selection on shift + mouse press or drag 2023-03-05 15:59:57 +01:00
Martin Fouilleul e95efe85e8 [wip, input system] Fixed bug on macOS, where keyUp events are not received when the command modifier key is down and makes a meaningful combination with the pressed key (note this is normal macOS event handling behaviour, but we still want all events to arrive to track key states).
Fixed by overloading the sendEvent method of our derived NSApplication class. There we check if modifier is down and send the event.
Note glfw solves that by adding a block handler for the keyUp event with addLocalMonitorForEventsMatchingMask.
2023-03-04 19:24:30 +01:00
Martin Fouilleul c04e8639ab [wip, ui] re-integrating UI subsystem and completing text box 2023-03-03 20:09:44 +01:00
Martin Fouilleul d21e737733 [wip] re-introducing UI subsystem 2023-03-03 17:13:03 +01:00
martinfouilleul 653ddec978 [win32 surface sharing] win32 surface sharing using window reparenting 2023-03-03 12:41:09 +01:00
Martin Fouilleul 731e5b1ae8 [surface] pull mp_layer into the generic mg_surface_data struct, out of each backend-specific implementation 2023-03-03 11:50:12 +01:00
martinfouilleul ac00cc9def [wip, win32 surface sharing] simplifyin the surface sharing API 2023-03-02 19:21:39 +01:00
martinfouilleul ee87976429 [win32 surface sharing] hacky proof of concept 2023-03-02 18:24:15 +01:00
martinfouilleul 3ada8ece9a [wip, win32 surface sharing] in surface sharing example, terminate child process when parent exits 2023-03-02 12:23:10 +01:00
martinfouilleul e58ae3ef52 [surface sharing] first draft for win32 using window reparenting 2023-03-02 09:54:12 +01:00
martinfouilleul 2560ddd5b4 [win32] adding simple IPC to test delegated surface 2023-03-01 18:58:59 +01:00
martinfouilleul 1dfc5dd684 [graphics, win32] applying changes to surface backend API 2023-03-01 17:41:39 +01:00
Martin Fouilleul 43d413dbbc [surface] graphics surface sharing API + osx implementation 2023-03-01 16:15:36 +01:00
Martin Fouilleul 28f5af32fa [graphics] Allocate canvases and fonts from graphics subsystem's arena 2023-03-01 11:37:33 +01:00
Martin Fouilleul 6bf989564d [graphics] use a single handle arena for all graphics subsystem handles 2023-02-28 20:33:55 +01:00
Martin Fouilleul 5a19c03ad6 [canvas] removing unused old atlasing api 2023-02-28 18:47:45 +01:00
Martin Fouilleul 3615775168 [canvas] decompose image atlas API into simple rect atlas API + image atlas helpers. This avoids creating a bunch of new types/handles, and exposes the underlying image/sourceRegion so that user code can freely use these for more complex scenarios (eg drawing only a sub-region of an atlased image, or using an atlas image for arbitrary path filling) 2023-02-28 16:54:39 +01:00
Martin Fouilleul d4bceba7e9 [canvas] basic image atlas API 2023-02-28 13:16:36 +01:00
martinfouilleul 9cb4aedbc5 [canvas, gl] use pre-multiplied alpha in draw shader and when compositing batches 2023-02-27 19:50:18 +01:00
martinfouilleul ac6a5db209 [canvas, gl] Checked batching/transparency 2023-02-27 19:39:26 +01:00
Martin Fouilleul 5fa07cb462 adding image with transparency (top512.png) in resources to test transparency/overlaying 2023-02-27 19:34:54 +01:00
martinfouilleul 8f834fa1a5 [wip, canvas, gl] implementing basic image API 2023-02-27 19:25:41 +01:00
Martin Fouilleul 5e5f8ac5e7 adding image test/example 2023-02-27 15:43:41 +01:00
Martin Fouilleul 30aa6a4a48 [canvas] Put primitive's transform in the attributes struct. When rendering, set current transform at the beginning of mg_next_shape(). (This avoid using an additional prevTransform matrix to correctly setup uvTransform when mg_finalize_shape() at the beginning of mg_next_shape()) 2023-02-27 15:01:44 +01:00
Martin Fouilleul d195fb1f61 [canvas, mtl backend] Compute each layer with pre-multiplied alpha, starting from transparent color. Composite them to surface with premultiplied alpha too. 2023-02-27 14:24:59 +01:00
Martin Fouilleul 9ed630fc55 [canvas]
- Clear final surface to clear color, and enable blending layers onto it
- Fixed Batching bug where we were writing to vertex/shape buffers while the previous batch is using them
- Fixed bug where uvTransform uses transform of next shape instead of that of shape being finalized
2023-02-27 11:56:04 +01:00
Martin Fouilleul e66932e624 [canvas] Set command attributes to canvas->attributes by default in mg_push_command() 2023-02-25 15:35:24 +01:00
Martin Fouilleul 193afb61fd [canvas] move canvas structs decl from graphics_internal.h to graphics.c, keep only surface/canvas backend interface stuff in graphics_internal.h 2023-02-25 15:23:15 +01:00
Martin Fouilleul 074b17b743 [canvas] Set transform matrix as part of primitive and don't replay push/pop during render 2023-02-25 14:20:07 +01:00
Martin Fouilleul b24de5d969 [canvas] Allow setting image source region 2023-02-25 12:59:49 +01:00
Martin Fouilleul 50569a1427 Allow setting texture on arbitrary path fills 2023-02-24 23:06:39 +01:00
Martin Fouilleul 4333ed02b0 [canvas] remove image draw commands, replace with rect/rounded rects + image source 2023-02-24 22:59:33 +01:00
Martin Fouilleul 1b62ec568c [canvas, mtl backend] Handle image rotation 2023-02-24 20:40:16 +01:00
Martin Fouilleul bb106b717f Build user-space bounding box of shape in mg_push_vertex() _before_ transforming vertices 2023-02-24 19:20:05 +01:00
Martin Fouilleul 11c25bf001 Make transform implicit in mg_push_vertex() 2023-02-24 19:11:03 +01:00
Martin Fouilleul 5be019d166 [canvas, metal] compute uv coords in shader using uvTransformed computed in canvas backend, using shape bounding box, image dimension, source and dest regions 2023-02-24 18:50:46 +01:00
Martin Fouilleul fd4c4e7be3 [canvas] simple image API 2023-02-24 12:01:00 +01:00
Martin Fouilleul d1b71110bb - Fixed metal canvas backend's drawBatch argument order
- Removed texturing in metal shader while we work on image API
- Started working on simple image API
2023-02-23 18:30:47 +01:00
Martin Fouilleul 2b60db292a [wip] image api 2023-02-23 17:07:41 +01:00
martinfouilleul 1250dfd7c1 hardcode GL/GLES versions per-platform for now 2023-02-22 18:30:10 +01:00
martinfouilleul 4b9b182762 Removed todo. Track todos/dev notes/etc in external obsidian vault for now 2023-02-22 17:21:31 +01:00
martinfouilleul 0f5c93b767 [win32 build] use /DELAYLOAD option for libEGL and libGLESv2 to allow apps that don't use GLES backend to work without redistributing those unused DLLs 2023-02-21 19:02:16 +01:00
martinfouilleul 665c63c3d0 [win32 build/link]
- Build milepost as a dynamic library
- Add import/export directives to public API symbols
- Change example build scripts accordingly
2023-02-21 18:43:30 +01:00
Martin Fouilleul dc2961f513 updated todo 2023-02-21 17:22:18 +01:00
Martin Fouilleul 3b26c92c85 [osx build/linking]
- Remove the need for client apps to explicitly link with all dependent libs and frameworks
- Don't require redistributing libEGL/libGLES if not used, by linking them with '-weak-l' option
- Change examples build scripts accordingly
2023-02-21 17:09:26 +01:00
Martin Fouilleul 94373d12ae [surface] extracted common layer functionality from osx surfaces. Use layer in platform-agnostic egl surface. 2023-02-21 13:40:30 +01:00
martinfouilleul 9ea9ea7636 [surface] abstracted child window layer from win32 surfaces 2023-02-21 12:35:22 +01:00
martinfouilleul 5ac512c15e [wgl] Keep dummy window/context around for gl context creation, and don't reload wgl functions every time 2023-02-20 20:20:52 +01:00
martinfouilleul 64d7b31e5c destroy gles surfaces resources 2023-02-20 19:38:24 +01:00
martinfouilleul 2dccfa5547 [win32 surfaces] Backing win32 surfaces with child window and implementing frame/hidding control 2023-02-20 18:34:29 +01:00
Martin Fouilleul 4306d0a01c back osx surfaces by CALayer 2023-02-20 16:49:44 +01:00
Martin Fouilleul 2232b647ed reintroduced GLES backend to osx 2023-02-20 11:05:01 +01:00
martinfouilleul 9eaa125129 add GLES headers to ext 2023-02-17 18:57:01 +01:00
martinfouilleul 333d3e9f9c [gles, wip] reintroducing egl surface (for win32 at first) 2023-02-17 18:56:16 +01:00
martinfouilleul 20e425494f Use a custom GL loader to allow different versions of GL/GLES APIs to co-exist. The loader fills an api struct with GL functions pointers.
We have a per-thread pointer to select which api struct is used, and GL functions are pound-defined to call the versions in that struct.
GL/GLES surfaces can use one of the loader function to load their api, and the prepare proc of the surface sets its api as the current one
before gl calls are issued.
2023-02-16 19:35:01 +01:00
Martin Fouilleul 54df26232c [wip, opengl] include gl headers in generated glapi files 2023-02-16 15:16:51 +01:00
Martin Fouilleul a32e2165c7 [wip, opengl] parsing opengl xml spec to auto-generate gl/gles loader 2023-02-16 13:59:11 +01:00
martinfouilleul 80ea8db687 [surface/canvas cleanup]
- Make build-time and runtime backend selection a bit easier
- Reorganized backend-specific files with slightly more coherent naming scheme
2023-02-10 16:56:10 +01:00
martinfouilleul f54f639db5 properly destroying windows and fonts 2023-02-10 12:05:52 +01:00
martinfouilleul 08d3521b61 [canvas/surface cleanup]
- properly destroy gl canvas backend
- properly destroy gl surface
2023-02-09 18:40:42 +01:00
martinfouilleul af7cbae1fa [canvas cleanup] cleanup canvas resources on creation failure 2023-02-09 18:18:12 +01:00
martinfouilleul 35e396e4c4 [canvas cleanup]
- Remove attributes/color arguments in functions where we don't need them anymore (since they're defined when calling mg_next_shape())
- Renamed "_with_zindex" functions with "_path" -> these function only fill a path (eg rect), but don't increment the current shape
2023-02-09 17:02:58 +01:00
martinfouilleul 09a18419e4 [canvas] make shapeIndex implicit in calls to mg_push_vertex 2023-02-09 16:42:02 +01:00
martinfouilleul 4e816a838b [Clean canvas/shaders]
- Simplified shader names, prefix embedded strings by "glsl_"
- Extracted shader compilation in common function
- Add shader version string and common structs in canvas code rather than in every shader file
- Renamed zIndex with shapeIndex everywhere
2023-02-09 16:14:15 +01:00
martinfouilleul 4a8c77f023 - Move and Zoom perf_text example with the mouse
- Reverted to using 4 bits of subpixel precision and computing cross products with 32 bits integers, for perf reasons
- Fixed some confusion in tile array size vs number of elements (could still clean-up naming a bit though)
- Fixed bug where triangles on the left or below canvas boundaries where bucketted to the first colum/row of tiles
- Fixed bug in mouse button message handling (was always sending press on left button)
2023-02-09 13:09:41 +01:00
martinfouilleul 833767d6e2 move text with the mouse in perf_text example 2023-02-09 09:50:53 +01:00
martinfouilleul 21c604104f fix mp_app_get_resource_path() 2023-02-08 20:40:48 +01:00
martinfouilleul c0601961f1 Reposition window when changing dpi 2023-02-08 20:40:48 +01:00
martinfouilleul 3f58b2ac3d glsl canvas shader: do cross products in 64 bits fixed point to avoid overflow 2023-02-08 20:36:39 +01:00
martinfouilleul 7cf4c3d925 opengl surface/renderer: set surface scaling according to dpi of first monitor. Use that dpi to scale backing texture of canvas renderer. Note: changing monitor isn't handled yet! 2023-02-08 18:22:54 +01:00
martinfouilleul 7fbc4ba270 canvas renderer: Use clip rects to cull tiles/pixels in tiling and drawing passes 2023-02-08 12:59:31 +01:00
martinfouilleul e6e674ee04 Allow setting surface swap interval in opengl surface 2023-02-08 11:49:00 +01:00
martinfouilleul c982b524c0 Merge branch 'gl_canvas' of ssh://git.forkingpaths.dev/martinfouilleul/milepost into gl_canvas 2023-02-08 10:47:20 +01:00
martinfouilleul 38c27f21d6 canvas: allow flushing externally built commands with mg_flush_commands() 2023-02-08 10:46:12 +01:00
Martin Fouilleul afaa95fe07 applied canvas changes to metal backend 2023-02-08 10:42:21 +01:00
martinfouilleul 2419ab7889 opengl canvas renderer: splitting vertex data and shape data 2023-02-07 18:59:51 +01:00
martinfouilleul f0bc88c4fb gl canvas renderer with buffer re-specification 2023-02-07 17:00:59 +01:00
martinfouilleul 5788cdbcda Desktop opengl 4.3 canvas 2023-02-07 13:24:14 +01:00
martinfouilleul 91780b12c7 reorder fields in glsl vertex struct to be less wasteful 2023-02-06 17:01:32 +01:00
martinfouilleul 5754fc1ad2 using temporary buffer to build canvas verex data and use glBufferData with exact number of vertices to submit buffer to gpu 2023-02-06 16:14:43 +01:00
martinfouilleul 3dfaea1bba temporarily reducing vertex buffer size to test perf impact 2023-02-06 09:20:52 +01:00
martinfouilleul fd836c00dd canvas renderer: parallel tiling pass and sorting pass 2023-02-05 21:03:16 +01:00
martinfouilleul e59f2b152b simple gles tiled renderer 2023-02-03 18:44:28 +01:00
martinfouilleul 8faf588bee Added text rendering in win_canvas test app and confirm it's slow as is... 2023-02-02 20:36:03 +01:00
martinfouilleul 68810d8bf0 updated todo 2023-02-02 19:15:20 +01:00
martinfouilleul 19988d045e breaking triangle buffer into batches each time the current image changes 2023-02-02 18:57:57 +01:00
Martin Fouilleul 9cadc2f23f added notes on bindless textures indexing 2023-02-02 17:02:55 +01:00
martinfouilleul 28e2a3648e Multisampling in gles canvas shader 2023-02-02 13:34:06 +01:00
martinfouilleul f73241e4a6 set background clear color correctly 2023-02-02 12:08:04 +01:00
martinfouilleul 0796b2cbcd Switched to fixed point in gles triangle rasterization, and fixed wrong offset curve check collapsing the internal control points 2023-02-02 11:40:22 +01:00
martinfouilleul e0300e9e3c Fixed indexing in gles_canvas_fragment shaders and fixed native keys buffer 2023-02-01 16:23:51 +01:00
martinfouilleul 8e87837fcc working on gles 3.1 canvas on windows 2023-01-31 15:51:50 +01:00
martinfouilleul c5ae556f22 [wip] win32 gles surface using angle 2023-01-29 01:04:24 +01:00
Martin Fouilleul bd7e1a15f1 - Conflating mp_views and surfaces
- Implicit canvas context in canvas API
- GLES window surface on mac
2023-01-28 17:24:43 +01:00
Martin Fouilleul 9bf62d2218 re-working graphics surfaces 2022-12-26 18:33:31 +01:00
Martin Fouilleul db5b4966e9 - Restructure osx version to use mp_app_internal.h/mp_app.c
- test new run loop structure on osx
2022-12-24 15:33:32 +01:00
martinfouilleul 72338b1a25 Extracted commonalities from platform specific app backends 2022-12-23 20:46:42 +01:00
martinfouilleul 30bd704af2 win32 opengl loader nonsense 2022-12-22 18:24:43 +01:00
martinfouilleul a696c2ba2b Added platform detection macros and atomic/thread_local abstraction 2022-12-22 15:29:07 +01:00
martinfouilleul c57e16db5a [win32 port] Hello triangle in OpenGL 4.3 2022-12-21 19:43:31 +01:00
martinfouilleul 2421871c3e windows port initial commit: simple window with GL 4.3 context 2022-12-21 12:03:55 +01:00
Martin Fouilleul 7f62938f84 directory create/remove 2022-08-28 13:49:40 +02:00
Martin Fouilleul 00b282dcd4 Platform file system functions (remove, move, etc) 2022-08-26 14:47:20 +02:00
Martin Fouilleul 884e05abd2 Adding plaform specific move file functions 2022-08-21 19:14:59 +02:00
Martin Fouilleul 1d77a36640 Fixed executable/bundle paths procs 2022-08-21 17:07:54 +02:00
Martin Fouilleul 440668129c Remote GLES surfaces 2022-08-19 20:55:00 +02:00
Martin Fouilleul 13cccdf5de trying to integrate mg_surface_client/server 2022-08-19 19:46:31 +02:00
Martin Fouilleul 0becc301d0 Fix panel scrolling issue (clamping scroll value was only done when scrollers were on) 2022-08-16 09:58:16 +02:00
Martin Fouilleul 6fe1a29a4b Allow driving resfresh from an NSTimer, which triggers even during live resize 2022-08-16 09:57:30 +02:00
Martin Fouilleul 5cfaf909fc adding animation flags 2022-08-16 00:01:07 +02:00
Martin Fouilleul 4ca01db7e8 remove CVDisplayLink during live resize (causing threading issues) 2022-08-16 00:00:20 +02:00
Martin Fouilleul beffc60634 redraw during live resize operations 2022-08-15 23:11:13 +02:00
Martin Fouilleul e22893e9ea animated ui positions 2022-08-15 23:11:00 +02:00
Martin Fouilleul 1d8485607e Allow to activate scroll bars with mousewheel 2022-08-15 18:28:13 +02:00
Martin Fouilleul c3f149c910 Fixing metal compute shader coordinate bug that prevented rendering the last row/column of tiles 2022-08-15 17:20:44 +02:00
Martin Fouilleul 094b0efc33 text box 2022-08-15 10:20:29 +02:00
Martin Fouilleul 39cfa35bfd initial commit 2022-08-14 18:19:40 +02:00
715 changed files with 155819 additions and 10107 deletions

34
.clang-format Normal file
View File

@ -0,0 +1,34 @@
AllowAllArgumentsOnNextLine: false
Cpp11BracedListStyle: false
ColumnLimit: 0
BreakBeforeBinaryOperators: NonAssignment
AlignOperands: AlignAfterOperator
IndentPPDirectives: BeforeHash
IndentCaseLabels: true
IndentWidth: 4
TabWidth: 4
UseTab: Never
LineEnding: LF
MaxEmptyLinesToKeep: 1
PointerAlignment: Left
SeparateDefinitionBlocks: Always
SpaceBeforeParens: Never
ReflowComments: false
SortIncludes: false
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterExternBlock: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterStruct: true
AfterObjCDeclaration: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
BeforeWhile: true
IndentExternBlock: false

22
.gitignore vendored
View File

@ -1,6 +1,7 @@
.DS_Store
*.dSYM
bin/*
build
*.metallib
*.pdb
*.exe
@ -13,13 +14,30 @@ bin/*
*.wasm
*.app
*.dylib
*.a
Debug/*
scripts/__pycache__
src/wasmbind/gles_api.json
src/bindgen_core_api.c
src/bindgen_gles_api.c
sdk/io_stubs.c
sdk/orca_surface.c
src/graphics/glsl_shaders.h
src/io_stubs.c
src/orca_surface.c
src/graphics/orca_gl31.h
*bind_gen.c
*_stubs.c
.vscode/launch.json
.vscode/settings.json
__pycache__
scripts/files
# explicitly abandon old ext dir
/ext
src/ext/angle
sketches/*/bin

4
.gitmodules vendored
View File

@ -1,4 +0,0 @@
[submodule "milepost"]
path = milepost
url = git@git.handmade.network:MartinFouilleul/milepost.git
branch = main

3
.orcaroot Normal file
View File

@ -0,0 +1,3 @@
You are currently at the root of the Orca source. Welcome.
This file exists to signal to the Orca CLI that you are in the Orca source and can do Orca source things. When the CLI detects this file, it will ignore the system Orca installation and use only the contents of this current source checkout.

2
FUNDING.yml Normal file
View File

@ -0,0 +1,2 @@
github: orca-app
custom: "https://orca-app.dev/sponsor.html"

207
LICENSE.txt Normal file
View File

@ -0,0 +1,207 @@
Orca
Copyright (C) 2023 Martin Fouilleul
Orca is distributed under the MIT license or the Apache License version 2.0,
at your option.
-------------------------------------------------------------------------------
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -1,29 +1,2 @@
# Install
**This repository is not used anymore. Development of Orca was moved here: [https://github.com/orca-app/orca](https://github.com/orca-app/orca)**
Clone the repo with the `--recurse-submodules` option.
Get and build ANGLE (see `milepost/ext/angle_install_notes.md`), and put `libEGL.dylib` and `libGLESv2.dylib` in `milepost/bin`.
Cd to orca and build milepost (the platform layer), wasm3 (the wasm runtime), then orca:
```
cd Orca
./build.sh milepost
./build.sh wasm3
./build.sh orca
```
Build the sample orca app:
```
pushd samples/pong ; ./build.sh ; popd
```
This creates a `Pong.app` bundle in `samples/pong` that you can double click to run.
You can also build milepost example apps like so:
```
cd milepost
pushd examples/canvas ; ./build.sh ; popd
pushd examples/perf_text ; ./build.sh ; popd
pushd examples/tiger ; ./build.sh ; popd
```

View File

@ -1,62 +0,0 @@
@echo off
set target=%1%
if "%~1%" == "" set target=orca
if not exist bin mkdir bin
if not exist bin\obj mkdir bin\obj
if %target% == wasm3 (
echo building wasm3
set wasm3_includes=/I .\ext\wasm3\source
set wasm3_sources=/I .\ext\wasm3\source\*.c
for %%f in ( .\ext\wasm3\source\*.c ) do (
cl /nologo /Zi /Zc:preprocessor /O2 /c /Fo:bin\obj\%%~nf.obj %wasm3_includes% %%f
)
lib /nologo /out:bin\wasm3.lib bin\obj\*.obj
)
if %target% == milepost (
echo building milepost
cd milepost
build.bat
cd ..
)
if %target% == orca (
echo building orca
::copy libraries
copy milepost\bin\milepost.dll bin
copy milepost\bin\milepost.dll.lib bin
::generate wasm3 api bindings
python3 scripts\bindgen.py core src\core_api.json^
--wasm3-bindings src\core_api_bind_gen.c
python3 scripts\bindgen.py gles src\gles_api.json^
--wasm3-bindings src\gles_api_bind_gen.c
python3 scripts\bindgen.py canvas src\canvas_api.json^
--guest-stubs sdk\orca_surface.c^
--guest-include graphics.h^
--wasm3-bindings src\canvas_api_bind_gen.c
python3 scripts\bindgen.py clock src\clock_api.json^
--guest-stubs sdk\orca_clock.c^
--guest-include platform_clock.h^
--wasm3-bindings src\clock_api_bind_gen.c
python3 scripts\bindgen.py io^
src\io_api.json^
--guest-stubs sdk\io_stubs.c^
--wasm3-bindings src\io_api_bind_gen.c
::compile orca
set INCLUDES=/I src /I sdk /I ext\wasm3\source /I milepost\src /I milepost\ext
set LIBS=/LIBPATH:bin milepost.dll.lib wasm3.lib
cl /Zi /Zc:preprocessor /std:c11 /experimental:c11atomics %INCLUDES% src\main.c /link %LIBS% /out:bin\orca.exe
)

View File

@ -1,97 +0,0 @@
#!/bin/bash
set -eo pipefail
target="$1"
if [ -z $target ] ; then
target='orca'
fi
target=$(echo $target | tr '[:upper:]' '[:lower:]')
if [ ! \( -e bin \) ] ; then
mkdir ./bin
fi
if [ ! \( -e resources \) ] ; then
mkdir ./resources
fi
if [ $target = milepost ] ; then
echo "building milepost"
pushd milepost > /dev/null
./build.sh lib "$2"
popd > /dev/null
elif [ $target = wasm3 ] ; then
echo "building wasm3"
mkdir ./bin/obj
for file in ./ext/wasm3/source/*.c ; do
name=$(basename $file)
name=${name/.c/.o}
clang -c -g -O2 -foptimize-sibling-calls -Wno-extern-initializer -Dd_m3VerboseErrorMessages -o ./bin/obj/$name -I./ext/wasm3/source $file
done
ar -rcs ./bin/libwasm3.a ./bin/obj/*.o
rm -rf ./bin/obj
elif [ $target = orca ] ; then
echo "building orca"
if [ ! \( -e milepost/bin/libmilepost.dylib \) -o ! \( -e milepost/bin/mtl_renderer.metallib \) ] ; then
./build.sh milepost
fi
if [ ! \( -e ./bin/libwasm3.a \) ] ; then
./build.sh wasm3
fi
# copy libraries
cp milepost/bin/mtl_renderer.metallib bin/
cp milepost/bin/libmilepost.dylib bin/
cp milepost/bin/libGLESv2.dylib bin/
cp milepost/bin/libEGL.dylib bin/
INCLUDES="-Isrc -Isdk -Imilepost/src -Imilepost/src/util -Imilepost/src/platform -Iext/wasm3/source -Imilepost/ext/"
LIBS="-Lbin -lmilepost -lwasm3"
FLAGS="-g -DLOG_COMPILE_DEBUG -mmacos-version-min=10.15.4 -maes"
# generate wasm3 api bindings
python3 ./scripts/bindgen.py core \
src/core_api.json \
--wasm3-bindings ./src/core_api_bind_gen.c
python3 ./scripts/bindgen.py gles \
src/gles_api.json \
--wasm3-bindings ./src/gles_api_bind_gen.c
python3 ./scripts/bindgen.py canvas \
src/canvas_api.json \
--guest-stubs sdk/orca_surface.c \
--guest-include graphics.h \
--wasm3-bindings ./src/canvas_api_bind_gen.c
python3 ./scripts/bindgen.py clock \
src/clock_api.json \
--guest-stubs sdk/orca_clock.c \
--guest-include platform_clock.h \
--wasm3-bindings ./src/clock_api_bind_gen.c
python3 ./scripts/bindgen.py io \
src/io_api.json \
--guest-stubs sdk/io_stubs.c \
--wasm3-bindings ./src/io_api_bind_gen.c
# compile orca
clang $FLAGS $INCLUDES $LIBS -o bin/orca src/main.c
# fix libs imports
install_name_tool -change "./bin/libmilepost.dylib" "@rpath/libmilepost.dylib" bin/orca
install_name_tool -add_rpath "@executable_path/" bin/orca
else
echo "unknown build target $target"
fi

View File

@ -1,23 +0,0 @@
#include <features.h>
#undef assert
#ifdef NDEBUG
#define assert(x) (void)0
#else
#define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__, __func__),0)))
#endif
#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus)
#define static_assert _Static_assert
#endif
#ifdef __cplusplus
extern "C" {
#endif
_Noreturn void __assert_fail (const char *, const char *, int, const char *);
#ifdef __cplusplus
}
#endif

View File

@ -1,134 +0,0 @@
#define EPERM 1
#define ENOENT 2
#define ESRCH 3
#define EINTR 4
#define EIO 5
#define ENXIO 6
#define E2BIG 7
#define ENOEXEC 8
#define EBADF 9
#define ECHILD 10
#define EAGAIN 11
#define ENOMEM 12
#define EACCES 13
#define EFAULT 14
#define ENOTBLK 15
#define EBUSY 16
#define EEXIST 17
#define EXDEV 18
#define ENODEV 19
#define ENOTDIR 20
#define EISDIR 21
#define EINVAL 22
#define ENFILE 23
#define EMFILE 24
#define ENOTTY 25
#define ETXTBSY 26
#define EFBIG 27
#define ENOSPC 28
#define ESPIPE 29
#define EROFS 30
#define EMLINK 31
#define EPIPE 32
#define EDOM 33
#define ERANGE 34
#define EDEADLK 35
#define ENAMETOOLONG 36
#define ENOLCK 37
#define ENOSYS 38
#define ENOTEMPTY 39
#define ELOOP 40
#define EWOULDBLOCK EAGAIN
#define ENOMSG 42
#define EIDRM 43
#define ECHRNG 44
#define EL2NSYNC 45
#define EL3HLT 46
#define EL3RST 47
#define ELNRNG 48
#define EUNATCH 49
#define ENOCSI 50
#define EL2HLT 51
#define EBADE 52
#define EBADR 53
#define EXFULL 54
#define ENOANO 55
#define EBADRQC 56
#define EBADSLT 57
#define EDEADLOCK EDEADLK
#define EBFONT 59
#define ENOSTR 60
#define ENODATA 61
#define ETIME 62
#define ENOSR 63
#define ENONET 64
#define ENOPKG 65
#define EREMOTE 66
#define ENOLINK 67
#define EADV 68
#define ESRMNT 69
#define ECOMM 70
#define EPROTO 71
#define EMULTIHOP 72
#define EDOTDOT 73
#define EBADMSG 74
#define EOVERFLOW 75
#define ENOTUNIQ 76
#define EBADFD 77
#define EREMCHG 78
#define ELIBACC 79
#define ELIBBAD 80
#define ELIBSCN 81
#define ELIBMAX 82
#define ELIBEXEC 83
#define EILSEQ 84
#define ERESTART 85
#define ESTRPIPE 86
#define EUSERS 87
#define ENOTSOCK 88
#define EDESTADDRREQ 89
#define EMSGSIZE 90
#define EPROTOTYPE 91
#define ENOPROTOOPT 92
#define EPROTONOSUPPORT 93
#define ESOCKTNOSUPPORT 94
#define EOPNOTSUPP 95
#define ENOTSUP EOPNOTSUPP
#define EPFNOSUPPORT 96
#define EAFNOSUPPORT 97
#define EADDRINUSE 98
#define EADDRNOTAVAIL 99
#define ENETDOWN 100
#define ENETUNREACH 101
#define ENETRESET 102
#define ECONNABORTED 103
#define ECONNRESET 104
#define ENOBUFS 105
#define EISCONN 106
#define ENOTCONN 107
#define ESHUTDOWN 108
#define ETOOMANYREFS 109
#define ETIMEDOUT 110
#define ECONNREFUSED 111
#define EHOSTDOWN 112
#define EHOSTUNREACH 113
#define EALREADY 114
#define EINPROGRESS 115
#define ESTALE 116
#define EUCLEAN 117
#define ENOTNAM 118
#define ENAVAIL 119
#define EISNAM 120
#define EREMOTEIO 121
#define EDQUOT 122
#define ENOMEDIUM 123
#define EMEDIUMTYPE 124
#define ECANCELED 125
#define ENOKEY 126
#define EKEYEXPIRED 127
#define EKEYREVOKED 128
#define EKEYREJECTED 129
#define EOWNERDEAD 130
#define ENOTRECOVERABLE 131
#define ERFKILL 132
#define EHWPOISON 133

View File

@ -1,94 +0,0 @@
#ifndef _MATH_H
#define _MATH_H
#ifdef __cplusplus
extern "C" {
#endif
// NOTE(orca): not doing anything fancy for float_t and double_t
typedef float float_t;
typedef double double_t;
#define NAN __builtin_nanf("")
#define INFINITY __builtin_inff()
#define FP_NAN 0
#define FP_INFINITE 1
#define FP_ZERO 2
#define FP_SUBNORMAL 3
#define FP_NORMAL 4
int __fpclassify(double);
int __fpclassifyf(float);
int __fpclassifyl(long double);
static __inline unsigned __FLOAT_BITS(float __f)
{
union {float __f; unsigned __i;} __u;
__u.__f = __f;
return __u.__i;
}
static __inline unsigned long long __DOUBLE_BITS(double __f)
{
union {double __f; unsigned long long __i;} __u;
__u.__f = __f;
return __u.__i;
}
#define fpclassify(x) ( \
sizeof(x) == sizeof(float) ? __fpclassifyf(x) : \
sizeof(x) == sizeof(double) ? __fpclassify(x) : \
__fpclassifyl(x) )
#define isinf(x) ( \
sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) == 0x7f800000 : \
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) == 0x7ffULL<<52 : \
__fpclassifyl(x) == FP_INFINITE)
#define isnan(x) ( \
sizeof(x) == sizeof(float) ? (__FLOAT_BITS(x) & 0x7fffffff) > 0x7f800000 : \
sizeof(x) == sizeof(double) ? (__DOUBLE_BITS(x) & -1ULL>>1) > 0x7ffULL<<52 : \
__fpclassifyl(x) == FP_NAN)
double acos(double);
double ceil(double);
double cos(double);
float cosf(float);
double fabs(double);
double floor(double);
double fmod(double, double);
double pow(double, double);
double scalbn(double, int);
double sin(double);
float sinf(float);
double sqrt(double);
float sqrtf(float);
#define M_E 2.7182818284590452354 /* e */
#define M_LOG2E 1.4426950408889634074 /* log_2 e */
#define M_LOG10E 0.43429448190325182765 /* log_10 e */
#define M_LN2 0.69314718055994530942 /* log_e 2 */
#define M_LN10 2.30258509299404568402 /* log_e 10 */
#define M_PI 3.14159265358979323846 /* pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#define M_PI_4 0.78539816339744830962 /* pi/4 */
#define M_1_PI 0.31830988618379067154 /* 1/pi */
#define M_2_PI 0.63661977236758134308 /* 2/pi */
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,25 +0,0 @@
#ifndef _STDIO_H
#define _STDIO_H
#ifdef __cplusplus
extern "C" {
#endif
struct _IO_FILE { char __x; };
typedef struct _IO_FILE FILE;
extern FILE *const stdin;
extern FILE *const stdout;
extern FILE *const stderr;
#define stdin (stdin)
#define stdout (stdout)
#define stderr (stderr)
int fprintf(FILE *__restrict, const char *__restrict, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,16 +0,0 @@
#ifndef _STDLIB_H
#define _STDLIB_H
#ifdef __cplusplus
extern "C" {
#endif
_Noreturn void abort (void);
int abs (int);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,8 +0,0 @@
#include "libm.h"
double __math_xflow(uint32_t sign, double y)
{
// NOTE(orca): no fp barriers
// return eval_as_double(fp_barrier(sign ? -y : y) * y);
return eval_as_double((sign ? -y : y) * y);
}

View File

@ -1,190 +0,0 @@
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*
* Optimized by Bruce D. Evans.
*/
/* __rem_pio2(x,y)
*
* return the remainder of x rem pi/2 in y[0]+y[1]
* use __rem_pio2_large() for large x
*/
#include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
/*
* invpio2: 53 bits of 2/pi
* pio2_1: first 33 bit of pi/2
* pio2_1t: pi/2 - pio2_1
* pio2_2: second 33 bit of pi/2
* pio2_2t: pi/2 - (pio2_1+pio2_2)
* pio2_3: third 33 bit of pi/2
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/
static const double
toint = 1.5/EPS,
pio4 = 0x1.921fb54442d18p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */
pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */
pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */
pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */
pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */
pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */
/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */
int __rem_pio2(double x, double *y)
{
union {double f; uint64_t i;} u = {x};
double_t z,w,t,r,fn;
double tx[3],ty[2];
uint32_t ix;
int sign, n, ex, ey, i;
sign = u.i>>63;
ix = u.i>>32 & 0x7fffffff;
if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */
if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */
goto medium; /* cancellation -- use medium case */
if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */
if (!sign) {
z = x - pio2_1; /* one round good to 85 bits */
y[0] = z - pio2_1t;
y[1] = (z-y[0]) - pio2_1t;
return 1;
} else {
z = x + pio2_1;
y[0] = z + pio2_1t;
y[1] = (z-y[0]) + pio2_1t;
return -1;
}
} else {
if (!sign) {
z = x - 2*pio2_1;
y[0] = z - 2*pio2_1t;
y[1] = (z-y[0]) - 2*pio2_1t;
return 2;
} else {
z = x + 2*pio2_1;
y[0] = z + 2*pio2_1t;
y[1] = (z-y[0]) + 2*pio2_1t;
return -2;
}
}
}
if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */
if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */
if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */
goto medium;
if (!sign) {
z = x - 3*pio2_1;
y[0] = z - 3*pio2_1t;
y[1] = (z-y[0]) - 3*pio2_1t;
return 3;
} else {
z = x + 3*pio2_1;
y[0] = z + 3*pio2_1t;
y[1] = (z-y[0]) + 3*pio2_1t;
return -3;
}
} else {
if (ix == 0x401921fb) /* |x| ~= 4pi/2 */
goto medium;
if (!sign) {
z = x - 4*pio2_1;
y[0] = z - 4*pio2_1t;
y[1] = (z-y[0]) - 4*pio2_1t;
return 4;
} else {
z = x + 4*pio2_1;
y[0] = z + 4*pio2_1t;
y[1] = (z-y[0]) + 4*pio2_1t;
return -4;
}
}
}
if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */
medium:
/* rint(x/(pi/2)) */
fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn;
r = x - fn*pio2_1;
w = fn*pio2_1t; /* 1st round, good to 85 bits */
/* Matters with directed rounding. */
if (predict_false(r - w < -pio4)) {
n--;
fn--;
r = x - fn*pio2_1;
w = fn*pio2_1t;
} else if (predict_false(r - w > pio4)) {
n++;
fn++;
r = x - fn*pio2_1;
w = fn*pio2_1t;
}
y[0] = r - w;
u.f = y[0];
ey = u.i>>52 & 0x7ff;
ex = ix>>20;
if (ex - ey > 16) { /* 2nd round, good to 118 bits */
t = r;
w = fn*pio2_2;
r = t - w;
w = fn*pio2_2t - ((t-r)-w);
y[0] = r - w;
u.f = y[0];
ey = u.i>>52 & 0x7ff;
if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */
t = r;
w = fn*pio2_3;
r = t - w;
w = fn*pio2_3t - ((t-r)-w);
y[0] = r - w;
}
}
y[1] = (r - y[0]) - w;
return n;
}
/*
* all other (large) arguments
*/
if (ix >= 0x7ff00000) { /* x is inf or NaN */
y[0] = y[1] = x - x;
return 0;
}
/* set z = scalbn(|x|,-ilogb(x)+23) */
u.f = x;
u.i &= (uint64_t)-1>>12;
u.i |= (uint64_t)(0x3ff + 23)<<52;
z = u.f;
for (i=0; i < 2; i++) {
tx[i] = (double)(int32_t)z;
z = (z-tx[i])*0x1p24;
}
tx[i] = z;
/* skip zero terms, first term is non-zero */
while (tx[i] == 0.0)
i--;
n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1);
if (sign) {
y[0] = -ty[0];
y[1] = -ty[1];
return -n;
}
y[0] = ty[0];
y[1] = ty[1];
return n;
}

View File

@ -1,442 +0,0 @@
/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/*
* __rem_pio2_large(x,y,e0,nx,prec)
* double x[],y[]; int e0,nx,prec;
*
* __rem_pio2_large return the last three digits of N with
* y = x - N*pi/2
* so that |y| < pi/2.
*
* The method is to compute the integer (mod 8) and fraction parts of
* (2/pi)*x without doing the full multiplication. In general we
* skip the part of the product that are known to be a huge integer (
* more accurately, = 0 mod 8 ). Thus the number of operations are
* independent of the exponent of the input.
*
* (2/pi) is represented by an array of 24-bit integers in ipio2[].
*
* Input parameters:
* x[] The input value (must be positive) is broken into nx
* pieces of 24-bit integers in double precision format.
* x[i] will be the i-th 24 bit of x. The scaled exponent
* of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
* match x's up to 24 bits.
*
* Example of breaking a double positive z into x[0]+x[1]+x[2]:
* e0 = ilogb(z)-23
* z = scalbn(z,-e0)
* for i = 0,1,2
* x[i] = floor(z)
* z = (z-x[i])*2**24
*
*
* y[] ouput result in an array of double precision numbers.
* The dimension of y[] is:
* 24-bit precision 1
* 53-bit precision 2
* 64-bit precision 2
* 113-bit precision 3
* The actual value is the sum of them. Thus for 113-bit
* precison, one may have to do something like:
*
* long double t,w,r_head, r_tail;
* t = (long double)y[2] + (long double)y[1];
* w = (long double)y[0];
* r_head = t+w;
* r_tail = w - (r_head - t);
*
* e0 The exponent of x[0]. Must be <= 16360 or you need to
* expand the ipio2 table.
*
* nx dimension of x[]
*
* prec an integer indicating the precision:
* 0 24 bits (single)
* 1 53 bits (double)
* 2 64 bits (extended)
* 3 113 bits (quad)
*
* External function:
* double scalbn(), floor();
*
*
* Here is the description of some local variables:
*
* jk jk+1 is the initial number of terms of ipio2[] needed
* in the computation. The minimum and recommended value
* for jk is 3,4,4,6 for single, double, extended, and quad.
* jk+1 must be 2 larger than you might expect so that our
* recomputation test works. (Up to 24 bits in the integer
* part (the 24 bits of it that we compute) and 23 bits in
* the fraction part may be lost to cancelation before we
* recompute.)
*
* jz local integer variable indicating the number of
* terms of ipio2[] used.
*
* jx nx - 1
*
* jv index for pointing to the suitable ipio2[] for the
* computation. In general, we want
* ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
* is an integer. Thus
* e0-3-24*jv >= 0 or (e0-3)/24 >= jv
* Hence jv = max(0,(e0-3)/24).
*
* jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
*
* q[] double array with integral value, representing the
* 24-bits chunk of the product of x and 2/pi.
*
* q0 the corresponding exponent of q[0]. Note that the
* exponent for q[i] would be q0-24*i.
*
* PIo2[] double precision array, obtained by cutting pi/2
* into 24 bits chunks.
*
* f[] ipio2[] in floating point
*
* iq[] integer array by breaking up q[] in 24-bits chunk.
*
* fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
*
* ih integer. If >0 it indicates q[] is >= 0.5, hence
* it also indicates the *sign* of the result.
*
*/
/*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "libm.h"
static const int init_jk[] = {3,4,4,6}; /* initial value for jk */
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*
* integer array, contains the (24*i)-th to (24*i+23)-th
* bit of 2/pi after binary point. The corresponding
* floating value is
*
* ipio2[i] * 2^(-24(i+1)).
*
* NB: This table must have at least (e0-3)/24 + jk terms.
* For quad precision (e0 <= 16360, jk = 6), this is 686.
*/
static const int32_t ipio2[] = {
0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62,
0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A,
0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129,
0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41,
0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8,
0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF,
0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5,
0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08,
0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3,
0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880,
0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B,
#if LDBL_MAX_EXP > 1024
0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6,
0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2,
0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35,
0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30,
0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C,
0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4,
0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770,
0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7,
0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19,
0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522,
0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16,
0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6,
0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E,
0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48,
0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3,
0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF,
0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55,
0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612,
0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929,
0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC,
0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B,
0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C,
0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4,
0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB,
0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC,
0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C,
0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F,
0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5,
0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437,
0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B,
0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA,
0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD,
0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3,
0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3,
0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717,
0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F,
0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61,
0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB,
0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51,
0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0,
0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C,
0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6,
0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC,
0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED,
0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328,
0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D,
0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0,
0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B,
0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4,
0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3,
0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F,
0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD,
0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B,
0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4,
0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761,
0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31,
0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30,
0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262,
0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E,
0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1,
0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C,
0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4,
0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08,
0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196,
0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9,
0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4,
0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC,
0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C,
0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0,
0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C,
0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0,
0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC,
0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22,
0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893,
0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7,
0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5,
0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F,
0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4,
0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF,
0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B,
0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2,
0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138,
0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E,
0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569,
0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34,
0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9,
0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D,
0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F,
0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855,
0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569,
0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B,
0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE,
0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41,
0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49,
0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F,
0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110,
0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8,
0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365,
0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A,
0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270,
0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5,
0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616,
0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B,
0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0,
#endif
};
static const double PIo2[] = {
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
};
int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec)
{
int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
double z,fw,f[20],fq[20],q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx-1;
jv = (e0-3)/24; if(jv<0) jv=0;
q0 = e0-24*(jv+1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv-jx; m = jx+jk;
for (i=0; i<=m; i++,j++)
f[i] = j<0 ? 0.0 : (double)ipio2[j];
/* compute q[0],q[1],...q[jk] */
for (i=0; i<=jk; i++) {
for (j=0,fw=0.0; j<=jx; j++)
fw += x[j]*f[jx+i-j];
q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for (i=0,j=jz,z=q[jz]; j>0; i++,j--) {
fw = (double)(int32_t)(0x1p-24*z);
iq[i] = (int32_t)(z - 0x1p24*fw);
z = q[j-1]+fw;
}
/* compute n */
z = scalbn(z,q0); /* actual value of z */
z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */
n = (int32_t)z;
z -= (double)n;
ih = 0;
if (q0 > 0) { /* need iq[jz-1] to determine n */
i = iq[jz-1]>>(24-q0); n += i;
iq[jz-1] -= i<<(24-q0);
ih = iq[jz-1]>>(23-q0);
}
else if (q0 == 0) ih = iq[jz-1]>>23;
else if (z >= 0.5) ih = 2;
if (ih > 0) { /* q > 0.5 */
n += 1; carry = 0;
for (i=0; i<jz; i++) { /* compute 1-q */
j = iq[i];
if (carry == 0) {
if (j != 0) {
carry = 1;
iq[i] = 0x1000000 - j;
}
} else
iq[i] = 0xffffff - j;
}
if (q0 > 0) { /* rare case: chance is 1 in 12 */
switch(q0) {
case 1:
iq[jz-1] &= 0x7fffff; break;
case 2:
iq[jz-1] &= 0x3fffff; break;
}
}
if (ih == 2) {
z = 1.0 - z;
if (carry != 0)
z -= scalbn(1.0,q0);
}
}
/* check if recomputation is needed */
if (z == 0.0) {
j = 0;
for (i=jz-1; i>=jk; i--) j |= iq[i];
if (j == 0) { /* need recomputation */
for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */
for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */
f[jx+i] = (double)ipio2[jv+i];
for (j=0,fw=0.0; j<=jx; j++)
fw += x[j]*f[jx+i-j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if (z == 0.0) {
jz -= 1;
q0 -= 24;
while (iq[jz] == 0) {
jz--;
q0 -= 24;
}
} else { /* break z into 24-bit if necessary */
z = scalbn(z,-q0);
if (z >= 0x1p24) {
fw = (double)(int32_t)(0x1p-24*z);
iq[jz] = (int32_t)(z - 0x1p24*fw);
jz += 1;
q0 += 24;
iq[jz] = (int32_t)fw;
} else
iq[jz] = (int32_t)z;
}
/* convert integer "bit" chunk to floating-point value */
fw = scalbn(1.0,q0);
for (i=jz; i>=0; i--) {
q[i] = fw*(double)iq[i];
fw *= 0x1p-24;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for(i=jz; i>=0; i--) {
for (fw=0.0,k=0; k<=jp && k<=jz-i; k++)
fw += PIo2[k]*q[i+k];
fq[jz-i] = fw;
}
/* compress fq[] into y[] */
switch(prec) {
case 0:
fw = 0.0;
for (i=jz; i>=0; i--)
fw += fq[i];
y[0] = ih==0 ? fw : -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i=jz; i>=0; i--)
fw += fq[i];
// TODO: drop excess precision here once double_t is used
fw = (double)fw;
y[0] = ih==0 ? fw : -fw;
fw = fq[0]-fw;
for (i=1; i<=jz; i++)
fw += fq[i];
y[1] = ih==0 ? fw : -fw;
break;
case 3: /* painful */
for (i=jz; i>0; i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (i=jz; i>1; i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (fw=0.0,i=jz; i>=2; i--)
fw += fq[i];
if (ih==0) {
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
} else {
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
}
}
return n&7;
}

View File

@ -1,86 +0,0 @@
/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2f.c */
/*
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
* Debugged and optimized by Bruce D. Evans.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* __rem_pio2f(x,y)
*
* return the remainder of x rem pi/2 in *y
* use double precision for everything except passing x
* use __rem_pio2_large() for large x
*/
#include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
/*
* invpio2: 53 bits of 2/pi
* pio2_1: first 25 bits of pi/2
* pio2_1t: pi/2 - pio2_1
*/
static const double
toint = 1.5/EPS,
pio4 = 0x1.921fb6p-1,
invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
pio2_1 = 1.57079631090164184570e+00, /* 0x3FF921FB, 0x50000000 */
pio2_1t = 1.58932547735281966916e-08; /* 0x3E5110b4, 0x611A6263 */
int __rem_pio2f(float x, double *y)
{
union {float f; uint32_t i;} u = {x};
double tx[1],ty[1];
double_t fn;
uint32_t ix;
int n, sign, e0;
ix = u.i & 0x7fffffff;
/* 25+53 bit pi is good enough for medium size */
if (ix < 0x4dc90fdb) { /* |x| ~< 2^28*(pi/2), medium size */
/* Use a specialized rint() to get fn. */
fn = (double_t)x*invpio2 + toint - toint;
n = (int32_t)fn;
*y = x - fn*pio2_1 - fn*pio2_1t;
/* Matters with directed rounding. */
if (predict_false(*y < -pio4)) {
n--;
fn--;
*y = x - fn*pio2_1 - fn*pio2_1t;
} else if (predict_false(*y > pio4)) {
n++;
fn++;
*y = x - fn*pio2_1 - fn*pio2_1t;
}
return n;
}
if(ix>=0x7f800000) { /* x is inf or NaN */
*y = x-x;
return 0;
}
/* scale x into [2^23, 2^24-1] */
sign = u.i>>31;
e0 = (ix>>23) - (0x7f+23); /* e0 = ilogb(|x|)-23, positive */
u.i = ix - (e0<<23);
tx[0] = u.f;
n = __rem_pio2_large(tx,ty,e0,1,0);
if (sign) {
*y = -ty[0];
return -n;
}
*y = ty[0];
return n;
}

View File

@ -1,6 +0,0 @@
// NOTE(orca): This is a clang intrinsic. I hope it generates a wasm unreachable. I have not verified this.
// TODO(orca): Verify this.
_Noreturn void abort(void)
{
__builtin_unreachable();
}

View File

@ -1,101 +0,0 @@
/* origin: FreeBSD /usr/src/lib/msun/src/e_acos.c */
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunSoft, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
/* acos(x)
* Method :
* acos(x) = pi/2 - asin(x)
* acos(-x) = pi/2 + asin(x)
* For |x|<=0.5
* acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c)
* For x>0.5
* acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2)))
* = 2asin(sqrt((1-x)/2))
* = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z)
* = 2f + (2c + 2s*z*R(z))
* where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term
* for f so that f+c ~ sqrt(z).
* For x<-0.5
* acos(x) = pi - 2asin(sqrt((1-|x|)/2))
* = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z)
*
* Special cases:
* if x is NaN, return x itself;
* if |x|>1, return NaN with invalid signal.
*
* Function needed: sqrt
*/
#include "libm.h"
static const double
pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
static double R(double z)
{
double_t p, q;
p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5)))));
q = 1.0+z*(qS1+z*(qS2+z*(qS3+z*qS4)));
return p/q;
}
double acos(double x)
{
double z,w,s,c,df;
uint32_t hx,ix;
GET_HIGH_WORD(hx, x);
ix = hx & 0x7fffffff;
/* |x| >= 1 or nan */
if (ix >= 0x3ff00000) {
uint32_t lx;
GET_LOW_WORD(lx,x);
if ((ix-0x3ff00000 | lx) == 0) {
/* acos(1)=0, acos(-1)=pi */
if (hx >> 31)
return 2*pio2_hi + 0x1p-120f;
return 0;
}
return 0/(x-x);
}
/* |x| < 0.5 */
if (ix < 0x3fe00000) {
if (ix <= 0x3c600000) /* |x| < 2**-57 */
return pio2_hi + 0x1p-120f;
return pio2_hi - (x - (pio2_lo-x*R(x*x)));
}
/* x < -0.5 */
if (hx >> 31) {
z = (1.0+x)*0.5;
s = sqrt(z);
w = R(z)*s-pio2_lo;
return 2*(pio2_hi - (s+w));
}
/* x > 0.5 */
z = (1.0-x)*0.5;
s = sqrt(z);
df = s;
SET_LOW_WORD(df,0);
c = (z-df*df)/(s+df);
w = R(z)*s+c;
return 2*(df+w);
}

View File

@ -1,9 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
_Noreturn void __assert_fail(const char *expr, const char *file, int line, const char *func)
{
// TODO(orca)
// fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
abort();
}

View File

@ -1,31 +0,0 @@
#include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
static const double_t toint = 1/EPS;
double ceil(double x)
{
union {double f; uint64_t i;} u = {x};
int e = u.i >> 52 & 0x7ff;
double_t y;
if (e >= 0x3ff+52 || x == 0)
return x;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i >> 63)
y = x - toint + toint - x;
else
y = x + toint - toint - x;
/* special case because of non-nearest rounding modes */
if (e <= 0x3ff-1) {
FORCE_EVAL(y);
return u.i >> 63 ? -0.0 : 1;
}
if (y < 0)
return x + y + 1;
return x + y;
}

View File

@ -1,78 +0,0 @@
/* origin: FreeBSD /usr/src/lib/msun/src/s_cosf.c */
/*
* Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
* Optimized by Bruce D. Evans.
*/
/*
* ====================================================
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
*
* Developed at SunPro, a Sun Microsystems, Inc. business.
* Permission to use, copy, modify, and distribute this
* software is freely granted, provided that this notice
* is preserved.
* ====================================================
*/
#include "libm.h"
/* Small multiples of pi/2 rounded to double precision. */
static const double
c1pio2 = 1*M_PI_2, /* 0x3FF921FB, 0x54442D18 */
c2pio2 = 2*M_PI_2, /* 0x400921FB, 0x54442D18 */
c3pio2 = 3*M_PI_2, /* 0x4012D97C, 0x7F3321D2 */
c4pio2 = 4*M_PI_2; /* 0x401921FB, 0x54442D18 */
float cosf(float x)
{
double y;
uint32_t ix;
unsigned n, sign;
GET_FLOAT_WORD(ix, x);
sign = ix >> 31;
ix &= 0x7fffffff;
if (ix <= 0x3f490fda) { /* |x| ~<= pi/4 */
if (ix < 0x39800000) { /* |x| < 2**-12 */
/* raise inexact if x != 0 */
FORCE_EVAL(x + 0x1p120f);
return 1.0f;
}
return __cosdf(x);
}
if (ix <= 0x407b53d1) { /* |x| ~<= 5*pi/4 */
if (ix > 0x4016cbe3) /* |x| ~> 3*pi/4 */
return -__cosdf(sign ? x+c2pio2 : x-c2pio2);
else {
if (sign)
return __sindf(x + c1pio2);
else
return __sindf(c1pio2 - x);
}
}
if (ix <= 0x40e231d5) { /* |x| ~<= 9*pi/4 */
if (ix > 0x40afeddf) /* |x| ~> 7*pi/4 */
return __cosdf(sign ? x+c4pio2 : x-c4pio2);
else {
if (sign)
return __sindf(-x - c3pio2);
else
return __sindf(x - c3pio2);
}
}
/* cos(Inf or NaN) is NaN */
if (ix >= 0x7f800000)
return x-x;
/* general argument reduction needed */
n = __rem_pio2f(x,&y);
switch (n&3) {
case 0: return __cosdf(y);
case 1: return __sindf(-y);
case 2: return -__cosdf(y);
default:
return __sindf(y);
}
}

View File

@ -1,9 +0,0 @@
#include <math.h>
#include <stdint.h>
double fabs(double x)
{
union {double f; uint64_t i;} u = {x};
u.i &= -1ULL/2;
return u.f;
}

View File

@ -1,31 +0,0 @@
#include "libm.h"
#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1
#define EPS DBL_EPSILON
#elif FLT_EVAL_METHOD==2
#define EPS LDBL_EPSILON
#endif
static const double_t toint = 1/EPS;
double floor(double x)
{
union {double f; uint64_t i;} u = {x};
int e = u.i >> 52 & 0x7ff;
double_t y;
if (e >= 0x3ff+52 || x == 0)
return x;
/* y = int(x) - x, where int(x) is an integer neighbor of x */
if (u.i >> 63)
y = x - toint + toint - x;
else
y = x + toint - toint - x;
/* special case because of non-nearest rounding modes */
if (e <= 0x3ff-1) {
FORCE_EVAL(y);
return u.i >> 63 ? -1 : 0;
}
if (y > 0)
return x + y - 1;
return x + y;
}

View File

@ -1,68 +0,0 @@
#include <math.h>
#include <stdint.h>
double fmod(double x, double y)
{
union {double f; uint64_t i;} ux = {x}, uy = {y};
int ex = ux.i>>52 & 0x7ff;
int ey = uy.i>>52 & 0x7ff;
int sx = ux.i>>63;
uint64_t i;
/* in the followings uxi should be ux.i, but then gcc wrongly adds */
/* float load/store to inner loops ruining performance and code size */
uint64_t uxi = ux.i;
if (uy.i<<1 == 0 || isnan(y) || ex == 0x7ff)
return (x*y)/(x*y);
if (uxi<<1 <= uy.i<<1) {
if (uxi<<1 == uy.i<<1)
return 0*x;
return x;
}
/* normalize x and y */
if (!ex) {
for (i = uxi<<12; i>>63 == 0; ex--, i <<= 1);
uxi <<= -ex + 1;
} else {
uxi &= -1ULL >> 12;
uxi |= 1ULL << 52;
}
if (!ey) {
for (i = uy.i<<12; i>>63 == 0; ey--, i <<= 1);
uy.i <<= -ey + 1;
} else {
uy.i &= -1ULL >> 12;
uy.i |= 1ULL << 52;
}
/* x mod y */
for (; ex > ey; ex--) {
i = uxi - uy.i;
if (i >> 63 == 0) {
if (i == 0)
return 0*x;
uxi = i;
}
uxi <<= 1;
}
i = uxi - uy.i;
if (i >> 63 == 0) {
if (i == 0)
return 0*x;
uxi = i;
}
for (; uxi>>52 == 0; uxi <<= 1, ex--);
/* scale result */
if (ex > 0) {
uxi -= 1ULL << 52;
uxi |= (uint64_t)ex << 52;
} else {
uxi >>= -ex + 1;
}
uxi |= (uint64_t)sx << 63;
ux.i = uxi;
return ux.f;
}

View File

@ -1,16 +0,0 @@
#include <stdio.h>
// #include <stdarg.h>
#include <stdlib.h>
int fprintf(FILE *restrict f, const char *restrict fmt, ...)
{
// TODO(orca)
abort();
// int ret;
// va_list ap;
// va_start(ap, fmt);
// ret = vfprintf(f, fmt, ap);
// va_end(ap);
// return ret;
}

View File

@ -1,135 +0,0 @@
#include <stdint.h>
#include <float.h>
#include <math.h>
#define WANT_ROUNDING 1
#if WANT_SNAN
#error SNaN is unsupported
#else
#define issignalingf_inline(x) 0
#define issignaling_inline(x) 0
#endif
/* Helps static branch prediction so hot path can be better optimized. */
#ifdef __GNUC__
#define predict_true(x) __builtin_expect(!!(x), 1)
#define predict_false(x) __builtin_expect(x, 0)
#else
#define predict_true(x) (x)
#define predict_false(x) (x)
#endif
static inline float eval_as_float(float x)
{
float y = x;
return y;
}
static inline double eval_as_double(double x)
{
double y = x;
return y;
}
/* fp_force_eval ensures that the input value is computed when that's
otherwise unused. To prevent the constant folding of the input
expression, an additional fp_barrier may be needed or a compilation
mode that does so (e.g. -frounding-math in gcc). Then it can be
used to evaluate an expression for its fenv side-effects only. */
#ifndef fp_force_evalf
#define fp_force_evalf fp_force_evalf
static inline void fp_force_evalf(float x)
{
volatile float y;
y = x;
}
#endif
#ifndef fp_force_eval
#define fp_force_eval fp_force_eval
static inline void fp_force_eval(double x)
{
volatile double y;
y = x;
}
#endif
#ifndef fp_force_evall
#define fp_force_evall fp_force_evall
static inline void fp_force_evall(long double x)
{
volatile long double y;
y = x;
}
#endif
#define FORCE_EVAL(x) do { \
if (sizeof(x) == sizeof(float)) { \
fp_force_evalf(x); \
} else if (sizeof(x) == sizeof(double)) { \
fp_force_eval(x); \
} else { \
fp_force_evall(x); \
} \
} while(0)
#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i
#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f
#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i
#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f
#define EXTRACT_WORDS(hi,lo,d) \
do { \
uint64_t __u = asuint64(d); \
(hi) = __u >> 32; \
(lo) = (uint32_t)__u; \
} while (0)
#define GET_HIGH_WORD(hi,d) \
do { \
(hi) = asuint64(d) >> 32; \
} while (0)
#define GET_LOW_WORD(lo,d) \
do { \
(lo) = (uint32_t)asuint64(d); \
} while (0)
#define INSERT_WORDS(d,hi,lo) \
do { \
(d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \
} while (0)
#define SET_HIGH_WORD(d,hi) \
INSERT_WORDS(d, hi, (uint32_t)asuint64(d))
#define SET_LOW_WORD(d,lo) \
INSERT_WORDS(d, asuint64(d)>>32, lo)
#define GET_FLOAT_WORD(w,d) \
do { \
(w) = asuint(d); \
} while (0)
#define SET_FLOAT_WORD(d,w) \
do { \
(d) = asfloat(w); \
} while (0)
int __rem_pio2_large(double*,double*,int,int,int);
int __rem_pio2(double,double*);
double __sin(double,double,int);
double __cos(double,double);
int __rem_pio2f(float,double*);
float __sindf(double);
float __cosdf(double);
float __math_invalidf(float);
double __math_xflow(uint32_t, double);
double __math_uflow(uint32_t);
double __math_oflow(uint32_t);
double __math_invalid(double);

View File

@ -1,346 +0,0 @@
/*
* Double-precision x^y function.
*
* Copyright (c) 2018, Arm Limited.
* SPDX-License-Identifier: MIT
*/
#include <math.h>
#include <stdint.h>
#include "libm.h"
#include "exp_data.h"
#include "pow_data.h"
/*
Worst-case error: 0.54 ULP (~= ulperr_exp + 1024*Ln2*relerr_log*2^53)
relerr_log: 1.3 * 2^-68 (Relative error of log, 1.5 * 2^-68 without fma)
ulperr_exp: 0.509 ULP (ULP error of exp, 0.511 ULP without fma)
*/
#define T __pow_log_data.tab
#define A __pow_log_data.poly
#define Ln2hi __pow_log_data.ln2hi
#define Ln2lo __pow_log_data.ln2lo
#define N (1 << POW_LOG_TABLE_BITS)
#define OFF 0x3fe6955500000000
/* Top 12 bits of a double (sign and exponent bits). */
static inline uint32_t top12(double x)
{
return asuint64(x) >> 52;
}
/* Compute y+TAIL = log(x) where the rounded result is y and TAIL has about
additional 15 bits precision. IX is the bit representation of x, but
normalized in the subnormal range using the sign bit for the exponent. */
static inline double_t log_inline(uint64_t ix, double_t *tail)
{
/* double_t for better performance on targets with FLT_EVAL_METHOD==2. */
double_t z, r, y, invc, logc, logctail, kd, hi, t1, t2, lo, lo1, lo2, p;
uint64_t iz, tmp;
int k, i;
/* x = 2^k z; where z is in range [OFF,2*OFF) and exact.
The range is split into N subintervals.
The ith subinterval contains z and c is near its center. */
tmp = ix - OFF;
i = (tmp >> (52 - POW_LOG_TABLE_BITS)) % N;
k = (int64_t)tmp >> 52; /* arithmetic shift */
iz = ix - (tmp & 0xfffULL << 52);
z = asdouble(iz);
kd = (double_t)k;
/* log(x) = k*Ln2 + log(c) + log1p(z/c-1). */
invc = T[i].invc;
logc = T[i].logc;
logctail = T[i].logctail;
/* Note: 1/c is j/N or j/N/2 where j is an integer in [N,2N) and
|z/c - 1| < 1/N, so r = z/c - 1 is exactly representible. */
#if __FP_FAST_FMA
r = __builtin_fma(z, invc, -1.0);
#else
/* Split z such that rhi, rlo and rhi*rhi are exact and |rlo| <= |r|. */
double_t zhi = asdouble((iz + (1ULL << 31)) & (-1ULL << 32));
double_t zlo = z - zhi;
double_t rhi = zhi * invc - 1.0;
double_t rlo = zlo * invc;
r = rhi + rlo;
#endif
/* k*Ln2 + log(c) + r. */
t1 = kd * Ln2hi + logc;
t2 = t1 + r;
lo1 = kd * Ln2lo + logctail;
lo2 = t1 - t2 + r;
/* Evaluation is optimized assuming superscalar pipelined execution. */
double_t ar, ar2, ar3, lo3, lo4;
ar = A[0] * r; /* A[0] = -0.5. */
ar2 = r * ar;
ar3 = r * ar2;
/* k*Ln2 + log(c) + r + A[0]*r*r. */
#if __FP_FAST_FMA
hi = t2 + ar2;
lo3 = __builtin_fma(ar, r, -ar2);
lo4 = t2 - hi + ar2;
#else
double_t arhi = A[0] * rhi;
double_t arhi2 = rhi * arhi;
hi = t2 + arhi2;
lo3 = rlo * (ar + arhi);
lo4 = t2 - hi + arhi2;
#endif
/* p = log1p(r) - r - A[0]*r*r. */
p = (ar3 * (A[1] + r * A[2] +
ar2 * (A[3] + r * A[4] + ar2 * (A[5] + r * A[6]))));
lo = lo1 + lo2 + lo3 + lo4 + p;
y = hi + lo;
*tail = hi - y + lo;
return y;
}
#undef N
#undef T
#define N (1 << EXP_TABLE_BITS)
#define InvLn2N __exp_data.invln2N
#define NegLn2hiN __exp_data.negln2hiN
#define NegLn2loN __exp_data.negln2loN
#define Shift __exp_data.shift
#define T __exp_data.tab
#define C2 __exp_data.poly[5 - EXP_POLY_ORDER]
#define C3 __exp_data.poly[6 - EXP_POLY_ORDER]
#define C4 __exp_data.poly[7 - EXP_POLY_ORDER]
#define C5 __exp_data.poly[8 - EXP_POLY_ORDER]
#define C6 __exp_data.poly[9 - EXP_POLY_ORDER]
/* Handle cases that may overflow or underflow when computing the result that
is scale*(1+TMP) without intermediate rounding. The bit representation of
scale is in SBITS, however it has a computed exponent that may have
overflown into the sign bit so that needs to be adjusted before using it as
a double. (int32_t)KI is the k used in the argument reduction and exponent
adjustment of scale, positive k here means the result may overflow and
negative k means the result may underflow. */
static inline double specialcase(double_t tmp, uint64_t sbits, uint64_t ki)
{
double_t scale, y;
if ((ki & 0x80000000) == 0) {
/* k > 0, the exponent of scale might have overflowed by <= 460. */
sbits -= 1009ull << 52;
scale = asdouble(sbits);
y = 0x1p1009 * (scale + scale * tmp);
return eval_as_double(y);
}
/* k < 0, need special care in the subnormal range. */
sbits += 1022ull << 52;
/* Note: sbits is signed scale. */
scale = asdouble(sbits);
y = scale + scale * tmp;
if (fabs(y) < 1.0) {
/* Round y to the right precision before scaling it into the subnormal
range to avoid double rounding that can cause 0.5+E/2 ulp error where
E is the worst-case ulp error outside the subnormal range. So this
is only useful if the goal is better than 1 ulp worst-case error. */
double_t hi, lo, one = 1.0;
if (y < 0.0)
one = -1.0;
lo = scale - y + scale * tmp;
hi = one + y;
lo = one - hi + y + lo;
y = eval_as_double(hi + lo) - one;
/* Fix the sign of 0. */
if (y == 0.0)
y = asdouble(sbits & 0x8000000000000000);
/* The underflow exception needs to be signaled explicitly. */
// NOTE(orca): removing special fp functions
// fp_force_eval(fp_barrier(0x1p-1022) * 0x1p-1022);
}
y = 0x1p-1022 * y;
return eval_as_double(y);
}
#define SIGN_BIAS (0x800 << EXP_TABLE_BITS)
/* Computes sign*exp(x+xtail) where |xtail| < 2^-8/N and |xtail| <= |x|.
The sign_bias argument is SIGN_BIAS or 0 and sets the sign to -1 or 1. */
static inline double exp_inline(double_t x, double_t xtail, uint32_t sign_bias)
{
uint32_t abstop;
uint64_t ki, idx, top, sbits;
/* double_t for better performance on targets with FLT_EVAL_METHOD==2. */
double_t kd, z, r, r2, scale, tail, tmp;
abstop = top12(x) & 0x7ff;
if (predict_false(abstop - top12(0x1p-54) >=
top12(512.0) - top12(0x1p-54))) {
if (abstop - top12(0x1p-54) >= 0x80000000) {
/* Avoid spurious underflow for tiny x. */
/* Note: 0 is common input. */
double_t one = WANT_ROUNDING ? 1.0 + x : 1.0;
return sign_bias ? -one : one;
}
if (abstop >= top12(1024.0)) {
/* Note: inf and nan are already handled. */
if (asuint64(x) >> 63)
return __math_uflow(sign_bias);
else
return __math_oflow(sign_bias);
}
/* Large x is special cased below. */
abstop = 0;
}
/* exp(x) = 2^(k/N) * exp(r), with exp(r) in [2^(-1/2N),2^(1/2N)]. */
/* x = ln2/N*k + r, with int k and r in [-ln2/2N, ln2/2N]. */
z = InvLn2N * x;
#if TOINT_INTRINSICS
kd = roundtoint(z);
ki = converttoint(z);
#elif EXP_USE_TOINT_NARROW
/* z - kd is in [-0.5-2^-16, 0.5] in all rounding modes. */
kd = eval_as_double(z + Shift);
ki = asuint64(kd) >> 16;
kd = (double_t)(int32_t)ki;
#else
/* z - kd is in [-1, 1] in non-nearest rounding modes. */
kd = eval_as_double(z + Shift);
ki = asuint64(kd);
kd -= Shift;
#endif
r = x + kd * NegLn2hiN + kd * NegLn2loN;
/* The code assumes 2^-200 < |xtail| < 2^-8/N. */
r += xtail;
/* 2^(k/N) ~= scale * (1 + tail). */
idx = 2 * (ki % N);
top = (ki + sign_bias) << (52 - EXP_TABLE_BITS);
tail = asdouble(T[idx]);
/* This is only a valid scale when -1023*N < k < 1024*N. */
sbits = T[idx + 1] + top;
/* exp(x) = 2^(k/N) * exp(r) ~= scale + scale * (tail + exp(r) - 1). */
/* Evaluation is optimized assuming superscalar pipelined execution. */
r2 = r * r;
/* Without fma the worst case error is 0.25/N ulp larger. */
/* Worst case error is less than 0.5+1.11/N+(abs poly error * 2^53) ulp. */
tmp = tail + r + r2 * (C2 + r * C3) + r2 * r2 * (C4 + r * C5);
if (predict_false(abstop == 0))
return specialcase(tmp, sbits, ki);
scale = asdouble(sbits);
/* Note: tmp == 0 or |tmp| > 2^-200 and scale > 2^-739, so there
is no spurious underflow here even without fma. */
return eval_as_double(scale + scale * tmp);
}
/* Returns 0 if not int, 1 if odd int, 2 if even int. The argument is
the bit representation of a non-zero finite floating-point value. */
static inline int checkint(uint64_t iy)
{
int e = iy >> 52 & 0x7ff;
if (e < 0x3ff)
return 0;
if (e > 0x3ff + 52)
return 2;
if (iy & ((1ULL << (0x3ff + 52 - e)) - 1))
return 0;
if (iy & (1ULL << (0x3ff + 52 - e)))
return 1;
return 2;
}
/* Returns 1 if input is the bit representation of 0, infinity or nan. */
static inline int zeroinfnan(uint64_t i)
{
return 2 * i - 1 >= 2 * asuint64(INFINITY) - 1;
}
double pow(double x, double y)
{
uint32_t sign_bias = 0;
uint64_t ix, iy;
uint32_t topx, topy;
ix = asuint64(x);
iy = asuint64(y);
topx = top12(x);
topy = top12(y);
if (predict_false(topx - 0x001 >= 0x7ff - 0x001 ||
(topy & 0x7ff) - 0x3be >= 0x43e - 0x3be)) {
/* Note: if |y| > 1075 * ln2 * 2^53 ~= 0x1.749p62 then pow(x,y) = inf/0
and if |y| < 2^-54 / 1075 ~= 0x1.e7b6p-65 then pow(x,y) = +-1. */
/* Special cases: (x < 0x1p-126 or inf or nan) or
(|y| < 0x1p-65 or |y| >= 0x1p63 or nan). */
if (predict_false(zeroinfnan(iy))) {
if (2 * iy == 0)
return issignaling_inline(x) ? x + y : 1.0;
if (ix == asuint64(1.0))
return issignaling_inline(y) ? x + y : 1.0;
if (2 * ix > 2 * asuint64(INFINITY) ||
2 * iy > 2 * asuint64(INFINITY))
return x + y;
if (2 * ix == 2 * asuint64(1.0))
return 1.0;
if ((2 * ix < 2 * asuint64(1.0)) == !(iy >> 63))
return 0.0; /* |x|<1 && y==inf or |x|>1 && y==-inf. */
return y * y;
}
if (predict_false(zeroinfnan(ix))) {
double_t x2 = x * x;
if (ix >> 63 && checkint(iy) == 1)
x2 = -x2;
/* Without the barrier some versions of clang hoist the 1/x2 and
thus division by zero exception can be signaled spuriously. */
// NOTE(orca): I hope my version of clang is not affected lol
// return iy >> 63 ? fp_barrier(1 / x2) : x2;
return iy >> 63 ? (1 / x2) : x2;
}
/* Here x and y are non-zero finite. */
if (ix >> 63) {
/* Finite x < 0. */
int yint = checkint(iy);
if (yint == 0)
return __math_invalid(x);
if (yint == 1)
sign_bias = SIGN_BIAS;
ix &= 0x7fffffffffffffff;
topx &= 0x7ff;
}
if ((topy & 0x7ff) - 0x3be >= 0x43e - 0x3be) {
/* Note: sign_bias == 0 here because y is not odd. */
if (ix == asuint64(1.0))
return 1.0;
if ((topy & 0x7ff) < 0x3be) {
/* |y| < 2^-65, x^y ~= 1 + y*log(x). */
if (WANT_ROUNDING)
return ix > asuint64(1.0) ? 1.0 + y :
1.0 - y;
else
return 1.0;
}
return (ix > asuint64(1.0)) == (topy < 0x800) ?
__math_oflow(0) :
__math_uflow(0);
}
if (topx == 0) {
/* Normalize subnormal x so exponent becomes negative. */
ix = asuint64(x * 0x1p52);
ix &= 0x7fffffffffffffff;
ix -= 52ULL << 52;
}
}
double_t lo;
double_t hi = log_inline(ix, &lo);
double_t ehi, elo;
#if __FP_FAST_FMA
ehi = y * hi;
elo = y * lo + __builtin_fma(y, hi, -ehi);
#else
double_t yhi = asdouble(iy & -1ULL << 27);
double_t ylo = y - yhi;
double_t lhi = asdouble(asuint64(hi) & -1ULL << 27);
double_t llo = hi - lhi + lo;
ehi = yhi * lhi;
elo = ylo * lhi + y * llo; /* |elo| < |ehi| * 2^-25. */
#endif
return exp_inline(ehi, elo, sign_bias);
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2018, Arm Limited.
* SPDX-License-Identifier: MIT
*/
#ifndef _POW_DATA_H
#define _POW_DATA_H
#include <features.h>
#define POW_LOG_TABLE_BITS 7
#define POW_LOG_POLY_ORDER 8
extern const struct pow_log_data {
double ln2hi;
double ln2lo;
double poly[POW_LOG_POLY_ORDER - 1]; /* First coefficient is 1. */
/* Note: the pad field is unused, but allows slightly faster indexing. */
struct {
double invc, pad, logc, logctail;
} tab[1 << POW_LOG_TABLE_BITS];
} __pow_log_data;
#endif

View File

@ -1,33 +0,0 @@
#include <math.h>
#include <stdint.h>
double scalbn(double x, int n)
{
union {double f; uint64_t i;} u;
double_t y = x;
if (n > 1023) {
y *= 0x1p1023;
n -= 1023;
if (n > 1023) {
y *= 0x1p1023;
n -= 1023;
if (n > 1023)
n = 1023;
}
} else if (n < -1022) {
/* make sure final n < -53 to avoid double
rounding in the subnormal range */
y *= 0x1p-1022 * 0x1p53;
n += 1022 - 53;
if (n < -1022) {
y *= 0x1p-1022 * 0x1p53;
n += 1022 - 53;
if (n < -1022)
n = -1022;
}
}
u.i = (uint64_t)(0x3ff+n)<<52;
x = y * u.f;
return x;
}

View File

@ -1,19 +0,0 @@
#include "sqrt_data.h"
const uint16_t __rsqrt_tab[128] = {
0xb451,0xb2f0,0xb196,0xb044,0xaef9,0xadb6,0xac79,0xab43,
0xaa14,0xa8eb,0xa7c8,0xa6aa,0xa592,0xa480,0xa373,0xa26b,
0xa168,0xa06a,0x9f70,0x9e7b,0x9d8a,0x9c9d,0x9bb5,0x9ad1,
0x99f0,0x9913,0x983a,0x9765,0x9693,0x95c4,0x94f8,0x9430,
0x936b,0x92a9,0x91ea,0x912e,0x9075,0x8fbe,0x8f0a,0x8e59,
0x8daa,0x8cfe,0x8c54,0x8bac,0x8b07,0x8a64,0x89c4,0x8925,
0x8889,0x87ee,0x8756,0x86c0,0x862b,0x8599,0x8508,0x8479,
0x83ec,0x8361,0x82d8,0x8250,0x81c9,0x8145,0x80c2,0x8040,
0xff02,0xfd0e,0xfb25,0xf947,0xf773,0xf5aa,0xf3ea,0xf234,
0xf087,0xeee3,0xed47,0xebb3,0xea27,0xe8a3,0xe727,0xe5b2,
0xe443,0xe2dc,0xe17a,0xe020,0xdecb,0xdd7d,0xdc34,0xdaf1,
0xd9b3,0xd87b,0xd748,0xd61a,0xd4f1,0xd3cd,0xd2ad,0xd192,
0xd07b,0xcf69,0xce5b,0xcd51,0xcc4a,0xcb48,0xca4a,0xc94f,
0xc858,0xc764,0xc674,0xc587,0xc49d,0xc3b7,0xc2d4,0xc1f4,
0xc116,0xc03c,0xbf65,0xbe90,0xbdbe,0xbcef,0xbc23,0xbb59,
0xba91,0xb9cc,0xb90a,0xb84a,0xb78c,0xb6d0,0xb617,0xb560,
};

View File

@ -1,83 +0,0 @@
#include <stdint.h>
#include <math.h>
#include "libm.h"
#include "sqrt_data.h"
#define FENV_SUPPORT 1
static inline uint32_t mul32(uint32_t a, uint32_t b)
{
return (uint64_t)a*b >> 32;
}
/* see sqrt.c for more detailed comments. */
float sqrtf(float x)
{
uint32_t ix, m, m1, m0, even, ey;
ix = asuint(x);
if (predict_false(ix - 0x00800000 >= 0x7f800000 - 0x00800000)) {
/* x < 0x1p-126 or inf or nan. */
if (ix * 2 == 0)
return x;
if (ix == 0x7f800000)
return x;
if (ix > 0x7f800000)
return __math_invalidf(x);
/* x is subnormal, normalize it. */
ix = asuint(x * 0x1p23f);
ix -= 23 << 23;
}
/* x = 4^e m; with int e and m in [1, 4). */
even = ix & 0x00800000;
m1 = (ix << 8) | 0x80000000;
m0 = (ix << 7) & 0x7fffffff;
m = even ? m0 : m1;
/* 2^e is the exponent part of the return value. */
ey = ix >> 1;
ey += 0x3f800000 >> 1;
ey &= 0x7f800000;
/* compute r ~ 1/sqrt(m), s ~ sqrt(m) with 2 goldschmidt iterations. */
static const uint32_t three = 0xc0000000;
uint32_t r, s, d, u, i;
i = (ix >> 17) % 128;
r = (uint32_t)__rsqrt_tab[i] << 16;
/* |r*sqrt(m) - 1| < 0x1p-8 */
s = mul32(m, r);
/* |s/sqrt(m) - 1| < 0x1p-8 */
d = mul32(s, r);
u = three - d;
r = mul32(r, u) << 1;
/* |r*sqrt(m) - 1| < 0x1.7bp-16 */
s = mul32(s, u) << 1;
/* |s/sqrt(m) - 1| < 0x1.7bp-16 */
d = mul32(s, r);
u = three - d;
s = mul32(s, u);
/* -0x1.03p-28 < s/sqrt(m) - 1 < 0x1.fp-31 */
s = (s - 1)>>6;
/* s < sqrt(m) < s + 0x1.08p-23 */
/* compute nearest rounded result. */
uint32_t d0, d1, d2;
float y, t;
d0 = (m << 16) - s*s;
d1 = s - d0;
d2 = d1 + s + 1;
s += d1 >> 31;
s &= 0x007fffff;
s |= ey;
y = asfloat(s);
if (FENV_SUPPORT) {
/* handle rounding and inexact exception. */
uint32_t tiny = predict_false(d2==0) ? 0 : 0x01000000;
tiny |= (d1^d2) & 0x80000000;
t = asfloat(tiny);
y = eval_as_float(y + t);
}
return y;
}

217
doc/QuickStart.md Normal file
View File

@ -0,0 +1,217 @@
--------
**DISCLAIMER: This project is very much a Work In Progress. We're making it accessible in this very early state so that participants to the [Wheel Reinvention Jam 2023](https://handmade.network/jam/2023) can try it out and maybe use it as their jamming platform. Expect bugs, missing and/or incomplete features, unstable APIs, and sparse documentation. Some current issues might be a show stopper for you, so make sure you can build and run the sample apps before jumping in.**
**If you do choose to try out Orca anyway, well thanks! We'll do our best to answer your questions, and we'd really appreciate to hear your feedback!**
--------
# Orca Quick Start Guide
This is a short introduction to developing an application that can be run by the Orca runtime. We'll present the basic structure of an Orca application, and walk through a simple example in C.
## What is an Orca app?
An Orca app is a WebAssembly module designed for the Orca runtime. Your app interacts with the Orca runtime via WebAssembly imports and exports. For example, you can import functions from the Orca runtime to get user input, and export functions to the Orca runtime to draw to the screen.
Orca also ships with a core library, written in C, which facilitates interaction with the Orca runtime and provides features like UI. This library should be compiled along with your app as part of producing your WebAssembly module.
You can, in principle, write an Orca app in any programming language that supports WebAssembly. However, at this early stage, C is the only officially supported language.
![Basic structure of a C app](images/app_c.png)
Once you have compiled your WebAssembly module, you can bundle this module into an executable using the `orca bundle` command. The application bundle can include images, fonts, or any other private data that the app needs in order to function. These files can be read or written from the app without asking the user for permission. The resulting Orca executables are therefore self-contained.
![Example Orca application bundle](images/app_bundle.png)
## Basic structure
Orca exposes a number of types and functions to applications. In order to use them the first thing to do is to include `orca.h`.
```c
#include<orca.h>
```
The Orca runtime manages the application's window and event loop. In order to receive a specific kind of event, you can define an associated _event handler_ and export it to the runtime. For instance, to be notified when your application's window is resized, you should define the `oc_on_resize()` handler:
```c
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{
// handle the window resize event
}
```
The `ORCA_EXPORT` macro makes the handler visible to the Orca runtime, which automatically binds it to the window resize event.
Handlers are optional. If you don't care about an event, you can just omit the associated handler. However, you will almost certainly want to define at least two important handlers:
- `oc_on_init()` is called once when your application starts and can be use to initialize your application's resources.
- `oc_on_frame_refresh()` is called when your application needs to render a new frame, typically tied to the refresh rate of the monitor.
For a list of available handlers and their signatures, see the [app cheatsheet](../doc/cheatsheets/cheatsheet_app.h).
## Clock example
Let's look at the [clock example](../samples/clock). This is a simple app that shows an analog clock and showcases a couple of interesting Orca APIs.
Open [`main.c`](../samples/clock/src/main.c) and look at the definition of `oc_on_init()`. This handler is called when the application starts, right after the application window has been created.
The first thing we do here is set the title and dimensions of the window. We then create the graphics resources that we'll use to draw the clock onto the window.
```c
ORCA_EXPORT void oc_on_init(void)
{
oc_window_set_title(OC_STR8("clock"));
oc_window_set_size((oc_vec2){ .x = 400, .y = 400 });
// ...
}
```
### Graphics surfaces
The next line of `oc_on_init()` creates a _graphics surface_. A surface represents a destination you can draw into using a specific API. In this sample, we're going to use a canvas surface, which allows drawing with a 2D vector graphics API. Other samples use a GLES surface to draw with the OpenGL ES API.
Before drawing into it, the surface must be selected as the current surface by calling `oc_surface_select()`. Once all drawing is done you can display the result by calling `oc_surface_present()`.
```c
oc_surface surface = { 0 };
oc_canvas canvas = { 0 };
ORCA_EXPORT void oc_on_init(void)
{
// ...
surface = oc_surface_canvas();
canvas = oc_canvas_create();
// ...
}
```
### Canvas
After creating the surface, we create a _canvas_. A canvas holds some context for drawing commands, like the current color or stroke width, as well as a command buffer that records all drawing commands. All canvas drawing functions use an implicit _current canvas_. You can select a canvas to be the current canvas by calling `oc_canvas_select()`, as seen at the begining of `oc_on_frame_refresh()`.
Canvas drawing functions like `oc_fill()` or `oc_stroke` merely add to the current canvas command buffer. You can later render those commands onto a canvas surface by calling `oc_render()`.
To summarize, the general structure of canvas drawing code is like the following:
```c
ORCA_EXPORT void oc_on_frame_refresh(void)
{
oc_canvas_select(canvas); // make the canvas current
//... add commands to the canvas command buffer using drawing functions
oc_surface_select(surface); // select the canvas surface
oc_render(canvas); // render the canvas commands into it
oc_surface_present(surface); // display the result
}
```
### Drawing
Canvas drawing functions can be roughly divided into three groups:
- Path functions like `oc_line_to()` or `oc_cubic_to()` are used to specify paths using lines and curves.
- Attribute setup functions like `oc_set_color()` or `oc_set_width()` are used to set attributes used by subsequent commands.
- Command functions like `oc_stroke()` and `oc_fill()` encode commands into the canvas command buffer using the current path and attributes.
Some helpers combine a path specification and a command, like `oc_circle_fill()`.
As an example, the back of the clock is drawn using these two calls:
```c
oc_set_color_rgba(1, 1, 1, 1);
oc_circle_fill(centerX, centerY, clockRadius);
```
For a list of canvas drawing functions, see the [graphics API cheatsheet](../doc/cheatsheets/cheatsheet_graphics.h).
#### Transforms
A special case of attribute setting function is the pair `oc_matrix_multiply_push()` and `oc_matrix_pop()`, which are used to manipulate a stack of transform matrices:
- `oc_matrix_multiply_push()` multiplies the matrix currently on top of the stack with its argument, and pushes the result on the stack.
- `oc_matrix_pop()` pops a matrix from the stack.
The matrix on the top of the stack at the time a command is encoded is used to transform the path of that command.
You can see an example of using transform matrices when drawing the clock's hands:
```c
// hour hand
oc_matrix_multiply_push(mat_transform(centerX, centerY, hoursRotation));
{
oc_set_color_rgba(.2, 0.2, 0.2, 1);
oc_rounded_rectangle_fill(0, -7.5 * uiScale, clockRadius * 0.5f, 15 * uiScale, 5 * uiScale);
}
oc_matrix_pop();
```
### Fonts and text
Going back to `oc_init()`, after creating a surface and a canvas, we create a font that we will use to draw the numbers on the clock's face:
```c
oc_unicode_range ranges[5] = {
OC_UNICODE_BASIC_LATIN,
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
OC_UNICODE_LATIN_EXTENDED_A,
OC_UNICODE_LATIN_EXTENDED_B,
OC_UNICODE_SPECIALS
};
font = oc_font_create_from_path(OC_STR8("/segoeui.ttf"), 5, ranges);
```
The font is loaded from a font file located in a data folder inside the app bundle. By default, Orca apps use this data folder as their "root" for file operations.
Along with the path of the font file, we pass to the creation function the unicode ranges we want to load.
We then use the font to draw the clock's face:
```c
// clock face
for(int i = 0; i < oc_array_size(clockNumberStrings); ++i)
{
oc_rect textRect = oc_font_text_metrics(font, fontSize, clockNumberStrings[i]).ink;
const f32 angle = i * ((M_PI * 2) / 12.0f) - (M_PI / 2);
oc_mat2x3 transform = mat_transform(centerX - (textRect.w / 2) - textRect.x,
centerY - (textRect.h / 2) - textRect.y,
angle);
oc_vec2 pos = oc_mat2x3_mul(transform, (oc_vec2){ clockRadius * 0.8f, 0 });
oc_set_color_rgba(0.2, 0.2, 0.2, 1);
oc_text_fill(pos.x, pos.y, clockNumberStrings[i]);
}
```
### Logging and asserts
The runtime has a console overlay whose visiblity can be toggled on and off with `⌘ + Shift + D` on macOS, or `Ctrl + Shift + D` on Windows. Your application can log messages, warnings, or errors to that console using the following functions:
```c
void oc_log_info(const char* fmt, ...); // informational messages
void oc_log_warning(const char* fmt, ...); // warnings, displayed in orange.
void oc_log_error(const char* fmt, ...); // errors, displayed in red.
```
If you started the application from a terminal, the log entries are also duplicated there.
You can assert on a condition using `OC_ASSERT(test, fmt, ...)`. If the test fails, the runtime displays a message box and terminates the application.
You can unconditionally abort the application with a message box using `OC_ABORT(fmt, ...)`.
## Where to go next?
For more examples of how to use Orca APIs, you can look at the other [sample apps](../samples):
- [breakout](../samples/breakout) is a mini breakout game making use of the vector graphics API. It demonstrates using input and drawing images.
- [triangle](../samples/triangle) shows how to draw a spining triangle using the GLES API.
- [fluid](../samples/fluid) is a fluid simulation using a more complex GLES setup.
- [ui](../samples/ui) showcases the UI API and Orca's default UI widgets.
For a list of Orca APIs, you can look at the [API cheatsheets](../doc/cheatsheets).
You can also ask questions in the [Handmade Network Discord](https://discord.gg/hmn), in particular in the [#orca](https://discord.com/channels/239737791225790464/1121811864066732082) channel.

7
doc/UIColors.md Normal file
View File

@ -0,0 +1,7 @@
# UI Colors
## Dark (default theme)
![Dark theme colors](images/UIDarkPalette.svg)
## Light
![Light theme colors](images/UILightPalette.svg)

View File

@ -0,0 +1,35 @@
/************************************************************/ /**
*
* @file: cheatsheet_app.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Handlers (can be defined by your app to respond to events)
//----------------------------------------------------------------
void oc_on_init(void);
void oc_on_mouse_down(oc_mouse_button button);
void oc_on_mouse_up(oc_mouse_button button);
void oc_on_mouse_enter(void);
void oc_on_mouse_leave(void);
void oc_on_mouse_move(f32 x, f32 y, f32 deltaX, f32 deltaY);
void oc_on_mouse_wheel(f32 deltaX, f32 deltaY);
void oc_on_key_down(oc_scan_code scan, oc_key_code key);
void oc_on_key_up(oc_scan_code scan, oc_key_code key);
void oc_on_frame_refresh(void);
void oc_on_resize(f32 width, f32 height);
void oc_on_raw_event(oc_event* event);
void oc_on_terminate(void);
//----------------------------------------------------------------
// Window
//----------------------------------------------------------------
void oc_window_set_title(oc_str8 title);
void oc_window_set_size(oc_vec2 size);
//----------------------------------------------------------------
// Quitting
//----------------------------------------------------------------
void oc_request_quit(void)

View File

@ -0,0 +1,166 @@
/************************************************************/ /**
*
* @file: cheatsheet_graphics.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//------------------------------------------------------------------------------------------
// graphics surface
//------------------------------------------------------------------------------------------
oc_surface oc_surface_nil(void);
bool oc_surface_is_nil(oc_surface surface);
oc_surface oc_surface_canvas();
oc_surface oc_surface_gles();
void oc_surface_destroy(oc_surface surface);
void oc_surface_select(oc_surface surface);
void oc_surface_deselect(void);
void oc_surface_present(oc_surface surface);
oc_vec2 oc_surface_get_size(oc_surface surface);
oc_vec2 oc_surface_contents_scaling(oc_surface surface);
void oc_surface_bring_to_front(oc_surface surface);
void oc_surface_send_to_back(oc_surface surface);
//------------------------------------------------------------------------------------------
// 2D canvas command buffer
//------------------------------------------------------------------------------------------
oc_canvas oc_canvas_nil(void);
bool oc_canvas_is_nil(oc_canvas canvas);
oc_canvas oc_canvas_create(void);
void oc_canvas_destroy(oc_canvas canvas);
oc_canvas oc_canvas_set_current(oc_canvas canvas);
void oc_render(oc_canvas canvas);
//------------------------------------------------------------------------------------------
// transform and clipping
//------------------------------------------------------------------------------------------
void oc_matrix_push(oc_mat2x3 matrix);
void oc_matrix_multiply_push(oc_mat2x3 matrix);
void oc_matrix_pop(void);
oc_mat2x3 oc_matrix_top();
void oc_clip_push(f32 x, f32 y, f32 w, f32 h);
void oc_clip_pop(void);
oc_rect oc_clip_top();
//------------------------------------------------------------------------------------------
// graphics attributes setting/getting
//------------------------------------------------------------------------------------------
void oc_set_color(oc_color color);
void oc_set_color_rgba(f32 r, f32 g, f32 b, f32 a);
void oc_set_width(f32 width);
void oc_set_tolerance(f32 tolerance);
void oc_set_joint(oc_joint_type joint);
void oc_set_max_joint_excursion(f32 maxJointExcursion);
void oc_set_cap(oc_cap_type cap);
void oc_set_font(oc_font font);
void oc_set_font_size(f32 size);
void oc_set_text_flip(bool flip);
void oc_set_image(oc_image image);
void oc_set_image_source_region(oc_rect region);
oc_color oc_get_color(void);
f32 oc_get_width(void);
f32 oc_get_tolerance(void);
oc_joint_type oc_get_joint(void);
f32 oc_get_max_joint_excursion(void);
oc_cap_type oc_get_cap(void);
oc_font oc_get_font(void);
f32 oc_get_font_size(void);
bool oc_get_text_flip(void);
oc_image oc_get_image();
//------------------------------------------------------------------------------------------
// path construction
//------------------------------------------------------------------------------------------
oc_vec2 oc_get_position(void);
void oc_move_to(f32 x, f32 y);
void oc_line_to(f32 x, f32 y);
void oc_quadratic_to(f32 x1, f32 y1, f32 x2, f32 y2);
void oc_cubic_to(f32 x1, f32 y1, f32 x2, f32 y2, f32 x3, f32 y3);
void oc_close_path(void);
oc_rect oc_glyph_outlines(oc_str32 glyphIndices);
void oc_codepoints_outlines(oc_str32 string);
void oc_text_outlines(oc_str8 string);
//------------------------------------------------------------------------------------------
// clear/fill/stroke
//------------------------------------------------------------------------------------------
void oc_clear(void);
void oc_fill(void);
void oc_stroke(void);
//------------------------------------------------------------------------------------------
// shapes helpers
//------------------------------------------------------------------------------------------
void oc_rectangle_fill(f32 x, f32 y, f32 w, f32 h);
void oc_rectangle_stroke(f32 x, f32 y, f32 w, f32 h);
void oc_rounded_rectangle_fill(f32 x, f32 y, f32 w, f32 h, f32 r);
void oc_rounded_rectangle_stroke(f32 x, f32 y, f32 w, f32 h, f32 r);
void oc_ellipse_fill(f32 x, f32 y, f32 rx, f32 ry);
void oc_ellipse_stroke(f32 x, f32 y, f32 rx, f32 ry);
void oc_circle_fill(f32 x, f32 y, f32 r);
void oc_circle_stroke(f32 x, f32 y, f32 r);
void oc_arc(f32 x, f32 y, f32 r, f32 arcAngle, f32 startAngle);
void oc_image_draw(oc_image image, oc_rect rect);
void oc_image_draw_region(oc_image image, oc_rect srcRegion, oc_rect dstRegion);
//------------------------------------------------------------------------------------------
// fonts
//------------------------------------------------------------------------------------------
oc_font oc_font_nil(void);
bool oc_font_is_nil(oc_font font);
oc_font oc_font_create_from_memory(oc_str8 mem, u32 rangeCount, oc_unicode_range* ranges);
oc_font oc_font_create_from_file(oc_file file, u32 rangeCount, oc_unicode_range* ranges);
oc_font oc_font_create_from_path(oc_str8 path, u32 rangeCount, oc_unicode_range* ranges);
void oc_font_destroy(oc_font font);
oc_str32 oc_font_get_glyph_indices(oc_font font, oc_str32 codePoints, oc_str32 backing);
oc_str32 oc_font_push_glyph_indices(oc_arena* arena, oc_font font, oc_str32 codePoints);
u32 oc_font_get_glyph_index(oc_font font, oc_utf32 codePoint);
oc_font_metrics oc_font_get_metrics(oc_font font, f32 emSize);
oc_font_metrics oc_font_get_metrics_unscaled(oc_font font);
f32 oc_font_get_scale_for_em_pixels(oc_font font, f32 emSize);
oc_text_metrics oc_font_text_metrics_utf32(oc_font font, f32 fontSize, oc_str32 codepoints);
oc_text_metrics oc_font_text_metrics(oc_font font, f32 fontSize, oc_str8 text);
//------------------------------------------------------------------------------------------
// images
//------------------------------------------------------------------------------------------
oc_image oc_image_nil(void);
bool oc_image_is_nil(oc_image a);
oc_image oc_image_create(oc_surface surface, u32 width, u32 height);
oc_image oc_image_create_from_rgba8(oc_surface surface, u32 width, u32 height, u8* pixels);
oc_image oc_image_create_from_memory(oc_surface surface, oc_str8 mem, bool flip);
oc_image oc_image_create_from_file(oc_surface surface, oc_file file, bool flip);
oc_image oc_image_create_from_path(oc_surface surface, oc_str8 path, bool flip);
void oc_image_destroy(oc_image image);
void oc_image_upload_region_rgba8(oc_image image, oc_rect region, u8* pixels);
oc_vec2 oc_image_size(oc_image image);
//------------------------------------------------------------------------------------------
// image atlas
//------------------------------------------------------------------------------------------
oc_rect_atlas* oc_rect_atlas_create(oc_arena* arena, i32 width, i32 height);
oc_rect oc_rect_atlas_alloc(oc_rect_atlas* atlas, i32 width, i32 height);
void oc_rect_atlas_recycle(oc_rect_atlas* atlas, oc_rect rect);
oc_image_region oc_image_atlas_alloc_from_rgba8(oc_rect_atlas* atlas, oc_image backingImage, u32 width, u32 height, u8* pixels);
oc_image_region oc_image_atlas_alloc_from_memory(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 mem, bool flip);
oc_image_region oc_image_atlas_alloc_from_file(oc_rect_atlas* atlas, oc_image backingImage, oc_file file, bool flip);
oc_image_region oc_image_atlas_alloc_from_path(oc_rect_atlas* atlas, oc_image backingImage, oc_str8 path, bool flip);
void oc_image_atlas_recycle(oc_rect_atlas* atlas, oc_image_region imageRgn);

View File

@ -0,0 +1,39 @@
/************************************************************/ /**
*
* @file: cheatsheet_io.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Low-level File IO API
//----------------------------------------------------------------
oc_io_cmp oc_io_wait_single_req(oc_io_req* req);
//----------------------------------------------------------------
// High-level File IO API
//----------------------------------------------------------------
oc_file oc_file_nil();
bool oc_file_is_nil(oc_file handle);
oc_file oc_file_open(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
oc_file oc_file_open_at(oc_file dir, oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
void oc_file_close(oc_file file);
oc_io_error oc_file_last_error(oc_file handle);
i64 oc_file_pos(oc_file file);
i64 oc_file_seek(oc_file file, i64 offset, oc_file_whence whence);
u64 oc_file_write(oc_file file, u64 size, char* buffer);
u64 oc_file_read(oc_file file, u64 size, char* buffer);
oc_file_status oc_file_get_status(oc_file file);
u64 oc_file_size(oc_file file);
//----------------------------------------------------------------
// Asking users for file capabilities
//----------------------------------------------------------------
oc_file oc_file_open_with_request(oc_str8 path, oc_file_access rights, oc_file_open_flags flags);
oc_file_open_with_dialog_result oc_file_open_with_dialog(oc_arena* arena, oc_file_access rights, oc_file_open_flags flags, oc_file_dialog_desc* desc);

View File

@ -0,0 +1,64 @@
/************************************************************/ /**
*
* @file: cheatsheet_ui.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Context and frame lifecycle
//----------------------------------------------------------------
void oc_ui_init(oc_ui_context* context);
oc_ui_context* oc_ui_get_context(void);
void oc_ui_set_context(oc_ui_context* context);
void oc_ui_process_event(oc_event* event);
void oc_ui_begin_frame(oc_vec2 size, oc_ui_style* defaultStyle, oc_ui_style_mask mask);
void oc_ui_end_frame(void);
void oc_ui_draw(void);
#define oc_ui_frame(size, style, mask)
//----------------------------------------------------------------
// Common widget helpers
//----------------------------------------------------------------
oc_ui_sig oc_ui_label(const char* label);
oc_ui_sig oc_ui_label_str8(oc_str8 label);
oc_ui_sig oc_ui_button(const char* label);
oc_ui_sig oc_ui_checkbox(const char* name, bool* checked);
oc_ui_box* oc_ui_slider(const char* label, f32 thumbRatio, f32* scrollValue);
oc_ui_text_box_result oc_ui_text_box(const char* name, oc_arena* arena, oc_str8 text);
oc_ui_select_popup_info oc_ui_select_popup(const char* name, oc_ui_select_popup_info* info);
void oc_ui_panel_begin(const char* name, oc_ui_flags flags);
void oc_ui_panel_end(void);
#define oc_ui_panel(s, f)
void oc_ui_menu_bar_begin(const char* label);
void oc_ui_menu_bar_end(void);
#define oc_ui_menu_bar(name)
void oc_ui_menu_begin(const char* label);
void oc_ui_menu_end(void);
#define oc_ui_menu(name)
oc_ui_sig oc_ui_menu_button(const char* name);
oc_ui_sig oc_ui_tooltip_begin(const char* name);
void oc_ui_tooltip_end(void);
#define oc_ui_tooltip(name)
//-------------------------------------------------------------------------------------
// Styling
//-------------------------------------------------------------------------------------
void oc_ui_style_next(oc_ui_style* style, oc_ui_style_mask mask);
void oc_ui_pattern_push(oc_arena* arena, oc_ui_pattern* pattern, oc_ui_selector selector);
oc_ui_pattern oc_ui_pattern_all(void);
oc_ui_pattern oc_ui_pattern_owner(void);
void oc_ui_style_match_before(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);
void oc_ui_style_match_after(oc_ui_pattern pattern, oc_ui_style* style, oc_ui_style_mask mask);

View File

@ -0,0 +1,101 @@
/************************************************************/ /**
*
* @file: cheatsheet_util.h
* @author: Martin Fouilleul
* @date: 05/09/2023
*
*****************************************************************/
//----------------------------------------------------------------
// Arenas
//----------------------------------------------------------------
void oc_arena_init(oc_arena* arena);
void oc_arena_init_with_options(oc_arena* arena, oc_arena_options* options);
void oc_arena_cleanup(oc_arena* arena);
void* oc_arena_push(oc_arena* arena, u64 size);
#define oc_arena_push_type(arena, type)
#define oc_arena_push_array(arena, type, count)
void oc_arena_clear(oc_arena* arena);
oc_arena_scope oc_arena_scope_begin(oc_arena* arena);
void oc_arena_scope_end(oc_arena_scope scope);
oc_arena_scope oc_scratch_begin(void);
oc_arena_scope oc_scratch_begin_next(oc_arena* used);
#define oc_scratch_end(scope)
//----------------------------------------------------------------
// Lists
//----------------------------------------------------------------
void oc_list_init(oc_list* list);
bool oc_list_empty(oc_list* list);
oc_list_elt* oc_list_begin(oc_list* list);
oc_list_elt* oc_list_end(oc_list* list);
oc_list_elt* oc_list_last(oc_list* list);
#define oc_list_next(elt)
#define oc_list_prev(elt)
#define oc_list_entry(ptr, type, member)
#define oc_list_next_entry(list, elt, type, member)
#define oc_list_prev_entry(list, elt, type, member)
#define oc_list_first_entry(list, type, member)
#define oc_list_last_entry(list, type, member)
#define oc_list_pop_entry(list, type, member)
void oc_list_insert(oc_list* list, oc_list_elt* afterElt, oc_list_elt* elt);
void oc_list_insert_before(oc_list* list, oc_list_elt* beforeElt, oc_list_elt* elt);
void oc_list_remove(oc_list* list, oc_list_elt* elt);
void oc_list_push(oc_list* list, oc_list_elt* elt);
oc_list_elt* oc_list_pop(oc_list* list);
void oc_list_push_back(oc_list* list, oc_list_elt* elt);
oc_list_elt* oc_list_pop_back(oc_list* list);
#define oc_list_for(list, elt, type, member)
#define oc_list_for_reverse(list, elt, type, member)
#define oc_list_for_safe(list, elt, type, member)
//----------------------------------------------------------------
// Strings / string lists / path strings
//----------------------------------------------------------------
oc_str8 oc_str8_from_buffer(u64 len, char* buffer);
oc_str8 oc_str8_slice(oc_str8 s, u64 start, u64 end);
oc_str8 oc_str8_push_buffer(oc_arena* arena, u64 len, char* buffer);
oc_str8 oc_str8_push_cstring(oc_arena* arena, const char* str);
oc_str8 oc_str8_push_copy(oc_arena* arena, oc_str8 s);
oc_str8 oc_str8_push_slice(oc_arena* arena, oc_str8 s, u64 start, u64 end);
oc_str8 oc_str8_pushfv(oc_arena* arena, const char* format, va_list args);
oc_str8 oc_str8_pushf(oc_arena* arena, const char* format, ...);
int oc_str8_cmp(oc_str8 s1, oc_str8 s2);
char* oc_str8_to_cstring(oc_arena* arena, oc_str8 string);
void oc_str8_list_push(oc_arena* arena, oc_str8_list* list, oc_str8 str);
void oc_str8_list_pushf(oc_arena* arena, oc_str8_list* list, const char* format, ...);
oc_str8 oc_str8_list_collate(oc_arena* arena, oc_str8_list list, oc_str8 prefix, oc_str8 separator, oc_str8 postfix);
oc_str8 oc_str8_list_join(oc_arena* arena, oc_str8_list list);
oc_str8_list oc_str8_split(oc_arena* arena, oc_str8 str, oc_str8_list separators);
oc_str8 oc_path_slice_directory(oc_str8 path);
oc_str8 oc_path_slice_filename(oc_str8 path);
oc_str8_list oc_path_split(oc_arena* arena, oc_str8 path);
oc_str8 oc_path_join(oc_arena* arena, oc_str8_list elements);
oc_str8 oc_path_append(oc_arena* arena, oc_str8 parent, oc_str8 relPath);
bool oc_path_is_absolute(oc_str8 path);
//----------------------------------------------------------------
// Debugging
//----------------------------------------------------------------
#define oc_log_info(message, ...)
#define oc_log_warning(message, ...)
#define oc_log_error(message, ...)
#define OC_ASSERT(test, message, ...)
#define OC_ABORT(message, ...)

View File

@ -0,0 +1,500 @@
<?xml version="1.0"?>
<!-- Generated by SVGo -->
<svg width="1200" height="1050"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
<![CDATA[
text {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"
}
]]>
</style>
<rect x="0" y="0" width="150" height="50" style="fill: #6C090B" />
<text x="5" y="29" style="font-size: 16px; fill: #fff3ef" >red0</text>
<text x="5" y="45" style="font-size: 12px; fill: #fff3ef" >#6C090B</text>
<rect x="0" y="50" width="150" height="50" style="fill: #901110" />
<text x="5" y="79" style="font-size: 16px; fill: #fff3ef" >red1</text>
<text x="5" y="95" style="font-size: 12px; fill: #fff3ef" >#901110</text>
<rect x="0" y="100" width="150" height="50" style="fill: #B42019" />
<text x="5" y="129" style="font-size: 16px; fill: #fff3ef" >red2</text>
<text x="5" y="145" style="font-size: 12px; fill: #fff3ef" >#B42019</text>
<rect x="0" y="150" width="150" height="50" style="fill: #D73324" />
<text x="5" y="179" style="font-size: 16px; fill: #fff3ef" >red3</text>
<text x="5" y="195" style="font-size: 12px; fill: #fff3ef" >#D73324</text>
<rect x="0" y="200" width="150" height="50" style="fill: #FB4932" />
<text x="5" y="229" style="font-size: 16px; fill: #fff3ef" >red4</text>
<text x="5" y="245" style="font-size: 12px; fill: #fff3ef" >#FB4932</text>
<rect x="0" y="250" width="150" height="50" style="fill: #FC725A" />
<text x="5" y="279" style="font-size: 16px; fill: #6c090b" >red5</text>
<text x="5" y="295" style="font-size: 12px; fill: #6c090b" >#FC725A</text>
<rect x="0" y="300" width="150" height="50" style="fill: #FD9983" />
<text x="5" y="329" style="font-size: 16px; fill: #6c090b" >red6</text>
<text x="5" y="345" style="font-size: 12px; fill: #6c090b" >#FD9983</text>
<rect x="0" y="350" width="150" height="50" style="fill: #FDBEAC" />
<text x="5" y="379" style="font-size: 16px; fill: #6c090b" >red7</text>
<text x="5" y="395" style="font-size: 12px; fill: #6c090b" >#FDBEAC</text>
<rect x="0" y="400" width="150" height="50" style="fill: #FEE0D5" />
<text x="5" y="429" style="font-size: 16px; fill: #6c090b" >red8</text>
<text x="5" y="445" style="font-size: 12px; fill: #6c090b" >#FEE0D5</text>
<rect x="0" y="450" width="150" height="50" style="fill: #FFF3EF" />
<text x="5" y="479" style="font-size: 16px; fill: #6c090b" >red9</text>
<text x="5" y="495" style="font-size: 12px; fill: #6c090b" >#FFF3EF</text>
<rect x="150" y="0" width="150" height="50" style="fill: #551F03" />
<text x="155" y="29" style="font-size: 16px; fill: #fff9ed" >orange0</text>
<text x="155" y="45" style="font-size: 12px; fill: #fff9ed" >#551F03</text>
<rect x="150" y="50" width="150" height="50" style="fill: #803506" />
<text x="155" y="79" style="font-size: 16px; fill: #fff9ed" >orange1</text>
<text x="155" y="95" style="font-size: 12px; fill: #fff9ed" >#803506</text>
<rect x="150" y="100" width="150" height="50" style="fill: #AA500A" />
<text x="155" y="129" style="font-size: 16px; fill: #fff9ed" >orange2</text>
<text x="155" y="145" style="font-size: 12px; fill: #fff9ed" >#AA500A</text>
<rect x="150" y="150" width="150" height="50" style="fill: #D56F0F" />
<text x="155" y="179" style="font-size: 16px; fill: #fff9ed" >orange3</text>
<text x="155" y="195" style="font-size: 12px; fill: #fff9ed" >#D56F0F</text>
<rect x="150" y="200" width="150" height="50" style="fill: #FF9214" />
<text x="155" y="229" style="font-size: 16px; fill: #fff9ed" >orange4</text>
<text x="155" y="245" style="font-size: 12px; fill: #fff9ed" >#FF9214</text>
<rect x="150" y="250" width="150" height="50" style="fill: #FFAE43" />
<text x="155" y="279" style="font-size: 16px; fill: #551f03" >orange5</text>
<text x="155" y="295" style="font-size: 12px; fill: #551f03" >#FFAE43</text>
<rect x="150" y="300" width="150" height="50" style="fill: #FFC772" />
<text x="155" y="329" style="font-size: 16px; fill: #551f03" >orange6</text>
<text x="155" y="345" style="font-size: 12px; fill: #551f03" >#FFC772</text>
<rect x="150" y="350" width="150" height="50" style="fill: #FFDDA1" />
<text x="155" y="379" style="font-size: 16px; fill: #551f03" >orange7</text>
<text x="155" y="395" style="font-size: 12px; fill: #551f03" >#FFDDA1</text>
<rect x="150" y="400" width="150" height="50" style="fill: #FFEFD0" />
<text x="155" y="429" style="font-size: 16px; fill: #551f03" >orange8</text>
<text x="155" y="445" style="font-size: 12px; fill: #551f03" >#FFEFD0</text>
<rect x="150" y="450" width="150" height="50" style="fill: #FFF9ED" />
<text x="155" y="479" style="font-size: 16px; fill: #551f03" >orange9</text>
<text x="155" y="495" style="font-size: 12px; fill: #551f03" >#FFF9ED</text>
<rect x="300" y="0" width="150" height="50" style="fill: #512E09" />
<text x="305" y="29" style="font-size: 16px; fill: #fefbed" >amber0</text>
<text x="305" y="45" style="font-size: 12px; fill: #fefbed" >#512E09</text>
<rect x="300" y="50" width="150" height="50" style="fill: #794B0F" />
<text x="305" y="79" style="font-size: 16px; fill: #fefbed" >amber1</text>
<text x="305" y="95" style="font-size: 12px; fill: #fefbed" >#794B0F</text>
<rect x="300" y="100" width="150" height="50" style="fill: #A16B16" />
<text x="305" y="129" style="font-size: 16px; fill: #fefbed" >amber2</text>
<text x="305" y="145" style="font-size: 12px; fill: #fefbed" >#A16B16</text>
<rect x="300" y="150" width="150" height="50" style="fill: #CA8F1E" />
<text x="305" y="179" style="font-size: 16px; fill: #fefbed" >amber3</text>
<text x="305" y="195" style="font-size: 12px; fill: #fefbed" >#CA8F1E</text>
<rect x="300" y="200" width="150" height="50" style="fill: #F2B726" />
<text x="305" y="229" style="font-size: 16px; fill: #fefbed" >amber4</text>
<text x="305" y="245" style="font-size: 12px; fill: #fefbed" >#F2B726</text>
<rect x="300" y="250" width="150" height="50" style="fill: #F5CA50" />
<text x="305" y="279" style="font-size: 16px; fill: #512e09" >amber5</text>
<text x="305" y="295" style="font-size: 12px; fill: #512e09" >#F5CA50</text>
<rect x="300" y="300" width="150" height="50" style="fill: #F7DB7A" />
<text x="305" y="329" style="font-size: 16px; fill: #512e09" >amber6</text>
<text x="305" y="345" style="font-size: 12px; fill: #512e09" >#F7DB7A</text>
<rect x="300" y="350" width="150" height="50" style="fill: #FAEAA6" />
<text x="305" y="379" style="font-size: 16px; fill: #512e09" >amber7</text>
<text x="305" y="395" style="font-size: 12px; fill: #512e09" >#FAEAA6</text>
<rect x="300" y="400" width="150" height="50" style="fill: #FCF6D2" />
<text x="305" y="429" style="font-size: 16px; fill: #512e09" >amber8</text>
<text x="305" y="445" style="font-size: 12px; fill: #512e09" >#FCF6D2</text>
<rect x="300" y="450" width="150" height="50" style="fill: #FEFBED" />
<text x="305" y="479" style="font-size: 16px; fill: #512e09" >amber9</text>
<text x="305" y="495" style="font-size: 12px; fill: #512e09" >#FEFBED</text>
<rect x="450" y="0" width="150" height="50" style="fill: #544903" />
<text x="455" y="29" style="font-size: 16px; fill: #fffeec" >yellow0</text>
<text x="455" y="45" style="font-size: 12px; fill: #fffeec" >#544903</text>
<rect x="450" y="50" width="150" height="50" style="fill: #7E6C06" />
<text x="455" y="79" style="font-size: 16px; fill: #fffeec" >yellow1</text>
<text x="455" y="95" style="font-size: 12px; fill: #fffeec" >#7E6C06</text>
<rect x="450" y="100" width="150" height="50" style="fill: #A88E0A" />
<text x="455" y="129" style="font-size: 16px; fill: #fffeec" >yellow2</text>
<text x="455" y="145" style="font-size: 12px; fill: #fffeec" >#A88E0A</text>
<rect x="450" y="150" width="150" height="50" style="fill: #D2AF0F" />
<text x="455" y="179" style="font-size: 16px; fill: #fffeec" >yellow3</text>
<text x="455" y="195" style="font-size: 12px; fill: #fffeec" >#D2AF0F</text>
<rect x="450" y="200" width="150" height="50" style="fill: #FCCE14" />
<text x="455" y="229" style="font-size: 16px; fill: #fffeec" >yellow4</text>
<text x="455" y="245" style="font-size: 12px; fill: #fffeec" >#FCCE14</text>
<rect x="450" y="250" width="150" height="50" style="fill: #FDDE43" />
<text x="455" y="279" style="font-size: 16px; fill: #544903" >yellow5</text>
<text x="455" y="295" style="font-size: 12px; fill: #544903" >#FDDE43</text>
<rect x="450" y="300" width="150" height="50" style="fill: #FDEB71" />
<text x="455" y="329" style="font-size: 16px; fill: #544903" >yellow6</text>
<text x="455" y="345" style="font-size: 12px; fill: #544903" >#FDEB71</text>
<rect x="450" y="350" width="150" height="50" style="fill: #FEF5A0" />
<text x="455" y="379" style="font-size: 16px; fill: #544903" >yellow7</text>
<text x="455" y="395" style="font-size: 12px; fill: #544903" >#FEF5A0</text>
<rect x="450" y="400" width="150" height="50" style="fill: #FEFBD0" />
<text x="455" y="429" style="font-size: 16px; fill: #544903" >yellow8</text>
<text x="455" y="445" style="font-size: 12px; fill: #544903" >#FEFBD0</text>
<rect x="450" y="450" width="150" height="50" style="fill: #FFFEEC" />
<text x="455" y="479" style="font-size: 16px; fill: #544903" >yellow9</text>
<text x="455" y="495" style="font-size: 12px; fill: #544903" >#FFFEEC</text>
<rect x="600" y="0" width="150" height="50" style="fill: #314603" />
<text x="605" y="29" style="font-size: 16px; fill: #f3fbe9" >lime0</text>
<text x="605" y="45" style="font-size: 12px; fill: #f3fbe9" >#314603</text>
<rect x="600" y="50" width="150" height="50" style="fill: #4B6905" />
<text x="605" y="79" style="font-size: 16px; fill: #f3fbe9" >lime1</text>
<text x="605" y="95" style="font-size: 12px; fill: #f3fbe9" >#4B6905</text>
<rect x="600" y="100" width="150" height="50" style="fill: #678D09" />
<text x="605" y="129" style="font-size: 16px; fill: #f3fbe9" >lime2</text>
<text x="605" y="145" style="font-size: 12px; fill: #f3fbe9" >#678D09</text>
<rect x="600" y="150" width="150" height="50" style="fill: #84B00C" />
<text x="605" y="179" style="font-size: 16px; fill: #f3fbe9" >lime3</text>
<text x="605" y="195" style="font-size: 12px; fill: #f3fbe9" >#84B00C</text>
<rect x="600" y="200" width="150" height="50" style="fill: #A2D311" />
<text x="605" y="229" style="font-size: 16px; fill: #f3fbe9" >lime4</text>
<text x="605" y="245" style="font-size: 12px; fill: #f3fbe9" >#A2D311</text>
<rect x="600" y="250" width="150" height="50" style="fill: #AEDC3A" />
<text x="605" y="279" style="font-size: 16px; fill: #314603" >lime5</text>
<text x="605" y="295" style="font-size: 12px; fill: #314603" >#AEDC3A</text>
<rect x="600" y="300" width="150" height="50" style="fill: #BDE566" />
<text x="605" y="329" style="font-size: 16px; fill: #314603" >lime6</text>
<text x="605" y="345" style="font-size: 12px; fill: #314603" >#BDE566</text>
<rect x="600" y="350" width="150" height="50" style="fill: #CFED96" />
<text x="605" y="379" style="font-size: 16px; fill: #314603" >lime7</text>
<text x="605" y="395" style="font-size: 12px; fill: #314603" >#CFED96</text>
<rect x="600" y="400" width="150" height="50" style="fill: #E5F6C9" />
<text x="605" y="429" style="font-size: 16px; fill: #314603" >lime8</text>
<text x="605" y="445" style="font-size: 12px; fill: #314603" >#E5F6C9</text>
<rect x="600" y="450" width="150" height="50" style="fill: #F3FBE9" />
<text x="605" y="479" style="font-size: 16px; fill: #314603" >lime9</text>
<text x="605" y="495" style="font-size: 12px; fill: #314603" >#F3FBE9</text>
<rect x="750" y="0" width="150" height="50" style="fill: #263D13" />
<text x="755" y="29" style="font-size: 16px; fill: #f3f8ed" >lightGreen0</text>
<text x="755" y="45" style="font-size: 12px; fill: #f3f8ed" >#263D13</text>
<rect x="750" y="50" width="150" height="50" style="fill: #3B5C1D" />
<text x="755" y="79" style="font-size: 16px; fill: #f3f8ed" >lightGreen1</text>
<text x="755" y="95" style="font-size: 12px; fill: #f3f8ed" >#3B5C1D</text>
<rect x="750" y="100" width="150" height="50" style="fill: #517B28" />
<text x="755" y="129" style="font-size: 16px; fill: #f3f8ed" >lightGreen2</text>
<text x="755" y="145" style="font-size: 12px; fill: #f3f8ed" >#517B28</text>
<rect x="750" y="150" width="150" height="50" style="fill: #679934" />
<text x="755" y="179" style="font-size: 16px; fill: #f3f8ed" >lightGreen3</text>
<text x="755" y="195" style="font-size: 12px; fill: #f3f8ed" >#679934</text>
<rect x="750" y="200" width="150" height="50" style="fill: #7FB840" />
<text x="755" y="229" style="font-size: 16px; fill: #f3f8ed" >lightGreen4</text>
<text x="755" y="245" style="font-size: 12px; fill: #f3f8ed" >#7FB840</text>
<rect x="750" y="250" width="150" height="50" style="fill: #97C65F" />
<text x="755" y="279" style="font-size: 16px; fill: #263d13" >lightGreen5</text>
<text x="755" y="295" style="font-size: 12px; fill: #263d13" >#97C65F</text>
<rect x="750" y="300" width="150" height="50" style="fill: #B0D481" />
<text x="755" y="329" style="font-size: 16px; fill: #263d13" >lightGreen6</text>
<text x="755" y="345" style="font-size: 12px; fill: #263d13" >#B0D481</text>
<rect x="750" y="350" width="150" height="50" style="fill: #C9E3A7" />
<text x="755" y="379" style="font-size: 16px; fill: #263d13" >lightGreen7</text>
<text x="755" y="395" style="font-size: 12px; fill: #263d13" >#C9E3A7</text>
<rect x="750" y="400" width="150" height="50" style="fill: #E4F1D1" />
<text x="755" y="429" style="font-size: 16px; fill: #263d13" >lightGreen8</text>
<text x="755" y="445" style="font-size: 12px; fill: #263d13" >#E4F1D1</text>
<rect x="750" y="450" width="150" height="50" style="fill: #F3F8ED" />
<text x="755" y="479" style="font-size: 16px; fill: #263d13" >lightGreen9</text>
<text x="755" y="495" style="font-size: 12px; fill: #263d13" >#F3F8ED</text>
<rect x="900" y="0" width="150" height="50" style="fill: #123C19" />
<text x="905" y="29" style="font-size: 16px; fill: #ecf7ec" >green0</text>
<text x="905" y="45" style="font-size: 12px; fill: #ecf7ec" >#123C19</text>
<rect x="900" y="50" width="150" height="50" style="fill: #1C5A25" />
<text x="905" y="79" style="font-size: 16px; fill: #ecf7ec" >green1</text>
<text x="905" y="95" style="font-size: 12px; fill: #ecf7ec" >#1C5A25</text>
<rect x="900" y="100" width="150" height="50" style="fill: #277731" />
<text x="905" y="129" style="font-size: 16px; fill: #ecf7ec" >green2</text>
<text x="905" y="145" style="font-size: 12px; fill: #ecf7ec" >#277731</text>
<rect x="900" y="150" width="150" height="50" style="fill: #32953D" />
<text x="905" y="179" style="font-size: 16px; fill: #ecf7ec" >green3</text>
<text x="905" y="195" style="font-size: 12px; fill: #ecf7ec" >#32953D</text>
<rect x="900" y="200" width="150" height="50" style="fill: #3EB349" />
<text x="905" y="229" style="font-size: 16px; fill: #ecf7ec" >green4</text>
<text x="905" y="245" style="font-size: 12px; fill: #ecf7ec" >#3EB349</text>
<rect x="900" y="250" width="150" height="50" style="fill: #5DC264" />
<text x="905" y="279" style="font-size: 16px; fill: #123c19" >green5</text>
<text x="905" y="295" style="font-size: 12px; fill: #123c19" >#5DC264</text>
<rect x="900" y="300" width="150" height="50" style="fill: #7FD184" />
<text x="905" y="329" style="font-size: 16px; fill: #123c19" >green6</text>
<text x="905" y="345" style="font-size: 12px; fill: #123c19" >#7FD184</text>
<rect x="900" y="350" width="150" height="50" style="fill: #A6E1A8" />
<text x="905" y="379" style="font-size: 16px; fill: #123c19" >green7</text>
<text x="905" y="395" style="font-size: 12px; fill: #123c19" >#A6E1A8</text>
<rect x="900" y="400" width="150" height="50" style="fill: #D0F0D1" />
<text x="905" y="429" style="font-size: 16px; fill: #123c19" >green8</text>
<text x="905" y="445" style="font-size: 12px; fill: #123c19" >#D0F0D1</text>
<rect x="900" y="450" width="150" height="50" style="fill: #ECF7EC" />
<text x="905" y="479" style="font-size: 16px; fill: #123c19" >green9</text>
<text x="905" y="495" style="font-size: 12px; fill: #123c19" >#ECF7EC</text>
<rect x="1050" y="0" width="150" height="50" style="fill: #023C39" />
<text x="1055" y="29" style="font-size: 16px; fill: #e6f7f4" >teal0</text>
<text x="1055" y="45" style="font-size: 12px; fill: #e6f7f4" >#023C39</text>
<rect x="1050" y="50" width="150" height="50" style="fill: #045A55" />
<text x="1055" y="79" style="font-size: 16px; fill: #e6f7f4" >teal1</text>
<text x="1055" y="95" style="font-size: 12px; fill: #e6f7f4" >#045A55</text>
<rect x="1050" y="100" width="150" height="50" style="fill: #07776F" />
<text x="1055" y="129" style="font-size: 16px; fill: #e6f7f4" >teal2</text>
<text x="1055" y="145" style="font-size: 12px; fill: #e6f7f4" >#07776F</text>
<rect x="1050" y="150" width="150" height="50" style="fill: #0A9588" />
<text x="1055" y="179" style="font-size: 16px; fill: #e6f7f4" >teal3</text>
<text x="1055" y="195" style="font-size: 12px; fill: #e6f7f4" >#0A9588</text>
<rect x="1050" y="200" width="150" height="50" style="fill: #0EB3A1" />
<text x="1055" y="229" style="font-size: 16px; fill: #e6f7f4" >teal4</text>
<text x="1055" y="245" style="font-size: 12px; fill: #e6f7f4" >#0EB3A1</text>
<rect x="1050" y="250" width="150" height="50" style="fill: #33C2B0" />
<text x="1055" y="279" style="font-size: 16px; fill: #023c39" >teal5</text>
<text x="1055" y="295" style="font-size: 12px; fill: #023c39" >#33C2B0</text>
<rect x="1050" y="300" width="150" height="50" style="fill: #5ED1C1" />
<text x="1055" y="329" style="font-size: 16px; fill: #023c39" >teal6</text>
<text x="1055" y="345" style="font-size: 12px; fill: #023c39" >#5ED1C1</text>
<rect x="1050" y="350" width="150" height="50" style="fill: #8EE1D3" />
<text x="1055" y="379" style="font-size: 16px; fill: #023c39" >teal7</text>
<text x="1055" y="395" style="font-size: 12px; fill: #023c39" >#8EE1D3</text>
<rect x="1050" y="400" width="150" height="50" style="fill: #C4F0E8" />
<text x="1055" y="429" style="font-size: 16px; fill: #023c39" >teal8</text>
<text x="1055" y="445" style="font-size: 12px; fill: #023c39" >#C4F0E8</text>
<rect x="1050" y="450" width="150" height="50" style="fill: #E6F7F4" />
<text x="1055" y="479" style="font-size: 16px; fill: #023c39" >teal9</text>
<text x="1055" y="495" style="font-size: 12px; fill: #023c39" >#E6F7F4</text>
<rect x="0" y="500" width="150" height="50" style="fill: #04343D" />
<text x="5" y="529" style="font-size: 16px; fill: #e7f7f8" >cyan0</text>
<text x="5" y="545" style="font-size: 12px; fill: #e7f7f8" >#04343D</text>
<rect x="0" y="550" width="150" height="50" style="fill: #074F5C" />
<text x="5" y="579" style="font-size: 16px; fill: #e7f7f8" >cyan1</text>
<text x="5" y="595" style="font-size: 12px; fill: #e7f7f8" >#074F5C</text>
<rect x="0" y="600" width="150" height="50" style="fill: #0A6C7B" />
<text x="5" y="629" style="font-size: 16px; fill: #e7f7f8" >cyan2</text>
<text x="5" y="645" style="font-size: 12px; fill: #e7f7f8" >#0A6C7B</text>
<rect x="0" y="650" width="150" height="50" style="fill: #0E8999" />
<text x="5" y="679" style="font-size: 16px; fill: #e7f7f8" >cyan3</text>
<text x="5" y="695" style="font-size: 12px; fill: #e7f7f8" >#0E8999</text>
<rect x="0" y="700" width="150" height="50" style="fill: #13A8B8" />
<text x="5" y="729" style="font-size: 16px; fill: #e7f7f8" >cyan4</text>
<text x="5" y="745" style="font-size: 12px; fill: #e7f7f8" >#13A8B8</text>
<rect x="0" y="750" width="150" height="50" style="fill: #38BBC6" />
<text x="5" y="779" style="font-size: 16px; fill: #04343d" >cyan5</text>
<text x="5" y="795" style="font-size: 12px; fill: #04343d" >#38BBC6</text>
<rect x="0" y="800" width="150" height="50" style="fill: #62CDD4" />
<text x="5" y="829" style="font-size: 16px; fill: #04343d" >cyan6</text>
<text x="5" y="845" style="font-size: 12px; fill: #04343d" >#62CDD4</text>
<rect x="0" y="850" width="150" height="50" style="fill: #91DFE3" />
<text x="5" y="879" style="font-size: 16px; fill: #04343d" >cyan7</text>
<text x="5" y="895" style="font-size: 12px; fill: #04343d" >#91DFE3</text>
<rect x="0" y="900" width="150" height="50" style="fill: #C6EFF1" />
<text x="5" y="929" style="font-size: 16px; fill: #04343d" >cyan8</text>
<text x="5" y="945" style="font-size: 12px; fill: #04343d" >#C6EFF1</text>
<rect x="0" y="950" width="150" height="50" style="fill: #E7F7F8" />
<text x="5" y="979" style="font-size: 16px; fill: #04343d" >cyan9</text>
<text x="5" y="995" style="font-size: 12px; fill: #04343d" >#E7F7F8</text>
<rect x="150" y="500" width="150" height="50" style="fill: #003761" />
<text x="155" y="529" style="font-size: 16px; fill: #ebf8fe" >lightBlue0</text>
<text x="155" y="545" style="font-size: 12px; fill: #ebf8fe" >#003761</text>
<rect x="150" y="550" width="150" height="50" style="fill: #004D85" />
<text x="155" y="579" style="font-size: 16px; fill: #ebf8fe" >lightBlue1</text>
<text x="155" y="595" style="font-size: 12px; fill: #ebf8fe" >#004D85</text>
<rect x="150" y="600" width="150" height="50" style="fill: #0366A9" />
<text x="155" y="629" style="font-size: 16px; fill: #ebf8fe" >lightBlue2</text>
<text x="155" y="645" style="font-size: 12px; fill: #ebf8fe" >#0366A9</text>
<rect x="150" y="650" width="150" height="50" style="fill: #0A81CC" />
<text x="155" y="679" style="font-size: 16px; fill: #ebf8fe" >lightBlue3</text>
<text x="155" y="695" style="font-size: 12px; fill: #ebf8fe" >#0A81CC</text>
<rect x="150" y="700" width="150" height="50" style="fill: #139FF0" />
<text x="155" y="729" style="font-size: 16px; fill: #ebf8fe" >lightBlue4</text>
<text x="155" y="745" style="font-size: 12px; fill: #ebf8fe" >#139FF0</text>
<rect x="150" y="750" width="150" height="50" style="fill: #40B4F3" />
<text x="155" y="779" style="font-size: 16px; fill: #003761" >lightBlue5</text>
<text x="155" y="795" style="font-size: 12px; fill: #003761" >#40B4F3</text>
<rect x="150" y="800" width="150" height="50" style="fill: #6EC8F6" />
<text x="155" y="829" style="font-size: 16px; fill: #003761" >lightBlue6</text>
<text x="155" y="845" style="font-size: 12px; fill: #003761" >#6EC8F6</text>
<rect x="150" y="850" width="150" height="50" style="fill: #9DDCF9" />
<text x="155" y="879" style="font-size: 16px; fill: #003761" >lightBlue7</text>
<text x="155" y="895" style="font-size: 12px; fill: #003761" >#9DDCF9</text>
<rect x="150" y="900" width="150" height="50" style="fill: #CEEEFC" />
<text x="155" y="929" style="font-size: 16px; fill: #003761" >lightBlue8</text>
<text x="155" y="945" style="font-size: 12px; fill: #003761" >#CEEEFC</text>
<rect x="150" y="950" width="150" height="50" style="fill: #EBF8FE" />
<text x="155" y="979" style="font-size: 16px; fill: #003761" >lightBlue9</text>
<text x="155" y="995" style="font-size: 12px; fill: #003761" >#EBF8FE</text>
<rect x="300" y="500" width="150" height="50" style="fill: #053170" />
<text x="305" y="529" style="font-size: 16px; fill: #eff8ff" >blue0</text>
<text x="305" y="545" style="font-size: 12px; fill: #eff8ff" >#053170</text>
<rect x="300" y="550" width="150" height="50" style="fill: #0A4694" />
<text x="305" y="579" style="font-size: 16px; fill: #eff8ff" >blue1</text>
<text x="305" y="595" style="font-size: 12px; fill: #eff8ff" >#0A4694</text>
<rect x="300" y="600" width="150" height="50" style="fill: #135CB8" />
<text x="305" y="629" style="font-size: 16px; fill: #eff8ff" >blue2</text>
<text x="305" y="645" style="font-size: 12px; fill: #eff8ff" >#135CB8</text>
<rect x="300" y="650" width="150" height="50" style="fill: #1D75DB" />
<text x="305" y="679" style="font-size: 16px; fill: #eff8ff" >blue3</text>
<text x="305" y="695" style="font-size: 12px; fill: #eff8ff" >#1D75DB</text>
<rect x="300" y="700" width="150" height="50" style="fill: #2990FF" />
<text x="305" y="729" style="font-size: 16px; fill: #eff8ff" >blue4</text>
<text x="305" y="745" style="font-size: 12px; fill: #eff8ff" >#2990FF</text>
<rect x="300" y="750" width="150" height="50" style="fill: #54A9FF" />
<text x="305" y="779" style="font-size: 16px; fill: #053170" >blue5</text>
<text x="305" y="795" style="font-size: 12px; fill: #053170" >#54A9FF</text>
<rect x="300" y="800" width="150" height="50" style="fill: #7FC1FF" />
<text x="305" y="829" style="font-size: 16px; fill: #053170" >blue6</text>
<text x="305" y="845" style="font-size: 12px; fill: #053170" >#7FC1FF</text>
<rect x="300" y="850" width="150" height="50" style="fill: #A9D7FF" />
<text x="305" y="879" style="font-size: 16px; fill: #053170" >blue7</text>
<text x="305" y="895" style="font-size: 12px; fill: #053170" >#A9D7FF</text>
<rect x="300" y="900" width="150" height="50" style="fill: #D4ECFF" />
<text x="305" y="929" style="font-size: 16px; fill: #053170" >blue8</text>
<text x="305" y="945" style="font-size: 12px; fill: #053170" >#D4ECFF</text>
<rect x="300" y="950" width="150" height="50" style="fill: #EFF8FF" />
<text x="305" y="979" style="font-size: 16px; fill: #053170" >blue9</text>
<text x="305" y="995" style="font-size: 12px; fill: #053170" >#EFF8FF</text>
<rect x="450" y="500" width="150" height="50" style="fill: #171E65" />
<text x="455" y="529" style="font-size: 16px; fill: #edeff8" >indigo0</text>
<text x="455" y="545" style="font-size: 12px; fill: #edeff8" >#171E65</text>
<rect x="450" y="550" width="150" height="50" style="fill: #20297A" />
<text x="455" y="579" style="font-size: 16px; fill: #edeff8" >indigo1</text>
<text x="455" y="595" style="font-size: 12px; fill: #edeff8" >#20297A</text>
<rect x="450" y="600" width="150" height="50" style="fill: #29368E" />
<text x="455" y="629" style="font-size: 16px; fill: #edeff8" >indigo2</text>
<text x="455" y="645" style="font-size: 12px; fill: #edeff8" >#29368E</text>
<rect x="450" y="650" width="150" height="50" style="fill: #3444A3" />
<text x="455" y="679" style="font-size: 16px; fill: #edeff8" >indigo3</text>
<text x="455" y="695" style="font-size: 12px; fill: #edeff8" >#3444A3</text>
<rect x="450" y="700" width="150" height="50" style="fill: #4053B7" />
<text x="455" y="729" style="font-size: 16px; fill: #edeff8" >indigo4</text>
<text x="455" y="745" style="font-size: 12px; fill: #edeff8" >#4053B7</text>
<rect x="450" y="750" width="150" height="50" style="fill: #5F71C5" />
<text x="455" y="779" style="font-size: 16px; fill: #171e65" >indigo5</text>
<text x="455" y="795" style="font-size: 12px; fill: #171e65" >#5F71C5</text>
<rect x="450" y="800" width="150" height="50" style="fill: #8191D4" />
<text x="455" y="829" style="font-size: 16px; fill: #171e65" >indigo6</text>
<text x="455" y="845" style="font-size: 12px; fill: #171e65" >#8191D4</text>
<rect x="450" y="850" width="150" height="50" style="fill: #A7B4E2" />
<text x="455" y="879" style="font-size: 16px; fill: #171e65" >indigo7</text>
<text x="455" y="895" style="font-size: 12px; fill: #171e65" >#A7B4E2</text>
<rect x="450" y="900" width="150" height="50" style="fill: #D1D8F1" />
<text x="455" y="929" style="font-size: 16px; fill: #171e65" >indigo8</text>
<text x="455" y="945" style="font-size: 12px; fill: #171e65" >#D1D8F1</text>
<rect x="450" y="950" width="150" height="50" style="fill: #EDEFF8" />
<text x="455" y="979" style="font-size: 16px; fill: #171e65" >indigo9</text>
<text x="455" y="995" style="font-size: 12px; fill: #171e65" >#EDEFF8</text>
<rect x="600" y="500" width="150" height="50" style="fill: #401B77" />
<text x="605" y="529" style="font-size: 16px; fill: #f1eefa" >violet0</text>
<text x="605" y="545" style="font-size: 12px; fill: #f1eefa" >#401B77</text>
<rect x="600" y="550" width="150" height="50" style="fill: #4C248C" />
<text x="605" y="579" style="font-size: 16px; fill: #f1eefa" >violet1</text>
<text x="605" y="595" style="font-size: 12px; fill: #f1eefa" >#4C248C</text>
<rect x="600" y="600" width="150" height="50" style="fill: #582EA0" />
<text x="605" y="629" style="font-size: 16px; fill: #f1eefa" >violet2</text>
<text x="605" y="645" style="font-size: 12px; fill: #f1eefa" >#582EA0</text>
<rect x="600" y="650" width="150" height="50" style="fill: #6439B5" />
<text x="605" y="679" style="font-size: 16px; fill: #f1eefa" >violet3</text>
<text x="605" y="695" style="font-size: 12px; fill: #f1eefa" >#6439B5</text>
<rect x="600" y="700" width="150" height="50" style="fill: #7246C9" />
<text x="605" y="729" style="font-size: 16px; fill: #f1eefa" >violet4</text>
<text x="605" y="745" style="font-size: 12px; fill: #f1eefa" >#7246C9</text>
<rect x="600" y="750" width="150" height="50" style="fill: #8865D4" />
<text x="605" y="779" style="font-size: 16px; fill: #401b77" >violet5</text>
<text x="605" y="795" style="font-size: 12px; fill: #401b77" >#8865D4</text>
<rect x="600" y="800" width="150" height="50" style="fill: #A288DF" />
<text x="605" y="829" style="font-size: 16px; fill: #401b77" >violet6</text>
<text x="605" y="845" style="font-size: 12px; fill: #401b77" >#A288DF</text>
<rect x="600" y="850" width="150" height="50" style="fill: #BEADE9" />
<text x="605" y="879" style="font-size: 16px; fill: #401b77" >violet7</text>
<text x="605" y="895" style="font-size: 12px; fill: #401b77" >#BEADE9</text>
<rect x="600" y="900" width="150" height="50" style="fill: #DDD4F4" />
<text x="605" y="929" style="font-size: 16px; fill: #401b77" >violet8</text>
<text x="605" y="945" style="font-size: 12px; fill: #401b77" >#DDD4F4</text>
<rect x="600" y="950" width="150" height="50" style="fill: #F1EEFA" />
<text x="605" y="979" style="font-size: 16px; fill: #401b77" >violet9</text>
<text x="605" y="995" style="font-size: 12px; fill: #401b77" >#F1EEFA</text>
<rect x="750" y="500" width="150" height="50" style="fill: #4A1061" />
<text x="755" y="529" style="font-size: 16px; fill: #f7ebf7" >purple0</text>
<text x="755" y="545" style="font-size: 12px; fill: #f7ebf7" >#4A1061</text>
<rect x="750" y="550" width="150" height="50" style="fill: #5E1776" />
<text x="755" y="579" style="font-size: 16px; fill: #f7ebf7" >purple1</text>
<text x="755" y="595" style="font-size: 12px; fill: #f7ebf7" >#5E1776</text>
<rect x="750" y="600" width="150" height="50" style="fill: #731F8A" />
<text x="755" y="629" style="font-size: 16px; fill: #f7ebf7" >purple2</text>
<text x="755" y="645" style="font-size: 12px; fill: #f7ebf7" >#731F8A</text>
<rect x="750" y="650" width="150" height="50" style="fill: #89289F" />
<text x="755" y="679" style="font-size: 16px; fill: #f7ebf7" >purple3</text>
<text x="755" y="695" style="font-size: 12px; fill: #f7ebf7" >#89289F</text>
<rect x="750" y="700" width="150" height="50" style="fill: #A033B3" />
<text x="755" y="729" style="font-size: 16px; fill: #f7ebf7" >purple4</text>
<text x="755" y="745" style="font-size: 12px; fill: #f7ebf7" >#A033B3</text>
<rect x="750" y="750" width="150" height="50" style="fill: #B553C2" />
<text x="755" y="779" style="font-size: 16px; fill: #4a1061" >purple5</text>
<text x="755" y="795" style="font-size: 12px; fill: #4a1061" >#B553C2</text>
<rect x="750" y="800" width="150" height="50" style="fill: #CA78D1" />
<text x="755" y="829" style="font-size: 16px; fill: #4a1061" >purple6</text>
<text x="755" y="845" style="font-size: 12px; fill: #4a1061" >#CA78D1</text>
<rect x="750" y="850" width="150" height="50" style="fill: #DDA0E1" />
<text x="755" y="879" style="font-size: 16px; fill: #4a1061" >purple7</text>
<text x="755" y="895" style="font-size: 12px; fill: #4a1061" >#DDA0E1</text>
<rect x="750" y="900" width="150" height="50" style="fill: #EFCEF0" />
<text x="755" y="929" style="font-size: 16px; fill: #4a1061" >purple8</text>
<text x="755" y="945" style="font-size: 12px; fill: #4a1061" >#EFCEF0</text>
<rect x="750" y="950" width="150" height="50" style="fill: #F7EBF7" />
<text x="755" y="979" style="font-size: 16px; fill: #4a1061" >purple9</text>
<text x="755" y="995" style="font-size: 12px; fill: #4a1061" >#F7EBF7</text>
<rect x="900" y="500" width="150" height="50" style="fill: #5C0730" />
<text x="905" y="529" style="font-size: 16px; fill: #fdeef1" >pink0</text>
<text x="905" y="545" style="font-size: 12px; fill: #fdeef1" >#5C0730</text>
<rect x="900" y="550" width="150" height="50" style="fill: #800E41" />
<text x="905" y="579" style="font-size: 16px; fill: #fdeef1" >pink1</text>
<text x="905" y="595" style="font-size: 12px; fill: #fdeef1" >#800E41</text>
<rect x="900" y="600" width="150" height="50" style="fill: #A41751" />
<text x="905" y="629" style="font-size: 16px; fill: #fdeef1" >pink2</text>
<text x="905" y="645" style="font-size: 12px; fill: #fdeef1" >#A41751</text>
<rect x="900" y="650" width="150" height="50" style="fill: #C72261" />
<text x="905" y="679" style="font-size: 16px; fill: #fdeef1" >pink3</text>
<text x="905" y="695" style="font-size: 12px; fill: #fdeef1" >#C72261</text>
<rect x="900" y="700" width="150" height="50" style="fill: #EB2F71" />
<text x="905" y="729" style="font-size: 16px; fill: #fdeef1" >pink4</text>
<text x="905" y="745" style="font-size: 12px; fill: #fdeef1" >#EB2F71</text>
<rect x="900" y="750" width="150" height="50" style="fill: #EF5686" />
<text x="905" y="779" style="font-size: 16px; fill: #5c0730" >pink5</text>
<text x="905" y="795" style="font-size: 12px; fill: #5c0730" >#EF5686</text>
<rect x="900" y="800" width="150" height="50" style="fill: #F37E9F" />
<text x="905" y="829" style="font-size: 16px; fill: #5c0730" >pink6</text>
<text x="905" y="845" style="font-size: 12px; fill: #5c0730" >#F37E9F</text>
<rect x="900" y="850" width="150" height="50" style="fill: #F7A8BC" />
<text x="905" y="879" style="font-size: 16px; fill: #5c0730" >pink7</text>
<text x="905" y="895" style="font-size: 12px; fill: #5c0730" >#F7A8BC</text>
<rect x="900" y="900" width="150" height="50" style="fill: #FBD3DC" />
<text x="905" y="929" style="font-size: 16px; fill: #5c0730" >pink8</text>
<text x="905" y="945" style="font-size: 12px; fill: #5c0730" >#FBD3DC</text>
<rect x="900" y="950" width="150" height="50" style="fill: #FDEEF1" />
<text x="905" y="979" style="font-size: 16px; fill: #5c0730" >pink9</text>
<text x="905" y="995" style="font-size: 12px; fill: #5c0730" >#FDEEF1</text>
<rect x="1050" y="500" width="150" height="50" style="fill: #1C1F23" />
<text x="1055" y="529" style="font-size: 16px; fill: #f9f9f9" >grey0</text>
<text x="1055" y="545" style="font-size: 12px; fill: #f9f9f9" >#1C1F23</text>
<rect x="1050" y="550" width="150" height="50" style="fill: #2E3238" />
<text x="1055" y="579" style="font-size: 16px; fill: #f9f9f9" >grey1</text>
<text x="1055" y="595" style="font-size: 12px; fill: #f9f9f9" >#2E3238</text>
<rect x="1050" y="600" width="150" height="50" style="fill: #41464C" />
<text x="1055" y="629" style="font-size: 16px; fill: #f9f9f9" >grey2</text>
<text x="1055" y="645" style="font-size: 12px; fill: #f9f9f9" >#41464C</text>
<rect x="1050" y="650" width="150" height="50" style="fill: #555B61" />
<text x="1055" y="679" style="font-size: 16px; fill: #f9f9f9" >grey3</text>
<text x="1055" y="695" style="font-size: 12px; fill: #f9f9f9" >#555B61</text>
<rect x="1050" y="700" width="150" height="50" style="fill: #6B7075" />
<text x="1055" y="729" style="font-size: 16px; fill: #f9f9f9" >grey4</text>
<text x="1055" y="745" style="font-size: 12px; fill: #f9f9f9" >#6B7075</text>
<rect x="1050" y="750" width="150" height="50" style="fill: #888D92" />
<text x="1055" y="779" style="font-size: 16px; fill: #1c1f23" >grey5</text>
<text x="1055" y="795" style="font-size: 12px; fill: #1c1f23" >#888D92</text>
<rect x="1050" y="800" width="150" height="50" style="fill: #A7ABB0" />
<text x="1055" y="829" style="font-size: 16px; fill: #1c1f23" >grey6</text>
<text x="1055" y="845" style="font-size: 12px; fill: #1c1f23" >#A7ABB0</text>
<rect x="1050" y="850" width="150" height="50" style="fill: #C6CACD" />
<text x="1055" y="879" style="font-size: 16px; fill: #1c1f23" >grey7</text>
<text x="1055" y="895" style="font-size: 12px; fill: #1c1f23" >#C6CACD</text>
<rect x="1050" y="900" width="150" height="50" style="fill: #E6E8EA" />
<text x="1055" y="929" style="font-size: 16px; fill: #1c1f23" >grey8</text>
<text x="1055" y="945" style="font-size: 12px; fill: #1c1f23" >#E6E8EA</text>
<rect x="1050" y="950" width="150" height="50" style="fill: #F9F9F9" />
<text x="1055" y="979" style="font-size: 16px; fill: #1c1f23" >grey9</text>
<text x="1055" y="995" style="font-size: 12px; fill: #1c1f23" >#F9F9F9</text>
<rect x="0" y="1000" width="600" height="50" style="fill: #FFFFFF" />
<text x="5" y="1029" style="font-size: 16px; fill: #808080" >white</text>
<text x="5" y="1045" style="font-size: 12px; fill: #808080" >#FFFFFF</text>
<rect x="600" y="1000" width="600" height="50" style="fill: #000000" />
<text x="605" y="1029" style="font-size: 16px; fill: #808080" >black</text>
<text x="605" y="1045" style="font-size: 12px; fill: #808080" >#000000</text>
</svg>

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -0,0 +1,500 @@
<?xml version="1.0"?>
<!-- Generated by SVGo -->
<svg width="1200" height="1050"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style type="text/css">
<![CDATA[
text {
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"
}
]]>
</style>
<rect x="0" y="0" width="150" height="50" style="fill: #FEF2ED" />
<text x="5" y="29" style="font-size: 16px; fill: #6a0103" >red0</text>
<text x="5" y="45" style="font-size: 12px; fill: #6a0103" >#FEF2ED</text>
<rect x="0" y="50" width="150" height="50" style="fill: #FEDDD2" />
<text x="5" y="79" style="font-size: 16px; fill: #6a0103" >red1</text>
<text x="5" y="95" style="font-size: 12px; fill: #6a0103" >#FEDDD2</text>
<rect x="0" y="100" width="150" height="50" style="fill: #FDB7A5" />
<text x="5" y="129" style="font-size: 16px; fill: #6a0103" >red2</text>
<text x="5" y="145" style="font-size: 12px; fill: #6a0103" >#FDB7A5</text>
<rect x="0" y="150" width="150" height="50" style="fill: #FB9078" />
<text x="5" y="179" style="font-size: 16px; fill: #6a0103" >red3</text>
<text x="5" y="195" style="font-size: 12px; fill: #6a0103" >#FB9078</text>
<rect x="0" y="200" width="150" height="50" style="fill: #FA664C" />
<text x="5" y="229" style="font-size: 16px; fill: #6a0103" >red4</text>
<text x="5" y="245" style="font-size: 12px; fill: #6a0103" >#FA664C</text>
<rect x="0" y="250" width="150" height="50" style="fill: #F93920" />
<text x="5" y="279" style="font-size: 16px; fill: #fef2ed" >red5</text>
<text x="5" y="295" style="font-size: 12px; fill: #fef2ed" >#F93920</text>
<rect x="0" y="300" width="150" height="50" style="fill: #D52515" />
<text x="5" y="329" style="font-size: 16px; fill: #fef2ed" >red6</text>
<text x="5" y="345" style="font-size: 12px; fill: #fef2ed" >#D52515</text>
<rect x="0" y="350" width="150" height="50" style="fill: #B2140C" />
<text x="5" y="379" style="font-size: 16px; fill: #fef2ed" >red7</text>
<text x="5" y="395" style="font-size: 12px; fill: #fef2ed" >#B2140C</text>
<rect x="0" y="400" width="150" height="50" style="fill: #8E0805" />
<text x="5" y="429" style="font-size: 16px; fill: #fef2ed" >red8</text>
<text x="5" y="445" style="font-size: 12px; fill: #fef2ed" >#8E0805</text>
<rect x="0" y="450" width="150" height="50" style="fill: #6A0103" />
<text x="5" y="479" style="font-size: 16px; fill: #fef2ed" >red9</text>
<text x="5" y="495" style="font-size: 12px; fill: #fef2ed" >#6A0103</text>
<rect x="150" y="0" width="150" height="50" style="fill: #FFF8EA" />
<text x="155" y="29" style="font-size: 16px; fill: #541d00" >orange0</text>
<text x="155" y="45" style="font-size: 12px; fill: #541d00" >#FFF8EA</text>
<rect x="150" y="50" width="150" height="50" style="fill: #FEEECC" />
<text x="155" y="79" style="font-size: 16px; fill: #541d00" >orange1</text>
<text x="155" y="95" style="font-size: 12px; fill: #541d00" >#FEEECC</text>
<rect x="150" y="100" width="150" height="50" style="fill: #FED998" />
<text x="155" y="129" style="font-size: 16px; fill: #541d00" >orange2</text>
<text x="155" y="145" style="font-size: 12px; fill: #541d00" >#FED998</text>
<rect x="150" y="150" width="150" height="50" style="fill: #FDC165" />
<text x="155" y="179" style="font-size: 16px; fill: #541d00" >orange3</text>
<text x="155" y="195" style="font-size: 12px; fill: #541d00" >#FDC165</text>
<rect x="150" y="200" width="150" height="50" style="fill: #FDA633" />
<text x="155" y="229" style="font-size: 16px; fill: #541d00" >orange4</text>
<text x="155" y="245" style="font-size: 12px; fill: #541d00" >#FDA633</text>
<rect x="150" y="250" width="150" height="50" style="fill: #FC8800" />
<text x="155" y="279" style="font-size: 16px; fill: #fff8ea" >orange5</text>
<text x="155" y="295" style="font-size: 12px; fill: #fff8ea" >#FC8800</text>
<rect x="150" y="300" width="150" height="50" style="fill: #D26700" />
<text x="155" y="329" style="font-size: 16px; fill: #fff8ea" >orange6</text>
<text x="155" y="345" style="font-size: 12px; fill: #fff8ea" >#D26700</text>
<rect x="150" y="350" width="150" height="50" style="fill: #A84A00" />
<text x="155" y="379" style="font-size: 16px; fill: #fff8ea" >orange7</text>
<text x="155" y="395" style="font-size: 12px; fill: #fff8ea" >#A84A00</text>
<rect x="150" y="400" width="150" height="50" style="fill: #7E3100" />
<text x="155" y="429" style="font-size: 16px; fill: #fff8ea" >orange8</text>
<text x="155" y="445" style="font-size: 12px; fill: #fff8ea" >#7E3100</text>
<rect x="150" y="450" width="150" height="50" style="fill: #541D00" />
<text x="155" y="479" style="font-size: 16px; fill: #fff8ea" >orange9</text>
<text x="155" y="495" style="font-size: 12px; fill: #fff8ea" >#541D00</text>
<rect x="300" y="0" width="150" height="50" style="fill: #FEFBEB" />
<text x="305" y="29" style="font-size: 16px; fill: #502b03" >amber0</text>
<text x="305" y="45" style="font-size: 12px; fill: #502b03" >#FEFBEB</text>
<rect x="300" y="50" width="150" height="50" style="fill: #FCF5CE" />
<text x="305" y="79" style="font-size: 16px; fill: #502b03" >amber1</text>
<text x="305" y="95" style="font-size: 12px; fill: #502b03" >#FCF5CE</text>
<rect x="300" y="100" width="150" height="50" style="fill: #F9E89E" />
<text x="305" y="129" style="font-size: 16px; fill: #502b03" >amber2</text>
<text x="305" y="145" style="font-size: 12px; fill: #502b03" >#F9E89E</text>
<rect x="300" y="150" width="150" height="50" style="fill: #F6D86F" />
<text x="305" y="179" style="font-size: 16px; fill: #502b03" >amber3</text>
<text x="305" y="195" style="font-size: 12px; fill: #502b03" >#F6D86F</text>
<rect x="300" y="200" width="150" height="50" style="fill: #F3C641" />
<text x="305" y="229" style="font-size: 16px; fill: #502b03" >amber4</text>
<text x="305" y="245" style="font-size: 12px; fill: #502b03" >#F3C641</text>
<rect x="300" y="250" width="150" height="50" style="fill: #F0B114" />
<text x="305" y="279" style="font-size: 16px; fill: #fefbeb" >amber5</text>
<text x="305" y="295" style="font-size: 12px; fill: #fefbeb" >#F0B114</text>
<rect x="300" y="300" width="150" height="50" style="fill: #C88A0F" />
<text x="305" y="329" style="font-size: 16px; fill: #fefbeb" >amber6</text>
<text x="305" y="345" style="font-size: 12px; fill: #fefbeb" >#C88A0F</text>
<rect x="300" y="350" width="150" height="50" style="fill: #A0660A" />
<text x="305" y="379" style="font-size: 16px; fill: #fefbeb" >amber7</text>
<text x="305" y="395" style="font-size: 12px; fill: #fefbeb" >#A0660A</text>
<rect x="300" y="400" width="150" height="50" style="fill: #784606" />
<text x="305" y="429" style="font-size: 16px; fill: #fefbeb" >amber8</text>
<text x="305" y="445" style="font-size: 12px; fill: #fefbeb" >#784606</text>
<rect x="300" y="450" width="150" height="50" style="fill: #502B03" />
<text x="305" y="479" style="font-size: 16px; fill: #fefbeb" >amber9</text>
<text x="305" y="495" style="font-size: 12px; fill: #fefbeb" >#502B03</text>
<rect x="450" y="0" width="150" height="50" style="fill: #FFFDEA" />
<text x="455" y="29" style="font-size: 16px; fill: #534800" >yellow0</text>
<text x="455" y="45" style="font-size: 12px; fill: #534800" >#FFFDEA</text>
<rect x="450" y="50" width="150" height="50" style="fill: #FEFBCB" />
<text x="455" y="79" style="font-size: 16px; fill: #534800" >yellow1</text>
<text x="455" y="95" style="font-size: 12px; fill: #534800" >#FEFBCB</text>
<rect x="450" y="100" width="150" height="50" style="fill: #FDF398" />
<text x="455" y="129" style="font-size: 16px; fill: #534800" >yellow2</text>
<text x="455" y="145" style="font-size: 12px; fill: #534800" >#FDF398</text>
<rect x="450" y="150" width="150" height="50" style="fill: #FCE865" />
<text x="455" y="179" style="font-size: 16px; fill: #534800" >yellow3</text>
<text x="455" y="195" style="font-size: 12px; fill: #534800" >#FCE865</text>
<rect x="450" y="200" width="150" height="50" style="fill: #FBDA32" />
<text x="455" y="229" style="font-size: 16px; fill: #534800" >yellow4</text>
<text x="455" y="245" style="font-size: 12px; fill: #534800" >#FBDA32</text>
<rect x="450" y="250" width="150" height="50" style="fill: #FAC800" />
<text x="455" y="279" style="font-size: 16px; fill: #fffdea" >yellow5</text>
<text x="455" y="295" style="font-size: 12px; fill: #fffdea" >#FAC800</text>
<rect x="450" y="300" width="150" height="50" style="fill: #D0AA00" />
<text x="455" y="329" style="font-size: 16px; fill: #fffdea" >yellow6</text>
<text x="455" y="345" style="font-size: 12px; fill: #fffdea" >#D0AA00</text>
<rect x="450" y="350" width="150" height="50" style="fill: #A78B00" />
<text x="455" y="379" style="font-size: 16px; fill: #fffdea" >yellow7</text>
<text x="455" y="395" style="font-size: 12px; fill: #fffdea" >#A78B00</text>
<rect x="450" y="400" width="150" height="50" style="fill: #7D6A00" />
<text x="455" y="429" style="font-size: 16px; fill: #fffdea" >yellow8</text>
<text x="455" y="445" style="font-size: 12px; fill: #fffdea" >#7D6A00</text>
<rect x="450" y="450" width="150" height="50" style="fill: #534800" />
<text x="455" y="479" style="font-size: 16px; fill: #fffdea" >yellow9</text>
<text x="455" y="495" style="font-size: 12px; fill: #fffdea" >#534800</text>
<rect x="600" y="0" width="150" height="50" style="fill: #F2FAE6" />
<text x="605" y="29" style="font-size: 16px; fill: #2f4600" >lime0</text>
<text x="605" y="45" style="font-size: 12px; fill: #2f4600" >#F2FAE6</text>
<rect x="600" y="50" width="150" height="50" style="fill: #E3F6C5" />
<text x="605" y="79" style="font-size: 16px; fill: #2f4600" >lime1</text>
<text x="605" y="95" style="font-size: 12px; fill: #2f4600" >#E3F6C5</text>
<rect x="600" y="100" width="150" height="50" style="fill: #CBED8E" />
<text x="605" y="129" style="font-size: 16px; fill: #2f4600" >lime2</text>
<text x="605" y="145" style="font-size: 12px; fill: #2f4600" >#CBED8E</text>
<rect x="600" y="150" width="150" height="50" style="fill: #B7E35B" />
<text x="605" y="179" style="font-size: 16px; fill: #2f4600" >lime3</text>
<text x="605" y="195" style="font-size: 12px; fill: #2f4600" >#B7E35B</text>
<rect x="600" y="200" width="150" height="50" style="fill: #A7DA2C" />
<text x="605" y="229" style="font-size: 16px; fill: #2f4600" >lime4</text>
<text x="605" y="245" style="font-size: 12px; fill: #2f4600" >#A7DA2C</text>
<rect x="600" y="250" width="150" height="50" style="fill: #9BD100" />
<text x="605" y="279" style="font-size: 16px; fill: #f2fae6" >lime5</text>
<text x="605" y="295" style="font-size: 12px; fill: #f2fae6" >#9BD100</text>
<rect x="600" y="300" width="150" height="50" style="fill: #7EAE00" />
<text x="605" y="329" style="font-size: 16px; fill: #f2fae6" >lime6</text>
<text x="605" y="345" style="font-size: 12px; fill: #f2fae6" >#7EAE00</text>
<rect x="600" y="350" width="150" height="50" style="fill: #638B00" />
<text x="605" y="379" style="font-size: 16px; fill: #f2fae6" >lime7</text>
<text x="605" y="395" style="font-size: 12px; fill: #f2fae6" >#638B00</text>
<rect x="600" y="400" width="150" height="50" style="fill: #486800" />
<text x="605" y="429" style="font-size: 16px; fill: #f2fae6" >lime8</text>
<text x="605" y="445" style="font-size: 12px; fill: #f2fae6" >#486800</text>
<rect x="600" y="450" width="150" height="50" style="fill: #2F4600" />
<text x="605" y="479" style="font-size: 16px; fill: #f2fae6" >lime9</text>
<text x="605" y="495" style="font-size: 12px; fill: #f2fae6" >#2F4600</text>
<rect x="750" y="0" width="150" height="50" style="fill: #F3F8EC" />
<text x="755" y="29" style="font-size: 16px; fill: #253d12" >lightGreen0</text>
<text x="755" y="45" style="font-size: 12px; fill: #253d12" >#F3F8EC</text>
<rect x="750" y="50" width="150" height="50" style="fill: #E3F0D0" />
<text x="755" y="79" style="font-size: 16px; fill: #253d12" >lightGreen1</text>
<text x="755" y="95" style="font-size: 12px; fill: #253d12" >#E3F0D0</text>
<rect x="750" y="100" width="150" height="50" style="fill: #C8E2A5" />
<text x="755" y="129" style="font-size: 16px; fill: #253d12" >lightGreen2</text>
<text x="755" y="145" style="font-size: 12px; fill: #253d12" >#C8E2A5</text>
<rect x="750" y="150" width="150" height="50" style="fill: #ADD37E" />
<text x="755" y="179" style="font-size: 16px; fill: #253d12" >lightGreen3</text>
<text x="755" y="195" style="font-size: 12px; fill: #253d12" >#ADD37E</text>
<rect x="750" y="200" width="150" height="50" style="fill: #93C55B" />
<text x="755" y="229" style="font-size: 16px; fill: #253d12" >lightGreen4</text>
<text x="755" y="245" style="font-size: 12px; fill: #253d12" >#93C55B</text>
<rect x="750" y="250" width="150" height="50" style="fill: #7BB63C" />
<text x="755" y="279" style="font-size: 16px; fill: #f3f8ec" >lightGreen5</text>
<text x="755" y="295" style="font-size: 12px; fill: #f3f8ec" >#7BB63C</text>
<rect x="750" y="300" width="150" height="50" style="fill: #649830" />
<text x="755" y="329" style="font-size: 16px; fill: #f3f8ec" >lightGreen6</text>
<text x="755" y="345" style="font-size: 12px; fill: #f3f8ec" >#649830</text>
<rect x="750" y="350" width="150" height="50" style="fill: #4E7926" />
<text x="755" y="379" style="font-size: 16px; fill: #f3f8ec" >lightGreen7</text>
<text x="755" y="395" style="font-size: 12px; fill: #f3f8ec" >#4E7926</text>
<rect x="750" y="400" width="150" height="50" style="fill: #395B1B" />
<text x="755" y="429" style="font-size: 16px; fill: #f3f8ec" >lightGreen8</text>
<text x="755" y="445" style="font-size: 12px; fill: #f3f8ec" >#395B1B</text>
<rect x="750" y="450" width="150" height="50" style="fill: #253D12" />
<text x="755" y="479" style="font-size: 16px; fill: #f3f8ec" >lightGreen9</text>
<text x="755" y="495" style="font-size: 12px; fill: #f3f8ec" >#253D12</text>
<rect x="900" y="0" width="150" height="50" style="fill: #ECF7EC" />
<text x="905" y="29" style="font-size: 16px; fill: #113c18" >green0</text>
<text x="905" y="45" style="font-size: 12px; fill: #113c18" >#ECF7EC</text>
<rect x="900" y="50" width="150" height="50" style="fill: #D0F0D1" />
<text x="905" y="79" style="font-size: 16px; fill: #113c18" >green1</text>
<text x="905" y="95" style="font-size: 12px; fill: #113c18" >#D0F0D1</text>
<rect x="900" y="100" width="150" height="50" style="fill: #A4E0A7" />
<text x="905" y="129" style="font-size: 16px; fill: #113c18" >green2</text>
<text x="905" y="145" style="font-size: 12px; fill: #113c18" >#A4E0A7</text>
<rect x="900" y="150" width="150" height="50" style="fill: #7DD182" />
<text x="905" y="179" style="font-size: 16px; fill: #113c18" >green3</text>
<text x="905" y="195" style="font-size: 12px; fill: #113c18" >#7DD182</text>
<rect x="900" y="200" width="150" height="50" style="fill: #5AC262" />
<text x="905" y="229" style="font-size: 16px; fill: #113c18" >green4</text>
<text x="905" y="245" style="font-size: 12px; fill: #113c18" >#5AC262</text>
<rect x="900" y="250" width="150" height="50" style="fill: #3BB346" />
<text x="905" y="279" style="font-size: 16px; fill: #ecf7ec" >green5</text>
<text x="905" y="295" style="font-size: 12px; fill: #ecf7ec" >#3BB346</text>
<rect x="900" y="300" width="150" height="50" style="fill: #30953B" />
<text x="905" y="329" style="font-size: 16px; fill: #ecf7ec" >green6</text>
<text x="905" y="345" style="font-size: 12px; fill: #ecf7ec" >#30953B</text>
<rect x="900" y="350" width="150" height="50" style="fill: #25772F" />
<text x="905" y="379" style="font-size: 16px; fill: #ecf7ec" >green7</text>
<text x="905" y="395" style="font-size: 12px; fill: #ecf7ec" >#25772F</text>
<rect x="900" y="400" width="150" height="50" style="fill: #1B5924" />
<text x="905" y="429" style="font-size: 16px; fill: #ecf7ec" >green8</text>
<text x="905" y="445" style="font-size: 12px; fill: #ecf7ec" >#1B5924</text>
<rect x="900" y="450" width="150" height="50" style="fill: #113C18" />
<text x="905" y="479" style="font-size: 16px; fill: #ecf7ec" >green9</text>
<text x="905" y="495" style="font-size: 12px; fill: #ecf7ec" >#113C18</text>
<rect x="1050" y="0" width="150" height="50" style="fill: #E4F7F4" />
<text x="1055" y="29" style="font-size: 16px; fill: #003c3a" >teal0</text>
<text x="1055" y="45" style="font-size: 12px; fill: #003c3a" >#E4F7F4</text>
<rect x="1050" y="50" width="150" height="50" style="fill: #C0F0E8" />
<text x="1055" y="79" style="font-size: 16px; fill: #003c3a" >teal1</text>
<text x="1055" y="95" style="font-size: 12px; fill: #003c3a" >#C0F0E8</text>
<rect x="1050" y="100" width="150" height="50" style="fill: #87E0D3" />
<text x="1055" y="129" style="font-size: 16px; fill: #003c3a" >teal2</text>
<text x="1055" y="145" style="font-size: 12px; fill: #003c3a" >#87E0D3</text>
<rect x="1050" y="150" width="150" height="50" style="fill: #54D1C1" />
<text x="1055" y="179" style="font-size: 16px; fill: #003c3a" >teal3</text>
<text x="1055" y="195" style="font-size: 12px; fill: #003c3a" >#54D1C1</text>
<rect x="1050" y="200" width="150" height="50" style="fill: #27C2B0" />
<text x="1055" y="229" style="font-size: 16px; fill: #003c3a" >teal4</text>
<text x="1055" y="245" style="font-size: 12px; fill: #003c3a" >#27C2B0</text>
<rect x="1050" y="250" width="150" height="50" style="fill: #00B3A1" />
<text x="1055" y="279" style="font-size: 16px; fill: #e4f7f4" >teal5</text>
<text x="1055" y="295" style="font-size: 12px; fill: #e4f7f4" >#00B3A1</text>
<rect x="1050" y="300" width="150" height="50" style="fill: #009589" />
<text x="1055" y="329" style="font-size: 16px; fill: #e4f7f4" >teal6</text>
<text x="1055" y="345" style="font-size: 12px; fill: #e4f7f4" >#009589</text>
<rect x="1050" y="350" width="150" height="50" style="fill: #00776F" />
<text x="1055" y="379" style="font-size: 16px; fill: #e4f7f4" >teal7</text>
<text x="1055" y="395" style="font-size: 12px; fill: #e4f7f4" >#00776F</text>
<rect x="1050" y="400" width="150" height="50" style="fill: #005955" />
<text x="1055" y="429" style="font-size: 16px; fill: #e4f7f4" >teal8</text>
<text x="1055" y="445" style="font-size: 12px; fill: #e4f7f4" >#005955</text>
<rect x="1050" y="450" width="150" height="50" style="fill: #003C3A" />
<text x="1055" y="479" style="font-size: 16px; fill: #e4f7f4" >teal9</text>
<text x="1055" y="495" style="font-size: 12px; fill: #e4f7f4" >#003C3A</text>
<rect x="0" y="500" width="150" height="50" style="fill: #E5F7F8" />
<text x="5" y="529" style="font-size: 16px; fill: #00323d" >cyan0</text>
<text x="5" y="545" style="font-size: 12px; fill: #00323d" >#E5F7F8</text>
<rect x="0" y="550" width="150" height="50" style="fill: #C2EFF0" />
<text x="5" y="579" style="font-size: 16px; fill: #00323d" >cyan1</text>
<text x="5" y="595" style="font-size: 12px; fill: #00323d" >#C2EFF0</text>
<rect x="0" y="600" width="150" height="50" style="fill: #8ADDE2" />
<text x="5" y="629" style="font-size: 16px; fill: #00323d" >cyan2</text>
<text x="5" y="645" style="font-size: 12px; fill: #00323d" >#8ADDE2</text>
<rect x="0" y="650" width="150" height="50" style="fill: #58CBD3" />
<text x="5" y="679" style="font-size: 16px; fill: #00323d" >cyan3</text>
<text x="5" y="695" style="font-size: 12px; fill: #00323d" >#58CBD3</text>
<rect x="0" y="700" width="150" height="50" style="fill: #2CB8C5" />
<text x="5" y="729" style="font-size: 16px; fill: #00323d" >cyan4</text>
<text x="5" y="745" style="font-size: 12px; fill: #00323d" >#2CB8C5</text>
<rect x="0" y="750" width="150" height="50" style="fill: #05A4B6" />
<text x="5" y="779" style="font-size: 16px; fill: #e5f7f8" >cyan5</text>
<text x="5" y="795" style="font-size: 12px; fill: #e5f7f8" >#05A4B6</text>
<rect x="0" y="800" width="150" height="50" style="fill: #038698" />
<text x="5" y="829" style="font-size: 16px; fill: #e5f7f8" >cyan6</text>
<text x="5" y="845" style="font-size: 12px; fill: #e5f7f8" >#038698</text>
<rect x="0" y="850" width="150" height="50" style="fill: #016979" />
<text x="5" y="879" style="font-size: 16px; fill: #e5f7f8" >cyan7</text>
<text x="5" y="895" style="font-size: 12px; fill: #e5f7f8" >#016979</text>
<rect x="0" y="900" width="150" height="50" style="fill: #004D5B" />
<text x="5" y="929" style="font-size: 16px; fill: #e5f7f8" >cyan8</text>
<text x="5" y="945" style="font-size: 12px; fill: #e5f7f8" >#004D5B</text>
<rect x="0" y="950" width="150" height="50" style="fill: #00323D" />
<text x="5" y="979" style="font-size: 16px; fill: #e5f7f8" >cyan9</text>
<text x="5" y="995" style="font-size: 12px; fill: #e5f7f8" >#00323D</text>
<rect x="150" y="500" width="150" height="50" style="fill: #E9F7FD" />
<text x="155" y="529" style="font-size: 16px; fill: #00355f" >lightBlue0</text>
<text x="155" y="545" style="font-size: 12px; fill: #00355f" >#E9F7FD</text>
<rect x="150" y="550" width="150" height="50" style="fill: #C9ECFC" />
<text x="155" y="579" style="font-size: 16px; fill: #00355f" >lightBlue1</text>
<text x="155" y="595" style="font-size: 12px; fill: #00355f" >#C9ECFC</text>
<rect x="150" y="600" width="150" height="50" style="fill: #95D8F8" />
<text x="155" y="629" style="font-size: 16px; fill: #00355f" >lightBlue2</text>
<text x="155" y="645" style="font-size: 12px; fill: #00355f" >#95D8F8</text>
<rect x="150" y="650" width="150" height="50" style="fill: #62C3F5" />
<text x="155" y="679" style="font-size: 16px; fill: #00355f" >lightBlue3</text>
<text x="155" y="695" style="font-size: 12px; fill: #00355f" >#62C3F5</text>
<rect x="150" y="700" width="150" height="50" style="fill: #30ACF1" />
<text x="155" y="729" style="font-size: 16px; fill: #00355f" >lightBlue4</text>
<text x="155" y="745" style="font-size: 12px; fill: #00355f" >#30ACF1</text>
<rect x="150" y="750" width="150" height="50" style="fill: #0095EE" />
<text x="155" y="779" style="font-size: 16px; fill: #e9f7fd" >lightBlue5</text>
<text x="155" y="795" style="font-size: 12px; fill: #e9f7fd" >#0095EE</text>
<rect x="150" y="800" width="150" height="50" style="fill: #007BCA" />
<text x="155" y="829" style="font-size: 16px; fill: #e9f7fd" >lightBlue6</text>
<text x="155" y="845" style="font-size: 12px; fill: #e9f7fd" >#007BCA</text>
<rect x="150" y="850" width="150" height="50" style="fill: #0063A7" />
<text x="155" y="879" style="font-size: 16px; fill: #e9f7fd" >lightBlue7</text>
<text x="155" y="895" style="font-size: 12px; fill: #e9f7fd" >#0063A7</text>
<rect x="150" y="900" width="150" height="50" style="fill: #004B83" />
<text x="155" y="929" style="font-size: 16px; fill: #e9f7fd" >lightBlue8</text>
<text x="155" y="945" style="font-size: 12px; fill: #e9f7fd" >#004B83</text>
<rect x="150" y="950" width="150" height="50" style="fill: #00355F" />
<text x="155" y="979" style="font-size: 16px; fill: #e9f7fd" >lightBlue9</text>
<text x="155" y="995" style="font-size: 12px; fill: #e9f7fd" >#00355F</text>
<rect x="300" y="500" width="150" height="50" style="fill: #EAF5FF" />
<text x="305" y="529" style="font-size: 16px; fill: #002c6b" >blue0</text>
<text x="305" y="545" style="font-size: 12px; fill: #002c6b" >#EAF5FF</text>
<rect x="300" y="550" width="150" height="50" style="fill: #CBE7FE" />
<text x="305" y="579" style="font-size: 16px; fill: #002c6b" >blue1</text>
<text x="305" y="595" style="font-size: 12px; fill: #002c6b" >#CBE7FE</text>
<rect x="300" y="600" width="150" height="50" style="fill: #98CDFD" />
<text x="305" y="629" style="font-size: 16px; fill: #002c6b" >blue2</text>
<text x="305" y="645" style="font-size: 12px; fill: #002c6b" >#98CDFD</text>
<rect x="300" y="650" width="150" height="50" style="fill: #65B2FC" />
<text x="305" y="679" style="font-size: 16px; fill: #002c6b" >blue3</text>
<text x="305" y="695" style="font-size: 12px; fill: #002c6b" >#65B2FC</text>
<rect x="300" y="700" width="150" height="50" style="fill: #3295FB" />
<text x="305" y="729" style="font-size: 16px; fill: #002c6b" >blue4</text>
<text x="305" y="745" style="font-size: 12px; fill: #002c6b" >#3295FB</text>
<rect x="300" y="750" width="150" height="50" style="fill: #0064FA" />
<text x="305" y="779" style="font-size: 16px; fill: #eaf5ff" >blue5</text>
<text x="305" y="795" style="font-size: 12px; fill: #eaf5ff" >#0064FA</text>
<rect x="300" y="800" width="150" height="50" style="fill: #0062D6" />
<text x="305" y="829" style="font-size: 16px; fill: #eaf5ff" >blue6</text>
<text x="305" y="845" style="font-size: 12px; fill: #eaf5ff" >#0062D6</text>
<rect x="300" y="850" width="150" height="50" style="fill: #004FB3" />
<text x="305" y="879" style="font-size: 16px; fill: #eaf5ff" >blue7</text>
<text x="305" y="895" style="font-size: 12px; fill: #eaf5ff" >#004FB3</text>
<rect x="300" y="900" width="150" height="50" style="fill: #003D8F" />
<text x="305" y="929" style="font-size: 16px; fill: #eaf5ff" >blue8</text>
<text x="305" y="945" style="font-size: 12px; fill: #eaf5ff" >#003D8F</text>
<rect x="300" y="950" width="150" height="50" style="fill: #002C6B" />
<text x="305" y="979" style="font-size: 16px; fill: #eaf5ff" >blue9</text>
<text x="305" y="995" style="font-size: 12px; fill: #eaf5ff" >#002C6B</text>
<rect x="450" y="500" width="150" height="50" style="fill: #ECEFF8" />
<text x="455" y="529" style="font-size: 16px; fill: #171d63" >indigo0</text>
<text x="455" y="545" style="font-size: 12px; fill: #171d63" >#ECEFF8</text>
<rect x="450" y="550" width="150" height="50" style="fill: #D1D8F0" />
<text x="455" y="579" style="font-size: 16px; fill: #171d63" >indigo1</text>
<text x="455" y="595" style="font-size: 12px; fill: #171d63" >#D1D8F0</text>
<rect x="450" y="600" width="150" height="50" style="fill: #A7B3E1" />
<text x="455" y="629" style="font-size: 16px; fill: #171d63" >indigo2</text>
<text x="455" y="645" style="font-size: 12px; fill: #171d63" >#A7B3E1</text>
<rect x="450" y="650" width="150" height="50" style="fill: #8090D3" />
<text x="455" y="679" style="font-size: 16px; fill: #171d63" >indigo3</text>
<text x="455" y="695" style="font-size: 12px; fill: #171d63" >#8090D3</text>
<rect x="450" y="700" width="150" height="50" style="fill: #5E6FC4" />
<text x="455" y="729" style="font-size: 16px; fill: #171d63" >indigo4</text>
<text x="455" y="745" style="font-size: 12px; fill: #171d63" >#5E6FC4</text>
<rect x="450" y="750" width="150" height="50" style="fill: #3F51B5" />
<text x="455" y="779" style="font-size: 16px; fill: #eceff8" >indigo5</text>
<text x="455" y="795" style="font-size: 12px; fill: #eceff8" >#3F51B5</text>
<rect x="450" y="800" width="150" height="50" style="fill: #3342A1" />
<text x="455" y="829" style="font-size: 16px; fill: #eceff8" >indigo6</text>
<text x="455" y="845" style="font-size: 12px; fill: #eceff8" >#3342A1</text>
<rect x="450" y="850" width="150" height="50" style="fill: #28348C" />
<text x="455" y="879" style="font-size: 16px; fill: #eceff8" >indigo7</text>
<text x="455" y="895" style="font-size: 12px; fill: #eceff8" >#28348C</text>
<rect x="450" y="900" width="150" height="50" style="fill: #1F2878" />
<text x="455" y="929" style="font-size: 16px; fill: #eceff8" >indigo8</text>
<text x="455" y="945" style="font-size: 12px; fill: #eceff8" >#1F2878</text>
<rect x="450" y="950" width="150" height="50" style="fill: #171D63" />
<text x="455" y="979" style="font-size: 16px; fill: #eceff8" >indigo9</text>
<text x="455" y="995" style="font-size: 12px; fill: #eceff8" >#171D63</text>
<rect x="600" y="500" width="150" height="50" style="fill: #F3EDF9" />
<text x="605" y="529" style="font-size: 16px; fill: #281475" >violet0</text>
<text x="605" y="545" style="font-size: 12px; fill: #281475" >#F3EDF9</text>
<rect x="600" y="550" width="150" height="50" style="fill: #E2D1F4" />
<text x="605" y="579" style="font-size: 16px; fill: #281475" >violet1</text>
<text x="605" y="595" style="font-size: 12px; fill: #281475" >#E2D1F4</text>
<rect x="600" y="600" width="150" height="50" style="fill: #C4A7E9" />
<text x="605" y="629" style="font-size: 16px; fill: #281475" >violet2</text>
<text x="605" y="645" style="font-size: 12px; fill: #281475" >#C4A7E9</text>
<rect x="600" y="650" width="150" height="50" style="fill: #A67FDD" />
<text x="605" y="679" style="font-size: 16px; fill: #281475" >violet3</text>
<text x="605" y="695" style="font-size: 12px; fill: #281475" >#A67FDD</text>
<rect x="600" y="700" width="150" height="50" style="fill: #885BD2" />
<text x="605" y="729" style="font-size: 16px; fill: #281475" >violet4</text>
<text x="605" y="745" style="font-size: 12px; fill: #281475" >#885BD2</text>
<rect x="600" y="750" width="150" height="50" style="fill: #6A3AC7" />
<text x="605" y="779" style="font-size: 16px; fill: #f3edf9" >violet5</text>
<text x="605" y="795" style="font-size: 12px; fill: #f3edf9" >#6A3AC7</text>
<rect x="600" y="800" width="150" height="50" style="fill: #572FB3" />
<text x="605" y="829" style="font-size: 16px; fill: #f3edf9" >violet6</text>
<text x="605" y="845" style="font-size: 12px; fill: #f3edf9" >#572FB3</text>
<rect x="600" y="850" width="150" height="50" style="fill: #46259E" />
<text x="605" y="879" style="font-size: 16px; fill: #f3edf9" >violet7</text>
<text x="605" y="895" style="font-size: 12px; fill: #f3edf9" >#46259E</text>
<rect x="600" y="900" width="150" height="50" style="fill: #361C8A" />
<text x="605" y="929" style="font-size: 16px; fill: #f3edf9" >violet8</text>
<text x="605" y="945" style="font-size: 12px; fill: #f3edf9" >#361C8A</text>
<rect x="600" y="950" width="150" height="50" style="fill: #281475" />
<text x="605" y="979" style="font-size: 16px; fill: #f3edf9" >violet9</text>
<text x="605" y="995" style="font-size: 12px; fill: #f3edf9" >#281475</text>
<rect x="750" y="500" width="150" height="50" style="fill: #F7E9F7" />
<text x="755" y="529" style="font-size: 16px; fill: #490a61" >purple0</text>
<text x="755" y="545" style="font-size: 12px; fill: #490a61" >#F7E9F7</text>
<rect x="750" y="550" width="150" height="50" style="fill: #EFCAF0" />
<text x="755" y="579" style="font-size: 16px; fill: #490a61" >purple1</text>
<text x="755" y="595" style="font-size: 12px; fill: #490a61" >#EFCAF0</text>
<rect x="750" y="600" width="150" height="50" style="fill: #DD9BE0" />
<text x="755" y="629" style="font-size: 16px; fill: #490a61" >purple2</text>
<text x="755" y="645" style="font-size: 12px; fill: #490a61" >#DD9BE0</text>
<rect x="750" y="650" width="150" height="50" style="fill: #C96FD1" />
<text x="755" y="679" style="font-size: 16px; fill: #490a61" >purple3</text>
<text x="755" y="695" style="font-size: 12px; fill: #490a61" >#C96FD1</text>
<rect x="750" y="700" width="150" height="50" style="fill: #B449C2" />
<text x="755" y="729" style="font-size: 16px; fill: #490a61" >purple4</text>
<text x="755" y="745" style="font-size: 12px; fill: #490a61" >#B449C2</text>
<rect x="750" y="750" width="150" height="50" style="fill: #9E28B3" />
<text x="755" y="779" style="font-size: 16px; fill: #f7e9f7" >purple5</text>
<text x="755" y="795" style="font-size: 12px; fill: #f7e9f7" >#9E28B3</text>
<rect x="750" y="800" width="150" height="50" style="fill: #871E9E" />
<text x="755" y="829" style="font-size: 16px; fill: #f7e9f7" >purple6</text>
<text x="755" y="845" style="font-size: 12px; fill: #f7e9f7" >#871E9E</text>
<rect x="750" y="850" width="150" height="50" style="fill: #71168A" />
<text x="755" y="879" style="font-size: 16px; fill: #f7e9f7" >purple7</text>
<text x="755" y="895" style="font-size: 12px; fill: #f7e9f7" >#71168A</text>
<rect x="750" y="900" width="150" height="50" style="fill: #5C0F75" />
<text x="755" y="929" style="font-size: 16px; fill: #f7e9f7" >purple8</text>
<text x="755" y="945" style="font-size: 12px; fill: #f7e9f7" >#5C0F75</text>
<rect x="750" y="950" width="150" height="50" style="fill: #490A61" />
<text x="755" y="979" style="font-size: 16px; fill: #f7e9f7" >purple9</text>
<text x="755" y="995" style="font-size: 12px; fill: #f7e9f7" >#490A61</text>
<rect x="900" y="500" width="150" height="50" style="fill: #FDECEF" />
<text x="905" y="529" style="font-size: 16px; fill: #5a012b" >pink0</text>
<text x="905" y="545" style="font-size: 12px; fill: #5a012b" >#FDECEF</text>
<rect x="900" y="550" width="150" height="50" style="fill: #FBCFD8" />
<text x="905" y="579" style="font-size: 16px; fill: #5a012b" >pink1</text>
<text x="905" y="595" style="font-size: 12px; fill: #5a012b" >#FBCFD8</text>
<rect x="900" y="600" width="150" height="50" style="fill: #F6A0B5" />
<text x="905" y="629" style="font-size: 16px; fill: #5a012b" >pink2</text>
<text x="905" y="645" style="font-size: 12px; fill: #5a012b" >#F6A0B5</text>
<rect x="900" y="650" width="150" height="50" style="fill: #F27396" />
<text x="905" y="679" style="font-size: 16px; fill: #5a012b" >pink3</text>
<text x="905" y="695" style="font-size: 12px; fill: #5a012b" >#F27396</text>
<rect x="900" y="700" width="150" height="50" style="fill: #ED487B" />
<text x="905" y="729" style="font-size: 16px; fill: #5a012b" >pink4</text>
<text x="905" y="745" style="font-size: 12px; fill: #5a012b" >#ED487B</text>
<rect x="900" y="750" width="150" height="50" style="fill: #E91E63" />
<text x="905" y="779" style="font-size: 16px; fill: #fdecef" >pink5</text>
<text x="905" y="795" style="font-size: 12px; fill: #fdecef" >#E91E63</text>
<rect x="900" y="800" width="150" height="50" style="fill: #C51356" />
<text x="905" y="829" style="font-size: 16px; fill: #fdecef" >pink6</text>
<text x="905" y="845" style="font-size: 12px; fill: #fdecef" >#C51356</text>
<rect x="900" y="850" width="150" height="50" style="fill: #A20B48" />
<text x="905" y="879" style="font-size: 16px; fill: #fdecef" >pink7</text>
<text x="905" y="895" style="font-size: 12px; fill: #fdecef" >#A20B48</text>
<rect x="900" y="900" width="150" height="50" style="fill: #7E053A" />
<text x="905" y="929" style="font-size: 16px; fill: #fdecef" >pink8</text>
<text x="905" y="945" style="font-size: 12px; fill: #fdecef" >#7E053A</text>
<rect x="900" y="950" width="150" height="50" style="fill: #5A012B" />
<text x="905" y="979" style="font-size: 16px; fill: #fdecef" >pink9</text>
<text x="905" y="995" style="font-size: 12px; fill: #fdecef" >#5A012B</text>
<rect x="1050" y="500" width="150" height="50" style="fill: #F9F9F9" />
<text x="1055" y="529" style="font-size: 16px; fill: #1c1f23" >grey0</text>
<text x="1055" y="545" style="font-size: 12px; fill: #1c1f23" >#F9F9F9</text>
<rect x="1050" y="550" width="150" height="50" style="fill: #E6E8EA" />
<text x="1055" y="579" style="font-size: 16px; fill: #1c1f23" >grey1</text>
<text x="1055" y="595" style="font-size: 12px; fill: #1c1f23" >#E6E8EA</text>
<rect x="1050" y="600" width="150" height="50" style="fill: #C6CACD" />
<text x="1055" y="629" style="font-size: 16px; fill: #1c1f23" >grey2</text>
<text x="1055" y="645" style="font-size: 12px; fill: #1c1f23" >#C6CACD</text>
<rect x="1050" y="650" width="150" height="50" style="fill: #A7ABB0" />
<text x="1055" y="679" style="font-size: 16px; fill: #1c1f23" >grey3</text>
<text x="1055" y="695" style="font-size: 12px; fill: #1c1f23" >#A7ABB0</text>
<rect x="1050" y="700" width="150" height="50" style="fill: #888D92" />
<text x="1055" y="729" style="font-size: 16px; fill: #1c1f23" >grey4</text>
<text x="1055" y="745" style="font-size: 12px; fill: #1c1f23" >#888D92</text>
<rect x="1050" y="750" width="150" height="50" style="fill: #6B7075" />
<text x="1055" y="779" style="font-size: 16px; fill: #f9f9f9" >grey5</text>
<text x="1055" y="795" style="font-size: 12px; fill: #f9f9f9" >#6B7075</text>
<rect x="1050" y="800" width="150" height="50" style="fill: #555B61" />
<text x="1055" y="829" style="font-size: 16px; fill: #f9f9f9" >grey6</text>
<text x="1055" y="845" style="font-size: 12px; fill: #f9f9f9" >#555B61</text>
<rect x="1050" y="850" width="150" height="50" style="fill: #41464C" />
<text x="1055" y="879" style="font-size: 16px; fill: #f9f9f9" >grey7</text>
<text x="1055" y="895" style="font-size: 12px; fill: #f9f9f9" >#41464C</text>
<rect x="1050" y="900" width="150" height="50" style="fill: #2E3238" />
<text x="1055" y="929" style="font-size: 16px; fill: #f9f9f9" >grey8</text>
<text x="1055" y="945" style="font-size: 12px; fill: #f9f9f9" >#2E3238</text>
<rect x="1050" y="950" width="150" height="50" style="fill: #1C1F23" />
<text x="1055" y="979" style="font-size: 16px; fill: #f9f9f9" >grey9</text>
<text x="1055" y="995" style="font-size: 12px; fill: #f9f9f9" >#1C1F23</text>
<rect x="0" y="1000" width="600" height="50" style="fill: #FFFFFF" />
<text x="5" y="1029" style="font-size: 16px; fill: #808080" >white</text>
<text x="5" y="1045" style="font-size: 12px; fill: #808080" >#FFFFFF</text>
<rect x="600" y="1000" width="600" height="50" style="fill: #000000" />
<text x="605" y="1029" style="font-size: 16px; fill: #808080" >black</text>
<text x="605" y="1045" style="font-size: 12px; fill: #808080" >#000000</text>
</svg>

After

Width:  |  Height:  |  Size: 36 KiB

BIN
doc/images/app_bundle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
doc/images/app_c.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

View File

@ -1,15 +0,0 @@
M3_SRC_DIR := ../../../source
SOURCES := ../../app/main.c \
$(shell find $(M3_SRC_DIR) -type f -name '*.c')
override CFLAGS += -std=c99 -O3 -flto -Dd_m3HasWASI -Wno-error=format-security -Wfatal-errors -I$(M3_SRC_DIR)
all: wasm3
wasm3: $(SOURCES)
$(CC) $(CFLAGS) $(SOURCES) -o wasm3 -lm
clean:
$(RM) wasm3

@ -1 +0,0 @@
Subproject commit 6221370aa0e8c520ebde179a1e715a8ed2e28611

59
orca Executable file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env python3
# This file is copied into the user's home directory on install,
# but also can be run from the root of an Orca source checkout.
import os
import sys
MAJOR, MINOR = 3, 8
if __name__ != "__main__":
print("why are you importing the orca command-line tool as a Python module, you absolute goofball")
exit(1)
if sys.version_info.major < MAJOR or sys.version_info.minor < MINOR:
print("Your Python version is too old.")
print("Orca requires version {}.{}, but you have version {}.{}.".format(MAJOR, MINOR, sys.version_info.major, sys.version_info.minor))
exit(1)
# If you modify this, be sure to modify the version in scripts/dev.py as well.
def check_if_source():
def path_is_in_orca_source(path):
dir = path
while True:
try:
os.stat(os.path.join(dir, ".orcaroot"))
return (True, dir)
except FileNotFoundError:
pass
newdir = os.path.dirname(dir)
if newdir == dir:
return (False, None)
dir = newdir
in_source, current_source_dir = path_is_in_orca_source(os.getcwd())
script_is_source, script_source_dir = path_is_in_orca_source(os.path.dirname(os.path.abspath(__file__)))
use_source = in_source or script_is_source
source_dir = current_source_dir or script_source_dir
return (use_source, source_dir, script_is_source)
use_source, source_dir, is_source = check_if_source()
if use_source:
# Use the source checkout's scripts instead of the system-installed scripts.
if not is_source:
print("The Orca tool is running from a local source checkout and will", file=sys.stderr)
print("use that instead of the system Orca installation.", file=sys.stderr)
print(file=sys.stderr)
sys.path.append(source_dir)
import scripts.orca
else:
# Running from outside Orca source checkout; use system Orca install.
import sys_scripts.orca

7
orca.bat Normal file
View File

@ -0,0 +1,7 @@
@echo off
rem Get the directory of this batch script
set "script_dir=%~dp0"
python "%script_dir%orca" %*
exit /b %errorlevel%

Binary file not shown.

Binary file not shown.

3
samples/breakout/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Breakout
profile.dtrace
profile.spall

View File

@ -0,0 +1,39 @@
@echo off
setlocal enabledelayedexpansion
:: The following code checks if you have the necessary programs to compile the samples.
:: This code exists to improve the experience of first-time Orca users and can
:: be safely deleted in your own projects if you wish.
if exist "..\..\scripts\sample_build_check.py" (
python ..\..\scripts\sample_build_check.py
if !ERRORLEVEL! neq 0 exit /b 1
) else (
echo Could not check if you have the necessary tools to build the Orca samples.
echo If you have copied this script to your own project, you can delete this code.
)
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: common flags to build wasm modules
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
:: build orca core as wasm module
clang %wasmFlags% -Wl,--relocatable -o .\liborca.a %ORCA_DIR%\src\orca.c %ORCA_DIR%\src\libc-shim\src\*.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: build sample as wasm module and link it with the orca module
clang %wasmFlags% -L . -lorca -o module.wasm src/main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: create app directory and copy files into it
orca bundle --orca-dir %ORCA_DIR% --name Breakout --icon icon.png --resource-dir data module.wasm

37
samples/breakout/build.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
# The following code checks if you have the necessary programs to compile the samples.
# This code exists to improve the experience of first-time Orca users and can
# be safely deleted in your own projects if you wish.
if [ -f ../../scripts/sample_build_check.py ]; then
python3 ../../scripts/sample_build_check.py
else
echo "Could not check if you have the necessary tools to build the Orca samples."
echo "If you have copied this script to your own project, you can delete this code."
fi
ORCA_DIR=../..
STDLIB_DIR=$ORCA_DIR/src/libc-shim
# common flags to build wasm modules
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
# build orca core as wasm module
clang $wasmFlags -Wl,--relocatable -o ./liborca.a $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c
# build sample as wasm module and link it with the orca module
clang $wasmFlags -L . -lorca -o module.wasm src/main.c
# create app directory and copy files into it
orca bundle --orca-dir $ORCA_DIR --name Breakout --icon icon.png --resource-dir data module.wasm

Binary file not shown.

After

Width:  |  Height:  |  Size: 490 KiB

View File

Before

Width:  |  Height:  |  Size: 314 KiB

After

Width:  |  Height:  |  Size: 314 KiB

View File

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

479
samples/breakout/src/main.c Normal file
View File

@ -0,0 +1,479 @@
/*************************************************************************
*
* Orca
* Copyright 2023 Martin Fouilleul and the Orca project contributors
* See LICENSE.txt for licensing information
*
**************************************************************************/
#include <math.h>
#include <orca.h>
#define NUM_BLOCKS_PER_ROW 7
#define NUM_BLOCKS 42 // 7 * 6
#define NUM_BLOCKS_TO_WIN (NUM_BLOCKS - 2)
#define BLOCKS_WIDTH 810.0f
#define BLOCK_HEIGHT 30.0f
#define BLOCKS_PADDING 15.0f
#define BLOCKS_BOTTOM 300.0f
#define PADDLE_MAX_LAUNCH_ANGLE 0.7f
const f32 BLOCK_WIDTH = (BLOCKS_WIDTH - ((NUM_BLOCKS_PER_ROW + 1) * BLOCKS_PADDING)) / NUM_BLOCKS_PER_ROW;
oc_vec2 velocity = { 5, 5 };
// This is upside down from how it will actually be drawn.
int blockHealth[NUM_BLOCKS] = {
0, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3
};
int score = 0;
bool leftDown = false;
bool rightDown = false;
oc_vec2 frameSize = { 100, 100 };
oc_surface surface;
oc_canvas canvas;
oc_image waterImage;
oc_image brickImage;
oc_image ballImage;
oc_font font;
const oc_color paddleColor = { 1, 0, 0, 1 };
oc_rect paddle = { 300, 50, 200, 24 };
oc_rect ball = { 200, 200, 20, 20 };
f32 lerp(f32 a, f32 b, f32 t)
{
return (1 - t) * a + t * b;
}
oc_mat2x3 flip_y(oc_rect r)
{
return (oc_mat2x3){
1, 0, 0,
0, -1, 2 * r.y + r.h
};
}
oc_mat2x3 flip_y_at(oc_vec2 pos)
{
return (oc_mat2x3){
1, 0, 0,
0, -1, 2 * pos.y
};
}
ORCA_EXPORT void oc_on_init(void)
{
oc_window_set_title(OC_STR8("Breakout"));
surface = oc_surface_canvas();
canvas = oc_canvas_create();
waterImage = oc_image_create_from_path(surface, OC_STR8("/underwater.jpg"), false);
brickImage = oc_image_create_from_path(surface, OC_STR8("/brick.png"), false);
ballImage = oc_image_create_from_path(surface, OC_STR8("/ball.png"), false);
if(oc_image_is_nil(waterImage))
{
oc_log_error("couldn't load water image\n");
}
if(oc_image_is_nil(brickImage))
{
oc_log_error("couldn't load brick image\n");
}
if(oc_image_is_nil(ballImage))
{
oc_log_error("couldn't load ball image\n");
}
oc_unicode_range ranges[5] = {
OC_UNICODE_BASIC_LATIN,
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
OC_UNICODE_LATIN_EXTENDED_A,
OC_UNICODE_LATIN_EXTENDED_B,
OC_UNICODE_SPECIALS
};
font = oc_font_create_from_path(OC_STR8("/Literata-SemiBoldItalic.ttf"), 5, ranges);
}
ORCA_EXPORT void oc_on_terminate(void)
{
if(score == NUM_BLOCKS_TO_WIN)
{
oc_log_info("you win!\n");
}
else
{
oc_log_info("goodbye world!\n");
}
}
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{
oc_log_info("frame resize %u, %u", width, height);
frameSize.x = width;
frameSize.y = height;
}
ORCA_EXPORT void oc_on_key_down(oc_scan_code scan, oc_key_code key)
{
oc_log_info("key down: %i", key);
if(key == OC_KEY_LEFT)
{
leftDown = true;
}
if(key == OC_KEY_RIGHT)
{
rightDown = true;
}
}
ORCA_EXPORT void oc_on_key_up(oc_scan_code scan, oc_key_code key)
{
oc_log_info("key up: %i", key);
if(key == OC_KEY_LEFT)
{
leftDown = false;
}
if(key == OC_KEY_RIGHT)
{
rightDown = false;
}
}
oc_rect block_rect(int i)
{
int row = i / NUM_BLOCKS_PER_ROW;
int col = i % NUM_BLOCKS_PER_ROW;
return (oc_rect){
BLOCKS_PADDING + (BLOCKS_PADDING + BLOCK_WIDTH) * col,
BLOCKS_BOTTOM + (BLOCKS_PADDING + BLOCK_HEIGHT) * row,
BLOCK_WIDTH,
BLOCK_HEIGHT
};
}
// Returns a cardinal direction 1-8 for the collision with the block, or zero
// if no collision. 1 is straight up and directions proceed clockwise.
int check_collision(oc_rect block)
{
// Note that all the logic for this game has the origin in the bottom left.
f32 ballx2 = ball.x + ball.w;
f32 bally2 = ball.y + ball.h;
f32 blockx2 = block.x + block.w;
f32 blocky2 = block.y + block.h;
if(ballx2 < block.x || blockx2 < ball.x || bally2 < block.y || blocky2 < ball.y)
{
// Ball is fully outside block
return 0;
}
// If moving right, the ball can bounce off its top right corner, right
// side, or bottom right corner. Corner bounces occur if the block's bottom
// left corner is in the ball's top right quadrant, or if the block's top
// left corner is in the ball's bottom left quadrant. Otherwise, an edge
// bounce occurs if the block's left edge falls in either of the ball's
// right quadrants.
//
// This logic generalizes to other directions.
//
// We assume significant tunneling can't happen.
oc_vec2 ballCenter = (oc_vec2){ ball.x + ball.w / 2, ball.y + ball.h / 2 };
oc_vec2 blockCenter = (oc_vec2){ block.x + block.w / 2, block.y + block.h / 2 };
// Moving right
if(velocity.x > 0)
{
// Ball's top right corner
if(ballCenter.x <= block.x && block.x <= ballx2 && ballCenter.y <= block.y && block.y <= bally2)
{
return 2;
}
// Ball's bottom right corner
if(ballCenter.x <= block.x && block.x <= ballx2 && ball.y <= blocky2 && blocky2 <= ballCenter.y)
{
return 4;
}
// Ball's right edge
if(ballCenter.x <= block.x && block.x <= ballx2)
{
return 3;
}
}
// Moving up
if(velocity.y > 0)
{
// Ball's top left corner
if(ball.x <= blockx2 && blockx2 <= ballCenter.x && ballCenter.y <= block.y && block.y <= bally2)
{
return 8;
}
// Ball's top right corner
if(ballCenter.x <= block.x && block.x <= ballx2 && ballCenter.y <= block.y && block.y <= bally2)
{
return 2;
}
// Ball's top edge
if(ballCenter.y <= block.y && block.y <= bally2)
{
return 1;
}
}
// Moving left
if(velocity.x < 0)
{
// Ball's bottom left corner
if(ball.x <= blockx2 && blockx2 <= ballCenter.x && ball.y <= blocky2 && blocky2 <= ballCenter.y)
{
return 6;
}
// Ball's top left corner
if(ball.x <= blockx2 && blockx2 <= ballCenter.x && ballCenter.y <= block.y && block.y <= bally2)
{
return 8;
}
// Ball's left edge
if(ball.x <= blockx2 && blockx2 <= ballCenter.x)
{
return 7;
}
}
// Moving down
if(velocity.y < 0)
{
// Ball's bottom right corner
if(ballCenter.x <= block.x && block.x <= ballx2 && ball.y <= blocky2 && blocky2 <= ballCenter.y)
{
return 4;
}
// Ball's bottom left corner
if(ball.x <= blockx2 && blockx2 <= ballCenter.x && ball.y <= blocky2 && blocky2 <= ballCenter.y)
{
return 6;
}
// Ball's bottom edge
if(ball.y <= blocky2 && blocky2 <= ballCenter.y)
{
return 5;
}
}
return 0;
}
ORCA_EXPORT void oc_on_frame_refresh(void)
{
oc_arena_scope scratch = oc_scratch_begin();
f32 aspect = frameSize.x / frameSize.y;
if(leftDown)
{
paddle.x -= 10;
}
else if(rightDown)
{
paddle.x += 10;
}
paddle.x = oc_clamp(paddle.x, 0, frameSize.x - paddle.w);
ball.x += velocity.x;
ball.y += velocity.y;
ball.x = oc_clamp(ball.x, 0, frameSize.x - ball.w);
ball.y = oc_clamp(ball.y, 0, frameSize.y - ball.h);
if(ball.x + ball.w >= frameSize.x)
{
velocity.x = -velocity.x;
}
if(ball.x <= 0)
{
velocity.x = -velocity.x;
}
if(ball.y + ball.h >= frameSize.y)
{
velocity.y = -velocity.y;
}
if(
ball.y <= paddle.y + paddle.h && ball.x + ball.w >= paddle.x && ball.x <= paddle.x + paddle.w && velocity.y < 0)
{
f32 t = ((ball.x + ball.w / 2) - paddle.x) / paddle.w;
f32 launchAngle = lerp(-PADDLE_MAX_LAUNCH_ANGLE, PADDLE_MAX_LAUNCH_ANGLE, t);
f32 speed = sqrtf(velocity.x * velocity.x + velocity.y * velocity.y);
velocity = (oc_vec2){
sinf(launchAngle) * speed,
cosf(launchAngle) * speed,
};
ball.y = paddle.y + paddle.h;
oc_log_info("PONG!");
}
if(ball.y <= 0)
{
ball.x = frameSize.x / 2. - ball.w;
ball.y = frameSize.y / 2. - ball.h;
}
for(int i = 0; i < NUM_BLOCKS; i++)
{
if(blockHealth[i] <= 0)
{
continue;
}
oc_rect r = block_rect(i);
int result = check_collision(r);
if(result)
{
oc_log_info("Collision! direction=%d", result);
blockHealth[i] -= 1;
if(blockHealth[i] == 0)
{
++score;
}
f32 vx = velocity.x;
f32 vy = velocity.y;
switch(result)
{
case 1:
case 5:
velocity.y = -vy;
break;
case 3:
case 7:
velocity.x = -vx;
break;
case 2:
case 6:
velocity.x = -vy;
velocity.y = -vx;
break;
case 4:
case 8:
velocity.x = vy;
velocity.y = vx;
break;
}
}
}
if(score == NUM_BLOCKS_TO_WIN)
{
oc_request_quit();
}
oc_canvas_select(canvas);
oc_set_color_rgba(10.0f / 255.0f, 31.0f / 255.0f, 72.0f / 255.0f, 1);
oc_clear();
oc_image_draw(waterImage, (oc_rect){ 0, 0, frameSize.x, frameSize.y });
oc_mat2x3 yUp = {
1, 0, 0,
0, -1, frameSize.y
};
oc_matrix_multiply_push(yUp);
{
for(int i = 0; i < NUM_BLOCKS; i++)
{
if(blockHealth[i] <= 0)
{
continue;
}
oc_rect r = block_rect(i);
oc_set_image(brickImage);
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
oc_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
oc_set_image(oc_image_nil());
oc_set_color_rgba(0.6, 0.6, 0.6, 1);
oc_set_width(2);
oc_rounded_rectangle_stroke(r.x, r.y, r.w, r.h, 4);
int fontSize = 18;
oc_str8 text = oc_str8_pushf(scratch.arena, "%d", blockHealth[i]);
oc_rect textRect = oc_font_text_metrics(font, fontSize, text).ink;
oc_vec2 textPos = {
r.x + r.w / 2 - textRect.w / 2 - textRect.x,
r.y + r.h / 2 - textRect.h / 2 - textRect.y - textRect.h, //NOTE: we render with y-up so we need to flip bounding box coordinates.
};
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
oc_circle_fill(r.x + r.w / 2, r.y + r.h / 2, r.h / 2.5);
oc_set_color_rgba(0, 0, 0, 1);
oc_set_font(font);
oc_set_font_size(18);
oc_move_to(textPos.x, textPos.y);
oc_matrix_multiply_push(flip_y_at(textPos));
{
oc_text_outlines(text);
oc_fill();
}
oc_matrix_pop();
}
oc_set_color(paddleColor);
oc_rounded_rectangle_fill(paddle.x, paddle.y, paddle.w, paddle.h, 4);
oc_matrix_multiply_push(flip_y(ball));
{
oc_image_draw(ballImage, ball);
}
oc_matrix_pop();
// draw score text
{
oc_move_to(20, 20);
oc_str8 text = oc_str8_pushf(scratch.arena, "Destroy all %d blocks to win! Current score: %d", NUM_BLOCKS_TO_WIN, score);
oc_vec2 textPos = { 20, 20 };
oc_matrix_multiply_push(flip_y_at(textPos));
{
oc_set_color_rgba(0.9, 0.9, 0.9, 1);
oc_text_outlines(text);
oc_fill();
}
oc_matrix_pop();
}
}
oc_matrix_pop();
oc_surface_select(surface);
oc_render(canvas);
oc_surface_present(surface);
oc_scratch_end(scratch);
}

View File

@ -1,3 +1,3 @@
Pong
Clock
profile.dtrace
profile.spall

39
samples/clock/build.bat Normal file
View File

@ -0,0 +1,39 @@
@echo off
setlocal enabledelayedexpansion
:: The following code checks if you have the necessary programs to compile the samples.
:: This code exists to improve the experience of first-time Orca users and can
:: be safely deleted in your own projects if you wish.
if exist "..\..\scripts\sample_build_check.py" (
python ..\..\scripts\sample_build_check.py
if !ERRORLEVEL! neq 0 exit /b 1
) else (
echo Could not check if you have the necessary tools to build the Orca samples.
echo If you have copied this script to your own project, you can delete this code.
)
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: common flags to build wasm modules
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
:: build orca core as wasm module
clang %wasmFlags% -Wl,--relocatable -o .\liborca.a %ORCA_DIR%\src\orca.c %ORCA_DIR%\src\libc-shim\src\*.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: build sample as wasm module and link it with the orca module
clang %wasmFlags% -L . -lorca -o module.wasm src/main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: create app directory and copy files into it
orca bundle --orca-dir %ORCA_DIR% --name Clock --icon icon.png --resource-dir data module.wasm

37
samples/clock/build.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
# The following code checks if you have the necessary programs to compile the samples.
# This code exists to improve the experience of first-time Orca users and can
# be safely deleted in your own projects if you wish.
if [ -f ../../scripts/sample_build_check.py ]; then
python3 ../../scripts/sample_build_check.py
else
echo "Could not check if you have the necessary tools to build the Orca samples."
echo "If you have copied this script to your own project, you can delete this code."
fi
ORCA_DIR=../..
STDLIB_DIR=$ORCA_DIR/src/libc-shim
# common flags to build wasm modules
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
# build orca core as wasm module
clang $wasmFlags -Wl,--relocatable -o ./liborca.a $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c
# build sample as wasm module and link it with the orca module
clang $wasmFlags -L . -lorca -o module.wasm src/main.c
# create app directory and copy files into it
orca bundle --orca-dir $ORCA_DIR --name Clock --icon icon.png --resource-dir data module.wasm

62
samples/clock/build_cpp.sh Executable file
View File

@ -0,0 +1,62 @@
#!/bin/bash
set -euo pipefail
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
CLANG=/usr/local/opt/llvm/bin/clang
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
CLANG=/opt/homebrew/opt/llvm/bin/clang
else
echo "Could not find Homebrew clang; this script will probably not work."
CLANG=clang
fi
if [[ -x /usr/local/opt/llvm/bin/clang++ ]]; then
CLANGPP=/usr/local/opt/llvm/bin/clang++
elif [[ -x /opt/homebrew/opt/llvm/bin/clang++ ]]; then
CLANGPP=/opt/homebrew/opt/llvm/bin/clang++
else
echo "Could not find Homebrew clang++; this script will probably not work."
CLANGPP=clang++
fi
ORCA_DIR=../..
STDLIB_DIR=../../src/libc-shim
wasmObjFlags="--target=wasm32 \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $ORCA_DIR/ext \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $ORCA_DIR/ext \
-I $STDLIB_DIR/include \
-I $ORCA_DIR/ext \
-I $ORCA_DIR/src"
if [ ! -e build ] ; then
mkdir build
fi
$CLANG $wasmObjFlags -c -o ./build/orca.o ../../src/orca.c
for file in $STDLIB_DIR/src/*.c ; do
name=$(basename $file)
name=${name%.c}
$CLANG $wasmObjFlags -c -o ./build/$name.o $file
done
$CLANGPP $wasmFlags -o ./module.wasm src/main.c ./build/*.o
orca bundle --orca-dir ../.. --name Clock --resource-dir data module.wasm

Binary file not shown.

BIN
samples/clock/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

147
samples/clock/src/main.c Normal file
View File

@ -0,0 +1,147 @@
/*************************************************************************
*
* Orca
* Copyright 2023 Martin Fouilleul and the Orca project contributors
* See LICENSE.txt for licensing information
*
**************************************************************************/
#include <math.h>
#include <orca.h>
const oc_str8 clockNumberStrings[] = {
OC_STR8_LIT("12"),
OC_STR8_LIT("1"),
OC_STR8_LIT("2"),
OC_STR8_LIT("3"),
OC_STR8_LIT("4"),
OC_STR8_LIT("5"),
OC_STR8_LIT("6"),
OC_STR8_LIT("7"),
OC_STR8_LIT("8"),
OC_STR8_LIT("9"),
OC_STR8_LIT("10"),
OC_STR8_LIT("11"),
};
oc_surface surface = { 0 };
oc_canvas canvas = { 0 };
oc_font font = { 0 };
oc_vec2 frameSize = { 100, 100 };
f64 lastSeconds = 0;
oc_mat2x3 mat_transform(f32 x, f32 y, f32 radians)
{
oc_mat2x3 rotation = oc_mat2x3_rotate(radians);
oc_mat2x3 translation = oc_mat2x3_translate(x, y);
return oc_mat2x3_mul_m(translation, rotation);
}
ORCA_EXPORT void oc_on_init(void)
{
oc_window_set_title(OC_STR8("clock"));
oc_window_set_size((oc_vec2){ .x = 400, .y = 400 });
surface = oc_surface_canvas();
canvas = oc_canvas_create();
oc_unicode_range ranges[5] = {
OC_UNICODE_BASIC_LATIN,
OC_UNICODE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
OC_UNICODE_LATIN_EXTENDED_A,
OC_UNICODE_LATIN_EXTENDED_B,
OC_UNICODE_SPECIALS
};
font = oc_font_create_from_path(OC_STR8("/segoeui.ttf"), 5, ranges);
}
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{
frameSize.x = width;
frameSize.y = height;
}
ORCA_EXPORT void oc_on_frame_refresh(void)
{
oc_canvas_select(canvas);
oc_set_color_rgba(.05, .05, .05, 1);
oc_clear();
const f64 timestampSecs = oc_clock_time(OC_CLOCK_DATE);
const f64 secs = fmod(timestampSecs, 60);
const f64 minutes = fmod(timestampSecs, 60 * 60) / 60;
const f64 hours = fmod(timestampSecs, 60 * 60 * 24) / (60 * 60);
const f64 hoursAs12Format = fmod(hours, 12.0);
if(lastSeconds != floor(secs))
{
lastSeconds = floor(secs);
oc_log_info("current time: %.0f:%.0f:%.0f", floor(hours), floor(minutes), floor(secs));
}
const f32 secondsRotation = (M_PI * 2) * (secs / 60.0) - (M_PI / 2);
const f32 minutesRotation = (M_PI * 2) * (minutes / 60.0) - (M_PI / 2);
const f32 hoursRotation = (M_PI * 2) * (hoursAs12Format / 12.0) - (M_PI / 2);
const f32 centerX = frameSize.x / 2;
const f32 centerY = frameSize.y / 2;
const f32 clockRadius = oc_min(frameSize.x, frameSize.y) * 0.5f * 0.85f;
const f32 DEFAULT_CLOCK_RADIUS = 260;
const f32 uiScale = clockRadius / DEFAULT_CLOCK_RADIUS;
const f32 fontSize = 26 * uiScale;
oc_set_font(font);
oc_set_font_size(fontSize);
// clock backing
oc_set_color_rgba(1, 1, 1, 1);
oc_circle_fill(centerX, centerY, clockRadius);
// clock face
for(int i = 0; i < oc_array_size(clockNumberStrings); ++i)
{
oc_rect textRect = oc_font_text_metrics(font, fontSize, clockNumberStrings[i]).ink;
const f32 angle = i * ((M_PI * 2) / 12.0f) - (M_PI / 2);
oc_mat2x3 transform = mat_transform(centerX - (textRect.w / 2) - textRect.x,
centerY - (textRect.h / 2) - textRect.y,
angle);
oc_vec2 pos = oc_mat2x3_mul(transform, (oc_vec2){ clockRadius * 0.8f, 0 });
oc_set_color_rgba(0.2, 0.2, 0.2, 1);
oc_text_fill(pos.x, pos.y, clockNumberStrings[i]);
}
// hours hand
oc_matrix_multiply_push(mat_transform(centerX, centerY, hoursRotation));
{
oc_set_color_rgba(.2, 0.2, 0.2, 1);
oc_rounded_rectangle_fill(0, -7.5 * uiScale, clockRadius * 0.5f, 15 * uiScale, 5 * uiScale);
}
oc_matrix_pop();
// minutes hand
oc_matrix_multiply_push(mat_transform(centerX, centerY, minutesRotation));
{
oc_set_color_rgba(.2, 0.2, 0.2, 1);
oc_rounded_rectangle_fill(0, -5 * uiScale, clockRadius * 0.7f, 10 * uiScale, 5 * uiScale);
}
oc_matrix_pop();
// seconds hand
oc_matrix_multiply_push(mat_transform(centerX, centerY, secondsRotation));
{
oc_set_color_rgba(1, 0.2, 0.2, 1);
oc_rounded_rectangle_fill(0, -2.5 * uiScale, clockRadius * 0.8f, 5 * uiScale, 5 * uiScale);
}
oc_matrix_pop();
oc_set_color_rgba(.2, 0.2, 0.2, 1);
oc_circle_fill(centerX, centerY, 10 * uiScale);
oc_surface_select(surface);
oc_render(canvas);
oc_surface_present(surface);
}

4
samples/fluid/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
Fluid
profile.dtrace
profile.spall
glsl_shaders.h

57
samples/fluid/build.bat Normal file
View File

@ -0,0 +1,57 @@
@echo off
setlocal enabledelayedexpansion
:: The following code checks if you have the necessary programs to compile the samples.
:: This code exists to improve the experience of first-time Orca users and can
:: be safely deleted in your own projects if you wish.
if exist "..\..\scripts\sample_build_check.py" (
python ..\..\scripts\sample_build_check.py
if !ERRORLEVEL! neq 0 exit /b 1
) else (
echo Could not check if you have the necessary tools to build the Orca samples.
echo If you have copied this script to your own project, you can delete this code.
)
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: common flags to build wasm modules
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
:: build orca core as wasm module
clang %wasmFlags% -Wl,--relocatable -o .\liborca.a %ORCA_DIR%\src\orca.c %ORCA_DIR%\src\libc-shim\src\*.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
set shaders=src/shaders/advect.glsl^
src/shaders/blit_div_fragment.glsl^
src/shaders/blit_div_vertex.glsl^
src/shaders/blit_fragment.glsl^
src/shaders/blit_residue_fragment.glsl^
src/shaders/blit_vertex.glsl^
src/shaders/common_vertex.glsl^
src/shaders/divergence.glsl^
src/shaders/jacobi_step.glsl^
src/shaders/multigrid_correct.glsl^
src/shaders/multigrid_restrict_residual.glsl^
src/shaders/splat.glsl^
src/shaders/subtract_pressure.glsl
call python ../../scripts/embed_text_files.py --prefix=glsl_ --output src/glsl_shaders.h %shaders%
if !ERRORLEVEL! neq 0 exit /b !ERRORLEVEL!
:: build sample as wasm module and link it with the orca module
clang %wasmFlags% -L . -lorca -o .\module.wasm src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: create app directory and copy files into it
orca bundle --orca-dir %ORCA_DIR% --name Fluid --icon icon.png module.wasm

39
samples/fluid/build.sh Executable file
View File

@ -0,0 +1,39 @@
#!/bin/bash
set -euo pipefail
# The following code checks if you have the necessary programs to compile the samples.
# This code exists to improve the experience of first-time Orca users and can
# be safely deleted in your own projects if you wish.
if [ -f ../../scripts/sample_build_check.py ]; then
python3 ../../scripts/sample_build_check.py
else
echo "Could not check if you have the necessary tools to build the Orca samples."
echo "If you have copied this script to your own project, you can delete this code."
fi
ORCA_DIR=../..
STDLIB_DIR=$ORCA_DIR/src/libc-shim
python3 ../../scripts/embed_text_files.py --prefix=glsl_ --output src/glsl_shaders.h src/shaders/*.glsl
# common flags to build wasm modules
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
# build orca core as wasm module
clang $wasmFlags -Wl,--relocatable -o ./liborca.a $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c
# build sample as wasm module and link it with the orca module
clang $wasmFlags -L . -lorca -o module.wasm src/main.c
# create app directory and copy files into it
orca bundle --orca-dir $ORCA_DIR --name Fluid --icon icon.png module.wasm

BIN
samples/fluid/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

861
samples/fluid/src/main.c Normal file
View File

@ -0,0 +1,861 @@
/*************************************************************************
*
* Orca
* Copyright 2023 Martin Fouilleul and the Orca project contributors
* See LICENSE.txt for licensing information
*
**************************************************************************/
#include "glsl_shaders.h"
#include "math.h"
#include "orca.h"
//----------------------------------------------------------------
//NOTE(martin): GL vertex struct and identifiers
//----------------------------------------------------------------
typedef struct Vertex
{
float x, y;
} Vertex;
typedef struct advect_program
{
GLuint prog;
GLint pos;
GLint src;
GLint velocity;
GLint delta;
GLint dissipation;
} advect_program;
typedef struct div_program
{
GLuint prog;
GLint pos;
GLint src;
} div_program;
typedef struct jacobi_program
{
GLuint prog;
GLint pos;
GLint xTex;
GLint bTex;
} jacobi_program;
typedef struct blit_residue_program
{
GLuint prog;
GLint pos;
GLint mvp;
GLint xTex;
GLint bTex;
} blit_residue_program;
typedef struct multigrid_restrict_residual_program
{
GLuint prog;
GLint pos;
GLint xTex;
GLint bTex;
} multigrid_restrict_residual_program;
typedef struct multigrid_correct_program
{
GLuint prog;
GLint pos;
GLint src;
GLint error;
GLint invGridSize;
} multigrid_correct_program;
typedef struct subtract_program
{
GLuint prog;
GLint pos;
GLint src;
GLint pressure;
GLint invGridSize;
} subtract_program;
typedef struct blit_program
{
GLuint prog;
GLint pos;
GLint mvp;
GLint gridSize;
GLint tex;
} blit_program;
typedef struct splat_program
{
GLuint prog;
GLint pos;
GLint src;
GLint splatPos;
GLint splatColor;
GLint radius;
GLint additive;
GLint blending;
GLint randomize;
} splat_program;
typedef struct frame_buffer
{
GLuint textures[2];
GLuint fbos[2];
} frame_buffer;
advect_program advectProgram;
div_program divProgram;
jacobi_program jacobiProgram;
multigrid_restrict_residual_program multigridRestrictResidualProgram;
multigrid_correct_program multigridCorrectProgram;
subtract_program subtractProgram;
splat_program splatProgram;
blit_program blitProgram;
blit_program blitDivProgram;
blit_residue_program blitResidueProgram;
frame_buffer colorBuffer;
frame_buffer velocityBuffer;
const int MULTIGRID_COUNT = 4;
frame_buffer pressureBuffer[4];
frame_buffer divBuffer[4];
GLuint vertexBuffer;
oc_surface surface;
f64 startTime;
//----------------------------------------------------------------
//NOTE(martin): initialization
//----------------------------------------------------------------
GLuint compile_shader(const char* vs, const char* fs)
{
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vs, 0);
glCompileShader(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fs, 0);
glCompileShader(fragmentShader);
GLuint prog = glCreateProgram();
glAttachShader(prog, vertexShader);
glAttachShader(prog, fragmentShader);
glLinkProgram(prog);
int status = 0;
glGetProgramiv(prog, GL_LINK_STATUS, &status);
if(status != GL_TRUE)
{
oc_log_error("program failed to link: ");
int logSize = 0;
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &logSize);
oc_arena_scope scratch = oc_scratch_begin();
char* log = oc_arena_push(scratch.arena, logSize);
glGetProgramInfoLog(prog, logSize, 0, log);
oc_log_error("%s\n", log);
oc_scratch_end(scratch);
}
int err = glGetError();
if(err)
{
oc_log_error("gl error %i\n", err);
}
return (prog);
}
void init_advect(advect_program* program)
{
oc_log_info("compiling advect...");
program->prog = compile_shader(glsl_common_vertex, glsl_advect);
program->pos = glGetAttribLocation(program->prog, "pos");
program->src = glGetUniformLocation(program->prog, "src");
program->velocity = glGetUniformLocation(program->prog, "velocity");
program->delta = glGetUniformLocation(program->prog, "delta");
program->dissipation = glGetUniformLocation(program->prog, "dissipation");
}
void init_div(div_program* program)
{
oc_log_info("compiling div...");
program->prog = compile_shader(glsl_common_vertex, glsl_divergence);
program->pos = glGetAttribLocation(program->prog, "pos");
program->src = glGetUniformLocation(program->prog, "src");
}
void init_jacobi(jacobi_program* program)
{
oc_log_info("compiling jacobi...");
program->prog = compile_shader(glsl_common_vertex, glsl_jacobi_step);
program->pos = glGetAttribLocation(program->prog, "pos");
program->xTex = glGetUniformLocation(program->prog, "xTex");
program->bTex = glGetUniformLocation(program->prog, "bTex");
}
void init_multigrid_restrict_residual(multigrid_restrict_residual_program* program)
{
oc_log_info("compiling multigrid restrict residual...");
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_restrict_residual);
program->pos = glGetAttribLocation(program->prog, "pos");
program->xTex = glGetUniformLocation(program->prog, "xTex");
program->bTex = glGetUniformLocation(program->prog, "bTex");
}
void init_multigrid_correct(multigrid_correct_program* program)
{
oc_log_info("compiling multigrid correct...");
program->prog = compile_shader(glsl_common_vertex, glsl_multigrid_correct);
program->pos = glGetAttribLocation(program->prog, "pos");
program->src = glGetUniformLocation(program->prog, "src");
program->error = glGetUniformLocation(program->prog, "error");
program->invGridSize = glGetUniformLocation(program->prog, "invGridSize");
}
void init_subtract(subtract_program* program)
{
oc_log_info("compiling subtract...");
program->prog = compile_shader(glsl_common_vertex, glsl_subtract_pressure);
program->pos = glGetAttribLocation(program->prog, "pos");
program->src = glGetUniformLocation(program->prog, "src");
program->pressure = glGetUniformLocation(program->prog, "pressure");
program->invGridSize = glGetUniformLocation(program->prog, "invGridSize");
}
void init_splat(splat_program* program)
{
oc_log_info("compiling splat...");
program->prog = compile_shader(glsl_common_vertex, glsl_splat);
program->pos = glGetAttribLocation(program->prog, "pos");
program->src = glGetUniformLocation(program->prog, "src");
program->splatPos = glGetUniformLocation(program->prog, "splatPos");
program->splatColor = glGetUniformLocation(program->prog, "splatColor");
program->radius = glGetUniformLocation(program->prog, "radius");
program->additive = glGetUniformLocation(program->prog, "additive");
program->blending = glGetUniformLocation(program->prog, "blending");
program->randomize = glGetUniformLocation(program->prog, "randomize");
}
void init_blit(blit_program* program)
{
oc_log_info("compiling blit...");
program->prog = compile_shader(glsl_blit_vertex, glsl_blit_fragment);
program->pos = glGetAttribLocation(program->prog, "pos");
program->mvp = glGetUniformLocation(program->prog, "mvp");
program->tex = glGetUniformLocation(program->prog, "tex");
program->gridSize = glGetUniformLocation(program->prog, "gridSize");
}
void init_blit_div(blit_program* program)
{
oc_log_info("compiling blit div...");
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_div_fragment);
program->pos = glGetAttribLocation(program->prog, "pos");
program->mvp = glGetUniformLocation(program->prog, "mvp");
program->tex = glGetUniformLocation(program->prog, "tex");
}
void init_blit_residue(blit_residue_program* program)
{
oc_log_info("compiling blit residue...");
program->prog = compile_shader(glsl_blit_div_vertex, glsl_blit_residue_fragment);
program->pos = glGetAttribLocation(program->prog, "pos");
program->mvp = glGetUniformLocation(program->prog, "mvp");
program->xTex = glGetUniformLocation(program->prog, "xTex");
program->bTex = glGetUniformLocation(program->prog, "bTex");
}
GLuint create_texture(int width, int height, GLenum internalFormat, GLenum format, GLenum type, char* initData)
{
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, type, initData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
return (texture);
}
GLuint create_fbo(GLuint texture)
{
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glBindTexture(GL_TEXTURE_2D, texture);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
return (fbo);
}
void init_frame_buffer(frame_buffer* framebuffer,
int width,
int height,
GLenum internalFormat,
GLenum format,
GLenum type,
char* initData)
{
for(int i = 0; i < 2; i++)
{
framebuffer->textures[i] = create_texture(width, height, internalFormat, format, type, initData);
framebuffer->fbos[i] = create_fbo(framebuffer->textures[i]);
}
GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(err != GL_FRAMEBUFFER_COMPLETE)
{
oc_log_info("Frame buffer incomplete, %i", err);
}
}
void frame_buffer_swap(frame_buffer* buffer)
{
GLuint tmp = buffer->fbos[0];
buffer->fbos[0] = buffer->fbos[1];
buffer->fbos[1] = tmp;
tmp = buffer->textures[0];
buffer->textures[0] = buffer->textures[1];
buffer->textures[1] = tmp;
}
//----------------------------------------------------------------
//NOTE(martin): entry point
//----------------------------------------------------------------
#define texWidth (256)
#define texHeight (256)
float colorInitData[texWidth][texHeight][4] = { 0 };
float velocityInitData[texWidth][texHeight][4] = { 0 };
const float EPSILON = 1.,
INV_GRID_SIZE = 1. / (float)texWidth,
DELTA = 1. / 120.;
const GLenum TEX_INTERNAL_FORMAT = GL_RGBA32F;
const GLenum TEX_FORMAT = GL_RGBA;
const GLenum TEX_TYPE = GL_FLOAT;
#define square(x) ((x) * (x))
/*
void reset_texture(GLuint texture, float width, float height, char* initData)
{
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, TEX_INTERNAL_FORMAT, width, height, 0, TEX_FORMAT, TEX_TYPE, initData);
}
static bool resetCmd = false;
void reset()
{
// resetCmd = true;
oc_log_info("reset");
reset_texture(colorBuffer.textures[0], texWidth, texHeight, (char*)colorInitData);
reset_texture(colorBuffer.textures[1], texWidth, texHeight, (char*)colorInitData);
reset_texture(velocityBuffer.textures[0], texWidth, texHeight, (char*)velocityInitData);
reset_texture(velocityBuffer.textures[1], texWidth, texHeight, (char*)velocityInitData);
int gridFactor = 1;
for(int i=0; i<MULTIGRID_COUNT; i++)
{
reset_texture(pressureBuffer[i].textures[0], texWidth/gridFactor, texHeight/gridFactor, 0);
reset_texture(pressureBuffer[i].textures[1], texWidth/gridFactor, texHeight/gridFactor, 0);
gridFactor *= 2;
}
}
*/
typedef struct mouse_input
{
float x;
float y;
float deltaX;
float deltaY;
bool down;
} mouse_input;
mouse_input mouseInput = { 0 };
bool mouseWasDown = false;
int frameWidth = 800;
int frameHeight = 600;
ORCA_EXPORT void oc_on_mouse_down(int button)
{
mouseInput.down = true;
mouseWasDown = true;
}
ORCA_EXPORT void oc_on_mouse_up(int button)
{
mouseInput.down = false;
}
ORCA_EXPORT void oc_on_mouse_move(float x, float y, float dx, float dy)
{
mouseInput.x = x;
mouseInput.y = y;
mouseInput.deltaX = dx;
mouseInput.deltaY = dy;
}
void init_color_checker()
{
for(int i = 0; i < texHeight; i++)
{
for(int j = 0; j < texWidth; j++)
{
float u = j / (float)texWidth;
float v = i / (float)texWidth;
float value = ((int)(u * 10) % 2) == ((int)(v * 10) % 2) ? 1. : 0.;
for(int k = 0; k < 3; k++)
{
colorInitData[i][j][k] = value;
}
colorInitData[i][j][3] = 1;
}
}
}
void init_velocity_vortex()
{
for(int i = 0; i < texHeight; i++)
{
for(int j = 0; j < texWidth; j++)
{
float x = 2 * j / (float)texWidth - 1;
float y = 2 * i / (float)texWidth - 1;
velocityInitData[i][j][0] = sinf(2 * M_PI * y);
velocityInitData[i][j][1] = sinf(2 * M_PI * x);
}
}
}
void apply_splat(float splatPosX, float splatPosY, float radius, float splatVelX, float splatVelY, float r, float g, float b, bool randomize)
{
glUseProgram(splatProgram.prog);
if(randomize)
{
glUniform1f(splatProgram.randomize, 1.);
}
else
{
glUniform1f(splatProgram.randomize, 0.);
}
// force
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(splatProgram.src, 0);
glUniform2f(splatProgram.splatPos, splatPosX, splatPosY);
glUniform3f(splatProgram.splatColor, splatVelX, splatVelY, 0);
glUniform1f(splatProgram.additive, 1);
glUniform1f(splatProgram.blending, 0);
glUniform1f(splatProgram.radius, radius);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&velocityBuffer);
// dye
glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
glUniform1i(splatProgram.src, 0);
glUniform2f(splatProgram.splatPos, splatPosX, splatPosY);
glUniform3f(splatProgram.splatColor, r, g, b);
glUniform1f(splatProgram.additive, 0);
glUniform1f(splatProgram.blending, 1);
glUniform1f(splatProgram.radius, radius);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&colorBuffer);
}
void jacobi_solve(frame_buffer* x, frame_buffer* b, float invGridSize, int iterationCount)
{
glUseProgram(jacobiProgram.prog);
for(int i = 0; i < iterationCount; i++)
{
glBindFramebuffer(GL_FRAMEBUFFER, x->fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
glUniform1i(jacobiProgram.xTex, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, b->textures[0]);
glUniform1i(jacobiProgram.bTex, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(x);
}
}
void multigrid_coarsen_residual(frame_buffer* output, frame_buffer* x, frame_buffer* b, float invFineGridSize)
{
//NOTE: compute residual and downsample to coarser grid, put result in coarser buffer
glUseProgram(multigridRestrictResidualProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, output->fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
glUniform1i(multigridRestrictResidualProgram.xTex, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, b->textures[0]);
glUniform1i(multigridRestrictResidualProgram.bTex, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(output);
}
void multigrid_prolongate_and_correct(frame_buffer* x, frame_buffer* error, float invFineGridSize)
{
//NOTE: correct finer pressure
glUseProgram(multigridCorrectProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, x->fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, x->textures[0]);
glUniform1i(multigridCorrectProgram.src, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, error->textures[0]);
glUniform1i(multigridCorrectProgram.error, 1);
glUniform1f(multigridCorrectProgram.invGridSize, invFineGridSize);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(x);
}
void multigrid_clear(frame_buffer* error)
{
glBindFramebuffer(GL_FRAMEBUFFER, error->fbos[0]);
glClear(GL_COLOR_BUFFER_BIT);
}
void input_splat(float t)
{
bool applySplat = false;
float x, y, deltaX, deltaY;
static f64 lastFrameTime = 0;
if (lastFrameTime == 0)
{
lastFrameTime = startTime;
}
f64 now = oc_clock_time(OC_CLOCK_MONOTONIC);
float frameDuration = now - lastFrameTime;
lastFrameTime = now;
if (mouseInput.down && (mouseInput.deltaX || mouseInput.deltaY))
{
oc_vec2 scaling = oc_surface_contents_scaling(surface);
applySplat = true;
x = mouseInput.x * scaling.x / frameWidth;
y = mouseInput.y * scaling.y / frameHeight;
deltaX = 1. / 60 / frameDuration * mouseInput.deltaX * scaling.x / frameWidth;
deltaY = 1. / 60 / frameDuration * mouseInput.deltaY * scaling.y / frameHeight;
mouseInput.deltaX = 0;
mouseInput.deltaY = 0;
}
f64 timeSinceStart = now - startTime;
if (!mouseWasDown && timeSinceStart < 1)
{
applySplat = true;
float totalDeltaX = 0.5;
x = 0.1 + totalDeltaX * timeSinceStart;
y = 0.5;
deltaX = totalDeltaX / 180;
deltaY = 0;
}
//NOTE: apply force and dye
if(applySplat)
{
// account for margin
float margin = 32;
float offset = margin / texWidth;
float ratio = 1 - 2 * margin / texWidth;
float splatPosX = x * ratio + offset;
float splatPosY = (1 - y) * ratio + offset;
float splatVelX = (10000. * DELTA * deltaX) * ratio;
float splatVelY = (-10000. * DELTA * deltaY) * ratio;
float intensity = 100 * sqrtf(square(ratio * deltaX) + square(ratio * deltaY));
float r = intensity * (sinf(2 * M_PI * 0.1 * t) + 1);
float g = 0.5 * intensity * (cosf(2 * M_PI * 0.1 / M_E * t + 654) + 1);
float b = intensity * (sinf(2 * M_PI * 0.1 / M_SQRT2 * t + 937) + 1);
float radius = 0.005;
apply_splat(splatPosX, splatPosY, radius, splatVelX, splatVelY, r, g, b, false);
}
}
float testDiv[texWidth / 2][texWidth / 2][4];
ORCA_EXPORT void oc_on_init()
{
oc_log_info("Hello, world (from C)");
oc_window_set_title(OC_STR8("fluid"));
surface = oc_surface_gles();
oc_surface_select(surface);
// init_color_checker();
// init_velocity_vortex();
// init programs
init_advect(&advectProgram);
init_div(&divProgram);
init_jacobi(&jacobiProgram);
init_multigrid_restrict_residual(&multigridRestrictResidualProgram);
init_multigrid_correct(&multigridCorrectProgram);
init_blit_residue(&blitResidueProgram);
init_subtract(&subtractProgram);
init_splat(&splatProgram);
init_blit(&blitProgram);
init_blit_div(&blitDivProgram);
// init frame buffers
oc_log_info("create color buffer");
init_frame_buffer(&colorBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)colorInitData);
oc_log_info("create velocity buffer");
init_frame_buffer(&velocityBuffer, texWidth, texHeight, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, (char*)velocityInitData);
int gridFactor = 1;
for(int i = 0; i < MULTIGRID_COUNT; i++)
{
oc_log_info("create div buffer %i", i);
init_frame_buffer(&divBuffer[i], texWidth / gridFactor, texHeight / gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
oc_log_info("create pressure buffer %i", i);
init_frame_buffer(&pressureBuffer[i], texWidth / gridFactor, texHeight / gridFactor, TEX_INTERNAL_FORMAT, TEX_FORMAT, TEX_TYPE, 0);
gridFactor *= 2;
}
// init vertex buffer
static Vertex vertices[6] = {
{ -1, -1 },
{ 1, -1 },
{ 1, 1 },
{ -1, -1 },
{ 1, 1 },
{ -1, 1 }
};
//WARN: we assume blitProgram.pos == advectProgram.pos, is there a situation where it wouldn't be true??
GLuint vertexBuffer = 0;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(Vertex), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(blitProgram.pos, 2, GL_FLOAT, GL_FALSE, 0, 0);
for(int i = 0; i < texWidth / 2; i++)
{
for(int j = 0; j < texHeight / 2; j++)
{
testDiv[i][j][0] = 0.5 + 0.5 * cosf(j / 100. * 3.14159 + i / 100. * 1.2139);
}
}
startTime = oc_clock_time(OC_CLOCK_MONOTONIC);
}
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{
oc_vec2 scaling = oc_surface_contents_scaling(surface);
frameWidth = width * scaling.x;
frameHeight = height * scaling.y;
}
ORCA_EXPORT void oc_on_frame_refresh()
{
float aspectRatio = texWidth / texHeight;
static float t = 0;
t += 1. / 60.;
oc_surface_select(surface);
glViewport(0, 0, texWidth, texHeight);
//NOTE: advect velocity thru itself
glUseProgram(advectProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(advectProgram.src, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(advectProgram.velocity, 1);
glUniform1f(advectProgram.delta, DELTA);
glUniform1f(advectProgram.dissipation, 0.01);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&velocityBuffer);
input_splat(t);
//NOTE: compute divergence of advected velocity
glUseProgram(divProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, divBuffer[0].fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(divProgram.src, 0);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&divBuffer[0]);
//NOTE: compute pressure
glBindFramebuffer(GL_FRAMEBUFFER, pressureBuffer[0].fbos[1]);
glClear(GL_COLOR_BUFFER_BIT);
#if 0
multigrid_clear(&pressureBuffer[0]);
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, texWidth*texHeight);
#else
multigrid_clear(&pressureBuffer[0]);
for(int i = 0; i < 1; i++)
{
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 2);
multigrid_coarsen_residual(&divBuffer[1], &pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE);
multigrid_clear(&pressureBuffer[1]);
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2 * INV_GRID_SIZE, 2);
multigrid_coarsen_residual(&divBuffer[2], &pressureBuffer[1], &divBuffer[1], 2 * INV_GRID_SIZE);
multigrid_clear(&pressureBuffer[2]);
jacobi_solve(&pressureBuffer[2], &divBuffer[2], 4 * INV_GRID_SIZE, 30);
multigrid_prolongate_and_correct(&pressureBuffer[1], &pressureBuffer[2], 2 * INV_GRID_SIZE);
jacobi_solve(&pressureBuffer[1], &divBuffer[1], 2 * INV_GRID_SIZE, 8);
multigrid_prolongate_and_correct(&pressureBuffer[0], &pressureBuffer[1], INV_GRID_SIZE);
jacobi_solve(&pressureBuffer[0], &divBuffer[0], INV_GRID_SIZE, 4);
}
#endif
//NOTE: subtract pressure gradient to advected velocity
glUseProgram(subtractProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, velocityBuffer.fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(subtractProgram.src, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, pressureBuffer[0].textures[0]);
glUniform1i(subtractProgram.pressure, 1);
glUniform1f(subtractProgram.invGridSize, INV_GRID_SIZE);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&velocityBuffer);
//NOTE: Advect color through corrected velocity field
glUseProgram(advectProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, colorBuffer.fbos[1]);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
glUniform1i(advectProgram.src, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, velocityBuffer.textures[0]);
glUniform1i(advectProgram.velocity, 1);
glUniform1f(advectProgram.delta, DELTA);
glUniform1f(advectProgram.dissipation, 0.001);
glDrawArrays(GL_TRIANGLES, 0, 6);
frame_buffer_swap(&colorBuffer);
//NOTE: Blit color texture to screen
glViewport(0, 0, frameWidth, frameHeight);
float displayMatrix[16] = {
1 / aspectRatio, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
glUseProgram(blitProgram.prog);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, colorBuffer.textures[0]);
glUniform1i(blitProgram.tex, 0);
glUniform2i(blitProgram.gridSize, texWidth, texHeight);
glUniformMatrix4fv(blitProgram.mvp, 1, GL_FALSE, displayMatrix);
glDrawArrays(GL_TRIANGLES, 0, 6);
oc_surface_present(surface);
}

View File

@ -0,0 +1,56 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D src;
uniform sampler2D velocity;
uniform float delta;
uniform float dissipation;
vec2 u(ivec2 coord)
{
return (texelFetch(velocity, coord, 0).xy);
}
vec4 q(ivec2 coord)
{
if(coord.x < 0
|| coord.x >= textureSize(src, 0).x
|| coord.y < 0
|| coord.y >= textureSize(src, 0).y)
{
return (vec4(0.));
}
return (texelFetch(src, coord, 0));
}
vec4 bilerpSrc(vec2 pos)
{
vec2 offset = fract(pos);
ivec2 bl = ivec2(floor(pos));
ivec2 br = bl + ivec2(1, 0);
ivec2 tl = bl + ivec2(0, 1);
ivec2 tr = bl + ivec2(1, 1);
vec4 lerpTop = (1. - offset.x) * q(tl) + offset.x * q(tr);
vec4 lerpBottom = (1. - offset.x) * q(bl) + offset.x * q(br);
vec4 result = (1. - offset.y) * lerpBottom + offset.y * lerpTop;
return (result);
}
void main()
{
float texWidth = float(textureSize(velocity, 0).x);
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
vec2 samplePos = vec2(pixelCoord) - texWidth * delta * u(pixelCoord);
fragColor = bilerpSrc(samplePos) / (1. + dissipation * delta);
}

View File

@ -0,0 +1,43 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D tex;
vec3 color_map(float v)
{
float logv = log(abs(v)) / log(10.0);
float f = floor(logv + 7.0);
float i = floor(4.0 * (logv + 7.0 - f));
if(f < 0.0)
return vec3(0.0);
if(f < 1.0)
return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i / 4.0);
if(f < 2.0)
return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 3.0)
return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 4.0)
return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 5.0)
return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 6.0)
return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i / 4.0);
if(f < 7.0)
return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i / 4.0);
if(f < 8.0)
return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i / 4.0);
return vec3(1.0);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(tex, 0).xy)));
float f = texelFetch(tex, pixelCoord, 0).x;
fragColor = vec4(color_map(f), 1.0);
}

View File

@ -0,0 +1,14 @@
#version 300 es
precision highp float;
in vec2 pos;
out vec2 texCoord;
uniform mat4 mvp;
void main()
{
texCoord = 0.5 * (pos + vec2(1, 1));
gl_Position = mvp * vec4(pos, 0, 1);
}

View File

@ -0,0 +1,15 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D tex;
void main()
{
fragColor = texture(tex, texCoord);
fragColor.a = 1.0;
}

View File

@ -0,0 +1,74 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D xTex;
uniform sampler2D bTex;
float x(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
{
return (0.);
}
return (texelFetch(xTex, coord, 0).x);
}
float b(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
{
return (0.);
}
return (texelFetch(bTex, coord, 0).x);
}
vec3 color_map(float v)
{
float logv = log(abs(v)) / log(10.0);
float f = floor(logv + 7.0);
float i = floor(4.0 * (logv + 7.0 - f));
if(f < 0.0)
return vec3(0.0);
if(f < 1.0)
return mix(vec3(1.0, 0.0, 0.0), vec3(1.0), i / 4.0);
if(f < 2.0)
return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 3.0)
return mix(vec3(0.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 4.0)
return mix(vec3(1.0, 1.0, 0.0), vec3(1.0), i / 4.0);
if(f < 5.0)
return mix(vec3(1.0, 0.0, 1.0), vec3(1.0), i / 4.0);
if(f < 6.0)
return mix(vec3(0.0, 1.0, 1.0), vec3(1.0), i / 4.0);
if(f < 7.0)
return mix(vec3(1.0, 0.5, 0.0), vec3(1.0), i / 4.0);
if(f < 8.0)
return mix(vec3(1.0, 1.0, 1.0), vec3(1.0), i / 4.0);
return vec3(1.0);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(texCoord.xy * vec2(textureSize(xTex, 0).xy)));
float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1));
float residue = b(pixelCoord) - (-tl - tr - bl - br + 4. * x(pixelCoord));
fragColor = vec4(color_map(residue), 1);
}

View File

@ -0,0 +1,18 @@
#version 300 es
precision highp float;
in vec2 pos;
out vec2 texCoord;
uniform mat4 mvp;
uniform ivec2 gridSize;
void main()
{
float margin = 32.;
float ratio = 1. - 2. * margin / float(gridSize.x);
texCoord = margin / float(gridSize.x) + ratio * (0.5 * (pos + vec2(1, 1)));
gl_Position = mvp * vec4(pos, 0, 1);
}

View File

@ -0,0 +1,12 @@
#version 300 es
precision highp float;
in vec2 pos;
out vec2 texCoord;
void main()
{
texCoord = 0.5 * (pos + vec2(1, 1));
gl_Position = vec4(pos, 0, 1);
}

View File

@ -0,0 +1,41 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D src;
vec2 u(ivec2 coord)
{
return (texelFetch(src, coord, 0).xy);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
if(pixelCoord.x <= 0
|| pixelCoord.x >= textureSize(src, 0).x
|| pixelCoord.y <= 0
|| pixelCoord.y >= textureSize(src, 0).y)
{
fragColor = vec4(0, 0, 0, 1);
}
else
{
vec2 tl = u(pixelCoord + ivec2(-1, 0));
vec2 tr = u(pixelCoord);
vec2 bl = u(pixelCoord + ivec2(-1, -1));
vec2 br = u(pixelCoord + ivec2(0, -1));
float r = (tr.x + br.x) / 2.;
float l = (tl.x + bl.x) / 2.;
float t = (tl.y + tr.y) / 2.;
float b = (bl.y + br.y) / 2.;
fragColor = vec4(-2. * (r - l + t - b), 0, 0, 1);
}
}

View File

@ -0,0 +1,55 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D xTex;
uniform sampler2D bTex;
float x(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
{
return (0.);
}
return (texelFetch(xTex, coord, 0).x);
}
float b(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
{
return (0.);
}
return (texelFetch(bTex, coord, 0).x);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
if(pixelCoord.x <= 0
|| pixelCoord.y <= 0)
{
fragColor = vec4(0, 0, 0, 1);
}
else
{
float tl = x(pixelCoord + ivec2(-1, 1));
float tr = x(pixelCoord + ivec2(1, 1));
float bl = x(pixelCoord + ivec2(-1, -1));
float br = x(pixelCoord + ivec2(1, -1));
float jacobi = (tl + tr + bl + br + b(pixelCoord)) / 4.;
fragColor = vec4(jacobi, 0, 0, 1);
}
}

View File

@ -0,0 +1,53 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D src;
uniform sampler2D error;
uniform float invGridSize;
float e(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(error, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(error, 0).y)
{
return (0.);
}
return (texelFetch(error, coord, 0).x);
}
float p(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(src, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(src, 0).y)
{
return (0.);
}
return (texelFetch(src, coord, 0).x);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
vec2 coarseCoord = vec2(pixelCoord) / 2.;
vec2 offset = fract(coarseCoord);
ivec2 bl = ivec2(floor(coarseCoord));
ivec2 br = bl + ivec2(1, 0);
ivec2 tl = bl + ivec2(0, 1);
ivec2 tr = bl + ivec2(1, 1);
float topLerp = (1. - offset.x) * e(tl) + offset.x * e(tr);
float bottomLerp = (1. - offset.x) * e(bl) + offset.x * e(br);
float bilerpError = (1. - offset.y) * bottomLerp + offset.y * topLerp;
fragColor = vec4(p(pixelCoord) + bilerpError, 0, 0, 1);
}

View File

@ -0,0 +1,61 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D xTex;
uniform sampler2D bTex;
float x(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(xTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(xTex, 0).y)
{
return (0.);
}
return (texelFetch(xTex, coord, 0).x);
}
float b(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(bTex, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(bTex, 0).y)
{
return (0.);
}
return (texelFetch(bTex, coord, 0).x);
}
float residual(ivec2 coord)
{
ivec2 vr = coord + ivec2(1, 0);
ivec2 vl = coord - ivec2(1, 0);
ivec2 vt = coord + ivec2(0, 1);
ivec2 vb = coord - ivec2(0, 1);
return ((x(vl) + x(vr) + x(vt) + x(vb) + b(coord) - 4. * x(coord)) * 4.);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
float restricted = residual(2 * pixelCoord + ivec2(-1, -1))
+ residual(2 * pixelCoord + ivec2(1, -1))
+ residual(2 * pixelCoord + ivec2(1, 1))
+ residual(2 * pixelCoord + ivec2(-1, 1))
+ 2. * residual(2 * pixelCoord + ivec2(-1, 0))
+ 2. * residual(2 * pixelCoord + ivec2(1, 0))
+ 2. * residual(2 * pixelCoord + ivec2(0, -1))
+ 2. * residual(2 * pixelCoord + ivec2(0, 1))
+ 4. * residual(2 * pixelCoord);
restricted /= 16.;
fragColor = vec4(restricted, 0, 0, 1);
}

View File

@ -0,0 +1,29 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D src;
uniform vec2 splatPos;
uniform vec3 splatColor;
uniform float radius;
uniform float additive;
uniform float blending;
uniform float randomize;
void main()
{
float d2 = dot(texCoord - splatPos, texCoord - splatPos);
float intensity = exp(-10. * d2 / radius);
vec2 force = splatColor.xy;
vec3 u = texture(src, texCoord).xyz;
vec3 uAdd = u + intensity * splatColor.xyz;
vec3 uBlend = u * (1. - intensity) + intensity * splatColor;
fragColor = vec4(uAdd * additive + uBlend * blending, 1);
}

View File

@ -0,0 +1,47 @@
#version 300 es
precision highp float;
precision highp sampler2D;
in vec2 texCoord;
out vec4 fragColor;
uniform sampler2D src;
uniform sampler2D pressure;
uniform float invGridSize;
vec2 u(ivec2 coord)
{
return (texelFetch(src, coord, 0).xy);
}
float p(ivec2 coord)
{
if(coord.x <= 0
|| coord.x >= textureSize(pressure, 0).x
|| coord.y <= 0
|| coord.y >= textureSize(pressure, 0).y)
{
return (0.);
}
return (texelFetch(pressure, coord, 0).x);
}
void main()
{
ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy));
float tl = p(pixelCoord + ivec2(0, 1));
float tr = p(pixelCoord + ivec2(1, 1));
float bl = p(pixelCoord);
float br = p(pixelCoord + ivec2(1, 0));
float r = (tr + br) / 2.;
float l = (tl + bl) / 2.;
float t = (tl + tr) / 2.;
float b = (bl + br) / 2.;
vec2 gradP = vec2(r - l, t - b);
fragColor = vec4(u(pixelCoord) - gradP, 0, 1);
}

View File

@ -1,17 +0,0 @@
@echo off
:: compile wasm module
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\cstdlib\include -I ..\..\sdk -I..\..\milepost\ext -I ..\..\milepost -I ..\..\milepost\src
clang %wasmFlags% -o .\module.wasm ..\..\sdk\orca.c ..\..\cstdlib\src\*.c src\main.c
python3 ..\..\scripts\mkapp.py --orca-dir ..\.. --name Pong --icon icon.png --resource-dir data module.wasm

View File

@ -1,33 +0,0 @@
#!/bin/bash
set -euo pipefail
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
CLANG=/usr/local/opt/llvm/bin/clang
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
CLANG=/opt/homebrew/opt/llvm/bin/clang
else
echo "Could not find Homebrew clang; this script will probably not work."
CLANG=clang
fi
STDLIB_DIR=../../cstdlib
ORCA_SDK_DIR=../../sdk
MILEPOST_DIR=../../milepost
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-I $STDLIB_DIR/include \
-I $ORCA_SDK_DIR \
-I $MILEPOST_DIR/ext -I $MILEPOST_DIR -I $MILEPOST_DIR/src"
$CLANG $wasmFlags -o ./module.wasm ../../sdk/orca.c ../../cstdlib/src/*.c src/main.c
python3 ../../scripts/mkapp.py --orca-dir ../.. --name Pong --icon icon.png --resource-dir data module.wasm

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1,465 +0,0 @@
#include <keys.h>
#include <graphics.h>
#include <math.h>
#include <orca.h>
#define NUM_BLOCKS_PER_ROW 7
#define NUM_BLOCKS 42 // 7 * 6
#define BLOCKS_WIDTH 810.0f
#define BLOCK_HEIGHT 30.0f
#define BLOCKS_PADDING 15.0f
#define BLOCKS_BOTTOM 300.0f
const f32 BLOCK_WIDTH = (BLOCKS_WIDTH - ((NUM_BLOCKS_PER_ROW + 1) * BLOCKS_PADDING)) / NUM_BLOCKS_PER_ROW;
#define PADDLE_MAX_LAUNCH_ANGLE 0.7f
const mg_color paddleColor = {1, 0, 0, 1};
mp_rect paddle = {300, 50, 200, 24};
const mg_color ballColor = {1, 1, 0, 1};
mp_rect ball = {200, 200, 20, 20};
vec2 velocity = {5, 5};
// This is upside down from how it will actually be drawn.
int blockHealth[NUM_BLOCKS] = {
0, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1,
2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3,
};
vec2 frameSize = {100, 100};
bool leftDown = false;
bool rightDown = false;
mg_surface surface;
mg_canvas canvas;
mg_image waterImage;
mg_image ballImage;
mg_image paddleImage;
mg_font pongFont;
// TODO(ben): Why is this here? Why isn't it forward-declared by some header?
mg_surface mg_surface_main(void);
f32 lerp(f32 a, f32 b, f32 t);
mp_rect blockRect(int i);
int checkCollision(mp_rect block);
mg_mat2x3 flipY(mp_rect r);
mg_mat2x3 flipYAt(vec2 pos);
str8 loadFile(mem_arena* arena, str8 filename) {
file_handle file = file_open(filename, FILE_ACCESS_READ, 0);
if(file_last_error(file) != IO_OK)
{
log_error("Couldn't open file %s\n", str8_to_cstring(mem_scratch(), filename));
}
u64 size = file_size(file);
char* buffer = mem_arena_alloc(arena, size);
file_read(file, size, buffer);
file_close(file);
return str8_from_buffer(size, buffer);
}
ORCA_EXPORT void OnInit(void)
{
surface = mg_surface_main();
canvas = mg_canvas_create();
waterImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/underwater.jpg")), false);
ballImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/ball.png")), false);
paddleImage = mg_image_create_from_data(surface, loadFile(mem_scratch(), STR8("/wall.png")), false);
if(mg_image_is_nil(waterImage))
{
log_error("coulnd't load ball image\n");
}
if(mg_image_is_nil(ballImage))
{
log_error("coulnd't load ball image\n");
}
if(mg_image_is_nil(paddleImage))
{
log_error("coulnd't load paddle image\n");
}
str8 fontStr = loadFile(mem_scratch(), STR8("/Literata-SemiBoldItalic.ttf"));
unicode_range ranges[5] = {UNICODE_RANGE_BASIC_LATIN,
UNICODE_RANGE_C1_CONTROLS_AND_LATIN_1_SUPPLEMENT,
UNICODE_RANGE_LATIN_EXTENDED_A,
UNICODE_RANGE_LATIN_EXTENDED_B,
UNICODE_RANGE_SPECIALS};
// NOTE(ben): Weird that images are "create from data" but fonts are "create from memory"
// TODO: Decide whether we're using strings or explicit pointer + length
pongFont = mg_font_create_from_memory(fontStr.len, (byte*)fontStr.ptr, 5, ranges);
mem_arena_clear(mem_scratch());
}
ORCA_EXPORT void OnFrameResize(u32 width, u32 height)
{
log_info("frame resize %u, %u", width, height);
frameSize.x = width;
frameSize.y = height;
}
ORCA_EXPORT void OnMouseDown(int button)
{
log_info("mouse down!");
}
ORCA_EXPORT void OnKeyDown(int key)
{
if(key == KEY_SPACE)
{
log_error("(this is just for testing errors)");
return;
}
if(key == KEY_ENTER)
{
log_warning("(this is just for testing warning)");
return;
}
log_info("key down: %i", key);
if(key == KEY_LEFT)
{
leftDown = true;
}
if(key == KEY_RIGHT)
{
rightDown = true;
}
}
ORCA_EXPORT void OnKeyUp(int key)
{
if(key == KEY_ENTER || key == KEY_SPACE)
{
return;
}
log_info("key up: %i", key);
if(key == KEY_LEFT)
{
leftDown = false;
}
if(key == KEY_RIGHT)
{
rightDown = false;
}
}
ORCA_EXPORT void OnFrameRefresh(void)
{
f32 aspect = frameSize.x/frameSize.y;
if(leftDown)
{
paddle.x -= 10;
}
else if(rightDown)
{
paddle.x += 10;
}
paddle.x = Clamp(paddle.x, 0, frameSize.x - paddle.w);
ball.x += velocity.x;
ball.y += velocity.y;
ball.x = Clamp(ball.x, 0, frameSize.x - ball.w);
ball.y = Clamp(ball.y, 0, frameSize.y - ball.h);
if (ball.x + ball.w >= frameSize.x) {
velocity.x = -velocity.x;
}
if (ball.x <= 0) {
velocity.x = -velocity.x;
}
if (ball.y + ball.h >= frameSize.y) {
velocity.y = -velocity.y;
}
if (
ball.y <= paddle.y + paddle.h
&& ball.x+ball.w >= paddle.x
&& ball.x <= paddle.x + paddle.w
&& velocity.y < 0
) {
f32 t = ((ball.x + ball.w/2) - paddle.x) / paddle.w;
f32 launchAngle = lerp(-PADDLE_MAX_LAUNCH_ANGLE, PADDLE_MAX_LAUNCH_ANGLE, t);
f32 speed = sqrtf(velocity.x*velocity.x + velocity.y*velocity.y);
velocity = (vec2){
sinf(launchAngle) * speed,
cosf(launchAngle) * speed,
};
ball.y = paddle.y + paddle.h;
log_info("PONG!");
}
if (ball.y <= 0) {
ball.x = frameSize.x/2. - ball.w;
ball.y = frameSize.y/2. - ball.h;
}
for (int i = 0; i < NUM_BLOCKS; i++) {
if (blockHealth[i] <= 0) {
continue;
}
mp_rect r = blockRect(i);
int result = checkCollision(r);
if (result) {
log_info("Collision! direction=%d", result);
blockHealth[i] -= 1;
f32 vx = velocity.x;
f32 vy = velocity.y;
switch (result) {
case 1:
case 5:
velocity.y = -vy;
break;
case 3:
case 7:
velocity.x = -vx;
break;
case 2:
case 6:
velocity.x = -vy;
velocity.y = -vx;
break;
case 4:
case 8:
velocity.x = vy;
velocity.y = vx;
break;
}
}
}
mg_canvas_set_current(canvas);
mg_set_color_rgba(10.0f/255.0f, 31.0f/255.0f, 72.0f/255.0f, 1);
mg_clear();
mg_image_draw(waterImage, (mp_rect){0, 0, frameSize.x, frameSize.y});
mg_mat2x3 yUp = {
1, 0, 0,
0, -1, frameSize.y,
};
mg_matrix_push(yUp);
{
for (int i = 0; i < NUM_BLOCKS; i++) {
if (blockHealth[i] <= 0) {
continue;
}
mp_rect r = blockRect(i);
mg_set_color_rgba(0, 0, 0, 0.2);
mg_rounded_rectangle_fill(r.x, r.y-2, r.w, r.h, 4);
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
mg_rounded_rectangle_fill(r.x, r.y, r.w, r.h, 4);
int fontSize = 18;
str8 text = str8_pushf(mem_scratch(),
"%d", blockHealth[i]
);
mp_rect textRect = mg_text_bounding_box(pongFont, fontSize, text);
vec2 textPos = {
r.x + r.w/2 - textRect.w/2,
r.y + 9, // TODO: mg_text_bounding_box is returning extremely wack results for height.
};
mg_set_color_rgba(0, 0, 0, 1);
mg_set_font(pongFont);
mg_set_font_size(18);
mg_move_to(textPos.x, textPos.y);
mg_matrix_push(flipYAt(textPos));
{
mg_text_outlines(text);
mg_fill();
}
mg_matrix_pop();
}
mg_set_color_rgba(0.9, 0.9, 0.9, 1);
mg_rounded_rectangle_fill(paddle.x, paddle.y, paddle.w, paddle.h, 4);
mg_matrix_push(flipY(ball));
{
mg_image_draw(ballImage, ball);
}
mg_matrix_pop();
}
mg_matrix_pop();
mg_surface_prepare(surface);
mg_render(surface, canvas);
mg_surface_present(surface);
}
mp_rect blockRect(int i) {
int row = i / NUM_BLOCKS_PER_ROW;
int col = i % NUM_BLOCKS_PER_ROW;
return (mp_rect){
BLOCKS_PADDING + (BLOCKS_PADDING + BLOCK_WIDTH) * col,
BLOCKS_BOTTOM + (BLOCKS_PADDING + BLOCK_HEIGHT) * row,
BLOCK_WIDTH,
BLOCK_HEIGHT
};
}
// Returns a cardinal direction 1-8 for the collision with the block, or zero
// if no collision. 1 is straight up and directions proceed clockwise.
int checkCollision(mp_rect block) {
// Note that all the logic for this game has the origin in the bottom left.
f32 ballx2 = ball.x + ball.w;
f32 bally2 = ball.y + ball.h;
f32 blockx2 = block.x + block.w;
f32 blocky2 = block.y + block.h;
if (
ballx2 < block.x
|| blockx2 < ball.x
|| bally2 < block.y
|| blocky2 < ball.y
) {
// Ball is fully outside block
return 0;
}
// if (
// (block.x <= ball.x && ballx2 <= blockx2)
// && (block.y <= ball.y && bally2 <= blocky2)
// ) {
// // Ball is fully inside block; do not consider as a collision
// return 0;
// }
// If moving right, the ball can bounce off its top right corner, right
// side, or bottom right corner. Corner bounces occur if the block's bottom
// left corner is in the ball's top right quadrant, or if the block's top
// left corner is in the ball's bottom left quadrant. Otherwise, an edge
// bounce occurs if the block's left edge falls in either of the ball's
// right quadrants.
//
// This logic generalizes to other directions.
//
// We assume significant tunneling can't happen.
vec2 ballCenter = (vec2){ball.x + ball.w/2, ball.y + ball.h/2};
vec2 blockCenter = (vec2){block.x + block.w/2, block.y + block.h/2};
// Moving right
if (velocity.x > 0) {
// Ball's top right corner
if (
ballCenter.x <= block.x && block.x <= ballx2
&& ballCenter.y <= block.y && block.y <= bally2
) { return 2; }
// Ball's bottom right corner
if (
ballCenter.x <= block.x && block.x <= ballx2
&& ball.y <= blocky2 && blocky2 <= ballCenter.y
) { return 4; }
// Ball's right edge
if (
ballCenter.x <= block.x && block.x <= ballx2
) { return 3; }
}
// Moving up
if (velocity.y > 0) {
// Ball's top left corner
if (
ball.x <= blockx2 && blockx2 <= ballCenter.x
&& ballCenter.y <= block.y && block.y <= bally2
) { return 8; }
// Ball's top right corner
if (
ballCenter.x <= block.x && block.x <= ballx2
&& ballCenter.y <= block.y && block.y <= bally2
) { return 2; }
// Ball's top edge
if (
ballCenter.y <= block.y && block.y <= bally2
) { return 1; }
}
// Moving left
if (velocity.x < 0) {
// Ball's bottom left corner
if (
ball.x <= blockx2 && blockx2 <= ballCenter.x
&& ball.y <= blocky2 && blocky2 <= ballCenter.y
) { return 6; }
// Ball's top left corner
if (
ball.x <= blockx2 && blockx2 <= ballCenter.x
&& ballCenter.y <= block.y && block.y <= bally2
) { return 8; }
// Ball's left edge
if (
ball.x <= blockx2 && blockx2 <= ballCenter.x
) { return 7; }
}
// Moving down
if (velocity.y < 0) {
// Ball's bottom right corner
if (
ballCenter.x <= block.x && block.x <= ballx2
&& ball.y <= blocky2 && blocky2 <= ballCenter.y
) { return 4; }
// Ball's bottom left corner
if (
ball.x <= blockx2 && blockx2 <= ballCenter.x
&& ball.y <= blocky2 && blocky2 <= ballCenter.y
) { return 6; }
// Ball's bottom edge
if (
ball.y <= blocky2 && blocky2 <= ballCenter.y
) { return 5; }
}
return 0;
}
f32 lerp(f32 a, f32 b, f32 t) {
return (1 - t) * a + t * b;
}
mg_mat2x3 flipY(mp_rect r) {
return (mg_mat2x3){
1, 0, 0,
0, -1, 2 * r.y + r.h,
};
}
mg_mat2x3 flipYAt(vec2 pos) {
return (mg_mat2x3){
1, 0, 0,
0, -1, 2 * pos.y,
};
}

3
samples/triangle/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Triangle
profile.dtrace
profile.spall

View File

@ -0,0 +1,39 @@
@echo off
setlocal enabledelayedexpansion
:: The following code checks if you have the necessary programs to compile the samples.
:: This code exists to improve the experience of first-time Orca users and can
:: be safely deleted in your own projects if you wish.
if exist "..\..\scripts\sample_build_check.py" (
python ..\..\scripts\sample_build_check.py
if !ERRORLEVEL! neq 0 exit /b 1
) else (
echo Could not check if you have the necessary tools to build the Orca samples.
echo If you have copied this script to your own project, you can delete this code.
)
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: common flags to build wasm modules
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
:: build orca core as wasm module
clang %wasmFlags% -Wl,--relocatable -o .\liborca.a %ORCA_DIR%\src\orca.c %ORCA_DIR%\src\libc-shim\src\*.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: build sample as wasm module and link it with the orca module
clang %wasmFlags% -L . -lorca -o module.wasm src/main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: create app directory and copy files into it
orca bundle --orca-dir %ORCA_DIR% --name Triangle --icon icon.png module.wasm

37
samples/triangle/build.sh Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
set -euo pipefail
# The following code checks if you have the necessary programs to compile the samples.
# This code exists to improve the experience of first-time Orca users and can
# be safely deleted in your own projects if you wish.
if [ -f ../../scripts/sample_build_check.py ]; then
python3 ../../scripts/sample_build_check.py
else
echo "Could not check if you have the necessary tools to build the Orca samples."
echo "If you have copied this script to your own project, you can delete this code."
fi
ORCA_DIR=../..
STDLIB_DIR=$ORCA_DIR/src/libc-shim
# common flags to build wasm modules
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
# build orca core as wasm module
clang $wasmFlags -Wl,--relocatable -o ./liborca.a $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c
# build sample as wasm module and link it with the orca module
clang $wasmFlags -L . -lorca -o module.wasm src/main.c
# create app directory and copy files into it
orca bundle --orca-dir $ORCA_DIR --name Triangle module.wasm

121
samples/triangle/src/main.c Normal file
View File

@ -0,0 +1,121 @@
/*************************************************************************
*
* Orca
* Copyright 2023 Martin Fouilleul and the Orca project contributors
* See LICENSE.txt for licensing information
*
**************************************************************************/
#include <math.h>
#include <orca.h>
oc_vec2 frameSize = { 100, 100 };
oc_surface surface;
unsigned int program;
const char* vshaderSource =
"attribute vec4 vPosition;\n"
"uniform mat4 transform;\n"
"void main()\n"
"{\n"
" gl_Position = transform*vPosition;\n"
"}\n";
const char* fshaderSource =
"precision mediump float;\n"
"void main()\n"
"{\n"
" gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"}\n";
void compile_shader(GLuint shader, const char* source)
{
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
int err = glGetError();
if(err)
{
oc_log_info("gl error");
}
}
ORCA_EXPORT void oc_on_init(void)
{
oc_window_set_title(OC_STR8("triangle"));
surface = oc_surface_gles();
oc_surface_select(surface);
const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
oc_log_info("GLES extensions: %s\n", extensions);
int extensionCount = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount);
for(int i = 0; i < extensionCount; i++)
{
const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
oc_log_info("GLES extension %i: %s\n", i, extension);
}
unsigned int vshader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fshader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
compile_shader(vshader, vshaderSource);
compile_shader(fshader, fshaderSource);
glAttachShader(program, vshader);
glAttachShader(program, fshader);
glLinkProgram(program);
glUseProgram(program);
GLfloat vertices[] = {
-0.866 / 2, -0.5 / 2, 0, 0.866 / 2, -0.5 / 2, 0, 0, 0.5, 0
};
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(GLfloat), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
}
ORCA_EXPORT void oc_on_resize(u32 width, u32 height)
{
oc_log_info("frame resize %u, %u", width, height);
frameSize.x = width;
frameSize.y = height;
}
ORCA_EXPORT void oc_on_frame_refresh(void)
{
f32 aspect = frameSize.x / frameSize.y;
oc_surface_select(surface);
glClearColor(0, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
static float alpha = 0;
oc_vec2 scaling = oc_surface_contents_scaling(surface);
glViewport(0, 0, frameSize.x * scaling.x, frameSize.y * scaling.y);
GLfloat matrix[] = { cosf(alpha) / aspect, sinf(alpha), 0, 0,
-sinf(alpha) / aspect, cosf(alpha), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1 };
alpha += 2 * M_PI / 120;
glUniformMatrix4fv(0, 1, false, matrix);
glDrawArrays(GL_TRIANGLES, 0, 3);
oc_surface_present(surface);
}

View File

@ -1,17 +1,39 @@
@echo off
setlocal enabledelayedexpansion
:: compile wasm module
:: The following code checks if you have the necessary programs to compile the samples.
:: This code exists to improve the experience of first-time Orca users and can
:: be safely deleted in your own projects if you wish.
if exist "..\..\scripts\sample_build_check.py" (
python ..\..\scripts\sample_build_check.py
if !ERRORLEVEL! neq 0 exit /b 1
) else (
echo Could not check if you have the necessary tools to build the Orca samples.
echo If you have copied this script to your own project, you can delete this code.
)
set ORCA_DIR=..\..
set STDLIB_DIR=%ORCA_DIR%\src\libc-shim
:: common flags to build wasm modules
set wasmFlags=--target=wasm32^
--no-standard-libraries ^
-fno-builtin ^
-mbulk-memory ^
-g -O2 ^
-D__ORCA__ ^
-Wl,--no-entry ^
-Wl,--export-dynamic ^
-g ^
-O2 ^
-mbulk-memory ^
-D__ORCA__ ^
-isystem ..\..\cstdlib\include -I ..\..\sdk -I..\..\milepost\ext -I ..\..\milepost -I ..\..\milepost\src
-isystem %STDLIB_DIR%\include ^
-I%ORCA_DIR%\src ^
-I%ORCA_DIR%\src\ext
clang %wasmFlags% -o .\module.wasm ..\..\sdk\orca.c ..\..\cstdlib\src\*.c src\main.c
:: build orca core as wasm module
clang %wasmFlags% -Wl,--relocatable -o .\liborca.a %ORCA_DIR%\src\orca.c %ORCA_DIR%\src\libc-shim\src\*.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
python3 ..\..\scripts\mkapp.py --orca-dir ..\.. --name UI --resource-dir data module.wasm
:: build sample as wasm module and link it with the orca module
clang %wasmFlags% -L . -lorca -o .\module.wasm src\main.c
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
:: create app directory and copy files into it
orca bundle --orca-dir %ORCA_DIR% --name UI --resource-dir data module.wasm

38
samples/ui/build.sh Normal file → Executable file
View File

@ -2,26 +2,36 @@
set -euo pipefail
if [[ -x /usr/local/opt/llvm/bin/clang ]]; then
CLANG=/usr/local/opt/llvm/bin/clang
elif [[ -x /opt/homebrew/opt/llvm/bin/clang ]]; then
CLANG=/opt/homebrew/opt/llvm/bin/clang
# The following code checks if you have the necessary programs to compile the samples.
# This code exists to improve the experience of first-time Orca users and can
# be safely deleted in your own projects if you wish.
if [ -f ../../scripts/sample_build_check.py ]; then
python3 ../../scripts/sample_build_check.py
else
echo "Could not find Homebrew clang; this script will probably not work."
CLANG=clang
echo "Could not check if you have the necessary tools to build the Orca samples."
echo "If you have copied this script to your own project, you can delete this code."
fi
ORCA_DIR=../..
STDLIB_DIR=$ORCA_DIR/src/libc-shim
# common flags to build wasm modules
wasmFlags="--target=wasm32 \
--no-standard-libraries \
-fno-builtin \
-mbulk-memory \
-g -O2 \
-D__ORCA__ \
-Wl,--no-entry \
-Wl,--export-dynamic \
-g \
-O2 \
-mbulk-memory \
-D__ORCA__ \
-isystem ../../cstdlib/include -I ../../sdk -I../../milepost/ext -I ../../milepost -I ../../milepost/src"
-isystem $STDLIB_DIR/include \
-I $ORCA_DIR/src \
-I $ORCA_DIR/src/ext"
$CLANG $wasmFlags -o ./module.wasm ../../sdk/orca.c ../../cstdlib/src/*.c src/main.c
# build orca core as wasm module
clang $wasmFlags -Wl,--relocatable -o ./liborca.a $ORCA_DIR/src/orca.c $STDLIB_DIR/src/*.c
python3 ../../scripts/mkapp.py --orca-dir ../.. --name UI --resource-dir data module.wasm
# build sample as wasm module and link it with the orca module
clang $wasmFlags -L . -lorca -o module.wasm src/main.c
# create app directory and copy files into it
orca bundle --orca-dir $ORCA_DIR --name UI --resource-dir data module.wasm

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More