From ceae5e2fe04dd05b80698131e622501bee67ba02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Sun, 19 Nov 2023 13:07:28 +0100 Subject: [PATCH] sync fwk --- MAKE.bat | 8 +- demos/01-demo2d.c | 6 +- demos/01-ui.c | 86 + demos/06-scene.c | 216 + demos/99-controller.c | 280 + demos/99-lod.c | 234 + demos/99-spine.c | 13 +- demos/99-sprite.c | 218 + demos/99-sprite2.c | 118 + .../art/editor}/fx/editorOutline.fs | 0 .../art => engine/art/editor}/icons/logo.ai | 0 .../art => engine/art/editor}/icons/logo.ico | Bin .../art/editor}/icons/logo.license | 0 .../art => engine/art/editor}/icons/logo.png | Bin .../editor}/icons/scale-ruler-icon.license | 0 .../art/editor}/icons/scale-ruler-icon.png | Bin .../art/editor}/icons/scale-ruler-icon.svg | 0 .../art/editor}/lite/data/core/command.lua | 0 .../lite/data/core/commands/command.lua | 0 .../editor}/lite/data/core/commands/core.lua | 0 .../editor}/lite/data/core/commands/doc.lua | 0 .../lite/data/core/commands/findreplace.lua | 0 .../editor}/lite/data/core/commands/root.lua | 0 .../editor}/lite/data/core/commandview.lua | 0 .../art/editor}/lite/data/core/common.lua | 0 .../art/editor}/lite/data/core/config.lua | 0 .../lite/data/core/doc/highlighter.lua | 0 .../art/editor}/lite/data/core/doc/init.lua | 0 .../art/editor}/lite/data/core/doc/search.lua | 0 .../editor}/lite/data/core/doc/translate.lua | 0 .../art/editor}/lite/data/core/docview.lua | 0 .../art/editor}/lite/data/core/init.lua | 0 .../art/editor}/lite/data/core/keymap.lua | 0 .../art/editor}/lite/data/core/logview.lua | 0 .../art/editor}/lite/data/core/node.lua | 0 .../art/editor}/lite/data/core/object.lua | 0 .../art/editor}/lite/data/core/rootview.lua | 0 .../art/editor}/lite/data/core/statusview.lua | 0 .../art/editor}/lite/data/core/strict.lua | 0 .../art/editor}/lite/data/core/style.lua | 0 .../art/editor}/lite/data/core/syntax.lua | 0 .../art/editor}/lite/data/core/tokenizer.lua | 0 .../art/editor}/lite/data/core/view.lua | 0 .../art/editor}/lite/data/fonts/font.ttf | Bin .../art/editor}/lite/data/fonts/icons.ttf | Bin .../art/editor}/lite/data/fonts/monospace.ttf | Bin .../lite/data/languages/language_bat.lua | 0 .../lite/data/languages/language_batch.lua | 0 .../lite/data/languages/language_c.lua | 0 .../lite/data/languages/language_cpp.lua | 0 .../lite/data/languages/language_csharp.lua | 0 .../lite/data/languages/language_css.lua | 0 .../lite/data/languages/language_glsl.lua | 0 .../lite/data/languages/language_hlsl.lua | 0 .../lite/data/languages/language_js.lua | 0 .../lite/data/languages/language_lua.lua | 0 .../lite/data/languages/language_md.lua | 0 .../lite/data/languages/language_moon.lua | 0 .../lite/data/languages/language_nim.lua | 0 .../lite/data/languages/language_odin.lua | 0 .../lite/data/languages/language_python.lua | 0 .../lite/data/languages/language_teal.lua | 0 .../lite/data/languages/language_ts.lua | 0 .../lite/data/languages/language_wren.lua | 0 .../lite/data/languages/language_xml.lua | 0 .../art/editor}/lite/data/lite.license | 0 .../art/editor}/lite/data/lite.readme | 0 .../art/editor}/lite/data/lite.usage | 0 .../editor/lite/data/plugins/autocomplete.lua | 284 + .../editor}/lite/data/plugins/autoinsert.lua | 0 .../editor/lite/data/plugins/autoreload.lua | 61 + .../editor}/lite/data/plugins/autowrap.lua | 0 .../lite/data/plugins/bracketmatch.lua | 0 .../lite/data/plugins/closeconfirmx.lua | 0 .../lite/data/plugins/colorpreview.lua | 0 .../art/editor}/lite/data/plugins/console.lua | 0 .../editor}/lite/data/plugins/contextmenu.lua | 0 .../lite/data/plugins/detectindent.lua | 0 .../lite/data/plugins/drawwhitespace.lua | 0 .../editor}/lite/data/plugins/eofnewline.lua | 0 .../art/editor}/lite/data/plugins/fsutils.lua | 0 .../editor}/lite/data/plugins/indentguide.lua | 0 .../lite/data/plugins/lfautoinsert.lua | 0 .../editor}/lite/data/plugins/lineguide.lua | 0 .../art/editor}/lite/data/plugins/macro.lua | 0 .../art/editor}/lite/data/plugins/markers.lua | 0 .../art/editor}/lite/data/plugins/minimap.lua | 0 .../editor}/lite/data/plugins/motiontrail.lua | 0 .../lite/data/plugins/openfilelocation.lua | 0 .../lite/data/plugins/projectsearch.lua | 0 .../art/editor}/lite/data/plugins/quote.lua | 0 .../lite/data/plugins/rainbowparen.lua | 0 .../art/editor}/lite/data/plugins/reflow.lua | 0 .../art/editor}/lite/data/plugins/scale.lua | 0 .../editor}/lite/data/plugins/scalestatus.lua | 0 .../lite/data/plugins/selectionhighlight.lua | 0 .../art/editor}/lite/data/plugins/sort.lua | 0 .../editor}/lite/data/plugins/tabularize.lua | 0 .../lite/data/plugins/todotreeview.lua | 0 .../editor}/lite/data/plugins/treeview.lua | 0 .../lite/data/plugins/trimwhitespace.lua | 0 .../editor}/lite/data/plugins/workspace.lua | 0 .../art/editor}/lite/data/themes/abyss.lua | 0 .../editor}/lite/data/themes/cold_lime.lua | 0 .../art/editor}/lite/data/themes/dracula.lua | 0 .../art/editor}/lite/data/themes/duorand.lua | 0 .../art/editor}/lite/data/themes/duotone.lua | 0 .../art/editor}/lite/data/themes/fall.lua | 0 .../art/editor}/lite/data/themes/fwk.lua | 0 .../art/editor}/lite/data/themes/github.lua | 0 .../editor}/lite/data/themes/gruvbox_dark.lua | 0 .../art/editor}/lite/data/themes/liqube.lua | 0 .../art/editor}/lite/data/themes/moe.lua | 0 .../art/editor}/lite/data/themes/monodark.lua | 0 .../art/editor}/lite/data/themes/monokai.lua | 0 .../art/editor}/lite/data/themes/nord.lua | 0 .../art/editor}/lite/data/themes/onedark.lua | 0 .../editor}/lite/data/themes/only_dark.lua | 0 .../lite/data/themes/solarized_light.lua | 0 .../art/editor}/lite/data/themes/solarobj.lua | 0 .../art/editor}/lite/data/themes/summer.lua | 0 .../editor}/lite/data/themes/vscode-dark.lua | 0 .../art/editor}/lite/data/themes/winter.lua | 0 .../art/editor}/lite/data/themes/zenburn.lua | 0 .../art/editor}/lite/data/user/init.lua | 2 +- .../materialdesignicons-webfont.license | 0 .../editor}/materialdesignicons-webfont.ttf | Bin {tools => engine/art}/editor/plugins/.gitkeep | 0 .../art/editor}/scripts/inspect.lua | 0 {tools/editor => engine}/editor.c | 40 +- engine/joint/v4k.h | 20592 ++++++++++++++-- engine/split/3rd_base64.h | 10 +- {tools/editor => engine/split}/3rd_icon_mdi.h | 0 {tools/editor => engine/split}/3rd_lite.h | 36 +- {tools/editor => engine/split}/3rd_lite_sys.h | 10 + .../split}/3rd_lite_sys_gleq.h | 0 engine/split/3rd_lua.h | 1731 +- engine/split/3rd_rpmalloc.c | 3629 +++ engine/split/3rd_rpmalloc.h | 373 + engine/split/3rd_rpmalloci.c | 488 + engine/split/v4k.c.inl | 15 +- engine/split/v4k.h.inl | 8 +- engine/split/v4k.x.inl | 19 + engine/split/v4k_cook.c | 9 +- engine/split/v4k_editor.c | 1290 +- engine/split/v4k_editor.h | 20 +- engine/split/v4k_editor0.c | 532 + .../split/v4k_editor_browser.h | 0 .../split/v4k_editor_console.h | 0 .../split/v4k_editor_nodes.h | 0 .../split/v4k_editor_scene.h | 2 - .../split/v4k_editor_script.h | 21 - .../split/v4k_editor_timeline.h | 0 engine/split/v4k_file.c | 2 +- engine/split/v4k_main.c | 2 +- engine/split/v4k_memory.c | 13 +- engine/split/v4k_obj.h | 14 + engine/split/v4k_pack.h | 30 +- engine/split/v4k_render.c | 1104 - engine/split/v4k_render.h | 76 - engine/split/v4k_sprite.c | 1466 ++ engine/split/v4k_sprite.h | 114 + engine/split/v4k_string.c | 149 + engine/split/v4k_string.h | 17 + engine/split/v4k_system.c | 8 +- engine/split/v4k_ui.c | 22 +- engine/split/v4k_window.c | 2 +- engine/v4k | 15057 ++++++++++- engine/v4k.c | 5143 +++- engine/v4k.h | 392 +- hello.c | 23 +- tools/3rd_delaunay.h | 1059 + tools/3rd_sproutline.h | 441 + tools/3rd_stb_image_resize.h | 2634 ++ tools/3rd_stb_rect_pack.h | 623 + tools/ark.linux | Bin 0 -> 13424 bytes tools/ase2ini.c | 8 +- tools/ase2ini.linux | Bin 0 -> 333040 bytes tools/ass2iqe.c | 49 +- tools/cook.c | 14 +- tools/cook.exe | Bin 5874688 -> 5855744 bytes tools/cook.ini | 6 +- tools/cook.linux | Bin 4029624 -> 4310840 bytes tools/cook.osx | Bin 9411016 -> 4139720 bytes tools/editor/v4k_editor.h | 750 - tools/editor/v4k_sprite.c | 455 - tools/join.py | 2 +- tools/{editor/labs.osc => labs}/MAKE.bat | 8 +- tools/labs/cmder.c | 42 + tools/labs/dll.c | 16 + tools/{editor/labs.vm => labs}/ecs.c | 0 tools/{editor => labs}/editor.h | 3 +- tools/{editor/labs.vm => labs}/fwk_diff.md | 0 tools/{editor/labs.vm => labs}/fwk_obj.c | 0 tools/{editor/labs.vm => labs}/hybrid-p2p.md | 0 tools/{editor/labs.meta => labs}/meta_dna.c | 0 tools/{editor/labs.meta => labs}/meta_info.c | 2 +- tools/{editor/labs.meta => labs}/meta_tool.c | 4 +- tools/labs/mt.c | 137 + tools/{editor/labs.vm => labs}/netproto.md | 0 tools/{editor => labs}/objtests.h | 0 tools/{editor/labs.osc => labs}/oscedit.c | 2 +- tools/{editor/labs.osc => labs}/oscedit.h | 0 tools/{editor/labs.osc => labs}/oscgame.c | 2 +- tools/{editor/labs.osc => labs}/osclab1.c | 2 +- tools/{editor/labs.osc => labs}/osclab2.c | 2 +- tools/{editor/labs.osc => labs}/oscpack.h | 0 tools/{editor/labs.osc => labs}/oscrecv.h | 0 tools/{editor/labs.osc => labs}/oscsend.c | 2 +- tools/{editor/labs.osc => labs}/oscsend.h | 0 tools/{editor => labs}/stdio2.c | 4 +- tools/luajit_make_bindings.lua | 14 +- tools/{editor => }/windows.ini | 0 213 files changed, 51818 insertions(+), 8448 deletions(-) create mode 100644 demos/01-ui.c create mode 100644 demos/06-scene.c create mode 100644 demos/99-controller.c create mode 100644 demos/99-lod.c create mode 100644 demos/99-sprite.c create mode 100644 demos/99-sprite2.c rename {tools/editor/art => engine/art/editor}/fx/editorOutline.fs (100%) rename {tools/editor/art => engine/art/editor}/icons/logo.ai (100%) rename {tools/editor/art => engine/art/editor}/icons/logo.ico (100%) rename {tools/editor/art => engine/art/editor}/icons/logo.license (100%) rename {tools/editor/art => engine/art/editor}/icons/logo.png (100%) rename {tools/editor/art => engine/art/editor}/icons/scale-ruler-icon.license (100%) rename {tools/editor/art => engine/art/editor}/icons/scale-ruler-icon.png (100%) rename {tools/editor/art => engine/art/editor}/icons/scale-ruler-icon.svg (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/command.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commands/command.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commands/core.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commands/doc.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commands/findreplace.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commands/root.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/commandview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/common.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/config.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/doc/highlighter.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/doc/init.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/doc/search.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/doc/translate.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/docview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/init.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/keymap.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/logview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/node.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/object.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/rootview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/statusview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/strict.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/style.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/syntax.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/tokenizer.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/core/view.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/fonts/font.ttf (100%) rename {tools/editor/art => engine/art/editor}/lite/data/fonts/icons.ttf (100%) rename {tools/editor/art => engine/art/editor}/lite/data/fonts/monospace.ttf (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_bat.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_batch.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_c.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_cpp.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_csharp.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_css.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_glsl.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_hlsl.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_js.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_lua.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_md.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_moon.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_nim.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_odin.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_python.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_teal.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_ts.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_wren.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/languages/language_xml.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/lite.license (100%) rename {tools/editor/art => engine/art/editor}/lite/data/lite.readme (100%) rename {tools/editor/art => engine/art/editor}/lite/data/lite.usage (100%) create mode 100644 engine/art/editor/lite/data/plugins/autocomplete.lua rename {tools/editor/art => engine/art/editor}/lite/data/plugins/autoinsert.lua (100%) create mode 100644 engine/art/editor/lite/data/plugins/autoreload.lua rename {tools/editor/art => engine/art/editor}/lite/data/plugins/autowrap.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/bracketmatch.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/closeconfirmx.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/colorpreview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/console.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/contextmenu.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/detectindent.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/drawwhitespace.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/eofnewline.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/fsutils.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/indentguide.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/lfautoinsert.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/lineguide.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/macro.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/markers.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/minimap.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/motiontrail.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/openfilelocation.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/projectsearch.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/quote.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/rainbowparen.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/reflow.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/scale.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/scalestatus.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/selectionhighlight.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/sort.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/tabularize.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/todotreeview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/treeview.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/trimwhitespace.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/plugins/workspace.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/abyss.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/cold_lime.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/dracula.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/duorand.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/duotone.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/fall.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/fwk.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/github.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/gruvbox_dark.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/liqube.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/moe.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/monodark.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/monokai.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/nord.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/onedark.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/only_dark.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/solarized_light.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/solarobj.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/summer.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/vscode-dark.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/winter.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/themes/zenburn.lua (100%) rename {tools/editor/art => engine/art/editor}/lite/data/user/init.lua (88%) rename {tools/editor/art => engine/art/editor}/materialdesignicons-webfont.license (100%) rename {tools/editor/art => engine/art/editor}/materialdesignicons-webfont.ttf (100%) rename {tools => engine/art}/editor/plugins/.gitkeep (100%) rename {tools/editor/art => engine/art/editor}/scripts/inspect.lua (100%) rename {tools/editor => engine}/editor.c (90%) rename {tools/editor => engine/split}/3rd_icon_mdi.h (100%) rename {tools/editor => engine/split}/3rd_lite.h (97%) rename {tools/editor => engine/split}/3rd_lite_sys.h (94%) rename {tools/editor => engine/split}/3rd_lite_sys_gleq.h (100%) create mode 100644 engine/split/3rd_rpmalloc.c create mode 100644 engine/split/3rd_rpmalloc.h create mode 100644 engine/split/3rd_rpmalloci.c create mode 100644 engine/split/v4k_editor0.c rename tools/editor/v4k_editor2_browser.h => engine/split/v4k_editor_browser.h (100%) rename tools/editor/v4k_editor4_console.h => engine/split/v4k_editor_console.h (100%) rename tools/editor/v4k_editor5_nodes.h => engine/split/v4k_editor_nodes.h (100%) rename tools/editor/v4k_editor1_scene.h => engine/split/v4k_editor_scene.h (99%) rename tools/editor/v4k_editor6_script.h => engine/split/v4k_editor_script.h (74%) rename tools/editor/v4k_editor3_timeline.h => engine/split/v4k_editor_timeline.h (100%) create mode 100644 engine/split/v4k_sprite.c create mode 100644 engine/split/v4k_sprite.h create mode 100644 tools/3rd_delaunay.h create mode 100644 tools/3rd_sproutline.h create mode 100644 tools/3rd_stb_image_resize.h create mode 100644 tools/3rd_stb_rect_pack.h create mode 100644 tools/ark.linux create mode 100644 tools/ase2ini.linux delete mode 100644 tools/editor/v4k_editor.h delete mode 100644 tools/editor/v4k_sprite.c rename tools/{editor/labs.osc => labs}/MAKE.bat (63%) create mode 100644 tools/labs/cmder.c create mode 100644 tools/labs/dll.c rename tools/{editor/labs.vm => labs}/ecs.c (100%) rename tools/{editor => labs}/editor.h (99%) rename tools/{editor/labs.vm => labs}/fwk_diff.md (100%) rename tools/{editor/labs.vm => labs}/fwk_obj.c (100%) rename tools/{editor/labs.vm => labs}/hybrid-p2p.md (100%) rename tools/{editor/labs.meta => labs}/meta_dna.c (100%) rename tools/{editor/labs.meta => labs}/meta_info.c (99%) rename tools/{editor/labs.meta => labs}/meta_tool.c (97%) create mode 100644 tools/labs/mt.c rename tools/{editor/labs.vm => labs}/netproto.md (100%) rename tools/{editor => labs}/objtests.h (100%) rename tools/{editor/labs.osc => labs}/oscedit.c (97%) rename tools/{editor/labs.osc => labs}/oscedit.h (100%) rename tools/{editor/labs.osc => labs}/oscgame.c (98%) rename tools/{editor/labs.osc => labs}/osclab1.c (99%) rename tools/{editor/labs.osc => labs}/osclab2.c (99%) rename tools/{editor/labs.osc => labs}/oscpack.h (100%) rename tools/{editor/labs.osc => labs}/oscrecv.h (100%) rename tools/{editor/labs.osc => labs}/oscsend.c (99%) rename tools/{editor/labs.osc => labs}/oscsend.h (100%) rename tools/{editor => labs}/stdio2.c (99%) rename tools/{editor => }/windows.ini (100%) diff --git a/MAKE.bat b/MAKE.bat index 7ce5957..02d9a6e 100644 --- a/MAKE.bat +++ b/MAKE.bat @@ -324,6 +324,7 @@ if "%1"=="fwk_prep" ( xcopy /y "engine\split\3rd_*" "_fwk\engine\split" xcopy /y "engine\art\shaders\*" "_fwk\engine\art\shaders" xcopy /y "demos" "_fwk\demos" + xcopy /y "engine\editor.c" "_fwk\engine\editor.c" rem xcopy /y/E "tools "_fwk\tools" for %%f in ("engine\split\v4k*") do ( set "filename=%%~nf" @@ -371,6 +372,10 @@ if "%1"=="back" ( xcopy /y "_fwk\engine\split\3rd_*" "engine\split" xcopy /y "_fwk\engine\art\shaders\*" "engine\art\shaders" xcopy /y "_fwk\demos" "demos" + xcopy /y "_fwk\engine\editor.c" "engine\editor.c" + tools\fwkren.exe "engine\editor.c" to + tools\fwkren.exe "hello.c" to + rem xcopy /y/E "_fwk\tools "tools" for %%f in ("_fwk\engine\split\fwk*") do ( set "filename=%%~nf" @@ -804,7 +809,8 @@ if "!v4k!"=="yes" ( rem editor if "!editor!"=="yes" ( set edit=-DCOOK_ON_DEMAND -!echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! -Iengine/joint !args! || set rc=1 +rem set edit=-DUI_LESSER_SPACING -DUI_ICONS_SMALL !edit! +!echo! editor && !cc! !o! editor.exe engine\editor.c !edit! -Iengine/joint !args! || set rc=1 rem if "!cc!"=="cl" ( rem set plug_export=/LD diff --git a/demos/01-demo2d.c b/demos/01-demo2d.c index 7dc45f6..854280b 100644 --- a/demos/01-demo2d.c +++ b/demos/01-demo2d.c @@ -32,7 +32,7 @@ void demo_kids(vec3 offs) { spritesheet, // num_frame in a 4x4 spritesheet position, 0, // position(x,y,depth:sort-by-Y), angle offset, scale, // offset(x,y), scale(x,y) - false, WHITE, false // is_additive, tint color, resolution-independent + WHITE, 0 // tint_color, no flags ); } } @@ -43,7 +43,7 @@ void demo_hud() { float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling float position[3] = {window_width() - tile_w, window_height() - tile_h, window_height() }; // position in screen-coordinates (x,y,z-index) - sprite_sheet(inputs, spritesheet, position, 0/*deg*/, offset, scale, false, WHITE, 1); + sprite_sheet(inputs, spritesheet, position, 0/*deg*/, offset, scale, WHITE, SPRITE_RESOLUTION_INDEPENDANT); } int main() { @@ -140,7 +140,7 @@ int main() { ui_panel_end(); } /*if( ui_panel("Spine", 0)) { - spine_ui(spn); + ui_spine(spn); ui_panel_end(); }*/ } diff --git a/demos/01-ui.c b/demos/01-ui.c new file mode 100644 index 0000000..7035670 --- /dev/null +++ b/demos/01-ui.c @@ -0,0 +1,86 @@ +// hello ui: config, window, system, ui, video +// - rlyeh, public domain. +// +// Compile with: +// `make demos\01-ui.c` (windows) +// `sh MAKE.bat demos/01-ui.c` (linux, osx) + +#include "v4k.h" + +int main() { + float app_volume = 1.00f; + unsigned app_size = flag("--fullscreen") ? 100 : 75; + unsigned app_flags = flag("--msaa") ? WINDOW_MSAA4 : 0; + unsigned app_target_fps = optioni("--fps", 60); // --fps=30, --fps=45, etc. defaults to 60. + + // window api (fullscreen or 75% sized, optional MSAA flags) + window_create(app_size, app_flags); + window_title(__FILE__); + window_fps_lock(app_target_fps); + + // load video + video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_LOOP ); + + // app loop + while( window_swap() ) { + // input controls + if( input(KEY_ESC) ) break; + + // profile api + texture_t *textures; + profile( "Video decoder" ) { + // video api: decode frame and get associated textures (audio is sent to audiomixer automatically) + textures = video_decode( v ); + // fullscreen video + // if(video_is_rgb(v)) fullscreen_quad_rgb( textures[0], 1.3f ); + // else fullscreen_quad_ycbcr( textures, 1.3f ); + } + + // create menubar on top + int choice1 = ui_menu("File;Shell;Exit"); + int choice2 = ui_menu("Help;About"); + if( choice1 == 1 ) system(ifdef(win32, "start \"\" cmd", ifdef(osx, "open sh", "xdg-open sh"))); + if( choice1 == 2 ) exit(0); + + // showcase a few ui widgets + ui_demo(0); + + // create ui panel + if( ui_panel("myPanel", PANEL_OPEN) ) { + // Print some numbers + ui_section("Stats"); + ui_label2("FPS", va("%5.2f", window_fps())); + ui_separator(); + + // add some buttons + ui_section("Buttons"); + if( ui_button("Screenshot") ) window_screenshot(__FILE__ ".png"), ui_notify(0,ICON_MD_WARNING "Screenshot"); + if( ui_button("Record Video") ) window_record(__FILE__ ".mp4"), ui_notify(0,ICON_MD_WARNING "Recoding video"); + if( ui_button("Toggle fullscreen") ) window_fullscreen( !window_has_fullscreen() ); + ui_separator(); + + // some more video controls + ui_section("Video"); + if( ui_button("Rewind") ) video_seek(v, video_position(v) - 3); + if( ui_button("Pause") ) video_pause(v, video_is_paused(v) ^ 1); + if( ui_button("Forward") ) video_seek(v, video_position(v) + 3); + if( ui_slider2("Volume", &app_volume, va("%.2f", app_volume))) audio_volume_master(app_volume); + + // end of panel. must be enclosed within same if() branch. + ui_panel_end(); + } + + // create window + static int open = 1; + if( ui_window("myWindow", &open) ) { + // present decoded texture in a widget, without any label (NULL) + ui_texture( NULL, textures[0] ); + // end of window. must be enclosed within same if() branch. + ui_window_end(); + } + } +} + +// this demo supersedes following old sources: +// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-hello.c +// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-video.c diff --git a/demos/06-scene.c b/demos/06-scene.c new file mode 100644 index 0000000..8bcd5a4 --- /dev/null +++ b/demos/06-scene.c @@ -0,0 +1,216 @@ +// scene demo +// - rlyeh, public domain + +#include "v4k.h" + +int main() { + // options + bool do_twosided = 1; + bool do_wireframe = 0; + bool do_billboard_x = 0, do_billboard_y = 0, do_billboard_z = 0; + + // window (80% sized, MSAA x4 flag) + window_create(80, WINDOW_MSAA4); + window_title(__FILE__); + + // load all postfx files in all subdirs + fx_load("fx**.fs"); + + // scene loading + #define SCENE(...) #__VA_ARGS__ + const char *my_scene = SCENE([ + { + skybox: 'cubemaps/stardust/', + }, + { + position:[-5.0,-2.0,2.0], + rotation: [90.0,0.0,180.0], + scale:0.20, + //anchor/pivot:[], + // vertex:'p3 t2', + mesh:'models/witch/witch.obj', + texture:'models/witch/witch_diffuse.tga.png', +// swapzy:true, + flipuv:false, + }, + { + position:[-5.0,-2.0,2.0], + rotation: [90.0,0.0,180.0], + scale:2.20, + //anchor/pivot:[], + // vertex:'p3 t2', + mesh:'models/witch/witch_object.obj', + texture:'models/witch/witch_object_diffuse.tga.png', +// swapzy:true, + flipuv:false, + }, + ]); + int num_spawned = scene_merge(my_scene); + object_t *obj1 = scene_index(0); + object_t *obj2 = scene_index(1); + + // manual spawn & loading + model_t m1 = model("kgirl/kgirls01.fbx", 0); //MODEL_NO_ANIMS); + texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB); + object_t* obj3 = scene_spawn(); + object_model(obj3, m1); + object_diffuse(obj3, t1); + object_scale(obj3, vec3(3,3,3)); + object_move(obj3, vec3(-10,0,-10)); + object_pivot(obj3, vec3(-90+180,180,0)); + + // camera + camera_t cam = camera(); + + // demo loop + while (window_swap()) + { + // input + if( input_down(KEY_ESC) ) break; + + // fps camera + bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); + window_cursor( !active ); + + if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f); + vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active); + vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed); + camera_moveby(&cam, wasdecq); + camera_fps(&cam, mouse.x,mouse.y); + + // queue model scale bounces + float t = fmod(window_time(), 0.3) / 0.3; + float s = 0.01f * ease_ping_pong(t, EASE_IN|EASE_CUBIC,EASE_OUT|EASE_CUBIC); + object_scale(obj1, vec3(0.20f - s,0.20f + s,0.20f - s)); + object_scale(obj2, vec3(0.20f - s,0.20f + s,0.20f - s)); + + // queue model billboard + object_billboard(obj1, (do_billboard_x << 2)|(do_billboard_y << 1)|(do_billboard_z << 0)); + object_billboard(obj2, (do_billboard_x << 2)|(do_billboard_y << 1)|(do_billboard_z << 0)); + + // queue model rotation + //object_rotate(obj3, vec3(0,1*window_time() * 20,0)); + + // flush render scene (background objects: skybox) + profile("Scene background") { + scene_render(SCENE_BACKGROUND); + } + + // queue debug drawcalls + profile("Debugdraw") { + ddraw_ground(0); + ddraw_color(YELLOW); + ddraw_text(vec3(+1,+1,-1), 0.04f, va("(%f,%f,%f)", cam.position.x,cam.position.y,cam.position.z)); + ddraw_color(YELLOW); + ddraw_flush(); + } + + // apply post-fxs from here + fx_begin(); + + // render scene (foreground objects) with post-effects + profile("Scene foreground") { + int scene_flags = 0; + scene_flags |= do_wireframe ? SCENE_WIREFRAME : 0; + scene_flags |= do_twosided ? 0 : SCENE_CULLFACE; + scene_render(SCENE_FOREGROUND | scene_flags); + } + + profile("Skeletal update") if(!window_has_pause()) { + float delta = window_delta() * 30 ; // 30fps anim + m1.curframe = model_animate(m1, m1.curframe + delta); + + ddraw_text(vec3(-10,5,-10), 0.05, va("Frame: %.1f", m1.curframe)); + } + + // post-fxs end here + fx_end(); + + // queue ui + if( ui_panel("Scene", 0)) { + if(ui_toggle("Billboard X", &do_billboard_x)) {} + if(ui_toggle("Billboard Y", &do_billboard_y)) {} + if(ui_toggle("Billboard Z", &do_billboard_z)) {} + if(ui_separator()) {} + if(ui_bool("Wireframe", &do_wireframe)) {} + if(ui_bool("Two sided", &do_twosided)) {} + ui_panel_end(); + } + } +} + +#if 0 + +// ---------------------------------------------------------------------------- +// material demo +// - rlyeh, public domain +// +// @todo: object_print(obj, ""); + +// create camera +camera_t cam = camera(); +// load video, RGB texture, no audio +video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_NO_AUDIO | VIDEO_LOOP ); video_seek(v, 30); +// load texture +texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB); +texture_t t2 = texture("matcaps/material3", 0); +// load model +model_t m1 = model("suzanne.obj", MODEL_NO_ANIMATIONS); +model_t m2 = model("suzanne.obj", MODEL_NO_ANIMATIONS|MODEL_MATCAPS); + +// spawn object1 (diffuse) +object_t* obj1 = scene_spawn(); +object_model(obj1, m1); +object_diffuse(obj1, t1); +object_scale(obj1, vec3(3,3,3)); +object_move(obj1, vec3(-10+5*0,0,-10)); +object_pivot(obj1, vec3(0,90,0)); + +// spawn object2 (matcap) +object_t* obj2 = scene_spawn(); +object_model(obj2, m2); +object_diffuse(obj2, t2); +object_scale(obj2, vec3(3,3,3)); +object_move(obj2, vec3(-10+5*2,0,-10)); +object_pivot(obj2, vec3(0,90,0)); + +// spawn object2 (video) +object_t* obj3 = scene_spawn(); +object_model(obj3, m1); +object_diffuse(obj3, video_textures(v)[0]); +object_scale(obj3, vec3(3,3,3)); +object_move(obj3, vec3(-10+5*1,0,-10)); +object_pivot(obj3, vec3(0,90,0)); + +// @todo: add shadertoy material + static model_t cube; do_once cube = model("cube.obj", 0); + static shadertoy_t s; do_once s = shadertoy("shadertoys/4ttGWM.fs", 256); + model_set_texture(cube, shadertoy_render(&s, window_delta())->tx); + model_render(cube, cam.proj, cam.view, cube.pivot, 0); + +while(window_swap() && !input(KEY_ESC)) { + // draw environment + viewport_color( RGB3(22,22,32) ); + ddraw_grid(0); + ddraw_flush(); + + // update video + video_decode( v ); + + // draw scene + scene_render(SCENE_FOREGROUND); +} + +// load static scene +// model_t sponza = model("sponza.obj", MODEL_MATCAPS); +// model_set_texture(sponza, texture("matcaps/normals", 0)); +// translation44(sponza.pivot, 0,-1,0); +// rotate44(sponza.pivot, -90,1,0,0); +// scale44(sponza.pivot, 10,10,10); + // model_render(sponza, cam.proj, cam.view, sponza.pivot, 0); + +// this demo supersedes following old sources: +// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-material.c +// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-shadertoy.c + +#endif diff --git a/demos/99-controller.c b/demos/99-controller.c new file mode 100644 index 0000000..faf5a98 --- /dev/null +++ b/demos/99-controller.c @@ -0,0 +1,280 @@ +// full controller demo: anims, input, collide; @todo: gamepad, input opts, easing on hits, notify on gamepad connect +// - rlyeh, public domain. +// +// Compile with: +// `make demos\99-controller.c` (windows) +// `sh MAKE.bat demos/99-controller.c` (linux, osx) + +#include "v4k.h" + +int main() { + // 75% window, MSAAx2 flag + window_create(75, WINDOW_MSAA2); + + // fx: load all post fx files in all subdirs + fx_load("fx**.fs"); + + // create a camera + camera_t cam = camera(); + camera_enable(&cam); + + // config 3d model #1 + model_t witch = model("witch/witch.obj", 0); + model_set_texture(witch, texture("witch/witch_diffuse.tga.png", 0)); + mat44 witch_pivot; vec3 witch_p = {-5,0,-5}, witch_r={-180,180,0}, witch_s={0.1,-0.1,0.1}; + + // config 3d model #2 + model_t girl = model("kgirl/kgirls01.fbx", 0); + mat44 girl_pivot; vec3 girl_p = {0,0,0}, girl_r = {270,0,0}, girl_s = {2,2,2}; + + // skybox + skybox_t sky = skybox("cubemaps/stardust", 0); + + // BGM + audio_play( audio_stream("waterworld-map.fur"), 0 ); + + // editor loop + while( window_swap() ) { + + // game camera + profile("Game.Camera") { + camera_t *cam = camera_get_active(); + + static vec3 source; + do_once source = cam->position; + + vec3 target = add3(girl_p, vec3(0,10,0)); + target = add3(target, scale3(norm3(sub3(source, target)), 10.0)); + source = mix3(source, target, 1-0.99f); + + camera_teleport(cam, source); + camera_lookat(cam, vec3(girl_p.x,0,girl_p.z)); + } + + // render begin (postfx) + fx_begin(); + + // skybox + skybox_render(&sky, cam.proj, cam.view); + + // world + ddraw_grid(0); + ddraw_flush(); + + // models + compose44(girl.pivot, girl_p, eulerq(girl_r), girl_s); + model_render(girl, cam.proj, cam.view, girl.pivot, 0); + + compose44(witch.pivot, witch_p, eulerq(witch_r), witch_s); + model_render(witch, cam.proj, cam.view, witch.pivot, 0); + + // render end (postfx) + fx_end(); + + // input controllers + + double GAME_JUMP_DOWN = input_down(KEY_Z); + double GAME_FIRE_DOWN = input_down(KEY_X); + double GAME_JUMP = input(KEY_Z); + double GAME_FIRE = input(KEY_X); + double GAME_LEFT = input(KEY_J); + double GAME_RIGHT = input(KEY_L); + double GAME_UP = input(KEY_I); + double GAME_DOWN = input(KEY_K); + double GAME_AXISX = input(KEY_L) - input(KEY_J); + double GAME_AXISY = input(KEY_I) - input(KEY_K); + + if( !input_anykey() ) { + if( input(GAMEPAD_CONNECTED) ) { + vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), 0.15f /*15% deadzone*/); + GAME_JUMP_DOWN = input_down(GAMEPAD_A); + GAME_FIRE_DOWN = input_down(GAMEPAD_B) || input_down(GAMEPAD_X) || input_down(GAMEPAD_Y); + GAME_JUMP = input(GAMEPAD_A); + GAME_FIRE = input(GAMEPAD_B) || input(GAMEPAD_X) || input(GAMEPAD_Y); + GAME_AXISX = filtered_lpad.x; + GAME_AXISY = filtered_lpad.y; + } + } + + // animation controllers + + profile("Game.Animate scene") if( !window_has_pause() ) { + float delta = window_delta() * 30; // 30fps anim + + // animate girl + girl.curframe = model_animate(girl, girl.curframe + delta); + + // jump controller: jump duration=1.5s, jump height=6 units, anims (expo->circ) + float jump_delta = 1.0; + static double jump_timer = 0, jump_ss = 1.5, jump_h = 6; + if( GAME_JUMP_DOWN ) if( jump_timer == 0 ) jump_timer = time_ss(); + jump_delta = clampf(time_ss() - jump_timer, 0, jump_ss) * (1.0/jump_ss); + if( jump_delta >= 1 ) { jump_timer = 0; } + float y = ease_ping_pong( jump_delta, EASE_OUT|EASE_EXPO, EASE_OUT|EASE_CIRC); + girl_p.y = y * jump_h; + + // punch controller + float punch_delta = 1; + if( jump_delta >= 1 ) { + static vec3 origin; + static double punch_timer = 0, punch_ss = 0.5; + if( GAME_FIRE_DOWN ) if( punch_timer == 0 ) punch_timer = time_ss(), origin = girl_p; + punch_delta = clampf(time_ss() - punch_timer, 0, punch_ss) * (1.0/punch_ss); + if( punch_delta >= 1 ) { punch_timer = 0; } + else { + float x = ease_out_expo( punch_delta ); + vec3 fwd = rotate3q(vec3(0,0,1), eulerq(vec3(girl_r.x - 170,girl_r.y,girl_r.z))); + vec3 mix = mix3(girl_p, add3(origin,scale3(fwd,x*2)), x); + girl_p.x = mix.x, girl_p.z = mix.z; + } + } + + int modern_controller = 1; + int running = 0; + + // girl controller + + // locomotion vars + float speed = 0.2f * delta; + float yaw_boost = GAME_AXISY > 0 ? 1.0 : 1.75; + if(punch_delta < 1) yaw_boost = 0.0; // if firing... + else if(punch_delta <= 0.1) yaw_boost = 4.0; // unless initial punch chaining, extra yaw + + // old fashioned locomotion controller (boat controller) + if(!modern_controller) { + running = GAME_AXISY > 0; + + girl_r.x -= 170; + quat q = eulerq(girl_r); // += custom.pivot + vec3 rgt = rotate3q(vec3(1,0,0), q); + vec3 up = rotate3q(vec3(0,1,0), q); + vec3 fwd = rotate3q(vec3(0,0,1), q); + vec3 dir = scale3(fwd, speed * GAME_AXISY * (GAME_AXISY > 0 ? 2.0 : 0.5)); + girl_r.x += speed * 20.0 * yaw_boost * GAME_AXISX; // yaw + girl_p = add3(girl_p, dir); + girl_r.x += 170; + } + + // modern locomotion controller (mario 3d) + if(modern_controller) { + running = GAME_AXISX != 0 || GAME_AXISY != 0; + + camera_t *cam = camera_get_active(); + vec3 fwd = sub3(girl_p, cam->position); fwd.y = 0; fwd = norm3(fwd); + vec3 rgt = norm3(cross3(fwd, vec3(0,1,0))); + + // target + vec3 dir = add3( + scale3(fwd, GAME_AXISY), + scale3(rgt, GAME_AXISX) + ); dir.y = 0; dir = norm3(dir); + + // smoothing + static vec3 olddir; do_once olddir = dir; + dir = mix3(dir, olddir, 1 - (yaw_boost / 4.0) * 0.85); + olddir = dir; + + // vis + // ddraw_arrow(girl_p, add3(girl_p,scale3(dir,10))); + + // apply direction + girl_p = add3(girl_p, scale3(dir, speed * 2)); + + // apply rotation + { + girl_r.x -= 170; + quat q = eulerq(girl_r); + vec3 fwdg = rotate3q(vec3(0,0,1), q); + girl_r.x += 170; + + //float cosAngle = dot3(dir,fwdg); + //float angle = acos(cosAngle) * TO_DEG; + float angle = TO_DEG * ( atan2(fwdg.z, fwdg.x) - atan2(dir.z, dir.x)); + + if( !isnan(angle) ) { + girl_r.x -= angle; + while(girl_r.x> 180) girl_r.x-=360; + while(girl_r.x<-180) girl_r.x+=360; + } + } + } + + // anim loops + if( jump_delta < 1 ) { // jump/kick anim +#if 0 + girl.curframe = clampf(girl.curframe, 184, 202); + if( girl.curframe > 202-4 && GAME_FIRE_DOWN ) girl.curframe = 184+4; +#else + #define loopf(frame, min, max) (frame < min ? min : frame > max ? min + frame - max : frame) + if(girl.curframe >= 203) + girl.curframe = loopf(girl.curframe, 203, 220); + else + girl.curframe = clampf(girl.curframe, 184, 202); + if( girl.curframe > 202-4 && girl.curframe < 208 && GAME_FIRE_DOWN ) girl.curframe = 203; +#endif + } + else if( punch_delta < 1 ) { // punch anim + girl.curframe = clampf(girl.curframe, 90, 101); + if( girl.curframe > 101-6 && GAME_FIRE_DOWN ) girl.curframe = 101-6; + } + else if( running ) { + // loop running anim + if( girl.curframe < 65 ) girl.curframe = 65; + if( girl.curframe > 85 ) girl.curframe = 65; + } + else { // loop idle anim + if( girl.curframe > 59 ) girl.curframe = 0; + } + } + + // Game collisions + + profile("Game.collisions") { + bool punching = girl.curframe >= 90 && girl.curframe < 101; + bool air_kicking = girl.curframe >= 184 && girl.curframe < 202; + bool jump_kicking = girl.curframe >= 203 && girl.curframe < 220; + bool attacking = punching || air_kicking || jump_kicking; + + if( attacking ) { + aabb boxg = model_aabb(girl, girl_pivot); + aabb boxw = model_aabb(witch, witch_pivot); +#if 0 // halve aabb. ok + { + vec3 diag = sub3(boxg.max, boxg.min); + vec3 halve = scale3(diag, 0.25); + vec3 center = scale3(add3(boxg.min, boxg.max), 0.5); + boxg.min = sub3(center, halve); + boxg.max = add3(center, halve); + } +#endif + hit* h = aabb_hit_aabb(boxg, boxw); + if( h && GAME_FIRE ) { + vec3 dir = norm3(sub3(witch_p, girl_p)); + witch_p = add3(witch_p, mul3(dir,vec3(1,0,1))); + } + } + } + + // ui + if( ui_panel("Input", 0) ) { // @todo: showcase input binding + ui_section("Controllers"); + ui_label("Gamepad #1"); + ui_label("Keys I/J/K/L + Z/X"); + ui_panel_end(); + } + } +} + +// vec2 do_gamepad_polarity = vec2(+1,+1); +// vec2 do_gamepad_sensitivity = vec2(0.1f,0.1f); +// vec2 do_mouse_polarity = vec2(+1,-1); +// vec2 do_mouse_sensitivity = vec2(0.2f,0.2f); +// float do_gamepad_deadzone = 0.15f;// +// +// if(ui_separator()) {} +// if(ui_slider("Gamepad deadzone", &do_gamepad_deadzone)) {} +// if(ui_float2("Gamepad polarity", do_gamepad_polarity.v2)) {} +// if(ui_float2("Gamepad sensitivity", do_gamepad_sensitivity.v2)) {} +// if(ui_separator()) {} +// if(ui_float2("Mouse polarity", do_mouse_polarity.v2)) {} +// if(ui_float2("Mouse sensitivity", do_mouse_sensitivity.v2)) {}// diff --git a/demos/99-lod.c b/demos/99-lod.c new file mode 100644 index 0000000..99bfe91 --- /dev/null +++ b/demos/99-lod.c @@ -0,0 +1,234 @@ +// LOD demo, based on Polygon Reduction Demo by Stan Melax (PD) +// - rlyeh, public domain. + +#include "v4k.h" + +vec2 world2screen(vec3 p) { + vec4 clip_pos = transform444(camera_get_active()->proj, transform444(camera_get_active()->view, vec4(p.x,p.y,p.z,1.0))); + vec4 ndc_pos = scale4(clip_pos, 1.0 / (clip_pos.w + !clip_pos.w)); // [-1..1] + vec2 screen_pos = vec2( window_width() * (ndc_pos.x + 1) / 2.0, window_height() * (1 - ndc_pos.y) / 2.0 ); + return screen_pos; +} + +float mesh_area(mesh_t *m) { + // @fixme: return 0 if mesh is out of frustum, or window is minimized + + aabb box = mesh_bounds(m); + ddraw_aabb(box.min, box.max); + + vec2 A = world2screen(vec3(box.min.x,box.min.y,box.min.z)); ddraw_text2d(A, va("A: %5.2f,%5.2f", A.x, A.y)); + vec2 B = world2screen(vec3(box.min.x,box.min.y,box.max.z)); ddraw_text2d(B, va("B: %5.2f,%5.2f", B.x, B.y)); + vec2 C = world2screen(vec3(box.min.x,box.max.y,box.min.z)); ddraw_text2d(C, va("C: %5.2f,%5.2f", C.x, C.y)); + vec2 D = world2screen(vec3(box.min.x,box.max.y,box.max.z)); ddraw_text2d(D, va("D: %5.2f,%5.2f", D.x, D.y)); + vec2 E = world2screen(vec3(box.max.x,box.min.y,box.min.z)); ddraw_text2d(E, va("E: %5.2f,%5.2f", E.x, E.y)); + vec2 F = world2screen(vec3(box.max.x,box.min.y,box.max.z)); ddraw_text2d(F, va("F: %5.2f,%5.2f", F.x, F.y)); + vec2 G = world2screen(vec3(box.max.x,box.max.y,box.min.z)); ddraw_text2d(G, va("G: %5.2f,%5.2f", G.x, G.y)); + vec2 H = world2screen(vec3(box.max.x,box.max.y,box.max.z)); ddraw_text2d(H, va("H: %5.2f,%5.2f", H.x, H.y)); + + vec2 O = min2(min2(min2(min2(min2(min2(min2(A,B),C),D),E),F),G),H); ddraw_text2d(O, "|\\"); + vec2 P = max2(max2(max2(max2(max2(max2(max2(A,B),C),D),E),F),G),H); ddraw_text2d(P, "\\|"); + + float area = (P.x-O.x) * (P.y-O.y); // len2(sub2(P,O)); + float pct = area / (float)(window_height() * window_width()); + + font_print(va(FONT_RIGHT "area: %5.2f%%", pct*100)); + return pct; +} + + +API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, const int *tri, int *map, int *permutation); + +// Map() +// +// Note that the use of the Map() function and the collapse_map Array isn't part of the polygon reduction +// algorithm. We set up the function here so that we could retrieve the model at any desired vertex count. +// +// When the model is rendered using a maximum of mx vertices then it is vertices 0 through mx-1 that are used. +// We are able to do this because the vertex Array gets sorted according to the collapse order. +// The Map() routine takes a vertex number 'n' and the maximum number of vertices 'mx' and returns the +// appropriate vertex in the range 0 to mx-1. When 'n' is greater than 'mx' the Map() routine follows the +// chain of edge collapses until a vertex within the limit is reached. +// An example to make this clear: assume there is a triangle with vertices 1, 3 and 12. But when +// rendering the model we limit ourselves to 10 vertices. In that case we find out how vertex 12 was +// removed by the polygon reduction algorithm. i.e. which edge was collapsed. Lets say that vertex 12 was +// collapsed to vertex number 7. This number would have been stored in the collapse_map array (i.e. +// collapse_map[12]==7). Since vertex 7 is in range (less than max of 10) we will want to render the +// triangle 1,3,7. Pretend now that we want to limit ourselves to 5 vertices. and vertex 7 was collapsed +// to vertex 3 (i.e. collapse_map[7]==3). Then triangle 1,3,12 would now be triangle 1,3,3. i.e. this +// polygon was removed by the progressive mesh polygon reduction algorithm by the time it had gotten down +// to 5 vertices. No need to draw a one dimensional polygon. :-) + +static inline int MapReduce(array(int) collapse_map, int n, int mx) { + while( n >= mx ) n = collapse_map[n]; + return n; +} + +mesh_t *ReduceModel(mesh_t *m, float lo_detail, float hi_detail, float morph) { + int max_verts_to_render = hi_detail * array_count(m->in_vertex3); + int min_verts_to_render = lo_detail * array_count(m->in_vertex3); + + if( max_verts_to_render <= 0 || min_verts_to_render <= 0 ) + return m; + + array_resize(m->out_index3, 0); + array_resize(m->out_vertex3, 0); + + ASSERT(array_count(m->lod_collapse_map)); + for( unsigned int i = 0; i < array_count(m->in_index3); i++ ) { + int p0 = MapReduce(m->lod_collapse_map, m->in_index3[i].x, max_verts_to_render); + int p1 = MapReduce(m->lod_collapse_map, m->in_index3[i].y, max_verts_to_render); + int p2 = MapReduce(m->lod_collapse_map, m->in_index3[i].z, max_verts_to_render); + // @fixme: serious optimization opportunity here, + // by sorting the triangles the following "continue" + // could have been made into a "break" statement. + if(p0==p1 || p0==p2 || p1==p2) continue; + // if we are not currenly morphing between 2 levels of detail + // (i.e. if morph=1.0) then q0,q1, and q2 may not be necessary + int q0 = MapReduce(m->lod_collapse_map, p0, min_verts_to_render); + int q1 = MapReduce(m->lod_collapse_map, p1, min_verts_to_render); + int q2 = MapReduce(m->lod_collapse_map, p2, min_verts_to_render); + vec3 v0, v1, v2; + v0 = mix3(m->in_vertex3[p0], m->in_vertex3[q0], (1-morph)); + v1 = mix3(m->in_vertex3[p1], m->in_vertex3[q1], (1-morph)); + v2 = mix3(m->in_vertex3[p2], m->in_vertex3[q2], (1-morph)); + vec3 normal = norm3(cross3(sub3(v1,v0),sub3(v2,v1))); + array_push(m->out_vertex3, v0); + array_push(m->out_vertex3, normal); + array_push(m->out_vertex3, v1); + array_push(m->out_vertex3, normal); + array_push(m->out_vertex3, v2); + array_push(m->out_vertex3, normal); + + int idx = array_count(m->out_vertex3) / 2; + array_push(m->out_index3, vec3i(idx-3,idx-2,idx-1)); + } + + return m; +} + +void DrawModel(mesh_t *m) { + static mat44 M; do_once id44(M); + static mat44 VP; multiply44x2(VP, camera_get_active()->proj, camera_get_active()->view); + + static const char *vs = + "#version 130\n" + "//" FILELINE "\n" + "uniform mat4 M,VP;\n" + "in vec3 att_position;\n" + "in vec3 att_normal;\n" + "out vec3 v_normal;\n" + "void main() {\n" + " v_normal = normalize(att_normal);\n" + " gl_Position = M * VP * vec4( att_position, 1.0 );\n" + "}\n"; + static const char *fs = + "#version 130\n" + "//" FILELINE "\n" + "in vec3 v_normal;\n" + "out vec4 fragcolor;\n" + "void main() {\n" + "fragcolor = vec4(v_normal, 1.0);\n" // diffuse + "}"; + + static unsigned program; do_once program = shader(vs, fs, "att_position,att_normal", "fragcolor", NULL); + shader_bind(program); + shader_mat44("VP", VP); + shader_mat44("M", M); + + mesh_update(m, "p3 n3", 0,array_count(m->out_vertex3)/2,m->out_vertex3, array_count(m->out_index3)*3,m->out_index3,0); + mesh_render(m); +} + +void InitModel(mesh_t *m) { + static const double verts[]={-0.334392,+0.133007,+0.062259,-0.350189,+0.150354,-0.147769,-0.234201,+0.343811,-0.174307,-0.200259,+0.285207,+0.093749,+0.003520,+0.475208,-0.159365,+0.001856,+0.419203,+0.098582,-0.252802,+0.093666,+0.237538,-0.162901,+0.237984,+0.206905,+0.000865,+0.318141,+0.235370,-0.414624,+0.164083,-0.278254,-0.262213,+0.357334,-0.293246,+0.004628,+0.482694,-0.338626,-0.402162,+0.133528,-0.443247,-0.243781,+0.324275,-0.436763,+0.005293,+0.437592,-0.458332,-0.339884,-0.041150,-0.668211,-0.248382,+0.255825,-0.627493,+0.006261,+0.376103,-0.631506,-0.216201,-0.126776,-0.886936,-0.171075,+0.011544,-0.881386,-0.181074,+0.098223,-0.814779,-0.119891,+0.218786,-0.760153,-0.078895,+0.276780,-0.739281,+0.006801,+0.310959,-0.735661,-0.168842,+0.102387,-0.920381,-0.104072,+0.177278,-0.952530,-0.129704,+0.211848,-0.836678,-0.099875,+0.310931,-0.799381,+0.007237,+0.361687,-0.794439,-0.077913,+0.258753,-0.921640,+0.007957,+0.282241,-0.931680,-0.252222,-0.550401,-0.557810,-0.267633,-0.603419,-0.655209,-0.446838,-0.118517,-0.466159,-0.459488,-0.093017,-0.311341,-0.370645,-0.100108,-0.159454,-0.371984,-0.091991,-0.011044,-0.328945,-0.098269,+0.088659,-0.282452,-0.018862,+0.311501,-0.352403,-0.131341,+0.144902,-0.364126,-0.200299,+0.202388,-0.283965,-0.231869,+0.023668,-0.298943,-0.155218,+0.369716,-0.293787,-0.121856,+0.419097,-0.290163,-0.290797,+0.107824,-0.264165,-0.272849,+0.036347,-0.228567,-0.372573,+0.290309,-0.190431,-0.286997,+0.421917,-0.191039,-0.240973,+0.507118,-0.287272,-0.276431,-0.065444,-0.295675,-0.280818,-0.174200,-0.399537,-0.313131,-0.376167,-0.392666,-0.488581,-0.427494,-0.331669,-0.570185,-0.466054,-0.282290,-0.618140,-0.589220,-0.374238,-0.594882,-0.323298,-0.381071,-0.629723,-0.350777,-0.382112,-0.624060,-0.221577,-0.272701,-0.566522,+0.259157,-0.256702,-0.663406,+0.286079,-0.280948,-0.428359,+0.055790,-0.184974,-0.508894,+0.326265,-0.279971,-0.526918,+0.395319,-0.282599,-0.663393,+0.412411,-0.188329,-0.475093,+0.417954,-0.263384,-0.663396,+0.466604,-0.209063,-0.663393,+0.509344,-0.002044,-0.319624,+0.553078,-0.001266,-0.371260,+0.413296,-0.219753,-0.339762,-0.040921,-0.256986,-0.282511,-0.006349,-0.271706,-0.260881,+0.001764,-0.091191,-0.419184,-0.045912,-0.114944,-0.429752,-0.124739,-0.113970,-0.382987,-0.188540,-0.243012,-0.464942,-0.242850,-0.314815,-0.505402,-0.324768,+0.002774,-0.437526,-0.262766,-0.072625,-0.417748,-0.221440,-0.160112,-0.476932,-0.293450,+0.003859,-0.453425,-0.443916,-0.120363,-0.581567,-0.438689,-0.091499,-0.584191,-0.294511,-0.116469,-0.599861,-0.188308,-0.208032,-0.513640,-0.134649,-0.235749,-0.610017,-0.040939,-0.344916,-0.622487,-0.085380,-0.336401,-0.531864,-0.212298,+0.001961,-0.459550,-0.135547,-0.058296,-0.430536,-0.043440,+0.001378,-0.449511,-0.037762,-0.130135,-0.510222,+0.079144,+0.000142,-0.477549,+0.157064,-0.114284,-0.453206,+0.304397,-0.000592,-0.443558,+0.285401,-0.056215,-0.663402,+0.326073,-0.026248,-0.568010,+0.273318,-0.049261,-0.531064,+0.389854,-0.127096,-0.663398,+0.479316,-0.058384,-0.663401,+0.372891,-0.303961,+0.054199,+0.625921,-0.268594,+0.193403,+0.502766,-0.277159,+0.126123,+0.443289,-0.287605,-0.005722,+0.531844,-0.231396,-0.121289,+0.587387,-0.253475,-0.081797,+0.756541,-0.195164,-0.137969,+0.728011,-0.167673,-0.156573,+0.609388,-0.145917,-0.169029,+0.697600,-0.077776,-0.214247,+0.622586,-0.076873,-0.214971,+0.696301,-0.002341,-0.233135,+0.622859,-0.002730,-0.213526,+0.691267,-0.003136,-0.192628,+0.762731,-0.056136,-0.201222,+0.763806,-0.114589,-0.166192,+0.770723,-0.155145,-0.129632,+0.791738,-0.183611,-0.058705,+0.847012,-0.165562,+0.001980,+0.833386,-0.220084,+0.019914,+0.768935,-0.255730,+0.090306,+0.670782,-0.255594,+0.113833,+0.663389,-0.226380,+0.212655,+0.617740,-0.003367,-0.195342,+0.799680,-0.029743,-0.210508,+0.827180,-0.003818,-0.194783,+0.873636,-0.004116,-0.157907,+0.931268,-0.031280,-0.184555,+0.889476,-0.059885,-0.184448,+0.841330,-0.135333,-0.164332,+0.878200,-0.085574,-0.170948,+0.925547,-0.163833,-0.094170,+0.897114,-0.138444,-0.104250,+0.945975,-0.083497,-0.084934,+0.979607,-0.004433,-0.146642,+0.985872,-0.150715,+0.032650,+0.884111,-0.135892,-0.035520,+0.945455,-0.070612,+0.036849,+0.975733,-0.004458,-0.042526,+1.015670,-0.004249,+0.046042,+1.003240,-0.086969,+0.133224,+0.947633,-0.003873,+0.161605,+0.970499,-0.125544,+0.140012,+0.917678,-0.125651,+0.250246,+0.857602,-0.003127,+0.284070,+0.878870,-0.159174,+0.125726,+0.888878,-0.183807,+0.196970,+0.844480,-0.159890,+0.291736,+0.732480,-0.199495,+0.207230,+0.779864,-0.206182,+0.164608,+0.693257,-0.186315,+0.160689,+0.817193,-0.192827,+0.166706,+0.782271,-0.175112,+0.110008,+0.860621,-0.161022,+0.057420,+0.855111,-0.172319,+0.036155,+0.816189,-0.190318,+0.064083,+0.760605,-0.195072,+0.129179,+0.731104,-0.203126,+0.410287,+0.680536,-0.216677,+0.309274,+0.642272,-0.241515,+0.311485,+0.587832,-0.002209,+0.366663,+0.749413,-0.088230,+0.396265,+0.678635,-0.170147,+0.109517,+0.840784,-0.160521,+0.067766,+0.830650,-0.181546,+0.139805,+0.812146,-0.180495,+0.148568,+0.776087,-0.180255,+0.129125,+0.744192,-0.186298,+0.078308,+0.769352,-0.167622,+0.060539,+0.806675,-0.189876,+0.102760,+0.802582,-0.108340,+0.455446,+0.657174,-0.241585,+0.527592,+0.669296,-0.265676,+0.513366,+0.634594,-0.203073,+0.478550,+0.581526,-0.266772,+0.642330,+0.602061,-0.216961,+0.564846,+0.535435,-0.202210,+0.525495,+0.475944,-0.193888,+0.467925,+0.520606,-0.265837,+0.757267,+0.500933,-0.240306,+0.653440,+0.463215,-0.309239,+0.776868,+0.304726,-0.271009,+0.683094,+0.382018,-0.312111,+0.671099,+0.286687,-0.268791,+0.624342,+0.377231,-0.302457,+0.533996,+0.360289,-0.263656,+0.529310,+0.412564,-0.282311,+0.415167,+0.447666,-0.239201,+0.442096,+0.495604,-0.220043,+0.569026,+0.445877,-0.001263,+0.395631,+0.602029,-0.057345,+0.442535,+0.572224,-0.088927,+0.506333,+0.529106,-0.125738,+0.535076,+0.612913,-0.126251,+0.577170,+0.483159,-0.149594,+0.611520,+0.557731,-0.163188,+0.660791,+0.491080,-0.172482,+0.663387,+0.415416,-0.160464,+0.591710,+0.370659,-0.156445,+0.536396,+0.378302,-0.136496,+0.444358,+0.425226,-0.095564,+0.373768,+0.473659,-0.104146,+0.315912,+0.498104,-0.000496,+0.384194,+0.473817,-0.000183,+0.297770,+0.401486,-0.129042,+0.270145,+0.434495,+0.000100,+0.272963,+0.349138,-0.113060,+0.236984,+0.385554,+0.007260,+0.016311,-0.883396,+0.007865,+0.122104,-0.956137,-0.032842,+0.115282,-0.953252,-0.089115,+0.108449,-0.950317,-0.047440,+0.014729,-0.882756,-0.104458,+0.013137,-0.882070,-0.086439,-0.584866,-0.608343,-0.115026,-0.662605,-0.436732,-0.071683,-0.665372,-0.606385,-0.257884,-0.665381,-0.658052,-0.272542,-0.665381,-0.592063,-0.371322,-0.665382,-0.353620,-0.372362,-0.665381,-0.224420,-0.335166,-0.665380,-0.078623,-0.225999,-0.665375,-0.038981,-0.106719,-0.665374,-0.186351,-0.081749,-0.665372,-0.292554,+0.006943,-0.091505,-0.858354,+0.006117,-0.280985,-0.769967,+0.004495,-0.502360,-0.559799,-0.198638,-0.302135,-0.845816,-0.237395,-0.542544,-0.587188,-0.270001,-0.279489,-0.669861,-0.134547,-0.119852,-0.959004,-0.052088,-0.122463,-0.944549,-0.124463,-0.293508,-0.899566,-0.047616,-0.289643,-0.879292,-0.168595,-0.529132,-0.654931,-0.099793,-0.515719,-0.645873,-0.186168,-0.605282,-0.724690,-0.112970,-0.583097,-0.707469,-0.108152,-0.665375,-0.700408,-0.183019,-0.665378,-0.717630,-0.349529,-0.334459,-0.511985,-0.141182,-0.437705,-0.798194,-0.212670,-0.448725,-0.737447,-0.261111,-0.414945,-0.613835,-0.077364,-0.431480,-0.778113,+0.005174,-0.425277,-0.651592,+0.089236,-0.431732,-0.777093,+0.271006,-0.415749,-0.610577,+0.223981,-0.449384,-0.734774,+0.153275,-0.438150,-0.796391,+0.358414,-0.335529,-0.507649,+0.193434,-0.665946,-0.715325,+0.118363,-0.665717,-0.699021,+0.123515,-0.583454,-0.706020,+0.196851,-0.605860,-0.722345,+0.109788,-0.516035,-0.644590,+0.178656,-0.529656,-0.652804,+0.061157,-0.289807,-0.878626,+0.138234,-0.293905,-0.897958,+0.066933,-0.122643,-0.943820,+0.149571,-0.120281,-0.957264,+0.280989,-0.280321,-0.666487,+0.246581,-0.543275,-0.584224,+0.211720,-0.302754,-0.843303,+0.086966,-0.665627,-0.291520,+0.110634,-0.665702,-0.185021,+0.228099,-0.666061,-0.036201,+0.337743,-0.666396,-0.074503,+0.376722,-0.666513,-0.219833,+0.377265,-0.666513,-0.349036,+0.281411,-0.666217,-0.588670,+0.267564,-0.666174,-0.654834,+0.080745,-0.665602,-0.605452,+0.122016,-0.662963,-0.435280,+0.095767,-0.585141,-0.607228,+0.118944,+0.012799,-0.880702,+0.061944,+0.014564,-0.882086,+0.104725,+0.108156,-0.949130,+0.048513,+0.115159,-0.952753,+0.112696,+0.236643,+0.386937,+0.128177,+0.269757,+0.436071,+0.102643,+0.315600,+0.499370,+0.094535,+0.373481,+0.474824,+0.136270,+0.443946,+0.426895,+0.157071,+0.535923,+0.380222,+0.161350,+0.591224,+0.372630,+0.173035,+0.662865,+0.417531,+0.162808,+0.660299,+0.493077,+0.148250,+0.611070,+0.559555,+0.125719,+0.576790,+0.484702,+0.123489,+0.534699,+0.614440,+0.087621,+0.506066,+0.530188,+0.055321,+0.442365,+0.572915,+0.219936,+0.568361,+0.448571,+0.238099,+0.441375,+0.498528,+0.281711,+0.414315,+0.451121,+0.263833,+0.528513,+0.415794,+0.303284,+0.533081,+0.363998,+0.269687,+0.623528,+0.380528,+0.314255,+0.670153,+0.290524,+0.272023,+0.682273,+0.385343,+0.311480,+0.775931,+0.308527,+0.240239,+0.652714,+0.466159,+0.265619,+0.756464,+0.504187,+0.192562,+0.467341,+0.522972,+0.201605,+0.524885,+0.478417,+0.215743,+0.564193,+0.538084,+0.264969,+0.641527,+0.605317,+0.201031,+0.477940,+0.584002,+0.263086,+0.512567,+0.637832,+0.238615,+0.526867,+0.672237,+0.105309,+0.455123,+0.658482,+0.183993,+0.102195,+0.804872,+0.161563,+0.060042,+0.808692,+0.180748,+0.077754,+0.771600,+0.175168,+0.128588,+0.746368,+0.175075,+0.148030,+0.778264,+0.175658,+0.139265,+0.814333,+0.154191,+0.067291,+0.832578,+0.163818,+0.109013,+0.842830,+0.084760,+0.396004,+0.679695,+0.238888,+0.310760,+0.590775,+0.213380,+0.308625,+0.644905,+0.199666,+0.409678,+0.683003,+0.190143,+0.128597,+0.733463,+0.184833,+0.063516,+0.762902,+0.166070,+0.035644,+0.818261,+0.154361,+0.056943,+0.857042,+0.168542,+0.109489,+0.862725,+0.187387,+0.166131,+0.784599,+0.180428,+0.160135,+0.819438,+0.201823,+0.163991,+0.695756,+0.194206,+0.206635,+0.782275,+0.155438,+0.291260,+0.734412,+0.177696,+0.196424,+0.846693,+0.152305,+0.125256,+0.890786,+0.119546,+0.249876,+0.859104,+0.118369,+0.139643,+0.919173,+0.079410,+0.132973,+0.948652,+0.062419,+0.036648,+0.976547,+0.127847,-0.035919,+0.947070,+0.143624,+0.032206,+0.885913,+0.074888,-0.085173,+0.980577,+0.130184,-0.104656,+0.947620,+0.156201,-0.094653,+0.899074,+0.077366,-0.171194,+0.926545,+0.127722,-0.164729,+0.879810,+0.052670,-0.184618,+0.842019,+0.023477,-0.184638,+0.889811,+0.022626,-0.210587,+0.827500,+0.223089,+0.211976,+0.620493,+0.251444,+0.113067,+0.666494,+0.251419,+0.089540,+0.673887,+0.214360,+0.019258,+0.771595,+0.158999,+0.001490,+0.835374,+0.176696,-0.059249,+0.849218,+0.148696,-0.130091,+0.793599,+0.108290,-0.166528,+0.772088,+0.049820,-0.201382,+0.764454,+0.071341,-0.215195,+0.697209,+0.073148,-0.214475,+0.623510,+0.140502,-0.169461,+0.699354,+0.163374,-0.157073,+0.611416,+0.189466,-0.138550,+0.730366,+0.247593,-0.082554,+0.759610,+0.227468,-0.121982,+0.590197,+0.284702,-0.006586,+0.535347,+0.275741,+0.125287,+0.446676,+0.266650,+0.192594,+0.506044,+0.300086,+0.053287,+0.629620,+0.055450,-0.663935,+0.375065,+0.122854,-0.664138,+0.482323,+0.046520,-0.531571,+0.391918,+0.024824,-0.568450,+0.275106,+0.053855,-0.663931,+0.328224,+0.112829,-0.453549,+0.305788,+0.131265,-0.510617,+0.080746,+0.061174,-0.430716,-0.042710,+0.341019,-0.532887,-0.208150,+0.347705,-0.623533,-0.081139,+0.238040,-0.610732,-0.038037,+0.211764,-0.514274,-0.132078,+0.120605,-0.600219,-0.186856,+0.096985,-0.584476,-0.293357,+0.127621,-0.581941,-0.437170,+0.165902,-0.477425,-0.291453,+0.077720,-0.417975,-0.220519,+0.320892,-0.506363,-0.320874,+0.248214,-0.465684,-0.239842,+0.118764,-0.383338,-0.187114,+0.118816,-0.430106,-0.123307,+0.094131,-0.419464,-0.044777,+0.274526,-0.261706,+0.005110,+0.259842,-0.283292,-0.003185,+0.222861,-0.340431,-0.038210,+0.204445,-0.664380,+0.513353,+0.259286,-0.664547,+0.471281,+0.185402,-0.476020,+0.421718,+0.279163,-0.664604,+0.417328,+0.277157,-0.528122,+0.400208,+0.183069,-0.509812,+0.329995,+0.282599,-0.429210,+0.059242,+0.254816,-0.664541,+0.290687,+0.271436,-0.567707,+0.263966,+0.386561,-0.625221,-0.216870,+0.387086,-0.630883,-0.346073,+0.380021,-0.596021,-0.318679,+0.291269,-0.619007,-0.585707,+0.339280,-0.571198,-0.461946,+0.400045,-0.489778,-0.422640,+0.406817,-0.314349,-0.371230,+0.300588,-0.281718,-0.170549,+0.290866,-0.277304,-0.061905,+0.187735,-0.241545,+0.509437,+0.188032,-0.287569,+0.424234,+0.227520,-0.373262,+0.293102,+0.266526,-0.273650,+0.039597,+0.291592,-0.291676,+0.111386,+0.291914,-0.122741,+0.422683,+0.297574,-0.156119,+0.373368,+0.286603,-0.232731,+0.027162,+0.364663,-0.201399,+0.206850,+0.353855,-0.132408,+0.149228,+0.282208,-0.019715,+0.314960,+0.331187,-0.099266,+0.092701,+0.375463,-0.093120,-0.006467,+0.375917,-0.101236,-0.154882,+0.466635,-0.094416,-0.305669,+0.455805,-0.119881,-0.460632,+0.277465,-0.604242,-0.651871,+0.261022,-0.551176,-0.554667,+0.093627,+0.258494,-0.920589,+0.114248,+0.310608,-0.798070,+0.144232,+0.211434,-0.835001,+0.119916,+0.176940,-0.951159,+0.184061,+0.101854,-0.918220,+0.092431,+0.276521,-0.738231,+0.133504,+0.218403,-0.758602,+0.194987,+0.097655,-0.812476,+0.185542,+0.011005,-0.879202,+0.230315,-0.127450,-0.884202,+0.260471,+0.255056,-0.624378,+0.351567,-0.042194,-0.663976,+0.253742,+0.323524,-0.433716,+0.411612,+0.132299,-0.438264,+0.270513,+0.356530,-0.289984,+0.422146,+0.162819,-0.273130,+0.164724,+0.237490,+0.208912,+0.253806,+0.092900,+0.240640,+0.203608,+0.284597,+0.096223,+0.241006,+0.343093,-0.171396,+0.356076,+0.149288,-0.143443,+0.337656,+0.131992,+0.066374,}; + static const int tris[]={126,134,133,342,138,134,133,134,138,126,342,134,312,316,317,169,163,162,312,317,319,312,319,318,169,162,164,169,168,163,312,314,315,169,164,165,169,167,168,312,315,316,312,313,314,169,165,166,169,166,167,312,318,313,308,304,305,308,305,306,179,181,188,177,173,175,177,175,176,302,293,300,322,294,304,188,176,175,188,175,179,158,177,187,305,293,302,305,302,306,322,304,308,188,181,183,158,173,177,293,298,300,304,294,296,304,296,305,185,176,188,185,188,183,187,177,176,187,176,185,305,296,298,305,298,293,436,432, 28,436, 28, 23,434,278,431, 30,208,209, 30,209, 29, 19, 20, 24,208,207,211,208,211,209, 19,210,212,433,434,431,433,431,432,433,432,436,436,437,433,277,275,276,277,276,278,209,210, 25, 21, 26, 24, 21, 24, 20, 25, 26, 27, 25, 27, 29,435,439,277,439,275,277,432,431, 30,432, 30, 28,433,437,438,433,438,435,434,277,278, 24, 25,210, 24, 26, 25, 29, 27, 28, 29, 28, 30, 19, 24,210,208, 30,431,208,431,278,435,434,433,435,277,434, 25, 29,209, 27, 22, 23, 27, 23, 28, 26, 22, 27, 26, 21, 22,212,210,209,212,209,211,207,208,278,207,278,276,439,435,438, 12, 9, 10, 12, 10, 13, 2, 3, 5, 2, 5, 4, 16, 13, 14, 16, 14, 17, 22, 21, 16, 13, 10, 11, 13, 11, 14, 1, 0, 3, 1, 3, 2, 15, 12, 16, 19, 18, 15, 19, 15, 16, 19, 16, 20, 9, 1, 2, 9, 2, 10, 3, 7, 8, 3, 8, 5, 16, 17, 23, 16, 23, 22, 21, 20, 16, 10, 2, 4, 10, 4, 11, 0, 6, 7, 0, 7, 3, 12, 13, 16,451,446,445,451,445,450,442,440,439,442,439,438,442,438,441,421,420,422,412,411,426,412,426,425,408,405,407,413, 67, 68,413, 68,414,391,390,412, 80,384,386,404,406,378,390,391,377,390,377, 88,400,415,375,398,396,395,398,395,371,398,371,370,112,359,358,112,358,113,351,352,369,125,349,348,345,343,342,342,340,339,341,335,337,328,341,327,331,323,333,331,322,323,327,318,319,327,319,328,315,314,324,302,300,301,302,301,303,320,311,292,285,284,289,310,307,288,310,288,290,321,350,281,321,281,282,423,448,367,272,273,384,272,384,274,264,265,382,264,382,383,440,442,261,440,261,263,252,253,254,252,254,251,262,256,249,262,249,248,228,243,242,228, 31,243,213,215,238,213,238,237, 19,212,230,224,225,233,224,233,231,217,218, 56,217, 56, 54,217,216,239,217,239,238,217,238,215,218,217,215,218,215,214, 6,102,206,186,199,200,197,182,180,170,171,157,201,200,189,170,190,191,170,191,192,175,174,178,175,178,179,168,167,155,122,149,158,122,158,159,135,153,154,135,154,118,143,140,141,143,141,144,132,133,136,130,126,133,124,125,127,122,101,100,122,100,121,110,108,107,110,107,109, 98, 99, 97, 98, 97, 64, 98, 64, 66, 87, 55, 57, 83, 82, 79, 83, 79, 84, 78, 74, 50, 49, 71, 41, 49, 41, 37, 49, 37, 36, 58, 44, 60, 60, 59, 58, 51, 34, 33, 39, 40, 42, 39, 42, 38,243,240, 33,243, 33,229, 39, 38, 6, 44, 46, 40, 55, 56, 57, 64, 62, 65, 64, 65, 66, 41, 71, 45, 75, 50, 51, 81, 79, 82, 77, 88, 73, 93, 92, 94, 68, 47, 46, 96, 97, 99, 96, 99, 95,110,109,111,111,112,110,114,113,123,114,123,124,132,131,129,133,137,136,135,142,145,145,152,135,149,147,157,157,158,149,164,150,151,153,163,168,153,168,154,185,183,182,185,182,184,161,189,190,200,199,191,200,191,190,180,178,195,180,195,196,102,101,204,102,204,206, 43, 48,104, 43,104,103,216,217, 54,216, 54, 32,207,224,231,230,212,211,230,211,231,227,232,241,227,241,242,235,234,241,235,241,244,430,248,247,272,274,253,272,253,252,439,260,275,225,224,259,225,259,257,269,270,407,269,407,405,270,269,273,270,273,272,273,269,268,273,268,267,273,267,266,273,266,265,273,265,264,448,279,367,281,350,368,285,286,301,290,323,310,290,311,323,282,281,189,292,311,290,292,290,291,307,306,302,307,302,303,316,315,324,316,324,329,331,351,350,330,334,335,330,335,328,341,337,338,344,355,354,346,345,348,346,348,347,364,369,352,364,352,353,365,363,361,365,361,362,376,401,402,373,372,397,373,397,400,376, 92,377,381,378,387,381,387,385,386, 77, 80,390,389,412,416,417,401,403,417,415,408,429,430,419,423,418,427,428,444,427,444,446,437,436,441,450,445, 11,450, 11, 4,447,449, 5,447, 5, 8,441,438,437,425,426,451,425,451,452,417,421,415,408,407,429,399,403,400,399,400,397,394,393,416,389,411,412,386,383,385,408,387,378,408,378,406,377,391,376, 94,375,415,372,373,374,372,374,370,359,111,360,359,112,111,113,358,349,113,349,123,346,343,345,343,340,342,338,336,144,338,144,141,327,341,354,327,354,326,331,350,321,331,321,322,314,313,326,314,326,325,300,298,299,300,299,301,288,287,289,189,292,282,287,288,303,284,285,297,368,280,281,448,447,279,274,226,255,267,268,404,267,404,379,429,262,430,439,440,260,257,258,249,257,249,246,430,262,248,234,228,242,234,242,241,237,238,239,237,239,236, 15, 18,227, 15,227,229,222,223, 82,222, 82, 83,214,215,213,214,213, 81, 38,102, 6,122,159,200,122,200,201,174,171,192,174,192,194,197,193,198,190,170,161,181,179,178,181,178,180,166,156,155,163,153,152,163,152,162,120,156,149,120,149,121,152,153,135,140,143,142,135,131,132,135,132,136,130,129,128,130,128,127,100,105,119,100,119,120,106,104,107,106,107,108, 91, 95, 59, 93, 94, 68, 91, 89, 92, 76, 53, 55, 76, 55, 87, 81, 78, 79, 74, 73, 49, 69, 60, 45, 58, 62, 64, 58, 64, 61, 53, 31, 32, 32, 54, 53, 42, 43, 38, 35, 36, 0, 35, 0, 1, 34, 35, 1, 34, 1, 9, 44, 40, 41, 44, 41, 45, 33,240, 51, 63, 62, 58, 63, 58, 59, 45, 71, 70, 76, 75, 51, 76, 51, 52, 86, 85, 84, 86, 84, 87, 89, 72, 73, 89, 73, 88, 91, 92, 96, 91, 96, 95, 72, 91, 60, 72, 60, 69,104,106,105,119,105,117,119,117,118,124,127,128,117,116,129,117,129,131,118,117,131,135,140,142,146,150,152,146,152,145,149,122,121,166,165,151,166,151,156,158,172,173,161,160,189,199,198,193,199,193,191,204,201,202,178,174,194,200,159,186,109, 48, 67, 48,107,104,216, 32,236,216,236,239,223,214, 81,223, 81, 82, 33, 12, 15, 32,228,234, 32,234,236,240, 31, 52,256,255,246,256,246,249,258,263,248,258,248,249,275,260,259,275,259,276,207,276,259,270,271,429,270,429,407,413,418,366,413,366,365,368,367,279,368,279,280,303,301,286,303,286,287,283,282,292,283,292,291,320,292,189,298,296,297,298,297,299,318,327,326,318,326,313,329,330,317,336,333,320,326,354,353,334,332,333,334,333,336,342,339,139,342,139,138,345,342,126,347,357,356,369,368,351,363,356,357,363,357,361,366,367,368,366,368,369,375,373,400, 92, 90,377,409,387,408,386,385,387,386,387,388,412,394,391,396,398,399,408,406,405,415,421,419,415,419,414,425,452,448,425,448,424,444,441,443,448,452,449,448,449,447,446,444,443,446,443,445,250,247,261,250,261,428,421,422,423,421,423,419,427,410,250,417,403,401,403,402,401,420,392,412,420,412,425,420,425,424,386,411,389,383,382,381,383,381,385,378,379,404,372,371,395,372,395,397,371,372,370,361,359,360,361,360,362,368,350,351,349,347,348,356,355,344,356,344,346,344,341,340,344,340,343,338,337,336,328,335,341,324,352,351,324,351,331,320,144,336,314,325,324,322,308,309,310,309,307,287,286,289,203,280,279,203,279,205,297,295,283,297,283,284,447,205,279,274,384, 80,274, 80,226,266,267,379,266,379,380,225,257,246,225,246,245,256,254,253,256,253,255,430,247,250,226,235,244,226,244,245,232,233,244,232,244,241,230, 18, 19, 32, 31,228,219,220, 86,219, 86, 57,226,213,235,206, 7, 6,122,201,101,201,204,101,180,196,197,170,192,171,200,190,189,194,193,195,183,181,180,183,180,182,155,154,168,149,156,151,149,151,148,155,156,120,145,142,143,145,143,146,136,137,140,133,132,130,128,129,116,100,120,121,110,112,113,110,113,114, 66, 65, 63, 66, 63, 99, 66, 99, 98, 96, 46, 61, 89, 88, 90, 86, 87, 57, 80, 78, 81, 72, 69, 49, 67, 48, 47, 67, 47, 68, 56, 55, 53, 50, 49, 36, 50, 36, 35, 40, 39, 41,242,243,229,242,229,227, 6, 37, 39, 42, 47, 48, 42, 48, 43, 61, 46, 44, 45, 70, 69, 69, 70, 71, 69, 71, 49, 74, 78, 77, 83, 84, 85, 73, 74, 77, 93, 96, 92, 68, 46, 93, 95, 99, 63, 95, 63, 59,115,108,110,115,110,114,125,126,127,129,130,132,137,133,138,137,138,139,148,146,143,148,143,147,119,118,154,161,147,143,165,164,151,158,157,171,158,171,172,159,158,187,159,187,186,194,192,191,194,191,193,189,202,201,182,197,184,205, 8, 7, 48,109,107,218,219, 57,218, 57, 56,207,231,211,232,230,231,232,231,233, 53, 52, 31,388,411,386,409,430,250,262,429,254,262,254,256,442,444,428,273,264,383,273,383,384,429,271,251,429,251,254,413,365,362, 67,413,360,282,283,295,285,301,299,202,281,280,284,283,291,284,291,289,320,189,160,308,306,307,307,309,308,319,317,330,319,330,328,353,352,324,332,331,333,340,341,338,354,341,344,349,358,357,349,357,347,364,355,356,364,356,363,364,365,366,364,366,369,374,376,402,375, 92,373, 77,389,390,382,380,381,389, 77,386,393,394,412,393,412,392,401,394,416,415,400,403,411,410,427,411,427,426,422,420,424,247,248,263,247,263,261,445,443, 14,445, 14, 11,449,450, 4,449, 4, 5,443,441, 17,443, 17, 14,436, 23, 17,436, 17,441,424,448,422,448,423,422,414,419,418,414,418,413,406,404,405,399,397,395,399,395,396,420,416,392,388,410,411,386,384,383,390, 88, 77,375, 94, 92,415,414, 68,415, 68, 94,370,374,402,370,402,398,361,357,358,361,358,359,125,348,126,346,344,343,340,338,339,337,335,334,337,334,336,325,353,324,324,331,332,324,332,329,323,322,309,323,309,310,294,295,297,294,297,296,289,286,285,202,280,203,288,307,303,282,295,321, 67,360,111,418,423,367,418,367,366,272,252,251,272,251,271,272,271,270,255,253,274,265,266,380,265,380,382,442,428,261,440,263,258,440,258,260,409,250,410,255,226,245,255,245,246, 31,240,243,236,234,235,236,235,237,233,225,245,233,245,244,220,221, 85,220, 85, 86, 81,213,226, 81,226, 80, 7,206,205,186,184,198,186,198,199,204,203,205,204,205,206,195,193,196,171,174,172,173,174,175,173,172,174,155,167,166,160,161,143,160,143,144,119,154,155,148,151,150,148,150,146,140,137,139,140,139,141,127,126,130,114,124,128,114,128,115,117,105,106,117,106,116,104,105,100,104,100,103, 59, 60, 91, 97, 96, 61, 97, 61, 64, 91, 72, 89, 87, 84, 79, 87, 79, 76, 78, 80, 77, 49, 50, 74, 60, 44, 45, 61, 44, 58, 51, 50, 35, 51, 35, 34, 39, 37, 41, 33, 34, 9, 33, 9, 12, 0, 36, 37, 0, 37, 6, 40, 46, 47, 40, 47, 42, 53, 54, 56, 65, 62, 63, 72, 49, 73, 79, 78, 75, 79, 75, 76, 52, 53, 76, 92, 89, 90, 96, 93, 46,102,103,100,102,100,101,116,106,108,116,108,115,123,125,124,116,115,128,118,131,135,140,135,136,148,147,149,120,119,155,164,162,152,164,152,150,157,147,161,157,161,170,186,187,185,186,185,184,193,197,196,202,203,204,194,195,178,198,184,197, 67,111,109, 38, 43,103, 38,103,102,214,223,222,214,222,221,214,221,220,214,220,219,214,219,218,213,237,235,221,222, 83,221, 83, 85, 15,229, 33,227, 18,230,227,230,232, 52, 51,240, 75, 78, 50,408,430,409,260,258,257,260,257,259,224,207,259,268,269,405,268,405,404,413,362,360,447, 8,205,299,297,285,189,281,202,290,288,289,290,289,291,322,321,295,322,295,294,333,323,311,333,311,320,317,316,329,320,160,144,353,325,326,329,332,334,329,334,330,339,338,141,339,141,139,348,345,126,347,356,346,123,349,125,364,353,354,364,354,355,365,364,363,376,391,394,376,394,401, 92,376,374, 92,374,373,377, 90, 88,380,379,378,380,378,381,388,387,409,388,409,410,416,393,392,399,398,402,399,402,403,250,428,427,421,417,416,421,416,420,426,427,446,426,446,451,444,442,441,452,451,450,452,450,449,}; + enum { NUM_VERTS = countof(verts) / 3, NUM_TRIS = countof(tris) / 3 }; + + // Copy the geometry from the arrays of data into the arrays which we send to the reduction routine + for(int i = 0; i < NUM_VERTS; i++ ) { + const double *vp = &verts[i*3]; + array_push(m->in_vertex3, vec3(vp[0],vp[1],vp[2])); + } + for(int i = 0; i < NUM_TRIS; i++ ) { + const int *td = &tris[i*3]; + array_push(m->in_index3, vec3i(td[0],td[1],td[2])); + } + + int tri_n = array_count(m->in_index3); + int vert_n = array_count(m->in_vertex3); + int vert_stride = sizeof(float) * 3; + array(int) permutation = 0; + array_resize(m->lod_collapse_map, vert_n); + array_resize(permutation, vert_n); + ProgressiveMesh(vert_n, vert_stride, (const float *)m->in_vertex3, tri_n, (const int *)m->in_index3, m->lod_collapse_map, permutation); + // PermuteVertices { + ASSERT(array_count(permutation) == array_count(m->in_vertex3)); + // rearrange the vertex Array + array(vec3) tmp = 0; + for(int i = 0; i < array_count(m->in_vertex3); i++) array_push(tmp, m->in_vertex3[i]); + for(int i = 0; i < array_count(m->in_vertex3); i++) m->in_vertex3[permutation[i]]=tmp[i]; + // update the changes in the entries in the triangle Array + for (int i = 0; i < array_count(m->in_index3); i++) { + m->in_index3[i].x = permutation[m->in_index3[i].x]; + m->in_index3[i].y = permutation[m->in_index3[i].y]; + m->in_index3[i].z = permutation[m->in_index3[i].z]; + } + array_free(tmp); + // } PermuteVertices + array_free(permutation); +} + +int main() { + window_create(0.75, 0); + window_color(PURPLE); + + camera_t cam = camera(); + cam.speed /= 4; + cam.position = vec3(1.667,0.503,2.417); + camera_lookat(&cam, vec3(0,0,0)); + + mesh_t m = mesh(); + InitModel(&m); + + float lo_detail=0.25f; + float hi_detail=1.00f; + float morph=0.75f; + + while( window_swap() && !input(KEY_ESC) ) { + if( input(KEY_LALT) && input_down(KEY_Z) ) window_record(__FILE__ ".mp4"); + + // fps camera + if( input(GAMEPAD_CONNECTED) ) { + vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), 0.15f/*do_gamepad_deadzone*/ + 1e-3 ); + vec2 filtered_rpad = input_filter_deadzone(input2(GAMEPAD_RPAD), 0.15f/*do_gamepad_deadzone*/ + 1e-3 ); + vec2 mouse = scale2(vec2(filtered_rpad.x, filtered_rpad.y), 1.0f); + vec3 wasdec = scale3(vec3(filtered_lpad.x, input(GAMEPAD_LT) - input(GAMEPAD_RT), filtered_lpad.y), 1.0f); + camera_moveby(&cam, wasdec); + camera_fps(&cam, mouse.x,mouse.y); + window_cursor( true ); + } else { + bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); + if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f); + vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active); + vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed); + camera_moveby(&cam, wasdecq); + camera_fps(&cam, mouse.x,mouse.y); + window_cursor( !active ); + } + + profile("LOD generation") { + ReduceModel(&m, lo_detail, hi_detail, morph); + mesh_area(&m); + } + + DrawModel(&m); + + if( ui_panel("LODs", PANEL_OPEN) ) { + ui_label(va("Polys: %d/%d Vertices: %d/%d", array_count(m.out_index3), array_count(m.in_index3), (int)(lo_detail * array_count(m.in_vertex3)), (int)(hi_detail * array_count(m.in_vertex3)))); + if(ui_slider("Lo detail", &lo_detail)) { lo_detail = clampf(lo_detail, 0.01f, 1.0f); if(lo_detail > hi_detail) hi_detail = lo_detail; } + if(ui_slider("Hi detail", &hi_detail)) { hi_detail = clampf(hi_detail, 0.01f, 1.0f); if(hi_detail < lo_detail) lo_detail = hi_detail; } + ui_slider("Morph", &morph); + ui_panel_end(); + } + } +} diff --git a/demos/99-spine.c b/demos/99-spine.c index 5f2454b..5ea8812 100644 --- a/demos/99-spine.c +++ b/demos/99-spine.c @@ -394,8 +394,8 @@ void spine_render(spine_t *p, vec3 offset, unsigned flags) { float offsy = 0; // /*-(rect.z * p->texture.h)*2*/ -p->atlas[self->atlas_id].h - (self->rect_id ? p->skins[p->skin].rects[self->rect_id].h/2 : 0); float deg_rect = self->rect_id ? p->skins[p->skin].rects[self->rect_id].deg : 0; float tilt = p->atlas[self->atlas_id].deg + self->deg2 - deg_rect; // + self->deg2 + deg_rect + p->atlas[self->atlas_id].deg - unsigned tint = ~0u; - sprite_rect(p->texture, rect, zindex, add4(vec4(target.x,target.y,1,1),vec4(offsx,offsy,0,0)), tilt, tint); + unsigned tint = ~0u, flags = 0; + sprite_rect(p->texture, rect, vec4(target.x,target.y,0,zindex), vec4(1,1,offsx,offsy), tilt, tint, flags); } } @@ -510,12 +510,9 @@ void ui_spine(spine_t *p) { spine_atlas_t *r = p->atlas + b->atlas_id; sprite_flush(); camera_get_active()->position = vec3(0,0,2); - vec4 rect = ptr4(&r->x); float zindex = 0; vec3 xy_zoom = vec3(0,0,0); unsigned tint = ~0u; - sprite_rect(p->texture, - // rect: vec4(r->x*1.0/p->texture.w,r->y*1.0/p->texture.h,(r->x+r->w)*1.0/p->texture.w,(r->y+r->h)*1.0/p->texture.h), - ptr4(&r->x), // atlas - 0, vec4(0,0,1,1), r->deg + tilt, tint); - sprite_flush(); + vec4 rect = ptr4(&r->x); float zindex = 0; vec4 scale_offset = vec4(1,1,0,0); + sprite_rect(p->texture, ptr4(&r->x), vec4(0,0,0,zindex), scale_offset, r->deg + tilt, ~0u, 0); + sprite_flush(); camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); } } diff --git a/demos/99-sprite.c b/demos/99-sprite.c new file mode 100644 index 0000000..65c1acc --- /dev/null +++ b/demos/99-sprite.c @@ -0,0 +1,218 @@ +// sprite routines +// - rlyeh, +// +// credits: original lovely demo by rxi (MIT License). +// see https://github.com/rxi/autobatch/tree/master/demo/cats + +#include "v4k.h" + +texture_t kids, catImage, shadowImage, inputs; +int NUM_SPRITES = 100, NUM_SPRITES_CHANGED = 1; + +typedef struct Cat { + int cat, flip; + double x, y; + double vx, vy; + double animSpeed; + double moveTimer; + double elapsed; +} Cat; + +void demo_cats() { + static array(Cat) cats = 0; + + // init + if( NUM_SPRITES_CHANGED ) { + NUM_SPRITES_CHANGED = 0; + + array_resize(cats, NUM_SPRITES); int i = 0; + for each_array_ptr(cats, Cat, c) { + randset(i++); + c->x = randf() * window_width(); + c->y = randf() * window_height(); + c->vx = c->vy = 0; + c->cat = randi(0, 4); + c->flip = randf() < 0.5; + c->animSpeed = 0.8 + randf() * 0.3; + c->moveTimer = 0; + c->elapsed = 0; + } + } + + // move + const float dt = 1/120.f; + const int appw = window_width(), apph = window_height(); + + enum { yscale = 1 }; + for( int i = 0; i < NUM_SPRITES; ++i ) { + Cat *c = &cats[i]; + // Add velocity to position //and wrap to screen + c->x += yscale * c->vx * dt; // % ; + c->y += yscale * c->vy * dt; // % (int)window_height(); + if( c->x < 0 ) c->x += appw; else if( c->x > appw ) c->x -= appw; + if( c->y < 0 ) c->y += apph; else if( c->y > apph ) c->y -= apph; + // Faster animation if walking + int boost = c->vx == 0 && c->vy == 0 ? 1 : 3; + // Update elapsed time + c->elapsed += dt * boost; + // Update move timer -- if we hit zero then change or zero velocity + c->moveTimer -= dt * boost; + if (c->moveTimer < 0) { + if (randf() < .2) { + c->vx = (randf() * 2 - 1) * 30 * 2; + c->vy = (randf() * 2 - 1) * 15 * 2; + c->flip = c->vx < 0; + } else { + c->vx = c->vy = 0; + } + c->moveTimer = 1 + randf() * 5; + } + } + + // render + uint32_t white = rgba(255,255,255,255); + uint32_t alpha = rgba(255,255,255,255*0.6); + for( int i = 0; i < NUM_SPRITES; ++i ) { + Cat *c = &cats[i]; + // Get current animation frame (8x4 tilesheet) + double e = c->elapsed * c->animSpeed; + double frame_num = c->cat * 8 + floor( ((int)(e * 8)) % 4 ); + frame_num = c->vx != 0 || c->vy != 0 ? frame_num + 4 : frame_num; + // Get x scale based on flip flag + int xscale = yscale * (c->flip ? -1 : 1); + // Draw + float angle = 0; //fmod(window_time()*360/5, 360); + float scale[2] = { 2*xscale, 2*yscale }; + float position[3] = { c->x,c->y,c->y }, no_offset[2] = {0,0}, spritesheet[3] = { frame_num,8,4 }; + sprite_sheet(catImage, + spritesheet, // frame_number in a 8x4 spritesheet + position, angle, // position(x,y,depth: sort by Y), angle + no_offset, scale, // offset(x,y), scale(x,y) + white,0 // tint_color, flags + ); + float position_neg_sort[3] = { c->x,c->y,-c->y }, offset[2] = {-1,5}, no_spritesheet[3] = {0,0,0}; + sprite_sheet(shadowImage, + no_spritesheet, // no frame_number (0x0 spritesheet) + position_neg_sort, angle, // position(x,y,depth: sort by Y), angle + offset, scale, // offset(x,y), scale(x,y) + alpha,0 // tint_color, flags + ); + } +} + +void demo_kids() { + static int angle; //++angle; + static int *x, *y, *v; + + // init + if( NUM_SPRITES_CHANGED ) { + NUM_SPRITES_CHANGED = 0; + + y = (int*)REALLOC(y, 0 ); + x = (int*)REALLOC(x, NUM_SPRITES * sizeof(int) ); + y = (int*)REALLOC(y, NUM_SPRITES * sizeof(int) ); + v = (int*)REALLOC(v, NUM_SPRITES * sizeof(int) ); + for( int i = 0; i < NUM_SPRITES; ++i ) { + randset(i); + x[i] = randi(0, window_width()); + y[i] = randi(0, window_height()); + v[i] = randi(1, 3); + } + } + + // config + const int appw = window_width(), apph = window_height(); + + // move & render + for( int i = 0; i < NUM_SPRITES; ++i ) { + y[i] = (y[i] + v[i]) % (apph + 128); + int col = ((x[i] / 10) % 4); // 4x4 tilesheet + int row = ((y[i] / 10) % 4); + int num_frame = col * 4 + row; + float position[3] = {x[i],y[i],y[i]}, offset[2]={0,0}, scale[2]={1,1}, spritesheet[3]={num_frame,4,4}; + sprite_sheet(kids, + spritesheet, // num_frame in a 4x4 spritesheet + position, angle, // position(x,y,depth: sort by Y), angle + offset, scale, // offset(x,y), scale(x,y) + ~0u, 0 // tint color, flags + ); + } +} + +int main(int argc, char **argv) { + window_create(75.f, 0); + window_title("V4K - Sprite"); + window_color( SILVER ); + + // options + int do_cats = 1; + NUM_SPRITES = optioni("--num_sprites,-N", NUM_SPRITES); + if(do_cats) NUM_SPRITES/=2; // cat-sprite+cat-shadow == 2 sprites + + // load sprites and sheets + kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR ); + catImage = texture( "cat.png", TEXTURE_LINEAR ); // + shadowImage = texture( "cat-shadow.png", TEXTURE_LINEAR ); + inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR ); + + // load all fx files, including subdirs + fx_load("fx**.fs"); + + // init camera (x,y) (z = zoom) + camera_t cam = camera(); + cam.position = vec3(window_width()/2,window_height()/2,1); + camera_enable(&cam); + + while(window_swap()) { + if( input(KEY_F5)) window_reload(); + if( input(KEY_F11)) window_fullscreen( window_has_fullscreen() ^ 1); + if( input(KEY_ESC) ) break; + + // camera panning (x,y) & zooming (z) + if( !ui_hover() && !ui_active() ) { + if( input(MOUSE_L) ) cam.position.x -= input_diff(MOUSE_X); + if( input(MOUSE_L) ) cam.position.y -= input_diff(MOUSE_Y); + cam.position.z += input_diff(MOUSE_W) * 0.1; // cam.p.z += 0.001f; for tests + } + + // apply post-fxs from here + fx_begin(); + + profile("Sprite batching") { + if(do_cats) demo_cats(); else demo_kids(); + } + + // flush retained renderer, so we ensure the fbos are up to date before fx_end() + profile("Sprite flushing") { + sprite_flush(); + } + + // post-fxs end here + fx_end(); + + // draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way + { + vec3 old_pos = camera_get_active()->position; + + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + + float zindex = window_height(); // large number, on top + float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation + float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling + float position[3] = {window_width() - tile_w, window_height() - tile_h, zindex }; // position in screen-coordinates + sprite_sheet(inputs, spritesheet, position, 0/*rotation*/, offset, scale, WHITE, SPRITE_RESOLUTION_INDEPENDANT); + + sprite_flush(); + camera_get_active()->position = old_pos; + } + + if( ui_panel("Sprite", 0) ) { + const char *labels[] = {"Kids","Cats"}; + if( ui_list("Sprite type", labels, countof(labels), &do_cats) ) NUM_SPRITES_CHANGED = 1; + if( ui_int("Number of Sprites", &NUM_SPRITES) ) NUM_SPRITES_CHANGED = 1; + if( ui_clampf("Zoom", &cam.position.z, 0.1, 10)); + ui_panel_end(); + } + } +} diff --git a/demos/99-sprite2.c b/demos/99-sprite2.c new file mode 100644 index 0000000..13caa01 --- /dev/null +++ b/demos/99-sprite2.c @@ -0,0 +1,118 @@ +#include "v4k.h" + +void game(unsigned frame) { + static camera_t cam2d,cam3d; + static sprite_t *s1 = 0; + static sprite_t *s2 = 0; + static sprite_t *s3 = 0; + static sprite_t *s4 = 0; + if( !frame ) { + cam3d = camera(); + cam3d.damping = true; + + // camera center(x,y) zoom(z) + cam2d = camera(); + cam2d.position = vec3(window_width()/2,window_height()/2,8); + camera_enable(&cam2d); + + sprite_del(s1); + sprite_del(s2); + sprite_del(s3); + sprite_del(s4); + + s1 = sprite_new("Captain Clown Nose.ase", (int[6]){KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT,KEY_A,KEY_S}); + s2 = sprite_new("Crew-Crabby.ase", (int[6]){KEY_I,KEY_K,KEY_J,KEY_L} ); + s3 = sprite_new("Props-Shooter Traps.ase", (int[6]){0} ); + s4 = sprite_new("Crew-Fierce Tooth.ase", (int[6]){0,0,KEY_N,KEY_M} ); + + obj_setname(s1, "Cap"); + obj_setname(s2, "Crab"); + obj_setname(s3, "Cannon"); + obj_setname(s4, "Shark"); + + // 2d pos and z-order + // s1->pos = vec3(window_width()/2, window_height()/2, 2); + // s2->pos = vec3(window_width()/2, window_height()/2, 1); + // s3->pos = vec3(window_width()/2, window_height()/2, 1); + // s4->pos = vec3(window_width()/2, window_height()/2, 1); + + // 3d position+scale + s1->pos = s2->pos = s3->pos = s4->pos = vec4(0,1.5,0,0); + s1->sca = s2->sca = s3->sca = s4->sca = vec2(0.125,0.125); + // 3d zindex + s1->pos.w = 0; s2->pos.w = 0.1; s3->pos.w = 0.2; s4->pos.w = 0.3; + + s4->flipped ^= 1; + } + + // draw world + camera_enable(&cam3d); + ddraw_grid(0); + ddraw_flush(); + + // camera logic + enum { is_editing = 0 }; + if( is_editing ) { + if( !ui_hover() && !ui_active() ) { + // camera panning (x,y) & zooming (z) + if( input(MOUSE_L) ) cam2d.position.x -= input_diff(MOUSE_X); + if( input(MOUSE_L) ) cam2d.position.y -= input_diff(MOUSE_Y); + cam2d.position.z += input_diff(MOUSE_W) * 0.1; // cam2d.p.z += 0.001f; for tests + } + camera_enable(&cam2d); + } else { + + // fps camera + bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R); + if( active ) { + cam3d.speed = clampf(cam3d.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f); + vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active); + vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam3d.speed); + camera_moveby(&cam3d, wasdecq); + camera_fps(&cam3d, mouse.x,mouse.y); + } else { + camera_teleport(&cam3d, add3(s1->pos.xyz, vec3(0,10,20))); + camera_lookat(&cam3d, s1->pos.xyz); + } + + window_cursor( !active ); + } + + obj_tick(s1); + obj_draw(s1); + + obj_tick(s2); + obj_draw(s2); + + obj_tick(s3); + obj_draw(s3); + + obj_tick(s4); + obj_draw(s4); + + if( ui_panel("Help", 0) ) { + ui_label2("Freecam", ICON_MD_MOUSE " RMB"); + ui_label2("Captain", ICON_MD_KEYBOARD " Cursor keys"); + ui_label2("Crab", ICON_MD_KEYBOARD " I/K/J/L keys"); + ui_label2("Shark", ICON_MD_KEYBOARD " N/M"); + ui_panel_end(); + } + + if( ui_panel("Sprites", PANEL_OPEN)) { + obj_edit(s1); + obj_edit(s2); + obj_edit(s3); + obj_edit(s4); + ui_panel_end(); + } +} + +int main() { + unsigned frame = 0; + + for( window_create(0.75, 0); window_swap(); ) { + if( input_down(KEY_Z) && input(KEY_ALT) ) window_record(file_counter(va("%s.mp4",app_name()))); + if( input_down(KEY_F5) ) frame = 0; + game( frame++ ); + } +} \ No newline at end of file diff --git a/tools/editor/art/fx/editorOutline.fs b/engine/art/editor/fx/editorOutline.fs similarity index 100% rename from tools/editor/art/fx/editorOutline.fs rename to engine/art/editor/fx/editorOutline.fs diff --git a/tools/editor/art/icons/logo.ai b/engine/art/editor/icons/logo.ai similarity index 100% rename from tools/editor/art/icons/logo.ai rename to engine/art/editor/icons/logo.ai diff --git a/tools/editor/art/icons/logo.ico b/engine/art/editor/icons/logo.ico similarity index 100% rename from tools/editor/art/icons/logo.ico rename to engine/art/editor/icons/logo.ico diff --git a/tools/editor/art/icons/logo.license b/engine/art/editor/icons/logo.license similarity index 100% rename from tools/editor/art/icons/logo.license rename to engine/art/editor/icons/logo.license diff --git a/tools/editor/art/icons/logo.png b/engine/art/editor/icons/logo.png similarity index 100% rename from tools/editor/art/icons/logo.png rename to engine/art/editor/icons/logo.png diff --git a/tools/editor/art/icons/scale-ruler-icon.license b/engine/art/editor/icons/scale-ruler-icon.license similarity index 100% rename from tools/editor/art/icons/scale-ruler-icon.license rename to engine/art/editor/icons/scale-ruler-icon.license diff --git a/tools/editor/art/icons/scale-ruler-icon.png b/engine/art/editor/icons/scale-ruler-icon.png similarity index 100% rename from tools/editor/art/icons/scale-ruler-icon.png rename to engine/art/editor/icons/scale-ruler-icon.png diff --git a/tools/editor/art/icons/scale-ruler-icon.svg b/engine/art/editor/icons/scale-ruler-icon.svg similarity index 100% rename from tools/editor/art/icons/scale-ruler-icon.svg rename to engine/art/editor/icons/scale-ruler-icon.svg diff --git a/tools/editor/art/lite/data/core/command.lua b/engine/art/editor/lite/data/core/command.lua similarity index 100% rename from tools/editor/art/lite/data/core/command.lua rename to engine/art/editor/lite/data/core/command.lua diff --git a/tools/editor/art/lite/data/core/commands/command.lua b/engine/art/editor/lite/data/core/commands/command.lua similarity index 100% rename from tools/editor/art/lite/data/core/commands/command.lua rename to engine/art/editor/lite/data/core/commands/command.lua diff --git a/tools/editor/art/lite/data/core/commands/core.lua b/engine/art/editor/lite/data/core/commands/core.lua similarity index 100% rename from tools/editor/art/lite/data/core/commands/core.lua rename to engine/art/editor/lite/data/core/commands/core.lua diff --git a/tools/editor/art/lite/data/core/commands/doc.lua b/engine/art/editor/lite/data/core/commands/doc.lua similarity index 100% rename from tools/editor/art/lite/data/core/commands/doc.lua rename to engine/art/editor/lite/data/core/commands/doc.lua diff --git a/tools/editor/art/lite/data/core/commands/findreplace.lua b/engine/art/editor/lite/data/core/commands/findreplace.lua similarity index 100% rename from tools/editor/art/lite/data/core/commands/findreplace.lua rename to engine/art/editor/lite/data/core/commands/findreplace.lua diff --git a/tools/editor/art/lite/data/core/commands/root.lua b/engine/art/editor/lite/data/core/commands/root.lua similarity index 100% rename from tools/editor/art/lite/data/core/commands/root.lua rename to engine/art/editor/lite/data/core/commands/root.lua diff --git a/tools/editor/art/lite/data/core/commandview.lua b/engine/art/editor/lite/data/core/commandview.lua similarity index 100% rename from tools/editor/art/lite/data/core/commandview.lua rename to engine/art/editor/lite/data/core/commandview.lua diff --git a/tools/editor/art/lite/data/core/common.lua b/engine/art/editor/lite/data/core/common.lua similarity index 100% rename from tools/editor/art/lite/data/core/common.lua rename to engine/art/editor/lite/data/core/common.lua diff --git a/tools/editor/art/lite/data/core/config.lua b/engine/art/editor/lite/data/core/config.lua similarity index 100% rename from tools/editor/art/lite/data/core/config.lua rename to engine/art/editor/lite/data/core/config.lua diff --git a/tools/editor/art/lite/data/core/doc/highlighter.lua b/engine/art/editor/lite/data/core/doc/highlighter.lua similarity index 100% rename from tools/editor/art/lite/data/core/doc/highlighter.lua rename to engine/art/editor/lite/data/core/doc/highlighter.lua diff --git a/tools/editor/art/lite/data/core/doc/init.lua b/engine/art/editor/lite/data/core/doc/init.lua similarity index 100% rename from tools/editor/art/lite/data/core/doc/init.lua rename to engine/art/editor/lite/data/core/doc/init.lua diff --git a/tools/editor/art/lite/data/core/doc/search.lua b/engine/art/editor/lite/data/core/doc/search.lua similarity index 100% rename from tools/editor/art/lite/data/core/doc/search.lua rename to engine/art/editor/lite/data/core/doc/search.lua diff --git a/tools/editor/art/lite/data/core/doc/translate.lua b/engine/art/editor/lite/data/core/doc/translate.lua similarity index 100% rename from tools/editor/art/lite/data/core/doc/translate.lua rename to engine/art/editor/lite/data/core/doc/translate.lua diff --git a/tools/editor/art/lite/data/core/docview.lua b/engine/art/editor/lite/data/core/docview.lua similarity index 100% rename from tools/editor/art/lite/data/core/docview.lua rename to engine/art/editor/lite/data/core/docview.lua diff --git a/tools/editor/art/lite/data/core/init.lua b/engine/art/editor/lite/data/core/init.lua similarity index 100% rename from tools/editor/art/lite/data/core/init.lua rename to engine/art/editor/lite/data/core/init.lua diff --git a/tools/editor/art/lite/data/core/keymap.lua b/engine/art/editor/lite/data/core/keymap.lua similarity index 100% rename from tools/editor/art/lite/data/core/keymap.lua rename to engine/art/editor/lite/data/core/keymap.lua diff --git a/tools/editor/art/lite/data/core/logview.lua b/engine/art/editor/lite/data/core/logview.lua similarity index 100% rename from tools/editor/art/lite/data/core/logview.lua rename to engine/art/editor/lite/data/core/logview.lua diff --git a/tools/editor/art/lite/data/core/node.lua b/engine/art/editor/lite/data/core/node.lua similarity index 100% rename from tools/editor/art/lite/data/core/node.lua rename to engine/art/editor/lite/data/core/node.lua diff --git a/tools/editor/art/lite/data/core/object.lua b/engine/art/editor/lite/data/core/object.lua similarity index 100% rename from tools/editor/art/lite/data/core/object.lua rename to engine/art/editor/lite/data/core/object.lua diff --git a/tools/editor/art/lite/data/core/rootview.lua b/engine/art/editor/lite/data/core/rootview.lua similarity index 100% rename from tools/editor/art/lite/data/core/rootview.lua rename to engine/art/editor/lite/data/core/rootview.lua diff --git a/tools/editor/art/lite/data/core/statusview.lua b/engine/art/editor/lite/data/core/statusview.lua similarity index 100% rename from tools/editor/art/lite/data/core/statusview.lua rename to engine/art/editor/lite/data/core/statusview.lua diff --git a/tools/editor/art/lite/data/core/strict.lua b/engine/art/editor/lite/data/core/strict.lua similarity index 100% rename from tools/editor/art/lite/data/core/strict.lua rename to engine/art/editor/lite/data/core/strict.lua diff --git a/tools/editor/art/lite/data/core/style.lua b/engine/art/editor/lite/data/core/style.lua similarity index 100% rename from tools/editor/art/lite/data/core/style.lua rename to engine/art/editor/lite/data/core/style.lua diff --git a/tools/editor/art/lite/data/core/syntax.lua b/engine/art/editor/lite/data/core/syntax.lua similarity index 100% rename from tools/editor/art/lite/data/core/syntax.lua rename to engine/art/editor/lite/data/core/syntax.lua diff --git a/tools/editor/art/lite/data/core/tokenizer.lua b/engine/art/editor/lite/data/core/tokenizer.lua similarity index 100% rename from tools/editor/art/lite/data/core/tokenizer.lua rename to engine/art/editor/lite/data/core/tokenizer.lua diff --git a/tools/editor/art/lite/data/core/view.lua b/engine/art/editor/lite/data/core/view.lua similarity index 100% rename from tools/editor/art/lite/data/core/view.lua rename to engine/art/editor/lite/data/core/view.lua diff --git a/tools/editor/art/lite/data/fonts/font.ttf b/engine/art/editor/lite/data/fonts/font.ttf similarity index 100% rename from tools/editor/art/lite/data/fonts/font.ttf rename to engine/art/editor/lite/data/fonts/font.ttf diff --git a/tools/editor/art/lite/data/fonts/icons.ttf b/engine/art/editor/lite/data/fonts/icons.ttf similarity index 100% rename from tools/editor/art/lite/data/fonts/icons.ttf rename to engine/art/editor/lite/data/fonts/icons.ttf diff --git a/tools/editor/art/lite/data/fonts/monospace.ttf b/engine/art/editor/lite/data/fonts/monospace.ttf similarity index 100% rename from tools/editor/art/lite/data/fonts/monospace.ttf rename to engine/art/editor/lite/data/fonts/monospace.ttf diff --git a/tools/editor/art/lite/data/languages/language_bat.lua b/engine/art/editor/lite/data/languages/language_bat.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_bat.lua rename to engine/art/editor/lite/data/languages/language_bat.lua diff --git a/tools/editor/art/lite/data/languages/language_batch.lua b/engine/art/editor/lite/data/languages/language_batch.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_batch.lua rename to engine/art/editor/lite/data/languages/language_batch.lua diff --git a/tools/editor/art/lite/data/languages/language_c.lua b/engine/art/editor/lite/data/languages/language_c.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_c.lua rename to engine/art/editor/lite/data/languages/language_c.lua diff --git a/tools/editor/art/lite/data/languages/language_cpp.lua b/engine/art/editor/lite/data/languages/language_cpp.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_cpp.lua rename to engine/art/editor/lite/data/languages/language_cpp.lua diff --git a/tools/editor/art/lite/data/languages/language_csharp.lua b/engine/art/editor/lite/data/languages/language_csharp.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_csharp.lua rename to engine/art/editor/lite/data/languages/language_csharp.lua diff --git a/tools/editor/art/lite/data/languages/language_css.lua b/engine/art/editor/lite/data/languages/language_css.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_css.lua rename to engine/art/editor/lite/data/languages/language_css.lua diff --git a/tools/editor/art/lite/data/languages/language_glsl.lua b/engine/art/editor/lite/data/languages/language_glsl.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_glsl.lua rename to engine/art/editor/lite/data/languages/language_glsl.lua diff --git a/tools/editor/art/lite/data/languages/language_hlsl.lua b/engine/art/editor/lite/data/languages/language_hlsl.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_hlsl.lua rename to engine/art/editor/lite/data/languages/language_hlsl.lua diff --git a/tools/editor/art/lite/data/languages/language_js.lua b/engine/art/editor/lite/data/languages/language_js.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_js.lua rename to engine/art/editor/lite/data/languages/language_js.lua diff --git a/tools/editor/art/lite/data/languages/language_lua.lua b/engine/art/editor/lite/data/languages/language_lua.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_lua.lua rename to engine/art/editor/lite/data/languages/language_lua.lua diff --git a/tools/editor/art/lite/data/languages/language_md.lua b/engine/art/editor/lite/data/languages/language_md.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_md.lua rename to engine/art/editor/lite/data/languages/language_md.lua diff --git a/tools/editor/art/lite/data/languages/language_moon.lua b/engine/art/editor/lite/data/languages/language_moon.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_moon.lua rename to engine/art/editor/lite/data/languages/language_moon.lua diff --git a/tools/editor/art/lite/data/languages/language_nim.lua b/engine/art/editor/lite/data/languages/language_nim.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_nim.lua rename to engine/art/editor/lite/data/languages/language_nim.lua diff --git a/tools/editor/art/lite/data/languages/language_odin.lua b/engine/art/editor/lite/data/languages/language_odin.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_odin.lua rename to engine/art/editor/lite/data/languages/language_odin.lua diff --git a/tools/editor/art/lite/data/languages/language_python.lua b/engine/art/editor/lite/data/languages/language_python.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_python.lua rename to engine/art/editor/lite/data/languages/language_python.lua diff --git a/tools/editor/art/lite/data/languages/language_teal.lua b/engine/art/editor/lite/data/languages/language_teal.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_teal.lua rename to engine/art/editor/lite/data/languages/language_teal.lua diff --git a/tools/editor/art/lite/data/languages/language_ts.lua b/engine/art/editor/lite/data/languages/language_ts.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_ts.lua rename to engine/art/editor/lite/data/languages/language_ts.lua diff --git a/tools/editor/art/lite/data/languages/language_wren.lua b/engine/art/editor/lite/data/languages/language_wren.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_wren.lua rename to engine/art/editor/lite/data/languages/language_wren.lua diff --git a/tools/editor/art/lite/data/languages/language_xml.lua b/engine/art/editor/lite/data/languages/language_xml.lua similarity index 100% rename from tools/editor/art/lite/data/languages/language_xml.lua rename to engine/art/editor/lite/data/languages/language_xml.lua diff --git a/tools/editor/art/lite/data/lite.license b/engine/art/editor/lite/data/lite.license similarity index 100% rename from tools/editor/art/lite/data/lite.license rename to engine/art/editor/lite/data/lite.license diff --git a/tools/editor/art/lite/data/lite.readme b/engine/art/editor/lite/data/lite.readme similarity index 100% rename from tools/editor/art/lite/data/lite.readme rename to engine/art/editor/lite/data/lite.readme diff --git a/tools/editor/art/lite/data/lite.usage b/engine/art/editor/lite/data/lite.usage similarity index 100% rename from tools/editor/art/lite/data/lite.usage rename to engine/art/editor/lite/data/lite.usage diff --git a/engine/art/editor/lite/data/plugins/autocomplete.lua b/engine/art/editor/lite/data/plugins/autocomplete.lua new file mode 100644 index 0000000..79e4513 --- /dev/null +++ b/engine/art/editor/lite/data/plugins/autocomplete.lua @@ -0,0 +1,284 @@ +local core = require "core" +local common = require "core.common" +local config = require "core.config" +local command = require "core.command" +local style = require "core.style" +local keymap = require "core.keymap" +local translate = require "core.doc.translate" +local RootView = require "core.rootview" +local DocView = require "core.docview" + +config.autocomplete_max_suggestions = 6 + +local autocomplete = {} +autocomplete.map = {} + + +local mt = { __tostring = function(t) return t.text end } + +function autocomplete.add(t) + local items = {} + for text, info in pairs(t.items) do + info = (type(info) == "string") and info + table.insert(items, setmetatable({ text = text, info = info }, mt)) + end + autocomplete.map[t.name] = { files = t.files or ".*", items = items } +end + + +core.add_thread(function() + local cache = setmetatable({}, { __mode = "k" }) + + local function get_symbols(doc) + local i = 1 + local s = {} + while i < #doc.lines do + for sym in doc.lines[i]:gmatch(config.symbol_pattern) do + s[sym] = true + end + i = i + 1 + if i % 100 == 0 then coroutine.yield() end + end + return s + end + + local function cache_is_valid(doc) + local c = cache[doc] + return c and c.last_change_id == doc:get_change_id() + end + + while true do + local symbols = {} + + -- lift all symbols from all docs + for _, doc in ipairs(core.docs) do + -- update the cache if the doc has changed since the last iteration + if not cache_is_valid(doc) then + cache[doc] = { + last_change_id = doc:get_change_id(), + symbols = get_symbols(doc) + } + end + -- update symbol set with doc's symbol set + for sym in pairs(cache[doc].symbols) do + symbols[sym] = true + end + coroutine.yield() + end + + -- update symbols list + autocomplete.add { name = "open-docs", items = symbols } + + -- wait for next scan + local valid = true + while valid do + coroutine.yield(1) + for _, doc in ipairs(core.docs) do + if not cache_is_valid(doc) then + valid = false + end + end + end + + end +end) + + +local partial = "" +local suggestions_idx = 1 +local suggestions = {} +local last_line, last_col + + +local function reset_suggestions() + suggestions_idx = 1 + suggestions = {} +end + + +local function update_suggestions() + local doc = core.active_view.doc + local filename = doc and doc.filename or "" + + -- get all relevant suggestions for given filename + local items = {} + for _, v in pairs(autocomplete.map) do + if common.match_pattern(filename, v.files) then + for _, item in pairs(v.items) do + table.insert(items, item) + end + end + end + + -- fuzzy match, remove duplicates and store + items = common.fuzzy_match(items, partial) + local j = 1 + for i = 1, config.autocomplete_max_suggestions do + suggestions[i] = items[j] + while items[j] and items[i].text == items[j].text do + items[i].info = items[i].info or items[j].info + j = j + 1 + end + end +end + + +local function get_partial_symbol() + local doc = core.active_view.doc + local line2, col2 = doc:get_selection() + local line1, col1 = doc:position_offset(line2, col2, translate.start_of_word) + return doc:get_text(line1, col1, line2, col2) +end + + +local function get_active_view() + if getmetatable(core.active_view) == DocView then + return core.active_view + end +end + + +local function get_suggestions_rect(av) + if #suggestions == 0 then + return 0, 0, 0, 0 + end + + local line, col = av.doc:get_selection() + local x, y = av:get_line_screen_position(line) + x = x + av:get_col_x_offset(line, col - #partial) + y = y + av:get_line_height() + style.padding.y + local font = av:get_font() + local th = font:get_height() + + local max_width = 0 + for _, s in ipairs(suggestions) do + local w = font:get_width(s.text) + if s.info then + w = w + style.font:get_width(s.info) + style.padding.x + end + max_width = math.max(max_width, w) + end + + return + x - style.padding.x, + y - style.padding.y, + max_width + style.padding.x * 2, + #suggestions * (th + style.padding.y) + style.padding.y +end + + +local function draw_suggestions_box(av) + -- draw background rect + local rx, ry, rw, rh = get_suggestions_rect(av) + renderer.draw_rect(rx, ry, rw, rh, style.background3) + + -- draw text + local font = av:get_font() + local lh = font:get_height() + style.padding.y + local y = ry + style.padding.y / 2 + for i, s in ipairs(suggestions) do + local color = (i == suggestions_idx) and style.accent or style.text + common.draw_text(font, color, s.text, "left", rx + style.padding.x, y, rw, lh) + if s.info then + color = (i == suggestions_idx) and style.text or style.dim + common.draw_text(style.font, color, s.info, "right", rx, y, rw - style.padding.x, lh) + end + y = y + lh + end +end + + +-- patch event logic into RootView +local on_text_input = RootView.on_text_input +local update = RootView.update +local draw = RootView.draw + + +RootView.on_text_input = function(...) + on_text_input(...) + + local av = get_active_view() + if av then + -- update partial symbol and suggestions + partial = get_partial_symbol() + if #partial >= 3 then + update_suggestions() + last_line, last_col = av.doc:get_selection() + else + reset_suggestions() + end + + -- scroll if rect is out of bounds of view + local _, y, _, h = get_suggestions_rect(av) + local limit = av.position.y + av.size.y + if y + h > limit then + av.scroll.to.y = av.scroll.y + y + h - limit + end + end +end + + +RootView.update = function(...) + update(...) + + local av = get_active_view() + if av then + -- reset suggestions if caret was moved + local line, col = av.doc:get_selection() + if line ~= last_line or col ~= last_col then + reset_suggestions() + end + end +end + + +RootView.draw = function(...) + draw(...) + + local av = get_active_view() + if av then + -- draw suggestions box after everything else + core.root_view:defer_draw(draw_suggestions_box, av) + end +end + + +local function predicate() + return get_active_view() and #suggestions > 0 +end + + +command.add(predicate, { + ["autocomplete:complete"] = function() + local doc = core.active_view.doc + local line, col = doc:get_selection() + local text = suggestions[suggestions_idx].text + doc:insert(line, col, text) + doc:remove(line, col, line, col - #partial) + doc:set_selection(line, col + #text - #partial) + reset_suggestions() + end, + + ["autocomplete:previous"] = function() + suggestions_idx = math.max(suggestions_idx - 1, 1) + end, + + ["autocomplete:next"] = function() + suggestions_idx = math.min(suggestions_idx + 1, #suggestions) + end, + + ["autocomplete:cancel"] = function() + reset_suggestions() + end, +}) + + +keymap.add { + ["tab"] = "autocomplete:complete", + ["up"] = "autocomplete:previous", + ["down"] = "autocomplete:next", + ["escape"] = "autocomplete:cancel", +} + + +return autocomplete diff --git a/tools/editor/art/lite/data/plugins/autoinsert.lua b/engine/art/editor/lite/data/plugins/autoinsert.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/autoinsert.lua rename to engine/art/editor/lite/data/plugins/autoinsert.lua diff --git a/engine/art/editor/lite/data/plugins/autoreload.lua b/engine/art/editor/lite/data/plugins/autoreload.lua new file mode 100644 index 0000000..a077b6d --- /dev/null +++ b/engine/art/editor/lite/data/plugins/autoreload.lua @@ -0,0 +1,61 @@ +local core = require "core" +local config = require "core.config" +local Doc = require "core.doc" + + +local times = setmetatable({}, { __mode = "k" }) + +local function update_time(doc) + local info = system.get_file_info(doc.filename) + times[doc] = info.modified +end + + +local function reload_doc(doc) + local fp = io.open(doc.filename, "r") + local text = fp:read("*a") + fp:close() + + local sel = { doc:get_selection() } + doc:remove(1, 1, math.huge, math.huge) + doc:insert(1, 1, text:gsub("\r", ""):gsub("\n$", "")) + doc:set_selection(table.unpack(sel)) + + update_time(doc) + doc:clean() + core.log_quiet("Auto-reloaded doc \"%s\"", doc.filename) +end + + +core.add_thread(function() + while true do + -- check all doc modified times + for _, doc in ipairs(core.docs) do + local info = system.get_file_info(doc.filename or "") + if info and times[doc] ~= info.modified then + reload_doc(doc) + end + coroutine.yield() + end + + -- wait for next scan + coroutine.yield(config.project_scan_rate) + end +end) + + +-- patch `Doc.save|load` to store modified time +local load = Doc.load +local save = Doc.save + +Doc.load = function(self, ...) + local res = load(self, ...) + update_time(self) + return res +end + +Doc.save = function(self, ...) + local res = save(self, ...) + update_time(self) + return res +end diff --git a/tools/editor/art/lite/data/plugins/autowrap.lua b/engine/art/editor/lite/data/plugins/autowrap.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/autowrap.lua rename to engine/art/editor/lite/data/plugins/autowrap.lua diff --git a/tools/editor/art/lite/data/plugins/bracketmatch.lua b/engine/art/editor/lite/data/plugins/bracketmatch.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/bracketmatch.lua rename to engine/art/editor/lite/data/plugins/bracketmatch.lua diff --git a/tools/editor/art/lite/data/plugins/closeconfirmx.lua b/engine/art/editor/lite/data/plugins/closeconfirmx.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/closeconfirmx.lua rename to engine/art/editor/lite/data/plugins/closeconfirmx.lua diff --git a/tools/editor/art/lite/data/plugins/colorpreview.lua b/engine/art/editor/lite/data/plugins/colorpreview.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/colorpreview.lua rename to engine/art/editor/lite/data/plugins/colorpreview.lua diff --git a/tools/editor/art/lite/data/plugins/console.lua b/engine/art/editor/lite/data/plugins/console.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/console.lua rename to engine/art/editor/lite/data/plugins/console.lua diff --git a/tools/editor/art/lite/data/plugins/contextmenu.lua b/engine/art/editor/lite/data/plugins/contextmenu.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/contextmenu.lua rename to engine/art/editor/lite/data/plugins/contextmenu.lua diff --git a/tools/editor/art/lite/data/plugins/detectindent.lua b/engine/art/editor/lite/data/plugins/detectindent.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/detectindent.lua rename to engine/art/editor/lite/data/plugins/detectindent.lua diff --git a/tools/editor/art/lite/data/plugins/drawwhitespace.lua b/engine/art/editor/lite/data/plugins/drawwhitespace.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/drawwhitespace.lua rename to engine/art/editor/lite/data/plugins/drawwhitespace.lua diff --git a/tools/editor/art/lite/data/plugins/eofnewline.lua b/engine/art/editor/lite/data/plugins/eofnewline.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/eofnewline.lua rename to engine/art/editor/lite/data/plugins/eofnewline.lua diff --git a/tools/editor/art/lite/data/plugins/fsutils.lua b/engine/art/editor/lite/data/plugins/fsutils.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/fsutils.lua rename to engine/art/editor/lite/data/plugins/fsutils.lua diff --git a/tools/editor/art/lite/data/plugins/indentguide.lua b/engine/art/editor/lite/data/plugins/indentguide.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/indentguide.lua rename to engine/art/editor/lite/data/plugins/indentguide.lua diff --git a/tools/editor/art/lite/data/plugins/lfautoinsert.lua b/engine/art/editor/lite/data/plugins/lfautoinsert.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/lfautoinsert.lua rename to engine/art/editor/lite/data/plugins/lfautoinsert.lua diff --git a/tools/editor/art/lite/data/plugins/lineguide.lua b/engine/art/editor/lite/data/plugins/lineguide.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/lineguide.lua rename to engine/art/editor/lite/data/plugins/lineguide.lua diff --git a/tools/editor/art/lite/data/plugins/macro.lua b/engine/art/editor/lite/data/plugins/macro.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/macro.lua rename to engine/art/editor/lite/data/plugins/macro.lua diff --git a/tools/editor/art/lite/data/plugins/markers.lua b/engine/art/editor/lite/data/plugins/markers.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/markers.lua rename to engine/art/editor/lite/data/plugins/markers.lua diff --git a/tools/editor/art/lite/data/plugins/minimap.lua b/engine/art/editor/lite/data/plugins/minimap.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/minimap.lua rename to engine/art/editor/lite/data/plugins/minimap.lua diff --git a/tools/editor/art/lite/data/plugins/motiontrail.lua b/engine/art/editor/lite/data/plugins/motiontrail.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/motiontrail.lua rename to engine/art/editor/lite/data/plugins/motiontrail.lua diff --git a/tools/editor/art/lite/data/plugins/openfilelocation.lua b/engine/art/editor/lite/data/plugins/openfilelocation.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/openfilelocation.lua rename to engine/art/editor/lite/data/plugins/openfilelocation.lua diff --git a/tools/editor/art/lite/data/plugins/projectsearch.lua b/engine/art/editor/lite/data/plugins/projectsearch.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/projectsearch.lua rename to engine/art/editor/lite/data/plugins/projectsearch.lua diff --git a/tools/editor/art/lite/data/plugins/quote.lua b/engine/art/editor/lite/data/plugins/quote.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/quote.lua rename to engine/art/editor/lite/data/plugins/quote.lua diff --git a/tools/editor/art/lite/data/plugins/rainbowparen.lua b/engine/art/editor/lite/data/plugins/rainbowparen.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/rainbowparen.lua rename to engine/art/editor/lite/data/plugins/rainbowparen.lua diff --git a/tools/editor/art/lite/data/plugins/reflow.lua b/engine/art/editor/lite/data/plugins/reflow.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/reflow.lua rename to engine/art/editor/lite/data/plugins/reflow.lua diff --git a/tools/editor/art/lite/data/plugins/scale.lua b/engine/art/editor/lite/data/plugins/scale.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/scale.lua rename to engine/art/editor/lite/data/plugins/scale.lua diff --git a/tools/editor/art/lite/data/plugins/scalestatus.lua b/engine/art/editor/lite/data/plugins/scalestatus.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/scalestatus.lua rename to engine/art/editor/lite/data/plugins/scalestatus.lua diff --git a/tools/editor/art/lite/data/plugins/selectionhighlight.lua b/engine/art/editor/lite/data/plugins/selectionhighlight.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/selectionhighlight.lua rename to engine/art/editor/lite/data/plugins/selectionhighlight.lua diff --git a/tools/editor/art/lite/data/plugins/sort.lua b/engine/art/editor/lite/data/plugins/sort.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/sort.lua rename to engine/art/editor/lite/data/plugins/sort.lua diff --git a/tools/editor/art/lite/data/plugins/tabularize.lua b/engine/art/editor/lite/data/plugins/tabularize.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/tabularize.lua rename to engine/art/editor/lite/data/plugins/tabularize.lua diff --git a/tools/editor/art/lite/data/plugins/todotreeview.lua b/engine/art/editor/lite/data/plugins/todotreeview.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/todotreeview.lua rename to engine/art/editor/lite/data/plugins/todotreeview.lua diff --git a/tools/editor/art/lite/data/plugins/treeview.lua b/engine/art/editor/lite/data/plugins/treeview.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/treeview.lua rename to engine/art/editor/lite/data/plugins/treeview.lua diff --git a/tools/editor/art/lite/data/plugins/trimwhitespace.lua b/engine/art/editor/lite/data/plugins/trimwhitespace.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/trimwhitespace.lua rename to engine/art/editor/lite/data/plugins/trimwhitespace.lua diff --git a/tools/editor/art/lite/data/plugins/workspace.lua b/engine/art/editor/lite/data/plugins/workspace.lua similarity index 100% rename from tools/editor/art/lite/data/plugins/workspace.lua rename to engine/art/editor/lite/data/plugins/workspace.lua diff --git a/tools/editor/art/lite/data/themes/abyss.lua b/engine/art/editor/lite/data/themes/abyss.lua similarity index 100% rename from tools/editor/art/lite/data/themes/abyss.lua rename to engine/art/editor/lite/data/themes/abyss.lua diff --git a/tools/editor/art/lite/data/themes/cold_lime.lua b/engine/art/editor/lite/data/themes/cold_lime.lua similarity index 100% rename from tools/editor/art/lite/data/themes/cold_lime.lua rename to engine/art/editor/lite/data/themes/cold_lime.lua diff --git a/tools/editor/art/lite/data/themes/dracula.lua b/engine/art/editor/lite/data/themes/dracula.lua similarity index 100% rename from tools/editor/art/lite/data/themes/dracula.lua rename to engine/art/editor/lite/data/themes/dracula.lua diff --git a/tools/editor/art/lite/data/themes/duorand.lua b/engine/art/editor/lite/data/themes/duorand.lua similarity index 100% rename from tools/editor/art/lite/data/themes/duorand.lua rename to engine/art/editor/lite/data/themes/duorand.lua diff --git a/tools/editor/art/lite/data/themes/duotone.lua b/engine/art/editor/lite/data/themes/duotone.lua similarity index 100% rename from tools/editor/art/lite/data/themes/duotone.lua rename to engine/art/editor/lite/data/themes/duotone.lua diff --git a/tools/editor/art/lite/data/themes/fall.lua b/engine/art/editor/lite/data/themes/fall.lua similarity index 100% rename from tools/editor/art/lite/data/themes/fall.lua rename to engine/art/editor/lite/data/themes/fall.lua diff --git a/tools/editor/art/lite/data/themes/fwk.lua b/engine/art/editor/lite/data/themes/fwk.lua similarity index 100% rename from tools/editor/art/lite/data/themes/fwk.lua rename to engine/art/editor/lite/data/themes/fwk.lua diff --git a/tools/editor/art/lite/data/themes/github.lua b/engine/art/editor/lite/data/themes/github.lua similarity index 100% rename from tools/editor/art/lite/data/themes/github.lua rename to engine/art/editor/lite/data/themes/github.lua diff --git a/tools/editor/art/lite/data/themes/gruvbox_dark.lua b/engine/art/editor/lite/data/themes/gruvbox_dark.lua similarity index 100% rename from tools/editor/art/lite/data/themes/gruvbox_dark.lua rename to engine/art/editor/lite/data/themes/gruvbox_dark.lua diff --git a/tools/editor/art/lite/data/themes/liqube.lua b/engine/art/editor/lite/data/themes/liqube.lua similarity index 100% rename from tools/editor/art/lite/data/themes/liqube.lua rename to engine/art/editor/lite/data/themes/liqube.lua diff --git a/tools/editor/art/lite/data/themes/moe.lua b/engine/art/editor/lite/data/themes/moe.lua similarity index 100% rename from tools/editor/art/lite/data/themes/moe.lua rename to engine/art/editor/lite/data/themes/moe.lua diff --git a/tools/editor/art/lite/data/themes/monodark.lua b/engine/art/editor/lite/data/themes/monodark.lua similarity index 100% rename from tools/editor/art/lite/data/themes/monodark.lua rename to engine/art/editor/lite/data/themes/monodark.lua diff --git a/tools/editor/art/lite/data/themes/monokai.lua b/engine/art/editor/lite/data/themes/monokai.lua similarity index 100% rename from tools/editor/art/lite/data/themes/monokai.lua rename to engine/art/editor/lite/data/themes/monokai.lua diff --git a/tools/editor/art/lite/data/themes/nord.lua b/engine/art/editor/lite/data/themes/nord.lua similarity index 100% rename from tools/editor/art/lite/data/themes/nord.lua rename to engine/art/editor/lite/data/themes/nord.lua diff --git a/tools/editor/art/lite/data/themes/onedark.lua b/engine/art/editor/lite/data/themes/onedark.lua similarity index 100% rename from tools/editor/art/lite/data/themes/onedark.lua rename to engine/art/editor/lite/data/themes/onedark.lua diff --git a/tools/editor/art/lite/data/themes/only_dark.lua b/engine/art/editor/lite/data/themes/only_dark.lua similarity index 100% rename from tools/editor/art/lite/data/themes/only_dark.lua rename to engine/art/editor/lite/data/themes/only_dark.lua diff --git a/tools/editor/art/lite/data/themes/solarized_light.lua b/engine/art/editor/lite/data/themes/solarized_light.lua similarity index 100% rename from tools/editor/art/lite/data/themes/solarized_light.lua rename to engine/art/editor/lite/data/themes/solarized_light.lua diff --git a/tools/editor/art/lite/data/themes/solarobj.lua b/engine/art/editor/lite/data/themes/solarobj.lua similarity index 100% rename from tools/editor/art/lite/data/themes/solarobj.lua rename to engine/art/editor/lite/data/themes/solarobj.lua diff --git a/tools/editor/art/lite/data/themes/summer.lua b/engine/art/editor/lite/data/themes/summer.lua similarity index 100% rename from tools/editor/art/lite/data/themes/summer.lua rename to engine/art/editor/lite/data/themes/summer.lua diff --git a/tools/editor/art/lite/data/themes/vscode-dark.lua b/engine/art/editor/lite/data/themes/vscode-dark.lua similarity index 100% rename from tools/editor/art/lite/data/themes/vscode-dark.lua rename to engine/art/editor/lite/data/themes/vscode-dark.lua diff --git a/tools/editor/art/lite/data/themes/winter.lua b/engine/art/editor/lite/data/themes/winter.lua similarity index 100% rename from tools/editor/art/lite/data/themes/winter.lua rename to engine/art/editor/lite/data/themes/winter.lua diff --git a/tools/editor/art/lite/data/themes/zenburn.lua b/engine/art/editor/lite/data/themes/zenburn.lua similarity index 100% rename from tools/editor/art/lite/data/themes/zenburn.lua rename to engine/art/editor/lite/data/themes/zenburn.lua diff --git a/tools/editor/art/lite/data/user/init.lua b/engine/art/editor/lite/data/user/init.lua similarity index 88% rename from tools/editor/art/lite/data/user/init.lua rename to engine/art/editor/lite/data/user/init.lua index 689c60e..173f73d 100644 --- a/tools/editor/art/lite/data/user/init.lua +++ b/engine/art/editor/lite/data/user/init.lua @@ -7,7 +7,7 @@ local style = require "core.style" -- light theme: -- require "themes.summer" -require "themes.fwk" -- monokai, dracula +--require "themes.fwk" -- monokai, dracula -- key binding: -- keymap.add { ["ctrl+escape"] = "core:quit" } diff --git a/tools/editor/art/materialdesignicons-webfont.license b/engine/art/editor/materialdesignicons-webfont.license similarity index 100% rename from tools/editor/art/materialdesignicons-webfont.license rename to engine/art/editor/materialdesignicons-webfont.license diff --git a/tools/editor/art/materialdesignicons-webfont.ttf b/engine/art/editor/materialdesignicons-webfont.ttf similarity index 100% rename from tools/editor/art/materialdesignicons-webfont.ttf rename to engine/art/editor/materialdesignicons-webfont.ttf diff --git a/tools/editor/plugins/.gitkeep b/engine/art/editor/plugins/.gitkeep similarity index 100% rename from tools/editor/plugins/.gitkeep rename to engine/art/editor/plugins/.gitkeep diff --git a/tools/editor/art/scripts/inspect.lua b/engine/art/editor/scripts/inspect.lua similarity index 100% rename from tools/editor/art/scripts/inspect.lua rename to engine/art/editor/scripts/inspect.lua diff --git a/tools/editor/editor.c b/engine/editor.c similarity index 90% rename from tools/editor/editor.c rename to engine/editor.c index c92f010..c00a656 100644 --- a/tools/editor/editor.c +++ b/engine/editor.c @@ -1,11 +1,13 @@ #define COOK_ON_DEMAND 1 // @fixme: these directives should be on client, not within v4k.dll #define ENABLE_AUTOTESTS 1 -#define V4K_IMPLEMENTATION -#include "v4k.h" -#include "objtests.h" +#include "v4k.c" +//#include "../tools/labs/objtests.h" // ---------------------------------------------------------------------------- +TODO("editor_load_on_boot()"); +TODO("editor_save_on_quit()"); + TODO("file_id: glow.hdr vs glow.png"); TODO("reflect: iterate components+metas on REFLECT too, so they're properly saved/loaded"); @@ -54,7 +56,7 @@ TODO("obj: free obj_components()/payload2"); TODO("pack: mp2json, json2mp"); TODO("pack: simplify msgpack API, make it growth similar to va()") -#if 0 // v4k_pack proposal +#if 0 // fwk_pack proposal static __thread char* mpin; static __thread unsigned mpinlen; static __thread char mpinbuf[256]; @@ -65,8 +67,28 @@ static __thread char mpoutbuf[256]; #define UNPACKMSG(ptr,fmt,...) (mpin = (char*)ptr, mpinlen = strlen(ptr), mpout = mpoutbuf, mpoutlen = sizeof(mpoutbuf), mpoutlen = cobs_decode(mpin, mpinlen, mpout, mpoutlen), msgunpack_new(mpout, mpoutlen) && msgunpack(fmt, __VA_ARGS__)) #endif -#include "3rd_icon_mdi.h" -#include "v4k_editor.h" +TODO("serialize array(types)") +TODO("serialize map(char*,types)") +TODO("serialize map(int,types)") +TODO("sprite: solid platforms, one-way platforms") +TODO("sprite: shake left-right, up-down") +TODO("sprite: coyote time") +TODO("sprite: jump buffering before grounded") +TODO("sprite: double jump, wall sliding, wall climbing") +TODO("sprite: hitbox for enemies -> wall detection") + +TODO("new: integrate with Art/ browser") +TODO("bug: lite key bindings are being sent to editor") +TODO("bug: not sending quit signal to lite neither at window close nor editor close (see: temporary files)") +TODO("bug: missing search results window") +TODO("bug: missing code completions popup") +// TODO("eval: https://github.com/drmargarido/linters") +// TODO("eval: https://github.com/monolifed/theme16") +// TODO("eval: https://github.com/vincens2005/lite-formatters") +// https://github.com/takase1121/lite-xl-img +// https://github.com/takase1121/lite-xl-finder +// https://github.com/rxi/lite/commit/236a585756cb9fa70130eee6c9a604780aced424 > suru.png +// https://github.com/rxi/lite/commit/f90b00748e1fe1cd2340aaa06d2526a1b2ea54ec void editor_gizmos(int dim) { // debugdraw @@ -247,8 +269,8 @@ void kid_draw(kid *obj) { float position[3] = {obj->pos.x,obj->pos.y,obj->pos.y}; // position(x,y,depth: sort by Y) float offset[2]={0,0}, scale[2]={1,1}; float coords[3]={col * 4 + row,4,4}; // num_frame(x) in a 4x4(y,z) spritesheet - sprite_sheet(obj->texture_, coords, position, obj->angle*TO_DEG, offset, scale, - 0, obj->color, 0); // is_additive, tint color, resolution independant + unsigned flags = 0; + sprite_sheet(obj->texture_, coords, position, obj->angle*TO_DEG, offset, scale, obj->color, flags); } int kid_aabb(kid *obj, aabb *box) { *box = aabb( vec3(obj->pos.x-16,obj->pos.y-16,0), vec3(obj->pos.x+16,obj->pos.y+16,1) ); @@ -399,7 +421,7 @@ int main(){ if( flag("--transparent") ) window_create(101, 0); else - window_create(80, flag("--borderless") ? WINDOW_BORDERLESS : 0); + window_create(80, flag("--windowed") ? 0 : WINDOW_BORDERLESS); window_icon("scale-ruler-icon.png"); while( window_swap() ) { diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 2ac99e0..9878932 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -14028,7 +14028,7 @@ extern "C" { //----------------------------------------------------------------------------- // Headers -#line 1 "engine/split/v4k_config.h" +#line 1 "v4k_config.h" // ----------------------------------------------------------------------------- // config directives @@ -14443,7 +14443,7 @@ typedef char bool; #endif #line 0 -#line 1 "engine/split/v4k_ds.h" +#line 1 "v4k_ds.h" // data structures and utils: array, set, map, hash, sort. // - rlyeh, public domain @@ -14882,7 +14882,7 @@ API bool (map_sort)(map* m); API void (map_clear)(map* m); #line 0 -#line 1 "engine/split/v4k_math.h" +#line 1 "v4k_math.h" // ----------------------------------------------------------------------------- // math framework: rand, ease, vec2, vec3, vec4, quat, mat2, mat33, mat34, mat4 // - rlyeh, public domain @@ -15163,7 +15163,7 @@ API void print34( float *m ); API void print44( float *m ); #line 0 -#line 1 "engine/split/v4k_obj.h" +#line 1 "v4k_obj.h" // ----------------------------------------------------------------------------- // factory of handle ids @@ -15327,6 +15327,7 @@ void* obj_free(void *o); // --- syntax sugars #define obj_extend(T,method) (obj_##method[OBJTYPE(T)] = (void*)T##_##method) +#define obj_extend_t(T,method) (obj_##method[OBJTYPE(T##_t)] = (void*)T##_##method) #define obj_method(method,o,...) (obj_##method[((struct obj*)(o))->objtype](o,##__VA_ARGS__)) // (obj_##method[((struct obj*)(o))->objtype]((o), ##__VA_ARGS__)) #define obj_hasmethod(o,method) (obj_typeid(o)[obj_##method]) @@ -15349,6 +15350,17 @@ void* obj_free(void *o); #define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) #define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) +#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__) +#define EXTEND_T2(o,F1) obj_extend_t(o,F1) +#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) +#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) +#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) +#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) +#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) +#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) +#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) +#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) + // --- declare vtables API extern void (*obj_ctor[256])(); ///- @@ -15367,6 +15379,8 @@ API extern int (*obj_lerp[256])(); ///- API extern int (*obj_edit[256])(); ///- API extern int (*obj_aabb[256])(); ///- +API extern const char*OBJTYPES[256]; /// - + // ---------------------------------------------------------------------------- // core @@ -15511,7 +15525,7 @@ typedef enum OBJTYPE_BUILTINS { #line 0 -#line 1 "engine/split/v4k_ai.h" +#line 1 "v4k_ai.h" // AI framework // - rlyeh, public domain. // @@ -15596,7 +15610,7 @@ API void swarm_update_acceleration_and_velocity_only(swarm_t *self, float del API int ui_swarm(swarm_t *self); #line 0 -#line 1 "engine/split/v4k_audio.h" +#line 1 "v4k_audio.h" // ----------------------------------------------------------------------------- // audio framework // - rlyeh, public domain @@ -15657,7 +15671,7 @@ enum AUDIO_FLAGS { API int audio_queue( const void *samples, int num_samples, int flags ); #line 0 -#line 1 "engine/split/v4k_collide.h" +#line 1 "v4k_collide.h" // ----------------------------------------------------------------------------- // original code by @vurtun (PD) and @barerose (CC0). // [src] https://gist.github.com/vurtun/95f088e4889da2474ad1ce82d7911fee @@ -15818,7 +15832,7 @@ API poly diamond(vec3 from, vec3 to, float size); // poly_free() required API void collide_demo(); // debug draw collisions #line 0 -#line 1 "engine/split/v4k_cook.h" +#line 1 "v4k_cook.h" // ----------------------------------------------------------------------------- // asset pipeline framework // - rlyeh, public domain. @@ -15854,7 +15868,7 @@ API int cook_progress(); // [0..100] API bool have_tools(); #line 0 -#line 1 "engine/split/v4k_data.h" +#line 1 "v4k_data.h" // ----------------------------------------------------------------------------- // data framework (json5, xml, compression) @todo:kvdb // - rlyeh, public domain @@ -15893,7 +15907,7 @@ API void xml_pop(); API bool data_tests(); #line 0 -#line 1 "engine/split/v4k_extend.h" +#line 1 "v4k_extend.h" // dll ------------------------------------------------------------------------ /// !!! `filename` must contain extension @@ -15930,54 +15944,7 @@ enum { API void *script_init_env(unsigned flags); #line 0 -#line 1 "engine/split/v4k_editor.h" -// ----------------------------------------------------------------------------- -// in-game editor -// - rlyeh, public domain. -// -// @todo: merge editor1.c and editor3.c internals into this api - -//API void editor(); -//API bool editor_active(); -API vec3 editor_pick(float mouse_x, float mouse_y); -API char* editor_path(const char *path); - -API float* engine_getf(const char *key); -API int* engine_geti(const char *key); -API char** engine_gets(const char *key); -API int engine_send(const char *cmd, const char *optional_value); - -API int ui_debug(); - -// open file dialog - -API char* dialog_load(); -API char* dialog_save(); - -// transform gizmos - -API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); -API bool gizmo_active(); -API bool gizmo_hover(); - -// localization kit (I18N, L10N) - -API bool kit_load( const char *filename ); // load translations file (xlsx) -API bool kit_merge( const char *filename ); // merge translations file into existing context -API void kit_insert( const char *id, const char *translation ); // insert single translation unit -API void kit_clear(); // delete all translations - -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context -API void kit_dump_state( FILE *fp ); // debug - -API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale - -API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... -API char* kit_translate( const char *id ); // perform a translation, given current locale -#line 0 - -#line 1 "engine/split/v4k_file.h" +#line 1 "v4k_file.h" // ----------------------------------------------------------------------------- // files, cache and virtual filesystem (registered directories and/or compressed zip archives). // - rlyeh, public domain. @@ -16077,7 +16044,7 @@ API void ini_destroy(ini_t); API bool ini_write(const char *filename, const char *section, const char *key, const char *value); #line 0 -#line 1 "engine/split/v4k_font.h" +#line 1 "v4k_font.h" // ----------------------------------------------------------------------------- // font framework // - rlyeh, public domain @@ -16169,7 +16136,7 @@ API void* font_colorize(const char *text, const char *comma_types, const char *c API vec2 font_highlight(const char *text, const void *colors); #line 0 -#line 1 "engine/split/v4k_input.h" +#line 1 "v4k_input.h" // ----------------------------------------------------------------------------- // input framework // - rlyeh, public domain @@ -16296,7 +16263,7 @@ enum INPUT_ALIASES { }; #line 0 -#line 1 "engine/split/v4k_memory.h" +#line 1 "v4k_memory.h" // ----------------------------------------------------------------------------- // memory framework // - rlyeh, public domain @@ -16336,7 +16303,7 @@ static FORCE_INLINE void *(CALLOC_)(size_t m, size_t n) { return n *= m, memset( static FORCE_INLINE char *(STRDUP_)(const char *s) { size_t n = strlen(s)+1; return ((char*)memcpy(REALLOC(0,n), s, n)); } ///- #line 0 -#line 1 "engine/split/v4k_network.h" +#line 1 "v4k_network.h" // ----------------------------------------------------------------------------- // network framework // - rlyeh, public domain @@ -16388,7 +16355,7 @@ API int tcp_debug(int); // toggle traffic monitoring on/off for given socket //API int tcp_crypt(int,uint64_t); // set shared secret #line 0 -#line 1 "engine/split/v4k_track.h" +#line 1 "v4k_track.h" #ifndef TRACK_SEND_BUFSIZE #define TRACK_SEND_BUFSIZE 576 #endif @@ -16449,7 +16416,7 @@ typedef struct track_prop { API int track_event_props(char const *event_id, char const *user_id, const track_prop *props); #line 0 -#line 1 "engine/split/v4k_netsync.h" +#line 1 "v4k_netsync.h" // high-level, socket-less networking api. inspired by Quake, MPI and RenderBuckets theories. // - rlyeh, public domain // @@ -16535,7 +16502,7 @@ API int64_t client_join(const char *ip, int port); #define LOCALHOST_IPV6 "::1" #line 0 -#line 1 "engine/split/v4k_pack.h" +#line 1 "v4k_pack.h" // ---------------------------------------------------------------------------- // compression api @@ -16664,25 +16631,25 @@ typedef struct double2 { double x,y; } double2; typedef struct double3 { double x,y,z; } double3; typedef struct double4 { double x,y,z,w; } double4; -#define byte2(x,y) M_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) -#define byte3(x,y,z) M_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) -#define byte4(x,y,z,w) M_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) +#define byte2(x,y) C_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) +#define byte3(x,y,z) C_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) +#define byte4(x,y,z,w) C_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) -#define int2(x,y) M_CAST(int2, (int)(x), (int)(y) ) -#define int3(x,y,z) M_CAST(int3, (int)(x), (int)(y), (int)(z) ) -#define int4(x,y,z,w) M_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) +#define int2(x,y) C_CAST(int2, (int)(x), (int)(y) ) +#define int3(x,y,z) C_CAST(int3, (int)(x), (int)(y), (int)(z) ) +#define int4(x,y,z,w) C_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) -#define uint2(x,y) M_CAST(uint2, (unsigned)(x), (unsigned)(y) ) -#define uint3(x,y,z) M_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) -#define uint4(x,y,z,w) M_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) +#define uint2(x,y) C_CAST(uint2, (unsigned)(x), (unsigned)(y) ) +#define uint3(x,y,z) C_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) +#define uint4(x,y,z,w) C_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) -#define float2(x,y) M_CAST(float2, (float)(x), (float)(y) ) -#define float3(x,y,z) M_CAST(float3, (float)(x), (float)(y), (float)(z) ) -#define float4(x,y,z,w) M_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) +#define float2(x,y) C_CAST(float2, (float)(x), (float)(y) ) +#define float3(x,y,z) C_CAST(float3, (float)(x), (float)(y), (float)(z) ) +#define float4(x,y,z,w) C_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) -#define double2(x,y) M_CAST(double2, (double)(x), (double)(y) ) -#define double3(x,y,z) M_CAST(double3, (double)(x), (double)(y), (double)(z) ) -#define double4(x,y,z,w) M_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) +#define double2(x,y) C_CAST(double2, (double)(x), (double)(y) ) +#define double3(x,y,z) C_CAST(double3, (double)(x), (double)(y), (double)(z) ) +#define double4(x,y,z,w) C_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) // ----------------------------------------------------------------------------- // compile-time fourcc, eightcc @@ -16927,7 +16894,7 @@ API int loadb(const unsigned char *buf, const char *format, ...); #line 0 -#line 1 "engine/split/v4k_profile.h" +#line 1 "v4k_profile.h" // ----------------------------------------------------------------------------- // profiler & stats (@fixme: threadsafe) @@ -16959,7 +16926,7 @@ extern API int profiler_enabled; ///- #endif #line 0 -#line 1 "engine/split/v4k_reflect.h" +#line 1 "v4k_reflect.h" // C reflection: enums, functions, structs, members and anotations. // - rlyeh, public domain // @@ -17026,7 +16993,7 @@ API const char* symbol_naked(const char *s); API int ui_reflect(const char *mask); // *, model* or NULL #line 0 -#line 1 "engine/split/v4k_render.h" +#line 1 "v4k_render.h" // ----------------------------------------------------------------------------- // naive rendering framework // - rlyeh, public domain @@ -17212,82 +17179,6 @@ API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); -// ----------------------------------------------------------------------------- -// sprites - -// texture id, position(x,y,depth sort), tint color, rotation angle -API void sprite( texture_t texture, float position[3], float rotation /*0*/, uint32_t color /*~0u*/); - -// texture id, rect(x,y,w,h) is [0..1] normalized, z-index, pos(xy,scale.xy), rotation (degrees), color (rgba) -API void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba); - -// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color -API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant); - -API void sprite_flush(); - -// ----------------------------------------------------------------------------- -// tilemaps - -typedef struct tileset_t { - texture_t tex; // spritesheet - unsigned tile_w, tile_h; // dimensions per tile in pixels - unsigned cols, rows; // tileset num_cols, num_rows - unsigned selected; // active tile (while editing) -} tileset_t; - -API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); - -API int ui_tileset( tileset_t t ); - -typedef struct tilemap_t { - int blank_chr; // transparent tile - unsigned cols, rows; // map dimensions (in tiles) - array(int) map; - - vec3 position; // x,y,scale - float zindex; - float tilt; - unsigned tint; - bool is_additive; -} tilemap_t; - -API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); -API void tilemap_render( tilemap_t m, tileset_t style ); -API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); - -// ----------------------------------------------------------------------------- -// tiled maps - -typedef struct tiled_t { - char *map_name; - unsigned first_gid, tilew, tileh, w, h; - - bool parallax; - vec3 position; - array(bool) visible; - array(tilemap_t) layers; - array(tileset_t) sets; - array(char*) names; -} tiled_t; - -API tiled_t tiled(const char *file_tmx); -API void tiled_render(tiled_t tmx, vec3 pos); - -API void ui_tiled(tiled_t *t); - -// ----------------------------------------------------------------------------- -// spines - -typedef struct spine_t spine_t; - -API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); -API void spine_skin(spine_t *p, unsigned skin); -API void spine_render(spine_t *p, vec3 offset, unsigned flags); -API void spine_animate(spine_t *p, float delta); - -API void ui_spine(spine_t *p); - // ----------------------------------------------------------------------------- // cubemaps @@ -17734,7 +17625,7 @@ API void* screenshot(int components); // 3 RGB, 4 RGBA, -3 BGR, -4 BGRA API void* screenshot_async(int components); // 3 RGB, 4 RGBA, -3 BGR, -4 BGRA #line 0 -#line 1 "engine/split/v4k_renderdd.h" +#line 1 "v4k_renderdd.h" // ----------------------------------------------------------------------------- // debugdraw framework // - rlyeh, public domain. @@ -17801,7 +17692,7 @@ API void ddraw_flush(); API void ddraw_flush_projview(mat44 proj, mat44 view); #line 0 -#line 1 "engine/split/v4k_scene.h" +#line 1 "v4k_scene.h" // ----------------------------------------------------------------------------- // scene framework // - rlyeh, public domain @@ -17938,7 +17829,124 @@ API unsigned scene_count_light(); API light_t* scene_index_light(unsigned index); #line 0 -#line 1 "engine/split/v4k_string.h" +#line 1 "v4k_sprite.h" +// ----------------------------------------------------------------------------- +// sprites + +typedef enum SPRITE_FLAGS { + SPRITE_PROJECTED = 1, + SPRITE_ADDITIVE = 2, + SPRITE_CENTERED = 4, + SPRITE_RESOLUTION_INDEPENDANT = 128, +} SPRITE_FLAGS; + +// texture id, position(x,y,depth sort), tint color, rotation angle +API void sprite( texture_t texture, float position[3], float rotation /*0*/, unsigned color /*~0u*/, unsigned flags); + +// texture id, rect(x,y,w,h) is [0..1] normalized, then: pos(xyz,z-index), (scale.xy,offset.xy), rotation (degrees), color (rgba) +API void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scaleoff, float tilt_deg, unsigned tint_rgba, unsigned flags); + +// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color +API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags); + +API void sprite_flush(); + +// ----------------------------------------------------------------------------- +// tilemaps + +typedef struct tileset_t { + texture_t tex; // spritesheet + unsigned tile_w, tile_h; // dimensions per tile in pixels + unsigned cols, rows; // tileset num_cols, num_rows + unsigned selected; // active tile (while editing) +} tileset_t; + +API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); + +API int ui_tileset( tileset_t t ); + +typedef struct tilemap_t { + int blank_chr; // transparent tile + unsigned cols, rows; // map dimensions (in tiles) + array(int) map; + + vec3 position; // x,y,scale + float zindex; + float tilt; + unsigned tint; + bool is_additive; +} tilemap_t; + +API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); +API void tilemap_render( tilemap_t m, tileset_t style ); +API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); + +// ----------------------------------------------------------------------------- +// tiled maps + +typedef struct tiled_t { + char *map_name; + unsigned first_gid, tilew, tileh, w, h; + + bool parallax; + vec3 position; + array(bool) visible; + array(tilemap_t) layers; + array(tileset_t) sets; + array(char*) names; +} tiled_t; + +API tiled_t tiled(const char *file_tmx); +API void tiled_render(tiled_t tmx, vec3 pos); + +API void ui_tiled(tiled_t *t); + +// ----------------------------------------------------------------------------- +// spines + +typedef struct spine_t spine_t; + +API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); +API void spine_skin(spine_t *p, unsigned skin); +API void spine_render(spine_t *p, vec3 offset, unsigned flags); +API void spine_animate(spine_t *p, float delta); + +API void ui_spine(spine_t *p); + +// ---------------------------------------------------------------------------- +// sprite v2 api + +typedef struct sprite_t { OBJ + vec4 gamepad; // up,down,left,right + vec2 fire; // a,b + + vec4 pos; + vec2 sca; + float tilt; + unsigned tint; + unsigned frame; + unsigned timer, timer_ms; + unsigned flip_, flipped; + unsigned play; + bool paused; + // array(unsigned) play_queue; or unsigned play_next; + struct atlas_t *a; // shared + //atlas_t own; // owned +} sprite_t; + +OBJTYPEDEF(sprite_t,10); +API void sprite_ctor(sprite_t *s); +API void sprite_dtor(sprite_t *s); +API void sprite_tick(sprite_t *s); +API void sprite_draw(sprite_t *s); +API void sprite_edit(sprite_t *s); + +API sprite_t*sprite_new(const char *ase, int bindings[6]); +API void sprite_del(sprite_t *s); +API void sprite_setanim(sprite_t *s, unsigned name); +#line 0 + +#line 1 "v4k_string.h" // string framework // - rlyeh, public domain @@ -18031,9 +18039,26 @@ typedef struct quarks_db { API unsigned quark_intern( quarks_db*, const char *string ); API const char *quark_string( quarks_db*, unsigned key ); + +// ----------------------------------------------------------------------------- +// ## localization kit (I18N, L10N) + +API bool kit_load( const char *filename ); // load translations file (xlsx) +API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit +API void kit_clear(); // delete all translations + +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + +API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale + +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 -#line 1 "engine/split/v4k_system.h" +#line 1 "v4k_system.h" // ----------------------------------------------------------------------------- // system framework utils // - rlyeh, public domain. @@ -18120,7 +18145,7 @@ API int (test)(const char *file, int line, const char *expr, bool result); #endif #line 0 -#line 1 "engine/split/v4k_time.h" +#line 1 "v4k_time.h" // ----------------------------------------------------------------------------- // time framework utils @@ -18279,7 +18304,7 @@ API vec3 curve_eval(curve_t *c, float dt, unsigned *color); API void curve_destroy(curve_t *c); #line 0 -#line 1 "engine/split/v4k_ui.h" +#line 1 "v4k_ui.h" // ----------------------------------------------------------------------------- // immediate ui framework // - rlyeh, public domain @@ -18373,7 +18398,7 @@ API int ui_demo(int do_windows); API void *ui_handle(); #line 0 -#line 1 "engine/split/v4k_video.h" +#line 1 "v4k_video.h" // ----------------------------------------------------------------------------- // video decoder (mpeg) // - rlyeh, public domain @@ -18416,7 +18441,7 @@ API bool record_active(); API void record_stop(void); #line 0 -#line 1 "engine/split/v4k_window.h" +#line 1 "v4k_window.h" // ----------------------------------------------------------------------------- // window framework // - rlyeh, public domain @@ -18520,6 +18545,39 @@ API void window_setclipboard(const char *text); // ---- +#line 1 "v4k_editor.h" +// ----------------------------------------------------------------------------- +// in-game editor +// - rlyeh, public domain. + +API int editor_send(const char *command); + +//API void editor(); +//API bool editor_active(); +API vec3 editor_pick(float mouse_x, float mouse_y); +API char* editor_path(const char *path); + +API float* engine_getf(const char *key); +API int* engine_geti(const char *key); +API char** engine_gets(const char *key); +API int engine_send(const char *cmd, const char *optional_value); + +API int ui_debug(); + +// open file dialog + +API char* dialog_load(); +API char* dialog_save(); + +// transform gizmos + +API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); +API bool gizmo_active(); +API bool gizmo_hover(); +#line 0 + +// ---- + #if is(cpp) } // extern "C" #endif @@ -18554,7 +18612,7 @@ API void window_setclipboard(const char *text); #define GLAD_GL_IMPLEMENTATION // glad #endif -#line 1 "engine/split/3rd_glad.h" +#line 1 "3rd_glad.h" #ifndef __EMSCRIPTEN__ #ifndef _GNU_SOURCE // juicy linux headers @@ -30236,7 +30294,7 @@ int gladLoadGL( GLADloadfunc load) { #endif /* __EMSCRIPTEN__ */ #line 0 -#line 1 "engine/split/3rd_icon_md.h" +#line 1 "3rd_icon_md.h" // Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++ // from https://github.com/google/material-design-icons/raw/master/font/MaterialIcons-Regular.codepoints // for use with https://github.com/google/material-design-icons/blob/master/font/MaterialIcons-Regular.ttf @@ -32580,7 +32638,7 @@ errno_t fopen_s( #endif //--- -#line 1 "engine/split/3rd_glfw3.h" +#line 1 "3rd_glfw3.h" #ifndef __EMSCRIPTEN__ // forked from https://github.com/SasLuca/glfw-single-header (CC0-1.0 licensed) @@ -71777,7 +71835,7 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym) #line 0 #undef timeGetTime //--- -#line 1 "engine/split/3rd_swrap.h" +#line 1 "3rd_swrap.h" // https://github.com/BareRose/swrap/blob/master/swrap.h /* @@ -72070,7 +72128,7 @@ SWDEF int swrapMultiSelect (int* socks, size_t socks_size, double timeout) { #endif //SWRAP_H #line 0 //--- -#line 1 "engine/split/3rd_jo_mp1.h" +#line 1 "3rd_jo_mp1.h" /* public domain Simple, Minimalistic MPEG Layer 1 decoder - http://jonolick.com * * Revision History: @@ -72481,7 +72539,7 @@ bool jo_read_mp1(const void *input, int inputSize, short **output_, int *outputS #line 0 #define get_bits stb_vorbis_get_bits #define error stb_vorbis_error -#line 1 "engine/split/3rd_stb_vorbis.h" +#line 1 "3rd_stb_vorbis.h" // Ogg Vorbis audio decoder - v1.22 - public domain // http://nothings.org/stb_vorbis/ // @@ -78069,7 +78127,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #line 0 #undef error #undef DEBUG -#line 1 "engine/split/3rd_sts_mixer.h" +#line 1 "3rd_sts_mixer.h" /////////////////////////////////////////////////////////////////////////////// // sts_mixer.h - v0.02 // written 2016 by Sebastian Steinhauer @@ -78582,7 +78640,7 @@ int main(int argc, char *argv[]) { For more information, please refer to */ #line 0 -#line 1 "engine/split/3rd_miniaudio.h" +#line 1 "3rd_miniaudio.h" /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. miniaudio - v0.11.18 - 2023-08-07 @@ -171127,12 +171185,12 @@ SOFTWARE. #undef R #define error l_error #define panic l_panic -#line 1 "engine/split/3rd_lua.h" +#line 1 "3rd_lua.h" /* minilua.h -- Lua in a single header Project URL: https://github.com/edubart/minilua - This is Lua 5.4.4 contained in a single header to be bundled in C/C++ applications with ease. + This is Lua 5.4.6 contained in a single header to be bundled in C/C++ applications with ease. Lua is a powerful, efficient, lightweight, embeddable scripting language. Do the following in *one* C file to create the implementation: @@ -171152,7 +171210,7 @@ SOFTWARE. */ /* detect system platform */ -#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) +#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) && !defined(LUA_USE_IOS) #if defined(_WIN32) #define LUA_USE_WINDOWS #elif defined(__linux__) @@ -171288,6 +171346,12 @@ extern "C" { #endif +#if defined(LUA_USE_IOS) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN +#endif + + /* @@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. */ @@ -171946,7 +172010,7 @@ extern "C" { ** CHANGE it if you need a different limit. This limit is arbitrary; ** its only purpose is to stop Lua from consuming unlimited stack ** space (and to reserve some numbers for pseudo-indices). -** (It must fit into max(size_t)/32.) +** (It must fit into max(size_t)/32 and max(int)/2.) */ #if LUAI_IS32INT #define LUAI_MAXSTACK 1000000 @@ -171965,14 +172029,15 @@ extern "C" { /* @@ LUA_IDSIZE gives the maximum size for the description of the source -@@ of a function in debug information. +** of a function in debug information. ** CHANGE it if you want a different size. */ #define LUA_IDSIZE 60 /* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +@@ LUAL_BUFFERSIZE is the initial buffer size used by the lauxlib +** buffer system. */ #define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) @@ -172022,14 +172087,14 @@ extern "C" { #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "4" +#define LUA_VERSION_RELEASE "6" #define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4) +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 6) #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio" +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" @@ -172135,6 +172200,16 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); +/* +** Type used by the debug API to collect debug information +*/ +typedef struct lua_Debug lua_Debug; + + +/* +** Functions to be called by the debugger in specific events +*/ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); /* @@ -172157,7 +172232,8 @@ extern const char lua_ident[]; LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); LUA_API void (lua_close) (lua_State *L); LUA_API lua_State *(lua_newthread) (lua_State *L); -LUA_API int (lua_resetthread) (lua_State *L); +LUA_API int (lua_closethread) (lua_State *L, lua_State *from); +LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); @@ -172446,12 +172522,6 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx); #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); @@ -172496,7 +172566,7 @@ struct lua_Debug { /****************************************************************************** -* Copyright (C) 1994-2022 Lua.org, PUC-Rio. +* Copyright (C) 1994-2023 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -172874,6 +172944,7 @@ LUALIB_API void (luaL_openlibs) (lua_State *L); #endif #ifdef LUA_IMPL +typedef struct CallInfo CallInfo; /* ** $Id: llimits.h $ ** Limits, basic types, and some other 'installation-dependent' definitions @@ -172947,11 +173018,24 @@ typedef signed char ls_byte; /* -** conversion of pointer to unsigned integer: -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value +** conversion of pointer to unsigned integer: this is for hashing only; +** there is no problem if the integer cannot hold the whole pointer +** value. (In strict ISO C this may cause undefined behavior, but no +** actual machine seems to bother.) */ -#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(UINTPTR_MAX) /* even in C99 this type is optional */ +#define L_P2I uintptr_t +#else /* no 'intptr'? */ +#define L_P2I uintmax_t /* use the largest available integer */ +#endif +#else /* C89 option */ +#define L_P2I size_t +#endif + +#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX)) @@ -173295,6 +173379,8 @@ typedef union Value { lua_CFunction f; /* light C functions */ lua_Integer i; /* integer numbers */ lua_Number n; /* float numbers */ + /* not used, but may avoid warnings for uninitialized value */ + lu_byte ub; } Value; @@ -173398,6 +173484,17 @@ typedef union StackValue { /* index to stack elements */ typedef StackValue *StkId; + +/* +** When reallocating the stack, change all pointers to the stack into +** proper offsets. +*/ +typedef union { + StkId p; /* actual pointer */ + ptrdiff_t offset; /* used while the stack is being reallocated */ +} StkIdRel; + + /* convert a 'StackValue' to a 'TValue' */ #define s2v(o) (&(o)->val) @@ -173858,8 +173955,10 @@ typedef struct Proto { */ typedef struct UpVal { CommonHeader; - lu_byte tbc; /* true if it represents a to-be-closed variable */ - TValue *v; /* points to stack or to its own value */ + union { + TValue *p; /* points to stack or to its own value */ + ptrdiff_t offset; /* used while the stack is being reallocated */ + } v; union { struct { /* (when open) */ struct UpVal *next; /* linked list */ @@ -174145,6 +174244,7 @@ LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); /*#include "lobject.h"*/ +/*#include "lstate.h"*/ /* @@ -174231,8 +174331,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, int inv, int isfloat, TMS event); LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, - struct CallInfo *ci, const Proto *p); -LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, + CallInfo *ci, const Proto *p); +LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted); @@ -174248,6 +174348,11 @@ LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, /*#include "lua.h"*/ + +/* Some header files included here need this definition */ +typedef struct CallInfo CallInfo; + + /*#include "lobject.h"*/ /*#include "ltm.h"*/ /*#include "lzio.h"*/ @@ -174378,7 +174483,7 @@ struct lua_longjmp; /* defined in ldo.c */ #define BASIC_STACK_SIZE (2*LUA_MINSTACK) -#define stacksize(th) cast_int((th)->stack_last - (th)->stack) +#define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p) /* kinds of Garbage Collection */ @@ -174408,9 +174513,9 @@ typedef struct stringtable { ** - field 'transferinfo' is used only during call/returnhooks, ** before the function starts or after it ends. */ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ +struct CallInfo { + StkIdRel func; /* function index in the stack */ + StkIdRel top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ union { struct { /* only for Lua functions */ @@ -174435,7 +174540,7 @@ typedef struct CallInfo { } u2; short nresults; /* expected number of results from this function */ unsigned short callstatus; -} CallInfo; +}; /* @@ -174530,7 +174635,7 @@ typedef struct global_State { struct lua_State *mainthread; TString *memerrmsg; /* message for memory-allocation errors */ TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ lua_WarnFunction warnf; /* warning function */ void *ud_warn; /* auxiliary data to 'warnf' */ @@ -174545,13 +174650,13 @@ struct lua_State { lu_byte status; lu_byte allowhook; unsigned short nci; /* number of items in 'ci' list */ - StkId top; /* first free slot in the stack */ + StkIdRel top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ - StkId stack_last; /* end of stack (last element + 1) */ - StkId stack; /* stack base */ + StkIdRel stack_last; /* end of stack (last element + 1) */ + StkIdRel stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ - StkId tbclist; /* list of to-be-closed variables */ + StkIdRel tbclist; /* list of to-be-closed variables */ GCObject *gclist; struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ @@ -174730,7 +174835,7 @@ iABC C(8) | B(8) |k| A(8) | Op(7) | iABx Bx(17) | A(8) | Op(7) | iAsBx sBx (signed)(17) | A(8) | Op(7) | iAx Ax(25) | Op(7) | -isJ sJ(25) | Op(7) | +isJ sJ (signed)(25) | Op(7) | A signed argument is represented in excess K: the represented value is the written unsigned value minus K, where K is half the maximum for the @@ -175129,7 +175234,7 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) /* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue(s2v((ci)->func))) +#define ci_func(ci) (clLvalue(s2v((ci)->func.p))) #define resethookcount(L) (L->hookcount = L->basehookcount) @@ -175185,6 +175290,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); #define ldo_h +/*#include "llimits.h"*/ /*#include "lobject.h"*/ /*#include "lstate.h"*/ /*#include "lzio.h"*/ @@ -175200,7 +175306,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); ** at every check. */ #define luaD_checkstackaux(L,n,pre,pos) \ - if (l_unlikely(L->stack_last - L->top <= (n))) \ + if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ { pre; luaD_growstack(L, n, 1); pos; } \ else { condmovestack(L,pre,pos); } @@ -175209,11 +175315,18 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((StkId)((char *)L->stack + (n))) +#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p)) +#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n)) /* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* macro to check stack size and GC, preserving 'p' */ #define checkstackGCp(L,n,p) \ luaD_checkstackaux(L, n, \ ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ @@ -175235,7 +175348,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); -LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta); +LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, + int narg1, int delta); LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); @@ -175428,24 +175542,27 @@ LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) -#define luaC_barrier(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) - -#define luaC_barrierback(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrierback_(L,p) : cast_void(0)) - #define luaC_objbarrier(L,p,o) ( \ (isblack(p) && iswhite(o)) ? \ luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) +#define luaC_barrier(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0)) + +#define luaC_objbarrierback(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : cast_void(0)) + LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, + size_t offset); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); @@ -175484,10 +175601,10 @@ LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); #define MAXUPVAL 255 -#define upisopen(up) ((up)->v != &(up)->u.value) +#define upisopen(up) ((up)->v.p != &(up)->u.value) -#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) +#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p)) /* @@ -175509,7 +175626,7 @@ LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); +LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); LUAI_FUNC void luaF_unlinkupval (UpVal *uv); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, @@ -175624,23 +175741,26 @@ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, /*#include "lstate.h"*/ -/* Increments 'L->top', checking for stack overflows */ -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} +/* Increments 'L->top.p', checking for stack overflows */ +#define api_incr_top(L) {L->top.p++; \ + api_check(L, L->top.p <= L->ci->top.p, \ + "stack overflow");} /* ** If a call returns too many multiple returns, the callee may not have ** stack space to accommodate all results. In this case, this macro -** increases its stack space ('L->ci->top'). +** increases its stack space ('L->ci->top.p'). */ #define adjustresults(L,nres) \ - { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + { if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \ + L->ci->top.p = L->top.p; } /* Ensure the stack has at least 'n' elements */ -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") +#define api_checknelems(L,n) \ + api_check(L, (n) < (L->top.p - L->ci->func.p), \ + "not enough elements in the stack") /* @@ -175811,7 +175931,6 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t); #if defined(LUA_DEBUG) LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (const Table *t); #endif @@ -176203,6 +176322,11 @@ typedef enum { luaC_barrierback(L, gcvalue(t), v); } +/* +** Shift right is the same as shift left with a negative 'y' +*/ +#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); @@ -176588,25 +176712,6 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { /*#include "lstate.h"*/ -#if defined(EMERGENCYGCTESTS) -/* -** First allocation will fail whenever not building initial state. -** (This fail will trigger 'tryagain' and a full GC cycle at every -** allocation.) -*/ -static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { - if (completestate(g) && ns > 0) /* frees never fail */ - return NULL; /* fail */ - else /* normal allocation */ - return (*g->frealloc)(g->ud, block, os, ns); -} -#else -#define firsttry(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) -#endif - - - - /* ** About the realloc function: @@ -176626,6 +176731,43 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { */ +/* +** Macro to call the allocation function. +*/ +#define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) + + +/* +** When an allocation fails, it will try again after an emergency +** collection, except when it cannot run a collection. The GC should +** not be called while the state is not fully built, as the collector +** is not yet fully initialized. Also, it should not be called when +** 'gcstopem' is true, because then the interpreter is in the middle of +** a collection step. +*/ +#define cantryagain(g) (completestate(g) && !g->gcstopem) + + + + +#if defined(EMERGENCYGCTESTS) +/* +** First allocation will fail except when freeing a block (frees never +** fail) and when it cannot try again; this fail will trigger 'tryagain' +** and a full GC cycle at every allocation. +*/ +static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { + if (ns > 0 && cantryagain(g)) + return NULL; /* fail */ + else /* normal allocation */ + return callfrealloc(g, block, os, ns); +} +#else +#define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns) +#endif + + + /* @@ -176698,7 +176840,7 @@ l_noret luaM_toobig (lua_State *L) { void luaM_free_ (lua_State *L, void *block, size_t osize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); - (*g->frealloc)(g->ud, block, osize, 0); + callfrealloc(g, block, osize, 0); g->GCdebt -= osize; } @@ -176706,19 +176848,15 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { /* ** In case of allocation fail, this function will do an emergency ** collection to free some memory and then try the allocation again. -** The GC should not be called while state is not fully built, as the -** collector is not yet fully initialized. Also, it should not be called -** when 'gcstopem' is true, because then the interpreter is in the -** middle of a collection step. */ static void *tryagain (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); - if (completestate(g) && !g->gcstopem) { + if (cantryagain(g)) { luaC_fullgc(L, 1); /* try to free some memory... */ - return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + return callfrealloc(g, block, osize, nsize); /* try again */ } - else return NULL; /* cannot free any memory without a full state */ + else return NULL; /* cannot run an emergency collection */ } @@ -176887,10 +177025,10 @@ static TString *loadStringN (LoadState *S, Proto *p) { } else { /* long string */ ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ + setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ luaD_inctop(L); loadVector(S, getstr(ts), size); /* load directly in final place */ - L->top--; /* pop string */ + L->top.p--; /* pop string */ } luaC_objbarrier(L, p, ts); return ts; @@ -177015,6 +177153,8 @@ static void loadDebug (LoadState *S, Proto *f) { f->locvars[i].endpc = loadInt(S); } n = loadInt(S); + if (n != 0) /* does it have debug information? */ + n = f->sizeupvalues; /* must be this many */ for (i = 0; i < n; i++) f->upvalues[i].name = loadStringN(S, f); } @@ -177088,7 +177228,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { S.Z = Z; checkHeader(&S); cl = luaF_newLclosure(L, loadByte(&S)); - setclLvalue2s(L, L->top, cl); + setclLvalue2s(L, L->top.p, cl); luaD_inctop(L); cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -177110,6 +177250,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { /*#include "lprefix.h"*/ +#include #include /*#include "lua.h"*/ @@ -177155,8 +177296,11 @@ static void dumpByte (DumpState *D, int y) { } -/* dumpInt Buff Size */ -#define DIBS ((sizeof(size_t) * 8 / 7) + 1) +/* +** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" +** rounds up the division.) +*/ +#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) static void dumpSize (DumpState *D, size_t x) { lu_byte buff[DIBS]; @@ -177506,33 +177650,33 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) { static void stack_init (lua_State *L1, lua_State *L) { int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); - L1->tbclist = L1->stack; + L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); + L1->tbclist.p = L1->stack.p; for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) - setnilvalue(s2v(L1->stack + i)); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + BASIC_STACK_SIZE; + setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ + L1->top.p = L1->stack.p; + L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; ci->callstatus = CIST_C; - ci->func = L1->top; + ci->func.p = L1->top.p; ci->u.c.k = NULL; ci->nresults = 0; - setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ - L1->top++; - ci->top = L1->top + LUA_MINSTACK; + setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ + L1->top.p++; + ci->top.p = L1->top.p + LUA_MINSTACK; L1->ci = ci; } static void freestack (lua_State *L) { - if (L->stack == NULL) + if (L->stack.p == NULL) return; /* stack not completely built yet */ L->ci = &L->base_ci; /* free the entire 'ci' list */ luaE_freeCI(L); lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ + luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ } @@ -177574,7 +177718,7 @@ static void f_luaopen (lua_State *L, void *ud) { */ static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; - L->stack = NULL; + L->stack.p = NULL; L->ci = NULL; L->nci = 0; L->twups = L; /* thread has no upvalues */ @@ -177610,20 +177754,16 @@ static void close_state (lua_State *L) { LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g; + global_State *g = G(L); + GCObject *o; lua_State *L1; lua_lock(L); - g = G(L); luaC_checkGC(L); /* create new thread */ - L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g); - L1->tt = LUA_VTHREAD; - /* link it on list 'allgc' */ - L1->next = g->allgc; - g->allgc = obj2gco(L1); + o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l)); + L1 = gco2th(o); /* anchor it on L stack */ - setthvalue2s(L, L->top, L1); + setthvalue2s(L, L->top.p, L1); api_incr_top(L); preinit_thread(L1, g); L1->hookmask = L->hookmask; @@ -177642,7 +177782,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { void luaE_freethread (lua_State *L, lua_State *L1) { LX *l = fromstate(L1); - luaF_closeupval(L1, L1->stack); /* close all upvalues */ + luaF_closeupval(L1, L1->stack.p); /* close all upvalues */ lua_assert(L1->openupval == NULL); luai_userstatefree(L, L1); freestack(L1); @@ -177652,32 +177792,41 @@ void luaE_freethread (lua_State *L, lua_State *L1) { int luaE_resetthread (lua_State *L, int status) { CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ - setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ - ci->func = L->stack; + setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ + ci->func.p = L->stack.p; ci->callstatus = CIST_C; if (status == LUA_YIELD) status = LUA_OK; L->status = LUA_OK; /* so it can run __close metamethods */ status = luaD_closeprotected(L, 1, status); if (status != LUA_OK) /* errors? */ - luaD_seterrorobj(L, status, L->stack + 1); + luaD_seterrorobj(L, status, L->stack.p + 1); else - L->top = L->stack + 1; - ci->top = L->top + LUA_MINSTACK; - luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); + L->top.p = L->stack.p + 1; + ci->top.p = L->top.p + LUA_MINSTACK; + luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); return status; } -LUA_API int lua_resetthread (lua_State *L) { +LUA_API int lua_closethread (lua_State *L, lua_State *from) { int status; lua_lock(L); + L->nCcalls = (from) ? getCcalls(from) : 0; status = luaE_resetthread(L, L->status); lua_unlock(L); return status; } +/* +** Deprecated! Use 'lua_closethread' instead. +*/ +LUA_API int lua_resetthread (lua_State *L) { + return lua_closethread(L, NULL); +} + + LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; @@ -177752,7 +177901,7 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) { ** Generate a warning from an error message */ void luaE_warnerror (lua_State *L, const char *where) { - TValue *errobj = s2v(L->top - 1); /* error object */ + TValue *errobj = s2v(L->top.p - 1); /* error object */ const char *msg = (ttisstring(errobj)) ? svalue(errobj) : "error object is not a string"; @@ -178018,12 +178167,13 @@ void luaC_fix (lua_State *L, GCObject *o) { /* -** create a new collectable object (with given type and size) and link -** it to 'allgc' list. +** create a new collectable object (with given type, size, and offset) +** and link it to 'allgc' list. */ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { +GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { global_State *g = G(L); - GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); + GCObject *o = cast(GCObject *, p + offset); o->marked = luaC_white(g); o->tt = tt; o->next = g->allgc; @@ -178031,6 +178181,11 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { return o; } + +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + return luaC_newobjdt(L, tt, sz, 0); +} + /* }====================================================== */ @@ -178067,7 +178222,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { set2gray(uv); /* open upvalues are kept gray */ else set2black(uv); /* closed upvalues are visited here */ - markvalue(g, uv->v); /* mark its content */ + markvalue(g, uv->v.p); /* mark its content */ break; } case LUA_VUSERDATA: { @@ -178142,7 +178297,7 @@ static int remarkupvals (global_State *g) { work++; if (!iswhite(uv)) { /* upvalue already visited? */ lua_assert(upisopen(uv) && isgray(uv)); - markvalue(g, uv->v); /* mark its value */ + markvalue(g, uv->v.p); /* mark its value */ } } } @@ -178386,19 +178541,19 @@ static int traverseLclosure (global_State *g, LClosure *cl) { */ static int traversethread (global_State *g, lua_State *th) { UpVal *uv; - StkId o = th->stack; + StkId o = th->stack.p; if (isold(th) || g->gcstate == GCSpropagate) linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ if (o == NULL) return 1; /* stack not completely built yet */ lua_assert(g->gcstate == GCSatomic || th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ + for (; o < th->top.p; o++) /* mark live elements in the stack */ markvalue(g, s2v(o)); for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ - for (; o < th->stack_last + EXTRA_STACK; o++) + for (; o < th->stack_last.p + EXTRA_STACK; o++) setnilvalue(s2v(o)); /* clear dead stack slice */ /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { @@ -178658,7 +178813,7 @@ static GCObject *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); + luaD_callnoyield(L, L->top.p - 2, 0); } @@ -178675,16 +178830,16 @@ static void GCTM (lua_State *L) { int oldgcstp = g->gcstp; g->gcstp |= GCSTPGC; /* avoid GC steps */ L->allowhook = 0; /* stop debug hooks during GC metamethod */ - setobj2s(L, L->top++, tm); /* push finalizer... */ - setobj2s(L, L->top++, &v); /* ... and its argument */ + setobj2s(L, L->top.p++, tm); /* push finalizer... */ + setobj2s(L, L->top.p++, &v); /* ... and its argument */ L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0); L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ g->gcstp = oldgcstp; /* restore state */ if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ luaE_warnerror(L, "__gc"); - L->top--; /* pops error object */ + L->top.p--; /* pops error object */ } } } @@ -178807,7 +178962,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** ======================================================= */ -static void setpause (global_State *g); + +/* +** Set the "time" to wait before starting a new GC cycle; cycle will +** start when memory use hits the threshold of ('estimate' * pause / +** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, +** because Lua cannot even start with less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + int pause = getgcparam(g->gcpause); + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (pause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * pause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + if (debt > 0) debt = 0; + luaE_setdebt(g, debt); +} /* @@ -179051,6 +179224,15 @@ static void atomic2gen (lua_State *L, global_State *g) { } +/* +** Set debt for the next minor collection, which will happen when +** memory grows 'genminormul'%. +*/ +static void setminordebt (global_State *g) { + luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); +} + + /* ** Enter generational mode. Must go until the end of an atomic cycle ** to ensure that all objects are correctly marked and weak tables @@ -179063,6 +179245,7 @@ static lu_mem entergen (lua_State *L, global_State *g) { luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ numobjs = atomic(L); /* propagates all and then do the atomic stuff */ atomic2gen(L, g); + setminordebt(g); /* set debt assuming next cycle will be minor */ return numobjs; } @@ -179108,15 +179291,6 @@ static lu_mem fullgen (lua_State *L, global_State *g) { } -/* -** Set debt for the next minor collection, which will happen when -** memory grows 'genminormul'%. -*/ -static void setminordebt (global_State *g) { - luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); -} - - /* ** Does a major collection after last collection was a "bad collection". ** @@ -179188,8 +179362,8 @@ static void genstep (lua_State *L, global_State *g) { lu_mem numobjs = fullgen(L, g); /* do a major collection */ if (gettotalbytes(g) < majorbase + (majorinc / 2)) { /* collected at least half of memory growth since last major - collection; keep doing minor collections */ - setminordebt(g); + collection; keep doing minor collections. */ + lua_assert(g->lastatomic == 0); } else { /* bad collection */ g->lastatomic = numobjs; /* signal that last collection was bad */ @@ -179215,26 +179389,6 @@ static void genstep (lua_State *L, global_State *g) { */ -/* -** Set the "time" to wait before starting a new GC cycle; cycle will -** start when memory use hits the threshold of ('estimate' * pause / -** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, -** because Lua cannot even start with less than PAUSEADJ bytes). -*/ -static void setpause (global_State *g) { - l_mem threshold, debt; - int pause = getgcparam(g->gcpause); - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (pause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * pause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - if (debt > 0) debt = 0; - luaE_setdebt(g, debt); -} - - /* ** Enter first sweep phase. ** The call to 'sweeptolive' makes the pointer point to an object @@ -179442,12 +179596,15 @@ static void incstep (lua_State *L, global_State *g) { } /* -** performs a basic GC step if collector is running +** Performs a basic GC step if collector is running. (If collector is +** not running, set a reasonable debt to avoid it being called at +** every single check.) */ void luaC_step (lua_State *L) { global_State *g = G(L); - lua_assert(!g->gcemergency); - if (gcrunning(g)) { /* running? */ + if (!gcrunning(g)) /* not running? */ + luaE_setdebt(g, -2000); + else { if(isdecGCmodegen(g)) genstep(L, g); else @@ -179625,7 +179782,7 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { ** ensuring there is only one copy of each unique string. The table ** here is used as a set: the string enters as the key, while its value ** is irrelevant. We use the string itself as the value only because it -** is a TValue readly available. Later, the code generation can change +** is a TValue readily available. Later, the code generation can change ** this value. */ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { @@ -179635,12 +179792,12 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { if (!ttisnil(o)) /* string already present? */ ts = keystrval(nodefromval(o)); /* get saved copy */ else { /* not in use yet */ - TValue *stv = s2v(L->top++); /* reserve stack space for string */ + TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ setsvalue(L, stv, ts); /* temporarily anchor the string */ luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ /* table is not a metatable, so it does not need to invalidate cache */ luaC_checkGC(L); - L->top--; /* remove string from stack */ + L->top.p--; /* remove string from stack */ } return ts; } @@ -181429,6 +181586,35 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, } +/* +** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) { + lua_assert(baser <= opr && + ((baser == OPR_ADD && opr <= OPR_SHR) || + (baser == OPR_LT && opr <= OPR_LE))); + return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base)); +} + + +/* +** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode unopr2op (UnOpr opr) { + return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) + + cast_int(OP_UNM)); +} + + +/* +** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM) +*/ +l_sinline TMS binopr2TM (BinOpr opr) { + lua_assert(OPR_ADD <= opr && opr <= OPR_SHR); + return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD)); +} + + /* ** Emit code for unary expressions that "produce values" ** (everything but 'not'). @@ -181467,12 +181653,15 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, ** Emit code for binary expressions that "produce values" over ** two registers. */ -static void codebinexpval (FuncState *fs, OpCode op, +static void codebinexpval (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { - int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADD); + int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */ + /* 'e1' must be already in a register or it is a constant */ + lua_assert((VNIL <= e1->k && e1->k <= VKSTR) || + e1->k == VNONRELOC || e1->k == VRELOC); lua_assert(OP_ADD <= op && op <= OP_SHR); - finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, - cast(TMS, (op - OP_ADD) + TM_ADD)); + finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr)); } @@ -181488,6 +181677,18 @@ static void codebini (FuncState *fs, OpCode op, } +/* +** Code binary operators with K operand. +*/ +static void codebinK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + TMS event = binopr2TM(opr); + int v2 = e2->u.info; /* K index */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); +} + + /* Try to code a binary operator negating its second operand. ** For the metamethod, 2nd operand must keep its original value. */ @@ -181515,24 +181716,27 @@ static void swapexps (expdesc *e1, expdesc *e2) { } +/* +** Code binary operators with no constant operand. +*/ +static void codebinNoK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + if (flip) + swapexps(e1, e2); /* back to original order */ + codebinexpval(fs, opr, e1, e2, line); /* use standard operators */ +} + + /* ** Code arithmetic operators ('+', '-', ...). If second operand is a ** constant in the proper range, use variant opcodes with K operands. */ static void codearith (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int flip, int line) { - TMS event = cast(TMS, opr + TM_ADD); - if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ - int v2 = e2->u.info; /* K index */ - OpCode op = cast(OpCode, opr + OP_ADDK); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); - } - else { /* 'e2' is neither an immediate nor a K operand */ - OpCode op = cast(OpCode, opr + OP_ADD); - if (flip) - swapexps(e1, e2); /* back to original order */ - codebinexpval(fs, op, e1, e2, line); /* use standard operators */ - } + if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* 'e2' is neither an immediate nor a K operand */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -181549,35 +181753,27 @@ static void codecommutative (FuncState *fs, BinOpr op, flip = 1; } if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ - codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); + codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD); else codearith(fs, op, e1, e2, flip, line); } /* -** Code bitwise operations; they are all associative, so the function +** Code bitwise operations; they are all commutative, so the function ** tries to put an integer constant as the 2nd operand (a K operand). */ static void codebitwise (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { int flip = 0; - int v2; - OpCode op; - if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { + if (e1->k == VKINT) { swapexps(e1, e2); /* 'e2' will be the constant operand */ flip = 1; } - else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ - op = cast(OpCode, opr + OP_ADD); - codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ - return; - } - v2 = e2->u.info; /* index in K array */ - op = cast(OpCode, opr + OP_ADDK); - lua_assert(ttisinteger(&fs->f->k[v2])); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, - cast(TMS, opr + TM_ADD)); + if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* no constants */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -181585,25 +181781,27 @@ static void codebitwise (FuncState *fs, BinOpr opr, ** Emit code for order comparisons. When using an immediate operand, ** 'isfloat' tells whether the original value was a float. */ -static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { +static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { int r1, r2; int im; int isfloat = 0; + OpCode op; if (isSCnumber(e2, &im, &isfloat)) { /* use immediate operand */ r1 = luaK_exp2anyreg(fs, e1); r2 = im; - op = cast(OpCode, (op - OP_LT) + OP_LTI); + op = binopr2op(opr, OPR_LT, OP_LTI); } else if (isSCnumber(e1, &im, &isfloat)) { /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ r1 = luaK_exp2anyreg(fs, e2); r2 = im; - op = (op == OP_LT) ? OP_GTI : OP_GEI; + op = binopr2op(opr, OPR_LT, OP_GTI); } else { /* regular case, compare two registers */ r1 = luaK_exp2anyreg(fs, e1); r2 = luaK_exp2anyreg(fs, e2); + op = binopr2op(opr, OPR_LT, OP_LT); } freeexps(fs, e1, e2); e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); @@ -181629,7 +181827,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { op = OP_EQI; r2 = im; /* immediate operand */ } - else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */ op = OP_EQK; r2 = e2->u.info; /* constant index */ } @@ -181646,16 +181844,16 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { /* ** Apply prefix operation 'op' to expression 'e'. */ -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { +void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) { static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; luaK_dischargevars(fs, e); - switch (op) { + switch (opr) { case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + if (constfolding(fs, opr + LUA_OPUNM, e, &ef)) break; /* else */ /* FALLTHROUGH */ case OPR_LEN: - codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + codeunexpval(fs, unopr2op(opr), e, line); break; case OPR_NOT: codenot(fs, e); break; default: lua_assert(0); @@ -181689,7 +181887,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { case OPR_SHL: case OPR_SHR: { if (!tonumeral(v, NULL)) luaK_exp2anyreg(fs, v); - /* else keep numeral, which may be folded with 2nd operand */ + /* else keep numeral, which may be folded or used as an immediate + operand */ break; } case OPR_EQ: case OPR_NE: { @@ -181784,30 +181983,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr, /* coded as (r1 >> -I) */; } else /* regular case (two registers) */ - codebinexpval(fs, OP_SHL, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_SHR: { if (isSCint(e2)) codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ else /* regular case (two registers) */ - codebinexpval(fs, OP_SHR, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_EQ: case OPR_NE: { codeeq(fs, opr, e1, e2); break; } - case OPR_LT: case OPR_LE: { - OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - codeorder(fs, op, e1, e2); - break; - } case OPR_GT: case OPR_GE: { /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ - OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); swapexps(e1, e2); - codeorder(fs, op, e1, e2); + opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT); + } /* FALLTHROUGH */ + case OPR_LT: case OPR_LE: { + codeorder(fs, opr, e1, e2); break; } default: lua_assert(0); @@ -182378,6 +182574,7 @@ static void singlevar (LexState *ls, expdesc *var) { expdesc key; singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ lua_assert(var->k != VVOID); /* this one must exist */ + luaK_exp2anyregup(fs, var); /* but could be a constant */ codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ } @@ -182430,12 +182627,12 @@ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { /* ** Solves the goto at index 'g' to given 'label' and removes it -** from the list of pending goto's. +** from the list of pending gotos. ** If it jumps into the scope of some variable, raises an error. */ static void solvegoto (LexState *ls, int g, Labeldesc *label) { int i; - Labellist *gl = &ls->dyd->gt; /* list of goto's */ + Labellist *gl = &ls->dyd->gt; /* list of gotos */ Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ lua_assert(eqstr(gt->name, label->name)); if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ @@ -182489,7 +182686,7 @@ static int newgotoentry (LexState *ls, TString *name, int line, int pc) { /* ** Solves forward jumps. Check whether new label 'lb' matches any ** pending gotos in current block and solves them. Return true -** if any of the goto's need to close upvalues. +** if any of the gotos need to close upvalues. */ static int solvegotos (LexState *ls, Labeldesc *lb) { Labellist *gl = &ls->dyd->gt; @@ -182510,7 +182707,7 @@ static int solvegotos (LexState *ls, Labeldesc *lb) { /* ** Create a new label with the given 'name' at the given 'line'. ** 'last' tells whether label is the last non-op statement in its -** block. Solves all pending goto's to this new label and adds +** block. Solves all pending gotos to this new label and adds ** a close instruction if necessary. ** Returns true iff it added a close instruction. */ @@ -182583,19 +182780,19 @@ static void leaveblock (FuncState *fs) { LexState *ls = fs->ls; int hasclose = 0; int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ - if (bl->isloop) /* fix pending breaks? */ + removevars(fs, bl->nactvar); /* remove block locals */ + lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ + if (bl->isloop) /* has to fix pending breaks? */ hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); - if (!hasclose && bl->previous && bl->upval) + if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */ luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); fs->freereg = stklevel; /* free registers */ ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ + fs->bl = bl->previous; /* current block now is previous one */ + if (bl->previous) /* was it a nested block? */ + movegotosout(fs, bl); /* update pending gotos to enclosing block */ else { - if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } } @@ -183853,10 +184050,10 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, LexState lexstate; FuncState funcstate; LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue2s(L, L->top, cl); /* anchor it (to avoid being collected) */ + setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ luaD_inctop(L); lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue2s(L, L->top, lexstate.h); /* anchor it */ + sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */ luaD_inctop(L); funcstate.f = cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -183870,7 +184067,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); /* all scopes should be correctly finished */ lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top--; /* remove scanner's table */ + L->top.p--; /* remove scanner's table */ return cl; /* closure is on the stack, too */ } @@ -184058,10 +184255,10 @@ static const char *upvalname (const Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func))->p->is_vararg) { + if (clLvalue(s2v(ci->func.p))->p->is_vararg) { int nextra = ci->u.l.nextraargs; if (n >= -nextra) { /* 'n' is negative */ - *pos = ci->func - nextra - (n + 1); + *pos = ci->func.p - nextra - (n + 1); return "(vararg)"; /* generic name for any vararg */ } } @@ -184070,7 +184267,7 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) { const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; const char *name = NULL; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ @@ -184079,7 +184276,7 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); } if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; + StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p; if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */ /* generic name for any valid slot */ name = isLua(ci) ? "(temporary)" : "(C temporary)"; @@ -184097,16 +184294,16 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */ + if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0); + name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0); } else { /* active function; get information through 'ar' */ StkId pos = NULL; /* to avoid warnings */ name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, L->top, pos); + setobjs2s(L, L->top.p, pos); api_incr_top(L); } } @@ -184121,8 +184318,8 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { lua_lock(L); name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ + setobjs2s(L, pos, L->top.p - 1); + L->top.p--; /* pop value */ } lua_unlock(L); return name; @@ -184165,7 +184362,7 @@ static int nextline (const Proto *p, int currentline, int pc) { static void collectvalidlines (lua_State *L, Closure *f) { if (noLuaClosure(f)) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); } else { @@ -184174,7 +184371,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { const Proto *p = f->l.p; int currentline = p->linedefined; Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue2s(L, L->top, t); /* push it on stack */ + sethvalue2s(L, L->top.p, t); /* push it on stack */ api_incr_top(L); setbtvalue(&v); /* boolean 'true' to be the value of all indices */ if (!p->is_vararg) /* regular function? */ @@ -184264,20 +184461,20 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { lua_lock(L); if (*what == '>') { ci = NULL; - func = s2v(L->top - 1); + func = s2v(L->top.p - 1); api_check(L, ttisfunction(func), "function expected"); what++; /* skip the '>' */ - L->top--; /* pop function */ + L->top.p--; /* pop function */ } else { ci = ar->i_ci; - func = s2v(ci->func); + func = s2v(ci->func.p); lua_assert(ttisfunction(func)); } cl = ttisclosure(func) ? clvalue(func) : NULL; status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - setobj2s(L, L->top, func); + setobj2s(L, L->top.p, func); api_incr_top(L); } if (strchr(what, 'L')) @@ -184532,18 +184729,19 @@ static const char *funcnamefromcall (lua_State *L, CallInfo *ci, /* -** Check whether pointer 'o' points to some value in the stack -** frame of the current function. Because 'o' may not point to a -** value in this stack, we cannot compare it with the region -** boundaries (undefined behaviour in ISO C). +** Check whether pointer 'o' points to some value in the stack frame of +** the current function and, if so, returns its index. Because 'o' may +** not point to a value in this stack, we cannot compare it with the +** region boundaries (undefined behavior in ISO C). */ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId pos; - for (pos = ci->func + 1; pos < ci->top; pos++) { - if (o == s2v(pos)) - return 1; +static int instack (CallInfo *ci, const TValue *o) { + int pos; + StkId base = ci->func.p + 1; + for (pos = 0; base + pos < ci->top.p; pos++) { + if (o == s2v(base + pos)) + return pos; } - return 0; /* not found */ + return -1; /* not found */ } @@ -184557,7 +184755,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, LClosure *c = ci_func(ci); int i; for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { + if (c->upvals[i]->v.p == o) { *name = upvalname(c->p, i); return "upvalue"; } @@ -184584,9 +184782,11 @@ static const char *varinfo (lua_State *L, const TValue *o) { const char *kind = NULL; if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(cast(StkId, o) - (ci->func + 1)), &name); + if (!kind) { /* not an upvalue? */ + int reg = instack(ci, o); /* try a register */ + if (reg >= 0) /* is 'o' a register? */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name); + } } return formatvarinfo(L, kind, name); } @@ -184683,10 +184883,10 @@ l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); lua_assert(ttisfunction(s2v(errfunc))); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top - 2, 1); /* call it */ + setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */ + setobjs2s(L, L->top.p - 1, errfunc); /* push function */ + L->top.p++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } @@ -184700,8 +184900,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ + if (isLua(ci)) { /* if Lua function, add source:line information */ luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); + setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ + L->top.p--; + } luaG_errormsg(L); } @@ -184718,7 +184921,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { if (p->lineinfo == NULL) /* no debug information? */ return 0; if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */ - int delta = 0; /* line diference */ + int delta = 0; /* line difference */ int pc = oldpc; for (;;) { int lineinfo = p->lineinfo[++pc]; @@ -184745,7 +184948,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { ** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc' ** at most causes an extra call to a line hook.) ** This function is not "Protected" when called, so it should correct -** 'L->top' before calling anything that can run the GC. +** 'L->top.p' before calling anything that can run the GC. */ int luaG_traceexec (lua_State *L, const Instruction *pc) { CallInfo *ci = L->ci; @@ -184768,7 +184971,7 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { return 1; /* do not call hook again (VM yielded, so it did not move) */ } if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ - L->top = ci->top; /* correct top */ + L->top.p = ci->top.p; /* correct top */ if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ if (mask & LUA_MASKLINE) { @@ -184844,8 +185047,8 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { for (i = 0; i < cl->nupvalues; i++) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); - uv->v = &uv->u.value; /* make it closed */ - setnilvalue(uv->v); + uv->v.p = &uv->u.value; /* make it closed */ + setnilvalue(uv->v.p); cl->upvals[i] = uv; luaC_objbarrier(L, cl, uv); } @@ -184856,12 +185059,11 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { ** Create a new upvalue at the given level, and link it to the list of ** open upvalues of 'L' after entry 'prev'. **/ -static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { +static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); UpVal *next = *prev; - uv->v = s2v(level); /* current value lives in the stack */ - uv->tbc = tbc; + uv->v.p = s2v(level); /* current value lives in the stack */ uv->u.open.next = next; /* link it to list of open upvalues */ uv->u.open.previous = prev; if (next) @@ -184890,7 +185092,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { pp = &p->u.open.next; } /* not found: create a new upvalue after 'pp' */ - return newupval(L, 0, level, pp); + return newupval(L, level, pp); } @@ -184900,12 +185102,12 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { ** (This function assumes EXTRA_STACK.) */ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { - StkId top = L->top; + StkId top = L->top.p; const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); setobj2s(L, top, tm); /* will call metamethod... */ setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ - L->top = top + 3; /* add function and arguments */ + L->top.p = top + 3; /* add function and arguments */ if (yy) luaD_call(L, top, 0); else @@ -184920,7 +185122,7 @@ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { static void checkclosemth (lua_State *L, StkId level) { const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); if (ttisnil(tm)) { /* no metamethod? */ - int idx = cast_int(level - L->ci->func); /* variable index */ + int idx = cast_int(level - L->ci->func.p); /* variable index */ const char *vname = luaG_findlocal(L, L->ci, idx, NULL); if (vname == NULL) vname = "?"; luaG_runerror(L, "variable '%s' got a non-closable value", vname); @@ -184954,23 +185156,23 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { ** is used.) */ #define MAXDELTA \ - ((256ul << ((sizeof(L->stack->tbclist.delta) - 1) * 8)) - 1) + ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) /* ** Insert a variable in the list of to-be-closed variables. */ void luaF_newtbcupval (lua_State *L, StkId level) { - lua_assert(level > L->tbclist); + lua_assert(level > L->tbclist.p); if (l_isfalse(s2v(level))) return; /* false doesn't need to be closed */ checkclosemth(L, level); /* value must have a close method */ - while (cast_uint(level - L->tbclist) > MAXDELTA) { - L->tbclist += MAXDELTA; /* create a dummy node at maximum delta */ - L->tbclist->tbclist.delta = 0; + while (cast_uint(level - L->tbclist.p) > MAXDELTA) { + L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ + L->tbclist.p->tbclist.delta = 0; } - level->tbclist.delta = cast(unsigned short, level - L->tbclist); - L->tbclist = level; + level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); + L->tbclist.p = level; } @@ -184990,10 +185192,10 @@ void luaF_closeupval (lua_State *L, StkId level) { StkId upl; /* stack index pointed by 'uv' */ while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { TValue *slot = &uv->u.value; /* new position for value */ - lua_assert(uplevel(uv) < L->top); + lua_assert(uplevel(uv) < L->top.p); luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ - setobj(L, slot, uv->v); /* move value to upvalue slot */ - uv->v = slot; /* now current value lives here */ + setobj(L, slot, uv->v.p); /* move value to upvalue slot */ + uv->v.p = slot; /* now current value lives here */ if (!iswhite(uv)) { /* neither white nor dead? */ nw2black(uv); /* closed upvalues cannot be gray */ luaC_barrier(L, uv, slot); @@ -185003,31 +185205,32 @@ void luaF_closeupval (lua_State *L, StkId level) { /* -** Remove firt element from the tbclist plus its dummy nodes. +** Remove first element from the tbclist plus its dummy nodes. */ static void poptbclist (lua_State *L) { - StkId tbc = L->tbclist; + StkId tbc = L->tbclist.p; lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ tbc -= tbc->tbclist.delta; - while (tbc > L->stack && tbc->tbclist.delta == 0) + while (tbc > L->stack.p && tbc->tbclist.delta == 0) tbc -= MAXDELTA; /* remove dummy nodes */ - L->tbclist = tbc; + L->tbclist.p = tbc; } /* ** Close all upvalues and to-be-closed variables up to the given stack -** level. +** level. Return restored 'level'. */ -void luaF_close (lua_State *L, StkId level, int status, int yy) { +StkId luaF_close (lua_State *L, StkId level, int status, int yy) { ptrdiff_t levelrel = savestack(L, level); luaF_closeupval(L, level); /* first, close the upvalues */ - while (L->tbclist >= level) { /* traverse tbc's down to that level */ - StkId tbc = L->tbclist; /* get variable index */ + while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ + StkId tbc = L->tbclist.p; /* get variable index */ poptbclist(L); /* remove it from list */ prepcallclosemth(L, tbc, status, yy); /* close variable */ level = restorestack(L, levelrel); } + return level; } @@ -185150,7 +185353,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, case LUA_OPBOR: return intop(|, v1, v2); case LUA_OPBXOR: return intop(^, v1, v2); case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPSHR: return luaV_shiftr(v1, v2); case LUA_OPUNM: return intop(-, 0, v1); case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); default: lua_assert(0); return 0; @@ -185474,29 +185677,39 @@ void luaO_tostring (lua_State *L, TValue *obj) { ** =================================================================== */ -/* size for buffer space used by 'luaO_pushvfstring' */ -#define BUFVFS 200 +/* +** Size for buffer space used by 'luaO_pushvfstring'. It should be +** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, +** so that 'luaG_addinfo' can work directly on the buffer. +*/ +#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) /* buffer used by 'luaO_pushvfstring' */ typedef struct BuffFS { lua_State *L; - int pushed; /* number of string pieces already on the stack */ + int pushed; /* true if there is a part of the result on the stack */ int blen; /* length of partial string in 'space' */ char space[BUFVFS]; /* holds last part of the result */ } BuffFS; /* -** Push given string to the stack, as part of the buffer, and -** join the partial strings in the stack into one. +** Push given string to the stack, as part of the result, and +** join it to previous partial result if there is one. +** It may call 'luaV_concat' while using one slot from EXTRA_STACK. +** This call cannot invoke metamethods, as both operands must be +** strings. It can, however, raise an error if the result is too +** long. In that case, 'luaV_concat' frees the extra slot before +** raising the error. */ -static void pushstr (BuffFS *buff, const char *str, size_t l) { +static void pushstr (BuffFS *buff, const char *str, size_t lstr) { lua_State *L = buff->L; - setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); - L->top++; /* may use one extra slot */ - buff->pushed++; - luaV_concat(L, buff->pushed); /* join partial results into one */ - buff->pushed = 1; + setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr)); + L->top.p++; /* may use one slot from EXTRA_STACK */ + if (!buff->pushed) /* no previous string on the stack? */ + buff->pushed = 1; /* now there is one */ + else /* join previous string with new one */ + luaV_concat(L, 2); } @@ -185542,7 +185755,7 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { /* -** Add a number to the buffer. +** Add a numeral to the buffer. */ static void addnum2buff (BuffFS *buff, TValue *num) { char *numbuff = getbuff(buff, MAXNUMBER2STR); @@ -185620,7 +185833,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ clearbuff(&buff); /* empty buffer into the stack */ lua_assert(buff.pushed == 1); - return svalue(s2v(L->top - 1)); + return svalue(s2v(L->top.p - 1)); } @@ -185782,12 +185995,12 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) { void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ setobj2s(L, func + 3, p3); /* 3rd argument */ - L->top = func + 4; + L->top.p = func + 4; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 0); @@ -185799,18 +186012,18 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top += 3; + L->top.p += 3; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 1); else luaD_callnoyield(L, func, 1); res = restorestack(L, result); - setobjs2s(L, res, --L->top); /* move result to its place */ + setobjs2s(L, res, --L->top.p); /* move result to its place */ } @@ -185845,7 +186058,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, void luaT_tryconcatTM (lua_State *L) { - StkId top = L->top; + StkId top = L->top.p; if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT))) luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); @@ -185880,15 +186093,15 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, */ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { - if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ - return !l_isfalse(s2v(L->top)); + if (callbinTM(L, p1, p2, L->top.p, event)) /* try original event */ + return !l_isfalse(s2v(L->top.p)); #if defined(LUA_COMPAT_LT_LE) else if (event == TM_LE) { /* try '!(p2 < p1)' for '(p1 <= p2)' */ L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - if (callbinTM(L, p2, p1, L->top, TM_LT)) { + if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - return l_isfalse(s2v(L->top)); + return l_isfalse(s2v(L->top.p)); } /* else error will remove this 'ci'; no need to clear mark */ } @@ -185918,20 +186131,20 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, const Proto *p) { int i; - int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ + int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */ int nextra = actual - nfixparams; /* number of extra arguments */ ci->u.l.nextraargs = nextra; luaD_checkstack(L, p->maxstacksize + 1); /* copy function to the top of the stack */ - setobjs2s(L, L->top++, ci->func); + setobjs2s(L, L->top.p++, ci->func.p); /* move fixed parameters to the top of the stack */ for (i = 1; i <= nfixparams; i++) { - setobjs2s(L, L->top++, ci->func + i); - setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */ + setobjs2s(L, L->top.p++, ci->func.p + i); + setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ } - ci->func += actual + 1; - ci->top += actual + 1; - lua_assert(L->top <= ci->top && ci->top <= L->stack_last); + ci->func.p += actual + 1; + ci->top.p += actual + 1; + lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); } @@ -185941,10 +186154,10 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { if (wanted < 0) { wanted = nextra; /* get all extra arguments available */ checkstackGCp(L, nextra, where); /* ensure stack space */ - L->top = where + nextra; /* next instruction will need top */ + L->top.p = where + nextra; /* next instruction will need top */ } for (i = 0; i < wanted && i < nextra; i++) - setobjs2s(L, where + i, ci->func - nextra + i); + setobjs2s(L, where + i, ci->func.p - nextra + i); for (; i < wanted; i++) /* complete required results with nil */ setnilvalue(s2v(where + i)); } @@ -186331,7 +186544,7 @@ static const TValue absentkey = {ABSTKEYCONSTANT}; */ static Node *hashint (const Table *t, lua_Integer i) { lua_Unsigned ui = l_castS2U(i); - if (ui <= (unsigned int)INT_MAX) + if (ui <= cast_uint(INT_MAX)) return hashmod(t, cast_int(ui)); else return hashmod(t, ui); @@ -186481,9 +186694,11 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) { size |= (size >> 2); size |= (size >> 4); size |= (size >> 8); +#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */ size |= (size >> 16); #if (UINT_MAX >> 30) > 3 size |= (size >> 32); /* unsigned int has more than 32 bits */ +#endif #endif size++; lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); @@ -186712,7 +186927,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { luaG_runerror(L, "table overflow"); size = twoto(lsize); t->node = luaM_newvector(L, size, Node); - for (i = 0; i < (int)size; i++) { + for (i = 0; i < cast_int(size); i++) { Node *n = gnode(t, i); gnext(n) = 0; setnilkey(n); @@ -187199,8 +187414,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainpositionTV(t, key); } -int luaH_isdummy (const Table *t) { return isdummy(t); } - #endif /* ** $Id: ldo.c $ @@ -187308,11 +187521,11 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { } default: { lua_assert(errorstatus(errcode)); /* real error */ - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ break; } } - L->top = oldtop + 1; + L->top.p = oldtop + 1; } @@ -187325,7 +187538,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { global_State *g = G(L); errcode = luaE_resetthread(L, errcode); /* close all upvalues */ if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ } else { /* no handler at all; abort */ @@ -187361,16 +187574,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ** Stack reallocation ** =================================================================== */ -static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { + + +/* +** Change all pointers to the stack into offsets. +*/ +static void relstack (lua_State *L) { CallInfo *ci; UpVal *up; - L->top = (L->top - oldstack) + newstack; - L->tbclist = (L->tbclist - oldstack) + newstack; + L->top.offset = savestack(L, L->top.p); + L->tbclist.offset = savestack(L, L->tbclist.p); for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v = s2v((uplevel(up) - oldstack) + newstack); + up->v.offset = savestack(L, uplevel(up)); for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + newstack; - ci->func = (ci->func - oldstack) + newstack; + ci->top.offset = savestack(L, ci->top.p); + ci->func.offset = savestack(L, ci->func.p); + } +} + + +/* +** Change back all offsets into pointers. +*/ +static void correctstack (lua_State *L) { + CallInfo *ci; + UpVal *up; + L->top.p = restorestack(L, L->top.offset); + L->tbclist.p = restorestack(L, L->tbclist.offset); + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v.p = s2v(restorestack(L, up->v.offset)); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top.p = restorestack(L, ci->top.offset); + ci->func.p = restorestack(L, ci->func.offset); if (isLua(ci)) ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ } @@ -187380,44 +187615,45 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { /* some space for error handling */ #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - /* -** Reallocate the stack to a new size, correcting all pointers into -** it. (There are pointers to a stack from its upvalues, from its list -** of call infos, plus a few individual pointers.) The reallocation is -** done in two steps (allocation + free) because the correction must be -** done while both addresses (the old stack and the new one) are valid. -** (In ISO C, any pointer use after the pointer has been deallocated is -** undefined behavior.) +** Reallocate the stack to a new size, correcting all pointers into it. +** In ISO C, any pointer use after the pointer has been deallocated is +** undefined behavior. So, before the reallocation, all pointers are +** changed to offsets, and after the reallocation they are changed back +** to pointers. As during the reallocation the pointers are invalid, the +** reallocation cannot run emergency collections. +** ** In case of allocation error, raise an error or return false according ** to 'raiseerror'. */ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { int oldsize = stacksize(L); int i; - StkId newstack = luaM_reallocvector(L, NULL, 0, - newsize + EXTRA_STACK, StackValue); + StkId newstack; + int oldgcstop = G(L)->gcstopem; lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + relstack(L); /* change pointers to offsets */ + G(L)->gcstopem = 1; /* stop emergency collection */ + newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, + newsize + EXTRA_STACK, StackValue); + G(L)->gcstopem = oldgcstop; /* restore emergency collection */ if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ + correctstack(L); /* change offsets back to pointers */ if (raiseerror) luaM_error(L); else return 0; /* do not raise an error */ } - /* number of elements to be copied to the new stack */ - i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK; - memcpy(newstack, L->stack, i * sizeof(StackValue)); - for (; i < newsize + EXTRA_STACK; i++) + L->stack.p = newstack; + correctstack(L); /* change offsets back to pointers */ + L->stack_last.p = L->stack.p + newsize; + for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) setnilvalue(s2v(newstack + i)); /* erase new segment */ - correctstack(L, L->stack, newstack); - luaM_freearray(L, L->stack, oldsize + EXTRA_STACK); - L->stack = newstack; - L->stack_last = L->stack + newsize; return 1; } /* -** Try to grow the stack by at least 'n' elements. when 'raiseerror' +** Try to grow the stack by at least 'n' elements. When 'raiseerror' ** is true, raises any error; otherwise, return 0 in case of errors. */ int luaD_growstack (lua_State *L, int n, int raiseerror) { @@ -187431,35 +187667,38 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { luaD_throw(L, LUA_ERRERR); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } - else { + else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ int newsize = 2 * size; /* tentative new size */ - int needed = cast_int(L->top - L->stack) + n; + int needed = cast_int(L->top.p - L->stack.p) + n; if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ newsize = LUAI_MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ newsize = needed; if (l_likely(newsize <= LUAI_MAXSTACK)) return luaD_reallocstack(L, newsize, raiseerror); - else { /* stack overflow */ - /* add extra size to be able to handle the error message */ - luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); - if (raiseerror) - luaG_runerror(L, "stack overflow"); - return 0; - } } + /* else stack overflow */ + /* add extra size to be able to handle the error message */ + luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); + if (raiseerror) + luaG_runerror(L, "stack overflow"); + return 0; } +/* +** Compute how much of the stack is being used, by computing the +** maximum top of all call frames in the stack and the current top. +*/ static int stackinuse (lua_State *L) { CallInfo *ci; int res; - StkId lim = L->top; + StkId lim = L->top.p; for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; + if (lim < ci->top.p) lim = ci->top.p; } - lua_assert(lim <= L->stack_last); - res = cast_int(lim - L->stack) + 1; /* part of stack in use */ + lua_assert(lim <= L->stack_last.p + EXTRA_STACK); + res = cast_int(lim - L->stack.p) + 1; /* part of stack in use */ if (res < LUA_MINSTACK) res = LUA_MINSTACK; /* ensure a minimum size */ return res; @@ -187477,17 +187716,13 @@ static int stackinuse (lua_State *L) { */ void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); - int nsize = inuse * 2; /* proposed new size */ - int max = inuse * 3; /* maximum "reasonable" size */ - if (max > LUAI_MAXSTACK) { - max = LUAI_MAXSTACK; /* respect stack limit */ - if (nsize > LUAI_MAXSTACK) - nsize = LUAI_MAXSTACK; - } + int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3; /* if thread is currently not handling a stack overflow and its size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) { + int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2; luaD_reallocstack(L, nsize, 0); /* ok if that fails */ + } else /* don't change stack */ condmovestack(L,{},{}); /* (change only for debugging) */ luaE_shrinkCI(L); /* shrink CI list */ @@ -187496,7 +187731,7 @@ void luaD_shrinkstack (lua_State *L) { void luaD_inctop (lua_State *L) { luaD_checkstack(L, 1); - L->top++; + L->top.p++; } /* }================================================================== */ @@ -187513,8 +187748,8 @@ void luaD_hook (lua_State *L, int event, int line, if (hook && L->allowhook) { /* make sure there is a hook */ int mask = CIST_HOOKED; CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); /* preserve original 'top' */ - ptrdiff_t ci_top = savestack(L, ci->top); /* idem for 'ci->top' */ + ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */ + ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */ lua_Debug ar; ar.event = event; ar.currentline = line; @@ -187524,11 +187759,11 @@ void luaD_hook (lua_State *L, int event, int line, ci->u2.transferinfo.ftransfer = ftransfer; ci->u2.transferinfo.ntransfer = ntransfer; } - if (isLua(ci) && L->top < ci->top) - L->top = ci->top; /* protect entire activation register */ + if (isLua(ci) && L->top.p < ci->top.p) + L->top.p = ci->top.p; /* protect entire activation register */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - if (ci->top < L->top + LUA_MINSTACK) - ci->top = L->top + LUA_MINSTACK; + if (ci->top.p < L->top.p + LUA_MINSTACK) + ci->top.p = L->top.p + LUA_MINSTACK; L->allowhook = 0; /* cannot call hooks inside a hook */ ci->callstatus |= mask; lua_unlock(L); @@ -187536,8 +187771,8 @@ void luaD_hook (lua_State *L, int event, int line, lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); + ci->top.p = restorestack(L, ci_top); + L->top.p = restorestack(L, top); ci->callstatus &= ~mask; } } @@ -187568,7 +187803,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { */ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ - StkId firstres = L->top - nres; /* index of first result */ + StkId firstres = L->top.p - nres; /* index of first result */ int delta = 0; /* correction for vararg functions */ int ftransfer; if (isLua(ci)) { @@ -187576,10 +187811,10 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (p->is_vararg) delta = ci->u.l.nextraargs + p->numparams + 1; } - ci->func += delta; /* if vararg, back to virtual 'func' */ - ftransfer = cast(unsigned short, firstres - ci->func); + ci->func.p += delta; /* if vararg, back to virtual 'func' */ + ftransfer = cast(unsigned short, firstres - ci->func.p); luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ - ci->func -= delta; + ci->func.p -= delta; } if (isLua(ci = ci->previous)) L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */ @@ -187598,9 +187833,9 @@ StkId luaD_tryfuncTM (lua_State *L, StkId func) { tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ if (l_unlikely(ttisnil(tm))) luaG_callerror(L, s2v(func)); /* nothing to call */ - for (p = L->top; p > func; p--) /* open space for metamethod */ + for (p = L->top.p; p > func; p--) /* open space for metamethod */ setobjs2s(L, p, p-1); - L->top++; /* stack space pre-allocated by the caller */ + L->top.p++; /* stack space pre-allocated by the caller */ setobj2s(L, func, tm); /* metamethod is the new function to be called */ return func; } @@ -187617,28 +187852,29 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { int i; switch (wanted) { /* handle typical cases separately */ case 0: /* no values needed */ - L->top = res; + L->top.p = res; return; case 1: /* one value needed */ if (nres == 0) /* no results? */ setnilvalue(s2v(res)); /* adjust with nil */ else /* at least one result */ - setobjs2s(L, res, L->top - nres); /* move it to proper place */ - L->top = res + 1; + setobjs2s(L, res, L->top.p - nres); /* move it to proper place */ + L->top.p = res + 1; return; case LUA_MULTRET: wanted = nres; /* we want all results */ break; default: /* two/more results and/or to-be-closed variables */ if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ - ptrdiff_t savedres = savestack(L, res); L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ L->ci->u2.nres = nres; - luaF_close(L, res, CLOSEKTOP, 1); + res = luaF_close(L, res, CLOSEKTOP, 1); L->ci->callstatus &= ~CIST_CLSRET; - if (L->hookmask) /* if needed, call hook after '__close's */ + if (L->hookmask) { /* if needed, call hook after '__close's */ + ptrdiff_t savedres = savestack(L, res); rethook(L, L->ci, nres); - res = restorestack(L, savedres); /* close and hook can move stack */ + res = restorestack(L, savedres); /* hook can move stack */ + } wanted = decodeNresults(wanted); if (wanted == LUA_MULTRET) wanted = nres; /* we want all results */ @@ -187646,14 +187882,14 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { break; } /* generic case */ - firstresult = L->top - nres; /* index of first result */ + firstresult = L->top.p - nres; /* index of first result */ if (nres > wanted) /* extra results? */ nres = wanted; /* don't need them */ for (i = 0; i < nres; i++) /* move all results to correct place */ setobjs2s(L, res + i, firstresult + i); for (; i < wanted; i++) /* complete wanted number of results */ setnilvalue(s2v(res + i)); - L->top = res + wanted; /* top points after the last result */ + L->top.p = res + wanted; /* top points after the last result */ } @@ -187668,7 +187904,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) rethook(L, ci, nres); /* move results to proper place */ - moveresults(L, ci->func, nres, wanted); + moveresults(L, ci->func.p, nres, wanted); /* function cannot be in any of these cases when returning */ lua_assert(!(ci->callstatus & (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); @@ -187683,10 +187919,10 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, int mask, StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ - ci->func = func; + ci->func.p = func; ci->nresults = nret; ci->callstatus = mask; - ci->top = top; + ci->top.p = top; return ci; } @@ -187700,10 +187936,10 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults, CallInfo *ci; checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, - L->top + LUA_MINSTACK); - lua_assert(ci->top <= L->stack_last); + L->top.p + LUA_MINSTACK); + lua_assert(ci->top.p <= L->stack_last.p); if (l_unlikely(L->hookmask & LUA_MASKCALL)) { - int narg = cast_int(L->top - func) - 1; + int narg = cast_int(L->top.p - func) - 1; luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); } lua_unlock(L); @@ -187735,17 +187971,17 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int nfixparams = p->numparams; int i; checkstackGCp(L, fsize - delta, func); - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ for (i = 0; i < narg1; i++) /* move down function and arguments */ - setobjs2s(L, ci->func + i, func + i); - func = ci->func; /* moved-down function */ + setobjs2s(L, ci->func.p + i, func + i); + func = ci->func.p; /* moved-down function */ for (; narg1 <= nfixparams; narg1++) setnilvalue(s2v(func + narg1)); /* complete missing arguments */ - ci->top = func + 1 + fsize; /* top for new function */ - lua_assert(ci->top <= L->stack_last); + ci->top.p = func + 1 + fsize; /* top for new function */ + lua_assert(ci->top.p <= L->stack_last.p); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus |= CIST_TAIL; - L->top = func + narg1; /* set top */ + L->top.p = func + narg1; /* set top */ return -1; } default: { /* not a function */ @@ -187778,15 +188014,15 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { case LUA_VLCL: { /* Lua function */ CallInfo *ci; Proto *p = clLvalue(s2v(func))->p; - int narg = cast_int(L->top - func) - 1; /* number of real arguments */ + int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ checkstackGCp(L, fsize, func); L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); ci->u.l.savedpc = p->code; /* starting point */ for (; narg < nfixparams; narg++) - setnilvalue(s2v(L->top++)); /* complete missing arguments */ - lua_assert(ci->top <= L->stack_last); + setnilvalue(s2v(L->top.p++)); /* complete missing arguments */ + lua_assert(ci->top.p <= L->stack_last.p); return ci; } default: { /* not a function */ @@ -187802,12 +188038,17 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { ** Call a function (C or Lua) through C. 'inc' can be 1 (increment ** number of recursive invocations in the C stack) or nyci (the same ** plus increment number of non-yieldable calls). +** This function can be called with some use of EXTRA_STACK, so it should +** check the stack before doing anything else. 'luaD_precall' already +** does that. */ -l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) { +l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { CallInfo *ci; L->nCcalls += inc; - if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) { + checkstackp(L, 0, func); /* free any use of EXTRA_STACK */ luaE_checkcstack(L); + } if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ luaV_execute(L, ci); /* call it */ @@ -187855,8 +188096,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) { else { /* error */ StkId func = restorestack(L, ci->u2.funcidx); L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ - luaF_close(L, func, status, 1); /* can yield or raise an error */ - func = restorestack(L, ci->u2.funcidx); /* stack may be moved */ + func = luaF_close(L, func, status, 1); /* can yield or raise an error */ luaD_seterrorobj(L, status, func); luaD_shrinkstack(L); /* restore stack size in case of overflow */ setcistrecst(ci, LUA_OK); /* clear original status */ @@ -187944,8 +188184,8 @@ static CallInfo *findpcall (lua_State *L) { ** coroutine error handler and should not kill the coroutine.) */ static int resume_error (lua_State *L, const char *msg, int narg) { - L->top -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + L->top.p -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ api_incr_top(L); lua_unlock(L); return LUA_ERRRUN; @@ -187961,7 +188201,7 @@ static int resume_error (lua_State *L, const char *msg, int narg) { */ static void resume (lua_State *L, void *ud) { int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top - n; /* first argument */ + StkId firstArg = L->top.p - n; /* first argument */ CallInfo *ci = L->ci; if (L->status == LUA_OK) /* starting a coroutine? */ ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */ @@ -187969,7 +188209,7 @@ static void resume (lua_State *L, void *ud) { lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ if (isLua(ci)) { /* yielded inside a hook? */ - L->top = firstArg; /* discard arguments */ + L->top.p = firstArg; /* discard arguments */ luaV_execute(L, ci); /* just continue running Lua code */ } else { /* 'common' yield */ @@ -188012,7 +188252,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, if (L->status == LUA_OK) { /* may be starting a coroutine */ if (L->ci != &L->base_ci) /* not in base level? */ return resume_error(L, "cannot resume non-suspended coroutine", nargs); - else if (L->top - (L->ci->func + 1) == nargs) /* no function? */ + else if (L->top.p - (L->ci->func.p + 1) == nargs) /* no function? */ return resume_error(L, "cannot resume dead coroutine", nargs); } else if (L->status != LUA_YIELD) /* ended with errors? */ @@ -188030,11 +188270,11 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, lua_assert(status == L->status); /* normal end or yield */ else { /* unrecoverable error */ L->status = cast_byte(status); /* mark thread as 'dead' */ - luaD_seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; + luaD_seterrorobj(L, status, L->top.p); /* push error message */ + L->ci->top.p = L->top.p; } *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield - : cast_int(L->top - (L->ci->func + 1)); + : cast_int(L->top.p - (L->ci->func.p + 1)); lua_unlock(L); return status; } @@ -188189,7 +188429,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; p.dyd.label.arr = NULL; p.dyd.label.size = 0; luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc); luaZ_freebuffer(L, &p.buff); luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); @@ -188809,8 +189049,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { if (tm == NULL) /* no TM? */ return 0; /* objects are different */ else { - luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ - return !l_isfalse(s2v(L->top)); + luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ + return !l_isfalse(s2v(L->top.p)); } } @@ -188834,17 +189074,17 @@ static void copy2buff (StkId top, int n, char *buff) { /* ** Main operation for concatenation: concat 'total' values in the stack, -** from 'L->top - total' up to 'L->top - 1'. +** from 'L->top.p - total' up to 'L->top.p - 1'. */ void luaV_concat (lua_State *L, int total) { if (total == 1) return; /* "all" values already concatenated */ do { - StkId top = L->top; + StkId top = L->top.p; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || !tostring(L, s2v(top - 1))) - luaT_tryconcatTM(L); + luaT_tryconcatTM(L); /* may invalidate 'top' */ else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ @@ -188857,8 +189097,10 @@ void luaV_concat (lua_State *L, int total) { /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { size_t l = vslen(s2v(top - n - 1)); - if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) + if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { + L->top.p = top - total; /* pop strings to avoid wasting stack */ luaG_runerror(L, "string length overflow"); + } tl += l; } if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ @@ -188872,8 +189114,8 @@ void luaV_concat (lua_State *L, int total) { } setsvalue2s(L, top - n, ts); /* create result */ } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ + total -= n - 1; /* got 'n' strings to create one new */ + L->top.p -= n - 1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ } @@ -188964,12 +189206,10 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { /* number of bits in an integer */ #define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + /* ** Shift left operation. (Shift right just negates 'y'.) */ -#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) - - lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { if (y < 0) { /* shift right? */ if (y <= -NBITS) return 0; @@ -189009,26 +189249,26 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, */ void luaV_finishOp (lua_State *L) { CallInfo *ci = L->ci; - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { - setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top); + setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top.p); break; } case OP_UNM: case OP_BNOT: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: case OP_GETFIELD: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); + setobjs2s(L, base + GETARG_A(inst), --L->top.p); break; } case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: case OP_GTI: case OP_GEI: case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ - int res = !l_isfalse(s2v(L->top - 1)); - L->top--; + int res = !l_isfalse(s2v(L->top.p - 1)); + L->top.p--; #if defined(LUA_COMPAT_LT_LE) if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ ci->callstatus ^= CIST_LEQ; /* clear mark */ @@ -189041,11 +189281,11 @@ void luaV_finishOp (lua_State *L) { break; } case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */ + StkId top = L->top.p - 1; /* top when 'luaT_tryconcatTM' was called */ int a = GETARG_A(inst); /* first element to concatenate */ int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ setobjs2s(L, top - 2, top); /* put TM result in proper position */ - L->top = top - 1; /* top is one after last element (at top-2) */ + L->top.p = top - 1; /* top is one after last element (at top-2) */ luaV_concat(L, total); /* concat them (may yield again) */ break; } @@ -189057,7 +189297,7 @@ void luaV_finishOp (lua_State *L) { StkId ra = base + GETARG_A(inst); /* adjust top to signal correct number of returns, in case the return is "up to top" ('isIT') */ - L->top = ra + ci->u2.nres; + L->top.p = ra + ci->u2.nres; /* repeat instruction to close other vars. and complete the return */ ci->u.l.savedpc--; break; @@ -189099,6 +189339,7 @@ void luaV_finishOp (lua_State *L) { ** operation, 'fop' is the float operation. */ #define op_arithI(L,iop,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ int imm = GETARG_sC(i); \ if (ttisinteger(v1)) { \ @@ -189127,6 +189368,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over floats and others with register operands. */ #define op_arithf(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ op_arithf_aux(L, v1, v2, fop); } @@ -189136,6 +189378,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations with K operands for floats. */ #define op_arithfK(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ op_arithf_aux(L, v1, v2, fop); } @@ -189145,6 +189388,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over integers and floats. */ #define op_arith_aux(L,v1,v2,iop,fop) { \ + StkId ra = RA(i); \ if (ttisinteger(v1) && ttisinteger(v2)) { \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ @@ -189174,6 +189418,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with constant operand. */ #define op_bitwiseK(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); \ lua_Integer i1; \ @@ -189187,6 +189432,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with register operands. */ #define op_bitwise(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ lua_Integer i1; lua_Integer i2; \ @@ -189201,18 +189447,19 @@ void luaV_finishOp (lua_State *L) { ** integers. */ #define op_order(L,opi,opn,other) { \ - int cond; \ - TValue *rb = vRB(i); \ - if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ - lua_Integer ia = ivalue(s2v(ra)); \ - lua_Integer ib = ivalue(rb); \ - cond = opi(ia, ib); \ - } \ - else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ - cond = opn(s2v(ra), rb); \ - else \ - Protect(cond = other(L, s2v(ra), rb)); \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + TValue *rb = vRB(i); \ + if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ + lua_Integer ia = ivalue(s2v(ra)); \ + lua_Integer ib = ivalue(rb); \ + cond = opi(ia, ib); \ + } \ + else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ + cond = opn(s2v(ra), rb); \ + else \ + Protect(cond = other(L, s2v(ra), rb)); \ + docondjump(); } /* @@ -189220,20 +189467,21 @@ void luaV_finishOp (lua_State *L) { ** always small enough to have an exact representation as a float.) */ #define op_orderI(L,opi,opf,inv,tm) { \ - int cond; \ - int im = GETARG_sB(i); \ - if (ttisinteger(s2v(ra))) \ - cond = opi(ivalue(s2v(ra)), im); \ - else if (ttisfloat(s2v(ra))) { \ - lua_Number fa = fltvalue(s2v(ra)); \ - lua_Number fim = cast_num(im); \ - cond = opf(fa, fim); \ - } \ - else { \ - int isf = GETARG_C(i); \ - Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ - } \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + int im = GETARG_sB(i); \ + if (ttisinteger(s2v(ra))) \ + cond = opi(ivalue(s2v(ra)), im); \ + else if (ttisfloat(s2v(ra))) { \ + lua_Number fa = fltvalue(s2v(ra)); \ + lua_Number fim = cast_num(im); \ + cond = opf(fa, fim); \ + } \ + else { \ + int isf = GETARG_C(i); \ + Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ + } \ + docondjump(); } /* }================================================================== */ @@ -189262,7 +189510,7 @@ void luaV_finishOp (lua_State *L) { #define updatetrap(ci) (trap = ci->u.l.trap) -#define updatebase(ci) (base = ci->func + 1) +#define updatebase(ci) (base = ci->func.p + 1) #define updatestack(ci) \ @@ -189297,7 +189545,7 @@ void luaV_finishOp (lua_State *L) { ** Whenever code can raise errors, the global 'pc' and the global ** 'top' must be correct to report occasional errors. */ -#define savestate(L,ci) (savepc(L), L->top = ci->top) +#define savestate(L,ci) (savepc(L), L->top.p = ci->top.p) /* @@ -189317,7 +189565,7 @@ void luaV_finishOp (lua_State *L) { /* 'c' is the limit of live values in the stack */ #define checkGC(L,c) \ - { luaC_condGC(L, (savepc(L), L->top = (c)), \ + { luaC_condGC(L, (savepc(L), L->top.p = (c)), \ updatetrap(ci)); \ luai_threadyield(L); } @@ -189329,7 +189577,6 @@ void luaV_finishOp (lua_State *L) { updatebase(ci); /* correct stack */ \ } \ i = *(pc++); \ - ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ } #define vmdispatch(o) switch(o) @@ -189461,7 +189708,7 @@ static const void *const disptab[NUM_OPCODES] = { startfunc: trap = L->hookmask; returning: /* trap already set */ - cl = clLvalue(s2v(ci->func)); + cl = clLvalue(s2v(ci->func.p)); k = cl->p->k; pc = ci->u.l.savedpc; if (l_unlikely(trap)) { @@ -189473,60 +189720,68 @@ static const void *const disptab[NUM_OPCODES] = { } ci->u.l.trap = 1; /* assume trap is on, for now */ } - base = ci->func + 1; + base = ci->func.p + 1; /* main loop of interpreter */ for (;;) { Instruction i; /* instruction being executed */ - StkId ra; /* instruction's A register */ vmfetch(); #if 0 /* low-level line tracing for debugging Lua */ printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); #endif - lua_assert(base == ci->func + 1); - lua_assert(base <= L->top && L->top < L->stack_last); + lua_assert(base == ci->func.p + 1); + lua_assert(base <= L->top.p && L->top.p <= L->stack_last.p); /* invalidate top for instructions not expecting it */ - lua_assert(isIT(i) || (cast_void(L->top = base), 1)); + lua_assert(isIT(i) || (cast_void(L->top.p = base), 1)); vmdispatch (GET_OPCODE(i)) { vmcase(OP_MOVE) { + StkId ra = RA(i); setobjs2s(L, ra, RB(i)); vmbreak; } vmcase(OP_LOADI) { + StkId ra = RA(i); lua_Integer b = GETARG_sBx(i); setivalue(s2v(ra), b); vmbreak; } vmcase(OP_LOADF) { + StkId ra = RA(i); int b = GETARG_sBx(i); setfltvalue(s2v(ra), cast_num(b)); vmbreak; } vmcase(OP_LOADK) { + StkId ra = RA(i); TValue *rb = k + GETARG_Bx(i); setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADKX) { + StkId ra = RA(i); TValue *rb; rb = k + GETARG_Ax(*pc); pc++; setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADFALSE) { + StkId ra = RA(i); setbfvalue(s2v(ra)); vmbreak; } vmcase(OP_LFALSESKIP) { + StkId ra = RA(i); setbfvalue(s2v(ra)); pc++; /* skip next instruction */ vmbreak; } vmcase(OP_LOADTRUE) { + StkId ra = RA(i); setbtvalue(s2v(ra)); vmbreak; } vmcase(OP_LOADNIL) { + StkId ra = RA(i); int b = GETARG_B(i); do { setnilvalue(s2v(ra++)); @@ -189534,19 +189789,22 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETUPVAL) { + StkId ra = RA(i); int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); + setobj2s(L, ra, cl->upvals[b]->v.p); vmbreak; } vmcase(OP_SETUPVAL) { + StkId ra = RA(i); UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, s2v(ra)); + setobj(L, uv->v.p, s2v(ra)); luaC_barrier(L, uv, s2v(ra)); vmbreak; } vmcase(OP_GETTABUP) { + StkId ra = RA(i); const TValue *slot; - TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *upval = cl->upvals[GETARG_B(i)]->v.p; TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a string */ if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { @@ -189557,6 +189815,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = vRC(i); @@ -189571,6 +189830,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETI) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); int c = GETARG_C(i); @@ -189585,6 +189845,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = KC(i); @@ -189598,7 +189859,7 @@ static const void *const disptab[NUM_OPCODES] = { } vmcase(OP_SETTABUP) { const TValue *slot; - TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *upval = cl->upvals[GETARG_A(i)]->v.p; TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a string */ @@ -189610,6 +189871,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); /* key (table is in 'ra') */ TValue *rc = RKC(i); /* value */ @@ -189624,6 +189886,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETI) { + StkId ra = RA(i); const TValue *slot; int c = GETARG_B(i); TValue *rc = RKC(i); @@ -189638,6 +189901,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = KB(i); TValue *rc = RKC(i); @@ -189650,6 +189914,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NEWTABLE) { + StkId ra = RA(i); int b = GETARG_B(i); /* log2(hash size) + 1 */ int c = GETARG_C(i); /* array size */ Table *t; @@ -189659,7 +189924,7 @@ static const void *const disptab[NUM_OPCODES] = { if (TESTARG_k(i)) /* non-zero extra argument? */ c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ pc++; /* skip extra argument */ - L->top = ra + 1; /* correct top in case of emergency GC */ + L->top.p = ra + 1; /* correct top in case of emergency GC */ t = luaH_new(L); /* memory allocation */ sethvalue2s(L, ra, t); if (b != 0 || c != 0) @@ -189668,6 +189933,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SELF) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = RKC(i); @@ -189697,6 +189963,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MODK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_mod, luaV_modf); vmbreak; } @@ -189709,6 +189976,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIVK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -189725,6 +189993,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHRI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -189734,6 +190003,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHLI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -189755,6 +190025,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MOD) { + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_mod, luaV_modf); vmbreak; } @@ -189767,6 +190038,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIV) { /* floor division */ + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -189791,6 +190063,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBIN) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *rb = vRB(i); TMS tm = (TMS)GETARG_C(i); @@ -189800,6 +190073,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINI) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ int imm = GETARG_sB(i); TMS tm = (TMS)GETARG_C(i); @@ -189809,6 +190083,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINK) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *imm = KB(i); TMS tm = (TMS)GETARG_C(i); @@ -189818,6 +190093,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_UNM) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Number nb; if (ttisinteger(rb)) { @@ -189832,6 +190108,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_BNOT) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Integer ib; if (tointegerns(rb, &ib)) { @@ -189842,6 +190119,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NOT) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb)) setbtvalue(s2v(ra)); @@ -189850,21 +190128,25 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_LEN) { + StkId ra = RA(i); Protect(luaV_objlen(L, ra, vRB(i))); vmbreak; } vmcase(OP_CONCAT) { + StkId ra = RA(i); int n = GETARG_B(i); /* number of elements to concatenate */ - L->top = ra + n; /* mark the end of concat operands */ + L->top.p = ra + n; /* mark the end of concat operands */ ProtectNT(luaV_concat(L, n)); - checkGC(L, L->top); /* 'luaV_concat' ensures correct top */ + checkGC(L, L->top.p); /* 'luaV_concat' ensures correct top */ vmbreak; } vmcase(OP_CLOSE) { + StkId ra = RA(i); Protect(luaF_close(L, ra, LUA_OK, 1)); vmbreak; } vmcase(OP_TBC) { + StkId ra = RA(i); /* create new to-be-closed upvalue */ halfProtect(luaF_newtbcupval(L, ra)); vmbreak; @@ -189874,6 +190156,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQ) { + StkId ra = RA(i); int cond; TValue *rb = vRB(i); Protect(cond = luaV_equalobj(L, s2v(ra), rb)); @@ -189889,6 +190172,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQK) { + StkId ra = RA(i); TValue *rb = KB(i); /* basic types do not use '__eq'; we can use raw equality */ int cond = luaV_rawequalobj(s2v(ra), rb); @@ -189896,6 +190180,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQI) { + StkId ra = RA(i); int cond; int im = GETARG_sB(i); if (ttisinteger(s2v(ra))) @@ -189924,11 +190209,13 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TEST) { + StkId ra = RA(i); int cond = !l_isfalse(s2v(ra)); docondjump(); vmbreak; } vmcase(OP_TESTSET) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb) == GETARG_k(i)) pc++; @@ -189939,11 +190226,12 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CALL) { + StkId ra = RA(i); CallInfo *newci; int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) /* fixed number of arguments? */ - L->top = ra + b; /* top signals number of arguments */ + L->top.p = ra + b; /* top signals number of arguments */ /* else previous instruction set top */ savepc(L); /* in case of errors */ if ((newci = luaD_precall(L, ra, nresults)) == NULL) @@ -189955,54 +190243,57 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TAILCALL) { + StkId ra = RA(i); int b = GETARG_B(i); /* number of arguments + 1 (function) */ int n; /* number of results when calling a C function */ int nparams1 = GETARG_C(i); /* delta is virtual 'func' - real 'func' (vararg functions) */ int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; if (b != 0) - L->top = ra + b; + L->top.p = ra + b; else /* previous instruction set top */ - b = cast_int(L->top - ra); + b = cast_int(L->top.p - ra); savepc(ci); /* several calls here can raise errors */ if (TESTARG_k(i)) { luaF_closeupval(L, base); /* close upvalues from current call */ - lua_assert(L->tbclist < base); /* no pending tbc variables */ - lua_assert(base == ci->func + 1); + lua_assert(L->tbclist.p < base); /* no pending tbc variables */ + lua_assert(base == ci->func.p + 1); } if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ goto startfunc; /* execute the callee */ else { /* C function? */ - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ luaD_poscall(L, ci, n); /* finish caller */ updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; /* caller returns after the tail call */ } } vmcase(OP_RETURN) { + StkId ra = RA(i); int n = GETARG_B(i) - 1; /* number of results */ int nparams1 = GETARG_C(i); if (n < 0) /* not fixed? */ - n = cast_int(L->top - ra); /* get what is available */ + n = cast_int(L->top.p - ra); /* get what is available */ savepc(ci); if (TESTARG_k(i)) { /* may there be open upvalues? */ ci->u2.nres = n; /* save number of returns */ - if (L->top < ci->top) - L->top = ci->top; + if (L->top.p < ci->top.p) + L->top.p = ci->top.p; luaF_close(L, base, CLOSEKTOP, 1); updatetrap(ci); updatestack(ci); } if (nparams1) /* vararg function? */ - ci->func -= ci->u.l.nextraargs + nparams1; - L->top = ra + n; /* set call for 'luaD_poscall' */ + ci->func.p -= ci->u.l.nextraargs + nparams1; + L->top.p = ra + n; /* set call for 'luaD_poscall' */ luaD_poscall(L, ci, n); updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; } vmcase(OP_RETURN0) { if (l_unlikely(L->hookmask)) { - L->top = ra; + StkId ra = RA(i); + L->top.p = ra; savepc(ci); luaD_poscall(L, ci, 0); /* no hurry... */ trap = 1; @@ -190010,15 +190301,16 @@ static const void *const disptab[NUM_OPCODES] = { else { /* do the 'poscall' here */ int nres; L->ci = ci->previous; /* back to caller */ - L->top = base - 1; + L->top.p = base - 1; for (nres = ci->nresults; l_unlikely(nres > 0); nres--) - setnilvalue(s2v(L->top++)); /* all results are nil */ + setnilvalue(s2v(L->top.p++)); /* all results are nil */ } goto ret; } vmcase(OP_RETURN1) { if (l_unlikely(L->hookmask)) { - L->top = ra + 1; + StkId ra = RA(i); + L->top.p = ra + 1; savepc(ci); luaD_poscall(L, ci, 1); /* no hurry... */ trap = 1; @@ -190027,12 +190319,13 @@ static const void *const disptab[NUM_OPCODES] = { int nres = ci->nresults; L->ci = ci->previous; /* back to caller */ if (nres == 0) - L->top = base - 1; /* asked for no results */ + L->top.p = base - 1; /* asked for no results */ else { + StkId ra = RA(i); setobjs2s(L, base - 1, ra); /* at least this result */ - L->top = base; + L->top.p = base; for (; l_unlikely(nres > 1); nres--) - setnilvalue(s2v(L->top++)); /* complete missing results */ + setnilvalue(s2v(L->top.p++)); /* complete missing results */ } } ret: /* return from a Lua function */ @@ -190044,6 +190337,7 @@ static const void *const disptab[NUM_OPCODES] = { } } vmcase(OP_FORLOOP) { + StkId ra = RA(i); if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); if (count > 0) { /* still more iterations? */ @@ -190062,12 +190356,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_FORPREP) { + StkId ra = RA(i); savestate(L, ci); /* in case of errors */ if (forprep(L, ra)) pc += GETARG_Bx(i) + 1; /* skip the loop */ vmbreak; } vmcase(OP_TFORPREP) { + StkId ra = RA(i); /* create to-be-closed upvalue (if needed) */ halfProtect(luaF_newtbcupval(L, ra + 3)); pc += GETARG_Bx(i); @@ -190076,7 +190372,8 @@ static const void *const disptab[NUM_OPCODES] = { goto l_tforcall; } vmcase(OP_TFORCALL) { - l_tforcall: + l_tforcall: { + StkId ra = RA(i); /* 'ra' has the iterator function, 'ra + 1' has the state, 'ra + 2' has the control variable, and 'ra + 3' has the to-be-closed variable. The call will use the stack after @@ -190084,29 +190381,31 @@ static const void *const disptab[NUM_OPCODES] = { */ /* push function, state, and control variable */ memcpy(ra + 4, ra, 3 * sizeof(*ra)); - L->top = ra + 4 + 3; + L->top.p = ra + 4 + 3; ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); goto l_tforloop; - } + }} vmcase(OP_TFORLOOP) { - l_tforloop: + l_tforloop: { + StkId ra = RA(i); if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ setobjs2s(L, ra + 2, ra + 4); /* save control variable */ pc -= GETARG_Bx(i); /* jump back */ } vmbreak; - } + }} vmcase(OP_SETLIST) { + StkId ra = RA(i); int n = GETARG_B(i); unsigned int last = GETARG_C(i); Table *h = hvalue(s2v(ra)); if (n == 0) - n = cast_int(L->top - ra) - 1; /* get up to the top */ + n = cast_int(L->top.p - ra) - 1; /* get up to the top */ else - L->top = ci->top; /* correct top in case of emergency GC */ + L->top.p = ci->top.p; /* correct top in case of emergency GC */ last += n; if (TESTARG_k(i)) { last += GETARG_Ax(*pc) * (MAXARG_C + 1); @@ -190123,12 +190422,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CLOSURE) { + StkId ra = RA(i); Proto *p = cl->p->p[GETARG_Bx(i)]; halfProtect(pushclosure(L, p, cl->upvals, base, ra)); checkGC(L, ra + 1); vmbreak; } vmcase(OP_VARARG) { + StkId ra = RA(i); int n = GETARG_C(i) - 1; /* required results */ Protect(luaT_getvarargs(L, ci, ra, n)); vmbreak; @@ -190213,27 +190514,28 @@ const char lua_ident[] = static TValue *index2value (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return &G(L)->nilvalue; + StkId o = ci->func.p + idx; + api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index"); + if (o >= L->top.p) return &G(L)->nilvalue; else return s2v(o); } else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return s2v(L->top + idx); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); + return s2v(L->top.p + idx); } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttisCclosure(s2v(ci->func))) { /* C closure? */ - CClosure *func = clCvalue(s2v(ci->func)); + if (ttisCclosure(s2v(ci->func.p))) { /* C closure? */ + CClosure *func = clCvalue(s2v(ci->func.p)); return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue; } else { /* light C function or Lua function (through a hook)?) */ - api_check(L, ttislcf(s2v(ci->func)), "caller not a C function"); + api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function"); return &G(L)->nilvalue; /* no upvalues */ } } @@ -190247,14 +190549,15 @@ static TValue *index2value (lua_State *L, int idx) { l_sinline StkId index2stack (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, o < L->top, "invalid index"); + StkId o = ci->func.p + idx; + api_check(L, o < L->top.p, "invalid index"); return o; } else { /* non-positive index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); api_check(L, !ispseudo(idx), "invalid index"); - return L->top + idx; + return L->top.p + idx; } } @@ -190265,17 +190568,12 @@ LUA_API int lua_checkstack (lua_State *L, int n) { lua_lock(L); ci = L->ci; api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ + if (L->stack_last.p - L->top.p > n) /* stack large enough? */ res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = luaD_growstack(L, n, 0); - } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ + else /* need to grow stack */ + res = luaD_growstack(L, n, 0); + if (res && ci->top.p < L->top.p + n) + ci->top.p = L->top.p + n; /* adjust frame top */ lua_unlock(L); return res; } @@ -190287,11 +190585,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); - from->top -= n; + api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); + from->top.p -= n; for (i = 0; i < n; i++) { - setobjs2s(to, to->top, from->top + i); - to->top++; /* stack already checked by previous 'api_check' */ + setobjs2s(to, to->top.p, from->top.p + i); + to->top.p++; /* stack already checked by previous 'api_check' */ } lua_unlock(to); } @@ -190325,12 +190623,12 @@ LUA_API lua_Number lua_version (lua_State *L) { LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx - : cast_int(L->top - L->ci->func) + idx; + : cast_int(L->top.p - L->ci->func.p) + idx; } LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); + return cast_int(L->top.p - (L->ci->func.p + 1)); } @@ -190340,24 +190638,24 @@ LUA_API void lua_settop (lua_State *L, int idx) { ptrdiff_t diff; /* difference for new top */ lua_lock(L); ci = L->ci; - func = ci->func; + func = ci->func.p; if (idx >= 0) { - api_check(L, idx <= ci->top - (func + 1), "new top too large"); - diff = ((func + 1) + idx) - L->top; + api_check(L, idx <= ci->top.p - (func + 1), "new top too large"); + diff = ((func + 1) + idx) - L->top.p; for (; diff > 0; diff--) - setnilvalue(s2v(L->top++)); /* clear new slots */ + setnilvalue(s2v(L->top.p++)); /* clear new slots */ } else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); diff = idx + 1; /* will "subtract" index (as it is negative) */ } - api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot"); - newtop = L->top + diff; - if (diff < 0 && L->tbclist >= newtop) { + api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot"); + newtop = L->top.p + diff; + if (diff < 0 && L->tbclist.p >= newtop) { lua_assert(hastocloseCfunc(ci->nresults)); - luaF_close(L, newtop, CLOSEKTOP, 0); + newtop = luaF_close(L, newtop, CLOSEKTOP, 0); } - L->top = newtop; /* correct top only after closing any upvalue */ + L->top.p = newtop; /* correct top only after closing any upvalue */ lua_unlock(L); } @@ -190366,10 +190664,9 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { StkId level; lua_lock(L); level = index2stack(L, idx); - api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level, + api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level, "no variable to close at given level"); - luaF_close(L, level, CLOSEKTOP, 0); - level = index2stack(L, idx); /* stack may be moved */ + level = luaF_close(L, level, CLOSEKTOP, 0); setnilvalue(s2v(level)); lua_unlock(L); } @@ -190398,7 +190695,7 @@ l_sinline void reverse (lua_State *L, StkId from, StkId to) { LUA_API void lua_rotate (lua_State *L, int idx, int n) { StkId p, t, m; lua_lock(L); - t = L->top - 1; /* end of stack segment being rotated */ + t = L->top.p - 1; /* end of stack segment being rotated */ p = index2stack(L, idx); /* start of segment */ api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ @@ -190417,7 +190714,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { api_check(L, isvalid(L, to), "invalid index"); setobj(L, to, fr); if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); + luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr); /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ lua_unlock(L); @@ -190426,7 +190723,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2value(L, idx)); + setobj2s(L, L->top.p, index2value(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -190495,12 +190792,12 @@ LUA_API void lua_arith (lua_State *L, int op) { api_checknelems(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); + setobjs2s(L, L->top.p, L->top.p - 1); api_incr_top(L); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); - L->top--; /* remove second operand */ + luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); + L->top.p--; /* remove second operand */ lua_unlock(L); } @@ -190526,7 +190823,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, s2v(L->top)); + size_t sz = luaO_str2num(s, s2v(L->top.p)); if (sz != 0) api_incr_top(L); return sz; @@ -190653,7 +190950,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -190661,7 +190958,7 @@ LUA_API void lua_pushnil (lua_State *L) { LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); - setfltvalue(s2v(L->top), n); + setfltvalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -190669,7 +190966,7 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); - setivalue(s2v(L->top), n); + setivalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -190684,7 +190981,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -190695,11 +190992,11 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushstring (lua_State *L, const char *s) { lua_lock(L); if (s == NULL) - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else { TString *ts; ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); s = getstr(ts); /* internal copy's address */ } api_incr_top(L); @@ -190736,7 +191033,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { - setfvalue(s2v(L->top), fn); + setfvalue(s2v(L->top.p), fn); api_incr_top(L); } else { @@ -190745,13 +191042,13 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { api_check(L, n <= MAXUPVAL, "upvalue index too large"); cl = luaF_newCclosure(L, n); cl->f = fn; - L->top -= n; + L->top.p -= n; while (n--) { - setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); + setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n)); /* does not need barrier because closure is white */ lua_assert(iswhite(cl)); } - setclCvalue(L, s2v(L->top), cl); + setclCvalue(L, s2v(L->top.p), cl); api_incr_top(L); luaC_checkGC(L); } @@ -190762,9 +191059,9 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); if (b) - setbtvalue(s2v(L->top)); + setbtvalue(s2v(L->top.p)); else - setbfvalue(s2v(L->top)); + setbfvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -190772,7 +191069,7 @@ LUA_API void lua_pushboolean (lua_State *L, int b) { LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); - setpvalue(s2v(L->top), p); + setpvalue(s2v(L->top.p), p); api_incr_top(L); lua_unlock(L); } @@ -190780,7 +191077,7 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); - setthvalue(L, s2v(L->top), L); + setthvalue(L, s2v(L->top.p), L); api_incr_top(L); lua_unlock(L); return (G(L)->mainthread == L); @@ -190797,16 +191094,16 @@ l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { const TValue *slot; TString *str = luaS_new(L, k); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); api_incr_top(L); } else { - setsvalue2s(L, L->top, str); + setsvalue2s(L, L->top.p, str); api_incr_top(L); - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); } lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -190833,13 +191130,13 @@ LUA_API int lua_gettable (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { - setobj2s(L, L->top - 1, slot); + if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { + setobj2s(L, L->top.p - 1, slot); } else - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -190855,27 +191152,27 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); } else { TValue aux; setivalue(&aux, n); - luaV_finishget(L, t, &aux, L->top, slot); + luaV_finishget(L, t, &aux, L->top.p, slot); } api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } l_sinline int finishrawget (lua_State *L, const TValue *val) { if (isempty(val)) /* avoid copying empty items to the stack */ - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -190892,8 +191189,8 @@ LUA_API int lua_rawget (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - val = luaH_get(t, s2v(L->top - 1)); - L->top--; /* remove key */ + val = luaH_get(t, s2v(L->top.p - 1)); + L->top.p--; /* remove key */ return finishrawget(L, val); } @@ -190920,7 +191217,7 @@ LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { Table *t; lua_lock(L); t = luaH_new(L); - sethvalue2s(L, L->top, t); + sethvalue2s(L, L->top.p, t); api_incr_top(L); if (narray > 0 || nrec > 0) luaH_resize(L, t, narray, nrec); @@ -190947,7 +191244,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { break; } if (mt != NULL) { - sethvalue2s(L, L->top, mt); + sethvalue2s(L, L->top.p, mt); api_incr_top(L); res = 1; } @@ -190963,12 +191260,12 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { o = index2value(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); if (n <= 0 || n > uvalue(o)->nuvalue) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); t = LUA_TNONE; } else { - setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); - t = ttype(s2v(L->top)); + setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv); + t = ttype(s2v(L->top.p)); } api_incr_top(L); lua_unlock(L); @@ -190988,14 +191285,14 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { TString *str = luaS_new(L, k); api_checknelems(L, 1); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); - L->top--; /* pop value */ + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); + L->top.p--; /* pop value */ } else { - setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ api_incr_top(L); - luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); - L->top -= 2; /* pop value and key */ + luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); + L->top.p -= 2; /* pop value and key */ } lua_unlock(L); /* lock done by caller */ } @@ -191015,12 +191312,12 @@ LUA_API void lua_settable (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 2); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else - luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); - L->top -= 2; /* pop index and value */ + luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); + L->top.p -= 2; /* pop index and value */ lua_unlock(L); } @@ -191038,14 +191335,14 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { api_checknelems(L, 1); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else { TValue aux; setivalue(&aux, n); - luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); + luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); } - L->top--; /* pop value */ + L->top.p--; /* pop value */ lua_unlock(L); } @@ -191055,16 +191352,16 @@ static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { lua_lock(L); api_checknelems(L, n); t = gettable(L, idx); - luaH_set(L, t, key, s2v(L->top - 1)); + luaH_set(L, t, key, s2v(L->top.p - 1)); invalidateTMcache(t); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top -= n; + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p -= n; lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { - aux_rawset(L, idx, s2v(L->top - 2), 2); + aux_rawset(L, idx, s2v(L->top.p - 2), 2); } @@ -191080,9 +191377,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - luaH_setint(L, t, n, s2v(L->top - 1)); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top--; + luaH_setint(L, t, n, s2v(L->top.p - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p--; lua_unlock(L); } @@ -191093,11 +191390,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { lua_lock(L); api_checknelems(L, 1); obj = index2value(L, objindex); - if (ttisnil(s2v(L->top - 1))) + if (ttisnil(s2v(L->top.p - 1))) mt = NULL; else { - api_check(L, ttistable(s2v(L->top - 1)), "table expected"); - mt = hvalue(s2v(L->top - 1)); + api_check(L, ttistable(s2v(L->top.p - 1)), "table expected"); + mt = hvalue(s2v(L->top.p - 1)); } switch (ttype(obj)) { case LUA_TTABLE: { @@ -191121,7 +191418,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { break; } } - L->top--; + L->top.p--; lua_unlock(L); return 1; } @@ -191137,11 +191434,11 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ else { - setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1)); res = 1; } - L->top--; + L->top.p--; lua_unlock(L); return res; } @@ -191153,7 +191450,8 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + api_check(L, (nr) == LUA_MULTRET \ + || (L->ci->top.p - L->top.p >= (nr) - (na)), \ "results from function overflow current stack size") @@ -191166,7 +191464,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); - func = L->top - (nargs+1); + func = L->top.p - (nargs+1); if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ @@ -191214,7 +191512,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); func = savestack(L, o); } - c.func = L->top - (nargs+1); /* function to be called */ + c.func = L->top.p - (nargs+1); /* function to be called */ if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ c.nresults = nresults; /* do a 'conventional' protected call */ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); @@ -191249,12 +191547,12 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, luaZ_init(L, &z, reader, data); status = luaD_protectedparser(L, &z, chunkname, mode); if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ + LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ if (f->nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ const TValue *gt = getGtable(L); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); + setobj(L, f->upvals[0]->v.p, gt); luaC_barrier(L, f->upvals[0], gt); } } @@ -191268,7 +191566,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { TValue *o; lua_lock(L); api_checknelems(L, 1); - o = s2v(L->top - 1); + o = s2v(L->top.p - 1); if (isLfunction(o)) status = luaU_dump(L, getproto(o), writer, data, strip); else @@ -191394,7 +191692,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { LUA_API int lua_error (lua_State *L) { TValue *errobj; lua_lock(L); - errobj = s2v(L->top - 1); + errobj = s2v(L->top.p - 1); api_checknelems(L, 1); /* error object is the memory error message? */ if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) @@ -191412,12 +191710,12 @@ LUA_API int lua_next (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - more = luaH_next(L, t, L->top - 1); + more = luaH_next(L, t, L->top.p - 1); if (more) { api_incr_top(L); } else /* no more elements */ - L->top -= 1; /* remove key */ + L->top.p -= 1; /* remove key */ lua_unlock(L); return more; } @@ -191429,7 +191727,7 @@ LUA_API void lua_toclose (lua_State *L, int idx) { lua_lock(L); o = index2stack(L, idx); nresults = L->ci->nresults; - api_check(L, L->tbclist < o, "given index below or equal a marked one"); + api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ if (!hastocloseCfunc(nresults)) /* function not marked yet? */ L->ci->nresults = codeNresults(nresults); /* mark it */ @@ -191444,7 +191742,7 @@ LUA_API void lua_concat (lua_State *L, int n) { if (n > 0) luaV_concat(L, n); else { /* nothing to concatenate */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ + setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ api_incr_top(L); } luaC_checkGC(L); @@ -191456,7 +191754,7 @@ LUA_API void lua_len (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - luaV_objlen(L, L->top, t); + luaV_objlen(L, L->top.p, t); api_incr_top(L); lua_unlock(L); } @@ -191501,7 +191799,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { lua_lock(L); api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); u = luaS_newudata(L, size, nuvalue); - setuvalue(L, s2v(L->top), u); + setuvalue(L, s2v(L->top.p), u); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -191527,7 +191825,7 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, Proto *p = f->p; if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) return NULL; /* 'n' not in [1, p->sizeupvalues] */ - *val = f->upvals[n-1]->v; + *val = f->upvals[n-1]->v.p; if (owner) *owner = obj2gco(f->upvals[n - 1]); name = p->upvalues[n-1].name; return (name == NULL) ? "(no name)" : getstr(name); @@ -191543,7 +191841,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { lua_lock(L); name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); if (name) { - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); } lua_unlock(L); @@ -191561,8 +191859,8 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { api_checknelems(L, 1); name = aux_upvalue(fi, n, &val, &owner); if (name) { - L->top--; - setobj(L, val, s2v(L->top)); + L->top.p--; + setobj(L, val, s2v(L->top.p)); luaC_barrier(L, owner, val); } lua_unlock(L); @@ -192145,13 +192443,14 @@ static void newbox (lua_State *L) { /* ** Compute new size for buffer 'B', enough to accommodate extra 'sz' -** bytes. +** bytes. (The test for "not big enough" also gets the case when the +** computation of 'newsize' overflows.) */ static size_t newbuffsize (luaL_Buffer *B, size_t sz) { - size_t newsize = B->size * 2; /* double buffer size */ + size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */ if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ return luaL_error(B->L, "buffer too large"); - if (newsize < B->n + sz) /* double is not big enough? */ + if (newsize < B->n + sz) /* not big enough? */ newsize = B->n + sz; return newsize; } @@ -192230,7 +192529,7 @@ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { ** box (if existent) is not on the top of the stack. So, instead of ** calling 'luaL_addlstring', it replicates the code using -2 as the ** last argument to 'prepbuffsize', signaling that the box is (or will -** be) bellow the string being added to the buffer. (Box creation can +** be) below the string being added to the buffer. (Box creation can ** trigger an emergency GC, so we should not remove the string from the ** stack before we have the space guaranteed.) */ @@ -192358,17 +192657,18 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { } -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ +/* +** Skip an optional BOM at the start of a stream. If there is an +** incomplete BOM (the first character is correct but the rest is +** not), returns the first character anyway to force an error +** (as no chunk can start with 0xEF). +*/ +static int skipBOM (FILE *f) { + int c = getc(f); /* read first character */ + if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF) /* correct BOM? */ + return getc(f); /* ignore BOM and return next char */ + else /* no (valid) BOM */ + return c; /* return first character */ } @@ -192379,13 +192679,13 @@ static int skipBOM (LoadF *lf) { ** first "valid" character of the file (after the optional BOM and ** a first-line comment). */ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); +static int skipcomment (FILE *f, int *cp) { + int c = *cp = skipBOM(f); if (c == '#') { /* first line is a comment (Unix exec. file)? */ do { /* skip first line */ - c = getc(lf->f); + c = getc(f); } while (c != EOF && c != '\n'); - *cp = getc(lf->f); /* skip end-of-line, if present */ + *cp = getc(f); /* next character after comment, if present */ return 1; /* there was a comment */ } else return 0; /* no comment */ @@ -192407,12 +192707,16 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ + lf.n = 0; + if (skipcomment(lf.f, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add newline to correct line numbers */ + if (c == LUA_SIGNATURE[0]) { /* binary file? */ + lf.n = 0; /* remove possible newline */ + if (filename) { /* "real" file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(lf.f, &c); /* re-read initial portion */ + } } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ @@ -193350,7 +193654,7 @@ static int luaB_auxwrap (lua_State *L) { if (l_unlikely(r < 0)) { /* error? */ int stat = lua_status(co); if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ - stat = lua_resetthread(co); /* close its tbc variables */ + stat = lua_closethread(co, L); /* close its tbc variables */ lua_assert(stat != LUA_OK); lua_xmove(co, L, 1); /* move error message to the caller */ } @@ -193446,7 +193750,7 @@ static int luaB_close (lua_State *L) { int status = auxstatus(L, co); switch (status) { case COS_DEAD: case COS_YIELD: { - status = lua_resetthread(co); + status = lua_closethread(co, L); if (status == LUA_OK) { lua_pushboolean(L, 1); return 1; @@ -195062,7 +195366,7 @@ static int math_type (lua_State *L) { /* try to find an integer type with at least 64 bits */ -#if (ULONG_MAX >> 31 >> 31) >= 3 +#if ((ULONG_MAX >> 31) >> 31) >= 3 /* 'long' has at least 64 bits */ #define Rand64 unsigned long @@ -195072,9 +195376,9 @@ static int math_type (lua_State *L) { /* there is a 'long long' type (which must have at least 64 bits) */ #define Rand64 unsigned long long -#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3 +#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 -/* 'lua_Integer' has at least 64 bits */ +/* 'lua_Unsigned' has at least 64 bits */ #define Rand64 lua_Unsigned #endif @@ -195295,12 +195599,12 @@ static lua_Number I2d (Rand64 x) { /* convert a 'Rand64' to a 'lua_Unsigned' */ static lua_Unsigned I2UInt (Rand64 x) { - return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l); + return (((lua_Unsigned)trim32(x.h) << 31) << 1) | (lua_Unsigned)trim32(x.l); } /* convert a 'lua_Unsigned' to a 'Rand64' */ static Rand64 Int2I (lua_Unsigned n) { - return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n); + return packI((lu_int32)((n >> 31) >> 1), (lu_int32)n); } #endif /* } */ @@ -196267,8 +196571,13 @@ static const luaL_Reg ll_funcs[] = { static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + static const lua_CFunction searchers[] = { + searcher_preload, + searcher_Lua, + searcher_C, + searcher_Croot, + NULL + }; int i; /* create 'searchers' table */ lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); @@ -196351,23 +196660,14 @@ LUAMOD_API int luaopen_package (lua_State *L) { */ #if !defined(LUA_STRFTIMEOPTIONS) /* { */ -/* options for ANSI C 89 (only 1-char options) */ -#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" - -/* options for ISO C 99 and POSIX */ -#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ - "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ - -/* options for Windows */ -#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ - "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ - #if defined(LUA_USE_WINDOWS) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN -#elif defined(LUA_USE_C89) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ +#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" #else /* C99 specification */ -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ #endif #endif /* } */ @@ -196459,12 +196759,21 @@ LUAMOD_API int luaopen_package (lua_State *L) { /* }================================================================== */ +#if !defined(l_system) +#if defined(LUA_USE_IOS) +/* Despite claiming to be ISO C, iOS does not implement 'system'. */ +#define l_system(cmd) ((cmd) == NULL ? 0 : -1) +#else +#define l_system(cmd) system(cmd) /* default definition */ +#endif +#endif + static int os_execute (lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); int stat; errno = 0; - stat = system(cmd); + stat = l_system(cmd); if (cmd != NULL) return luaL_execresult(L, stat); else { @@ -196581,9 +196890,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { res = d; } else { - /* unsigned avoids overflow when lua_Integer has 32 bits */ - if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta - : (lua_Integer)INT_MIN + delta <= res)) + if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) return luaL_error(L, "field '%s' is out-of-bound", key); res -= delta; } @@ -197321,7 +197628,7 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { if (l_unlikely(ms->matchdepth-- == 0)) luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ + init: /* using goto to optimize tail recursion */ if (p != ms->p_end) { /* end of pattern? */ switch (*p) { case '(': { /* start capture */ @@ -198718,7 +199025,7 @@ static int tremove (lua_State *L) { lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ /* check whether 'pos' is in [1, size + 1] */ - luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, + luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2, "position out of bounds"); lua_geti(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { @@ -199080,6 +199387,9 @@ LUAMOD_API int luaopen_table (lua_State *L) { #define MAXUTF 0x7FFFFFFFu + +#define MSGInvalid "invalid UTF-8 code" + /* ** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. */ @@ -199090,7 +199400,8 @@ typedef unsigned long utfint; #endif -#define iscont(p) ((*(p) & 0xC0) == 0x80) +#define iscont(c) (((c) & 0xC0) == 0x80) +#define iscontp(p) iscont(*(p)) /* from strlib */ @@ -199120,7 +199431,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { int count = 0; /* to count number of continuation bytes */ for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ unsigned int cc = (unsigned char)s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + if (!iscont(cc)) /* not a continuation byte? */ return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ } @@ -199195,7 +199506,7 @@ static int codepoint (lua_State *L) { utfint code; s = utf8_decode(s, &code, !lax); if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); + return luaL_error(L, MSGInvalid); lua_pushinteger(L, code); n++; } @@ -199245,16 +199556,16 @@ static int byteoffset (lua_State *L) { "position out of bounds"); if (n == 0) { /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; + while (posi > 0 && iscontp(s + posi)) posi--; } else { - if (iscont(s + posi)) + if (iscontp(s + posi)) return luaL_error(L, "initial position is a continuation byte"); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ do { /* find beginning of previous character */ posi--; - } while (posi > 0 && iscont(s + posi)); + } while (posi > 0 && iscontp(s + posi)); n++; } } @@ -199263,7 +199574,7 @@ static int byteoffset (lua_State *L) { while (n > 0 && posi < (lua_Integer)len) { do { /* find beginning of next character */ posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ + } while (iscontp(s + posi)); /* (cannot pass final '\0') */ n--; } } @@ -199281,15 +199592,15 @@ static int iter_aux (lua_State *L, int strict) { const char *s = luaL_checklstring(L, 1, &len); lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); if (n < len) { - while (iscont(s + n)) n++; /* skip continuation bytes */ + while (iscontp(s + n)) n++; /* go to next character */ } if (n >= len) /* (also handles original 'n' being negative) */ return 0; /* no more codepoints */ else { utfint code; const char *next = utf8_decode(s + n, &code, strict); - if (next == NULL) - return luaL_error(L, "invalid UTF-8 code"); + if (next == NULL || iscontp(next)) + return luaL_error(L, MSGInvalid); lua_pushinteger(L, n + 1); lua_pushinteger(L, code); return 2; @@ -199308,7 +199619,8 @@ static int iter_auxlax (lua_State *L) { static int iter_codes (lua_State *L) { int lax = lua_toboolean(L, 2); - luaL_checkstring(L, 1); + const char *s = luaL_checkstring(L, 1); + luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); lua_pushvalue(L, 1); lua_pushinteger(L, 0); @@ -199588,10 +199900,11 @@ static void print_version (void) { ** to the script (everything after 'script') go to positive indices; ** other arguments (before the script name) go to negative indices. ** If there is no script name, assume interpreter's name as base. +** (If there is no interpreter's name either, 'script' is -1, so +** table sizes are zero.) */ static void createargtable (lua_State *L, char **argv, int argc, int script) { int i, narg; - if (script == argc) script = 0; /* no script name? */ narg = argc - (script + 1); /* number of positive indices */ lua_createtable(L, narg, script + 1); for (i = 0; i < argc; i++) { @@ -199679,14 +199992,23 @@ static int handle_script (lua_State *L, char **argv) { /* ** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code (or an error code if it finds -** any invalid argument). 'first' returns the first not-handled argument -** (either the script name or a bad argument in case of error). +** needed before running any Lua code or an error code if it finds any +** invalid argument. In case of error, 'first' is the index of the bad +** argument. Otherwise, 'first' is -1 if there is no program name, +** 0 if there is no script name, or the index of the script name. */ static int collectargs (char **argv, int *first) { int args = 0; int i; - for (i = 1; argv[i] != NULL; i++) { + if (argv[0] != NULL) { /* is there a program name? */ + if (argv[0][0]) /* not empty? */ + progname = argv[0]; /* save it */ + } + else { /* no program name */ + *first = -1; + return 0; + } + for (i = 1; argv[i] != NULL; i++) { /* handle arguments */ *first = i; if (argv[i][0] != '-') /* not an option? */ return args; /* stop handling options */ @@ -199727,7 +200049,7 @@ static int collectargs (char **argv, int *first) { return has_error; } } - *first = i; /* no script name */ + *first = 0; /* no script name */ return args; } @@ -200020,8 +200342,8 @@ static int pmain (lua_State *L) { char **argv = (char **)lua_touserdata(L, 2); int script; int args = collectargs(argv, &script); + int optlim = (script > 0) ? script : argc; /* first argv not an option */ luaL_checkversion(L); /* check that interpreter has correct version */ - if (argv[0] && argv[0][0]) progname = argv[0]; if (args == has_error) { /* bad arg? */ print_usage(argv[script]); /* 'script' has index of bad arg. */ return 0; @@ -200034,19 +200356,21 @@ static int pmain (lua_State *L) { } luaL_openlibs(L); /* open standard libraries */ createargtable(L, argv, argc, script); /* create table 'arg' */ - lua_gc(L, LUA_GCGEN, 0, 0); /* GC in generational mode */ + lua_gc(L, LUA_GCRESTART); /* start GC... */ + lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ if (!(args & has_E)) { /* no option '-E'? */ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ return 0; /* error running LUA_INIT */ } - if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */ return 0; /* something failed */ - if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script) != LUA_OK) - return 0; + if (script > 0) { /* execute main script (if there is one) */ + if (handle_script(L, argv + script) != LUA_OK) + return 0; /* interrupt in case of error */ + } if (args & has_i) /* -i option? */ doREPL(L); /* do read-eval-print loop */ - else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */ if (lua_stdin_is_tty()) { /* running in interactive mode? */ print_version(); doREPL(L); /* do read-eval-print loop */ @@ -200065,6 +200389,7 @@ int main (int argc, char **argv) { l_message(argv[0], "cannot create state: not enough memory"); return EXIT_FAILURE; } + lua_gc(L, LUA_GCSTOP); /* stop GC while building state */ lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ lua_pushinteger(L, argc); /* 1st argument */ lua_pushlightuserdata(L, argv); /* 2nd argument */ @@ -200081,7 +200406,7 @@ int main (int argc, char **argv) { MIT License Copyright (c) 1994–2019 Lua.org, PUC-Rio. - Copyright (c) 2020-2022 Eduardo Bart (https://github.com/edubart). + Copyright (c) 2020-2023 Eduardo Bart (https://github.com/edubart). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -200105,7 +200430,7 @@ int main (int argc, char **argv) { #undef cast #undef G //--- -#line 1 "engine/split/3rd_stb_image.h" +#line 1 "3rd_stb_image.h" /* stb_image - v2.28 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk @@ -208094,7 +208419,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ #line 0 -#line 1 "engine/split/3rd_stb_image_write.h" +#line 1 "3rd_stb_image_write.h" /* stb_image_write - v1.16 - public domain - http://nothings.org/stb writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -209826,7 +210151,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define STBTT_free(x,u) ((void)(u),FREE(x)) #define NK_ASSERT ASSERT #define NK_DTOA(s,n) strcpy(s, va("%f", n)) // override cos built-in nk_dtoa() will freeze while parsing UINT_MAX otherwise -#line 1 "engine/split/3rd_nuklear.h" +#line 1 "3rd_nuklear.h" /* /// # Nuklear /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) @@ -240198,7 +240523,7 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// for his single header file packer. */ #line 0 -#line 1 "engine/split/3rd_nuklear_glfw_gl3.h" +#line 1 "3rd_nuklear_glfw_gl3.h" /* * Nuklear - 1.32.0 - public domain @@ -240753,7 +241078,7 @@ void nk_glfw3_shutdown(struct nk_glfw* glfw) #endif #line 0 static char *ui_filter = 0; -#line 1 "engine/split/3rd_nuklear_filebrowser.h" +#line 1 "3rd_nuklear_filebrowser.h" // file browser for nuklear, based on https://github.com/vurtun/nuklear/blob/master/example/file_browser.c (public domain) // - rlyeh, public domain // @@ -241246,7 +241571,7 @@ static struct nk_image icon_load_rect(unsigned id, unsigned w, unsigned h, unsig //#include "3rd_assimp/postprocess.h" //#pragma comment(lib, "3rd/3rd_assimp/x64/assimp") #endif -#line 1 "engine/split/3rd_json5.h" +#line 1 "3rd_json5.h" // JSON5 + SJSON parser module // // License: @@ -241688,7 +242013,7 @@ int main() { #endif // JSON5_C #line 0 -#line 1 "engine/split/3rd_gjk.h" +#line 1 "3rd_gjk.h" // GJK distance algorithm. original code by @vurtun and @randygaul, public domain. // [src] https://gist.github.com/vurtun/29727217c269a2fbf4c0ed9a1d11cb40 // - rlyeh, public domain. @@ -242297,7 +242622,7 @@ gjk_result gjk_quad(float a_radius, float b_radius) { #endif #line 0 -#line 1 "engine/split/3rd_compress.h" +#line 1 "3rd_compress.h" // compress.c de/compressors into a single-file header // - rlyeh, public domain // @@ -253138,7 +253463,7 @@ unsigned file_decode(FILE* in, FILE* out, FILE *logfile) { // multi decoder #endif // COMPRESS_C #line 0 -#line 1 "engine/split/3rd_archive.h" +#line 1 "3rd_archive.h" // archive.c pak/zip/tar/dir archivers // - rlyeh, public domain @@ -254767,7 +255092,7 @@ int main( int argc, char **argv ) { #if is(win32) #include // timeapi.h #endif -#line 1 "engine/split/3rd_thread.h" +#line 1 "3rd_thread.h" /* ------------------------------------------------------------------------------ Licensing information can be found at the end of the file. @@ -256497,7 +256822,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ #line 0 -#line 1 "engine/split/3rd_plmpeg.h" +#line 1 "3rd_plmpeg.h" /* PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer @@ -260763,7 +261088,7 @@ void plm_audio_matrix_transform(int s[32][3], int ss, float *d, int dp) { #endif // PL_MPEG_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_jo_mpeg.h" +#line 1 "3rd_jo_mpeg.h" /* public domain Simple, Minimalistic, No Allocations MPEG writer - http://jonolick.com * * Latest revisions: @@ -261030,7 +261355,7 @@ void jo_write_mpeg(FILE *fp, const unsigned char *bgrx, int width, int height, i #endif #line 0 //#define _RTL_RUN_ONCE _RTL_RUN_ONCE2 // __MINGW64__ -#line 1 "engine/split/3rd_https.h" +#line 1 "3rd_https.h" /* ------------------------------------------------------------------------------ Licensing information can be found at the end of the file. @@ -308013,7 +308338,7 @@ int main() { #line 0 #undef F2 #undef F3 -#line 1 "engine/split/3rd_enet.h" +#line 1 "3rd_enet.h" /** * include/enet.h - a Single-Header auto-generated variant of enet.h library. * @@ -314154,7 +314479,7 @@ extern "C" { #endif // ENET_INCLUDE_H #line 0 #define tls_init tls_init2 -#line 1 "engine/split/3rd_bq_websocket.h" +#line 1 "3rd_bq_websocket.h" /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. @@ -320517,7 +320842,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif // BQ_PLATFORM_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_simplex.h" +#line 1 "3rd_simplex.h" /** 1D, 2D, 3D and 4D float Perlin Simplex noise */ /** Original code, stefan gustavson (PD). */ @@ -321000,7 +321325,7 @@ float snoise4(float x, float y, float z, float w) { #endif #line 0 -#line 1 "engine/split/3rd_tfd.h" +#line 1 "3rd_tfd.h" /* If you are using a C++ compiler to compile tinyfiledialogs.c (maybe renamed with an extension ".cpp") then comment out << extern "C" >> bellow in this header file) */ @@ -329060,7 +329385,7 @@ tinyfd_messageBox("The selected hexcolor is", #endif // TFD_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_stb_sprintf.h" +#line 1 "3rd_stb_sprintf.h" // stb_sprintf - v1.10 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb @@ -330969,7 +331294,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #line 0 #define g g2 -#line 1 "engine/split/3rd_xml.h" +#line 1 "3rd_xml.h" // original xml.h/xml.c files by tor andersson, public domain #ifndef xml_h @@ -331500,7 +331825,7 @@ struct xml *xml_parse(char *s, int preserve_white, char **errorp) #endif #line 0 #undef g -#line 1 "engine/split/3rd_polychop.h" +#line 1 "3rd_polychop.h" /* Progressive Mesh type Polygon Reduction Algorithm * * 1998: Original version by Stan Melax (c) 1998 @@ -331921,7 +332246,7 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, else if(!strcmp(id, "held") && nargs ==1) push(ev, input_held(pop(ev))); \ else if(!strcmp(id, "up") && nargs ==1) push(ev, input_up(pop(ev))); \ else if(!strcmp(id, "idle") && nargs ==1) push(ev, input_idle(pop(ev))); -#line 1 "engine/split/3rd_eval.h" +#line 1 "3rd_eval.h" /* A mathematical expression evaluator. * It uses a recursive descent parser internally. * Author: Werner Stoop @@ -332431,7 +332756,7 @@ int main() { } #endif #line 0 -#line 1 "engine/split/3rd_luadebugger.h" +#line 1 "3rd_luadebugger.h" /* Copyright (c) 2023 Scott Lembcke and Howling Moon Software @@ -333911,7 +334236,7 @@ int dbg_pcall(lua_State *lua, int nargs, int nresults, int msgh){ return err; } #line 0 -#line 1 "engine/split/3rd_base64.h" +#line 1 "3rd_base64.h" // base64 de/encoder. Based on code by Jon Mayo - November 13, 2003 (PUBLIC DOMAIN). // - rlyeh, public domain @@ -333940,7 +334265,7 @@ unsigned base64_bounds(unsigned size) { char* base64_encode(const void *inp, unsigned inlen) { // free() after use unsigned outlen = base64_bounds(inlen); - char *out_ = malloc(outlen); + char *out_ = MALLOC(outlen); out_[outlen] = 0; uint_least32_t v; @@ -333957,21 +334282,21 @@ char* base64_encode(const void *inp, unsigned inlen) { // free() after use while (rem >= 6) { rem -= 6; if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[(v >> rem) & 63]; } } if (rem) { v <<= (6 - rem); if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[v & 63]; } while(io&3) { - if(io>=outlen) return (free(out_), 0); /* truncation is failure */ + if(io>=outlen) return (FREE(out_), NULL); /* truncation is failure */ out[io++]='='; } - if(io>=outlen) return (free(out_), 0); /* no room for null terminator */ + if(io>=outlen) return (FREE(out_), NULL); /* no room for null terminator */ out[io]=0; return out_; } @@ -334053,6 +334378,4020 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft #endif // array_resize #endif // BASE64_C #line 0 + +#if ENABLE_RPMALLOC +#line 1 "3rd_rpmalloc.h" +/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__clang__) || defined(__GNUC__) +# define RPMALLOC_EXPORT __attribute__((visibility("default"))) +# define RPMALLOC_ALLOCATOR +# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) +# else +# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__)) +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size))) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size))) +# endif +# define RPMALLOC_CDECL +#elif defined(_MSC_VER) +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL __cdecl +#else +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL +#endif + +//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce +// a very small overhead due to some size calculations not being compile time constants +#ifndef RPMALLOC_CONFIGURABLE +#define RPMALLOC_CONFIGURABLE 0 +#endif + +//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions). +// Will introduce a very small overhead to track fully allocated spans in heaps +#ifndef RPMALLOC_FIRST_CLASS_HEAPS +#define RPMALLOC_FIRST_CLASS_HEAPS 0 +#endif + +//! Flag to rpaligned_realloc to not preserve content in reallocation +#define RPMALLOC_NO_PRESERVE 1 +//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place, +// in which case the original pointer is still valid (just like a call to realloc which failes to allocate +// a new block). +#define RPMALLOC_GROW_OR_FAIL 2 + +typedef struct rpmalloc_global_statistics_t { + //! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped; + //! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped_peak; + //! Current amount of memory in global caches for small and medium sizes (<32KiB) + size_t cached; + //! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc; + //! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc_peak; + //! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1) + size_t mapped_total; + //! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1) + size_t unmapped_total; +} rpmalloc_global_statistics_t; + +typedef struct rpmalloc_thread_statistics_t { + //! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB) + size_t sizecache; + //! Current number of bytes available in thread span caches for small and medium sizes (<32KiB) + size_t spancache; + //! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1) + size_t thread_to_global; + //! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1) + size_t global_to_thread; + //! Per span count statistics (only if ENABLE_STATISTICS=1) + struct { + //! Currently used number of spans + size_t current; + //! High water mark of spans used + size_t peak; + //! Number of spans transitioned to global cache + size_t to_global; + //! Number of spans transitioned from global cache + size_t from_global; + //! Number of spans transitioned to thread cache + size_t to_cache; + //! Number of spans transitioned from thread cache + size_t from_cache; + //! Number of spans transitioned to reserved state + size_t to_reserved; + //! Number of spans transitioned from reserved state + size_t from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } span_use[64]; + //! Per size class statistics (only if ENABLE_STATISTICS=1) + struct { + //! Current number of allocations + size_t alloc_current; + //! Peak number of allocations + size_t alloc_peak; + //! Total number of allocations + size_t alloc_total; + //! Total number of frees + size_t free_total; + //! Number of spans transitioned to cache + size_t spans_to_cache; + //! Number of spans transitioned from cache + size_t spans_from_cache; + //! Number of spans transitioned from reserved state + size_t spans_from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } size_use[128]; +} rpmalloc_thread_statistics_t; + +typedef struct rpmalloc_config_t { + //! Map memory pages for the given number of bytes. The returned address MUST be + // aligned to the rpmalloc span size, which will always be a power of two. + // Optionally the function can store an alignment offset in the offset variable + // in case it performs alignment and the returned pointer is offset from the + // actual start of the memory region due to this alignment. The alignment offset + // will be passed to the memory unmap function. The alignment offset MUST NOT be + // larger than 65535 (storable in an uint16_t), if it is you must use natural + // alignment to shift it into 16 bits. If you set a memory_map function, you + // must also set a memory_unmap function or else the default implementation will + // be used for both. This function must be thread safe, it can be called by + // multiple threads simultaneously. + void* (*memory_map)(size_t size, size_t* offset); + //! Unmap the memory pages starting at address and spanning the given number of bytes. + // If release is set to non-zero, the unmap is for an entire span range as returned by + // a previous call to memory_map and that the entire range should be released. The + // release argument holds the size of the entire span range. If release is set to 0, + // the unmap is a partial decommit of a subset of the mapped memory range. + // If you set a memory_unmap function, you must also set a memory_map function or + // else the default implementation will be used for both. This function must be thread + // safe, it can be called by multiple threads simultaneously. + void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release); + //! Called when an assert fails, if asserts are enabled. Will use the standard assert() + // if this is not set. + void (*error_callback)(const char* message); + //! Called when a call to map memory pages fails (out of memory). If this callback is + // not set or returns zero the library will return a null pointer in the allocation + // call. If this callback returns non-zero the map call will be retried. The argument + // passed is the number of bytes that was requested in the map call. Only used if + // the default system memory map function is used (memory_map callback is not set). + int (*map_fail_callback)(size_t size); + //! Size of memory pages. The page size MUST be a power of two. All memory mapping + // requests to memory_map will be made with size set to a multiple of the page size. + // Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used. + size_t page_size; + //! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144] + // range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE + // is defined to 1. + size_t span_size; + //! Number of spans to map at each request to map new virtual memory blocks. This can + // be used to minimize the system call overhead at the cost of virtual memory address + // space. The extra mapped pages will not be written until actually used, so physical + // committed memory should not be affected in the default implementation. Will be + // aligned to a multiple of spans that match memory page size in case of huge pages. + size_t span_map_count; + //! Enable use of large/huge pages. If this flag is set to non-zero and page size is + // zero, the allocator will try to enable huge pages and auto detect the configuration. + // If this is set to non-zero and page_size is also non-zero, the allocator will + // assume huge pages have been configured and enabled prior to initializing the + // allocator. + // For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support + // For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt + int enable_huge_pages; + //! Respectively allocated pages and huge allocated pages names for systems + // supporting it to be able to distinguish among anonymous regions. + const char *page_name; + const char *huge_page_name; +} rpmalloc_config_t; + +//! Initialize allocator with default configuration +RPMALLOC_EXPORT int +rpmalloc_initialize(void); + +//! Initialize allocator with given configuration +RPMALLOC_EXPORT int +rpmalloc_initialize_config(const rpmalloc_config_t* config); + +//! Get allocator configuration +RPMALLOC_EXPORT const rpmalloc_config_t* +rpmalloc_config(void); + +//! Finalize allocator +RPMALLOC_EXPORT void +rpmalloc_finalize(void); + +//! Initialize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_initialize(void); + +//! Finalize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_finalize(int release_caches); + +//! Perform deferred deallocations pending for the calling thread heap +RPMALLOC_EXPORT void +rpmalloc_thread_collect(void); + +//! Query if allocator is initialized for calling thread +RPMALLOC_EXPORT int +rpmalloc_is_thread_initialized(void); + +//! Get per-thread statistics +RPMALLOC_EXPORT void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats); + +//! Get global statistics +RPMALLOC_EXPORT void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats); + +//! Dump all statistics in human readable format to file (should be a FILE*) +RPMALLOC_EXPORT void +rpmalloc_dump_statistics(void* file); + +//! Allocate a memory block of at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1); + +//! Free the given memory block +RPMALLOC_EXPORT void +rpfree(void* ptr); + +//! Allocate a memory block of at least the given size and zero initialize it +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2); + +//! Reallocate the given block to at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Reallocate the given block to at least the given size and alignment, +// with optional control flags (see RPMALLOC_NO_PRESERVE). +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment, and zero initialize it. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT int +rpposix_memalign(void** memptr, size_t alignment, size_t size); + +//! Query the usable size of the given memory block (from given pointer to the end of block) +RPMALLOC_EXPORT size_t +rpmalloc_usable_size(void* ptr); + +//! Dummy empty function for forcing linker symbol inclusion +RPMALLOC_EXPORT void +rpmalloc_linker_reference(void); + +#if RPMALLOC_FIRST_CLASS_HEAPS + +//! Heap type +typedef struct heap_t rpmalloc_heap_t; + +//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap +// if none available. Heap API is implemented with the strict assumption that only one single +// thread will call heap functions for a given heap at any given time, no functions are thread safe. +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_heap_acquire(void); + +//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap). +// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer. +RPMALLOC_EXPORT void +rpmalloc_heap_release(rpmalloc_heap_t* heap); + +//! Allocate a memory block of at least the given size using the given heap. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size using the given heap. The returned +// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned +// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. The returned block will have the requested alignment. +// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be +// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than +// the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4); + +//! Free the given memory block from the given heap. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr); + +//! Free all memory allocated by the heap +RPMALLOC_EXPORT void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap); + +//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap +// for a single thread, a heap can never be shared between multiple threads. The previous +// current heap for the calling thread is released to be reused by other threads. +RPMALLOC_EXPORT void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap); + +//! Returns which heap the given pointer is allocated on +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr); + +#endif + +#ifdef __cplusplus +} +#endif +#line 0 +#line 1 "3rd_rpmalloc.c" +/* rpmalloc.c - Memory allocator - Public Domain - 2016-2020 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +// #include "rpmalloc.h" //< @r-lyeh + +//////////// +/// +/// Build time configurable limits +/// +////// + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-macros" +#pragma clang diagnostic ignored "-Wunused-function" +#if __has_warning("-Wreserved-identifier") +#pragma clang diagnostic ignored "-Wreserved-identifier" +#endif +#if __has_warning("-Wstatic-in-inline") +#pragma clang diagnostic ignored "-Wstatic-in-inline" +#endif +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if !defined(__has_builtin) +#define __has_builtin(b) 0 +#endif + +#if defined(__GNUC__) || defined(__clang__) + +#if __has_builtin(__builtin_memcpy_inline) +#define _rpmalloc_memcpy_const(x, y, s) __builtin_memcpy_inline(x, y, s) +#else +#define _rpmalloc_memcpy_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memcpy(x, y, s); \ + } while (0) +#endif + +#if __has_builtin(__builtin_memset_inline) +#define _rpmalloc_memset_const(x, y, s) __builtin_memset_inline(x, y, s) +#else +#define _rpmalloc_memset_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memset(x, y, s); \ + } while (0) +#endif +#else +#define _rpmalloc_memcpy_const(x, y, s) memcpy(x, y, s) +#define _rpmalloc_memset_const(x, y, s) memset(x, y, s) +#endif + +#if __has_builtin(__builtin_assume) +#define rpmalloc_assume(cond) __builtin_assume(cond) +#elif defined(__GNUC__) +#define rpmalloc_assume(cond) \ + do { \ + if (!__builtin_expect(cond, 0)) \ + __builtin_unreachable(); \ + } while (0) +#elif defined(_MSC_VER) +#define rpmalloc_assume(cond) __assume(cond) +#else +#define rpmalloc_assume(cond) 0 +#endif + +#ifndef HEAP_ARRAY_SIZE +//! Size of heap hashmap +#define HEAP_ARRAY_SIZE 47 +#endif +#ifndef ENABLE_THREAD_CACHE +//! Enable per-thread cache +#define ENABLE_THREAD_CACHE 1 +#endif +#ifndef ENABLE_GLOBAL_CACHE +//! Enable global cache shared between all threads, requires thread cache +#define ENABLE_GLOBAL_CACHE 1 +#endif +#ifndef ENABLE_VALIDATE_ARGS +//! Enable validation of args to public entry points +#define ENABLE_VALIDATE_ARGS 0 +#endif +#ifndef ENABLE_STATISTICS +//! Enable statistics collection +#define ENABLE_STATISTICS 0 +#endif +#ifndef ENABLE_ASSERTS +//! Enable asserts +#define ENABLE_ASSERTS 0 +#endif +#ifndef ENABLE_OVERRIDE +//! Override standard library malloc/free and new/delete entry points +#define ENABLE_OVERRIDE 0 +#endif +#ifndef ENABLE_PRELOAD +//! Support preloading +#define ENABLE_PRELOAD 0 +#endif +#ifndef DISABLE_UNMAP +//! Disable unmapping memory pages (also enables unlimited cache) +#define DISABLE_UNMAP 0 +#endif +#ifndef ENABLE_UNLIMITED_CACHE +//! Enable unlimited global cache (no unmapping until finalization) +#define ENABLE_UNLIMITED_CACHE 0 +#endif +#ifndef ENABLE_ADAPTIVE_THREAD_CACHE +//! Enable adaptive thread cache size based on use heuristics +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif +#ifndef DEFAULT_SPAN_MAP_COUNT +//! Default number of spans to map in call to map more virtual memory (default values yield 4MiB here) +#define DEFAULT_SPAN_MAP_COUNT 64 +#endif +#ifndef GLOBAL_CACHE_MULTIPLIER +//! Multiplier for global cache +#define GLOBAL_CACHE_MULTIPLIER 8 +#endif + +#if DISABLE_UNMAP && !ENABLE_GLOBAL_CACHE +#error Must use global cache if unmap is disabled +#endif + +#if DISABLE_UNMAP +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 1 +#endif + +#if !ENABLE_GLOBAL_CACHE +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 0 +#endif + +#if !ENABLE_THREAD_CACHE +#undef ENABLE_ADAPTIVE_THREAD_CACHE +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) +# define PLATFORM_WINDOWS 1 +# define PLATFORM_POSIX 0 +#else +# define PLATFORM_WINDOWS 0 +# define PLATFORM_POSIX 1 +#endif + +/// Platform and arch specifics +#if defined(_MSC_VER) && !defined(__clang__) +# pragma warning (disable: 5105) +# ifndef FORCEINLINE +# define FORCEINLINE inline __forceinline +# endif +# define _Static_assert static_assert +#else +# ifndef FORCEINLINE +# define FORCEINLINE inline __attribute__((__always_inline__)) +# endif +#endif +#if PLATFORM_WINDOWS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if ENABLE_VALIDATE_ARGS +# include +# endif +#else +# include +# include +# include +# include +# if defined(__linux__) || defined(__ANDROID__) +# include +# if !defined(PR_SET_VMA) +# define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 +# endif +# endif +# if defined(__APPLE__) +# include +# if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +# include +# include +# endif +# include +# endif +# if defined(__HAIKU__) || defined(__TINYC__) +# include +# endif +#endif + +#include +#include +#include + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +#include +static DWORD fls_key; +#endif + +#if PLATFORM_POSIX +# include +# include +# ifdef __FreeBSD__ +# include +# define MAP_HUGETLB MAP_ALIGNED_SUPER +# ifndef PROT_MAX +# define PROT_MAX(f) 0 +# endif +# else +# define PROT_MAX(f) 0 +# endif +# ifdef __sun +extern int madvise(caddr_t, size_t, int); +# endif +# ifndef MAP_UNINITIALIZED +# define MAP_UNINITIALIZED 0 +# endif +#endif +#include + +#if ENABLE_ASSERTS +# undef NDEBUG +# if defined(_MSC_VER) && !defined(_DEBUG) +# define _DEBUG +# endif +# include +#define RPMALLOC_TOSTRING_M(x) #x +#define RPMALLOC_TOSTRING(x) RPMALLOC_TOSTRING_M(x) +#define rpmalloc_assert(truth, message) \ + do { \ + if (!(truth)) { \ + if (_memory_config.error_callback) { \ + _memory_config.error_callback( \ + message " (" RPMALLOC_TOSTRING(truth) ") at " __FILE__ ":" RPMALLOC_TOSTRING(__LINE__)); \ + } else { \ + assert((truth) && message); \ + } \ + } \ + } while (0) +#else +# define rpmalloc_assert(truth, message) do {} while(0) +#endif +#if ENABLE_STATISTICS +# include +#endif + +////// +/// +/// Atomic access abstraction (since MSVC does not do C11 yet) +/// +////// + +#if defined(_MSC_VER) && !defined(__clang__) + +typedef volatile long atomic32_t; +typedef volatile long long atomic64_t; +typedef volatile void* atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return *src; } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return (int32_t)InterlockedIncrement(val); } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return (int32_t)InterlockedDecrement(val); } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return (int32_t)InterlockedExchangeAdd(val, add) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return (InterlockedCompareExchange(dst, val, ref) == ref) ? 1 : 0; } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int64_t atomic_load64(atomic64_t* src) { return *src; } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return (int64_t)InterlockedExchangeAdd64(val, add) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return (void*)*src; } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return (void*)InterlockedExchangePointer((void* volatile*)dst, val); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return (InterlockedCompareExchangePointer((void* volatile*)dst, val, ref) == ref) ? 1 : 0; } + +#define EXPECTED(x) (x) +#define UNEXPECTED(x) (x) + +#else + +#include + +typedef volatile _Atomic(int32_t) atomic32_t; +typedef volatile _Atomic(int64_t) atomic64_t; +typedef volatile _Atomic(void*) atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, -1, memory_order_relaxed) - 1; } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_acquire, memory_order_relaxed); } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE int64_t atomic_load64(atomic64_t* val) { return atomic_load_explicit(val, memory_order_relaxed); } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return atomic_exchange_explicit(dst, val, memory_order_acquire); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_relaxed, memory_order_relaxed); } + +#define EXPECTED(x) __builtin_expect((x), 1) +#define UNEXPECTED(x) __builtin_expect((x), 0) + +#endif + +//////////// +/// +/// Statistics related functions (evaluate to nothing when statistics not enabled) +/// +////// + +#if ENABLE_STATISTICS +# define _rpmalloc_stat_inc(counter) atomic_incr32(counter) +# define _rpmalloc_stat_dec(counter) atomic_decr32(counter) +# define _rpmalloc_stat_add(counter, value) atomic_add32(counter, (int32_t)(value)) +# define _rpmalloc_stat_add64(counter, value) atomic_add64(counter, (int64_t)(value)) +# define _rpmalloc_stat_add_peak(counter, value, peak) do { int32_t _cur_count = atomic_add32(counter, (int32_t)(value)); if (_cur_count > (peak)) peak = _cur_count; } while (0) +# define _rpmalloc_stat_sub(counter, value) atomic_add32(counter, -(int32_t)(value)) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do { \ + int32_t alloc_current = atomic_incr32(&heap->size_class_use[class_idx].alloc_current); \ + if (alloc_current > heap->size_class_use[class_idx].alloc_peak) \ + heap->size_class_use[class_idx].alloc_peak = alloc_current; \ + atomic_incr32(&heap->size_class_use[class_idx].alloc_total); \ +} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do { \ + atomic_decr32(&heap->size_class_use[class_idx].alloc_current); \ + atomic_incr32(&heap->size_class_use[class_idx].free_total); \ +} while(0) +#else +# define _rpmalloc_stat_inc(counter) do {} while(0) +# define _rpmalloc_stat_dec(counter) do {} while(0) +# define _rpmalloc_stat_add(counter, value) do {} while(0) +# define _rpmalloc_stat_add64(counter, value) do {} while(0) +# define _rpmalloc_stat_add_peak(counter, value, peak) do {} while (0) +# define _rpmalloc_stat_sub(counter, value) do {} while(0) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do {} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do {} while(0) +#endif + + +/// +/// Preconfigured limits and sizes +/// + +//! Granularity of a small allocation block (must be power of two) +#define SMALL_GRANULARITY 16 +//! Small granularity shift count +#define SMALL_GRANULARITY_SHIFT 4 +//! Number of small block size classes +#define SMALL_CLASS_COUNT 65 +//! Maximum size of a small block +#define SMALL_SIZE_LIMIT (SMALL_GRANULARITY * (SMALL_CLASS_COUNT - 1)) +//! Granularity of a medium allocation block +#define MEDIUM_GRANULARITY 512 +//! Medium granularity shift count +#define MEDIUM_GRANULARITY_SHIFT 9 +//! Number of medium block size classes +#define MEDIUM_CLASS_COUNT 61 +//! Total number of small + medium size classes +#define SIZE_CLASS_COUNT (SMALL_CLASS_COUNT + MEDIUM_CLASS_COUNT) +//! Number of large block size classes +#define LARGE_CLASS_COUNT 63 +//! Maximum size of a medium block +#define MEDIUM_SIZE_LIMIT (SMALL_SIZE_LIMIT + (MEDIUM_GRANULARITY * MEDIUM_CLASS_COUNT)) +//! Maximum size of a large block +#define LARGE_SIZE_LIMIT ((LARGE_CLASS_COUNT * _memory_span_size) - SPAN_HEADER_SIZE) +//! Size of a span header (must be a multiple of SMALL_GRANULARITY and a power of two) +#define SPAN_HEADER_SIZE 128 +//! Number of spans in thread cache +#define MAX_THREAD_SPAN_CACHE 400 +//! Number of spans to transfer between thread and global cache +#define THREAD_SPAN_CACHE_TRANSFER 64 +//! Number of spans in thread cache for large spans (must be greater than LARGE_CLASS_COUNT / 2) +#define MAX_THREAD_SPAN_LARGE_CACHE 100 +//! Number of spans to transfer between thread and global cache for large spans +#define THREAD_SPAN_LARGE_CACHE_TRANSFER 6 + +_Static_assert((SMALL_GRANULARITY & (SMALL_GRANULARITY - 1)) == 0, "Small granularity must be power of two"); +_Static_assert((SPAN_HEADER_SIZE & (SPAN_HEADER_SIZE - 1)) == 0, "Span header size must be power of two"); + +#if ENABLE_VALIDATE_ARGS +//! Maximum allocation size to avoid integer overflow +#undef MAX_ALLOC_SIZE +#define MAX_ALLOC_SIZE (((size_t)-1) - _memory_span_size) +#endif + +#define pointer_offset(ptr, ofs) (void*)((char*)(ptr) + (ptrdiff_t)(ofs)) +#define pointer_diff(first, second) (ptrdiff_t)((const char*)(first) - (const char*)(second)) + +#define INVALID_POINTER ((void*)((uintptr_t)-1)) + +#define SIZE_CLASS_LARGE SIZE_CLASS_COUNT +#define SIZE_CLASS_HUGE ((uint32_t)-1) + +//////////// +/// +/// Data types +/// +////// + +//! A memory heap, per thread +typedef struct heap_t heap_t; +//! Span of memory pages +typedef struct span_t span_t; +//! Span list +typedef struct span_list_t span_list_t; +//! Span active data +typedef struct span_active_t span_active_t; +//! Size class definition +typedef struct size_class_t size_class_t; +//! Global cache +typedef struct global_cache_t global_cache_t; + +//! Flag indicating span is the first (master) span of a split superspan +#define SPAN_FLAG_MASTER 1U +//! Flag indicating span is a secondary (sub) span of a split superspan +#define SPAN_FLAG_SUBSPAN 2U +//! Flag indicating span has blocks with increased alignment +#define SPAN_FLAG_ALIGNED_BLOCKS 4U +//! Flag indicating an unmapped master span +#define SPAN_FLAG_UNMAPPED_MASTER 8U + +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS +struct span_use_t { + //! Current number of spans used (actually used, not in cache) + atomic32_t current; + //! High water mark of spans used + atomic32_t high; +#if ENABLE_STATISTICS + //! Number of spans in deferred list + atomic32_t spans_deferred; + //! Number of spans transitioned to global cache + atomic32_t spans_to_global; + //! Number of spans transitioned from global cache + atomic32_t spans_from_global; + //! Number of spans transitioned to thread cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from thread cache + atomic32_t spans_from_cache; + //! Number of spans transitioned to reserved state + atomic32_t spans_to_reserved; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of raw memory map calls + atomic32_t spans_map_calls; +#endif +}; +typedef struct span_use_t span_use_t; +#endif + +#if ENABLE_STATISTICS +struct size_class_use_t { + //! Current number of allocations + atomic32_t alloc_current; + //! Peak number of allocations + int32_t alloc_peak; + //! Total number of allocations + atomic32_t alloc_total; + //! Total number of frees + atomic32_t free_total; + //! Number of spans in use + atomic32_t spans_current; + //! Number of spans transitioned to cache + int32_t spans_peak; + //! Number of spans transitioned to cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from cache + atomic32_t spans_from_cache; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of spans mapped + atomic32_t spans_map_calls; + int32_t unused; +}; +typedef struct size_class_use_t size_class_use_t; +#endif + +// A span can either represent a single span of memory pages with size declared by span_map_count configuration variable, +// or a set of spans in a continuous region, a super span. Any reference to the term "span" usually refers to both a single +// span or a super span. A super span can further be divided into multiple spans (or this, super spans), where the first +// (super)span is the master and subsequent (super)spans are subspans. The master span keeps track of how many subspans +// that are still alive and mapped in virtual memory, and once all subspans and master have been unmapped the entire +// superspan region is released and unmapped (on Windows for example, the entire superspan range has to be released +// in the same call to release the virtual memory range, but individual subranges can be decommitted individually +// to reduce physical memory use). +struct span_t { + //! Free list + void* free_list; + //! Total block count of size class + uint32_t block_count; + //! Size class + uint32_t size_class; + //! Index of last block initialized in free list + uint32_t free_list_limit; + //! Number of used blocks remaining when in partial state + uint32_t used_count; + //! Deferred free list + atomicptr_t free_list_deferred; + //! Size of deferred free list, or list of spans when part of a cache list + uint32_t list_size; + //! Size of a block + uint32_t block_size; + //! Flags and counters + uint32_t flags; + //! Number of spans + uint32_t span_count; + //! Total span counter for master spans + uint32_t total_spans; + //! Offset from master span for subspans + uint32_t offset_from_master; + //! Remaining span counter, for master spans + atomic32_t remaining_spans; + //! Alignment offset + uint32_t align_offset; + //! Owning heap + heap_t* heap; + //! Next span + span_t* next; + //! Previous span + span_t* prev; +}; +_Static_assert(sizeof(span_t) <= SPAN_HEADER_SIZE, "span size mismatch"); + +struct span_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_CACHE]; +}; +typedef struct span_cache_t span_cache_t; + +struct span_large_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_LARGE_CACHE]; +}; +typedef struct span_large_cache_t span_large_cache_t; + +struct heap_size_class_t { + //! Free list of active span + void* free_list; + //! Double linked list of partially used spans with free blocks. + // Previous span pointer in head points to tail span of list. + span_t* partial_span; + //! Early level cache of fully free spans + span_t* cache; +}; +typedef struct heap_size_class_t heap_size_class_t; + +// Control structure for a heap, either a thread heap or a first class heap if enabled +struct heap_t { + //! Owning thread ID + uintptr_t owner_thread; + //! Free lists for each size class + heap_size_class_t size_class[SIZE_CLASS_COUNT]; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, single span + span_cache_t span_cache; +#endif + //! List of deferred free spans (single linked list) + atomicptr_t span_free_deferred; + //! Number of full spans + size_t full_span_count; + //! Mapped but unused spans + span_t* span_reserve; + //! Master span for mapped but unused spans + span_t* span_reserve_master; + //! Number of mapped but unused spans + uint32_t spans_reserved; + //! Child count + atomic32_t child_count; + //! Next heap in id list + heap_t* next_heap; + //! Next heap in orphan list + heap_t* next_orphan; + //! Heap ID + int32_t id; + //! Finalization state flag + int finalize; + //! Master heap owning the memory pages + heap_t* master_heap; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, large spans with > 1 span count + span_large_cache_t span_large_cache[LARGE_CLASS_COUNT - 1]; +#endif +#if RPMALLOC_FIRST_CLASS_HEAPS + //! Double linked list of fully utilized spans with free blocks for each size class. + // Previous span pointer in head points to tail span of list. + span_t* full_span[SIZE_CLASS_COUNT]; + //! Double linked list of large and huge spans allocated by this heap + span_t* large_huge_span; +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //! Current and high water mark of spans used per span count + span_use_t span_use[LARGE_CLASS_COUNT]; +#endif +#if ENABLE_STATISTICS + //! Allocation stats per size class + size_class_use_t size_class_use[SIZE_CLASS_COUNT + 1]; + //! Number of bytes transitioned thread -> global + atomic64_t thread_to_global; + //! Number of bytes transitioned global -> thread + atomic64_t global_to_thread; +#endif +}; + +// Size class for defining a block size bucket +struct size_class_t { + //! Size of blocks in this class + uint32_t block_size; + //! Number of blocks in each chunk + uint16_t block_count; + //! Class index this class is merged with + uint16_t class_idx; +}; +_Static_assert(sizeof(size_class_t) == 8, "Size class size mismatch"); + +struct global_cache_t { + //! Cache lock + atomic32_t lock; + //! Cache count + uint32_t count; +#if ENABLE_STATISTICS + //! Insert count + size_t insert_count; + //! Extract count + size_t extract_count; +#endif + //! Cached spans + span_t* span[GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE]; + //! Unlimited cache overflow + span_t* overflow; +}; + +//////////// +/// +/// Global data +/// +////// + +//! Default span size (64KiB) +#define _memory_default_span_size (64 * 1024) +#define _memory_default_span_size_shift 16 +#define _memory_default_span_mask (~((uintptr_t)(_memory_span_size - 1))) + +//! Initialized flag +static int _rpmalloc_initialized; +//! Main thread ID +static uintptr_t _rpmalloc_main_thread_id; +//! Configuration +static rpmalloc_config_t _memory_config; +//! Memory page size +static size_t _memory_page_size; +//! Shift to divide by page size +static size_t _memory_page_size_shift; +//! Granularity at which memory pages are mapped by OS +static size_t _memory_map_granularity; +#if RPMALLOC_CONFIGURABLE +//! Size of a span of memory pages +static size_t _memory_span_size; +//! Shift to divide by span size +static size_t _memory_span_size_shift; +//! Mask to get to start of a memory span +static uintptr_t _memory_span_mask; +#else +//! Hardwired span size +#define _memory_span_size _memory_default_span_size +#define _memory_span_size_shift _memory_default_span_size_shift +#define _memory_span_mask _memory_default_span_mask +#endif +//! Number of spans to map in each map call +static size_t _memory_span_map_count; +//! Number of spans to keep reserved in each heap +static size_t _memory_heap_reserve_count; +//! Global size classes +static size_class_t _memory_size_class[SIZE_CLASS_COUNT]; +//! Run-time size limit of medium blocks +static size_t _memory_medium_size_limit; +//! Heap ID counter +static atomic32_t _memory_heap_id; +//! Huge page support +static int _memory_huge_pages; +#if ENABLE_GLOBAL_CACHE +//! Global span cache +static global_cache_t _memory_span_cache[LARGE_CLASS_COUNT]; +#endif +//! Global reserved spans +static span_t* _memory_global_reserve; +//! Global reserved count +static size_t _memory_global_reserve_count; +//! Global reserved master +static span_t* _memory_global_reserve_master; +//! All heaps +static heap_t* _memory_heaps[HEAP_ARRAY_SIZE]; +//! Used to restrict access to mapping memory for huge pages +static atomic32_t _memory_global_lock; +//! Orphaned heaps +static heap_t* _memory_orphan_heaps; +#if RPMALLOC_FIRST_CLASS_HEAPS +//! Orphaned heaps (first class heaps) +static heap_t* _memory_first_class_orphan_heaps; +#endif +#if ENABLE_STATISTICS +//! Allocations counter +static atomic64_t _allocation_counter; +//! Deallocations counter +static atomic64_t _deallocation_counter; +//! Active heap count +static atomic32_t _memory_active_heaps; +//! Number of currently mapped memory pages +static atomic32_t _mapped_pages; +//! Peak number of concurrently mapped memory pages +static int32_t _mapped_pages_peak; +//! Number of mapped master spans +static atomic32_t _master_spans; +//! Number of unmapped dangling master spans +static atomic32_t _unmapped_master_spans; +//! Running counter of total number of mapped memory pages since start +static atomic32_t _mapped_total; +//! Running counter of total number of unmapped memory pages since start +static atomic32_t _unmapped_total; +//! Number of currently mapped memory pages in OS calls +static atomic32_t _mapped_pages_os; +//! Number of currently allocated pages in huge allocations +static atomic32_t _huge_pages_current; +//! Peak number of currently allocated pages in huge allocations +static int32_t _huge_pages_peak; +#endif + +//////////// +/// +/// Thread local heap and ID +/// +////// + +//! Current thread heap +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) +static pthread_key_t _memory_thread_heap; +#else +# ifdef _MSC_VER +# define _Thread_local __declspec(thread) +# define TLS_MODEL +# else +# ifndef __HAIKU__ +# define TLS_MODEL __attribute__((tls_model("initial-exec"))) +# else +# define TLS_MODEL +# endif +# if !defined(__clang__) && defined(__GNUC__) +# define _Thread_local __thread +# endif +# endif +static _Thread_local heap_t* _memory_thread_heap TLS_MODEL; +#endif + +static inline heap_t* +get_thread_heap_raw(void) { +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + return pthread_getspecific(_memory_thread_heap); +#else + return _memory_thread_heap; +#endif +} + +//! Get the current thread heap +static inline heap_t* +get_thread_heap(void) { + heap_t* heap = get_thread_heap_raw(); +#if ENABLE_PRELOAD + if (EXPECTED(heap != 0)) + return heap; + rpmalloc_initialize(); + return get_thread_heap_raw(); +#else + return heap; +#endif +} + +//! Fast thread ID +static inline uintptr_t +get_thread_id(void) { +#if defined(_WIN32) + return (uintptr_t)((void*)NtCurrentTeb()); +#elif (defined(__GNUC__) || defined(__clang__)) && !defined(__CYGWIN__) + uintptr_t tid; +# if defined(__i386__) + __asm__("movl %%gs:0, %0" : "=r" (tid) : : ); +# elif defined(__x86_64__) +# if defined(__MACH__) + __asm__("movq %%gs:0, %0" : "=r" (tid) : : ); +# else + __asm__("movq %%fs:0, %0" : "=r" (tid) : : ); +# endif +# elif defined(__arm__) + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid)); +# elif defined(__aarch64__) +# if defined(__MACH__) + // tpidr_el0 likely unused, always return 0 on iOS + __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tid)); +# else + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tid)); +# endif +# else +# error This platform needs implementation of get_thread_id() +# endif + return tid; +#else +# error This platform needs implementation of get_thread_id() +#endif +} + +//! Set the current thread heap +static void +set_thread_heap(heap_t* heap) { +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + pthread_setspecific(_memory_thread_heap, heap); +#else + _memory_thread_heap = heap; +#endif + if (heap) + heap->owner_thread = get_thread_id(); +} + +//! Set main thread ID +extern void +rpmalloc_set_main_thread(void); + +void +rpmalloc_set_main_thread(void) { + _rpmalloc_main_thread_id = get_thread_id(); +} + +static void +_rpmalloc_spin(void) { +#if defined(_MSC_VER) + _mm_pause(); +#elif defined(__x86_64__) || defined(__i386__) + __asm__ volatile("pause" ::: "memory"); +#elif defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH >= 7) + __asm__ volatile("yield" ::: "memory"); +#elif defined(__powerpc__) || defined(__powerpc64__) + // No idea if ever been compiled in such archs but ... as precaution + __asm__ volatile("or 27,27,27"); +#elif defined(__sparc__) + __asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0"); +#else + struct timespec ts = {0}; + nanosleep(&ts, 0); +#endif +} + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +static void NTAPI +_rpmalloc_thread_destructor(void* value) { +#if ENABLE_OVERRIDE + // If this is called on main thread it means rpmalloc_finalize + // has not been called and shutdown is forced (through _exit) or unclean + if (get_thread_id() == _rpmalloc_main_thread_id) + return; +#endif + if (value) + rpmalloc_thread_finalize(1); +} +#endif + + +//////////// +/// +/// Low level memory map/unmap +/// +////// + +static void +_rpmalloc_set_name(void* address, size_t size) { +#if defined(__linux__) || defined(__ANDROID__) + const char *name = _memory_huge_pages ? _memory_config.huge_page_name : _memory_config.page_name; + if (address == MAP_FAILED || !name) + return; + // If the kernel does not support CONFIG_ANON_VMA_NAME or if the call fails + // (e.g. invalid name) it is a no-op basically. + (void)prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)address, size, (uintptr_t)name); +#else + (void)sizeof(size); + (void)sizeof(address); +#endif +} + + +//! Map more virtual memory +// size is number of bytes to map +// offset receives the offset in bytes from start of mapped region +// returns address to start of mapped region to use +static void* +_rpmalloc_mmap(size_t size, size_t* offset) { + rpmalloc_assert(!(size % _memory_page_size), "Invalid mmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); + void* address = _memory_config.memory_map(size, offset); + if (EXPECTED(address != 0)) { + _rpmalloc_stat_add_peak(&_mapped_pages, (size >> _memory_page_size_shift), _mapped_pages_peak); + _rpmalloc_stat_add(&_mapped_total, (size >> _memory_page_size_shift)); + } + return address; +} + +//! Unmap virtual memory +// address is the memory address to unmap, as returned from _memory_map +// size is the number of bytes to unmap, which might be less than full region for a partial unmap +// offset is the offset in bytes to the actual mapped region, as set by _memory_map +// release is set to 0 for partial unmap, or size of entire range for a full unmap +static void +_rpmalloc_unmap(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(!release || (release >= size), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + if (release) { + rpmalloc_assert(!(release % _memory_page_size), "Invalid unmap size"); + _rpmalloc_stat_sub(&_mapped_pages, (release >> _memory_page_size_shift)); + _rpmalloc_stat_add(&_unmapped_total, (release >> _memory_page_size_shift)); + } + _memory_config.memory_unmap(address, size, offset, release); +} + +//! Default implementation to map new pages to virtual memory +static void* +_rpmalloc_mmap_os(size_t size, size_t* offset) { + //Either size is a heap (a single page) or a (multiple) span - we only need to align spans, and only if larger than map granularity + size_t padding = ((size >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) ? _memory_span_size : 0; + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); +#if PLATFORM_WINDOWS + //Ok to MEM_COMMIT - according to MSDN, "actual physical pages are not allocated unless/until the virtual addresses are actually accessed" + void* ptr = VirtualAlloc(0, size + padding, (_memory_huge_pages ? MEM_LARGE_PAGES : 0) | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (!ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else { + rpmalloc_assert(ptr, "Failed to map virtual memory block"); + } + return 0; + } +#else + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED; +# if defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + int fd = (int)VM_MAKE_TAG(240U); + if (_memory_huge_pages) + fd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, fd, 0); +# elif defined(MAP_HUGETLB) + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE | PROT_MAX(PROT_READ | PROT_WRITE), (_memory_huge_pages ? MAP_HUGETLB : 0) | flags, -1, 0); +# if defined(MADV_HUGEPAGE) + // In some configurations, huge pages allocations might fail thus + // we fallback to normal allocations and promote the region as transparent huge page + if ((ptr == MAP_FAILED || !ptr) && _memory_huge_pages) { + ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); + if (ptr && ptr != MAP_FAILED) { + int prm = madvise(ptr, size + padding, MADV_HUGEPAGE); + (void)prm; + rpmalloc_assert((prm == 0), "Failed to promote the page to THP"); + } + } +# endif + _rpmalloc_set_name(ptr, size + padding); +# elif defined(MAP_ALIGNED) + const size_t align = (sizeof(size_t) * 8) - (size_t)(__builtin_clzl(size - 1)); + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGNED(align) : 0) | flags, -1, 0); +# elif defined(MAP_ALIGN) + caddr_t base = (_memory_huge_pages ? (caddr_t)(4 << 20) : 0); + void* ptr = mmap(base, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGN : 0) | flags, -1, 0); +# else + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); +# endif + if ((ptr == MAP_FAILED) || !ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else if (errno != ENOMEM) { + rpmalloc_assert((ptr != MAP_FAILED) && ptr, "Failed to map virtual memory block"); + } + return 0; + } +#endif + _rpmalloc_stat_add(&_mapped_pages_os, (int32_t)((size + padding) >> _memory_page_size_shift)); + if (padding) { + size_t final_padding = padding - ((uintptr_t)ptr & ~_memory_span_mask); + rpmalloc_assert(final_padding <= _memory_span_size, "Internal failure in padding"); + rpmalloc_assert(final_padding <= padding, "Internal failure in padding"); + rpmalloc_assert(!(final_padding % 8), "Internal failure in padding"); + ptr = pointer_offset(ptr, final_padding); + *offset = final_padding >> 3; + } + rpmalloc_assert((size < _memory_span_size) || !((uintptr_t)ptr & ~_memory_span_mask), "Internal failure in padding"); + return ptr; +} + +//! Default implementation to unmap pages from virtual memory +static void +_rpmalloc_unmap_os(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(release || (offset == 0), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid unmap size"); + if (release && offset) { + offset <<= 3; + address = pointer_offset(address, -(int32_t)offset); + if ((release >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) { + //Padding is always one span size + release += _memory_span_size; + } + } +#if !DISABLE_UNMAP +#if PLATFORM_WINDOWS + if (!VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } +#else + if (release) { + if (munmap(address, release)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } + } else { +#if defined(MADV_FREE_REUSABLE) + int ret; + while ((ret = madvise(address, size, MADV_FREE_REUSABLE)) == -1 && (errno == EAGAIN)) + errno = 0; + if ((ret == -1) && (errno != 0)) { +#elif defined(MADV_DONTNEED) + if (madvise(address, size, MADV_DONTNEED)) { +#elif defined(MADV_PAGEOUT) + if (madvise(address, size, MADV_PAGEOUT)) { +#elif defined(MADV_FREE) + if (madvise(address, size, MADV_FREE)) { +#else + if (posix_madvise(address, size, POSIX_MADV_DONTNEED)) { +#endif + rpmalloc_assert(0, "Failed to madvise virtual memory block as free"); + } + } +#endif +#endif + if (release) + _rpmalloc_stat_sub(&_mapped_pages_os, release >> _memory_page_size_shift); +} + +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count); + +//! Use global reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_global_get_reserved_spans(size_t span_count) { + span_t* span = _memory_global_reserve; + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, span, span_count); + _memory_global_reserve_count -= span_count; + if (_memory_global_reserve_count) + _memory_global_reserve = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + else + _memory_global_reserve = 0; + return span; +} + +//! Store the given spans as global reserve (must only be called from within new heap allocation, not thread safe) +static void +_rpmalloc_global_set_reserved_spans(span_t* master, span_t* reserve, size_t reserve_span_count) { + _memory_global_reserve_master = master; + _memory_global_reserve_count = reserve_span_count; + _memory_global_reserve = reserve; +} + + +//////////// +/// +/// Span linked list management +/// +////// + +//! Add a span to double linked list at the head +static void +_rpmalloc_span_double_link_list_add(span_t** head, span_t* span) { + if (*head) + (*head)->prev = span; + span->next = *head; + *head = span; +} + +//! Pop head span from double linked list +static void +_rpmalloc_span_double_link_list_pop_head(span_t** head, span_t* span) { + rpmalloc_assert(*head == span, "Linked list corrupted"); + span = *head; + *head = span->next; +} + +//! Remove a span from double linked list +static void +_rpmalloc_span_double_link_list_remove(span_t** head, span_t* span) { + rpmalloc_assert(*head, "Linked list corrupted"); + if (*head == span) { + *head = span->next; + } else { + span_t* next_span = span->next; + span_t* prev_span = span->prev; + prev_span->next = next_span; + if (EXPECTED(next_span != 0)) + next_span->prev = prev_span; + } +} + + +//////////// +/// +/// Span control +/// +////// + +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span); + +static void +_rpmalloc_heap_finalize(heap_t* heap); + +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count); + +//! Declare the span to be a subspan and store distance from master span and span count +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count) { + rpmalloc_assert((subspan != master) || (subspan->flags & SPAN_FLAG_MASTER), "Span master pointer and/or flag mismatch"); + if (subspan != master) { + subspan->flags = SPAN_FLAG_SUBSPAN; + subspan->offset_from_master = (uint32_t)((uintptr_t)pointer_diff(subspan, master) >> _memory_span_size_shift); + subspan->align_offset = 0; + } + subspan->span_count = (uint32_t)span_count; +} + +//! Use reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_span_map_from_reserve(heap_t* heap, size_t span_count) { + //Update the heap span reserve + span_t* span = heap->span_reserve; + heap->span_reserve = (span_t*)pointer_offset(span, span_count * _memory_span_size); + heap->spans_reserved -= (uint32_t)span_count; + + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, span, span_count); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_reserved); + + return span; +} + +//! Get the aligned number of spans to map in based on wanted count, configured mapping granularity and the page size +static size_t +_rpmalloc_span_align_count(size_t span_count) { + size_t request_count = (span_count > _memory_span_map_count) ? span_count : _memory_span_map_count; + if ((_memory_page_size > _memory_span_size) && ((request_count * _memory_span_size) % _memory_page_size)) + request_count += _memory_span_map_count - (request_count % _memory_span_map_count); + return request_count; +} + +//! Setup a newly mapped span +static void +_rpmalloc_span_initialize(span_t* span, size_t total_span_count, size_t span_count, size_t align_offset) { + span->total_spans = (uint32_t)total_span_count; + span->span_count = (uint32_t)span_count; + span->align_offset = (uint32_t)align_offset; + span->flags = SPAN_FLAG_MASTER; + atomic_store32(&span->remaining_spans, (int32_t)total_span_count); +} + +static void +_rpmalloc_span_unmap(span_t* span); + +//! Map an aligned set of spans, taking configured mapping granularity and the page size into account +static span_t* +_rpmalloc_span_map_aligned_count(heap_t* heap, size_t span_count) { + //If we already have some, but not enough, reserved spans, release those to heap cache and map a new + //full set of spans. Otherwise we would waste memory if page size > span size (huge pages) + size_t aligned_span_count = _rpmalloc_span_align_count(span_count); + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(aligned_span_count * _memory_span_size, &align_offset); + if (!span) + return 0; + _rpmalloc_span_initialize(span, aligned_span_count, span_count, align_offset); + _rpmalloc_stat_inc(&_master_spans); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_map_calls); + if (aligned_span_count > span_count) { + span_t* reserved_spans = (span_t*)pointer_offset(span, span_count * _memory_span_size); + size_t reserved_count = aligned_span_count - span_count; + if (heap->spans_reserved) { + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, heap->span_reserve, heap->spans_reserved); + _rpmalloc_heap_cache_insert(heap, heap->span_reserve); + } + if (reserved_count > _memory_heap_reserve_count) { + // If huge pages or eager spam map count, the global reserve spin lock is held by caller, _rpmalloc_span_map + rpmalloc_assert(atomic_load32(&_memory_global_lock) == 1, "Global spin lock not held as expected"); + size_t remain_count = reserved_count - _memory_heap_reserve_count; + reserved_count = _memory_heap_reserve_count; + span_t* remain_span = (span_t*)pointer_offset(reserved_spans, reserved_count * _memory_span_size); + if (_memory_global_reserve) { + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, _memory_global_reserve, _memory_global_reserve_count); + _rpmalloc_span_unmap(_memory_global_reserve); + } + _rpmalloc_global_set_reserved_spans(span, remain_span, remain_count); + } + _rpmalloc_heap_set_reserved_spans(heap, span, reserved_spans, reserved_count); + } + return span; +} + +//! Map in memory pages for the given number of spans (or use previously reserved pages) +static span_t* +_rpmalloc_span_map(heap_t* heap, size_t span_count) { + if (span_count <= heap->spans_reserved) + return _rpmalloc_span_map_from_reserve(heap, span_count); + span_t* span = 0; + int use_global_reserve = (_memory_page_size > _memory_span_size) || (_memory_span_map_count > _memory_heap_reserve_count); + if (use_global_reserve) { + // If huge pages, make sure only one thread maps more memory to avoid bloat + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (_memory_global_reserve_count >= span_count) { + size_t reserve_count = (!heap->spans_reserved ? _memory_heap_reserve_count : span_count); + if (_memory_global_reserve_count < reserve_count) + reserve_count = _memory_global_reserve_count; + span = _rpmalloc_global_get_reserved_spans(reserve_count); + if (span) { + if (reserve_count > span_count) { + span_t* reserved_span = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + _rpmalloc_heap_set_reserved_spans(heap, _memory_global_reserve_master, reserved_span, reserve_count - span_count); + } + // Already marked as subspan in _rpmalloc_global_get_reserved_spans + span->span_count = (uint32_t)span_count; + } + } + } + if (!span) + span = _rpmalloc_span_map_aligned_count(heap, span_count); + if (use_global_reserve) + atomic_store32_release(&_memory_global_lock, 0); + return span; +} + +//! Unmap memory pages for the given number of spans (or mark as unused if no partial unmappings) +static void +_rpmalloc_span_unmap(span_t* span) { + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + + int is_master = !!(span->flags & SPAN_FLAG_MASTER); + span_t* master = is_master ? span : ((span_t*)pointer_offset(span, -(intptr_t)((uintptr_t)span->offset_from_master * _memory_span_size))); + rpmalloc_assert(is_master || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + + size_t span_count = span->span_count; + if (!is_master) { + //Directly unmap subspans (unless huge pages, in which case we defer and unmap entire page range with master) + rpmalloc_assert(span->align_offset == 0, "Span align offset corrupted"); + if (_memory_span_size >= _memory_page_size) + _rpmalloc_unmap(span, span_count * _memory_span_size, 0, 0); + } else { + //Special double flag to denote an unmapped master + //It must be kept in memory since span header must be used + span->flags |= SPAN_FLAG_MASTER | SPAN_FLAG_SUBSPAN | SPAN_FLAG_UNMAPPED_MASTER; + _rpmalloc_stat_add(&_unmapped_master_spans, 1); + } + + if (atomic_add32(&master->remaining_spans, -(int32_t)span_count) <= 0) { + //Everything unmapped, unmap the master span with release flag to unmap the entire range of the super span + rpmalloc_assert(!!(master->flags & SPAN_FLAG_MASTER) && !!(master->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + size_t unmap_count = master->span_count; + if (_memory_span_size < _memory_page_size) + unmap_count = master->total_spans; + _rpmalloc_stat_sub(&_master_spans, 1); + _rpmalloc_stat_sub(&_unmapped_master_spans, 1); + _rpmalloc_unmap(master, unmap_count * _memory_span_size, master->align_offset, (size_t)master->total_spans * _memory_span_size); + } +} + +//! Move the span (used for small or medium allocations) to the heap thread cache +static void +_rpmalloc_span_release_to_cache(heap_t* heap, span_t* span) { + rpmalloc_assert(heap == span->heap, "Span heap pointer corrupted"); + rpmalloc_assert(span->size_class < SIZE_CLASS_COUNT, "Invalid span size class"); + rpmalloc_assert(span->span_count == 1, "Invalid span count"); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + atomic_decr32(&heap->span_use[0].current); +#endif + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (!heap->finalize) { + _rpmalloc_stat_inc(&heap->span_use[0].spans_to_cache); + _rpmalloc_stat_inc(&heap->size_class_use[span->size_class].spans_to_cache); + if (heap->size_class[span->size_class].cache) + _rpmalloc_heap_cache_insert(heap, heap->size_class[span->size_class].cache); + heap->size_class[span->size_class].cache = span; + } else { + _rpmalloc_span_unmap(span); + } +} + +//! Initialize a (partial) free list up to next system memory page, while reserving the first block +//! as allocated, returning number of blocks in list +static uint32_t +free_list_partial_init(void** list, void** first_block, void* page_start, void* block_start, uint32_t block_count, uint32_t block_size) { + rpmalloc_assert(block_count, "Internal failure"); + *first_block = block_start; + if (block_count > 1) { + void* free_block = pointer_offset(block_start, block_size); + void* block_end = pointer_offset(block_start, (size_t)block_size * block_count); + //If block size is less than half a memory page, bound init to next memory page boundary + if (block_size < (_memory_page_size >> 1)) { + void* page_end = pointer_offset(page_start, _memory_page_size); + if (page_end < block_end) + block_end = page_end; + } + *list = free_block; + block_count = 2; + void* next_block = pointer_offset(free_block, block_size); + while (next_block < block_end) { + *((void**)free_block) = next_block; + free_block = next_block; + ++block_count; + next_block = pointer_offset(next_block, block_size); + } + *((void**)free_block) = 0; + } else { + *list = 0; + } + return block_count; +} + +//! Initialize an unused span (from cache or mapped) to be new active span, putting the initial free list in heap class free list +static void* +_rpmalloc_span_initialize_new(heap_t* heap, heap_size_class_t* heap_size_class, span_t* span, uint32_t class_idx) { + rpmalloc_assert(span->span_count == 1, "Internal failure"); + size_class_t* size_class = _memory_size_class + class_idx; + span->size_class = class_idx; + span->heap = heap; + span->flags &= ~SPAN_FLAG_ALIGNED_BLOCKS; + span->block_size = size_class->block_size; + span->block_count = size_class->block_count; + span->free_list = 0; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); + + //Setup free list. Only initialize one system page worth of free blocks in list + void* block; + span->free_list_limit = free_list_partial_init(&heap_size_class->free_list, &block, + span, pointer_offset(span, SPAN_HEADER_SIZE), size_class->block_count, size_class->block_size); + //Link span as partial if there remains blocks to be initialized as free list, or full if fully initialized + if (span->free_list_limit < span->block_count) { + _rpmalloc_span_double_link_list_add(&heap_size_class->partial_span, span); + span->used_count = span->free_list_limit; + } else { +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + span->used_count = span->block_count; + } + return block; +} + +static void +_rpmalloc_span_extract_free_list_deferred(span_t* span) { + // We need acquire semantics on the CAS operation since we are interested in the list size + // Refer to _rpmalloc_deallocate_defer_small_or_medium for further comments on this dependency + do { + span->free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (span->free_list == INVALID_POINTER); + span->used_count -= span->list_size; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); +} + +static int +_rpmalloc_span_is_fully_utilized(span_t* span) { + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span free list corrupted"); + return !span->free_list && (span->free_list_limit >= span->block_count); +} + +static int +_rpmalloc_span_finalize(heap_t* heap, size_t iclass, span_t* span, span_t** list_head) { + void* free_list = heap->size_class[iclass].free_list; + span_t* class_span = (span_t*)((uintptr_t)free_list & _memory_span_mask); + if (span == class_span) { + // Adopt the heap class free list back into the span free list + void* block = span->free_list; + void* last_block = 0; + while (block) { + last_block = block; + block = *((void**)block); + } + uint32_t free_count = 0; + block = free_list; + while (block) { + ++free_count; + block = *((void**)block); + } + if (last_block) { + *((void**)last_block) = free_list; + } else { + span->free_list = free_list; + } + heap->size_class[iclass].free_list = 0; + span->used_count -= free_count; + } + //If this assert triggers you have memory leaks + rpmalloc_assert(span->list_size == span->used_count, "Memory leak detected"); + if (span->list_size == span->used_count) { + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[iclass].spans_current); + // This function only used for spans in double linked lists + if (list_head) + _rpmalloc_span_double_link_list_remove(list_head, span); + _rpmalloc_span_unmap(span); + return 1; + } + return 0; +} + + +//////////// +/// +/// Global cache +/// +////// + +#if ENABLE_GLOBAL_CACHE + +//! Finalize a global cache +static void +_rpmalloc_global_cache_finalize(global_cache_t* cache) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + for (size_t ispan = 0; ispan < cache->count; ++ispan) + _rpmalloc_span_unmap(cache->span[ispan]); + cache->count = 0; + + while (cache->overflow) { + span_t* span = cache->overflow; + cache->overflow = span->next; + _rpmalloc_span_unmap(span); + } + + atomic_store32_release(&cache->lock, 0); +} + +static void +_rpmalloc_global_cache_insert_spans(span_t** span, size_t span_count, size_t count) { + const size_t cache_limit = (span_count == 1) ? + GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE : + GLOBAL_CACHE_MULTIPLIER * (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t insert_count = count; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->insert_count += count; +#endif + if ((cache->count + insert_count) > cache_limit) + insert_count = cache_limit - cache->count; + + memcpy(cache->span + cache->count, span, sizeof(span_t*) * insert_count); + cache->count += (uint32_t)insert_count; + +#if ENABLE_UNLIMITED_CACHE + while (insert_count < count) { +#else + // Enable unlimited cache if huge pages, or we will leak since it is unlikely that an entire huge page + // will be unmapped, and we're unable to partially decommit a huge page + while ((_memory_page_size > _memory_span_size) && (insert_count < count)) { +#endif + span_t* current_span = span[insert_count++]; + current_span->next = cache->overflow; + cache->overflow = current_span; + } + atomic_store32_release(&cache->lock, 0); + + span_t* keep = 0; + for (size_t ispan = insert_count; ispan < count; ++ispan) { + span_t* current_span = span[ispan]; + // Keep master spans that has remaining subspans to avoid dangling them + if ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) > (int32_t)current_span->span_count)) { + current_span->next = keep; + keep = current_span; + } else { + _rpmalloc_span_unmap(current_span); + } + } + + if (keep) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + size_t islot = 0; + while (keep) { + for (; islot < cache->count; ++islot) { + span_t* current_span = cache->span[islot]; + if (!(current_span->flags & SPAN_FLAG_MASTER) || ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) <= (int32_t)current_span->span_count))) { + _rpmalloc_span_unmap(current_span); + cache->span[islot] = keep; + break; + } + } + if (islot == cache->count) + break; + keep = keep->next; + } + + if (keep) { + span_t* tail = keep; + while (tail->next) + tail = tail->next; + tail->next = cache->overflow; + cache->overflow = keep; + } + + atomic_store32_release(&cache->lock, 0); + } +} + +static size_t +_rpmalloc_global_cache_extract_spans(span_t** span, size_t span_count, size_t count) { + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t extract_count = 0; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->extract_count += count; +#endif + size_t want = count - extract_count; + if (want > cache->count) + want = cache->count; + + memcpy(span + extract_count, cache->span + (cache->count - want), sizeof(span_t*) * want); + cache->count -= (uint32_t)want; + extract_count += want; + + while ((extract_count < count) && cache->overflow) { + span_t* current_span = cache->overflow; + span[extract_count++] = current_span; + cache->overflow = current_span->next; + } + +#if ENABLE_ASSERTS + for (size_t ispan = 0; ispan < extract_count; ++ispan) { + rpmalloc_assert(span[ispan]->span_count == span_count, "Global cache span count mismatch"); + } +#endif + + atomic_store32_release(&cache->lock, 0); + + return extract_count; +} + +#endif + +//////////// +/// +/// Heap control +/// +////// + +static void _rpmalloc_deallocate_huge(span_t*); + +//! Store the given spans as reserve in the given heap +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count) { + heap->span_reserve_master = master; + heap->span_reserve = reserve; + heap->spans_reserved = (uint32_t)reserve_span_count; +} + +//! Adopt the deferred span cache list, optionally extracting the first single span for immediate re-use +static void +_rpmalloc_heap_cache_adopt_deferred(heap_t* heap, span_t** single_span) { + span_t* span = (span_t*)((void*)atomic_exchange_ptr_acquire(&heap->span_free_deferred, 0)); + while (span) { + span_t* next_span = (span_t*)span->free_list; + rpmalloc_assert(span->heap == heap, "Span heap pointer corrupted"); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; + _rpmalloc_stat_dec(&heap->span_use[0].spans_deferred); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } else { + if (span->size_class == SIZE_CLASS_HUGE) { + _rpmalloc_deallocate_huge(span); + } else { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Span size class invalid"); + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->large_huge_span, span); +#endif + uint32_t idx = span->span_count - 1; + _rpmalloc_stat_dec(&heap->span_use[idx].spans_deferred); + _rpmalloc_stat_dec(&heap->span_use[idx].current); + if (!idx && single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } + } + span = next_span; + } +} + +static void +_rpmalloc_heap_unmap(heap_t* heap) { + if (!heap->master_heap) { + if ((heap->finalize > 1) && !atomic_load32(&heap->child_count)) { + span_t* span = (span_t*)((uintptr_t)heap & _memory_span_mask); + _rpmalloc_span_unmap(span); + } + } else { + if (atomic_decr32(&heap->master_heap->child_count) == 0) { + _rpmalloc_heap_unmap(heap->master_heap); + } + } +} + +static void +_rpmalloc_heap_global_finalize(heap_t* heap) { + if (heap->finalize++ > 1) { + --heap->finalize; + return; + } + + _rpmalloc_heap_finalize(heap); + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + + if (heap->full_span_count) { + --heap->finalize; + return; + } + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].free_list || heap->size_class[iclass].partial_span) { + --heap->finalize; + return; + } + } + //Heap is now completely free, unmap and remove from heap list + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap_t* list_heap = _memory_heaps[list_idx]; + if (list_heap == heap) { + _memory_heaps[list_idx] = heap->next_heap; + } else { + while (list_heap->next_heap != heap) + list_heap = list_heap->next_heap; + list_heap->next_heap = heap->next_heap; + } + + _rpmalloc_heap_unmap(heap); +} + +//! Insert a single span into thread heap cache, releasing to global cache if overflow +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span) { + if (UNEXPECTED(heap->finalize != 0)) { + _rpmalloc_span_unmap(span); + _rpmalloc_heap_global_finalize(heap); + return; + } +#if ENABLE_THREAD_CACHE + size_t span_count = span->span_count; + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_to_cache); + if (span_count == 1) { + span_cache_t* span_cache = &heap->span_cache; + span_cache->span[span_cache->count++] = span; + if (span_cache->count == MAX_THREAD_SPAN_CACHE) { + const size_t remain_count = MAX_THREAD_SPAN_CACHE - THREAD_SPAN_CACHE_TRANSFER; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, THREAD_SPAN_CACHE_TRANSFER * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, THREAD_SPAN_CACHE_TRANSFER); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, THREAD_SPAN_CACHE_TRANSFER); +#else + for (size_t ispan = 0; ispan < THREAD_SPAN_CACHE_TRANSFER; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } else { + size_t cache_idx = span_count - 2; + span_large_cache_t* span_cache = heap->span_large_cache + cache_idx; + span_cache->span[span_cache->count++] = span; + const size_t cache_limit = (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + if (span_cache->count == cache_limit) { + const size_t transfer_limit = 2 + (cache_limit >> 2); + const size_t transfer_count = (THREAD_SPAN_LARGE_CACHE_TRANSFER <= transfer_limit ? THREAD_SPAN_LARGE_CACHE_TRANSFER : transfer_limit); + const size_t remain_count = cache_limit - transfer_count; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, transfer_count * span_count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, transfer_count); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, transfer_count); +#else + for (size_t ispan = 0; ispan < transfer_count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } +#else + (void)sizeof(heap); + _rpmalloc_span_unmap(span); +#endif +} + +//! Extract the given number of spans from the different cache levels +static span_t* +_rpmalloc_heap_thread_cache_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + if (span_count == 1) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + if (span_cache->count) { + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_cache); + return span_cache->span[--span_cache->count]; + } +#endif + return span; +} + +static span_t* +_rpmalloc_heap_thread_cache_deferred_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; + if (span_count == 1) { + _rpmalloc_heap_cache_adopt_deferred(heap, &span); + } else { + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + } + return span; +} + +static span_t* +_rpmalloc_heap_reserved_extract(heap_t* heap, size_t span_count) { + if (heap->spans_reserved >= span_count) + return _rpmalloc_span_map(heap, span_count); + return 0; +} + +//! Extract a span from the global cache +static span_t* +_rpmalloc_heap_global_cache_extract(heap_t* heap, size_t span_count) { +#if ENABLE_GLOBAL_CACHE +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + size_t wanted_count; + if (span_count == 1) { + span_cache = &heap->span_cache; + wanted_count = THREAD_SPAN_CACHE_TRANSFER; + } else { + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + wanted_count = THREAD_SPAN_LARGE_CACHE_TRANSFER; + } + span_cache->count = _rpmalloc_global_cache_extract_spans(span_cache->span, span_count, wanted_count); + if (span_cache->count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * span_cache->count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, span_cache->count); + return span_cache->span[--span_cache->count]; + } +#else + span_t* span = 0; + size_t count = _rpmalloc_global_cache_extract_spans(&span, span_count, 1); + if (count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, count); + return span; + } +#endif +#endif + (void)sizeof(heap); + (void)sizeof(span_count); + return 0; +} + +static void +_rpmalloc_inc_span_statistics(heap_t* heap, size_t span_count, uint32_t class_idx) { + (void)sizeof(heap); + (void)sizeof(span_count); + (void)sizeof(class_idx); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + uint32_t idx = (uint32_t)span_count - 1; + uint32_t current_count = (uint32_t)atomic_incr32(&heap->span_use[idx].current); + if (current_count > (uint32_t)atomic_load32(&heap->span_use[idx].high)) + atomic_store32(&heap->span_use[idx].high, (int32_t)current_count); + _rpmalloc_stat_add_peak(&heap->size_class_use[class_idx].spans_current, 1, heap->size_class_use[class_idx].spans_peak); +#endif +} + +//! Get a span from one of the cache levels (thread cache, reserved, global cache) or fallback to mapping more memory +static span_t* +_rpmalloc_heap_extract_new_span(heap_t* heap, heap_size_class_t* heap_size_class, size_t span_count, uint32_t class_idx) { + span_t* span; +#if ENABLE_THREAD_CACHE + if (heap_size_class && heap_size_class->cache) { + span = heap_size_class->cache; + heap_size_class->cache = (heap->span_cache.count ? heap->span_cache.span[--heap->span_cache.count] : 0); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } +#endif + (void)sizeof(class_idx); + // Allow 50% overhead to increase cache hits + size_t base_span_count = span_count; + size_t limit_span_count = (span_count > 2) ? (span_count + (span_count >> 1)) : span_count; + if (limit_span_count > LARGE_CLASS_COUNT) + limit_span_count = LARGE_CLASS_COUNT; + do { + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_thread_cache_deferred_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_reserved_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_reserved); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_global_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + ++span_count; + } while (span_count <= limit_span_count); + //Final fallback, map in more virtual memory + span = _rpmalloc_span_map(heap, base_span_count); + _rpmalloc_inc_span_statistics(heap, base_span_count, class_idx); + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_map_calls); + return span; +} + +static void +_rpmalloc_heap_initialize(heap_t* heap) { + _rpmalloc_memset_const(heap, 0, sizeof(heap_t)); + //Get a new heap ID + heap->id = 1 + atomic_incr32(&_memory_heap_id); + + //Link in heap in heap ID map + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap->next_heap = _memory_heaps[list_idx]; + _memory_heaps[list_idx] = heap; +} + +static void +_rpmalloc_heap_orphan(heap_t* heap, int first_class) { + heap->owner_thread = (uintptr_t)-1; +#if RPMALLOC_FIRST_CLASS_HEAPS + heap_t** heap_list = (first_class ? &_memory_first_class_orphan_heaps : &_memory_orphan_heaps); +#else + (void)sizeof(first_class); + heap_t** heap_list = &_memory_orphan_heaps; +#endif + heap->next_orphan = *heap_list; + *heap_list = heap; +} + +//! Allocate a new heap from newly mapped memory pages +static heap_t* +_rpmalloc_heap_allocate_new(void) { + // Map in pages for a 16 heaps. If page size is greater than required size for this, map a page and + // use first part for heaps and remaining part for spans for allocations. Adds a lot of complexity, + // but saves a lot of memory on systems where page size > 64 spans (4MiB) + size_t heap_size = sizeof(heap_t); + size_t aligned_heap_size = 16 * ((heap_size + 15) / 16); + size_t request_heap_count = 16; + size_t heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + size_t block_size = _memory_span_size * heap_span_count; + size_t span_count = heap_span_count; + span_t* span = 0; + // If there are global reserved spans, use these first + if (_memory_global_reserve_count >= heap_span_count) { + span = _rpmalloc_global_get_reserved_spans(heap_span_count); + } + if (!span) { + if (_memory_page_size > block_size) { + span_count = _memory_page_size / _memory_span_size; + block_size = _memory_page_size; + // If using huge pages, make sure to grab enough heaps to avoid reallocating a huge page just to serve new heaps + size_t possible_heap_count = (block_size - sizeof(span_t)) / aligned_heap_size; + if (possible_heap_count >= (request_heap_count * 16)) + request_heap_count *= 16; + else if (possible_heap_count < request_heap_count) + request_heap_count = possible_heap_count; + heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + } + + size_t align_offset = 0; + span = (span_t*)_rpmalloc_mmap(block_size, &align_offset); + if (!span) + return 0; + + // Master span will contain the heaps + _rpmalloc_stat_inc(&_master_spans); + _rpmalloc_span_initialize(span, span_count, heap_span_count, align_offset); + } + + size_t remain_size = _memory_span_size - sizeof(span_t); + heap_t* heap = (heap_t*)pointer_offset(span, sizeof(span_t)); + _rpmalloc_heap_initialize(heap); + + // Put extra heaps as orphans + size_t num_heaps = remain_size / aligned_heap_size; + if (num_heaps < request_heap_count) + num_heaps = request_heap_count; + atomic_store32(&heap->child_count, (int32_t)num_heaps - 1); + heap_t* extra_heap = (heap_t*)pointer_offset(heap, aligned_heap_size); + while (num_heaps > 1) { + _rpmalloc_heap_initialize(extra_heap); + extra_heap->master_heap = heap; + _rpmalloc_heap_orphan(extra_heap, 1); + extra_heap = (heap_t*)pointer_offset(extra_heap, aligned_heap_size); + --num_heaps; + } + + if (span_count > heap_span_count) { + // Cap reserved spans + size_t remain_count = span_count - heap_span_count; + size_t reserve_count = (remain_count > _memory_heap_reserve_count ? _memory_heap_reserve_count : remain_count); + span_t* remain_span = (span_t*)pointer_offset(span, heap_span_count * _memory_span_size); + _rpmalloc_heap_set_reserved_spans(heap, span, remain_span, reserve_count); + + if (remain_count > reserve_count) { + // Set to global reserved spans + remain_span = (span_t*)pointer_offset(remain_span, reserve_count * _memory_span_size); + reserve_count = remain_count - reserve_count; + _rpmalloc_global_set_reserved_spans(span, remain_span, reserve_count); + } + } + + return heap; +} + +static heap_t* +_rpmalloc_heap_extract_orphan(heap_t** heap_list) { + heap_t* heap = *heap_list; + *heap_list = (heap ? heap->next_orphan : 0); + return heap; +} + +//! Allocate a new heap, potentially reusing a previously orphaned heap +static heap_t* +_rpmalloc_heap_allocate(int first_class) { + heap_t* heap = 0; + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (first_class == 0) + heap = _rpmalloc_heap_extract_orphan(&_memory_orphan_heaps); +#if RPMALLOC_FIRST_CLASS_HEAPS + if (!heap) + heap = _rpmalloc_heap_extract_orphan(&_memory_first_class_orphan_heaps); +#endif + if (!heap) + heap = _rpmalloc_heap_allocate_new(); + atomic_store32_release(&_memory_global_lock, 0); + if (heap) + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + return heap; +} + +static void +_rpmalloc_heap_release(void* heapptr, int first_class, int release_cache) { + heap_t* heap = (heap_t*)heapptr; + if (!heap) + return; + //Release thread cache spans back to global cache + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + if (release_cache || heap->finalize) { +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + if (heap->finalize) { + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + } else { + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); + } +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + } + + if (get_thread_heap_raw() == heap) + set_thread_heap(0); + +#if ENABLE_STATISTICS + atomic_decr32(&_memory_active_heaps); + rpmalloc_assert(atomic_load32(&_memory_active_heaps) >= 0, "Still active heaps during finalization"); +#endif + + // If we are forcibly terminating with _exit the state of the + // lock atomic is unknown and it's best to just go ahead and exit + if (get_thread_id() != _rpmalloc_main_thread_id) { + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + } + _rpmalloc_heap_orphan(heap, first_class); + atomic_store32_release(&_memory_global_lock, 0); +} + +static void +_rpmalloc_heap_release_raw(void* heapptr, int release_cache) { + _rpmalloc_heap_release(heapptr, 0, release_cache); +} + +static void +_rpmalloc_heap_release_raw_fc(void* heapptr) { + _rpmalloc_heap_release_raw(heapptr, 1); +} + +static void +_rpmalloc_heap_finalize(heap_t* heap) { + if (heap->spans_reserved) { + span_t* span = _rpmalloc_span_map(heap, heap->spans_reserved); + _rpmalloc_span_unmap(span); + heap->spans_reserved = 0; + } + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].cache) + _rpmalloc_span_unmap(heap->size_class[iclass].cache); + heap->size_class[iclass].cache = 0; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + span_t* next = span->next; + _rpmalloc_span_finalize(heap, iclass, span, &heap->size_class[iclass].partial_span); + span = next; + } + // If class still has a free list it must be a full span + if (heap->size_class[iclass].free_list) { + span_t* class_span = (span_t*)((uintptr_t)heap->size_class[iclass].free_list & _memory_span_mask); + span_t** list = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + list = &heap->full_span[iclass]; +#endif + --heap->full_span_count; + if (!_rpmalloc_span_finalize(heap, iclass, class_span, list)) { + if (list) + _rpmalloc_span_double_link_list_remove(list, class_span); + _rpmalloc_span_double_link_list_add(&heap->size_class[iclass].partial_span, class_span); + } + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + rpmalloc_assert(!atomic_load_ptr(&heap->span_free_deferred), "Heaps still active during finalization"); +} + + +//////////// +/// +/// Allocation entry points +/// +////// + +//! Pop first block from a free list +static void* +free_list_pop(void** list) { + void* block = *list; + *list = *((void**)block); + return block; +} + +//! Allocate a small/medium sized memory block from the given heap +static void* +_rpmalloc_allocate_from_heap_fallback(heap_t* heap, heap_size_class_t* heap_size_class, uint32_t class_idx) { + span_t* span = heap_size_class->partial_span; + rpmalloc_assume(heap != 0); + if (EXPECTED(span != 0)) { + rpmalloc_assert(span->block_count == _memory_size_class[span->size_class].block_count, "Span block count corrupted"); + rpmalloc_assert(!_rpmalloc_span_is_fully_utilized(span), "Internal failure"); + void* block; + if (span->free_list) { + //Span local free list is not empty, swap to size class free list + block = free_list_pop(&span->free_list); + heap_size_class->free_list = span->free_list; + span->free_list = 0; + } else { + //If the span did not fully initialize free list, link up another page worth of blocks + void* block_start = pointer_offset(span, SPAN_HEADER_SIZE + ((size_t)span->free_list_limit * span->block_size)); + span->free_list_limit += free_list_partial_init(&heap_size_class->free_list, &block, + (void*)((uintptr_t)block_start & ~(_memory_page_size - 1)), block_start, + span->block_count - span->free_list_limit, span->block_size); + } + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span block count corrupted"); + span->used_count = span->free_list_limit; + + //Swap in deferred free list if present + if (atomic_load_ptr(&span->free_list_deferred)) + _rpmalloc_span_extract_free_list_deferred(span); + + //If span is still not fully utilized keep it in partial list and early return block + if (!_rpmalloc_span_is_fully_utilized(span)) + return block; + + //The span is fully utilized, unlink from partial list and add to fully utilized list + _rpmalloc_span_double_link_list_pop_head(&heap_size_class->partial_span, span); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + return block; + } + + //Find a span in one of the cache levels + span = _rpmalloc_heap_extract_new_span(heap, heap_size_class, 1, class_idx); + if (EXPECTED(span != 0)) { + //Mark span as owned by this heap and set base data, return first block + return _rpmalloc_span_initialize_new(heap, heap_size_class, span, class_idx); + } + + return 0; +} + +//! Allocate a small sized memory block from the given heap +static void* +_rpmalloc_allocate_small(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Small sizes have unique size classes + const uint32_t class_idx = (uint32_t)((size + (SMALL_GRANULARITY - 1)) >> SMALL_GRANULARITY_SHIFT); + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a medium sized memory block from the given heap +static void* +_rpmalloc_allocate_medium(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate the size class index and do a dependent lookup of the final class index (in case of merged classes) + const uint32_t base_idx = (uint32_t)(SMALL_CLASS_COUNT + ((size - (SMALL_SIZE_LIMIT + 1)) >> MEDIUM_GRANULARITY_SHIFT)); + const uint32_t class_idx = _memory_size_class[base_idx].class_idx; + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a large sized memory block from the given heap +static void* +_rpmalloc_allocate_large(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate number of needed max sized spans (including header) + //Since this function is never called if size > LARGE_SIZE_LIMIT + //the span_count is guaranteed to be <= LARGE_CLASS_COUNT + size += SPAN_HEADER_SIZE; + size_t span_count = size >> _memory_span_size_shift; + if (size & (_memory_span_size - 1)) + ++span_count; + + //Find a span in one of the cache levels + span_t* span = _rpmalloc_heap_extract_new_span(heap, 0, span_count, SIZE_CLASS_LARGE); + if (!span) + return span; + + //Mark span as owned by this heap and set base data + rpmalloc_assert(span->span_count >= span_count, "Internal failure"); + span->size_class = SIZE_CLASS_LARGE; + span->heap = heap; + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a huge block by mapping memory pages directly +static void* +_rpmalloc_allocate_huge(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + size += SPAN_HEADER_SIZE; + size_t num_pages = size >> _memory_page_size_shift; + if (size & (_memory_page_size - 1)) + ++num_pages; + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(num_pages * _memory_page_size, &align_offset); + if (!span) + return span; + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a block of the given size +static void* +_rpmalloc_allocate(heap_t* heap, size_t size) { + _rpmalloc_stat_add64(&_allocation_counter, 1); + if (EXPECTED(size <= SMALL_SIZE_LIMIT)) + return _rpmalloc_allocate_small(heap, size); + else if (size <= _memory_medium_size_limit) + return _rpmalloc_allocate_medium(heap, size); + else if (size <= LARGE_SIZE_LIMIT) + return _rpmalloc_allocate_large(heap, size); + return _rpmalloc_allocate_huge(heap, size); +} + +static void* +_rpmalloc_aligned_allocate(heap_t* heap, size_t alignment, size_t size) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_allocate(heap, size); + +#if ENABLE_VALIDATE_ARGS + if ((size + alignment) < size) { + errno = EINVAL; + return 0; + } + if (alignment & (alignment - 1)) { + errno = EINVAL; + return 0; + } +#endif + + if ((alignment <= SPAN_HEADER_SIZE) && ((size + SPAN_HEADER_SIZE) < _memory_medium_size_limit)) { + // If alignment is less or equal to span header size (which is power of two), + // and size aligned to span header size multiples is less than size + alignment, + // then use natural alignment of blocks to provide alignment + size_t multiple_size = size ? (size + (SPAN_HEADER_SIZE - 1)) & ~(uintptr_t)(SPAN_HEADER_SIZE - 1) : SPAN_HEADER_SIZE; + rpmalloc_assert(!(multiple_size % SPAN_HEADER_SIZE), "Failed alignment calculation"); + if (multiple_size <= (size + alignment)) + return _rpmalloc_allocate(heap, multiple_size); + } + + void* ptr = 0; + size_t align_mask = alignment - 1; + if (alignment <= _memory_page_size) { + ptr = _rpmalloc_allocate(heap, size + alignment); + if ((uintptr_t)ptr & align_mask) { + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + //Mark as having aligned blocks + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + span->flags |= SPAN_FLAG_ALIGNED_BLOCKS; + } + return ptr; + } + + // Fallback to mapping new pages for this request. Since pointers passed + // to rpfree must be able to reach the start of the span by bitmasking of + // the address with the span size, the returned aligned pointer from this + // function must be with a span size of the start of the mapped area. + // In worst case this requires us to loop and map pages until we get a + // suitable memory address. It also means we can never align to span size + // or greater, since the span header will push alignment more than one + // span size away from span start (thus causing pointer mask to give us + // an invalid span start on free) + if (alignment & align_mask) { + errno = EINVAL; + return 0; + } + if (alignment >= _memory_span_size) { + errno = EINVAL; + return 0; + } + + size_t extra_pages = alignment / _memory_page_size; + + // Since each span has a header, we will at least need one extra memory page + size_t num_pages = 1 + (size / _memory_page_size); + if (size & (_memory_page_size - 1)) + ++num_pages; + + if (extra_pages > num_pages) + num_pages = 1 + extra_pages; + + size_t original_pages = num_pages; + size_t limit_pages = (_memory_span_size / _memory_page_size) * 2; + if (limit_pages < (original_pages * 2)) + limit_pages = original_pages * 2; + + size_t mapped_size, align_offset; + span_t* span; + +retry: + align_offset = 0; + mapped_size = num_pages * _memory_page_size; + + span = (span_t*)_rpmalloc_mmap(mapped_size, &align_offset); + if (!span) { + errno = ENOMEM; + return 0; + } + ptr = pointer_offset(span, SPAN_HEADER_SIZE); + + if ((uintptr_t)ptr & align_mask) + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + + if (((size_t)pointer_diff(ptr, span) >= _memory_span_size) || + (pointer_offset(ptr, size) > pointer_offset(span, mapped_size)) || + (((uintptr_t)ptr & _memory_span_mask) != (uintptr_t)span)) { + _rpmalloc_unmap(span, mapped_size, align_offset, mapped_size); + ++num_pages; + if (num_pages > limit_pages) { + errno = EINVAL; + return 0; + } + goto retry; + } + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + _rpmalloc_stat_add64(&_allocation_counter, 1); + + return ptr; +} + + +//////////// +/// +/// Deallocation entry points +/// +////// + +//! Deallocate the given small/medium memory block in the current thread local heap +static void +_rpmalloc_deallocate_direct_small_or_medium(span_t* span, void* block) { + heap_t* heap = span->heap; + rpmalloc_assert(heap->owner_thread == get_thread_id() || !heap->owner_thread || heap->finalize, "Internal failure"); + //Add block to free list + if (UNEXPECTED(_rpmalloc_span_is_fully_utilized(span))) { + span->used_count = span->block_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_span_double_link_list_add(&heap->size_class[span->size_class].partial_span, span); + --heap->full_span_count; + } + *((void**)block) = span->free_list; + --span->used_count; + span->free_list = block; + if (UNEXPECTED(span->used_count == span->list_size)) { + // If there are no used blocks it is guaranteed that no other external thread is accessing the span + if (span->used_count) { + // Make sure we have synchronized the deferred list and list size by using acquire semantics + // and guarantee that no external thread is accessing span concurrently + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + atomic_store_ptr_release(&span->free_list_deferred, free_list); + } + _rpmalloc_span_double_link_list_remove(&heap->size_class[span->size_class].partial_span, span); + _rpmalloc_span_release_to_cache(heap, span); + } +} + +static void +_rpmalloc_deallocate_defer_free_span(heap_t* heap, span_t* span) { + if (span->size_class != SIZE_CLASS_HUGE) + _rpmalloc_stat_inc(&heap->span_use[span->span_count - 1].spans_deferred); + //This list does not need ABA protection, no mutable side state + do { + span->free_list = (void*)atomic_load_ptr(&heap->span_free_deferred); + } while (!atomic_cas_ptr(&heap->span_free_deferred, span, span->free_list)); +} + +//! Put the block in the deferred free list of the owning span +static void +_rpmalloc_deallocate_defer_small_or_medium(span_t* span, void* block) { + // The memory ordering here is a bit tricky, to avoid having to ABA protect + // the deferred free list to avoid desynchronization of list and list size + // we need to have acquire semantics on successful CAS of the pointer to + // guarantee the list_size variable validity + release semantics on pointer store + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + *((void**)block) = free_list; + uint32_t free_count = ++span->list_size; + int all_deferred_free = (free_count == span->block_count); + atomic_store_ptr_release(&span->free_list_deferred, block); + if (all_deferred_free) { + // Span was completely freed by this block. Due to the INVALID_POINTER spin lock + // no other thread can reach this state simultaneously on this span. + // Safe to move to owner heap deferred cache + _rpmalloc_deallocate_defer_free_span(span->heap, span); + } +} + +static void +_rpmalloc_deallocate_small_or_medium(span_t* span, void* p) { + _rpmalloc_stat_inc_free(span->heap, span->size_class); + if (span->flags & SPAN_FLAG_ALIGNED_BLOCKS) { + //Realign pointer to block start + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + p = pointer_offset(p, -(int32_t)(block_offset % span->block_size)); + } + //Check if block belongs to this heap or if deallocation should be deferred +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (!defer) + _rpmalloc_deallocate_direct_small_or_medium(span, p); + else + _rpmalloc_deallocate_defer_small_or_medium(span, p); +} + +//! Deallocate the given large memory block to the current heap +static void +_rpmalloc_deallocate_large(span_t* span) { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Bad span size class"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + //We must always defer (unless finalizing) if from another heap since we cannot touch the list or counters of another heap +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //Decrease counter + size_t idx = span->span_count - 1; + atomic_decr32(&span->heap->span_use[idx].current); +#endif + heap_t* heap = span->heap; + rpmalloc_assert(heap, "No thread heap"); +#if ENABLE_THREAD_CACHE + const int set_as_reserved = ((span->span_count > 1) && (heap->span_cache.count == 0) && !heap->finalize && !heap->spans_reserved); +#else + const int set_as_reserved = ((span->span_count > 1) && !heap->finalize && !heap->spans_reserved); +#endif + if (set_as_reserved) { + heap->span_reserve = span; + heap->spans_reserved = span->span_count; + if (span->flags & SPAN_FLAG_MASTER) { + heap->span_reserve_master = span; + } else { //SPAN_FLAG_SUBSPAN + span_t* master = (span_t*)pointer_offset(span, -(intptr_t)((size_t)span->offset_from_master * _memory_span_size)); + heap->span_reserve_master = master; + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + rpmalloc_assert(atomic_load32(&master->remaining_spans) >= (int32_t)span->span_count, "Master span count corrupted"); + } + _rpmalloc_stat_inc(&heap->span_use[idx].spans_to_reserved); + } else { + //Insert into cache list + _rpmalloc_heap_cache_insert(heap, span); + } +} + +//! Deallocate the given huge span +static void +_rpmalloc_deallocate_huge(span_t* span) { + rpmalloc_assert(span->heap, "No span heap"); +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif + + //Oversized allocation, page count is stored in span_count + size_t num_pages = span->span_count; + _rpmalloc_unmap(span, num_pages * _memory_page_size, span->align_offset, num_pages * _memory_page_size); + _rpmalloc_stat_sub(&_huge_pages_current, num_pages); +} + +//! Deallocate the given block +static void +_rpmalloc_deallocate(void* p) { + _rpmalloc_stat_add64(&_deallocation_counter, 1); + //Grab the span (always at start of span, using span alignment) + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (UNEXPECTED(!span)) + return; + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) + _rpmalloc_deallocate_small_or_medium(span, p); + else if (span->size_class == SIZE_CLASS_LARGE) + _rpmalloc_deallocate_large(span); + else + _rpmalloc_deallocate_huge(span); +} + +//////////// +/// +/// Reallocation entry points +/// +////// + +static size_t +_rpmalloc_usable_size(void* p); + +//! Reallocate the given block to the given size +static void* +_rpmalloc_reallocate(heap_t* heap, void* p, size_t size, size_t oldsize, unsigned int flags) { + if (p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + //Small/medium sized block + rpmalloc_assert(span->span_count == 1, "Span counter corrupted"); + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + uint32_t block_idx = block_offset / span->block_size; + void* block = pointer_offset(blocks_start, (size_t)block_idx * span->block_size); + if (!oldsize) + oldsize = (size_t)((ptrdiff_t)span->block_size - pointer_diff(p, block)); + if ((size_t)span->block_size >= size) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_spans = total_size >> _memory_span_size_shift; + if (total_size & (_memory_span_mask - 1)) + ++num_spans; + size_t current_spans = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_spans * _memory_span_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_spans >= num_spans) && (total_size >= (oldsize / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else { + //Oversized block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_pages = total_size >> _memory_page_size_shift; + if (total_size & (_memory_page_size - 1)) + ++num_pages; + //Page count is stored in span_count + size_t current_pages = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_pages * _memory_page_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_pages >= num_pages) && (num_pages >= (current_pages / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } + } else { + oldsize = 0; + } + + if (!!(flags & RPMALLOC_GROW_OR_FAIL)) + return 0; + + //Size is greater than block size, need to allocate a new block and deallocate the old + //Avoid hysteresis by overallocating if increase is small (below 37%) + size_t lower_bound = oldsize + (oldsize >> 2) + (oldsize >> 3); + size_t new_size = (size > lower_bound) ? size : ((size > oldsize) ? lower_bound : size); + void* block = _rpmalloc_allocate(heap, new_size); + if (p && block) { + if (!(flags & RPMALLOC_NO_PRESERVE)) + memcpy(block, p, oldsize < new_size ? oldsize : new_size); + _rpmalloc_deallocate(p); + } + + return block; +} + +static void* +_rpmalloc_aligned_reallocate(heap_t* heap, void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_reallocate(heap, ptr, size, oldsize, flags); + + int no_alloc = !!(flags & RPMALLOC_GROW_OR_FAIL); + size_t usablesize = (ptr ? _rpmalloc_usable_size(ptr) : 0); + if ((usablesize >= size) && !((uintptr_t)ptr & (alignment - 1))) { + if (no_alloc || (size >= (usablesize / 2))) + return ptr; + } + // Aligned alloc marks span as having aligned blocks + void* block = (!no_alloc ? _rpmalloc_aligned_allocate(heap, alignment, size) : 0); + if (EXPECTED(block != 0)) { + if (!(flags & RPMALLOC_NO_PRESERVE) && ptr) { + if (!oldsize) + oldsize = usablesize; + memcpy(block, ptr, oldsize < size ? oldsize : size); + } + _rpmalloc_deallocate(ptr); + } + return block; +} + + +//////////// +/// +/// Initialization, finalization and utility +/// +////// + +//! Get the usable size of the given block +static size_t +_rpmalloc_usable_size(void* p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (span->size_class < SIZE_CLASS_COUNT) { + //Small/medium block + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + return span->block_size - ((size_t)pointer_diff(p, blocks_start) % span->block_size); + } + if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t current_spans = span->span_count; + return (current_spans * _memory_span_size) - (size_t)pointer_diff(p, span); + } + //Oversized block, page count is stored in span_count + size_t current_pages = span->span_count; + return (current_pages * _memory_page_size) - (size_t)pointer_diff(p, span); +} + +//! Adjust and optimize the size class properties for the given class +static void +_rpmalloc_adjust_size_class(size_t iclass) { + size_t block_size = _memory_size_class[iclass].block_size; + size_t block_count = (_memory_span_size - SPAN_HEADER_SIZE) / block_size; + + _memory_size_class[iclass].block_count = (uint16_t)block_count; + _memory_size_class[iclass].class_idx = (uint16_t)iclass; + + //Check if previous size classes can be merged + if (iclass >= SMALL_CLASS_COUNT) { + size_t prevclass = iclass; + while (prevclass > 0) { + --prevclass; + //A class can be merged if number of pages and number of blocks are equal + if (_memory_size_class[prevclass].block_count == _memory_size_class[iclass].block_count) + _rpmalloc_memcpy_const(_memory_size_class + prevclass, _memory_size_class + iclass, sizeof(_memory_size_class[iclass])); + else + break; + } + } +} + +//! Initialize the allocator and setup global data +extern inline int +rpmalloc_initialize(void) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + return rpmalloc_initialize_config(0); +} + +int +rpmalloc_initialize_config(const rpmalloc_config_t* config) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + _rpmalloc_initialized = 1; + + if (config) + memcpy(&_memory_config, config, sizeof(rpmalloc_config_t)); + else + _rpmalloc_memset_const(&_memory_config, 0, sizeof(rpmalloc_config_t)); + + if (!_memory_config.memory_map || !_memory_config.memory_unmap) { + _memory_config.memory_map = _rpmalloc_mmap_os; + _memory_config.memory_unmap = _rpmalloc_unmap_os; + } + +#if PLATFORM_WINDOWS + SYSTEM_INFO system_info; + memset(&system_info, 0, sizeof(system_info)); + GetSystemInfo(&system_info); + _memory_map_granularity = system_info.dwAllocationGranularity; +#else + _memory_map_granularity = (size_t)sysconf(_SC_PAGESIZE); +#endif + +#if RPMALLOC_CONFIGURABLE + _memory_page_size = _memory_config.page_size; +#else + _memory_page_size = 0; +#endif + _memory_huge_pages = 0; + if (!_memory_page_size) { +#if PLATFORM_WINDOWS + _memory_page_size = system_info.dwPageSize; +#else + _memory_page_size = _memory_map_granularity; + if (_memory_config.enable_huge_pages) { +#if defined(__linux__) + size_t huge_page_size = 0; + FILE* meminfo = fopen("/proc/meminfo", "r"); + if (meminfo) { + char line[128]; + while (!huge_page_size && fgets(line, sizeof(line) - 1, meminfo)) { + line[sizeof(line) - 1] = 0; + if (strstr(line, "Hugepagesize:")) + huge_page_size = (size_t)strtol(line + 13, 0, 10) * 1024; + } + fclose(meminfo); + } + if (huge_page_size) { + _memory_huge_pages = 1; + _memory_page_size = huge_page_size; + _memory_map_granularity = huge_page_size; + } +#elif defined(__FreeBSD__) + int rc; + size_t sz = sizeof(rc); + + if (sysctlbyname("vm.pmap.pg_ps_enabled", &rc, &sz, NULL, 0) == 0 && rc == 1) { + static size_t defsize = 2 * 1024 * 1024; + int nsize = 0; + size_t sizes[4] = {0}; + _memory_huge_pages = 1; + _memory_page_size = defsize; + if ((nsize = getpagesizes(sizes, 4)) >= 2) { + nsize --; + for (size_t csize = sizes[nsize]; nsize >= 0 && csize; --nsize, csize = sizes[nsize]) { + //! Unlikely, but as a precaution.. + rpmalloc_assert(!(csize & (csize -1)) && !(csize % 1024), "Invalid page size"); + if (defsize < csize) { + _memory_page_size = csize; + break; + } + } + } + _memory_map_granularity = _memory_page_size; + } +#elif defined(__APPLE__) || defined(__NetBSD__) + _memory_huge_pages = 1; + _memory_page_size = 2 * 1024 * 1024; + _memory_map_granularity = _memory_page_size; +#endif + } +#endif + } else { + if (_memory_config.enable_huge_pages) + _memory_huge_pages = 1; + } + +#if PLATFORM_WINDOWS + if (_memory_config.enable_huge_pages) { + HANDLE token = 0; + size_t large_page_minimum = GetLargePageMinimum(); + if (large_page_minimum) + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (token) { + LUID luid; + if (LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) { + TOKEN_PRIVILEGES token_privileges; + memset(&token_privileges, 0, sizeof(token_privileges)); + token_privileges.PrivilegeCount = 1; + token_privileges.Privileges[0].Luid = luid; + token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(token, FALSE, &token_privileges, 0, 0, 0)) { + if (GetLastError() == ERROR_SUCCESS) + _memory_huge_pages = 1; + } + } + CloseHandle(token); + } + if (_memory_huge_pages) { + if (large_page_minimum > _memory_page_size) + _memory_page_size = large_page_minimum; + if (large_page_minimum > _memory_map_granularity) + _memory_map_granularity = large_page_minimum; + } + } +#endif + + size_t min_span_size = 256; + size_t max_page_size; +#if UINTPTR_MAX > 0xFFFFFFFF + max_page_size = 4096ULL * 1024ULL * 1024ULL; +#else + max_page_size = 4 * 1024 * 1024; +#endif + if (_memory_page_size < min_span_size) + _memory_page_size = min_span_size; + if (_memory_page_size > max_page_size) + _memory_page_size = max_page_size; + _memory_page_size_shift = 0; + size_t page_size_bit = _memory_page_size; + while (page_size_bit != 1) { + ++_memory_page_size_shift; + page_size_bit >>= 1; + } + _memory_page_size = ((size_t)1 << _memory_page_size_shift); + +#if RPMALLOC_CONFIGURABLE + if (!_memory_config.span_size) { + _memory_span_size = _memory_default_span_size; + _memory_span_size_shift = _memory_default_span_size_shift; + _memory_span_mask = _memory_default_span_mask; + } else { + size_t span_size = _memory_config.span_size; + if (span_size > (256 * 1024)) + span_size = (256 * 1024); + _memory_span_size = 4096; + _memory_span_size_shift = 12; + while (_memory_span_size < span_size) { + _memory_span_size <<= 1; + ++_memory_span_size_shift; + } + _memory_span_mask = ~(uintptr_t)(_memory_span_size - 1); + } +#endif + + _memory_span_map_count = ( _memory_config.span_map_count ? _memory_config.span_map_count : DEFAULT_SPAN_MAP_COUNT); + if ((_memory_span_size * _memory_span_map_count) < _memory_page_size) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + if ((_memory_page_size >= _memory_span_size) && ((_memory_span_map_count * _memory_span_size) % _memory_page_size)) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + _memory_heap_reserve_count = (_memory_span_map_count > DEFAULT_SPAN_MAP_COUNT) ? DEFAULT_SPAN_MAP_COUNT : _memory_span_map_count; + + _memory_config.page_size = _memory_page_size; + _memory_config.span_size = _memory_span_size; + _memory_config.span_map_count = _memory_span_map_count; + _memory_config.enable_huge_pages = _memory_huge_pages; + +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + if (pthread_key_create(&_memory_thread_heap, _rpmalloc_heap_release_raw_fc)) + return -1; +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + fls_key = FlsAlloc(&_rpmalloc_thread_destructor); +#endif + + //Setup all small and medium size classes + size_t iclass = 0; + _memory_size_class[iclass].block_size = SMALL_GRANULARITY; + _rpmalloc_adjust_size_class(iclass); + for (iclass = 1; iclass < SMALL_CLASS_COUNT; ++iclass) { + size_t size = iclass * SMALL_GRANULARITY; + _memory_size_class[iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(iclass); + } + //At least two blocks per span, then fall back to large allocations + _memory_medium_size_limit = (_memory_span_size - SPAN_HEADER_SIZE) >> 1; + if (_memory_medium_size_limit > MEDIUM_SIZE_LIMIT) + _memory_medium_size_limit = MEDIUM_SIZE_LIMIT; + for (iclass = 0; iclass < MEDIUM_CLASS_COUNT; ++iclass) { + size_t size = SMALL_SIZE_LIMIT + ((iclass + 1) * MEDIUM_GRANULARITY); + if (size > _memory_medium_size_limit) { + _memory_medium_size_limit = SMALL_SIZE_LIMIT + (iclass * MEDIUM_GRANULARITY); + break; + } + _memory_size_class[SMALL_CLASS_COUNT + iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(SMALL_CLASS_COUNT + iclass); + } + + _memory_orphan_heaps = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + _memory_first_class_orphan_heaps = 0; +#endif +#if ENABLE_STATISTICS + atomic_store32(&_memory_active_heaps, 0); + atomic_store32(&_mapped_pages, 0); + _mapped_pages_peak = 0; + atomic_store32(&_master_spans, 0); + atomic_store32(&_mapped_total, 0); + atomic_store32(&_unmapped_total, 0); + atomic_store32(&_mapped_pages_os, 0); + atomic_store32(&_huge_pages_current, 0); + _huge_pages_peak = 0; +#endif + memset(_memory_heaps, 0, sizeof(_memory_heaps)); + atomic_store32_release(&_memory_global_lock, 0); + + rpmalloc_linker_reference(); + + //Initialize this thread + rpmalloc_thread_initialize(); + return 0; +} + +//! Finalize the allocator +void +rpmalloc_finalize(void) { + rpmalloc_thread_finalize(1); + //rpmalloc_dump_statistics(stdout); + + if (_memory_global_reserve) { + atomic_add32(&_memory_global_reserve_master->remaining_spans, -(int32_t)_memory_global_reserve_count); + _memory_global_reserve_master = 0; + _memory_global_reserve_count = 0; + _memory_global_reserve = 0; + } + atomic_store32_release(&_memory_global_lock, 0); + + //Free all thread caches and fully free spans + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + heap_t* next_heap = heap->next_heap; + heap->finalize = 1; + _rpmalloc_heap_global_finalize(heap); + heap = next_heap; + } + } + +#if ENABLE_GLOBAL_CACHE + //Free global caches + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) + _rpmalloc_global_cache_finalize(&_memory_span_cache[iclass]); +#endif + +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + pthread_key_delete(_memory_thread_heap); +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsFree(fls_key); + fls_key = 0; +#endif +#if ENABLE_STATISTICS + //If you hit these asserts you probably have memory leaks (perhaps global scope data doing dynamic allocations) or double frees in your code + rpmalloc_assert(atomic_load32(&_mapped_pages) == 0, "Memory leak detected"); + rpmalloc_assert(atomic_load32(&_mapped_pages_os) == 0, "Memory leak detected"); +#endif + + _rpmalloc_initialized = 0; +} + +//! Initialize thread, assign heap +extern inline void +rpmalloc_thread_initialize(void) { + if (!get_thread_heap_raw()) { + heap_t* heap = _rpmalloc_heap_allocate(0); + if (heap) { + _rpmalloc_stat_inc(&_memory_active_heaps); + set_thread_heap(heap); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, heap); +#endif + } + } +} + +//! Finalize thread, orphan heap +void +rpmalloc_thread_finalize(int release_caches) { + heap_t* heap = get_thread_heap_raw(); + if (heap) + _rpmalloc_heap_release_raw(heap, release_caches); + set_thread_heap(0); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, 0); +#endif +} + +int +rpmalloc_is_thread_initialized(void) { + return (get_thread_heap_raw() != 0) ? 1 : 0; +} + +const rpmalloc_config_t* +rpmalloc_config(void) { + return &_memory_config; +} + +// Extern interface + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_allocate(heap, size); +} + +extern inline void +rpfree(void* ptr) { + _rpmalloc_deallocate(ptr); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + heap_t* heap = get_thread_heap(); + void* block = _rpmalloc_allocate(heap, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_reallocate(heap, ptr, size, 0, 0); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, oldsize, flags); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) { + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = rpaligned_alloc(alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) { + return rpaligned_alloc(alignment, size); +} + +extern inline int +rpposix_memalign(void **memptr, size_t alignment, size_t size) { + if (memptr) + *memptr = rpaligned_alloc(alignment, size); + else + return EINVAL; + return *memptr ? 0 : ENOMEM; +} + +extern inline size_t +rpmalloc_usable_size(void* ptr) { + return (ptr ? _rpmalloc_usable_size(ptr) : 0); +} + +extern inline void +rpmalloc_thread_collect(void) { +} + +void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_thread_statistics_t)); + heap_t* heap = get_thread_heap_raw(); + if (!heap) + return; + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + size_class_t* size_class = _memory_size_class + iclass; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + size_t free_count = span->list_size; + size_t block_count = size_class->block_count; + if (span->free_list_limit < block_count) + block_count = span->free_list_limit; + free_count += (block_count - span->used_count); + stats->sizecache += free_count * size_class->block_size; + span = span->next; + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + stats->spancache += span_cache->count * (iclass + 1) * _memory_span_size; + } +#endif + + span_t* deferred = (span_t*)atomic_load_ptr(&heap->span_free_deferred); + while (deferred) { + if (deferred->size_class != SIZE_CLASS_HUGE) + stats->spancache += (size_t)deferred->span_count * _memory_span_size; + deferred = (span_t*)deferred->free_list; + } + +#if ENABLE_STATISTICS + stats->thread_to_global = (size_t)atomic_load64(&heap->thread_to_global); + stats->global_to_thread = (size_t)atomic_load64(&heap->global_to_thread); + + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + stats->span_use[iclass].current = (size_t)atomic_load32(&heap->span_use[iclass].current); + stats->span_use[iclass].peak = (size_t)atomic_load32(&heap->span_use[iclass].high); + stats->span_use[iclass].to_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_global); + stats->span_use[iclass].from_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_global); + stats->span_use[iclass].to_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache); + stats->span_use[iclass].from_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache); + stats->span_use[iclass].to_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved); + stats->span_use[iclass].from_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved); + stats->span_use[iclass].map_calls = (size_t)atomic_load32(&heap->span_use[iclass].spans_map_calls); + } + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + stats->size_use[iclass].alloc_current = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_current); + stats->size_use[iclass].alloc_peak = (size_t)heap->size_class_use[iclass].alloc_peak; + stats->size_use[iclass].alloc_total = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_total); + stats->size_use[iclass].free_total = (size_t)atomic_load32(&heap->size_class_use[iclass].free_total); + stats->size_use[iclass].spans_to_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache); + stats->size_use[iclass].spans_from_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache); + stats->size_use[iclass].spans_from_reserved = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved); + stats->size_use[iclass].map_calls = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_map_calls); + } +#endif +} + +void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_global_statistics_t)); +#if ENABLE_STATISTICS + stats->mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + stats->mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + stats->mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + stats->unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + stats->huge_alloc = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + stats->huge_alloc_peak = (size_t)_huge_pages_peak * _memory_page_size; +#endif +#if ENABLE_GLOBAL_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = &_memory_span_cache[iclass]; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + uint32_t count = cache->count; +#if ENABLE_UNLIMITED_CACHE + span_t* current_span = cache->overflow; + while (current_span) { + ++count; + current_span = current_span->next; + } +#endif + atomic_store32_release(&cache->lock, 0); + stats->cached += count * (iclass + 1) * _memory_span_size; + } +#endif +} + +#if ENABLE_STATISTICS + +static void +_memory_heap_dump_statistics(heap_t* heap, void* file) { + fprintf(file, "Heap %d stats:\n", heap->id); + fprintf(file, "Class CurAlloc PeakAlloc TotAlloc TotFree BlkSize BlkCount SpansCur SpansPeak PeakAllocMiB ToCacheMiB FromCacheMiB FromReserveMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) + continue; + fprintf(file, "%3u: %10u %10u %10u %10u %8u %8u %8d %9d %13zu %11zu %12zu %14zu %9u\n", (uint32_t)iclass, + atomic_load32(&heap->size_class_use[iclass].alloc_current), + heap->size_class_use[iclass].alloc_peak, + atomic_load32(&heap->size_class_use[iclass].alloc_total), + atomic_load32(&heap->size_class_use[iclass].free_total), + _memory_size_class[iclass].block_size, + _memory_size_class[iclass].block_count, + atomic_load32(&heap->size_class_use[iclass].spans_current), + heap->size_class_use[iclass].spans_peak, + ((size_t)heap->size_class_use[iclass].alloc_peak * (size_t)_memory_size_class[iclass].block_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved) * _memory_span_size) / (size_t)(1024 * 1024), + atomic_load32(&heap->size_class_use[iclass].spans_map_calls)); + } + fprintf(file, "Spans Current Peak Deferred PeakMiB Cached ToCacheMiB FromCacheMiB ToReserveMiB FromReserveMiB ToGlobalMiB FromGlobalMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + fprintf(file, "%4u: %8d %8u %8u %8zu %7u %11zu %12zu %12zu %14zu %11zu %13zu %10u\n", (uint32_t)(iclass + 1), + atomic_load32(&heap->span_use[iclass].current), + atomic_load32(&heap->span_use[iclass].high), + atomic_load32(&heap->span_use[iclass].spans_deferred), + ((size_t)atomic_load32(&heap->span_use[iclass].high) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), +#if ENABLE_THREAD_CACHE + (unsigned int)(!iclass ? heap->span_cache.count : heap->span_large_cache[iclass - 1].count), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), +#else + 0, (size_t)0, (size_t)0, +#endif + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + atomic_load32(&heap->span_use[iclass].spans_map_calls)); + } + fprintf(file, "Full spans: %zu\n", heap->full_span_count); + fprintf(file, "ThreadToGlobalMiB GlobalToThreadMiB\n"); + fprintf(file, "%17zu %17zu\n", (size_t)atomic_load64(&heap->thread_to_global) / (size_t)(1024 * 1024), (size_t)atomic_load64(&heap->global_to_thread) / (size_t)(1024 * 1024)); +} + +#endif + +void +rpmalloc_dump_statistics(void* file) { +#if ENABLE_STATISTICS + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + int need_dump = 0; + for (size_t iclass = 0; !need_dump && (iclass < SIZE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) { + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].free_total), "Heap statistics counter mismatch"); + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].spans_map_calls), "Heap statistics counter mismatch"); + continue; + } + need_dump = 1; + } + for (size_t iclass = 0; !need_dump && (iclass < LARGE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + need_dump = 1; + } + if (need_dump) + _memory_heap_dump_statistics(heap, file); + heap = heap->next_heap; + } + } + fprintf(file, "Global stats:\n"); + size_t huge_current = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + size_t huge_peak = (size_t)_huge_pages_peak * _memory_page_size; + fprintf(file, "HugeCurrentMiB HugePeakMiB\n"); + fprintf(file, "%14zu %11zu\n", huge_current / (size_t)(1024 * 1024), huge_peak / (size_t)(1024 * 1024)); + +#if ENABLE_GLOBAL_CACHE + fprintf(file, "GlobalCacheMiB\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = _memory_span_cache + iclass; + size_t global_cache = (size_t)cache->count * iclass * _memory_span_size; + + size_t global_overflow_cache = 0; + span_t* span = cache->overflow; + while (span) { + global_overflow_cache += iclass * _memory_span_size; + span = span->next; + } + if (global_cache || global_overflow_cache || cache->insert_count || cache->extract_count) + fprintf(file, "%4zu: %8zuMiB (%8zuMiB overflow) %14zu insert %14zu extract\n", iclass + 1, global_cache / (size_t)(1024 * 1024), global_overflow_cache / (size_t)(1024 * 1024), cache->insert_count, cache->extract_count); + } +#endif + + size_t mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + size_t mapped_os = (size_t)atomic_load32(&_mapped_pages_os) * _memory_page_size; + size_t mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + size_t mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + size_t unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + fprintf(file, "MappedMiB MappedOSMiB MappedPeakMiB MappedTotalMiB UnmappedTotalMiB\n"); + fprintf(file, "%9zu %11zu %13zu %14zu %16zu\n", + mapped / (size_t)(1024 * 1024), + mapped_os / (size_t)(1024 * 1024), + mapped_peak / (size_t)(1024 * 1024), + mapped_total / (size_t)(1024 * 1024), + unmapped_total / (size_t)(1024 * 1024)); + + fprintf(file, "\n"); +#if 0 + int64_t allocated = atomic_load64(&_allocation_counter); + int64_t deallocated = atomic_load64(&_deallocation_counter); + fprintf(file, "Allocation count: %lli\n", allocated); + fprintf(file, "Deallocation count: %lli\n", deallocated); + fprintf(file, "Current allocations: %lli\n", (allocated - deallocated)); + fprintf(file, "Master spans: %d\n", atomic_load32(&_master_spans)); + fprintf(file, "Dangling master spans: %d\n", atomic_load32(&_unmapped_master_spans)); +#endif +#endif + (void)sizeof(file); +} + +#if RPMALLOC_FIRST_CLASS_HEAPS + +extern inline rpmalloc_heap_t* +rpmalloc_heap_acquire(void) { + // Must be a pristine heap from newly mapped memory pages, or else memory blocks + // could already be allocated from the heap which would (wrongly) be released when + // heap is cleared with rpmalloc_heap_free_all(). Also heaps guaranteed to be + // pristine from the dedicated orphan list can be used. + heap_t* heap = _rpmalloc_heap_allocate(1); + rpmalloc_assume(heap != NULL); + heap->owner_thread = 0; + _rpmalloc_stat_inc(&_memory_active_heaps); + return heap; +} + +extern inline void +rpmalloc_heap_release(rpmalloc_heap_t* heap) { + if (heap) + _rpmalloc_heap_release(heap, 1, 1); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_allocate(heap, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) { + return rpmalloc_heap_aligned_calloc(heap, 0, num, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = _rpmalloc_aligned_allocate(heap, alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + return _rpmalloc_reallocate(heap, ptr, size, 0, flags); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, 0, flags); +} + +extern inline void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr) { + (void)sizeof(heap); + _rpmalloc_deallocate(ptr); +} + +extern inline void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap) { + span_t* span; + span_t* next_span; + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + span = heap->size_class[iclass].partial_span; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->size_class[iclass].partial_span = 0; + span = heap->full_span[iclass]; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + } + memset(heap->size_class, 0, sizeof(heap->size_class)); + memset(heap->full_span, 0, sizeof(heap->full_span)); + + span = heap->large_huge_span; + while (span) { + next_span = span->next; + if (UNEXPECTED(span->size_class == SIZE_CLASS_HUGE)) + _rpmalloc_deallocate_huge(span); + else + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->large_huge_span = 0; + heap->full_span_count = 0; + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + +#if ENABLE_STATISTICS + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->size_class_use[iclass].alloc_current, 0); + atomic_store32(&heap->size_class_use[iclass].spans_current, 0); + } + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->span_use[iclass].current, 0); + } +#endif +} + +extern inline void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap) { + heap_t* prev_heap = get_thread_heap_raw(); + if (prev_heap != heap) { + set_thread_heap(heap); + if (prev_heap) + rpmalloc_heap_release(prev_heap); + } +} + +extern inline rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr) +{ + //Grab the span, and then the heap from the span + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + if (span) + { + return span->heap; + } + return 0; +} + +#endif + +#if ENABLE_PRELOAD || ENABLE_OVERRIDE + +#include "malloc.c" + +#endif + +void +rpmalloc_linker_reference(void) { + (void)sizeof(_rpmalloc_initialized); +} +#line 0 +//{{FILE: 3rd_rpmalloci.c}} +#define SYS_MEM_INIT() rpmalloc_initialize() +#define SYS_MEM_REALLOC rprealloc +#define SYS_MEM_SIZE rpmalloc_usable_size +#endif + //#define SQLITE_OMIT_LOAD_EXTENSION //#define SQLITE_CORE 1 //#define SQLITE_DEBUG 1 @@ -334066,6 +338405,9244 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft //#undef rehash //#undef NB //#undef threadid + +// editor +#line 1 "3rd_icon_mdi.h" +// Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++ +// from https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/css/materialdesignicons.css +// for use with https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf +#pragma once + +#define FONT_ICON_FILE_NAME_MDI "materialdesignicons-webfont.ttf" + +#define ICON_MIN_MDI 0xF68C +#define ICON_MAX_16_MDI 0xF68C +#define ICON_MAX_MDI 0xF1CC7 +#define ICON_MDI_AB_TESTING "\xf3\xb0\x87\x89" // U+F01C9 +#define ICON_MDI_ABACUS "\xf3\xb1\x9b\xa0" // U+F16E0 +#define ICON_MDI_ABJAD_ARABIC "\xf3\xb1\x8c\xa8" // U+F1328 +#define ICON_MDI_ABJAD_HEBREW "\xf3\xb1\x8c\xa9" // U+F1329 +#define ICON_MDI_ABUGIDA_DEVANAGARI "\xf3\xb1\x8c\xaa" // U+F132A +#define ICON_MDI_ABUGIDA_THAI "\xf3\xb1\x8c\xab" // U+F132B +#define ICON_MDI_ACCESS_POINT "\xf3\xb0\x80\x83" // U+F0003 +#define ICON_MDI_ACCESS_POINT_CHECK "\xf3\xb1\x94\xb8" // U+F1538 +#define ICON_MDI_ACCESS_POINT_MINUS "\xf3\xb1\x94\xb9" // U+F1539 +#define ICON_MDI_ACCESS_POINT_NETWORK "\xf3\xb0\x80\x82" // U+F0002 +#define ICON_MDI_ACCESS_POINT_NETWORK_OFF "\xf3\xb0\xaf\xa1" // U+F0BE1 +#define ICON_MDI_ACCESS_POINT_OFF "\xf3\xb1\x94\x91" // U+F1511 +#define ICON_MDI_ACCESS_POINT_PLUS "\xf3\xb1\x94\xba" // U+F153A +#define ICON_MDI_ACCESS_POINT_REMOVE "\xf3\xb1\x94\xbb" // U+F153B +#define ICON_MDI_ACCOUNT "\xf3\xb0\x80\x84" // U+F0004 +#define ICON_MDI_ACCOUNT_ALERT "\xf3\xb0\x80\x85" // U+F0005 +#define ICON_MDI_ACCOUNT_ALERT_OUTLINE "\xf3\xb0\xad\x90" // U+F0B50 +#define ICON_MDI_ACCOUNT_ARROW_DOWN "\xf3\xb1\xa1\xa8" // U+F1868 +#define ICON_MDI_ACCOUNT_ARROW_DOWN_OUTLINE "\xf3\xb1\xa1\xa9" // U+F1869 +#define ICON_MDI_ACCOUNT_ARROW_LEFT "\xf3\xb0\xad\x91" // U+F0B51 +#define ICON_MDI_ACCOUNT_ARROW_LEFT_OUTLINE "\xf3\xb0\xad\x92" // U+F0B52 +#define ICON_MDI_ACCOUNT_ARROW_RIGHT "\xf3\xb0\xad\x93" // U+F0B53 +#define ICON_MDI_ACCOUNT_ARROW_RIGHT_OUTLINE "\xf3\xb0\xad\x94" // U+F0B54 +#define ICON_MDI_ACCOUNT_ARROW_UP "\xf3\xb1\xa1\xa7" // U+F1867 +#define ICON_MDI_ACCOUNT_ARROW_UP_OUTLINE "\xf3\xb1\xa1\xaa" // U+F186A +#define ICON_MDI_ACCOUNT_BADGE "\xf3\xb1\xac\x8a" // U+F1B0A +#define ICON_MDI_ACCOUNT_BADGE_OUTLINE "\xf3\xb1\xac\x8b" // U+F1B0B +#define ICON_MDI_ACCOUNT_BOX "\xf3\xb0\x80\x86" // U+F0006 +#define ICON_MDI_ACCOUNT_BOX_MULTIPLE "\xf3\xb0\xa4\xb4" // U+F0934 +#define ICON_MDI_ACCOUNT_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x80\x8a" // U+F100A +#define ICON_MDI_ACCOUNT_BOX_OUTLINE "\xf3\xb0\x80\x87" // U+F0007 +#define ICON_MDI_ACCOUNT_CANCEL "\xf3\xb1\x8b\x9f" // U+F12DF +#define ICON_MDI_ACCOUNT_CANCEL_OUTLINE "\xf3\xb1\x8b\xa0" // U+F12E0 +#define ICON_MDI_ACCOUNT_CARD "\xf3\xb1\xae\xa4" // U+F1BA4 +#define ICON_MDI_ACCOUNT_CARD_OUTLINE "\xf3\xb1\xae\xa5" // U+F1BA5 +#define ICON_MDI_ACCOUNT_CASH "\xf3\xb1\x82\x97" // U+F1097 +#define ICON_MDI_ACCOUNT_CASH_OUTLINE "\xf3\xb1\x82\x98" // U+F1098 +#define ICON_MDI_ACCOUNT_CHECK "\xf3\xb0\x80\x88" // U+F0008 +#define ICON_MDI_ACCOUNT_CHECK_OUTLINE "\xf3\xb0\xaf\xa2" // U+F0BE2 +#define ICON_MDI_ACCOUNT_CHILD "\xf3\xb0\xaa\x89" // U+F0A89 +#define ICON_MDI_ACCOUNT_CHILD_CIRCLE "\xf3\xb0\xaa\x8a" // U+F0A8A +#define ICON_MDI_ACCOUNT_CHILD_OUTLINE "\xf3\xb1\x83\x88" // U+F10C8 +#define ICON_MDI_ACCOUNT_CIRCLE "\xf3\xb0\x80\x89" // U+F0009 +#define ICON_MDI_ACCOUNT_CIRCLE_OUTLINE "\xf3\xb0\xad\x95" // U+F0B55 +#define ICON_MDI_ACCOUNT_CLOCK "\xf3\xb0\xad\x96" // U+F0B56 +#define ICON_MDI_ACCOUNT_CLOCK_OUTLINE "\xf3\xb0\xad\x97" // U+F0B57 +#define ICON_MDI_ACCOUNT_COG "\xf3\xb1\x8d\xb0" // U+F1370 +#define ICON_MDI_ACCOUNT_COG_OUTLINE "\xf3\xb1\x8d\xb1" // U+F1371 +#define ICON_MDI_ACCOUNT_CONVERT "\xf3\xb0\x80\x8a" // U+F000A +#define ICON_MDI_ACCOUNT_CONVERT_OUTLINE "\xf3\xb1\x8c\x81" // U+F1301 +#define ICON_MDI_ACCOUNT_COWBOY_HAT "\xf3\xb0\xba\x9b" // U+F0E9B +#define ICON_MDI_ACCOUNT_COWBOY_HAT_OUTLINE "\xf3\xb1\x9f\xb3" // U+F17F3 +#define ICON_MDI_ACCOUNT_CREDIT_CARD "\xf3\xb1\xae\xa6" // U+F1BA6 +#define ICON_MDI_ACCOUNT_CREDIT_CARD_OUTLINE "\xf3\xb1\xae\xa7" // U+F1BA7 +#define ICON_MDI_ACCOUNT_DETAILS "\xf3\xb0\x98\xb1" // U+F0631 +#define ICON_MDI_ACCOUNT_DETAILS_OUTLINE "\xf3\xb1\x8d\xb2" // U+F1372 +#define ICON_MDI_ACCOUNT_EDIT "\xf3\xb0\x9a\xbc" // U+F06BC +#define ICON_MDI_ACCOUNT_EDIT_OUTLINE "\xf3\xb0\xbf\xbb" // U+F0FFB +#define ICON_MDI_ACCOUNT_EYE "\xf3\xb0\x90\xa0" // U+F0420 +#define ICON_MDI_ACCOUNT_EYE_OUTLINE "\xf3\xb1\x89\xbb" // U+F127B +#define ICON_MDI_ACCOUNT_FILE "\xf3\xb1\xb2\xa7" // U+F1CA7 +#define ICON_MDI_ACCOUNT_FILE_OUTLINE "\xf3\xb1\xb2\xa8" // U+F1CA8 +#define ICON_MDI_ACCOUNT_FILE_TEXT "\xf3\xb1\xb2\xa9" // U+F1CA9 +#define ICON_MDI_ACCOUNT_FILE_TEXT_OUTLINE "\xf3\xb1\xb2\xaa" // U+F1CAA +#define ICON_MDI_ACCOUNT_FILTER "\xf3\xb0\xa4\xb6" // U+F0936 +#define ICON_MDI_ACCOUNT_FILTER_OUTLINE "\xf3\xb0\xbe\x9d" // U+F0F9D +#define ICON_MDI_ACCOUNT_GROUP "\xf3\xb0\xa1\x89" // U+F0849 +#define ICON_MDI_ACCOUNT_GROUP_OUTLINE "\xf3\xb0\xad\x98" // U+F0B58 +#define ICON_MDI_ACCOUNT_HARD_HAT "\xf3\xb0\x96\xb5" // U+F05B5 +#define ICON_MDI_ACCOUNT_HARD_HAT_OUTLINE "\xf3\xb1\xa8\x9f" // U+F1A1F +#define ICON_MDI_ACCOUNT_HEART "\xf3\xb0\xa2\x99" // U+F0899 +#define ICON_MDI_ACCOUNT_HEART_OUTLINE "\xf3\xb0\xaf\xa3" // U+F0BE3 +#define ICON_MDI_ACCOUNT_INJURY "\xf3\xb1\xa0\x95" // U+F1815 +#define ICON_MDI_ACCOUNT_INJURY_OUTLINE "\xf3\xb1\xa0\x96" // U+F1816 +#define ICON_MDI_ACCOUNT_KEY "\xf3\xb0\x80\x8b" // U+F000B +#define ICON_MDI_ACCOUNT_KEY_OUTLINE "\xf3\xb0\xaf\xa4" // U+F0BE4 +#define ICON_MDI_ACCOUNT_LOCK "\xf3\xb1\x85\x9e" // U+F115E +#define ICON_MDI_ACCOUNT_LOCK_OPEN "\xf3\xb1\xa5\xa0" // U+F1960 +#define ICON_MDI_ACCOUNT_LOCK_OPEN_OUTLINE "\xf3\xb1\xa5\xa1" // U+F1961 +#define ICON_MDI_ACCOUNT_LOCK_OUTLINE "\xf3\xb1\x85\x9f" // U+F115F +#define ICON_MDI_ACCOUNT_MINUS "\xf3\xb0\x80\x8d" // U+F000D +#define ICON_MDI_ACCOUNT_MINUS_OUTLINE "\xf3\xb0\xab\xac" // U+F0AEC +#define ICON_MDI_ACCOUNT_MULTIPLE "\xf3\xb0\x80\x8e" // U+F000E +#define ICON_MDI_ACCOUNT_MULTIPLE_CHECK "\xf3\xb0\xa3\x85" // U+F08C5 +#define ICON_MDI_ACCOUNT_MULTIPLE_CHECK_OUTLINE "\xf3\xb1\x87\xbe" // U+F11FE +#define ICON_MDI_ACCOUNT_MULTIPLE_MINUS "\xf3\xb0\x97\x93" // U+F05D3 +#define ICON_MDI_ACCOUNT_MULTIPLE_MINUS_OUTLINE "\xf3\xb0\xaf\xa5" // U+F0BE5 +#define ICON_MDI_ACCOUNT_MULTIPLE_OUTLINE "\xf3\xb0\x80\x8f" // U+F000F +#define ICON_MDI_ACCOUNT_MULTIPLE_PLUS "\xf3\xb0\x80\x90" // U+F0010 +#define ICON_MDI_ACCOUNT_MULTIPLE_PLUS_OUTLINE "\xf3\xb0\xa0\x80" // U+F0800 +#define ICON_MDI_ACCOUNT_MULTIPLE_REMOVE "\xf3\xb1\x88\x8a" // U+F120A +#define ICON_MDI_ACCOUNT_MULTIPLE_REMOVE_OUTLINE "\xf3\xb1\x88\x8b" // U+F120B +#define ICON_MDI_ACCOUNT_MUSIC "\xf3\xb0\xa0\x83" // U+F0803 +#define ICON_MDI_ACCOUNT_MUSIC_OUTLINE "\xf3\xb0\xb3\xa9" // U+F0CE9 +#define ICON_MDI_ACCOUNT_NETWORK "\xf3\xb0\x80\x91" // U+F0011 +#define ICON_MDI_ACCOUNT_NETWORK_OFF "\xf3\xb1\xab\xb1" // U+F1AF1 +#define ICON_MDI_ACCOUNT_NETWORK_OFF_OUTLINE "\xf3\xb1\xab\xb2" // U+F1AF2 +#define ICON_MDI_ACCOUNT_NETWORK_OUTLINE "\xf3\xb0\xaf\xa6" // U+F0BE6 +#define ICON_MDI_ACCOUNT_OFF "\xf3\xb0\x80\x92" // U+F0012 +#define ICON_MDI_ACCOUNT_OFF_OUTLINE "\xf3\xb0\xaf\xa7" // U+F0BE7 +#define ICON_MDI_ACCOUNT_OUTLINE "\xf3\xb0\x80\x93" // U+F0013 +#define ICON_MDI_ACCOUNT_PLUS "\xf3\xb0\x80\x94" // U+F0014 +#define ICON_MDI_ACCOUNT_PLUS_OUTLINE "\xf3\xb0\xa0\x81" // U+F0801 +#define ICON_MDI_ACCOUNT_QUESTION "\xf3\xb0\xad\x99" // U+F0B59 +#define ICON_MDI_ACCOUNT_QUESTION_OUTLINE "\xf3\xb0\xad\x9a" // U+F0B5A +#define ICON_MDI_ACCOUNT_REACTIVATE "\xf3\xb1\x94\xab" // U+F152B +#define ICON_MDI_ACCOUNT_REACTIVATE_OUTLINE "\xf3\xb1\x94\xac" // U+F152C +#define ICON_MDI_ACCOUNT_REMOVE "\xf3\xb0\x80\x95" // U+F0015 +#define ICON_MDI_ACCOUNT_REMOVE_OUTLINE "\xf3\xb0\xab\xad" // U+F0AED +#define ICON_MDI_ACCOUNT_SCHOOL "\xf3\xb1\xa8\xa0" // U+F1A20 +#define ICON_MDI_ACCOUNT_SCHOOL_OUTLINE "\xf3\xb1\xa8\xa1" // U+F1A21 +#define ICON_MDI_ACCOUNT_SEARCH "\xf3\xb0\x80\x96" // U+F0016 +#define ICON_MDI_ACCOUNT_SEARCH_OUTLINE "\xf3\xb0\xa4\xb5" // U+F0935 +#define ICON_MDI_ACCOUNT_SETTINGS "\xf3\xb0\x98\xb0" // U+F0630 +#define ICON_MDI_ACCOUNT_SETTINGS_OUTLINE "\xf3\xb1\x83\x89" // U+F10C9 +#define ICON_MDI_ACCOUNT_STAR "\xf3\xb0\x80\x97" // U+F0017 +#define ICON_MDI_ACCOUNT_STAR_OUTLINE "\xf3\xb0\xaf\xa8" // U+F0BE8 +#define ICON_MDI_ACCOUNT_SUPERVISOR "\xf3\xb0\xaa\x8b" // U+F0A8B +#define ICON_MDI_ACCOUNT_SUPERVISOR_CIRCLE "\xf3\xb0\xaa\x8c" // U+F0A8C +#define ICON_MDI_ACCOUNT_SUPERVISOR_CIRCLE_OUTLINE "\xf3\xb1\x93\xac" // U+F14EC +#define ICON_MDI_ACCOUNT_SUPERVISOR_OUTLINE "\xf3\xb1\x84\xad" // U+F112D +#define ICON_MDI_ACCOUNT_SWITCH "\xf3\xb0\x80\x99" // U+F0019 +#define ICON_MDI_ACCOUNT_SWITCH_OUTLINE "\xf3\xb0\x93\x8b" // U+F04CB +#define ICON_MDI_ACCOUNT_SYNC "\xf3\xb1\xa4\x9b" // U+F191B +#define ICON_MDI_ACCOUNT_SYNC_OUTLINE "\xf3\xb1\xa4\x9c" // U+F191C +#define ICON_MDI_ACCOUNT_TAG "\xf3\xb1\xb0\x9b" // U+F1C1B +#define ICON_MDI_ACCOUNT_TAG_OUTLINE "\xf3\xb1\xb0\x9c" // U+F1C1C +#define ICON_MDI_ACCOUNT_TIE "\xf3\xb0\xb3\xa3" // U+F0CE3 +#define ICON_MDI_ACCOUNT_TIE_HAT "\xf3\xb1\xa2\x98" // U+F1898 +#define ICON_MDI_ACCOUNT_TIE_HAT_OUTLINE "\xf3\xb1\xa2\x99" // U+F1899 +#define ICON_MDI_ACCOUNT_TIE_OUTLINE "\xf3\xb1\x83\x8a" // U+F10CA +#define ICON_MDI_ACCOUNT_TIE_VOICE "\xf3\xb1\x8c\x88" // U+F1308 +#define ICON_MDI_ACCOUNT_TIE_VOICE_OFF "\xf3\xb1\x8c\x8a" // U+F130A +#define ICON_MDI_ACCOUNT_TIE_VOICE_OFF_OUTLINE "\xf3\xb1\x8c\x8b" // U+F130B +#define ICON_MDI_ACCOUNT_TIE_VOICE_OUTLINE "\xf3\xb1\x8c\x89" // U+F1309 +#define ICON_MDI_ACCOUNT_TIE_WOMAN "\xf3\xb1\xaa\x8c" // U+F1A8C +#define ICON_MDI_ACCOUNT_VOICE "\xf3\xb0\x97\x8b" // U+F05CB +#define ICON_MDI_ACCOUNT_VOICE_OFF "\xf3\xb0\xbb\x94" // U+F0ED4 +#define ICON_MDI_ACCOUNT_WRENCH "\xf3\xb1\xa2\x9a" // U+F189A +#define ICON_MDI_ACCOUNT_WRENCH_OUTLINE "\xf3\xb1\xa2\x9b" // U+F189B +#define ICON_MDI_ADJUST "\xf3\xb0\x80\x9a" // U+F001A +#define ICON_MDI_ADVERTISEMENTS "\xf3\xb1\xa4\xaa" // U+F192A +#define ICON_MDI_ADVERTISEMENTS_OFF "\xf3\xb1\xa4\xab" // U+F192B +#define ICON_MDI_AIR_CONDITIONER "\xf3\xb0\x80\x9b" // U+F001B +#define ICON_MDI_AIR_FILTER "\xf3\xb0\xb5\x83" // U+F0D43 +#define ICON_MDI_AIR_HORN "\xf3\xb0\xb6\xac" // U+F0DAC +#define ICON_MDI_AIR_HUMIDIFIER "\xf3\xb1\x82\x99" // U+F1099 +#define ICON_MDI_AIR_HUMIDIFIER_OFF "\xf3\xb1\x91\xa6" // U+F1466 +#define ICON_MDI_AIR_PURIFIER "\xf3\xb0\xb5\x84" // U+F0D44 +#define ICON_MDI_AIR_PURIFIER_OFF "\xf3\xb1\xad\x97" // U+F1B57 +#define ICON_MDI_AIRBAG "\xf3\xb0\xaf\xa9" // U+F0BE9 +#define ICON_MDI_AIRBALLOON "\xf3\xb0\x80\x9c" // U+F001C +#define ICON_MDI_AIRBALLOON_OUTLINE "\xf3\xb1\x80\x8b" // U+F100B +#define ICON_MDI_AIRPLANE "\xf3\xb0\x80\x9d" // U+F001D +#define ICON_MDI_AIRPLANE_ALERT "\xf3\xb1\xa1\xba" // U+F187A +#define ICON_MDI_AIRPLANE_CHECK "\xf3\xb1\xa1\xbb" // U+F187B +#define ICON_MDI_AIRPLANE_CLOCK "\xf3\xb1\xa1\xbc" // U+F187C +#define ICON_MDI_AIRPLANE_COG "\xf3\xb1\xa1\xbd" // U+F187D +#define ICON_MDI_AIRPLANE_EDIT "\xf3\xb1\xa1\xbe" // U+F187E +#define ICON_MDI_AIRPLANE_LANDING "\xf3\xb0\x97\x94" // U+F05D4 +#define ICON_MDI_AIRPLANE_MARKER "\xf3\xb1\xa1\xbf" // U+F187F +#define ICON_MDI_AIRPLANE_MINUS "\xf3\xb1\xa2\x80" // U+F1880 +#define ICON_MDI_AIRPLANE_OFF "\xf3\xb0\x80\x9e" // U+F001E +#define ICON_MDI_AIRPLANE_PLUS "\xf3\xb1\xa2\x81" // U+F1881 +#define ICON_MDI_AIRPLANE_REMOVE "\xf3\xb1\xa2\x82" // U+F1882 +#define ICON_MDI_AIRPLANE_SEARCH "\xf3\xb1\xa2\x83" // U+F1883 +#define ICON_MDI_AIRPLANE_SETTINGS "\xf3\xb1\xa2\x84" // U+F1884 +#define ICON_MDI_AIRPLANE_TAKEOFF "\xf3\xb0\x97\x95" // U+F05D5 +#define ICON_MDI_AIRPORT "\xf3\xb0\xa1\x8b" // U+F084B +#define ICON_MDI_ALARM "\xf3\xb0\x80\xa0" // U+F0020 +#define ICON_MDI_ALARM_BELL "\xf3\xb0\x9e\x8e" // U+F078E +#define ICON_MDI_ALARM_CHECK "\xf3\xb0\x80\xa1" // U+F0021 +#define ICON_MDI_ALARM_LIGHT "\xf3\xb0\x9e\x8f" // U+F078F +#define ICON_MDI_ALARM_LIGHT_OFF "\xf3\xb1\x9c\x9e" // U+F171E +#define ICON_MDI_ALARM_LIGHT_OFF_OUTLINE "\xf3\xb1\x9c\x9f" // U+F171F +#define ICON_MDI_ALARM_LIGHT_OUTLINE "\xf3\xb0\xaf\xaa" // U+F0BEA +#define ICON_MDI_ALARM_MULTIPLE "\xf3\xb0\x80\xa2" // U+F0022 +#define ICON_MDI_ALARM_NOTE "\xf3\xb0\xb9\xb1" // U+F0E71 +#define ICON_MDI_ALARM_NOTE_OFF "\xf3\xb0\xb9\xb2" // U+F0E72 +#define ICON_MDI_ALARM_OFF "\xf3\xb0\x80\xa3" // U+F0023 +#define ICON_MDI_ALARM_PANEL "\xf3\xb1\x97\x84" // U+F15C4 +#define ICON_MDI_ALARM_PANEL_OUTLINE "\xf3\xb1\x97\x85" // U+F15C5 +#define ICON_MDI_ALARM_PLUS "\xf3\xb0\x80\xa4" // U+F0024 +#define ICON_MDI_ALARM_SNOOZE "\xf3\xb0\x9a\x8e" // U+F068E +#define ICON_MDI_ALBUM "\xf3\xb0\x80\xa5" // U+F0025 +#define ICON_MDI_ALERT "\xf3\xb0\x80\xa6" // U+F0026 +#define ICON_MDI_ALERT_BOX "\xf3\xb0\x80\xa7" // U+F0027 +#define ICON_MDI_ALERT_BOX_OUTLINE "\xf3\xb0\xb3\xa4" // U+F0CE4 +#define ICON_MDI_ALERT_CIRCLE "\xf3\xb0\x80\xa8" // U+F0028 +#define ICON_MDI_ALERT_CIRCLE_CHECK "\xf3\xb1\x87\xad" // U+F11ED +#define ICON_MDI_ALERT_CIRCLE_CHECK_OUTLINE "\xf3\xb1\x87\xae" // U+F11EE +#define ICON_MDI_ALERT_CIRCLE_OUTLINE "\xf3\xb0\x97\x96" // U+F05D6 +#define ICON_MDI_ALERT_DECAGRAM "\xf3\xb0\x9a\xbd" // U+F06BD +#define ICON_MDI_ALERT_DECAGRAM_OUTLINE "\xf3\xb0\xb3\xa5" // U+F0CE5 +#define ICON_MDI_ALERT_MINUS "\xf3\xb1\x92\xbb" // U+F14BB +#define ICON_MDI_ALERT_MINUS_OUTLINE "\xf3\xb1\x92\xbe" // U+F14BE +#define ICON_MDI_ALERT_OCTAGON "\xf3\xb0\x80\xa9" // U+F0029 +#define ICON_MDI_ALERT_OCTAGON_OUTLINE "\xf3\xb0\xb3\xa6" // U+F0CE6 +#define ICON_MDI_ALERT_OCTAGRAM "\xf3\xb0\x9d\xa7" // U+F0767 +#define ICON_MDI_ALERT_OCTAGRAM_OUTLINE "\xf3\xb0\xb3\xa7" // U+F0CE7 +#define ICON_MDI_ALERT_OUTLINE "\xf3\xb0\x80\xaa" // U+F002A +#define ICON_MDI_ALERT_PLUS "\xf3\xb1\x92\xba" // U+F14BA +#define ICON_MDI_ALERT_PLUS_OUTLINE "\xf3\xb1\x92\xbd" // U+F14BD +#define ICON_MDI_ALERT_REMOVE "\xf3\xb1\x92\xbc" // U+F14BC +#define ICON_MDI_ALERT_REMOVE_OUTLINE "\xf3\xb1\x92\xbf" // U+F14BF +#define ICON_MDI_ALERT_RHOMBUS "\xf3\xb1\x87\x8e" // U+F11CE +#define ICON_MDI_ALERT_RHOMBUS_OUTLINE "\xf3\xb1\x87\x8f" // U+F11CF +#define ICON_MDI_ALIEN "\xf3\xb0\xa2\x9a" // U+F089A +#define ICON_MDI_ALIEN_OUTLINE "\xf3\xb1\x83\x8b" // U+F10CB +#define ICON_MDI_ALIGN_HORIZONTAL_CENTER "\xf3\xb1\x87\x83" // U+F11C3 +#define ICON_MDI_ALIGN_HORIZONTAL_DISTRIBUTE "\xf3\xb1\xa5\xa2" // U+F1962 +#define ICON_MDI_ALIGN_HORIZONTAL_LEFT "\xf3\xb1\x87\x82" // U+F11C2 +#define ICON_MDI_ALIGN_HORIZONTAL_RIGHT "\xf3\xb1\x87\x84" // U+F11C4 +#define ICON_MDI_ALIGN_VERTICAL_BOTTOM "\xf3\xb1\x87\x85" // U+F11C5 +#define ICON_MDI_ALIGN_VERTICAL_CENTER "\xf3\xb1\x87\x86" // U+F11C6 +#define ICON_MDI_ALIGN_VERTICAL_DISTRIBUTE "\xf3\xb1\xa5\xa3" // U+F1963 +#define ICON_MDI_ALIGN_VERTICAL_TOP "\xf3\xb1\x87\x87" // U+F11C7 +#define ICON_MDI_ALL_INCLUSIVE "\xf3\xb0\x9a\xbe" // U+F06BE +#define ICON_MDI_ALL_INCLUSIVE_BOX "\xf3\xb1\xa2\x8d" // U+F188D +#define ICON_MDI_ALL_INCLUSIVE_BOX_OUTLINE "\xf3\xb1\xa2\x8e" // U+F188E +#define ICON_MDI_ALLERGY "\xf3\xb1\x89\x98" // U+F1258 +#define ICON_MDI_ALPHA "\xf3\xb0\x80\xab" // U+F002B +#define ICON_MDI_ALPHA_A "\xf3\xb0\xab\xae" // U+F0AEE +#define ICON_MDI_ALPHA_A_BOX "\xf3\xb0\xac\x88" // U+F0B08 +#define ICON_MDI_ALPHA_A_BOX_OUTLINE "\xf3\xb0\xaf\xab" // U+F0BEB +#define ICON_MDI_ALPHA_A_CIRCLE "\xf3\xb0\xaf\xac" // U+F0BEC +#define ICON_MDI_ALPHA_A_CIRCLE_OUTLINE "\xf3\xb0\xaf\xad" // U+F0BED +#define ICON_MDI_ALPHA_B "\xf3\xb0\xab\xaf" // U+F0AEF +#define ICON_MDI_ALPHA_B_BOX "\xf3\xb0\xac\x89" // U+F0B09 +#define ICON_MDI_ALPHA_B_BOX_OUTLINE "\xf3\xb0\xaf\xae" // U+F0BEE +#define ICON_MDI_ALPHA_B_CIRCLE "\xf3\xb0\xaf\xaf" // U+F0BEF +#define ICON_MDI_ALPHA_B_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb0" // U+F0BF0 +#define ICON_MDI_ALPHA_C "\xf3\xb0\xab\xb0" // U+F0AF0 +#define ICON_MDI_ALPHA_C_BOX "\xf3\xb0\xac\x8a" // U+F0B0A +#define ICON_MDI_ALPHA_C_BOX_OUTLINE "\xf3\xb0\xaf\xb1" // U+F0BF1 +#define ICON_MDI_ALPHA_C_CIRCLE "\xf3\xb0\xaf\xb2" // U+F0BF2 +#define ICON_MDI_ALPHA_C_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb3" // U+F0BF3 +#define ICON_MDI_ALPHA_D "\xf3\xb0\xab\xb1" // U+F0AF1 +#define ICON_MDI_ALPHA_D_BOX "\xf3\xb0\xac\x8b" // U+F0B0B +#define ICON_MDI_ALPHA_D_BOX_OUTLINE "\xf3\xb0\xaf\xb4" // U+F0BF4 +#define ICON_MDI_ALPHA_D_CIRCLE "\xf3\xb0\xaf\xb5" // U+F0BF5 +#define ICON_MDI_ALPHA_D_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb6" // U+F0BF6 +#define ICON_MDI_ALPHA_E "\xf3\xb0\xab\xb2" // U+F0AF2 +#define ICON_MDI_ALPHA_E_BOX "\xf3\xb0\xac\x8c" // U+F0B0C +#define ICON_MDI_ALPHA_E_BOX_OUTLINE "\xf3\xb0\xaf\xb7" // U+F0BF7 +#define ICON_MDI_ALPHA_E_CIRCLE "\xf3\xb0\xaf\xb8" // U+F0BF8 +#define ICON_MDI_ALPHA_E_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb9" // U+F0BF9 +#define ICON_MDI_ALPHA_F "\xf3\xb0\xab\xb3" // U+F0AF3 +#define ICON_MDI_ALPHA_F_BOX "\xf3\xb0\xac\x8d" // U+F0B0D +#define ICON_MDI_ALPHA_F_BOX_OUTLINE "\xf3\xb0\xaf\xba" // U+F0BFA +#define ICON_MDI_ALPHA_F_CIRCLE "\xf3\xb0\xaf\xbb" // U+F0BFB +#define ICON_MDI_ALPHA_F_CIRCLE_OUTLINE "\xf3\xb0\xaf\xbc" // U+F0BFC +#define ICON_MDI_ALPHA_G "\xf3\xb0\xab\xb4" // U+F0AF4 +#define ICON_MDI_ALPHA_G_BOX "\xf3\xb0\xac\x8e" // U+F0B0E +#define ICON_MDI_ALPHA_G_BOX_OUTLINE "\xf3\xb0\xaf\xbd" // U+F0BFD +#define ICON_MDI_ALPHA_G_CIRCLE "\xf3\xb0\xaf\xbe" // U+F0BFE +#define ICON_MDI_ALPHA_G_CIRCLE_OUTLINE "\xf3\xb0\xaf\xbf" // U+F0BFF +#define ICON_MDI_ALPHA_H "\xf3\xb0\xab\xb5" // U+F0AF5 +#define ICON_MDI_ALPHA_H_BOX "\xf3\xb0\xac\x8f" // U+F0B0F +#define ICON_MDI_ALPHA_H_BOX_OUTLINE "\xf3\xb0\xb0\x80" // U+F0C00 +#define ICON_MDI_ALPHA_H_CIRCLE "\xf3\xb0\xb0\x81" // U+F0C01 +#define ICON_MDI_ALPHA_H_CIRCLE_OUTLINE "\xf3\xb0\xb0\x82" // U+F0C02 +#define ICON_MDI_ALPHA_I "\xf3\xb0\xab\xb6" // U+F0AF6 +#define ICON_MDI_ALPHA_I_BOX "\xf3\xb0\xac\x90" // U+F0B10 +#define ICON_MDI_ALPHA_I_BOX_OUTLINE "\xf3\xb0\xb0\x83" // U+F0C03 +#define ICON_MDI_ALPHA_I_CIRCLE "\xf3\xb0\xb0\x84" // U+F0C04 +#define ICON_MDI_ALPHA_I_CIRCLE_OUTLINE "\xf3\xb0\xb0\x85" // U+F0C05 +#define ICON_MDI_ALPHA_J "\xf3\xb0\xab\xb7" // U+F0AF7 +#define ICON_MDI_ALPHA_J_BOX "\xf3\xb0\xac\x91" // U+F0B11 +#define ICON_MDI_ALPHA_J_BOX_OUTLINE "\xf3\xb0\xb0\x86" // U+F0C06 +#define ICON_MDI_ALPHA_J_CIRCLE "\xf3\xb0\xb0\x87" // U+F0C07 +#define ICON_MDI_ALPHA_J_CIRCLE_OUTLINE "\xf3\xb0\xb0\x88" // U+F0C08 +#define ICON_MDI_ALPHA_K "\xf3\xb0\xab\xb8" // U+F0AF8 +#define ICON_MDI_ALPHA_K_BOX "\xf3\xb0\xac\x92" // U+F0B12 +#define ICON_MDI_ALPHA_K_BOX_OUTLINE "\xf3\xb0\xb0\x89" // U+F0C09 +#define ICON_MDI_ALPHA_K_CIRCLE "\xf3\xb0\xb0\x8a" // U+F0C0A +#define ICON_MDI_ALPHA_K_CIRCLE_OUTLINE "\xf3\xb0\xb0\x8b" // U+F0C0B +#define ICON_MDI_ALPHA_L "\xf3\xb0\xab\xb9" // U+F0AF9 +#define ICON_MDI_ALPHA_L_BOX "\xf3\xb0\xac\x93" // U+F0B13 +#define ICON_MDI_ALPHA_L_BOX_OUTLINE "\xf3\xb0\xb0\x8c" // U+F0C0C +#define ICON_MDI_ALPHA_L_CIRCLE "\xf3\xb0\xb0\x8d" // U+F0C0D +#define ICON_MDI_ALPHA_L_CIRCLE_OUTLINE "\xf3\xb0\xb0\x8e" // U+F0C0E +#define ICON_MDI_ALPHA_M "\xf3\xb0\xab\xba" // U+F0AFA +#define ICON_MDI_ALPHA_M_BOX "\xf3\xb0\xac\x94" // U+F0B14 +#define ICON_MDI_ALPHA_M_BOX_OUTLINE "\xf3\xb0\xb0\x8f" // U+F0C0F +#define ICON_MDI_ALPHA_M_CIRCLE "\xf3\xb0\xb0\x90" // U+F0C10 +#define ICON_MDI_ALPHA_M_CIRCLE_OUTLINE "\xf3\xb0\xb0\x91" // U+F0C11 +#define ICON_MDI_ALPHA_N "\xf3\xb0\xab\xbb" // U+F0AFB +#define ICON_MDI_ALPHA_N_BOX "\xf3\xb0\xac\x95" // U+F0B15 +#define ICON_MDI_ALPHA_N_BOX_OUTLINE "\xf3\xb0\xb0\x92" // U+F0C12 +#define ICON_MDI_ALPHA_N_CIRCLE "\xf3\xb0\xb0\x93" // U+F0C13 +#define ICON_MDI_ALPHA_N_CIRCLE_OUTLINE "\xf3\xb0\xb0\x94" // U+F0C14 +#define ICON_MDI_ALPHA_O "\xf3\xb0\xab\xbc" // U+F0AFC +#define ICON_MDI_ALPHA_O_BOX "\xf3\xb0\xac\x96" // U+F0B16 +#define ICON_MDI_ALPHA_O_BOX_OUTLINE "\xf3\xb0\xb0\x95" // U+F0C15 +#define ICON_MDI_ALPHA_O_CIRCLE "\xf3\xb0\xb0\x96" // U+F0C16 +#define ICON_MDI_ALPHA_O_CIRCLE_OUTLINE "\xf3\xb0\xb0\x97" // U+F0C17 +#define ICON_MDI_ALPHA_P "\xf3\xb0\xab\xbd" // U+F0AFD +#define ICON_MDI_ALPHA_P_BOX "\xf3\xb0\xac\x97" // U+F0B17 +#define ICON_MDI_ALPHA_P_BOX_OUTLINE "\xf3\xb0\xb0\x98" // U+F0C18 +#define ICON_MDI_ALPHA_P_CIRCLE "\xf3\xb0\xb0\x99" // U+F0C19 +#define ICON_MDI_ALPHA_P_CIRCLE_OUTLINE "\xf3\xb0\xb0\x9a" // U+F0C1A +#define ICON_MDI_ALPHA_Q "\xf3\xb0\xab\xbe" // U+F0AFE +#define ICON_MDI_ALPHA_Q_BOX "\xf3\xb0\xac\x98" // U+F0B18 +#define ICON_MDI_ALPHA_Q_BOX_OUTLINE "\xf3\xb0\xb0\x9b" // U+F0C1B +#define ICON_MDI_ALPHA_Q_CIRCLE "\xf3\xb0\xb0\x9c" // U+F0C1C +#define ICON_MDI_ALPHA_Q_CIRCLE_OUTLINE "\xf3\xb0\xb0\x9d" // U+F0C1D +#define ICON_MDI_ALPHA_R "\xf3\xb0\xab\xbf" // U+F0AFF +#define ICON_MDI_ALPHA_R_BOX "\xf3\xb0\xac\x99" // U+F0B19 +#define ICON_MDI_ALPHA_R_BOX_OUTLINE "\xf3\xb0\xb0\x9e" // U+F0C1E +#define ICON_MDI_ALPHA_R_CIRCLE "\xf3\xb0\xb0\x9f" // U+F0C1F +#define ICON_MDI_ALPHA_R_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa0" // U+F0C20 +#define ICON_MDI_ALPHA_S "\xf3\xb0\xac\x80" // U+F0B00 +#define ICON_MDI_ALPHA_S_BOX "\xf3\xb0\xac\x9a" // U+F0B1A +#define ICON_MDI_ALPHA_S_BOX_OUTLINE "\xf3\xb0\xb0\xa1" // U+F0C21 +#define ICON_MDI_ALPHA_S_CIRCLE "\xf3\xb0\xb0\xa2" // U+F0C22 +#define ICON_MDI_ALPHA_S_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa3" // U+F0C23 +#define ICON_MDI_ALPHA_T "\xf3\xb0\xac\x81" // U+F0B01 +#define ICON_MDI_ALPHA_T_BOX "\xf3\xb0\xac\x9b" // U+F0B1B +#define ICON_MDI_ALPHA_T_BOX_OUTLINE "\xf3\xb0\xb0\xa4" // U+F0C24 +#define ICON_MDI_ALPHA_T_CIRCLE "\xf3\xb0\xb0\xa5" // U+F0C25 +#define ICON_MDI_ALPHA_T_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa6" // U+F0C26 +#define ICON_MDI_ALPHA_U "\xf3\xb0\xac\x82" // U+F0B02 +#define ICON_MDI_ALPHA_U_BOX "\xf3\xb0\xac\x9c" // U+F0B1C +#define ICON_MDI_ALPHA_U_BOX_OUTLINE "\xf3\xb0\xb0\xa7" // U+F0C27 +#define ICON_MDI_ALPHA_U_CIRCLE "\xf3\xb0\xb0\xa8" // U+F0C28 +#define ICON_MDI_ALPHA_U_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa9" // U+F0C29 +#define ICON_MDI_ALPHA_V "\xf3\xb0\xac\x83" // U+F0B03 +#define ICON_MDI_ALPHA_V_BOX "\xf3\xb0\xac\x9d" // U+F0B1D +#define ICON_MDI_ALPHA_V_BOX_OUTLINE "\xf3\xb0\xb0\xaa" // U+F0C2A +#define ICON_MDI_ALPHA_V_CIRCLE "\xf3\xb0\xb0\xab" // U+F0C2B +#define ICON_MDI_ALPHA_V_CIRCLE_OUTLINE "\xf3\xb0\xb0\xac" // U+F0C2C +#define ICON_MDI_ALPHA_W "\xf3\xb0\xac\x84" // U+F0B04 +#define ICON_MDI_ALPHA_W_BOX "\xf3\xb0\xac\x9e" // U+F0B1E +#define ICON_MDI_ALPHA_W_BOX_OUTLINE "\xf3\xb0\xb0\xad" // U+F0C2D +#define ICON_MDI_ALPHA_W_CIRCLE "\xf3\xb0\xb0\xae" // U+F0C2E +#define ICON_MDI_ALPHA_W_CIRCLE_OUTLINE "\xf3\xb0\xb0\xaf" // U+F0C2F +#define ICON_MDI_ALPHA_X "\xf3\xb0\xac\x85" // U+F0B05 +#define ICON_MDI_ALPHA_X_BOX "\xf3\xb0\xac\x9f" // U+F0B1F +#define ICON_MDI_ALPHA_X_BOX_OUTLINE "\xf3\xb0\xb0\xb0" // U+F0C30 +#define ICON_MDI_ALPHA_X_CIRCLE "\xf3\xb0\xb0\xb1" // U+F0C31 +#define ICON_MDI_ALPHA_X_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb2" // U+F0C32 +#define ICON_MDI_ALPHA_Y "\xf3\xb0\xac\x86" // U+F0B06 +#define ICON_MDI_ALPHA_Y_BOX "\xf3\xb0\xac\xa0" // U+F0B20 +#define ICON_MDI_ALPHA_Y_BOX_OUTLINE "\xf3\xb0\xb0\xb3" // U+F0C33 +#define ICON_MDI_ALPHA_Y_CIRCLE "\xf3\xb0\xb0\xb4" // U+F0C34 +#define ICON_MDI_ALPHA_Y_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb5" // U+F0C35 +#define ICON_MDI_ALPHA_Z "\xf3\xb0\xac\x87" // U+F0B07 +#define ICON_MDI_ALPHA_Z_BOX "\xf3\xb0\xac\xa1" // U+F0B21 +#define ICON_MDI_ALPHA_Z_BOX_OUTLINE "\xf3\xb0\xb0\xb6" // U+F0C36 +#define ICON_MDI_ALPHA_Z_CIRCLE "\xf3\xb0\xb0\xb7" // U+F0C37 +#define ICON_MDI_ALPHA_Z_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb8" // U+F0C38 +#define ICON_MDI_ALPHABET_AUREBESH "\xf3\xb1\x8c\xac" // U+F132C +#define ICON_MDI_ALPHABET_CYRILLIC "\xf3\xb1\x8c\xad" // U+F132D +#define ICON_MDI_ALPHABET_GREEK "\xf3\xb1\x8c\xae" // U+F132E +#define ICON_MDI_ALPHABET_LATIN "\xf3\xb1\x8c\xaf" // U+F132F +#define ICON_MDI_ALPHABET_PIQAD "\xf3\xb1\x8c\xb0" // U+F1330 +#define ICON_MDI_ALPHABET_TENGWAR "\xf3\xb1\x8c\xb7" // U+F1337 +#define ICON_MDI_ALPHABETICAL "\xf3\xb0\x80\xac" // U+F002C +#define ICON_MDI_ALPHABETICAL_OFF "\xf3\xb1\x80\x8c" // U+F100C +#define ICON_MDI_ALPHABETICAL_VARIANT "\xf3\xb1\x80\x8d" // U+F100D +#define ICON_MDI_ALPHABETICAL_VARIANT_OFF "\xf3\xb1\x80\x8e" // U+F100E +#define ICON_MDI_ALTIMETER "\xf3\xb0\x97\x97" // U+F05D7 +#define ICON_MDI_AMBULANCE "\xf3\xb0\x80\xaf" // U+F002F +#define ICON_MDI_AMMUNITION "\xf3\xb0\xb3\xa8" // U+F0CE8 +#define ICON_MDI_AMPERSAND "\xf3\xb0\xaa\x8d" // U+F0A8D +#define ICON_MDI_AMPLIFIER "\xf3\xb0\x80\xb0" // U+F0030 +#define ICON_MDI_AMPLIFIER_OFF "\xf3\xb1\x86\xb5" // U+F11B5 +#define ICON_MDI_ANCHOR "\xf3\xb0\x80\xb1" // U+F0031 +#define ICON_MDI_ANDROID "\xf3\xb0\x80\xb2" // U+F0032 +#define ICON_MDI_ANDROID_STUDIO "\xf3\xb0\x80\xb4" // U+F0034 +#define ICON_MDI_ANGLE_ACUTE "\xf3\xb0\xa4\xb7" // U+F0937 +#define ICON_MDI_ANGLE_OBTUSE "\xf3\xb0\xa4\xb8" // U+F0938 +#define ICON_MDI_ANGLE_RIGHT "\xf3\xb0\xa4\xb9" // U+F0939 +#define ICON_MDI_ANGULAR "\xf3\xb0\x9a\xb2" // U+F06B2 +#define ICON_MDI_ANGULARJS "\xf3\xb0\x9a\xbf" // U+F06BF +#define ICON_MDI_ANIMATION "\xf3\xb0\x97\x98" // U+F05D8 +#define ICON_MDI_ANIMATION_OUTLINE "\xf3\xb0\xaa\x8f" // U+F0A8F +#define ICON_MDI_ANIMATION_PLAY "\xf3\xb0\xa4\xba" // U+F093A +#define ICON_MDI_ANIMATION_PLAY_OUTLINE "\xf3\xb0\xaa\x90" // U+F0A90 +#define ICON_MDI_ANSIBLE "\xf3\xb1\x82\x9a" // U+F109A +#define ICON_MDI_ANTENNA "\xf3\xb1\x84\x99" // U+F1119 +#define ICON_MDI_ANVIL "\xf3\xb0\xa2\x9b" // U+F089B +#define ICON_MDI_APACHE_KAFKA "\xf3\xb1\x80\x8f" // U+F100F +#define ICON_MDI_API "\xf3\xb1\x82\x9b" // U+F109B +#define ICON_MDI_API_OFF "\xf3\xb1\x89\x97" // U+F1257 +#define ICON_MDI_APPLE "\xf3\xb0\x80\xb5" // U+F0035 +#define ICON_MDI_APPLE_FINDER "\xf3\xb0\x80\xb6" // U+F0036 +#define ICON_MDI_APPLE_ICLOUD "\xf3\xb0\x80\xb8" // U+F0038 +#define ICON_MDI_APPLE_IOS "\xf3\xb0\x80\xb7" // U+F0037 +#define ICON_MDI_APPLE_KEYBOARD_CAPS "\xf3\xb0\x98\xb2" // U+F0632 +#define ICON_MDI_APPLE_KEYBOARD_COMMAND "\xf3\xb0\x98\xb3" // U+F0633 +#define ICON_MDI_APPLE_KEYBOARD_CONTROL "\xf3\xb0\x98\xb4" // U+F0634 +#define ICON_MDI_APPLE_KEYBOARD_OPTION "\xf3\xb0\x98\xb5" // U+F0635 +#define ICON_MDI_APPLE_KEYBOARD_SHIFT "\xf3\xb0\x98\xb6" // U+F0636 +#define ICON_MDI_APPLE_SAFARI "\xf3\xb0\x80\xb9" // U+F0039 +#define ICON_MDI_APPLICATION "\xf3\xb0\xa3\x86" // U+F08C6 +#define ICON_MDI_APPLICATION_ARRAY "\xf3\xb1\x83\xb5" // U+F10F5 +#define ICON_MDI_APPLICATION_ARRAY_OUTLINE "\xf3\xb1\x83\xb6" // U+F10F6 +#define ICON_MDI_APPLICATION_BRACES "\xf3\xb1\x83\xb7" // U+F10F7 +#define ICON_MDI_APPLICATION_BRACES_OUTLINE "\xf3\xb1\x83\xb8" // U+F10F8 +#define ICON_MDI_APPLICATION_BRACKETS "\xf3\xb0\xb2\x8b" // U+F0C8B +#define ICON_MDI_APPLICATION_BRACKETS_OUTLINE "\xf3\xb0\xb2\x8c" // U+F0C8C +#define ICON_MDI_APPLICATION_COG "\xf3\xb0\x99\xb5" // U+F0675 +#define ICON_MDI_APPLICATION_COG_OUTLINE "\xf3\xb1\x95\xb7" // U+F1577 +#define ICON_MDI_APPLICATION_EDIT "\xf3\xb0\x82\xae" // U+F00AE +#define ICON_MDI_APPLICATION_EDIT_OUTLINE "\xf3\xb0\x98\x99" // U+F0619 +#define ICON_MDI_APPLICATION_EXPORT "\xf3\xb0\xb6\xad" // U+F0DAD +#define ICON_MDI_APPLICATION_IMPORT "\xf3\xb0\xb6\xae" // U+F0DAE +#define ICON_MDI_APPLICATION_OUTLINE "\xf3\xb0\x98\x94" // U+F0614 +#define ICON_MDI_APPLICATION_PARENTHESES "\xf3\xb1\x83\xb9" // U+F10F9 +#define ICON_MDI_APPLICATION_PARENTHESES_OUTLINE "\xf3\xb1\x83\xba" // U+F10FA +#define ICON_MDI_APPLICATION_SETTINGS "\xf3\xb0\xad\xa0" // U+F0B60 +#define ICON_MDI_APPLICATION_SETTINGS_OUTLINE "\xf3\xb1\x95\x95" // U+F1555 +#define ICON_MDI_APPLICATION_VARIABLE "\xf3\xb1\x83\xbb" // U+F10FB +#define ICON_MDI_APPLICATION_VARIABLE_OUTLINE "\xf3\xb1\x83\xbc" // U+F10FC +#define ICON_MDI_APPROXIMATELY_EQUAL "\xf3\xb0\xbe\x9e" // U+F0F9E +#define ICON_MDI_APPROXIMATELY_EQUAL_BOX "\xf3\xb0\xbe\x9f" // U+F0F9F +#define ICON_MDI_APPS "\xf3\xb0\x80\xbb" // U+F003B +#define ICON_MDI_APPS_BOX "\xf3\xb0\xb5\x86" // U+F0D46 +#define ICON_MDI_ARCH "\xf3\xb0\xa3\x87" // U+F08C7 +#define ICON_MDI_ARCHIVE "\xf3\xb0\x80\xbc" // U+F003C +#define ICON_MDI_ARCHIVE_ALERT "\xf3\xb1\x93\xbd" // U+F14FD +#define ICON_MDI_ARCHIVE_ALERT_OUTLINE "\xf3\xb1\x93\xbe" // U+F14FE +#define ICON_MDI_ARCHIVE_ARROW_DOWN "\xf3\xb1\x89\x99" // U+F1259 +#define ICON_MDI_ARCHIVE_ARROW_DOWN_OUTLINE "\xf3\xb1\x89\x9a" // U+F125A +#define ICON_MDI_ARCHIVE_ARROW_UP "\xf3\xb1\x89\x9b" // U+F125B +#define ICON_MDI_ARCHIVE_ARROW_UP_OUTLINE "\xf3\xb1\x89\x9c" // U+F125C +#define ICON_MDI_ARCHIVE_CANCEL "\xf3\xb1\x9d\x8b" // U+F174B +#define ICON_MDI_ARCHIVE_CANCEL_OUTLINE "\xf3\xb1\x9d\x8c" // U+F174C +#define ICON_MDI_ARCHIVE_CHECK "\xf3\xb1\x9d\x8d" // U+F174D +#define ICON_MDI_ARCHIVE_CHECK_OUTLINE "\xf3\xb1\x9d\x8e" // U+F174E +#define ICON_MDI_ARCHIVE_CLOCK "\xf3\xb1\x9d\x8f" // U+F174F +#define ICON_MDI_ARCHIVE_CLOCK_OUTLINE "\xf3\xb1\x9d\x90" // U+F1750 +#define ICON_MDI_ARCHIVE_COG "\xf3\xb1\x9d\x91" // U+F1751 +#define ICON_MDI_ARCHIVE_COG_OUTLINE "\xf3\xb1\x9d\x92" // U+F1752 +#define ICON_MDI_ARCHIVE_EDIT "\xf3\xb1\x9d\x93" // U+F1753 +#define ICON_MDI_ARCHIVE_EDIT_OUTLINE "\xf3\xb1\x9d\x94" // U+F1754 +#define ICON_MDI_ARCHIVE_EYE "\xf3\xb1\x9d\x95" // U+F1755 +#define ICON_MDI_ARCHIVE_EYE_OUTLINE "\xf3\xb1\x9d\x96" // U+F1756 +#define ICON_MDI_ARCHIVE_LOCK "\xf3\xb1\x9d\x97" // U+F1757 +#define ICON_MDI_ARCHIVE_LOCK_OPEN "\xf3\xb1\x9d\x98" // U+F1758 +#define ICON_MDI_ARCHIVE_LOCK_OPEN_OUTLINE "\xf3\xb1\x9d\x99" // U+F1759 +#define ICON_MDI_ARCHIVE_LOCK_OUTLINE "\xf3\xb1\x9d\x9a" // U+F175A +#define ICON_MDI_ARCHIVE_MARKER "\xf3\xb1\x9d\x9b" // U+F175B +#define ICON_MDI_ARCHIVE_MARKER_OUTLINE "\xf3\xb1\x9d\x9c" // U+F175C +#define ICON_MDI_ARCHIVE_MINUS "\xf3\xb1\x9d\x9d" // U+F175D +#define ICON_MDI_ARCHIVE_MINUS_OUTLINE "\xf3\xb1\x9d\x9e" // U+F175E +#define ICON_MDI_ARCHIVE_MUSIC "\xf3\xb1\x9d\x9f" // U+F175F +#define ICON_MDI_ARCHIVE_MUSIC_OUTLINE "\xf3\xb1\x9d\xa0" // U+F1760 +#define ICON_MDI_ARCHIVE_OFF "\xf3\xb1\x9d\xa1" // U+F1761 +#define ICON_MDI_ARCHIVE_OFF_OUTLINE "\xf3\xb1\x9d\xa2" // U+F1762 +#define ICON_MDI_ARCHIVE_OUTLINE "\xf3\xb1\x88\x8e" // U+F120E +#define ICON_MDI_ARCHIVE_PLUS "\xf3\xb1\x9d\xa3" // U+F1763 +#define ICON_MDI_ARCHIVE_PLUS_OUTLINE "\xf3\xb1\x9d\xa4" // U+F1764 +#define ICON_MDI_ARCHIVE_REFRESH "\xf3\xb1\x9d\xa5" // U+F1765 +#define ICON_MDI_ARCHIVE_REFRESH_OUTLINE "\xf3\xb1\x9d\xa6" // U+F1766 +#define ICON_MDI_ARCHIVE_REMOVE "\xf3\xb1\x9d\xa7" // U+F1767 +#define ICON_MDI_ARCHIVE_REMOVE_OUTLINE "\xf3\xb1\x9d\xa8" // U+F1768 +#define ICON_MDI_ARCHIVE_SEARCH "\xf3\xb1\x9d\xa9" // U+F1769 +#define ICON_MDI_ARCHIVE_SEARCH_OUTLINE "\xf3\xb1\x9d\xaa" // U+F176A +#define ICON_MDI_ARCHIVE_SETTINGS "\xf3\xb1\x9d\xab" // U+F176B +#define ICON_MDI_ARCHIVE_SETTINGS_OUTLINE "\xf3\xb1\x9d\xac" // U+F176C +#define ICON_MDI_ARCHIVE_STAR "\xf3\xb1\x9d\xad" // U+F176D +#define ICON_MDI_ARCHIVE_STAR_OUTLINE "\xf3\xb1\x9d\xae" // U+F176E +#define ICON_MDI_ARCHIVE_SYNC "\xf3\xb1\x9d\xaf" // U+F176F +#define ICON_MDI_ARCHIVE_SYNC_OUTLINE "\xf3\xb1\x9d\xb0" // U+F1770 +#define ICON_MDI_ARM_FLEX "\xf3\xb0\xbf\x97" // U+F0FD7 +#define ICON_MDI_ARM_FLEX_OUTLINE "\xf3\xb0\xbf\x96" // U+F0FD6 +#define ICON_MDI_ARRANGE_BRING_FORWARD "\xf3\xb0\x80\xbd" // U+F003D +#define ICON_MDI_ARRANGE_BRING_TO_FRONT "\xf3\xb0\x80\xbe" // U+F003E +#define ICON_MDI_ARRANGE_SEND_BACKWARD "\xf3\xb0\x80\xbf" // U+F003F +#define ICON_MDI_ARRANGE_SEND_TO_BACK "\xf3\xb0\x81\x80" // U+F0040 +#define ICON_MDI_ARROW_ALL "\xf3\xb0\x81\x81" // U+F0041 +#define ICON_MDI_ARROW_BOTTOM_LEFT "\xf3\xb0\x81\x82" // U+F0042 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_BOX "\xf3\xb1\xa5\xa4" // U+F1964 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa5" // U+F1965 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_OUTLINE "\xf3\xb0\xa6\xb7" // U+F09B7 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THICK "\xf3\xb0\xa6\xb8" // U+F09B8 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THIN "\xf3\xb1\xa6\xb6" // U+F19B6 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x96" // U+F1596 +#define ICON_MDI_ARROW_BOTTOM_RIGHT "\xf3\xb0\x81\x83" // U+F0043 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_BOX "\xf3\xb1\xa5\xa6" // U+F1966 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa7" // U+F1967 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa6\xb9" // U+F09B9 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THICK "\xf3\xb0\xa6\xba" // U+F09BA +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THIN "\xf3\xb1\xa6\xb7" // U+F19B7 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x95" // U+F1595 +#define ICON_MDI_ARROW_COLLAPSE "\xf3\xb0\x98\x95" // U+F0615 +#define ICON_MDI_ARROW_COLLAPSE_ALL "\xf3\xb0\x81\x84" // U+F0044 +#define ICON_MDI_ARROW_COLLAPSE_DOWN "\xf3\xb0\x9e\x92" // U+F0792 +#define ICON_MDI_ARROW_COLLAPSE_HORIZONTAL "\xf3\xb0\xa1\x8c" // U+F084C +#define ICON_MDI_ARROW_COLLAPSE_LEFT "\xf3\xb0\x9e\x93" // U+F0793 +#define ICON_MDI_ARROW_COLLAPSE_RIGHT "\xf3\xb0\x9e\x94" // U+F0794 +#define ICON_MDI_ARROW_COLLAPSE_UP "\xf3\xb0\x9e\x95" // U+F0795 +#define ICON_MDI_ARROW_COLLAPSE_VERTICAL "\xf3\xb0\xa1\x8d" // U+F084D +#define ICON_MDI_ARROW_DECISION "\xf3\xb0\xa6\xbb" // U+F09BB +#define ICON_MDI_ARROW_DECISION_AUTO "\xf3\xb0\xa6\xbc" // U+F09BC +#define ICON_MDI_ARROW_DECISION_AUTO_OUTLINE "\xf3\xb0\xa6\xbd" // U+F09BD +#define ICON_MDI_ARROW_DECISION_OUTLINE "\xf3\xb0\xa6\xbe" // U+F09BE +#define ICON_MDI_ARROW_DOWN "\xf3\xb0\x81\x85" // U+F0045 +#define ICON_MDI_ARROW_DOWN_BOLD "\xf3\xb0\x9c\xae" // U+F072E +#define ICON_MDI_ARROW_DOWN_BOLD_BOX "\xf3\xb0\x9c\xaf" // U+F072F +#define ICON_MDI_ARROW_DOWN_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb0" // U+F0730 +#define ICON_MDI_ARROW_DOWN_BOLD_CIRCLE "\xf3\xb0\x81\x87" // U+F0047 +#define ICON_MDI_ARROW_DOWN_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x88" // U+F0048 +#define ICON_MDI_ARROW_DOWN_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x89" // U+F0049 +#define ICON_MDI_ARROW_DOWN_BOLD_OUTLINE "\xf3\xb0\xa6\xbf" // U+F09BF +#define ICON_MDI_ARROW_DOWN_BOX "\xf3\xb0\x9b\x80" // U+F06C0 +#define ICON_MDI_ARROW_DOWN_CIRCLE "\xf3\xb0\xb3\x9b" // U+F0CDB +#define ICON_MDI_ARROW_DOWN_CIRCLE_OUTLINE "\xf3\xb0\xb3\x9c" // U+F0CDC +#define ICON_MDI_ARROW_DOWN_DROP_CIRCLE "\xf3\xb0\x81\x8a" // U+F004A +#define ICON_MDI_ARROW_DOWN_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x8b" // U+F004B +#define ICON_MDI_ARROW_DOWN_LEFT "\xf3\xb1\x9e\xa1" // U+F17A1 +#define ICON_MDI_ARROW_DOWN_LEFT_BOLD "\xf3\xb1\x9e\xa2" // U+F17A2 +#define ICON_MDI_ARROW_DOWN_RIGHT "\xf3\xb1\x9e\xa3" // U+F17A3 +#define ICON_MDI_ARROW_DOWN_RIGHT_BOLD "\xf3\xb1\x9e\xa4" // U+F17A4 +#define ICON_MDI_ARROW_DOWN_THICK "\xf3\xb0\x81\x86" // U+F0046 +#define ICON_MDI_ARROW_DOWN_THIN "\xf3\xb1\xa6\xb3" // U+F19B3 +#define ICON_MDI_ARROW_DOWN_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x99" // U+F1599 +#define ICON_MDI_ARROW_EXPAND "\xf3\xb0\x98\x96" // U+F0616 +#define ICON_MDI_ARROW_EXPAND_ALL "\xf3\xb0\x81\x8c" // U+F004C +#define ICON_MDI_ARROW_EXPAND_DOWN "\xf3\xb0\x9e\x96" // U+F0796 +#define ICON_MDI_ARROW_EXPAND_HORIZONTAL "\xf3\xb0\xa1\x8e" // U+F084E +#define ICON_MDI_ARROW_EXPAND_LEFT "\xf3\xb0\x9e\x97" // U+F0797 +#define ICON_MDI_ARROW_EXPAND_RIGHT "\xf3\xb0\x9e\x98" // U+F0798 +#define ICON_MDI_ARROW_EXPAND_UP "\xf3\xb0\x9e\x99" // U+F0799 +#define ICON_MDI_ARROW_EXPAND_VERTICAL "\xf3\xb0\xa1\x8f" // U+F084F +#define ICON_MDI_ARROW_HORIZONTAL_LOCK "\xf3\xb1\x85\x9b" // U+F115B +#define ICON_MDI_ARROW_LEFT "\xf3\xb0\x81\x8d" // U+F004D +#define ICON_MDI_ARROW_LEFT_BOLD "\xf3\xb0\x9c\xb1" // U+F0731 +#define ICON_MDI_ARROW_LEFT_BOLD_BOX "\xf3\xb0\x9c\xb2" // U+F0732 +#define ICON_MDI_ARROW_LEFT_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb3" // U+F0733 +#define ICON_MDI_ARROW_LEFT_BOLD_CIRCLE "\xf3\xb0\x81\x8f" // U+F004F +#define ICON_MDI_ARROW_LEFT_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x90" // U+F0050 +#define ICON_MDI_ARROW_LEFT_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x91" // U+F0051 +#define ICON_MDI_ARROW_LEFT_BOLD_OUTLINE "\xf3\xb0\xa7\x80" // U+F09C0 +#define ICON_MDI_ARROW_LEFT_BOTTOM "\xf3\xb1\x9e\xa5" // U+F17A5 +#define ICON_MDI_ARROW_LEFT_BOTTOM_BOLD "\xf3\xb1\x9e\xa6" // U+F17A6 +#define ICON_MDI_ARROW_LEFT_BOX "\xf3\xb0\x9b\x81" // U+F06C1 +#define ICON_MDI_ARROW_LEFT_CIRCLE "\xf3\xb0\xb3\x9d" // U+F0CDD +#define ICON_MDI_ARROW_LEFT_CIRCLE_OUTLINE "\xf3\xb0\xb3\x9e" // U+F0CDE +#define ICON_MDI_ARROW_LEFT_DROP_CIRCLE "\xf3\xb0\x81\x92" // U+F0052 +#define ICON_MDI_ARROW_LEFT_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x93" // U+F0053 +#define ICON_MDI_ARROW_LEFT_RIGHT "\xf3\xb0\xb9\xb3" // U+F0E73 +#define ICON_MDI_ARROW_LEFT_RIGHT_BOLD "\xf3\xb0\xb9\xb4" // U+F0E74 +#define ICON_MDI_ARROW_LEFT_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x81" // U+F09C1 +#define ICON_MDI_ARROW_LEFT_THICK "\xf3\xb0\x81\x8e" // U+F004E +#define ICON_MDI_ARROW_LEFT_THIN "\xf3\xb1\xa6\xb1" // U+F19B1 +#define ICON_MDI_ARROW_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x9a" // U+F159A +#define ICON_MDI_ARROW_LEFT_TOP "\xf3\xb1\x9e\xa7" // U+F17A7 +#define ICON_MDI_ARROW_LEFT_TOP_BOLD "\xf3\xb1\x9e\xa8" // U+F17A8 +#define ICON_MDI_ARROW_OSCILLATING "\xf3\xb1\xb2\x91" // U+F1C91 +#define ICON_MDI_ARROW_OSCILLATING_OFF "\xf3\xb1\xb2\x92" // U+F1C92 +#define ICON_MDI_ARROW_PROJECTILE "\xf3\xb1\xa1\x80" // U+F1840 +#define ICON_MDI_ARROW_PROJECTILE_MULTIPLE "\xf3\xb1\xa0\xbf" // U+F183F +#define ICON_MDI_ARROW_RIGHT "\xf3\xb0\x81\x94" // U+F0054 +#define ICON_MDI_ARROW_RIGHT_BOLD "\xf3\xb0\x9c\xb4" // U+F0734 +#define ICON_MDI_ARROW_RIGHT_BOLD_BOX "\xf3\xb0\x9c\xb5" // U+F0735 +#define ICON_MDI_ARROW_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb6" // U+F0736 +#define ICON_MDI_ARROW_RIGHT_BOLD_CIRCLE "\xf3\xb0\x81\x96" // U+F0056 +#define ICON_MDI_ARROW_RIGHT_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x97" // U+F0057 +#define ICON_MDI_ARROW_RIGHT_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x98" // U+F0058 +#define ICON_MDI_ARROW_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x82" // U+F09C2 +#define ICON_MDI_ARROW_RIGHT_BOTTOM "\xf3\xb1\x9e\xa9" // U+F17A9 +#define ICON_MDI_ARROW_RIGHT_BOTTOM_BOLD "\xf3\xb1\x9e\xaa" // U+F17AA +#define ICON_MDI_ARROW_RIGHT_BOX "\xf3\xb0\x9b\x82" // U+F06C2 +#define ICON_MDI_ARROW_RIGHT_CIRCLE "\xf3\xb0\xb3\x9f" // U+F0CDF +#define ICON_MDI_ARROW_RIGHT_CIRCLE_OUTLINE "\xf3\xb0\xb3\xa0" // U+F0CE0 +#define ICON_MDI_ARROW_RIGHT_DROP_CIRCLE "\xf3\xb0\x81\x99" // U+F0059 +#define ICON_MDI_ARROW_RIGHT_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x9a" // U+F005A +#define ICON_MDI_ARROW_RIGHT_THICK "\xf3\xb0\x81\x95" // U+F0055 +#define ICON_MDI_ARROW_RIGHT_THIN "\xf3\xb1\xa6\xb0" // U+F19B0 +#define ICON_MDI_ARROW_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x98" // U+F1598 +#define ICON_MDI_ARROW_RIGHT_TOP "\xf3\xb1\x9e\xab" // U+F17AB +#define ICON_MDI_ARROW_RIGHT_TOP_BOLD "\xf3\xb1\x9e\xac" // U+F17AC +#define ICON_MDI_ARROW_SPLIT_HORIZONTAL "\xf3\xb0\xa4\xbb" // U+F093B +#define ICON_MDI_ARROW_SPLIT_VERTICAL "\xf3\xb0\xa4\xbc" // U+F093C +#define ICON_MDI_ARROW_TOP_LEFT "\xf3\xb0\x81\x9b" // U+F005B +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_BOX "\xf3\xb1\xa5\xa8" // U+F1968 +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa9" // U+F1969 +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_OUTLINE "\xf3\xb0\xa7\x83" // U+F09C3 +#define ICON_MDI_ARROW_TOP_LEFT_BOTTOM_RIGHT "\xf3\xb0\xb9\xb5" // U+F0E75 +#define ICON_MDI_ARROW_TOP_LEFT_BOTTOM_RIGHT_BOLD "\xf3\xb0\xb9\xb6" // U+F0E76 +#define ICON_MDI_ARROW_TOP_LEFT_THICK "\xf3\xb0\xa7\x84" // U+F09C4 +#define ICON_MDI_ARROW_TOP_LEFT_THIN "\xf3\xb1\xa6\xb5" // U+F19B5 +#define ICON_MDI_ARROW_TOP_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x93" // U+F1593 +#define ICON_MDI_ARROW_TOP_RIGHT "\xf3\xb0\x81\x9c" // U+F005C +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_BOX "\xf3\xb1\xa5\xaa" // U+F196A +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xab" // U+F196B +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x85" // U+F09C5 +#define ICON_MDI_ARROW_TOP_RIGHT_BOTTOM_LEFT "\xf3\xb0\xb9\xb7" // U+F0E77 +#define ICON_MDI_ARROW_TOP_RIGHT_BOTTOM_LEFT_BOLD "\xf3\xb0\xb9\xb8" // U+F0E78 +#define ICON_MDI_ARROW_TOP_RIGHT_THICK "\xf3\xb0\xa7\x86" // U+F09C6 +#define ICON_MDI_ARROW_TOP_RIGHT_THIN "\xf3\xb1\xa6\xb4" // U+F19B4 +#define ICON_MDI_ARROW_TOP_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x94" // U+F1594 +#define ICON_MDI_ARROW_U_DOWN_LEFT "\xf3\xb1\x9e\xad" // U+F17AD +#define ICON_MDI_ARROW_U_DOWN_LEFT_BOLD "\xf3\xb1\x9e\xae" // U+F17AE +#define ICON_MDI_ARROW_U_DOWN_RIGHT "\xf3\xb1\x9e\xaf" // U+F17AF +#define ICON_MDI_ARROW_U_DOWN_RIGHT_BOLD "\xf3\xb1\x9e\xb0" // U+F17B0 +#define ICON_MDI_ARROW_U_LEFT_BOTTOM "\xf3\xb1\x9e\xb1" // U+F17B1 +#define ICON_MDI_ARROW_U_LEFT_BOTTOM_BOLD "\xf3\xb1\x9e\xb2" // U+F17B2 +#define ICON_MDI_ARROW_U_LEFT_TOP "\xf3\xb1\x9e\xb3" // U+F17B3 +#define ICON_MDI_ARROW_U_LEFT_TOP_BOLD "\xf3\xb1\x9e\xb4" // U+F17B4 +#define ICON_MDI_ARROW_U_RIGHT_BOTTOM "\xf3\xb1\x9e\xb5" // U+F17B5 +#define ICON_MDI_ARROW_U_RIGHT_BOTTOM_BOLD "\xf3\xb1\x9e\xb6" // U+F17B6 +#define ICON_MDI_ARROW_U_RIGHT_TOP "\xf3\xb1\x9e\xb7" // U+F17B7 +#define ICON_MDI_ARROW_U_RIGHT_TOP_BOLD "\xf3\xb1\x9e\xb8" // U+F17B8 +#define ICON_MDI_ARROW_U_UP_LEFT "\xf3\xb1\x9e\xb9" // U+F17B9 +#define ICON_MDI_ARROW_U_UP_LEFT_BOLD "\xf3\xb1\x9e\xba" // U+F17BA +#define ICON_MDI_ARROW_U_UP_RIGHT "\xf3\xb1\x9e\xbb" // U+F17BB +#define ICON_MDI_ARROW_U_UP_RIGHT_BOLD "\xf3\xb1\x9e\xbc" // U+F17BC +#define ICON_MDI_ARROW_UP "\xf3\xb0\x81\x9d" // U+F005D +#define ICON_MDI_ARROW_UP_BOLD "\xf3\xb0\x9c\xb7" // U+F0737 +#define ICON_MDI_ARROW_UP_BOLD_BOX "\xf3\xb0\x9c\xb8" // U+F0738 +#define ICON_MDI_ARROW_UP_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb9" // U+F0739 +#define ICON_MDI_ARROW_UP_BOLD_CIRCLE "\xf3\xb0\x81\x9f" // U+F005F +#define ICON_MDI_ARROW_UP_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\xa0" // U+F0060 +#define ICON_MDI_ARROW_UP_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\xa1" // U+F0061 +#define ICON_MDI_ARROW_UP_BOLD_OUTLINE "\xf3\xb0\xa7\x87" // U+F09C7 +#define ICON_MDI_ARROW_UP_BOX "\xf3\xb0\x9b\x83" // U+F06C3 +#define ICON_MDI_ARROW_UP_CIRCLE "\xf3\xb0\xb3\xa1" // U+F0CE1 +#define ICON_MDI_ARROW_UP_CIRCLE_OUTLINE "\xf3\xb0\xb3\xa2" // U+F0CE2 +#define ICON_MDI_ARROW_UP_DOWN "\xf3\xb0\xb9\xb9" // U+F0E79 +#define ICON_MDI_ARROW_UP_DOWN_BOLD "\xf3\xb0\xb9\xba" // U+F0E7A +#define ICON_MDI_ARROW_UP_DOWN_BOLD_OUTLINE "\xf3\xb0\xa7\x88" // U+F09C8 +#define ICON_MDI_ARROW_UP_DROP_CIRCLE "\xf3\xb0\x81\xa2" // U+F0062 +#define ICON_MDI_ARROW_UP_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\xa3" // U+F0063 +#define ICON_MDI_ARROW_UP_LEFT "\xf3\xb1\x9e\xbd" // U+F17BD +#define ICON_MDI_ARROW_UP_LEFT_BOLD "\xf3\xb1\x9e\xbe" // U+F17BE +#define ICON_MDI_ARROW_UP_RIGHT "\xf3\xb1\x9e\xbf" // U+F17BF +#define ICON_MDI_ARROW_UP_RIGHT_BOLD "\xf3\xb1\x9f\x80" // U+F17C0 +#define ICON_MDI_ARROW_UP_THICK "\xf3\xb0\x81\x9e" // U+F005E +#define ICON_MDI_ARROW_UP_THIN "\xf3\xb1\xa6\xb2" // U+F19B2 +#define ICON_MDI_ARROW_UP_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x97" // U+F1597 +#define ICON_MDI_ARROW_VERTICAL_LOCK "\xf3\xb1\x85\x9c" // U+F115C +#define ICON_MDI_ARTBOARD "\xf3\xb1\xae\x9a" // U+F1B9A +#define ICON_MDI_ARTSTATION "\xf3\xb0\xad\x9b" // U+F0B5B +#define ICON_MDI_ASPECT_RATIO "\xf3\xb0\xa8\xa4" // U+F0A24 +#define ICON_MDI_ASSISTANT "\xf3\xb0\x81\xa4" // U+F0064 +#define ICON_MDI_ASTERISK "\xf3\xb0\x9b\x84" // U+F06C4 +#define ICON_MDI_ASTERISK_CIRCLE_OUTLINE "\xf3\xb1\xa8\xa7" // U+F1A27 +#define ICON_MDI_AT "\xf3\xb0\x81\xa5" // U+F0065 +#define ICON_MDI_ATLASSIAN "\xf3\xb0\xa0\x84" // U+F0804 +#define ICON_MDI_ATM "\xf3\xb0\xb5\x87" // U+F0D47 +#define ICON_MDI_ATOM "\xf3\xb0\x9d\xa8" // U+F0768 +#define ICON_MDI_ATOM_VARIANT "\xf3\xb0\xb9\xbb" // U+F0E7B +#define ICON_MDI_ATTACHMENT "\xf3\xb0\x81\xa6" // U+F0066 +#define ICON_MDI_ATTACHMENT_CHECK "\xf3\xb1\xab\x81" // U+F1AC1 +#define ICON_MDI_ATTACHMENT_LOCK "\xf3\xb1\xa7\x84" // U+F19C4 +#define ICON_MDI_ATTACHMENT_MINUS "\xf3\xb1\xab\x82" // U+F1AC2 +#define ICON_MDI_ATTACHMENT_OFF "\xf3\xb1\xab\x83" // U+F1AC3 +#define ICON_MDI_ATTACHMENT_PLUS "\xf3\xb1\xab\x84" // U+F1AC4 +#define ICON_MDI_ATTACHMENT_REMOVE "\xf3\xb1\xab\x85" // U+F1AC5 +#define ICON_MDI_ATV "\xf3\xb1\xad\xb0" // U+F1B70 +#define ICON_MDI_AUDIO_INPUT_RCA "\xf3\xb1\xa1\xab" // U+F186B +#define ICON_MDI_AUDIO_INPUT_STEREO_MINIJACK "\xf3\xb1\xa1\xac" // U+F186C +#define ICON_MDI_AUDIO_INPUT_XLR "\xf3\xb1\xa1\xad" // U+F186D +#define ICON_MDI_AUDIO_VIDEO "\xf3\xb0\xa4\xbd" // U+F093D +#define ICON_MDI_AUDIO_VIDEO_OFF "\xf3\xb1\x86\xb6" // U+F11B6 +#define ICON_MDI_AUGMENTED_REALITY "\xf3\xb0\xa1\x90" // U+F0850 +#define ICON_MDI_AURORA "\xf3\xb1\xae\xb9" // U+F1BB9 +#define ICON_MDI_AUTO_DOWNLOAD "\xf3\xb1\x8d\xbe" // U+F137E +#define ICON_MDI_AUTO_FIX "\xf3\xb0\x81\xa8" // U+F0068 +#define ICON_MDI_AUTO_MODE "\xf3\xb1\xb0\xa0" // U+F1C20 +#define ICON_MDI_AUTO_UPLOAD "\xf3\xb0\x81\xa9" // U+F0069 +#define ICON_MDI_AUTORENEW "\xf3\xb0\x81\xaa" // U+F006A +#define ICON_MDI_AUTORENEW_OFF "\xf3\xb1\xa7\xa7" // U+F19E7 +#define ICON_MDI_AV_TIMER "\xf3\xb0\x81\xab" // U+F006B +#define ICON_MDI_AWNING "\xf3\xb1\xae\x87" // U+F1B87 +#define ICON_MDI_AWNING_OUTLINE "\xf3\xb1\xae\x88" // U+F1B88 +#define ICON_MDI_AWS "\xf3\xb0\xb8\x8f" // U+F0E0F +#define ICON_MDI_AXE "\xf3\xb0\xa3\x88" // U+F08C8 +#define ICON_MDI_AXE_BATTLE "\xf3\xb1\xa1\x82" // U+F1842 +#define ICON_MDI_AXIS "\xf3\xb0\xb5\x88" // U+F0D48 +#define ICON_MDI_AXIS_ARROW "\xf3\xb0\xb5\x89" // U+F0D49 +#define ICON_MDI_AXIS_ARROW_INFO "\xf3\xb1\x90\x8e" // U+F140E +#define ICON_MDI_AXIS_ARROW_LOCK "\xf3\xb0\xb5\x8a" // U+F0D4A +#define ICON_MDI_AXIS_LOCK "\xf3\xb0\xb5\x8b" // U+F0D4B +#define ICON_MDI_AXIS_X_ARROW "\xf3\xb0\xb5\x8c" // U+F0D4C +#define ICON_MDI_AXIS_X_ARROW_LOCK "\xf3\xb0\xb5\x8d" // U+F0D4D +#define ICON_MDI_AXIS_X_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x8e" // U+F0D4E +#define ICON_MDI_AXIS_X_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x8f" // U+F0D4F +#define ICON_MDI_AXIS_X_Y_ARROW_LOCK "\xf3\xb0\xb5\x90" // U+F0D50 +#define ICON_MDI_AXIS_Y_ARROW "\xf3\xb0\xb5\x91" // U+F0D51 +#define ICON_MDI_AXIS_Y_ARROW_LOCK "\xf3\xb0\xb5\x92" // U+F0D52 +#define ICON_MDI_AXIS_Y_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x93" // U+F0D53 +#define ICON_MDI_AXIS_Y_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x94" // U+F0D54 +#define ICON_MDI_AXIS_Z_ARROW "\xf3\xb0\xb5\x95" // U+F0D55 +#define ICON_MDI_AXIS_Z_ARROW_LOCK "\xf3\xb0\xb5\x96" // U+F0D56 +#define ICON_MDI_AXIS_Z_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x97" // U+F0D57 +#define ICON_MDI_AXIS_Z_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x98" // U+F0D58 +#define ICON_MDI_BABEL "\xf3\xb0\xa8\xa5" // U+F0A25 +#define ICON_MDI_BABY "\xf3\xb0\x81\xac" // U+F006C +#define ICON_MDI_BABY_BOTTLE "\xf3\xb0\xbc\xb9" // U+F0F39 +#define ICON_MDI_BABY_BOTTLE_OUTLINE "\xf3\xb0\xbc\xba" // U+F0F3A +#define ICON_MDI_BABY_BUGGY "\xf3\xb1\x8f\xa0" // U+F13E0 +#define ICON_MDI_BABY_BUGGY_OFF "\xf3\xb1\xab\xb3" // U+F1AF3 +#define ICON_MDI_BABY_CARRIAGE "\xf3\xb0\x9a\x8f" // U+F068F +#define ICON_MDI_BABY_CARRIAGE_OFF "\xf3\xb0\xbe\xa0" // U+F0FA0 +#define ICON_MDI_BABY_FACE "\xf3\xb0\xb9\xbc" // U+F0E7C +#define ICON_MDI_BABY_FACE_OUTLINE "\xf3\xb0\xb9\xbd" // U+F0E7D +#define ICON_MDI_BACKBURGER "\xf3\xb0\x81\xad" // U+F006D +#define ICON_MDI_BACKSPACE "\xf3\xb0\x81\xae" // U+F006E +#define ICON_MDI_BACKSPACE_OUTLINE "\xf3\xb0\xad\x9c" // U+F0B5C +#define ICON_MDI_BACKSPACE_REVERSE "\xf3\xb0\xb9\xbe" // U+F0E7E +#define ICON_MDI_BACKSPACE_REVERSE_OUTLINE "\xf3\xb0\xb9\xbf" // U+F0E7F +#define ICON_MDI_BACKUP_RESTORE "\xf3\xb0\x81\xaf" // U+F006F +#define ICON_MDI_BACTERIA "\xf3\xb0\xbb\x95" // U+F0ED5 +#define ICON_MDI_BACTERIA_OUTLINE "\xf3\xb0\xbb\x96" // U+F0ED6 +#define ICON_MDI_BADGE_ACCOUNT "\xf3\xb0\xb6\xa7" // U+F0DA7 +#define ICON_MDI_BADGE_ACCOUNT_ALERT "\xf3\xb0\xb6\xa8" // U+F0DA8 +#define ICON_MDI_BADGE_ACCOUNT_ALERT_OUTLINE "\xf3\xb0\xb6\xa9" // U+F0DA9 +#define ICON_MDI_BADGE_ACCOUNT_HORIZONTAL "\xf3\xb0\xb8\x8d" // U+F0E0D +#define ICON_MDI_BADGE_ACCOUNT_HORIZONTAL_OUTLINE "\xf3\xb0\xb8\x8e" // U+F0E0E +#define ICON_MDI_BADGE_ACCOUNT_OUTLINE "\xf3\xb0\xb6\xaa" // U+F0DAA +#define ICON_MDI_BADMINTON "\xf3\xb0\xa1\x91" // U+F0851 +#define ICON_MDI_BAG_CARRY_ON "\xf3\xb0\xbc\xbb" // U+F0F3B +#define ICON_MDI_BAG_CARRY_ON_CHECK "\xf3\xb0\xb5\xa5" // U+F0D65 +#define ICON_MDI_BAG_CARRY_ON_OFF "\xf3\xb0\xbc\xbc" // U+F0F3C +#define ICON_MDI_BAG_CHECKED "\xf3\xb0\xbc\xbd" // U+F0F3D +#define ICON_MDI_BAG_PERSONAL "\xf3\xb0\xb8\x90" // U+F0E10 +#define ICON_MDI_BAG_PERSONAL_OFF "\xf3\xb0\xb8\x91" // U+F0E11 +#define ICON_MDI_BAG_PERSONAL_OFF_OUTLINE "\xf3\xb0\xb8\x92" // U+F0E12 +#define ICON_MDI_BAG_PERSONAL_OUTLINE "\xf3\xb0\xb8\x93" // U+F0E13 +#define ICON_MDI_BAG_PERSONAL_PLUS "\xf3\xb1\xb2\xa4" // U+F1CA4 +#define ICON_MDI_BAG_PERSONAL_PLUS_OUTLINE "\xf3\xb1\xb2\xa5" // U+F1CA5 +#define ICON_MDI_BAG_PERSONAL_TAG "\xf3\xb1\xac\x8c" // U+F1B0C +#define ICON_MDI_BAG_PERSONAL_TAG_OUTLINE "\xf3\xb1\xac\x8d" // U+F1B0D +#define ICON_MDI_BAG_SUITCASE "\xf3\xb1\x96\x8b" // U+F158B +#define ICON_MDI_BAG_SUITCASE_OFF "\xf3\xb1\x96\x8d" // U+F158D +#define ICON_MDI_BAG_SUITCASE_OFF_OUTLINE "\xf3\xb1\x96\x8e" // U+F158E +#define ICON_MDI_BAG_SUITCASE_OUTLINE "\xf3\xb1\x96\x8c" // U+F158C +#define ICON_MDI_BAGUETTE "\xf3\xb0\xbc\xbe" // U+F0F3E +#define ICON_MDI_BALCONY "\xf3\xb1\xa0\x97" // U+F1817 +#define ICON_MDI_BALLOON "\xf3\xb0\xa8\xa6" // U+F0A26 +#define ICON_MDI_BALLOT "\xf3\xb0\xa7\x89" // U+F09C9 +#define ICON_MDI_BALLOT_OUTLINE "\xf3\xb0\xa7\x8a" // U+F09CA +#define ICON_MDI_BALLOT_RECOUNT "\xf3\xb0\xb0\xb9" // U+F0C39 +#define ICON_MDI_BALLOT_RECOUNT_OUTLINE "\xf3\xb0\xb0\xba" // U+F0C3A +#define ICON_MDI_BANDAGE "\xf3\xb0\xb6\xaf" // U+F0DAF +#define ICON_MDI_BANK "\xf3\xb0\x81\xb0" // U+F0070 +#define ICON_MDI_BANK_CHECK "\xf3\xb1\x99\x95" // U+F1655 +#define ICON_MDI_BANK_CIRCLE "\xf3\xb1\xb0\x83" // U+F1C03 +#define ICON_MDI_BANK_CIRCLE_OUTLINE "\xf3\xb1\xb0\x84" // U+F1C04 +#define ICON_MDI_BANK_MINUS "\xf3\xb0\xb6\xb0" // U+F0DB0 +#define ICON_MDI_BANK_OFF "\xf3\xb1\x99\x96" // U+F1656 +#define ICON_MDI_BANK_OFF_OUTLINE "\xf3\xb1\x99\x97" // U+F1657 +#define ICON_MDI_BANK_OUTLINE "\xf3\xb0\xba\x80" // U+F0E80 +#define ICON_MDI_BANK_PLUS "\xf3\xb0\xb6\xb1" // U+F0DB1 +#define ICON_MDI_BANK_REMOVE "\xf3\xb0\xb6\xb2" // U+F0DB2 +#define ICON_MDI_BANK_TRANSFER "\xf3\xb0\xa8\xa7" // U+F0A27 +#define ICON_MDI_BANK_TRANSFER_IN "\xf3\xb0\xa8\xa8" // U+F0A28 +#define ICON_MDI_BANK_TRANSFER_OUT "\xf3\xb0\xa8\xa9" // U+F0A29 +#define ICON_MDI_BARCODE "\xf3\xb0\x81\xb1" // U+F0071 +#define ICON_MDI_BARCODE_OFF "\xf3\xb1\x88\xb6" // U+F1236 +#define ICON_MDI_BARCODE_SCAN "\xf3\xb0\x81\xb2" // U+F0072 +#define ICON_MDI_BARLEY "\xf3\xb0\x81\xb3" // U+F0073 +#define ICON_MDI_BARLEY_OFF "\xf3\xb0\xad\x9d" // U+F0B5D +#define ICON_MDI_BARN "\xf3\xb0\xad\x9e" // U+F0B5E +#define ICON_MDI_BARREL "\xf3\xb0\x81\xb4" // U+F0074 +#define ICON_MDI_BARREL_OUTLINE "\xf3\xb1\xa8\xa8" // U+F1A28 +#define ICON_MDI_BASEBALL "\xf3\xb0\xa1\x92" // U+F0852 +#define ICON_MDI_BASEBALL_BAT "\xf3\xb0\xa1\x93" // U+F0853 +#define ICON_MDI_BASEBALL_DIAMOND "\xf3\xb1\x97\xac" // U+F15EC +#define ICON_MDI_BASEBALL_DIAMOND_OUTLINE "\xf3\xb1\x97\xad" // U+F15ED +#define ICON_MDI_BASEBALL_OUTLINE "\xf3\xb1\xb1\x9a" // U+F1C5A +#define ICON_MDI_BASH "\xf3\xb1\x86\x83" // U+F1183 +#define ICON_MDI_BASKET "\xf3\xb0\x81\xb6" // U+F0076 +#define ICON_MDI_BASKET_CHECK "\xf3\xb1\xa3\xa5" // U+F18E5 +#define ICON_MDI_BASKET_CHECK_OUTLINE "\xf3\xb1\xa3\xa6" // U+F18E6 +#define ICON_MDI_BASKET_FILL "\xf3\xb0\x81\xb7" // U+F0077 +#define ICON_MDI_BASKET_MINUS "\xf3\xb1\x94\xa3" // U+F1523 +#define ICON_MDI_BASKET_MINUS_OUTLINE "\xf3\xb1\x94\xa4" // U+F1524 +#define ICON_MDI_BASKET_OFF "\xf3\xb1\x94\xa5" // U+F1525 +#define ICON_MDI_BASKET_OFF_OUTLINE "\xf3\xb1\x94\xa6" // U+F1526 +#define ICON_MDI_BASKET_OUTLINE "\xf3\xb1\x86\x81" // U+F1181 +#define ICON_MDI_BASKET_PLUS "\xf3\xb1\x94\xa7" // U+F1527 +#define ICON_MDI_BASKET_PLUS_OUTLINE "\xf3\xb1\x94\xa8" // U+F1528 +#define ICON_MDI_BASKET_REMOVE "\xf3\xb1\x94\xa9" // U+F1529 +#define ICON_MDI_BASKET_REMOVE_OUTLINE "\xf3\xb1\x94\xaa" // U+F152A +#define ICON_MDI_BASKET_UNFILL "\xf3\xb0\x81\xb8" // U+F0078 +#define ICON_MDI_BASKETBALL "\xf3\xb0\xa0\x86" // U+F0806 +#define ICON_MDI_BASKETBALL_HOOP "\xf3\xb0\xb0\xbb" // U+F0C3B +#define ICON_MDI_BASKETBALL_HOOP_OUTLINE "\xf3\xb0\xb0\xbc" // U+F0C3C +#define ICON_MDI_BAT "\xf3\xb0\xad\x9f" // U+F0B5F +#define ICON_MDI_BATHTUB "\xf3\xb1\xa0\x98" // U+F1818 +#define ICON_MDI_BATHTUB_OUTLINE "\xf3\xb1\xa0\x99" // U+F1819 +#define ICON_MDI_BATTERY "\xf3\xb0\x81\xb9" // U+F0079 +#define ICON_MDI_BATTERY_10 "\xf3\xb0\x81\xba" // U+F007A +#define ICON_MDI_BATTERY_10_BLUETOOTH "\xf3\xb0\xa4\xbe" // U+F093E +#define ICON_MDI_BATTERY_20 "\xf3\xb0\x81\xbb" // U+F007B +#define ICON_MDI_BATTERY_20_BLUETOOTH "\xf3\xb0\xa4\xbf" // U+F093F +#define ICON_MDI_BATTERY_30 "\xf3\xb0\x81\xbc" // U+F007C +#define ICON_MDI_BATTERY_30_BLUETOOTH "\xf3\xb0\xa5\x80" // U+F0940 +#define ICON_MDI_BATTERY_40 "\xf3\xb0\x81\xbd" // U+F007D +#define ICON_MDI_BATTERY_40_BLUETOOTH "\xf3\xb0\xa5\x81" // U+F0941 +#define ICON_MDI_BATTERY_50 "\xf3\xb0\x81\xbe" // U+F007E +#define ICON_MDI_BATTERY_50_BLUETOOTH "\xf3\xb0\xa5\x82" // U+F0942 +#define ICON_MDI_BATTERY_60 "\xf3\xb0\x81\xbf" // U+F007F +#define ICON_MDI_BATTERY_60_BLUETOOTH "\xf3\xb0\xa5\x83" // U+F0943 +#define ICON_MDI_BATTERY_70 "\xf3\xb0\x82\x80" // U+F0080 +#define ICON_MDI_BATTERY_70_BLUETOOTH "\xf3\xb0\xa5\x84" // U+F0944 +#define ICON_MDI_BATTERY_80 "\xf3\xb0\x82\x81" // U+F0081 +#define ICON_MDI_BATTERY_80_BLUETOOTH "\xf3\xb0\xa5\x85" // U+F0945 +#define ICON_MDI_BATTERY_90 "\xf3\xb0\x82\x82" // U+F0082 +#define ICON_MDI_BATTERY_90_BLUETOOTH "\xf3\xb0\xa5\x86" // U+F0946 +#define ICON_MDI_BATTERY_ALERT "\xf3\xb0\x82\x83" // U+F0083 +#define ICON_MDI_BATTERY_ALERT_BLUETOOTH "\xf3\xb0\xa5\x87" // U+F0947 +#define ICON_MDI_BATTERY_ALERT_VARIANT "\xf3\xb1\x83\x8c" // U+F10CC +#define ICON_MDI_BATTERY_ALERT_VARIANT_OUTLINE "\xf3\xb1\x83\x8d" // U+F10CD +#define ICON_MDI_BATTERY_ARROW_DOWN "\xf3\xb1\x9f\x9e" // U+F17DE +#define ICON_MDI_BATTERY_ARROW_DOWN_OUTLINE "\xf3\xb1\x9f\x9f" // U+F17DF +#define ICON_MDI_BATTERY_ARROW_UP "\xf3\xb1\x9f\xa0" // U+F17E0 +#define ICON_MDI_BATTERY_ARROW_UP_OUTLINE "\xf3\xb1\x9f\xa1" // U+F17E1 +#define ICON_MDI_BATTERY_BLUETOOTH "\xf3\xb0\xa5\x88" // U+F0948 +#define ICON_MDI_BATTERY_BLUETOOTH_VARIANT "\xf3\xb0\xa5\x89" // U+F0949 +#define ICON_MDI_BATTERY_CHARGING "\xf3\xb0\x82\x84" // U+F0084 +#define ICON_MDI_BATTERY_CHARGING_10 "\xf3\xb0\xa2\x9c" // U+F089C +#define ICON_MDI_BATTERY_CHARGING_100 "\xf3\xb0\x82\x85" // U+F0085 +#define ICON_MDI_BATTERY_CHARGING_20 "\xf3\xb0\x82\x86" // U+F0086 +#define ICON_MDI_BATTERY_CHARGING_30 "\xf3\xb0\x82\x87" // U+F0087 +#define ICON_MDI_BATTERY_CHARGING_40 "\xf3\xb0\x82\x88" // U+F0088 +#define ICON_MDI_BATTERY_CHARGING_50 "\xf3\xb0\xa2\x9d" // U+F089D +#define ICON_MDI_BATTERY_CHARGING_60 "\xf3\xb0\x82\x89" // U+F0089 +#define ICON_MDI_BATTERY_CHARGING_70 "\xf3\xb0\xa2\x9e" // U+F089E +#define ICON_MDI_BATTERY_CHARGING_80 "\xf3\xb0\x82\x8a" // U+F008A +#define ICON_MDI_BATTERY_CHARGING_90 "\xf3\xb0\x82\x8b" // U+F008B +#define ICON_MDI_BATTERY_CHARGING_HIGH "\xf3\xb1\x8a\xa6" // U+F12A6 +#define ICON_MDI_BATTERY_CHARGING_LOW "\xf3\xb1\x8a\xa4" // U+F12A4 +#define ICON_MDI_BATTERY_CHARGING_MEDIUM "\xf3\xb1\x8a\xa5" // U+F12A5 +#define ICON_MDI_BATTERY_CHARGING_OUTLINE "\xf3\xb0\xa2\x9f" // U+F089F +#define ICON_MDI_BATTERY_CHARGING_WIRELESS "\xf3\xb0\xa0\x87" // U+F0807 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_10 "\xf3\xb0\xa0\x88" // U+F0808 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_20 "\xf3\xb0\xa0\x89" // U+F0809 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_30 "\xf3\xb0\xa0\x8a" // U+F080A +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_40 "\xf3\xb0\xa0\x8b" // U+F080B +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_50 "\xf3\xb0\xa0\x8c" // U+F080C +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_60 "\xf3\xb0\xa0\x8d" // U+F080D +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_70 "\xf3\xb0\xa0\x8e" // U+F080E +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_80 "\xf3\xb0\xa0\x8f" // U+F080F +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_90 "\xf3\xb0\xa0\x90" // U+F0810 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_ALERT "\xf3\xb0\xa0\x91" // U+F0811 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_OUTLINE "\xf3\xb0\xa0\x92" // U+F0812 +#define ICON_MDI_BATTERY_CHECK "\xf3\xb1\x9f\xa2" // U+F17E2 +#define ICON_MDI_BATTERY_CHECK_OUTLINE "\xf3\xb1\x9f\xa3" // U+F17E3 +#define ICON_MDI_BATTERY_CLOCK "\xf3\xb1\xa7\xa5" // U+F19E5 +#define ICON_MDI_BATTERY_CLOCK_OUTLINE "\xf3\xb1\xa7\xa6" // U+F19E6 +#define ICON_MDI_BATTERY_HEART "\xf3\xb1\x88\x8f" // U+F120F +#define ICON_MDI_BATTERY_HEART_OUTLINE "\xf3\xb1\x88\x90" // U+F1210 +#define ICON_MDI_BATTERY_HEART_VARIANT "\xf3\xb1\x88\x91" // U+F1211 +#define ICON_MDI_BATTERY_HIGH "\xf3\xb1\x8a\xa3" // U+F12A3 +#define ICON_MDI_BATTERY_LOCK "\xf3\xb1\x9e\x9c" // U+F179C +#define ICON_MDI_BATTERY_LOCK_OPEN "\xf3\xb1\x9e\x9d" // U+F179D +#define ICON_MDI_BATTERY_LOW "\xf3\xb1\x8a\xa1" // U+F12A1 +#define ICON_MDI_BATTERY_MEDIUM "\xf3\xb1\x8a\xa2" // U+F12A2 +#define ICON_MDI_BATTERY_MINUS "\xf3\xb1\x9f\xa4" // U+F17E4 +#define ICON_MDI_BATTERY_MINUS_OUTLINE "\xf3\xb1\x9f\xa5" // U+F17E5 +#define ICON_MDI_BATTERY_MINUS_VARIANT "\xf3\xb0\x82\x8c" // U+F008C +#define ICON_MDI_BATTERY_NEGATIVE "\xf3\xb0\x82\x8d" // U+F008D +#define ICON_MDI_BATTERY_OFF "\xf3\xb1\x89\x9d" // U+F125D +#define ICON_MDI_BATTERY_OFF_OUTLINE "\xf3\xb1\x89\x9e" // U+F125E +#define ICON_MDI_BATTERY_OUTLINE "\xf3\xb0\x82\x8e" // U+F008E +#define ICON_MDI_BATTERY_PLUS "\xf3\xb1\x9f\xa6" // U+F17E6 +#define ICON_MDI_BATTERY_PLUS_OUTLINE "\xf3\xb1\x9f\xa7" // U+F17E7 +#define ICON_MDI_BATTERY_PLUS_VARIANT "\xf3\xb0\x82\x8f" // U+F008F +#define ICON_MDI_BATTERY_POSITIVE "\xf3\xb0\x82\x90" // U+F0090 +#define ICON_MDI_BATTERY_REMOVE "\xf3\xb1\x9f\xa8" // U+F17E8 +#define ICON_MDI_BATTERY_REMOVE_OUTLINE "\xf3\xb1\x9f\xa9" // U+F17E9 +#define ICON_MDI_BATTERY_SYNC "\xf3\xb1\xa0\xb4" // U+F1834 +#define ICON_MDI_BATTERY_SYNC_OUTLINE "\xf3\xb1\xa0\xb5" // U+F1835 +#define ICON_MDI_BATTERY_UNKNOWN "\xf3\xb0\x82\x91" // U+F0091 +#define ICON_MDI_BATTERY_UNKNOWN_BLUETOOTH "\xf3\xb0\xa5\x8a" // U+F094A +#define ICON_MDI_BEACH "\xf3\xb0\x82\x92" // U+F0092 +#define ICON_MDI_BEAKER "\xf3\xb0\xb3\xaa" // U+F0CEA +#define ICON_MDI_BEAKER_ALERT "\xf3\xb1\x88\xa9" // U+F1229 +#define ICON_MDI_BEAKER_ALERT_OUTLINE "\xf3\xb1\x88\xaa" // U+F122A +#define ICON_MDI_BEAKER_CHECK "\xf3\xb1\x88\xab" // U+F122B +#define ICON_MDI_BEAKER_CHECK_OUTLINE "\xf3\xb1\x88\xac" // U+F122C +#define ICON_MDI_BEAKER_MINUS "\xf3\xb1\x88\xad" // U+F122D +#define ICON_MDI_BEAKER_MINUS_OUTLINE "\xf3\xb1\x88\xae" // U+F122E +#define ICON_MDI_BEAKER_OUTLINE "\xf3\xb0\x9a\x90" // U+F0690 +#define ICON_MDI_BEAKER_PLUS "\xf3\xb1\x88\xaf" // U+F122F +#define ICON_MDI_BEAKER_PLUS_OUTLINE "\xf3\xb1\x88\xb0" // U+F1230 +#define ICON_MDI_BEAKER_QUESTION "\xf3\xb1\x88\xb1" // U+F1231 +#define ICON_MDI_BEAKER_QUESTION_OUTLINE "\xf3\xb1\x88\xb2" // U+F1232 +#define ICON_MDI_BEAKER_REMOVE "\xf3\xb1\x88\xb3" // U+F1233 +#define ICON_MDI_BEAKER_REMOVE_OUTLINE "\xf3\xb1\x88\xb4" // U+F1234 +#define ICON_MDI_BED "\xf3\xb0\x8b\xa3" // U+F02E3 +#define ICON_MDI_BED_CLOCK "\xf3\xb1\xae\x94" // U+F1B94 +#define ICON_MDI_BED_DOUBLE "\xf3\xb0\xbf\x94" // U+F0FD4 +#define ICON_MDI_BED_DOUBLE_OUTLINE "\xf3\xb0\xbf\x93" // U+F0FD3 +#define ICON_MDI_BED_EMPTY "\xf3\xb0\xa2\xa0" // U+F08A0 +#define ICON_MDI_BED_KING "\xf3\xb0\xbf\x92" // U+F0FD2 +#define ICON_MDI_BED_KING_OUTLINE "\xf3\xb0\xbf\x91" // U+F0FD1 +#define ICON_MDI_BED_OUTLINE "\xf3\xb0\x82\x99" // U+F0099 +#define ICON_MDI_BED_QUEEN "\xf3\xb0\xbf\x90" // U+F0FD0 +#define ICON_MDI_BED_QUEEN_OUTLINE "\xf3\xb0\xbf\x9b" // U+F0FDB +#define ICON_MDI_BED_SINGLE "\xf3\xb1\x81\xad" // U+F106D +#define ICON_MDI_BED_SINGLE_OUTLINE "\xf3\xb1\x81\xae" // U+F106E +#define ICON_MDI_BEE "\xf3\xb0\xbe\xa1" // U+F0FA1 +#define ICON_MDI_BEE_FLOWER "\xf3\xb0\xbe\xa2" // U+F0FA2 +#define ICON_MDI_BEEHIVE_OFF_OUTLINE "\xf3\xb1\x8f\xad" // U+F13ED +#define ICON_MDI_BEEHIVE_OUTLINE "\xf3\xb1\x83\x8e" // U+F10CE +#define ICON_MDI_BEEKEEPER "\xf3\xb1\x93\xa2" // U+F14E2 +#define ICON_MDI_BEER "\xf3\xb0\x82\x98" // U+F0098 +#define ICON_MDI_BEER_OUTLINE "\xf3\xb1\x8c\x8c" // U+F130C +#define ICON_MDI_BELL "\xf3\xb0\x82\x9a" // U+F009A +#define ICON_MDI_BELL_ALERT "\xf3\xb0\xb5\x99" // U+F0D59 +#define ICON_MDI_BELL_ALERT_OUTLINE "\xf3\xb0\xba\x81" // U+F0E81 +#define ICON_MDI_BELL_BADGE "\xf3\xb1\x85\xab" // U+F116B +#define ICON_MDI_BELL_BADGE_OUTLINE "\xf3\xb0\x85\xb8" // U+F0178 +#define ICON_MDI_BELL_CANCEL "\xf3\xb1\x8f\xa7" // U+F13E7 +#define ICON_MDI_BELL_CANCEL_OUTLINE "\xf3\xb1\x8f\xa8" // U+F13E8 +#define ICON_MDI_BELL_CHECK "\xf3\xb1\x87\xa5" // U+F11E5 +#define ICON_MDI_BELL_CHECK_OUTLINE "\xf3\xb1\x87\xa6" // U+F11E6 +#define ICON_MDI_BELL_CIRCLE "\xf3\xb0\xb5\x9a" // U+F0D5A +#define ICON_MDI_BELL_CIRCLE_OUTLINE "\xf3\xb0\xb5\x9b" // U+F0D5B +#define ICON_MDI_BELL_COG "\xf3\xb1\xa8\xa9" // U+F1A29 +#define ICON_MDI_BELL_COG_OUTLINE "\xf3\xb1\xa8\xaa" // U+F1A2A +#define ICON_MDI_BELL_MINUS "\xf3\xb1\x8f\xa9" // U+F13E9 +#define ICON_MDI_BELL_MINUS_OUTLINE "\xf3\xb1\x8f\xaa" // U+F13EA +#define ICON_MDI_BELL_OFF "\xf3\xb0\x82\x9b" // U+F009B +#define ICON_MDI_BELL_OFF_OUTLINE "\xf3\xb0\xaa\x91" // U+F0A91 +#define ICON_MDI_BELL_OUTLINE "\xf3\xb0\x82\x9c" // U+F009C +#define ICON_MDI_BELL_PLUS "\xf3\xb0\x82\x9d" // U+F009D +#define ICON_MDI_BELL_PLUS_OUTLINE "\xf3\xb0\xaa\x92" // U+F0A92 +#define ICON_MDI_BELL_REMOVE "\xf3\xb1\x8f\xab" // U+F13EB +#define ICON_MDI_BELL_REMOVE_OUTLINE "\xf3\xb1\x8f\xac" // U+F13EC +#define ICON_MDI_BELL_RING "\xf3\xb0\x82\x9e" // U+F009E +#define ICON_MDI_BELL_RING_OUTLINE "\xf3\xb0\x82\x9f" // U+F009F +#define ICON_MDI_BELL_SLEEP "\xf3\xb0\x82\xa0" // U+F00A0 +#define ICON_MDI_BELL_SLEEP_OUTLINE "\xf3\xb0\xaa\x93" // U+F0A93 +#define ICON_MDI_BENCH "\xf3\xb1\xb0\xa1" // U+F1C21 +#define ICON_MDI_BENCH_BACK "\xf3\xb1\xb0\xa2" // U+F1C22 +#define ICON_MDI_BETA "\xf3\xb0\x82\xa1" // U+F00A1 +#define ICON_MDI_BETAMAX "\xf3\xb0\xa7\x8b" // U+F09CB +#define ICON_MDI_BIATHLON "\xf3\xb0\xb8\x94" // U+F0E14 +#define ICON_MDI_BICYCLE "\xf3\xb1\x82\x9c" // U+F109C +#define ICON_MDI_BICYCLE_BASKET "\xf3\xb1\x88\xb5" // U+F1235 +#define ICON_MDI_BICYCLE_CARGO "\xf3\xb1\xa2\x9c" // U+F189C +#define ICON_MDI_BICYCLE_ELECTRIC "\xf3\xb1\x96\xb4" // U+F15B4 +#define ICON_MDI_BICYCLE_PENNY_FARTHING "\xf3\xb1\x97\xa9" // U+F15E9 +#define ICON_MDI_BIKE "\xf3\xb0\x82\xa3" // U+F00A3 +#define ICON_MDI_BIKE_FAST "\xf3\xb1\x84\x9f" // U+F111F +#define ICON_MDI_BIKE_PEDAL "\xf3\xb1\xb0\xa3" // U+F1C23 +#define ICON_MDI_BIKE_PEDAL_CLIPLESS "\xf3\xb1\xb0\xa4" // U+F1C24 +#define ICON_MDI_BIKE_PEDAL_MOUNTAIN "\xf3\xb1\xb0\xa5" // U+F1C25 +#define ICON_MDI_BILLBOARD "\xf3\xb1\x80\x90" // U+F1010 +#define ICON_MDI_BILLIARDS "\xf3\xb0\xad\xa1" // U+F0B61 +#define ICON_MDI_BILLIARDS_RACK "\xf3\xb0\xad\xa2" // U+F0B62 +#define ICON_MDI_BINOCULARS "\xf3\xb0\x82\xa5" // U+F00A5 +#define ICON_MDI_BIO "\xf3\xb0\x82\xa6" // U+F00A6 +#define ICON_MDI_BIOHAZARD "\xf3\xb0\x82\xa7" // U+F00A7 +#define ICON_MDI_BIRD "\xf3\xb1\x97\x86" // U+F15C6 +#define ICON_MDI_BITBUCKET "\xf3\xb0\x82\xa8" // U+F00A8 +#define ICON_MDI_BITCOIN "\xf3\xb0\xa0\x93" // U+F0813 +#define ICON_MDI_BLACK_MESA "\xf3\xb0\x82\xa9" // U+F00A9 +#define ICON_MDI_BLENDER "\xf3\xb0\xb3\xab" // U+F0CEB +#define ICON_MDI_BLENDER_OUTLINE "\xf3\xb1\xa0\x9a" // U+F181A +#define ICON_MDI_BLENDER_SOFTWARE "\xf3\xb0\x82\xab" // U+F00AB +#define ICON_MDI_BLINDS "\xf3\xb0\x82\xac" // U+F00AC +#define ICON_MDI_BLINDS_HORIZONTAL "\xf3\xb1\xa8\xab" // U+F1A2B +#define ICON_MDI_BLINDS_HORIZONTAL_CLOSED "\xf3\xb1\xa8\xac" // U+F1A2C +#define ICON_MDI_BLINDS_OPEN "\xf3\xb1\x80\x91" // U+F1011 +#define ICON_MDI_BLINDS_VERTICAL "\xf3\xb1\xa8\xad" // U+F1A2D +#define ICON_MDI_BLINDS_VERTICAL_CLOSED "\xf3\xb1\xa8\xae" // U+F1A2E +#define ICON_MDI_BLOCK_HELPER "\xf3\xb0\x82\xad" // U+F00AD +#define ICON_MDI_BLOOD_BAG "\xf3\xb0\xb3\xac" // U+F0CEC +#define ICON_MDI_BLUETOOTH "\xf3\xb0\x82\xaf" // U+F00AF +#define ICON_MDI_BLUETOOTH_AUDIO "\xf3\xb0\x82\xb0" // U+F00B0 +#define ICON_MDI_BLUETOOTH_CONNECT "\xf3\xb0\x82\xb1" // U+F00B1 +#define ICON_MDI_BLUETOOTH_OFF "\xf3\xb0\x82\xb2" // U+F00B2 +#define ICON_MDI_BLUETOOTH_SETTINGS "\xf3\xb0\x82\xb3" // U+F00B3 +#define ICON_MDI_BLUETOOTH_TRANSFER "\xf3\xb0\x82\xb4" // U+F00B4 +#define ICON_MDI_BLUR "\xf3\xb0\x82\xb5" // U+F00B5 +#define ICON_MDI_BLUR_LINEAR "\xf3\xb0\x82\xb6" // U+F00B6 +#define ICON_MDI_BLUR_OFF "\xf3\xb0\x82\xb7" // U+F00B7 +#define ICON_MDI_BLUR_RADIAL "\xf3\xb0\x82\xb8" // U+F00B8 +#define ICON_MDI_BOLT "\xf3\xb0\xb6\xb3" // U+F0DB3 +#define ICON_MDI_BOMB "\xf3\xb0\x9a\x91" // U+F0691 +#define ICON_MDI_BOMB_OFF "\xf3\xb0\x9b\x85" // U+F06C5 +#define ICON_MDI_BONE "\xf3\xb0\x82\xb9" // U+F00B9 +#define ICON_MDI_BONE_OFF "\xf3\xb1\xa7\xa0" // U+F19E0 +#define ICON_MDI_BOOK "\xf3\xb0\x82\xba" // U+F00BA +#define ICON_MDI_BOOK_ACCOUNT "\xf3\xb1\x8e\xad" // U+F13AD +#define ICON_MDI_BOOK_ACCOUNT_OUTLINE "\xf3\xb1\x8e\xae" // U+F13AE +#define ICON_MDI_BOOK_ALERT "\xf3\xb1\x99\xbc" // U+F167C +#define ICON_MDI_BOOK_ALERT_OUTLINE "\xf3\xb1\x99\xbd" // U+F167D +#define ICON_MDI_BOOK_ALPHABET "\xf3\xb0\x98\x9d" // U+F061D +#define ICON_MDI_BOOK_ARROW_DOWN "\xf3\xb1\x99\xbe" // U+F167E +#define ICON_MDI_BOOK_ARROW_DOWN_OUTLINE "\xf3\xb1\x99\xbf" // U+F167F +#define ICON_MDI_BOOK_ARROW_LEFT "\xf3\xb1\x9a\x80" // U+F1680 +#define ICON_MDI_BOOK_ARROW_LEFT_OUTLINE "\xf3\xb1\x9a\x81" // U+F1681 +#define ICON_MDI_BOOK_ARROW_RIGHT "\xf3\xb1\x9a\x82" // U+F1682 +#define ICON_MDI_BOOK_ARROW_RIGHT_OUTLINE "\xf3\xb1\x9a\x83" // U+F1683 +#define ICON_MDI_BOOK_ARROW_UP "\xf3\xb1\x9a\x84" // U+F1684 +#define ICON_MDI_BOOK_ARROW_UP_OUTLINE "\xf3\xb1\x9a\x85" // U+F1685 +#define ICON_MDI_BOOK_CANCEL "\xf3\xb1\x9a\x86" // U+F1686 +#define ICON_MDI_BOOK_CANCEL_OUTLINE "\xf3\xb1\x9a\x87" // U+F1687 +#define ICON_MDI_BOOK_CHECK "\xf3\xb1\x93\xb3" // U+F14F3 +#define ICON_MDI_BOOK_CHECK_OUTLINE "\xf3\xb1\x93\xb4" // U+F14F4 +#define ICON_MDI_BOOK_CLOCK "\xf3\xb1\x9a\x88" // U+F1688 +#define ICON_MDI_BOOK_CLOCK_OUTLINE "\xf3\xb1\x9a\x89" // U+F1689 +#define ICON_MDI_BOOK_COG "\xf3\xb1\x9a\x8a" // U+F168A +#define ICON_MDI_BOOK_COG_OUTLINE "\xf3\xb1\x9a\x8b" // U+F168B +#define ICON_MDI_BOOK_CROSS "\xf3\xb0\x82\xa2" // U+F00A2 +#define ICON_MDI_BOOK_EDIT "\xf3\xb1\x9a\x8c" // U+F168C +#define ICON_MDI_BOOK_EDIT_OUTLINE "\xf3\xb1\x9a\x8d" // U+F168D +#define ICON_MDI_BOOK_EDUCATION "\xf3\xb1\x9b\x89" // U+F16C9 +#define ICON_MDI_BOOK_EDUCATION_OUTLINE "\xf3\xb1\x9b\x8a" // U+F16CA +#define ICON_MDI_BOOK_HEART "\xf3\xb1\xa8\x9d" // U+F1A1D +#define ICON_MDI_BOOK_HEART_OUTLINE "\xf3\xb1\xa8\x9e" // U+F1A1E +#define ICON_MDI_BOOK_INFORMATION_VARIANT "\xf3\xb1\x81\xaf" // U+F106F +#define ICON_MDI_BOOK_LOCK "\xf3\xb0\x9e\x9a" // U+F079A +#define ICON_MDI_BOOK_LOCK_OPEN "\xf3\xb0\x9e\x9b" // U+F079B +#define ICON_MDI_BOOK_LOCK_OPEN_OUTLINE "\xf3\xb1\x9a\x8e" // U+F168E +#define ICON_MDI_BOOK_LOCK_OUTLINE "\xf3\xb1\x9a\x8f" // U+F168F +#define ICON_MDI_BOOK_MARKER "\xf3\xb1\x9a\x90" // U+F1690 +#define ICON_MDI_BOOK_MARKER_OUTLINE "\xf3\xb1\x9a\x91" // U+F1691 +#define ICON_MDI_BOOK_MINUS "\xf3\xb0\x97\x99" // U+F05D9 +#define ICON_MDI_BOOK_MINUS_MULTIPLE "\xf3\xb0\xaa\x94" // U+F0A94 +#define ICON_MDI_BOOK_MINUS_MULTIPLE_OUTLINE "\xf3\xb0\xa4\x8b" // U+F090B +#define ICON_MDI_BOOK_MINUS_OUTLINE "\xf3\xb1\x9a\x92" // U+F1692 +#define ICON_MDI_BOOK_MULTIPLE "\xf3\xb0\x82\xbb" // U+F00BB +#define ICON_MDI_BOOK_MULTIPLE_OUTLINE "\xf3\xb0\x90\xb6" // U+F0436 +#define ICON_MDI_BOOK_MUSIC "\xf3\xb0\x81\xa7" // U+F0067 +#define ICON_MDI_BOOK_MUSIC_OUTLINE "\xf3\xb1\x9a\x93" // U+F1693 +#define ICON_MDI_BOOK_OFF "\xf3\xb1\x9a\x94" // U+F1694 +#define ICON_MDI_BOOK_OFF_OUTLINE "\xf3\xb1\x9a\x95" // U+F1695 +#define ICON_MDI_BOOK_OPEN "\xf3\xb0\x82\xbd" // U+F00BD +#define ICON_MDI_BOOK_OPEN_BLANK_VARIANT "\xf3\xb0\x82\xbe" // U+F00BE +#define ICON_MDI_BOOK_OPEN_OUTLINE "\xf3\xb0\xad\xa3" // U+F0B63 +#define ICON_MDI_BOOK_OPEN_PAGE_VARIANT "\xf3\xb0\x97\x9a" // U+F05DA +#define ICON_MDI_BOOK_OPEN_PAGE_VARIANT_OUTLINE "\xf3\xb1\x97\x96" // U+F15D6 +#define ICON_MDI_BOOK_OPEN_VARIANT "\xf3\xb1\x93\xb7" // U+F14F7 +#define ICON_MDI_BOOK_OUTLINE "\xf3\xb0\xad\xa4" // U+F0B64 +#define ICON_MDI_BOOK_PLAY "\xf3\xb0\xba\x82" // U+F0E82 +#define ICON_MDI_BOOK_PLAY_OUTLINE "\xf3\xb0\xba\x83" // U+F0E83 +#define ICON_MDI_BOOK_PLUS "\xf3\xb0\x97\x9b" // U+F05DB +#define ICON_MDI_BOOK_PLUS_MULTIPLE "\xf3\xb0\xaa\x95" // U+F0A95 +#define ICON_MDI_BOOK_PLUS_MULTIPLE_OUTLINE "\xf3\xb0\xab\x9e" // U+F0ADE +#define ICON_MDI_BOOK_PLUS_OUTLINE "\xf3\xb1\x9a\x96" // U+F1696 +#define ICON_MDI_BOOK_REFRESH "\xf3\xb1\x9a\x97" // U+F1697 +#define ICON_MDI_BOOK_REFRESH_OUTLINE "\xf3\xb1\x9a\x98" // U+F1698 +#define ICON_MDI_BOOK_REMOVE "\xf3\xb0\xaa\x97" // U+F0A97 +#define ICON_MDI_BOOK_REMOVE_MULTIPLE "\xf3\xb0\xaa\x96" // U+F0A96 +#define ICON_MDI_BOOK_REMOVE_MULTIPLE_OUTLINE "\xf3\xb0\x93\x8a" // U+F04CA +#define ICON_MDI_BOOK_REMOVE_OUTLINE "\xf3\xb1\x9a\x99" // U+F1699 +#define ICON_MDI_BOOK_SEARCH "\xf3\xb0\xba\x84" // U+F0E84 +#define ICON_MDI_BOOK_SEARCH_OUTLINE "\xf3\xb0\xba\x85" // U+F0E85 +#define ICON_MDI_BOOK_SETTINGS "\xf3\xb1\x9a\x9a" // U+F169A +#define ICON_MDI_BOOK_SETTINGS_OUTLINE "\xf3\xb1\x9a\x9b" // U+F169B +#define ICON_MDI_BOOK_SYNC "\xf3\xb1\x9a\x9c" // U+F169C +#define ICON_MDI_BOOK_SYNC_OUTLINE "\xf3\xb1\x9b\x88" // U+F16C8 +#define ICON_MDI_BOOK_VARIANT "\xf3\xb0\x82\xbf" // U+F00BF +#define ICON_MDI_BOOKMARK "\xf3\xb0\x83\x80" // U+F00C0 +#define ICON_MDI_BOOKMARK_BOX "\xf3\xb1\xad\xb5" // U+F1B75 +#define ICON_MDI_BOOKMARK_BOX_MULTIPLE "\xf3\xb1\xa5\xac" // U+F196C +#define ICON_MDI_BOOKMARK_BOX_MULTIPLE_OUTLINE "\xf3\xb1\xa5\xad" // U+F196D +#define ICON_MDI_BOOKMARK_BOX_OUTLINE "\xf3\xb1\xad\xb6" // U+F1B76 +#define ICON_MDI_BOOKMARK_CHECK "\xf3\xb0\x83\x81" // U+F00C1 +#define ICON_MDI_BOOKMARK_CHECK_OUTLINE "\xf3\xb1\x8d\xbb" // U+F137B +#define ICON_MDI_BOOKMARK_MINUS "\xf3\xb0\xa7\x8c" // U+F09CC +#define ICON_MDI_BOOKMARK_MINUS_OUTLINE "\xf3\xb0\xa7\x8d" // U+F09CD +#define ICON_MDI_BOOKMARK_MULTIPLE "\xf3\xb0\xb8\x95" // U+F0E15 +#define ICON_MDI_BOOKMARK_MULTIPLE_OUTLINE "\xf3\xb0\xb8\x96" // U+F0E16 +#define ICON_MDI_BOOKMARK_MUSIC "\xf3\xb0\x83\x82" // U+F00C2 +#define ICON_MDI_BOOKMARK_MUSIC_OUTLINE "\xf3\xb1\x8d\xb9" // U+F1379 +#define ICON_MDI_BOOKMARK_OFF "\xf3\xb0\xa7\x8e" // U+F09CE +#define ICON_MDI_BOOKMARK_OFF_OUTLINE "\xf3\xb0\xa7\x8f" // U+F09CF +#define ICON_MDI_BOOKMARK_OUTLINE "\xf3\xb0\x83\x83" // U+F00C3 +#define ICON_MDI_BOOKMARK_PLUS "\xf3\xb0\x83\x85" // U+F00C5 +#define ICON_MDI_BOOKMARK_PLUS_OUTLINE "\xf3\xb0\x83\x84" // U+F00C4 +#define ICON_MDI_BOOKMARK_REMOVE "\xf3\xb0\x83\x86" // U+F00C6 +#define ICON_MDI_BOOKMARK_REMOVE_OUTLINE "\xf3\xb1\x8d\xba" // U+F137A +#define ICON_MDI_BOOKSHELF "\xf3\xb1\x89\x9f" // U+F125F +#define ICON_MDI_BOOM_GATE "\xf3\xb0\xba\x86" // U+F0E86 +#define ICON_MDI_BOOM_GATE_ALERT "\xf3\xb0\xba\x87" // U+F0E87 +#define ICON_MDI_BOOM_GATE_ALERT_OUTLINE "\xf3\xb0\xba\x88" // U+F0E88 +#define ICON_MDI_BOOM_GATE_ARROW_DOWN "\xf3\xb0\xba\x89" // U+F0E89 +#define ICON_MDI_BOOM_GATE_ARROW_DOWN_OUTLINE "\xf3\xb0\xba\x8a" // U+F0E8A +#define ICON_MDI_BOOM_GATE_ARROW_UP "\xf3\xb0\xba\x8c" // U+F0E8C +#define ICON_MDI_BOOM_GATE_ARROW_UP_OUTLINE "\xf3\xb0\xba\x8d" // U+F0E8D +#define ICON_MDI_BOOM_GATE_OUTLINE "\xf3\xb0\xba\x8b" // U+F0E8B +#define ICON_MDI_BOOM_GATE_UP "\xf3\xb1\x9f\xb9" // U+F17F9 +#define ICON_MDI_BOOM_GATE_UP_OUTLINE "\xf3\xb1\x9f\xba" // U+F17FA +#define ICON_MDI_BOOMBOX "\xf3\xb0\x97\x9c" // U+F05DC +#define ICON_MDI_BOOMERANG "\xf3\xb1\x83\x8f" // U+F10CF +#define ICON_MDI_BOOTSTRAP "\xf3\xb0\x9b\x86" // U+F06C6 +#define ICON_MDI_BORDER_ALL "\xf3\xb0\x83\x87" // U+F00C7 +#define ICON_MDI_BORDER_ALL_VARIANT "\xf3\xb0\xa2\xa1" // U+F08A1 +#define ICON_MDI_BORDER_BOTTOM "\xf3\xb0\x83\x88" // U+F00C8 +#define ICON_MDI_BORDER_BOTTOM_VARIANT "\xf3\xb0\xa2\xa2" // U+F08A2 +#define ICON_MDI_BORDER_COLOR "\xf3\xb0\x83\x89" // U+F00C9 +#define ICON_MDI_BORDER_HORIZONTAL "\xf3\xb0\x83\x8a" // U+F00CA +#define ICON_MDI_BORDER_INSIDE "\xf3\xb0\x83\x8b" // U+F00CB +#define ICON_MDI_BORDER_LEFT "\xf3\xb0\x83\x8c" // U+F00CC +#define ICON_MDI_BORDER_LEFT_VARIANT "\xf3\xb0\xa2\xa3" // U+F08A3 +#define ICON_MDI_BORDER_NONE "\xf3\xb0\x83\x8d" // U+F00CD +#define ICON_MDI_BORDER_NONE_VARIANT "\xf3\xb0\xa2\xa4" // U+F08A4 +#define ICON_MDI_BORDER_OUTSIDE "\xf3\xb0\x83\x8e" // U+F00CE +#define ICON_MDI_BORDER_RADIUS "\xf3\xb1\xab\xb4" // U+F1AF4 +#define ICON_MDI_BORDER_RIGHT "\xf3\xb0\x83\x8f" // U+F00CF +#define ICON_MDI_BORDER_RIGHT_VARIANT "\xf3\xb0\xa2\xa5" // U+F08A5 +#define ICON_MDI_BORDER_STYLE "\xf3\xb0\x83\x90" // U+F00D0 +#define ICON_MDI_BORDER_TOP "\xf3\xb0\x83\x91" // U+F00D1 +#define ICON_MDI_BORDER_TOP_VARIANT "\xf3\xb0\xa2\xa6" // U+F08A6 +#define ICON_MDI_BORDER_VERTICAL "\xf3\xb0\x83\x92" // U+F00D2 +#define ICON_MDI_BOTTLE_SODA "\xf3\xb1\x81\xb0" // U+F1070 +#define ICON_MDI_BOTTLE_SODA_CLASSIC "\xf3\xb1\x81\xb1" // U+F1071 +#define ICON_MDI_BOTTLE_SODA_CLASSIC_OUTLINE "\xf3\xb1\x8d\xa3" // U+F1363 +#define ICON_MDI_BOTTLE_SODA_OUTLINE "\xf3\xb1\x81\xb2" // U+F1072 +#define ICON_MDI_BOTTLE_TONIC "\xf3\xb1\x84\xae" // U+F112E +#define ICON_MDI_BOTTLE_TONIC_OUTLINE "\xf3\xb1\x84\xaf" // U+F112F +#define ICON_MDI_BOTTLE_TONIC_PLUS "\xf3\xb1\x84\xb0" // U+F1130 +#define ICON_MDI_BOTTLE_TONIC_PLUS_OUTLINE "\xf3\xb1\x84\xb1" // U+F1131 +#define ICON_MDI_BOTTLE_TONIC_SKULL "\xf3\xb1\x84\xb2" // U+F1132 +#define ICON_MDI_BOTTLE_TONIC_SKULL_OUTLINE "\xf3\xb1\x84\xb3" // U+F1133 +#define ICON_MDI_BOTTLE_WINE "\xf3\xb0\xa1\x94" // U+F0854 +#define ICON_MDI_BOTTLE_WINE_OUTLINE "\xf3\xb1\x8c\x90" // U+F1310 +#define ICON_MDI_BOW_ARROW "\xf3\xb1\xa1\x81" // U+F1841 +#define ICON_MDI_BOW_TIE "\xf3\xb0\x99\xb8" // U+F0678 +#define ICON_MDI_BOWL "\xf3\xb0\x8a\x8e" // U+F028E +#define ICON_MDI_BOWL_MIX "\xf3\xb0\x98\x97" // U+F0617 +#define ICON_MDI_BOWL_MIX_OUTLINE "\xf3\xb0\x8b\xa4" // U+F02E4 +#define ICON_MDI_BOWL_OUTLINE "\xf3\xb0\x8a\xa9" // U+F02A9 +#define ICON_MDI_BOWLING "\xf3\xb0\x83\x93" // U+F00D3 +#define ICON_MDI_BOX "\xf3\xb0\x83\x94" // U+F00D4 +#define ICON_MDI_BOX_CUTTER "\xf3\xb0\x83\x95" // U+F00D5 +#define ICON_MDI_BOX_CUTTER_OFF "\xf3\xb0\xad\x8a" // U+F0B4A +#define ICON_MDI_BOX_SHADOW "\xf3\xb0\x98\xb7" // U+F0637 +#define ICON_MDI_BOXING_GLOVE "\xf3\xb0\xad\xa5" // U+F0B65 +#define ICON_MDI_BRAILLE "\xf3\xb0\xa7\x90" // U+F09D0 +#define ICON_MDI_BRAIN "\xf3\xb0\xa7\x91" // U+F09D1 +#define ICON_MDI_BREAD_SLICE "\xf3\xb0\xb3\xae" // U+F0CEE +#define ICON_MDI_BREAD_SLICE_OUTLINE "\xf3\xb0\xb3\xaf" // U+F0CEF +#define ICON_MDI_BRIDGE "\xf3\xb0\x98\x98" // U+F0618 +#define ICON_MDI_BRIEFCASE "\xf3\xb0\x83\x96" // U+F00D6 +#define ICON_MDI_BRIEFCASE_ACCOUNT "\xf3\xb0\xb3\xb0" // U+F0CF0 +#define ICON_MDI_BRIEFCASE_ACCOUNT_OUTLINE "\xf3\xb0\xb3\xb1" // U+F0CF1 +#define ICON_MDI_BRIEFCASE_ARROW_LEFT_RIGHT "\xf3\xb1\xaa\x8d" // U+F1A8D +#define ICON_MDI_BRIEFCASE_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xaa\x8e" // U+F1A8E +#define ICON_MDI_BRIEFCASE_ARROW_UP_DOWN "\xf3\xb1\xaa\x8f" // U+F1A8F +#define ICON_MDI_BRIEFCASE_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xaa\x90" // U+F1A90 +#define ICON_MDI_BRIEFCASE_CHECK "\xf3\xb0\x83\x97" // U+F00D7 +#define ICON_MDI_BRIEFCASE_CHECK_OUTLINE "\xf3\xb1\x8c\x9e" // U+F131E +#define ICON_MDI_BRIEFCASE_CLOCK "\xf3\xb1\x83\x90" // U+F10D0 +#define ICON_MDI_BRIEFCASE_CLOCK_OUTLINE "\xf3\xb1\x83\x91" // U+F10D1 +#define ICON_MDI_BRIEFCASE_DOWNLOAD "\xf3\xb0\x83\x98" // U+F00D8 +#define ICON_MDI_BRIEFCASE_DOWNLOAD_OUTLINE "\xf3\xb0\xb0\xbd" // U+F0C3D +#define ICON_MDI_BRIEFCASE_EDIT "\xf3\xb0\xaa\x98" // U+F0A98 +#define ICON_MDI_BRIEFCASE_EDIT_OUTLINE "\xf3\xb0\xb0\xbe" // U+F0C3E +#define ICON_MDI_BRIEFCASE_EYE "\xf3\xb1\x9f\x99" // U+F17D9 +#define ICON_MDI_BRIEFCASE_EYE_OUTLINE "\xf3\xb1\x9f\x9a" // U+F17DA +#define ICON_MDI_BRIEFCASE_MINUS "\xf3\xb0\xa8\xaa" // U+F0A2A +#define ICON_MDI_BRIEFCASE_MINUS_OUTLINE "\xf3\xb0\xb0\xbf" // U+F0C3F +#define ICON_MDI_BRIEFCASE_OFF "\xf3\xb1\x99\x98" // U+F1658 +#define ICON_MDI_BRIEFCASE_OFF_OUTLINE "\xf3\xb1\x99\x99" // U+F1659 +#define ICON_MDI_BRIEFCASE_OUTLINE "\xf3\xb0\xa0\x94" // U+F0814 +#define ICON_MDI_BRIEFCASE_PLUS "\xf3\xb0\xa8\xab" // U+F0A2B +#define ICON_MDI_BRIEFCASE_PLUS_OUTLINE "\xf3\xb0\xb1\x80" // U+F0C40 +#define ICON_MDI_BRIEFCASE_REMOVE "\xf3\xb0\xa8\xac" // U+F0A2C +#define ICON_MDI_BRIEFCASE_REMOVE_OUTLINE "\xf3\xb0\xb1\x81" // U+F0C41 +#define ICON_MDI_BRIEFCASE_SEARCH "\xf3\xb0\xa8\xad" // U+F0A2D +#define ICON_MDI_BRIEFCASE_SEARCH_OUTLINE "\xf3\xb0\xb1\x82" // U+F0C42 +#define ICON_MDI_BRIEFCASE_UPLOAD "\xf3\xb0\x83\x99" // U+F00D9 +#define ICON_MDI_BRIEFCASE_UPLOAD_OUTLINE "\xf3\xb0\xb1\x83" // U+F0C43 +#define ICON_MDI_BRIEFCASE_VARIANT "\xf3\xb1\x92\x94" // U+F1494 +#define ICON_MDI_BRIEFCASE_VARIANT_OFF "\xf3\xb1\x99\x9a" // U+F165A +#define ICON_MDI_BRIEFCASE_VARIANT_OFF_OUTLINE "\xf3\xb1\x99\x9b" // U+F165B +#define ICON_MDI_BRIEFCASE_VARIANT_OUTLINE "\xf3\xb1\x92\x95" // U+F1495 +#define ICON_MDI_BRIGHTNESS_1 "\xf3\xb0\x83\x9a" // U+F00DA +#define ICON_MDI_BRIGHTNESS_2 "\xf3\xb0\x83\x9b" // U+F00DB +#define ICON_MDI_BRIGHTNESS_3 "\xf3\xb0\x83\x9c" // U+F00DC +#define ICON_MDI_BRIGHTNESS_4 "\xf3\xb0\x83\x9d" // U+F00DD +#define ICON_MDI_BRIGHTNESS_5 "\xf3\xb0\x83\x9e" // U+F00DE +#define ICON_MDI_BRIGHTNESS_6 "\xf3\xb0\x83\x9f" // U+F00DF +#define ICON_MDI_BRIGHTNESS_7 "\xf3\xb0\x83\xa0" // U+F00E0 +#define ICON_MDI_BRIGHTNESS_AUTO "\xf3\xb0\x83\xa1" // U+F00E1 +#define ICON_MDI_BRIGHTNESS_PERCENT "\xf3\xb0\xb3\xb2" // U+F0CF2 +#define ICON_MDI_BROADCAST "\xf3\xb1\x9c\xa0" // U+F1720 +#define ICON_MDI_BROADCAST_OFF "\xf3\xb1\x9c\xa1" // U+F1721 +#define ICON_MDI_BROOM "\xf3\xb0\x83\xa2" // U+F00E2 +#define ICON_MDI_BRUSH "\xf3\xb0\x83\xa3" // U+F00E3 +#define ICON_MDI_BRUSH_OFF "\xf3\xb1\x9d\xb1" // U+F1771 +#define ICON_MDI_BRUSH_OUTLINE "\xf3\xb1\xa8\x8d" // U+F1A0D +#define ICON_MDI_BRUSH_VARIANT "\xf3\xb1\xa0\x93" // U+F1813 +#define ICON_MDI_BUCKET "\xf3\xb1\x90\x95" // U+F1415 +#define ICON_MDI_BUCKET_OUTLINE "\xf3\xb1\x90\x96" // U+F1416 +#define ICON_MDI_BUFFET "\xf3\xb0\x95\xb8" // U+F0578 +#define ICON_MDI_BUG "\xf3\xb0\x83\xa4" // U+F00E4 +#define ICON_MDI_BUG_CHECK "\xf3\xb0\xa8\xae" // U+F0A2E +#define ICON_MDI_BUG_CHECK_OUTLINE "\xf3\xb0\xa8\xaf" // U+F0A2F +#define ICON_MDI_BUG_OUTLINE "\xf3\xb0\xa8\xb0" // U+F0A30 +#define ICON_MDI_BUG_PAUSE "\xf3\xb1\xab\xb5" // U+F1AF5 +#define ICON_MDI_BUG_PAUSE_OUTLINE "\xf3\xb1\xab\xb6" // U+F1AF6 +#define ICON_MDI_BUG_PLAY "\xf3\xb1\xab\xb7" // U+F1AF7 +#define ICON_MDI_BUG_PLAY_OUTLINE "\xf3\xb1\xab\xb8" // U+F1AF8 +#define ICON_MDI_BUG_STOP "\xf3\xb1\xab\xb9" // U+F1AF9 +#define ICON_MDI_BUG_STOP_OUTLINE "\xf3\xb1\xab\xba" // U+F1AFA +#define ICON_MDI_BUGLE "\xf3\xb0\xb6\xb4" // U+F0DB4 +#define ICON_MDI_BULKHEAD_LIGHT "\xf3\xb1\xa8\xaf" // U+F1A2F +#define ICON_MDI_BULLDOZER "\xf3\xb0\xac\xa2" // U+F0B22 +#define ICON_MDI_BULLET "\xf3\xb0\xb3\xb3" // U+F0CF3 +#define ICON_MDI_BULLETIN_BOARD "\xf3\xb0\x83\xa5" // U+F00E5 +#define ICON_MDI_BULLHORN "\xf3\xb0\x83\xa6" // U+F00E6 +#define ICON_MDI_BULLHORN_OUTLINE "\xf3\xb0\xac\xa3" // U+F0B23 +#define ICON_MDI_BULLHORN_VARIANT "\xf3\xb1\xa5\xae" // U+F196E +#define ICON_MDI_BULLHORN_VARIANT_OUTLINE "\xf3\xb1\xa5\xaf" // U+F196F +#define ICON_MDI_BULLSEYE "\xf3\xb0\x97\x9d" // U+F05DD +#define ICON_MDI_BULLSEYE_ARROW "\xf3\xb0\xa3\x89" // U+F08C9 +#define ICON_MDI_BULMA "\xf3\xb1\x8b\xa7" // U+F12E7 +#define ICON_MDI_BUNK_BED "\xf3\xb1\x8c\x82" // U+F1302 +#define ICON_MDI_BUNK_BED_OUTLINE "\xf3\xb0\x82\x97" // U+F0097 +#define ICON_MDI_BUS "\xf3\xb0\x83\xa7" // U+F00E7 +#define ICON_MDI_BUS_ALERT "\xf3\xb0\xaa\x99" // U+F0A99 +#define ICON_MDI_BUS_ARTICULATED_END "\xf3\xb0\x9e\x9c" // U+F079C +#define ICON_MDI_BUS_ARTICULATED_FRONT "\xf3\xb0\x9e\x9d" // U+F079D +#define ICON_MDI_BUS_CLOCK "\xf3\xb0\xa3\x8a" // U+F08CA +#define ICON_MDI_BUS_DOUBLE_DECKER "\xf3\xb0\x9e\x9e" // U+F079E +#define ICON_MDI_BUS_ELECTRIC "\xf3\xb1\xa4\x9d" // U+F191D +#define ICON_MDI_BUS_MARKER "\xf3\xb1\x88\x92" // U+F1212 +#define ICON_MDI_BUS_MULTIPLE "\xf3\xb0\xbc\xbf" // U+F0F3F +#define ICON_MDI_BUS_SCHOOL "\xf3\xb0\x9e\x9f" // U+F079F +#define ICON_MDI_BUS_SIDE "\xf3\xb0\x9e\xa0" // U+F07A0 +#define ICON_MDI_BUS_SIGN "\xf3\xb1\xb3\x81" // U+F1CC1 +#define ICON_MDI_BUS_STOP "\xf3\xb1\x80\x92" // U+F1012 +#define ICON_MDI_BUS_STOP_COVERED "\xf3\xb1\x80\x93" // U+F1013 +#define ICON_MDI_BUS_STOP_UNCOVERED "\xf3\xb1\x80\x94" // U+F1014 +#define ICON_MDI_BUS_WRENCH "\xf3\xb1\xb3\x82" // U+F1CC2 +#define ICON_MDI_BUTTERFLY "\xf3\xb1\x96\x89" // U+F1589 +#define ICON_MDI_BUTTERFLY_OUTLINE "\xf3\xb1\x96\x8a" // U+F158A +#define ICON_MDI_BUTTON_CURSOR "\xf3\xb1\xad\x8f" // U+F1B4F +#define ICON_MDI_BUTTON_POINTER "\xf3\xb1\xad\x90" // U+F1B50 +#define ICON_MDI_CABIN_A_FRAME "\xf3\xb1\xa2\x8c" // U+F188C +#define ICON_MDI_CABLE_DATA "\xf3\xb1\x8e\x94" // U+F1394 +#define ICON_MDI_CACHED "\xf3\xb0\x83\xa8" // U+F00E8 +#define ICON_MDI_CACTUS "\xf3\xb0\xb6\xb5" // U+F0DB5 +#define ICON_MDI_CAKE "\xf3\xb0\x83\xa9" // U+F00E9 +#define ICON_MDI_CAKE_LAYERED "\xf3\xb0\x83\xaa" // U+F00EA +#define ICON_MDI_CAKE_VARIANT "\xf3\xb0\x83\xab" // U+F00EB +#define ICON_MDI_CAKE_VARIANT_OUTLINE "\xf3\xb1\x9f\xb0" // U+F17F0 +#define ICON_MDI_CALCULATOR "\xf3\xb0\x83\xac" // U+F00EC +#define ICON_MDI_CALCULATOR_VARIANT "\xf3\xb0\xaa\x9a" // U+F0A9A +#define ICON_MDI_CALCULATOR_VARIANT_OUTLINE "\xf3\xb1\x96\xa6" // U+F15A6 +#define ICON_MDI_CALENDAR "\xf3\xb0\x83\xad" // U+F00ED +#define ICON_MDI_CALENDAR_ACCOUNT "\xf3\xb0\xbb\x97" // U+F0ED7 +#define ICON_MDI_CALENDAR_ACCOUNT_OUTLINE "\xf3\xb0\xbb\x98" // U+F0ED8 +#define ICON_MDI_CALENDAR_ALERT "\xf3\xb0\xa8\xb1" // U+F0A31 +#define ICON_MDI_CALENDAR_ALERT_OUTLINE "\xf3\xb1\xad\xa2" // U+F1B62 +#define ICON_MDI_CALENDAR_ARROW_LEFT "\xf3\xb1\x84\xb4" // U+F1134 +#define ICON_MDI_CALENDAR_ARROW_RIGHT "\xf3\xb1\x84\xb5" // U+F1135 +#define ICON_MDI_CALENDAR_BADGE "\xf3\xb1\xae\x9d" // U+F1B9D +#define ICON_MDI_CALENDAR_BADGE_OUTLINE "\xf3\xb1\xae\x9e" // U+F1B9E +#define ICON_MDI_CALENDAR_BLANK "\xf3\xb0\x83\xae" // U+F00EE +#define ICON_MDI_CALENDAR_BLANK_MULTIPLE "\xf3\xb1\x81\xb3" // U+F1073 +#define ICON_MDI_CALENDAR_BLANK_OUTLINE "\xf3\xb0\xad\xa6" // U+F0B66 +#define ICON_MDI_CALENDAR_CHECK "\xf3\xb0\x83\xaf" // U+F00EF +#define ICON_MDI_CALENDAR_CHECK_OUTLINE "\xf3\xb0\xb1\x84" // U+F0C44 +#define ICON_MDI_CALENDAR_CLOCK "\xf3\xb0\x83\xb0" // U+F00F0 +#define ICON_MDI_CALENDAR_CLOCK_OUTLINE "\xf3\xb1\x9b\xa1" // U+F16E1 +#define ICON_MDI_CALENDAR_COLLAPSE_HORIZONTAL "\xf3\xb1\xa2\x9d" // U+F189D +#define ICON_MDI_CALENDAR_COLLAPSE_HORIZONTAL_OUTLINE "\xf3\xb1\xad\xa3" // U+F1B63 +#define ICON_MDI_CALENDAR_CURSOR "\xf3\xb1\x95\xbb" // U+F157B +#define ICON_MDI_CALENDAR_CURSOR_OUTLINE "\xf3\xb1\xad\xa4" // U+F1B64 +#define ICON_MDI_CALENDAR_EDIT "\xf3\xb0\xa2\xa7" // U+F08A7 +#define ICON_MDI_CALENDAR_EDIT_OUTLINE "\xf3\xb1\xad\xa5" // U+F1B65 +#define ICON_MDI_CALENDAR_END "\xf3\xb1\x99\xac" // U+F166C +#define ICON_MDI_CALENDAR_END_OUTLINE "\xf3\xb1\xad\xa6" // U+F1B66 +#define ICON_MDI_CALENDAR_EXPAND_HORIZONTAL "\xf3\xb1\xa2\x9e" // U+F189E +#define ICON_MDI_CALENDAR_EXPAND_HORIZONTAL_OUTLINE "\xf3\xb1\xad\xa7" // U+F1B67 +#define ICON_MDI_CALENDAR_EXPORT "\xf3\xb0\xac\xa4" // U+F0B24 +#define ICON_MDI_CALENDAR_EXPORT_OUTLINE "\xf3\xb1\xad\xa8" // U+F1B68 +#define ICON_MDI_CALENDAR_FILTER "\xf3\xb1\xa8\xb2" // U+F1A32 +#define ICON_MDI_CALENDAR_FILTER_OUTLINE "\xf3\xb1\xa8\xb3" // U+F1A33 +#define ICON_MDI_CALENDAR_HEART "\xf3\xb0\xa7\x92" // U+F09D2 +#define ICON_MDI_CALENDAR_HEART_OUTLINE "\xf3\xb1\xad\xa9" // U+F1B69 +#define ICON_MDI_CALENDAR_IMPORT "\xf3\xb0\xac\xa5" // U+F0B25 +#define ICON_MDI_CALENDAR_IMPORT_OUTLINE "\xf3\xb1\xad\xaa" // U+F1B6A +#define ICON_MDI_CALENDAR_LOCK "\xf3\xb1\x99\x81" // U+F1641 +#define ICON_MDI_CALENDAR_LOCK_OPEN "\xf3\xb1\xad\x9b" // U+F1B5B +#define ICON_MDI_CALENDAR_LOCK_OPEN_OUTLINE "\xf3\xb1\xad\x9c" // U+F1B5C +#define ICON_MDI_CALENDAR_LOCK_OUTLINE "\xf3\xb1\x99\x82" // U+F1642 +#define ICON_MDI_CALENDAR_MINUS "\xf3\xb0\xb5\x9c" // U+F0D5C +#define ICON_MDI_CALENDAR_MINUS_OUTLINE "\xf3\xb1\xad\xab" // U+F1B6B +#define ICON_MDI_CALENDAR_MONTH "\xf3\xb0\xb8\x97" // U+F0E17 +#define ICON_MDI_CALENDAR_MONTH_OUTLINE "\xf3\xb0\xb8\x98" // U+F0E18 +#define ICON_MDI_CALENDAR_MULTIPLE "\xf3\xb0\x83\xb1" // U+F00F1 +#define ICON_MDI_CALENDAR_MULTIPLE_CHECK "\xf3\xb0\x83\xb2" // U+F00F2 +#define ICON_MDI_CALENDAR_MULTISELECT "\xf3\xb0\xa8\xb2" // U+F0A32 +#define ICON_MDI_CALENDAR_MULTISELECT_OUTLINE "\xf3\xb1\xad\x95" // U+F1B55 +#define ICON_MDI_CALENDAR_OUTLINE "\xf3\xb0\xad\xa7" // U+F0B67 +#define ICON_MDI_CALENDAR_PLUS "\xf3\xb0\x83\xb3" // U+F00F3 +#define ICON_MDI_CALENDAR_PLUS_OUTLINE "\xf3\xb1\xad\xac" // U+F1B6C +#define ICON_MDI_CALENDAR_QUESTION "\xf3\xb0\x9a\x92" // U+F0692 +#define ICON_MDI_CALENDAR_QUESTION_OUTLINE "\xf3\xb1\xad\xad" // U+F1B6D +#define ICON_MDI_CALENDAR_RANGE "\xf3\xb0\x99\xb9" // U+F0679 +#define ICON_MDI_CALENDAR_RANGE_OUTLINE "\xf3\xb0\xad\xa8" // U+F0B68 +#define ICON_MDI_CALENDAR_REFRESH "\xf3\xb0\x87\xa1" // U+F01E1 +#define ICON_MDI_CALENDAR_REFRESH_OUTLINE "\xf3\xb0\x88\x83" // U+F0203 +#define ICON_MDI_CALENDAR_REMOVE "\xf3\xb0\x83\xb4" // U+F00F4 +#define ICON_MDI_CALENDAR_REMOVE_OUTLINE "\xf3\xb0\xb1\x85" // U+F0C45 +#define ICON_MDI_CALENDAR_SEARCH "\xf3\xb0\xa5\x8c" // U+F094C +#define ICON_MDI_CALENDAR_SEARCH_OUTLINE "\xf3\xb1\xad\xae" // U+F1B6E +#define ICON_MDI_CALENDAR_STAR "\xf3\xb0\xa7\x93" // U+F09D3 +#define ICON_MDI_CALENDAR_STAR_FOUR_POINTS "\xf3\xb1\xb0\x9f" // U+F1C1F +#define ICON_MDI_CALENDAR_STAR_OUTLINE "\xf3\xb1\xad\x93" // U+F1B53 +#define ICON_MDI_CALENDAR_START "\xf3\xb1\x99\xad" // U+F166D +#define ICON_MDI_CALENDAR_START_OUTLINE "\xf3\xb1\xad\xaf" // U+F1B6F +#define ICON_MDI_CALENDAR_SYNC "\xf3\xb0\xba\x8e" // U+F0E8E +#define ICON_MDI_CALENDAR_SYNC_OUTLINE "\xf3\xb0\xba\x8f" // U+F0E8F +#define ICON_MDI_CALENDAR_TEXT "\xf3\xb0\x83\xb5" // U+F00F5 +#define ICON_MDI_CALENDAR_TEXT_OUTLINE "\xf3\xb0\xb1\x86" // U+F0C46 +#define ICON_MDI_CALENDAR_TODAY "\xf3\xb0\x83\xb6" // U+F00F6 +#define ICON_MDI_CALENDAR_TODAY_OUTLINE "\xf3\xb1\xa8\xb0" // U+F1A30 +#define ICON_MDI_CALENDAR_WEEK "\xf3\xb0\xa8\xb3" // U+F0A33 +#define ICON_MDI_CALENDAR_WEEK_BEGIN "\xf3\xb0\xa8\xb4" // U+F0A34 +#define ICON_MDI_CALENDAR_WEEK_BEGIN_OUTLINE "\xf3\xb1\xa8\xb1" // U+F1A31 +#define ICON_MDI_CALENDAR_WEEK_OUTLINE "\xf3\xb1\xa8\xb4" // U+F1A34 +#define ICON_MDI_CALENDAR_WEEKEND "\xf3\xb0\xbb\x99" // U+F0ED9 +#define ICON_MDI_CALENDAR_WEEKEND_OUTLINE "\xf3\xb0\xbb\x9a" // U+F0EDA +#define ICON_MDI_CALL_MADE "\xf3\xb0\x83\xb7" // U+F00F7 +#define ICON_MDI_CALL_MERGE "\xf3\xb0\x83\xb8" // U+F00F8 +#define ICON_MDI_CALL_MISSED "\xf3\xb0\x83\xb9" // U+F00F9 +#define ICON_MDI_CALL_RECEIVED "\xf3\xb0\x83\xba" // U+F00FA +#define ICON_MDI_CALL_SPLIT "\xf3\xb0\x83\xbb" // U+F00FB +#define ICON_MDI_CAMCORDER "\xf3\xb0\x83\xbc" // U+F00FC +#define ICON_MDI_CAMCORDER_OFF "\xf3\xb0\x83\xbf" // U+F00FF +#define ICON_MDI_CAMERA "\xf3\xb0\x84\x80" // U+F0100 +#define ICON_MDI_CAMERA_ACCOUNT "\xf3\xb0\xa3\x8b" // U+F08CB +#define ICON_MDI_CAMERA_BURST "\xf3\xb0\x9a\x93" // U+F0693 +#define ICON_MDI_CAMERA_CONTROL "\xf3\xb0\xad\xa9" // U+F0B69 +#define ICON_MDI_CAMERA_DOCUMENT "\xf3\xb1\xa1\xb1" // U+F1871 +#define ICON_MDI_CAMERA_DOCUMENT_OFF "\xf3\xb1\xa1\xb2" // U+F1872 +#define ICON_MDI_CAMERA_ENHANCE "\xf3\xb0\x84\x81" // U+F0101 +#define ICON_MDI_CAMERA_ENHANCE_OUTLINE "\xf3\xb0\xad\xaa" // U+F0B6A +#define ICON_MDI_CAMERA_FLIP "\xf3\xb1\x97\x99" // U+F15D9 +#define ICON_MDI_CAMERA_FLIP_OUTLINE "\xf3\xb1\x97\x9a" // U+F15DA +#define ICON_MDI_CAMERA_FRONT "\xf3\xb0\x84\x82" // U+F0102 +#define ICON_MDI_CAMERA_FRONT_VARIANT "\xf3\xb0\x84\x83" // U+F0103 +#define ICON_MDI_CAMERA_GOPRO "\xf3\xb0\x9e\xa1" // U+F07A1 +#define ICON_MDI_CAMERA_IMAGE "\xf3\xb0\xa3\x8c" // U+F08CC +#define ICON_MDI_CAMERA_IRIS "\xf3\xb0\x84\x84" // U+F0104 +#define ICON_MDI_CAMERA_LOCK "\xf3\xb1\xa8\x94" // U+F1A14 +#define ICON_MDI_CAMERA_LOCK_OPEN "\xf3\xb1\xb0\x8d" // U+F1C0D +#define ICON_MDI_CAMERA_LOCK_OPEN_OUTLINE "\xf3\xb1\xb0\x8e" // U+F1C0E +#define ICON_MDI_CAMERA_LOCK_OUTLINE "\xf3\xb1\xa8\x95" // U+F1A15 +#define ICON_MDI_CAMERA_MARKER "\xf3\xb1\xa6\xa7" // U+F19A7 +#define ICON_MDI_CAMERA_MARKER_OUTLINE "\xf3\xb1\xa6\xa8" // U+F19A8 +#define ICON_MDI_CAMERA_METERING_CENTER "\xf3\xb0\x9e\xa2" // U+F07A2 +#define ICON_MDI_CAMERA_METERING_MATRIX "\xf3\xb0\x9e\xa3" // U+F07A3 +#define ICON_MDI_CAMERA_METERING_PARTIAL "\xf3\xb0\x9e\xa4" // U+F07A4 +#define ICON_MDI_CAMERA_METERING_SPOT "\xf3\xb0\x9e\xa5" // U+F07A5 +#define ICON_MDI_CAMERA_OFF "\xf3\xb0\x97\x9f" // U+F05DF +#define ICON_MDI_CAMERA_OFF_OUTLINE "\xf3\xb1\xa6\xbf" // U+F19BF +#define ICON_MDI_CAMERA_OUTLINE "\xf3\xb0\xb5\x9d" // U+F0D5D +#define ICON_MDI_CAMERA_PARTY_MODE "\xf3\xb0\x84\x85" // U+F0105 +#define ICON_MDI_CAMERA_PLUS "\xf3\xb0\xbb\x9b" // U+F0EDB +#define ICON_MDI_CAMERA_PLUS_OUTLINE "\xf3\xb0\xbb\x9c" // U+F0EDC +#define ICON_MDI_CAMERA_REAR "\xf3\xb0\x84\x86" // U+F0106 +#define ICON_MDI_CAMERA_REAR_VARIANT "\xf3\xb0\x84\x87" // U+F0107 +#define ICON_MDI_CAMERA_RETAKE "\xf3\xb0\xb8\x99" // U+F0E19 +#define ICON_MDI_CAMERA_RETAKE_OUTLINE "\xf3\xb0\xb8\x9a" // U+F0E1A +#define ICON_MDI_CAMERA_SWITCH "\xf3\xb0\x84\x88" // U+F0108 +#define ICON_MDI_CAMERA_SWITCH_OUTLINE "\xf3\xb0\xa1\x8a" // U+F084A +#define ICON_MDI_CAMERA_TIMER "\xf3\xb0\x84\x89" // U+F0109 +#define ICON_MDI_CAMERA_WIRELESS "\xf3\xb0\xb6\xb6" // U+F0DB6 +#define ICON_MDI_CAMERA_WIRELESS_OUTLINE "\xf3\xb0\xb6\xb7" // U+F0DB7 +#define ICON_MDI_CAMPFIRE "\xf3\xb0\xbb\x9d" // U+F0EDD +#define ICON_MDI_CANCEL "\xf3\xb0\x9c\xba" // U+F073A +#define ICON_MDI_CANDELABRA "\xf3\xb1\x9f\x92" // U+F17D2 +#define ICON_MDI_CANDELABRA_FIRE "\xf3\xb1\x9f\x93" // U+F17D3 +#define ICON_MDI_CANDLE "\xf3\xb0\x97\xa2" // U+F05E2 +#define ICON_MDI_CANDY "\xf3\xb1\xa5\xb0" // U+F1970 +#define ICON_MDI_CANDY_OFF "\xf3\xb1\xa5\xb1" // U+F1971 +#define ICON_MDI_CANDY_OFF_OUTLINE "\xf3\xb1\xa5\xb2" // U+F1972 +#define ICON_MDI_CANDY_OUTLINE "\xf3\xb1\xa5\xb3" // U+F1973 +#define ICON_MDI_CANDYCANE "\xf3\xb0\x84\x8a" // U+F010A +#define ICON_MDI_CANNABIS "\xf3\xb0\x9e\xa6" // U+F07A6 +#define ICON_MDI_CANNABIS_OFF "\xf3\xb1\x99\xae" // U+F166E +#define ICON_MDI_CAPS_LOCK "\xf3\xb0\xaa\x9b" // U+F0A9B +#define ICON_MDI_CAR "\xf3\xb0\x84\x8b" // U+F010B +#define ICON_MDI_CAR_2_PLUS "\xf3\xb1\x80\x95" // U+F1015 +#define ICON_MDI_CAR_3_PLUS "\xf3\xb1\x80\x96" // U+F1016 +#define ICON_MDI_CAR_ARROW_LEFT "\xf3\xb1\x8e\xb2" // U+F13B2 +#define ICON_MDI_CAR_ARROW_RIGHT "\xf3\xb1\x8e\xb3" // U+F13B3 +#define ICON_MDI_CAR_BACK "\xf3\xb0\xb8\x9b" // U+F0E1B +#define ICON_MDI_CAR_BATTERY "\xf3\xb0\x84\x8c" // U+F010C +#define ICON_MDI_CAR_BRAKE_ABS "\xf3\xb0\xb1\x87" // U+F0C47 +#define ICON_MDI_CAR_BRAKE_ALERT "\xf3\xb0\xb1\x88" // U+F0C48 +#define ICON_MDI_CAR_BRAKE_FLUID_LEVEL "\xf3\xb1\xa4\x89" // U+F1909 +#define ICON_MDI_CAR_BRAKE_HOLD "\xf3\xb0\xb5\x9e" // U+F0D5E +#define ICON_MDI_CAR_BRAKE_LOW_PRESSURE "\xf3\xb1\xa4\x8a" // U+F190A +#define ICON_MDI_CAR_BRAKE_PARKING "\xf3\xb0\xb5\x9f" // U+F0D5F +#define ICON_MDI_CAR_BRAKE_RETARDER "\xf3\xb1\x80\x97" // U+F1017 +#define ICON_MDI_CAR_BRAKE_TEMPERATURE "\xf3\xb1\xa4\x8b" // U+F190B +#define ICON_MDI_CAR_BRAKE_WORN_LININGS "\xf3\xb1\xa4\x8c" // U+F190C +#define ICON_MDI_CAR_CHILD_SEAT "\xf3\xb0\xbe\xa3" // U+F0FA3 +#define ICON_MDI_CAR_CLOCK "\xf3\xb1\xa5\xb4" // U+F1974 +#define ICON_MDI_CAR_CLUTCH "\xf3\xb1\x80\x98" // U+F1018 +#define ICON_MDI_CAR_COG "\xf3\xb1\x8f\x8c" // U+F13CC +#define ICON_MDI_CAR_CONNECTED "\xf3\xb0\x84\x8d" // U+F010D +#define ICON_MDI_CAR_CONVERTIBLE "\xf3\xb0\x9e\xa7" // U+F07A7 +#define ICON_MDI_CAR_COOLANT_LEVEL "\xf3\xb1\x80\x99" // U+F1019 +#define ICON_MDI_CAR_CRUISE_CONTROL "\xf3\xb0\xb5\xa0" // U+F0D60 +#define ICON_MDI_CAR_DEFROST_FRONT "\xf3\xb0\xb5\xa1" // U+F0D61 +#define ICON_MDI_CAR_DEFROST_REAR "\xf3\xb0\xb5\xa2" // U+F0D62 +#define ICON_MDI_CAR_DOOR "\xf3\xb0\xad\xab" // U+F0B6B +#define ICON_MDI_CAR_DOOR_LOCK "\xf3\xb1\x82\x9d" // U+F109D +#define ICON_MDI_CAR_DOOR_LOCK_OPEN "\xf3\xb1\xb2\x81" // U+F1C81 +#define ICON_MDI_CAR_ELECTRIC "\xf3\xb0\xad\xac" // U+F0B6C +#define ICON_MDI_CAR_ELECTRIC_OUTLINE "\xf3\xb1\x96\xb5" // U+F15B5 +#define ICON_MDI_CAR_EMERGENCY "\xf3\xb1\x98\x8f" // U+F160F +#define ICON_MDI_CAR_ESP "\xf3\xb0\xb1\x89" // U+F0C49 +#define ICON_MDI_CAR_ESTATE "\xf3\xb0\x9e\xa8" // U+F07A8 +#define ICON_MDI_CAR_HATCHBACK "\xf3\xb0\x9e\xa9" // U+F07A9 +#define ICON_MDI_CAR_INFO "\xf3\xb1\x86\xbe" // U+F11BE +#define ICON_MDI_CAR_KEY "\xf3\xb0\xad\xad" // U+F0B6D +#define ICON_MDI_CAR_LIFTED_PICKUP "\xf3\xb1\x94\xad" // U+F152D +#define ICON_MDI_CAR_LIGHT_ALERT "\xf3\xb1\xa4\x8d" // U+F190D +#define ICON_MDI_CAR_LIGHT_DIMMED "\xf3\xb0\xb1\x8a" // U+F0C4A +#define ICON_MDI_CAR_LIGHT_FOG "\xf3\xb0\xb1\x8b" // U+F0C4B +#define ICON_MDI_CAR_LIGHT_HIGH "\xf3\xb0\xb1\x8c" // U+F0C4C +#define ICON_MDI_CAR_LIMOUSINE "\xf3\xb0\xa3\x8d" // U+F08CD +#define ICON_MDI_CAR_MULTIPLE "\xf3\xb0\xad\xae" // U+F0B6E +#define ICON_MDI_CAR_OFF "\xf3\xb0\xb8\x9c" // U+F0E1C +#define ICON_MDI_CAR_OUTLINE "\xf3\xb1\x93\xad" // U+F14ED +#define ICON_MDI_CAR_PARKING_LIGHTS "\xf3\xb0\xb5\xa3" // U+F0D63 +#define ICON_MDI_CAR_PICKUP "\xf3\xb0\x9e\xaa" // U+F07AA +#define ICON_MDI_CAR_SEARCH "\xf3\xb1\xae\x8d" // U+F1B8D +#define ICON_MDI_CAR_SEARCH_OUTLINE "\xf3\xb1\xae\x8e" // U+F1B8E +#define ICON_MDI_CAR_SEAT "\xf3\xb0\xbe\xa4" // U+F0FA4 +#define ICON_MDI_CAR_SEAT_COOLER "\xf3\xb0\xbe\xa5" // U+F0FA5 +#define ICON_MDI_CAR_SEAT_HEATER "\xf3\xb0\xbe\xa6" // U+F0FA6 +#define ICON_MDI_CAR_SELECT "\xf3\xb1\xa1\xb9" // U+F1879 +#define ICON_MDI_CAR_SETTINGS "\xf3\xb1\x8f\x8d" // U+F13CD +#define ICON_MDI_CAR_SHIFT_PATTERN "\xf3\xb0\xbd\x80" // U+F0F40 +#define ICON_MDI_CAR_SIDE "\xf3\xb0\x9e\xab" // U+F07AB +#define ICON_MDI_CAR_SPEED_LIMITER "\xf3\xb1\xa4\x8e" // U+F190E +#define ICON_MDI_CAR_SPORTS "\xf3\xb0\x9e\xac" // U+F07AC +#define ICON_MDI_CAR_TIRE_ALERT "\xf3\xb0\xb1\x8d" // U+F0C4D +#define ICON_MDI_CAR_TRACTION_CONTROL "\xf3\xb0\xb5\xa4" // U+F0D64 +#define ICON_MDI_CAR_TURBOCHARGER "\xf3\xb1\x80\x9a" // U+F101A +#define ICON_MDI_CAR_WASH "\xf3\xb0\x84\x8e" // U+F010E +#define ICON_MDI_CAR_WINDSHIELD "\xf3\xb1\x80\x9b" // U+F101B +#define ICON_MDI_CAR_WINDSHIELD_OUTLINE "\xf3\xb1\x80\x9c" // U+F101C +#define ICON_MDI_CAR_WIRELESS "\xf3\xb1\xa1\xb8" // U+F1878 +#define ICON_MDI_CAR_WRENCH "\xf3\xb1\xa0\x94" // U+F1814 +#define ICON_MDI_CARABINER "\xf3\xb1\x93\x80" // U+F14C0 +#define ICON_MDI_CARAVAN "\xf3\xb0\x9e\xad" // U+F07AD +#define ICON_MDI_CARD "\xf3\xb0\xad\xaf" // U+F0B6F +#define ICON_MDI_CARD_ACCOUNT_DETAILS "\xf3\xb0\x97\x92" // U+F05D2 +#define ICON_MDI_CARD_ACCOUNT_DETAILS_OUTLINE "\xf3\xb0\xb6\xab" // U+F0DAB +#define ICON_MDI_CARD_ACCOUNT_DETAILS_STAR "\xf3\xb0\x8a\xa3" // U+F02A3 +#define ICON_MDI_CARD_ACCOUNT_DETAILS_STAR_OUTLINE "\xf3\xb0\x9b\x9b" // U+F06DB +#define ICON_MDI_CARD_ACCOUNT_MAIL "\xf3\xb0\x86\x8e" // U+F018E +#define ICON_MDI_CARD_ACCOUNT_MAIL_OUTLINE "\xf3\xb0\xba\x98" // U+F0E98 +#define ICON_MDI_CARD_ACCOUNT_PHONE "\xf3\xb0\xba\x99" // U+F0E99 +#define ICON_MDI_CARD_ACCOUNT_PHONE_OUTLINE "\xf3\xb0\xba\x9a" // U+F0E9A +#define ICON_MDI_CARD_BULLETED "\xf3\xb0\xad\xb0" // U+F0B70 +#define ICON_MDI_CARD_BULLETED_OFF "\xf3\xb0\xad\xb1" // U+F0B71 +#define ICON_MDI_CARD_BULLETED_OFF_OUTLINE "\xf3\xb0\xad\xb2" // U+F0B72 +#define ICON_MDI_CARD_BULLETED_OUTLINE "\xf3\xb0\xad\xb3" // U+F0B73 +#define ICON_MDI_CARD_BULLETED_SETTINGS "\xf3\xb0\xad\xb4" // U+F0B74 +#define ICON_MDI_CARD_BULLETED_SETTINGS_OUTLINE "\xf3\xb0\xad\xb5" // U+F0B75 +#define ICON_MDI_CARD_MINUS "\xf3\xb1\x98\x80" // U+F1600 +#define ICON_MDI_CARD_MINUS_OUTLINE "\xf3\xb1\x98\x81" // U+F1601 +#define ICON_MDI_CARD_MULTIPLE "\xf3\xb1\x9f\xb1" // U+F17F1 +#define ICON_MDI_CARD_MULTIPLE_OUTLINE "\xf3\xb1\x9f\xb2" // U+F17F2 +#define ICON_MDI_CARD_OFF "\xf3\xb1\x98\x82" // U+F1602 +#define ICON_MDI_CARD_OFF_OUTLINE "\xf3\xb1\x98\x83" // U+F1603 +#define ICON_MDI_CARD_OUTLINE "\xf3\xb0\xad\xb6" // U+F0B76 +#define ICON_MDI_CARD_PLUS "\xf3\xb1\x87\xbf" // U+F11FF +#define ICON_MDI_CARD_PLUS_OUTLINE "\xf3\xb1\x88\x80" // U+F1200 +#define ICON_MDI_CARD_REMOVE "\xf3\xb1\x98\x84" // U+F1604 +#define ICON_MDI_CARD_REMOVE_OUTLINE "\xf3\xb1\x98\x85" // U+F1605 +#define ICON_MDI_CARD_SEARCH "\xf3\xb1\x81\xb4" // U+F1074 +#define ICON_MDI_CARD_SEARCH_OUTLINE "\xf3\xb1\x81\xb5" // U+F1075 +#define ICON_MDI_CARD_TEXT "\xf3\xb0\xad\xb7" // U+F0B77 +#define ICON_MDI_CARD_TEXT_OUTLINE "\xf3\xb0\xad\xb8" // U+F0B78 +#define ICON_MDI_CARDS "\xf3\xb0\x98\xb8" // U+F0638 +#define ICON_MDI_CARDS_CLUB "\xf3\xb0\xa3\x8e" // U+F08CE +#define ICON_MDI_CARDS_CLUB_OUTLINE "\xf3\xb1\xa2\x9f" // U+F189F +#define ICON_MDI_CARDS_DIAMOND "\xf3\xb0\xa3\x8f" // U+F08CF +#define ICON_MDI_CARDS_DIAMOND_OUTLINE "\xf3\xb1\x80\x9d" // U+F101D +#define ICON_MDI_CARDS_HEART "\xf3\xb0\xa3\x90" // U+F08D0 +#define ICON_MDI_CARDS_HEART_OUTLINE "\xf3\xb1\xa2\xa0" // U+F18A0 +#define ICON_MDI_CARDS_OUTLINE "\xf3\xb0\x98\xb9" // U+F0639 +#define ICON_MDI_CARDS_PLAYING "\xf3\xb1\xa2\xa1" // U+F18A1 +#define ICON_MDI_CARDS_PLAYING_CLUB "\xf3\xb1\xa2\xa2" // U+F18A2 +#define ICON_MDI_CARDS_PLAYING_CLUB_MULTIPLE "\xf3\xb1\xa2\xa3" // U+F18A3 +#define ICON_MDI_CARDS_PLAYING_CLUB_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xa4" // U+F18A4 +#define ICON_MDI_CARDS_PLAYING_CLUB_OUTLINE "\xf3\xb1\xa2\xa5" // U+F18A5 +#define ICON_MDI_CARDS_PLAYING_DIAMOND "\xf3\xb1\xa2\xa6" // U+F18A6 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_MULTIPLE "\xf3\xb1\xa2\xa7" // U+F18A7 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xa8" // U+F18A8 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_OUTLINE "\xf3\xb1\xa2\xa9" // U+F18A9 +#define ICON_MDI_CARDS_PLAYING_HEART "\xf3\xb1\xa2\xaa" // U+F18AA +#define ICON_MDI_CARDS_PLAYING_HEART_MULTIPLE "\xf3\xb1\xa2\xab" // U+F18AB +#define ICON_MDI_CARDS_PLAYING_HEART_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xac" // U+F18AC +#define ICON_MDI_CARDS_PLAYING_HEART_OUTLINE "\xf3\xb1\xa2\xad" // U+F18AD +#define ICON_MDI_CARDS_PLAYING_OUTLINE "\xf3\xb0\x98\xba" // U+F063A +#define ICON_MDI_CARDS_PLAYING_SPADE "\xf3\xb1\xa2\xae" // U+F18AE +#define ICON_MDI_CARDS_PLAYING_SPADE_MULTIPLE "\xf3\xb1\xa2\xaf" // U+F18AF +#define ICON_MDI_CARDS_PLAYING_SPADE_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xb0" // U+F18B0 +#define ICON_MDI_CARDS_PLAYING_SPADE_OUTLINE "\xf3\xb1\xa2\xb1" // U+F18B1 +#define ICON_MDI_CARDS_SPADE "\xf3\xb0\xa3\x91" // U+F08D1 +#define ICON_MDI_CARDS_SPADE_OUTLINE "\xf3\xb1\xa2\xb2" // U+F18B2 +#define ICON_MDI_CARDS_VARIANT "\xf3\xb0\x9b\x87" // U+F06C7 +#define ICON_MDI_CARROT "\xf3\xb0\x84\x8f" // U+F010F +#define ICON_MDI_CART "\xf3\xb0\x84\x90" // U+F0110 +#define ICON_MDI_CART_ARROW_DOWN "\xf3\xb0\xb5\xa6" // U+F0D66 +#define ICON_MDI_CART_ARROW_RIGHT "\xf3\xb0\xb1\x8e" // U+F0C4E +#define ICON_MDI_CART_ARROW_UP "\xf3\xb0\xb5\xa7" // U+F0D67 +#define ICON_MDI_CART_CHECK "\xf3\xb1\x97\xaa" // U+F15EA +#define ICON_MDI_CART_HEART "\xf3\xb1\xa3\xa0" // U+F18E0 +#define ICON_MDI_CART_MINUS "\xf3\xb0\xb5\xa8" // U+F0D68 +#define ICON_MDI_CART_OFF "\xf3\xb0\x99\xab" // U+F066B +#define ICON_MDI_CART_OUTLINE "\xf3\xb0\x84\x91" // U+F0111 +#define ICON_MDI_CART_PERCENT "\xf3\xb1\xae\xae" // U+F1BAE +#define ICON_MDI_CART_PLUS "\xf3\xb0\x84\x92" // U+F0112 +#define ICON_MDI_CART_REMOVE "\xf3\xb0\xb5\xa9" // U+F0D69 +#define ICON_MDI_CART_VARIANT "\xf3\xb1\x97\xab" // U+F15EB +#define ICON_MDI_CASE_SENSITIVE_ALT "\xf3\xb0\x84\x93" // U+F0113 +#define ICON_MDI_CASH "\xf3\xb0\x84\x94" // U+F0114 +#define ICON_MDI_CASH_100 "\xf3\xb0\x84\x95" // U+F0115 +#define ICON_MDI_CASH_CHECK "\xf3\xb1\x93\xae" // U+F14EE +#define ICON_MDI_CASH_CLOCK "\xf3\xb1\xaa\x91" // U+F1A91 +#define ICON_MDI_CASH_EDIT "\xf3\xb1\xb2\xab" // U+F1CAB +#define ICON_MDI_CASH_FAST "\xf3\xb1\xa1\x9c" // U+F185C +#define ICON_MDI_CASH_LOCK "\xf3\xb1\x93\xaa" // U+F14EA +#define ICON_MDI_CASH_LOCK_OPEN "\xf3\xb1\x93\xab" // U+F14EB +#define ICON_MDI_CASH_MARKER "\xf3\xb0\xb6\xb8" // U+F0DB8 +#define ICON_MDI_CASH_MINUS "\xf3\xb1\x89\xa0" // U+F1260 +#define ICON_MDI_CASH_MULTIPLE "\xf3\xb0\x84\x96" // U+F0116 +#define ICON_MDI_CASH_OFF "\xf3\xb1\xb1\xb9" // U+F1C79 +#define ICON_MDI_CASH_PLUS "\xf3\xb1\x89\xa1" // U+F1261 +#define ICON_MDI_CASH_REFUND "\xf3\xb0\xaa\x9c" // U+F0A9C +#define ICON_MDI_CASH_REGISTER "\xf3\xb0\xb3\xb4" // U+F0CF4 +#define ICON_MDI_CASH_REMOVE "\xf3\xb1\x89\xa2" // U+F1262 +#define ICON_MDI_CASH_SYNC "\xf3\xb1\xaa\x92" // U+F1A92 +#define ICON_MDI_CASSETTE "\xf3\xb0\xa7\x94" // U+F09D4 +#define ICON_MDI_CAST "\xf3\xb0\x84\x98" // U+F0118 +#define ICON_MDI_CAST_AUDIO "\xf3\xb1\x80\x9e" // U+F101E +#define ICON_MDI_CAST_AUDIO_VARIANT "\xf3\xb1\x9d\x89" // U+F1749 +#define ICON_MDI_CAST_CONNECTED "\xf3\xb0\x84\x99" // U+F0119 +#define ICON_MDI_CAST_EDUCATION "\xf3\xb0\xb8\x9d" // U+F0E1D +#define ICON_MDI_CAST_OFF "\xf3\xb0\x9e\x8a" // U+F078A +#define ICON_MDI_CAST_VARIANT "\xf3\xb0\x80\x9f" // U+F001F +#define ICON_MDI_CASTLE "\xf3\xb0\x84\x9a" // U+F011A +#define ICON_MDI_CAT "\xf3\xb0\x84\x9b" // U+F011B +#define ICON_MDI_CCTV "\xf3\xb0\x9e\xae" // U+F07AE +#define ICON_MDI_CCTV_OFF "\xf3\xb1\xa1\x9f" // U+F185F +#define ICON_MDI_CEILING_FAN "\xf3\xb1\x9e\x97" // U+F1797 +#define ICON_MDI_CEILING_FAN_LIGHT "\xf3\xb1\x9e\x98" // U+F1798 +#define ICON_MDI_CEILING_LIGHT "\xf3\xb0\x9d\xa9" // U+F0769 +#define ICON_MDI_CEILING_LIGHT_MULTIPLE "\xf3\xb1\xa3\x9d" // U+F18DD +#define ICON_MDI_CEILING_LIGHT_MULTIPLE_OUTLINE "\xf3\xb1\xa3\x9e" // U+F18DE +#define ICON_MDI_CEILING_LIGHT_OUTLINE "\xf3\xb1\x9f\x87" // U+F17C7 +#define ICON_MDI_CELLPHONE "\xf3\xb0\x84\x9c" // U+F011C +#define ICON_MDI_CELLPHONE_ARROW_DOWN "\xf3\xb0\xa7\x95" // U+F09D5 +#define ICON_MDI_CELLPHONE_ARROW_DOWN_VARIANT "\xf3\xb1\xa7\x85" // U+F19C5 +#define ICON_MDI_CELLPHONE_BASIC "\xf3\xb0\x84\x9e" // U+F011E +#define ICON_MDI_CELLPHONE_CHARGING "\xf3\xb1\x8e\x97" // U+F1397 +#define ICON_MDI_CELLPHONE_CHECK "\xf3\xb1\x9f\xbd" // U+F17FD +#define ICON_MDI_CELLPHONE_COG "\xf3\xb0\xa5\x91" // U+F0951 +#define ICON_MDI_CELLPHONE_DOCK "\xf3\xb0\x84\x9f" // U+F011F +#define ICON_MDI_CELLPHONE_INFORMATION "\xf3\xb0\xbd\x81" // U+F0F41 +#define ICON_MDI_CELLPHONE_KEY "\xf3\xb0\xa5\x8e" // U+F094E +#define ICON_MDI_CELLPHONE_LINK "\xf3\xb0\x84\xa1" // U+F0121 +#define ICON_MDI_CELLPHONE_LINK_OFF "\xf3\xb0\x84\xa2" // U+F0122 +#define ICON_MDI_CELLPHONE_LOCK "\xf3\xb0\xa5\x8f" // U+F094F +#define ICON_MDI_CELLPHONE_MARKER "\xf3\xb1\xa0\xba" // U+F183A +#define ICON_MDI_CELLPHONE_MESSAGE "\xf3\xb0\xa3\x93" // U+F08D3 +#define ICON_MDI_CELLPHONE_MESSAGE_OFF "\xf3\xb1\x83\x92" // U+F10D2 +#define ICON_MDI_CELLPHONE_NFC "\xf3\xb0\xba\x90" // U+F0E90 +#define ICON_MDI_CELLPHONE_NFC_OFF "\xf3\xb1\x8b\x98" // U+F12D8 +#define ICON_MDI_CELLPHONE_OFF "\xf3\xb0\xa5\x90" // U+F0950 +#define ICON_MDI_CELLPHONE_PLAY "\xf3\xb1\x80\x9f" // U+F101F +#define ICON_MDI_CELLPHONE_REMOVE "\xf3\xb0\xa5\x8d" // U+F094D +#define ICON_MDI_CELLPHONE_SCREENSHOT "\xf3\xb0\xa8\xb5" // U+F0A35 +#define ICON_MDI_CELLPHONE_SETTINGS "\xf3\xb0\x84\xa3" // U+F0123 +#define ICON_MDI_CELLPHONE_SOUND "\xf3\xb0\xa5\x92" // U+F0952 +#define ICON_MDI_CELLPHONE_TEXT "\xf3\xb0\xa3\x92" // U+F08D2 +#define ICON_MDI_CELLPHONE_WIRELESS "\xf3\xb0\xa0\x95" // U+F0815 +#define ICON_MDI_CENTOS "\xf3\xb1\x84\x9a" // U+F111A +#define ICON_MDI_CERTIFICATE "\xf3\xb0\x84\xa4" // U+F0124 +#define ICON_MDI_CERTIFICATE_OUTLINE "\xf3\xb1\x86\x88" // U+F1188 +#define ICON_MDI_CHAIR_ROLLING "\xf3\xb0\xbd\x88" // U+F0F48 +#define ICON_MDI_CHAIR_SCHOOL "\xf3\xb0\x84\xa5" // U+F0125 +#define ICON_MDI_CHANDELIER "\xf3\xb1\x9e\x93" // U+F1793 +#define ICON_MDI_CHARITY "\xf3\xb0\xb1\x8f" // U+F0C4F +#define ICON_MDI_CHARITY_SEARCH "\xf3\xb1\xb2\x82" // U+F1C82 +#define ICON_MDI_CHART_ARC "\xf3\xb0\x84\xa6" // U+F0126 +#define ICON_MDI_CHART_AREASPLINE "\xf3\xb0\x84\xa7" // U+F0127 +#define ICON_MDI_CHART_AREASPLINE_VARIANT "\xf3\xb0\xba\x91" // U+F0E91 +#define ICON_MDI_CHART_BAR "\xf3\xb0\x84\xa8" // U+F0128 +#define ICON_MDI_CHART_BAR_STACKED "\xf3\xb0\x9d\xaa" // U+F076A +#define ICON_MDI_CHART_BELL_CURVE "\xf3\xb0\xb1\x90" // U+F0C50 +#define ICON_MDI_CHART_BELL_CURVE_CUMULATIVE "\xf3\xb0\xbe\xa7" // U+F0FA7 +#define ICON_MDI_CHART_BOX "\xf3\xb1\x95\x8d" // U+F154D +#define ICON_MDI_CHART_BOX_OUTLINE "\xf3\xb1\x95\x8e" // U+F154E +#define ICON_MDI_CHART_BOX_PLUS_OUTLINE "\xf3\xb1\x95\x8f" // U+F154F +#define ICON_MDI_CHART_BUBBLE "\xf3\xb0\x97\xa3" // U+F05E3 +#define ICON_MDI_CHART_DONUT "\xf3\xb0\x9e\xaf" // U+F07AF +#define ICON_MDI_CHART_DONUT_VARIANT "\xf3\xb0\x9e\xb0" // U+F07B0 +#define ICON_MDI_CHART_GANTT "\xf3\xb0\x99\xac" // U+F066C +#define ICON_MDI_CHART_HISTOGRAM "\xf3\xb0\x84\xa9" // U+F0129 +#define ICON_MDI_CHART_LINE "\xf3\xb0\x84\xaa" // U+F012A +#define ICON_MDI_CHART_LINE_STACKED "\xf3\xb0\x9d\xab" // U+F076B +#define ICON_MDI_CHART_LINE_VARIANT "\xf3\xb0\x9e\xb1" // U+F07B1 +#define ICON_MDI_CHART_MULTILINE "\xf3\xb0\xa3\x94" // U+F08D4 +#define ICON_MDI_CHART_MULTIPLE "\xf3\xb1\x88\x93" // U+F1213 +#define ICON_MDI_CHART_PIE "\xf3\xb0\x84\xab" // U+F012B +#define ICON_MDI_CHART_PIE_OUTLINE "\xf3\xb1\xaf\x9f" // U+F1BDF +#define ICON_MDI_CHART_PPF "\xf3\xb1\x8e\x80" // U+F1380 +#define ICON_MDI_CHART_SANKEY "\xf3\xb1\x87\x9f" // U+F11DF +#define ICON_MDI_CHART_SANKEY_VARIANT "\xf3\xb1\x87\xa0" // U+F11E0 +#define ICON_MDI_CHART_SCATTER_PLOT "\xf3\xb0\xba\x92" // U+F0E92 +#define ICON_MDI_CHART_SCATTER_PLOT_HEXBIN "\xf3\xb0\x99\xad" // U+F066D +#define ICON_MDI_CHART_TIMELINE "\xf3\xb0\x99\xae" // U+F066E +#define ICON_MDI_CHART_TIMELINE_VARIANT "\xf3\xb0\xba\x93" // U+F0E93 +#define ICON_MDI_CHART_TIMELINE_VARIANT_SHIMMER "\xf3\xb1\x96\xb6" // U+F15B6 +#define ICON_MDI_CHART_TREE "\xf3\xb0\xba\x94" // U+F0E94 +#define ICON_MDI_CHART_WATERFALL "\xf3\xb1\xa4\x98" // U+F1918 +#define ICON_MDI_CHAT "\xf3\xb0\xad\xb9" // U+F0B79 +#define ICON_MDI_CHAT_ALERT "\xf3\xb0\xad\xba" // U+F0B7A +#define ICON_MDI_CHAT_ALERT_OUTLINE "\xf3\xb1\x8b\x89" // U+F12C9 +#define ICON_MDI_CHAT_MINUS "\xf3\xb1\x90\x90" // U+F1410 +#define ICON_MDI_CHAT_MINUS_OUTLINE "\xf3\xb1\x90\x93" // U+F1413 +#define ICON_MDI_CHAT_OUTLINE "\xf3\xb0\xbb\x9e" // U+F0EDE +#define ICON_MDI_CHAT_PLUS "\xf3\xb1\x90\x8f" // U+F140F +#define ICON_MDI_CHAT_PLUS_OUTLINE "\xf3\xb1\x90\x92" // U+F1412 +#define ICON_MDI_CHAT_PROCESSING "\xf3\xb0\xad\xbb" // U+F0B7B +#define ICON_MDI_CHAT_PROCESSING_OUTLINE "\xf3\xb1\x8b\x8a" // U+F12CA +#define ICON_MDI_CHAT_QUESTION "\xf3\xb1\x9c\xb8" // U+F1738 +#define ICON_MDI_CHAT_QUESTION_OUTLINE "\xf3\xb1\x9c\xb9" // U+F1739 +#define ICON_MDI_CHAT_REMOVE "\xf3\xb1\x90\x91" // U+F1411 +#define ICON_MDI_CHAT_REMOVE_OUTLINE "\xf3\xb1\x90\x94" // U+F1414 +#define ICON_MDI_CHAT_SLEEP "\xf3\xb1\x8b\x91" // U+F12D1 +#define ICON_MDI_CHAT_SLEEP_OUTLINE "\xf3\xb1\x8b\x92" // U+F12D2 +#define ICON_MDI_CHECK "\xf3\xb0\x84\xac" // U+F012C +#define ICON_MDI_CHECK_ALL "\xf3\xb0\x84\xad" // U+F012D +#define ICON_MDI_CHECK_BOLD "\xf3\xb0\xb8\x9e" // U+F0E1E +#define ICON_MDI_CHECK_CIRCLE "\xf3\xb0\x97\xa0" // U+F05E0 +#define ICON_MDI_CHECK_CIRCLE_OUTLINE "\xf3\xb0\x97\xa1" // U+F05E1 +#define ICON_MDI_CHECK_DECAGRAM "\xf3\xb0\x9e\x91" // U+F0791 +#define ICON_MDI_CHECK_DECAGRAM_OUTLINE "\xf3\xb1\x9d\x80" // U+F1740 +#define ICON_MDI_CHECK_NETWORK "\xf3\xb0\xb1\x93" // U+F0C53 +#define ICON_MDI_CHECK_NETWORK_OUTLINE "\xf3\xb0\xb1\x94" // U+F0C54 +#define ICON_MDI_CHECK_OUTLINE "\xf3\xb0\xa1\x95" // U+F0855 +#define ICON_MDI_CHECK_UNDERLINE "\xf3\xb0\xb8\x9f" // U+F0E1F +#define ICON_MDI_CHECK_UNDERLINE_CIRCLE "\xf3\xb0\xb8\xa0" // U+F0E20 +#define ICON_MDI_CHECK_UNDERLINE_CIRCLE_OUTLINE "\xf3\xb0\xb8\xa1" // U+F0E21 +#define ICON_MDI_CHECKBOOK "\xf3\xb0\xaa\x9d" // U+F0A9D +#define ICON_MDI_CHECKBOOK_ARROW_LEFT "\xf3\xb1\xb0\x9d" // U+F1C1D +#define ICON_MDI_CHECKBOOK_ARROW_RIGHT "\xf3\xb1\xb0\x9e" // U+F1C1E +#define ICON_MDI_CHECKBOX_BLANK "\xf3\xb0\x84\xae" // U+F012E +#define ICON_MDI_CHECKBOX_BLANK_BADGE "\xf3\xb1\x85\xb6" // U+F1176 +#define ICON_MDI_CHECKBOX_BLANK_BADGE_OUTLINE "\xf3\xb0\x84\x97" // U+F0117 +#define ICON_MDI_CHECKBOX_BLANK_CIRCLE "\xf3\xb0\x84\xaf" // U+F012F +#define ICON_MDI_CHECKBOX_BLANK_CIRCLE_OUTLINE "\xf3\xb0\x84\xb0" // U+F0130 +#define ICON_MDI_CHECKBOX_BLANK_OFF "\xf3\xb1\x8b\xac" // U+F12EC +#define ICON_MDI_CHECKBOX_BLANK_OFF_OUTLINE "\xf3\xb1\x8b\xad" // U+F12ED +#define ICON_MDI_CHECKBOX_BLANK_OUTLINE "\xf3\xb0\x84\xb1" // U+F0131 +#define ICON_MDI_CHECKBOX_INTERMEDIATE "\xf3\xb0\xa1\x96" // U+F0856 +#define ICON_MDI_CHECKBOX_INTERMEDIATE_VARIANT "\xf3\xb1\xad\x94" // U+F1B54 +#define ICON_MDI_CHECKBOX_MARKED "\xf3\xb0\x84\xb2" // U+F0132 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE "\xf3\xb0\x84\xb3" // U+F0133 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_AUTO_OUTLINE "\xf3\xb1\xb0\xa6" // U+F1C26 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_MINUS_OUTLINE "\xf3\xb1\xb0\xa7" // U+F1C27 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_OUTLINE "\xf3\xb0\x84\xb4" // U+F0134 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_PLUS_OUTLINE "\xf3\xb1\xa4\xa7" // U+F1927 +#define ICON_MDI_CHECKBOX_MARKED_OUTLINE "\xf3\xb0\x84\xb5" // U+F0135 +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK "\xf3\xb0\x84\xb6" // U+F0136 +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_CIRCLE "\xf3\xb0\x98\xbb" // U+F063B +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_CIRCLE_OUTLINE "\xf3\xb0\x98\xbc" // U+F063C +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_OUTLINE "\xf3\xb0\x84\xb7" // U+F0137 +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED "\xf3\xb0\x84\xb8" // U+F0138 +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_CIRCLE "\xf3\xb0\x98\xbd" // U+F063D +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_CIRCLE_OUTLINE "\xf3\xb0\x98\xbe" // U+F063E +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_OUTLINE "\xf3\xb0\x84\xb9" // U+F0139 +#define ICON_MDI_CHECKBOX_MULTIPLE_OUTLINE "\xf3\xb0\xb1\x91" // U+F0C51 +#define ICON_MDI_CHECKBOX_OUTLINE "\xf3\xb0\xb1\x92" // U+F0C52 +#define ICON_MDI_CHECKERBOARD "\xf3\xb0\x84\xba" // U+F013A +#define ICON_MDI_CHECKERBOARD_MINUS "\xf3\xb1\x88\x82" // U+F1202 +#define ICON_MDI_CHECKERBOARD_PLUS "\xf3\xb1\x88\x81" // U+F1201 +#define ICON_MDI_CHECKERBOARD_REMOVE "\xf3\xb1\x88\x83" // U+F1203 +#define ICON_MDI_CHEESE "\xf3\xb1\x8a\xb9" // U+F12B9 +#define ICON_MDI_CHEESE_OFF "\xf3\xb1\x8f\xae" // U+F13EE +#define ICON_MDI_CHEF_HAT "\xf3\xb0\xad\xbc" // U+F0B7C +#define ICON_MDI_CHEMICAL_WEAPON "\xf3\xb0\x84\xbb" // U+F013B +#define ICON_MDI_CHESS_BISHOP "\xf3\xb0\xa1\x9c" // U+F085C +#define ICON_MDI_CHESS_KING "\xf3\xb0\xa1\x97" // U+F0857 +#define ICON_MDI_CHESS_KNIGHT "\xf3\xb0\xa1\x98" // U+F0858 +#define ICON_MDI_CHESS_PAWN "\xf3\xb0\xa1\x99" // U+F0859 +#define ICON_MDI_CHESS_QUEEN "\xf3\xb0\xa1\x9a" // U+F085A +#define ICON_MDI_CHESS_ROOK "\xf3\xb0\xa1\x9b" // U+F085B +#define ICON_MDI_CHEVRON_DOUBLE_DOWN "\xf3\xb0\x84\xbc" // U+F013C +#define ICON_MDI_CHEVRON_DOUBLE_LEFT "\xf3\xb0\x84\xbd" // U+F013D +#define ICON_MDI_CHEVRON_DOUBLE_RIGHT "\xf3\xb0\x84\xbe" // U+F013E +#define ICON_MDI_CHEVRON_DOUBLE_UP "\xf3\xb0\x84\xbf" // U+F013F +#define ICON_MDI_CHEVRON_DOWN "\xf3\xb0\x85\x80" // U+F0140 +#define ICON_MDI_CHEVRON_DOWN_BOX "\xf3\xb0\xa7\x96" // U+F09D6 +#define ICON_MDI_CHEVRON_DOWN_BOX_OUTLINE "\xf3\xb0\xa7\x97" // U+F09D7 +#define ICON_MDI_CHEVRON_DOWN_CIRCLE "\xf3\xb0\xac\xa6" // U+F0B26 +#define ICON_MDI_CHEVRON_DOWN_CIRCLE_OUTLINE "\xf3\xb0\xac\xa7" // U+F0B27 +#define ICON_MDI_CHEVRON_LEFT "\xf3\xb0\x85\x81" // U+F0141 +#define ICON_MDI_CHEVRON_LEFT_BOX "\xf3\xb0\xa7\x98" // U+F09D8 +#define ICON_MDI_CHEVRON_LEFT_BOX_OUTLINE "\xf3\xb0\xa7\x99" // U+F09D9 +#define ICON_MDI_CHEVRON_LEFT_CIRCLE "\xf3\xb0\xac\xa8" // U+F0B28 +#define ICON_MDI_CHEVRON_LEFT_CIRCLE_OUTLINE "\xf3\xb0\xac\xa9" // U+F0B29 +#define ICON_MDI_CHEVRON_RIGHT "\xf3\xb0\x85\x82" // U+F0142 +#define ICON_MDI_CHEVRON_RIGHT_BOX "\xf3\xb0\xa7\x9a" // U+F09DA +#define ICON_MDI_CHEVRON_RIGHT_BOX_OUTLINE "\xf3\xb0\xa7\x9b" // U+F09DB +#define ICON_MDI_CHEVRON_RIGHT_CIRCLE "\xf3\xb0\xac\xaa" // U+F0B2A +#define ICON_MDI_CHEVRON_RIGHT_CIRCLE_OUTLINE "\xf3\xb0\xac\xab" // U+F0B2B +#define ICON_MDI_CHEVRON_TRIPLE_DOWN "\xf3\xb0\xb6\xb9" // U+F0DB9 +#define ICON_MDI_CHEVRON_TRIPLE_LEFT "\xf3\xb0\xb6\xba" // U+F0DBA +#define ICON_MDI_CHEVRON_TRIPLE_RIGHT "\xf3\xb0\xb6\xbb" // U+F0DBB +#define ICON_MDI_CHEVRON_TRIPLE_UP "\xf3\xb0\xb6\xbc" // U+F0DBC +#define ICON_MDI_CHEVRON_UP "\xf3\xb0\x85\x83" // U+F0143 +#define ICON_MDI_CHEVRON_UP_BOX "\xf3\xb0\xa7\x9c" // U+F09DC +#define ICON_MDI_CHEVRON_UP_BOX_OUTLINE "\xf3\xb0\xa7\x9d" // U+F09DD +#define ICON_MDI_CHEVRON_UP_CIRCLE "\xf3\xb0\xac\xac" // U+F0B2C +#define ICON_MDI_CHEVRON_UP_CIRCLE_OUTLINE "\xf3\xb0\xac\xad" // U+F0B2D +#define ICON_MDI_CHILI_ALERT "\xf3\xb1\x9f\xaa" // U+F17EA +#define ICON_MDI_CHILI_ALERT_OUTLINE "\xf3\xb1\x9f\xab" // U+F17EB +#define ICON_MDI_CHILI_HOT "\xf3\xb0\x9e\xb2" // U+F07B2 +#define ICON_MDI_CHILI_HOT_OUTLINE "\xf3\xb1\x9f\xac" // U+F17EC +#define ICON_MDI_CHILI_MEDIUM "\xf3\xb0\x9e\xb3" // U+F07B3 +#define ICON_MDI_CHILI_MEDIUM_OUTLINE "\xf3\xb1\x9f\xad" // U+F17ED +#define ICON_MDI_CHILI_MILD "\xf3\xb0\x9e\xb4" // U+F07B4 +#define ICON_MDI_CHILI_MILD_OUTLINE "\xf3\xb1\x9f\xae" // U+F17EE +#define ICON_MDI_CHILI_OFF "\xf3\xb1\x91\xa7" // U+F1467 +#define ICON_MDI_CHILI_OFF_OUTLINE "\xf3\xb1\x9f\xaf" // U+F17EF +#define ICON_MDI_CHIP "\xf3\xb0\x98\x9a" // U+F061A +#define ICON_MDI_CHURCH "\xf3\xb0\x85\x84" // U+F0144 +#define ICON_MDI_CHURCH_OUTLINE "\xf3\xb1\xac\x82" // U+F1B02 +#define ICON_MDI_CIGAR "\xf3\xb1\x86\x89" // U+F1189 +#define ICON_MDI_CIGAR_OFF "\xf3\xb1\x90\x9b" // U+F141B +#define ICON_MDI_CIRCLE "\xf3\xb0\x9d\xa5" // U+F0765 +#define ICON_MDI_CIRCLE_BOX "\xf3\xb1\x97\x9c" // U+F15DC +#define ICON_MDI_CIRCLE_BOX_OUTLINE "\xf3\xb1\x97\x9d" // U+F15DD +#define ICON_MDI_CIRCLE_DOUBLE "\xf3\xb0\xba\x95" // U+F0E95 +#define ICON_MDI_CIRCLE_EDIT_OUTLINE "\xf3\xb0\xa3\x95" // U+F08D5 +#define ICON_MDI_CIRCLE_EXPAND "\xf3\xb0\xba\x96" // U+F0E96 +#define ICON_MDI_CIRCLE_HALF "\xf3\xb1\x8e\x95" // U+F1395 +#define ICON_MDI_CIRCLE_HALF_FULL "\xf3\xb1\x8e\x96" // U+F1396 +#define ICON_MDI_CIRCLE_MEDIUM "\xf3\xb0\xa7\x9e" // U+F09DE +#define ICON_MDI_CIRCLE_MULTIPLE "\xf3\xb0\xac\xb8" // U+F0B38 +#define ICON_MDI_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\x9a\x95" // U+F0695 +#define ICON_MDI_CIRCLE_OFF_OUTLINE "\xf3\xb1\x83\x93" // U+F10D3 +#define ICON_MDI_CIRCLE_OPACITY "\xf3\xb1\xa1\x93" // U+F1853 +#define ICON_MDI_CIRCLE_OUTLINE "\xf3\xb0\x9d\xa6" // U+F0766 +#define ICON_MDI_CIRCLE_SLICE_1 "\xf3\xb0\xaa\x9e" // U+F0A9E +#define ICON_MDI_CIRCLE_SLICE_2 "\xf3\xb0\xaa\x9f" // U+F0A9F +#define ICON_MDI_CIRCLE_SLICE_3 "\xf3\xb0\xaa\xa0" // U+F0AA0 +#define ICON_MDI_CIRCLE_SLICE_4 "\xf3\xb0\xaa\xa1" // U+F0AA1 +#define ICON_MDI_CIRCLE_SLICE_5 "\xf3\xb0\xaa\xa2" // U+F0AA2 +#define ICON_MDI_CIRCLE_SLICE_6 "\xf3\xb0\xaa\xa3" // U+F0AA3 +#define ICON_MDI_CIRCLE_SLICE_7 "\xf3\xb0\xaa\xa4" // U+F0AA4 +#define ICON_MDI_CIRCLE_SLICE_8 "\xf3\xb0\xaa\xa5" // U+F0AA5 +#define ICON_MDI_CIRCLE_SMALL "\xf3\xb0\xa7\x9f" // U+F09DF +#define ICON_MDI_CIRCULAR_SAW "\xf3\xb0\xb8\xa2" // U+F0E22 +#define ICON_MDI_CITY "\xf3\xb0\x85\x86" // U+F0146 +#define ICON_MDI_CITY_SWITCH "\xf3\xb1\xb0\xa8" // U+F1C28 +#define ICON_MDI_CITY_VARIANT "\xf3\xb0\xa8\xb6" // U+F0A36 +#define ICON_MDI_CITY_VARIANT_OUTLINE "\xf3\xb0\xa8\xb7" // U+F0A37 +#define ICON_MDI_CLIPBOARD "\xf3\xb0\x85\x87" // U+F0147 +#define ICON_MDI_CLIPBOARD_ACCOUNT "\xf3\xb0\x85\x88" // U+F0148 +#define ICON_MDI_CLIPBOARD_ACCOUNT_OUTLINE "\xf3\xb0\xb1\x95" // U+F0C55 +#define ICON_MDI_CLIPBOARD_ALERT "\xf3\xb0\x85\x89" // U+F0149 +#define ICON_MDI_CLIPBOARD_ALERT_OUTLINE "\xf3\xb0\xb3\xb7" // U+F0CF7 +#define ICON_MDI_CLIPBOARD_ARROW_DOWN "\xf3\xb0\x85\x8a" // U+F014A +#define ICON_MDI_CLIPBOARD_ARROW_DOWN_OUTLINE "\xf3\xb0\xb1\x96" // U+F0C56 +#define ICON_MDI_CLIPBOARD_ARROW_LEFT "\xf3\xb0\x85\x8b" // U+F014B +#define ICON_MDI_CLIPBOARD_ARROW_LEFT_OUTLINE "\xf3\xb0\xb3\xb8" // U+F0CF8 +#define ICON_MDI_CLIPBOARD_ARROW_RIGHT "\xf3\xb0\xb3\xb9" // U+F0CF9 +#define ICON_MDI_CLIPBOARD_ARROW_RIGHT_OUTLINE "\xf3\xb0\xb3\xba" // U+F0CFA +#define ICON_MDI_CLIPBOARD_ARROW_UP "\xf3\xb0\xb1\x97" // U+F0C57 +#define ICON_MDI_CLIPBOARD_ARROW_UP_OUTLINE "\xf3\xb0\xb1\x98" // U+F0C58 +#define ICON_MDI_CLIPBOARD_CHECK "\xf3\xb0\x85\x8e" // U+F014E +#define ICON_MDI_CLIPBOARD_CHECK_MULTIPLE "\xf3\xb1\x89\xa3" // U+F1263 +#define ICON_MDI_CLIPBOARD_CHECK_MULTIPLE_OUTLINE "\xf3\xb1\x89\xa4" // U+F1264 +#define ICON_MDI_CLIPBOARD_CHECK_OUTLINE "\xf3\xb0\xa2\xa8" // U+F08A8 +#define ICON_MDI_CLIPBOARD_CLOCK "\xf3\xb1\x9b\xa2" // U+F16E2 +#define ICON_MDI_CLIPBOARD_CLOCK_OUTLINE "\xf3\xb1\x9b\xa3" // U+F16E3 +#define ICON_MDI_CLIPBOARD_EDIT "\xf3\xb1\x93\xa5" // U+F14E5 +#define ICON_MDI_CLIPBOARD_EDIT_OUTLINE "\xf3\xb1\x93\xa6" // U+F14E6 +#define ICON_MDI_CLIPBOARD_FILE "\xf3\xb1\x89\xa5" // U+F1265 +#define ICON_MDI_CLIPBOARD_FILE_OUTLINE "\xf3\xb1\x89\xa6" // U+F1266 +#define ICON_MDI_CLIPBOARD_FLOW "\xf3\xb0\x9b\x88" // U+F06C8 +#define ICON_MDI_CLIPBOARD_FLOW_OUTLINE "\xf3\xb1\x84\x97" // U+F1117 +#define ICON_MDI_CLIPBOARD_LIST "\xf3\xb1\x83\x94" // U+F10D4 +#define ICON_MDI_CLIPBOARD_LIST_OUTLINE "\xf3\xb1\x83\x95" // U+F10D5 +#define ICON_MDI_CLIPBOARD_MINUS "\xf3\xb1\x98\x98" // U+F1618 +#define ICON_MDI_CLIPBOARD_MINUS_OUTLINE "\xf3\xb1\x98\x99" // U+F1619 +#define ICON_MDI_CLIPBOARD_MULTIPLE "\xf3\xb1\x89\xa7" // U+F1267 +#define ICON_MDI_CLIPBOARD_MULTIPLE_OUTLINE "\xf3\xb1\x89\xa8" // U+F1268 +#define ICON_MDI_CLIPBOARD_OFF "\xf3\xb1\x98\x9a" // U+F161A +#define ICON_MDI_CLIPBOARD_OFF_OUTLINE "\xf3\xb1\x98\x9b" // U+F161B +#define ICON_MDI_CLIPBOARD_OUTLINE "\xf3\xb0\x85\x8c" // U+F014C +#define ICON_MDI_CLIPBOARD_PLAY "\xf3\xb0\xb1\x99" // U+F0C59 +#define ICON_MDI_CLIPBOARD_PLAY_MULTIPLE "\xf3\xb1\x89\xa9" // U+F1269 +#define ICON_MDI_CLIPBOARD_PLAY_MULTIPLE_OUTLINE "\xf3\xb1\x89\xaa" // U+F126A +#define ICON_MDI_CLIPBOARD_PLAY_OUTLINE "\xf3\xb0\xb1\x9a" // U+F0C5A +#define ICON_MDI_CLIPBOARD_PLUS "\xf3\xb0\x9d\x91" // U+F0751 +#define ICON_MDI_CLIPBOARD_PLUS_OUTLINE "\xf3\xb1\x8c\x9f" // U+F131F +#define ICON_MDI_CLIPBOARD_PULSE "\xf3\xb0\xa1\x9d" // U+F085D +#define ICON_MDI_CLIPBOARD_PULSE_OUTLINE "\xf3\xb0\xa1\x9e" // U+F085E +#define ICON_MDI_CLIPBOARD_REMOVE "\xf3\xb1\x98\x9c" // U+F161C +#define ICON_MDI_CLIPBOARD_REMOVE_OUTLINE "\xf3\xb1\x98\x9d" // U+F161D +#define ICON_MDI_CLIPBOARD_SEARCH "\xf3\xb1\x98\x9e" // U+F161E +#define ICON_MDI_CLIPBOARD_SEARCH_OUTLINE "\xf3\xb1\x98\x9f" // U+F161F +#define ICON_MDI_CLIPBOARD_TEXT "\xf3\xb0\x85\x8d" // U+F014D +#define ICON_MDI_CLIPBOARD_TEXT_CLOCK "\xf3\xb1\xa3\xb9" // U+F18F9 +#define ICON_MDI_CLIPBOARD_TEXT_CLOCK_OUTLINE "\xf3\xb1\xa3\xba" // U+F18FA +#define ICON_MDI_CLIPBOARD_TEXT_MULTIPLE "\xf3\xb1\x89\xab" // U+F126B +#define ICON_MDI_CLIPBOARD_TEXT_MULTIPLE_OUTLINE "\xf3\xb1\x89\xac" // U+F126C +#define ICON_MDI_CLIPBOARD_TEXT_OFF "\xf3\xb1\x98\xa0" // U+F1620 +#define ICON_MDI_CLIPBOARD_TEXT_OFF_OUTLINE "\xf3\xb1\x98\xa1" // U+F1621 +#define ICON_MDI_CLIPBOARD_TEXT_OUTLINE "\xf3\xb0\xa8\xb8" // U+F0A38 +#define ICON_MDI_CLIPBOARD_TEXT_PLAY "\xf3\xb0\xb1\x9b" // U+F0C5B +#define ICON_MDI_CLIPBOARD_TEXT_PLAY_OUTLINE "\xf3\xb0\xb1\x9c" // U+F0C5C +#define ICON_MDI_CLIPBOARD_TEXT_SEARCH "\xf3\xb1\x98\xa2" // U+F1622 +#define ICON_MDI_CLIPBOARD_TEXT_SEARCH_OUTLINE "\xf3\xb1\x98\xa3" // U+F1623 +#define ICON_MDI_CLIPPY "\xf3\xb0\x85\x8f" // U+F014F +#define ICON_MDI_CLOCK "\xf3\xb0\xa5\x94" // U+F0954 +#define ICON_MDI_CLOCK_ALERT "\xf3\xb0\xa5\x95" // U+F0955 +#define ICON_MDI_CLOCK_ALERT_OUTLINE "\xf3\xb0\x97\x8e" // U+F05CE +#define ICON_MDI_CLOCK_CHECK "\xf3\xb0\xbe\xa8" // U+F0FA8 +#define ICON_MDI_CLOCK_CHECK_OUTLINE "\xf3\xb0\xbe\xa9" // U+F0FA9 +#define ICON_MDI_CLOCK_DIGITAL "\xf3\xb0\xba\x97" // U+F0E97 +#define ICON_MDI_CLOCK_EDIT "\xf3\xb1\xa6\xba" // U+F19BA +#define ICON_MDI_CLOCK_EDIT_OUTLINE "\xf3\xb1\xa6\xbb" // U+F19BB +#define ICON_MDI_CLOCK_END "\xf3\xb0\x85\x91" // U+F0151 +#define ICON_MDI_CLOCK_FAST "\xf3\xb0\x85\x92" // U+F0152 +#define ICON_MDI_CLOCK_IN "\xf3\xb0\x85\x93" // U+F0153 +#define ICON_MDI_CLOCK_MINUS "\xf3\xb1\xa1\xa3" // U+F1863 +#define ICON_MDI_CLOCK_MINUS_OUTLINE "\xf3\xb1\xa1\xa4" // U+F1864 +#define ICON_MDI_CLOCK_OUT "\xf3\xb0\x85\x94" // U+F0154 +#define ICON_MDI_CLOCK_OUTLINE "\xf3\xb0\x85\x90" // U+F0150 +#define ICON_MDI_CLOCK_PLUS "\xf3\xb1\xa1\xa1" // U+F1861 +#define ICON_MDI_CLOCK_PLUS_OUTLINE "\xf3\xb1\xa1\xa2" // U+F1862 +#define ICON_MDI_CLOCK_REMOVE "\xf3\xb1\xa1\xa5" // U+F1865 +#define ICON_MDI_CLOCK_REMOVE_OUTLINE "\xf3\xb1\xa1\xa6" // U+F1866 +#define ICON_MDI_CLOCK_STAR_FOUR_POINTS "\xf3\xb1\xb0\xa9" // U+F1C29 +#define ICON_MDI_CLOCK_STAR_FOUR_POINTS_OUTLINE "\xf3\xb1\xb0\xaa" // U+F1C2A +#define ICON_MDI_CLOCK_START "\xf3\xb0\x85\x95" // U+F0155 +#define ICON_MDI_CLOCK_TIME_EIGHT "\xf3\xb1\x91\x86" // U+F1446 +#define ICON_MDI_CLOCK_TIME_EIGHT_OUTLINE "\xf3\xb1\x91\x92" // U+F1452 +#define ICON_MDI_CLOCK_TIME_ELEVEN "\xf3\xb1\x91\x89" // U+F1449 +#define ICON_MDI_CLOCK_TIME_ELEVEN_OUTLINE "\xf3\xb1\x91\x95" // U+F1455 +#define ICON_MDI_CLOCK_TIME_FIVE "\xf3\xb1\x91\x83" // U+F1443 +#define ICON_MDI_CLOCK_TIME_FIVE_OUTLINE "\xf3\xb1\x91\x8f" // U+F144F +#define ICON_MDI_CLOCK_TIME_FOUR "\xf3\xb1\x91\x82" // U+F1442 +#define ICON_MDI_CLOCK_TIME_FOUR_OUTLINE "\xf3\xb1\x91\x8e" // U+F144E +#define ICON_MDI_CLOCK_TIME_NINE "\xf3\xb1\x91\x87" // U+F1447 +#define ICON_MDI_CLOCK_TIME_NINE_OUTLINE "\xf3\xb1\x91\x93" // U+F1453 +#define ICON_MDI_CLOCK_TIME_ONE "\xf3\xb1\x90\xbf" // U+F143F +#define ICON_MDI_CLOCK_TIME_ONE_OUTLINE "\xf3\xb1\x91\x8b" // U+F144B +#define ICON_MDI_CLOCK_TIME_SEVEN "\xf3\xb1\x91\x85" // U+F1445 +#define ICON_MDI_CLOCK_TIME_SEVEN_OUTLINE "\xf3\xb1\x91\x91" // U+F1451 +#define ICON_MDI_CLOCK_TIME_SIX "\xf3\xb1\x91\x84" // U+F1444 +#define ICON_MDI_CLOCK_TIME_SIX_OUTLINE "\xf3\xb1\x91\x90" // U+F1450 +#define ICON_MDI_CLOCK_TIME_TEN "\xf3\xb1\x91\x88" // U+F1448 +#define ICON_MDI_CLOCK_TIME_TEN_OUTLINE "\xf3\xb1\x91\x94" // U+F1454 +#define ICON_MDI_CLOCK_TIME_THREE "\xf3\xb1\x91\x81" // U+F1441 +#define ICON_MDI_CLOCK_TIME_THREE_OUTLINE "\xf3\xb1\x91\x8d" // U+F144D +#define ICON_MDI_CLOCK_TIME_TWELVE "\xf3\xb1\x91\x8a" // U+F144A +#define ICON_MDI_CLOCK_TIME_TWELVE_OUTLINE "\xf3\xb1\x91\x96" // U+F1456 +#define ICON_MDI_CLOCK_TIME_TWO "\xf3\xb1\x91\x80" // U+F1440 +#define ICON_MDI_CLOCK_TIME_TWO_OUTLINE "\xf3\xb1\x91\x8c" // U+F144C +#define ICON_MDI_CLOSE "\xf3\xb0\x85\x96" // U+F0156 +#define ICON_MDI_CLOSE_BOX "\xf3\xb0\x85\x97" // U+F0157 +#define ICON_MDI_CLOSE_BOX_MULTIPLE "\xf3\xb0\xb1\x9d" // U+F0C5D +#define ICON_MDI_CLOSE_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xb1\x9e" // U+F0C5E +#define ICON_MDI_CLOSE_BOX_OUTLINE "\xf3\xb0\x85\x98" // U+F0158 +#define ICON_MDI_CLOSE_CIRCLE "\xf3\xb0\x85\x99" // U+F0159 +#define ICON_MDI_CLOSE_CIRCLE_MULTIPLE "\xf3\xb0\x98\xaa" // U+F062A +#define ICON_MDI_CLOSE_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\xa2\x83" // U+F0883 +#define ICON_MDI_CLOSE_CIRCLE_OUTLINE "\xf3\xb0\x85\x9a" // U+F015A +#define ICON_MDI_CLOSE_NETWORK "\xf3\xb0\x85\x9b" // U+F015B +#define ICON_MDI_CLOSE_NETWORK_OUTLINE "\xf3\xb0\xb1\x9f" // U+F0C5F +#define ICON_MDI_CLOSE_OCTAGON "\xf3\xb0\x85\x9c" // U+F015C +#define ICON_MDI_CLOSE_OCTAGON_OUTLINE "\xf3\xb0\x85\x9d" // U+F015D +#define ICON_MDI_CLOSE_OUTLINE "\xf3\xb0\x9b\x89" // U+F06C9 +#define ICON_MDI_CLOSE_THICK "\xf3\xb1\x8e\x98" // U+F1398 +#define ICON_MDI_CLOSED_CAPTION "\xf3\xb0\x85\x9e" // U+F015E +#define ICON_MDI_CLOSED_CAPTION_OUTLINE "\xf3\xb0\xb6\xbd" // U+F0DBD +#define ICON_MDI_CLOUD "\xf3\xb0\x85\x9f" // U+F015F +#define ICON_MDI_CLOUD_ALERT "\xf3\xb0\xa7\xa0" // U+F09E0 +#define ICON_MDI_CLOUD_ALERT_OUTLINE "\xf3\xb1\xaf\xa0" // U+F1BE0 +#define ICON_MDI_CLOUD_ARROW_DOWN "\xf3\xb1\xaf\xa1" // U+F1BE1 +#define ICON_MDI_CLOUD_ARROW_DOWN_OUTLINE "\xf3\xb1\xaf\xa2" // U+F1BE2 +#define ICON_MDI_CLOUD_ARROW_LEFT "\xf3\xb1\xaf\xa3" // U+F1BE3 +#define ICON_MDI_CLOUD_ARROW_LEFT_OUTLINE "\xf3\xb1\xaf\xa4" // U+F1BE4 +#define ICON_MDI_CLOUD_ARROW_RIGHT "\xf3\xb1\xaf\xa5" // U+F1BE5 +#define ICON_MDI_CLOUD_ARROW_RIGHT_OUTLINE "\xf3\xb1\xaf\xa6" // U+F1BE6 +#define ICON_MDI_CLOUD_ARROW_UP "\xf3\xb1\xaf\xa7" // U+F1BE7 +#define ICON_MDI_CLOUD_ARROW_UP_OUTLINE "\xf3\xb1\xaf\xa8" // U+F1BE8 +#define ICON_MDI_CLOUD_BRACES "\xf3\xb0\x9e\xb5" // U+F07B5 +#define ICON_MDI_CLOUD_CANCEL "\xf3\xb1\xaf\xa9" // U+F1BE9 +#define ICON_MDI_CLOUD_CANCEL_OUTLINE "\xf3\xb1\xaf\xaa" // U+F1BEA +#define ICON_MDI_CLOUD_CHECK "\xf3\xb1\xaf\xab" // U+F1BEB +#define ICON_MDI_CLOUD_CHECK_OUTLINE "\xf3\xb1\xaf\xac" // U+F1BEC +#define ICON_MDI_CLOUD_CHECK_VARIANT "\xf3\xb0\x85\xa0" // U+F0160 +#define ICON_MDI_CLOUD_CHECK_VARIANT_OUTLINE "\xf3\xb1\x8b\x8c" // U+F12CC +#define ICON_MDI_CLOUD_CIRCLE "\xf3\xb0\x85\xa1" // U+F0161 +#define ICON_MDI_CLOUD_CIRCLE_OUTLINE "\xf3\xb1\xaf\xad" // U+F1BED +#define ICON_MDI_CLOUD_CLOCK "\xf3\xb1\xaf\xae" // U+F1BEE +#define ICON_MDI_CLOUD_CLOCK_OUTLINE "\xf3\xb1\xaf\xaf" // U+F1BEF +#define ICON_MDI_CLOUD_COG "\xf3\xb1\xaf\xb0" // U+F1BF0 +#define ICON_MDI_CLOUD_COG_OUTLINE "\xf3\xb1\xaf\xb1" // U+F1BF1 +#define ICON_MDI_CLOUD_DOWNLOAD "\xf3\xb0\x85\xa2" // U+F0162 +#define ICON_MDI_CLOUD_DOWNLOAD_OUTLINE "\xf3\xb0\xad\xbd" // U+F0B7D +#define ICON_MDI_CLOUD_KEY "\xf3\xb1\xb2\xa1" // U+F1CA1 +#define ICON_MDI_CLOUD_KEY_OUTLINE "\xf3\xb1\xb2\xa2" // U+F1CA2 +#define ICON_MDI_CLOUD_LOCK "\xf3\xb1\x87\xb1" // U+F11F1 +#define ICON_MDI_CLOUD_LOCK_OPEN "\xf3\xb1\xaf\xb2" // U+F1BF2 +#define ICON_MDI_CLOUD_LOCK_OPEN_OUTLINE "\xf3\xb1\xaf\xb3" // U+F1BF3 +#define ICON_MDI_CLOUD_LOCK_OUTLINE "\xf3\xb1\x87\xb2" // U+F11F2 +#define ICON_MDI_CLOUD_MINUS "\xf3\xb1\xaf\xb4" // U+F1BF4 +#define ICON_MDI_CLOUD_MINUS_OUTLINE "\xf3\xb1\xaf\xb5" // U+F1BF5 +#define ICON_MDI_CLOUD_OFF "\xf3\xb1\xaf\xb6" // U+F1BF6 +#define ICON_MDI_CLOUD_OFF_OUTLINE "\xf3\xb0\x85\xa4" // U+F0164 +#define ICON_MDI_CLOUD_OUTLINE "\xf3\xb0\x85\xa3" // U+F0163 +#define ICON_MDI_CLOUD_PERCENT "\xf3\xb1\xa8\xb5" // U+F1A35 +#define ICON_MDI_CLOUD_PERCENT_OUTLINE "\xf3\xb1\xa8\xb6" // U+F1A36 +#define ICON_MDI_CLOUD_PLUS "\xf3\xb1\xaf\xb7" // U+F1BF7 +#define ICON_MDI_CLOUD_PLUS_OUTLINE "\xf3\xb1\xaf\xb8" // U+F1BF8 +#define ICON_MDI_CLOUD_PRINT "\xf3\xb0\x85\xa5" // U+F0165 +#define ICON_MDI_CLOUD_PRINT_OUTLINE "\xf3\xb0\x85\xa6" // U+F0166 +#define ICON_MDI_CLOUD_QUESTION "\xf3\xb0\xa8\xb9" // U+F0A39 +#define ICON_MDI_CLOUD_QUESTION_OUTLINE "\xf3\xb1\xaf\xb9" // U+F1BF9 +#define ICON_MDI_CLOUD_REFRESH "\xf3\xb1\xaf\xba" // U+F1BFA +#define ICON_MDI_CLOUD_REFRESH_OUTLINE "\xf3\xb1\xaf\xbb" // U+F1BFB +#define ICON_MDI_CLOUD_REFRESH_VARIANT "\xf3\xb0\x94\xaa" // U+F052A +#define ICON_MDI_CLOUD_REFRESH_VARIANT_OUTLINE "\xf3\xb1\xaf\xbc" // U+F1BFC +#define ICON_MDI_CLOUD_REMOVE "\xf3\xb1\xaf\xbd" // U+F1BFD +#define ICON_MDI_CLOUD_REMOVE_OUTLINE "\xf3\xb1\xaf\xbe" // U+F1BFE +#define ICON_MDI_CLOUD_SEARCH "\xf3\xb0\xa5\x96" // U+F0956 +#define ICON_MDI_CLOUD_SEARCH_OUTLINE "\xf3\xb0\xa5\x97" // U+F0957 +#define ICON_MDI_CLOUD_SYNC "\xf3\xb0\x98\xbf" // U+F063F +#define ICON_MDI_CLOUD_SYNC_OUTLINE "\xf3\xb1\x8b\x96" // U+F12D6 +#define ICON_MDI_CLOUD_TAGS "\xf3\xb0\x9e\xb6" // U+F07B6 +#define ICON_MDI_CLOUD_UPLOAD "\xf3\xb0\x85\xa7" // U+F0167 +#define ICON_MDI_CLOUD_UPLOAD_OUTLINE "\xf3\xb0\xad\xbe" // U+F0B7E +#define ICON_MDI_CLOUDS "\xf3\xb1\xae\x95" // U+F1B95 +#define ICON_MDI_CLOVER "\xf3\xb0\xa0\x96" // U+F0816 +#define ICON_MDI_CLOVER_OUTLINE "\xf3\xb1\xb1\xa2" // U+F1C62 +#define ICON_MDI_COACH_LAMP "\xf3\xb1\x80\xa0" // U+F1020 +#define ICON_MDI_COACH_LAMP_VARIANT "\xf3\xb1\xa8\xb7" // U+F1A37 +#define ICON_MDI_COAT_RACK "\xf3\xb1\x82\x9e" // U+F109E +#define ICON_MDI_CODE_ARRAY "\xf3\xb0\x85\xa8" // U+F0168 +#define ICON_MDI_CODE_BLOCK_BRACES "\xf3\xb1\xb2\x83" // U+F1C83 +#define ICON_MDI_CODE_BLOCK_BRACKETS "\xf3\xb1\xb2\x84" // U+F1C84 +#define ICON_MDI_CODE_BLOCK_PARENTHESES "\xf3\xb1\xb2\x85" // U+F1C85 +#define ICON_MDI_CODE_BLOCK_TAGS "\xf3\xb1\xb2\x86" // U+F1C86 +#define ICON_MDI_CODE_BRACES "\xf3\xb0\x85\xa9" // U+F0169 +#define ICON_MDI_CODE_BRACES_BOX "\xf3\xb1\x83\x96" // U+F10D6 +#define ICON_MDI_CODE_BRACKETS "\xf3\xb0\x85\xaa" // U+F016A +#define ICON_MDI_CODE_EQUAL "\xf3\xb0\x85\xab" // U+F016B +#define ICON_MDI_CODE_GREATER_THAN "\xf3\xb0\x85\xac" // U+F016C +#define ICON_MDI_CODE_GREATER_THAN_OR_EQUAL "\xf3\xb0\x85\xad" // U+F016D +#define ICON_MDI_CODE_JSON "\xf3\xb0\x98\xa6" // U+F0626 +#define ICON_MDI_CODE_LESS_THAN "\xf3\xb0\x85\xae" // U+F016E +#define ICON_MDI_CODE_LESS_THAN_OR_EQUAL "\xf3\xb0\x85\xaf" // U+F016F +#define ICON_MDI_CODE_NOT_EQUAL "\xf3\xb0\x85\xb0" // U+F0170 +#define ICON_MDI_CODE_NOT_EQUAL_VARIANT "\xf3\xb0\x85\xb1" // U+F0171 +#define ICON_MDI_CODE_PARENTHESES "\xf3\xb0\x85\xb2" // U+F0172 +#define ICON_MDI_CODE_PARENTHESES_BOX "\xf3\xb1\x83\x97" // U+F10D7 +#define ICON_MDI_CODE_STRING "\xf3\xb0\x85\xb3" // U+F0173 +#define ICON_MDI_CODE_TAGS "\xf3\xb0\x85\xb4" // U+F0174 +#define ICON_MDI_CODE_TAGS_CHECK "\xf3\xb0\x9a\x94" // U+F0694 +#define ICON_MDI_CODEPEN "\xf3\xb0\x85\xb5" // U+F0175 +#define ICON_MDI_COFFEE "\xf3\xb0\x85\xb6" // U+F0176 +#define ICON_MDI_COFFEE_MAKER "\xf3\xb1\x82\x9f" // U+F109F +#define ICON_MDI_COFFEE_MAKER_CHECK "\xf3\xb1\xa4\xb1" // U+F1931 +#define ICON_MDI_COFFEE_MAKER_CHECK_OUTLINE "\xf3\xb1\xa4\xb2" // U+F1932 +#define ICON_MDI_COFFEE_MAKER_OUTLINE "\xf3\xb1\xa0\x9b" // U+F181B +#define ICON_MDI_COFFEE_OFF "\xf3\xb0\xbe\xaa" // U+F0FAA +#define ICON_MDI_COFFEE_OFF_OUTLINE "\xf3\xb0\xbe\xab" // U+F0FAB +#define ICON_MDI_COFFEE_OUTLINE "\xf3\xb0\x9b\x8a" // U+F06CA +#define ICON_MDI_COFFEE_TO_GO "\xf3\xb0\x85\xb7" // U+F0177 +#define ICON_MDI_COFFEE_TO_GO_OUTLINE "\xf3\xb1\x8c\x8e" // U+F130E +#define ICON_MDI_COFFIN "\xf3\xb0\xad\xbf" // U+F0B7F +#define ICON_MDI_COG "\xf3\xb0\x92\x93" // U+F0493 +#define ICON_MDI_COG_BOX "\xf3\xb0\x92\x94" // U+F0494 +#define ICON_MDI_COG_CLOCKWISE "\xf3\xb1\x87\x9d" // U+F11DD +#define ICON_MDI_COG_COUNTERCLOCKWISE "\xf3\xb1\x87\x9e" // U+F11DE +#define ICON_MDI_COG_OFF "\xf3\xb1\x8f\x8e" // U+F13CE +#define ICON_MDI_COG_OFF_OUTLINE "\xf3\xb1\x8f\x8f" // U+F13CF +#define ICON_MDI_COG_OUTLINE "\xf3\xb0\xa2\xbb" // U+F08BB +#define ICON_MDI_COG_PAUSE "\xf3\xb1\xa4\xb3" // U+F1933 +#define ICON_MDI_COG_PAUSE_OUTLINE "\xf3\xb1\xa4\xb4" // U+F1934 +#define ICON_MDI_COG_PLAY "\xf3\xb1\xa4\xb5" // U+F1935 +#define ICON_MDI_COG_PLAY_OUTLINE "\xf3\xb1\xa4\xb6" // U+F1936 +#define ICON_MDI_COG_REFRESH "\xf3\xb1\x91\x9e" // U+F145E +#define ICON_MDI_COG_REFRESH_OUTLINE "\xf3\xb1\x91\x9f" // U+F145F +#define ICON_MDI_COG_STOP "\xf3\xb1\xa4\xb7" // U+F1937 +#define ICON_MDI_COG_STOP_OUTLINE "\xf3\xb1\xa4\xb8" // U+F1938 +#define ICON_MDI_COG_SYNC "\xf3\xb1\x91\xa0" // U+F1460 +#define ICON_MDI_COG_SYNC_OUTLINE "\xf3\xb1\x91\xa1" // U+F1461 +#define ICON_MDI_COG_TRANSFER "\xf3\xb1\x81\x9b" // U+F105B +#define ICON_MDI_COG_TRANSFER_OUTLINE "\xf3\xb1\x81\x9c" // U+F105C +#define ICON_MDI_COGS "\xf3\xb0\xa3\x96" // U+F08D6 +#define ICON_MDI_COLLAGE "\xf3\xb0\x99\x80" // U+F0640 +#define ICON_MDI_COLLAPSE_ALL "\xf3\xb0\xaa\xa6" // U+F0AA6 +#define ICON_MDI_COLLAPSE_ALL_OUTLINE "\xf3\xb0\xaa\xa7" // U+F0AA7 +#define ICON_MDI_COLOR_HELPER "\xf3\xb0\x85\xb9" // U+F0179 +#define ICON_MDI_COMMA "\xf3\xb0\xb8\xa3" // U+F0E23 +#define ICON_MDI_COMMA_BOX "\xf3\xb0\xb8\xab" // U+F0E2B +#define ICON_MDI_COMMA_BOX_OUTLINE "\xf3\xb0\xb8\xa4" // U+F0E24 +#define ICON_MDI_COMMA_CIRCLE "\xf3\xb0\xb8\xa5" // U+F0E25 +#define ICON_MDI_COMMA_CIRCLE_OUTLINE "\xf3\xb0\xb8\xa6" // U+F0E26 +#define ICON_MDI_COMMENT "\xf3\xb0\x85\xba" // U+F017A +#define ICON_MDI_COMMENT_ACCOUNT "\xf3\xb0\x85\xbb" // U+F017B +#define ICON_MDI_COMMENT_ACCOUNT_OUTLINE "\xf3\xb0\x85\xbc" // U+F017C +#define ICON_MDI_COMMENT_ALERT "\xf3\xb0\x85\xbd" // U+F017D +#define ICON_MDI_COMMENT_ALERT_OUTLINE "\xf3\xb0\x85\xbe" // U+F017E +#define ICON_MDI_COMMENT_ARROW_LEFT "\xf3\xb0\xa7\xa1" // U+F09E1 +#define ICON_MDI_COMMENT_ARROW_LEFT_OUTLINE "\xf3\xb0\xa7\xa2" // U+F09E2 +#define ICON_MDI_COMMENT_ARROW_RIGHT "\xf3\xb0\xa7\xa3" // U+F09E3 +#define ICON_MDI_COMMENT_ARROW_RIGHT_OUTLINE "\xf3\xb0\xa7\xa4" // U+F09E4 +#define ICON_MDI_COMMENT_BOOKMARK "\xf3\xb1\x96\xae" // U+F15AE +#define ICON_MDI_COMMENT_BOOKMARK_OUTLINE "\xf3\xb1\x96\xaf" // U+F15AF +#define ICON_MDI_COMMENT_CHECK "\xf3\xb0\x85\xbf" // U+F017F +#define ICON_MDI_COMMENT_CHECK_OUTLINE "\xf3\xb0\x86\x80" // U+F0180 +#define ICON_MDI_COMMENT_EDIT "\xf3\xb1\x86\xbf" // U+F11BF +#define ICON_MDI_COMMENT_EDIT_OUTLINE "\xf3\xb1\x8b\x84" // U+F12C4 +#define ICON_MDI_COMMENT_EYE "\xf3\xb0\xa8\xba" // U+F0A3A +#define ICON_MDI_COMMENT_EYE_OUTLINE "\xf3\xb0\xa8\xbb" // U+F0A3B +#define ICON_MDI_COMMENT_FLASH "\xf3\xb1\x96\xb0" // U+F15B0 +#define ICON_MDI_COMMENT_FLASH_OUTLINE "\xf3\xb1\x96\xb1" // U+F15B1 +#define ICON_MDI_COMMENT_MINUS "\xf3\xb1\x97\x9f" // U+F15DF +#define ICON_MDI_COMMENT_MINUS_OUTLINE "\xf3\xb1\x97\xa0" // U+F15E0 +#define ICON_MDI_COMMENT_MULTIPLE "\xf3\xb0\xa1\x9f" // U+F085F +#define ICON_MDI_COMMENT_MULTIPLE_OUTLINE "\xf3\xb0\x86\x81" // U+F0181 +#define ICON_MDI_COMMENT_OFF "\xf3\xb1\x97\xa1" // U+F15E1 +#define ICON_MDI_COMMENT_OFF_OUTLINE "\xf3\xb1\x97\xa2" // U+F15E2 +#define ICON_MDI_COMMENT_OUTLINE "\xf3\xb0\x86\x82" // U+F0182 +#define ICON_MDI_COMMENT_PLUS "\xf3\xb0\xa7\xa5" // U+F09E5 +#define ICON_MDI_COMMENT_PLUS_OUTLINE "\xf3\xb0\x86\x83" // U+F0183 +#define ICON_MDI_COMMENT_PROCESSING "\xf3\xb0\x86\x84" // U+F0184 +#define ICON_MDI_COMMENT_PROCESSING_OUTLINE "\xf3\xb0\x86\x85" // U+F0185 +#define ICON_MDI_COMMENT_QUESTION "\xf3\xb0\xa0\x97" // U+F0817 +#define ICON_MDI_COMMENT_QUESTION_OUTLINE "\xf3\xb0\x86\x86" // U+F0186 +#define ICON_MDI_COMMENT_QUOTE "\xf3\xb1\x80\xa1" // U+F1021 +#define ICON_MDI_COMMENT_QUOTE_OUTLINE "\xf3\xb1\x80\xa2" // U+F1022 +#define ICON_MDI_COMMENT_REMOVE "\xf3\xb0\x97\x9e" // U+F05DE +#define ICON_MDI_COMMENT_REMOVE_OUTLINE "\xf3\xb0\x86\x87" // U+F0187 +#define ICON_MDI_COMMENT_SEARCH "\xf3\xb0\xa8\xbc" // U+F0A3C +#define ICON_MDI_COMMENT_SEARCH_OUTLINE "\xf3\xb0\xa8\xbd" // U+F0A3D +#define ICON_MDI_COMMENT_TEXT "\xf3\xb0\x86\x88" // U+F0188 +#define ICON_MDI_COMMENT_TEXT_MULTIPLE "\xf3\xb0\xa1\xa0" // U+F0860 +#define ICON_MDI_COMMENT_TEXT_MULTIPLE_OUTLINE "\xf3\xb0\xa1\xa1" // U+F0861 +#define ICON_MDI_COMMENT_TEXT_OUTLINE "\xf3\xb0\x86\x89" // U+F0189 +#define ICON_MDI_COMPARE "\xf3\xb0\x86\x8a" // U+F018A +#define ICON_MDI_COMPARE_HORIZONTAL "\xf3\xb1\x92\x92" // U+F1492 +#define ICON_MDI_COMPARE_REMOVE "\xf3\xb1\xa2\xb3" // U+F18B3 +#define ICON_MDI_COMPARE_VERTICAL "\xf3\xb1\x92\x93" // U+F1493 +#define ICON_MDI_COMPASS "\xf3\xb0\x86\x8b" // U+F018B +#define ICON_MDI_COMPASS_OFF "\xf3\xb0\xae\x80" // U+F0B80 +#define ICON_MDI_COMPASS_OFF_OUTLINE "\xf3\xb0\xae\x81" // U+F0B81 +#define ICON_MDI_COMPASS_OUTLINE "\xf3\xb0\x86\x8c" // U+F018C +#define ICON_MDI_COMPASS_ROSE "\xf3\xb1\x8e\x82" // U+F1382 +#define ICON_MDI_COMPOST "\xf3\xb1\xa8\xb8" // U+F1A38 +#define ICON_MDI_CONE "\xf3\xb1\xa5\x8c" // U+F194C +#define ICON_MDI_CONE_OFF "\xf3\xb1\xa5\x8d" // U+F194D +#define ICON_MDI_CONNECTION "\xf3\xb1\x98\x96" // U+F1616 +#define ICON_MDI_CONSOLE "\xf3\xb0\x86\x8d" // U+F018D +#define ICON_MDI_CONSOLE_LINE "\xf3\xb0\x9e\xb7" // U+F07B7 +#define ICON_MDI_CONSOLE_NETWORK "\xf3\xb0\xa2\xa9" // U+F08A9 +#define ICON_MDI_CONSOLE_NETWORK_OUTLINE "\xf3\xb0\xb1\xa0" // U+F0C60 +#define ICON_MDI_CONSOLIDATE "\xf3\xb1\x83\x98" // U+F10D8 +#define ICON_MDI_CONTACTLESS_PAYMENT "\xf3\xb0\xb5\xaa" // U+F0D6A +#define ICON_MDI_CONTACTLESS_PAYMENT_CIRCLE "\xf3\xb0\x8c\xa1" // U+F0321 +#define ICON_MDI_CONTACTLESS_PAYMENT_CIRCLE_OUTLINE "\xf3\xb0\x90\x88" // U+F0408 +#define ICON_MDI_CONTACTS "\xf3\xb0\x9b\x8b" // U+F06CB +#define ICON_MDI_CONTACTS_OUTLINE "\xf3\xb0\x96\xb8" // U+F05B8 +#define ICON_MDI_CONTAIN "\xf3\xb0\xa8\xbe" // U+F0A3E +#define ICON_MDI_CONTAIN_END "\xf3\xb0\xa8\xbf" // U+F0A3F +#define ICON_MDI_CONTAIN_START "\xf3\xb0\xa9\x80" // U+F0A40 +#define ICON_MDI_CONTENT_COPY "\xf3\xb0\x86\x8f" // U+F018F +#define ICON_MDI_CONTENT_CUT "\xf3\xb0\x86\x90" // U+F0190 +#define ICON_MDI_CONTENT_DUPLICATE "\xf3\xb0\x86\x91" // U+F0191 +#define ICON_MDI_CONTENT_PASTE "\xf3\xb0\x86\x92" // U+F0192 +#define ICON_MDI_CONTENT_SAVE "\xf3\xb0\x86\x93" // U+F0193 +#define ICON_MDI_CONTENT_SAVE_ALERT "\xf3\xb0\xbd\x82" // U+F0F42 +#define ICON_MDI_CONTENT_SAVE_ALERT_OUTLINE "\xf3\xb0\xbd\x83" // U+F0F43 +#define ICON_MDI_CONTENT_SAVE_ALL "\xf3\xb0\x86\x94" // U+F0194 +#define ICON_MDI_CONTENT_SAVE_ALL_OUTLINE "\xf3\xb0\xbd\x84" // U+F0F44 +#define ICON_MDI_CONTENT_SAVE_CHECK "\xf3\xb1\xa3\xaa" // U+F18EA +#define ICON_MDI_CONTENT_SAVE_CHECK_OUTLINE "\xf3\xb1\xa3\xab" // U+F18EB +#define ICON_MDI_CONTENT_SAVE_COG "\xf3\xb1\x91\x9b" // U+F145B +#define ICON_MDI_CONTENT_SAVE_COG_OUTLINE "\xf3\xb1\x91\x9c" // U+F145C +#define ICON_MDI_CONTENT_SAVE_EDIT "\xf3\xb0\xb3\xbb" // U+F0CFB +#define ICON_MDI_CONTENT_SAVE_EDIT_OUTLINE "\xf3\xb0\xb3\xbc" // U+F0CFC +#define ICON_MDI_CONTENT_SAVE_MINUS "\xf3\xb1\xad\x83" // U+F1B43 +#define ICON_MDI_CONTENT_SAVE_MINUS_OUTLINE "\xf3\xb1\xad\x84" // U+F1B44 +#define ICON_MDI_CONTENT_SAVE_MOVE "\xf3\xb0\xb8\xa7" // U+F0E27 +#define ICON_MDI_CONTENT_SAVE_MOVE_OUTLINE "\xf3\xb0\xb8\xa8" // U+F0E28 +#define ICON_MDI_CONTENT_SAVE_OFF "\xf3\xb1\x99\x83" // U+F1643 +#define ICON_MDI_CONTENT_SAVE_OFF_OUTLINE "\xf3\xb1\x99\x84" // U+F1644 +#define ICON_MDI_CONTENT_SAVE_OUTLINE "\xf3\xb0\xa0\x98" // U+F0818 +#define ICON_MDI_CONTENT_SAVE_PLUS "\xf3\xb1\xad\x81" // U+F1B41 +#define ICON_MDI_CONTENT_SAVE_PLUS_OUTLINE "\xf3\xb1\xad\x82" // U+F1B42 +#define ICON_MDI_CONTENT_SAVE_SETTINGS "\xf3\xb0\x98\x9b" // U+F061B +#define ICON_MDI_CONTENT_SAVE_SETTINGS_OUTLINE "\xf3\xb0\xac\xae" // U+F0B2E +#define ICON_MDI_CONTRAST "\xf3\xb0\x86\x95" // U+F0195 +#define ICON_MDI_CONTRAST_BOX "\xf3\xb0\x86\x96" // U+F0196 +#define ICON_MDI_CONTRAST_CIRCLE "\xf3\xb0\x86\x97" // U+F0197 +#define ICON_MDI_CONTROLLER "\xf3\xb0\x8a\xb4" // U+F02B4 +#define ICON_MDI_CONTROLLER_CLASSIC "\xf3\xb0\xae\x82" // U+F0B82 +#define ICON_MDI_CONTROLLER_CLASSIC_OUTLINE "\xf3\xb0\xae\x83" // U+F0B83 +#define ICON_MDI_CONTROLLER_OFF "\xf3\xb0\x8a\xb5" // U+F02B5 +#define ICON_MDI_COOKIE "\xf3\xb0\x86\x98" // U+F0198 +#define ICON_MDI_COOKIE_ALERT "\xf3\xb1\x9b\x90" // U+F16D0 +#define ICON_MDI_COOKIE_ALERT_OUTLINE "\xf3\xb1\x9b\x91" // U+F16D1 +#define ICON_MDI_COOKIE_CHECK "\xf3\xb1\x9b\x92" // U+F16D2 +#define ICON_MDI_COOKIE_CHECK_OUTLINE "\xf3\xb1\x9b\x93" // U+F16D3 +#define ICON_MDI_COOKIE_CLOCK "\xf3\xb1\x9b\xa4" // U+F16E4 +#define ICON_MDI_COOKIE_CLOCK_OUTLINE "\xf3\xb1\x9b\xa5" // U+F16E5 +#define ICON_MDI_COOKIE_COG "\xf3\xb1\x9b\x94" // U+F16D4 +#define ICON_MDI_COOKIE_COG_OUTLINE "\xf3\xb1\x9b\x95" // U+F16D5 +#define ICON_MDI_COOKIE_EDIT "\xf3\xb1\x9b\xa6" // U+F16E6 +#define ICON_MDI_COOKIE_EDIT_OUTLINE "\xf3\xb1\x9b\xa7" // U+F16E7 +#define ICON_MDI_COOKIE_LOCK "\xf3\xb1\x9b\xa8" // U+F16E8 +#define ICON_MDI_COOKIE_LOCK_OUTLINE "\xf3\xb1\x9b\xa9" // U+F16E9 +#define ICON_MDI_COOKIE_MINUS "\xf3\xb1\x9b\x9a" // U+F16DA +#define ICON_MDI_COOKIE_MINUS_OUTLINE "\xf3\xb1\x9b\x9b" // U+F16DB +#define ICON_MDI_COOKIE_OFF "\xf3\xb1\x9b\xaa" // U+F16EA +#define ICON_MDI_COOKIE_OFF_OUTLINE "\xf3\xb1\x9b\xab" // U+F16EB +#define ICON_MDI_COOKIE_OUTLINE "\xf3\xb1\x9b\x9e" // U+F16DE +#define ICON_MDI_COOKIE_PLUS "\xf3\xb1\x9b\x96" // U+F16D6 +#define ICON_MDI_COOKIE_PLUS_OUTLINE "\xf3\xb1\x9b\x97" // U+F16D7 +#define ICON_MDI_COOKIE_REFRESH "\xf3\xb1\x9b\xac" // U+F16EC +#define ICON_MDI_COOKIE_REFRESH_OUTLINE "\xf3\xb1\x9b\xad" // U+F16ED +#define ICON_MDI_COOKIE_REMOVE "\xf3\xb1\x9b\x98" // U+F16D8 +#define ICON_MDI_COOKIE_REMOVE_OUTLINE "\xf3\xb1\x9b\x99" // U+F16D9 +#define ICON_MDI_COOKIE_SETTINGS "\xf3\xb1\x9b\x9c" // U+F16DC +#define ICON_MDI_COOKIE_SETTINGS_OUTLINE "\xf3\xb1\x9b\x9d" // U+F16DD +#define ICON_MDI_COOLANT_TEMPERATURE "\xf3\xb0\x8f\x88" // U+F03C8 +#define ICON_MDI_COPYLEFT "\xf3\xb1\xa4\xb9" // U+F1939 +#define ICON_MDI_COPYRIGHT "\xf3\xb0\x97\xa6" // U+F05E6 +#define ICON_MDI_CORDOVA "\xf3\xb0\xa5\x98" // U+F0958 +#define ICON_MDI_CORN "\xf3\xb0\x9e\xb8" // U+F07B8 +#define ICON_MDI_CORN_OFF "\xf3\xb1\x8f\xaf" // U+F13EF +#define ICON_MDI_COSINE_WAVE "\xf3\xb1\x91\xb9" // U+F1479 +#define ICON_MDI_COUNTER "\xf3\xb0\x86\x99" // U+F0199 +#define ICON_MDI_COUNTERTOP "\xf3\xb1\xa0\x9c" // U+F181C +#define ICON_MDI_COUNTERTOP_OUTLINE "\xf3\xb1\xa0\x9d" // U+F181D +#define ICON_MDI_COW "\xf3\xb0\x86\x9a" // U+F019A +#define ICON_MDI_COW_OFF "\xf3\xb1\xa3\xbc" // U+F18FC +#define ICON_MDI_CPU_32_BIT "\xf3\xb0\xbb\x9f" // U+F0EDF +#define ICON_MDI_CPU_64_BIT "\xf3\xb0\xbb\xa0" // U+F0EE0 +#define ICON_MDI_CRADLE "\xf3\xb1\xa6\x8b" // U+F198B +#define ICON_MDI_CRADLE_OUTLINE "\xf3\xb1\xa6\x91" // U+F1991 +#define ICON_MDI_CRANE "\xf3\xb0\xa1\xa2" // U+F0862 +#define ICON_MDI_CREATION "\xf3\xb0\x99\xb4" // U+F0674 +#define ICON_MDI_CREATION_OUTLINE "\xf3\xb1\xb0\xab" // U+F1C2B +#define ICON_MDI_CREATIVE_COMMONS "\xf3\xb0\xb5\xab" // U+F0D6B +#define ICON_MDI_CREDIT_CARD "\xf3\xb0\xbf\xaf" // U+F0FEF +#define ICON_MDI_CREDIT_CARD_CHECK "\xf3\xb1\x8f\x90" // U+F13D0 +#define ICON_MDI_CREDIT_CARD_CHECK_OUTLINE "\xf3\xb1\x8f\x91" // U+F13D1 +#define ICON_MDI_CREDIT_CARD_CHIP "\xf3\xb1\xa4\x8f" // U+F190F +#define ICON_MDI_CREDIT_CARD_CHIP_OUTLINE "\xf3\xb1\xa4\x90" // U+F1910 +#define ICON_MDI_CREDIT_CARD_CLOCK "\xf3\xb0\xbb\xa1" // U+F0EE1 +#define ICON_MDI_CREDIT_CARD_CLOCK_OUTLINE "\xf3\xb0\xbb\xa2" // U+F0EE2 +#define ICON_MDI_CREDIT_CARD_EDIT "\xf3\xb1\x9f\x97" // U+F17D7 +#define ICON_MDI_CREDIT_CARD_EDIT_OUTLINE "\xf3\xb1\x9f\x98" // U+F17D8 +#define ICON_MDI_CREDIT_CARD_FAST "\xf3\xb1\xa4\x91" // U+F1911 +#define ICON_MDI_CREDIT_CARD_FAST_OUTLINE "\xf3\xb1\xa4\x92" // U+F1912 +#define ICON_MDI_CREDIT_CARD_LOCK "\xf3\xb1\xa3\xa7" // U+F18E7 +#define ICON_MDI_CREDIT_CARD_LOCK_OUTLINE "\xf3\xb1\xa3\xa8" // U+F18E8 +#define ICON_MDI_CREDIT_CARD_MARKER "\xf3\xb0\x9a\xa8" // U+F06A8 +#define ICON_MDI_CREDIT_CARD_MARKER_OUTLINE "\xf3\xb0\xb6\xbe" // U+F0DBE +#define ICON_MDI_CREDIT_CARD_MINUS "\xf3\xb0\xbe\xac" // U+F0FAC +#define ICON_MDI_CREDIT_CARD_MINUS_OUTLINE "\xf3\xb0\xbe\xad" // U+F0FAD +#define ICON_MDI_CREDIT_CARD_MULTIPLE "\xf3\xb0\xbf\xb0" // U+F0FF0 +#define ICON_MDI_CREDIT_CARD_MULTIPLE_OUTLINE "\xf3\xb0\x86\x9c" // U+F019C +#define ICON_MDI_CREDIT_CARD_OFF "\xf3\xb0\xbf\xb1" // U+F0FF1 +#define ICON_MDI_CREDIT_CARD_OFF_OUTLINE "\xf3\xb0\x97\xa4" // U+F05E4 +#define ICON_MDI_CREDIT_CARD_OUTLINE "\xf3\xb0\x86\x9b" // U+F019B +#define ICON_MDI_CREDIT_CARD_PLUS "\xf3\xb0\xbf\xb2" // U+F0FF2 +#define ICON_MDI_CREDIT_CARD_PLUS_OUTLINE "\xf3\xb0\x99\xb6" // U+F0676 +#define ICON_MDI_CREDIT_CARD_REFRESH "\xf3\xb1\x99\x85" // U+F1645 +#define ICON_MDI_CREDIT_CARD_REFRESH_OUTLINE "\xf3\xb1\x99\x86" // U+F1646 +#define ICON_MDI_CREDIT_CARD_REFUND "\xf3\xb0\xbf\xb3" // U+F0FF3 +#define ICON_MDI_CREDIT_CARD_REFUND_OUTLINE "\xf3\xb0\xaa\xa8" // U+F0AA8 +#define ICON_MDI_CREDIT_CARD_REMOVE "\xf3\xb0\xbe\xae" // U+F0FAE +#define ICON_MDI_CREDIT_CARD_REMOVE_OUTLINE "\xf3\xb0\xbe\xaf" // U+F0FAF +#define ICON_MDI_CREDIT_CARD_SCAN "\xf3\xb0\xbf\xb4" // U+F0FF4 +#define ICON_MDI_CREDIT_CARD_SCAN_OUTLINE "\xf3\xb0\x86\x9d" // U+F019D +#define ICON_MDI_CREDIT_CARD_SEARCH "\xf3\xb1\x99\x87" // U+F1647 +#define ICON_MDI_CREDIT_CARD_SEARCH_OUTLINE "\xf3\xb1\x99\x88" // U+F1648 +#define ICON_MDI_CREDIT_CARD_SETTINGS "\xf3\xb0\xbf\xb5" // U+F0FF5 +#define ICON_MDI_CREDIT_CARD_SETTINGS_OUTLINE "\xf3\xb0\xa3\x97" // U+F08D7 +#define ICON_MDI_CREDIT_CARD_SYNC "\xf3\xb1\x99\x89" // U+F1649 +#define ICON_MDI_CREDIT_CARD_SYNC_OUTLINE "\xf3\xb1\x99\x8a" // U+F164A +#define ICON_MDI_CREDIT_CARD_WIRELESS "\xf3\xb0\xa0\x82" // U+F0802 +#define ICON_MDI_CREDIT_CARD_WIRELESS_OFF "\xf3\xb0\x95\xba" // U+F057A +#define ICON_MDI_CREDIT_CARD_WIRELESS_OFF_OUTLINE "\xf3\xb0\x95\xbb" // U+F057B +#define ICON_MDI_CREDIT_CARD_WIRELESS_OUTLINE "\xf3\xb0\xb5\xac" // U+F0D6C +#define ICON_MDI_CRICKET "\xf3\xb0\xb5\xad" // U+F0D6D +#define ICON_MDI_CROP "\xf3\xb0\x86\x9e" // U+F019E +#define ICON_MDI_CROP_FREE "\xf3\xb0\x86\x9f" // U+F019F +#define ICON_MDI_CROP_LANDSCAPE "\xf3\xb0\x86\xa0" // U+F01A0 +#define ICON_MDI_CROP_PORTRAIT "\xf3\xb0\x86\xa1" // U+F01A1 +#define ICON_MDI_CROP_ROTATE "\xf3\xb0\x9a\x96" // U+F0696 +#define ICON_MDI_CROP_SQUARE "\xf3\xb0\x86\xa2" // U+F01A2 +#define ICON_MDI_CROSS "\xf3\xb0\xa5\x93" // U+F0953 +#define ICON_MDI_CROSS_BOLNISI "\xf3\xb0\xb3\xad" // U+F0CED +#define ICON_MDI_CROSS_CELTIC "\xf3\xb0\xb3\xb5" // U+F0CF5 +#define ICON_MDI_CROSS_OUTLINE "\xf3\xb0\xb3\xb6" // U+F0CF6 +#define ICON_MDI_CROSSHAIRS "\xf3\xb0\x86\xa3" // U+F01A3 +#define ICON_MDI_CROSSHAIRS_GPS "\xf3\xb0\x86\xa4" // U+F01A4 +#define ICON_MDI_CROSSHAIRS_OFF "\xf3\xb0\xbd\x85" // U+F0F45 +#define ICON_MDI_CROSSHAIRS_QUESTION "\xf3\xb1\x84\xb6" // U+F1136 +#define ICON_MDI_CROWD "\xf3\xb1\xa5\xb5" // U+F1975 +#define ICON_MDI_CROWN "\xf3\xb0\x86\xa5" // U+F01A5 +#define ICON_MDI_CROWN_CIRCLE "\xf3\xb1\x9f\x9c" // U+F17DC +#define ICON_MDI_CROWN_CIRCLE_OUTLINE "\xf3\xb1\x9f\x9d" // U+F17DD +#define ICON_MDI_CROWN_OUTLINE "\xf3\xb1\x87\x90" // U+F11D0 +#define ICON_MDI_CRYENGINE "\xf3\xb0\xa5\x99" // U+F0959 +#define ICON_MDI_CRYSTAL_BALL "\xf3\xb0\xac\xaf" // U+F0B2F +#define ICON_MDI_CUBE "\xf3\xb0\x86\xa6" // U+F01A6 +#define ICON_MDI_CUBE_OFF "\xf3\xb1\x90\x9c" // U+F141C +#define ICON_MDI_CUBE_OFF_OUTLINE "\xf3\xb1\x90\x9d" // U+F141D +#define ICON_MDI_CUBE_OUTLINE "\xf3\xb0\x86\xa7" // U+F01A7 +#define ICON_MDI_CUBE_SCAN "\xf3\xb0\xae\x84" // U+F0B84 +#define ICON_MDI_CUBE_SEND "\xf3\xb0\x86\xa8" // U+F01A8 +#define ICON_MDI_CUBE_UNFOLDED "\xf3\xb0\x86\xa9" // U+F01A9 +#define ICON_MDI_CUP "\xf3\xb0\x86\xaa" // U+F01AA +#define ICON_MDI_CUP_OFF "\xf3\xb0\x97\xa5" // U+F05E5 +#define ICON_MDI_CUP_OFF_OUTLINE "\xf3\xb1\x8d\xbd" // U+F137D +#define ICON_MDI_CUP_OUTLINE "\xf3\xb1\x8c\x8f" // U+F130F +#define ICON_MDI_CUP_WATER "\xf3\xb0\x86\xab" // U+F01AB +#define ICON_MDI_CUPBOARD "\xf3\xb0\xbd\x86" // U+F0F46 +#define ICON_MDI_CUPBOARD_OUTLINE "\xf3\xb0\xbd\x87" // U+F0F47 +#define ICON_MDI_CUPCAKE "\xf3\xb0\xa5\x9a" // U+F095A +#define ICON_MDI_CURLING "\xf3\xb0\xa1\xa3" // U+F0863 +#define ICON_MDI_CURRENCY_BDT "\xf3\xb0\xa1\xa4" // U+F0864 +#define ICON_MDI_CURRENCY_BRL "\xf3\xb0\xae\x85" // U+F0B85 +#define ICON_MDI_CURRENCY_BTC "\xf3\xb0\x86\xac" // U+F01AC +#define ICON_MDI_CURRENCY_CNY "\xf3\xb0\x9e\xba" // U+F07BA +#define ICON_MDI_CURRENCY_ETH "\xf3\xb0\x9e\xbb" // U+F07BB +#define ICON_MDI_CURRENCY_EUR "\xf3\xb0\x86\xad" // U+F01AD +#define ICON_MDI_CURRENCY_EUR_OFF "\xf3\xb1\x8c\x95" // U+F1315 +#define ICON_MDI_CURRENCY_FRA "\xf3\xb1\xa8\xb9" // U+F1A39 +#define ICON_MDI_CURRENCY_GBP "\xf3\xb0\x86\xae" // U+F01AE +#define ICON_MDI_CURRENCY_ILS "\xf3\xb0\xb1\xa1" // U+F0C61 +#define ICON_MDI_CURRENCY_INR "\xf3\xb0\x86\xaf" // U+F01AF +#define ICON_MDI_CURRENCY_JPY "\xf3\xb0\x9e\xbc" // U+F07BC +#define ICON_MDI_CURRENCY_KRW "\xf3\xb0\x9e\xbd" // U+F07BD +#define ICON_MDI_CURRENCY_KZT "\xf3\xb0\xa1\xa5" // U+F0865 +#define ICON_MDI_CURRENCY_MNT "\xf3\xb1\x94\x92" // U+F1512 +#define ICON_MDI_CURRENCY_NGN "\xf3\xb0\x86\xb0" // U+F01B0 +#define ICON_MDI_CURRENCY_PHP "\xf3\xb0\xa7\xa6" // U+F09E6 +#define ICON_MDI_CURRENCY_RIAL "\xf3\xb0\xba\x9c" // U+F0E9C +#define ICON_MDI_CURRENCY_RUB "\xf3\xb0\x86\xb1" // U+F01B1 +#define ICON_MDI_CURRENCY_RUPEE "\xf3\xb1\xa5\xb6" // U+F1976 +#define ICON_MDI_CURRENCY_SIGN "\xf3\xb0\x9e\xbe" // U+F07BE +#define ICON_MDI_CURRENCY_THB "\xf3\xb1\xb0\x85" // U+F1C05 +#define ICON_MDI_CURRENCY_TRY "\xf3\xb0\x86\xb2" // U+F01B2 +#define ICON_MDI_CURRENCY_TWD "\xf3\xb0\x9e\xbf" // U+F07BF +#define ICON_MDI_CURRENCY_UAH "\xf3\xb1\xae\x9b" // U+F1B9B +#define ICON_MDI_CURRENCY_USD "\xf3\xb0\x87\x81" // U+F01C1 +#define ICON_MDI_CURRENCY_USD_OFF "\xf3\xb0\x99\xba" // U+F067A +#define ICON_MDI_CURRENT_AC "\xf3\xb1\x92\x80" // U+F1480 +#define ICON_MDI_CURRENT_DC "\xf3\xb0\xa5\x9c" // U+F095C +#define ICON_MDI_CURSOR_DEFAULT "\xf3\xb0\x87\x80" // U+F01C0 +#define ICON_MDI_CURSOR_DEFAULT_CLICK "\xf3\xb0\xb3\xbd" // U+F0CFD +#define ICON_MDI_CURSOR_DEFAULT_CLICK_OUTLINE "\xf3\xb0\xb3\xbe" // U+F0CFE +#define ICON_MDI_CURSOR_DEFAULT_GESTURE "\xf3\xb1\x84\xa7" // U+F1127 +#define ICON_MDI_CURSOR_DEFAULT_GESTURE_OUTLINE "\xf3\xb1\x84\xa8" // U+F1128 +#define ICON_MDI_CURSOR_DEFAULT_OUTLINE "\xf3\xb0\x86\xbf" // U+F01BF +#define ICON_MDI_CURSOR_MOVE "\xf3\xb0\x86\xbe" // U+F01BE +#define ICON_MDI_CURSOR_POINTER "\xf3\xb0\x86\xbd" // U+F01BD +#define ICON_MDI_CURSOR_TEXT "\xf3\xb0\x97\xa7" // U+F05E7 +#define ICON_MDI_CURTAINS "\xf3\xb1\xa1\x86" // U+F1846 +#define ICON_MDI_CURTAINS_CLOSED "\xf3\xb1\xa1\x87" // U+F1847 +#define ICON_MDI_CYLINDER "\xf3\xb1\xa5\x8e" // U+F194E +#define ICON_MDI_CYLINDER_OFF "\xf3\xb1\xa5\x8f" // U+F194F +#define ICON_MDI_DANCE_BALLROOM "\xf3\xb1\x97\xbb" // U+F15FB +#define ICON_MDI_DANCE_POLE "\xf3\xb1\x95\xb8" // U+F1578 +#define ICON_MDI_DATA_MATRIX "\xf3\xb1\x94\xbc" // U+F153C +#define ICON_MDI_DATA_MATRIX_EDIT "\xf3\xb1\x94\xbd" // U+F153D +#define ICON_MDI_DATA_MATRIX_MINUS "\xf3\xb1\x94\xbe" // U+F153E +#define ICON_MDI_DATA_MATRIX_PLUS "\xf3\xb1\x94\xbf" // U+F153F +#define ICON_MDI_DATA_MATRIX_REMOVE "\xf3\xb1\x95\x80" // U+F1540 +#define ICON_MDI_DATA_MATRIX_SCAN "\xf3\xb1\x95\x81" // U+F1541 +#define ICON_MDI_DATABASE "\xf3\xb0\x86\xbc" // U+F01BC +#define ICON_MDI_DATABASE_ALERT "\xf3\xb1\x98\xba" // U+F163A +#define ICON_MDI_DATABASE_ALERT_OUTLINE "\xf3\xb1\x98\xa4" // U+F1624 +#define ICON_MDI_DATABASE_ARROW_DOWN "\xf3\xb1\x98\xbb" // U+F163B +#define ICON_MDI_DATABASE_ARROW_DOWN_OUTLINE "\xf3\xb1\x98\xa5" // U+F1625 +#define ICON_MDI_DATABASE_ARROW_LEFT "\xf3\xb1\x98\xbc" // U+F163C +#define ICON_MDI_DATABASE_ARROW_LEFT_OUTLINE "\xf3\xb1\x98\xa6" // U+F1626 +#define ICON_MDI_DATABASE_ARROW_RIGHT "\xf3\xb1\x98\xbd" // U+F163D +#define ICON_MDI_DATABASE_ARROW_RIGHT_OUTLINE "\xf3\xb1\x98\xa7" // U+F1627 +#define ICON_MDI_DATABASE_ARROW_UP "\xf3\xb1\x98\xbe" // U+F163E +#define ICON_MDI_DATABASE_ARROW_UP_OUTLINE "\xf3\xb1\x98\xa8" // U+F1628 +#define ICON_MDI_DATABASE_CHECK "\xf3\xb0\xaa\xa9" // U+F0AA9 +#define ICON_MDI_DATABASE_CHECK_OUTLINE "\xf3\xb1\x98\xa9" // U+F1629 +#define ICON_MDI_DATABASE_CLOCK "\xf3\xb1\x98\xbf" // U+F163F +#define ICON_MDI_DATABASE_CLOCK_OUTLINE "\xf3\xb1\x98\xaa" // U+F162A +#define ICON_MDI_DATABASE_COG "\xf3\xb1\x99\x8b" // U+F164B +#define ICON_MDI_DATABASE_COG_OUTLINE "\xf3\xb1\x99\x8c" // U+F164C +#define ICON_MDI_DATABASE_EDIT "\xf3\xb0\xae\x86" // U+F0B86 +#define ICON_MDI_DATABASE_EDIT_OUTLINE "\xf3\xb1\x98\xab" // U+F162B +#define ICON_MDI_DATABASE_EXPORT "\xf3\xb0\xa5\x9e" // U+F095E +#define ICON_MDI_DATABASE_EXPORT_OUTLINE "\xf3\xb1\x98\xac" // U+F162C +#define ICON_MDI_DATABASE_EYE "\xf3\xb1\xa4\x9f" // U+F191F +#define ICON_MDI_DATABASE_EYE_OFF "\xf3\xb1\xa4\xa0" // U+F1920 +#define ICON_MDI_DATABASE_EYE_OFF_OUTLINE "\xf3\xb1\xa4\xa1" // U+F1921 +#define ICON_MDI_DATABASE_EYE_OUTLINE "\xf3\xb1\xa4\xa2" // U+F1922 +#define ICON_MDI_DATABASE_IMPORT "\xf3\xb0\xa5\x9d" // U+F095D +#define ICON_MDI_DATABASE_IMPORT_OUTLINE "\xf3\xb1\x98\xad" // U+F162D +#define ICON_MDI_DATABASE_LOCK "\xf3\xb0\xaa\xaa" // U+F0AAA +#define ICON_MDI_DATABASE_LOCK_OUTLINE "\xf3\xb1\x98\xae" // U+F162E +#define ICON_MDI_DATABASE_MARKER "\xf3\xb1\x8b\xb6" // U+F12F6 +#define ICON_MDI_DATABASE_MARKER_OUTLINE "\xf3\xb1\x98\xaf" // U+F162F +#define ICON_MDI_DATABASE_MINUS "\xf3\xb0\x86\xbb" // U+F01BB +#define ICON_MDI_DATABASE_MINUS_OUTLINE "\xf3\xb1\x98\xb0" // U+F1630 +#define ICON_MDI_DATABASE_OFF "\xf3\xb1\x99\x80" // U+F1640 +#define ICON_MDI_DATABASE_OFF_OUTLINE "\xf3\xb1\x98\xb1" // U+F1631 +#define ICON_MDI_DATABASE_OUTLINE "\xf3\xb1\x98\xb2" // U+F1632 +#define ICON_MDI_DATABASE_PLUS "\xf3\xb0\x86\xba" // U+F01BA +#define ICON_MDI_DATABASE_PLUS_OUTLINE "\xf3\xb1\x98\xb3" // U+F1633 +#define ICON_MDI_DATABASE_REFRESH "\xf3\xb0\x97\x82" // U+F05C2 +#define ICON_MDI_DATABASE_REFRESH_OUTLINE "\xf3\xb1\x98\xb4" // U+F1634 +#define ICON_MDI_DATABASE_REMOVE "\xf3\xb0\xb4\x80" // U+F0D00 +#define ICON_MDI_DATABASE_REMOVE_OUTLINE "\xf3\xb1\x98\xb5" // U+F1635 +#define ICON_MDI_DATABASE_SEARCH "\xf3\xb0\xa1\xa6" // U+F0866 +#define ICON_MDI_DATABASE_SEARCH_OUTLINE "\xf3\xb1\x98\xb6" // U+F1636 +#define ICON_MDI_DATABASE_SETTINGS "\xf3\xb0\xb4\x81" // U+F0D01 +#define ICON_MDI_DATABASE_SETTINGS_OUTLINE "\xf3\xb1\x98\xb7" // U+F1637 +#define ICON_MDI_DATABASE_SYNC "\xf3\xb0\xb3\xbf" // U+F0CFF +#define ICON_MDI_DATABASE_SYNC_OUTLINE "\xf3\xb1\x98\xb8" // U+F1638 +#define ICON_MDI_DEATH_STAR "\xf3\xb0\xa3\x98" // U+F08D8 +#define ICON_MDI_DEATH_STAR_VARIANT "\xf3\xb0\xa3\x99" // U+F08D9 +#define ICON_MDI_DEATHLY_HALLOWS "\xf3\xb0\xae\x87" // U+F0B87 +#define ICON_MDI_DEBIAN "\xf3\xb0\xa3\x9a" // U+F08DA +#define ICON_MDI_DEBUG_STEP_INTO "\xf3\xb0\x86\xb9" // U+F01B9 +#define ICON_MDI_DEBUG_STEP_OUT "\xf3\xb0\x86\xb8" // U+F01B8 +#define ICON_MDI_DEBUG_STEP_OVER "\xf3\xb0\x86\xb7" // U+F01B7 +#define ICON_MDI_DECAGRAM "\xf3\xb0\x9d\xac" // U+F076C +#define ICON_MDI_DECAGRAM_OUTLINE "\xf3\xb0\x9d\xad" // U+F076D +#define ICON_MDI_DECIMAL "\xf3\xb1\x82\xa1" // U+F10A1 +#define ICON_MDI_DECIMAL_COMMA "\xf3\xb1\x82\xa2" // U+F10A2 +#define ICON_MDI_DECIMAL_COMMA_DECREASE "\xf3\xb1\x82\xa3" // U+F10A3 +#define ICON_MDI_DECIMAL_COMMA_INCREASE "\xf3\xb1\x82\xa4" // U+F10A4 +#define ICON_MDI_DECIMAL_DECREASE "\xf3\xb0\x86\xb6" // U+F01B6 +#define ICON_MDI_DECIMAL_INCREASE "\xf3\xb0\x86\xb5" // U+F01B5 +#define ICON_MDI_DELETE "\xf3\xb0\x86\xb4" // U+F01B4 +#define ICON_MDI_DELETE_ALERT "\xf3\xb1\x82\xa5" // U+F10A5 +#define ICON_MDI_DELETE_ALERT_OUTLINE "\xf3\xb1\x82\xa6" // U+F10A6 +#define ICON_MDI_DELETE_CIRCLE "\xf3\xb0\x9a\x83" // U+F0683 +#define ICON_MDI_DELETE_CIRCLE_OUTLINE "\xf3\xb0\xae\x88" // U+F0B88 +#define ICON_MDI_DELETE_CLOCK "\xf3\xb1\x95\x96" // U+F1556 +#define ICON_MDI_DELETE_CLOCK_OUTLINE "\xf3\xb1\x95\x97" // U+F1557 +#define ICON_MDI_DELETE_EMPTY "\xf3\xb0\x9b\x8c" // U+F06CC +#define ICON_MDI_DELETE_EMPTY_OUTLINE "\xf3\xb0\xba\x9d" // U+F0E9D +#define ICON_MDI_DELETE_FOREVER "\xf3\xb0\x97\xa8" // U+F05E8 +#define ICON_MDI_DELETE_FOREVER_OUTLINE "\xf3\xb0\xae\x89" // U+F0B89 +#define ICON_MDI_DELETE_OFF "\xf3\xb1\x82\xa7" // U+F10A7 +#define ICON_MDI_DELETE_OFF_OUTLINE "\xf3\xb1\x82\xa8" // U+F10A8 +#define ICON_MDI_DELETE_OUTLINE "\xf3\xb0\xa7\xa7" // U+F09E7 +#define ICON_MDI_DELETE_RESTORE "\xf3\xb0\xa0\x99" // U+F0819 +#define ICON_MDI_DELETE_SWEEP "\xf3\xb0\x97\xa9" // U+F05E9 +#define ICON_MDI_DELETE_SWEEP_OUTLINE "\xf3\xb0\xb1\xa2" // U+F0C62 +#define ICON_MDI_DELETE_VARIANT "\xf3\xb0\x86\xb3" // U+F01B3 +#define ICON_MDI_DELTA "\xf3\xb0\x87\x82" // U+F01C2 +#define ICON_MDI_DESK "\xf3\xb1\x88\xb9" // U+F1239 +#define ICON_MDI_DESK_LAMP "\xf3\xb0\xa5\x9f" // U+F095F +#define ICON_MDI_DESK_LAMP_OFF "\xf3\xb1\xac\x9f" // U+F1B1F +#define ICON_MDI_DESK_LAMP_ON "\xf3\xb1\xac\xa0" // U+F1B20 +#define ICON_MDI_DESKPHONE "\xf3\xb0\x87\x83" // U+F01C3 +#define ICON_MDI_DESKTOP_CLASSIC "\xf3\xb0\x9f\x80" // U+F07C0 +#define ICON_MDI_DESKTOP_TOWER "\xf3\xb0\x87\x85" // U+F01C5 +#define ICON_MDI_DESKTOP_TOWER_MONITOR "\xf3\xb0\xaa\xab" // U+F0AAB +#define ICON_MDI_DETAILS "\xf3\xb0\x87\x86" // U+F01C6 +#define ICON_MDI_DEV_TO "\xf3\xb0\xb5\xae" // U+F0D6E +#define ICON_MDI_DEVELOPER_BOARD "\xf3\xb0\x9a\x97" // U+F0697 +#define ICON_MDI_DEVIANTART "\xf3\xb0\x87\x87" // U+F01C7 +#define ICON_MDI_DEVICES "\xf3\xb0\xbe\xb0" // U+F0FB0 +#define ICON_MDI_DHARMACHAKRA "\xf3\xb0\xa5\x8b" // U+F094B +#define ICON_MDI_DIABETES "\xf3\xb1\x84\xa6" // U+F1126 +#define ICON_MDI_DIALPAD "\xf3\xb0\x98\x9c" // U+F061C +#define ICON_MDI_DIAMETER "\xf3\xb0\xb1\xa3" // U+F0C63 +#define ICON_MDI_DIAMETER_OUTLINE "\xf3\xb0\xb1\xa4" // U+F0C64 +#define ICON_MDI_DIAMETER_VARIANT "\xf3\xb0\xb1\xa5" // U+F0C65 +#define ICON_MDI_DIAMOND "\xf3\xb0\xae\x8a" // U+F0B8A +#define ICON_MDI_DIAMOND_OUTLINE "\xf3\xb0\xae\x8b" // U+F0B8B +#define ICON_MDI_DIAMOND_STONE "\xf3\xb0\x87\x88" // U+F01C8 +#define ICON_MDI_DICE_1 "\xf3\xb0\x87\x8a" // U+F01CA +#define ICON_MDI_DICE_1_OUTLINE "\xf3\xb1\x85\x8a" // U+F114A +#define ICON_MDI_DICE_2 "\xf3\xb0\x87\x8b" // U+F01CB +#define ICON_MDI_DICE_2_OUTLINE "\xf3\xb1\x85\x8b" // U+F114B +#define ICON_MDI_DICE_3 "\xf3\xb0\x87\x8c" // U+F01CC +#define ICON_MDI_DICE_3_OUTLINE "\xf3\xb1\x85\x8c" // U+F114C +#define ICON_MDI_DICE_4 "\xf3\xb0\x87\x8d" // U+F01CD +#define ICON_MDI_DICE_4_OUTLINE "\xf3\xb1\x85\x8d" // U+F114D +#define ICON_MDI_DICE_5 "\xf3\xb0\x87\x8e" // U+F01CE +#define ICON_MDI_DICE_5_OUTLINE "\xf3\xb1\x85\x8e" // U+F114E +#define ICON_MDI_DICE_6 "\xf3\xb0\x87\x8f" // U+F01CF +#define ICON_MDI_DICE_6_OUTLINE "\xf3\xb1\x85\x8f" // U+F114F +#define ICON_MDI_DICE_D10 "\xf3\xb1\x85\x93" // U+F1153 +#define ICON_MDI_DICE_D10_OUTLINE "\xf3\xb0\x9d\xaf" // U+F076F +#define ICON_MDI_DICE_D12 "\xf3\xb1\x85\x94" // U+F1154 +#define ICON_MDI_DICE_D12_OUTLINE "\xf3\xb0\xa1\xa7" // U+F0867 +#define ICON_MDI_DICE_D20 "\xf3\xb1\x85\x95" // U+F1155 +#define ICON_MDI_DICE_D20_OUTLINE "\xf3\xb0\x97\xaa" // U+F05EA +#define ICON_MDI_DICE_D4 "\xf3\xb1\x85\x90" // U+F1150 +#define ICON_MDI_DICE_D4_OUTLINE "\xf3\xb0\x97\xab" // U+F05EB +#define ICON_MDI_DICE_D6 "\xf3\xb1\x85\x91" // U+F1151 +#define ICON_MDI_DICE_D6_OUTLINE "\xf3\xb0\x97\xad" // U+F05ED +#define ICON_MDI_DICE_D8 "\xf3\xb1\x85\x92" // U+F1152 +#define ICON_MDI_DICE_D8_OUTLINE "\xf3\xb0\x97\xac" // U+F05EC +#define ICON_MDI_DICE_MULTIPLE "\xf3\xb0\x9d\xae" // U+F076E +#define ICON_MDI_DICE_MULTIPLE_OUTLINE "\xf3\xb1\x85\x96" // U+F1156 +#define ICON_MDI_DIGITAL_OCEAN "\xf3\xb1\x88\xb7" // U+F1237 +#define ICON_MDI_DIP_SWITCH "\xf3\xb0\x9f\x81" // U+F07C1 +#define ICON_MDI_DIRECTIONS "\xf3\xb0\x87\x90" // U+F01D0 +#define ICON_MDI_DIRECTIONS_FORK "\xf3\xb0\x99\x81" // U+F0641 +#define ICON_MDI_DISC "\xf3\xb0\x97\xae" // U+F05EE +#define ICON_MDI_DISC_ALERT "\xf3\xb0\x87\x91" // U+F01D1 +#define ICON_MDI_DISC_PLAYER "\xf3\xb0\xa5\xa0" // U+F0960 +#define ICON_MDI_DISHWASHER "\xf3\xb0\xaa\xac" // U+F0AAC +#define ICON_MDI_DISHWASHER_ALERT "\xf3\xb1\x86\xb8" // U+F11B8 +#define ICON_MDI_DISHWASHER_OFF "\xf3\xb1\x86\xb9" // U+F11B9 +#define ICON_MDI_DISQUS "\xf3\xb0\x87\x92" // U+F01D2 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_CENTER "\xf3\xb1\x87\x89" // U+F11C9 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_LEFT "\xf3\xb1\x87\x88" // U+F11C8 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_RIGHT "\xf3\xb1\x87\x8a" // U+F11CA +#define ICON_MDI_DISTRIBUTE_VERTICAL_BOTTOM "\xf3\xb1\x87\x8b" // U+F11CB +#define ICON_MDI_DISTRIBUTE_VERTICAL_CENTER "\xf3\xb1\x87\x8c" // U+F11CC +#define ICON_MDI_DISTRIBUTE_VERTICAL_TOP "\xf3\xb1\x87\x8d" // U+F11CD +#define ICON_MDI_DIVERSIFY "\xf3\xb1\xa1\xb7" // U+F1877 +#define ICON_MDI_DIVING "\xf3\xb1\xa5\xb7" // U+F1977 +#define ICON_MDI_DIVING_FLIPPERS "\xf3\xb0\xb6\xbf" // U+F0DBF +#define ICON_MDI_DIVING_HELMET "\xf3\xb0\xb7\x80" // U+F0DC0 +#define ICON_MDI_DIVING_SCUBA "\xf3\xb1\xad\xb7" // U+F1B77 +#define ICON_MDI_DIVING_SCUBA_FLAG "\xf3\xb0\xb7\x82" // U+F0DC2 +#define ICON_MDI_DIVING_SCUBA_MASK "\xf3\xb0\xb7\x81" // U+F0DC1 +#define ICON_MDI_DIVING_SCUBA_TANK "\xf3\xb0\xb7\x83" // U+F0DC3 +#define ICON_MDI_DIVING_SCUBA_TANK_MULTIPLE "\xf3\xb0\xb7\x84" // U+F0DC4 +#define ICON_MDI_DIVING_SNORKEL "\xf3\xb0\xb7\x85" // U+F0DC5 +#define ICON_MDI_DIVISION "\xf3\xb0\x87\x94" // U+F01D4 +#define ICON_MDI_DIVISION_BOX "\xf3\xb0\x87\x95" // U+F01D5 +#define ICON_MDI_DLNA "\xf3\xb0\xa9\x81" // U+F0A41 +#define ICON_MDI_DNA "\xf3\xb0\x9a\x84" // U+F0684 +#define ICON_MDI_DNS "\xf3\xb0\x87\x96" // U+F01D6 +#define ICON_MDI_DNS_OUTLINE "\xf3\xb0\xae\x8c" // U+F0B8C +#define ICON_MDI_DOCK_BOTTOM "\xf3\xb1\x82\xa9" // U+F10A9 +#define ICON_MDI_DOCK_LEFT "\xf3\xb1\x82\xaa" // U+F10AA +#define ICON_MDI_DOCK_RIGHT "\xf3\xb1\x82\xab" // U+F10AB +#define ICON_MDI_DOCK_TOP "\xf3\xb1\x94\x93" // U+F1513 +#define ICON_MDI_DOCK_WINDOW "\xf3\xb1\x82\xac" // U+F10AC +#define ICON_MDI_DOCKER "\xf3\xb0\xa1\xa8" // U+F0868 +#define ICON_MDI_DOCTOR "\xf3\xb0\xa9\x82" // U+F0A42 +#define ICON_MDI_DOG "\xf3\xb0\xa9\x83" // U+F0A43 +#define ICON_MDI_DOG_SERVICE "\xf3\xb0\xaa\xad" // U+F0AAD +#define ICON_MDI_DOG_SIDE "\xf3\xb0\xa9\x84" // U+F0A44 +#define ICON_MDI_DOG_SIDE_OFF "\xf3\xb1\x9b\xae" // U+F16EE +#define ICON_MDI_DOLBY "\xf3\xb0\x9a\xb3" // U+F06B3 +#define ICON_MDI_DOLLY "\xf3\xb0\xba\x9e" // U+F0E9E +#define ICON_MDI_DOLPHIN "\xf3\xb1\xa2\xb4" // U+F18B4 +#define ICON_MDI_DOMAIN "\xf3\xb0\x87\x97" // U+F01D7 +#define ICON_MDI_DOMAIN_OFF "\xf3\xb0\xb5\xaf" // U+F0D6F +#define ICON_MDI_DOMAIN_PLUS "\xf3\xb1\x82\xad" // U+F10AD +#define ICON_MDI_DOMAIN_REMOVE "\xf3\xb1\x82\xae" // U+F10AE +#define ICON_MDI_DOMAIN_SWITCH "\xf3\xb1\xb0\xac" // U+F1C2C +#define ICON_MDI_DOME_LIGHT "\xf3\xb1\x90\x9e" // U+F141E +#define ICON_MDI_DOMINO_MASK "\xf3\xb1\x80\xa3" // U+F1023 +#define ICON_MDI_DONKEY "\xf3\xb0\x9f\x82" // U+F07C2 +#define ICON_MDI_DOOR "\xf3\xb0\xa0\x9a" // U+F081A +#define ICON_MDI_DOOR_CLOSED "\xf3\xb0\xa0\x9b" // U+F081B +#define ICON_MDI_DOOR_CLOSED_CANCEL "\xf3\xb1\xb2\x93" // U+F1C93 +#define ICON_MDI_DOOR_CLOSED_LOCK "\xf3\xb1\x82\xaf" // U+F10AF +#define ICON_MDI_DOOR_OPEN "\xf3\xb0\xa0\x9c" // U+F081C +#define ICON_MDI_DOOR_SLIDING "\xf3\xb1\xa0\x9e" // U+F181E +#define ICON_MDI_DOOR_SLIDING_LOCK "\xf3\xb1\xa0\x9f" // U+F181F +#define ICON_MDI_DOOR_SLIDING_OPEN "\xf3\xb1\xa0\xa0" // U+F1820 +#define ICON_MDI_DOORBELL "\xf3\xb1\x8b\xa6" // U+F12E6 +#define ICON_MDI_DOORBELL_VIDEO "\xf3\xb0\xa1\xa9" // U+F0869 +#define ICON_MDI_DOT_NET "\xf3\xb0\xaa\xae" // U+F0AAE +#define ICON_MDI_DOTS_CIRCLE "\xf3\xb1\xa5\xb8" // U+F1978 +#define ICON_MDI_DOTS_GRID "\xf3\xb1\x97\xbc" // U+F15FC +#define ICON_MDI_DOTS_HEXAGON "\xf3\xb1\x97\xbf" // U+F15FF +#define ICON_MDI_DOTS_HORIZONTAL "\xf3\xb0\x87\x98" // U+F01D8 +#define ICON_MDI_DOTS_HORIZONTAL_CIRCLE "\xf3\xb0\x9f\x83" // U+F07C3 +#define ICON_MDI_DOTS_HORIZONTAL_CIRCLE_OUTLINE "\xf3\xb0\xae\x8d" // U+F0B8D +#define ICON_MDI_DOTS_SQUARE "\xf3\xb1\x97\xbd" // U+F15FD +#define ICON_MDI_DOTS_TRIANGLE "\xf3\xb1\x97\xbe" // U+F15FE +#define ICON_MDI_DOTS_VERTICAL "\xf3\xb0\x87\x99" // U+F01D9 +#define ICON_MDI_DOTS_VERTICAL_CIRCLE "\xf3\xb0\x9f\x84" // U+F07C4 +#define ICON_MDI_DOTS_VERTICAL_CIRCLE_OUTLINE "\xf3\xb0\xae\x8e" // U+F0B8E +#define ICON_MDI_DOWNLOAD "\xf3\xb0\x87\x9a" // U+F01DA +#define ICON_MDI_DOWNLOAD_BOX "\xf3\xb1\x91\xa2" // U+F1462 +#define ICON_MDI_DOWNLOAD_BOX_OUTLINE "\xf3\xb1\x91\xa3" // U+F1463 +#define ICON_MDI_DOWNLOAD_CIRCLE "\xf3\xb1\x91\xa4" // U+F1464 +#define ICON_MDI_DOWNLOAD_CIRCLE_OUTLINE "\xf3\xb1\x91\xa5" // U+F1465 +#define ICON_MDI_DOWNLOAD_LOCK "\xf3\xb1\x8c\xa0" // U+F1320 +#define ICON_MDI_DOWNLOAD_LOCK_OUTLINE "\xf3\xb1\x8c\xa1" // U+F1321 +#define ICON_MDI_DOWNLOAD_MULTIPLE "\xf3\xb0\xa7\xa9" // U+F09E9 +#define ICON_MDI_DOWNLOAD_NETWORK "\xf3\xb0\x9b\xb4" // U+F06F4 +#define ICON_MDI_DOWNLOAD_NETWORK_OUTLINE "\xf3\xb0\xb1\xa6" // U+F0C66 +#define ICON_MDI_DOWNLOAD_OFF "\xf3\xb1\x82\xb0" // U+F10B0 +#define ICON_MDI_DOWNLOAD_OFF_OUTLINE "\xf3\xb1\x82\xb1" // U+F10B1 +#define ICON_MDI_DOWNLOAD_OUTLINE "\xf3\xb0\xae\x8f" // U+F0B8F +#define ICON_MDI_DRAG "\xf3\xb0\x87\x9b" // U+F01DB +#define ICON_MDI_DRAG_HORIZONTAL "\xf3\xb0\x87\x9c" // U+F01DC +#define ICON_MDI_DRAG_HORIZONTAL_VARIANT "\xf3\xb1\x8b\xb0" // U+F12F0 +#define ICON_MDI_DRAG_VARIANT "\xf3\xb0\xae\x90" // U+F0B90 +#define ICON_MDI_DRAG_VERTICAL "\xf3\xb0\x87\x9d" // U+F01DD +#define ICON_MDI_DRAG_VERTICAL_VARIANT "\xf3\xb1\x8b\xb1" // U+F12F1 +#define ICON_MDI_DRAMA_MASKS "\xf3\xb0\xb4\x82" // U+F0D02 +#define ICON_MDI_DRAW "\xf3\xb0\xbd\x89" // U+F0F49 +#define ICON_MDI_DRAW_PEN "\xf3\xb1\xa6\xb9" // U+F19B9 +#define ICON_MDI_DRAWING "\xf3\xb0\x87\x9e" // U+F01DE +#define ICON_MDI_DRAWING_BOX "\xf3\xb0\x87\x9f" // U+F01DF +#define ICON_MDI_DRESSER "\xf3\xb0\xbd\x8a" // U+F0F4A +#define ICON_MDI_DRESSER_OUTLINE "\xf3\xb0\xbd\x8b" // U+F0F4B +#define ICON_MDI_DRONE "\xf3\xb0\x87\xa2" // U+F01E2 +#define ICON_MDI_DROPBOX "\xf3\xb0\x87\xa3" // U+F01E3 +#define ICON_MDI_DRUPAL "\xf3\xb0\x87\xa4" // U+F01E4 +#define ICON_MDI_DUCK "\xf3\xb0\x87\xa5" // U+F01E5 +#define ICON_MDI_DUMBBELL "\xf3\xb0\x87\xa6" // U+F01E6 +#define ICON_MDI_DUMP_TRUCK "\xf3\xb0\xb1\xa7" // U+F0C67 +#define ICON_MDI_EAR_HEARING "\xf3\xb0\x9f\x85" // U+F07C5 +#define ICON_MDI_EAR_HEARING_LOOP "\xf3\xb1\xab\xae" // U+F1AEE +#define ICON_MDI_EAR_HEARING_OFF "\xf3\xb0\xa9\x85" // U+F0A45 +#define ICON_MDI_EARBUDS "\xf3\xb1\xa1\x8f" // U+F184F +#define ICON_MDI_EARBUDS_OFF "\xf3\xb1\xa1\x90" // U+F1850 +#define ICON_MDI_EARBUDS_OFF_OUTLINE "\xf3\xb1\xa1\x91" // U+F1851 +#define ICON_MDI_EARBUDS_OUTLINE "\xf3\xb1\xa1\x92" // U+F1852 +#define ICON_MDI_EARTH "\xf3\xb0\x87\xa7" // U+F01E7 +#define ICON_MDI_EARTH_ARROW_DOWN "\xf3\xb1\xb2\x87" // U+F1C87 +#define ICON_MDI_EARTH_ARROW_LEFT "\xf3\xb1\xb2\x88" // U+F1C88 +#define ICON_MDI_EARTH_ARROW_RIGHT "\xf3\xb1\x8c\x91" // U+F1311 +#define ICON_MDI_EARTH_ARROW_UP "\xf3\xb1\xb2\x89" // U+F1C89 +#define ICON_MDI_EARTH_BOX "\xf3\xb0\x9b\x8d" // U+F06CD +#define ICON_MDI_EARTH_BOX_MINUS "\xf3\xb1\x90\x87" // U+F1407 +#define ICON_MDI_EARTH_BOX_OFF "\xf3\xb0\x9b\x8e" // U+F06CE +#define ICON_MDI_EARTH_BOX_PLUS "\xf3\xb1\x90\x86" // U+F1406 +#define ICON_MDI_EARTH_BOX_REMOVE "\xf3\xb1\x90\x88" // U+F1408 +#define ICON_MDI_EARTH_MINUS "\xf3\xb1\x90\x84" // U+F1404 +#define ICON_MDI_EARTH_OFF "\xf3\xb0\x87\xa8" // U+F01E8 +#define ICON_MDI_EARTH_PLUS "\xf3\xb1\x90\x83" // U+F1403 +#define ICON_MDI_EARTH_REMOVE "\xf3\xb1\x90\x85" // U+F1405 +#define ICON_MDI_EGG "\xf3\xb0\xaa\xaf" // U+F0AAF +#define ICON_MDI_EGG_EASTER "\xf3\xb0\xaa\xb0" // U+F0AB0 +#define ICON_MDI_EGG_FRIED "\xf3\xb1\xa1\x8a" // U+F184A +#define ICON_MDI_EGG_OFF "\xf3\xb1\x8f\xb0" // U+F13F0 +#define ICON_MDI_EGG_OFF_OUTLINE "\xf3\xb1\x8f\xb1" // U+F13F1 +#define ICON_MDI_EGG_OUTLINE "\xf3\xb1\x8f\xb2" // U+F13F2 +#define ICON_MDI_EIFFEL_TOWER "\xf3\xb1\x95\xab" // U+F156B +#define ICON_MDI_EIGHT_TRACK "\xf3\xb0\xa7\xaa" // U+F09EA +#define ICON_MDI_EJECT "\xf3\xb0\x87\xaa" // U+F01EA +#define ICON_MDI_EJECT_CIRCLE "\xf3\xb1\xac\xa3" // U+F1B23 +#define ICON_MDI_EJECT_CIRCLE_OUTLINE "\xf3\xb1\xac\xa4" // U+F1B24 +#define ICON_MDI_EJECT_OUTLINE "\xf3\xb0\xae\x91" // U+F0B91 +#define ICON_MDI_ELECTRIC_SWITCH "\xf3\xb0\xba\x9f" // U+F0E9F +#define ICON_MDI_ELECTRIC_SWITCH_CLOSED "\xf3\xb1\x83\x99" // U+F10D9 +#define ICON_MDI_ELECTRON_FRAMEWORK "\xf3\xb1\x80\xa4" // U+F1024 +#define ICON_MDI_ELEPHANT "\xf3\xb0\x9f\x86" // U+F07C6 +#define ICON_MDI_ELEVATION_DECLINE "\xf3\xb0\x87\xab" // U+F01EB +#define ICON_MDI_ELEVATION_RISE "\xf3\xb0\x87\xac" // U+F01EC +#define ICON_MDI_ELEVATOR "\xf3\xb0\x87\xad" // U+F01ED +#define ICON_MDI_ELEVATOR_DOWN "\xf3\xb1\x8b\x82" // U+F12C2 +#define ICON_MDI_ELEVATOR_PASSENGER "\xf3\xb1\x8e\x81" // U+F1381 +#define ICON_MDI_ELEVATOR_PASSENGER_OFF "\xf3\xb1\xa5\xb9" // U+F1979 +#define ICON_MDI_ELEVATOR_PASSENGER_OFF_OUTLINE "\xf3\xb1\xa5\xba" // U+F197A +#define ICON_MDI_ELEVATOR_PASSENGER_OUTLINE "\xf3\xb1\xa5\xbb" // U+F197B +#define ICON_MDI_ELEVATOR_UP "\xf3\xb1\x8b\x81" // U+F12C1 +#define ICON_MDI_ELLIPSE "\xf3\xb0\xba\xa0" // U+F0EA0 +#define ICON_MDI_ELLIPSE_OUTLINE "\xf3\xb0\xba\xa1" // U+F0EA1 +#define ICON_MDI_EMAIL "\xf3\xb0\x87\xae" // U+F01EE +#define ICON_MDI_EMAIL_ALERT "\xf3\xb0\x9b\x8f" // U+F06CF +#define ICON_MDI_EMAIL_ALERT_OUTLINE "\xf3\xb0\xb5\x82" // U+F0D42 +#define ICON_MDI_EMAIL_ARROW_LEFT "\xf3\xb1\x83\x9a" // U+F10DA +#define ICON_MDI_EMAIL_ARROW_LEFT_OUTLINE "\xf3\xb1\x83\x9b" // U+F10DB +#define ICON_MDI_EMAIL_ARROW_RIGHT "\xf3\xb1\x83\x9c" // U+F10DC +#define ICON_MDI_EMAIL_ARROW_RIGHT_OUTLINE "\xf3\xb1\x83\x9d" // U+F10DD +#define ICON_MDI_EMAIL_BOX "\xf3\xb0\xb4\x83" // U+F0D03 +#define ICON_MDI_EMAIL_CHECK "\xf3\xb0\xaa\xb1" // U+F0AB1 +#define ICON_MDI_EMAIL_CHECK_OUTLINE "\xf3\xb0\xaa\xb2" // U+F0AB2 +#define ICON_MDI_EMAIL_EDIT "\xf3\xb0\xbb\xa3" // U+F0EE3 +#define ICON_MDI_EMAIL_EDIT_OUTLINE "\xf3\xb0\xbb\xa4" // U+F0EE4 +#define ICON_MDI_EMAIL_FAST "\xf3\xb1\xa1\xaf" // U+F186F +#define ICON_MDI_EMAIL_FAST_OUTLINE "\xf3\xb1\xa1\xb0" // U+F1870 +#define ICON_MDI_EMAIL_HEART_OUTLINE "\xf3\xb1\xb1\x9b" // U+F1C5B +#define ICON_MDI_EMAIL_LOCK "\xf3\xb0\x87\xb1" // U+F01F1 +#define ICON_MDI_EMAIL_LOCK_OUTLINE "\xf3\xb1\xad\xa1" // U+F1B61 +#define ICON_MDI_EMAIL_MARK_AS_UNREAD "\xf3\xb0\xae\x92" // U+F0B92 +#define ICON_MDI_EMAIL_MINUS "\xf3\xb0\xbb\xa5" // U+F0EE5 +#define ICON_MDI_EMAIL_MINUS_OUTLINE "\xf3\xb0\xbb\xa6" // U+F0EE6 +#define ICON_MDI_EMAIL_MULTIPLE "\xf3\xb0\xbb\xa7" // U+F0EE7 +#define ICON_MDI_EMAIL_MULTIPLE_OUTLINE "\xf3\xb0\xbb\xa8" // U+F0EE8 +#define ICON_MDI_EMAIL_NEWSLETTER "\xf3\xb0\xbe\xb1" // U+F0FB1 +#define ICON_MDI_EMAIL_OFF "\xf3\xb1\x8f\xa3" // U+F13E3 +#define ICON_MDI_EMAIL_OFF_OUTLINE "\xf3\xb1\x8f\xa4" // U+F13E4 +#define ICON_MDI_EMAIL_OPEN "\xf3\xb0\x87\xaf" // U+F01EF +#define ICON_MDI_EMAIL_OPEN_HEART_OUTLINE "\xf3\xb1\xb1\x9c" // U+F1C5C +#define ICON_MDI_EMAIL_OPEN_MULTIPLE "\xf3\xb0\xbb\xa9" // U+F0EE9 +#define ICON_MDI_EMAIL_OPEN_MULTIPLE_OUTLINE "\xf3\xb0\xbb\xaa" // U+F0EEA +#define ICON_MDI_EMAIL_OPEN_OUTLINE "\xf3\xb0\x97\xaf" // U+F05EF +#define ICON_MDI_EMAIL_OUTLINE "\xf3\xb0\x87\xb0" // U+F01F0 +#define ICON_MDI_EMAIL_PLUS "\xf3\xb0\xa7\xab" // U+F09EB +#define ICON_MDI_EMAIL_PLUS_OUTLINE "\xf3\xb0\xa7\xac" // U+F09EC +#define ICON_MDI_EMAIL_REMOVE "\xf3\xb1\x99\xa1" // U+F1661 +#define ICON_MDI_EMAIL_REMOVE_OUTLINE "\xf3\xb1\x99\xa2" // U+F1662 +#define ICON_MDI_EMAIL_SEAL "\xf3\xb1\xa5\x9b" // U+F195B +#define ICON_MDI_EMAIL_SEAL_OUTLINE "\xf3\xb1\xa5\x9c" // U+F195C +#define ICON_MDI_EMAIL_SEARCH "\xf3\xb0\xa5\xa1" // U+F0961 +#define ICON_MDI_EMAIL_SEARCH_OUTLINE "\xf3\xb0\xa5\xa2" // U+F0962 +#define ICON_MDI_EMAIL_SYNC "\xf3\xb1\x8b\x87" // U+F12C7 +#define ICON_MDI_EMAIL_SYNC_OUTLINE "\xf3\xb1\x8b\x88" // U+F12C8 +#define ICON_MDI_EMAIL_VARIANT "\xf3\xb0\x97\xb0" // U+F05F0 +#define ICON_MDI_EMBER "\xf3\xb0\xac\xb0" // U+F0B30 +#define ICON_MDI_EMBY "\xf3\xb0\x9a\xb4" // U+F06B4 +#define ICON_MDI_EMOTICON "\xf3\xb0\xb1\xa8" // U+F0C68 +#define ICON_MDI_EMOTICON_ANGRY "\xf3\xb0\xb1\xa9" // U+F0C69 +#define ICON_MDI_EMOTICON_ANGRY_OUTLINE "\xf3\xb0\xb1\xaa" // U+F0C6A +#define ICON_MDI_EMOTICON_CONFUSED "\xf3\xb1\x83\x9e" // U+F10DE +#define ICON_MDI_EMOTICON_CONFUSED_OUTLINE "\xf3\xb1\x83\x9f" // U+F10DF +#define ICON_MDI_EMOTICON_COOL "\xf3\xb0\xb1\xab" // U+F0C6B +#define ICON_MDI_EMOTICON_COOL_OUTLINE "\xf3\xb0\x87\xb3" // U+F01F3 +#define ICON_MDI_EMOTICON_CRY "\xf3\xb0\xb1\xac" // U+F0C6C +#define ICON_MDI_EMOTICON_CRY_OUTLINE "\xf3\xb0\xb1\xad" // U+F0C6D +#define ICON_MDI_EMOTICON_DEAD "\xf3\xb0\xb1\xae" // U+F0C6E +#define ICON_MDI_EMOTICON_DEAD_OUTLINE "\xf3\xb0\x9a\x9b" // U+F069B +#define ICON_MDI_EMOTICON_DEVIL "\xf3\xb0\xb1\xaf" // U+F0C6F +#define ICON_MDI_EMOTICON_DEVIL_OUTLINE "\xf3\xb0\x87\xb4" // U+F01F4 +#define ICON_MDI_EMOTICON_EXCITED "\xf3\xb0\xb1\xb0" // U+F0C70 +#define ICON_MDI_EMOTICON_EXCITED_OUTLINE "\xf3\xb0\x9a\x9c" // U+F069C +#define ICON_MDI_EMOTICON_FROWN "\xf3\xb0\xbd\x8c" // U+F0F4C +#define ICON_MDI_EMOTICON_FROWN_OUTLINE "\xf3\xb0\xbd\x8d" // U+F0F4D +#define ICON_MDI_EMOTICON_HAPPY "\xf3\xb0\xb1\xb1" // U+F0C71 +#define ICON_MDI_EMOTICON_HAPPY_OUTLINE "\xf3\xb0\x87\xb5" // U+F01F5 +#define ICON_MDI_EMOTICON_KISS "\xf3\xb0\xb1\xb2" // U+F0C72 +#define ICON_MDI_EMOTICON_KISS_OUTLINE "\xf3\xb0\xb1\xb3" // U+F0C73 +#define ICON_MDI_EMOTICON_LOL "\xf3\xb1\x88\x94" // U+F1214 +#define ICON_MDI_EMOTICON_LOL_OUTLINE "\xf3\xb1\x88\x95" // U+F1215 +#define ICON_MDI_EMOTICON_MINUS "\xf3\xb1\xb2\xb2" // U+F1CB2 +#define ICON_MDI_EMOTICON_MINUS_OUTLINE "\xf3\xb1\xb2\xb3" // U+F1CB3 +#define ICON_MDI_EMOTICON_NEUTRAL "\xf3\xb0\xb1\xb4" // U+F0C74 +#define ICON_MDI_EMOTICON_NEUTRAL_OUTLINE "\xf3\xb0\x87\xb6" // U+F01F6 +#define ICON_MDI_EMOTICON_OUTLINE "\xf3\xb0\x87\xb2" // U+F01F2 +#define ICON_MDI_EMOTICON_PLUS "\xf3\xb1\xb2\xb4" // U+F1CB4 +#define ICON_MDI_EMOTICON_PLUS_OUTLINE "\xf3\xb1\xb2\xb5" // U+F1CB5 +#define ICON_MDI_EMOTICON_POOP "\xf3\xb0\x87\xb7" // U+F01F7 +#define ICON_MDI_EMOTICON_POOP_OUTLINE "\xf3\xb0\xb1\xb5" // U+F0C75 +#define ICON_MDI_EMOTICON_REMOVE "\xf3\xb1\xb2\xb6" // U+F1CB6 +#define ICON_MDI_EMOTICON_REMOVE_OUTLINE "\xf3\xb1\xb2\xb7" // U+F1CB7 +#define ICON_MDI_EMOTICON_SAD "\xf3\xb0\xb1\xb6" // U+F0C76 +#define ICON_MDI_EMOTICON_SAD_OUTLINE "\xf3\xb0\x87\xb8" // U+F01F8 +#define ICON_MDI_EMOTICON_SICK "\xf3\xb1\x95\xbc" // U+F157C +#define ICON_MDI_EMOTICON_SICK_OUTLINE "\xf3\xb1\x95\xbd" // U+F157D +#define ICON_MDI_EMOTICON_TONGUE "\xf3\xb0\x87\xb9" // U+F01F9 +#define ICON_MDI_EMOTICON_TONGUE_OUTLINE "\xf3\xb0\xb1\xb7" // U+F0C77 +#define ICON_MDI_EMOTICON_WINK "\xf3\xb0\xb1\xb8" // U+F0C78 +#define ICON_MDI_EMOTICON_WINK_OUTLINE "\xf3\xb0\xb1\xb9" // U+F0C79 +#define ICON_MDI_ENGINE "\xf3\xb0\x87\xba" // U+F01FA +#define ICON_MDI_ENGINE_OFF "\xf3\xb0\xa9\x86" // U+F0A46 +#define ICON_MDI_ENGINE_OFF_OUTLINE "\xf3\xb0\xa9\x87" // U+F0A47 +#define ICON_MDI_ENGINE_OUTLINE "\xf3\xb0\x87\xbb" // U+F01FB +#define ICON_MDI_EPSILON "\xf3\xb1\x83\xa0" // U+F10E0 +#define ICON_MDI_EQUAL "\xf3\xb0\x87\xbc" // U+F01FC +#define ICON_MDI_EQUAL_BOX "\xf3\xb0\x87\xbd" // U+F01FD +#define ICON_MDI_EQUALIZER "\xf3\xb0\xba\xa2" // U+F0EA2 +#define ICON_MDI_EQUALIZER_OUTLINE "\xf3\xb0\xba\xa3" // U+F0EA3 +#define ICON_MDI_ERASER "\xf3\xb0\x87\xbe" // U+F01FE +#define ICON_MDI_ERASER_VARIANT "\xf3\xb0\x99\x82" // U+F0642 +#define ICON_MDI_ESCALATOR "\xf3\xb0\x87\xbf" // U+F01FF +#define ICON_MDI_ESCALATOR_BOX "\xf3\xb1\x8e\x99" // U+F1399 +#define ICON_MDI_ESCALATOR_DOWN "\xf3\xb1\x8b\x80" // U+F12C0 +#define ICON_MDI_ESCALATOR_UP "\xf3\xb1\x8a\xbf" // U+F12BF +#define ICON_MDI_ESLINT "\xf3\xb0\xb1\xba" // U+F0C7A +#define ICON_MDI_ET "\xf3\xb0\xaa\xb3" // U+F0AB3 +#define ICON_MDI_ETHEREUM "\xf3\xb0\xa1\xaa" // U+F086A +#define ICON_MDI_ETHERNET "\xf3\xb0\x88\x80" // U+F0200 +#define ICON_MDI_ETHERNET_CABLE "\xf3\xb0\x88\x81" // U+F0201 +#define ICON_MDI_ETHERNET_CABLE_OFF "\xf3\xb0\x88\x82" // U+F0202 +#define ICON_MDI_EV_PLUG_CCS1 "\xf3\xb1\x94\x99" // U+F1519 +#define ICON_MDI_EV_PLUG_CCS2 "\xf3\xb1\x94\x9a" // U+F151A +#define ICON_MDI_EV_PLUG_CHADEMO "\xf3\xb1\x94\x9b" // U+F151B +#define ICON_MDI_EV_PLUG_TESLA "\xf3\xb1\x94\x9c" // U+F151C +#define ICON_MDI_EV_PLUG_TYPE1 "\xf3\xb1\x94\x9d" // U+F151D +#define ICON_MDI_EV_PLUG_TYPE2 "\xf3\xb1\x94\x9e" // U+F151E +#define ICON_MDI_EV_STATION "\xf3\xb0\x97\xb1" // U+F05F1 +#define ICON_MDI_EVERNOTE "\xf3\xb0\x88\x84" // U+F0204 +#define ICON_MDI_EXCAVATOR "\xf3\xb1\x80\xa5" // U+F1025 +#define ICON_MDI_EXCLAMATION "\xf3\xb0\x88\x85" // U+F0205 +#define ICON_MDI_EXCLAMATION_THICK "\xf3\xb1\x88\xb8" // U+F1238 +#define ICON_MDI_EXIT_RUN "\xf3\xb0\xa9\x88" // U+F0A48 +#define ICON_MDI_EXIT_TO_APP "\xf3\xb0\x88\x86" // U+F0206 +#define ICON_MDI_EXPAND_ALL "\xf3\xb0\xaa\xb4" // U+F0AB4 +#define ICON_MDI_EXPAND_ALL_OUTLINE "\xf3\xb0\xaa\xb5" // U+F0AB5 +#define ICON_MDI_EXPANSION_CARD "\xf3\xb0\xa2\xae" // U+F08AE +#define ICON_MDI_EXPANSION_CARD_VARIANT "\xf3\xb0\xbe\xb2" // U+F0FB2 +#define ICON_MDI_EXPONENT "\xf3\xb0\xa5\xa3" // U+F0963 +#define ICON_MDI_EXPONENT_BOX "\xf3\xb0\xa5\xa4" // U+F0964 +#define ICON_MDI_EXPORT "\xf3\xb0\x88\x87" // U+F0207 +#define ICON_MDI_EXPORT_VARIANT "\xf3\xb0\xae\x93" // U+F0B93 +#define ICON_MDI_EYE "\xf3\xb0\x88\x88" // U+F0208 +#define ICON_MDI_EYE_ARROW_LEFT "\xf3\xb1\xa3\xbd" // U+F18FD +#define ICON_MDI_EYE_ARROW_LEFT_OUTLINE "\xf3\xb1\xa3\xbe" // U+F18FE +#define ICON_MDI_EYE_ARROW_RIGHT "\xf3\xb1\xa3\xbf" // U+F18FF +#define ICON_MDI_EYE_ARROW_RIGHT_OUTLINE "\xf3\xb1\xa4\x80" // U+F1900 +#define ICON_MDI_EYE_CHECK "\xf3\xb0\xb4\x84" // U+F0D04 +#define ICON_MDI_EYE_CHECK_OUTLINE "\xf3\xb0\xb4\x85" // U+F0D05 +#define ICON_MDI_EYE_CIRCLE "\xf3\xb0\xae\x94" // U+F0B94 +#define ICON_MDI_EYE_CIRCLE_OUTLINE "\xf3\xb0\xae\x95" // U+F0B95 +#define ICON_MDI_EYE_CLOSED "\xf3\xb1\xb2\xa3" // U+F1CA3 +#define ICON_MDI_EYE_LOCK "\xf3\xb1\xb0\x86" // U+F1C06 +#define ICON_MDI_EYE_LOCK_OPEN "\xf3\xb1\xb0\x87" // U+F1C07 +#define ICON_MDI_EYE_LOCK_OPEN_OUTLINE "\xf3\xb1\xb0\x88" // U+F1C08 +#define ICON_MDI_EYE_LOCK_OUTLINE "\xf3\xb1\xb0\x89" // U+F1C09 +#define ICON_MDI_EYE_MINUS "\xf3\xb1\x80\xa6" // U+F1026 +#define ICON_MDI_EYE_MINUS_OUTLINE "\xf3\xb1\x80\xa7" // U+F1027 +#define ICON_MDI_EYE_OFF "\xf3\xb0\x88\x89" // U+F0209 +#define ICON_MDI_EYE_OFF_OUTLINE "\xf3\xb0\x9b\x91" // U+F06D1 +#define ICON_MDI_EYE_OUTLINE "\xf3\xb0\x9b\x90" // U+F06D0 +#define ICON_MDI_EYE_PLUS "\xf3\xb0\xa1\xab" // U+F086B +#define ICON_MDI_EYE_PLUS_OUTLINE "\xf3\xb0\xa1\xac" // U+F086C +#define ICON_MDI_EYE_REFRESH "\xf3\xb1\xa5\xbc" // U+F197C +#define ICON_MDI_EYE_REFRESH_OUTLINE "\xf3\xb1\xa5\xbd" // U+F197D +#define ICON_MDI_EYE_REMOVE "\xf3\xb1\x97\xa3" // U+F15E3 +#define ICON_MDI_EYE_REMOVE_OUTLINE "\xf3\xb1\x97\xa4" // U+F15E4 +#define ICON_MDI_EYE_SETTINGS "\xf3\xb0\xa1\xad" // U+F086D +#define ICON_MDI_EYE_SETTINGS_OUTLINE "\xf3\xb0\xa1\xae" // U+F086E +#define ICON_MDI_EYEDROPPER "\xf3\xb0\x88\x8a" // U+F020A +#define ICON_MDI_EYEDROPPER_MINUS "\xf3\xb1\x8f\x9d" // U+F13DD +#define ICON_MDI_EYEDROPPER_OFF "\xf3\xb1\x8f\x9f" // U+F13DF +#define ICON_MDI_EYEDROPPER_PLUS "\xf3\xb1\x8f\x9c" // U+F13DC +#define ICON_MDI_EYEDROPPER_REMOVE "\xf3\xb1\x8f\x9e" // U+F13DE +#define ICON_MDI_EYEDROPPER_VARIANT "\xf3\xb0\x88\x8b" // U+F020B +#define ICON_MDI_FACE_AGENT "\xf3\xb0\xb5\xb0" // U+F0D70 +#define ICON_MDI_FACE_MAN "\xf3\xb0\x99\x83" // U+F0643 +#define ICON_MDI_FACE_MAN_OUTLINE "\xf3\xb0\xae\x96" // U+F0B96 +#define ICON_MDI_FACE_MAN_PROFILE "\xf3\xb0\x99\x84" // U+F0644 +#define ICON_MDI_FACE_MAN_SHIMMER "\xf3\xb1\x97\x8c" // U+F15CC +#define ICON_MDI_FACE_MAN_SHIMMER_OUTLINE "\xf3\xb1\x97\x8d" // U+F15CD +#define ICON_MDI_FACE_MASK "\xf3\xb1\x96\x86" // U+F1586 +#define ICON_MDI_FACE_MASK_OUTLINE "\xf3\xb1\x96\x87" // U+F1587 +#define ICON_MDI_FACE_RECOGNITION "\xf3\xb0\xb1\xbb" // U+F0C7B +#define ICON_MDI_FACE_WOMAN "\xf3\xb1\x81\xb7" // U+F1077 +#define ICON_MDI_FACE_WOMAN_OUTLINE "\xf3\xb1\x81\xb8" // U+F1078 +#define ICON_MDI_FACE_WOMAN_PROFILE "\xf3\xb1\x81\xb6" // U+F1076 +#define ICON_MDI_FACE_WOMAN_SHIMMER "\xf3\xb1\x97\x8e" // U+F15CE +#define ICON_MDI_FACE_WOMAN_SHIMMER_OUTLINE "\xf3\xb1\x97\x8f" // U+F15CF +#define ICON_MDI_FACEBOOK "\xf3\xb0\x88\x8c" // U+F020C +#define ICON_MDI_FACEBOOK_GAMING "\xf3\xb0\x9f\x9d" // U+F07DD +#define ICON_MDI_FACEBOOK_MESSENGER "\xf3\xb0\x88\x8e" // U+F020E +#define ICON_MDI_FACEBOOK_WORKPLACE "\xf3\xb0\xac\xb1" // U+F0B31 +#define ICON_MDI_FACTORY "\xf3\xb0\x88\x8f" // U+F020F +#define ICON_MDI_FAMILY_TREE "\xf3\xb1\x98\x8e" // U+F160E +#define ICON_MDI_FAN "\xf3\xb0\x88\x90" // U+F0210 +#define ICON_MDI_FAN_ALERT "\xf3\xb1\x91\xac" // U+F146C +#define ICON_MDI_FAN_AUTO "\xf3\xb1\x9c\x9d" // U+F171D +#define ICON_MDI_FAN_CHEVRON_DOWN "\xf3\xb1\x91\xad" // U+F146D +#define ICON_MDI_FAN_CHEVRON_UP "\xf3\xb1\x91\xae" // U+F146E +#define ICON_MDI_FAN_CLOCK "\xf3\xb1\xa8\xba" // U+F1A3A +#define ICON_MDI_FAN_MINUS "\xf3\xb1\x91\xb0" // U+F1470 +#define ICON_MDI_FAN_OFF "\xf3\xb0\xa0\x9d" // U+F081D +#define ICON_MDI_FAN_PLUS "\xf3\xb1\x91\xaf" // U+F146F +#define ICON_MDI_FAN_REMOVE "\xf3\xb1\x91\xb1" // U+F1471 +#define ICON_MDI_FAN_SPEED_1 "\xf3\xb1\x91\xb2" // U+F1472 +#define ICON_MDI_FAN_SPEED_2 "\xf3\xb1\x91\xb3" // U+F1473 +#define ICON_MDI_FAN_SPEED_3 "\xf3\xb1\x91\xb4" // U+F1474 +#define ICON_MDI_FAST_FORWARD "\xf3\xb0\x88\x91" // U+F0211 +#define ICON_MDI_FAST_FORWARD_10 "\xf3\xb0\xb5\xb1" // U+F0D71 +#define ICON_MDI_FAST_FORWARD_15 "\xf3\xb1\xa4\xba" // U+F193A +#define ICON_MDI_FAST_FORWARD_30 "\xf3\xb0\xb4\x86" // U+F0D06 +#define ICON_MDI_FAST_FORWARD_45 "\xf3\xb1\xac\x92" // U+F1B12 +#define ICON_MDI_FAST_FORWARD_5 "\xf3\xb1\x87\xb8" // U+F11F8 +#define ICON_MDI_FAST_FORWARD_60 "\xf3\xb1\x98\x8b" // U+F160B +#define ICON_MDI_FAST_FORWARD_OUTLINE "\xf3\xb0\x9b\x92" // U+F06D2 +#define ICON_MDI_FAUCET "\xf3\xb1\xac\xa9" // U+F1B29 +#define ICON_MDI_FAUCET_VARIANT "\xf3\xb1\xac\xaa" // U+F1B2A +#define ICON_MDI_FAX "\xf3\xb0\x88\x92" // U+F0212 +#define ICON_MDI_FEATHER "\xf3\xb0\x9b\x93" // U+F06D3 +#define ICON_MDI_FEATURE_SEARCH "\xf3\xb0\xa9\x89" // U+F0A49 +#define ICON_MDI_FEATURE_SEARCH_OUTLINE "\xf3\xb0\xa9\x8a" // U+F0A4A +#define ICON_MDI_FEDORA "\xf3\xb0\xa3\x9b" // U+F08DB +#define ICON_MDI_FENCE "\xf3\xb1\x9e\x9a" // U+F179A +#define ICON_MDI_FENCE_ELECTRIC "\xf3\xb1\x9f\xb6" // U+F17F6 +#define ICON_MDI_FENCING "\xf3\xb1\x93\x81" // U+F14C1 +#define ICON_MDI_FERRIS_WHEEL "\xf3\xb0\xba\xa4" // U+F0EA4 +#define ICON_MDI_FERRY "\xf3\xb0\x88\x93" // U+F0213 +#define ICON_MDI_FILE "\xf3\xb0\x88\x94" // U+F0214 +#define ICON_MDI_FILE_ACCOUNT "\xf3\xb0\x9c\xbb" // U+F073B +#define ICON_MDI_FILE_ACCOUNT_OUTLINE "\xf3\xb1\x80\xa8" // U+F1028 +#define ICON_MDI_FILE_ALERT "\xf3\xb0\xa9\x8b" // U+F0A4B +#define ICON_MDI_FILE_ALERT_OUTLINE "\xf3\xb0\xa9\x8c" // U+F0A4C +#define ICON_MDI_FILE_ARROW_LEFT_RIGHT "\xf3\xb1\xaa\x93" // U+F1A93 +#define ICON_MDI_FILE_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xaa\x94" // U+F1A94 +#define ICON_MDI_FILE_ARROW_UP_DOWN "\xf3\xb1\xaa\x95" // U+F1A95 +#define ICON_MDI_FILE_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xaa\x96" // U+F1A96 +#define ICON_MDI_FILE_CABINET "\xf3\xb0\xaa\xb6" // U+F0AB6 +#define ICON_MDI_FILE_CAD "\xf3\xb0\xbb\xab" // U+F0EEB +#define ICON_MDI_FILE_CAD_BOX "\xf3\xb0\xbb\xac" // U+F0EEC +#define ICON_MDI_FILE_CANCEL "\xf3\xb0\xb7\x86" // U+F0DC6 +#define ICON_MDI_FILE_CANCEL_OUTLINE "\xf3\xb0\xb7\x87" // U+F0DC7 +#define ICON_MDI_FILE_CERTIFICATE "\xf3\xb1\x86\x86" // U+F1186 +#define ICON_MDI_FILE_CERTIFICATE_OUTLINE "\xf3\xb1\x86\x87" // U+F1187 +#define ICON_MDI_FILE_CHART "\xf3\xb0\x88\x95" // U+F0215 +#define ICON_MDI_FILE_CHART_CHECK "\xf3\xb1\xa7\x86" // U+F19C6 +#define ICON_MDI_FILE_CHART_CHECK_OUTLINE "\xf3\xb1\xa7\x87" // U+F19C7 +#define ICON_MDI_FILE_CHART_OUTLINE "\xf3\xb1\x80\xa9" // U+F1029 +#define ICON_MDI_FILE_CHECK "\xf3\xb0\x88\x96" // U+F0216 +#define ICON_MDI_FILE_CHECK_OUTLINE "\xf3\xb0\xb8\xa9" // U+F0E29 +#define ICON_MDI_FILE_CLOCK "\xf3\xb1\x8b\xa1" // U+F12E1 +#define ICON_MDI_FILE_CLOCK_OUTLINE "\xf3\xb1\x8b\xa2" // U+F12E2 +#define ICON_MDI_FILE_CLOUD "\xf3\xb0\x88\x97" // U+F0217 +#define ICON_MDI_FILE_CLOUD_OUTLINE "\xf3\xb1\x80\xaa" // U+F102A +#define ICON_MDI_FILE_CODE "\xf3\xb0\x88\xae" // U+F022E +#define ICON_MDI_FILE_CODE_OUTLINE "\xf3\xb1\x80\xab" // U+F102B +#define ICON_MDI_FILE_COG "\xf3\xb1\x81\xbb" // U+F107B +#define ICON_MDI_FILE_COG_OUTLINE "\xf3\xb1\x81\xbc" // U+F107C +#define ICON_MDI_FILE_COMPARE "\xf3\xb0\xa2\xaa" // U+F08AA +#define ICON_MDI_FILE_DELIMITED "\xf3\xb0\x88\x98" // U+F0218 +#define ICON_MDI_FILE_DELIMITED_OUTLINE "\xf3\xb0\xba\xa5" // U+F0EA5 +#define ICON_MDI_FILE_DOCUMENT "\xf3\xb0\x88\x99" // U+F0219 +#define ICON_MDI_FILE_DOCUMENT_ALERT "\xf3\xb1\xaa\x97" // U+F1A97 +#define ICON_MDI_FILE_DOCUMENT_ALERT_OUTLINE "\xf3\xb1\xaa\x98" // U+F1A98 +#define ICON_MDI_FILE_DOCUMENT_ARROW_RIGHT "\xf3\xb1\xb0\x8f" // U+F1C0F +#define ICON_MDI_FILE_DOCUMENT_ARROW_RIGHT_OUTLINE "\xf3\xb1\xb0\x90" // U+F1C10 +#define ICON_MDI_FILE_DOCUMENT_CHECK "\xf3\xb1\xaa\x99" // U+F1A99 +#define ICON_MDI_FILE_DOCUMENT_CHECK_OUTLINE "\xf3\xb1\xaa\x9a" // U+F1A9A +#define ICON_MDI_FILE_DOCUMENT_EDIT "\xf3\xb0\xb7\x88" // U+F0DC8 +#define ICON_MDI_FILE_DOCUMENT_EDIT_OUTLINE "\xf3\xb0\xb7\x89" // U+F0DC9 +#define ICON_MDI_FILE_DOCUMENT_MINUS "\xf3\xb1\xaa\x9b" // U+F1A9B +#define ICON_MDI_FILE_DOCUMENT_MINUS_OUTLINE "\xf3\xb1\xaa\x9c" // U+F1A9C +#define ICON_MDI_FILE_DOCUMENT_MULTIPLE "\xf3\xb1\x94\x97" // U+F1517 +#define ICON_MDI_FILE_DOCUMENT_MULTIPLE_OUTLINE "\xf3\xb1\x94\x98" // U+F1518 +#define ICON_MDI_FILE_DOCUMENT_OUTLINE "\xf3\xb0\xa7\xae" // U+F09EE +#define ICON_MDI_FILE_DOCUMENT_PLUS "\xf3\xb1\xaa\x9d" // U+F1A9D +#define ICON_MDI_FILE_DOCUMENT_PLUS_OUTLINE "\xf3\xb1\xaa\x9e" // U+F1A9E +#define ICON_MDI_FILE_DOCUMENT_REFRESH "\xf3\xb1\xb1\xba" // U+F1C7A +#define ICON_MDI_FILE_DOCUMENT_REFRESH_OUTLINE "\xf3\xb1\xb1\xbb" // U+F1C7B +#define ICON_MDI_FILE_DOCUMENT_REMOVE "\xf3\xb1\xaa\x9f" // U+F1A9F +#define ICON_MDI_FILE_DOCUMENT_REMOVE_OUTLINE "\xf3\xb1\xaa\xa0" // U+F1AA0 +#define ICON_MDI_FILE_DOWNLOAD "\xf3\xb0\xa5\xa5" // U+F0965 +#define ICON_MDI_FILE_DOWNLOAD_OUTLINE "\xf3\xb0\xa5\xa6" // U+F0966 +#define ICON_MDI_FILE_EDIT "\xf3\xb1\x87\xa7" // U+F11E7 +#define ICON_MDI_FILE_EDIT_OUTLINE "\xf3\xb1\x87\xa8" // U+F11E8 +#define ICON_MDI_FILE_EXCEL "\xf3\xb0\x88\x9b" // U+F021B +#define ICON_MDI_FILE_EXCEL_BOX "\xf3\xb0\x88\x9c" // U+F021C +#define ICON_MDI_FILE_EXCEL_BOX_OUTLINE "\xf3\xb1\x80\xac" // U+F102C +#define ICON_MDI_FILE_EXCEL_OUTLINE "\xf3\xb1\x80\xad" // U+F102D +#define ICON_MDI_FILE_EXPORT "\xf3\xb0\x88\x9d" // U+F021D +#define ICON_MDI_FILE_EXPORT_OUTLINE "\xf3\xb1\x80\xae" // U+F102E +#define ICON_MDI_FILE_EYE "\xf3\xb0\xb7\x8a" // U+F0DCA +#define ICON_MDI_FILE_EYE_OUTLINE "\xf3\xb0\xb7\x8b" // U+F0DCB +#define ICON_MDI_FILE_FIND "\xf3\xb0\x88\x9e" // U+F021E +#define ICON_MDI_FILE_FIND_OUTLINE "\xf3\xb0\xae\x97" // U+F0B97 +#define ICON_MDI_FILE_GIF_BOX "\xf3\xb0\xb5\xb8" // U+F0D78 +#define ICON_MDI_FILE_HIDDEN "\xf3\xb0\x98\x93" // U+F0613 +#define ICON_MDI_FILE_IMAGE "\xf3\xb0\x88\x9f" // U+F021F +#define ICON_MDI_FILE_IMAGE_MARKER "\xf3\xb1\x9d\xb2" // U+F1772 +#define ICON_MDI_FILE_IMAGE_MARKER_OUTLINE "\xf3\xb1\x9d\xb3" // U+F1773 +#define ICON_MDI_FILE_IMAGE_MINUS "\xf3\xb1\xa4\xbb" // U+F193B +#define ICON_MDI_FILE_IMAGE_MINUS_OUTLINE "\xf3\xb1\xa4\xbc" // U+F193C +#define ICON_MDI_FILE_IMAGE_OUTLINE "\xf3\xb0\xba\xb0" // U+F0EB0 +#define ICON_MDI_FILE_IMAGE_PLUS "\xf3\xb1\xa4\xbd" // U+F193D +#define ICON_MDI_FILE_IMAGE_PLUS_OUTLINE "\xf3\xb1\xa4\xbe" // U+F193E +#define ICON_MDI_FILE_IMAGE_REMOVE "\xf3\xb1\xa4\xbf" // U+F193F +#define ICON_MDI_FILE_IMAGE_REMOVE_OUTLINE "\xf3\xb1\xa5\x80" // U+F1940 +#define ICON_MDI_FILE_IMPORT "\xf3\xb0\x88\xa0" // U+F0220 +#define ICON_MDI_FILE_IMPORT_OUTLINE "\xf3\xb1\x80\xaf" // U+F102F +#define ICON_MDI_FILE_JPG_BOX "\xf3\xb0\x88\xa5" // U+F0225 +#define ICON_MDI_FILE_KEY "\xf3\xb1\x86\x84" // U+F1184 +#define ICON_MDI_FILE_KEY_OUTLINE "\xf3\xb1\x86\x85" // U+F1185 +#define ICON_MDI_FILE_LINK "\xf3\xb1\x85\xb7" // U+F1177 +#define ICON_MDI_FILE_LINK_OUTLINE "\xf3\xb1\x85\xb8" // U+F1178 +#define ICON_MDI_FILE_LOCK "\xf3\xb0\x88\xa1" // U+F0221 +#define ICON_MDI_FILE_LOCK_OPEN "\xf3\xb1\xa7\x88" // U+F19C8 +#define ICON_MDI_FILE_LOCK_OPEN_OUTLINE "\xf3\xb1\xa7\x89" // U+F19C9 +#define ICON_MDI_FILE_LOCK_OUTLINE "\xf3\xb1\x80\xb0" // U+F1030 +#define ICON_MDI_FILE_MARKER "\xf3\xb1\x9d\xb4" // U+F1774 +#define ICON_MDI_FILE_MARKER_OUTLINE "\xf3\xb1\x9d\xb5" // U+F1775 +#define ICON_MDI_FILE_MINUS "\xf3\xb1\xaa\xa1" // U+F1AA1 +#define ICON_MDI_FILE_MINUS_OUTLINE "\xf3\xb1\xaa\xa2" // U+F1AA2 +#define ICON_MDI_FILE_MOVE "\xf3\xb0\xaa\xb9" // U+F0AB9 +#define ICON_MDI_FILE_MOVE_OUTLINE "\xf3\xb1\x80\xb1" // U+F1031 +#define ICON_MDI_FILE_MULTIPLE "\xf3\xb0\x88\xa2" // U+F0222 +#define ICON_MDI_FILE_MULTIPLE_OUTLINE "\xf3\xb1\x80\xb2" // U+F1032 +#define ICON_MDI_FILE_MUSIC "\xf3\xb0\x88\xa3" // U+F0223 +#define ICON_MDI_FILE_MUSIC_OUTLINE "\xf3\xb0\xb8\xaa" // U+F0E2A +#define ICON_MDI_FILE_OUTLINE "\xf3\xb0\x88\xa4" // U+F0224 +#define ICON_MDI_FILE_PDF_BOX "\xf3\xb0\x88\xa6" // U+F0226 +#define ICON_MDI_FILE_PERCENT "\xf3\xb0\xa0\x9e" // U+F081E +#define ICON_MDI_FILE_PERCENT_OUTLINE "\xf3\xb1\x80\xb3" // U+F1033 +#define ICON_MDI_FILE_PHONE "\xf3\xb1\x85\xb9" // U+F1179 +#define ICON_MDI_FILE_PHONE_OUTLINE "\xf3\xb1\x85\xba" // U+F117A +#define ICON_MDI_FILE_PLUS "\xf3\xb0\x9d\x92" // U+F0752 +#define ICON_MDI_FILE_PLUS_OUTLINE "\xf3\xb0\xbb\xad" // U+F0EED +#define ICON_MDI_FILE_PNG_BOX "\xf3\xb0\xb8\xad" // U+F0E2D +#define ICON_MDI_FILE_POWERPOINT "\xf3\xb0\x88\xa7" // U+F0227 +#define ICON_MDI_FILE_POWERPOINT_BOX "\xf3\xb0\x88\xa8" // U+F0228 +#define ICON_MDI_FILE_POWERPOINT_BOX_OUTLINE "\xf3\xb1\x80\xb4" // U+F1034 +#define ICON_MDI_FILE_POWERPOINT_OUTLINE "\xf3\xb1\x80\xb5" // U+F1035 +#define ICON_MDI_FILE_PRESENTATION_BOX "\xf3\xb0\x88\xa9" // U+F0229 +#define ICON_MDI_FILE_QUESTION "\xf3\xb0\xa1\xaf" // U+F086F +#define ICON_MDI_FILE_QUESTION_OUTLINE "\xf3\xb1\x80\xb6" // U+F1036 +#define ICON_MDI_FILE_REFRESH "\xf3\xb0\xa4\x98" // U+F0918 +#define ICON_MDI_FILE_REFRESH_OUTLINE "\xf3\xb0\x95\x81" // U+F0541 +#define ICON_MDI_FILE_REMOVE "\xf3\xb0\xae\x98" // U+F0B98 +#define ICON_MDI_FILE_REMOVE_OUTLINE "\xf3\xb1\x80\xb7" // U+F1037 +#define ICON_MDI_FILE_REPLACE "\xf3\xb0\xac\xb2" // U+F0B32 +#define ICON_MDI_FILE_REPLACE_OUTLINE "\xf3\xb0\xac\xb3" // U+F0B33 +#define ICON_MDI_FILE_RESTORE "\xf3\xb0\x99\xb0" // U+F0670 +#define ICON_MDI_FILE_RESTORE_OUTLINE "\xf3\xb1\x80\xb8" // U+F1038 +#define ICON_MDI_FILE_ROTATE_LEFT "\xf3\xb1\xa8\xbb" // U+F1A3B +#define ICON_MDI_FILE_ROTATE_LEFT_OUTLINE "\xf3\xb1\xa8\xbc" // U+F1A3C +#define ICON_MDI_FILE_ROTATE_RIGHT "\xf3\xb1\xa8\xbd" // U+F1A3D +#define ICON_MDI_FILE_ROTATE_RIGHT_OUTLINE "\xf3\xb1\xa8\xbe" // U+F1A3E +#define ICON_MDI_FILE_SEARCH "\xf3\xb0\xb1\xbc" // U+F0C7C +#define ICON_MDI_FILE_SEARCH_OUTLINE "\xf3\xb0\xb1\xbd" // U+F0C7D +#define ICON_MDI_FILE_SEND "\xf3\xb0\x88\xaa" // U+F022A +#define ICON_MDI_FILE_SEND_OUTLINE "\xf3\xb1\x80\xb9" // U+F1039 +#define ICON_MDI_FILE_SETTINGS "\xf3\xb1\x81\xb9" // U+F1079 +#define ICON_MDI_FILE_SETTINGS_OUTLINE "\xf3\xb1\x81\xba" // U+F107A +#define ICON_MDI_FILE_SIGN "\xf3\xb1\xa7\x83" // U+F19C3 +#define ICON_MDI_FILE_STAR "\xf3\xb1\x80\xba" // U+F103A +#define ICON_MDI_FILE_STAR_FOUR_POINTS "\xf3\xb1\xb0\xad" // U+F1C2D +#define ICON_MDI_FILE_STAR_FOUR_POINTS_OUTLINE "\xf3\xb1\xb0\xae" // U+F1C2E +#define ICON_MDI_FILE_STAR_OUTLINE "\xf3\xb1\x80\xbb" // U+F103B +#define ICON_MDI_FILE_SWAP "\xf3\xb0\xbe\xb4" // U+F0FB4 +#define ICON_MDI_FILE_SWAP_OUTLINE "\xf3\xb0\xbe\xb5" // U+F0FB5 +#define ICON_MDI_FILE_SYNC "\xf3\xb1\x88\x96" // U+F1216 +#define ICON_MDI_FILE_SYNC_OUTLINE "\xf3\xb1\x88\x97" // U+F1217 +#define ICON_MDI_FILE_TABLE "\xf3\xb0\xb1\xbe" // U+F0C7E +#define ICON_MDI_FILE_TABLE_BOX "\xf3\xb1\x83\xa1" // U+F10E1 +#define ICON_MDI_FILE_TABLE_BOX_MULTIPLE "\xf3\xb1\x83\xa2" // U+F10E2 +#define ICON_MDI_FILE_TABLE_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x83\xa3" // U+F10E3 +#define ICON_MDI_FILE_TABLE_BOX_OUTLINE "\xf3\xb1\x83\xa4" // U+F10E4 +#define ICON_MDI_FILE_TABLE_OUTLINE "\xf3\xb0\xb1\xbf" // U+F0C7F +#define ICON_MDI_FILE_TREE "\xf3\xb0\x99\x85" // U+F0645 +#define ICON_MDI_FILE_TREE_OUTLINE "\xf3\xb1\x8f\x92" // U+F13D2 +#define ICON_MDI_FILE_UNDO "\xf3\xb0\xa3\x9c" // U+F08DC +#define ICON_MDI_FILE_UNDO_OUTLINE "\xf3\xb1\x80\xbc" // U+F103C +#define ICON_MDI_FILE_UPLOAD "\xf3\xb0\xa9\x8d" // U+F0A4D +#define ICON_MDI_FILE_UPLOAD_OUTLINE "\xf3\xb0\xa9\x8e" // U+F0A4E +#define ICON_MDI_FILE_VIDEO "\xf3\xb0\x88\xab" // U+F022B +#define ICON_MDI_FILE_VIDEO_OUTLINE "\xf3\xb0\xb8\xac" // U+F0E2C +#define ICON_MDI_FILE_WORD "\xf3\xb0\x88\xac" // U+F022C +#define ICON_MDI_FILE_WORD_BOX "\xf3\xb0\x88\xad" // U+F022D +#define ICON_MDI_FILE_WORD_BOX_OUTLINE "\xf3\xb1\x80\xbd" // U+F103D +#define ICON_MDI_FILE_WORD_OUTLINE "\xf3\xb1\x80\xbe" // U+F103E +#define ICON_MDI_FILE_XML_BOX "\xf3\xb1\xad\x8b" // U+F1B4B +#define ICON_MDI_FILM "\xf3\xb0\x88\xaf" // U+F022F +#define ICON_MDI_FILMSTRIP "\xf3\xb0\x88\xb0" // U+F0230 +#define ICON_MDI_FILMSTRIP_BOX "\xf3\xb0\x8c\xb2" // U+F0332 +#define ICON_MDI_FILMSTRIP_BOX_MULTIPLE "\xf3\xb0\xb4\x98" // U+F0D18 +#define ICON_MDI_FILMSTRIP_OFF "\xf3\xb0\x88\xb1" // U+F0231 +#define ICON_MDI_FILTER "\xf3\xb0\x88\xb2" // U+F0232 +#define ICON_MDI_FILTER_CHECK "\xf3\xb1\xa3\xac" // U+F18EC +#define ICON_MDI_FILTER_CHECK_OUTLINE "\xf3\xb1\xa3\xad" // U+F18ED +#define ICON_MDI_FILTER_COG "\xf3\xb1\xaa\xa3" // U+F1AA3 +#define ICON_MDI_FILTER_COG_OUTLINE "\xf3\xb1\xaa\xa4" // U+F1AA4 +#define ICON_MDI_FILTER_MENU "\xf3\xb1\x83\xa5" // U+F10E5 +#define ICON_MDI_FILTER_MENU_OUTLINE "\xf3\xb1\x83\xa6" // U+F10E6 +#define ICON_MDI_FILTER_MINUS "\xf3\xb0\xbb\xae" // U+F0EEE +#define ICON_MDI_FILTER_MINUS_OUTLINE "\xf3\xb0\xbb\xaf" // U+F0EEF +#define ICON_MDI_FILTER_MULTIPLE "\xf3\xb1\xa8\xbf" // U+F1A3F +#define ICON_MDI_FILTER_MULTIPLE_OUTLINE "\xf3\xb1\xa9\x80" // U+F1A40 +#define ICON_MDI_FILTER_OFF "\xf3\xb1\x93\xaf" // U+F14EF +#define ICON_MDI_FILTER_OFF_OUTLINE "\xf3\xb1\x93\xb0" // U+F14F0 +#define ICON_MDI_FILTER_OUTLINE "\xf3\xb0\x88\xb3" // U+F0233 +#define ICON_MDI_FILTER_PLUS "\xf3\xb0\xbb\xb0" // U+F0EF0 +#define ICON_MDI_FILTER_PLUS_OUTLINE "\xf3\xb0\xbb\xb1" // U+F0EF1 +#define ICON_MDI_FILTER_REMOVE "\xf3\xb0\x88\xb4" // U+F0234 +#define ICON_MDI_FILTER_REMOVE_OUTLINE "\xf3\xb0\x88\xb5" // U+F0235 +#define ICON_MDI_FILTER_SETTINGS "\xf3\xb1\xaa\xa5" // U+F1AA5 +#define ICON_MDI_FILTER_SETTINGS_OUTLINE "\xf3\xb1\xaa\xa6" // U+F1AA6 +#define ICON_MDI_FILTER_VARIANT "\xf3\xb0\x88\xb6" // U+F0236 +#define ICON_MDI_FILTER_VARIANT_MINUS "\xf3\xb1\x84\x92" // U+F1112 +#define ICON_MDI_FILTER_VARIANT_PLUS "\xf3\xb1\x84\x93" // U+F1113 +#define ICON_MDI_FILTER_VARIANT_REMOVE "\xf3\xb1\x80\xbf" // U+F103F +#define ICON_MDI_FINANCE "\xf3\xb0\xa0\x9f" // U+F081F +#define ICON_MDI_FIND_REPLACE "\xf3\xb0\x9b\x94" // U+F06D4 +#define ICON_MDI_FINGERPRINT "\xf3\xb0\x88\xb7" // U+F0237 +#define ICON_MDI_FINGERPRINT_OFF "\xf3\xb0\xba\xb1" // U+F0EB1 +#define ICON_MDI_FIRE "\xf3\xb0\x88\xb8" // U+F0238 +#define ICON_MDI_FIRE_ALERT "\xf3\xb1\x97\x97" // U+F15D7 +#define ICON_MDI_FIRE_CIRCLE "\xf3\xb1\xa0\x87" // U+F1807 +#define ICON_MDI_FIRE_EXTINGUISHER "\xf3\xb0\xbb\xb2" // U+F0EF2 +#define ICON_MDI_FIRE_HYDRANT "\xf3\xb1\x84\xb7" // U+F1137 +#define ICON_MDI_FIRE_HYDRANT_ALERT "\xf3\xb1\x84\xb8" // U+F1138 +#define ICON_MDI_FIRE_HYDRANT_OFF "\xf3\xb1\x84\xb9" // U+F1139 +#define ICON_MDI_FIRE_OFF "\xf3\xb1\x9c\xa2" // U+F1722 +#define ICON_MDI_FIRE_STATION "\xf3\xb1\xb3\x83" // U+F1CC3 +#define ICON_MDI_FIRE_TRUCK "\xf3\xb0\xa2\xab" // U+F08AB +#define ICON_MDI_FIREBASE "\xf3\xb0\xa5\xa7" // U+F0967 +#define ICON_MDI_FIREFOX "\xf3\xb0\x88\xb9" // U+F0239 +#define ICON_MDI_FIREPLACE "\xf3\xb0\xb8\xae" // U+F0E2E +#define ICON_MDI_FIREPLACE_OFF "\xf3\xb0\xb8\xaf" // U+F0E2F +#define ICON_MDI_FIREWIRE "\xf3\xb0\x96\xbe" // U+F05BE +#define ICON_MDI_FIREWORK "\xf3\xb0\xb8\xb0" // U+F0E30 +#define ICON_MDI_FIREWORK_OFF "\xf3\xb1\x9c\xa3" // U+F1723 +#define ICON_MDI_FISH "\xf3\xb0\x88\xba" // U+F023A +#define ICON_MDI_FISH_OFF "\xf3\xb1\x8f\xb3" // U+F13F3 +#define ICON_MDI_FISHBOWL "\xf3\xb0\xbb\xb3" // U+F0EF3 +#define ICON_MDI_FISHBOWL_OUTLINE "\xf3\xb0\xbb\xb4" // U+F0EF4 +#define ICON_MDI_FIT_TO_PAGE "\xf3\xb0\xbb\xb5" // U+F0EF5 +#define ICON_MDI_FIT_TO_PAGE_OUTLINE "\xf3\xb0\xbb\xb6" // U+F0EF6 +#define ICON_MDI_FIT_TO_SCREEN "\xf3\xb1\xa3\xb4" // U+F18F4 +#define ICON_MDI_FIT_TO_SCREEN_OUTLINE "\xf3\xb1\xa3\xb5" // U+F18F5 +#define ICON_MDI_FLAG "\xf3\xb0\x88\xbb" // U+F023B +#define ICON_MDI_FLAG_CHECKERED "\xf3\xb0\x88\xbc" // U+F023C +#define ICON_MDI_FLAG_MINUS "\xf3\xb0\xae\x99" // U+F0B99 +#define ICON_MDI_FLAG_MINUS_OUTLINE "\xf3\xb1\x82\xb2" // U+F10B2 +#define ICON_MDI_FLAG_OFF "\xf3\xb1\xa3\xae" // U+F18EE +#define ICON_MDI_FLAG_OFF_OUTLINE "\xf3\xb1\xa3\xaf" // U+F18EF +#define ICON_MDI_FLAG_OUTLINE "\xf3\xb0\x88\xbd" // U+F023D +#define ICON_MDI_FLAG_PLUS "\xf3\xb0\xae\x9a" // U+F0B9A +#define ICON_MDI_FLAG_PLUS_OUTLINE "\xf3\xb1\x82\xb3" // U+F10B3 +#define ICON_MDI_FLAG_REMOVE "\xf3\xb0\xae\x9b" // U+F0B9B +#define ICON_MDI_FLAG_REMOVE_OUTLINE "\xf3\xb1\x82\xb4" // U+F10B4 +#define ICON_MDI_FLAG_TRIANGLE "\xf3\xb0\x88\xbf" // U+F023F +#define ICON_MDI_FLAG_VARIANT "\xf3\xb0\x89\x80" // U+F0240 +#define ICON_MDI_FLAG_VARIANT_MINUS "\xf3\xb1\xae\xb4" // U+F1BB4 +#define ICON_MDI_FLAG_VARIANT_MINUS_OUTLINE "\xf3\xb1\xae\xb5" // U+F1BB5 +#define ICON_MDI_FLAG_VARIANT_OFF "\xf3\xb1\xae\xb0" // U+F1BB0 +#define ICON_MDI_FLAG_VARIANT_OFF_OUTLINE "\xf3\xb1\xae\xb1" // U+F1BB1 +#define ICON_MDI_FLAG_VARIANT_OUTLINE "\xf3\xb0\x88\xbe" // U+F023E +#define ICON_MDI_FLAG_VARIANT_PLUS "\xf3\xb1\xae\xb2" // U+F1BB2 +#define ICON_MDI_FLAG_VARIANT_PLUS_OUTLINE "\xf3\xb1\xae\xb3" // U+F1BB3 +#define ICON_MDI_FLAG_VARIANT_REMOVE "\xf3\xb1\xae\xb6" // U+F1BB6 +#define ICON_MDI_FLAG_VARIANT_REMOVE_OUTLINE "\xf3\xb1\xae\xb7" // U+F1BB7 +#define ICON_MDI_FLARE "\xf3\xb0\xb5\xb2" // U+F0D72 +#define ICON_MDI_FLASH "\xf3\xb0\x89\x81" // U+F0241 +#define ICON_MDI_FLASH_ALERT "\xf3\xb0\xbb\xb7" // U+F0EF7 +#define ICON_MDI_FLASH_ALERT_OUTLINE "\xf3\xb0\xbb\xb8" // U+F0EF8 +#define ICON_MDI_FLASH_AUTO "\xf3\xb0\x89\x82" // U+F0242 +#define ICON_MDI_FLASH_OFF "\xf3\xb0\x89\x83" // U+F0243 +#define ICON_MDI_FLASH_OFF_OUTLINE "\xf3\xb1\xad\x85" // U+F1B45 +#define ICON_MDI_FLASH_OUTLINE "\xf3\xb0\x9b\x95" // U+F06D5 +#define ICON_MDI_FLASH_RED_EYE "\xf3\xb0\x99\xbb" // U+F067B +#define ICON_MDI_FLASH_TRIANGLE "\xf3\xb1\xac\x9d" // U+F1B1D +#define ICON_MDI_FLASH_TRIANGLE_OUTLINE "\xf3\xb1\xac\x9e" // U+F1B1E +#define ICON_MDI_FLASHLIGHT "\xf3\xb0\x89\x84" // U+F0244 +#define ICON_MDI_FLASHLIGHT_OFF "\xf3\xb0\x89\x85" // U+F0245 +#define ICON_MDI_FLASK "\xf3\xb0\x82\x93" // U+F0093 +#define ICON_MDI_FLASK_EMPTY "\xf3\xb0\x82\x94" // U+F0094 +#define ICON_MDI_FLASK_EMPTY_MINUS "\xf3\xb1\x88\xba" // U+F123A +#define ICON_MDI_FLASK_EMPTY_MINUS_OUTLINE "\xf3\xb1\x88\xbb" // U+F123B +#define ICON_MDI_FLASK_EMPTY_OFF "\xf3\xb1\x8f\xb4" // U+F13F4 +#define ICON_MDI_FLASK_EMPTY_OFF_OUTLINE "\xf3\xb1\x8f\xb5" // U+F13F5 +#define ICON_MDI_FLASK_EMPTY_OUTLINE "\xf3\xb0\x82\x95" // U+F0095 +#define ICON_MDI_FLASK_EMPTY_PLUS "\xf3\xb1\x88\xbc" // U+F123C +#define ICON_MDI_FLASK_EMPTY_PLUS_OUTLINE "\xf3\xb1\x88\xbd" // U+F123D +#define ICON_MDI_FLASK_EMPTY_REMOVE "\xf3\xb1\x88\xbe" // U+F123E +#define ICON_MDI_FLASK_EMPTY_REMOVE_OUTLINE "\xf3\xb1\x88\xbf" // U+F123F +#define ICON_MDI_FLASK_MINUS "\xf3\xb1\x89\x80" // U+F1240 +#define ICON_MDI_FLASK_MINUS_OUTLINE "\xf3\xb1\x89\x81" // U+F1241 +#define ICON_MDI_FLASK_OFF "\xf3\xb1\x8f\xb6" // U+F13F6 +#define ICON_MDI_FLASK_OFF_OUTLINE "\xf3\xb1\x8f\xb7" // U+F13F7 +#define ICON_MDI_FLASK_OUTLINE "\xf3\xb0\x82\x96" // U+F0096 +#define ICON_MDI_FLASK_PLUS "\xf3\xb1\x89\x82" // U+F1242 +#define ICON_MDI_FLASK_PLUS_OUTLINE "\xf3\xb1\x89\x83" // U+F1243 +#define ICON_MDI_FLASK_REMOVE "\xf3\xb1\x89\x84" // U+F1244 +#define ICON_MDI_FLASK_REMOVE_OUTLINE "\xf3\xb1\x89\x85" // U+F1245 +#define ICON_MDI_FLASK_ROUND_BOTTOM "\xf3\xb1\x89\x8b" // U+F124B +#define ICON_MDI_FLASK_ROUND_BOTTOM_EMPTY "\xf3\xb1\x89\x8c" // U+F124C +#define ICON_MDI_FLASK_ROUND_BOTTOM_EMPTY_OUTLINE "\xf3\xb1\x89\x8d" // U+F124D +#define ICON_MDI_FLASK_ROUND_BOTTOM_OUTLINE "\xf3\xb1\x89\x8e" // U+F124E +#define ICON_MDI_FLEUR_DE_LIS "\xf3\xb1\x8c\x83" // U+F1303 +#define ICON_MDI_FLIP_HORIZONTAL "\xf3\xb1\x83\xa7" // U+F10E7 +#define ICON_MDI_FLIP_TO_BACK "\xf3\xb0\x89\x87" // U+F0247 +#define ICON_MDI_FLIP_TO_FRONT "\xf3\xb0\x89\x88" // U+F0248 +#define ICON_MDI_FLIP_VERTICAL "\xf3\xb1\x83\xa8" // U+F10E8 +#define ICON_MDI_FLOOR_LAMP "\xf3\xb0\xa3\x9d" // U+F08DD +#define ICON_MDI_FLOOR_LAMP_DUAL "\xf3\xb1\x81\x80" // U+F1040 +#define ICON_MDI_FLOOR_LAMP_DUAL_OUTLINE "\xf3\xb1\x9f\x8e" // U+F17CE +#define ICON_MDI_FLOOR_LAMP_OUTLINE "\xf3\xb1\x9f\x88" // U+F17C8 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE "\xf3\xb1\x9d\x87" // U+F1747 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_OUTLINE "\xf3\xb1\x9f\x96" // U+F17D6 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_VARIANT "\xf3\xb1\x81\x81" // U+F1041 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_VARIANT_OUTLINE "\xf3\xb1\x9f\x8f" // U+F17CF +#define ICON_MDI_FLOOR_PLAN "\xf3\xb0\xa0\xa1" // U+F0821 +#define ICON_MDI_FLOPPY "\xf3\xb0\x89\x89" // U+F0249 +#define ICON_MDI_FLOPPY_VARIANT "\xf3\xb0\xa7\xaf" // U+F09EF +#define ICON_MDI_FLOWER "\xf3\xb0\x89\x8a" // U+F024A +#define ICON_MDI_FLOWER_OUTLINE "\xf3\xb0\xa7\xb0" // U+F09F0 +#define ICON_MDI_FLOWER_POLLEN "\xf3\xb1\xa2\x85" // U+F1885 +#define ICON_MDI_FLOWER_POLLEN_OUTLINE "\xf3\xb1\xa2\x86" // U+F1886 +#define ICON_MDI_FLOWER_POPPY "\xf3\xb0\xb4\x88" // U+F0D08 +#define ICON_MDI_FLOWER_TULIP "\xf3\xb0\xa7\xb1" // U+F09F1 +#define ICON_MDI_FLOWER_TULIP_OUTLINE "\xf3\xb0\xa7\xb2" // U+F09F2 +#define ICON_MDI_FOCUS_AUTO "\xf3\xb0\xbd\x8e" // U+F0F4E +#define ICON_MDI_FOCUS_FIELD "\xf3\xb0\xbd\x8f" // U+F0F4F +#define ICON_MDI_FOCUS_FIELD_HORIZONTAL "\xf3\xb0\xbd\x90" // U+F0F50 +#define ICON_MDI_FOCUS_FIELD_VERTICAL "\xf3\xb0\xbd\x91" // U+F0F51 +#define ICON_MDI_FOLDER "\xf3\xb0\x89\x8b" // U+F024B +#define ICON_MDI_FOLDER_ACCOUNT "\xf3\xb0\x89\x8c" // U+F024C +#define ICON_MDI_FOLDER_ACCOUNT_OUTLINE "\xf3\xb0\xae\x9c" // U+F0B9C +#define ICON_MDI_FOLDER_ALERT "\xf3\xb0\xb7\x8c" // U+F0DCC +#define ICON_MDI_FOLDER_ALERT_OUTLINE "\xf3\xb0\xb7\x8d" // U+F0DCD +#define ICON_MDI_FOLDER_ARROW_DOWN "\xf3\xb1\xa7\xa8" // U+F19E8 +#define ICON_MDI_FOLDER_ARROW_DOWN_OUTLINE "\xf3\xb1\xa7\xa9" // U+F19E9 +#define ICON_MDI_FOLDER_ARROW_LEFT "\xf3\xb1\xa7\xaa" // U+F19EA +#define ICON_MDI_FOLDER_ARROW_LEFT_OUTLINE "\xf3\xb1\xa7\xab" // U+F19EB +#define ICON_MDI_FOLDER_ARROW_LEFT_RIGHT "\xf3\xb1\xa7\xac" // U+F19EC +#define ICON_MDI_FOLDER_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xa7\xad" // U+F19ED +#define ICON_MDI_FOLDER_ARROW_RIGHT "\xf3\xb1\xa7\xae" // U+F19EE +#define ICON_MDI_FOLDER_ARROW_RIGHT_OUTLINE "\xf3\xb1\xa7\xaf" // U+F19EF +#define ICON_MDI_FOLDER_ARROW_UP "\xf3\xb1\xa7\xb0" // U+F19F0 +#define ICON_MDI_FOLDER_ARROW_UP_DOWN "\xf3\xb1\xa7\xb1" // U+F19F1 +#define ICON_MDI_FOLDER_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xa7\xb2" // U+F19F2 +#define ICON_MDI_FOLDER_ARROW_UP_OUTLINE "\xf3\xb1\xa7\xb3" // U+F19F3 +#define ICON_MDI_FOLDER_CANCEL "\xf3\xb1\xa7\xb4" // U+F19F4 +#define ICON_MDI_FOLDER_CANCEL_OUTLINE "\xf3\xb1\xa7\xb5" // U+F19F5 +#define ICON_MDI_FOLDER_CHECK "\xf3\xb1\xa5\xbe" // U+F197E +#define ICON_MDI_FOLDER_CHECK_OUTLINE "\xf3\xb1\xa5\xbf" // U+F197F +#define ICON_MDI_FOLDER_CLOCK "\xf3\xb0\xaa\xba" // U+F0ABA +#define ICON_MDI_FOLDER_CLOCK_OUTLINE "\xf3\xb0\xaa\xbb" // U+F0ABB +#define ICON_MDI_FOLDER_COG "\xf3\xb1\x81\xbf" // U+F107F +#define ICON_MDI_FOLDER_COG_OUTLINE "\xf3\xb1\x82\x80" // U+F1080 +#define ICON_MDI_FOLDER_DOWNLOAD "\xf3\xb0\x89\x8d" // U+F024D +#define ICON_MDI_FOLDER_DOWNLOAD_OUTLINE "\xf3\xb1\x83\xa9" // U+F10E9 +#define ICON_MDI_FOLDER_EDIT "\xf3\xb0\xa3\x9e" // U+F08DE +#define ICON_MDI_FOLDER_EDIT_OUTLINE "\xf3\xb0\xb7\x8e" // U+F0DCE +#define ICON_MDI_FOLDER_EYE "\xf3\xb1\x9e\x8a" // U+F178A +#define ICON_MDI_FOLDER_EYE_OUTLINE "\xf3\xb1\x9e\x8b" // U+F178B +#define ICON_MDI_FOLDER_FILE "\xf3\xb1\xa7\xb6" // U+F19F6 +#define ICON_MDI_FOLDER_FILE_OUTLINE "\xf3\xb1\xa7\xb7" // U+F19F7 +#define ICON_MDI_FOLDER_GOOGLE_DRIVE "\xf3\xb0\x89\x8e" // U+F024E +#define ICON_MDI_FOLDER_HEART "\xf3\xb1\x83\xaa" // U+F10EA +#define ICON_MDI_FOLDER_HEART_OUTLINE "\xf3\xb1\x83\xab" // U+F10EB +#define ICON_MDI_FOLDER_HIDDEN "\xf3\xb1\x9e\x9e" // U+F179E +#define ICON_MDI_FOLDER_HOME "\xf3\xb1\x82\xb5" // U+F10B5 +#define ICON_MDI_FOLDER_HOME_OUTLINE "\xf3\xb1\x82\xb6" // U+F10B6 +#define ICON_MDI_FOLDER_IMAGE "\xf3\xb0\x89\x8f" // U+F024F +#define ICON_MDI_FOLDER_INFORMATION "\xf3\xb1\x82\xb7" // U+F10B7 +#define ICON_MDI_FOLDER_INFORMATION_OUTLINE "\xf3\xb1\x82\xb8" // U+F10B8 +#define ICON_MDI_FOLDER_KEY "\xf3\xb0\xa2\xac" // U+F08AC +#define ICON_MDI_FOLDER_KEY_NETWORK "\xf3\xb0\xa2\xad" // U+F08AD +#define ICON_MDI_FOLDER_KEY_NETWORK_OUTLINE "\xf3\xb0\xb2\x80" // U+F0C80 +#define ICON_MDI_FOLDER_KEY_OUTLINE "\xf3\xb1\x83\xac" // U+F10EC +#define ICON_MDI_FOLDER_LOCK "\xf3\xb0\x89\x90" // U+F0250 +#define ICON_MDI_FOLDER_LOCK_OPEN "\xf3\xb0\x89\x91" // U+F0251 +#define ICON_MDI_FOLDER_LOCK_OPEN_OUTLINE "\xf3\xb1\xaa\xa7" // U+F1AA7 +#define ICON_MDI_FOLDER_LOCK_OUTLINE "\xf3\xb1\xaa\xa8" // U+F1AA8 +#define ICON_MDI_FOLDER_MARKER "\xf3\xb1\x89\xad" // U+F126D +#define ICON_MDI_FOLDER_MARKER_OUTLINE "\xf3\xb1\x89\xae" // U+F126E +#define ICON_MDI_FOLDER_MINUS "\xf3\xb1\xad\x89" // U+F1B49 +#define ICON_MDI_FOLDER_MINUS_OUTLINE "\xf3\xb1\xad\x8a" // U+F1B4A +#define ICON_MDI_FOLDER_MOVE "\xf3\xb0\x89\x92" // U+F0252 +#define ICON_MDI_FOLDER_MOVE_OUTLINE "\xf3\xb1\x89\x86" // U+F1246 +#define ICON_MDI_FOLDER_MULTIPLE "\xf3\xb0\x89\x93" // U+F0253 +#define ICON_MDI_FOLDER_MULTIPLE_IMAGE "\xf3\xb0\x89\x94" // U+F0254 +#define ICON_MDI_FOLDER_MULTIPLE_OUTLINE "\xf3\xb0\x89\x95" // U+F0255 +#define ICON_MDI_FOLDER_MULTIPLE_PLUS "\xf3\xb1\x91\xbe" // U+F147E +#define ICON_MDI_FOLDER_MULTIPLE_PLUS_OUTLINE "\xf3\xb1\x91\xbf" // U+F147F +#define ICON_MDI_FOLDER_MUSIC "\xf3\xb1\x8d\x99" // U+F1359 +#define ICON_MDI_FOLDER_MUSIC_OUTLINE "\xf3\xb1\x8d\x9a" // U+F135A +#define ICON_MDI_FOLDER_NETWORK "\xf3\xb0\xa1\xb0" // U+F0870 +#define ICON_MDI_FOLDER_NETWORK_OUTLINE "\xf3\xb0\xb2\x81" // U+F0C81 +#define ICON_MDI_FOLDER_OFF "\xf3\xb1\xa7\xb8" // U+F19F8 +#define ICON_MDI_FOLDER_OFF_OUTLINE "\xf3\xb1\xa7\xb9" // U+F19F9 +#define ICON_MDI_FOLDER_OPEN "\xf3\xb0\x9d\xb0" // U+F0770 +#define ICON_MDI_FOLDER_OPEN_OUTLINE "\xf3\xb0\xb7\x8f" // U+F0DCF +#define ICON_MDI_FOLDER_OUTLINE "\xf3\xb0\x89\x96" // U+F0256 +#define ICON_MDI_FOLDER_PLAY "\xf3\xb1\xa7\xba" // U+F19FA +#define ICON_MDI_FOLDER_PLAY_OUTLINE "\xf3\xb1\xa7\xbb" // U+F19FB +#define ICON_MDI_FOLDER_PLUS "\xf3\xb0\x89\x97" // U+F0257 +#define ICON_MDI_FOLDER_PLUS_OUTLINE "\xf3\xb0\xae\x9d" // U+F0B9D +#define ICON_MDI_FOLDER_POUND "\xf3\xb0\xb4\x89" // U+F0D09 +#define ICON_MDI_FOLDER_POUND_OUTLINE "\xf3\xb0\xb4\x8a" // U+F0D0A +#define ICON_MDI_FOLDER_QUESTION "\xf3\xb1\xa7\x8a" // U+F19CA +#define ICON_MDI_FOLDER_QUESTION_OUTLINE "\xf3\xb1\xa7\x8b" // U+F19CB +#define ICON_MDI_FOLDER_REFRESH "\xf3\xb0\x9d\x89" // U+F0749 +#define ICON_MDI_FOLDER_REFRESH_OUTLINE "\xf3\xb0\x95\x82" // U+F0542 +#define ICON_MDI_FOLDER_REMOVE "\xf3\xb0\x89\x98" // U+F0258 +#define ICON_MDI_FOLDER_REMOVE_OUTLINE "\xf3\xb0\xae\x9e" // U+F0B9E +#define ICON_MDI_FOLDER_SEARCH "\xf3\xb0\xa5\xa8" // U+F0968 +#define ICON_MDI_FOLDER_SEARCH_OUTLINE "\xf3\xb0\xa5\xa9" // U+F0969 +#define ICON_MDI_FOLDER_SETTINGS "\xf3\xb1\x81\xbd" // U+F107D +#define ICON_MDI_FOLDER_SETTINGS_OUTLINE "\xf3\xb1\x81\xbe" // U+F107E +#define ICON_MDI_FOLDER_STAR "\xf3\xb0\x9a\x9d" // U+F069D +#define ICON_MDI_FOLDER_STAR_MULTIPLE "\xf3\xb1\x8f\x93" // U+F13D3 +#define ICON_MDI_FOLDER_STAR_MULTIPLE_OUTLINE "\xf3\xb1\x8f\x94" // U+F13D4 +#define ICON_MDI_FOLDER_STAR_OUTLINE "\xf3\xb0\xae\x9f" // U+F0B9F +#define ICON_MDI_FOLDER_SWAP "\xf3\xb0\xbe\xb6" // U+F0FB6 +#define ICON_MDI_FOLDER_SWAP_OUTLINE "\xf3\xb0\xbe\xb7" // U+F0FB7 +#define ICON_MDI_FOLDER_SYNC "\xf3\xb0\xb4\x8b" // U+F0D0B +#define ICON_MDI_FOLDER_SYNC_OUTLINE "\xf3\xb0\xb4\x8c" // U+F0D0C +#define ICON_MDI_FOLDER_TABLE "\xf3\xb1\x8b\xa3" // U+F12E3 +#define ICON_MDI_FOLDER_TABLE_OUTLINE "\xf3\xb1\x8b\xa4" // U+F12E4 +#define ICON_MDI_FOLDER_TEXT "\xf3\xb0\xb2\x82" // U+F0C82 +#define ICON_MDI_FOLDER_TEXT_OUTLINE "\xf3\xb0\xb2\x83" // U+F0C83 +#define ICON_MDI_FOLDER_UPLOAD "\xf3\xb0\x89\x99" // U+F0259 +#define ICON_MDI_FOLDER_UPLOAD_OUTLINE "\xf3\xb1\x83\xad" // U+F10ED +#define ICON_MDI_FOLDER_WRENCH "\xf3\xb1\xa7\xbc" // U+F19FC +#define ICON_MDI_FOLDER_WRENCH_OUTLINE "\xf3\xb1\xa7\xbd" // U+F19FD +#define ICON_MDI_FOLDER_ZIP "\xf3\xb0\x9b\xab" // U+F06EB +#define ICON_MDI_FOLDER_ZIP_OUTLINE "\xf3\xb0\x9e\xb9" // U+F07B9 +#define ICON_MDI_FONT_AWESOME "\xf3\xb0\x80\xba" // U+F003A +#define ICON_MDI_FOOD "\xf3\xb0\x89\x9a" // U+F025A +#define ICON_MDI_FOOD_APPLE "\xf3\xb0\x89\x9b" // U+F025B +#define ICON_MDI_FOOD_APPLE_OUTLINE "\xf3\xb0\xb2\x84" // U+F0C84 +#define ICON_MDI_FOOD_CROISSANT "\xf3\xb0\x9f\x88" // U+F07C8 +#define ICON_MDI_FOOD_DRUMSTICK "\xf3\xb1\x90\x9f" // U+F141F +#define ICON_MDI_FOOD_DRUMSTICK_OFF "\xf3\xb1\x91\xa8" // U+F1468 +#define ICON_MDI_FOOD_DRUMSTICK_OFF_OUTLINE "\xf3\xb1\x91\xa9" // U+F1469 +#define ICON_MDI_FOOD_DRUMSTICK_OUTLINE "\xf3\xb1\x90\xa0" // U+F1420 +#define ICON_MDI_FOOD_FORK_DRINK "\xf3\xb0\x97\xb2" // U+F05F2 +#define ICON_MDI_FOOD_HALAL "\xf3\xb1\x95\xb2" // U+F1572 +#define ICON_MDI_FOOD_HOT_DOG "\xf3\xb1\xa1\x8b" // U+F184B +#define ICON_MDI_FOOD_KOSHER "\xf3\xb1\x95\xb3" // U+F1573 +#define ICON_MDI_FOOD_OFF "\xf3\xb0\x97\xb3" // U+F05F3 +#define ICON_MDI_FOOD_OFF_OUTLINE "\xf3\xb1\xa4\x95" // U+F1915 +#define ICON_MDI_FOOD_OUTLINE "\xf3\xb1\xa4\x96" // U+F1916 +#define ICON_MDI_FOOD_STEAK "\xf3\xb1\x91\xaa" // U+F146A +#define ICON_MDI_FOOD_STEAK_OFF "\xf3\xb1\x91\xab" // U+F146B +#define ICON_MDI_FOOD_TAKEOUT_BOX "\xf3\xb1\xa0\xb6" // U+F1836 +#define ICON_MDI_FOOD_TAKEOUT_BOX_OUTLINE "\xf3\xb1\xa0\xb7" // U+F1837 +#define ICON_MDI_FOOD_TURKEY "\xf3\xb1\x9c\x9c" // U+F171C +#define ICON_MDI_FOOD_VARIANT "\xf3\xb0\x89\x9c" // U+F025C +#define ICON_MDI_FOOD_VARIANT_OFF "\xf3\xb1\x8f\xa5" // U+F13E5 +#define ICON_MDI_FOOT_PRINT "\xf3\xb0\xbd\x92" // U+F0F52 +#define ICON_MDI_FOOTBALL "\xf3\xb0\x89\x9d" // U+F025D +#define ICON_MDI_FOOTBALL_AUSTRALIAN "\xf3\xb0\x89\x9e" // U+F025E +#define ICON_MDI_FOOTBALL_HELMET "\xf3\xb0\x89\x9f" // U+F025F +#define ICON_MDI_FOREST "\xf3\xb1\xa2\x97" // U+F1897 +#define ICON_MDI_FOREST_OUTLINE "\xf3\xb1\xb1\xa3" // U+F1C63 +#define ICON_MDI_FORKLIFT "\xf3\xb0\x9f\x89" // U+F07C9 +#define ICON_MDI_FORM_DROPDOWN "\xf3\xb1\x90\x80" // U+F1400 +#define ICON_MDI_FORM_SELECT "\xf3\xb1\x90\x81" // U+F1401 +#define ICON_MDI_FORM_TEXTAREA "\xf3\xb1\x82\x95" // U+F1095 +#define ICON_MDI_FORM_TEXTBOX "\xf3\xb0\x98\x8e" // U+F060E +#define ICON_MDI_FORM_TEXTBOX_LOCK "\xf3\xb1\x8d\x9d" // U+F135D +#define ICON_MDI_FORM_TEXTBOX_PASSWORD "\xf3\xb0\x9f\xb5" // U+F07F5 +#define ICON_MDI_FORMAT_ALIGN_BOTTOM "\xf3\xb0\x9d\x93" // U+F0753 +#define ICON_MDI_FORMAT_ALIGN_CENTER "\xf3\xb0\x89\xa0" // U+F0260 +#define ICON_MDI_FORMAT_ALIGN_JUSTIFY "\xf3\xb0\x89\xa1" // U+F0261 +#define ICON_MDI_FORMAT_ALIGN_LEFT "\xf3\xb0\x89\xa2" // U+F0262 +#define ICON_MDI_FORMAT_ALIGN_MIDDLE "\xf3\xb0\x9d\x94" // U+F0754 +#define ICON_MDI_FORMAT_ALIGN_RIGHT "\xf3\xb0\x89\xa3" // U+F0263 +#define ICON_MDI_FORMAT_ALIGN_TOP "\xf3\xb0\x9d\x95" // U+F0755 +#define ICON_MDI_FORMAT_ANNOTATION_MINUS "\xf3\xb0\xaa\xbc" // U+F0ABC +#define ICON_MDI_FORMAT_ANNOTATION_PLUS "\xf3\xb0\x99\x86" // U+F0646 +#define ICON_MDI_FORMAT_BOLD "\xf3\xb0\x89\xa4" // U+F0264 +#define ICON_MDI_FORMAT_CLEAR "\xf3\xb0\x89\xa5" // U+F0265 +#define ICON_MDI_FORMAT_COLOR_FILL "\xf3\xb0\x89\xa6" // U+F0266 +#define ICON_MDI_FORMAT_COLOR_HIGHLIGHT "\xf3\xb0\xb8\xb1" // U+F0E31 +#define ICON_MDI_FORMAT_COLOR_MARKER_CANCEL "\xf3\xb1\x8c\x93" // U+F1313 +#define ICON_MDI_FORMAT_COLOR_TEXT "\xf3\xb0\x9a\x9e" // U+F069E +#define ICON_MDI_FORMAT_COLUMNS "\xf3\xb0\xa3\x9f" // U+F08DF +#define ICON_MDI_FORMAT_FLOAT_CENTER "\xf3\xb0\x89\xa7" // U+F0267 +#define ICON_MDI_FORMAT_FLOAT_LEFT "\xf3\xb0\x89\xa8" // U+F0268 +#define ICON_MDI_FORMAT_FLOAT_NONE "\xf3\xb0\x89\xa9" // U+F0269 +#define ICON_MDI_FORMAT_FLOAT_RIGHT "\xf3\xb0\x89\xaa" // U+F026A +#define ICON_MDI_FORMAT_FONT "\xf3\xb0\x9b\x96" // U+F06D6 +#define ICON_MDI_FORMAT_FONT_SIZE_DECREASE "\xf3\xb0\xa7\xb3" // U+F09F3 +#define ICON_MDI_FORMAT_FONT_SIZE_INCREASE "\xf3\xb0\xa7\xb4" // U+F09F4 +#define ICON_MDI_FORMAT_HEADER_1 "\xf3\xb0\x89\xab" // U+F026B +#define ICON_MDI_FORMAT_HEADER_2 "\xf3\xb0\x89\xac" // U+F026C +#define ICON_MDI_FORMAT_HEADER_3 "\xf3\xb0\x89\xad" // U+F026D +#define ICON_MDI_FORMAT_HEADER_4 "\xf3\xb0\x89\xae" // U+F026E +#define ICON_MDI_FORMAT_HEADER_5 "\xf3\xb0\x89\xaf" // U+F026F +#define ICON_MDI_FORMAT_HEADER_6 "\xf3\xb0\x89\xb0" // U+F0270 +#define ICON_MDI_FORMAT_HEADER_DECREASE "\xf3\xb0\x89\xb1" // U+F0271 +#define ICON_MDI_FORMAT_HEADER_EQUAL "\xf3\xb0\x89\xb2" // U+F0272 +#define ICON_MDI_FORMAT_HEADER_INCREASE "\xf3\xb0\x89\xb3" // U+F0273 +#define ICON_MDI_FORMAT_HEADER_POUND "\xf3\xb0\x89\xb4" // U+F0274 +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_CENTER "\xf3\xb0\x98\x9e" // U+F061E +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_LEFT "\xf3\xb0\x98\x9f" // U+F061F +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_RIGHT "\xf3\xb0\x98\xa0" // U+F0620 +#define ICON_MDI_FORMAT_INDENT_DECREASE "\xf3\xb0\x89\xb5" // U+F0275 +#define ICON_MDI_FORMAT_INDENT_INCREASE "\xf3\xb0\x89\xb6" // U+F0276 +#define ICON_MDI_FORMAT_ITALIC "\xf3\xb0\x89\xb7" // U+F0277 +#define ICON_MDI_FORMAT_LETTER_CASE "\xf3\xb0\xac\xb4" // U+F0B34 +#define ICON_MDI_FORMAT_LETTER_CASE_LOWER "\xf3\xb0\xac\xb5" // U+F0B35 +#define ICON_MDI_FORMAT_LETTER_CASE_UPPER "\xf3\xb0\xac\xb6" // U+F0B36 +#define ICON_MDI_FORMAT_LETTER_ENDS_WITH "\xf3\xb0\xbe\xb8" // U+F0FB8 +#define ICON_MDI_FORMAT_LETTER_MATCHES "\xf3\xb0\xbe\xb9" // U+F0FB9 +#define ICON_MDI_FORMAT_LETTER_SPACING "\xf3\xb1\xa5\x96" // U+F1956 +#define ICON_MDI_FORMAT_LETTER_SPACING_VARIANT "\xf3\xb1\xab\xbb" // U+F1AFB +#define ICON_MDI_FORMAT_LETTER_STARTS_WITH "\xf3\xb0\xbe\xba" // U+F0FBA +#define ICON_MDI_FORMAT_LINE_HEIGHT "\xf3\xb1\xab\xbc" // U+F1AFC +#define ICON_MDI_FORMAT_LINE_SPACING "\xf3\xb0\x89\xb8" // U+F0278 +#define ICON_MDI_FORMAT_LINE_STYLE "\xf3\xb0\x97\x88" // U+F05C8 +#define ICON_MDI_FORMAT_LINE_WEIGHT "\xf3\xb0\x97\x89" // U+F05C9 +#define ICON_MDI_FORMAT_LIST_BULLETED "\xf3\xb0\x89\xb9" // U+F0279 +#define ICON_MDI_FORMAT_LIST_BULLETED_SQUARE "\xf3\xb0\xb7\x90" // U+F0DD0 +#define ICON_MDI_FORMAT_LIST_BULLETED_TRIANGLE "\xf3\xb0\xba\xb2" // U+F0EB2 +#define ICON_MDI_FORMAT_LIST_BULLETED_TYPE "\xf3\xb0\x89\xba" // U+F027A +#define ICON_MDI_FORMAT_LIST_CHECKBOX "\xf3\xb0\xa5\xaa" // U+F096A +#define ICON_MDI_FORMAT_LIST_CHECKS "\xf3\xb0\x9d\x96" // U+F0756 +#define ICON_MDI_FORMAT_LIST_GROUP "\xf3\xb1\xa1\xa0" // U+F1860 +#define ICON_MDI_FORMAT_LIST_GROUP_PLUS "\xf3\xb1\xad\x96" // U+F1B56 +#define ICON_MDI_FORMAT_LIST_NUMBERED "\xf3\xb0\x89\xbb" // U+F027B +#define ICON_MDI_FORMAT_LIST_NUMBERED_RTL "\xf3\xb0\xb4\x8d" // U+F0D0D +#define ICON_MDI_FORMAT_LIST_TEXT "\xf3\xb1\x89\xaf" // U+F126F +#define ICON_MDI_FORMAT_OVERLINE "\xf3\xb0\xba\xb3" // U+F0EB3 +#define ICON_MDI_FORMAT_PAGE_BREAK "\xf3\xb0\x9b\x97" // U+F06D7 +#define ICON_MDI_FORMAT_PAGE_SPLIT "\xf3\xb1\xa4\x97" // U+F1917 +#define ICON_MDI_FORMAT_PAINT "\xf3\xb0\x89\xbc" // U+F027C +#define ICON_MDI_FORMAT_PARAGRAPH "\xf3\xb0\x89\xbd" // U+F027D +#define ICON_MDI_FORMAT_PARAGRAPH_SPACING "\xf3\xb1\xab\xbd" // U+F1AFD +#define ICON_MDI_FORMAT_PILCROW "\xf3\xb0\x9b\x98" // U+F06D8 +#define ICON_MDI_FORMAT_PILCROW_ARROW_LEFT "\xf3\xb0\x8a\x86" // U+F0286 +#define ICON_MDI_FORMAT_PILCROW_ARROW_RIGHT "\xf3\xb0\x8a\x85" // U+F0285 +#define ICON_MDI_FORMAT_QUOTE_CLOSE "\xf3\xb0\x89\xbe" // U+F027E +#define ICON_MDI_FORMAT_QUOTE_CLOSE_OUTLINE "\xf3\xb1\x86\xa8" // U+F11A8 +#define ICON_MDI_FORMAT_QUOTE_OPEN "\xf3\xb0\x9d\x97" // U+F0757 +#define ICON_MDI_FORMAT_QUOTE_OPEN_OUTLINE "\xf3\xb1\x86\xa7" // U+F11A7 +#define ICON_MDI_FORMAT_ROTATE_90 "\xf3\xb0\x9a\xaa" // U+F06AA +#define ICON_MDI_FORMAT_SECTION "\xf3\xb0\x9a\x9f" // U+F069F +#define ICON_MDI_FORMAT_SIZE "\xf3\xb0\x89\xbf" // U+F027F +#define ICON_MDI_FORMAT_STRIKETHROUGH "\xf3\xb0\x8a\x80" // U+F0280 +#define ICON_MDI_FORMAT_STRIKETHROUGH_VARIANT "\xf3\xb0\x8a\x81" // U+F0281 +#define ICON_MDI_FORMAT_SUBSCRIPT "\xf3\xb0\x8a\x82" // U+F0282 +#define ICON_MDI_FORMAT_SUPERSCRIPT "\xf3\xb0\x8a\x83" // U+F0283 +#define ICON_MDI_FORMAT_TEXT "\xf3\xb0\x8a\x84" // U+F0284 +#define ICON_MDI_FORMAT_TEXT_ROTATION_ANGLE_DOWN "\xf3\xb0\xbe\xbb" // U+F0FBB +#define ICON_MDI_FORMAT_TEXT_ROTATION_ANGLE_UP "\xf3\xb0\xbe\xbc" // U+F0FBC +#define ICON_MDI_FORMAT_TEXT_ROTATION_DOWN "\xf3\xb0\xb5\xb3" // U+F0D73 +#define ICON_MDI_FORMAT_TEXT_ROTATION_DOWN_VERTICAL "\xf3\xb0\xbe\xbd" // U+F0FBD +#define ICON_MDI_FORMAT_TEXT_ROTATION_NONE "\xf3\xb0\xb5\xb4" // U+F0D74 +#define ICON_MDI_FORMAT_TEXT_ROTATION_UP "\xf3\xb0\xbe\xbe" // U+F0FBE +#define ICON_MDI_FORMAT_TEXT_ROTATION_VERTICAL "\xf3\xb0\xbe\xbf" // U+F0FBF +#define ICON_MDI_FORMAT_TEXT_VARIANT "\xf3\xb0\xb8\xb2" // U+F0E32 +#define ICON_MDI_FORMAT_TEXT_VARIANT_OUTLINE "\xf3\xb1\x94\x8f" // U+F150F +#define ICON_MDI_FORMAT_TEXT_WRAPPING_CLIP "\xf3\xb0\xb4\x8e" // U+F0D0E +#define ICON_MDI_FORMAT_TEXT_WRAPPING_OVERFLOW "\xf3\xb0\xb4\x8f" // U+F0D0F +#define ICON_MDI_FORMAT_TEXT_WRAPPING_WRAP "\xf3\xb0\xb4\x90" // U+F0D10 +#define ICON_MDI_FORMAT_TEXTBOX "\xf3\xb0\xb4\x91" // U+F0D11 +#define ICON_MDI_FORMAT_TITLE "\xf3\xb0\x97\xb4" // U+F05F4 +#define ICON_MDI_FORMAT_UNDERLINE "\xf3\xb0\x8a\x87" // U+F0287 +#define ICON_MDI_FORMAT_UNDERLINE_WAVY "\xf3\xb1\xa3\xa9" // U+F18E9 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_BOTTOM "\xf3\xb0\x98\xa1" // U+F0621 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_CENTER "\xf3\xb0\x98\xa2" // U+F0622 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_TOP "\xf3\xb0\x98\xa3" // U+F0623 +#define ICON_MDI_FORMAT_WRAP_INLINE "\xf3\xb0\x8a\x88" // U+F0288 +#define ICON_MDI_FORMAT_WRAP_SQUARE "\xf3\xb0\x8a\x89" // U+F0289 +#define ICON_MDI_FORMAT_WRAP_TIGHT "\xf3\xb0\x8a\x8a" // U+F028A +#define ICON_MDI_FORMAT_WRAP_TOP_BOTTOM "\xf3\xb0\x8a\x8b" // U+F028B +#define ICON_MDI_FORUM "\xf3\xb0\x8a\x8c" // U+F028C +#define ICON_MDI_FORUM_MINUS "\xf3\xb1\xaa\xa9" // U+F1AA9 +#define ICON_MDI_FORUM_MINUS_OUTLINE "\xf3\xb1\xaa\xaa" // U+F1AAA +#define ICON_MDI_FORUM_OUTLINE "\xf3\xb0\xa0\xa2" // U+F0822 +#define ICON_MDI_FORUM_PLUS "\xf3\xb1\xaa\xab" // U+F1AAB +#define ICON_MDI_FORUM_PLUS_OUTLINE "\xf3\xb1\xaa\xac" // U+F1AAC +#define ICON_MDI_FORUM_REMOVE "\xf3\xb1\xaa\xad" // U+F1AAD +#define ICON_MDI_FORUM_REMOVE_OUTLINE "\xf3\xb1\xaa\xae" // U+F1AAE +#define ICON_MDI_FORWARD "\xf3\xb0\x8a\x8d" // U+F028D +#define ICON_MDI_FORWARDBURGER "\xf3\xb0\xb5\xb5" // U+F0D75 +#define ICON_MDI_FOUNTAIN "\xf3\xb0\xa5\xab" // U+F096B +#define ICON_MDI_FOUNTAIN_PEN "\xf3\xb0\xb4\x92" // U+F0D12 +#define ICON_MDI_FOUNTAIN_PEN_TIP "\xf3\xb0\xb4\x93" // U+F0D13 +#define ICON_MDI_FRACTION_ONE_HALF "\xf3\xb1\xa6\x92" // U+F1992 +#define ICON_MDI_FREEBSD "\xf3\xb0\xa3\xa0" // U+F08E0 +#define ICON_MDI_FRENCH_FRIES "\xf3\xb1\xa5\x97" // U+F1957 +#define ICON_MDI_FREQUENTLY_ASKED_QUESTIONS "\xf3\xb0\xba\xb4" // U+F0EB4 +#define ICON_MDI_FRIDGE "\xf3\xb0\x8a\x90" // U+F0290 +#define ICON_MDI_FRIDGE_ALERT "\xf3\xb1\x86\xb1" // U+F11B1 +#define ICON_MDI_FRIDGE_ALERT_OUTLINE "\xf3\xb1\x86\xb2" // U+F11B2 +#define ICON_MDI_FRIDGE_BOTTOM "\xf3\xb0\x8a\x92" // U+F0292 +#define ICON_MDI_FRIDGE_INDUSTRIAL "\xf3\xb1\x97\xae" // U+F15EE +#define ICON_MDI_FRIDGE_INDUSTRIAL_ALERT "\xf3\xb1\x97\xaf" // U+F15EF +#define ICON_MDI_FRIDGE_INDUSTRIAL_ALERT_OUTLINE "\xf3\xb1\x97\xb0" // U+F15F0 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OFF "\xf3\xb1\x97\xb1" // U+F15F1 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OFF_OUTLINE "\xf3\xb1\x97\xb2" // U+F15F2 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OUTLINE "\xf3\xb1\x97\xb3" // U+F15F3 +#define ICON_MDI_FRIDGE_OFF "\xf3\xb1\x86\xaf" // U+F11AF +#define ICON_MDI_FRIDGE_OFF_OUTLINE "\xf3\xb1\x86\xb0" // U+F11B0 +#define ICON_MDI_FRIDGE_OUTLINE "\xf3\xb0\x8a\x8f" // U+F028F +#define ICON_MDI_FRIDGE_TOP "\xf3\xb0\x8a\x91" // U+F0291 +#define ICON_MDI_FRIDGE_VARIANT "\xf3\xb1\x97\xb4" // U+F15F4 +#define ICON_MDI_FRIDGE_VARIANT_ALERT "\xf3\xb1\x97\xb5" // U+F15F5 +#define ICON_MDI_FRIDGE_VARIANT_ALERT_OUTLINE "\xf3\xb1\x97\xb6" // U+F15F6 +#define ICON_MDI_FRIDGE_VARIANT_OFF "\xf3\xb1\x97\xb7" // U+F15F7 +#define ICON_MDI_FRIDGE_VARIANT_OFF_OUTLINE "\xf3\xb1\x97\xb8" // U+F15F8 +#define ICON_MDI_FRIDGE_VARIANT_OUTLINE "\xf3\xb1\x97\xb9" // U+F15F9 +#define ICON_MDI_FRUIT_CHERRIES "\xf3\xb1\x81\x82" // U+F1042 +#define ICON_MDI_FRUIT_CHERRIES_OFF "\xf3\xb1\x8f\xb8" // U+F13F8 +#define ICON_MDI_FRUIT_CITRUS "\xf3\xb1\x81\x83" // U+F1043 +#define ICON_MDI_FRUIT_CITRUS_OFF "\xf3\xb1\x8f\xb9" // U+F13F9 +#define ICON_MDI_FRUIT_GRAPES "\xf3\xb1\x81\x84" // U+F1044 +#define ICON_MDI_FRUIT_GRAPES_OUTLINE "\xf3\xb1\x81\x85" // U+F1045 +#define ICON_MDI_FRUIT_PEAR "\xf3\xb1\xa8\x8e" // U+F1A0E +#define ICON_MDI_FRUIT_PINEAPPLE "\xf3\xb1\x81\x86" // U+F1046 +#define ICON_MDI_FRUIT_WATERMELON "\xf3\xb1\x81\x87" // U+F1047 +#define ICON_MDI_FUEL "\xf3\xb0\x9f\x8a" // U+F07CA +#define ICON_MDI_FUEL_CELL "\xf3\xb1\xa2\xb5" // U+F18B5 +#define ICON_MDI_FULLSCREEN "\xf3\xb0\x8a\x93" // U+F0293 +#define ICON_MDI_FULLSCREEN_EXIT "\xf3\xb0\x8a\x94" // U+F0294 +#define ICON_MDI_FUNCTION "\xf3\xb0\x8a\x95" // U+F0295 +#define ICON_MDI_FUNCTION_VARIANT "\xf3\xb0\xa1\xb1" // U+F0871 +#define ICON_MDI_FURIGANA_HORIZONTAL "\xf3\xb1\x82\x81" // U+F1081 +#define ICON_MDI_FURIGANA_VERTICAL "\xf3\xb1\x82\x82" // U+F1082 +#define ICON_MDI_FUSE "\xf3\xb0\xb2\x85" // U+F0C85 +#define ICON_MDI_FUSE_ALERT "\xf3\xb1\x90\xad" // U+F142D +#define ICON_MDI_FUSE_BLADE "\xf3\xb0\xb2\x86" // U+F0C86 +#define ICON_MDI_FUSE_OFF "\xf3\xb1\x90\xac" // U+F142C +#define ICON_MDI_GAMEPAD "\xf3\xb0\x8a\x96" // U+F0296 +#define ICON_MDI_GAMEPAD_CIRCLE "\xf3\xb0\xb8\xb3" // U+F0E33 +#define ICON_MDI_GAMEPAD_CIRCLE_DOWN "\xf3\xb0\xb8\xb4" // U+F0E34 +#define ICON_MDI_GAMEPAD_CIRCLE_LEFT "\xf3\xb0\xb8\xb5" // U+F0E35 +#define ICON_MDI_GAMEPAD_CIRCLE_OUTLINE "\xf3\xb0\xb8\xb6" // U+F0E36 +#define ICON_MDI_GAMEPAD_CIRCLE_RIGHT "\xf3\xb0\xb8\xb7" // U+F0E37 +#define ICON_MDI_GAMEPAD_CIRCLE_UP "\xf3\xb0\xb8\xb8" // U+F0E38 +#define ICON_MDI_GAMEPAD_DOWN "\xf3\xb0\xb8\xb9" // U+F0E39 +#define ICON_MDI_GAMEPAD_LEFT "\xf3\xb0\xb8\xba" // U+F0E3A +#define ICON_MDI_GAMEPAD_OUTLINE "\xf3\xb1\xa4\x99" // U+F1919 +#define ICON_MDI_GAMEPAD_RIGHT "\xf3\xb0\xb8\xbb" // U+F0E3B +#define ICON_MDI_GAMEPAD_ROUND "\xf3\xb0\xb8\xbc" // U+F0E3C +#define ICON_MDI_GAMEPAD_ROUND_DOWN "\xf3\xb0\xb8\xbd" // U+F0E3D +#define ICON_MDI_GAMEPAD_ROUND_LEFT "\xf3\xb0\xb8\xbe" // U+F0E3E +#define ICON_MDI_GAMEPAD_ROUND_OUTLINE "\xf3\xb0\xb8\xbf" // U+F0E3F +#define ICON_MDI_GAMEPAD_ROUND_RIGHT "\xf3\xb0\xb9\x80" // U+F0E40 +#define ICON_MDI_GAMEPAD_ROUND_UP "\xf3\xb0\xb9\x81" // U+F0E41 +#define ICON_MDI_GAMEPAD_SQUARE "\xf3\xb0\xba\xb5" // U+F0EB5 +#define ICON_MDI_GAMEPAD_SQUARE_OUTLINE "\xf3\xb0\xba\xb6" // U+F0EB6 +#define ICON_MDI_GAMEPAD_UP "\xf3\xb0\xb9\x82" // U+F0E42 +#define ICON_MDI_GAMEPAD_VARIANT "\xf3\xb0\x8a\x97" // U+F0297 +#define ICON_MDI_GAMEPAD_VARIANT_OUTLINE "\xf3\xb0\xba\xb7" // U+F0EB7 +#define ICON_MDI_GAMMA "\xf3\xb1\x83\xae" // U+F10EE +#define ICON_MDI_GANTRY_CRANE "\xf3\xb0\xb7\x91" // U+F0DD1 +#define ICON_MDI_GARAGE "\xf3\xb0\x9b\x99" // U+F06D9 +#define ICON_MDI_GARAGE_ALERT "\xf3\xb0\xa1\xb2" // U+F0872 +#define ICON_MDI_GARAGE_ALERT_VARIANT "\xf3\xb1\x8b\x95" // U+F12D5 +#define ICON_MDI_GARAGE_LOCK "\xf3\xb1\x9f\xbb" // U+F17FB +#define ICON_MDI_GARAGE_OPEN "\xf3\xb0\x9b\x9a" // U+F06DA +#define ICON_MDI_GARAGE_OPEN_VARIANT "\xf3\xb1\x8b\x94" // U+F12D4 +#define ICON_MDI_GARAGE_VARIANT "\xf3\xb1\x8b\x93" // U+F12D3 +#define ICON_MDI_GARAGE_VARIANT_LOCK "\xf3\xb1\x9f\xbc" // U+F17FC +#define ICON_MDI_GAS_BURNER "\xf3\xb1\xa8\x9b" // U+F1A1B +#define ICON_MDI_GAS_CYLINDER "\xf3\xb0\x99\x87" // U+F0647 +#define ICON_MDI_GAS_STATION "\xf3\xb0\x8a\x98" // U+F0298 +#define ICON_MDI_GAS_STATION_IN_USE "\xf3\xb1\xb3\x84" // U+F1CC4 +#define ICON_MDI_GAS_STATION_IN_USE_OUTLINE "\xf3\xb1\xb3\x85" // U+F1CC5 +#define ICON_MDI_GAS_STATION_OFF "\xf3\xb1\x90\x89" // U+F1409 +#define ICON_MDI_GAS_STATION_OFF_OUTLINE "\xf3\xb1\x90\x8a" // U+F140A +#define ICON_MDI_GAS_STATION_OUTLINE "\xf3\xb0\xba\xb8" // U+F0EB8 +#define ICON_MDI_GATE "\xf3\xb0\x8a\x99" // U+F0299 +#define ICON_MDI_GATE_ALERT "\xf3\xb1\x9f\xb8" // U+F17F8 +#define ICON_MDI_GATE_AND "\xf3\xb0\xa3\xa1" // U+F08E1 +#define ICON_MDI_GATE_ARROW_LEFT "\xf3\xb1\x9f\xb7" // U+F17F7 +#define ICON_MDI_GATE_ARROW_RIGHT "\xf3\xb1\x85\xa9" // U+F1169 +#define ICON_MDI_GATE_BUFFER "\xf3\xb1\xab\xbe" // U+F1AFE +#define ICON_MDI_GATE_NAND "\xf3\xb0\xa3\xa2" // U+F08E2 +#define ICON_MDI_GATE_NOR "\xf3\xb0\xa3\xa3" // U+F08E3 +#define ICON_MDI_GATE_NOT "\xf3\xb0\xa3\xa4" // U+F08E4 +#define ICON_MDI_GATE_OPEN "\xf3\xb1\x85\xaa" // U+F116A +#define ICON_MDI_GATE_OR "\xf3\xb0\xa3\xa5" // U+F08E5 +#define ICON_MDI_GATE_XNOR "\xf3\xb0\xa3\xa6" // U+F08E6 +#define ICON_MDI_GATE_XOR "\xf3\xb0\xa3\xa7" // U+F08E7 +#define ICON_MDI_GATSBY "\xf3\xb0\xb9\x83" // U+F0E43 +#define ICON_MDI_GAUGE "\xf3\xb0\x8a\x9a" // U+F029A +#define ICON_MDI_GAUGE_EMPTY "\xf3\xb0\xa1\xb3" // U+F0873 +#define ICON_MDI_GAUGE_FULL "\xf3\xb0\xa1\xb4" // U+F0874 +#define ICON_MDI_GAUGE_LOW "\xf3\xb0\xa1\xb5" // U+F0875 +#define ICON_MDI_GAVEL "\xf3\xb0\x8a\x9b" // U+F029B +#define ICON_MDI_GENDER_FEMALE "\xf3\xb0\x8a\x9c" // U+F029C +#define ICON_MDI_GENDER_MALE "\xf3\xb0\x8a\x9d" // U+F029D +#define ICON_MDI_GENDER_MALE_FEMALE "\xf3\xb0\x8a\x9e" // U+F029E +#define ICON_MDI_GENDER_MALE_FEMALE_VARIANT "\xf3\xb1\x84\xbf" // U+F113F +#define ICON_MDI_GENDER_NON_BINARY "\xf3\xb1\x85\x80" // U+F1140 +#define ICON_MDI_GENDER_TRANSGENDER "\xf3\xb0\x8a\x9f" // U+F029F +#define ICON_MDI_GENERATOR_MOBILE "\xf3\xb1\xb2\x8a" // U+F1C8A +#define ICON_MDI_GENERATOR_PORTABLE "\xf3\xb1\xb2\x8b" // U+F1C8B +#define ICON_MDI_GENERATOR_STATIONARY "\xf3\xb1\xb2\x8c" // U+F1C8C +#define ICON_MDI_GENTOO "\xf3\xb0\xa3\xa8" // U+F08E8 +#define ICON_MDI_GESTURE "\xf3\xb0\x9f\x8b" // U+F07CB +#define ICON_MDI_GESTURE_DOUBLE_TAP "\xf3\xb0\x9c\xbc" // U+F073C +#define ICON_MDI_GESTURE_PINCH "\xf3\xb0\xaa\xbd" // U+F0ABD +#define ICON_MDI_GESTURE_SPREAD "\xf3\xb0\xaa\xbe" // U+F0ABE +#define ICON_MDI_GESTURE_SWIPE "\xf3\xb0\xb5\xb6" // U+F0D76 +#define ICON_MDI_GESTURE_SWIPE_DOWN "\xf3\xb0\x9c\xbd" // U+F073D +#define ICON_MDI_GESTURE_SWIPE_HORIZONTAL "\xf3\xb0\xaa\xbf" // U+F0ABF +#define ICON_MDI_GESTURE_SWIPE_LEFT "\xf3\xb0\x9c\xbe" // U+F073E +#define ICON_MDI_GESTURE_SWIPE_RIGHT "\xf3\xb0\x9c\xbf" // U+F073F +#define ICON_MDI_GESTURE_SWIPE_UP "\xf3\xb0\x9d\x80" // U+F0740 +#define ICON_MDI_GESTURE_SWIPE_VERTICAL "\xf3\xb0\xab\x80" // U+F0AC0 +#define ICON_MDI_GESTURE_TAP "\xf3\xb0\x9d\x81" // U+F0741 +#define ICON_MDI_GESTURE_TAP_BOX "\xf3\xb1\x8a\xa9" // U+F12A9 +#define ICON_MDI_GESTURE_TAP_BUTTON "\xf3\xb1\x8a\xa8" // U+F12A8 +#define ICON_MDI_GESTURE_TAP_HOLD "\xf3\xb0\xb5\xb7" // U+F0D77 +#define ICON_MDI_GESTURE_TWO_DOUBLE_TAP "\xf3\xb0\x9d\x82" // U+F0742 +#define ICON_MDI_GESTURE_TWO_TAP "\xf3\xb0\x9d\x83" // U+F0743 +#define ICON_MDI_GHOST "\xf3\xb0\x8a\xa0" // U+F02A0 +#define ICON_MDI_GHOST_OFF "\xf3\xb0\xa7\xb5" // U+F09F5 +#define ICON_MDI_GHOST_OFF_OUTLINE "\xf3\xb1\x99\x9c" // U+F165C +#define ICON_MDI_GHOST_OUTLINE "\xf3\xb1\x99\x9d" // U+F165D +#define ICON_MDI_GIFT "\xf3\xb0\xb9\x84" // U+F0E44 +#define ICON_MDI_GIFT_OFF "\xf3\xb1\x9b\xaf" // U+F16EF +#define ICON_MDI_GIFT_OFF_OUTLINE "\xf3\xb1\x9b\xb0" // U+F16F0 +#define ICON_MDI_GIFT_OPEN "\xf3\xb1\x9b\xb1" // U+F16F1 +#define ICON_MDI_GIFT_OPEN_OUTLINE "\xf3\xb1\x9b\xb2" // U+F16F2 +#define ICON_MDI_GIFT_OUTLINE "\xf3\xb0\x8a\xa1" // U+F02A1 +#define ICON_MDI_GIT "\xf3\xb0\x8a\xa2" // U+F02A2 +#define ICON_MDI_GITHUB "\xf3\xb0\x8a\xa4" // U+F02A4 +#define ICON_MDI_GITLAB "\xf3\xb0\xae\xa0" // U+F0BA0 +#define ICON_MDI_GLASS_COCKTAIL "\xf3\xb0\x8d\x96" // U+F0356 +#define ICON_MDI_GLASS_COCKTAIL_OFF "\xf3\xb1\x97\xa6" // U+F15E6 +#define ICON_MDI_GLASS_FLUTE "\xf3\xb0\x8a\xa5" // U+F02A5 +#define ICON_MDI_GLASS_FRAGILE "\xf3\xb1\xa1\xb3" // U+F1873 +#define ICON_MDI_GLASS_MUG "\xf3\xb0\x8a\xa6" // U+F02A6 +#define ICON_MDI_GLASS_MUG_OFF "\xf3\xb1\x97\xa7" // U+F15E7 +#define ICON_MDI_GLASS_MUG_VARIANT "\xf3\xb1\x84\x96" // U+F1116 +#define ICON_MDI_GLASS_MUG_VARIANT_OFF "\xf3\xb1\x97\xa8" // U+F15E8 +#define ICON_MDI_GLASS_PINT_OUTLINE "\xf3\xb1\x8c\x8d" // U+F130D +#define ICON_MDI_GLASS_STANGE "\xf3\xb0\x8a\xa7" // U+F02A7 +#define ICON_MDI_GLASS_TULIP "\xf3\xb0\x8a\xa8" // U+F02A8 +#define ICON_MDI_GLASS_WINE "\xf3\xb0\xa1\xb6" // U+F0876 +#define ICON_MDI_GLASSES "\xf3\xb0\x8a\xaa" // U+F02AA +#define ICON_MDI_GLOBE_LIGHT "\xf3\xb0\x99\xaf" // U+F066F +#define ICON_MDI_GLOBE_LIGHT_OUTLINE "\xf3\xb1\x8b\x97" // U+F12D7 +#define ICON_MDI_GLOBE_MODEL "\xf3\xb0\xa3\xa9" // U+F08E9 +#define ICON_MDI_GMAIL "\xf3\xb0\x8a\xab" // U+F02AB +#define ICON_MDI_GNOME "\xf3\xb0\x8a\xac" // U+F02AC +#define ICON_MDI_GO_KART "\xf3\xb0\xb5\xb9" // U+F0D79 +#define ICON_MDI_GO_KART_TRACK "\xf3\xb0\xb5\xba" // U+F0D7A +#define ICON_MDI_GOG "\xf3\xb0\xae\xa1" // U+F0BA1 +#define ICON_MDI_GOLD "\xf3\xb1\x89\x8f" // U+F124F +#define ICON_MDI_GOLF "\xf3\xb0\xa0\xa3" // U+F0823 +#define ICON_MDI_GOLF_CART "\xf3\xb1\x86\xa4" // U+F11A4 +#define ICON_MDI_GOLF_TEE "\xf3\xb1\x82\x83" // U+F1083 +#define ICON_MDI_GONDOLA "\xf3\xb0\x9a\x86" // U+F0686 +#define ICON_MDI_GOODREADS "\xf3\xb0\xb5\xbb" // U+F0D7B +#define ICON_MDI_GOOGLE "\xf3\xb0\x8a\xad" // U+F02AD +#define ICON_MDI_GOOGLE_ADS "\xf3\xb0\xb2\x87" // U+F0C87 +#define ICON_MDI_GOOGLE_ANALYTICS "\xf3\xb0\x9f\x8c" // U+F07CC +#define ICON_MDI_GOOGLE_ASSISTANT "\xf3\xb0\x9f\x8d" // U+F07CD +#define ICON_MDI_GOOGLE_CARDBOARD "\xf3\xb0\x8a\xae" // U+F02AE +#define ICON_MDI_GOOGLE_CHROME "\xf3\xb0\x8a\xaf" // U+F02AF +#define ICON_MDI_GOOGLE_CIRCLES "\xf3\xb0\x8a\xb0" // U+F02B0 +#define ICON_MDI_GOOGLE_CIRCLES_COMMUNITIES "\xf3\xb0\x8a\xb1" // U+F02B1 +#define ICON_MDI_GOOGLE_CIRCLES_EXTENDED "\xf3\xb0\x8a\xb2" // U+F02B2 +#define ICON_MDI_GOOGLE_CIRCLES_GROUP "\xf3\xb0\x8a\xb3" // U+F02B3 +#define ICON_MDI_GOOGLE_CLASSROOM "\xf3\xb0\x8b\x80" // U+F02C0 +#define ICON_MDI_GOOGLE_CLOUD "\xf3\xb1\x87\xb6" // U+F11F6 +#define ICON_MDI_GOOGLE_DOWNASAUR "\xf3\xb1\x8d\xa2" // U+F1362 +#define ICON_MDI_GOOGLE_DRIVE "\xf3\xb0\x8a\xb6" // U+F02B6 +#define ICON_MDI_GOOGLE_EARTH "\xf3\xb0\x8a\xb7" // U+F02B7 +#define ICON_MDI_GOOGLE_FIT "\xf3\xb0\xa5\xac" // U+F096C +#define ICON_MDI_GOOGLE_GLASS "\xf3\xb0\x8a\xb8" // U+F02B8 +#define ICON_MDI_GOOGLE_HANGOUTS "\xf3\xb0\x8b\x89" // U+F02C9 +#define ICON_MDI_GOOGLE_KEEP "\xf3\xb0\x9b\x9c" // U+F06DC +#define ICON_MDI_GOOGLE_LENS "\xf3\xb0\xa7\xb6" // U+F09F6 +#define ICON_MDI_GOOGLE_MAPS "\xf3\xb0\x97\xb5" // U+F05F5 +#define ICON_MDI_GOOGLE_MY_BUSINESS "\xf3\xb1\x81\x88" // U+F1048 +#define ICON_MDI_GOOGLE_NEARBY "\xf3\xb0\x8a\xb9" // U+F02B9 +#define ICON_MDI_GOOGLE_PLAY "\xf3\xb0\x8a\xbc" // U+F02BC +#define ICON_MDI_GOOGLE_PLUS "\xf3\xb0\x8a\xbd" // U+F02BD +#define ICON_MDI_GOOGLE_PODCAST "\xf3\xb0\xba\xb9" // U+F0EB9 +#define ICON_MDI_GOOGLE_SPREADSHEET "\xf3\xb0\xa7\xb7" // U+F09F7 +#define ICON_MDI_GOOGLE_STREET_VIEW "\xf3\xb0\xb2\x88" // U+F0C88 +#define ICON_MDI_GOOGLE_TRANSLATE "\xf3\xb0\x8a\xbf" // U+F02BF +#define ICON_MDI_GRADIENT_HORIZONTAL "\xf3\xb1\x9d\x8a" // U+F174A +#define ICON_MDI_GRADIENT_VERTICAL "\xf3\xb0\x9a\xa0" // U+F06A0 +#define ICON_MDI_GRAIN "\xf3\xb0\xb5\xbc" // U+F0D7C +#define ICON_MDI_GRAPH "\xf3\xb1\x81\x89" // U+F1049 +#define ICON_MDI_GRAPH_OUTLINE "\xf3\xb1\x81\x8a" // U+F104A +#define ICON_MDI_GRAPHQL "\xf3\xb0\xa1\xb7" // U+F0877 +#define ICON_MDI_GRASS "\xf3\xb1\x94\x90" // U+F1510 +#define ICON_MDI_GRAVE_STONE "\xf3\xb0\xae\xa2" // U+F0BA2 +#define ICON_MDI_GREASE_PENCIL "\xf3\xb0\x99\x88" // U+F0648 +#define ICON_MDI_GREATER_THAN "\xf3\xb0\xa5\xad" // U+F096D +#define ICON_MDI_GREATER_THAN_OR_EQUAL "\xf3\xb0\xa5\xae" // U+F096E +#define ICON_MDI_GREENHOUSE "\xf3\xb0\x80\xad" // U+F002D +#define ICON_MDI_GRID "\xf3\xb0\x8b\x81" // U+F02C1 +#define ICON_MDI_GRID_LARGE "\xf3\xb0\x9d\x98" // U+F0758 +#define ICON_MDI_GRID_OFF "\xf3\xb0\x8b\x82" // U+F02C2 +#define ICON_MDI_GRILL "\xf3\xb0\xb9\x85" // U+F0E45 +#define ICON_MDI_GRILL_OUTLINE "\xf3\xb1\x86\x8a" // U+F118A +#define ICON_MDI_GROUP "\xf3\xb0\x8b\x83" // U+F02C3 +#define ICON_MDI_GUITAR_ACOUSTIC "\xf3\xb0\x9d\xb1" // U+F0771 +#define ICON_MDI_GUITAR_ELECTRIC "\xf3\xb0\x8b\x84" // U+F02C4 +#define ICON_MDI_GUITAR_PICK "\xf3\xb0\x8b\x85" // U+F02C5 +#define ICON_MDI_GUITAR_PICK_OUTLINE "\xf3\xb0\x8b\x86" // U+F02C6 +#define ICON_MDI_GUY_FAWKES_MASK "\xf3\xb0\xa0\xa5" // U+F0825 +#define ICON_MDI_GYMNASTICS "\xf3\xb1\xa9\x81" // U+F1A41 +#define ICON_MDI_HAIL "\xf3\xb0\xab\x81" // U+F0AC1 +#define ICON_MDI_HAIR_DRYER "\xf3\xb1\x83\xaf" // U+F10EF +#define ICON_MDI_HAIR_DRYER_OUTLINE "\xf3\xb1\x83\xb0" // U+F10F0 +#define ICON_MDI_HALLOWEEN "\xf3\xb0\xae\xa3" // U+F0BA3 +#define ICON_MDI_HAMBURGER "\xf3\xb0\x9a\x85" // U+F0685 +#define ICON_MDI_HAMBURGER_CHECK "\xf3\xb1\x9d\xb6" // U+F1776 +#define ICON_MDI_HAMBURGER_MINUS "\xf3\xb1\x9d\xb7" // U+F1777 +#define ICON_MDI_HAMBURGER_OFF "\xf3\xb1\x9d\xb8" // U+F1778 +#define ICON_MDI_HAMBURGER_PLUS "\xf3\xb1\x9d\xb9" // U+F1779 +#define ICON_MDI_HAMBURGER_REMOVE "\xf3\xb1\x9d\xba" // U+F177A +#define ICON_MDI_HAMMER "\xf3\xb0\xa3\xaa" // U+F08EA +#define ICON_MDI_HAMMER_SCREWDRIVER "\xf3\xb1\x8c\xa2" // U+F1322 +#define ICON_MDI_HAMMER_SICKLE "\xf3\xb1\xa2\x87" // U+F1887 +#define ICON_MDI_HAMMER_WRENCH "\xf3\xb1\x8c\xa3" // U+F1323 +#define ICON_MDI_HAND_BACK_LEFT "\xf3\xb0\xb9\x86" // U+F0E46 +#define ICON_MDI_HAND_BACK_LEFT_OFF "\xf3\xb1\xa0\xb0" // U+F1830 +#define ICON_MDI_HAND_BACK_LEFT_OFF_OUTLINE "\xf3\xb1\xa0\xb2" // U+F1832 +#define ICON_MDI_HAND_BACK_LEFT_OUTLINE "\xf3\xb1\xa0\xac" // U+F182C +#define ICON_MDI_HAND_BACK_RIGHT "\xf3\xb0\xb9\x87" // U+F0E47 +#define ICON_MDI_HAND_BACK_RIGHT_OFF "\xf3\xb1\xa0\xb1" // U+F1831 +#define ICON_MDI_HAND_BACK_RIGHT_OFF_OUTLINE "\xf3\xb1\xa0\xb3" // U+F1833 +#define ICON_MDI_HAND_BACK_RIGHT_OUTLINE "\xf3\xb1\xa0\xad" // U+F182D +#define ICON_MDI_HAND_CLAP "\xf3\xb1\xa5\x8b" // U+F194B +#define ICON_MDI_HAND_CLAP_OFF "\xf3\xb1\xa9\x82" // U+F1A42 +#define ICON_MDI_HAND_COIN "\xf3\xb1\xa2\x8f" // U+F188F +#define ICON_MDI_HAND_COIN_OUTLINE "\xf3\xb1\xa2\x90" // U+F1890 +#define ICON_MDI_HAND_CYCLE "\xf3\xb1\xae\x9c" // U+F1B9C +#define ICON_MDI_HAND_EXTENDED "\xf3\xb1\xa2\xb6" // U+F18B6 +#define ICON_MDI_HAND_EXTENDED_OUTLINE "\xf3\xb1\xa2\xb7" // U+F18B7 +#define ICON_MDI_HAND_FRONT_LEFT "\xf3\xb1\xa0\xab" // U+F182B +#define ICON_MDI_HAND_FRONT_LEFT_OUTLINE "\xf3\xb1\xa0\xae" // U+F182E +#define ICON_MDI_HAND_FRONT_RIGHT "\xf3\xb0\xa9\x8f" // U+F0A4F +#define ICON_MDI_HAND_FRONT_RIGHT_OUTLINE "\xf3\xb1\xa0\xaf" // U+F182F +#define ICON_MDI_HAND_HEART "\xf3\xb1\x83\xb1" // U+F10F1 +#define ICON_MDI_HAND_HEART_OUTLINE "\xf3\xb1\x95\xbe" // U+F157E +#define ICON_MDI_HAND_OKAY "\xf3\xb0\xa9\x90" // U+F0A50 +#define ICON_MDI_HAND_PEACE "\xf3\xb0\xa9\x91" // U+F0A51 +#define ICON_MDI_HAND_PEACE_VARIANT "\xf3\xb0\xa9\x92" // U+F0A52 +#define ICON_MDI_HAND_POINTING_DOWN "\xf3\xb0\xa9\x93" // U+F0A53 +#define ICON_MDI_HAND_POINTING_LEFT "\xf3\xb0\xa9\x94" // U+F0A54 +#define ICON_MDI_HAND_POINTING_RIGHT "\xf3\xb0\x8b\x87" // U+F02C7 +#define ICON_MDI_HAND_POINTING_UP "\xf3\xb0\xa9\x95" // U+F0A55 +#define ICON_MDI_HAND_SAW "\xf3\xb0\xb9\x88" // U+F0E48 +#define ICON_MDI_HAND_WASH "\xf3\xb1\x95\xbf" // U+F157F +#define ICON_MDI_HAND_WASH_OUTLINE "\xf3\xb1\x96\x80" // U+F1580 +#define ICON_MDI_HAND_WATER "\xf3\xb1\x8e\x9f" // U+F139F +#define ICON_MDI_HAND_WAVE "\xf3\xb1\xa0\xa1" // U+F1821 +#define ICON_MDI_HAND_WAVE_OUTLINE "\xf3\xb1\xa0\xa2" // U+F1822 +#define ICON_MDI_HANDBALL "\xf3\xb0\xbd\x93" // U+F0F53 +#define ICON_MDI_HANDCUFFS "\xf3\xb1\x84\xbe" // U+F113E +#define ICON_MDI_HANDS_PRAY "\xf3\xb0\x95\xb9" // U+F0579 +#define ICON_MDI_HANDSHAKE "\xf3\xb1\x88\x98" // U+F1218 +#define ICON_MDI_HANDSHAKE_OUTLINE "\xf3\xb1\x96\xa1" // U+F15A1 +#define ICON_MDI_HANGER "\xf3\xb0\x8b\x88" // U+F02C8 +#define ICON_MDI_HARD_HAT "\xf3\xb0\xa5\xaf" // U+F096F +#define ICON_MDI_HARDDISK "\xf3\xb0\x8b\x8a" // U+F02CA +#define ICON_MDI_HARDDISK_PLUS "\xf3\xb1\x81\x8b" // U+F104B +#define ICON_MDI_HARDDISK_REMOVE "\xf3\xb1\x81\x8c" // U+F104C +#define ICON_MDI_HAT_FEDORA "\xf3\xb0\xae\xa4" // U+F0BA4 +#define ICON_MDI_HAZARD_LIGHTS "\xf3\xb0\xb2\x89" // U+F0C89 +#define ICON_MDI_HDMI_PORT "\xf3\xb1\xae\xb8" // U+F1BB8 +#define ICON_MDI_HDR "\xf3\xb0\xb5\xbd" // U+F0D7D +#define ICON_MDI_HDR_OFF "\xf3\xb0\xb5\xbe" // U+F0D7E +#define ICON_MDI_HEAD "\xf3\xb1\x8d\x9e" // U+F135E +#define ICON_MDI_HEAD_ALERT "\xf3\xb1\x8c\xb8" // U+F1338 +#define ICON_MDI_HEAD_ALERT_OUTLINE "\xf3\xb1\x8c\xb9" // U+F1339 +#define ICON_MDI_HEAD_CHECK "\xf3\xb1\x8c\xba" // U+F133A +#define ICON_MDI_HEAD_CHECK_OUTLINE "\xf3\xb1\x8c\xbb" // U+F133B +#define ICON_MDI_HEAD_COG "\xf3\xb1\x8c\xbc" // U+F133C +#define ICON_MDI_HEAD_COG_OUTLINE "\xf3\xb1\x8c\xbd" // U+F133D +#define ICON_MDI_HEAD_DOTS_HORIZONTAL "\xf3\xb1\x8c\xbe" // U+F133E +#define ICON_MDI_HEAD_DOTS_HORIZONTAL_OUTLINE "\xf3\xb1\x8c\xbf" // U+F133F +#define ICON_MDI_HEAD_FLASH "\xf3\xb1\x8d\x80" // U+F1340 +#define ICON_MDI_HEAD_FLASH_OUTLINE "\xf3\xb1\x8d\x81" // U+F1341 +#define ICON_MDI_HEAD_HEART "\xf3\xb1\x8d\x82" // U+F1342 +#define ICON_MDI_HEAD_HEART_OUTLINE "\xf3\xb1\x8d\x83" // U+F1343 +#define ICON_MDI_HEAD_LIGHTBULB "\xf3\xb1\x8d\x84" // U+F1344 +#define ICON_MDI_HEAD_LIGHTBULB_OUTLINE "\xf3\xb1\x8d\x85" // U+F1345 +#define ICON_MDI_HEAD_MINUS "\xf3\xb1\x8d\x86" // U+F1346 +#define ICON_MDI_HEAD_MINUS_OUTLINE "\xf3\xb1\x8d\x87" // U+F1347 +#define ICON_MDI_HEAD_OUTLINE "\xf3\xb1\x8d\x9f" // U+F135F +#define ICON_MDI_HEAD_PLUS "\xf3\xb1\x8d\x88" // U+F1348 +#define ICON_MDI_HEAD_PLUS_OUTLINE "\xf3\xb1\x8d\x89" // U+F1349 +#define ICON_MDI_HEAD_QUESTION "\xf3\xb1\x8d\x8a" // U+F134A +#define ICON_MDI_HEAD_QUESTION_OUTLINE "\xf3\xb1\x8d\x8b" // U+F134B +#define ICON_MDI_HEAD_REMOVE "\xf3\xb1\x8d\x8c" // U+F134C +#define ICON_MDI_HEAD_REMOVE_OUTLINE "\xf3\xb1\x8d\x8d" // U+F134D +#define ICON_MDI_HEAD_SNOWFLAKE "\xf3\xb1\x8d\x8e" // U+F134E +#define ICON_MDI_HEAD_SNOWFLAKE_OUTLINE "\xf3\xb1\x8d\x8f" // U+F134F +#define ICON_MDI_HEAD_SYNC "\xf3\xb1\x8d\x90" // U+F1350 +#define ICON_MDI_HEAD_SYNC_OUTLINE "\xf3\xb1\x8d\x91" // U+F1351 +#define ICON_MDI_HEADPHONES "\xf3\xb0\x8b\x8b" // U+F02CB +#define ICON_MDI_HEADPHONES_BLUETOOTH "\xf3\xb0\xa5\xb0" // U+F0970 +#define ICON_MDI_HEADPHONES_BOX "\xf3\xb0\x8b\x8c" // U+F02CC +#define ICON_MDI_HEADPHONES_OFF "\xf3\xb0\x9f\x8e" // U+F07CE +#define ICON_MDI_HEADPHONES_SETTINGS "\xf3\xb0\x8b\x8d" // U+F02CD +#define ICON_MDI_HEADSET "\xf3\xb0\x8b\x8e" // U+F02CE +#define ICON_MDI_HEADSET_DOCK "\xf3\xb0\x8b\x8f" // U+F02CF +#define ICON_MDI_HEADSET_OFF "\xf3\xb0\x8b\x90" // U+F02D0 +#define ICON_MDI_HEART "\xf3\xb0\x8b\x91" // U+F02D1 +#define ICON_MDI_HEART_BOX "\xf3\xb0\x8b\x92" // U+F02D2 +#define ICON_MDI_HEART_BOX_OUTLINE "\xf3\xb0\x8b\x93" // U+F02D3 +#define ICON_MDI_HEART_BROKEN "\xf3\xb0\x8b\x94" // U+F02D4 +#define ICON_MDI_HEART_BROKEN_OUTLINE "\xf3\xb0\xb4\x94" // U+F0D14 +#define ICON_MDI_HEART_CIRCLE "\xf3\xb0\xa5\xb1" // U+F0971 +#define ICON_MDI_HEART_CIRCLE_OUTLINE "\xf3\xb0\xa5\xb2" // U+F0972 +#define ICON_MDI_HEART_COG "\xf3\xb1\x99\xa3" // U+F1663 +#define ICON_MDI_HEART_COG_OUTLINE "\xf3\xb1\x99\xa4" // U+F1664 +#define ICON_MDI_HEART_FLASH "\xf3\xb0\xbb\xb9" // U+F0EF9 +#define ICON_MDI_HEART_HALF "\xf3\xb0\x9b\x9f" // U+F06DF +#define ICON_MDI_HEART_HALF_FULL "\xf3\xb0\x9b\x9e" // U+F06DE +#define ICON_MDI_HEART_HALF_OUTLINE "\xf3\xb0\x9b\xa0" // U+F06E0 +#define ICON_MDI_HEART_MINUS "\xf3\xb1\x90\xaf" // U+F142F +#define ICON_MDI_HEART_MINUS_OUTLINE "\xf3\xb1\x90\xb2" // U+F1432 +#define ICON_MDI_HEART_MULTIPLE "\xf3\xb0\xa9\x96" // U+F0A56 +#define ICON_MDI_HEART_MULTIPLE_OUTLINE "\xf3\xb0\xa9\x97" // U+F0A57 +#define ICON_MDI_HEART_OFF "\xf3\xb0\x9d\x99" // U+F0759 +#define ICON_MDI_HEART_OFF_OUTLINE "\xf3\xb1\x90\xb4" // U+F1434 +#define ICON_MDI_HEART_OUTLINE "\xf3\xb0\x8b\x95" // U+F02D5 +#define ICON_MDI_HEART_PLUS "\xf3\xb1\x90\xae" // U+F142E +#define ICON_MDI_HEART_PLUS_OUTLINE "\xf3\xb1\x90\xb1" // U+F1431 +#define ICON_MDI_HEART_PULSE "\xf3\xb0\x97\xb6" // U+F05F6 +#define ICON_MDI_HEART_REMOVE "\xf3\xb1\x90\xb0" // U+F1430 +#define ICON_MDI_HEART_REMOVE_OUTLINE "\xf3\xb1\x90\xb3" // U+F1433 +#define ICON_MDI_HEART_SEARCH "\xf3\xb1\xb2\x8d" // U+F1C8D +#define ICON_MDI_HEART_SETTINGS "\xf3\xb1\x99\xa5" // U+F1665 +#define ICON_MDI_HEART_SETTINGS_OUTLINE "\xf3\xb1\x99\xa6" // U+F1666 +#define ICON_MDI_HEAT_PUMP "\xf3\xb1\xa9\x83" // U+F1A43 +#define ICON_MDI_HEAT_PUMP_OUTLINE "\xf3\xb1\xa9\x84" // U+F1A44 +#define ICON_MDI_HEAT_WAVE "\xf3\xb1\xa9\x85" // U+F1A45 +#define ICON_MDI_HEATING_COIL "\xf3\xb1\xaa\xaf" // U+F1AAF +#define ICON_MDI_HELICOPTER "\xf3\xb0\xab\x82" // U+F0AC2 +#define ICON_MDI_HELP "\xf3\xb0\x8b\x96" // U+F02D6 +#define ICON_MDI_HELP_BOX "\xf3\xb0\x9e\x8b" // U+F078B +#define ICON_MDI_HELP_BOX_MULTIPLE "\xf3\xb1\xb0\x8a" // U+F1C0A +#define ICON_MDI_HELP_BOX_MULTIPLE_OUTLINE "\xf3\xb1\xb0\x8b" // U+F1C0B +#define ICON_MDI_HELP_BOX_OUTLINE "\xf3\xb1\xb0\x8c" // U+F1C0C +#define ICON_MDI_HELP_CIRCLE "\xf3\xb0\x8b\x97" // U+F02D7 +#define ICON_MDI_HELP_CIRCLE_OUTLINE "\xf3\xb0\x98\xa5" // U+F0625 +#define ICON_MDI_HELP_NETWORK "\xf3\xb0\x9b\xb5" // U+F06F5 +#define ICON_MDI_HELP_NETWORK_OUTLINE "\xf3\xb0\xb2\x8a" // U+F0C8A +#define ICON_MDI_HELP_RHOMBUS "\xf3\xb0\xae\xa5" // U+F0BA5 +#define ICON_MDI_HELP_RHOMBUS_OUTLINE "\xf3\xb0\xae\xa6" // U+F0BA6 +#define ICON_MDI_HEXADECIMAL "\xf3\xb1\x8a\xa7" // U+F12A7 +#define ICON_MDI_HEXAGON "\xf3\xb0\x8b\x98" // U+F02D8 +#define ICON_MDI_HEXAGON_MULTIPLE "\xf3\xb0\x9b\xa1" // U+F06E1 +#define ICON_MDI_HEXAGON_MULTIPLE_OUTLINE "\xf3\xb1\x83\xb2" // U+F10F2 +#define ICON_MDI_HEXAGON_OUTLINE "\xf3\xb0\x8b\x99" // U+F02D9 +#define ICON_MDI_HEXAGON_SLICE_1 "\xf3\xb0\xab\x83" // U+F0AC3 +#define ICON_MDI_HEXAGON_SLICE_2 "\xf3\xb0\xab\x84" // U+F0AC4 +#define ICON_MDI_HEXAGON_SLICE_3 "\xf3\xb0\xab\x85" // U+F0AC5 +#define ICON_MDI_HEXAGON_SLICE_4 "\xf3\xb0\xab\x86" // U+F0AC6 +#define ICON_MDI_HEXAGON_SLICE_5 "\xf3\xb0\xab\x87" // U+F0AC7 +#define ICON_MDI_HEXAGON_SLICE_6 "\xf3\xb0\xab\x88" // U+F0AC8 +#define ICON_MDI_HEXAGRAM "\xf3\xb0\xab\x89" // U+F0AC9 +#define ICON_MDI_HEXAGRAM_OUTLINE "\xf3\xb0\xab\x8a" // U+F0ACA +#define ICON_MDI_HIGH_DEFINITION "\xf3\xb0\x9f\x8f" // U+F07CF +#define ICON_MDI_HIGH_DEFINITION_BOX "\xf3\xb0\xa1\xb8" // U+F0878 +#define ICON_MDI_HIGHWAY "\xf3\xb0\x97\xb7" // U+F05F7 +#define ICON_MDI_HIKING "\xf3\xb0\xb5\xbf" // U+F0D7F +#define ICON_MDI_HISTORY "\xf3\xb0\x8b\x9a" // U+F02DA +#define ICON_MDI_HOCKEY_PUCK "\xf3\xb0\xa1\xb9" // U+F0879 +#define ICON_MDI_HOCKEY_STICKS "\xf3\xb0\xa1\xba" // U+F087A +#define ICON_MDI_HOLOLENS "\xf3\xb0\x8b\x9b" // U+F02DB +#define ICON_MDI_HOME "\xf3\xb0\x8b\x9c" // U+F02DC +#define ICON_MDI_HOME_ACCOUNT "\xf3\xb0\xa0\xa6" // U+F0826 +#define ICON_MDI_HOME_ALERT "\xf3\xb0\xa1\xbb" // U+F087B +#define ICON_MDI_HOME_ALERT_OUTLINE "\xf3\xb1\x97\x90" // U+F15D0 +#define ICON_MDI_HOME_ANALYTICS "\xf3\xb0\xba\xba" // U+F0EBA +#define ICON_MDI_HOME_ASSISTANT "\xf3\xb0\x9f\x90" // U+F07D0 +#define ICON_MDI_HOME_AUTOMATION "\xf3\xb0\x9f\x91" // U+F07D1 +#define ICON_MDI_HOME_BATTERY "\xf3\xb1\xa4\x81" // U+F1901 +#define ICON_MDI_HOME_BATTERY_OUTLINE "\xf3\xb1\xa4\x82" // U+F1902 +#define ICON_MDI_HOME_CIRCLE "\xf3\xb0\x9f\x92" // U+F07D2 +#define ICON_MDI_HOME_CIRCLE_OUTLINE "\xf3\xb1\x81\x8d" // U+F104D +#define ICON_MDI_HOME_CITY "\xf3\xb0\xb4\x95" // U+F0D15 +#define ICON_MDI_HOME_CITY_OUTLINE "\xf3\xb0\xb4\x96" // U+F0D16 +#define ICON_MDI_HOME_CLOCK "\xf3\xb1\xa8\x92" // U+F1A12 +#define ICON_MDI_HOME_CLOCK_OUTLINE "\xf3\xb1\xa8\x93" // U+F1A13 +#define ICON_MDI_HOME_EDIT "\xf3\xb1\x85\x99" // U+F1159 +#define ICON_MDI_HOME_EDIT_OUTLINE "\xf3\xb1\x85\x9a" // U+F115A +#define ICON_MDI_HOME_EXPORT_OUTLINE "\xf3\xb0\xbe\x9b" // U+F0F9B +#define ICON_MDI_HOME_FLOOD "\xf3\xb0\xbb\xba" // U+F0EFA +#define ICON_MDI_HOME_FLOOR_0 "\xf3\xb0\xb7\x92" // U+F0DD2 +#define ICON_MDI_HOME_FLOOR_1 "\xf3\xb0\xb6\x80" // U+F0D80 +#define ICON_MDI_HOME_FLOOR_2 "\xf3\xb0\xb6\x81" // U+F0D81 +#define ICON_MDI_HOME_FLOOR_3 "\xf3\xb0\xb6\x82" // U+F0D82 +#define ICON_MDI_HOME_FLOOR_A "\xf3\xb0\xb6\x83" // U+F0D83 +#define ICON_MDI_HOME_FLOOR_B "\xf3\xb0\xb6\x84" // U+F0D84 +#define ICON_MDI_HOME_FLOOR_G "\xf3\xb0\xb6\x85" // U+F0D85 +#define ICON_MDI_HOME_FLOOR_L "\xf3\xb0\xb6\x86" // U+F0D86 +#define ICON_MDI_HOME_FLOOR_NEGATIVE_1 "\xf3\xb0\xb7\x93" // U+F0DD3 +#define ICON_MDI_HOME_GROUP "\xf3\xb0\xb7\x94" // U+F0DD4 +#define ICON_MDI_HOME_GROUP_MINUS "\xf3\xb1\xa7\x81" // U+F19C1 +#define ICON_MDI_HOME_GROUP_PLUS "\xf3\xb1\xa7\x80" // U+F19C0 +#define ICON_MDI_HOME_GROUP_REMOVE "\xf3\xb1\xa7\x82" // U+F19C2 +#define ICON_MDI_HOME_HEART "\xf3\xb0\xa0\xa7" // U+F0827 +#define ICON_MDI_HOME_IMPORT_OUTLINE "\xf3\xb0\xbe\x9c" // U+F0F9C +#define ICON_MDI_HOME_LIGHTBULB "\xf3\xb1\x89\x91" // U+F1251 +#define ICON_MDI_HOME_LIGHTBULB_OUTLINE "\xf3\xb1\x89\x92" // U+F1252 +#define ICON_MDI_HOME_LIGHTNING_BOLT "\xf3\xb1\xa4\x83" // U+F1903 +#define ICON_MDI_HOME_LIGHTNING_BOLT_OUTLINE "\xf3\xb1\xa4\x84" // U+F1904 +#define ICON_MDI_HOME_LOCK "\xf3\xb0\xa3\xab" // U+F08EB +#define ICON_MDI_HOME_LOCK_OPEN "\xf3\xb0\xa3\xac" // U+F08EC +#define ICON_MDI_HOME_MAP_MARKER "\xf3\xb0\x97\xb8" // U+F05F8 +#define ICON_MDI_HOME_MINUS "\xf3\xb0\xa5\xb4" // U+F0974 +#define ICON_MDI_HOME_MINUS_OUTLINE "\xf3\xb1\x8f\x95" // U+F13D5 +#define ICON_MDI_HOME_MODERN "\xf3\xb0\x8b\x9d" // U+F02DD +#define ICON_MDI_HOME_OFF "\xf3\xb1\xa9\x86" // U+F1A46 +#define ICON_MDI_HOME_OFF_OUTLINE "\xf3\xb1\xa9\x87" // U+F1A47 +#define ICON_MDI_HOME_OUTLINE "\xf3\xb0\x9a\xa1" // U+F06A1 +#define ICON_MDI_HOME_PERCENT "\xf3\xb1\xb1\xbc" // U+F1C7C +#define ICON_MDI_HOME_PERCENT_OUTLINE "\xf3\xb1\xb1\xbd" // U+F1C7D +#define ICON_MDI_HOME_PLUS "\xf3\xb0\xa5\xb5" // U+F0975 +#define ICON_MDI_HOME_PLUS_OUTLINE "\xf3\xb1\x8f\x96" // U+F13D6 +#define ICON_MDI_HOME_REMOVE "\xf3\xb1\x89\x87" // U+F1247 +#define ICON_MDI_HOME_REMOVE_OUTLINE "\xf3\xb1\x8f\x97" // U+F13D7 +#define ICON_MDI_HOME_ROOF "\xf3\xb1\x84\xab" // U+F112B +#define ICON_MDI_HOME_SEARCH "\xf3\xb1\x8e\xb0" // U+F13B0 +#define ICON_MDI_HOME_SEARCH_OUTLINE "\xf3\xb1\x8e\xb1" // U+F13B1 +#define ICON_MDI_HOME_SILO "\xf3\xb1\xae\xa0" // U+F1BA0 +#define ICON_MDI_HOME_SILO_OUTLINE "\xf3\xb1\xae\xa1" // U+F1BA1 +#define ICON_MDI_HOME_SOUND_IN "\xf3\xb1\xb0\xaf" // U+F1C2F +#define ICON_MDI_HOME_SOUND_IN_OUTLINE "\xf3\xb1\xb0\xb0" // U+F1C30 +#define ICON_MDI_HOME_SOUND_OUT "\xf3\xb1\xb0\xb1" // U+F1C31 +#define ICON_MDI_HOME_SOUND_OUT_OUTLINE "\xf3\xb1\xb0\xb2" // U+F1C32 +#define ICON_MDI_HOME_SWITCH "\xf3\xb1\x9e\x94" // U+F1794 +#define ICON_MDI_HOME_SWITCH_OUTLINE "\xf3\xb1\x9e\x95" // U+F1795 +#define ICON_MDI_HOME_THERMOMETER "\xf3\xb0\xbd\x94" // U+F0F54 +#define ICON_MDI_HOME_THERMOMETER_OUTLINE "\xf3\xb0\xbd\x95" // U+F0F55 +#define ICON_MDI_HOME_VARIANT "\xf3\xb0\x8b\x9e" // U+F02DE +#define ICON_MDI_HOME_VARIANT_OUTLINE "\xf3\xb0\xae\xa7" // U+F0BA7 +#define ICON_MDI_HOOK "\xf3\xb0\x9b\xa2" // U+F06E2 +#define ICON_MDI_HOOK_OFF "\xf3\xb0\x9b\xa3" // U+F06E3 +#define ICON_MDI_HOOP_HOUSE "\xf3\xb0\xb9\x96" // U+F0E56 +#define ICON_MDI_HOPS "\xf3\xb0\x8b\x9f" // U+F02DF +#define ICON_MDI_HORIZONTAL_ROTATE_CLOCKWISE "\xf3\xb1\x83\xb3" // U+F10F3 +#define ICON_MDI_HORIZONTAL_ROTATE_COUNTERCLOCKWISE "\xf3\xb1\x83\xb4" // U+F10F4 +#define ICON_MDI_HORSE "\xf3\xb1\x96\xbf" // U+F15BF +#define ICON_MDI_HORSE_HUMAN "\xf3\xb1\x97\x80" // U+F15C0 +#define ICON_MDI_HORSE_VARIANT "\xf3\xb1\x97\x81" // U+F15C1 +#define ICON_MDI_HORSE_VARIANT_FAST "\xf3\xb1\xa1\xae" // U+F186E +#define ICON_MDI_HORSESHOE "\xf3\xb0\xa9\x98" // U+F0A58 +#define ICON_MDI_HOSPITAL "\xf3\xb0\xbf\xb6" // U+F0FF6 +#define ICON_MDI_HOSPITAL_BOX "\xf3\xb0\x8b\xa0" // U+F02E0 +#define ICON_MDI_HOSPITAL_BOX_OUTLINE "\xf3\xb0\xbf\xb7" // U+F0FF7 +#define ICON_MDI_HOSPITAL_BUILDING "\xf3\xb0\x8b\xa1" // U+F02E1 +#define ICON_MDI_HOSPITAL_MARKER "\xf3\xb0\x8b\xa2" // U+F02E2 +#define ICON_MDI_HOT_TUB "\xf3\xb0\xa0\xa8" // U+F0828 +#define ICON_MDI_HOURS_12 "\xf3\xb1\xb2\x94" // U+F1C94 +#define ICON_MDI_HOURS_24 "\xf3\xb1\x91\xb8" // U+F1478 +#define ICON_MDI_HUB "\xf3\xb1\xb2\x95" // U+F1C95 +#define ICON_MDI_HUB_OUTLINE "\xf3\xb1\xb2\x96" // U+F1C96 +#define ICON_MDI_HUBSPOT "\xf3\xb0\xb4\x97" // U+F0D17 +#define ICON_MDI_HULU "\xf3\xb0\xa0\xa9" // U+F0829 +#define ICON_MDI_HUMAN "\xf3\xb0\x8b\xa6" // U+F02E6 +#define ICON_MDI_HUMAN_BABY_CHANGING_TABLE "\xf3\xb1\x8e\x8b" // U+F138B +#define ICON_MDI_HUMAN_CANE "\xf3\xb1\x96\x81" // U+F1581 +#define ICON_MDI_HUMAN_CAPACITY_DECREASE "\xf3\xb1\x96\x9b" // U+F159B +#define ICON_MDI_HUMAN_CAPACITY_INCREASE "\xf3\xb1\x96\x9c" // U+F159C +#define ICON_MDI_HUMAN_CHILD "\xf3\xb0\x8b\xa7" // U+F02E7 +#define ICON_MDI_HUMAN_DOLLY "\xf3\xb1\xa6\x80" // U+F1980 +#define ICON_MDI_HUMAN_EDIT "\xf3\xb1\x93\xa8" // U+F14E8 +#define ICON_MDI_HUMAN_FEMALE "\xf3\xb0\x99\x89" // U+F0649 +#define ICON_MDI_HUMAN_FEMALE_BOY "\xf3\xb0\xa9\x99" // U+F0A59 +#define ICON_MDI_HUMAN_FEMALE_DANCE "\xf3\xb1\x97\x89" // U+F15C9 +#define ICON_MDI_HUMAN_FEMALE_FEMALE "\xf3\xb0\xa9\x9a" // U+F0A5A +#define ICON_MDI_HUMAN_FEMALE_FEMALE_CHILD "\xf3\xb1\xb2\x8e" // U+F1C8E +#define ICON_MDI_HUMAN_FEMALE_GIRL "\xf3\xb0\xa9\x9b" // U+F0A5B +#define ICON_MDI_HUMAN_GREETING "\xf3\xb1\x9f\x84" // U+F17C4 +#define ICON_MDI_HUMAN_GREETING_PROXIMITY "\xf3\xb1\x96\x9d" // U+F159D +#define ICON_MDI_HUMAN_GREETING_VARIANT "\xf3\xb0\x99\x8a" // U+F064A +#define ICON_MDI_HUMAN_HANDSDOWN "\xf3\xb0\x99\x8b" // U+F064B +#define ICON_MDI_HUMAN_HANDSUP "\xf3\xb0\x99\x8c" // U+F064C +#define ICON_MDI_HUMAN_MALE "\xf3\xb0\x99\x8d" // U+F064D +#define ICON_MDI_HUMAN_MALE_BOARD "\xf3\xb0\xa2\x90" // U+F0890 +#define ICON_MDI_HUMAN_MALE_BOARD_POLL "\xf3\xb0\xa1\x86" // U+F0846 +#define ICON_MDI_HUMAN_MALE_BOY "\xf3\xb0\xa9\x9c" // U+F0A5C +#define ICON_MDI_HUMAN_MALE_CHILD "\xf3\xb1\x8e\x8c" // U+F138C +#define ICON_MDI_HUMAN_MALE_FEMALE "\xf3\xb0\x8b\xa8" // U+F02E8 +#define ICON_MDI_HUMAN_MALE_FEMALE_CHILD "\xf3\xb1\xa0\xa3" // U+F1823 +#define ICON_MDI_HUMAN_MALE_GIRL "\xf3\xb0\xa9\x9d" // U+F0A5D +#define ICON_MDI_HUMAN_MALE_HEIGHT "\xf3\xb0\xbb\xbb" // U+F0EFB +#define ICON_MDI_HUMAN_MALE_HEIGHT_VARIANT "\xf3\xb0\xbb\xbc" // U+F0EFC +#define ICON_MDI_HUMAN_MALE_MALE "\xf3\xb0\xa9\x9e" // U+F0A5E +#define ICON_MDI_HUMAN_MALE_MALE_CHILD "\xf3\xb1\xb2\x8f" // U+F1C8F +#define ICON_MDI_HUMAN_NON_BINARY "\xf3\xb1\xa1\x88" // U+F1848 +#define ICON_MDI_HUMAN_PREGNANT "\xf3\xb0\x97\x8f" // U+F05CF +#define ICON_MDI_HUMAN_QUEUE "\xf3\xb1\x95\xb1" // U+F1571 +#define ICON_MDI_HUMAN_SCOOTER "\xf3\xb1\x87\xa9" // U+F11E9 +#define ICON_MDI_HUMAN_WALKER "\xf3\xb1\xad\xb1" // U+F1B71 +#define ICON_MDI_HUMAN_WHEELCHAIR "\xf3\xb1\x8e\x8d" // U+F138D +#define ICON_MDI_HUMAN_WHITE_CANE "\xf3\xb1\xa6\x81" // U+F1981 +#define ICON_MDI_HUMBLE_BUNDLE "\xf3\xb0\x9d\x84" // U+F0744 +#define ICON_MDI_HVAC "\xf3\xb1\x8d\x92" // U+F1352 +#define ICON_MDI_HVAC_OFF "\xf3\xb1\x96\x9e" // U+F159E +#define ICON_MDI_HYDRAULIC_OIL_LEVEL "\xf3\xb1\x8c\xa4" // U+F1324 +#define ICON_MDI_HYDRAULIC_OIL_TEMPERATURE "\xf3\xb1\x8c\xa5" // U+F1325 +#define ICON_MDI_HYDRO_POWER "\xf3\xb1\x8b\xa5" // U+F12E5 +#define ICON_MDI_HYDROGEN_STATION "\xf3\xb1\xa2\x94" // U+F1894 +#define ICON_MDI_ICE_CREAM "\xf3\xb0\xa0\xaa" // U+F082A +#define ICON_MDI_ICE_CREAM_OFF "\xf3\xb0\xb9\x92" // U+F0E52 +#define ICON_MDI_ICE_POP "\xf3\xb0\xbb\xbd" // U+F0EFD +#define ICON_MDI_ID_CARD "\xf3\xb0\xbf\x80" // U+F0FC0 +#define ICON_MDI_IDENTIFIER "\xf3\xb0\xbb\xbe" // U+F0EFE +#define ICON_MDI_IDEOGRAM_CJK "\xf3\xb1\x8c\xb1" // U+F1331 +#define ICON_MDI_IDEOGRAM_CJK_VARIANT "\xf3\xb1\x8c\xb2" // U+F1332 +#define ICON_MDI_IMAGE "\xf3\xb0\x8b\xa9" // U+F02E9 +#define ICON_MDI_IMAGE_ALBUM "\xf3\xb0\x8b\xaa" // U+F02EA +#define ICON_MDI_IMAGE_AREA "\xf3\xb0\x8b\xab" // U+F02EB +#define ICON_MDI_IMAGE_AREA_CLOSE "\xf3\xb0\x8b\xac" // U+F02EC +#define ICON_MDI_IMAGE_AUTO_ADJUST "\xf3\xb0\xbf\x81" // U+F0FC1 +#define ICON_MDI_IMAGE_BROKEN "\xf3\xb0\x8b\xad" // U+F02ED +#define ICON_MDI_IMAGE_BROKEN_VARIANT "\xf3\xb0\x8b\xae" // U+F02EE +#define ICON_MDI_IMAGE_CHECK "\xf3\xb1\xac\xa5" // U+F1B25 +#define ICON_MDI_IMAGE_CHECK_OUTLINE "\xf3\xb1\xac\xa6" // U+F1B26 +#define ICON_MDI_IMAGE_EDIT "\xf3\xb1\x87\xa3" // U+F11E3 +#define ICON_MDI_IMAGE_EDIT_OUTLINE "\xf3\xb1\x87\xa4" // U+F11E4 +#define ICON_MDI_IMAGE_FILTER_BLACK_WHITE "\xf3\xb0\x8b\xb0" // U+F02F0 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS "\xf3\xb0\x8b\xb1" // U+F02F1 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_STRONG "\xf3\xb0\xbb\xbf" // U+F0EFF +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_STRONG_OUTLINE "\xf3\xb0\xbc\x80" // U+F0F00 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_WEAK "\xf3\xb0\x8b\xb2" // U+F02F2 +#define ICON_MDI_IMAGE_FILTER_DRAMA "\xf3\xb0\x8b\xb3" // U+F02F3 +#define ICON_MDI_IMAGE_FILTER_DRAMA_OUTLINE "\xf3\xb1\xaf\xbf" // U+F1BFF +#define ICON_MDI_IMAGE_FILTER_FRAMES "\xf3\xb0\x8b\xb4" // U+F02F4 +#define ICON_MDI_IMAGE_FILTER_HDR "\xf3\xb0\x8b\xb5" // U+F02F5 +#define ICON_MDI_IMAGE_FILTER_HDR_OUTLINE "\xf3\xb1\xb1\xa4" // U+F1C64 +#define ICON_MDI_IMAGE_FILTER_NONE "\xf3\xb0\x8b\xb6" // U+F02F6 +#define ICON_MDI_IMAGE_FILTER_TILT_SHIFT "\xf3\xb0\x8b\xb7" // U+F02F7 +#define ICON_MDI_IMAGE_FILTER_VINTAGE "\xf3\xb0\x8b\xb8" // U+F02F8 +#define ICON_MDI_IMAGE_FRAME "\xf3\xb0\xb9\x89" // U+F0E49 +#define ICON_MDI_IMAGE_LOCK "\xf3\xb1\xaa\xb0" // U+F1AB0 +#define ICON_MDI_IMAGE_LOCK_OUTLINE "\xf3\xb1\xaa\xb1" // U+F1AB1 +#define ICON_MDI_IMAGE_MARKER "\xf3\xb1\x9d\xbb" // U+F177B +#define ICON_MDI_IMAGE_MARKER_OUTLINE "\xf3\xb1\x9d\xbc" // U+F177C +#define ICON_MDI_IMAGE_MINUS "\xf3\xb1\x90\x99" // U+F1419 +#define ICON_MDI_IMAGE_MINUS_OUTLINE "\xf3\xb1\xad\x87" // U+F1B47 +#define ICON_MDI_IMAGE_MOVE "\xf3\xb0\xa7\xb8" // U+F09F8 +#define ICON_MDI_IMAGE_MULTIPLE "\xf3\xb0\x8b\xb9" // U+F02F9 +#define ICON_MDI_IMAGE_MULTIPLE_OUTLINE "\xf3\xb0\x8b\xaf" // U+F02EF +#define ICON_MDI_IMAGE_OFF "\xf3\xb0\xa0\xab" // U+F082B +#define ICON_MDI_IMAGE_OFF_OUTLINE "\xf3\xb1\x87\x91" // U+F11D1 +#define ICON_MDI_IMAGE_OUTLINE "\xf3\xb0\xa5\xb6" // U+F0976 +#define ICON_MDI_IMAGE_PLUS "\xf3\xb0\xa1\xbc" // U+F087C +#define ICON_MDI_IMAGE_PLUS_OUTLINE "\xf3\xb1\xad\x86" // U+F1B46 +#define ICON_MDI_IMAGE_REFRESH "\xf3\xb1\xa7\xbe" // U+F19FE +#define ICON_MDI_IMAGE_REFRESH_OUTLINE "\xf3\xb1\xa7\xbf" // U+F19FF +#define ICON_MDI_IMAGE_REMOVE "\xf3\xb1\x90\x98" // U+F1418 +#define ICON_MDI_IMAGE_REMOVE_OUTLINE "\xf3\xb1\xad\x88" // U+F1B48 +#define ICON_MDI_IMAGE_SEARCH "\xf3\xb0\xa5\xb7" // U+F0977 +#define ICON_MDI_IMAGE_SEARCH_OUTLINE "\xf3\xb0\xa5\xb8" // U+F0978 +#define ICON_MDI_IMAGE_SIZE_SELECT_ACTUAL "\xf3\xb0\xb2\x8d" // U+F0C8D +#define ICON_MDI_IMAGE_SIZE_SELECT_LARGE "\xf3\xb0\xb2\x8e" // U+F0C8E +#define ICON_MDI_IMAGE_SIZE_SELECT_SMALL "\xf3\xb0\xb2\x8f" // U+F0C8F +#define ICON_MDI_IMAGE_SYNC "\xf3\xb1\xa8\x80" // U+F1A00 +#define ICON_MDI_IMAGE_SYNC_OUTLINE "\xf3\xb1\xa8\x81" // U+F1A01 +#define ICON_MDI_IMAGE_TEXT "\xf3\xb1\x98\x8d" // U+F160D +#define ICON_MDI_IMPORT "\xf3\xb0\x8b\xba" // U+F02FA +#define ICON_MDI_INBOX "\xf3\xb0\x9a\x87" // U+F0687 +#define ICON_MDI_INBOX_ARROW_DOWN "\xf3\xb0\x8b\xbb" // U+F02FB +#define ICON_MDI_INBOX_ARROW_DOWN_OUTLINE "\xf3\xb1\x89\xb0" // U+F1270 +#define ICON_MDI_INBOX_ARROW_UP "\xf3\xb0\x8f\x91" // U+F03D1 +#define ICON_MDI_INBOX_ARROW_UP_OUTLINE "\xf3\xb1\x89\xb1" // U+F1271 +#define ICON_MDI_INBOX_FULL "\xf3\xb1\x89\xb2" // U+F1272 +#define ICON_MDI_INBOX_FULL_OUTLINE "\xf3\xb1\x89\xb3" // U+F1273 +#define ICON_MDI_INBOX_MULTIPLE "\xf3\xb0\xa2\xb0" // U+F08B0 +#define ICON_MDI_INBOX_MULTIPLE_OUTLINE "\xf3\xb0\xae\xa8" // U+F0BA8 +#define ICON_MDI_INBOX_OUTLINE "\xf3\xb1\x89\xb4" // U+F1274 +#define ICON_MDI_INBOX_REMOVE "\xf3\xb1\x96\x9f" // U+F159F +#define ICON_MDI_INBOX_REMOVE_OUTLINE "\xf3\xb1\x96\xa0" // U+F15A0 +#define ICON_MDI_INCOGNITO "\xf3\xb0\x97\xb9" // U+F05F9 +#define ICON_MDI_INCOGNITO_CIRCLE "\xf3\xb1\x90\xa1" // U+F1421 +#define ICON_MDI_INCOGNITO_CIRCLE_OFF "\xf3\xb1\x90\xa2" // U+F1422 +#define ICON_MDI_INCOGNITO_OFF "\xf3\xb0\x81\xb5" // U+F0075 +#define ICON_MDI_INDUCTION "\xf3\xb1\xa1\x8c" // U+F184C +#define ICON_MDI_INFINITY "\xf3\xb0\x9b\xa4" // U+F06E4 +#define ICON_MDI_INFORMATION "\xf3\xb0\x8b\xbc" // U+F02FC +#define ICON_MDI_INFORMATION_BOX "\xf3\xb1\xb1\xa5" // U+F1C65 +#define ICON_MDI_INFORMATION_BOX_OUTLINE "\xf3\xb1\xb1\xa6" // U+F1C66 +#define ICON_MDI_INFORMATION_OFF "\xf3\xb1\x9e\x8c" // U+F178C +#define ICON_MDI_INFORMATION_OFF_OUTLINE "\xf3\xb1\x9e\x8d" // U+F178D +#define ICON_MDI_INFORMATION_OUTLINE "\xf3\xb0\x8b\xbd" // U+F02FD +#define ICON_MDI_INFORMATION_SLAB_BOX "\xf3\xb1\xb1\xa7" // U+F1C67 +#define ICON_MDI_INFORMATION_SLAB_BOX_OUTLINE "\xf3\xb1\xb1\xa8" // U+F1C68 +#define ICON_MDI_INFORMATION_SLAB_CIRCLE "\xf3\xb1\xb1\xa9" // U+F1C69 +#define ICON_MDI_INFORMATION_SLAB_CIRCLE_OUTLINE "\xf3\xb1\xb1\xaa" // U+F1C6A +#define ICON_MDI_INFORMATION_SLAB_SYMBOL "\xf3\xb1\xb1\xab" // U+F1C6B +#define ICON_MDI_INFORMATION_SYMBOL "\xf3\xb1\xb1\xac" // U+F1C6C +#define ICON_MDI_INFORMATION_VARIANT "\xf3\xb0\x99\x8e" // U+F064E +#define ICON_MDI_INFORMATION_VARIANT_BOX "\xf3\xb1\xb1\xad" // U+F1C6D +#define ICON_MDI_INFORMATION_VARIANT_BOX_OUTLINE "\xf3\xb1\xb1\xae" // U+F1C6E +#define ICON_MDI_INFORMATION_VARIANT_CIRCLE "\xf3\xb1\xb1\xaf" // U+F1C6F +#define ICON_MDI_INFORMATION_VARIANT_CIRCLE_OUTLINE "\xf3\xb1\xb1\xb0" // U+F1C70 +#define ICON_MDI_INSTAGRAM "\xf3\xb0\x8b\xbe" // U+F02FE +#define ICON_MDI_INSTRUMENT_TRIANGLE "\xf3\xb1\x81\x8e" // U+F104E +#define ICON_MDI_INTEGRATED_CIRCUIT_CHIP "\xf3\xb1\xa4\x93" // U+F1913 +#define ICON_MDI_INVERT_COLORS "\xf3\xb0\x8c\x81" // U+F0301 +#define ICON_MDI_INVERT_COLORS_OFF "\xf3\xb0\xb9\x8a" // U+F0E4A +#define ICON_MDI_IOBROKER "\xf3\xb1\x8b\xa8" // U+F12E8 +#define ICON_MDI_IP "\xf3\xb0\xa9\x9f" // U+F0A5F +#define ICON_MDI_IP_NETWORK "\xf3\xb0\xa9\xa0" // U+F0A60 +#define ICON_MDI_IP_NETWORK_OUTLINE "\xf3\xb0\xb2\x90" // U+F0C90 +#define ICON_MDI_IP_OUTLINE "\xf3\xb1\xa6\x82" // U+F1982 +#define ICON_MDI_IPOD "\xf3\xb0\xb2\x91" // U+F0C91 +#define ICON_MDI_IRON "\xf3\xb1\xa0\xa4" // U+F1824 +#define ICON_MDI_IRON_BOARD "\xf3\xb1\xa0\xb8" // U+F1838 +#define ICON_MDI_IRON_OUTLINE "\xf3\xb1\xa0\xa5" // U+F1825 +#define ICON_MDI_ISLAND "\xf3\xb1\x81\x8f" // U+F104F +#define ICON_MDI_ISLAND_VARIANT "\xf3\xb1\xb3\x86" // U+F1CC6 +#define ICON_MDI_IV_BAG "\xf3\xb1\x82\xb9" // U+F10B9 +#define ICON_MDI_JABBER "\xf3\xb0\xb7\x95" // U+F0DD5 +#define ICON_MDI_JEEPNEY "\xf3\xb0\x8c\x82" // U+F0302 +#define ICON_MDI_JELLYFISH "\xf3\xb0\xbc\x81" // U+F0F01 +#define ICON_MDI_JELLYFISH_OUTLINE "\xf3\xb0\xbc\x82" // U+F0F02 +#define ICON_MDI_JIRA "\xf3\xb0\x8c\x83" // U+F0303 +#define ICON_MDI_JQUERY "\xf3\xb0\xa1\xbd" // U+F087D +#define ICON_MDI_JSFIDDLE "\xf3\xb0\x8c\x84" // U+F0304 +#define ICON_MDI_JUMP_ROPE "\xf3\xb1\x8b\xbf" // U+F12FF +#define ICON_MDI_KABADDI "\xf3\xb0\xb6\x87" // U+F0D87 +#define ICON_MDI_KANGAROO "\xf3\xb1\x95\x98" // U+F1558 +#define ICON_MDI_KARATE "\xf3\xb0\xa0\xac" // U+F082C +#define ICON_MDI_KAYAKING "\xf3\xb0\xa2\xaf" // U+F08AF +#define ICON_MDI_KEG "\xf3\xb0\x8c\x85" // U+F0305 +#define ICON_MDI_KETTLE "\xf3\xb0\x97\xba" // U+F05FA +#define ICON_MDI_KETTLE_ALERT "\xf3\xb1\x8c\x97" // U+F1317 +#define ICON_MDI_KETTLE_ALERT_OUTLINE "\xf3\xb1\x8c\x98" // U+F1318 +#define ICON_MDI_KETTLE_OFF "\xf3\xb1\x8c\x9b" // U+F131B +#define ICON_MDI_KETTLE_OFF_OUTLINE "\xf3\xb1\x8c\x9c" // U+F131C +#define ICON_MDI_KETTLE_OUTLINE "\xf3\xb0\xbd\x96" // U+F0F56 +#define ICON_MDI_KETTLE_POUR_OVER "\xf3\xb1\x9c\xbc" // U+F173C +#define ICON_MDI_KETTLE_STEAM "\xf3\xb1\x8c\x99" // U+F1319 +#define ICON_MDI_KETTLE_STEAM_OUTLINE "\xf3\xb1\x8c\x9a" // U+F131A +#define ICON_MDI_KETTLEBELL "\xf3\xb1\x8c\x80" // U+F1300 +#define ICON_MDI_KEY "\xf3\xb0\x8c\x86" // U+F0306 +#define ICON_MDI_KEY_ALERT "\xf3\xb1\xa6\x83" // U+F1983 +#define ICON_MDI_KEY_ALERT_OUTLINE "\xf3\xb1\xa6\x84" // U+F1984 +#define ICON_MDI_KEY_ARROW_RIGHT "\xf3\xb1\x8c\x92" // U+F1312 +#define ICON_MDI_KEY_CHAIN "\xf3\xb1\x95\xb4" // U+F1574 +#define ICON_MDI_KEY_CHAIN_VARIANT "\xf3\xb1\x95\xb5" // U+F1575 +#define ICON_MDI_KEY_CHANGE "\xf3\xb0\x8c\x87" // U+F0307 +#define ICON_MDI_KEY_LINK "\xf3\xb1\x86\x9f" // U+F119F +#define ICON_MDI_KEY_MINUS "\xf3\xb0\x8c\x88" // U+F0308 +#define ICON_MDI_KEY_OUTLINE "\xf3\xb0\xb7\x96" // U+F0DD6 +#define ICON_MDI_KEY_PLUS "\xf3\xb0\x8c\x89" // U+F0309 +#define ICON_MDI_KEY_REMOVE "\xf3\xb0\x8c\x8a" // U+F030A +#define ICON_MDI_KEY_STAR "\xf3\xb1\x86\x9e" // U+F119E +#define ICON_MDI_KEY_VARIANT "\xf3\xb0\x8c\x8b" // U+F030B +#define ICON_MDI_KEY_WIRELESS "\xf3\xb0\xbf\x82" // U+F0FC2 +#define ICON_MDI_KEYBOARD "\xf3\xb0\x8c\x8c" // U+F030C +#define ICON_MDI_KEYBOARD_BACKSPACE "\xf3\xb0\x8c\x8d" // U+F030D +#define ICON_MDI_KEYBOARD_CAPS "\xf3\xb0\x8c\x8e" // U+F030E +#define ICON_MDI_KEYBOARD_CLOSE "\xf3\xb0\x8c\x8f" // U+F030F +#define ICON_MDI_KEYBOARD_CLOSE_OUTLINE "\xf3\xb1\xb0\x80" // U+F1C00 +#define ICON_MDI_KEYBOARD_ESC "\xf3\xb1\x8a\xb7" // U+F12B7 +#define ICON_MDI_KEYBOARD_F1 "\xf3\xb1\x8a\xab" // U+F12AB +#define ICON_MDI_KEYBOARD_F10 "\xf3\xb1\x8a\xb4" // U+F12B4 +#define ICON_MDI_KEYBOARD_F11 "\xf3\xb1\x8a\xb5" // U+F12B5 +#define ICON_MDI_KEYBOARD_F12 "\xf3\xb1\x8a\xb6" // U+F12B6 +#define ICON_MDI_KEYBOARD_F2 "\xf3\xb1\x8a\xac" // U+F12AC +#define ICON_MDI_KEYBOARD_F3 "\xf3\xb1\x8a\xad" // U+F12AD +#define ICON_MDI_KEYBOARD_F4 "\xf3\xb1\x8a\xae" // U+F12AE +#define ICON_MDI_KEYBOARD_F5 "\xf3\xb1\x8a\xaf" // U+F12AF +#define ICON_MDI_KEYBOARD_F6 "\xf3\xb1\x8a\xb0" // U+F12B0 +#define ICON_MDI_KEYBOARD_F7 "\xf3\xb1\x8a\xb1" // U+F12B1 +#define ICON_MDI_KEYBOARD_F8 "\xf3\xb1\x8a\xb2" // U+F12B2 +#define ICON_MDI_KEYBOARD_F9 "\xf3\xb1\x8a\xb3" // U+F12B3 +#define ICON_MDI_KEYBOARD_OFF "\xf3\xb0\x8c\x90" // U+F0310 +#define ICON_MDI_KEYBOARD_OFF_OUTLINE "\xf3\xb0\xb9\x8b" // U+F0E4B +#define ICON_MDI_KEYBOARD_OUTLINE "\xf3\xb0\xa5\xbb" // U+F097B +#define ICON_MDI_KEYBOARD_RETURN "\xf3\xb0\x8c\x91" // U+F0311 +#define ICON_MDI_KEYBOARD_SETTINGS "\xf3\xb0\xa7\xb9" // U+F09F9 +#define ICON_MDI_KEYBOARD_SETTINGS_OUTLINE "\xf3\xb0\xa7\xba" // U+F09FA +#define ICON_MDI_KEYBOARD_SPACE "\xf3\xb1\x81\x90" // U+F1050 +#define ICON_MDI_KEYBOARD_TAB "\xf3\xb0\x8c\x92" // U+F0312 +#define ICON_MDI_KEYBOARD_TAB_REVERSE "\xf3\xb0\x8c\xa5" // U+F0325 +#define ICON_MDI_KEYBOARD_VARIANT "\xf3\xb0\x8c\x93" // U+F0313 +#define ICON_MDI_KHANDA "\xf3\xb1\x83\xbd" // U+F10FD +#define ICON_MDI_KICKSTARTER "\xf3\xb0\x9d\x85" // U+F0745 +#define ICON_MDI_KITE "\xf3\xb1\xa6\x85" // U+F1985 +#define ICON_MDI_KITE_OUTLINE "\xf3\xb1\xa6\x86" // U+F1986 +#define ICON_MDI_KITESURFING "\xf3\xb1\x9d\x84" // U+F1744 +#define ICON_MDI_KLINGON "\xf3\xb1\x8d\x9b" // U+F135B +#define ICON_MDI_KNIFE "\xf3\xb0\xa7\xbb" // U+F09FB +#define ICON_MDI_KNIFE_MILITARY "\xf3\xb0\xa7\xbc" // U+F09FC +#define ICON_MDI_KNOB "\xf3\xb1\xae\x96" // U+F1B96 +#define ICON_MDI_KOALA "\xf3\xb1\x9c\xbf" // U+F173F +#define ICON_MDI_KODI "\xf3\xb0\x8c\x94" // U+F0314 +#define ICON_MDI_KUBERNETES "\xf3\xb1\x83\xbe" // U+F10FE +#define ICON_MDI_LABEL "\xf3\xb0\x8c\x95" // U+F0315 +#define ICON_MDI_LABEL_MULTIPLE "\xf3\xb1\x8d\xb5" // U+F1375 +#define ICON_MDI_LABEL_MULTIPLE_OUTLINE "\xf3\xb1\x8d\xb6" // U+F1376 +#define ICON_MDI_LABEL_OFF "\xf3\xb0\xab\x8b" // U+F0ACB +#define ICON_MDI_LABEL_OFF_OUTLINE "\xf3\xb0\xab\x8c" // U+F0ACC +#define ICON_MDI_LABEL_OUTLINE "\xf3\xb0\x8c\x96" // U+F0316 +#define ICON_MDI_LABEL_PERCENT "\xf3\xb1\x8b\xaa" // U+F12EA +#define ICON_MDI_LABEL_PERCENT_OUTLINE "\xf3\xb1\x8b\xab" // U+F12EB +#define ICON_MDI_LABEL_VARIANT "\xf3\xb0\xab\x8d" // U+F0ACD +#define ICON_MDI_LABEL_VARIANT_OUTLINE "\xf3\xb0\xab\x8e" // U+F0ACE +#define ICON_MDI_LADDER "\xf3\xb1\x96\xa2" // U+F15A2 +#define ICON_MDI_LADYBUG "\xf3\xb0\xa0\xad" // U+F082D +#define ICON_MDI_LAMBDA "\xf3\xb0\x98\xa7" // U+F0627 +#define ICON_MDI_LAMP "\xf3\xb0\x9a\xb5" // U+F06B5 +#define ICON_MDI_LAMP_OUTLINE "\xf3\xb1\x9f\x90" // U+F17D0 +#define ICON_MDI_LAMPS "\xf3\xb1\x95\xb6" // U+F1576 +#define ICON_MDI_LAMPS_OUTLINE "\xf3\xb1\x9f\x91" // U+F17D1 +#define ICON_MDI_LAN "\xf3\xb0\x8c\x97" // U+F0317 +#define ICON_MDI_LAN_CHECK "\xf3\xb1\x8a\xaa" // U+F12AA +#define ICON_MDI_LAN_CONNECT "\xf3\xb0\x8c\x98" // U+F0318 +#define ICON_MDI_LAN_DISCONNECT "\xf3\xb0\x8c\x99" // U+F0319 +#define ICON_MDI_LAN_PENDING "\xf3\xb0\x8c\x9a" // U+F031A +#define ICON_MDI_LAND_FIELDS "\xf3\xb1\xaa\xb2" // U+F1AB2 +#define ICON_MDI_LAND_PLOTS "\xf3\xb1\xaa\xb3" // U+F1AB3 +#define ICON_MDI_LAND_PLOTS_CIRCLE "\xf3\xb1\xaa\xb4" // U+F1AB4 +#define ICON_MDI_LAND_PLOTS_CIRCLE_VARIANT "\xf3\xb1\xaa\xb5" // U+F1AB5 +#define ICON_MDI_LAND_PLOTS_MARKER "\xf3\xb1\xb1\x9d" // U+F1C5D +#define ICON_MDI_LAND_ROWS_HORIZONTAL "\xf3\xb1\xaa\xb6" // U+F1AB6 +#define ICON_MDI_LAND_ROWS_VERTICAL "\xf3\xb1\xaa\xb7" // U+F1AB7 +#define ICON_MDI_LANDSLIDE "\xf3\xb1\xa9\x88" // U+F1A48 +#define ICON_MDI_LANDSLIDE_OUTLINE "\xf3\xb1\xa9\x89" // U+F1A49 +#define ICON_MDI_LANGUAGE_C "\xf3\xb0\x99\xb1" // U+F0671 +#define ICON_MDI_LANGUAGE_CPP "\xf3\xb0\x99\xb2" // U+F0672 +#define ICON_MDI_LANGUAGE_CSHARP "\xf3\xb0\x8c\x9b" // U+F031B +#define ICON_MDI_LANGUAGE_CSS3 "\xf3\xb0\x8c\x9c" // U+F031C +#define ICON_MDI_LANGUAGE_FORTRAN "\xf3\xb1\x88\x9a" // U+F121A +#define ICON_MDI_LANGUAGE_GO "\xf3\xb0\x9f\x93" // U+F07D3 +#define ICON_MDI_LANGUAGE_HASKELL "\xf3\xb0\xb2\x92" // U+F0C92 +#define ICON_MDI_LANGUAGE_HTML5 "\xf3\xb0\x8c\x9d" // U+F031D +#define ICON_MDI_LANGUAGE_JAVA "\xf3\xb0\xac\xb7" // U+F0B37 +#define ICON_MDI_LANGUAGE_JAVASCRIPT "\xf3\xb0\x8c\x9e" // U+F031E +#define ICON_MDI_LANGUAGE_KOTLIN "\xf3\xb1\x88\x99" // U+F1219 +#define ICON_MDI_LANGUAGE_LUA "\xf3\xb0\xa2\xb1" // U+F08B1 +#define ICON_MDI_LANGUAGE_MARKDOWN "\xf3\xb0\x8d\x94" // U+F0354 +#define ICON_MDI_LANGUAGE_MARKDOWN_OUTLINE "\xf3\xb0\xbd\x9b" // U+F0F5B +#define ICON_MDI_LANGUAGE_PHP "\xf3\xb0\x8c\x9f" // U+F031F +#define ICON_MDI_LANGUAGE_PYTHON "\xf3\xb0\x8c\xa0" // U+F0320 +#define ICON_MDI_LANGUAGE_R "\xf3\xb0\x9f\x94" // U+F07D4 +#define ICON_MDI_LANGUAGE_RUBY "\xf3\xb0\xb4\xad" // U+F0D2D +#define ICON_MDI_LANGUAGE_RUBY_ON_RAILS "\xf3\xb0\xab\x8f" // U+F0ACF +#define ICON_MDI_LANGUAGE_RUST "\xf3\xb1\x98\x97" // U+F1617 +#define ICON_MDI_LANGUAGE_SWIFT "\xf3\xb0\x9b\xa5" // U+F06E5 +#define ICON_MDI_LANGUAGE_TYPESCRIPT "\xf3\xb0\x9b\xa6" // U+F06E6 +#define ICON_MDI_LANGUAGE_XAML "\xf3\xb0\x99\xb3" // U+F0673 +#define ICON_MDI_LAPTOP "\xf3\xb0\x8c\xa2" // U+F0322 +#define ICON_MDI_LAPTOP_ACCOUNT "\xf3\xb1\xa9\x8a" // U+F1A4A +#define ICON_MDI_LAPTOP_OFF "\xf3\xb0\x9b\xa7" // U+F06E7 +#define ICON_MDI_LARAVEL "\xf3\xb0\xab\x90" // U+F0AD0 +#define ICON_MDI_LASER_POINTER "\xf3\xb1\x92\x84" // U+F1484 +#define ICON_MDI_LASSO "\xf3\xb0\xbc\x83" // U+F0F03 +#define ICON_MDI_LASTPASS "\xf3\xb0\x91\x86" // U+F0446 +#define ICON_MDI_LATITUDE "\xf3\xb0\xbd\x97" // U+F0F57 +#define ICON_MDI_LAUNCH "\xf3\xb0\x8c\xa7" // U+F0327 +#define ICON_MDI_LAVA_LAMP "\xf3\xb0\x9f\x95" // U+F07D5 +#define ICON_MDI_LAYERS "\xf3\xb0\x8c\xa8" // U+F0328 +#define ICON_MDI_LAYERS_EDIT "\xf3\xb1\xa2\x92" // U+F1892 +#define ICON_MDI_LAYERS_MINUS "\xf3\xb0\xb9\x8c" // U+F0E4C +#define ICON_MDI_LAYERS_OFF "\xf3\xb0\x8c\xa9" // U+F0329 +#define ICON_MDI_LAYERS_OFF_OUTLINE "\xf3\xb0\xa7\xbd" // U+F09FD +#define ICON_MDI_LAYERS_OUTLINE "\xf3\xb0\xa7\xbe" // U+F09FE +#define ICON_MDI_LAYERS_PLUS "\xf3\xb0\xb9\x8d" // U+F0E4D +#define ICON_MDI_LAYERS_REMOVE "\xf3\xb0\xb9\x8e" // U+F0E4E +#define ICON_MDI_LAYERS_SEARCH "\xf3\xb1\x88\x86" // U+F1206 +#define ICON_MDI_LAYERS_SEARCH_OUTLINE "\xf3\xb1\x88\x87" // U+F1207 +#define ICON_MDI_LAYERS_TRIPLE "\xf3\xb0\xbd\x98" // U+F0F58 +#define ICON_MDI_LAYERS_TRIPLE_OUTLINE "\xf3\xb0\xbd\x99" // U+F0F59 +#define ICON_MDI_LEAD_PENCIL "\xf3\xb0\x99\x8f" // U+F064F +#define ICON_MDI_LEAF "\xf3\xb0\x8c\xaa" // U+F032A +#define ICON_MDI_LEAF_CIRCLE "\xf3\xb1\xa4\x85" // U+F1905 +#define ICON_MDI_LEAF_CIRCLE_OUTLINE "\xf3\xb1\xa4\x86" // U+F1906 +#define ICON_MDI_LEAF_MAPLE "\xf3\xb0\xb2\x93" // U+F0C93 +#define ICON_MDI_LEAF_MAPLE_OFF "\xf3\xb1\x8b\x9a" // U+F12DA +#define ICON_MDI_LEAF_OFF "\xf3\xb1\x8b\x99" // U+F12D9 +#define ICON_MDI_LEAK "\xf3\xb0\xb7\x97" // U+F0DD7 +#define ICON_MDI_LEAK_OFF "\xf3\xb0\xb7\x98" // U+F0DD8 +#define ICON_MDI_LECTERN "\xf3\xb1\xab\xb0" // U+F1AF0 +#define ICON_MDI_LED_OFF "\xf3\xb0\x8c\xab" // U+F032B +#define ICON_MDI_LED_ON "\xf3\xb0\x8c\xac" // U+F032C +#define ICON_MDI_LED_OUTLINE "\xf3\xb0\x8c\xad" // U+F032D +#define ICON_MDI_LED_STRIP "\xf3\xb0\x9f\x96" // U+F07D6 +#define ICON_MDI_LED_STRIP_VARIANT "\xf3\xb1\x81\x91" // U+F1051 +#define ICON_MDI_LED_STRIP_VARIANT_OFF "\xf3\xb1\xa9\x8b" // U+F1A4B +#define ICON_MDI_LED_VARIANT_OFF "\xf3\xb0\x8c\xae" // U+F032E +#define ICON_MDI_LED_VARIANT_ON "\xf3\xb0\x8c\xaf" // U+F032F +#define ICON_MDI_LED_VARIANT_OUTLINE "\xf3\xb0\x8c\xb0" // U+F0330 +#define ICON_MDI_LEEK "\xf3\xb1\x85\xbd" // U+F117D +#define ICON_MDI_LESS_THAN "\xf3\xb0\xa5\xbc" // U+F097C +#define ICON_MDI_LESS_THAN_OR_EQUAL "\xf3\xb0\xa5\xbd" // U+F097D +#define ICON_MDI_LIBRARY "\xf3\xb0\x8c\xb1" // U+F0331 +#define ICON_MDI_LIBRARY_OUTLINE "\xf3\xb1\xa8\xa2" // U+F1A22 +#define ICON_MDI_LIBRARY_SHELVES "\xf3\xb0\xae\xa9" // U+F0BA9 +#define ICON_MDI_LICENSE "\xf3\xb0\xbf\x83" // U+F0FC3 +#define ICON_MDI_LIFEBUOY "\xf3\xb0\xa1\xbe" // U+F087E +#define ICON_MDI_LIGHT_FLOOD_DOWN "\xf3\xb1\xa6\x87" // U+F1987 +#define ICON_MDI_LIGHT_FLOOD_UP "\xf3\xb1\xa6\x88" // U+F1988 +#define ICON_MDI_LIGHT_RECESSED "\xf3\xb1\x9e\x9b" // U+F179B +#define ICON_MDI_LIGHT_SWITCH "\xf3\xb0\xa5\xbe" // U+F097E +#define ICON_MDI_LIGHT_SWITCH_OFF "\xf3\xb1\xa8\xa4" // U+F1A24 +#define ICON_MDI_LIGHTBULB "\xf3\xb0\x8c\xb5" // U+F0335 +#define ICON_MDI_LIGHTBULB_ALERT "\xf3\xb1\xa7\xa1" // U+F19E1 +#define ICON_MDI_LIGHTBULB_ALERT_OUTLINE "\xf3\xb1\xa7\xa2" // U+F19E2 +#define ICON_MDI_LIGHTBULB_AUTO "\xf3\xb1\xa0\x80" // U+F1800 +#define ICON_MDI_LIGHTBULB_AUTO_OUTLINE "\xf3\xb1\xa0\x81" // U+F1801 +#define ICON_MDI_LIGHTBULB_CFL "\xf3\xb1\x88\x88" // U+F1208 +#define ICON_MDI_LIGHTBULB_CFL_OFF "\xf3\xb1\x88\x89" // U+F1209 +#define ICON_MDI_LIGHTBULB_CFL_SPIRAL "\xf3\xb1\x89\xb5" // U+F1275 +#define ICON_MDI_LIGHTBULB_CFL_SPIRAL_OFF "\xf3\xb1\x8b\x83" // U+F12C3 +#define ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE "\xf3\xb1\xa0\x84" // U+F1804 +#define ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE_OUTLINE "\xf3\xb1\xa0\x85" // U+F1805 +#define ICON_MDI_LIGHTBULB_GROUP "\xf3\xb1\x89\x93" // U+F1253 +#define ICON_MDI_LIGHTBULB_GROUP_OFF "\xf3\xb1\x8b\x8d" // U+F12CD +#define ICON_MDI_LIGHTBULB_GROUP_OFF_OUTLINE "\xf3\xb1\x8b\x8e" // U+F12CE +#define ICON_MDI_LIGHTBULB_GROUP_OUTLINE "\xf3\xb1\x89\x94" // U+F1254 +#define ICON_MDI_LIGHTBULB_MULTIPLE "\xf3\xb1\x89\x95" // U+F1255 +#define ICON_MDI_LIGHTBULB_MULTIPLE_OFF "\xf3\xb1\x8b\x8f" // U+F12CF +#define ICON_MDI_LIGHTBULB_MULTIPLE_OFF_OUTLINE "\xf3\xb1\x8b\x90" // U+F12D0 +#define ICON_MDI_LIGHTBULB_MULTIPLE_OUTLINE "\xf3\xb1\x89\x96" // U+F1256 +#define ICON_MDI_LIGHTBULB_NIGHT "\xf3\xb1\xa9\x8c" // U+F1A4C +#define ICON_MDI_LIGHTBULB_NIGHT_OUTLINE "\xf3\xb1\xa9\x8d" // U+F1A4D +#define ICON_MDI_LIGHTBULB_OFF "\xf3\xb0\xb9\x8f" // U+F0E4F +#define ICON_MDI_LIGHTBULB_OFF_OUTLINE "\xf3\xb0\xb9\x90" // U+F0E50 +#define ICON_MDI_LIGHTBULB_ON "\xf3\xb0\x9b\xa8" // U+F06E8 +#define ICON_MDI_LIGHTBULB_ON_10 "\xf3\xb1\xa9\x8e" // U+F1A4E +#define ICON_MDI_LIGHTBULB_ON_20 "\xf3\xb1\xa9\x8f" // U+F1A4F +#define ICON_MDI_LIGHTBULB_ON_30 "\xf3\xb1\xa9\x90" // U+F1A50 +#define ICON_MDI_LIGHTBULB_ON_40 "\xf3\xb1\xa9\x91" // U+F1A51 +#define ICON_MDI_LIGHTBULB_ON_50 "\xf3\xb1\xa9\x92" // U+F1A52 +#define ICON_MDI_LIGHTBULB_ON_60 "\xf3\xb1\xa9\x93" // U+F1A53 +#define ICON_MDI_LIGHTBULB_ON_70 "\xf3\xb1\xa9\x94" // U+F1A54 +#define ICON_MDI_LIGHTBULB_ON_80 "\xf3\xb1\xa9\x95" // U+F1A55 +#define ICON_MDI_LIGHTBULB_ON_90 "\xf3\xb1\xa9\x96" // U+F1A56 +#define ICON_MDI_LIGHTBULB_ON_OUTLINE "\xf3\xb0\x9b\xa9" // U+F06E9 +#define ICON_MDI_LIGHTBULB_OUTLINE "\xf3\xb0\x8c\xb6" // U+F0336 +#define ICON_MDI_LIGHTBULB_QUESTION "\xf3\xb1\xa7\xa3" // U+F19E3 +#define ICON_MDI_LIGHTBULB_QUESTION_OUTLINE "\xf3\xb1\xa7\xa4" // U+F19E4 +#define ICON_MDI_LIGHTBULB_SPOT "\xf3\xb1\x9f\xb4" // U+F17F4 +#define ICON_MDI_LIGHTBULB_SPOT_OFF "\xf3\xb1\x9f\xb5" // U+F17F5 +#define ICON_MDI_LIGHTBULB_VARIANT "\xf3\xb1\xa0\x82" // U+F1802 +#define ICON_MDI_LIGHTBULB_VARIANT_OUTLINE "\xf3\xb1\xa0\x83" // U+F1803 +#define ICON_MDI_LIGHTHOUSE "\xf3\xb0\xa7\xbf" // U+F09FF +#define ICON_MDI_LIGHTHOUSE_ON "\xf3\xb0\xa8\x80" // U+F0A00 +#define ICON_MDI_LIGHTNING_BOLT "\xf3\xb1\x90\x8b" // U+F140B +#define ICON_MDI_LIGHTNING_BOLT_CIRCLE "\xf3\xb0\xa0\xa0" // U+F0820 +#define ICON_MDI_LIGHTNING_BOLT_OUTLINE "\xf3\xb1\x90\x8c" // U+F140C +#define ICON_MDI_LINE_SCAN "\xf3\xb0\x98\xa4" // U+F0624 +#define ICON_MDI_LINGERIE "\xf3\xb1\x91\xb6" // U+F1476 +#define ICON_MDI_LINK "\xf3\xb0\x8c\xb7" // U+F0337 +#define ICON_MDI_LINK_BOX "\xf3\xb0\xb4\x9a" // U+F0D1A +#define ICON_MDI_LINK_BOX_OUTLINE "\xf3\xb0\xb4\x9b" // U+F0D1B +#define ICON_MDI_LINK_BOX_VARIANT "\xf3\xb0\xb4\x9c" // U+F0D1C +#define ICON_MDI_LINK_BOX_VARIANT_OUTLINE "\xf3\xb0\xb4\x9d" // U+F0D1D +#define ICON_MDI_LINK_CIRCLE "\xf3\xb1\xb2\xac" // U+F1CAC +#define ICON_MDI_LINK_CIRCLE_OUTLINE "\xf3\xb1\xb2\xad" // U+F1CAD +#define ICON_MDI_LINK_EDIT "\xf3\xb1\xb2\xae" // U+F1CAE +#define ICON_MDI_LINK_LOCK "\xf3\xb1\x82\xba" // U+F10BA +#define ICON_MDI_LINK_OFF "\xf3\xb0\x8c\xb8" // U+F0338 +#define ICON_MDI_LINK_PLUS "\xf3\xb0\xb2\x94" // U+F0C94 +#define ICON_MDI_LINK_VARIANT "\xf3\xb0\x8c\xb9" // U+F0339 +#define ICON_MDI_LINK_VARIANT_MINUS "\xf3\xb1\x83\xbf" // U+F10FF +#define ICON_MDI_LINK_VARIANT_OFF "\xf3\xb0\x8c\xba" // U+F033A +#define ICON_MDI_LINK_VARIANT_PLUS "\xf3\xb1\x84\x80" // U+F1100 +#define ICON_MDI_LINK_VARIANT_REMOVE "\xf3\xb1\x84\x81" // U+F1101 +#define ICON_MDI_LINKEDIN "\xf3\xb0\x8c\xbb" // U+F033B +#define ICON_MDI_LINUX "\xf3\xb0\x8c\xbd" // U+F033D +#define ICON_MDI_LINUX_MINT "\xf3\xb0\xa3\xad" // U+F08ED +#define ICON_MDI_LIPSTICK "\xf3\xb1\x8e\xb5" // U+F13B5 +#define ICON_MDI_LIQUID_SPOT "\xf3\xb1\xa0\xa6" // U+F1826 +#define ICON_MDI_LIQUOR "\xf3\xb1\xa4\x9e" // U+F191E +#define ICON_MDI_LIST_BOX "\xf3\xb1\xad\xbb" // U+F1B7B +#define ICON_MDI_LIST_BOX_OUTLINE "\xf3\xb1\xad\xbc" // U+F1B7C +#define ICON_MDI_LIST_STATUS "\xf3\xb1\x96\xab" // U+F15AB +#define ICON_MDI_LITECOIN "\xf3\xb0\xa9\xa1" // U+F0A61 +#define ICON_MDI_LOADING "\xf3\xb0\x9d\xb2" // U+F0772 +#define ICON_MDI_LOCATION_ENTER "\xf3\xb0\xbf\x84" // U+F0FC4 +#define ICON_MDI_LOCATION_EXIT "\xf3\xb0\xbf\x85" // U+F0FC5 +#define ICON_MDI_LOCK "\xf3\xb0\x8c\xbe" // U+F033E +#define ICON_MDI_LOCK_ALERT "\xf3\xb0\xa3\xae" // U+F08EE +#define ICON_MDI_LOCK_ALERT_OUTLINE "\xf3\xb1\x97\x91" // U+F15D1 +#define ICON_MDI_LOCK_CHECK "\xf3\xb1\x8e\x9a" // U+F139A +#define ICON_MDI_LOCK_CHECK_OUTLINE "\xf3\xb1\x9a\xa8" // U+F16A8 +#define ICON_MDI_LOCK_CLOCK "\xf3\xb0\xa5\xbf" // U+F097F +#define ICON_MDI_LOCK_MINUS "\xf3\xb1\x9a\xa9" // U+F16A9 +#define ICON_MDI_LOCK_MINUS_OUTLINE "\xf3\xb1\x9a\xaa" // U+F16AA +#define ICON_MDI_LOCK_OFF "\xf3\xb1\x99\xb1" // U+F1671 +#define ICON_MDI_LOCK_OFF_OUTLINE "\xf3\xb1\x99\xb2" // U+F1672 +#define ICON_MDI_LOCK_OPEN "\xf3\xb0\x8c\xbf" // U+F033F +#define ICON_MDI_LOCK_OPEN_ALERT "\xf3\xb1\x8e\x9b" // U+F139B +#define ICON_MDI_LOCK_OPEN_ALERT_OUTLINE "\xf3\xb1\x97\x92" // U+F15D2 +#define ICON_MDI_LOCK_OPEN_CHECK "\xf3\xb1\x8e\x9c" // U+F139C +#define ICON_MDI_LOCK_OPEN_CHECK_OUTLINE "\xf3\xb1\x9a\xab" // U+F16AB +#define ICON_MDI_LOCK_OPEN_MINUS "\xf3\xb1\x9a\xac" // U+F16AC +#define ICON_MDI_LOCK_OPEN_MINUS_OUTLINE "\xf3\xb1\x9a\xad" // U+F16AD +#define ICON_MDI_LOCK_OPEN_OUTLINE "\xf3\xb0\x8d\x80" // U+F0340 +#define ICON_MDI_LOCK_OPEN_PLUS "\xf3\xb1\x9a\xae" // U+F16AE +#define ICON_MDI_LOCK_OPEN_PLUS_OUTLINE "\xf3\xb1\x9a\xaf" // U+F16AF +#define ICON_MDI_LOCK_OPEN_REMOVE "\xf3\xb1\x9a\xb0" // U+F16B0 +#define ICON_MDI_LOCK_OPEN_REMOVE_OUTLINE "\xf3\xb1\x9a\xb1" // U+F16B1 +#define ICON_MDI_LOCK_OPEN_VARIANT "\xf3\xb0\xbf\x86" // U+F0FC6 +#define ICON_MDI_LOCK_OPEN_VARIANT_OUTLINE "\xf3\xb0\xbf\x87" // U+F0FC7 +#define ICON_MDI_LOCK_OUTLINE "\xf3\xb0\x8d\x81" // U+F0341 +#define ICON_MDI_LOCK_PATTERN "\xf3\xb0\x9b\xaa" // U+F06EA +#define ICON_MDI_LOCK_PERCENT "\xf3\xb1\xb0\x92" // U+F1C12 +#define ICON_MDI_LOCK_PERCENT_OPEN "\xf3\xb1\xb0\x93" // U+F1C13 +#define ICON_MDI_LOCK_PERCENT_OPEN_OUTLINE "\xf3\xb1\xb0\x94" // U+F1C14 +#define ICON_MDI_LOCK_PERCENT_OPEN_VARIANT "\xf3\xb1\xb0\x95" // U+F1C15 +#define ICON_MDI_LOCK_PERCENT_OPEN_VARIANT_OUTLINE "\xf3\xb1\xb0\x96" // U+F1C16 +#define ICON_MDI_LOCK_PERCENT_OUTLINE "\xf3\xb1\xb0\x97" // U+F1C17 +#define ICON_MDI_LOCK_PLUS "\xf3\xb0\x97\xbb" // U+F05FB +#define ICON_MDI_LOCK_PLUS_OUTLINE "\xf3\xb1\x9a\xb2" // U+F16B2 +#define ICON_MDI_LOCK_QUESTION "\xf3\xb0\xa3\xaf" // U+F08EF +#define ICON_MDI_LOCK_REMOVE "\xf3\xb1\x9a\xb3" // U+F16B3 +#define ICON_MDI_LOCK_REMOVE_OUTLINE "\xf3\xb1\x9a\xb4" // U+F16B4 +#define ICON_MDI_LOCK_RESET "\xf3\xb0\x9d\xb3" // U+F0773 +#define ICON_MDI_LOCK_SMART "\xf3\xb0\xa2\xb2" // U+F08B2 +#define ICON_MDI_LOCKER "\xf3\xb0\x9f\x97" // U+F07D7 +#define ICON_MDI_LOCKER_MULTIPLE "\xf3\xb0\x9f\x98" // U+F07D8 +#define ICON_MDI_LOGIN "\xf3\xb0\x8d\x82" // U+F0342 +#define ICON_MDI_LOGIN_VARIANT "\xf3\xb0\x97\xbc" // U+F05FC +#define ICON_MDI_LOGOUT "\xf3\xb0\x8d\x83" // U+F0343 +#define ICON_MDI_LOGOUT_VARIANT "\xf3\xb0\x97\xbd" // U+F05FD +#define ICON_MDI_LONGITUDE "\xf3\xb0\xbd\x9a" // U+F0F5A +#define ICON_MDI_LOOKS "\xf3\xb0\x8d\x84" // U+F0344 +#define ICON_MDI_LOTION "\xf3\xb1\x96\x82" // U+F1582 +#define ICON_MDI_LOTION_OUTLINE "\xf3\xb1\x96\x83" // U+F1583 +#define ICON_MDI_LOTION_PLUS "\xf3\xb1\x96\x84" // U+F1584 +#define ICON_MDI_LOTION_PLUS_OUTLINE "\xf3\xb1\x96\x85" // U+F1585 +#define ICON_MDI_LOUPE "\xf3\xb0\x8d\x85" // U+F0345 +#define ICON_MDI_LUMX "\xf3\xb0\x8d\x86" // U+F0346 +#define ICON_MDI_LUNGS "\xf3\xb1\x82\x84" // U+F1084 +#define ICON_MDI_MACE "\xf3\xb1\xa1\x83" // U+F1843 +#define ICON_MDI_MAGAZINE_PISTOL "\xf3\xb0\x8c\xa4" // U+F0324 +#define ICON_MDI_MAGAZINE_RIFLE "\xf3\xb0\x8c\xa3" // U+F0323 +#define ICON_MDI_MAGIC_STAFF "\xf3\xb1\xa1\x84" // U+F1844 +#define ICON_MDI_MAGNET "\xf3\xb0\x8d\x87" // U+F0347 +#define ICON_MDI_MAGNET_ON "\xf3\xb0\x8d\x88" // U+F0348 +#define ICON_MDI_MAGNIFY "\xf3\xb0\x8d\x89" // U+F0349 +#define ICON_MDI_MAGNIFY_CLOSE "\xf3\xb0\xa6\x80" // U+F0980 +#define ICON_MDI_MAGNIFY_EXPAND "\xf3\xb1\xa1\xb4" // U+F1874 +#define ICON_MDI_MAGNIFY_MINUS "\xf3\xb0\x8d\x8a" // U+F034A +#define ICON_MDI_MAGNIFY_MINUS_CURSOR "\xf3\xb0\xa9\xa2" // U+F0A62 +#define ICON_MDI_MAGNIFY_MINUS_OUTLINE "\xf3\xb0\x9b\xac" // U+F06EC +#define ICON_MDI_MAGNIFY_PLUS "\xf3\xb0\x8d\x8b" // U+F034B +#define ICON_MDI_MAGNIFY_PLUS_CURSOR "\xf3\xb0\xa9\xa3" // U+F0A63 +#define ICON_MDI_MAGNIFY_PLUS_OUTLINE "\xf3\xb0\x9b\xad" // U+F06ED +#define ICON_MDI_MAGNIFY_REMOVE_CURSOR "\xf3\xb1\x88\x8c" // U+F120C +#define ICON_MDI_MAGNIFY_REMOVE_OUTLINE "\xf3\xb1\x88\x8d" // U+F120D +#define ICON_MDI_MAGNIFY_SCAN "\xf3\xb1\x89\xb6" // U+F1276 +#define ICON_MDI_MAIL "\xf3\xb0\xba\xbb" // U+F0EBB +#define ICON_MDI_MAILBOX "\xf3\xb0\x9b\xae" // U+F06EE +#define ICON_MDI_MAILBOX_OPEN "\xf3\xb0\xb6\x88" // U+F0D88 +#define ICON_MDI_MAILBOX_OPEN_OUTLINE "\xf3\xb0\xb6\x89" // U+F0D89 +#define ICON_MDI_MAILBOX_OPEN_UP "\xf3\xb0\xb6\x8a" // U+F0D8A +#define ICON_MDI_MAILBOX_OPEN_UP_OUTLINE "\xf3\xb0\xb6\x8b" // U+F0D8B +#define ICON_MDI_MAILBOX_OUTLINE "\xf3\xb0\xb6\x8c" // U+F0D8C +#define ICON_MDI_MAILBOX_UP "\xf3\xb0\xb6\x8d" // U+F0D8D +#define ICON_MDI_MAILBOX_UP_OUTLINE "\xf3\xb0\xb6\x8e" // U+F0D8E +#define ICON_MDI_MANJARO "\xf3\xb1\x98\x8a" // U+F160A +#define ICON_MDI_MAP "\xf3\xb0\x8d\x8d" // U+F034D +#define ICON_MDI_MAP_CHECK "\xf3\xb0\xba\xbc" // U+F0EBC +#define ICON_MDI_MAP_CHECK_OUTLINE "\xf3\xb0\xba\xbd" // U+F0EBD +#define ICON_MDI_MAP_CLOCK "\xf3\xb0\xb4\x9e" // U+F0D1E +#define ICON_MDI_MAP_CLOCK_OUTLINE "\xf3\xb0\xb4\x9f" // U+F0D1F +#define ICON_MDI_MAP_LEGEND "\xf3\xb0\xa8\x81" // U+F0A01 +#define ICON_MDI_MAP_MARKER "\xf3\xb0\x8d\x8e" // U+F034E +#define ICON_MDI_MAP_MARKER_ACCOUNT "\xf3\xb1\xa3\xa3" // U+F18E3 +#define ICON_MDI_MAP_MARKER_ACCOUNT_OUTLINE "\xf3\xb1\xa3\xa4" // U+F18E4 +#define ICON_MDI_MAP_MARKER_ALERT "\xf3\xb0\xbc\x85" // U+F0F05 +#define ICON_MDI_MAP_MARKER_ALERT_OUTLINE "\xf3\xb0\xbc\x86" // U+F0F06 +#define ICON_MDI_MAP_MARKER_CHECK "\xf3\xb0\xb2\x95" // U+F0C95 +#define ICON_MDI_MAP_MARKER_CHECK_OUTLINE "\xf3\xb1\x8b\xbb" // U+F12FB +#define ICON_MDI_MAP_MARKER_CIRCLE "\xf3\xb0\x8d\x8f" // U+F034F +#define ICON_MDI_MAP_MARKER_DISTANCE "\xf3\xb0\xa3\xb0" // U+F08F0 +#define ICON_MDI_MAP_MARKER_DOWN "\xf3\xb1\x84\x82" // U+F1102 +#define ICON_MDI_MAP_MARKER_LEFT "\xf3\xb1\x8b\x9b" // U+F12DB +#define ICON_MDI_MAP_MARKER_LEFT_OUTLINE "\xf3\xb1\x8b\x9d" // U+F12DD +#define ICON_MDI_MAP_MARKER_MINUS "\xf3\xb0\x99\x90" // U+F0650 +#define ICON_MDI_MAP_MARKER_MINUS_OUTLINE "\xf3\xb1\x8b\xb9" // U+F12F9 +#define ICON_MDI_MAP_MARKER_MULTIPLE "\xf3\xb0\x8d\x90" // U+F0350 +#define ICON_MDI_MAP_MARKER_MULTIPLE_OUTLINE "\xf3\xb1\x89\xb7" // U+F1277 +#define ICON_MDI_MAP_MARKER_OFF "\xf3\xb0\x8d\x91" // U+F0351 +#define ICON_MDI_MAP_MARKER_OFF_OUTLINE "\xf3\xb1\x8b\xbd" // U+F12FD +#define ICON_MDI_MAP_MARKER_OUTLINE "\xf3\xb0\x9f\x99" // U+F07D9 +#define ICON_MDI_MAP_MARKER_PATH "\xf3\xb0\xb4\xa0" // U+F0D20 +#define ICON_MDI_MAP_MARKER_PLUS "\xf3\xb0\x99\x91" // U+F0651 +#define ICON_MDI_MAP_MARKER_PLUS_OUTLINE "\xf3\xb1\x8b\xb8" // U+F12F8 +#define ICON_MDI_MAP_MARKER_QUESTION "\xf3\xb0\xbc\x87" // U+F0F07 +#define ICON_MDI_MAP_MARKER_QUESTION_OUTLINE "\xf3\xb0\xbc\x88" // U+F0F08 +#define ICON_MDI_MAP_MARKER_RADIUS "\xf3\xb0\x8d\x92" // U+F0352 +#define ICON_MDI_MAP_MARKER_RADIUS_OUTLINE "\xf3\xb1\x8b\xbc" // U+F12FC +#define ICON_MDI_MAP_MARKER_REMOVE "\xf3\xb0\xbc\x89" // U+F0F09 +#define ICON_MDI_MAP_MARKER_REMOVE_OUTLINE "\xf3\xb1\x8b\xba" // U+F12FA +#define ICON_MDI_MAP_MARKER_REMOVE_VARIANT "\xf3\xb0\xbc\x8a" // U+F0F0A +#define ICON_MDI_MAP_MARKER_RIGHT "\xf3\xb1\x8b\x9c" // U+F12DC +#define ICON_MDI_MAP_MARKER_RIGHT_OUTLINE "\xf3\xb1\x8b\x9e" // U+F12DE +#define ICON_MDI_MAP_MARKER_STAR "\xf3\xb1\x98\x88" // U+F1608 +#define ICON_MDI_MAP_MARKER_STAR_OUTLINE "\xf3\xb1\x98\x89" // U+F1609 +#define ICON_MDI_MAP_MARKER_UP "\xf3\xb1\x84\x83" // U+F1103 +#define ICON_MDI_MAP_MINUS "\xf3\xb0\xa6\x81" // U+F0981 +#define ICON_MDI_MAP_OUTLINE "\xf3\xb0\xa6\x82" // U+F0982 +#define ICON_MDI_MAP_PLUS "\xf3\xb0\xa6\x83" // U+F0983 +#define ICON_MDI_MAP_SEARCH "\xf3\xb0\xa6\x84" // U+F0984 +#define ICON_MDI_MAP_SEARCH_OUTLINE "\xf3\xb0\xa6\x85" // U+F0985 +#define ICON_MDI_MAPBOX "\xf3\xb0\xae\xaa" // U+F0BAA +#define ICON_MDI_MARGIN "\xf3\xb0\x8d\x93" // U+F0353 +#define ICON_MDI_MARKER "\xf3\xb0\x99\x92" // U+F0652 +#define ICON_MDI_MARKER_CANCEL "\xf3\xb0\xb7\x99" // U+F0DD9 +#define ICON_MDI_MARKER_CHECK "\xf3\xb0\x8d\x95" // U+F0355 +#define ICON_MDI_MASTODON "\xf3\xb0\xab\x91" // U+F0AD1 +#define ICON_MDI_MATERIAL_DESIGN "\xf3\xb0\xa6\x86" // U+F0986 +#define ICON_MDI_MATERIAL_UI "\xf3\xb0\x8d\x97" // U+F0357 +#define ICON_MDI_MATH_COMPASS "\xf3\xb0\x8d\x98" // U+F0358 +#define ICON_MDI_MATH_COS "\xf3\xb0\xb2\x96" // U+F0C96 +#define ICON_MDI_MATH_INTEGRAL "\xf3\xb0\xbf\x88" // U+F0FC8 +#define ICON_MDI_MATH_INTEGRAL_BOX "\xf3\xb0\xbf\x89" // U+F0FC9 +#define ICON_MDI_MATH_LOG "\xf3\xb1\x82\x85" // U+F1085 +#define ICON_MDI_MATH_NORM "\xf3\xb0\xbf\x8a" // U+F0FCA +#define ICON_MDI_MATH_NORM_BOX "\xf3\xb0\xbf\x8b" // U+F0FCB +#define ICON_MDI_MATH_SIN "\xf3\xb0\xb2\x97" // U+F0C97 +#define ICON_MDI_MATH_TAN "\xf3\xb0\xb2\x98" // U+F0C98 +#define ICON_MDI_MATRIX "\xf3\xb0\x98\xa8" // U+F0628 +#define ICON_MDI_MEDAL "\xf3\xb0\xa6\x87" // U+F0987 +#define ICON_MDI_MEDAL_OUTLINE "\xf3\xb1\x8c\xa6" // U+F1326 +#define ICON_MDI_MEDICAL_BAG "\xf3\xb0\x9b\xaf" // U+F06EF +#define ICON_MDI_MEDICAL_COTTON_SWAB "\xf3\xb1\xaa\xb8" // U+F1AB8 +#define ICON_MDI_MEDICATION "\xf3\xb1\xac\x94" // U+F1B14 +#define ICON_MDI_MEDICATION_OUTLINE "\xf3\xb1\xac\x95" // U+F1B15 +#define ICON_MDI_MEDITATION "\xf3\xb1\x85\xbb" // U+F117B +#define ICON_MDI_MEMORY "\xf3\xb0\x8d\x9b" // U+F035B +#define ICON_MDI_MEMORY_ARROW_DOWN "\xf3\xb1\xb2\xa6" // U+F1CA6 +#define ICON_MDI_MENORAH "\xf3\xb1\x9f\x94" // U+F17D4 +#define ICON_MDI_MENORAH_FIRE "\xf3\xb1\x9f\x95" // U+F17D5 +#define ICON_MDI_MENU "\xf3\xb0\x8d\x9c" // U+F035C +#define ICON_MDI_MENU_CLOSE "\xf3\xb1\xb2\x90" // U+F1C90 +#define ICON_MDI_MENU_DOWN "\xf3\xb0\x8d\x9d" // U+F035D +#define ICON_MDI_MENU_DOWN_OUTLINE "\xf3\xb0\x9a\xb6" // U+F06B6 +#define ICON_MDI_MENU_LEFT "\xf3\xb0\x8d\x9e" // U+F035E +#define ICON_MDI_MENU_LEFT_OUTLINE "\xf3\xb0\xa8\x82" // U+F0A02 +#define ICON_MDI_MENU_OPEN "\xf3\xb0\xae\xab" // U+F0BAB +#define ICON_MDI_MENU_RIGHT "\xf3\xb0\x8d\x9f" // U+F035F +#define ICON_MDI_MENU_RIGHT_OUTLINE "\xf3\xb0\xa8\x83" // U+F0A03 +#define ICON_MDI_MENU_SWAP "\xf3\xb0\xa9\xa4" // U+F0A64 +#define ICON_MDI_MENU_SWAP_OUTLINE "\xf3\xb0\xa9\xa5" // U+F0A65 +#define ICON_MDI_MENU_UP "\xf3\xb0\x8d\xa0" // U+F0360 +#define ICON_MDI_MENU_UP_OUTLINE "\xf3\xb0\x9a\xb7" // U+F06B7 +#define ICON_MDI_MERGE "\xf3\xb0\xbd\x9c" // U+F0F5C +#define ICON_MDI_MESSAGE "\xf3\xb0\x8d\xa1" // U+F0361 +#define ICON_MDI_MESSAGE_ALERT "\xf3\xb0\x8d\xa2" // U+F0362 +#define ICON_MDI_MESSAGE_ALERT_OUTLINE "\xf3\xb0\xa8\x84" // U+F0A04 +#define ICON_MDI_MESSAGE_ARROW_LEFT "\xf3\xb1\x8b\xb2" // U+F12F2 +#define ICON_MDI_MESSAGE_ARROW_LEFT_OUTLINE "\xf3\xb1\x8b\xb3" // U+F12F3 +#define ICON_MDI_MESSAGE_ARROW_RIGHT "\xf3\xb1\x8b\xb4" // U+F12F4 +#define ICON_MDI_MESSAGE_ARROW_RIGHT_OUTLINE "\xf3\xb1\x8b\xb5" // U+F12F5 +#define ICON_MDI_MESSAGE_BADGE "\xf3\xb1\xa5\x81" // U+F1941 +#define ICON_MDI_MESSAGE_BADGE_OUTLINE "\xf3\xb1\xa5\x82" // U+F1942 +#define ICON_MDI_MESSAGE_BOOKMARK "\xf3\xb1\x96\xac" // U+F15AC +#define ICON_MDI_MESSAGE_BOOKMARK_OUTLINE "\xf3\xb1\x96\xad" // U+F15AD +#define ICON_MDI_MESSAGE_BULLETED "\xf3\xb0\x9a\xa2" // U+F06A2 +#define ICON_MDI_MESSAGE_BULLETED_OFF "\xf3\xb0\x9a\xa3" // U+F06A3 +#define ICON_MDI_MESSAGE_CHECK "\xf3\xb1\xae\x8a" // U+F1B8A +#define ICON_MDI_MESSAGE_CHECK_OUTLINE "\xf3\xb1\xae\x8b" // U+F1B8B +#define ICON_MDI_MESSAGE_COG "\xf3\xb0\x9b\xb1" // U+F06F1 +#define ICON_MDI_MESSAGE_COG_OUTLINE "\xf3\xb1\x85\xb2" // U+F1172 +#define ICON_MDI_MESSAGE_DRAW "\xf3\xb0\x8d\xa3" // U+F0363 +#define ICON_MDI_MESSAGE_FAST "\xf3\xb1\xa7\x8c" // U+F19CC +#define ICON_MDI_MESSAGE_FAST_OUTLINE "\xf3\xb1\xa7\x8d" // U+F19CD +#define ICON_MDI_MESSAGE_FLASH "\xf3\xb1\x96\xa9" // U+F15A9 +#define ICON_MDI_MESSAGE_FLASH_OUTLINE "\xf3\xb1\x96\xaa" // U+F15AA +#define ICON_MDI_MESSAGE_IMAGE "\xf3\xb0\x8d\xa4" // U+F0364 +#define ICON_MDI_MESSAGE_IMAGE_OUTLINE "\xf3\xb1\x85\xac" // U+F116C +#define ICON_MDI_MESSAGE_LOCK "\xf3\xb0\xbf\x8c" // U+F0FCC +#define ICON_MDI_MESSAGE_LOCK_OUTLINE "\xf3\xb1\x85\xad" // U+F116D +#define ICON_MDI_MESSAGE_MINUS "\xf3\xb1\x85\xae" // U+F116E +#define ICON_MDI_MESSAGE_MINUS_OUTLINE "\xf3\xb1\x85\xaf" // U+F116F +#define ICON_MDI_MESSAGE_OFF "\xf3\xb1\x99\x8d" // U+F164D +#define ICON_MDI_MESSAGE_OFF_OUTLINE "\xf3\xb1\x99\x8e" // U+F164E +#define ICON_MDI_MESSAGE_OUTLINE "\xf3\xb0\x8d\xa5" // U+F0365 +#define ICON_MDI_MESSAGE_PLUS "\xf3\xb0\x99\x93" // U+F0653 +#define ICON_MDI_MESSAGE_PLUS_OUTLINE "\xf3\xb1\x82\xbb" // U+F10BB +#define ICON_MDI_MESSAGE_PROCESSING "\xf3\xb0\x8d\xa6" // U+F0366 +#define ICON_MDI_MESSAGE_PROCESSING_OUTLINE "\xf3\xb1\x85\xb0" // U+F1170 +#define ICON_MDI_MESSAGE_QUESTION "\xf3\xb1\x9c\xba" // U+F173A +#define ICON_MDI_MESSAGE_QUESTION_OUTLINE "\xf3\xb1\x9c\xbb" // U+F173B +#define ICON_MDI_MESSAGE_REPLY "\xf3\xb0\x8d\xa7" // U+F0367 +#define ICON_MDI_MESSAGE_REPLY_OUTLINE "\xf3\xb1\x9c\xbd" // U+F173D +#define ICON_MDI_MESSAGE_REPLY_TEXT "\xf3\xb0\x8d\xa8" // U+F0368 +#define ICON_MDI_MESSAGE_REPLY_TEXT_OUTLINE "\xf3\xb1\x9c\xbe" // U+F173E +#define ICON_MDI_MESSAGE_SETTINGS "\xf3\xb0\x9b\xb0" // U+F06F0 +#define ICON_MDI_MESSAGE_SETTINGS_OUTLINE "\xf3\xb1\x85\xb1" // U+F1171 +#define ICON_MDI_MESSAGE_STAR "\xf3\xb0\x9a\x9a" // U+F069A +#define ICON_MDI_MESSAGE_STAR_OUTLINE "\xf3\xb1\x89\x90" // U+F1250 +#define ICON_MDI_MESSAGE_TEXT "\xf3\xb0\x8d\xa9" // U+F0369 +#define ICON_MDI_MESSAGE_TEXT_CLOCK "\xf3\xb1\x85\xb3" // U+F1173 +#define ICON_MDI_MESSAGE_TEXT_CLOCK_OUTLINE "\xf3\xb1\x85\xb4" // U+F1174 +#define ICON_MDI_MESSAGE_TEXT_FAST "\xf3\xb1\xa7\x8e" // U+F19CE +#define ICON_MDI_MESSAGE_TEXT_FAST_OUTLINE "\xf3\xb1\xa7\x8f" // U+F19CF +#define ICON_MDI_MESSAGE_TEXT_LOCK "\xf3\xb0\xbf\x8d" // U+F0FCD +#define ICON_MDI_MESSAGE_TEXT_LOCK_OUTLINE "\xf3\xb1\x85\xb5" // U+F1175 +#define ICON_MDI_MESSAGE_TEXT_OUTLINE "\xf3\xb0\x8d\xaa" // U+F036A +#define ICON_MDI_MESSAGE_VIDEO "\xf3\xb0\x8d\xab" // U+F036B +#define ICON_MDI_METEOR "\xf3\xb0\x98\xa9" // U+F0629 +#define ICON_MDI_METER_ELECTRIC "\xf3\xb1\xa9\x97" // U+F1A57 +#define ICON_MDI_METER_ELECTRIC_OUTLINE "\xf3\xb1\xa9\x98" // U+F1A58 +#define ICON_MDI_METER_GAS "\xf3\xb1\xa9\x99" // U+F1A59 +#define ICON_MDI_METER_GAS_OUTLINE "\xf3\xb1\xa9\x9a" // U+F1A5A +#define ICON_MDI_METRONOME "\xf3\xb0\x9f\x9a" // U+F07DA +#define ICON_MDI_METRONOME_TICK "\xf3\xb0\x9f\x9b" // U+F07DB +#define ICON_MDI_MICRO_SD "\xf3\xb0\x9f\x9c" // U+F07DC +#define ICON_MDI_MICROPHONE "\xf3\xb0\x8d\xac" // U+F036C +#define ICON_MDI_MICROPHONE_MESSAGE "\xf3\xb0\x94\x8a" // U+F050A +#define ICON_MDI_MICROPHONE_MESSAGE_OFF "\xf3\xb0\x94\x8b" // U+F050B +#define ICON_MDI_MICROPHONE_MINUS "\xf3\xb0\xa2\xb3" // U+F08B3 +#define ICON_MDI_MICROPHONE_OFF "\xf3\xb0\x8d\xad" // U+F036D +#define ICON_MDI_MICROPHONE_OUTLINE "\xf3\xb0\x8d\xae" // U+F036E +#define ICON_MDI_MICROPHONE_PLUS "\xf3\xb0\xa2\xb4" // U+F08B4 +#define ICON_MDI_MICROPHONE_QUESTION "\xf3\xb1\xa6\x89" // U+F1989 +#define ICON_MDI_MICROPHONE_QUESTION_OUTLINE "\xf3\xb1\xa6\x8a" // U+F198A +#define ICON_MDI_MICROPHONE_SETTINGS "\xf3\xb0\x8d\xaf" // U+F036F +#define ICON_MDI_MICROPHONE_VARIANT "\xf3\xb0\x8d\xb0" // U+F0370 +#define ICON_MDI_MICROPHONE_VARIANT_OFF "\xf3\xb0\x8d\xb1" // U+F0371 +#define ICON_MDI_MICROSCOPE "\xf3\xb0\x99\x94" // U+F0654 +#define ICON_MDI_MICROSOFT "\xf3\xb0\x8d\xb2" // U+F0372 +#define ICON_MDI_MICROSOFT_ACCESS "\xf3\xb1\x8e\x8e" // U+F138E +#define ICON_MDI_MICROSOFT_AZURE "\xf3\xb0\xa0\x85" // U+F0805 +#define ICON_MDI_MICROSOFT_AZURE_DEVOPS "\xf3\xb0\xbf\x95" // U+F0FD5 +#define ICON_MDI_MICROSOFT_BING "\xf3\xb0\x82\xa4" // U+F00A4 +#define ICON_MDI_MICROSOFT_DYNAMICS_365 "\xf3\xb0\xa6\x88" // U+F0988 +#define ICON_MDI_MICROSOFT_EDGE "\xf3\xb0\x87\xa9" // U+F01E9 +#define ICON_MDI_MICROSOFT_EXCEL "\xf3\xb1\x8e\x8f" // U+F138F +#define ICON_MDI_MICROSOFT_INTERNET_EXPLORER "\xf3\xb0\x8c\x80" // U+F0300 +#define ICON_MDI_MICROSOFT_OFFICE "\xf3\xb0\x8f\x86" // U+F03C6 +#define ICON_MDI_MICROSOFT_ONEDRIVE "\xf3\xb0\x8f\x8a" // U+F03CA +#define ICON_MDI_MICROSOFT_ONENOTE "\xf3\xb0\x9d\x87" // U+F0747 +#define ICON_MDI_MICROSOFT_OUTLOOK "\xf3\xb0\xb4\xa2" // U+F0D22 +#define ICON_MDI_MICROSOFT_POWERPOINT "\xf3\xb1\x8e\x90" // U+F1390 +#define ICON_MDI_MICROSOFT_SHAREPOINT "\xf3\xb1\x8e\x91" // U+F1391 +#define ICON_MDI_MICROSOFT_TEAMS "\xf3\xb0\x8a\xbb" // U+F02BB +#define ICON_MDI_MICROSOFT_VISUAL_STUDIO "\xf3\xb0\x98\x90" // U+F0610 +#define ICON_MDI_MICROSOFT_VISUAL_STUDIO_CODE "\xf3\xb0\xa8\x9e" // U+F0A1E +#define ICON_MDI_MICROSOFT_WINDOWS "\xf3\xb0\x96\xb3" // U+F05B3 +#define ICON_MDI_MICROSOFT_WINDOWS_CLASSIC "\xf3\xb0\xa8\xa1" // U+F0A21 +#define ICON_MDI_MICROSOFT_WORD "\xf3\xb1\x8e\x92" // U+F1392 +#define ICON_MDI_MICROSOFT_XBOX "\xf3\xb0\x96\xb9" // U+F05B9 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER "\xf3\xb0\x96\xba" // U+F05BA +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_ALERT "\xf3\xb0\x9d\x8b" // U+F074B +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_CHARGING "\xf3\xb0\xa8\xa2" // U+F0A22 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_EMPTY "\xf3\xb0\x9d\x8c" // U+F074C +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_FULL "\xf3\xb0\x9d\x8d" // U+F074D +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_LOW "\xf3\xb0\x9d\x8e" // U+F074E +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_MEDIUM "\xf3\xb0\x9d\x8f" // U+F074F +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_UNKNOWN "\xf3\xb0\x9d\x90" // U+F0750 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_MENU "\xf3\xb0\xb9\xaf" // U+F0E6F +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_OFF "\xf3\xb0\x96\xbb" // U+F05BB +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_VIEW "\xf3\xb0\xb9\xb0" // U+F0E70 +#define ICON_MDI_MICROWAVE "\xf3\xb0\xb2\x99" // U+F0C99 +#define ICON_MDI_MICROWAVE_OFF "\xf3\xb1\x90\xa3" // U+F1423 +#define ICON_MDI_MIDDLEWARE "\xf3\xb0\xbd\x9d" // U+F0F5D +#define ICON_MDI_MIDDLEWARE_OUTLINE "\xf3\xb0\xbd\x9e" // U+F0F5E +#define ICON_MDI_MIDI "\xf3\xb0\xa3\xb1" // U+F08F1 +#define ICON_MDI_MIDI_PORT "\xf3\xb0\xa3\xb2" // U+F08F2 +#define ICON_MDI_MINE "\xf3\xb0\xb7\x9a" // U+F0DDA +#define ICON_MDI_MINECRAFT "\xf3\xb0\x8d\xb3" // U+F0373 +#define ICON_MDI_MINI_SD "\xf3\xb0\xa8\x85" // U+F0A05 +#define ICON_MDI_MINIDISC "\xf3\xb0\xa8\x86" // U+F0A06 +#define ICON_MDI_MINUS "\xf3\xb0\x8d\xb4" // U+F0374 +#define ICON_MDI_MINUS_BOX "\xf3\xb0\x8d\xb5" // U+F0375 +#define ICON_MDI_MINUS_BOX_MULTIPLE "\xf3\xb1\x85\x81" // U+F1141 +#define ICON_MDI_MINUS_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x82" // U+F1142 +#define ICON_MDI_MINUS_BOX_OUTLINE "\xf3\xb0\x9b\xb2" // U+F06F2 +#define ICON_MDI_MINUS_CIRCLE "\xf3\xb0\x8d\xb6" // U+F0376 +#define ICON_MDI_MINUS_CIRCLE_MULTIPLE "\xf3\xb0\x8d\x9a" // U+F035A +#define ICON_MDI_MINUS_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\xab\x93" // U+F0AD3 +#define ICON_MDI_MINUS_CIRCLE_OFF "\xf3\xb1\x91\x99" // U+F1459 +#define ICON_MDI_MINUS_CIRCLE_OFF_OUTLINE "\xf3\xb1\x91\x9a" // U+F145A +#define ICON_MDI_MINUS_CIRCLE_OUTLINE "\xf3\xb0\x8d\xb7" // U+F0377 +#define ICON_MDI_MINUS_NETWORK "\xf3\xb0\x8d\xb8" // U+F0378 +#define ICON_MDI_MINUS_NETWORK_OUTLINE "\xf3\xb0\xb2\x9a" // U+F0C9A +#define ICON_MDI_MINUS_THICK "\xf3\xb1\x98\xb9" // U+F1639 +#define ICON_MDI_MIRROR "\xf3\xb1\x87\xbd" // U+F11FD +#define ICON_MDI_MIRROR_RECTANGLE "\xf3\xb1\x9e\x9f" // U+F179F +#define ICON_MDI_MIRROR_VARIANT "\xf3\xb1\x9e\xa0" // U+F17A0 +#define ICON_MDI_MIXED_MARTIAL_ARTS "\xf3\xb0\xb6\x8f" // U+F0D8F +#define ICON_MDI_MIXED_REALITY "\xf3\xb0\xa1\xbf" // U+F087F +#define ICON_MDI_MOLECULE "\xf3\xb0\xae\xac" // U+F0BAC +#define ICON_MDI_MOLECULE_CO "\xf3\xb1\x8b\xbe" // U+F12FE +#define ICON_MDI_MOLECULE_CO2 "\xf3\xb0\x9f\xa4" // U+F07E4 +#define ICON_MDI_MONITOR "\xf3\xb0\x8d\xb9" // U+F0379 +#define ICON_MDI_MONITOR_ACCOUNT "\xf3\xb1\xa9\x9b" // U+F1A5B +#define ICON_MDI_MONITOR_ARROW_DOWN "\xf3\xb1\xa7\x90" // U+F19D0 +#define ICON_MDI_MONITOR_ARROW_DOWN_VARIANT "\xf3\xb1\xa7\x91" // U+F19D1 +#define ICON_MDI_MONITOR_CELLPHONE "\xf3\xb0\xa6\x89" // U+F0989 +#define ICON_MDI_MONITOR_CELLPHONE_STAR "\xf3\xb0\xa6\x8a" // U+F098A +#define ICON_MDI_MONITOR_DASHBOARD "\xf3\xb0\xa8\x87" // U+F0A07 +#define ICON_MDI_MONITOR_EDIT "\xf3\xb1\x8b\x86" // U+F12C6 +#define ICON_MDI_MONITOR_EYE "\xf3\xb1\x8e\xb4" // U+F13B4 +#define ICON_MDI_MONITOR_LOCK "\xf3\xb0\xb7\x9b" // U+F0DDB +#define ICON_MDI_MONITOR_MULTIPLE "\xf3\xb0\x8d\xba" // U+F037A +#define ICON_MDI_MONITOR_OFF "\xf3\xb0\xb6\x90" // U+F0D90 +#define ICON_MDI_MONITOR_SCREENSHOT "\xf3\xb0\xb9\x91" // U+F0E51 +#define ICON_MDI_MONITOR_SHARE "\xf3\xb1\x92\x83" // U+F1483 +#define ICON_MDI_MONITOR_SHIMMER "\xf3\xb1\x84\x84" // U+F1104 +#define ICON_MDI_MONITOR_SMALL "\xf3\xb1\xa1\xb6" // U+F1876 +#define ICON_MDI_MONITOR_SPEAKER "\xf3\xb0\xbd\x9f" // U+F0F5F +#define ICON_MDI_MONITOR_SPEAKER_OFF "\xf3\xb0\xbd\xa0" // U+F0F60 +#define ICON_MDI_MONITOR_STAR "\xf3\xb0\xb7\x9c" // U+F0DDC +#define ICON_MDI_MONITOR_VERTICAL "\xf3\xb1\xb0\xb3" // U+F1C33 +#define ICON_MDI_MOON_FIRST_QUARTER "\xf3\xb0\xbd\xa1" // U+F0F61 +#define ICON_MDI_MOON_FULL "\xf3\xb0\xbd\xa2" // U+F0F62 +#define ICON_MDI_MOON_LAST_QUARTER "\xf3\xb0\xbd\xa3" // U+F0F63 +#define ICON_MDI_MOON_NEW "\xf3\xb0\xbd\xa4" // U+F0F64 +#define ICON_MDI_MOON_WANING_CRESCENT "\xf3\xb0\xbd\xa5" // U+F0F65 +#define ICON_MDI_MOON_WANING_GIBBOUS "\xf3\xb0\xbd\xa6" // U+F0F66 +#define ICON_MDI_MOON_WAXING_CRESCENT "\xf3\xb0\xbd\xa7" // U+F0F67 +#define ICON_MDI_MOON_WAXING_GIBBOUS "\xf3\xb0\xbd\xa8" // U+F0F68 +#define ICON_MDI_MOPED "\xf3\xb1\x82\x86" // U+F1086 +#define ICON_MDI_MOPED_ELECTRIC "\xf3\xb1\x96\xb7" // U+F15B7 +#define ICON_MDI_MOPED_ELECTRIC_OUTLINE "\xf3\xb1\x96\xb8" // U+F15B8 +#define ICON_MDI_MOPED_OUTLINE "\xf3\xb1\x96\xb9" // U+F15B9 +#define ICON_MDI_MORE "\xf3\xb0\x8d\xbb" // U+F037B +#define ICON_MDI_MORTAR_PESTLE "\xf3\xb1\x9d\x88" // U+F1748 +#define ICON_MDI_MORTAR_PESTLE_PLUS "\xf3\xb0\x8f\xb1" // U+F03F1 +#define ICON_MDI_MOSQUE "\xf3\xb0\xb5\x85" // U+F0D45 +#define ICON_MDI_MOSQUE_OUTLINE "\xf3\xb1\xa0\xa7" // U+F1827 +#define ICON_MDI_MOTHER_HEART "\xf3\xb1\x8c\x94" // U+F1314 +#define ICON_MDI_MOTHER_NURSE "\xf3\xb0\xb4\xa1" // U+F0D21 +#define ICON_MDI_MOTION "\xf3\xb1\x96\xb2" // U+F15B2 +#define ICON_MDI_MOTION_OUTLINE "\xf3\xb1\x96\xb3" // U+F15B3 +#define ICON_MDI_MOTION_PAUSE "\xf3\xb1\x96\x90" // U+F1590 +#define ICON_MDI_MOTION_PAUSE_OUTLINE "\xf3\xb1\x96\x92" // U+F1592 +#define ICON_MDI_MOTION_PLAY "\xf3\xb1\x96\x8f" // U+F158F +#define ICON_MDI_MOTION_PLAY_OUTLINE "\xf3\xb1\x96\x91" // U+F1591 +#define ICON_MDI_MOTION_SENSOR "\xf3\xb0\xb6\x91" // U+F0D91 +#define ICON_MDI_MOTION_SENSOR_OFF "\xf3\xb1\x90\xb5" // U+F1435 +#define ICON_MDI_MOTORBIKE "\xf3\xb0\x8d\xbc" // U+F037C +#define ICON_MDI_MOTORBIKE_ELECTRIC "\xf3\xb1\x96\xba" // U+F15BA +#define ICON_MDI_MOTORBIKE_OFF "\xf3\xb1\xac\x96" // U+F1B16 +#define ICON_MDI_MOUSE "\xf3\xb0\x8d\xbd" // U+F037D +#define ICON_MDI_MOUSE_BLUETOOTH "\xf3\xb0\xa6\x8b" // U+F098B +#define ICON_MDI_MOUSE_MOVE_DOWN "\xf3\xb1\x95\x90" // U+F1550 +#define ICON_MDI_MOUSE_MOVE_UP "\xf3\xb1\x95\x91" // U+F1551 +#define ICON_MDI_MOUSE_MOVE_VERTICAL "\xf3\xb1\x95\x92" // U+F1552 +#define ICON_MDI_MOUSE_OFF "\xf3\xb0\x8d\xbe" // U+F037E +#define ICON_MDI_MOUSE_VARIANT "\xf3\xb0\x8d\xbf" // U+F037F +#define ICON_MDI_MOUSE_VARIANT_OFF "\xf3\xb0\x8e\x80" // U+F0380 +#define ICON_MDI_MOVE_RESIZE "\xf3\xb0\x99\x95" // U+F0655 +#define ICON_MDI_MOVE_RESIZE_VARIANT "\xf3\xb0\x99\x96" // U+F0656 +#define ICON_MDI_MOVIE "\xf3\xb0\x8e\x81" // U+F0381 +#define ICON_MDI_MOVIE_CHECK "\xf3\xb1\x9b\xb3" // U+F16F3 +#define ICON_MDI_MOVIE_CHECK_OUTLINE "\xf3\xb1\x9b\xb4" // U+F16F4 +#define ICON_MDI_MOVIE_COG "\xf3\xb1\x9b\xb5" // U+F16F5 +#define ICON_MDI_MOVIE_COG_OUTLINE "\xf3\xb1\x9b\xb6" // U+F16F6 +#define ICON_MDI_MOVIE_EDIT "\xf3\xb1\x84\xa2" // U+F1122 +#define ICON_MDI_MOVIE_EDIT_OUTLINE "\xf3\xb1\x84\xa3" // U+F1123 +#define ICON_MDI_MOVIE_FILTER "\xf3\xb1\x84\xa4" // U+F1124 +#define ICON_MDI_MOVIE_FILTER_OUTLINE "\xf3\xb1\x84\xa5" // U+F1125 +#define ICON_MDI_MOVIE_MINUS "\xf3\xb1\x9b\xb7" // U+F16F7 +#define ICON_MDI_MOVIE_MINUS_OUTLINE "\xf3\xb1\x9b\xb8" // U+F16F8 +#define ICON_MDI_MOVIE_OFF "\xf3\xb1\x9b\xb9" // U+F16F9 +#define ICON_MDI_MOVIE_OFF_OUTLINE "\xf3\xb1\x9b\xba" // U+F16FA +#define ICON_MDI_MOVIE_OPEN "\xf3\xb0\xbf\x8e" // U+F0FCE +#define ICON_MDI_MOVIE_OPEN_CHECK "\xf3\xb1\x9b\xbb" // U+F16FB +#define ICON_MDI_MOVIE_OPEN_CHECK_OUTLINE "\xf3\xb1\x9b\xbc" // U+F16FC +#define ICON_MDI_MOVIE_OPEN_COG "\xf3\xb1\x9b\xbd" // U+F16FD +#define ICON_MDI_MOVIE_OPEN_COG_OUTLINE "\xf3\xb1\x9b\xbe" // U+F16FE +#define ICON_MDI_MOVIE_OPEN_EDIT "\xf3\xb1\x9b\xbf" // U+F16FF +#define ICON_MDI_MOVIE_OPEN_EDIT_OUTLINE "\xf3\xb1\x9c\x80" // U+F1700 +#define ICON_MDI_MOVIE_OPEN_MINUS "\xf3\xb1\x9c\x81" // U+F1701 +#define ICON_MDI_MOVIE_OPEN_MINUS_OUTLINE "\xf3\xb1\x9c\x82" // U+F1702 +#define ICON_MDI_MOVIE_OPEN_OFF "\xf3\xb1\x9c\x83" // U+F1703 +#define ICON_MDI_MOVIE_OPEN_OFF_OUTLINE "\xf3\xb1\x9c\x84" // U+F1704 +#define ICON_MDI_MOVIE_OPEN_OUTLINE "\xf3\xb0\xbf\x8f" // U+F0FCF +#define ICON_MDI_MOVIE_OPEN_PLAY "\xf3\xb1\x9c\x85" // U+F1705 +#define ICON_MDI_MOVIE_OPEN_PLAY_OUTLINE "\xf3\xb1\x9c\x86" // U+F1706 +#define ICON_MDI_MOVIE_OPEN_PLUS "\xf3\xb1\x9c\x87" // U+F1707 +#define ICON_MDI_MOVIE_OPEN_PLUS_OUTLINE "\xf3\xb1\x9c\x88" // U+F1708 +#define ICON_MDI_MOVIE_OPEN_REMOVE "\xf3\xb1\x9c\x89" // U+F1709 +#define ICON_MDI_MOVIE_OPEN_REMOVE_OUTLINE "\xf3\xb1\x9c\x8a" // U+F170A +#define ICON_MDI_MOVIE_OPEN_SETTINGS "\xf3\xb1\x9c\x8b" // U+F170B +#define ICON_MDI_MOVIE_OPEN_SETTINGS_OUTLINE "\xf3\xb1\x9c\x8c" // U+F170C +#define ICON_MDI_MOVIE_OPEN_STAR "\xf3\xb1\x9c\x8d" // U+F170D +#define ICON_MDI_MOVIE_OPEN_STAR_OUTLINE "\xf3\xb1\x9c\x8e" // U+F170E +#define ICON_MDI_MOVIE_OUTLINE "\xf3\xb0\xb7\x9d" // U+F0DDD +#define ICON_MDI_MOVIE_PLAY "\xf3\xb1\x9c\x8f" // U+F170F +#define ICON_MDI_MOVIE_PLAY_OUTLINE "\xf3\xb1\x9c\x90" // U+F1710 +#define ICON_MDI_MOVIE_PLUS "\xf3\xb1\x9c\x91" // U+F1711 +#define ICON_MDI_MOVIE_PLUS_OUTLINE "\xf3\xb1\x9c\x92" // U+F1712 +#define ICON_MDI_MOVIE_REMOVE "\xf3\xb1\x9c\x93" // U+F1713 +#define ICON_MDI_MOVIE_REMOVE_OUTLINE "\xf3\xb1\x9c\x94" // U+F1714 +#define ICON_MDI_MOVIE_ROLL "\xf3\xb0\x9f\x9e" // U+F07DE +#define ICON_MDI_MOVIE_SEARCH "\xf3\xb1\x87\x92" // U+F11D2 +#define ICON_MDI_MOVIE_SEARCH_OUTLINE "\xf3\xb1\x87\x93" // U+F11D3 +#define ICON_MDI_MOVIE_SETTINGS "\xf3\xb1\x9c\x95" // U+F1715 +#define ICON_MDI_MOVIE_SETTINGS_OUTLINE "\xf3\xb1\x9c\x96" // U+F1716 +#define ICON_MDI_MOVIE_STAR "\xf3\xb1\x9c\x97" // U+F1717 +#define ICON_MDI_MOVIE_STAR_OUTLINE "\xf3\xb1\x9c\x98" // U+F1718 +#define ICON_MDI_MOWER "\xf3\xb1\x99\xaf" // U+F166F +#define ICON_MDI_MOWER_BAG "\xf3\xb1\x99\xb0" // U+F1670 +#define ICON_MDI_MOWER_BAG_ON "\xf3\xb1\xad\xa0" // U+F1B60 +#define ICON_MDI_MOWER_ON "\xf3\xb1\xad\x9f" // U+F1B5F +#define ICON_MDI_MUFFIN "\xf3\xb0\xa6\x8c" // U+F098C +#define ICON_MDI_MULTICAST "\xf3\xb1\xa2\x93" // U+F1893 +#define ICON_MDI_MULTIMEDIA "\xf3\xb1\xae\x97" // U+F1B97 +#define ICON_MDI_MULTIPLICATION "\xf3\xb0\x8e\x82" // U+F0382 +#define ICON_MDI_MULTIPLICATION_BOX "\xf3\xb0\x8e\x83" // U+F0383 +#define ICON_MDI_MUSHROOM "\xf3\xb0\x9f\x9f" // U+F07DF +#define ICON_MDI_MUSHROOM_OFF "\xf3\xb1\x8f\xba" // U+F13FA +#define ICON_MDI_MUSHROOM_OFF_OUTLINE "\xf3\xb1\x8f\xbb" // U+F13FB +#define ICON_MDI_MUSHROOM_OUTLINE "\xf3\xb0\x9f\xa0" // U+F07E0 +#define ICON_MDI_MUSIC "\xf3\xb0\x9d\x9a" // U+F075A +#define ICON_MDI_MUSIC_ACCIDENTAL_DOUBLE_FLAT "\xf3\xb0\xbd\xa9" // U+F0F69 +#define ICON_MDI_MUSIC_ACCIDENTAL_DOUBLE_SHARP "\xf3\xb0\xbd\xaa" // U+F0F6A +#define ICON_MDI_MUSIC_ACCIDENTAL_FLAT "\xf3\xb0\xbd\xab" // U+F0F6B +#define ICON_MDI_MUSIC_ACCIDENTAL_NATURAL "\xf3\xb0\xbd\xac" // U+F0F6C +#define ICON_MDI_MUSIC_ACCIDENTAL_SHARP "\xf3\xb0\xbd\xad" // U+F0F6D +#define ICON_MDI_MUSIC_BOX "\xf3\xb0\x8e\x84" // U+F0384 +#define ICON_MDI_MUSIC_BOX_MULTIPLE "\xf3\xb0\x8c\xb3" // U+F0333 +#define ICON_MDI_MUSIC_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xbc\x84" // U+F0F04 +#define ICON_MDI_MUSIC_BOX_OUTLINE "\xf3\xb0\x8e\x85" // U+F0385 +#define ICON_MDI_MUSIC_CIRCLE "\xf3\xb0\x8e\x86" // U+F0386 +#define ICON_MDI_MUSIC_CIRCLE_OUTLINE "\xf3\xb0\xab\x94" // U+F0AD4 +#define ICON_MDI_MUSIC_CLEF_ALTO "\xf3\xb0\xbd\xae" // U+F0F6E +#define ICON_MDI_MUSIC_CLEF_BASS "\xf3\xb0\xbd\xaf" // U+F0F6F +#define ICON_MDI_MUSIC_CLEF_TREBLE "\xf3\xb0\xbd\xb0" // U+F0F70 +#define ICON_MDI_MUSIC_NOTE "\xf3\xb0\x8e\x87" // U+F0387 +#define ICON_MDI_MUSIC_NOTE_BLUETOOTH "\xf3\xb0\x97\xbe" // U+F05FE +#define ICON_MDI_MUSIC_NOTE_BLUETOOTH_OFF "\xf3\xb0\x97\xbf" // U+F05FF +#define ICON_MDI_MUSIC_NOTE_EIGHTH "\xf3\xb0\x8e\x88" // U+F0388 +#define ICON_MDI_MUSIC_NOTE_EIGHTH_DOTTED "\xf3\xb0\xbd\xb1" // U+F0F71 +#define ICON_MDI_MUSIC_NOTE_HALF "\xf3\xb0\x8e\x89" // U+F0389 +#define ICON_MDI_MUSIC_NOTE_HALF_DOTTED "\xf3\xb0\xbd\xb2" // U+F0F72 +#define ICON_MDI_MUSIC_NOTE_MINUS "\xf3\xb1\xae\x89" // U+F1B89 +#define ICON_MDI_MUSIC_NOTE_OFF "\xf3\xb0\x8e\x8a" // U+F038A +#define ICON_MDI_MUSIC_NOTE_OFF_OUTLINE "\xf3\xb0\xbd\xb3" // U+F0F73 +#define ICON_MDI_MUSIC_NOTE_OUTLINE "\xf3\xb0\xbd\xb4" // U+F0F74 +#define ICON_MDI_MUSIC_NOTE_PLUS "\xf3\xb0\xb7\x9e" // U+F0DDE +#define ICON_MDI_MUSIC_NOTE_QUARTER "\xf3\xb0\x8e\x8b" // U+F038B +#define ICON_MDI_MUSIC_NOTE_QUARTER_DOTTED "\xf3\xb0\xbd\xb5" // U+F0F75 +#define ICON_MDI_MUSIC_NOTE_SIXTEENTH "\xf3\xb0\x8e\x8c" // U+F038C +#define ICON_MDI_MUSIC_NOTE_SIXTEENTH_DOTTED "\xf3\xb0\xbd\xb6" // U+F0F76 +#define ICON_MDI_MUSIC_NOTE_WHOLE "\xf3\xb0\x8e\x8d" // U+F038D +#define ICON_MDI_MUSIC_NOTE_WHOLE_DOTTED "\xf3\xb0\xbd\xb7" // U+F0F77 +#define ICON_MDI_MUSIC_OFF "\xf3\xb0\x9d\x9b" // U+F075B +#define ICON_MDI_MUSIC_REST_EIGHTH "\xf3\xb0\xbd\xb8" // U+F0F78 +#define ICON_MDI_MUSIC_REST_HALF "\xf3\xb0\xbd\xb9" // U+F0F79 +#define ICON_MDI_MUSIC_REST_QUARTER "\xf3\xb0\xbd\xba" // U+F0F7A +#define ICON_MDI_MUSIC_REST_SIXTEENTH "\xf3\xb0\xbd\xbb" // U+F0F7B +#define ICON_MDI_MUSIC_REST_WHOLE "\xf3\xb0\xbd\xbc" // U+F0F7C +#define ICON_MDI_MUSTACHE "\xf3\xb1\x97\x9e" // U+F15DE +#define ICON_MDI_NAIL "\xf3\xb0\xb7\x9f" // U+F0DDF +#define ICON_MDI_NAS "\xf3\xb0\xa3\xb3" // U+F08F3 +#define ICON_MDI_NATIVESCRIPT "\xf3\xb0\xa2\x80" // U+F0880 +#define ICON_MDI_NATURE "\xf3\xb0\x8e\x8e" // U+F038E +#define ICON_MDI_NATURE_OUTLINE "\xf3\xb1\xb1\xb1" // U+F1C71 +#define ICON_MDI_NATURE_PEOPLE "\xf3\xb0\x8e\x8f" // U+F038F +#define ICON_MDI_NATURE_PEOPLE_OUTLINE "\xf3\xb1\xb1\xb2" // U+F1C72 +#define ICON_MDI_NAVIGATION "\xf3\xb0\x8e\x90" // U+F0390 +#define ICON_MDI_NAVIGATION_OUTLINE "\xf3\xb1\x98\x87" // U+F1607 +#define ICON_MDI_NAVIGATION_VARIANT "\xf3\xb1\xa3\xb0" // U+F18F0 +#define ICON_MDI_NAVIGATION_VARIANT_OUTLINE "\xf3\xb1\xa3\xb1" // U+F18F1 +#define ICON_MDI_NEAR_ME "\xf3\xb0\x97\x8d" // U+F05CD +#define ICON_MDI_NECKLACE "\xf3\xb0\xbc\x8b" // U+F0F0B +#define ICON_MDI_NEEDLE "\xf3\xb0\x8e\x91" // U+F0391 +#define ICON_MDI_NEEDLE_OFF "\xf3\xb1\xa7\x92" // U+F19D2 +#define ICON_MDI_NETFLIX "\xf3\xb0\x9d\x86" // U+F0746 +#define ICON_MDI_NETWORK "\xf3\xb0\x9b\xb3" // U+F06F3 +#define ICON_MDI_NETWORK_OFF "\xf3\xb0\xb2\x9b" // U+F0C9B +#define ICON_MDI_NETWORK_OFF_OUTLINE "\xf3\xb0\xb2\x9c" // U+F0C9C +#define ICON_MDI_NETWORK_OUTLINE "\xf3\xb0\xb2\x9d" // U+F0C9D +#define ICON_MDI_NETWORK_POS "\xf3\xb1\xab\x8b" // U+F1ACB +#define ICON_MDI_NETWORK_STRENGTH_1 "\xf3\xb0\xa3\xb4" // U+F08F4 +#define ICON_MDI_NETWORK_STRENGTH_1_ALERT "\xf3\xb0\xa3\xb5" // U+F08F5 +#define ICON_MDI_NETWORK_STRENGTH_2 "\xf3\xb0\xa3\xb6" // U+F08F6 +#define ICON_MDI_NETWORK_STRENGTH_2_ALERT "\xf3\xb0\xa3\xb7" // U+F08F7 +#define ICON_MDI_NETWORK_STRENGTH_3 "\xf3\xb0\xa3\xb8" // U+F08F8 +#define ICON_MDI_NETWORK_STRENGTH_3_ALERT "\xf3\xb0\xa3\xb9" // U+F08F9 +#define ICON_MDI_NETWORK_STRENGTH_4 "\xf3\xb0\xa3\xba" // U+F08FA +#define ICON_MDI_NETWORK_STRENGTH_4_ALERT "\xf3\xb0\xa3\xbb" // U+F08FB +#define ICON_MDI_NETWORK_STRENGTH_4_COG "\xf3\xb1\xa4\x9a" // U+F191A +#define ICON_MDI_NETWORK_STRENGTH_OFF "\xf3\xb0\xa3\xbc" // U+F08FC +#define ICON_MDI_NETWORK_STRENGTH_OFF_OUTLINE "\xf3\xb0\xa3\xbd" // U+F08FD +#define ICON_MDI_NETWORK_STRENGTH_OUTLINE "\xf3\xb0\xa3\xbe" // U+F08FE +#define ICON_MDI_NEW_BOX "\xf3\xb0\x8e\x94" // U+F0394 +#define ICON_MDI_NEWSPAPER "\xf3\xb0\x8e\x95" // U+F0395 +#define ICON_MDI_NEWSPAPER_CHECK "\xf3\xb1\xa5\x83" // U+F1943 +#define ICON_MDI_NEWSPAPER_MINUS "\xf3\xb0\xbc\x8c" // U+F0F0C +#define ICON_MDI_NEWSPAPER_PLUS "\xf3\xb0\xbc\x8d" // U+F0F0D +#define ICON_MDI_NEWSPAPER_REMOVE "\xf3\xb1\xa5\x84" // U+F1944 +#define ICON_MDI_NEWSPAPER_VARIANT "\xf3\xb1\x80\x81" // U+F1001 +#define ICON_MDI_NEWSPAPER_VARIANT_MULTIPLE "\xf3\xb1\x80\x82" // U+F1002 +#define ICON_MDI_NEWSPAPER_VARIANT_MULTIPLE_OUTLINE "\xf3\xb1\x80\x83" // U+F1003 +#define ICON_MDI_NEWSPAPER_VARIANT_OUTLINE "\xf3\xb1\x80\x84" // U+F1004 +#define ICON_MDI_NFC "\xf3\xb0\x8e\x96" // U+F0396 +#define ICON_MDI_NFC_SEARCH_VARIANT "\xf3\xb0\xb9\x93" // U+F0E53 +#define ICON_MDI_NFC_TAP "\xf3\xb0\x8e\x97" // U+F0397 +#define ICON_MDI_NFC_VARIANT "\xf3\xb0\x8e\x98" // U+F0398 +#define ICON_MDI_NFC_VARIANT_OFF "\xf3\xb0\xb9\x94" // U+F0E54 +#define ICON_MDI_NINJA "\xf3\xb0\x9d\xb4" // U+F0774 +#define ICON_MDI_NINTENDO_GAME_BOY "\xf3\xb1\x8e\x93" // U+F1393 +#define ICON_MDI_NINTENDO_SWITCH "\xf3\xb0\x9f\xa1" // U+F07E1 +#define ICON_MDI_NINTENDO_WII "\xf3\xb0\x96\xab" // U+F05AB +#define ICON_MDI_NINTENDO_WIIU "\xf3\xb0\x9c\xad" // U+F072D +#define ICON_MDI_NIX "\xf3\xb1\x84\x85" // U+F1105 +#define ICON_MDI_NODEJS "\xf3\xb0\x8e\x99" // U+F0399 +#define ICON_MDI_NOODLES "\xf3\xb1\x85\xbe" // U+F117E +#define ICON_MDI_NOT_EQUAL "\xf3\xb0\xa6\x8d" // U+F098D +#define ICON_MDI_NOT_EQUAL_VARIANT "\xf3\xb0\xa6\x8e" // U+F098E +#define ICON_MDI_NOTE "\xf3\xb0\x8e\x9a" // U+F039A +#define ICON_MDI_NOTE_ALERT "\xf3\xb1\x9d\xbd" // U+F177D +#define ICON_MDI_NOTE_ALERT_OUTLINE "\xf3\xb1\x9d\xbe" // U+F177E +#define ICON_MDI_NOTE_CHECK "\xf3\xb1\x9d\xbf" // U+F177F +#define ICON_MDI_NOTE_CHECK_OUTLINE "\xf3\xb1\x9e\x80" // U+F1780 +#define ICON_MDI_NOTE_EDIT "\xf3\xb1\x9e\x81" // U+F1781 +#define ICON_MDI_NOTE_EDIT_OUTLINE "\xf3\xb1\x9e\x82" // U+F1782 +#define ICON_MDI_NOTE_MINUS "\xf3\xb1\x99\x8f" // U+F164F +#define ICON_MDI_NOTE_MINUS_OUTLINE "\xf3\xb1\x99\x90" // U+F1650 +#define ICON_MDI_NOTE_MULTIPLE "\xf3\xb0\x9a\xb8" // U+F06B8 +#define ICON_MDI_NOTE_MULTIPLE_OUTLINE "\xf3\xb0\x9a\xb9" // U+F06B9 +#define ICON_MDI_NOTE_OFF "\xf3\xb1\x9e\x83" // U+F1783 +#define ICON_MDI_NOTE_OFF_OUTLINE "\xf3\xb1\x9e\x84" // U+F1784 +#define ICON_MDI_NOTE_OUTLINE "\xf3\xb0\x8e\x9b" // U+F039B +#define ICON_MDI_NOTE_PLUS "\xf3\xb0\x8e\x9c" // U+F039C +#define ICON_MDI_NOTE_PLUS_OUTLINE "\xf3\xb0\x8e\x9d" // U+F039D +#define ICON_MDI_NOTE_REMOVE "\xf3\xb1\x99\x91" // U+F1651 +#define ICON_MDI_NOTE_REMOVE_OUTLINE "\xf3\xb1\x99\x92" // U+F1652 +#define ICON_MDI_NOTE_SEARCH "\xf3\xb1\x99\x93" // U+F1653 +#define ICON_MDI_NOTE_SEARCH_OUTLINE "\xf3\xb1\x99\x94" // U+F1654 +#define ICON_MDI_NOTE_TEXT "\xf3\xb0\x8e\x9e" // U+F039E +#define ICON_MDI_NOTE_TEXT_OUTLINE "\xf3\xb1\x87\x97" // U+F11D7 +#define ICON_MDI_NOTEBOOK "\xf3\xb0\xa0\xae" // U+F082E +#define ICON_MDI_NOTEBOOK_CHECK "\xf3\xb1\x93\xb5" // U+F14F5 +#define ICON_MDI_NOTEBOOK_CHECK_OUTLINE "\xf3\xb1\x93\xb6" // U+F14F6 +#define ICON_MDI_NOTEBOOK_EDIT "\xf3\xb1\x93\xa7" // U+F14E7 +#define ICON_MDI_NOTEBOOK_EDIT_OUTLINE "\xf3\xb1\x93\xa9" // U+F14E9 +#define ICON_MDI_NOTEBOOK_HEART "\xf3\xb1\xa8\x8b" // U+F1A0B +#define ICON_MDI_NOTEBOOK_HEART_OUTLINE "\xf3\xb1\xa8\x8c" // U+F1A0C +#define ICON_MDI_NOTEBOOK_MINUS "\xf3\xb1\x98\x90" // U+F1610 +#define ICON_MDI_NOTEBOOK_MINUS_OUTLINE "\xf3\xb1\x98\x91" // U+F1611 +#define ICON_MDI_NOTEBOOK_MULTIPLE "\xf3\xb0\xb9\x95" // U+F0E55 +#define ICON_MDI_NOTEBOOK_OUTLINE "\xf3\xb0\xba\xbf" // U+F0EBF +#define ICON_MDI_NOTEBOOK_PLUS "\xf3\xb1\x98\x92" // U+F1612 +#define ICON_MDI_NOTEBOOK_PLUS_OUTLINE "\xf3\xb1\x98\x93" // U+F1613 +#define ICON_MDI_NOTEBOOK_REMOVE "\xf3\xb1\x98\x94" // U+F1614 +#define ICON_MDI_NOTEBOOK_REMOVE_OUTLINE "\xf3\xb1\x98\x95" // U+F1615 +#define ICON_MDI_NOTIFICATION_CLEAR_ALL "\xf3\xb0\x8e\x9f" // U+F039F +#define ICON_MDI_NPM "\xf3\xb0\x9b\xb7" // U+F06F7 +#define ICON_MDI_NUKE "\xf3\xb0\x9a\xa4" // U+F06A4 +#define ICON_MDI_NULL "\xf3\xb0\x9f\xa2" // U+F07E2 +#define ICON_MDI_NUMERIC "\xf3\xb0\x8e\xa0" // U+F03A0 +#define ICON_MDI_NUMERIC_0 "\xf3\xb0\xac\xb9" // U+F0B39 +#define ICON_MDI_NUMERIC_0_BOX "\xf3\xb0\x8e\xa1" // U+F03A1 +#define ICON_MDI_NUMERIC_0_BOX_MULTIPLE "\xf3\xb0\xbc\x8e" // U+F0F0E +#define ICON_MDI_NUMERIC_0_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa2" // U+F03A2 +#define ICON_MDI_NUMERIC_0_BOX_OUTLINE "\xf3\xb0\x8e\xa3" // U+F03A3 +#define ICON_MDI_NUMERIC_0_CIRCLE "\xf3\xb0\xb2\x9e" // U+F0C9E +#define ICON_MDI_NUMERIC_0_CIRCLE_OUTLINE "\xf3\xb0\xb2\x9f" // U+F0C9F +#define ICON_MDI_NUMERIC_1 "\xf3\xb0\xac\xba" // U+F0B3A +#define ICON_MDI_NUMERIC_1_BOX "\xf3\xb0\x8e\xa4" // U+F03A4 +#define ICON_MDI_NUMERIC_1_BOX_MULTIPLE "\xf3\xb0\xbc\x8f" // U+F0F0F +#define ICON_MDI_NUMERIC_1_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa5" // U+F03A5 +#define ICON_MDI_NUMERIC_1_BOX_OUTLINE "\xf3\xb0\x8e\xa6" // U+F03A6 +#define ICON_MDI_NUMERIC_1_CIRCLE "\xf3\xb0\xb2\xa0" // U+F0CA0 +#define ICON_MDI_NUMERIC_1_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa1" // U+F0CA1 +#define ICON_MDI_NUMERIC_10 "\xf3\xb0\xbf\xa9" // U+F0FE9 +#define ICON_MDI_NUMERIC_10_BOX "\xf3\xb0\xbd\xbd" // U+F0F7D +#define ICON_MDI_NUMERIC_10_BOX_MULTIPLE "\xf3\xb0\xbf\xaa" // U+F0FEA +#define ICON_MDI_NUMERIC_10_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xbf\xab" // U+F0FEB +#define ICON_MDI_NUMERIC_10_BOX_OUTLINE "\xf3\xb0\xbd\xbe" // U+F0F7E +#define ICON_MDI_NUMERIC_10_CIRCLE "\xf3\xb0\xbf\xac" // U+F0FEC +#define ICON_MDI_NUMERIC_10_CIRCLE_OUTLINE "\xf3\xb0\xbf\xad" // U+F0FED +#define ICON_MDI_NUMERIC_2 "\xf3\xb0\xac\xbb" // U+F0B3B +#define ICON_MDI_NUMERIC_2_BOX "\xf3\xb0\x8e\xa7" // U+F03A7 +#define ICON_MDI_NUMERIC_2_BOX_MULTIPLE "\xf3\xb0\xbc\x90" // U+F0F10 +#define ICON_MDI_NUMERIC_2_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa8" // U+F03A8 +#define ICON_MDI_NUMERIC_2_BOX_OUTLINE "\xf3\xb0\x8e\xa9" // U+F03A9 +#define ICON_MDI_NUMERIC_2_CIRCLE "\xf3\xb0\xb2\xa2" // U+F0CA2 +#define ICON_MDI_NUMERIC_2_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa3" // U+F0CA3 +#define ICON_MDI_NUMERIC_3 "\xf3\xb0\xac\xbc" // U+F0B3C +#define ICON_MDI_NUMERIC_3_BOX "\xf3\xb0\x8e\xaa" // U+F03AA +#define ICON_MDI_NUMERIC_3_BOX_MULTIPLE "\xf3\xb0\xbc\x91" // U+F0F11 +#define ICON_MDI_NUMERIC_3_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xab" // U+F03AB +#define ICON_MDI_NUMERIC_3_BOX_OUTLINE "\xf3\xb0\x8e\xac" // U+F03AC +#define ICON_MDI_NUMERIC_3_CIRCLE "\xf3\xb0\xb2\xa4" // U+F0CA4 +#define ICON_MDI_NUMERIC_3_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa5" // U+F0CA5 +#define ICON_MDI_NUMERIC_4 "\xf3\xb0\xac\xbd" // U+F0B3D +#define ICON_MDI_NUMERIC_4_BOX "\xf3\xb0\x8e\xad" // U+F03AD +#define ICON_MDI_NUMERIC_4_BOX_MULTIPLE "\xf3\xb0\xbc\x92" // U+F0F12 +#define ICON_MDI_NUMERIC_4_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb2" // U+F03B2 +#define ICON_MDI_NUMERIC_4_BOX_OUTLINE "\xf3\xb0\x8e\xae" // U+F03AE +#define ICON_MDI_NUMERIC_4_CIRCLE "\xf3\xb0\xb2\xa6" // U+F0CA6 +#define ICON_MDI_NUMERIC_4_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa7" // U+F0CA7 +#define ICON_MDI_NUMERIC_5 "\xf3\xb0\xac\xbe" // U+F0B3E +#define ICON_MDI_NUMERIC_5_BOX "\xf3\xb0\x8e\xb1" // U+F03B1 +#define ICON_MDI_NUMERIC_5_BOX_MULTIPLE "\xf3\xb0\xbc\x93" // U+F0F13 +#define ICON_MDI_NUMERIC_5_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xaf" // U+F03AF +#define ICON_MDI_NUMERIC_5_BOX_OUTLINE "\xf3\xb0\x8e\xb0" // U+F03B0 +#define ICON_MDI_NUMERIC_5_CIRCLE "\xf3\xb0\xb2\xa8" // U+F0CA8 +#define ICON_MDI_NUMERIC_5_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa9" // U+F0CA9 +#define ICON_MDI_NUMERIC_6 "\xf3\xb0\xac\xbf" // U+F0B3F +#define ICON_MDI_NUMERIC_6_BOX "\xf3\xb0\x8e\xb3" // U+F03B3 +#define ICON_MDI_NUMERIC_6_BOX_MULTIPLE "\xf3\xb0\xbc\x94" // U+F0F14 +#define ICON_MDI_NUMERIC_6_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb4" // U+F03B4 +#define ICON_MDI_NUMERIC_6_BOX_OUTLINE "\xf3\xb0\x8e\xb5" // U+F03B5 +#define ICON_MDI_NUMERIC_6_CIRCLE "\xf3\xb0\xb2\xaa" // U+F0CAA +#define ICON_MDI_NUMERIC_6_CIRCLE_OUTLINE "\xf3\xb0\xb2\xab" // U+F0CAB +#define ICON_MDI_NUMERIC_7 "\xf3\xb0\xad\x80" // U+F0B40 +#define ICON_MDI_NUMERIC_7_BOX "\xf3\xb0\x8e\xb6" // U+F03B6 +#define ICON_MDI_NUMERIC_7_BOX_MULTIPLE "\xf3\xb0\xbc\x95" // U+F0F15 +#define ICON_MDI_NUMERIC_7_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb7" // U+F03B7 +#define ICON_MDI_NUMERIC_7_BOX_OUTLINE "\xf3\xb0\x8e\xb8" // U+F03B8 +#define ICON_MDI_NUMERIC_7_CIRCLE "\xf3\xb0\xb2\xac" // U+F0CAC +#define ICON_MDI_NUMERIC_7_CIRCLE_OUTLINE "\xf3\xb0\xb2\xad" // U+F0CAD +#define ICON_MDI_NUMERIC_8 "\xf3\xb0\xad\x81" // U+F0B41 +#define ICON_MDI_NUMERIC_8_BOX "\xf3\xb0\x8e\xb9" // U+F03B9 +#define ICON_MDI_NUMERIC_8_BOX_MULTIPLE "\xf3\xb0\xbc\x96" // U+F0F16 +#define ICON_MDI_NUMERIC_8_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xba" // U+F03BA +#define ICON_MDI_NUMERIC_8_BOX_OUTLINE "\xf3\xb0\x8e\xbb" // U+F03BB +#define ICON_MDI_NUMERIC_8_CIRCLE "\xf3\xb0\xb2\xae" // U+F0CAE +#define ICON_MDI_NUMERIC_8_CIRCLE_OUTLINE "\xf3\xb0\xb2\xaf" // U+F0CAF +#define ICON_MDI_NUMERIC_9 "\xf3\xb0\xad\x82" // U+F0B42 +#define ICON_MDI_NUMERIC_9_BOX "\xf3\xb0\x8e\xbc" // U+F03BC +#define ICON_MDI_NUMERIC_9_BOX_MULTIPLE "\xf3\xb0\xbc\x97" // U+F0F17 +#define ICON_MDI_NUMERIC_9_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xbd" // U+F03BD +#define ICON_MDI_NUMERIC_9_BOX_OUTLINE "\xf3\xb0\x8e\xbe" // U+F03BE +#define ICON_MDI_NUMERIC_9_CIRCLE "\xf3\xb0\xb2\xb0" // U+F0CB0 +#define ICON_MDI_NUMERIC_9_CIRCLE_OUTLINE "\xf3\xb0\xb2\xb1" // U+F0CB1 +#define ICON_MDI_NUMERIC_9_PLUS "\xf3\xb0\xbf\xae" // U+F0FEE +#define ICON_MDI_NUMERIC_9_PLUS_BOX "\xf3\xb0\x8e\xbf" // U+F03BF +#define ICON_MDI_NUMERIC_9_PLUS_BOX_MULTIPLE "\xf3\xb0\xbc\x98" // U+F0F18 +#define ICON_MDI_NUMERIC_9_PLUS_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8f\x80" // U+F03C0 +#define ICON_MDI_NUMERIC_9_PLUS_BOX_OUTLINE "\xf3\xb0\x8f\x81" // U+F03C1 +#define ICON_MDI_NUMERIC_9_PLUS_CIRCLE "\xf3\xb0\xb2\xb2" // U+F0CB2 +#define ICON_MDI_NUMERIC_9_PLUS_CIRCLE_OUTLINE "\xf3\xb0\xb2\xb3" // U+F0CB3 +#define ICON_MDI_NUMERIC_NEGATIVE_1 "\xf3\xb1\x81\x92" // U+F1052 +#define ICON_MDI_NUMERIC_OFF "\xf3\xb1\xa7\x93" // U+F19D3 +#define ICON_MDI_NUMERIC_POSITIVE_1 "\xf3\xb1\x97\x8b" // U+F15CB +#define ICON_MDI_NUT "\xf3\xb0\x9b\xb8" // U+F06F8 +#define ICON_MDI_NUTRITION "\xf3\xb0\x8f\x82" // U+F03C2 +#define ICON_MDI_NUXT "\xf3\xb1\x84\x86" // U+F1106 +#define ICON_MDI_OAR "\xf3\xb0\x99\xbc" // U+F067C +#define ICON_MDI_OCARINA "\xf3\xb0\xb7\xa0" // U+F0DE0 +#define ICON_MDI_OCI "\xf3\xb1\x8b\xa9" // U+F12E9 +#define ICON_MDI_OCR "\xf3\xb1\x84\xba" // U+F113A +#define ICON_MDI_OCTAGON "\xf3\xb0\x8f\x83" // U+F03C3 +#define ICON_MDI_OCTAGON_OUTLINE "\xf3\xb0\x8f\x84" // U+F03C4 +#define ICON_MDI_OCTAGRAM "\xf3\xb0\x9b\xb9" // U+F06F9 +#define ICON_MDI_OCTAGRAM_EDIT "\xf3\xb1\xb0\xb4" // U+F1C34 +#define ICON_MDI_OCTAGRAM_EDIT_OUTLINE "\xf3\xb1\xb0\xb5" // U+F1C35 +#define ICON_MDI_OCTAGRAM_MINUS "\xf3\xb1\xb0\xb6" // U+F1C36 +#define ICON_MDI_OCTAGRAM_MINUS_OUTLINE "\xf3\xb1\xb0\xb7" // U+F1C37 +#define ICON_MDI_OCTAGRAM_OUTLINE "\xf3\xb0\x9d\xb5" // U+F0775 +#define ICON_MDI_OCTAGRAM_PLUS "\xf3\xb1\xb0\xb8" // U+F1C38 +#define ICON_MDI_OCTAGRAM_PLUS_OUTLINE "\xf3\xb1\xb0\xb9" // U+F1C39 +#define ICON_MDI_OCTAHEDRON "\xf3\xb1\xa5\x90" // U+F1950 +#define ICON_MDI_OCTAHEDRON_OFF "\xf3\xb1\xa5\x91" // U+F1951 +#define ICON_MDI_ODNOKLASSNIKI "\xf3\xb0\x8f\x85" // U+F03C5 +#define ICON_MDI_OFFER "\xf3\xb1\x88\x9b" // U+F121B +#define ICON_MDI_OFFICE_BUILDING "\xf3\xb0\xa6\x91" // U+F0991 +#define ICON_MDI_OFFICE_BUILDING_COG "\xf3\xb1\xa5\x89" // U+F1949 +#define ICON_MDI_OFFICE_BUILDING_COG_OUTLINE "\xf3\xb1\xa5\x8a" // U+F194A +#define ICON_MDI_OFFICE_BUILDING_MARKER "\xf3\xb1\x94\xa0" // U+F1520 +#define ICON_MDI_OFFICE_BUILDING_MARKER_OUTLINE "\xf3\xb1\x94\xa1" // U+F1521 +#define ICON_MDI_OFFICE_BUILDING_MINUS "\xf3\xb1\xae\xaa" // U+F1BAA +#define ICON_MDI_OFFICE_BUILDING_MINUS_OUTLINE "\xf3\xb1\xae\xab" // U+F1BAB +#define ICON_MDI_OFFICE_BUILDING_OUTLINE "\xf3\xb1\x94\x9f" // U+F151F +#define ICON_MDI_OFFICE_BUILDING_PLUS "\xf3\xb1\xae\xa8" // U+F1BA8 +#define ICON_MDI_OFFICE_BUILDING_PLUS_OUTLINE "\xf3\xb1\xae\xa9" // U+F1BA9 +#define ICON_MDI_OFFICE_BUILDING_REMOVE "\xf3\xb1\xae\xac" // U+F1BAC +#define ICON_MDI_OFFICE_BUILDING_REMOVE_OUTLINE "\xf3\xb1\xae\xad" // U+F1BAD +#define ICON_MDI_OIL "\xf3\xb0\x8f\x87" // U+F03C7 +#define ICON_MDI_OIL_LAMP "\xf3\xb0\xbc\x99" // U+F0F19 +#define ICON_MDI_OIL_LEVEL "\xf3\xb1\x81\x93" // U+F1053 +#define ICON_MDI_OIL_TEMPERATURE "\xf3\xb0\xbf\xb8" // U+F0FF8 +#define ICON_MDI_OM "\xf3\xb0\xa5\xb3" // U+F0973 +#define ICON_MDI_OMEGA "\xf3\xb0\x8f\x89" // U+F03C9 +#define ICON_MDI_ONE_UP "\xf3\xb0\xae\xad" // U+F0BAD +#define ICON_MDI_ONEPASSWORD "\xf3\xb0\xa2\x81" // U+F0881 +#define ICON_MDI_OPACITY "\xf3\xb0\x97\x8c" // U+F05CC +#define ICON_MDI_OPEN_IN_APP "\xf3\xb0\x8f\x8b" // U+F03CB +#define ICON_MDI_OPEN_IN_NEW "\xf3\xb0\x8f\x8c" // U+F03CC +#define ICON_MDI_OPEN_SOURCE_INITIATIVE "\xf3\xb0\xae\xae" // U+F0BAE +#define ICON_MDI_OPENID "\xf3\xb0\x8f\x8d" // U+F03CD +#define ICON_MDI_OPERA "\xf3\xb0\x8f\x8e" // U+F03CE +#define ICON_MDI_ORBIT "\xf3\xb0\x80\x98" // U+F0018 +#define ICON_MDI_ORBIT_VARIANT "\xf3\xb1\x97\x9b" // U+F15DB +#define ICON_MDI_ORDER_ALPHABETICAL_ASCENDING "\xf3\xb0\x88\x8d" // U+F020D +#define ICON_MDI_ORDER_ALPHABETICAL_DESCENDING "\xf3\xb0\xb4\x87" // U+F0D07 +#define ICON_MDI_ORDER_BOOL_ASCENDING "\xf3\xb0\x8a\xbe" // U+F02BE +#define ICON_MDI_ORDER_BOOL_ASCENDING_VARIANT "\xf3\xb0\xa6\x8f" // U+F098F +#define ICON_MDI_ORDER_BOOL_DESCENDING "\xf3\xb1\x8e\x84" // U+F1384 +#define ICON_MDI_ORDER_BOOL_DESCENDING_VARIANT "\xf3\xb0\xa6\x90" // U+F0990 +#define ICON_MDI_ORDER_NUMERIC_ASCENDING "\xf3\xb0\x95\x85" // U+F0545 +#define ICON_MDI_ORDER_NUMERIC_DESCENDING "\xf3\xb0\x95\x86" // U+F0546 +#define ICON_MDI_ORIGIN "\xf3\xb0\xad\x83" // U+F0B43 +#define ICON_MDI_ORNAMENT "\xf3\xb0\x8f\x8f" // U+F03CF +#define ICON_MDI_ORNAMENT_VARIANT "\xf3\xb0\x8f\x90" // U+F03D0 +#define ICON_MDI_OUTDOOR_LAMP "\xf3\xb1\x81\x94" // U+F1054 +#define ICON_MDI_OVERSCAN "\xf3\xb1\x80\x85" // U+F1005 +#define ICON_MDI_OWL "\xf3\xb0\x8f\x92" // U+F03D2 +#define ICON_MDI_PAC_MAN "\xf3\xb0\xae\xaf" // U+F0BAF +#define ICON_MDI_PACKAGE "\xf3\xb0\x8f\x93" // U+F03D3 +#define ICON_MDI_PACKAGE_CHECK "\xf3\xb1\xad\x91" // U+F1B51 +#define ICON_MDI_PACKAGE_DOWN "\xf3\xb0\x8f\x94" // U+F03D4 +#define ICON_MDI_PACKAGE_UP "\xf3\xb0\x8f\x95" // U+F03D5 +#define ICON_MDI_PACKAGE_VARIANT "\xf3\xb0\x8f\x96" // U+F03D6 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED "\xf3\xb0\x8f\x97" // U+F03D7 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_CHECK "\xf3\xb1\xad\x92" // U+F1B52 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_MINUS "\xf3\xb1\xa7\x94" // U+F19D4 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_PLUS "\xf3\xb1\xa7\x95" // U+F19D5 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_REMOVE "\xf3\xb1\xa7\x96" // U+F19D6 +#define ICON_MDI_PACKAGE_VARIANT_MINUS "\xf3\xb1\xa7\x97" // U+F19D7 +#define ICON_MDI_PACKAGE_VARIANT_PLUS "\xf3\xb1\xa7\x98" // U+F19D8 +#define ICON_MDI_PACKAGE_VARIANT_REMOVE "\xf3\xb1\xa7\x99" // U+F19D9 +#define ICON_MDI_PAGE_FIRST "\xf3\xb0\x98\x80" // U+F0600 +#define ICON_MDI_PAGE_LAST "\xf3\xb0\x98\x81" // U+F0601 +#define ICON_MDI_PAGE_LAYOUT_BODY "\xf3\xb0\x9b\xba" // U+F06FA +#define ICON_MDI_PAGE_LAYOUT_FOOTER "\xf3\xb0\x9b\xbb" // U+F06FB +#define ICON_MDI_PAGE_LAYOUT_HEADER "\xf3\xb0\x9b\xbc" // U+F06FC +#define ICON_MDI_PAGE_LAYOUT_HEADER_FOOTER "\xf3\xb0\xbd\xbf" // U+F0F7F +#define ICON_MDI_PAGE_LAYOUT_SIDEBAR_LEFT "\xf3\xb0\x9b\xbd" // U+F06FD +#define ICON_MDI_PAGE_LAYOUT_SIDEBAR_RIGHT "\xf3\xb0\x9b\xbe" // U+F06FE +#define ICON_MDI_PAGE_NEXT "\xf3\xb0\xae\xb0" // U+F0BB0 +#define ICON_MDI_PAGE_NEXT_OUTLINE "\xf3\xb0\xae\xb1" // U+F0BB1 +#define ICON_MDI_PAGE_PREVIOUS "\xf3\xb0\xae\xb2" // U+F0BB2 +#define ICON_MDI_PAGE_PREVIOUS_OUTLINE "\xf3\xb0\xae\xb3" // U+F0BB3 +#define ICON_MDI_PAIL "\xf3\xb1\x90\x97" // U+F1417 +#define ICON_MDI_PAIL_MINUS "\xf3\xb1\x90\xb7" // U+F1437 +#define ICON_MDI_PAIL_MINUS_OUTLINE "\xf3\xb1\x90\xbc" // U+F143C +#define ICON_MDI_PAIL_OFF "\xf3\xb1\x90\xb9" // U+F1439 +#define ICON_MDI_PAIL_OFF_OUTLINE "\xf3\xb1\x90\xbe" // U+F143E +#define ICON_MDI_PAIL_OUTLINE "\xf3\xb1\x90\xba" // U+F143A +#define ICON_MDI_PAIL_PLUS "\xf3\xb1\x90\xb6" // U+F1436 +#define ICON_MDI_PAIL_PLUS_OUTLINE "\xf3\xb1\x90\xbb" // U+F143B +#define ICON_MDI_PAIL_REMOVE "\xf3\xb1\x90\xb8" // U+F1438 +#define ICON_MDI_PAIL_REMOVE_OUTLINE "\xf3\xb1\x90\xbd" // U+F143D +#define ICON_MDI_PALETTE "\xf3\xb0\x8f\x98" // U+F03D8 +#define ICON_MDI_PALETTE_ADVANCED "\xf3\xb0\x8f\x99" // U+F03D9 +#define ICON_MDI_PALETTE_OUTLINE "\xf3\xb0\xb8\x8c" // U+F0E0C +#define ICON_MDI_PALETTE_SWATCH "\xf3\xb0\xa2\xb5" // U+F08B5 +#define ICON_MDI_PALETTE_SWATCH_OUTLINE "\xf3\xb1\x8d\x9c" // U+F135C +#define ICON_MDI_PALETTE_SWATCH_VARIANT "\xf3\xb1\xa5\x9a" // U+F195A +#define ICON_MDI_PALM_TREE "\xf3\xb1\x81\x95" // U+F1055 +#define ICON_MDI_PAN "\xf3\xb0\xae\xb4" // U+F0BB4 +#define ICON_MDI_PAN_BOTTOM_LEFT "\xf3\xb0\xae\xb5" // U+F0BB5 +#define ICON_MDI_PAN_BOTTOM_RIGHT "\xf3\xb0\xae\xb6" // U+F0BB6 +#define ICON_MDI_PAN_DOWN "\xf3\xb0\xae\xb7" // U+F0BB7 +#define ICON_MDI_PAN_HORIZONTAL "\xf3\xb0\xae\xb8" // U+F0BB8 +#define ICON_MDI_PAN_LEFT "\xf3\xb0\xae\xb9" // U+F0BB9 +#define ICON_MDI_PAN_RIGHT "\xf3\xb0\xae\xba" // U+F0BBA +#define ICON_MDI_PAN_TOP_LEFT "\xf3\xb0\xae\xbb" // U+F0BBB +#define ICON_MDI_PAN_TOP_RIGHT "\xf3\xb0\xae\xbc" // U+F0BBC +#define ICON_MDI_PAN_UP "\xf3\xb0\xae\xbd" // U+F0BBD +#define ICON_MDI_PAN_VERTICAL "\xf3\xb0\xae\xbe" // U+F0BBE +#define ICON_MDI_PANDA "\xf3\xb0\x8f\x9a" // U+F03DA +#define ICON_MDI_PANDORA "\xf3\xb0\x8f\x9b" // U+F03DB +#define ICON_MDI_PANORAMA "\xf3\xb0\x8f\x9c" // U+F03DC +#define ICON_MDI_PANORAMA_FISHEYE "\xf3\xb0\x8f\x9d" // U+F03DD +#define ICON_MDI_PANORAMA_HORIZONTAL "\xf3\xb1\xa4\xa8" // U+F1928 +#define ICON_MDI_PANORAMA_HORIZONTAL_OUTLINE "\xf3\xb0\x8f\x9e" // U+F03DE +#define ICON_MDI_PANORAMA_OUTLINE "\xf3\xb1\xa6\x8c" // U+F198C +#define ICON_MDI_PANORAMA_SPHERE "\xf3\xb1\xa6\x8d" // U+F198D +#define ICON_MDI_PANORAMA_SPHERE_OUTLINE "\xf3\xb1\xa6\x8e" // U+F198E +#define ICON_MDI_PANORAMA_VARIANT "\xf3\xb1\xa6\x8f" // U+F198F +#define ICON_MDI_PANORAMA_VARIANT_OUTLINE "\xf3\xb1\xa6\x90" // U+F1990 +#define ICON_MDI_PANORAMA_VERTICAL "\xf3\xb1\xa4\xa9" // U+F1929 +#define ICON_MDI_PANORAMA_VERTICAL_OUTLINE "\xf3\xb0\x8f\x9f" // U+F03DF +#define ICON_MDI_PANORAMA_WIDE_ANGLE "\xf3\xb1\xa5\x9f" // U+F195F +#define ICON_MDI_PANORAMA_WIDE_ANGLE_OUTLINE "\xf3\xb0\x8f\xa0" // U+F03E0 +#define ICON_MDI_PAPER_CUT_VERTICAL "\xf3\xb0\x8f\xa1" // U+F03E1 +#define ICON_MDI_PAPER_ROLL "\xf3\xb1\x85\x97" // U+F1157 +#define ICON_MDI_PAPER_ROLL_OUTLINE "\xf3\xb1\x85\x98" // U+F1158 +#define ICON_MDI_PAPERCLIP "\xf3\xb0\x8f\xa2" // U+F03E2 +#define ICON_MDI_PAPERCLIP_CHECK "\xf3\xb1\xab\x86" // U+F1AC6 +#define ICON_MDI_PAPERCLIP_LOCK "\xf3\xb1\xa7\x9a" // U+F19DA +#define ICON_MDI_PAPERCLIP_MINUS "\xf3\xb1\xab\x87" // U+F1AC7 +#define ICON_MDI_PAPERCLIP_OFF "\xf3\xb1\xab\x88" // U+F1AC8 +#define ICON_MDI_PAPERCLIP_PLUS "\xf3\xb1\xab\x89" // U+F1AC9 +#define ICON_MDI_PAPERCLIP_REMOVE "\xf3\xb1\xab\x8a" // U+F1ACA +#define ICON_MDI_PARACHUTE "\xf3\xb0\xb2\xb4" // U+F0CB4 +#define ICON_MDI_PARACHUTE_OUTLINE "\xf3\xb0\xb2\xb5" // U+F0CB5 +#define ICON_MDI_PARAGLIDING "\xf3\xb1\x9d\x85" // U+F1745 +#define ICON_MDI_PARKING "\xf3\xb0\x8f\xa3" // U+F03E3 +#define ICON_MDI_PARTY_POPPER "\xf3\xb1\x81\x96" // U+F1056 +#define ICON_MDI_PASSPORT "\xf3\xb0\x9f\xa3" // U+F07E3 +#define ICON_MDI_PASSPORT_ALERT "\xf3\xb1\xb2\xb8" // U+F1CB8 +#define ICON_MDI_PASSPORT_BIOMETRIC "\xf3\xb0\xb7\xa1" // U+F0DE1 +#define ICON_MDI_PASSPORT_CANCEL "\xf3\xb1\xb2\xb9" // U+F1CB9 +#define ICON_MDI_PASSPORT_CHECK "\xf3\xb1\xb2\xba" // U+F1CBA +#define ICON_MDI_PASSPORT_MINUS "\xf3\xb1\xb2\xbb" // U+F1CBB +#define ICON_MDI_PASSPORT_PLUS "\xf3\xb1\xb2\xbc" // U+F1CBC +#define ICON_MDI_PASSPORT_REMOVE "\xf3\xb1\xb2\xbd" // U+F1CBD +#define ICON_MDI_PASTA "\xf3\xb1\x85\xa0" // U+F1160 +#define ICON_MDI_PATIO_HEATER "\xf3\xb0\xbe\x80" // U+F0F80 +#define ICON_MDI_PATREON "\xf3\xb0\xa2\x82" // U+F0882 +#define ICON_MDI_PAUSE "\xf3\xb0\x8f\xa4" // U+F03E4 +#define ICON_MDI_PAUSE_BOX "\xf3\xb0\x82\xbc" // U+F00BC +#define ICON_MDI_PAUSE_BOX_OUTLINE "\xf3\xb1\xad\xba" // U+F1B7A +#define ICON_MDI_PAUSE_CIRCLE "\xf3\xb0\x8f\xa5" // U+F03E5 +#define ICON_MDI_PAUSE_CIRCLE_OUTLINE "\xf3\xb0\x8f\xa6" // U+F03E6 +#define ICON_MDI_PAUSE_OCTAGON "\xf3\xb0\x8f\xa7" // U+F03E7 +#define ICON_MDI_PAUSE_OCTAGON_OUTLINE "\xf3\xb0\x8f\xa8" // U+F03E8 +#define ICON_MDI_PAW "\xf3\xb0\x8f\xa9" // U+F03E9 +#define ICON_MDI_PAW_OFF "\xf3\xb0\x99\x97" // U+F0657 +#define ICON_MDI_PAW_OFF_OUTLINE "\xf3\xb1\x99\xb6" // U+F1676 +#define ICON_MDI_PAW_OUTLINE "\xf3\xb1\x99\xb5" // U+F1675 +#define ICON_MDI_PEACE "\xf3\xb0\xa2\x84" // U+F0884 +#define ICON_MDI_PEANUT "\xf3\xb0\xbf\xbc" // U+F0FFC +#define ICON_MDI_PEANUT_OFF "\xf3\xb0\xbf\xbd" // U+F0FFD +#define ICON_MDI_PEANUT_OFF_OUTLINE "\xf3\xb0\xbf\xbf" // U+F0FFF +#define ICON_MDI_PEANUT_OUTLINE "\xf3\xb0\xbf\xbe" // U+F0FFE +#define ICON_MDI_PEN "\xf3\xb0\x8f\xaa" // U+F03EA +#define ICON_MDI_PEN_LOCK "\xf3\xb0\xb7\xa2" // U+F0DE2 +#define ICON_MDI_PEN_MINUS "\xf3\xb0\xb7\xa3" // U+F0DE3 +#define ICON_MDI_PEN_OFF "\xf3\xb0\xb7\xa4" // U+F0DE4 +#define ICON_MDI_PEN_PLUS "\xf3\xb0\xb7\xa5" // U+F0DE5 +#define ICON_MDI_PEN_REMOVE "\xf3\xb0\xb7\xa6" // U+F0DE6 +#define ICON_MDI_PENCIL "\xf3\xb0\x8f\xab" // U+F03EB +#define ICON_MDI_PENCIL_BOX "\xf3\xb0\x8f\xac" // U+F03EC +#define ICON_MDI_PENCIL_BOX_MULTIPLE "\xf3\xb1\x85\x84" // U+F1144 +#define ICON_MDI_PENCIL_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x85" // U+F1145 +#define ICON_MDI_PENCIL_BOX_OUTLINE "\xf3\xb0\x8f\xad" // U+F03ED +#define ICON_MDI_PENCIL_CIRCLE "\xf3\xb0\x9b\xbf" // U+F06FF +#define ICON_MDI_PENCIL_CIRCLE_OUTLINE "\xf3\xb0\x9d\xb6" // U+F0776 +#define ICON_MDI_PENCIL_LOCK "\xf3\xb0\x8f\xae" // U+F03EE +#define ICON_MDI_PENCIL_LOCK_OUTLINE "\xf3\xb0\xb7\xa7" // U+F0DE7 +#define ICON_MDI_PENCIL_MINUS "\xf3\xb0\xb7\xa8" // U+F0DE8 +#define ICON_MDI_PENCIL_MINUS_OUTLINE "\xf3\xb0\xb7\xa9" // U+F0DE9 +#define ICON_MDI_PENCIL_OFF "\xf3\xb0\x8f\xaf" // U+F03EF +#define ICON_MDI_PENCIL_OFF_OUTLINE "\xf3\xb0\xb7\xaa" // U+F0DEA +#define ICON_MDI_PENCIL_OUTLINE "\xf3\xb0\xb2\xb6" // U+F0CB6 +#define ICON_MDI_PENCIL_PLUS "\xf3\xb0\xb7\xab" // U+F0DEB +#define ICON_MDI_PENCIL_PLUS_OUTLINE "\xf3\xb0\xb7\xac" // U+F0DEC +#define ICON_MDI_PENCIL_REMOVE "\xf3\xb0\xb7\xad" // U+F0DED +#define ICON_MDI_PENCIL_REMOVE_OUTLINE "\xf3\xb0\xb7\xae" // U+F0DEE +#define ICON_MDI_PENCIL_RULER "\xf3\xb1\x8d\x93" // U+F1353 +#define ICON_MDI_PENCIL_RULER_OUTLINE "\xf3\xb1\xb0\x91" // U+F1C11 +#define ICON_MDI_PENGUIN "\xf3\xb0\xbb\x80" // U+F0EC0 +#define ICON_MDI_PENTAGON "\xf3\xb0\x9c\x81" // U+F0701 +#define ICON_MDI_PENTAGON_OUTLINE "\xf3\xb0\x9c\x80" // U+F0700 +#define ICON_MDI_PENTAGRAM "\xf3\xb1\x99\xa7" // U+F1667 +#define ICON_MDI_PERCENT "\xf3\xb0\x8f\xb0" // U+F03F0 +#define ICON_MDI_PERCENT_BOX "\xf3\xb1\xa8\x82" // U+F1A02 +#define ICON_MDI_PERCENT_BOX_OUTLINE "\xf3\xb1\xa8\x83" // U+F1A03 +#define ICON_MDI_PERCENT_CIRCLE "\xf3\xb1\xa8\x84" // U+F1A04 +#define ICON_MDI_PERCENT_CIRCLE_OUTLINE "\xf3\xb1\xa8\x85" // U+F1A05 +#define ICON_MDI_PERCENT_OUTLINE "\xf3\xb1\x89\xb8" // U+F1278 +#define ICON_MDI_PERIODIC_TABLE "\xf3\xb0\xa2\xb6" // U+F08B6 +#define ICON_MDI_PERSPECTIVE_LESS "\xf3\xb0\xb4\xa3" // U+F0D23 +#define ICON_MDI_PERSPECTIVE_MORE "\xf3\xb0\xb4\xa4" // U+F0D24 +#define ICON_MDI_PH "\xf3\xb1\x9f\x85" // U+F17C5 +#define ICON_MDI_PHONE "\xf3\xb0\x8f\xb2" // U+F03F2 +#define ICON_MDI_PHONE_ALERT "\xf3\xb0\xbc\x9a" // U+F0F1A +#define ICON_MDI_PHONE_ALERT_OUTLINE "\xf3\xb1\x86\x8e" // U+F118E +#define ICON_MDI_PHONE_BLUETOOTH "\xf3\xb0\x8f\xb3" // U+F03F3 +#define ICON_MDI_PHONE_BLUETOOTH_OUTLINE "\xf3\xb1\x86\x8f" // U+F118F +#define ICON_MDI_PHONE_CANCEL "\xf3\xb1\x82\xbc" // U+F10BC +#define ICON_MDI_PHONE_CANCEL_OUTLINE "\xf3\xb1\x86\x90" // U+F1190 +#define ICON_MDI_PHONE_CHECK "\xf3\xb1\x86\xa9" // U+F11A9 +#define ICON_MDI_PHONE_CHECK_OUTLINE "\xf3\xb1\x86\xaa" // U+F11AA +#define ICON_MDI_PHONE_CLASSIC "\xf3\xb0\x98\x82" // U+F0602 +#define ICON_MDI_PHONE_CLASSIC_OFF "\xf3\xb1\x89\xb9" // U+F1279 +#define ICON_MDI_PHONE_CLOCK "\xf3\xb1\xa7\x9b" // U+F19DB +#define ICON_MDI_PHONE_DIAL "\xf3\xb1\x95\x99" // U+F1559 +#define ICON_MDI_PHONE_DIAL_OUTLINE "\xf3\xb1\x95\x9a" // U+F155A +#define ICON_MDI_PHONE_FORWARD "\xf3\xb0\x8f\xb4" // U+F03F4 +#define ICON_MDI_PHONE_FORWARD_OUTLINE "\xf3\xb1\x86\x91" // U+F1191 +#define ICON_MDI_PHONE_HANGUP "\xf3\xb0\x8f\xb5" // U+F03F5 +#define ICON_MDI_PHONE_HANGUP_OUTLINE "\xf3\xb1\x86\x92" // U+F1192 +#define ICON_MDI_PHONE_IN_TALK "\xf3\xb0\x8f\xb6" // U+F03F6 +#define ICON_MDI_PHONE_IN_TALK_OUTLINE "\xf3\xb1\x86\x82" // U+F1182 +#define ICON_MDI_PHONE_INCOMING "\xf3\xb0\x8f\xb7" // U+F03F7 +#define ICON_MDI_PHONE_INCOMING_OUTGOING "\xf3\xb1\xac\xbf" // U+F1B3F +#define ICON_MDI_PHONE_INCOMING_OUTGOING_OUTLINE "\xf3\xb1\xad\x80" // U+F1B40 +#define ICON_MDI_PHONE_INCOMING_OUTLINE "\xf3\xb1\x86\x93" // U+F1193 +#define ICON_MDI_PHONE_LOCK "\xf3\xb0\x8f\xb8" // U+F03F8 +#define ICON_MDI_PHONE_LOCK_OUTLINE "\xf3\xb1\x86\x94" // U+F1194 +#define ICON_MDI_PHONE_LOG "\xf3\xb0\x8f\xb9" // U+F03F9 +#define ICON_MDI_PHONE_LOG_OUTLINE "\xf3\xb1\x86\x95" // U+F1195 +#define ICON_MDI_PHONE_MESSAGE "\xf3\xb1\x86\x96" // U+F1196 +#define ICON_MDI_PHONE_MESSAGE_OUTLINE "\xf3\xb1\x86\x97" // U+F1197 +#define ICON_MDI_PHONE_MINUS "\xf3\xb0\x99\x98" // U+F0658 +#define ICON_MDI_PHONE_MINUS_OUTLINE "\xf3\xb1\x86\x98" // U+F1198 +#define ICON_MDI_PHONE_MISSED "\xf3\xb0\x8f\xba" // U+F03FA +#define ICON_MDI_PHONE_MISSED_OUTLINE "\xf3\xb1\x86\xa5" // U+F11A5 +#define ICON_MDI_PHONE_OFF "\xf3\xb0\xb7\xaf" // U+F0DEF +#define ICON_MDI_PHONE_OFF_OUTLINE "\xf3\xb1\x86\xa6" // U+F11A6 +#define ICON_MDI_PHONE_OUTGOING "\xf3\xb0\x8f\xbb" // U+F03FB +#define ICON_MDI_PHONE_OUTGOING_OUTLINE "\xf3\xb1\x86\x99" // U+F1199 +#define ICON_MDI_PHONE_OUTLINE "\xf3\xb0\xb7\xb0" // U+F0DF0 +#define ICON_MDI_PHONE_PAUSED "\xf3\xb0\x8f\xbc" // U+F03FC +#define ICON_MDI_PHONE_PAUSED_OUTLINE "\xf3\xb1\x86\x9a" // U+F119A +#define ICON_MDI_PHONE_PLUS "\xf3\xb0\x99\x99" // U+F0659 +#define ICON_MDI_PHONE_PLUS_OUTLINE "\xf3\xb1\x86\x9b" // U+F119B +#define ICON_MDI_PHONE_REFRESH "\xf3\xb1\xa6\x93" // U+F1993 +#define ICON_MDI_PHONE_REFRESH_OUTLINE "\xf3\xb1\xa6\x94" // U+F1994 +#define ICON_MDI_PHONE_REMOVE "\xf3\xb1\x94\xaf" // U+F152F +#define ICON_MDI_PHONE_REMOVE_OUTLINE "\xf3\xb1\x94\xb0" // U+F1530 +#define ICON_MDI_PHONE_RETURN "\xf3\xb0\xa0\xaf" // U+F082F +#define ICON_MDI_PHONE_RETURN_OUTLINE "\xf3\xb1\x86\x9c" // U+F119C +#define ICON_MDI_PHONE_RING "\xf3\xb1\x86\xab" // U+F11AB +#define ICON_MDI_PHONE_RING_OUTLINE "\xf3\xb1\x86\xac" // U+F11AC +#define ICON_MDI_PHONE_ROTATE_LANDSCAPE "\xf3\xb0\xa2\x85" // U+F0885 +#define ICON_MDI_PHONE_ROTATE_PORTRAIT "\xf3\xb0\xa2\x86" // U+F0886 +#define ICON_MDI_PHONE_SETTINGS "\xf3\xb0\x8f\xbd" // U+F03FD +#define ICON_MDI_PHONE_SETTINGS_OUTLINE "\xf3\xb1\x86\x9d" // U+F119D +#define ICON_MDI_PHONE_SYNC "\xf3\xb1\xa6\x95" // U+F1995 +#define ICON_MDI_PHONE_SYNC_OUTLINE "\xf3\xb1\xa6\x96" // U+F1996 +#define ICON_MDI_PHONE_VOIP "\xf3\xb0\x8f\xbe" // U+F03FE +#define ICON_MDI_PI "\xf3\xb0\x8f\xbf" // U+F03FF +#define ICON_MDI_PI_BOX "\xf3\xb0\x90\x80" // U+F0400 +#define ICON_MDI_PI_HOLE "\xf3\xb0\xb7\xb1" // U+F0DF1 +#define ICON_MDI_PIANO "\xf3\xb0\x99\xbd" // U+F067D +#define ICON_MDI_PIANO_OFF "\xf3\xb0\x9a\x98" // U+F0698 +#define ICON_MDI_PICKAXE "\xf3\xb0\xa2\xb7" // U+F08B7 +#define ICON_MDI_PICTURE_IN_PICTURE_BOTTOM_RIGHT "\xf3\xb0\xb9\x97" // U+F0E57 +#define ICON_MDI_PICTURE_IN_PICTURE_BOTTOM_RIGHT_OUTLINE "\xf3\xb0\xb9\x98" // U+F0E58 +#define ICON_MDI_PICTURE_IN_PICTURE_TOP_RIGHT "\xf3\xb0\xb9\x99" // U+F0E59 +#define ICON_MDI_PICTURE_IN_PICTURE_TOP_RIGHT_OUTLINE "\xf3\xb0\xb9\x9a" // U+F0E5A +#define ICON_MDI_PIER "\xf3\xb0\xa2\x87" // U+F0887 +#define ICON_MDI_PIER_CRANE "\xf3\xb0\xa2\x88" // U+F0888 +#define ICON_MDI_PIG "\xf3\xb0\x90\x81" // U+F0401 +#define ICON_MDI_PIG_VARIANT "\xf3\xb1\x80\x86" // U+F1006 +#define ICON_MDI_PIG_VARIANT_OUTLINE "\xf3\xb1\x99\xb8" // U+F1678 +#define ICON_MDI_PIGGY_BANK "\xf3\xb1\x80\x87" // U+F1007 +#define ICON_MDI_PIGGY_BANK_OUTLINE "\xf3\xb1\x99\xb9" // U+F1679 +#define ICON_MDI_PILL "\xf3\xb0\x90\x82" // U+F0402 +#define ICON_MDI_PILL_MULTIPLE "\xf3\xb1\xad\x8c" // U+F1B4C +#define ICON_MDI_PILL_OFF "\xf3\xb1\xa9\x9c" // U+F1A5C +#define ICON_MDI_PILLAR "\xf3\xb0\x9c\x82" // U+F0702 +#define ICON_MDI_PIN "\xf3\xb0\x90\x83" // U+F0403 +#define ICON_MDI_PIN_OFF "\xf3\xb0\x90\x84" // U+F0404 +#define ICON_MDI_PIN_OFF_OUTLINE "\xf3\xb0\xa4\xb0" // U+F0930 +#define ICON_MDI_PIN_OUTLINE "\xf3\xb0\xa4\xb1" // U+F0931 +#define ICON_MDI_PINE_TREE "\xf3\xb0\x90\x85" // U+F0405 +#define ICON_MDI_PINE_TREE_BOX "\xf3\xb0\x90\x86" // U+F0406 +#define ICON_MDI_PINE_TREE_FIRE "\xf3\xb1\x90\x9a" // U+F141A +#define ICON_MDI_PINE_TREE_VARIANT "\xf3\xb1\xb1\xb3" // U+F1C73 +#define ICON_MDI_PINE_TREE_VARIANT_OUTLINE "\xf3\xb1\xb1\xb4" // U+F1C74 +#define ICON_MDI_PINTEREST "\xf3\xb0\x90\x87" // U+F0407 +#define ICON_MDI_PINWHEEL "\xf3\xb0\xab\x95" // U+F0AD5 +#define ICON_MDI_PINWHEEL_OUTLINE "\xf3\xb0\xab\x96" // U+F0AD6 +#define ICON_MDI_PIPE "\xf3\xb0\x9f\xa5" // U+F07E5 +#define ICON_MDI_PIPE_DISCONNECTED "\xf3\xb0\x9f\xa6" // U+F07E6 +#define ICON_MDI_PIPE_LEAK "\xf3\xb0\xa2\x89" // U+F0889 +#define ICON_MDI_PIPE_VALVE "\xf3\xb1\xa1\x8d" // U+F184D +#define ICON_MDI_PIPE_WRENCH "\xf3\xb1\x8d\x94" // U+F1354 +#define ICON_MDI_PIRATE "\xf3\xb0\xa8\x88" // U+F0A08 +#define ICON_MDI_PISTOL "\xf3\xb0\x9c\x83" // U+F0703 +#define ICON_MDI_PISTON "\xf3\xb0\xa2\x8a" // U+F088A +#define ICON_MDI_PITCHFORK "\xf3\xb1\x95\x93" // U+F1553 +#define ICON_MDI_PIZZA "\xf3\xb0\x90\x89" // U+F0409 +#define ICON_MDI_PLANE_CAR "\xf3\xb1\xab\xbf" // U+F1AFF +#define ICON_MDI_PLANE_TRAIN "\xf3\xb1\xac\x80" // U+F1B00 +#define ICON_MDI_PLAY "\xf3\xb0\x90\x8a" // U+F040A +#define ICON_MDI_PLAY_BOX "\xf3\xb1\x89\xba" // U+F127A +#define ICON_MDI_PLAY_BOX_EDIT_OUTLINE "\xf3\xb1\xb0\xba" // U+F1C3A +#define ICON_MDI_PLAY_BOX_LOCK "\xf3\xb1\xa8\x96" // U+F1A16 +#define ICON_MDI_PLAY_BOX_LOCK_OPEN "\xf3\xb1\xa8\x97" // U+F1A17 +#define ICON_MDI_PLAY_BOX_LOCK_OPEN_OUTLINE "\xf3\xb1\xa8\x98" // U+F1A18 +#define ICON_MDI_PLAY_BOX_LOCK_OUTLINE "\xf3\xb1\xa8\x99" // U+F1A19 +#define ICON_MDI_PLAY_BOX_MULTIPLE "\xf3\xb0\xb4\x99" // U+F0D19 +#define ICON_MDI_PLAY_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x8f\xa6" // U+F13E6 +#define ICON_MDI_PLAY_BOX_OUTLINE "\xf3\xb0\x90\x8b" // U+F040B +#define ICON_MDI_PLAY_CIRCLE "\xf3\xb0\x90\x8c" // U+F040C +#define ICON_MDI_PLAY_CIRCLE_OUTLINE "\xf3\xb0\x90\x8d" // U+F040D +#define ICON_MDI_PLAY_NETWORK "\xf3\xb0\xa2\x8b" // U+F088B +#define ICON_MDI_PLAY_NETWORK_OUTLINE "\xf3\xb0\xb2\xb7" // U+F0CB7 +#define ICON_MDI_PLAY_OUTLINE "\xf3\xb0\xbc\x9b" // U+F0F1B +#define ICON_MDI_PLAY_PAUSE "\xf3\xb0\x90\x8e" // U+F040E +#define ICON_MDI_PLAY_PROTECTED_CONTENT "\xf3\xb0\x90\x8f" // U+F040F +#define ICON_MDI_PLAY_SPEED "\xf3\xb0\xa3\xbf" // U+F08FF +#define ICON_MDI_PLAYLIST_CHECK "\xf3\xb0\x97\x87" // U+F05C7 +#define ICON_MDI_PLAYLIST_EDIT "\xf3\xb0\xa4\x80" // U+F0900 +#define ICON_MDI_PLAYLIST_MINUS "\xf3\xb0\x90\x90" // U+F0410 +#define ICON_MDI_PLAYLIST_MUSIC "\xf3\xb0\xb2\xb8" // U+F0CB8 +#define ICON_MDI_PLAYLIST_MUSIC_OUTLINE "\xf3\xb0\xb2\xb9" // U+F0CB9 +#define ICON_MDI_PLAYLIST_PLAY "\xf3\xb0\x90\x91" // U+F0411 +#define ICON_MDI_PLAYLIST_PLUS "\xf3\xb0\x90\x92" // U+F0412 +#define ICON_MDI_PLAYLIST_REMOVE "\xf3\xb0\x90\x93" // U+F0413 +#define ICON_MDI_PLAYLIST_STAR "\xf3\xb0\xb7\xb2" // U+F0DF2 +#define ICON_MDI_PLEX "\xf3\xb0\x9a\xba" // U+F06BA +#define ICON_MDI_PLIERS "\xf3\xb1\xa6\xa4" // U+F19A4 +#define ICON_MDI_PLUS "\xf3\xb0\x90\x95" // U+F0415 +#define ICON_MDI_PLUS_BOX "\xf3\xb0\x90\x96" // U+F0416 +#define ICON_MDI_PLUS_BOX_MULTIPLE "\xf3\xb0\x8c\xb4" // U+F0334 +#define ICON_MDI_PLUS_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x83" // U+F1143 +#define ICON_MDI_PLUS_BOX_OUTLINE "\xf3\xb0\x9c\x84" // U+F0704 +#define ICON_MDI_PLUS_CIRCLE "\xf3\xb0\x90\x97" // U+F0417 +#define ICON_MDI_PLUS_CIRCLE_MULTIPLE "\xf3\xb0\x8d\x8c" // U+F034C +#define ICON_MDI_PLUS_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\x90\x98" // U+F0418 +#define ICON_MDI_PLUS_CIRCLE_OUTLINE "\xf3\xb0\x90\x99" // U+F0419 +#define ICON_MDI_PLUS_LOCK "\xf3\xb1\xa9\x9d" // U+F1A5D +#define ICON_MDI_PLUS_LOCK_OPEN "\xf3\xb1\xa9\x9e" // U+F1A5E +#define ICON_MDI_PLUS_MINUS "\xf3\xb0\xa6\x92" // U+F0992 +#define ICON_MDI_PLUS_MINUS_BOX "\xf3\xb0\xa6\x93" // U+F0993 +#define ICON_MDI_PLUS_MINUS_VARIANT "\xf3\xb1\x93\x89" // U+F14C9 +#define ICON_MDI_PLUS_NETWORK "\xf3\xb0\x90\x9a" // U+F041A +#define ICON_MDI_PLUS_NETWORK_OUTLINE "\xf3\xb0\xb2\xba" // U+F0CBA +#define ICON_MDI_PLUS_OUTLINE "\xf3\xb0\x9c\x85" // U+F0705 +#define ICON_MDI_PLUS_THICK "\xf3\xb1\x87\xac" // U+F11EC +#define ICON_MDI_POCKET "\xf3\xb1\xb2\xbe" // U+F1CBE +#define ICON_MDI_PODCAST "\xf3\xb0\xa6\x94" // U+F0994 +#define ICON_MDI_PODIUM "\xf3\xb0\xb4\xa5" // U+F0D25 +#define ICON_MDI_PODIUM_BRONZE "\xf3\xb0\xb4\xa6" // U+F0D26 +#define ICON_MDI_PODIUM_GOLD "\xf3\xb0\xb4\xa7" // U+F0D27 +#define ICON_MDI_PODIUM_SILVER "\xf3\xb0\xb4\xa8" // U+F0D28 +#define ICON_MDI_POINT_OF_SALE "\xf3\xb0\xb6\x92" // U+F0D92 +#define ICON_MDI_POKEBALL "\xf3\xb0\x90\x9d" // U+F041D +#define ICON_MDI_POKEMON_GO "\xf3\xb0\xa8\x89" // U+F0A09 +#define ICON_MDI_POKER_CHIP "\xf3\xb0\xa0\xb0" // U+F0830 +#define ICON_MDI_POLAROID "\xf3\xb0\x90\x9e" // U+F041E +#define ICON_MDI_POLICE_BADGE "\xf3\xb1\x85\xa7" // U+F1167 +#define ICON_MDI_POLICE_BADGE_OUTLINE "\xf3\xb1\x85\xa8" // U+F1168 +#define ICON_MDI_POLICE_STATION "\xf3\xb1\xa0\xb9" // U+F1839 +#define ICON_MDI_POLL "\xf3\xb0\x90\x9f" // U+F041F +#define ICON_MDI_POLO "\xf3\xb1\x93\x83" // U+F14C3 +#define ICON_MDI_POLYMER "\xf3\xb0\x90\xa1" // U+F0421 +#define ICON_MDI_POOL "\xf3\xb0\x98\x86" // U+F0606 +#define ICON_MDI_POOL_THERMOMETER "\xf3\xb1\xa9\x9f" // U+F1A5F +#define ICON_MDI_POPCORN "\xf3\xb0\x90\xa2" // U+F0422 +#define ICON_MDI_POST "\xf3\xb1\x80\x88" // U+F1008 +#define ICON_MDI_POST_LAMP "\xf3\xb1\xa9\xa0" // U+F1A60 +#define ICON_MDI_POST_OUTLINE "\xf3\xb1\x80\x89" // U+F1009 +#define ICON_MDI_POSTAGE_STAMP "\xf3\xb0\xb2\xbb" // U+F0CBB +#define ICON_MDI_POT "\xf3\xb0\x8b\xa5" // U+F02E5 +#define ICON_MDI_POT_MIX "\xf3\xb0\x99\x9b" // U+F065B +#define ICON_MDI_POT_MIX_OUTLINE "\xf3\xb0\x99\xb7" // U+F0677 +#define ICON_MDI_POT_OUTLINE "\xf3\xb0\x8b\xbf" // U+F02FF +#define ICON_MDI_POT_STEAM "\xf3\xb0\x99\x9a" // U+F065A +#define ICON_MDI_POT_STEAM_OUTLINE "\xf3\xb0\x8c\xa6" // U+F0326 +#define ICON_MDI_POUND "\xf3\xb0\x90\xa3" // U+F0423 +#define ICON_MDI_POUND_BOX "\xf3\xb0\x90\xa4" // U+F0424 +#define ICON_MDI_POUND_BOX_OUTLINE "\xf3\xb1\x85\xbf" // U+F117F +#define ICON_MDI_POWER "\xf3\xb0\x90\xa5" // U+F0425 +#define ICON_MDI_POWER_CYCLE "\xf3\xb0\xa4\x81" // U+F0901 +#define ICON_MDI_POWER_OFF "\xf3\xb0\xa4\x82" // U+F0902 +#define ICON_MDI_POWER_ON "\xf3\xb0\xa4\x83" // U+F0903 +#define ICON_MDI_POWER_PLUG "\xf3\xb0\x9a\xa5" // U+F06A5 +#define ICON_MDI_POWER_PLUG_BATTERY "\xf3\xb1\xb0\xbb" // U+F1C3B +#define ICON_MDI_POWER_PLUG_BATTERY_OUTLINE "\xf3\xb1\xb0\xbc" // U+F1C3C +#define ICON_MDI_POWER_PLUG_OFF "\xf3\xb0\x9a\xa6" // U+F06A6 +#define ICON_MDI_POWER_PLUG_OFF_OUTLINE "\xf3\xb1\x90\xa4" // U+F1424 +#define ICON_MDI_POWER_PLUG_OUTLINE "\xf3\xb1\x90\xa5" // U+F1425 +#define ICON_MDI_POWER_SETTINGS "\xf3\xb0\x90\xa6" // U+F0426 +#define ICON_MDI_POWER_SLEEP "\xf3\xb0\xa4\x84" // U+F0904 +#define ICON_MDI_POWER_SOCKET "\xf3\xb0\x90\xa7" // U+F0427 +#define ICON_MDI_POWER_SOCKET_AU "\xf3\xb0\xa4\x85" // U+F0905 +#define ICON_MDI_POWER_SOCKET_CH "\xf3\xb0\xbe\xb3" // U+F0FB3 +#define ICON_MDI_POWER_SOCKET_DE "\xf3\xb1\x84\x87" // U+F1107 +#define ICON_MDI_POWER_SOCKET_EU "\xf3\xb0\x9f\xa7" // U+F07E7 +#define ICON_MDI_POWER_SOCKET_FR "\xf3\xb1\x84\x88" // U+F1108 +#define ICON_MDI_POWER_SOCKET_IT "\xf3\xb1\x93\xbf" // U+F14FF +#define ICON_MDI_POWER_SOCKET_JP "\xf3\xb1\x84\x89" // U+F1109 +#define ICON_MDI_POWER_SOCKET_UK "\xf3\xb0\x9f\xa8" // U+F07E8 +#define ICON_MDI_POWER_SOCKET_US "\xf3\xb0\x9f\xa9" // U+F07E9 +#define ICON_MDI_POWER_STANDBY "\xf3\xb0\xa4\x86" // U+F0906 +#define ICON_MDI_POWERSHELL "\xf3\xb0\xa8\x8a" // U+F0A0A +#define ICON_MDI_PRESCRIPTION "\xf3\xb0\x9c\x86" // U+F0706 +#define ICON_MDI_PRESENTATION "\xf3\xb0\x90\xa8" // U+F0428 +#define ICON_MDI_PRESENTATION_PLAY "\xf3\xb0\x90\xa9" // U+F0429 +#define ICON_MDI_PRETZEL "\xf3\xb1\x95\xa2" // U+F1562 +#define ICON_MDI_PRINTER "\xf3\xb0\x90\xaa" // U+F042A +#define ICON_MDI_PRINTER_3D "\xf3\xb0\x90\xab" // U+F042B +#define ICON_MDI_PRINTER_3D_NOZZLE "\xf3\xb0\xb9\x9b" // U+F0E5B +#define ICON_MDI_PRINTER_3D_NOZZLE_ALERT "\xf3\xb1\x87\x80" // U+F11C0 +#define ICON_MDI_PRINTER_3D_NOZZLE_ALERT_OUTLINE "\xf3\xb1\x87\x81" // U+F11C1 +#define ICON_MDI_PRINTER_3D_NOZZLE_HEAT "\xf3\xb1\xa2\xb8" // U+F18B8 +#define ICON_MDI_PRINTER_3D_NOZZLE_HEAT_OUTLINE "\xf3\xb1\xa2\xb9" // U+F18B9 +#define ICON_MDI_PRINTER_3D_NOZZLE_OFF "\xf3\xb1\xac\x99" // U+F1B19 +#define ICON_MDI_PRINTER_3D_NOZZLE_OFF_OUTLINE "\xf3\xb1\xac\x9a" // U+F1B1A +#define ICON_MDI_PRINTER_3D_NOZZLE_OUTLINE "\xf3\xb0\xb9\x9c" // U+F0E5C +#define ICON_MDI_PRINTER_3D_OFF "\xf3\xb1\xac\x8e" // U+F1B0E +#define ICON_MDI_PRINTER_ALERT "\xf3\xb0\x90\xac" // U+F042C +#define ICON_MDI_PRINTER_CHECK "\xf3\xb1\x85\x86" // U+F1146 +#define ICON_MDI_PRINTER_EYE "\xf3\xb1\x91\x98" // U+F1458 +#define ICON_MDI_PRINTER_OFF "\xf3\xb0\xb9\x9d" // U+F0E5D +#define ICON_MDI_PRINTER_OFF_OUTLINE "\xf3\xb1\x9e\x85" // U+F1785 +#define ICON_MDI_PRINTER_OUTLINE "\xf3\xb1\x9e\x86" // U+F1786 +#define ICON_MDI_PRINTER_POS "\xf3\xb1\x81\x97" // U+F1057 +#define ICON_MDI_PRINTER_POS_ALERT "\xf3\xb1\xae\xbc" // U+F1BBC +#define ICON_MDI_PRINTER_POS_ALERT_OUTLINE "\xf3\xb1\xae\xbd" // U+F1BBD +#define ICON_MDI_PRINTER_POS_CANCEL "\xf3\xb1\xae\xbe" // U+F1BBE +#define ICON_MDI_PRINTER_POS_CANCEL_OUTLINE "\xf3\xb1\xae\xbf" // U+F1BBF +#define ICON_MDI_PRINTER_POS_CHECK "\xf3\xb1\xaf\x80" // U+F1BC0 +#define ICON_MDI_PRINTER_POS_CHECK_OUTLINE "\xf3\xb1\xaf\x81" // U+F1BC1 +#define ICON_MDI_PRINTER_POS_COG "\xf3\xb1\xaf\x82" // U+F1BC2 +#define ICON_MDI_PRINTER_POS_COG_OUTLINE "\xf3\xb1\xaf\x83" // U+F1BC3 +#define ICON_MDI_PRINTER_POS_EDIT "\xf3\xb1\xaf\x84" // U+F1BC4 +#define ICON_MDI_PRINTER_POS_EDIT_OUTLINE "\xf3\xb1\xaf\x85" // U+F1BC5 +#define ICON_MDI_PRINTER_POS_MINUS "\xf3\xb1\xaf\x86" // U+F1BC6 +#define ICON_MDI_PRINTER_POS_MINUS_OUTLINE "\xf3\xb1\xaf\x87" // U+F1BC7 +#define ICON_MDI_PRINTER_POS_NETWORK "\xf3\xb1\xaf\x88" // U+F1BC8 +#define ICON_MDI_PRINTER_POS_NETWORK_OUTLINE "\xf3\xb1\xaf\x89" // U+F1BC9 +#define ICON_MDI_PRINTER_POS_OFF "\xf3\xb1\xaf\x8a" // U+F1BCA +#define ICON_MDI_PRINTER_POS_OFF_OUTLINE "\xf3\xb1\xaf\x8b" // U+F1BCB +#define ICON_MDI_PRINTER_POS_OUTLINE "\xf3\xb1\xaf\x8c" // U+F1BCC +#define ICON_MDI_PRINTER_POS_PAUSE "\xf3\xb1\xaf\x8d" // U+F1BCD +#define ICON_MDI_PRINTER_POS_PAUSE_OUTLINE "\xf3\xb1\xaf\x8e" // U+F1BCE +#define ICON_MDI_PRINTER_POS_PLAY "\xf3\xb1\xaf\x8f" // U+F1BCF +#define ICON_MDI_PRINTER_POS_PLAY_OUTLINE "\xf3\xb1\xaf\x90" // U+F1BD0 +#define ICON_MDI_PRINTER_POS_PLUS "\xf3\xb1\xaf\x91" // U+F1BD1 +#define ICON_MDI_PRINTER_POS_PLUS_OUTLINE "\xf3\xb1\xaf\x92" // U+F1BD2 +#define ICON_MDI_PRINTER_POS_REFRESH "\xf3\xb1\xaf\x93" // U+F1BD3 +#define ICON_MDI_PRINTER_POS_REFRESH_OUTLINE "\xf3\xb1\xaf\x94" // U+F1BD4 +#define ICON_MDI_PRINTER_POS_REMOVE "\xf3\xb1\xaf\x95" // U+F1BD5 +#define ICON_MDI_PRINTER_POS_REMOVE_OUTLINE "\xf3\xb1\xaf\x96" // U+F1BD6 +#define ICON_MDI_PRINTER_POS_STAR "\xf3\xb1\xaf\x97" // U+F1BD7 +#define ICON_MDI_PRINTER_POS_STAR_OUTLINE "\xf3\xb1\xaf\x98" // U+F1BD8 +#define ICON_MDI_PRINTER_POS_STOP "\xf3\xb1\xaf\x99" // U+F1BD9 +#define ICON_MDI_PRINTER_POS_STOP_OUTLINE "\xf3\xb1\xaf\x9a" // U+F1BDA +#define ICON_MDI_PRINTER_POS_SYNC "\xf3\xb1\xaf\x9b" // U+F1BDB +#define ICON_MDI_PRINTER_POS_SYNC_OUTLINE "\xf3\xb1\xaf\x9c" // U+F1BDC +#define ICON_MDI_PRINTER_POS_WRENCH "\xf3\xb1\xaf\x9d" // U+F1BDD +#define ICON_MDI_PRINTER_POS_WRENCH_OUTLINE "\xf3\xb1\xaf\x9e" // U+F1BDE +#define ICON_MDI_PRINTER_SEARCH "\xf3\xb1\x91\x97" // U+F1457 +#define ICON_MDI_PRINTER_SETTINGS "\xf3\xb0\x9c\x87" // U+F0707 +#define ICON_MDI_PRINTER_WIRELESS "\xf3\xb0\xa8\x8b" // U+F0A0B +#define ICON_MDI_PRIORITY_HIGH "\xf3\xb0\x98\x83" // U+F0603 +#define ICON_MDI_PRIORITY_LOW "\xf3\xb0\x98\x84" // U+F0604 +#define ICON_MDI_PROFESSIONAL_HEXAGON "\xf3\xb0\x90\xad" // U+F042D +#define ICON_MDI_PROGRESS_ALERT "\xf3\xb0\xb2\xbc" // U+F0CBC +#define ICON_MDI_PROGRESS_CHECK "\xf3\xb0\xa6\x95" // U+F0995 +#define ICON_MDI_PROGRESS_CLOCK "\xf3\xb0\xa6\x96" // U+F0996 +#define ICON_MDI_PROGRESS_CLOSE "\xf3\xb1\x84\x8a" // U+F110A +#define ICON_MDI_PROGRESS_DOWNLOAD "\xf3\xb0\xa6\x97" // U+F0997 +#define ICON_MDI_PROGRESS_HELPER "\xf3\xb1\xae\xa2" // U+F1BA2 +#define ICON_MDI_PROGRESS_PENCIL "\xf3\xb1\x9e\x87" // U+F1787 +#define ICON_MDI_PROGRESS_QUESTION "\xf3\xb1\x94\xa2" // U+F1522 +#define ICON_MDI_PROGRESS_STAR "\xf3\xb1\x9e\x88" // U+F1788 +#define ICON_MDI_PROGRESS_STAR_FOUR_POINTS "\xf3\xb1\xb0\xbd" // U+F1C3D +#define ICON_MDI_PROGRESS_UPLOAD "\xf3\xb0\xa6\x98" // U+F0998 +#define ICON_MDI_PROGRESS_WRENCH "\xf3\xb0\xb2\xbd" // U+F0CBD +#define ICON_MDI_PROJECTOR "\xf3\xb0\x90\xae" // U+F042E +#define ICON_MDI_PROJECTOR_OFF "\xf3\xb1\xa8\xa3" // U+F1A23 +#define ICON_MDI_PROJECTOR_SCREEN "\xf3\xb0\x90\xaf" // U+F042F +#define ICON_MDI_PROJECTOR_SCREEN_OFF "\xf3\xb1\xa0\x8d" // U+F180D +#define ICON_MDI_PROJECTOR_SCREEN_OFF_OUTLINE "\xf3\xb1\xa0\x8e" // U+F180E +#define ICON_MDI_PROJECTOR_SCREEN_OUTLINE "\xf3\xb1\x9c\xa4" // U+F1724 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT "\xf3\xb1\xa0\x8f" // U+F180F +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OFF "\xf3\xb1\xa0\x90" // U+F1810 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OFF_OUTLINE "\xf3\xb1\xa0\x91" // U+F1811 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OUTLINE "\xf3\xb1\xa0\x92" // U+F1812 +#define ICON_MDI_PROPANE_TANK "\xf3\xb1\x8d\x97" // U+F1357 +#define ICON_MDI_PROPANE_TANK_OUTLINE "\xf3\xb1\x8d\x98" // U+F1358 +#define ICON_MDI_PROTOCOL "\xf3\xb0\xbf\x98" // U+F0FD8 +#define ICON_MDI_PUBLISH "\xf3\xb0\x9a\xa7" // U+F06A7 +#define ICON_MDI_PUBLISH_OFF "\xf3\xb1\xa5\x85" // U+F1945 +#define ICON_MDI_PULSE "\xf3\xb0\x90\xb0" // U+F0430 +#define ICON_MDI_PUMP "\xf3\xb1\x90\x82" // U+F1402 +#define ICON_MDI_PUMP_OFF "\xf3\xb1\xac\xa2" // U+F1B22 +#define ICON_MDI_PUMPKIN "\xf3\xb0\xae\xbf" // U+F0BBF +#define ICON_MDI_PURSE "\xf3\xb0\xbc\x9c" // U+F0F1C +#define ICON_MDI_PURSE_OUTLINE "\xf3\xb0\xbc\x9d" // U+F0F1D +#define ICON_MDI_PUZZLE "\xf3\xb0\x90\xb1" // U+F0431 +#define ICON_MDI_PUZZLE_CHECK "\xf3\xb1\x90\xa6" // U+F1426 +#define ICON_MDI_PUZZLE_CHECK_OUTLINE "\xf3\xb1\x90\xa7" // U+F1427 +#define ICON_MDI_PUZZLE_EDIT "\xf3\xb1\x93\x93" // U+F14D3 +#define ICON_MDI_PUZZLE_EDIT_OUTLINE "\xf3\xb1\x93\x99" // U+F14D9 +#define ICON_MDI_PUZZLE_HEART "\xf3\xb1\x93\x94" // U+F14D4 +#define ICON_MDI_PUZZLE_HEART_OUTLINE "\xf3\xb1\x93\x9a" // U+F14DA +#define ICON_MDI_PUZZLE_MINUS "\xf3\xb1\x93\x91" // U+F14D1 +#define ICON_MDI_PUZZLE_MINUS_OUTLINE "\xf3\xb1\x93\x97" // U+F14D7 +#define ICON_MDI_PUZZLE_OUTLINE "\xf3\xb0\xa9\xa6" // U+F0A66 +#define ICON_MDI_PUZZLE_PLUS "\xf3\xb1\x93\x90" // U+F14D0 +#define ICON_MDI_PUZZLE_PLUS_OUTLINE "\xf3\xb1\x93\x96" // U+F14D6 +#define ICON_MDI_PUZZLE_REMOVE "\xf3\xb1\x93\x92" // U+F14D2 +#define ICON_MDI_PUZZLE_REMOVE_OUTLINE "\xf3\xb1\x93\x98" // U+F14D8 +#define ICON_MDI_PUZZLE_STAR "\xf3\xb1\x93\x95" // U+F14D5 +#define ICON_MDI_PUZZLE_STAR_OUTLINE "\xf3\xb1\x93\x9b" // U+F14DB +#define ICON_MDI_PYRAMID "\xf3\xb1\xa5\x92" // U+F1952 +#define ICON_MDI_PYRAMID_OFF "\xf3\xb1\xa5\x93" // U+F1953 +#define ICON_MDI_QI "\xf3\xb0\xa6\x99" // U+F0999 +#define ICON_MDI_QQCHAT "\xf3\xb0\x98\x85" // U+F0605 +#define ICON_MDI_QRCODE "\xf3\xb0\x90\xb2" // U+F0432 +#define ICON_MDI_QRCODE_EDIT "\xf3\xb0\xa2\xb8" // U+F08B8 +#define ICON_MDI_QRCODE_MINUS "\xf3\xb1\x86\x8c" // U+F118C +#define ICON_MDI_QRCODE_PLUS "\xf3\xb1\x86\x8b" // U+F118B +#define ICON_MDI_QRCODE_REMOVE "\xf3\xb1\x86\x8d" // U+F118D +#define ICON_MDI_QRCODE_SCAN "\xf3\xb0\x90\xb3" // U+F0433 +#define ICON_MDI_QUADCOPTER "\xf3\xb0\x90\xb4" // U+F0434 +#define ICON_MDI_QUALITY_HIGH "\xf3\xb0\x90\xb5" // U+F0435 +#define ICON_MDI_QUALITY_LOW "\xf3\xb0\xa8\x8c" // U+F0A0C +#define ICON_MDI_QUALITY_MEDIUM "\xf3\xb0\xa8\x8d" // U+F0A0D +#define ICON_MDI_QUEUE_FIRST_IN_LAST_OUT "\xf3\xb1\xb2\xaf" // U+F1CAF +#define ICON_MDI_QUORA "\xf3\xb0\xb4\xa9" // U+F0D29 +#define ICON_MDI_RABBIT "\xf3\xb0\xa4\x87" // U+F0907 +#define ICON_MDI_RABBIT_VARIANT "\xf3\xb1\xa9\xa1" // U+F1A61 +#define ICON_MDI_RABBIT_VARIANT_OUTLINE "\xf3\xb1\xa9\xa2" // U+F1A62 +#define ICON_MDI_RACING_HELMET "\xf3\xb0\xb6\x93" // U+F0D93 +#define ICON_MDI_RACQUETBALL "\xf3\xb0\xb6\x94" // U+F0D94 +#define ICON_MDI_RADAR "\xf3\xb0\x90\xb7" // U+F0437 +#define ICON_MDI_RADIATOR "\xf3\xb0\x90\xb8" // U+F0438 +#define ICON_MDI_RADIATOR_DISABLED "\xf3\xb0\xab\x97" // U+F0AD7 +#define ICON_MDI_RADIATOR_OFF "\xf3\xb0\xab\x98" // U+F0AD8 +#define ICON_MDI_RADIO "\xf3\xb0\x90\xb9" // U+F0439 +#define ICON_MDI_RADIO_AM "\xf3\xb0\xb2\xbe" // U+F0CBE +#define ICON_MDI_RADIO_FM "\xf3\xb0\xb2\xbf" // U+F0CBF +#define ICON_MDI_RADIO_HANDHELD "\xf3\xb0\x90\xba" // U+F043A +#define ICON_MDI_RADIO_OFF "\xf3\xb1\x88\x9c" // U+F121C +#define ICON_MDI_RADIO_TOWER "\xf3\xb0\x90\xbb" // U+F043B +#define ICON_MDI_RADIOACTIVE "\xf3\xb0\x90\xbc" // U+F043C +#define ICON_MDI_RADIOACTIVE_CIRCLE "\xf3\xb1\xa1\x9d" // U+F185D +#define ICON_MDI_RADIOACTIVE_CIRCLE_OUTLINE "\xf3\xb1\xa1\x9e" // U+F185E +#define ICON_MDI_RADIOACTIVE_OFF "\xf3\xb0\xbb\x81" // U+F0EC1 +#define ICON_MDI_RADIOBOX_BLANK "\xf3\xb0\x90\xbd" // U+F043D +#define ICON_MDI_RADIOBOX_INDETERMINATE_VARIANT "\xf3\xb1\xb1\x9e" // U+F1C5E +#define ICON_MDI_RADIOBOX_MARKED "\xf3\xb0\x90\xbe" // U+F043E +#define ICON_MDI_RADIOLOGY_BOX "\xf3\xb1\x93\x85" // U+F14C5 +#define ICON_MDI_RADIOLOGY_BOX_OUTLINE "\xf3\xb1\x93\x86" // U+F14C6 +#define ICON_MDI_RADIUS "\xf3\xb0\xb3\x80" // U+F0CC0 +#define ICON_MDI_RADIUS_OUTLINE "\xf3\xb0\xb3\x81" // U+F0CC1 +#define ICON_MDI_RAILROAD_LIGHT "\xf3\xb0\xbc\x9e" // U+F0F1E +#define ICON_MDI_RAKE "\xf3\xb1\x95\x84" // U+F1544 +#define ICON_MDI_RASPBERRY_PI "\xf3\xb0\x90\xbf" // U+F043F +#define ICON_MDI_RAW "\xf3\xb1\xa8\x8f" // U+F1A0F +#define ICON_MDI_RAW_OFF "\xf3\xb1\xa8\x90" // U+F1A10 +#define ICON_MDI_RAY_END "\xf3\xb0\x91\x80" // U+F0440 +#define ICON_MDI_RAY_END_ARROW "\xf3\xb0\x91\x81" // U+F0441 +#define ICON_MDI_RAY_START "\xf3\xb0\x91\x82" // U+F0442 +#define ICON_MDI_RAY_START_ARROW "\xf3\xb0\x91\x83" // U+F0443 +#define ICON_MDI_RAY_START_END "\xf3\xb0\x91\x84" // U+F0444 +#define ICON_MDI_RAY_START_VERTEX_END "\xf3\xb1\x97\x98" // U+F15D8 +#define ICON_MDI_RAY_VERTEX "\xf3\xb0\x91\x85" // U+F0445 +#define ICON_MDI_RAZOR_DOUBLE_EDGE "\xf3\xb1\xa6\x97" // U+F1997 +#define ICON_MDI_RAZOR_SINGLE_EDGE "\xf3\xb1\xa6\x98" // U+F1998 +#define ICON_MDI_REACT "\xf3\xb0\x9c\x88" // U+F0708 +#define ICON_MDI_READ "\xf3\xb0\x91\x87" // U+F0447 +#define ICON_MDI_RECEIPT "\xf3\xb0\xa0\xa4" // U+F0824 +#define ICON_MDI_RECEIPT_CLOCK "\xf3\xb1\xb0\xbe" // U+F1C3E +#define ICON_MDI_RECEIPT_CLOCK_OUTLINE "\xf3\xb1\xb0\xbf" // U+F1C3F +#define ICON_MDI_RECEIPT_OUTLINE "\xf3\xb0\x93\xb7" // U+F04F7 +#define ICON_MDI_RECEIPT_SEND "\xf3\xb1\xb1\x80" // U+F1C40 +#define ICON_MDI_RECEIPT_SEND_OUTLINE "\xf3\xb1\xb1\x81" // U+F1C41 +#define ICON_MDI_RECEIPT_TEXT "\xf3\xb0\x91\x89" // U+F0449 +#define ICON_MDI_RECEIPT_TEXT_ARROW_LEFT "\xf3\xb1\xb1\x82" // U+F1C42 +#define ICON_MDI_RECEIPT_TEXT_ARROW_LEFT_OUTLINE "\xf3\xb1\xb1\x83" // U+F1C43 +#define ICON_MDI_RECEIPT_TEXT_ARROW_RIGHT "\xf3\xb1\xb1\x84" // U+F1C44 +#define ICON_MDI_RECEIPT_TEXT_ARROW_RIGHT_OUTLINE "\xf3\xb1\xb1\x85" // U+F1C45 +#define ICON_MDI_RECEIPT_TEXT_CHECK "\xf3\xb1\xa9\xa3" // U+F1A63 +#define ICON_MDI_RECEIPT_TEXT_CHECK_OUTLINE "\xf3\xb1\xa9\xa4" // U+F1A64 +#define ICON_MDI_RECEIPT_TEXT_CLOCK "\xf3\xb1\xb1\x86" // U+F1C46 +#define ICON_MDI_RECEIPT_TEXT_CLOCK_OUTLINE "\xf3\xb1\xb1\x87" // U+F1C47 +#define ICON_MDI_RECEIPT_TEXT_EDIT "\xf3\xb1\xb1\x88" // U+F1C48 +#define ICON_MDI_RECEIPT_TEXT_EDIT_OUTLINE "\xf3\xb1\xb1\x89" // U+F1C49 +#define ICON_MDI_RECEIPT_TEXT_MINUS "\xf3\xb1\xa9\xa5" // U+F1A65 +#define ICON_MDI_RECEIPT_TEXT_MINUS_OUTLINE "\xf3\xb1\xa9\xa6" // U+F1A66 +#define ICON_MDI_RECEIPT_TEXT_OUTLINE "\xf3\xb1\xa7\x9c" // U+F19DC +#define ICON_MDI_RECEIPT_TEXT_PLUS "\xf3\xb1\xa9\xa7" // U+F1A67 +#define ICON_MDI_RECEIPT_TEXT_PLUS_OUTLINE "\xf3\xb1\xa9\xa8" // U+F1A68 +#define ICON_MDI_RECEIPT_TEXT_REMOVE "\xf3\xb1\xa9\xa9" // U+F1A69 +#define ICON_MDI_RECEIPT_TEXT_REMOVE_OUTLINE "\xf3\xb1\xa9\xaa" // U+F1A6A +#define ICON_MDI_RECEIPT_TEXT_SEND "\xf3\xb1\xb1\x8a" // U+F1C4A +#define ICON_MDI_RECEIPT_TEXT_SEND_OUTLINE "\xf3\xb1\xb1\x8b" // U+F1C4B +#define ICON_MDI_RECORD "\xf3\xb0\x91\x8a" // U+F044A +#define ICON_MDI_RECORD_CIRCLE "\xf3\xb0\xbb\x82" // U+F0EC2 +#define ICON_MDI_RECORD_CIRCLE_OUTLINE "\xf3\xb0\xbb\x83" // U+F0EC3 +#define ICON_MDI_RECORD_PLAYER "\xf3\xb0\xa6\x9a" // U+F099A +#define ICON_MDI_RECORD_REC "\xf3\xb0\x91\x8b" // U+F044B +#define ICON_MDI_RECTANGLE "\xf3\xb0\xb9\x9e" // U+F0E5E +#define ICON_MDI_RECTANGLE_OUTLINE "\xf3\xb0\xb9\x9f" // U+F0E5F +#define ICON_MDI_RECYCLE "\xf3\xb0\x91\x8c" // U+F044C +#define ICON_MDI_RECYCLE_VARIANT "\xf3\xb1\x8e\x9d" // U+F139D +#define ICON_MDI_REDDIT "\xf3\xb0\x91\x8d" // U+F044D +#define ICON_MDI_REDHAT "\xf3\xb1\x84\x9b" // U+F111B +#define ICON_MDI_REDO "\xf3\xb0\x91\x8e" // U+F044E +#define ICON_MDI_REDO_VARIANT "\xf3\xb0\x91\x8f" // U+F044F +#define ICON_MDI_REFLECT_HORIZONTAL "\xf3\xb0\xa8\x8e" // U+F0A0E +#define ICON_MDI_REFLECT_VERTICAL "\xf3\xb0\xa8\x8f" // U+F0A0F +#define ICON_MDI_REFRESH "\xf3\xb0\x91\x90" // U+F0450 +#define ICON_MDI_REFRESH_AUTO "\xf3\xb1\xa3\xb2" // U+F18F2 +#define ICON_MDI_REFRESH_CIRCLE "\xf3\xb1\x8d\xb7" // U+F1377 +#define ICON_MDI_REGEX "\xf3\xb0\x91\x91" // U+F0451 +#define ICON_MDI_REGISTERED_TRADEMARK "\xf3\xb0\xa9\xa7" // U+F0A67 +#define ICON_MDI_REITERATE "\xf3\xb1\x96\x88" // U+F1588 +#define ICON_MDI_RELATION_MANY_TO_MANY "\xf3\xb1\x92\x96" // U+F1496 +#define ICON_MDI_RELATION_MANY_TO_ONE "\xf3\xb1\x92\x97" // U+F1497 +#define ICON_MDI_RELATION_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\x98" // U+F1498 +#define ICON_MDI_RELATION_MANY_TO_ONLY_ONE "\xf3\xb1\x92\x99" // U+F1499 +#define ICON_MDI_RELATION_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\x9a" // U+F149A +#define ICON_MDI_RELATION_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\x9b" // U+F149B +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_MANY "\xf3\xb1\x92\x9c" // U+F149C +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONE "\xf3\xb1\x92\x9d" // U+F149D +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\x9e" // U+F149E +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONLY_ONE "\xf3\xb1\x92\x9f" // U+F149F +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\xa0" // U+F14A0 +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\xa1" // U+F14A1 +#define ICON_MDI_RELATION_ONE_TO_MANY "\xf3\xb1\x92\xa2" // U+F14A2 +#define ICON_MDI_RELATION_ONE_TO_ONE "\xf3\xb1\x92\xa3" // U+F14A3 +#define ICON_MDI_RELATION_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xa4" // U+F14A4 +#define ICON_MDI_RELATION_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xa5" // U+F14A5 +#define ICON_MDI_RELATION_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xa6" // U+F14A6 +#define ICON_MDI_RELATION_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xa7" // U+F14A7 +#define ICON_MDI_RELATION_ONLY_ONE_TO_MANY "\xf3\xb1\x92\xa8" // U+F14A8 +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONE "\xf3\xb1\x92\xa9" // U+F14A9 +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xaa" // U+F14AA +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xab" // U+F14AB +#define ICON_MDI_RELATION_ONLY_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xac" // U+F14AC +#define ICON_MDI_RELATION_ONLY_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xad" // U+F14AD +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_MANY "\xf3\xb1\x92\xae" // U+F14AE +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONE "\xf3\xb1\x92\xaf" // U+F14AF +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\xb0" // U+F14B0 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONLY_ONE "\xf3\xb1\x92\xb1" // U+F14B1 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\xb2" // U+F14B2 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\xb3" // U+F14B3 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_MANY "\xf3\xb1\x92\xb4" // U+F14B4 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONE "\xf3\xb1\x92\xb5" // U+F14B5 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xb6" // U+F14B6 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xb7" // U+F14B7 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xb8" // U+F14B8 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xb9" // U+F14B9 +#define ICON_MDI_RELATIVE_SCALE "\xf3\xb0\x91\x92" // U+F0452 +#define ICON_MDI_RELOAD "\xf3\xb0\x91\x93" // U+F0453 +#define ICON_MDI_RELOAD_ALERT "\xf3\xb1\x84\x8b" // U+F110B +#define ICON_MDI_REMINDER "\xf3\xb0\xa2\x8c" // U+F088C +#define ICON_MDI_REMOTE "\xf3\xb0\x91\x94" // U+F0454 +#define ICON_MDI_REMOTE_DESKTOP "\xf3\xb0\xa2\xb9" // U+F08B9 +#define ICON_MDI_REMOTE_OFF "\xf3\xb0\xbb\x84" // U+F0EC4 +#define ICON_MDI_REMOTE_TV "\xf3\xb0\xbb\x85" // U+F0EC5 +#define ICON_MDI_REMOTE_TV_OFF "\xf3\xb0\xbb\x86" // U+F0EC6 +#define ICON_MDI_RENAME "\xf3\xb1\xb0\x98" // U+F1C18 +#define ICON_MDI_RENAME_BOX "\xf3\xb0\x91\x95" // U+F0455 +#define ICON_MDI_RENAME_BOX_OUTLINE "\xf3\xb1\xb0\x99" // U+F1C19 +#define ICON_MDI_RENAME_OUTLINE "\xf3\xb1\xb0\x9a" // U+F1C1A +#define ICON_MDI_REORDER_HORIZONTAL "\xf3\xb0\x9a\x88" // U+F0688 +#define ICON_MDI_REORDER_VERTICAL "\xf3\xb0\x9a\x89" // U+F0689 +#define ICON_MDI_REPEAT "\xf3\xb0\x91\x96" // U+F0456 +#define ICON_MDI_REPEAT_OFF "\xf3\xb0\x91\x97" // U+F0457 +#define ICON_MDI_REPEAT_ONCE "\xf3\xb0\x91\x98" // U+F0458 +#define ICON_MDI_REPEAT_VARIANT "\xf3\xb0\x95\x87" // U+F0547 +#define ICON_MDI_REPLAY "\xf3\xb0\x91\x99" // U+F0459 +#define ICON_MDI_REPLY "\xf3\xb0\x91\x9a" // U+F045A +#define ICON_MDI_REPLY_ALL "\xf3\xb0\x91\x9b" // U+F045B +#define ICON_MDI_REPLY_ALL_OUTLINE "\xf3\xb0\xbc\x9f" // U+F0F1F +#define ICON_MDI_REPLY_CIRCLE "\xf3\xb1\x86\xae" // U+F11AE +#define ICON_MDI_REPLY_OUTLINE "\xf3\xb0\xbc\xa0" // U+F0F20 +#define ICON_MDI_REPRODUCTION "\xf3\xb0\x91\x9c" // U+F045C +#define ICON_MDI_RESISTOR "\xf3\xb0\xad\x84" // U+F0B44 +#define ICON_MDI_RESISTOR_NODES "\xf3\xb0\xad\x85" // U+F0B45 +#define ICON_MDI_RESIZE "\xf3\xb0\xa9\xa8" // U+F0A68 +#define ICON_MDI_RESIZE_BOTTOM_RIGHT "\xf3\xb0\x91\x9d" // U+F045D +#define ICON_MDI_RESPONSIVE "\xf3\xb0\x91\x9e" // U+F045E +#define ICON_MDI_RESTART "\xf3\xb0\x9c\x89" // U+F0709 +#define ICON_MDI_RESTART_ALERT "\xf3\xb1\x84\x8c" // U+F110C +#define ICON_MDI_RESTART_OFF "\xf3\xb0\xb6\x95" // U+F0D95 +#define ICON_MDI_RESTORE "\xf3\xb0\xa6\x9b" // U+F099B +#define ICON_MDI_RESTORE_ALERT "\xf3\xb1\x84\x8d" // U+F110D +#define ICON_MDI_REWIND "\xf3\xb0\x91\x9f" // U+F045F +#define ICON_MDI_REWIND_10 "\xf3\xb0\xb4\xaa" // U+F0D2A +#define ICON_MDI_REWIND_15 "\xf3\xb1\xa5\x86" // U+F1946 +#define ICON_MDI_REWIND_30 "\xf3\xb0\xb6\x96" // U+F0D96 +#define ICON_MDI_REWIND_45 "\xf3\xb1\xac\x93" // U+F1B13 +#define ICON_MDI_REWIND_5 "\xf3\xb1\x87\xb9" // U+F11F9 +#define ICON_MDI_REWIND_60 "\xf3\xb1\x98\x8c" // U+F160C +#define ICON_MDI_REWIND_OUTLINE "\xf3\xb0\x9c\x8a" // U+F070A +#define ICON_MDI_RHOMBUS "\xf3\xb0\x9c\x8b" // U+F070B +#define ICON_MDI_RHOMBUS_MEDIUM "\xf3\xb0\xa8\x90" // U+F0A10 +#define ICON_MDI_RHOMBUS_MEDIUM_OUTLINE "\xf3\xb1\x93\x9c" // U+F14DC +#define ICON_MDI_RHOMBUS_OUTLINE "\xf3\xb0\x9c\x8c" // U+F070C +#define ICON_MDI_RHOMBUS_SPLIT "\xf3\xb0\xa8\x91" // U+F0A11 +#define ICON_MDI_RHOMBUS_SPLIT_OUTLINE "\xf3\xb1\x93\x9d" // U+F14DD +#define ICON_MDI_RIBBON "\xf3\xb0\x91\xa0" // U+F0460 +#define ICON_MDI_RICE "\xf3\xb0\x9f\xaa" // U+F07EA +#define ICON_MDI_RICKSHAW "\xf3\xb1\x96\xbb" // U+F15BB +#define ICON_MDI_RICKSHAW_ELECTRIC "\xf3\xb1\x96\xbc" // U+F15BC +#define ICON_MDI_RING "\xf3\xb0\x9f\xab" // U+F07EB +#define ICON_MDI_RIVET "\xf3\xb0\xb9\xa0" // U+F0E60 +#define ICON_MDI_ROAD "\xf3\xb0\x91\xa1" // U+F0461 +#define ICON_MDI_ROAD_VARIANT "\xf3\xb0\x91\xa2" // U+F0462 +#define ICON_MDI_ROBBER "\xf3\xb1\x81\x98" // U+F1058 +#define ICON_MDI_ROBOT "\xf3\xb0\x9a\xa9" // U+F06A9 +#define ICON_MDI_ROBOT_ANGRY "\xf3\xb1\x9a\x9d" // U+F169D +#define ICON_MDI_ROBOT_ANGRY_OUTLINE "\xf3\xb1\x9a\x9e" // U+F169E +#define ICON_MDI_ROBOT_CONFUSED "\xf3\xb1\x9a\x9f" // U+F169F +#define ICON_MDI_ROBOT_CONFUSED_OUTLINE "\xf3\xb1\x9a\xa0" // U+F16A0 +#define ICON_MDI_ROBOT_DEAD "\xf3\xb1\x9a\xa1" // U+F16A1 +#define ICON_MDI_ROBOT_DEAD_OUTLINE "\xf3\xb1\x9a\xa2" // U+F16A2 +#define ICON_MDI_ROBOT_EXCITED "\xf3\xb1\x9a\xa3" // U+F16A3 +#define ICON_MDI_ROBOT_EXCITED_OUTLINE "\xf3\xb1\x9a\xa4" // U+F16A4 +#define ICON_MDI_ROBOT_HAPPY "\xf3\xb1\x9c\x99" // U+F1719 +#define ICON_MDI_ROBOT_HAPPY_OUTLINE "\xf3\xb1\x9c\x9a" // U+F171A +#define ICON_MDI_ROBOT_INDUSTRIAL "\xf3\xb0\xad\x86" // U+F0B46 +#define ICON_MDI_ROBOT_INDUSTRIAL_OUTLINE "\xf3\xb1\xa8\x9a" // U+F1A1A +#define ICON_MDI_ROBOT_LOVE "\xf3\xb1\x9a\xa5" // U+F16A5 +#define ICON_MDI_ROBOT_LOVE_OUTLINE "\xf3\xb1\x9a\xa6" // U+F16A6 +#define ICON_MDI_ROBOT_MOWER "\xf3\xb1\x87\xb7" // U+F11F7 +#define ICON_MDI_ROBOT_MOWER_OUTLINE "\xf3\xb1\x87\xb3" // U+F11F3 +#define ICON_MDI_ROBOT_OFF "\xf3\xb1\x9a\xa7" // U+F16A7 +#define ICON_MDI_ROBOT_OFF_OUTLINE "\xf3\xb1\x99\xbb" // U+F167B +#define ICON_MDI_ROBOT_OUTLINE "\xf3\xb1\x99\xba" // U+F167A +#define ICON_MDI_ROBOT_VACUUM "\xf3\xb0\x9c\x8d" // U+F070D +#define ICON_MDI_ROBOT_VACUUM_ALERT "\xf3\xb1\xad\x9d" // U+F1B5D +#define ICON_MDI_ROBOT_VACUUM_OFF "\xf3\xb1\xb0\x81" // U+F1C01 +#define ICON_MDI_ROBOT_VACUUM_VARIANT "\xf3\xb0\xa4\x88" // U+F0908 +#define ICON_MDI_ROBOT_VACUUM_VARIANT_ALERT "\xf3\xb1\xad\x9e" // U+F1B5E +#define ICON_MDI_ROBOT_VACUUM_VARIANT_OFF "\xf3\xb1\xb0\x82" // U+F1C02 +#define ICON_MDI_ROCKET "\xf3\xb0\x91\xa3" // U+F0463 +#define ICON_MDI_ROCKET_LAUNCH "\xf3\xb1\x93\x9e" // U+F14DE +#define ICON_MDI_ROCKET_LAUNCH_OUTLINE "\xf3\xb1\x93\x9f" // U+F14DF +#define ICON_MDI_ROCKET_OUTLINE "\xf3\xb1\x8e\xaf" // U+F13AF +#define ICON_MDI_RODENT "\xf3\xb1\x8c\xa7" // U+F1327 +#define ICON_MDI_ROLLER_SHADE "\xf3\xb1\xa9\xab" // U+F1A6B +#define ICON_MDI_ROLLER_SHADE_CLOSED "\xf3\xb1\xa9\xac" // U+F1A6C +#define ICON_MDI_ROLLER_SKATE "\xf3\xb0\xb4\xab" // U+F0D2B +#define ICON_MDI_ROLLER_SKATE_OFF "\xf3\xb0\x85\x85" // U+F0145 +#define ICON_MDI_ROLLERBLADE "\xf3\xb0\xb4\xac" // U+F0D2C +#define ICON_MDI_ROLLERBLADE_OFF "\xf3\xb0\x80\xae" // U+F002E +#define ICON_MDI_ROLLUPJS "\xf3\xb0\xaf\x80" // U+F0BC0 +#define ICON_MDI_ROLODEX "\xf3\xb1\xaa\xb9" // U+F1AB9 +#define ICON_MDI_ROLODEX_OUTLINE "\xf3\xb1\xaa\xba" // U+F1ABA +#define ICON_MDI_ROMAN_NUMERAL_1 "\xf3\xb1\x82\x88" // U+F1088 +#define ICON_MDI_ROMAN_NUMERAL_10 "\xf3\xb1\x82\x91" // U+F1091 +#define ICON_MDI_ROMAN_NUMERAL_2 "\xf3\xb1\x82\x89" // U+F1089 +#define ICON_MDI_ROMAN_NUMERAL_3 "\xf3\xb1\x82\x8a" // U+F108A +#define ICON_MDI_ROMAN_NUMERAL_4 "\xf3\xb1\x82\x8b" // U+F108B +#define ICON_MDI_ROMAN_NUMERAL_5 "\xf3\xb1\x82\x8c" // U+F108C +#define ICON_MDI_ROMAN_NUMERAL_6 "\xf3\xb1\x82\x8d" // U+F108D +#define ICON_MDI_ROMAN_NUMERAL_7 "\xf3\xb1\x82\x8e" // U+F108E +#define ICON_MDI_ROMAN_NUMERAL_8 "\xf3\xb1\x82\x8f" // U+F108F +#define ICON_MDI_ROMAN_NUMERAL_9 "\xf3\xb1\x82\x90" // U+F1090 +#define ICON_MDI_ROOM_SERVICE "\xf3\xb0\xa2\x8d" // U+F088D +#define ICON_MDI_ROOM_SERVICE_OUTLINE "\xf3\xb0\xb6\x97" // U+F0D97 +#define ICON_MDI_ROTATE_360 "\xf3\xb1\xa6\x99" // U+F1999 +#define ICON_MDI_ROTATE_3D "\xf3\xb0\xbb\x87" // U+F0EC7 +#define ICON_MDI_ROTATE_3D_VARIANT "\xf3\xb0\x91\xa4" // U+F0464 +#define ICON_MDI_ROTATE_LEFT "\xf3\xb0\x91\xa5" // U+F0465 +#define ICON_MDI_ROTATE_LEFT_VARIANT "\xf3\xb0\x91\xa6" // U+F0466 +#define ICON_MDI_ROTATE_ORBIT "\xf3\xb0\xb6\x98" // U+F0D98 +#define ICON_MDI_ROTATE_RIGHT "\xf3\xb0\x91\xa7" // U+F0467 +#define ICON_MDI_ROTATE_RIGHT_VARIANT "\xf3\xb0\x91\xa8" // U+F0468 +#define ICON_MDI_ROUNDED_CORNER "\xf3\xb0\x98\x87" // U+F0607 +#define ICON_MDI_ROUTER "\xf3\xb1\x87\xa2" // U+F11E2 +#define ICON_MDI_ROUTER_NETWORK "\xf3\xb1\x82\x87" // U+F1087 +#define ICON_MDI_ROUTER_NETWORK_WIRELESS "\xf3\xb1\xb2\x97" // U+F1C97 +#define ICON_MDI_ROUTER_WIRELESS "\xf3\xb0\x91\xa9" // U+F0469 +#define ICON_MDI_ROUTER_WIRELESS_OFF "\xf3\xb1\x96\xa3" // U+F15A3 +#define ICON_MDI_ROUTER_WIRELESS_SETTINGS "\xf3\xb0\xa9\xa9" // U+F0A69 +#define ICON_MDI_ROUTES "\xf3\xb0\x91\xaa" // U+F046A +#define ICON_MDI_ROUTES_CLOCK "\xf3\xb1\x81\x99" // U+F1059 +#define ICON_MDI_ROWING "\xf3\xb0\x98\x88" // U+F0608 +#define ICON_MDI_RSS "\xf3\xb0\x91\xab" // U+F046B +#define ICON_MDI_RSS_BOX "\xf3\xb0\x91\xac" // U+F046C +#define ICON_MDI_RSS_OFF "\xf3\xb0\xbc\xa1" // U+F0F21 +#define ICON_MDI_RUG "\xf3\xb1\x91\xb5" // U+F1475 +#define ICON_MDI_RUGBY "\xf3\xb0\xb6\x99" // U+F0D99 +#define ICON_MDI_RULER "\xf3\xb0\x91\xad" // U+F046D +#define ICON_MDI_RULER_SQUARE "\xf3\xb0\xb3\x82" // U+F0CC2 +#define ICON_MDI_RULER_SQUARE_COMPASS "\xf3\xb0\xba\xbe" // U+F0EBE +#define ICON_MDI_RUN "\xf3\xb0\x9c\x8e" // U+F070E +#define ICON_MDI_RUN_FAST "\xf3\xb0\x91\xae" // U+F046E +#define ICON_MDI_RV_TRUCK "\xf3\xb1\x87\x94" // U+F11D4 +#define ICON_MDI_SACK "\xf3\xb0\xb4\xae" // U+F0D2E +#define ICON_MDI_SACK_OUTLINE "\xf3\xb1\xb1\x8c" // U+F1C4C +#define ICON_MDI_SACK_PERCENT "\xf3\xb0\xb4\xaf" // U+F0D2F +#define ICON_MDI_SAFE "\xf3\xb0\xa9\xaa" // U+F0A6A +#define ICON_MDI_SAFE_SQUARE "\xf3\xb1\x89\xbc" // U+F127C +#define ICON_MDI_SAFE_SQUARE_OUTLINE "\xf3\xb1\x89\xbd" // U+F127D +#define ICON_MDI_SAFETY_GOGGLES "\xf3\xb0\xb4\xb0" // U+F0D30 +#define ICON_MDI_SAIL_BOAT "\xf3\xb0\xbb\x88" // U+F0EC8 +#define ICON_MDI_SAIL_BOAT_SINK "\xf3\xb1\xab\xaf" // U+F1AEF +#define ICON_MDI_SALE "\xf3\xb0\x91\xaf" // U+F046F +#define ICON_MDI_SALE_OUTLINE "\xf3\xb1\xa8\x86" // U+F1A06 +#define ICON_MDI_SALESFORCE "\xf3\xb0\xa2\x8e" // U+F088E +#define ICON_MDI_SASS "\xf3\xb0\x9f\xac" // U+F07EC +#define ICON_MDI_SATELLITE "\xf3\xb0\x91\xb0" // U+F0470 +#define ICON_MDI_SATELLITE_UPLINK "\xf3\xb0\xa4\x89" // U+F0909 +#define ICON_MDI_SATELLITE_VARIANT "\xf3\xb0\x91\xb1" // U+F0471 +#define ICON_MDI_SAUSAGE "\xf3\xb0\xa2\xba" // U+F08BA +#define ICON_MDI_SAUSAGE_OFF "\xf3\xb1\x9e\x89" // U+F1789 +#define ICON_MDI_SAW_BLADE "\xf3\xb0\xb9\xa1" // U+F0E61 +#define ICON_MDI_SAWTOOTH_WAVE "\xf3\xb1\x91\xba" // U+F147A +#define ICON_MDI_SAXOPHONE "\xf3\xb0\x98\x89" // U+F0609 +#define ICON_MDI_SCALE "\xf3\xb0\x91\xb2" // U+F0472 +#define ICON_MDI_SCALE_BALANCE "\xf3\xb0\x97\x91" // U+F05D1 +#define ICON_MDI_SCALE_BATHROOM "\xf3\xb0\x91\xb3" // U+F0473 +#define ICON_MDI_SCALE_OFF "\xf3\xb1\x81\x9a" // U+F105A +#define ICON_MDI_SCALE_UNBALANCED "\xf3\xb1\xa6\xb8" // U+F19B8 +#define ICON_MDI_SCAN_HELPER "\xf3\xb1\x8f\x98" // U+F13D8 +#define ICON_MDI_SCANNER "\xf3\xb0\x9a\xab" // U+F06AB +#define ICON_MDI_SCANNER_OFF "\xf3\xb0\xa4\x8a" // U+F090A +#define ICON_MDI_SCATTER_PLOT "\xf3\xb0\xbb\x89" // U+F0EC9 +#define ICON_MDI_SCATTER_PLOT_OUTLINE "\xf3\xb0\xbb\x8a" // U+F0ECA +#define ICON_MDI_SCENT "\xf3\xb1\xa5\x98" // U+F1958 +#define ICON_MDI_SCENT_OFF "\xf3\xb1\xa5\x99" // U+F1959 +#define ICON_MDI_SCHOOL "\xf3\xb0\x91\xb4" // U+F0474 +#define ICON_MDI_SCHOOL_OUTLINE "\xf3\xb1\x86\x80" // U+F1180 +#define ICON_MDI_SCISSORS_CUTTING "\xf3\xb0\xa9\xab" // U+F0A6B +#define ICON_MDI_SCOOTER "\xf3\xb1\x96\xbd" // U+F15BD +#define ICON_MDI_SCOOTER_ELECTRIC "\xf3\xb1\x96\xbe" // U+F15BE +#define ICON_MDI_SCOREBOARD "\xf3\xb1\x89\xbe" // U+F127E +#define ICON_MDI_SCOREBOARD_OUTLINE "\xf3\xb1\x89\xbf" // U+F127F +#define ICON_MDI_SCREEN_ROTATION "\xf3\xb0\x91\xb5" // U+F0475 +#define ICON_MDI_SCREEN_ROTATION_LOCK "\xf3\xb0\x91\xb8" // U+F0478 +#define ICON_MDI_SCREW_FLAT_TOP "\xf3\xb0\xb7\xb3" // U+F0DF3 +#define ICON_MDI_SCREW_LAG "\xf3\xb0\xb7\xb4" // U+F0DF4 +#define ICON_MDI_SCREW_MACHINE_FLAT_TOP "\xf3\xb0\xb7\xb5" // U+F0DF5 +#define ICON_MDI_SCREW_MACHINE_ROUND_TOP "\xf3\xb0\xb7\xb6" // U+F0DF6 +#define ICON_MDI_SCREW_ROUND_TOP "\xf3\xb0\xb7\xb7" // U+F0DF7 +#define ICON_MDI_SCREWDRIVER "\xf3\xb0\x91\xb6" // U+F0476 +#define ICON_MDI_SCRIPT "\xf3\xb0\xaf\x81" // U+F0BC1 +#define ICON_MDI_SCRIPT_OUTLINE "\xf3\xb0\x91\xb7" // U+F0477 +#define ICON_MDI_SCRIPT_TEXT "\xf3\xb0\xaf\x82" // U+F0BC2 +#define ICON_MDI_SCRIPT_TEXT_KEY "\xf3\xb1\x9c\xa5" // U+F1725 +#define ICON_MDI_SCRIPT_TEXT_KEY_OUTLINE "\xf3\xb1\x9c\xa6" // U+F1726 +#define ICON_MDI_SCRIPT_TEXT_OUTLINE "\xf3\xb0\xaf\x83" // U+F0BC3 +#define ICON_MDI_SCRIPT_TEXT_PLAY "\xf3\xb1\x9c\xa7" // U+F1727 +#define ICON_MDI_SCRIPT_TEXT_PLAY_OUTLINE "\xf3\xb1\x9c\xa8" // U+F1728 +#define ICON_MDI_SD "\xf3\xb0\x91\xb9" // U+F0479 +#define ICON_MDI_SEAL "\xf3\xb0\x91\xba" // U+F047A +#define ICON_MDI_SEAL_VARIANT "\xf3\xb0\xbf\x99" // U+F0FD9 +#define ICON_MDI_SEARCH_WEB "\xf3\xb0\x9c\x8f" // U+F070F +#define ICON_MDI_SEAT "\xf3\xb0\xb3\x83" // U+F0CC3 +#define ICON_MDI_SEAT_FLAT "\xf3\xb0\x91\xbb" // U+F047B +#define ICON_MDI_SEAT_FLAT_ANGLED "\xf3\xb0\x91\xbc" // U+F047C +#define ICON_MDI_SEAT_INDIVIDUAL_SUITE "\xf3\xb0\x91\xbd" // U+F047D +#define ICON_MDI_SEAT_LEGROOM_EXTRA "\xf3\xb0\x91\xbe" // U+F047E +#define ICON_MDI_SEAT_LEGROOM_NORMAL "\xf3\xb0\x91\xbf" // U+F047F +#define ICON_MDI_SEAT_LEGROOM_REDUCED "\xf3\xb0\x92\x80" // U+F0480 +#define ICON_MDI_SEAT_OUTLINE "\xf3\xb0\xb3\x84" // U+F0CC4 +#define ICON_MDI_SEAT_PASSENGER "\xf3\xb1\x89\x89" // U+F1249 +#define ICON_MDI_SEAT_RECLINE_EXTRA "\xf3\xb0\x92\x81" // U+F0481 +#define ICON_MDI_SEAT_RECLINE_NORMAL "\xf3\xb0\x92\x82" // U+F0482 +#define ICON_MDI_SEATBELT "\xf3\xb0\xb3\x85" // U+F0CC5 +#define ICON_MDI_SECURITY "\xf3\xb0\x92\x83" // U+F0483 +#define ICON_MDI_SECURITY_NETWORK "\xf3\xb0\x92\x84" // U+F0484 +#define ICON_MDI_SEED "\xf3\xb0\xb9\xa2" // U+F0E62 +#define ICON_MDI_SEED_OFF "\xf3\xb1\x8f\xbd" // U+F13FD +#define ICON_MDI_SEED_OFF_OUTLINE "\xf3\xb1\x8f\xbe" // U+F13FE +#define ICON_MDI_SEED_OUTLINE "\xf3\xb0\xb9\xa3" // U+F0E63 +#define ICON_MDI_SEED_PLUS "\xf3\xb1\xa9\xad" // U+F1A6D +#define ICON_MDI_SEED_PLUS_OUTLINE "\xf3\xb1\xa9\xae" // U+F1A6E +#define ICON_MDI_SEESAW "\xf3\xb1\x96\xa4" // U+F15A4 +#define ICON_MDI_SEGMENT "\xf3\xb0\xbb\x8b" // U+F0ECB +#define ICON_MDI_SELECT "\xf3\xb0\x92\x85" // U+F0485 +#define ICON_MDI_SELECT_ALL "\xf3\xb0\x92\x86" // U+F0486 +#define ICON_MDI_SELECT_ARROW_DOWN "\xf3\xb1\xad\x99" // U+F1B59 +#define ICON_MDI_SELECT_ARROW_UP "\xf3\xb1\xad\x98" // U+F1B58 +#define ICON_MDI_SELECT_COLOR "\xf3\xb0\xb4\xb1" // U+F0D31 +#define ICON_MDI_SELECT_COMPARE "\xf3\xb0\xab\x99" // U+F0AD9 +#define ICON_MDI_SELECT_DRAG "\xf3\xb0\xa9\xac" // U+F0A6C +#define ICON_MDI_SELECT_GROUP "\xf3\xb0\xbe\x82" // U+F0F82 +#define ICON_MDI_SELECT_INVERSE "\xf3\xb0\x92\x87" // U+F0487 +#define ICON_MDI_SELECT_MARKER "\xf3\xb1\x8a\x80" // U+F1280 +#define ICON_MDI_SELECT_MULTIPLE "\xf3\xb1\x8a\x81" // U+F1281 +#define ICON_MDI_SELECT_MULTIPLE_MARKER "\xf3\xb1\x8a\x82" // U+F1282 +#define ICON_MDI_SELECT_OFF "\xf3\xb0\x92\x88" // U+F0488 +#define ICON_MDI_SELECT_PLACE "\xf3\xb0\xbf\x9a" // U+F0FDA +#define ICON_MDI_SELECT_REMOVE "\xf3\xb1\x9f\x81" // U+F17C1 +#define ICON_MDI_SELECT_SEARCH "\xf3\xb1\x88\x84" // U+F1204 +#define ICON_MDI_SELECTION "\xf3\xb0\x92\x89" // U+F0489 +#define ICON_MDI_SELECTION_DRAG "\xf3\xb0\xa9\xad" // U+F0A6D +#define ICON_MDI_SELECTION_ELLIPSE "\xf3\xb0\xb4\xb2" // U+F0D32 +#define ICON_MDI_SELECTION_ELLIPSE_ARROW_INSIDE "\xf3\xb0\xbc\xa2" // U+F0F22 +#define ICON_MDI_SELECTION_ELLIPSE_REMOVE "\xf3\xb1\x9f\x82" // U+F17C2 +#define ICON_MDI_SELECTION_MARKER "\xf3\xb1\x8a\x83" // U+F1283 +#define ICON_MDI_SELECTION_MULTIPLE "\xf3\xb1\x8a\x85" // U+F1285 +#define ICON_MDI_SELECTION_MULTIPLE_MARKER "\xf3\xb1\x8a\x84" // U+F1284 +#define ICON_MDI_SELECTION_OFF "\xf3\xb0\x9d\xb7" // U+F0777 +#define ICON_MDI_SELECTION_REMOVE "\xf3\xb1\x9f\x83" // U+F17C3 +#define ICON_MDI_SELECTION_SEARCH "\xf3\xb1\x88\x85" // U+F1205 +#define ICON_MDI_SEMANTIC_WEB "\xf3\xb1\x8c\x96" // U+F1316 +#define ICON_MDI_SEND "\xf3\xb0\x92\x8a" // U+F048A +#define ICON_MDI_SEND_CHECK "\xf3\xb1\x85\xa1" // U+F1161 +#define ICON_MDI_SEND_CHECK_OUTLINE "\xf3\xb1\x85\xa2" // U+F1162 +#define ICON_MDI_SEND_CIRCLE "\xf3\xb0\xb7\xb8" // U+F0DF8 +#define ICON_MDI_SEND_CIRCLE_OUTLINE "\xf3\xb0\xb7\xb9" // U+F0DF9 +#define ICON_MDI_SEND_CLOCK "\xf3\xb1\x85\xa3" // U+F1163 +#define ICON_MDI_SEND_CLOCK_OUTLINE "\xf3\xb1\x85\xa4" // U+F1164 +#define ICON_MDI_SEND_LOCK "\xf3\xb0\x9f\xad" // U+F07ED +#define ICON_MDI_SEND_LOCK_OUTLINE "\xf3\xb1\x85\xa6" // U+F1166 +#define ICON_MDI_SEND_OUTLINE "\xf3\xb1\x85\xa5" // U+F1165 +#define ICON_MDI_SEND_VARIANT "\xf3\xb1\xb1\x8d" // U+F1C4D +#define ICON_MDI_SEND_VARIANT_CLOCK "\xf3\xb1\xb1\xbe" // U+F1C7E +#define ICON_MDI_SEND_VARIANT_CLOCK_OUTLINE "\xf3\xb1\xb1\xbf" // U+F1C7F +#define ICON_MDI_SEND_VARIANT_OUTLINE "\xf3\xb1\xb1\x8e" // U+F1C4E +#define ICON_MDI_SERIAL_PORT "\xf3\xb0\x99\x9c" // U+F065C +#define ICON_MDI_SERVER "\xf3\xb0\x92\x8b" // U+F048B +#define ICON_MDI_SERVER_MINUS "\xf3\xb0\x92\x8c" // U+F048C +#define ICON_MDI_SERVER_MINUS_OUTLINE "\xf3\xb1\xb2\x98" // U+F1C98 +#define ICON_MDI_SERVER_NETWORK "\xf3\xb0\x92\x8d" // U+F048D +#define ICON_MDI_SERVER_NETWORK_OFF "\xf3\xb0\x92\x8e" // U+F048E +#define ICON_MDI_SERVER_NETWORK_OUTLINE "\xf3\xb1\xb2\x99" // U+F1C99 +#define ICON_MDI_SERVER_OFF "\xf3\xb0\x92\x8f" // U+F048F +#define ICON_MDI_SERVER_OUTLINE "\xf3\xb1\xb2\x9a" // U+F1C9A +#define ICON_MDI_SERVER_PLUS "\xf3\xb0\x92\x90" // U+F0490 +#define ICON_MDI_SERVER_PLUS_OUTLINE "\xf3\xb1\xb2\x9b" // U+F1C9B +#define ICON_MDI_SERVER_REMOVE "\xf3\xb0\x92\x91" // U+F0491 +#define ICON_MDI_SERVER_SECURITY "\xf3\xb0\x92\x92" // U+F0492 +#define ICON_MDI_SET_ALL "\xf3\xb0\x9d\xb8" // U+F0778 +#define ICON_MDI_SET_CENTER "\xf3\xb0\x9d\xb9" // U+F0779 +#define ICON_MDI_SET_CENTER_RIGHT "\xf3\xb0\x9d\xba" // U+F077A +#define ICON_MDI_SET_LEFT "\xf3\xb0\x9d\xbb" // U+F077B +#define ICON_MDI_SET_LEFT_CENTER "\xf3\xb0\x9d\xbc" // U+F077C +#define ICON_MDI_SET_LEFT_RIGHT "\xf3\xb0\x9d\xbd" // U+F077D +#define ICON_MDI_SET_MERGE "\xf3\xb1\x93\xa0" // U+F14E0 +#define ICON_MDI_SET_NONE "\xf3\xb0\x9d\xbe" // U+F077E +#define ICON_MDI_SET_RIGHT "\xf3\xb0\x9d\xbf" // U+F077F +#define ICON_MDI_SET_SPLIT "\xf3\xb1\x93\xa1" // U+F14E1 +#define ICON_MDI_SET_SQUARE "\xf3\xb1\x91\x9d" // U+F145D +#define ICON_MDI_SET_TOP_BOX "\xf3\xb0\xa6\x9f" // U+F099F +#define ICON_MDI_SETTINGS_HELPER "\xf3\xb0\xa9\xae" // U+F0A6E +#define ICON_MDI_SHAKER "\xf3\xb1\x84\x8e" // U+F110E +#define ICON_MDI_SHAKER_OUTLINE "\xf3\xb1\x84\x8f" // U+F110F +#define ICON_MDI_SHAPE "\xf3\xb0\xa0\xb1" // U+F0831 +#define ICON_MDI_SHAPE_CIRCLE_PLUS "\xf3\xb0\x99\x9d" // U+F065D +#define ICON_MDI_SHAPE_OUTLINE "\xf3\xb0\xa0\xb2" // U+F0832 +#define ICON_MDI_SHAPE_OVAL_PLUS "\xf3\xb1\x87\xba" // U+F11FA +#define ICON_MDI_SHAPE_PLUS "\xf3\xb0\x92\x95" // U+F0495 +#define ICON_MDI_SHAPE_PLUS_OUTLINE "\xf3\xb1\xb1\x8f" // U+F1C4F +#define ICON_MDI_SHAPE_POLYGON_PLUS "\xf3\xb0\x99\x9e" // U+F065E +#define ICON_MDI_SHAPE_RECTANGLE_PLUS "\xf3\xb0\x99\x9f" // U+F065F +#define ICON_MDI_SHAPE_SQUARE_PLUS "\xf3\xb0\x99\xa0" // U+F0660 +#define ICON_MDI_SHAPE_SQUARE_ROUNDED_PLUS "\xf3\xb1\x93\xba" // U+F14FA +#define ICON_MDI_SHARE "\xf3\xb0\x92\x96" // U+F0496 +#define ICON_MDI_SHARE_ALL "\xf3\xb1\x87\xb4" // U+F11F4 +#define ICON_MDI_SHARE_ALL_OUTLINE "\xf3\xb1\x87\xb5" // U+F11F5 +#define ICON_MDI_SHARE_CIRCLE "\xf3\xb1\x86\xad" // U+F11AD +#define ICON_MDI_SHARE_OFF "\xf3\xb0\xbc\xa3" // U+F0F23 +#define ICON_MDI_SHARE_OFF_OUTLINE "\xf3\xb0\xbc\xa4" // U+F0F24 +#define ICON_MDI_SHARE_OUTLINE "\xf3\xb0\xa4\xb2" // U+F0932 +#define ICON_MDI_SHARE_VARIANT "\xf3\xb0\x92\x97" // U+F0497 +#define ICON_MDI_SHARE_VARIANT_OUTLINE "\xf3\xb1\x94\x94" // U+F1514 +#define ICON_MDI_SHARK "\xf3\xb1\xa2\xba" // U+F18BA +#define ICON_MDI_SHARK_FIN "\xf3\xb1\x99\xb3" // U+F1673 +#define ICON_MDI_SHARK_FIN_OUTLINE "\xf3\xb1\x99\xb4" // U+F1674 +#define ICON_MDI_SHARK_OFF "\xf3\xb1\xa2\xbb" // U+F18BB +#define ICON_MDI_SHEEP "\xf3\xb0\xb3\x86" // U+F0CC6 +#define ICON_MDI_SHIELD "\xf3\xb0\x92\x98" // U+F0498 +#define ICON_MDI_SHIELD_ACCOUNT "\xf3\xb0\xa2\x8f" // U+F088F +#define ICON_MDI_SHIELD_ACCOUNT_OUTLINE "\xf3\xb0\xa8\x92" // U+F0A12 +#define ICON_MDI_SHIELD_ACCOUNT_VARIANT "\xf3\xb1\x96\xa7" // U+F15A7 +#define ICON_MDI_SHIELD_ACCOUNT_VARIANT_OUTLINE "\xf3\xb1\x96\xa8" // U+F15A8 +#define ICON_MDI_SHIELD_AIRPLANE "\xf3\xb0\x9a\xbb" // U+F06BB +#define ICON_MDI_SHIELD_AIRPLANE_OUTLINE "\xf3\xb0\xb3\x87" // U+F0CC7 +#define ICON_MDI_SHIELD_ALERT "\xf3\xb0\xbb\x8c" // U+F0ECC +#define ICON_MDI_SHIELD_ALERT_OUTLINE "\xf3\xb0\xbb\x8d" // U+F0ECD +#define ICON_MDI_SHIELD_BUG "\xf3\xb1\x8f\x9a" // U+F13DA +#define ICON_MDI_SHIELD_BUG_OUTLINE "\xf3\xb1\x8f\x9b" // U+F13DB +#define ICON_MDI_SHIELD_CAR "\xf3\xb0\xbe\x83" // U+F0F83 +#define ICON_MDI_SHIELD_CHECK "\xf3\xb0\x95\xa5" // U+F0565 +#define ICON_MDI_SHIELD_CHECK_OUTLINE "\xf3\xb0\xb3\x88" // U+F0CC8 +#define ICON_MDI_SHIELD_CROSS "\xf3\xb0\xb3\x89" // U+F0CC9 +#define ICON_MDI_SHIELD_CROSS_OUTLINE "\xf3\xb0\xb3\x8a" // U+F0CCA +#define ICON_MDI_SHIELD_CROWN "\xf3\xb1\xa2\xbc" // U+F18BC +#define ICON_MDI_SHIELD_CROWN_OUTLINE "\xf3\xb1\xa2\xbd" // U+F18BD +#define ICON_MDI_SHIELD_EDIT "\xf3\xb1\x86\xa0" // U+F11A0 +#define ICON_MDI_SHIELD_EDIT_OUTLINE "\xf3\xb1\x86\xa1" // U+F11A1 +#define ICON_MDI_SHIELD_HALF "\xf3\xb1\x8d\xa0" // U+F1360 +#define ICON_MDI_SHIELD_HALF_FULL "\xf3\xb0\x9e\x80" // U+F0780 +#define ICON_MDI_SHIELD_HOME "\xf3\xb0\x9a\x8a" // U+F068A +#define ICON_MDI_SHIELD_HOME_OUTLINE "\xf3\xb0\xb3\x8b" // U+F0CCB +#define ICON_MDI_SHIELD_KEY "\xf3\xb0\xaf\x84" // U+F0BC4 +#define ICON_MDI_SHIELD_KEY_OUTLINE "\xf3\xb0\xaf\x85" // U+F0BC5 +#define ICON_MDI_SHIELD_LINK_VARIANT "\xf3\xb0\xb4\xb3" // U+F0D33 +#define ICON_MDI_SHIELD_LINK_VARIANT_OUTLINE "\xf3\xb0\xb4\xb4" // U+F0D34 +#define ICON_MDI_SHIELD_LOCK "\xf3\xb0\xa6\x9d" // U+F099D +#define ICON_MDI_SHIELD_LOCK_OPEN "\xf3\xb1\xa6\x9a" // U+F199A +#define ICON_MDI_SHIELD_LOCK_OPEN_OUTLINE "\xf3\xb1\xa6\x9b" // U+F199B +#define ICON_MDI_SHIELD_LOCK_OUTLINE "\xf3\xb0\xb3\x8c" // U+F0CCC +#define ICON_MDI_SHIELD_MOON "\xf3\xb1\xa0\xa8" // U+F1828 +#define ICON_MDI_SHIELD_MOON_OUTLINE "\xf3\xb1\xa0\xa9" // U+F1829 +#define ICON_MDI_SHIELD_OFF "\xf3\xb0\xa6\x9e" // U+F099E +#define ICON_MDI_SHIELD_OFF_OUTLINE "\xf3\xb0\xa6\x9c" // U+F099C +#define ICON_MDI_SHIELD_OUTLINE "\xf3\xb0\x92\x99" // U+F0499 +#define ICON_MDI_SHIELD_PLUS "\xf3\xb0\xab\x9a" // U+F0ADA +#define ICON_MDI_SHIELD_PLUS_OUTLINE "\xf3\xb0\xab\x9b" // U+F0ADB +#define ICON_MDI_SHIELD_REFRESH "\xf3\xb0\x82\xaa" // U+F00AA +#define ICON_MDI_SHIELD_REFRESH_OUTLINE "\xf3\xb0\x87\xa0" // U+F01E0 +#define ICON_MDI_SHIELD_REMOVE "\xf3\xb0\xab\x9c" // U+F0ADC +#define ICON_MDI_SHIELD_REMOVE_OUTLINE "\xf3\xb0\xab\x9d" // U+F0ADD +#define ICON_MDI_SHIELD_SEARCH "\xf3\xb0\xb6\x9a" // U+F0D9A +#define ICON_MDI_SHIELD_STAR "\xf3\xb1\x84\xbb" // U+F113B +#define ICON_MDI_SHIELD_STAR_OUTLINE "\xf3\xb1\x84\xbc" // U+F113C +#define ICON_MDI_SHIELD_SUN "\xf3\xb1\x81\x9d" // U+F105D +#define ICON_MDI_SHIELD_SUN_OUTLINE "\xf3\xb1\x81\x9e" // U+F105E +#define ICON_MDI_SHIELD_SWORD "\xf3\xb1\xa2\xbe" // U+F18BE +#define ICON_MDI_SHIELD_SWORD_OUTLINE "\xf3\xb1\xa2\xbf" // U+F18BF +#define ICON_MDI_SHIELD_SYNC "\xf3\xb1\x86\xa2" // U+F11A2 +#define ICON_MDI_SHIELD_SYNC_OUTLINE "\xf3\xb1\x86\xa3" // U+F11A3 +#define ICON_MDI_SHIMMER "\xf3\xb1\x95\x85" // U+F1545 +#define ICON_MDI_SHIP_WHEEL "\xf3\xb0\xa0\xb3" // U+F0833 +#define ICON_MDI_SHIPPING_PALLET "\xf3\xb1\xa1\x8e" // U+F184E +#define ICON_MDI_SHOE_BALLET "\xf3\xb1\x97\x8a" // U+F15CA +#define ICON_MDI_SHOE_CLEAT "\xf3\xb1\x97\x87" // U+F15C7 +#define ICON_MDI_SHOE_FORMAL "\xf3\xb0\xad\x87" // U+F0B47 +#define ICON_MDI_SHOE_HEEL "\xf3\xb0\xad\x88" // U+F0B48 +#define ICON_MDI_SHOE_PRINT "\xf3\xb0\xb7\xba" // U+F0DFA +#define ICON_MDI_SHOE_SNEAKER "\xf3\xb1\x97\x88" // U+F15C8 +#define ICON_MDI_SHOPPING "\xf3\xb0\x92\x9a" // U+F049A +#define ICON_MDI_SHOPPING_MUSIC "\xf3\xb0\x92\x9b" // U+F049B +#define ICON_MDI_SHOPPING_OUTLINE "\xf3\xb1\x87\x95" // U+F11D5 +#define ICON_MDI_SHOPPING_SEARCH "\xf3\xb0\xbe\x84" // U+F0F84 +#define ICON_MDI_SHOPPING_SEARCH_OUTLINE "\xf3\xb1\xa9\xaf" // U+F1A6F +#define ICON_MDI_SHORE "\xf3\xb1\x93\xb9" // U+F14F9 +#define ICON_MDI_SHOVEL "\xf3\xb0\x9c\x90" // U+F0710 +#define ICON_MDI_SHOVEL_OFF "\xf3\xb0\x9c\x91" // U+F0711 +#define ICON_MDI_SHOWER "\xf3\xb0\xa6\xa0" // U+F09A0 +#define ICON_MDI_SHOWER_HEAD "\xf3\xb0\xa6\xa1" // U+F09A1 +#define ICON_MDI_SHREDDER "\xf3\xb0\x92\x9c" // U+F049C +#define ICON_MDI_SHUFFLE "\xf3\xb0\x92\x9d" // U+F049D +#define ICON_MDI_SHUFFLE_DISABLED "\xf3\xb0\x92\x9e" // U+F049E +#define ICON_MDI_SHUFFLE_VARIANT "\xf3\xb0\x92\x9f" // U+F049F +#define ICON_MDI_SHURIKEN "\xf3\xb1\x8d\xbf" // U+F137F +#define ICON_MDI_SICKLE "\xf3\xb1\xa3\x80" // U+F18C0 +#define ICON_MDI_SIGMA "\xf3\xb0\x92\xa0" // U+F04A0 +#define ICON_MDI_SIGMA_LOWER "\xf3\xb0\x98\xab" // U+F062B +#define ICON_MDI_SIGN_CAUTION "\xf3\xb0\x92\xa1" // U+F04A1 +#define ICON_MDI_SIGN_DIRECTION "\xf3\xb0\x9e\x81" // U+F0781 +#define ICON_MDI_SIGN_DIRECTION_MINUS "\xf3\xb1\x80\x80" // U+F1000 +#define ICON_MDI_SIGN_DIRECTION_PLUS "\xf3\xb0\xbf\x9c" // U+F0FDC +#define ICON_MDI_SIGN_DIRECTION_REMOVE "\xf3\xb0\xbf\x9d" // U+F0FDD +#define ICON_MDI_SIGN_LANGUAGE "\xf3\xb1\xad\x8d" // U+F1B4D +#define ICON_MDI_SIGN_LANGUAGE_OUTLINE "\xf3\xb1\xad\x8e" // U+F1B4E +#define ICON_MDI_SIGN_POLE "\xf3\xb1\x93\xb8" // U+F14F8 +#define ICON_MDI_SIGN_REAL_ESTATE "\xf3\xb1\x84\x98" // U+F1118 +#define ICON_MDI_SIGN_TEXT "\xf3\xb0\x9e\x82" // U+F0782 +#define ICON_MDI_SIGN_YIELD "\xf3\xb1\xae\xaf" // U+F1BAF +#define ICON_MDI_SIGNAL "\xf3\xb0\x92\xa2" // U+F04A2 +#define ICON_MDI_SIGNAL_2G "\xf3\xb0\x9c\x92" // U+F0712 +#define ICON_MDI_SIGNAL_3G "\xf3\xb0\x9c\x93" // U+F0713 +#define ICON_MDI_SIGNAL_4G "\xf3\xb0\x9c\x94" // U+F0714 +#define ICON_MDI_SIGNAL_5G "\xf3\xb0\xa9\xaf" // U+F0A6F +#define ICON_MDI_SIGNAL_CELLULAR_1 "\xf3\xb0\xa2\xbc" // U+F08BC +#define ICON_MDI_SIGNAL_CELLULAR_2 "\xf3\xb0\xa2\xbd" // U+F08BD +#define ICON_MDI_SIGNAL_CELLULAR_3 "\xf3\xb0\xa2\xbe" // U+F08BE +#define ICON_MDI_SIGNAL_CELLULAR_OUTLINE "\xf3\xb0\xa2\xbf" // U+F08BF +#define ICON_MDI_SIGNAL_DISTANCE_VARIANT "\xf3\xb0\xb9\xa4" // U+F0E64 +#define ICON_MDI_SIGNAL_HSPA "\xf3\xb0\x9c\x95" // U+F0715 +#define ICON_MDI_SIGNAL_HSPA_PLUS "\xf3\xb0\x9c\x96" // U+F0716 +#define ICON_MDI_SIGNAL_OFF "\xf3\xb0\x9e\x83" // U+F0783 +#define ICON_MDI_SIGNAL_VARIANT "\xf3\xb0\x98\x8a" // U+F060A +#define ICON_MDI_SIGNATURE "\xf3\xb0\xb7\xbb" // U+F0DFB +#define ICON_MDI_SIGNATURE_FREEHAND "\xf3\xb0\xb7\xbc" // U+F0DFC +#define ICON_MDI_SIGNATURE_IMAGE "\xf3\xb0\xb7\xbd" // U+F0DFD +#define ICON_MDI_SIGNATURE_TEXT "\xf3\xb0\xb7\xbe" // U+F0DFE +#define ICON_MDI_SILO "\xf3\xb1\xae\x9f" // U+F1B9F +#define ICON_MDI_SILO_OUTLINE "\xf3\xb0\xad\x89" // U+F0B49 +#define ICON_MDI_SILVERWARE "\xf3\xb0\x92\xa3" // U+F04A3 +#define ICON_MDI_SILVERWARE_CLEAN "\xf3\xb0\xbf\x9e" // U+F0FDE +#define ICON_MDI_SILVERWARE_FORK "\xf3\xb0\x92\xa4" // U+F04A4 +#define ICON_MDI_SILVERWARE_FORK_KNIFE "\xf3\xb0\xa9\xb0" // U+F0A70 +#define ICON_MDI_SILVERWARE_SPOON "\xf3\xb0\x92\xa5" // U+F04A5 +#define ICON_MDI_SILVERWARE_VARIANT "\xf3\xb0\x92\xa6" // U+F04A6 +#define ICON_MDI_SIM "\xf3\xb0\x92\xa7" // U+F04A7 +#define ICON_MDI_SIM_ALERT "\xf3\xb0\x92\xa8" // U+F04A8 +#define ICON_MDI_SIM_ALERT_OUTLINE "\xf3\xb1\x97\x93" // U+F15D3 +#define ICON_MDI_SIM_OFF "\xf3\xb0\x92\xa9" // U+F04A9 +#define ICON_MDI_SIM_OFF_OUTLINE "\xf3\xb1\x97\x94" // U+F15D4 +#define ICON_MDI_SIM_OUTLINE "\xf3\xb1\x97\x95" // U+F15D5 +#define ICON_MDI_SIMPLE_ICONS "\xf3\xb1\x8c\x9d" // U+F131D +#define ICON_MDI_SINA_WEIBO "\xf3\xb0\xab\x9f" // U+F0ADF +#define ICON_MDI_SINE_WAVE "\xf3\xb0\xa5\x9b" // U+F095B +#define ICON_MDI_SITEMAP "\xf3\xb0\x92\xaa" // U+F04AA +#define ICON_MDI_SITEMAP_OUTLINE "\xf3\xb1\xa6\x9c" // U+F199C +#define ICON_MDI_SIZE_L "\xf3\xb1\x8e\xa6" // U+F13A6 +#define ICON_MDI_SIZE_M "\xf3\xb1\x8e\xa5" // U+F13A5 +#define ICON_MDI_SIZE_S "\xf3\xb1\x8e\xa4" // U+F13A4 +#define ICON_MDI_SIZE_XL "\xf3\xb1\x8e\xa7" // U+F13A7 +#define ICON_MDI_SIZE_XS "\xf3\xb1\x8e\xa3" // U+F13A3 +#define ICON_MDI_SIZE_XXL "\xf3\xb1\x8e\xa8" // U+F13A8 +#define ICON_MDI_SIZE_XXS "\xf3\xb1\x8e\xa2" // U+F13A2 +#define ICON_MDI_SIZE_XXXL "\xf3\xb1\x8e\xa9" // U+F13A9 +#define ICON_MDI_SKATE "\xf3\xb0\xb4\xb5" // U+F0D35 +#define ICON_MDI_SKATE_OFF "\xf3\xb0\x9a\x99" // U+F0699 +#define ICON_MDI_SKATEBOARD "\xf3\xb1\x93\x82" // U+F14C2 +#define ICON_MDI_SKATEBOARDING "\xf3\xb0\x94\x81" // U+F0501 +#define ICON_MDI_SKEW_LESS "\xf3\xb0\xb4\xb6" // U+F0D36 +#define ICON_MDI_SKEW_MORE "\xf3\xb0\xb4\xb7" // U+F0D37 +#define ICON_MDI_SKI "\xf3\xb1\x8c\x84" // U+F1304 +#define ICON_MDI_SKI_CROSS_COUNTRY "\xf3\xb1\x8c\x85" // U+F1305 +#define ICON_MDI_SKI_WATER "\xf3\xb1\x8c\x86" // U+F1306 +#define ICON_MDI_SKIP_BACKWARD "\xf3\xb0\x92\xab" // U+F04AB +#define ICON_MDI_SKIP_BACKWARD_OUTLINE "\xf3\xb0\xbc\xa5" // U+F0F25 +#define ICON_MDI_SKIP_FORWARD "\xf3\xb0\x92\xac" // U+F04AC +#define ICON_MDI_SKIP_FORWARD_OUTLINE "\xf3\xb0\xbc\xa6" // U+F0F26 +#define ICON_MDI_SKIP_NEXT "\xf3\xb0\x92\xad" // U+F04AD +#define ICON_MDI_SKIP_NEXT_CIRCLE "\xf3\xb0\x99\xa1" // U+F0661 +#define ICON_MDI_SKIP_NEXT_CIRCLE_OUTLINE "\xf3\xb0\x99\xa2" // U+F0662 +#define ICON_MDI_SKIP_NEXT_OUTLINE "\xf3\xb0\xbc\xa7" // U+F0F27 +#define ICON_MDI_SKIP_PREVIOUS "\xf3\xb0\x92\xae" // U+F04AE +#define ICON_MDI_SKIP_PREVIOUS_CIRCLE "\xf3\xb0\x99\xa3" // U+F0663 +#define ICON_MDI_SKIP_PREVIOUS_CIRCLE_OUTLINE "\xf3\xb0\x99\xa4" // U+F0664 +#define ICON_MDI_SKIP_PREVIOUS_OUTLINE "\xf3\xb0\xbc\xa8" // U+F0F28 +#define ICON_MDI_SKULL "\xf3\xb0\x9a\x8c" // U+F068C +#define ICON_MDI_SKULL_CROSSBONES "\xf3\xb0\xaf\x86" // U+F0BC6 +#define ICON_MDI_SKULL_CROSSBONES_OUTLINE "\xf3\xb0\xaf\x87" // U+F0BC7 +#define ICON_MDI_SKULL_OUTLINE "\xf3\xb0\xaf\x88" // U+F0BC8 +#define ICON_MDI_SKULL_SCAN "\xf3\xb1\x93\x87" // U+F14C7 +#define ICON_MDI_SKULL_SCAN_OUTLINE "\xf3\xb1\x93\x88" // U+F14C8 +#define ICON_MDI_SKYPE "\xf3\xb0\x92\xaf" // U+F04AF +#define ICON_MDI_SKYPE_BUSINESS "\xf3\xb0\x92\xb0" // U+F04B0 +#define ICON_MDI_SLACK "\xf3\xb0\x92\xb1" // U+F04B1 +#define ICON_MDI_SLASH_FORWARD "\xf3\xb0\xbf\x9f" // U+F0FDF +#define ICON_MDI_SLASH_FORWARD_BOX "\xf3\xb0\xbf\xa0" // U+F0FE0 +#define ICON_MDI_SLEDDING "\xf3\xb0\x90\x9b" // U+F041B +#define ICON_MDI_SLEEP "\xf3\xb0\x92\xb2" // U+F04B2 +#define ICON_MDI_SLEEP_OFF "\xf3\xb0\x92\xb3" // U+F04B3 +#define ICON_MDI_SLIDE "\xf3\xb1\x96\xa5" // U+F15A5 +#define ICON_MDI_SLOPE_DOWNHILL "\xf3\xb0\xb7\xbf" // U+F0DFF +#define ICON_MDI_SLOPE_UPHILL "\xf3\xb0\xb8\x80" // U+F0E00 +#define ICON_MDI_SLOT_MACHINE "\xf3\xb1\x84\x94" // U+F1114 +#define ICON_MDI_SLOT_MACHINE_OUTLINE "\xf3\xb1\x84\x95" // U+F1115 +#define ICON_MDI_SMART_CARD "\xf3\xb1\x82\xbd" // U+F10BD +#define ICON_MDI_SMART_CARD_OFF "\xf3\xb1\xa3\xb7" // U+F18F7 +#define ICON_MDI_SMART_CARD_OFF_OUTLINE "\xf3\xb1\xa3\xb8" // U+F18F8 +#define ICON_MDI_SMART_CARD_OUTLINE "\xf3\xb1\x82\xbe" // U+F10BE +#define ICON_MDI_SMART_CARD_READER "\xf3\xb1\x82\xbf" // U+F10BF +#define ICON_MDI_SMART_CARD_READER_OUTLINE "\xf3\xb1\x83\x80" // U+F10C0 +#define ICON_MDI_SMOG "\xf3\xb0\xa9\xb1" // U+F0A71 +#define ICON_MDI_SMOKE "\xf3\xb1\x9e\x99" // U+F1799 +#define ICON_MDI_SMOKE_DETECTOR "\xf3\xb0\x8e\x92" // U+F0392 +#define ICON_MDI_SMOKE_DETECTOR_ALERT "\xf3\xb1\xa4\xae" // U+F192E +#define ICON_MDI_SMOKE_DETECTOR_ALERT_OUTLINE "\xf3\xb1\xa4\xaf" // U+F192F +#define ICON_MDI_SMOKE_DETECTOR_OFF "\xf3\xb1\xa0\x89" // U+F1809 +#define ICON_MDI_SMOKE_DETECTOR_OFF_OUTLINE "\xf3\xb1\xa0\x8a" // U+F180A +#define ICON_MDI_SMOKE_DETECTOR_OUTLINE "\xf3\xb1\xa0\x88" // U+F1808 +#define ICON_MDI_SMOKE_DETECTOR_VARIANT "\xf3\xb1\xa0\x8b" // U+F180B +#define ICON_MDI_SMOKE_DETECTOR_VARIANT_ALERT "\xf3\xb1\xa4\xb0" // U+F1930 +#define ICON_MDI_SMOKE_DETECTOR_VARIANT_OFF "\xf3\xb1\xa0\x8c" // U+F180C +#define ICON_MDI_SMOKING "\xf3\xb0\x92\xb4" // U+F04B4 +#define ICON_MDI_SMOKING_OFF "\xf3\xb0\x92\xb5" // U+F04B5 +#define ICON_MDI_SMOKING_PIPE "\xf3\xb1\x90\x8d" // U+F140D +#define ICON_MDI_SMOKING_PIPE_OFF "\xf3\xb1\x90\xa8" // U+F1428 +#define ICON_MDI_SNAIL "\xf3\xb1\x99\xb7" // U+F1677 +#define ICON_MDI_SNAKE "\xf3\xb1\x94\x8e" // U+F150E +#define ICON_MDI_SNAPCHAT "\xf3\xb0\x92\xb6" // U+F04B6 +#define ICON_MDI_SNOWBOARD "\xf3\xb1\x8c\x87" // U+F1307 +#define ICON_MDI_SNOWFLAKE "\xf3\xb0\x9c\x97" // U+F0717 +#define ICON_MDI_SNOWFLAKE_ALERT "\xf3\xb0\xbc\xa9" // U+F0F29 +#define ICON_MDI_SNOWFLAKE_CHECK "\xf3\xb1\xa9\xb0" // U+F1A70 +#define ICON_MDI_SNOWFLAKE_MELT "\xf3\xb1\x8b\x8b" // U+F12CB +#define ICON_MDI_SNOWFLAKE_OFF "\xf3\xb1\x93\xa3" // U+F14E3 +#define ICON_MDI_SNOWFLAKE_THERMOMETER "\xf3\xb1\xa9\xb1" // U+F1A71 +#define ICON_MDI_SNOWFLAKE_VARIANT "\xf3\xb0\xbc\xaa" // U+F0F2A +#define ICON_MDI_SNOWMAN "\xf3\xb0\x92\xb7" // U+F04B7 +#define ICON_MDI_SNOWMOBILE "\xf3\xb0\x9b\x9d" // U+F06DD +#define ICON_MDI_SNOWSHOEING "\xf3\xb1\xa9\xb2" // U+F1A72 +#define ICON_MDI_SOCCER "\xf3\xb0\x92\xb8" // U+F04B8 +#define ICON_MDI_SOCCER_FIELD "\xf3\xb0\xa0\xb4" // U+F0834 +#define ICON_MDI_SOCIAL_DISTANCE_2_METERS "\xf3\xb1\x95\xb9" // U+F1579 +#define ICON_MDI_SOCIAL_DISTANCE_6_FEET "\xf3\xb1\x95\xba" // U+F157A +#define ICON_MDI_SOFA "\xf3\xb0\x92\xb9" // U+F04B9 +#define ICON_MDI_SOFA_OUTLINE "\xf3\xb1\x95\xad" // U+F156D +#define ICON_MDI_SOFA_SINGLE "\xf3\xb1\x95\xae" // U+F156E +#define ICON_MDI_SOFA_SINGLE_OUTLINE "\xf3\xb1\x95\xaf" // U+F156F +#define ICON_MDI_SOLAR_PANEL "\xf3\xb0\xb6\x9b" // U+F0D9B +#define ICON_MDI_SOLAR_PANEL_LARGE "\xf3\xb0\xb6\x9c" // U+F0D9C +#define ICON_MDI_SOLAR_POWER "\xf3\xb0\xa9\xb2" // U+F0A72 +#define ICON_MDI_SOLAR_POWER_VARIANT "\xf3\xb1\xa9\xb3" // U+F1A73 +#define ICON_MDI_SOLAR_POWER_VARIANT_OUTLINE "\xf3\xb1\xa9\xb4" // U+F1A74 +#define ICON_MDI_SOLDERING_IRON "\xf3\xb1\x82\x92" // U+F1092 +#define ICON_MDI_SOLID "\xf3\xb0\x9a\x8d" // U+F068D +#define ICON_MDI_SONY_PLAYSTATION "\xf3\xb0\x90\x94" // U+F0414 +#define ICON_MDI_SORT "\xf3\xb0\x92\xba" // U+F04BA +#define ICON_MDI_SORT_ALPHABETICAL_ASCENDING "\xf3\xb0\x96\xbd" // U+F05BD +#define ICON_MDI_SORT_ALPHABETICAL_ASCENDING_VARIANT "\xf3\xb1\x85\x88" // U+F1148 +#define ICON_MDI_SORT_ALPHABETICAL_DESCENDING "\xf3\xb0\x96\xbf" // U+F05BF +#define ICON_MDI_SORT_ALPHABETICAL_DESCENDING_VARIANT "\xf3\xb1\x85\x89" // U+F1149 +#define ICON_MDI_SORT_ALPHABETICAL_VARIANT "\xf3\xb0\x92\xbb" // U+F04BB +#define ICON_MDI_SORT_ASCENDING "\xf3\xb0\x92\xbc" // U+F04BC +#define ICON_MDI_SORT_BOOL_ASCENDING "\xf3\xb1\x8e\x85" // U+F1385 +#define ICON_MDI_SORT_BOOL_ASCENDING_VARIANT "\xf3\xb1\x8e\x86" // U+F1386 +#define ICON_MDI_SORT_BOOL_DESCENDING "\xf3\xb1\x8e\x87" // U+F1387 +#define ICON_MDI_SORT_BOOL_DESCENDING_VARIANT "\xf3\xb1\x8e\x88" // U+F1388 +#define ICON_MDI_SORT_CALENDAR_ASCENDING "\xf3\xb1\x95\x87" // U+F1547 +#define ICON_MDI_SORT_CALENDAR_DESCENDING "\xf3\xb1\x95\x88" // U+F1548 +#define ICON_MDI_SORT_CLOCK_ASCENDING "\xf3\xb1\x95\x89" // U+F1549 +#define ICON_MDI_SORT_CLOCK_ASCENDING_OUTLINE "\xf3\xb1\x95\x8a" // U+F154A +#define ICON_MDI_SORT_CLOCK_DESCENDING "\xf3\xb1\x95\x8b" // U+F154B +#define ICON_MDI_SORT_CLOCK_DESCENDING_OUTLINE "\xf3\xb1\x95\x8c" // U+F154C +#define ICON_MDI_SORT_DESCENDING "\xf3\xb0\x92\xbd" // U+F04BD +#define ICON_MDI_SORT_NUMERIC_ASCENDING "\xf3\xb1\x8e\x89" // U+F1389 +#define ICON_MDI_SORT_NUMERIC_ASCENDING_VARIANT "\xf3\xb0\xa4\x8d" // U+F090D +#define ICON_MDI_SORT_NUMERIC_DESCENDING "\xf3\xb1\x8e\x8a" // U+F138A +#define ICON_MDI_SORT_NUMERIC_DESCENDING_VARIANT "\xf3\xb0\xab\x92" // U+F0AD2 +#define ICON_MDI_SORT_NUMERIC_VARIANT "\xf3\xb0\x92\xbe" // U+F04BE +#define ICON_MDI_SORT_REVERSE_VARIANT "\xf3\xb0\x8c\xbc" // U+F033C +#define ICON_MDI_SORT_VARIANT "\xf3\xb0\x92\xbf" // U+F04BF +#define ICON_MDI_SORT_VARIANT_LOCK "\xf3\xb0\xb3\x8d" // U+F0CCD +#define ICON_MDI_SORT_VARIANT_LOCK_OPEN "\xf3\xb0\xb3\x8e" // U+F0CCE +#define ICON_MDI_SORT_VARIANT_OFF "\xf3\xb1\xaa\xbb" // U+F1ABB +#define ICON_MDI_SORT_VARIANT_REMOVE "\xf3\xb1\x85\x87" // U+F1147 +#define ICON_MDI_SOUNDBAR "\xf3\xb1\x9f\x9b" // U+F17DB +#define ICON_MDI_SOUNDCLOUD "\xf3\xb0\x93\x80" // U+F04C0 +#define ICON_MDI_SOURCE_BRANCH "\xf3\xb0\x98\xac" // U+F062C +#define ICON_MDI_SOURCE_BRANCH_CHECK "\xf3\xb1\x93\x8f" // U+F14CF +#define ICON_MDI_SOURCE_BRANCH_MINUS "\xf3\xb1\x93\x8b" // U+F14CB +#define ICON_MDI_SOURCE_BRANCH_PLUS "\xf3\xb1\x93\x8a" // U+F14CA +#define ICON_MDI_SOURCE_BRANCH_REFRESH "\xf3\xb1\x93\x8d" // U+F14CD +#define ICON_MDI_SOURCE_BRANCH_REMOVE "\xf3\xb1\x93\x8c" // U+F14CC +#define ICON_MDI_SOURCE_BRANCH_SYNC "\xf3\xb1\x93\x8e" // U+F14CE +#define ICON_MDI_SOURCE_COMMIT "\xf3\xb0\x9c\x98" // U+F0718 +#define ICON_MDI_SOURCE_COMMIT_END "\xf3\xb0\x9c\x99" // U+F0719 +#define ICON_MDI_SOURCE_COMMIT_END_LOCAL "\xf3\xb0\x9c\x9a" // U+F071A +#define ICON_MDI_SOURCE_COMMIT_LOCAL "\xf3\xb0\x9c\x9b" // U+F071B +#define ICON_MDI_SOURCE_COMMIT_NEXT_LOCAL "\xf3\xb0\x9c\x9c" // U+F071C +#define ICON_MDI_SOURCE_COMMIT_START "\xf3\xb0\x9c\x9d" // U+F071D +#define ICON_MDI_SOURCE_COMMIT_START_NEXT_LOCAL "\xf3\xb0\x9c\x9e" // U+F071E +#define ICON_MDI_SOURCE_FORK "\xf3\xb0\x93\x81" // U+F04C1 +#define ICON_MDI_SOURCE_MERGE "\xf3\xb0\x98\xad" // U+F062D +#define ICON_MDI_SOURCE_PULL "\xf3\xb0\x93\x82" // U+F04C2 +#define ICON_MDI_SOURCE_REPOSITORY "\xf3\xb0\xb3\x8f" // U+F0CCF +#define ICON_MDI_SOURCE_REPOSITORY_MULTIPLE "\xf3\xb0\xb3\x90" // U+F0CD0 +#define ICON_MDI_SOY_SAUCE "\xf3\xb0\x9f\xae" // U+F07EE +#define ICON_MDI_SOY_SAUCE_OFF "\xf3\xb1\x8f\xbc" // U+F13FC +#define ICON_MDI_SPA "\xf3\xb0\xb3\x91" // U+F0CD1 +#define ICON_MDI_SPA_OUTLINE "\xf3\xb0\xb3\x92" // U+F0CD2 +#define ICON_MDI_SPACE_INVADERS "\xf3\xb0\xaf\x89" // U+F0BC9 +#define ICON_MDI_SPACE_STATION "\xf3\xb1\x8e\x83" // U+F1383 +#define ICON_MDI_SPADE "\xf3\xb0\xb9\xa5" // U+F0E65 +#define ICON_MDI_SPEAKER "\xf3\xb0\x93\x83" // U+F04C3 +#define ICON_MDI_SPEAKER_BLUETOOTH "\xf3\xb0\xa6\xa2" // U+F09A2 +#define ICON_MDI_SPEAKER_MESSAGE "\xf3\xb1\xac\x91" // U+F1B11 +#define ICON_MDI_SPEAKER_MULTIPLE "\xf3\xb0\xb4\xb8" // U+F0D38 +#define ICON_MDI_SPEAKER_OFF "\xf3\xb0\x93\x84" // U+F04C4 +#define ICON_MDI_SPEAKER_PAUSE "\xf3\xb1\xad\xb3" // U+F1B73 +#define ICON_MDI_SPEAKER_PLAY "\xf3\xb1\xad\xb2" // U+F1B72 +#define ICON_MDI_SPEAKER_STOP "\xf3\xb1\xad\xb4" // U+F1B74 +#define ICON_MDI_SPEAKER_WIRELESS "\xf3\xb0\x9c\x9f" // U+F071F +#define ICON_MDI_SPEAR "\xf3\xb1\xa1\x85" // U+F1845 +#define ICON_MDI_SPEEDOMETER "\xf3\xb0\x93\x85" // U+F04C5 +#define ICON_MDI_SPEEDOMETER_MEDIUM "\xf3\xb0\xbe\x85" // U+F0F85 +#define ICON_MDI_SPEEDOMETER_SLOW "\xf3\xb0\xbe\x86" // U+F0F86 +#define ICON_MDI_SPELLCHECK "\xf3\xb0\x93\x86" // U+F04C6 +#define ICON_MDI_SPHERE "\xf3\xb1\xa5\x94" // U+F1954 +#define ICON_MDI_SPHERE_OFF "\xf3\xb1\xa5\x95" // U+F1955 +#define ICON_MDI_SPIDER "\xf3\xb1\x87\xaa" // U+F11EA +#define ICON_MDI_SPIDER_OUTLINE "\xf3\xb1\xb1\xb5" // U+F1C75 +#define ICON_MDI_SPIDER_THREAD "\xf3\xb1\x87\xab" // U+F11EB +#define ICON_MDI_SPIDER_WEB "\xf3\xb0\xaf\x8a" // U+F0BCA +#define ICON_MDI_SPIRIT_LEVEL "\xf3\xb1\x93\xb1" // U+F14F1 +#define ICON_MDI_SPOON_SUGAR "\xf3\xb1\x90\xa9" // U+F1429 +#define ICON_MDI_SPOTIFY "\xf3\xb0\x93\x87" // U+F04C7 +#define ICON_MDI_SPOTLIGHT "\xf3\xb0\x93\x88" // U+F04C8 +#define ICON_MDI_SPOTLIGHT_BEAM "\xf3\xb0\x93\x89" // U+F04C9 +#define ICON_MDI_SPRAY "\xf3\xb0\x99\xa5" // U+F0665 +#define ICON_MDI_SPRAY_BOTTLE "\xf3\xb0\xab\xa0" // U+F0AE0 +#define ICON_MDI_SPRINKLER "\xf3\xb1\x81\x9f" // U+F105F +#define ICON_MDI_SPRINKLER_FIRE "\xf3\xb1\xa6\x9d" // U+F199D +#define ICON_MDI_SPRINKLER_VARIANT "\xf3\xb1\x81\xa0" // U+F1060 +#define ICON_MDI_SPROUT "\xf3\xb0\xb9\xa6" // U+F0E66 +#define ICON_MDI_SPROUT_OUTLINE "\xf3\xb0\xb9\xa7" // U+F0E67 +#define ICON_MDI_SQUARE "\xf3\xb0\x9d\xa4" // U+F0764 +#define ICON_MDI_SQUARE_CIRCLE "\xf3\xb1\x94\x80" // U+F1500 +#define ICON_MDI_SQUARE_CIRCLE_OUTLINE "\xf3\xb1\xb1\x90" // U+F1C50 +#define ICON_MDI_SQUARE_EDIT_OUTLINE "\xf3\xb0\xa4\x8c" // U+F090C +#define ICON_MDI_SQUARE_MEDIUM "\xf3\xb0\xa8\x93" // U+F0A13 +#define ICON_MDI_SQUARE_MEDIUM_OUTLINE "\xf3\xb0\xa8\x94" // U+F0A14 +#define ICON_MDI_SQUARE_OFF "\xf3\xb1\x8b\xae" // U+F12EE +#define ICON_MDI_SQUARE_OFF_OUTLINE "\xf3\xb1\x8b\xaf" // U+F12EF +#define ICON_MDI_SQUARE_OPACITY "\xf3\xb1\xa1\x94" // U+F1854 +#define ICON_MDI_SQUARE_OUTLINE "\xf3\xb0\x9d\xa3" // U+F0763 +#define ICON_MDI_SQUARE_ROOT "\xf3\xb0\x9e\x84" // U+F0784 +#define ICON_MDI_SQUARE_ROOT_BOX "\xf3\xb0\xa6\xa3" // U+F09A3 +#define ICON_MDI_SQUARE_ROUNDED "\xf3\xb1\x93\xbb" // U+F14FB +#define ICON_MDI_SQUARE_ROUNDED_BADGE "\xf3\xb1\xa8\x87" // U+F1A07 +#define ICON_MDI_SQUARE_ROUNDED_BADGE_OUTLINE "\xf3\xb1\xa8\x88" // U+F1A08 +#define ICON_MDI_SQUARE_ROUNDED_OUTLINE "\xf3\xb1\x93\xbc" // U+F14FC +#define ICON_MDI_SQUARE_SMALL "\xf3\xb0\xa8\x95" // U+F0A15 +#define ICON_MDI_SQUARE_WAVE "\xf3\xb1\x91\xbb" // U+F147B +#define ICON_MDI_SQUEEGEE "\xf3\xb0\xab\xa1" // U+F0AE1 +#define ICON_MDI_SSH "\xf3\xb0\xa3\x80" // U+F08C0 +#define ICON_MDI_STACK_EXCHANGE "\xf3\xb0\x98\x8b" // U+F060B +#define ICON_MDI_STACK_OVERFLOW "\xf3\xb0\x93\x8c" // U+F04CC +#define ICON_MDI_STACKPATH "\xf3\xb0\x8d\x99" // U+F0359 +#define ICON_MDI_STADIUM "\xf3\xb0\xbf\xb9" // U+F0FF9 +#define ICON_MDI_STADIUM_OUTLINE "\xf3\xb1\xac\x83" // U+F1B03 +#define ICON_MDI_STADIUM_VARIANT "\xf3\xb0\x9c\xa0" // U+F0720 +#define ICON_MDI_STAIRS "\xf3\xb0\x93\x8d" // U+F04CD +#define ICON_MDI_STAIRS_BOX "\xf3\xb1\x8e\x9e" // U+F139E +#define ICON_MDI_STAIRS_DOWN "\xf3\xb1\x8a\xbe" // U+F12BE +#define ICON_MDI_STAIRS_UP "\xf3\xb1\x8a\xbd" // U+F12BD +#define ICON_MDI_STAMPER "\xf3\xb0\xb4\xb9" // U+F0D39 +#define ICON_MDI_STANDARD_DEFINITION "\xf3\xb0\x9f\xaf" // U+F07EF +#define ICON_MDI_STAR "\xf3\xb0\x93\x8e" // U+F04CE +#define ICON_MDI_STAR_BOX "\xf3\xb0\xa9\xb3" // U+F0A73 +#define ICON_MDI_STAR_BOX_MULTIPLE "\xf3\xb1\x8a\x86" // U+F1286 +#define ICON_MDI_STAR_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x8a\x87" // U+F1287 +#define ICON_MDI_STAR_BOX_OUTLINE "\xf3\xb0\xa9\xb4" // U+F0A74 +#define ICON_MDI_STAR_CHECK "\xf3\xb1\x95\xa6" // U+F1566 +#define ICON_MDI_STAR_CHECK_OUTLINE "\xf3\xb1\x95\xaa" // U+F156A +#define ICON_MDI_STAR_CIRCLE "\xf3\xb0\x93\x8f" // U+F04CF +#define ICON_MDI_STAR_CIRCLE_OUTLINE "\xf3\xb0\xa6\xa4" // U+F09A4 +#define ICON_MDI_STAR_COG "\xf3\xb1\x99\xa8" // U+F1668 +#define ICON_MDI_STAR_COG_OUTLINE "\xf3\xb1\x99\xa9" // U+F1669 +#define ICON_MDI_STAR_CRESCENT "\xf3\xb0\xa5\xb9" // U+F0979 +#define ICON_MDI_STAR_DAVID "\xf3\xb0\xa5\xba" // U+F097A +#define ICON_MDI_STAR_FACE "\xf3\xb0\xa6\xa5" // U+F09A5 +#define ICON_MDI_STAR_FOUR_POINTS "\xf3\xb0\xab\xa2" // U+F0AE2 +#define ICON_MDI_STAR_FOUR_POINTS_BOX "\xf3\xb1\xb1\x91" // U+F1C51 +#define ICON_MDI_STAR_FOUR_POINTS_BOX_OUTLINE "\xf3\xb1\xb1\x92" // U+F1C52 +#define ICON_MDI_STAR_FOUR_POINTS_CIRCLE "\xf3\xb1\xb1\x93" // U+F1C53 +#define ICON_MDI_STAR_FOUR_POINTS_CIRCLE_OUTLINE "\xf3\xb1\xb1\x94" // U+F1C54 +#define ICON_MDI_STAR_FOUR_POINTS_OUTLINE "\xf3\xb0\xab\xa3" // U+F0AE3 +#define ICON_MDI_STAR_FOUR_POINTS_SMALL "\xf3\xb1\xb1\x95" // U+F1C55 +#define ICON_MDI_STAR_HALF "\xf3\xb0\x89\x86" // U+F0246 +#define ICON_MDI_STAR_HALF_FULL "\xf3\xb0\x93\x90" // U+F04D0 +#define ICON_MDI_STAR_MINUS "\xf3\xb1\x95\xa4" // U+F1564 +#define ICON_MDI_STAR_MINUS_OUTLINE "\xf3\xb1\x95\xa8" // U+F1568 +#define ICON_MDI_STAR_OFF "\xf3\xb0\x93\x91" // U+F04D1 +#define ICON_MDI_STAR_OFF_OUTLINE "\xf3\xb1\x95\x9b" // U+F155B +#define ICON_MDI_STAR_OUTLINE "\xf3\xb0\x93\x92" // U+F04D2 +#define ICON_MDI_STAR_PLUS "\xf3\xb1\x95\xa3" // U+F1563 +#define ICON_MDI_STAR_PLUS_OUTLINE "\xf3\xb1\x95\xa7" // U+F1567 +#define ICON_MDI_STAR_REMOVE "\xf3\xb1\x95\xa5" // U+F1565 +#define ICON_MDI_STAR_REMOVE_OUTLINE "\xf3\xb1\x95\xa9" // U+F1569 +#define ICON_MDI_STAR_SETTINGS "\xf3\xb1\x99\xaa" // U+F166A +#define ICON_MDI_STAR_SETTINGS_OUTLINE "\xf3\xb1\x99\xab" // U+F166B +#define ICON_MDI_STAR_SHOOTING "\xf3\xb1\x9d\x81" // U+F1741 +#define ICON_MDI_STAR_SHOOTING_OUTLINE "\xf3\xb1\x9d\x82" // U+F1742 +#define ICON_MDI_STAR_THREE_POINTS "\xf3\xb0\xab\xa4" // U+F0AE4 +#define ICON_MDI_STAR_THREE_POINTS_OUTLINE "\xf3\xb0\xab\xa5" // U+F0AE5 +#define ICON_MDI_STATE_MACHINE "\xf3\xb1\x87\xaf" // U+F11EF +#define ICON_MDI_STEAM "\xf3\xb0\x93\x93" // U+F04D3 +#define ICON_MDI_STEERING "\xf3\xb0\x93\x94" // U+F04D4 +#define ICON_MDI_STEERING_OFF "\xf3\xb0\xa4\x8e" // U+F090E +#define ICON_MDI_STEP_BACKWARD "\xf3\xb0\x93\x95" // U+F04D5 +#define ICON_MDI_STEP_BACKWARD_2 "\xf3\xb0\x93\x96" // U+F04D6 +#define ICON_MDI_STEP_FORWARD "\xf3\xb0\x93\x97" // U+F04D7 +#define ICON_MDI_STEP_FORWARD_2 "\xf3\xb0\x93\x98" // U+F04D8 +#define ICON_MDI_STETHOSCOPE "\xf3\xb0\x93\x99" // U+F04D9 +#define ICON_MDI_STICKER "\xf3\xb1\x8d\xa4" // U+F1364 +#define ICON_MDI_STICKER_ALERT "\xf3\xb1\x8d\xa5" // U+F1365 +#define ICON_MDI_STICKER_ALERT_OUTLINE "\xf3\xb1\x8d\xa6" // U+F1366 +#define ICON_MDI_STICKER_CHECK "\xf3\xb1\x8d\xa7" // U+F1367 +#define ICON_MDI_STICKER_CHECK_OUTLINE "\xf3\xb1\x8d\xa8" // U+F1368 +#define ICON_MDI_STICKER_CIRCLE_OUTLINE "\xf3\xb0\x97\x90" // U+F05D0 +#define ICON_MDI_STICKER_EMOJI "\xf3\xb0\x9e\x85" // U+F0785 +#define ICON_MDI_STICKER_MINUS "\xf3\xb1\x8d\xa9" // U+F1369 +#define ICON_MDI_STICKER_MINUS_OUTLINE "\xf3\xb1\x8d\xaa" // U+F136A +#define ICON_MDI_STICKER_OUTLINE "\xf3\xb1\x8d\xab" // U+F136B +#define ICON_MDI_STICKER_PLUS "\xf3\xb1\x8d\xac" // U+F136C +#define ICON_MDI_STICKER_PLUS_OUTLINE "\xf3\xb1\x8d\xad" // U+F136D +#define ICON_MDI_STICKER_REMOVE "\xf3\xb1\x8d\xae" // U+F136E +#define ICON_MDI_STICKER_REMOVE_OUTLINE "\xf3\xb1\x8d\xaf" // U+F136F +#define ICON_MDI_STICKER_TEXT "\xf3\xb1\x9e\x8e" // U+F178E +#define ICON_MDI_STICKER_TEXT_OUTLINE "\xf3\xb1\x9e\x8f" // U+F178F +#define ICON_MDI_STOCKING "\xf3\xb0\x93\x9a" // U+F04DA +#define ICON_MDI_STOMACH "\xf3\xb1\x82\x93" // U+F1093 +#define ICON_MDI_STOOL "\xf3\xb1\xa5\x9d" // U+F195D +#define ICON_MDI_STOOL_OUTLINE "\xf3\xb1\xa5\x9e" // U+F195E +#define ICON_MDI_STOP "\xf3\xb0\x93\x9b" // U+F04DB +#define ICON_MDI_STOP_CIRCLE "\xf3\xb0\x99\xa6" // U+F0666 +#define ICON_MDI_STOP_CIRCLE_OUTLINE "\xf3\xb0\x99\xa7" // U+F0667 +#define ICON_MDI_STORAGE_TANK "\xf3\xb1\xa9\xb5" // U+F1A75 +#define ICON_MDI_STORAGE_TANK_OUTLINE "\xf3\xb1\xa9\xb6" // U+F1A76 +#define ICON_MDI_STORE "\xf3\xb0\x93\x9c" // U+F04DC +#define ICON_MDI_STORE_24_HOUR "\xf3\xb0\x93\x9d" // U+F04DD +#define ICON_MDI_STORE_ALERT "\xf3\xb1\xa3\x81" // U+F18C1 +#define ICON_MDI_STORE_ALERT_OUTLINE "\xf3\xb1\xa3\x82" // U+F18C2 +#define ICON_MDI_STORE_CHECK "\xf3\xb1\xa3\x83" // U+F18C3 +#define ICON_MDI_STORE_CHECK_OUTLINE "\xf3\xb1\xa3\x84" // U+F18C4 +#define ICON_MDI_STORE_CLOCK "\xf3\xb1\xa3\x85" // U+F18C5 +#define ICON_MDI_STORE_CLOCK_OUTLINE "\xf3\xb1\xa3\x86" // U+F18C6 +#define ICON_MDI_STORE_COG "\xf3\xb1\xa3\x87" // U+F18C7 +#define ICON_MDI_STORE_COG_OUTLINE "\xf3\xb1\xa3\x88" // U+F18C8 +#define ICON_MDI_STORE_EDIT "\xf3\xb1\xa3\x89" // U+F18C9 +#define ICON_MDI_STORE_EDIT_OUTLINE "\xf3\xb1\xa3\x8a" // U+F18CA +#define ICON_MDI_STORE_MARKER "\xf3\xb1\xa3\x8b" // U+F18CB +#define ICON_MDI_STORE_MARKER_OUTLINE "\xf3\xb1\xa3\x8c" // U+F18CC +#define ICON_MDI_STORE_MINUS "\xf3\xb1\x99\x9e" // U+F165E +#define ICON_MDI_STORE_MINUS_OUTLINE "\xf3\xb1\xa3\x8d" // U+F18CD +#define ICON_MDI_STORE_OFF "\xf3\xb1\xa3\x8e" // U+F18CE +#define ICON_MDI_STORE_OFF_OUTLINE "\xf3\xb1\xa3\x8f" // U+F18CF +#define ICON_MDI_STORE_OUTLINE "\xf3\xb1\x8d\xa1" // U+F1361 +#define ICON_MDI_STORE_PLUS "\xf3\xb1\x99\x9f" // U+F165F +#define ICON_MDI_STORE_PLUS_OUTLINE "\xf3\xb1\xa3\x90" // U+F18D0 +#define ICON_MDI_STORE_REMOVE "\xf3\xb1\x99\xa0" // U+F1660 +#define ICON_MDI_STORE_REMOVE_OUTLINE "\xf3\xb1\xa3\x91" // U+F18D1 +#define ICON_MDI_STORE_SEARCH "\xf3\xb1\xa3\x92" // U+F18D2 +#define ICON_MDI_STORE_SEARCH_OUTLINE "\xf3\xb1\xa3\x93" // U+F18D3 +#define ICON_MDI_STORE_SETTINGS "\xf3\xb1\xa3\x94" // U+F18D4 +#define ICON_MDI_STORE_SETTINGS_OUTLINE "\xf3\xb1\xa3\x95" // U+F18D5 +#define ICON_MDI_STOREFRONT "\xf3\xb0\x9f\x87" // U+F07C7 +#define ICON_MDI_STOREFRONT_CHECK "\xf3\xb1\xad\xbd" // U+F1B7D +#define ICON_MDI_STOREFRONT_CHECK_OUTLINE "\xf3\xb1\xad\xbe" // U+F1B7E +#define ICON_MDI_STOREFRONT_EDIT "\xf3\xb1\xad\xbf" // U+F1B7F +#define ICON_MDI_STOREFRONT_EDIT_OUTLINE "\xf3\xb1\xae\x80" // U+F1B80 +#define ICON_MDI_STOREFRONT_MINUS "\xf3\xb1\xae\x83" // U+F1B83 +#define ICON_MDI_STOREFRONT_MINUS_OUTLINE "\xf3\xb1\xae\x84" // U+F1B84 +#define ICON_MDI_STOREFRONT_OUTLINE "\xf3\xb1\x83\x81" // U+F10C1 +#define ICON_MDI_STOREFRONT_PLUS "\xf3\xb1\xae\x81" // U+F1B81 +#define ICON_MDI_STOREFRONT_PLUS_OUTLINE "\xf3\xb1\xae\x82" // U+F1B82 +#define ICON_MDI_STOREFRONT_REMOVE "\xf3\xb1\xae\x85" // U+F1B85 +#define ICON_MDI_STOREFRONT_REMOVE_OUTLINE "\xf3\xb1\xae\x86" // U+F1B86 +#define ICON_MDI_STOVE "\xf3\xb0\x93\x9e" // U+F04DE +#define ICON_MDI_STRATEGY "\xf3\xb1\x87\x96" // U+F11D6 +#define ICON_MDI_STRETCH_TO_PAGE "\xf3\xb0\xbc\xab" // U+F0F2B +#define ICON_MDI_STRETCH_TO_PAGE_OUTLINE "\xf3\xb0\xbc\xac" // U+F0F2C +#define ICON_MDI_STRING_LIGHTS "\xf3\xb1\x8a\xba" // U+F12BA +#define ICON_MDI_STRING_LIGHTS_OFF "\xf3\xb1\x8a\xbb" // U+F12BB +#define ICON_MDI_SUBDIRECTORY_ARROW_LEFT "\xf3\xb0\x98\x8c" // U+F060C +#define ICON_MDI_SUBDIRECTORY_ARROW_RIGHT "\xf3\xb0\x98\x8d" // U+F060D +#define ICON_MDI_SUBMARINE "\xf3\xb1\x95\xac" // U+F156C +#define ICON_MDI_SUBTITLES "\xf3\xb0\xa8\x96" // U+F0A16 +#define ICON_MDI_SUBTITLES_OUTLINE "\xf3\xb0\xa8\x97" // U+F0A17 +#define ICON_MDI_SUBWAY "\xf3\xb0\x9a\xac" // U+F06AC +#define ICON_MDI_SUBWAY_ALERT_VARIANT "\xf3\xb0\xb6\x9d" // U+F0D9D +#define ICON_MDI_SUBWAY_VARIANT "\xf3\xb0\x93\x9f" // U+F04DF +#define ICON_MDI_SUMMIT "\xf3\xb0\x9e\x86" // U+F0786 +#define ICON_MDI_SUN_ANGLE "\xf3\xb1\xac\xa7" // U+F1B27 +#define ICON_MDI_SUN_ANGLE_OUTLINE "\xf3\xb1\xac\xa8" // U+F1B28 +#define ICON_MDI_SUN_CLOCK "\xf3\xb1\xa9\xb7" // U+F1A77 +#define ICON_MDI_SUN_CLOCK_OUTLINE "\xf3\xb1\xa9\xb8" // U+F1A78 +#define ICON_MDI_SUN_COMPASS "\xf3\xb1\xa6\xa5" // U+F19A5 +#define ICON_MDI_SUN_SNOWFLAKE "\xf3\xb1\x9e\x96" // U+F1796 +#define ICON_MDI_SUN_SNOWFLAKE_VARIANT "\xf3\xb1\xa9\xb9" // U+F1A79 +#define ICON_MDI_SUN_THERMOMETER "\xf3\xb1\xa3\x96" // U+F18D6 +#define ICON_MDI_SUN_THERMOMETER_OUTLINE "\xf3\xb1\xa3\x97" // U+F18D7 +#define ICON_MDI_SUN_WIRELESS "\xf3\xb1\x9f\xbe" // U+F17FE +#define ICON_MDI_SUN_WIRELESS_OUTLINE "\xf3\xb1\x9f\xbf" // U+F17FF +#define ICON_MDI_SUNGLASSES "\xf3\xb0\x93\xa0" // U+F04E0 +#define ICON_MDI_SURFING "\xf3\xb1\x9d\x86" // U+F1746 +#define ICON_MDI_SURROUND_SOUND "\xf3\xb0\x97\x85" // U+F05C5 +#define ICON_MDI_SURROUND_SOUND_2_0 "\xf3\xb0\x9f\xb0" // U+F07F0 +#define ICON_MDI_SURROUND_SOUND_2_1 "\xf3\xb1\x9c\xa9" // U+F1729 +#define ICON_MDI_SURROUND_SOUND_3_1 "\xf3\xb0\x9f\xb1" // U+F07F1 +#define ICON_MDI_SURROUND_SOUND_5_1 "\xf3\xb0\x9f\xb2" // U+F07F2 +#define ICON_MDI_SURROUND_SOUND_5_1_2 "\xf3\xb1\x9c\xaa" // U+F172A +#define ICON_MDI_SURROUND_SOUND_7_1 "\xf3\xb0\x9f\xb3" // U+F07F3 +#define ICON_MDI_SVG "\xf3\xb0\x9c\xa1" // U+F0721 +#define ICON_MDI_SWAP_HORIZONTAL "\xf3\xb0\x93\xa1" // U+F04E1 +#define ICON_MDI_SWAP_HORIZONTAL_BOLD "\xf3\xb0\xaf\x8d" // U+F0BCD +#define ICON_MDI_SWAP_HORIZONTAL_CIRCLE "\xf3\xb0\xbf\xa1" // U+F0FE1 +#define ICON_MDI_SWAP_HORIZONTAL_CIRCLE_OUTLINE "\xf3\xb0\xbf\xa2" // U+F0FE2 +#define ICON_MDI_SWAP_HORIZONTAL_VARIANT "\xf3\xb0\xa3\x81" // U+F08C1 +#define ICON_MDI_SWAP_VERTICAL "\xf3\xb0\x93\xa2" // U+F04E2 +#define ICON_MDI_SWAP_VERTICAL_BOLD "\xf3\xb0\xaf\x8e" // U+F0BCE +#define ICON_MDI_SWAP_VERTICAL_CIRCLE "\xf3\xb0\xbf\xa3" // U+F0FE3 +#define ICON_MDI_SWAP_VERTICAL_CIRCLE_OUTLINE "\xf3\xb0\xbf\xa4" // U+F0FE4 +#define ICON_MDI_SWAP_VERTICAL_VARIANT "\xf3\xb0\xa3\x82" // U+F08C2 +#define ICON_MDI_SWIM "\xf3\xb0\x93\xa3" // U+F04E3 +#define ICON_MDI_SWITCH "\xf3\xb0\x93\xa4" // U+F04E4 +#define ICON_MDI_SWORD "\xf3\xb0\x93\xa5" // U+F04E5 +#define ICON_MDI_SWORD_CROSS "\xf3\xb0\x9e\x87" // U+F0787 +#define ICON_MDI_SYLLABARY_HANGUL "\xf3\xb1\x8c\xb3" // U+F1333 +#define ICON_MDI_SYLLABARY_HIRAGANA "\xf3\xb1\x8c\xb4" // U+F1334 +#define ICON_MDI_SYLLABARY_KATAKANA "\xf3\xb1\x8c\xb5" // U+F1335 +#define ICON_MDI_SYLLABARY_KATAKANA_HALFWIDTH "\xf3\xb1\x8c\xb6" // U+F1336 +#define ICON_MDI_SYMBOL "\xf3\xb1\x94\x81" // U+F1501 +#define ICON_MDI_SYMFONY "\xf3\xb0\xab\xa6" // U+F0AE6 +#define ICON_MDI_SYNAGOGUE "\xf3\xb1\xac\x84" // U+F1B04 +#define ICON_MDI_SYNAGOGUE_OUTLINE "\xf3\xb1\xac\x85" // U+F1B05 +#define ICON_MDI_SYNC "\xf3\xb0\x93\xa6" // U+F04E6 +#define ICON_MDI_SYNC_ALERT "\xf3\xb0\x93\xa7" // U+F04E7 +#define ICON_MDI_SYNC_CIRCLE "\xf3\xb1\x8d\xb8" // U+F1378 +#define ICON_MDI_SYNC_OFF "\xf3\xb0\x93\xa8" // U+F04E8 +#define ICON_MDI_TAB "\xf3\xb0\x93\xa9" // U+F04E9 +#define ICON_MDI_TAB_MINUS "\xf3\xb0\xad\x8b" // U+F0B4B +#define ICON_MDI_TAB_PLUS "\xf3\xb0\x9d\x9c" // U+F075C +#define ICON_MDI_TAB_REMOVE "\xf3\xb0\xad\x8c" // U+F0B4C +#define ICON_MDI_TAB_SEARCH "\xf3\xb1\xa6\x9e" // U+F199E +#define ICON_MDI_TAB_UNSELECTED "\xf3\xb0\x93\xaa" // U+F04EA +#define ICON_MDI_TABLE "\xf3\xb0\x93\xab" // U+F04EB +#define ICON_MDI_TABLE_ACCOUNT "\xf3\xb1\x8e\xb9" // U+F13B9 +#define ICON_MDI_TABLE_ALERT "\xf3\xb1\x8e\xba" // U+F13BA +#define ICON_MDI_TABLE_ARROW_DOWN "\xf3\xb1\x8e\xbb" // U+F13BB +#define ICON_MDI_TABLE_ARROW_LEFT "\xf3\xb1\x8e\xbc" // U+F13BC +#define ICON_MDI_TABLE_ARROW_RIGHT "\xf3\xb1\x8e\xbd" // U+F13BD +#define ICON_MDI_TABLE_ARROW_UP "\xf3\xb1\x8e\xbe" // U+F13BE +#define ICON_MDI_TABLE_BORDER "\xf3\xb0\xa8\x98" // U+F0A18 +#define ICON_MDI_TABLE_CANCEL "\xf3\xb1\x8e\xbf" // U+F13BF +#define ICON_MDI_TABLE_CHAIR "\xf3\xb1\x81\xa1" // U+F1061 +#define ICON_MDI_TABLE_CHECK "\xf3\xb1\x8f\x80" // U+F13C0 +#define ICON_MDI_TABLE_CLOCK "\xf3\xb1\x8f\x81" // U+F13C1 +#define ICON_MDI_TABLE_COG "\xf3\xb1\x8f\x82" // U+F13C2 +#define ICON_MDI_TABLE_COLUMN "\xf3\xb0\xa0\xb5" // U+F0835 +#define ICON_MDI_TABLE_COLUMN_PLUS_AFTER "\xf3\xb0\x93\xac" // U+F04EC +#define ICON_MDI_TABLE_COLUMN_PLUS_BEFORE "\xf3\xb0\x93\xad" // U+F04ED +#define ICON_MDI_TABLE_COLUMN_REMOVE "\xf3\xb0\x93\xae" // U+F04EE +#define ICON_MDI_TABLE_COLUMN_WIDTH "\xf3\xb0\x93\xaf" // U+F04EF +#define ICON_MDI_TABLE_EDIT "\xf3\xb0\x93\xb0" // U+F04F0 +#define ICON_MDI_TABLE_EYE "\xf3\xb1\x82\x94" // U+F1094 +#define ICON_MDI_TABLE_EYE_OFF "\xf3\xb1\x8f\x83" // U+F13C3 +#define ICON_MDI_TABLE_FILTER "\xf3\xb1\xae\x8c" // U+F1B8C +#define ICON_MDI_TABLE_FURNITURE "\xf3\xb0\x96\xbc" // U+F05BC +#define ICON_MDI_TABLE_HEADERS_EYE "\xf3\xb1\x88\x9d" // U+F121D +#define ICON_MDI_TABLE_HEADERS_EYE_OFF "\xf3\xb1\x88\x9e" // U+F121E +#define ICON_MDI_TABLE_HEART "\xf3\xb1\x8f\x84" // U+F13C4 +#define ICON_MDI_TABLE_KEY "\xf3\xb1\x8f\x85" // U+F13C5 +#define ICON_MDI_TABLE_LARGE "\xf3\xb0\x93\xb1" // U+F04F1 +#define ICON_MDI_TABLE_LARGE_PLUS "\xf3\xb0\xbe\x87" // U+F0F87 +#define ICON_MDI_TABLE_LARGE_REMOVE "\xf3\xb0\xbe\x88" // U+F0F88 +#define ICON_MDI_TABLE_LOCK "\xf3\xb1\x8f\x86" // U+F13C6 +#define ICON_MDI_TABLE_MERGE_CELLS "\xf3\xb0\xa6\xa6" // U+F09A6 +#define ICON_MDI_TABLE_MINUS "\xf3\xb1\x8f\x87" // U+F13C7 +#define ICON_MDI_TABLE_MULTIPLE "\xf3\xb1\x8f\x88" // U+F13C8 +#define ICON_MDI_TABLE_NETWORK "\xf3\xb1\x8f\x89" // U+F13C9 +#define ICON_MDI_TABLE_OF_CONTENTS "\xf3\xb0\xa0\xb6" // U+F0836 +#define ICON_MDI_TABLE_OFF "\xf3\xb1\x8f\x8a" // U+F13CA +#define ICON_MDI_TABLE_PICNIC "\xf3\xb1\x9d\x83" // U+F1743 +#define ICON_MDI_TABLE_PIVOT "\xf3\xb1\xa0\xbc" // U+F183C +#define ICON_MDI_TABLE_PLUS "\xf3\xb0\xa9\xb5" // U+F0A75 +#define ICON_MDI_TABLE_QUESTION "\xf3\xb1\xac\xa1" // U+F1B21 +#define ICON_MDI_TABLE_REFRESH "\xf3\xb1\x8e\xa0" // U+F13A0 +#define ICON_MDI_TABLE_REMOVE "\xf3\xb0\xa9\xb6" // U+F0A76 +#define ICON_MDI_TABLE_ROW "\xf3\xb0\xa0\xb7" // U+F0837 +#define ICON_MDI_TABLE_ROW_HEIGHT "\xf3\xb0\x93\xb2" // U+F04F2 +#define ICON_MDI_TABLE_ROW_PLUS_AFTER "\xf3\xb0\x93\xb3" // U+F04F3 +#define ICON_MDI_TABLE_ROW_PLUS_BEFORE "\xf3\xb0\x93\xb4" // U+F04F4 +#define ICON_MDI_TABLE_ROW_REMOVE "\xf3\xb0\x93\xb5" // U+F04F5 +#define ICON_MDI_TABLE_SEARCH "\xf3\xb0\xa4\x8f" // U+F090F +#define ICON_MDI_TABLE_SETTINGS "\xf3\xb0\xa0\xb8" // U+F0838 +#define ICON_MDI_TABLE_SPLIT_CELL "\xf3\xb1\x90\xaa" // U+F142A +#define ICON_MDI_TABLE_STAR "\xf3\xb1\x8f\x8b" // U+F13CB +#define ICON_MDI_TABLE_SYNC "\xf3\xb1\x8e\xa1" // U+F13A1 +#define ICON_MDI_TABLE_TENNIS "\xf3\xb0\xb9\xa8" // U+F0E68 +#define ICON_MDI_TABLET "\xf3\xb0\x93\xb6" // U+F04F6 +#define ICON_MDI_TABLET_CELLPHONE "\xf3\xb0\xa6\xa7" // U+F09A7 +#define ICON_MDI_TABLET_DASHBOARD "\xf3\xb0\xbb\x8e" // U+F0ECE +#define ICON_MDI_TACO "\xf3\xb0\x9d\xa2" // U+F0762 +#define ICON_MDI_TAG "\xf3\xb0\x93\xb9" // U+F04F9 +#define ICON_MDI_TAG_ARROW_DOWN "\xf3\xb1\x9c\xab" // U+F172B +#define ICON_MDI_TAG_ARROW_DOWN_OUTLINE "\xf3\xb1\x9c\xac" // U+F172C +#define ICON_MDI_TAG_ARROW_LEFT "\xf3\xb1\x9c\xad" // U+F172D +#define ICON_MDI_TAG_ARROW_LEFT_OUTLINE "\xf3\xb1\x9c\xae" // U+F172E +#define ICON_MDI_TAG_ARROW_RIGHT "\xf3\xb1\x9c\xaf" // U+F172F +#define ICON_MDI_TAG_ARROW_RIGHT_OUTLINE "\xf3\xb1\x9c\xb0" // U+F1730 +#define ICON_MDI_TAG_ARROW_UP "\xf3\xb1\x9c\xb1" // U+F1731 +#define ICON_MDI_TAG_ARROW_UP_OUTLINE "\xf3\xb1\x9c\xb2" // U+F1732 +#define ICON_MDI_TAG_CHECK "\xf3\xb1\xa9\xba" // U+F1A7A +#define ICON_MDI_TAG_CHECK_OUTLINE "\xf3\xb1\xa9\xbb" // U+F1A7B +#define ICON_MDI_TAG_EDIT "\xf3\xb1\xb2\x9c" // U+F1C9C +#define ICON_MDI_TAG_EDIT_OUTLINE "\xf3\xb1\xb2\x9d" // U+F1C9D +#define ICON_MDI_TAG_FACES "\xf3\xb0\x93\xba" // U+F04FA +#define ICON_MDI_TAG_HEART "\xf3\xb0\x9a\x8b" // U+F068B +#define ICON_MDI_TAG_HEART_OUTLINE "\xf3\xb0\xaf\x8f" // U+F0BCF +#define ICON_MDI_TAG_HIDDEN "\xf3\xb1\xb1\xb6" // U+F1C76 +#define ICON_MDI_TAG_MINUS "\xf3\xb0\xa4\x90" // U+F0910 +#define ICON_MDI_TAG_MINUS_OUTLINE "\xf3\xb1\x88\x9f" // U+F121F +#define ICON_MDI_TAG_MULTIPLE "\xf3\xb0\x93\xbb" // U+F04FB +#define ICON_MDI_TAG_MULTIPLE_OUTLINE "\xf3\xb1\x8b\xb7" // U+F12F7 +#define ICON_MDI_TAG_OFF "\xf3\xb1\x88\xa0" // U+F1220 +#define ICON_MDI_TAG_OFF_OUTLINE "\xf3\xb1\x88\xa1" // U+F1221 +#define ICON_MDI_TAG_OUTLINE "\xf3\xb0\x93\xbc" // U+F04FC +#define ICON_MDI_TAG_PLUS "\xf3\xb0\x9c\xa2" // U+F0722 +#define ICON_MDI_TAG_PLUS_OUTLINE "\xf3\xb1\x88\xa2" // U+F1222 +#define ICON_MDI_TAG_REMOVE "\xf3\xb0\x9c\xa3" // U+F0723 +#define ICON_MDI_TAG_REMOVE_OUTLINE "\xf3\xb1\x88\xa3" // U+F1223 +#define ICON_MDI_TAG_SEARCH "\xf3\xb1\xa4\x87" // U+F1907 +#define ICON_MDI_TAG_SEARCH_OUTLINE "\xf3\xb1\xa4\x88" // U+F1908 +#define ICON_MDI_TAG_TEXT "\xf3\xb1\x88\xa4" // U+F1224 +#define ICON_MDI_TAG_TEXT_OUTLINE "\xf3\xb0\x93\xbd" // U+F04FD +#define ICON_MDI_TAILWIND "\xf3\xb1\x8f\xbf" // U+F13FF +#define ICON_MDI_TALLY_MARK_1 "\xf3\xb1\xaa\xbc" // U+F1ABC +#define ICON_MDI_TALLY_MARK_2 "\xf3\xb1\xaa\xbd" // U+F1ABD +#define ICON_MDI_TALLY_MARK_3 "\xf3\xb1\xaa\xbe" // U+F1ABE +#define ICON_MDI_TALLY_MARK_4 "\xf3\xb1\xaa\xbf" // U+F1ABF +#define ICON_MDI_TALLY_MARK_5 "\xf3\xb1\xab\x80" // U+F1AC0 +#define ICON_MDI_TANGRAM "\xf3\xb0\x93\xb8" // U+F04F8 +#define ICON_MDI_TANK "\xf3\xb0\xb4\xba" // U+F0D3A +#define ICON_MDI_TANKER_TRUCK "\xf3\xb0\xbf\xa5" // U+F0FE5 +#define ICON_MDI_TAPE_DRIVE "\xf3\xb1\x9b\x9f" // U+F16DF +#define ICON_MDI_TAPE_MEASURE "\xf3\xb0\xad\x8d" // U+F0B4D +#define ICON_MDI_TARGET "\xf3\xb0\x93\xbe" // U+F04FE +#define ICON_MDI_TARGET_ACCOUNT "\xf3\xb0\xaf\x90" // U+F0BD0 +#define ICON_MDI_TARGET_VARIANT "\xf3\xb0\xa9\xb7" // U+F0A77 +#define ICON_MDI_TAXI "\xf3\xb0\x93\xbf" // U+F04FF +#define ICON_MDI_TEA "\xf3\xb0\xb6\x9e" // U+F0D9E +#define ICON_MDI_TEA_OUTLINE "\xf3\xb0\xb6\x9f" // U+F0D9F +#define ICON_MDI_TEAMVIEWER "\xf3\xb0\x94\x80" // U+F0500 +#define ICON_MDI_TEDDY_BEAR "\xf3\xb1\xa3\xbb" // U+F18FB +#define ICON_MDI_TELESCOPE "\xf3\xb0\xad\x8e" // U+F0B4E +#define ICON_MDI_TELEVISION "\xf3\xb0\x94\x82" // U+F0502 +#define ICON_MDI_TELEVISION_AMBIENT_LIGHT "\xf3\xb1\x8d\x96" // U+F1356 +#define ICON_MDI_TELEVISION_BOX "\xf3\xb0\xa0\xb9" // U+F0839 +#define ICON_MDI_TELEVISION_CLASSIC "\xf3\xb0\x9f\xb4" // U+F07F4 +#define ICON_MDI_TELEVISION_CLASSIC_OFF "\xf3\xb0\xa0\xba" // U+F083A +#define ICON_MDI_TELEVISION_GUIDE "\xf3\xb0\x94\x83" // U+F0503 +#define ICON_MDI_TELEVISION_OFF "\xf3\xb0\xa0\xbb" // U+F083B +#define ICON_MDI_TELEVISION_PAUSE "\xf3\xb0\xbe\x89" // U+F0F89 +#define ICON_MDI_TELEVISION_PLAY "\xf3\xb0\xbb\x8f" // U+F0ECF +#define ICON_MDI_TELEVISION_SHIMMER "\xf3\xb1\x84\x90" // U+F1110 +#define ICON_MDI_TELEVISION_SPEAKER "\xf3\xb1\xac\x9b" // U+F1B1B +#define ICON_MDI_TELEVISION_SPEAKER_OFF "\xf3\xb1\xac\x9c" // U+F1B1C +#define ICON_MDI_TELEVISION_STOP "\xf3\xb0\xbe\x8a" // U+F0F8A +#define ICON_MDI_TEMPERATURE_CELSIUS "\xf3\xb0\x94\x84" // U+F0504 +#define ICON_MDI_TEMPERATURE_FAHRENHEIT "\xf3\xb0\x94\x85" // U+F0505 +#define ICON_MDI_TEMPERATURE_KELVIN "\xf3\xb0\x94\x86" // U+F0506 +#define ICON_MDI_TEMPLE_BUDDHIST "\xf3\xb1\xac\x86" // U+F1B06 +#define ICON_MDI_TEMPLE_BUDDHIST_OUTLINE "\xf3\xb1\xac\x87" // U+F1B07 +#define ICON_MDI_TEMPLE_HINDU "\xf3\xb1\xac\x88" // U+F1B08 +#define ICON_MDI_TEMPLE_HINDU_OUTLINE "\xf3\xb1\xac\x89" // U+F1B09 +#define ICON_MDI_TENNIS "\xf3\xb0\xb6\xa0" // U+F0DA0 +#define ICON_MDI_TENNIS_BALL "\xf3\xb0\x94\x87" // U+F0507 +#define ICON_MDI_TENNIS_BALL_OUTLINE "\xf3\xb1\xb1\x9f" // U+F1C5F +#define ICON_MDI_TENT "\xf3\xb0\x94\x88" // U+F0508 +#define ICON_MDI_TERRAFORM "\xf3\xb1\x81\xa2" // U+F1062 +#define ICON_MDI_TERRAIN "\xf3\xb0\x94\x89" // U+F0509 +#define ICON_MDI_TEST_TUBE "\xf3\xb0\x99\xa8" // U+F0668 +#define ICON_MDI_TEST_TUBE_EMPTY "\xf3\xb0\xa4\x91" // U+F0911 +#define ICON_MDI_TEST_TUBE_OFF "\xf3\xb0\xa4\x92" // U+F0912 +#define ICON_MDI_TEXT "\xf3\xb0\xa6\xa8" // U+F09A8 +#define ICON_MDI_TEXT_ACCOUNT "\xf3\xb1\x95\xb0" // U+F1570 +#define ICON_MDI_TEXT_BOX "\xf3\xb0\x88\x9a" // U+F021A +#define ICON_MDI_TEXT_BOX_CHECK "\xf3\xb0\xba\xa6" // U+F0EA6 +#define ICON_MDI_TEXT_BOX_CHECK_OUTLINE "\xf3\xb0\xba\xa7" // U+F0EA7 +#define ICON_MDI_TEXT_BOX_EDIT "\xf3\xb1\xa9\xbc" // U+F1A7C +#define ICON_MDI_TEXT_BOX_EDIT_OUTLINE "\xf3\xb1\xa9\xbd" // U+F1A7D +#define ICON_MDI_TEXT_BOX_MINUS "\xf3\xb0\xba\xa8" // U+F0EA8 +#define ICON_MDI_TEXT_BOX_MINUS_OUTLINE "\xf3\xb0\xba\xa9" // U+F0EA9 +#define ICON_MDI_TEXT_BOX_MULTIPLE "\xf3\xb0\xaa\xb7" // U+F0AB7 +#define ICON_MDI_TEXT_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xaa\xb8" // U+F0AB8 +#define ICON_MDI_TEXT_BOX_OUTLINE "\xf3\xb0\xa7\xad" // U+F09ED +#define ICON_MDI_TEXT_BOX_PLUS "\xf3\xb0\xba\xaa" // U+F0EAA +#define ICON_MDI_TEXT_BOX_PLUS_OUTLINE "\xf3\xb0\xba\xab" // U+F0EAB +#define ICON_MDI_TEXT_BOX_REMOVE "\xf3\xb0\xba\xac" // U+F0EAC +#define ICON_MDI_TEXT_BOX_REMOVE_OUTLINE "\xf3\xb0\xba\xad" // U+F0EAD +#define ICON_MDI_TEXT_BOX_SEARCH "\xf3\xb0\xba\xae" // U+F0EAE +#define ICON_MDI_TEXT_BOX_SEARCH_OUTLINE "\xf3\xb0\xba\xaf" // U+F0EAF +#define ICON_MDI_TEXT_LONG "\xf3\xb0\xa6\xaa" // U+F09AA +#define ICON_MDI_TEXT_RECOGNITION "\xf3\xb1\x84\xbd" // U+F113D +#define ICON_MDI_TEXT_SEARCH "\xf3\xb1\x8e\xb8" // U+F13B8 +#define ICON_MDI_TEXT_SEARCH_VARIANT "\xf3\xb1\xa9\xbe" // U+F1A7E +#define ICON_MDI_TEXT_SHADOW "\xf3\xb0\x99\xa9" // U+F0669 +#define ICON_MDI_TEXT_SHORT "\xf3\xb0\xa6\xa9" // U+F09A9 +#define ICON_MDI_TEXTURE "\xf3\xb0\x94\x8c" // U+F050C +#define ICON_MDI_TEXTURE_BOX "\xf3\xb0\xbf\xa6" // U+F0FE6 +#define ICON_MDI_THEATER "\xf3\xb0\x94\x8d" // U+F050D +#define ICON_MDI_THEME_LIGHT_DARK "\xf3\xb0\x94\x8e" // U+F050E +#define ICON_MDI_THERMOMETER "\xf3\xb0\x94\x8f" // U+F050F +#define ICON_MDI_THERMOMETER_ALERT "\xf3\xb0\xb8\x81" // U+F0E01 +#define ICON_MDI_THERMOMETER_AUTO "\xf3\xb1\xac\x8f" // U+F1B0F +#define ICON_MDI_THERMOMETER_BLUETOOTH "\xf3\xb1\xa2\x95" // U+F1895 +#define ICON_MDI_THERMOMETER_CHECK "\xf3\xb1\xa9\xbf" // U+F1A7F +#define ICON_MDI_THERMOMETER_CHEVRON_DOWN "\xf3\xb0\xb8\x82" // U+F0E02 +#define ICON_MDI_THERMOMETER_CHEVRON_UP "\xf3\xb0\xb8\x83" // U+F0E03 +#define ICON_MDI_THERMOMETER_HIGH "\xf3\xb1\x83\x82" // U+F10C2 +#define ICON_MDI_THERMOMETER_LINES "\xf3\xb0\x94\x90" // U+F0510 +#define ICON_MDI_THERMOMETER_LOW "\xf3\xb1\x83\x83" // U+F10C3 +#define ICON_MDI_THERMOMETER_MINUS "\xf3\xb0\xb8\x84" // U+F0E04 +#define ICON_MDI_THERMOMETER_OFF "\xf3\xb1\x94\xb1" // U+F1531 +#define ICON_MDI_THERMOMETER_PLUS "\xf3\xb0\xb8\x85" // U+F0E05 +#define ICON_MDI_THERMOMETER_PROBE "\xf3\xb1\xac\xab" // U+F1B2B +#define ICON_MDI_THERMOMETER_PROBE_OFF "\xf3\xb1\xac\xac" // U+F1B2C +#define ICON_MDI_THERMOMETER_WATER "\xf3\xb1\xaa\x80" // U+F1A80 +#define ICON_MDI_THERMOSTAT "\xf3\xb0\x8e\x93" // U+F0393 +#define ICON_MDI_THERMOSTAT_AUTO "\xf3\xb1\xac\x97" // U+F1B17 +#define ICON_MDI_THERMOSTAT_BOX "\xf3\xb0\xa2\x91" // U+F0891 +#define ICON_MDI_THERMOSTAT_BOX_AUTO "\xf3\xb1\xac\x98" // U+F1B18 +#define ICON_MDI_THERMOSTAT_COG "\xf3\xb1\xb2\x80" // U+F1C80 +#define ICON_MDI_THOUGHT_BUBBLE "\xf3\xb0\x9f\xb6" // U+F07F6 +#define ICON_MDI_THOUGHT_BUBBLE_OUTLINE "\xf3\xb0\x9f\xb7" // U+F07F7 +#define ICON_MDI_THUMB_DOWN "\xf3\xb0\x94\x91" // U+F0511 +#define ICON_MDI_THUMB_DOWN_OUTLINE "\xf3\xb0\x94\x92" // U+F0512 +#define ICON_MDI_THUMB_UP "\xf3\xb0\x94\x93" // U+F0513 +#define ICON_MDI_THUMB_UP_OUTLINE "\xf3\xb0\x94\x94" // U+F0514 +#define ICON_MDI_THUMBS_UP_DOWN "\xf3\xb0\x94\x95" // U+F0515 +#define ICON_MDI_THUMBS_UP_DOWN_OUTLINE "\xf3\xb1\xa4\x94" // U+F1914 +#define ICON_MDI_TICKET "\xf3\xb0\x94\x96" // U+F0516 +#define ICON_MDI_TICKET_ACCOUNT "\xf3\xb0\x94\x97" // U+F0517 +#define ICON_MDI_TICKET_CONFIRMATION "\xf3\xb0\x94\x98" // U+F0518 +#define ICON_MDI_TICKET_CONFIRMATION_OUTLINE "\xf3\xb1\x8e\xaa" // U+F13AA +#define ICON_MDI_TICKET_OUTLINE "\xf3\xb0\xa4\x93" // U+F0913 +#define ICON_MDI_TICKET_PERCENT "\xf3\xb0\x9c\xa4" // U+F0724 +#define ICON_MDI_TICKET_PERCENT_OUTLINE "\xf3\xb1\x90\xab" // U+F142B +#define ICON_MDI_TIE "\xf3\xb0\x94\x99" // U+F0519 +#define ICON_MDI_TILDE "\xf3\xb0\x9c\xa5" // U+F0725 +#define ICON_MDI_TILDE_OFF "\xf3\xb1\xa3\xb3" // U+F18F3 +#define ICON_MDI_TIMELAPSE "\xf3\xb0\x94\x9a" // U+F051A +#define ICON_MDI_TIMELINE "\xf3\xb0\xaf\x91" // U+F0BD1 +#define ICON_MDI_TIMELINE_ALERT "\xf3\xb0\xbe\x95" // U+F0F95 +#define ICON_MDI_TIMELINE_ALERT_OUTLINE "\xf3\xb0\xbe\x98" // U+F0F98 +#define ICON_MDI_TIMELINE_CHECK "\xf3\xb1\x94\xb2" // U+F1532 +#define ICON_MDI_TIMELINE_CHECK_OUTLINE "\xf3\xb1\x94\xb3" // U+F1533 +#define ICON_MDI_TIMELINE_CLOCK "\xf3\xb1\x87\xbb" // U+F11FB +#define ICON_MDI_TIMELINE_CLOCK_OUTLINE "\xf3\xb1\x87\xbc" // U+F11FC +#define ICON_MDI_TIMELINE_MINUS "\xf3\xb1\x94\xb4" // U+F1534 +#define ICON_MDI_TIMELINE_MINUS_OUTLINE "\xf3\xb1\x94\xb5" // U+F1535 +#define ICON_MDI_TIMELINE_OUTLINE "\xf3\xb0\xaf\x92" // U+F0BD2 +#define ICON_MDI_TIMELINE_PLUS "\xf3\xb0\xbe\x96" // U+F0F96 +#define ICON_MDI_TIMELINE_PLUS_OUTLINE "\xf3\xb0\xbe\x97" // U+F0F97 +#define ICON_MDI_TIMELINE_QUESTION "\xf3\xb0\xbe\x99" // U+F0F99 +#define ICON_MDI_TIMELINE_QUESTION_OUTLINE "\xf3\xb0\xbe\x9a" // U+F0F9A +#define ICON_MDI_TIMELINE_REMOVE "\xf3\xb1\x94\xb6" // U+F1536 +#define ICON_MDI_TIMELINE_REMOVE_OUTLINE "\xf3\xb1\x94\xb7" // U+F1537 +#define ICON_MDI_TIMELINE_TEXT "\xf3\xb0\xaf\x93" // U+F0BD3 +#define ICON_MDI_TIMELINE_TEXT_OUTLINE "\xf3\xb0\xaf\x94" // U+F0BD4 +#define ICON_MDI_TIMER "\xf3\xb1\x8e\xab" // U+F13AB +#define ICON_MDI_TIMER_10 "\xf3\xb0\x94\x9c" // U+F051C +#define ICON_MDI_TIMER_3 "\xf3\xb0\x94\x9d" // U+F051D +#define ICON_MDI_TIMER_ALERT "\xf3\xb1\xab\x8c" // U+F1ACC +#define ICON_MDI_TIMER_ALERT_OUTLINE "\xf3\xb1\xab\x8d" // U+F1ACD +#define ICON_MDI_TIMER_CANCEL "\xf3\xb1\xab\x8e" // U+F1ACE +#define ICON_MDI_TIMER_CANCEL_OUTLINE "\xf3\xb1\xab\x8f" // U+F1ACF +#define ICON_MDI_TIMER_CHECK "\xf3\xb1\xab\x90" // U+F1AD0 +#define ICON_MDI_TIMER_CHECK_OUTLINE "\xf3\xb1\xab\x91" // U+F1AD1 +#define ICON_MDI_TIMER_COG "\xf3\xb1\xa4\xa5" // U+F1925 +#define ICON_MDI_TIMER_COG_OUTLINE "\xf3\xb1\xa4\xa6" // U+F1926 +#define ICON_MDI_TIMER_EDIT "\xf3\xb1\xab\x92" // U+F1AD2 +#define ICON_MDI_TIMER_EDIT_OUTLINE "\xf3\xb1\xab\x93" // U+F1AD3 +#define ICON_MDI_TIMER_LOCK "\xf3\xb1\xab\x94" // U+F1AD4 +#define ICON_MDI_TIMER_LOCK_OPEN "\xf3\xb1\xab\x95" // U+F1AD5 +#define ICON_MDI_TIMER_LOCK_OPEN_OUTLINE "\xf3\xb1\xab\x96" // U+F1AD6 +#define ICON_MDI_TIMER_LOCK_OUTLINE "\xf3\xb1\xab\x97" // U+F1AD7 +#define ICON_MDI_TIMER_MARKER "\xf3\xb1\xab\x98" // U+F1AD8 +#define ICON_MDI_TIMER_MARKER_OUTLINE "\xf3\xb1\xab\x99" // U+F1AD9 +#define ICON_MDI_TIMER_MINUS "\xf3\xb1\xab\x9a" // U+F1ADA +#define ICON_MDI_TIMER_MINUS_OUTLINE "\xf3\xb1\xab\x9b" // U+F1ADB +#define ICON_MDI_TIMER_MUSIC "\xf3\xb1\xab\x9c" // U+F1ADC +#define ICON_MDI_TIMER_MUSIC_OUTLINE "\xf3\xb1\xab\x9d" // U+F1ADD +#define ICON_MDI_TIMER_OFF "\xf3\xb1\x8e\xac" // U+F13AC +#define ICON_MDI_TIMER_OFF_OUTLINE "\xf3\xb0\x94\x9e" // U+F051E +#define ICON_MDI_TIMER_OUTLINE "\xf3\xb0\x94\x9b" // U+F051B +#define ICON_MDI_TIMER_PAUSE "\xf3\xb1\xab\x9e" // U+F1ADE +#define ICON_MDI_TIMER_PAUSE_OUTLINE "\xf3\xb1\xab\x9f" // U+F1ADF +#define ICON_MDI_TIMER_PLAY "\xf3\xb1\xab\xa0" // U+F1AE0 +#define ICON_MDI_TIMER_PLAY_OUTLINE "\xf3\xb1\xab\xa1" // U+F1AE1 +#define ICON_MDI_TIMER_PLUS "\xf3\xb1\xab\xa2" // U+F1AE2 +#define ICON_MDI_TIMER_PLUS_OUTLINE "\xf3\xb1\xab\xa3" // U+F1AE3 +#define ICON_MDI_TIMER_REFRESH "\xf3\xb1\xab\xa4" // U+F1AE4 +#define ICON_MDI_TIMER_REFRESH_OUTLINE "\xf3\xb1\xab\xa5" // U+F1AE5 +#define ICON_MDI_TIMER_REMOVE "\xf3\xb1\xab\xa6" // U+F1AE6 +#define ICON_MDI_TIMER_REMOVE_OUTLINE "\xf3\xb1\xab\xa7" // U+F1AE7 +#define ICON_MDI_TIMER_SAND "\xf3\xb0\x94\x9f" // U+F051F +#define ICON_MDI_TIMER_SAND_COMPLETE "\xf3\xb1\xa6\x9f" // U+F199F +#define ICON_MDI_TIMER_SAND_EMPTY "\xf3\xb0\x9a\xad" // U+F06AD +#define ICON_MDI_TIMER_SAND_FULL "\xf3\xb0\x9e\x8c" // U+F078C +#define ICON_MDI_TIMER_SAND_PAUSED "\xf3\xb1\xa6\xa0" // U+F19A0 +#define ICON_MDI_TIMER_SETTINGS "\xf3\xb1\xa4\xa3" // U+F1923 +#define ICON_MDI_TIMER_SETTINGS_OUTLINE "\xf3\xb1\xa4\xa4" // U+F1924 +#define ICON_MDI_TIMER_STAR "\xf3\xb1\xab\xa8" // U+F1AE8 +#define ICON_MDI_TIMER_STAR_OUTLINE "\xf3\xb1\xab\xa9" // U+F1AE9 +#define ICON_MDI_TIMER_STOP "\xf3\xb1\xab\xaa" // U+F1AEA +#define ICON_MDI_TIMER_STOP_OUTLINE "\xf3\xb1\xab\xab" // U+F1AEB +#define ICON_MDI_TIMER_SYNC "\xf3\xb1\xab\xac" // U+F1AEC +#define ICON_MDI_TIMER_SYNC_OUTLINE "\xf3\xb1\xab\xad" // U+F1AED +#define ICON_MDI_TIMETABLE "\xf3\xb0\x94\xa0" // U+F0520 +#define ICON_MDI_TIRE "\xf3\xb1\xa2\x96" // U+F1896 +#define ICON_MDI_TOASTER "\xf3\xb1\x81\xa3" // U+F1063 +#define ICON_MDI_TOASTER_OFF "\xf3\xb1\x86\xb7" // U+F11B7 +#define ICON_MDI_TOASTER_OVEN "\xf3\xb0\xb3\x93" // U+F0CD3 +#define ICON_MDI_TOGGLE_SWITCH "\xf3\xb0\x94\xa1" // U+F0521 +#define ICON_MDI_TOGGLE_SWITCH_OFF "\xf3\xb0\x94\xa2" // U+F0522 +#define ICON_MDI_TOGGLE_SWITCH_OFF_OUTLINE "\xf3\xb0\xa8\x99" // U+F0A19 +#define ICON_MDI_TOGGLE_SWITCH_OUTLINE "\xf3\xb0\xa8\x9a" // U+F0A1A +#define ICON_MDI_TOGGLE_SWITCH_VARIANT "\xf3\xb1\xa8\xa5" // U+F1A25 +#define ICON_MDI_TOGGLE_SWITCH_VARIANT_OFF "\xf3\xb1\xa8\xa6" // U+F1A26 +#define ICON_MDI_TOILET "\xf3\xb0\xa6\xab" // U+F09AB +#define ICON_MDI_TOOLBOX "\xf3\xb0\xa6\xac" // U+F09AC +#define ICON_MDI_TOOLBOX_OUTLINE "\xf3\xb0\xa6\xad" // U+F09AD +#define ICON_MDI_TOOLS "\xf3\xb1\x81\xa4" // U+F1064 +#define ICON_MDI_TOOLTIP "\xf3\xb0\x94\xa3" // U+F0523 +#define ICON_MDI_TOOLTIP_ACCOUNT "\xf3\xb0\x80\x8c" // U+F000C +#define ICON_MDI_TOOLTIP_CELLPHONE "\xf3\xb1\xa0\xbb" // U+F183B +#define ICON_MDI_TOOLTIP_CHECK "\xf3\xb1\x95\x9c" // U+F155C +#define ICON_MDI_TOOLTIP_CHECK_OUTLINE "\xf3\xb1\x95\x9d" // U+F155D +#define ICON_MDI_TOOLTIP_EDIT "\xf3\xb0\x94\xa4" // U+F0524 +#define ICON_MDI_TOOLTIP_EDIT_OUTLINE "\xf3\xb1\x8b\x85" // U+F12C5 +#define ICON_MDI_TOOLTIP_IMAGE "\xf3\xb0\x94\xa5" // U+F0525 +#define ICON_MDI_TOOLTIP_IMAGE_OUTLINE "\xf3\xb0\xaf\x95" // U+F0BD5 +#define ICON_MDI_TOOLTIP_MINUS "\xf3\xb1\x95\x9e" // U+F155E +#define ICON_MDI_TOOLTIP_MINUS_OUTLINE "\xf3\xb1\x95\x9f" // U+F155F +#define ICON_MDI_TOOLTIP_OUTLINE "\xf3\xb0\x94\xa6" // U+F0526 +#define ICON_MDI_TOOLTIP_PLUS "\xf3\xb0\xaf\x96" // U+F0BD6 +#define ICON_MDI_TOOLTIP_PLUS_OUTLINE "\xf3\xb0\x94\xa7" // U+F0527 +#define ICON_MDI_TOOLTIP_QUESTION "\xf3\xb1\xae\xba" // U+F1BBA +#define ICON_MDI_TOOLTIP_QUESTION_OUTLINE "\xf3\xb1\xae\xbb" // U+F1BBB +#define ICON_MDI_TOOLTIP_REMOVE "\xf3\xb1\x95\xa0" // U+F1560 +#define ICON_MDI_TOOLTIP_REMOVE_OUTLINE "\xf3\xb1\x95\xa1" // U+F1561 +#define ICON_MDI_TOOLTIP_TEXT "\xf3\xb0\x94\xa8" // U+F0528 +#define ICON_MDI_TOOLTIP_TEXT_OUTLINE "\xf3\xb0\xaf\x97" // U+F0BD7 +#define ICON_MDI_TOOTH "\xf3\xb0\xa3\x83" // U+F08C3 +#define ICON_MDI_TOOTH_OUTLINE "\xf3\xb0\x94\xa9" // U+F0529 +#define ICON_MDI_TOOTHBRUSH "\xf3\xb1\x84\xa9" // U+F1129 +#define ICON_MDI_TOOTHBRUSH_ELECTRIC "\xf3\xb1\x84\xac" // U+F112C +#define ICON_MDI_TOOTHBRUSH_PASTE "\xf3\xb1\x84\xaa" // U+F112A +#define ICON_MDI_TORCH "\xf3\xb1\x98\x86" // U+F1606 +#define ICON_MDI_TORTOISE "\xf3\xb0\xb4\xbb" // U+F0D3B +#define ICON_MDI_TOSLINK "\xf3\xb1\x8a\xb8" // U+F12B8 +#define ICON_MDI_TOUCH_TEXT_OUTLINE "\xf3\xb1\xb1\xa0" // U+F1C60 +#define ICON_MDI_TOURNAMENT "\xf3\xb0\xa6\xae" // U+F09AE +#define ICON_MDI_TOW_TRUCK "\xf3\xb0\xa0\xbc" // U+F083C +#define ICON_MDI_TOWER_BEACH "\xf3\xb0\x9a\x81" // U+F0681 +#define ICON_MDI_TOWER_FIRE "\xf3\xb0\x9a\x82" // U+F0682 +#define ICON_MDI_TOWN_HALL "\xf3\xb1\xa1\xb5" // U+F1875 +#define ICON_MDI_TOY_BRICK "\xf3\xb1\x8a\x88" // U+F1288 +#define ICON_MDI_TOY_BRICK_MARKER "\xf3\xb1\x8a\x89" // U+F1289 +#define ICON_MDI_TOY_BRICK_MARKER_OUTLINE "\xf3\xb1\x8a\x8a" // U+F128A +#define ICON_MDI_TOY_BRICK_MINUS "\xf3\xb1\x8a\x8b" // U+F128B +#define ICON_MDI_TOY_BRICK_MINUS_OUTLINE "\xf3\xb1\x8a\x8c" // U+F128C +#define ICON_MDI_TOY_BRICK_OUTLINE "\xf3\xb1\x8a\x8d" // U+F128D +#define ICON_MDI_TOY_BRICK_PLUS "\xf3\xb1\x8a\x8e" // U+F128E +#define ICON_MDI_TOY_BRICK_PLUS_OUTLINE "\xf3\xb1\x8a\x8f" // U+F128F +#define ICON_MDI_TOY_BRICK_REMOVE "\xf3\xb1\x8a\x90" // U+F1290 +#define ICON_MDI_TOY_BRICK_REMOVE_OUTLINE "\xf3\xb1\x8a\x91" // U+F1291 +#define ICON_MDI_TOY_BRICK_SEARCH "\xf3\xb1\x8a\x92" // U+F1292 +#define ICON_MDI_TOY_BRICK_SEARCH_OUTLINE "\xf3\xb1\x8a\x93" // U+F1293 +#define ICON_MDI_TRACK_LIGHT "\xf3\xb0\xa4\x94" // U+F0914 +#define ICON_MDI_TRACK_LIGHT_OFF "\xf3\xb1\xac\x81" // U+F1B01 +#define ICON_MDI_TRACKPAD "\xf3\xb0\x9f\xb8" // U+F07F8 +#define ICON_MDI_TRACKPAD_LOCK "\xf3\xb0\xa4\xb3" // U+F0933 +#define ICON_MDI_TRACTOR "\xf3\xb0\xa2\x92" // U+F0892 +#define ICON_MDI_TRACTOR_VARIANT "\xf3\xb1\x93\x84" // U+F14C4 +#define ICON_MDI_TRADEMARK "\xf3\xb0\xa9\xb8" // U+F0A78 +#define ICON_MDI_TRAFFIC_CONE "\xf3\xb1\x8d\xbc" // U+F137C +#define ICON_MDI_TRAFFIC_LIGHT "\xf3\xb0\x94\xab" // U+F052B +#define ICON_MDI_TRAFFIC_LIGHT_OUTLINE "\xf3\xb1\xa0\xaa" // U+F182A +#define ICON_MDI_TRAIN "\xf3\xb0\x94\xac" // U+F052C +#define ICON_MDI_TRAIN_BUS "\xf3\xb1\xb3\x87" // U+F1CC7 +#define ICON_MDI_TRAIN_CAR "\xf3\xb0\xaf\x98" // U+F0BD8 +#define ICON_MDI_TRAIN_CAR_AUTORACK "\xf3\xb1\xac\xad" // U+F1B2D +#define ICON_MDI_TRAIN_CAR_BOX "\xf3\xb1\xac\xae" // U+F1B2E +#define ICON_MDI_TRAIN_CAR_BOX_FULL "\xf3\xb1\xac\xaf" // U+F1B2F +#define ICON_MDI_TRAIN_CAR_BOX_OPEN "\xf3\xb1\xac\xb0" // U+F1B30 +#define ICON_MDI_TRAIN_CAR_CABOOSE "\xf3\xb1\xac\xb1" // U+F1B31 +#define ICON_MDI_TRAIN_CAR_CENTERBEAM "\xf3\xb1\xac\xb2" // U+F1B32 +#define ICON_MDI_TRAIN_CAR_CENTERBEAM_FULL "\xf3\xb1\xac\xb3" // U+F1B33 +#define ICON_MDI_TRAIN_CAR_CONTAINER "\xf3\xb1\xac\xb4" // U+F1B34 +#define ICON_MDI_TRAIN_CAR_FLATBED "\xf3\xb1\xac\xb5" // U+F1B35 +#define ICON_MDI_TRAIN_CAR_FLATBED_CAR "\xf3\xb1\xac\xb6" // U+F1B36 +#define ICON_MDI_TRAIN_CAR_FLATBED_TANK "\xf3\xb1\xac\xb7" // U+F1B37 +#define ICON_MDI_TRAIN_CAR_GONDOLA "\xf3\xb1\xac\xb8" // U+F1B38 +#define ICON_MDI_TRAIN_CAR_GONDOLA_FULL "\xf3\xb1\xac\xb9" // U+F1B39 +#define ICON_MDI_TRAIN_CAR_HOPPER "\xf3\xb1\xac\xba" // U+F1B3A +#define ICON_MDI_TRAIN_CAR_HOPPER_COVERED "\xf3\xb1\xac\xbb" // U+F1B3B +#define ICON_MDI_TRAIN_CAR_HOPPER_FULL "\xf3\xb1\xac\xbc" // U+F1B3C +#define ICON_MDI_TRAIN_CAR_INTERMODAL "\xf3\xb1\xac\xbd" // U+F1B3D +#define ICON_MDI_TRAIN_CAR_PASSENGER "\xf3\xb1\x9c\xb3" // U+F1733 +#define ICON_MDI_TRAIN_CAR_PASSENGER_DOOR "\xf3\xb1\x9c\xb4" // U+F1734 +#define ICON_MDI_TRAIN_CAR_PASSENGER_DOOR_OPEN "\xf3\xb1\x9c\xb5" // U+F1735 +#define ICON_MDI_TRAIN_CAR_PASSENGER_VARIANT "\xf3\xb1\x9c\xb6" // U+F1736 +#define ICON_MDI_TRAIN_CAR_TANK "\xf3\xb1\xac\xbe" // U+F1B3E +#define ICON_MDI_TRAIN_VARIANT "\xf3\xb0\xa3\x84" // U+F08C4 +#define ICON_MDI_TRAM "\xf3\xb0\x94\xad" // U+F052D +#define ICON_MDI_TRAM_SIDE "\xf3\xb0\xbf\xa7" // U+F0FE7 +#define ICON_MDI_TRANSCRIBE "\xf3\xb0\x94\xae" // U+F052E +#define ICON_MDI_TRANSCRIBE_CLOSE "\xf3\xb0\x94\xaf" // U+F052F +#define ICON_MDI_TRANSFER "\xf3\xb1\x81\xa5" // U+F1065 +#define ICON_MDI_TRANSFER_DOWN "\xf3\xb0\xb6\xa1" // U+F0DA1 +#define ICON_MDI_TRANSFER_LEFT "\xf3\xb0\xb6\xa2" // U+F0DA2 +#define ICON_MDI_TRANSFER_RIGHT "\xf3\xb0\x94\xb0" // U+F0530 +#define ICON_MDI_TRANSFER_UP "\xf3\xb0\xb6\xa3" // U+F0DA3 +#define ICON_MDI_TRANSIT_CONNECTION "\xf3\xb0\xb4\xbc" // U+F0D3C +#define ICON_MDI_TRANSIT_CONNECTION_HORIZONTAL "\xf3\xb1\x95\x86" // U+F1546 +#define ICON_MDI_TRANSIT_CONNECTION_VARIANT "\xf3\xb0\xb4\xbd" // U+F0D3D +#define ICON_MDI_TRANSIT_DETOUR "\xf3\xb0\xbe\x8b" // U+F0F8B +#define ICON_MDI_TRANSIT_SKIP "\xf3\xb1\x94\x95" // U+F1515 +#define ICON_MDI_TRANSIT_TRANSFER "\xf3\xb0\x9a\xae" // U+F06AE +#define ICON_MDI_TRANSITION "\xf3\xb0\xa4\x95" // U+F0915 +#define ICON_MDI_TRANSITION_MASKED "\xf3\xb0\xa4\x96" // U+F0916 +#define ICON_MDI_TRANSLATE "\xf3\xb0\x97\x8a" // U+F05CA +#define ICON_MDI_TRANSLATE_OFF "\xf3\xb0\xb8\x86" // U+F0E06 +#define ICON_MDI_TRANSLATE_VARIANT "\xf3\xb1\xae\x99" // U+F1B99 +#define ICON_MDI_TRANSMISSION_TOWER "\xf3\xb0\xb4\xbe" // U+F0D3E +#define ICON_MDI_TRANSMISSION_TOWER_EXPORT "\xf3\xb1\xa4\xac" // U+F192C +#define ICON_MDI_TRANSMISSION_TOWER_IMPORT "\xf3\xb1\xa4\xad" // U+F192D +#define ICON_MDI_TRANSMISSION_TOWER_OFF "\xf3\xb1\xa7\x9d" // U+F19DD +#define ICON_MDI_TRASH_CAN "\xf3\xb0\xa9\xb9" // U+F0A79 +#define ICON_MDI_TRASH_CAN_OUTLINE "\xf3\xb0\xa9\xba" // U+F0A7A +#define ICON_MDI_TRAY "\xf3\xb1\x8a\x94" // U+F1294 +#define ICON_MDI_TRAY_ALERT "\xf3\xb1\x8a\x95" // U+F1295 +#define ICON_MDI_TRAY_ARROW_DOWN "\xf3\xb0\x84\xa0" // U+F0120 +#define ICON_MDI_TRAY_ARROW_UP "\xf3\xb0\x84\x9d" // U+F011D +#define ICON_MDI_TRAY_FULL "\xf3\xb1\x8a\x96" // U+F1296 +#define ICON_MDI_TRAY_MINUS "\xf3\xb1\x8a\x97" // U+F1297 +#define ICON_MDI_TRAY_PLUS "\xf3\xb1\x8a\x98" // U+F1298 +#define ICON_MDI_TRAY_REMOVE "\xf3\xb1\x8a\x99" // U+F1299 +#define ICON_MDI_TREASURE_CHEST "\xf3\xb0\x9c\xa6" // U+F0726 +#define ICON_MDI_TREASURE_CHEST_OUTLINE "\xf3\xb1\xb1\xb7" // U+F1C77 +#define ICON_MDI_TREE "\xf3\xb0\x94\xb1" // U+F0531 +#define ICON_MDI_TREE_OUTLINE "\xf3\xb0\xb9\xa9" // U+F0E69 +#define ICON_MDI_TRELLO "\xf3\xb0\x94\xb2" // U+F0532 +#define ICON_MDI_TRENDING_DOWN "\xf3\xb0\x94\xb3" // U+F0533 +#define ICON_MDI_TRENDING_NEUTRAL "\xf3\xb0\x94\xb4" // U+F0534 +#define ICON_MDI_TRENDING_UP "\xf3\xb0\x94\xb5" // U+F0535 +#define ICON_MDI_TRIANGLE "\xf3\xb0\x94\xb6" // U+F0536 +#define ICON_MDI_TRIANGLE_DOWN "\xf3\xb1\xb1\x96" // U+F1C56 +#define ICON_MDI_TRIANGLE_DOWN_OUTLINE "\xf3\xb1\xb1\x97" // U+F1C57 +#define ICON_MDI_TRIANGLE_OUTLINE "\xf3\xb0\x94\xb7" // U+F0537 +#define ICON_MDI_TRIANGLE_SMALL_DOWN "\xf3\xb1\xa8\x89" // U+F1A09 +#define ICON_MDI_TRIANGLE_SMALL_UP "\xf3\xb1\xa8\x8a" // U+F1A0A +#define ICON_MDI_TRIANGLE_WAVE "\xf3\xb1\x91\xbc" // U+F147C +#define ICON_MDI_TRIFORCE "\xf3\xb0\xaf\x99" // U+F0BD9 +#define ICON_MDI_TROPHY "\xf3\xb0\x94\xb8" // U+F0538 +#define ICON_MDI_TROPHY_AWARD "\xf3\xb0\x94\xb9" // U+F0539 +#define ICON_MDI_TROPHY_BROKEN "\xf3\xb0\xb6\xa4" // U+F0DA4 +#define ICON_MDI_TROPHY_OUTLINE "\xf3\xb0\x94\xba" // U+F053A +#define ICON_MDI_TROPHY_VARIANT "\xf3\xb0\x94\xbb" // U+F053B +#define ICON_MDI_TROPHY_VARIANT_OUTLINE "\xf3\xb0\x94\xbc" // U+F053C +#define ICON_MDI_TRUCK "\xf3\xb0\x94\xbd" // U+F053D +#define ICON_MDI_TRUCK_ALERT "\xf3\xb1\xa7\x9e" // U+F19DE +#define ICON_MDI_TRUCK_ALERT_OUTLINE "\xf3\xb1\xa7\x9f" // U+F19DF +#define ICON_MDI_TRUCK_CARGO_CONTAINER "\xf3\xb1\xa3\x98" // U+F18D8 +#define ICON_MDI_TRUCK_CHECK "\xf3\xb0\xb3\x94" // U+F0CD4 +#define ICON_MDI_TRUCK_CHECK_OUTLINE "\xf3\xb1\x8a\x9a" // U+F129A +#define ICON_MDI_TRUCK_DELIVERY "\xf3\xb0\x94\xbe" // U+F053E +#define ICON_MDI_TRUCK_DELIVERY_OUTLINE "\xf3\xb1\x8a\x9b" // U+F129B +#define ICON_MDI_TRUCK_FAST "\xf3\xb0\x9e\x88" // U+F0788 +#define ICON_MDI_TRUCK_FAST_OUTLINE "\xf3\xb1\x8a\x9c" // U+F129C +#define ICON_MDI_TRUCK_FLATBED "\xf3\xb1\xa2\x91" // U+F1891 +#define ICON_MDI_TRUCK_MINUS "\xf3\xb1\xa6\xae" // U+F19AE +#define ICON_MDI_TRUCK_MINUS_OUTLINE "\xf3\xb1\xa6\xbd" // U+F19BD +#define ICON_MDI_TRUCK_OFF_ROAD "\xf3\xb1\xb2\x9e" // U+F1C9E +#define ICON_MDI_TRUCK_OFF_ROAD_OFF "\xf3\xb1\xb2\x9f" // U+F1C9F +#define ICON_MDI_TRUCK_OUTLINE "\xf3\xb1\x8a\x9d" // U+F129D +#define ICON_MDI_TRUCK_PLUS "\xf3\xb1\xa6\xad" // U+F19AD +#define ICON_MDI_TRUCK_PLUS_OUTLINE "\xf3\xb1\xa6\xbc" // U+F19BC +#define ICON_MDI_TRUCK_REMOVE "\xf3\xb1\xa6\xaf" // U+F19AF +#define ICON_MDI_TRUCK_REMOVE_OUTLINE "\xf3\xb1\xa6\xbe" // U+F19BE +#define ICON_MDI_TRUCK_SNOWFLAKE "\xf3\xb1\xa6\xa6" // U+F19A6 +#define ICON_MDI_TRUCK_TRAILER "\xf3\xb0\x9c\xa7" // U+F0727 +#define ICON_MDI_TRUMPET "\xf3\xb1\x82\x96" // U+F1096 +#define ICON_MDI_TSHIRT_CREW "\xf3\xb0\xa9\xbb" // U+F0A7B +#define ICON_MDI_TSHIRT_CREW_OUTLINE "\xf3\xb0\x94\xbf" // U+F053F +#define ICON_MDI_TSHIRT_V "\xf3\xb0\xa9\xbc" // U+F0A7C +#define ICON_MDI_TSHIRT_V_OUTLINE "\xf3\xb0\x95\x80" // U+F0540 +#define ICON_MDI_TSUNAMI "\xf3\xb1\xaa\x81" // U+F1A81 +#define ICON_MDI_TUMBLE_DRYER "\xf3\xb0\xa4\x97" // U+F0917 +#define ICON_MDI_TUMBLE_DRYER_ALERT "\xf3\xb1\x86\xba" // U+F11BA +#define ICON_MDI_TUMBLE_DRYER_OFF "\xf3\xb1\x86\xbb" // U+F11BB +#define ICON_MDI_TUNE "\xf3\xb0\x98\xae" // U+F062E +#define ICON_MDI_TUNE_VARIANT "\xf3\xb1\x95\x82" // U+F1542 +#define ICON_MDI_TUNE_VERTICAL "\xf3\xb0\x99\xaa" // U+F066A +#define ICON_MDI_TUNE_VERTICAL_VARIANT "\xf3\xb1\x95\x83" // U+F1543 +#define ICON_MDI_TUNNEL "\xf3\xb1\xa0\xbd" // U+F183D +#define ICON_MDI_TUNNEL_OUTLINE "\xf3\xb1\xa0\xbe" // U+F183E +#define ICON_MDI_TURBINE "\xf3\xb1\xaa\x82" // U+F1A82 +#define ICON_MDI_TURKEY "\xf3\xb1\x9c\x9b" // U+F171B +#define ICON_MDI_TURNSTILE "\xf3\xb0\xb3\x95" // U+F0CD5 +#define ICON_MDI_TURNSTILE_OUTLINE "\xf3\xb0\xb3\x96" // U+F0CD6 +#define ICON_MDI_TURTLE "\xf3\xb0\xb3\x97" // U+F0CD7 +#define ICON_MDI_TWITCH "\xf3\xb0\x95\x83" // U+F0543 +#define ICON_MDI_TWITTER "\xf3\xb0\x95\x84" // U+F0544 +#define ICON_MDI_TWO_FACTOR_AUTHENTICATION "\xf3\xb0\xa6\xaf" // U+F09AF +#define ICON_MDI_TYPEWRITER "\xf3\xb0\xbc\xad" // U+F0F2D +#define ICON_MDI_UBISOFT "\xf3\xb0\xaf\x9a" // U+F0BDA +#define ICON_MDI_UBUNTU "\xf3\xb0\x95\x88" // U+F0548 +#define ICON_MDI_UFO "\xf3\xb1\x83\x84" // U+F10C4 +#define ICON_MDI_UFO_OUTLINE "\xf3\xb1\x83\x85" // U+F10C5 +#define ICON_MDI_ULTRA_HIGH_DEFINITION "\xf3\xb0\x9f\xb9" // U+F07F9 +#define ICON_MDI_UMBRACO "\xf3\xb0\x95\x89" // U+F0549 +#define ICON_MDI_UMBRELLA "\xf3\xb0\x95\x8a" // U+F054A +#define ICON_MDI_UMBRELLA_BEACH "\xf3\xb1\xa2\x8a" // U+F188A +#define ICON_MDI_UMBRELLA_BEACH_OUTLINE "\xf3\xb1\xa2\x8b" // U+F188B +#define ICON_MDI_UMBRELLA_CLOSED "\xf3\xb0\xa6\xb0" // U+F09B0 +#define ICON_MDI_UMBRELLA_CLOSED_OUTLINE "\xf3\xb1\x8f\xa2" // U+F13E2 +#define ICON_MDI_UMBRELLA_CLOSED_VARIANT "\xf3\xb1\x8f\xa1" // U+F13E1 +#define ICON_MDI_UMBRELLA_OUTLINE "\xf3\xb0\x95\x8b" // U+F054B +#define ICON_MDI_UNDO "\xf3\xb0\x95\x8c" // U+F054C +#define ICON_MDI_UNDO_VARIANT "\xf3\xb0\x95\x8d" // U+F054D +#define ICON_MDI_UNFOLD_LESS_HORIZONTAL "\xf3\xb0\x95\x8e" // U+F054E +#define ICON_MDI_UNFOLD_LESS_VERTICAL "\xf3\xb0\x9d\xa0" // U+F0760 +#define ICON_MDI_UNFOLD_MORE_HORIZONTAL "\xf3\xb0\x95\x8f" // U+F054F +#define ICON_MDI_UNFOLD_MORE_VERTICAL "\xf3\xb0\x9d\xa1" // U+F0761 +#define ICON_MDI_UNGROUP "\xf3\xb0\x95\x90" // U+F0550 +#define ICON_MDI_UNICODE "\xf3\xb0\xbb\x90" // U+F0ED0 +#define ICON_MDI_UNICORN "\xf3\xb1\x97\x82" // U+F15C2 +#define ICON_MDI_UNICORN_VARIANT "\xf3\xb1\x97\x83" // U+F15C3 +#define ICON_MDI_UNICYCLE "\xf3\xb1\x97\xa5" // U+F15E5 +#define ICON_MDI_UNITY "\xf3\xb0\x9a\xaf" // U+F06AF +#define ICON_MDI_UNREAL "\xf3\xb0\xa6\xb1" // U+F09B1 +#define ICON_MDI_UPDATE "\xf3\xb0\x9a\xb0" // U+F06B0 +#define ICON_MDI_UPLOAD "\xf3\xb0\x95\x92" // U+F0552 +#define ICON_MDI_UPLOAD_LOCK "\xf3\xb1\x8d\xb3" // U+F1373 +#define ICON_MDI_UPLOAD_LOCK_OUTLINE "\xf3\xb1\x8d\xb4" // U+F1374 +#define ICON_MDI_UPLOAD_MULTIPLE "\xf3\xb0\xa0\xbd" // U+F083D +#define ICON_MDI_UPLOAD_NETWORK "\xf3\xb0\x9b\xb6" // U+F06F6 +#define ICON_MDI_UPLOAD_NETWORK_OUTLINE "\xf3\xb0\xb3\x98" // U+F0CD8 +#define ICON_MDI_UPLOAD_OFF "\xf3\xb1\x83\x86" // U+F10C6 +#define ICON_MDI_UPLOAD_OFF_OUTLINE "\xf3\xb1\x83\x87" // U+F10C7 +#define ICON_MDI_UPLOAD_OUTLINE "\xf3\xb0\xb8\x87" // U+F0E07 +#define ICON_MDI_USB "\xf3\xb0\x95\x93" // U+F0553 +#define ICON_MDI_USB_C_PORT "\xf3\xb1\xb2\xbf" // U+F1CBF +#define ICON_MDI_USB_FLASH_DRIVE "\xf3\xb1\x8a\x9e" // U+F129E +#define ICON_MDI_USB_FLASH_DRIVE_OUTLINE "\xf3\xb1\x8a\x9f" // U+F129F +#define ICON_MDI_USB_PORT "\xf3\xb1\x87\xb0" // U+F11F0 +#define ICON_MDI_VACUUM "\xf3\xb1\xa6\xa1" // U+F19A1 +#define ICON_MDI_VACUUM_OUTLINE "\xf3\xb1\xa6\xa2" // U+F19A2 +#define ICON_MDI_VALVE "\xf3\xb1\x81\xa6" // U+F1066 +#define ICON_MDI_VALVE_CLOSED "\xf3\xb1\x81\xa7" // U+F1067 +#define ICON_MDI_VALVE_OPEN "\xf3\xb1\x81\xa8" // U+F1068 +#define ICON_MDI_VAN_PASSENGER "\xf3\xb0\x9f\xba" // U+F07FA +#define ICON_MDI_VAN_UTILITY "\xf3\xb0\x9f\xbb" // U+F07FB +#define ICON_MDI_VANISH "\xf3\xb0\x9f\xbc" // U+F07FC +#define ICON_MDI_VANISH_QUARTER "\xf3\xb1\x95\x94" // U+F1554 +#define ICON_MDI_VANITY_LIGHT "\xf3\xb1\x87\xa1" // U+F11E1 +#define ICON_MDI_VARIABLE "\xf3\xb0\xab\xa7" // U+F0AE7 +#define ICON_MDI_VARIABLE_BOX "\xf3\xb1\x84\x91" // U+F1111 +#define ICON_MDI_VECTOR_ARRANGE_ABOVE "\xf3\xb0\x95\x94" // U+F0554 +#define ICON_MDI_VECTOR_ARRANGE_BELOW "\xf3\xb0\x95\x95" // U+F0555 +#define ICON_MDI_VECTOR_BEZIER "\xf3\xb0\xab\xa8" // U+F0AE8 +#define ICON_MDI_VECTOR_CIRCLE "\xf3\xb0\x95\x96" // U+F0556 +#define ICON_MDI_VECTOR_CIRCLE_VARIANT "\xf3\xb0\x95\x97" // U+F0557 +#define ICON_MDI_VECTOR_COMBINE "\xf3\xb0\x95\x98" // U+F0558 +#define ICON_MDI_VECTOR_CURVE "\xf3\xb0\x95\x99" // U+F0559 +#define ICON_MDI_VECTOR_DIFFERENCE "\xf3\xb0\x95\x9a" // U+F055A +#define ICON_MDI_VECTOR_DIFFERENCE_AB "\xf3\xb0\x95\x9b" // U+F055B +#define ICON_MDI_VECTOR_DIFFERENCE_BA "\xf3\xb0\x95\x9c" // U+F055C +#define ICON_MDI_VECTOR_ELLIPSE "\xf3\xb0\xa2\x93" // U+F0893 +#define ICON_MDI_VECTOR_INTERSECTION "\xf3\xb0\x95\x9d" // U+F055D +#define ICON_MDI_VECTOR_LINE "\xf3\xb0\x95\x9e" // U+F055E +#define ICON_MDI_VECTOR_LINK "\xf3\xb0\xbf\xa8" // U+F0FE8 +#define ICON_MDI_VECTOR_POINT "\xf3\xb0\x87\x84" // U+F01C4 +#define ICON_MDI_VECTOR_POINT_EDIT "\xf3\xb0\xa7\xa8" // U+F09E8 +#define ICON_MDI_VECTOR_POINT_MINUS "\xf3\xb1\xad\xb8" // U+F1B78 +#define ICON_MDI_VECTOR_POINT_PLUS "\xf3\xb1\xad\xb9" // U+F1B79 +#define ICON_MDI_VECTOR_POINT_SELECT "\xf3\xb0\x95\x9f" // U+F055F +#define ICON_MDI_VECTOR_POLYGON "\xf3\xb0\x95\xa0" // U+F0560 +#define ICON_MDI_VECTOR_POLYGON_VARIANT "\xf3\xb1\xa1\x96" // U+F1856 +#define ICON_MDI_VECTOR_POLYLINE "\xf3\xb0\x95\xa1" // U+F0561 +#define ICON_MDI_VECTOR_POLYLINE_EDIT "\xf3\xb1\x88\xa5" // U+F1225 +#define ICON_MDI_VECTOR_POLYLINE_MINUS "\xf3\xb1\x88\xa6" // U+F1226 +#define ICON_MDI_VECTOR_POLYLINE_PLUS "\xf3\xb1\x88\xa7" // U+F1227 +#define ICON_MDI_VECTOR_POLYLINE_REMOVE "\xf3\xb1\x88\xa8" // U+F1228 +#define ICON_MDI_VECTOR_RADIUS "\xf3\xb0\x9d\x8a" // U+F074A +#define ICON_MDI_VECTOR_RECTANGLE "\xf3\xb0\x97\x86" // U+F05C6 +#define ICON_MDI_VECTOR_SELECTION "\xf3\xb0\x95\xa2" // U+F0562 +#define ICON_MDI_VECTOR_SQUARE "\xf3\xb0\x80\x81" // U+F0001 +#define ICON_MDI_VECTOR_SQUARE_CLOSE "\xf3\xb1\xa1\x97" // U+F1857 +#define ICON_MDI_VECTOR_SQUARE_EDIT "\xf3\xb1\xa3\x99" // U+F18D9 +#define ICON_MDI_VECTOR_SQUARE_MINUS "\xf3\xb1\xa3\x9a" // U+F18DA +#define ICON_MDI_VECTOR_SQUARE_OPEN "\xf3\xb1\xa1\x98" // U+F1858 +#define ICON_MDI_VECTOR_SQUARE_PLUS "\xf3\xb1\xa3\x9b" // U+F18DB +#define ICON_MDI_VECTOR_SQUARE_REMOVE "\xf3\xb1\xa3\x9c" // U+F18DC +#define ICON_MDI_VECTOR_TRIANGLE "\xf3\xb0\x95\xa3" // U+F0563 +#define ICON_MDI_VECTOR_UNION "\xf3\xb0\x95\xa4" // U+F0564 +#define ICON_MDI_VHS "\xf3\xb0\xa8\x9b" // U+F0A1B +#define ICON_MDI_VIBRATE "\xf3\xb0\x95\xa6" // U+F0566 +#define ICON_MDI_VIBRATE_OFF "\xf3\xb0\xb3\x99" // U+F0CD9 +#define ICON_MDI_VIDEO "\xf3\xb0\x95\xa7" // U+F0567 +#define ICON_MDI_VIDEO_2D "\xf3\xb1\xa8\x9c" // U+F1A1C +#define ICON_MDI_VIDEO_3D "\xf3\xb0\x9f\xbd" // U+F07FD +#define ICON_MDI_VIDEO_3D_OFF "\xf3\xb1\x8f\x99" // U+F13D9 +#define ICON_MDI_VIDEO_3D_VARIANT "\xf3\xb0\xbb\x91" // U+F0ED1 +#define ICON_MDI_VIDEO_4K_BOX "\xf3\xb0\xa0\xbe" // U+F083E +#define ICON_MDI_VIDEO_ACCOUNT "\xf3\xb0\xa4\x99" // U+F0919 +#define ICON_MDI_VIDEO_BOX "\xf3\xb0\x83\xbd" // U+F00FD +#define ICON_MDI_VIDEO_BOX_OFF "\xf3\xb0\x83\xbe" // U+F00FE +#define ICON_MDI_VIDEO_CHECK "\xf3\xb1\x81\xa9" // U+F1069 +#define ICON_MDI_VIDEO_CHECK_OUTLINE "\xf3\xb1\x81\xaa" // U+F106A +#define ICON_MDI_VIDEO_HIGH_DEFINITION "\xf3\xb1\x94\xae" // U+F152E +#define ICON_MDI_VIDEO_IMAGE "\xf3\xb0\xa4\x9a" // U+F091A +#define ICON_MDI_VIDEO_INPUT_ANTENNA "\xf3\xb0\xa0\xbf" // U+F083F +#define ICON_MDI_VIDEO_INPUT_COMPONENT "\xf3\xb0\xa1\x80" // U+F0840 +#define ICON_MDI_VIDEO_INPUT_HDMI "\xf3\xb0\xa1\x81" // U+F0841 +#define ICON_MDI_VIDEO_INPUT_SCART "\xf3\xb0\xbe\x8c" // U+F0F8C +#define ICON_MDI_VIDEO_INPUT_SVIDEO "\xf3\xb0\xa1\x82" // U+F0842 +#define ICON_MDI_VIDEO_MARKER "\xf3\xb1\xa6\xa9" // U+F19A9 +#define ICON_MDI_VIDEO_MARKER_OUTLINE "\xf3\xb1\xa6\xaa" // U+F19AA +#define ICON_MDI_VIDEO_MINUS "\xf3\xb0\xa6\xb2" // U+F09B2 +#define ICON_MDI_VIDEO_MINUS_OUTLINE "\xf3\xb0\x8a\xba" // U+F02BA +#define ICON_MDI_VIDEO_OFF "\xf3\xb0\x95\xa8" // U+F0568 +#define ICON_MDI_VIDEO_OFF_OUTLINE "\xf3\xb0\xaf\x9b" // U+F0BDB +#define ICON_MDI_VIDEO_OUTLINE "\xf3\xb0\xaf\x9c" // U+F0BDC +#define ICON_MDI_VIDEO_PLUS "\xf3\xb0\xa6\xb3" // U+F09B3 +#define ICON_MDI_VIDEO_PLUS_OUTLINE "\xf3\xb0\x87\x93" // U+F01D3 +#define ICON_MDI_VIDEO_STABILIZATION "\xf3\xb0\xa4\x9b" // U+F091B +#define ICON_MDI_VIDEO_STANDARD_DEFINITION "\xf3\xb1\xb2\xa0" // U+F1CA0 +#define ICON_MDI_VIDEO_SWITCH "\xf3\xb0\x95\xa9" // U+F0569 +#define ICON_MDI_VIDEO_SWITCH_OUTLINE "\xf3\xb0\x9e\x90" // U+F0790 +#define ICON_MDI_VIDEO_VINTAGE "\xf3\xb0\xa8\x9c" // U+F0A1C +#define ICON_MDI_VIDEO_WIRELESS "\xf3\xb0\xbb\x92" // U+F0ED2 +#define ICON_MDI_VIDEO_WIRELESS_OUTLINE "\xf3\xb0\xbb\x93" // U+F0ED3 +#define ICON_MDI_VIEW_AGENDA "\xf3\xb0\x95\xaa" // U+F056A +#define ICON_MDI_VIEW_AGENDA_OUTLINE "\xf3\xb1\x87\x98" // U+F11D8 +#define ICON_MDI_VIEW_ARRAY "\xf3\xb0\x95\xab" // U+F056B +#define ICON_MDI_VIEW_ARRAY_OUTLINE "\xf3\xb1\x92\x85" // U+F1485 +#define ICON_MDI_VIEW_CAROUSEL "\xf3\xb0\x95\xac" // U+F056C +#define ICON_MDI_VIEW_CAROUSEL_OUTLINE "\xf3\xb1\x92\x86" // U+F1486 +#define ICON_MDI_VIEW_COLUMN "\xf3\xb0\x95\xad" // U+F056D +#define ICON_MDI_VIEW_COLUMN_OUTLINE "\xf3\xb1\x92\x87" // U+F1487 +#define ICON_MDI_VIEW_COMFY "\xf3\xb0\xb9\xaa" // U+F0E6A +#define ICON_MDI_VIEW_COMFY_OUTLINE "\xf3\xb1\x92\x88" // U+F1488 +#define ICON_MDI_VIEW_COMPACT "\xf3\xb0\xb9\xab" // U+F0E6B +#define ICON_MDI_VIEW_COMPACT_OUTLINE "\xf3\xb0\xb9\xac" // U+F0E6C +#define ICON_MDI_VIEW_DASHBOARD "\xf3\xb0\x95\xae" // U+F056E +#define ICON_MDI_VIEW_DASHBOARD_EDIT "\xf3\xb1\xa5\x87" // U+F1947 +#define ICON_MDI_VIEW_DASHBOARD_EDIT_OUTLINE "\xf3\xb1\xa5\x88" // U+F1948 +#define ICON_MDI_VIEW_DASHBOARD_OUTLINE "\xf3\xb0\xa8\x9d" // U+F0A1D +#define ICON_MDI_VIEW_DASHBOARD_VARIANT "\xf3\xb0\xa1\x83" // U+F0843 +#define ICON_MDI_VIEW_DASHBOARD_VARIANT_OUTLINE "\xf3\xb1\x92\x89" // U+F1489 +#define ICON_MDI_VIEW_DAY "\xf3\xb0\x95\xaf" // U+F056F +#define ICON_MDI_VIEW_DAY_OUTLINE "\xf3\xb1\x92\x8a" // U+F148A +#define ICON_MDI_VIEW_GALLERY "\xf3\xb1\xa2\x88" // U+F1888 +#define ICON_MDI_VIEW_GALLERY_OUTLINE "\xf3\xb1\xa2\x89" // U+F1889 +#define ICON_MDI_VIEW_GRID "\xf3\xb0\x95\xb0" // U+F0570 +#define ICON_MDI_VIEW_GRID_COMPACT "\xf3\xb1\xb1\xa1" // U+F1C61 +#define ICON_MDI_VIEW_GRID_OUTLINE "\xf3\xb1\x87\x99" // U+F11D9 +#define ICON_MDI_VIEW_GRID_PLUS "\xf3\xb0\xbe\x8d" // U+F0F8D +#define ICON_MDI_VIEW_GRID_PLUS_OUTLINE "\xf3\xb1\x87\x9a" // U+F11DA +#define ICON_MDI_VIEW_HEADLINE "\xf3\xb0\x95\xb1" // U+F0571 +#define ICON_MDI_VIEW_LIST "\xf3\xb0\x95\xb2" // U+F0572 +#define ICON_MDI_VIEW_LIST_OUTLINE "\xf3\xb1\x92\x8b" // U+F148B +#define ICON_MDI_VIEW_MODULE "\xf3\xb0\x95\xb3" // U+F0573 +#define ICON_MDI_VIEW_MODULE_OUTLINE "\xf3\xb1\x92\x8c" // U+F148C +#define ICON_MDI_VIEW_PARALLEL "\xf3\xb0\x9c\xa8" // U+F0728 +#define ICON_MDI_VIEW_PARALLEL_OUTLINE "\xf3\xb1\x92\x8d" // U+F148D +#define ICON_MDI_VIEW_QUILT "\xf3\xb0\x95\xb4" // U+F0574 +#define ICON_MDI_VIEW_QUILT_OUTLINE "\xf3\xb1\x92\x8e" // U+F148E +#define ICON_MDI_VIEW_SEQUENTIAL "\xf3\xb0\x9c\xa9" // U+F0729 +#define ICON_MDI_VIEW_SEQUENTIAL_OUTLINE "\xf3\xb1\x92\x8f" // U+F148F +#define ICON_MDI_VIEW_SPLIT_HORIZONTAL "\xf3\xb0\xaf\x8b" // U+F0BCB +#define ICON_MDI_VIEW_SPLIT_VERTICAL "\xf3\xb0\xaf\x8c" // U+F0BCC +#define ICON_MDI_VIEW_STREAM "\xf3\xb0\x95\xb5" // U+F0575 +#define ICON_MDI_VIEW_STREAM_OUTLINE "\xf3\xb1\x92\x90" // U+F1490 +#define ICON_MDI_VIEW_WEEK "\xf3\xb0\x95\xb6" // U+F0576 +#define ICON_MDI_VIEW_WEEK_OUTLINE "\xf3\xb1\x92\x91" // U+F1491 +#define ICON_MDI_VIMEO "\xf3\xb0\x95\xb7" // U+F0577 +#define ICON_MDI_VIOLIN "\xf3\xb0\x98\x8f" // U+F060F +#define ICON_MDI_VIRTUAL_REALITY "\xf3\xb0\xa2\x94" // U+F0894 +#define ICON_MDI_VIRUS "\xf3\xb1\x8e\xb6" // U+F13B6 +#define ICON_MDI_VIRUS_OFF "\xf3\xb1\xa3\xa1" // U+F18E1 +#define ICON_MDI_VIRUS_OFF_OUTLINE "\xf3\xb1\xa3\xa2" // U+F18E2 +#define ICON_MDI_VIRUS_OUTLINE "\xf3\xb1\x8e\xb7" // U+F13B7 +#define ICON_MDI_VLC "\xf3\xb0\x95\xbc" // U+F057C +#define ICON_MDI_VOICEMAIL "\xf3\xb0\x95\xbd" // U+F057D +#define ICON_MDI_VOLCANO "\xf3\xb1\xaa\x83" // U+F1A83 +#define ICON_MDI_VOLCANO_OUTLINE "\xf3\xb1\xaa\x84" // U+F1A84 +#define ICON_MDI_VOLLEYBALL "\xf3\xb0\xa6\xb4" // U+F09B4 +#define ICON_MDI_VOLUME_EQUAL "\xf3\xb1\xac\x90" // U+F1B10 +#define ICON_MDI_VOLUME_HIGH "\xf3\xb0\x95\xbe" // U+F057E +#define ICON_MDI_VOLUME_LOW "\xf3\xb0\x95\xbf" // U+F057F +#define ICON_MDI_VOLUME_MEDIUM "\xf3\xb0\x96\x80" // U+F0580 +#define ICON_MDI_VOLUME_MINUS "\xf3\xb0\x9d\x9e" // U+F075E +#define ICON_MDI_VOLUME_MUTE "\xf3\xb0\x9d\x9f" // U+F075F +#define ICON_MDI_VOLUME_OFF "\xf3\xb0\x96\x81" // U+F0581 +#define ICON_MDI_VOLUME_PLUS "\xf3\xb0\x9d\x9d" // U+F075D +#define ICON_MDI_VOLUME_SOURCE "\xf3\xb1\x84\xa0" // U+F1120 +#define ICON_MDI_VOLUME_VARIANT_OFF "\xf3\xb0\xb8\x88" // U+F0E08 +#define ICON_MDI_VOLUME_VIBRATE "\xf3\xb1\x84\xa1" // U+F1121 +#define ICON_MDI_VOTE "\xf3\xb0\xa8\x9f" // U+F0A1F +#define ICON_MDI_VOTE_OUTLINE "\xf3\xb0\xa8\xa0" // U+F0A20 +#define ICON_MDI_VPN "\xf3\xb0\x96\x82" // U+F0582 +#define ICON_MDI_VUEJS "\xf3\xb0\xa1\x84" // U+F0844 +#define ICON_MDI_VUETIFY "\xf3\xb0\xb9\xad" // U+F0E6D +#define ICON_MDI_WALK "\xf3\xb0\x96\x83" // U+F0583 +#define ICON_MDI_WALL "\xf3\xb0\x9f\xbe" // U+F07FE +#define ICON_MDI_WALL_FIRE "\xf3\xb1\xa8\x91" // U+F1A11 +#define ICON_MDI_WALL_SCONCE "\xf3\xb0\xa4\x9c" // U+F091C +#define ICON_MDI_WALL_SCONCE_FLAT "\xf3\xb0\xa4\x9d" // U+F091D +#define ICON_MDI_WALL_SCONCE_FLAT_OUTLINE "\xf3\xb1\x9f\x89" // U+F17C9 +#define ICON_MDI_WALL_SCONCE_FLAT_VARIANT "\xf3\xb0\x90\x9c" // U+F041C +#define ICON_MDI_WALL_SCONCE_FLAT_VARIANT_OUTLINE "\xf3\xb1\x9f\x8a" // U+F17CA +#define ICON_MDI_WALL_SCONCE_OUTLINE "\xf3\xb1\x9f\x8b" // U+F17CB +#define ICON_MDI_WALL_SCONCE_ROUND "\xf3\xb0\x9d\x88" // U+F0748 +#define ICON_MDI_WALL_SCONCE_ROUND_OUTLINE "\xf3\xb1\x9f\x8c" // U+F17CC +#define ICON_MDI_WALL_SCONCE_ROUND_VARIANT "\xf3\xb0\xa4\x9e" // U+F091E +#define ICON_MDI_WALL_SCONCE_ROUND_VARIANT_OUTLINE "\xf3\xb1\x9f\x8d" // U+F17CD +#define ICON_MDI_WALLET "\xf3\xb0\x96\x84" // U+F0584 +#define ICON_MDI_WALLET_BIFOLD "\xf3\xb1\xb1\x98" // U+F1C58 +#define ICON_MDI_WALLET_BIFOLD_OUTLINE "\xf3\xb1\xb1\x99" // U+F1C59 +#define ICON_MDI_WALLET_GIFTCARD "\xf3\xb0\x96\x85" // U+F0585 +#define ICON_MDI_WALLET_MEMBERSHIP "\xf3\xb0\x96\x86" // U+F0586 +#define ICON_MDI_WALLET_OUTLINE "\xf3\xb0\xaf\x9d" // U+F0BDD +#define ICON_MDI_WALLET_PLUS "\xf3\xb0\xbe\x8e" // U+F0F8E +#define ICON_MDI_WALLET_PLUS_OUTLINE "\xf3\xb0\xbe\x8f" // U+F0F8F +#define ICON_MDI_WALLET_TRAVEL "\xf3\xb0\x96\x87" // U+F0587 +#define ICON_MDI_WALLPAPER "\xf3\xb0\xb8\x89" // U+F0E09 +#define ICON_MDI_WAN "\xf3\xb0\x96\x88" // U+F0588 +#define ICON_MDI_WARDROBE "\xf3\xb0\xbe\x90" // U+F0F90 +#define ICON_MDI_WARDROBE_OUTLINE "\xf3\xb0\xbe\x91" // U+F0F91 +#define ICON_MDI_WAREHOUSE "\xf3\xb0\xbe\x81" // U+F0F81 +#define ICON_MDI_WASHING_MACHINE "\xf3\xb0\x9c\xaa" // U+F072A +#define ICON_MDI_WASHING_MACHINE_ALERT "\xf3\xb1\x86\xbc" // U+F11BC +#define ICON_MDI_WASHING_MACHINE_OFF "\xf3\xb1\x86\xbd" // U+F11BD +#define ICON_MDI_WATCH "\xf3\xb0\x96\x89" // U+F0589 +#define ICON_MDI_WATCH_EXPORT "\xf3\xb0\x96\x8a" // U+F058A +#define ICON_MDI_WATCH_EXPORT_VARIANT "\xf3\xb0\xa2\x95" // U+F0895 +#define ICON_MDI_WATCH_IMPORT "\xf3\xb0\x96\x8b" // U+F058B +#define ICON_MDI_WATCH_IMPORT_VARIANT "\xf3\xb0\xa2\x96" // U+F0896 +#define ICON_MDI_WATCH_VARIANT "\xf3\xb0\xa2\x97" // U+F0897 +#define ICON_MDI_WATCH_VIBRATE "\xf3\xb0\x9a\xb1" // U+F06B1 +#define ICON_MDI_WATCH_VIBRATE_OFF "\xf3\xb0\xb3\x9a" // U+F0CDA +#define ICON_MDI_WATER "\xf3\xb0\x96\x8c" // U+F058C +#define ICON_MDI_WATER_ALERT "\xf3\xb1\x94\x82" // U+F1502 +#define ICON_MDI_WATER_ALERT_OUTLINE "\xf3\xb1\x94\x83" // U+F1503 +#define ICON_MDI_WATER_BOILER "\xf3\xb0\xbe\x92" // U+F0F92 +#define ICON_MDI_WATER_BOILER_ALERT "\xf3\xb1\x86\xb3" // U+F11B3 +#define ICON_MDI_WATER_BOILER_AUTO "\xf3\xb1\xae\x98" // U+F1B98 +#define ICON_MDI_WATER_BOILER_OFF "\xf3\xb1\x86\xb4" // U+F11B4 +#define ICON_MDI_WATER_CHECK "\xf3\xb1\x94\x84" // U+F1504 +#define ICON_MDI_WATER_CHECK_OUTLINE "\xf3\xb1\x94\x85" // U+F1505 +#define ICON_MDI_WATER_CIRCLE "\xf3\xb1\xa0\x86" // U+F1806 +#define ICON_MDI_WATER_MINUS "\xf3\xb1\x94\x86" // U+F1506 +#define ICON_MDI_WATER_MINUS_OUTLINE "\xf3\xb1\x94\x87" // U+F1507 +#define ICON_MDI_WATER_OFF "\xf3\xb0\x96\x8d" // U+F058D +#define ICON_MDI_WATER_OFF_OUTLINE "\xf3\xb1\x94\x88" // U+F1508 +#define ICON_MDI_WATER_OPACITY "\xf3\xb1\xa1\x95" // U+F1855 +#define ICON_MDI_WATER_OUTLINE "\xf3\xb0\xb8\x8a" // U+F0E0A +#define ICON_MDI_WATER_PERCENT "\xf3\xb0\x96\x8e" // U+F058E +#define ICON_MDI_WATER_PERCENT_ALERT "\xf3\xb1\x94\x89" // U+F1509 +#define ICON_MDI_WATER_PLUS "\xf3\xb1\x94\x8a" // U+F150A +#define ICON_MDI_WATER_PLUS_OUTLINE "\xf3\xb1\x94\x8b" // U+F150B +#define ICON_MDI_WATER_POLO "\xf3\xb1\x8a\xa0" // U+F12A0 +#define ICON_MDI_WATER_PUMP "\xf3\xb0\x96\x8f" // U+F058F +#define ICON_MDI_WATER_PUMP_OFF "\xf3\xb0\xbe\x93" // U+F0F93 +#define ICON_MDI_WATER_REMOVE "\xf3\xb1\x94\x8c" // U+F150C +#define ICON_MDI_WATER_REMOVE_OUTLINE "\xf3\xb1\x94\x8d" // U+F150D +#define ICON_MDI_WATER_SYNC "\xf3\xb1\x9f\x86" // U+F17C6 +#define ICON_MDI_WATER_THERMOMETER "\xf3\xb1\xaa\x85" // U+F1A85 +#define ICON_MDI_WATER_THERMOMETER_OUTLINE "\xf3\xb1\xaa\x86" // U+F1A86 +#define ICON_MDI_WATER_WELL "\xf3\xb1\x81\xab" // U+F106B +#define ICON_MDI_WATER_WELL_OUTLINE "\xf3\xb1\x81\xac" // U+F106C +#define ICON_MDI_WATERFALL "\xf3\xb1\xa1\x89" // U+F1849 +#define ICON_MDI_WATERING_CAN "\xf3\xb1\x92\x81" // U+F1481 +#define ICON_MDI_WATERING_CAN_OUTLINE "\xf3\xb1\x92\x82" // U+F1482 +#define ICON_MDI_WATERMARK "\xf3\xb0\x98\x92" // U+F0612 +#define ICON_MDI_WAVE "\xf3\xb0\xbc\xae" // U+F0F2E +#define ICON_MDI_WAVE_ARROW_DOWN "\xf3\xb1\xb2\xb0" // U+F1CB0 +#define ICON_MDI_WAVE_ARROW_UP "\xf3\xb1\xb2\xb1" // U+F1CB1 +#define ICON_MDI_WAVE_UNDERCURRENT "\xf3\xb1\xb3\x80" // U+F1CC0 +#define ICON_MDI_WAVEFORM "\xf3\xb1\x91\xbd" // U+F147D +#define ICON_MDI_WAVES "\xf3\xb0\x9e\x8d" // U+F078D +#define ICON_MDI_WAVES_ARROW_LEFT "\xf3\xb1\xa1\x99" // U+F1859 +#define ICON_MDI_WAVES_ARROW_RIGHT "\xf3\xb1\xa1\x9a" // U+F185A +#define ICON_MDI_WAVES_ARROW_UP "\xf3\xb1\xa1\x9b" // U+F185B +#define ICON_MDI_WAZE "\xf3\xb0\xaf\x9e" // U+F0BDE +#define ICON_MDI_WEATHER_CLOUDY "\xf3\xb0\x96\x90" // U+F0590 +#define ICON_MDI_WEATHER_CLOUDY_ALERT "\xf3\xb0\xbc\xaf" // U+F0F2F +#define ICON_MDI_WEATHER_CLOUDY_ARROW_RIGHT "\xf3\xb0\xb9\xae" // U+F0E6E +#define ICON_MDI_WEATHER_CLOUDY_CLOCK "\xf3\xb1\xa3\xb6" // U+F18F6 +#define ICON_MDI_WEATHER_DUST "\xf3\xb1\xad\x9a" // U+F1B5A +#define ICON_MDI_WEATHER_FOG "\xf3\xb0\x96\x91" // U+F0591 +#define ICON_MDI_WEATHER_HAIL "\xf3\xb0\x96\x92" // U+F0592 +#define ICON_MDI_WEATHER_HAZY "\xf3\xb0\xbc\xb0" // U+F0F30 +#define ICON_MDI_WEATHER_HURRICANE "\xf3\xb0\xa2\x98" // U+F0898 +#define ICON_MDI_WEATHER_HURRICANE_OUTLINE "\xf3\xb1\xb1\xb8" // U+F1C78 +#define ICON_MDI_WEATHER_LIGHTNING "\xf3\xb0\x96\x93" // U+F0593 +#define ICON_MDI_WEATHER_LIGHTNING_RAINY "\xf3\xb0\x99\xbe" // U+F067E +#define ICON_MDI_WEATHER_NIGHT "\xf3\xb0\x96\x94" // U+F0594 +#define ICON_MDI_WEATHER_NIGHT_PARTLY_CLOUDY "\xf3\xb0\xbc\xb1" // U+F0F31 +#define ICON_MDI_WEATHER_PARTLY_CLOUDY "\xf3\xb0\x96\x95" // U+F0595 +#define ICON_MDI_WEATHER_PARTLY_LIGHTNING "\xf3\xb0\xbc\xb2" // U+F0F32 +#define ICON_MDI_WEATHER_PARTLY_RAINY "\xf3\xb0\xbc\xb3" // U+F0F33 +#define ICON_MDI_WEATHER_PARTLY_SNOWY "\xf3\xb0\xbc\xb4" // U+F0F34 +#define ICON_MDI_WEATHER_PARTLY_SNOWY_RAINY "\xf3\xb0\xbc\xb5" // U+F0F35 +#define ICON_MDI_WEATHER_POURING "\xf3\xb0\x96\x96" // U+F0596 +#define ICON_MDI_WEATHER_RAINY "\xf3\xb0\x96\x97" // U+F0597 +#define ICON_MDI_WEATHER_SNOWY "\xf3\xb0\x96\x98" // U+F0598 +#define ICON_MDI_WEATHER_SNOWY_HEAVY "\xf3\xb0\xbc\xb6" // U+F0F36 +#define ICON_MDI_WEATHER_SNOWY_RAINY "\xf3\xb0\x99\xbf" // U+F067F +#define ICON_MDI_WEATHER_SUNNY "\xf3\xb0\x96\x99" // U+F0599 +#define ICON_MDI_WEATHER_SUNNY_ALERT "\xf3\xb0\xbc\xb7" // U+F0F37 +#define ICON_MDI_WEATHER_SUNNY_OFF "\xf3\xb1\x93\xa4" // U+F14E4 +#define ICON_MDI_WEATHER_SUNSET "\xf3\xb0\x96\x9a" // U+F059A +#define ICON_MDI_WEATHER_SUNSET_DOWN "\xf3\xb0\x96\x9b" // U+F059B +#define ICON_MDI_WEATHER_SUNSET_UP "\xf3\xb0\x96\x9c" // U+F059C +#define ICON_MDI_WEATHER_TORNADO "\xf3\xb0\xbc\xb8" // U+F0F38 +#define ICON_MDI_WEATHER_WINDY "\xf3\xb0\x96\x9d" // U+F059D +#define ICON_MDI_WEATHER_WINDY_VARIANT "\xf3\xb0\x96\x9e" // U+F059E +#define ICON_MDI_WEB "\xf3\xb0\x96\x9f" // U+F059F +#define ICON_MDI_WEB_BOX "\xf3\xb0\xbe\x94" // U+F0F94 +#define ICON_MDI_WEB_CANCEL "\xf3\xb1\x9e\x90" // U+F1790 +#define ICON_MDI_WEB_CHECK "\xf3\xb0\x9e\x89" // U+F0789 +#define ICON_MDI_WEB_CLOCK "\xf3\xb1\x89\x8a" // U+F124A +#define ICON_MDI_WEB_MINUS "\xf3\xb1\x82\xa0" // U+F10A0 +#define ICON_MDI_WEB_OFF "\xf3\xb0\xaa\x8e" // U+F0A8E +#define ICON_MDI_WEB_PLUS "\xf3\xb0\x80\xb3" // U+F0033 +#define ICON_MDI_WEB_REFRESH "\xf3\xb1\x9e\x91" // U+F1791 +#define ICON_MDI_WEB_REMOVE "\xf3\xb0\x95\x91" // U+F0551 +#define ICON_MDI_WEB_SYNC "\xf3\xb1\x9e\x92" // U+F1792 +#define ICON_MDI_WEBCAM "\xf3\xb0\x96\xa0" // U+F05A0 +#define ICON_MDI_WEBCAM_OFF "\xf3\xb1\x9c\xb7" // U+F1737 +#define ICON_MDI_WEBHOOK "\xf3\xb0\x98\xaf" // U+F062F +#define ICON_MDI_WEBPACK "\xf3\xb0\x9c\xab" // U+F072B +#define ICON_MDI_WEBRTC "\xf3\xb1\x89\x88" // U+F1248 +#define ICON_MDI_WECHAT "\xf3\xb0\x98\x91" // U+F0611 +#define ICON_MDI_WEIGHT "\xf3\xb0\x96\xa1" // U+F05A1 +#define ICON_MDI_WEIGHT_GRAM "\xf3\xb0\xb4\xbf" // U+F0D3F +#define ICON_MDI_WEIGHT_KILOGRAM "\xf3\xb0\x96\xa2" // U+F05A2 +#define ICON_MDI_WEIGHT_LIFTER "\xf3\xb1\x85\x9d" // U+F115D +#define ICON_MDI_WEIGHT_POUND "\xf3\xb0\xa6\xb5" // U+F09B5 +#define ICON_MDI_WHATSAPP "\xf3\xb0\x96\xa3" // U+F05A3 +#define ICON_MDI_WHEEL_BARROW "\xf3\xb1\x93\xb2" // U+F14F2 +#define ICON_MDI_WHEELCHAIR "\xf3\xb1\xaa\x87" // U+F1A87 +#define ICON_MDI_WHEELCHAIR_ACCESSIBILITY "\xf3\xb0\x96\xa4" // U+F05A4 +#define ICON_MDI_WHISTLE "\xf3\xb0\xa6\xb6" // U+F09B6 +#define ICON_MDI_WHISTLE_OUTLINE "\xf3\xb1\x8a\xbc" // U+F12BC +#define ICON_MDI_WHITE_BALANCE_AUTO "\xf3\xb0\x96\xa5" // U+F05A5 +#define ICON_MDI_WHITE_BALANCE_INCANDESCENT "\xf3\xb0\x96\xa6" // U+F05A6 +#define ICON_MDI_WHITE_BALANCE_IRIDESCENT "\xf3\xb0\x96\xa7" // U+F05A7 +#define ICON_MDI_WHITE_BALANCE_SUNNY "\xf3\xb0\x96\xa8" // U+F05A8 +#define ICON_MDI_WIDGETS "\xf3\xb0\x9c\xac" // U+F072C +#define ICON_MDI_WIDGETS_OUTLINE "\xf3\xb1\x8d\x95" // U+F1355 +#define ICON_MDI_WIFI "\xf3\xb0\x96\xa9" // U+F05A9 +#define ICON_MDI_WIFI_ALERT "\xf3\xb1\x9a\xb5" // U+F16B5 +#define ICON_MDI_WIFI_ARROW_DOWN "\xf3\xb1\x9a\xb6" // U+F16B6 +#define ICON_MDI_WIFI_ARROW_LEFT "\xf3\xb1\x9a\xb7" // U+F16B7 +#define ICON_MDI_WIFI_ARROW_LEFT_RIGHT "\xf3\xb1\x9a\xb8" // U+F16B8 +#define ICON_MDI_WIFI_ARROW_RIGHT "\xf3\xb1\x9a\xb9" // U+F16B9 +#define ICON_MDI_WIFI_ARROW_UP "\xf3\xb1\x9a\xba" // U+F16BA +#define ICON_MDI_WIFI_ARROW_UP_DOWN "\xf3\xb1\x9a\xbb" // U+F16BB +#define ICON_MDI_WIFI_CANCEL "\xf3\xb1\x9a\xbc" // U+F16BC +#define ICON_MDI_WIFI_CHECK "\xf3\xb1\x9a\xbd" // U+F16BD +#define ICON_MDI_WIFI_COG "\xf3\xb1\x9a\xbe" // U+F16BE +#define ICON_MDI_WIFI_LOCK "\xf3\xb1\x9a\xbf" // U+F16BF +#define ICON_MDI_WIFI_LOCK_OPEN "\xf3\xb1\x9b\x80" // U+F16C0 +#define ICON_MDI_WIFI_MARKER "\xf3\xb1\x9b\x81" // U+F16C1 +#define ICON_MDI_WIFI_MINUS "\xf3\xb1\x9b\x82" // U+F16C2 +#define ICON_MDI_WIFI_OFF "\xf3\xb0\x96\xaa" // U+F05AA +#define ICON_MDI_WIFI_PLUS "\xf3\xb1\x9b\x83" // U+F16C3 +#define ICON_MDI_WIFI_REFRESH "\xf3\xb1\x9b\x84" // U+F16C4 +#define ICON_MDI_WIFI_REMOVE "\xf3\xb1\x9b\x85" // U+F16C5 +#define ICON_MDI_WIFI_SETTINGS "\xf3\xb1\x9b\x86" // U+F16C6 +#define ICON_MDI_WIFI_STAR "\xf3\xb0\xb8\x8b" // U+F0E0B +#define ICON_MDI_WIFI_STRENGTH_1 "\xf3\xb0\xa4\x9f" // U+F091F +#define ICON_MDI_WIFI_STRENGTH_1_ALERT "\xf3\xb0\xa4\xa0" // U+F0920 +#define ICON_MDI_WIFI_STRENGTH_1_LOCK "\xf3\xb0\xa4\xa1" // U+F0921 +#define ICON_MDI_WIFI_STRENGTH_1_LOCK_OPEN "\xf3\xb1\x9b\x8b" // U+F16CB +#define ICON_MDI_WIFI_STRENGTH_2 "\xf3\xb0\xa4\xa2" // U+F0922 +#define ICON_MDI_WIFI_STRENGTH_2_ALERT "\xf3\xb0\xa4\xa3" // U+F0923 +#define ICON_MDI_WIFI_STRENGTH_2_LOCK "\xf3\xb0\xa4\xa4" // U+F0924 +#define ICON_MDI_WIFI_STRENGTH_2_LOCK_OPEN "\xf3\xb1\x9b\x8c" // U+F16CC +#define ICON_MDI_WIFI_STRENGTH_3 "\xf3\xb0\xa4\xa5" // U+F0925 +#define ICON_MDI_WIFI_STRENGTH_3_ALERT "\xf3\xb0\xa4\xa6" // U+F0926 +#define ICON_MDI_WIFI_STRENGTH_3_LOCK "\xf3\xb0\xa4\xa7" // U+F0927 +#define ICON_MDI_WIFI_STRENGTH_3_LOCK_OPEN "\xf3\xb1\x9b\x8d" // U+F16CD +#define ICON_MDI_WIFI_STRENGTH_4 "\xf3\xb0\xa4\xa8" // U+F0928 +#define ICON_MDI_WIFI_STRENGTH_4_ALERT "\xf3\xb0\xa4\xa9" // U+F0929 +#define ICON_MDI_WIFI_STRENGTH_4_LOCK "\xf3\xb0\xa4\xaa" // U+F092A +#define ICON_MDI_WIFI_STRENGTH_4_LOCK_OPEN "\xf3\xb1\x9b\x8e" // U+F16CE +#define ICON_MDI_WIFI_STRENGTH_ALERT_OUTLINE "\xf3\xb0\xa4\xab" // U+F092B +#define ICON_MDI_WIFI_STRENGTH_LOCK_OPEN_OUTLINE "\xf3\xb1\x9b\x8f" // U+F16CF +#define ICON_MDI_WIFI_STRENGTH_LOCK_OUTLINE "\xf3\xb0\xa4\xac" // U+F092C +#define ICON_MDI_WIFI_STRENGTH_OFF "\xf3\xb0\xa4\xad" // U+F092D +#define ICON_MDI_WIFI_STRENGTH_OFF_OUTLINE "\xf3\xb0\xa4\xae" // U+F092E +#define ICON_MDI_WIFI_STRENGTH_OUTLINE "\xf3\xb0\xa4\xaf" // U+F092F +#define ICON_MDI_WIFI_SYNC "\xf3\xb1\x9b\x87" // U+F16C7 +#define ICON_MDI_WIKIPEDIA "\xf3\xb0\x96\xac" // U+F05AC +#define ICON_MDI_WIND_POWER "\xf3\xb1\xaa\x88" // U+F1A88 +#define ICON_MDI_WIND_POWER_OUTLINE "\xf3\xb1\xaa\x89" // U+F1A89 +#define ICON_MDI_WIND_TURBINE "\xf3\xb0\xb6\xa5" // U+F0DA5 +#define ICON_MDI_WIND_TURBINE_ALERT "\xf3\xb1\xa6\xab" // U+F19AB +#define ICON_MDI_WIND_TURBINE_CHECK "\xf3\xb1\xa6\xac" // U+F19AC +#define ICON_MDI_WINDOW_CLOSE "\xf3\xb0\x96\xad" // U+F05AD +#define ICON_MDI_WINDOW_CLOSED "\xf3\xb0\x96\xae" // U+F05AE +#define ICON_MDI_WINDOW_CLOSED_VARIANT "\xf3\xb1\x87\x9b" // U+F11DB +#define ICON_MDI_WINDOW_MAXIMIZE "\xf3\xb0\x96\xaf" // U+F05AF +#define ICON_MDI_WINDOW_MINIMIZE "\xf3\xb0\x96\xb0" // U+F05B0 +#define ICON_MDI_WINDOW_OPEN "\xf3\xb0\x96\xb1" // U+F05B1 +#define ICON_MDI_WINDOW_OPEN_VARIANT "\xf3\xb1\x87\x9c" // U+F11DC +#define ICON_MDI_WINDOW_RESTORE "\xf3\xb0\x96\xb2" // U+F05B2 +#define ICON_MDI_WINDOW_SHUTTER "\xf3\xb1\x84\x9c" // U+F111C +#define ICON_MDI_WINDOW_SHUTTER_ALERT "\xf3\xb1\x84\x9d" // U+F111D +#define ICON_MDI_WINDOW_SHUTTER_AUTO "\xf3\xb1\xae\xa3" // U+F1BA3 +#define ICON_MDI_WINDOW_SHUTTER_COG "\xf3\xb1\xaa\x8a" // U+F1A8A +#define ICON_MDI_WINDOW_SHUTTER_OPEN "\xf3\xb1\x84\x9e" // U+F111E +#define ICON_MDI_WINDOW_SHUTTER_SETTINGS "\xf3\xb1\xaa\x8b" // U+F1A8B +#define ICON_MDI_WINDSOCK "\xf3\xb1\x97\xba" // U+F15FA +#define ICON_MDI_WIPER "\xf3\xb0\xab\xa9" // U+F0AE9 +#define ICON_MDI_WIPER_WASH "\xf3\xb0\xb6\xa6" // U+F0DA6 +#define ICON_MDI_WIPER_WASH_ALERT "\xf3\xb1\xa3\x9f" // U+F18DF +#define ICON_MDI_WIZARD_HAT "\xf3\xb1\x91\xb7" // U+F1477 +#define ICON_MDI_WORDPRESS "\xf3\xb0\x96\xb4" // U+F05B4 +#define ICON_MDI_WRAP "\xf3\xb0\x96\xb6" // U+F05B6 +#define ICON_MDI_WRAP_DISABLED "\xf3\xb0\xaf\x9f" // U+F0BDF +#define ICON_MDI_WRENCH "\xf3\xb0\x96\xb7" // U+F05B7 +#define ICON_MDI_WRENCH_CHECK "\xf3\xb1\xae\x8f" // U+F1B8F +#define ICON_MDI_WRENCH_CHECK_OUTLINE "\xf3\xb1\xae\x90" // U+F1B90 +#define ICON_MDI_WRENCH_CLOCK "\xf3\xb1\xa6\xa3" // U+F19A3 +#define ICON_MDI_WRENCH_CLOCK_OUTLINE "\xf3\xb1\xae\x93" // U+F1B93 +#define ICON_MDI_WRENCH_COG "\xf3\xb1\xae\x91" // U+F1B91 +#define ICON_MDI_WRENCH_COG_OUTLINE "\xf3\xb1\xae\x92" // U+F1B92 +#define ICON_MDI_WRENCH_OUTLINE "\xf3\xb0\xaf\xa0" // U+F0BE0 +#define ICON_MDI_XAMARIN "\xf3\xb0\xa1\x85" // U+F0845 +#define ICON_MDI_XML "\xf3\xb0\x97\x80" // U+F05C0 +#define ICON_MDI_XMPP "\xf3\xb0\x9f\xbf" // U+F07FF +#define ICON_MDI_YAHOO "\xf3\xb0\xad\x8f" // U+F0B4F +#define ICON_MDI_YEAST "\xf3\xb0\x97\x81" // U+F05C1 +#define ICON_MDI_YIN_YANG "\xf3\xb0\x9a\x80" // U+F0680 +#define ICON_MDI_YOGA "\xf3\xb1\x85\xbc" // U+F117C +#define ICON_MDI_YOUTUBE "\xf3\xb0\x97\x83" // U+F05C3 +#define ICON_MDI_YOUTUBE_GAMING "\xf3\xb0\xa1\x88" // U+F0848 +#define ICON_MDI_YOUTUBE_STUDIO "\xf3\xb0\xa1\x87" // U+F0847 +#define ICON_MDI_YOUTUBE_SUBSCRIPTION "\xf3\xb0\xb5\x80" // U+F0D40 +#define ICON_MDI_YOUTUBE_TV "\xf3\xb0\x91\x88" // U+F0448 +#define ICON_MDI_YURT "\xf3\xb1\x94\x96" // U+F1516 +#define ICON_MDI_Z_WAVE "\xf3\xb0\xab\xaa" // U+F0AEA +#define ICON_MDI_ZEND "\xf3\xb0\xab\xab" // U+F0AEB +#define ICON_MDI_ZIGBEE "\xf3\xb0\xb5\x81" // U+F0D41 +#define ICON_MDI_ZIP_BOX "\xf3\xb0\x97\x84" // U+F05C4 +#define ICON_MDI_ZIP_BOX_OUTLINE "\xf3\xb0\xbf\xba" // U+F0FFA +#define ICON_MDI_ZIP_DISK "\xf3\xb0\xa8\xa3" // U+F0A23 +#define ICON_MDI_ZODIAC_AQUARIUS "\xf3\xb0\xa9\xbd" // U+F0A7D +#define ICON_MDI_ZODIAC_ARIES "\xf3\xb0\xa9\xbe" // U+F0A7E +#define ICON_MDI_ZODIAC_CANCER "\xf3\xb0\xa9\xbf" // U+F0A7F +#define ICON_MDI_ZODIAC_CAPRICORN "\xf3\xb0\xaa\x80" // U+F0A80 +#define ICON_MDI_ZODIAC_GEMINI "\xf3\xb0\xaa\x81" // U+F0A81 +#define ICON_MDI_ZODIAC_LEO "\xf3\xb0\xaa\x82" // U+F0A82 +#define ICON_MDI_ZODIAC_LIBRA "\xf3\xb0\xaa\x83" // U+F0A83 +#define ICON_MDI_ZODIAC_PISCES "\xf3\xb0\xaa\x84" // U+F0A84 +#define ICON_MDI_ZODIAC_SAGITTARIUS "\xf3\xb0\xaa\x85" // U+F0A85 +#define ICON_MDI_ZODIAC_SCORPIO "\xf3\xb0\xaa\x86" // U+F0A86 +#define ICON_MDI_ZODIAC_TAURUS "\xf3\xb0\xaa\x87" // U+F0A87 +#define ICON_MDI_ZODIAC_VIRGO "\xf3\xb0\xaa\x88" // U+F0A88 +#define ICON_MDI_BLANK "\xef\x9a\x8c" // U+F68C +#line 0 +// editor_script +#define GLEQ_IMPLEMENTATION +#line 1 "3rd_lite_sys_gleq.h" +/* + * GLEQ - A basic event queue for GLFW 3 + * Copyright © Camilla Löwy + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would + * be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ + +#ifndef GLEQ_HEADER_FILE +#define GLEQ_HEADER_FILE + +// #include + +#ifdef GLEQ_STATIC + #define GLEQDEF static +#else + #define GLEQDEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + GLEQ_NONE = 0, + GLEQ_WINDOW_MOVED = 1<<1, + GLEQ_WINDOW_RESIZED = 1<<2, + GLEQ_WINDOW_CLOSED = 1<<3, + GLEQ_WINDOW_REFRESH = 1<<4, + GLEQ_WINDOW_FOCUSED = 1<<5, + GLEQ_WINDOW_DEFOCUSED = 1<<6, + GLEQ_WINDOW_ICONIFIED = 1<<7, + GLEQ_WINDOW_UNICONIFIED = 1<<8, + GLEQ_FRAMEBUFFER_RESIZED = 1<<9, + GLEQ_BUTTON_PRESSED = 1<<10, + GLEQ_BUTTON_RELEASED = 1<<11, + GLEQ_CURSOR_MOVED = 1<<12, + GLEQ_CURSOR_ENTERED = 1<<13, + GLEQ_CURSOR_LEFT = 1<<14, + GLEQ_SCROLLED = 1<<15, + GLEQ_KEY_PRESSED = 1<<16, + GLEQ_KEY_REPEATED = 1<<17, + GLEQ_KEY_RELEASED = 1<<18, + GLEQ_CODEPOINT_INPUT = 1<<19, + GLEQ_MONITOR_CONNECTED = 1<<20, + GLEQ_MONITOR_DISCONNECTED = 1<<21, +#if GLFW_VERSION_MINOR >= 1 + GLEQ_FILE_DROPPED = 1<<22, +#endif +#if GLFW_VERSION_MINOR >= 2 + GLEQ_JOYSTICK_CONNECTED = 1<<23, + GLEQ_JOYSTICK_DISCONNECTED = 1<<24, +#endif +#if GLFW_VERSION_MINOR >= 3 + GLEQ_WINDOW_MAXIMIZED = 1<<25, + GLEQ_WINDOW_UNMAXIMIZED = 1<<26, + GLEQ_WINDOW_SCALE_CHANGED = 1<<27, +#endif +} GLEQtype; + +typedef struct GLEQevent +{ + unsigned/*GLEQtype*/ type; + union { + GLFWwindow* window; + GLFWmonitor* monitor; + int joystick; + }; + union { + struct { + int x; + int y; + } pos; + struct { + int width; + int height; + } size; + struct { + double x; + double y; + } scroll; + struct { + int key; + int scancode; + int mods; + } keyboard; + struct { + int button; + int mods; + } mouse; + unsigned int codepoint; +#if GLFW_VERSION_MINOR >= 1 + struct { + char** paths; + int count; + } file; +#endif +#if GLFW_VERSION_MINOR >= 3 + struct { + float x; + float y; + } scale; +#endif + }; +} GLEQevent; + +GLEQDEF void gleqInit(void); +GLEQDEF void gleqTrackWindow(GLFWwindow* window); + +GLEQDEF int gleqNextEvent(GLEQevent* event); +GLEQDEF void gleqFreeEvent(GLEQevent* event); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEQ_IMPLEMENTATION + +#include +#include +#include + +#ifndef GLEQ_CAPACITY + #define GLEQ_CAPACITY 1024 +#endif + +static struct +{ + GLEQevent events[GLEQ_CAPACITY]; + size_t head; + size_t tail; +} gleq_queue = { {0}, 0, 0 }; + +static char* gleq_strdup(const char* string) +{ + const size_t size = strlen(string) + 1; + char* result = (char*) malloc(size); + memcpy(result, string, size); + return result; +} + +static GLEQevent* gleq_new_event(void) +{ + GLEQevent* event = gleq_queue.events + gleq_queue.head; + gleq_queue.head = (gleq_queue.head + 1) % GLEQ_CAPACITY; + assert(gleq_queue.head != gleq_queue.tail); + memset(event, 0, sizeof(GLEQevent)); + return event; +} + +static void gleq_window_pos_callback(GLFWwindow* window, int x, int y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_MOVED; + event->window = window; + event->pos.x = x; + event->pos.y = y; +} + +static void gleq_window_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_window_close_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_CLOSED; + event->window = window; +} + +static void gleq_window_refresh_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_REFRESH; + event->window = window; +} + +static void gleq_window_focus_callback(GLFWwindow* window, int focused) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (focused) + event->type = GLEQ_WINDOW_FOCUSED; + else + event->type = GLEQ_WINDOW_DEFOCUSED; +} + +static void gleq_window_iconify_callback(GLFWwindow* window, int iconified) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (iconified) + event->type = GLEQ_WINDOW_ICONIFIED; + else + event->type = GLEQ_WINDOW_UNICONIFIED; +} + +static void gleq_framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FRAMEBUFFER_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->mouse.button = button; + event->mouse.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_BUTTON_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_BUTTON_RELEASED; +} + +static void gleq_cursor_pos_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CURSOR_MOVED; + event->window = window; + event->pos.x = (int) x; + event->pos.y = (int) y; +} + +static void gleq_cursor_enter_callback(GLFWwindow* window, int entered) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (entered) + event->type = GLEQ_CURSOR_ENTERED; + else + event->type = GLEQ_CURSOR_LEFT; +} + +static void gleq_scroll_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_SCROLLED; + event->window = window; + event->scroll.x = x; + event->scroll.y = y; +} + +static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->keyboard.key = key; + event->keyboard.scancode = scancode; + event->keyboard.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_KEY_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_KEY_RELEASED; + else if (action == GLFW_REPEAT) + event->type = GLEQ_KEY_REPEATED; +} + +static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CODEPOINT_INPUT; + event->window = window; + event->codepoint = codepoint; +} + +static void gleq_monitor_callback(GLFWmonitor* monitor, int action) +{ + GLEQevent* event = gleq_new_event(); + event->monitor = monitor; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_MONITOR_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_MONITOR_DISCONNECTED; +} + +#if GLFW_VERSION_MINOR >= 1 +static void gleq_file_drop_callback(GLFWwindow* window, int count, const char** paths) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FILE_DROPPED; + event->window = window; + event->file.paths = (char**) malloc(count * sizeof(char*)); + event->file.count = count; + + while (count--) + event->file.paths[count] = gleq_strdup(paths[count]); +} +#endif + +#if GLFW_VERSION_MINOR >= 2 +static void gleq_joystick_callback(int jid, int action) +{ + GLEQevent* event = gleq_new_event(); + event->joystick = jid; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_JOYSTICK_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_JOYSTICK_DISCONNECTED; +} +#endif + +#if GLFW_VERSION_MINOR >= 3 +static void gleq_window_maximize_callback(GLFWwindow* window, int maximized) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (maximized) + event->type = GLEQ_WINDOW_MAXIMIZED; + else + event->type = GLEQ_WINDOW_UNMAXIMIZED; +} + +static void gleq_window_content_scale_callback(GLFWwindow* window, float xscale, float yscale) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->type = GLEQ_WINDOW_SCALE_CHANGED; + event->scale.x = xscale; + event->scale.y = yscale; +} +#endif + +GLEQDEF void gleqInit(void) +{ + glfwSetMonitorCallback(gleq_monitor_callback); +#if GLFW_VERSION_MINOR >= 2 + glfwSetJoystickCallback(gleq_joystick_callback); +#endif +} + +GLEQDEF void gleqTrackWindow(GLFWwindow* window) +{ + glfwSetWindowPosCallback(window, gleq_window_pos_callback); + glfwSetWindowSizeCallback(window, gleq_window_size_callback); + glfwSetWindowCloseCallback(window, gleq_window_close_callback); + glfwSetWindowRefreshCallback(window, gleq_window_refresh_callback); + glfwSetWindowFocusCallback(window, gleq_window_focus_callback); + glfwSetWindowIconifyCallback(window, gleq_window_iconify_callback); + glfwSetFramebufferSizeCallback(window, gleq_framebuffer_size_callback); + glfwSetMouseButtonCallback(window, gleq_mouse_button_callback); + glfwSetCursorPosCallback(window, gleq_cursor_pos_callback); + glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback); + glfwSetScrollCallback(window, gleq_scroll_callback); + glfwSetKeyCallback(window, gleq_key_callback); + glfwSetCharCallback(window, gleq_char_callback); +#if GLFW_VERSION_MINOR >= 1 + glfwSetDropCallback(window, gleq_file_drop_callback); +#endif +#if GLFW_VERSION_MINOR >= 3 + glfwSetWindowMaximizeCallback(window, gleq_window_maximize_callback); + glfwSetWindowContentScaleCallback(window, gleq_window_content_scale_callback); +#endif +} + +GLEQDEF int gleqNextEvent(GLEQevent* event) +{ + memset(event, 0, sizeof(GLEQevent)); + + if (gleq_queue.head != gleq_queue.tail) + { + *event = gleq_queue.events[gleq_queue.tail]; + gleq_queue.tail = (gleq_queue.tail + 1) % GLEQ_CAPACITY; + } + + return event->type != GLEQ_NONE; +} + +GLEQDEF void gleqFreeEvent(GLEQevent* event) +{ +#if GLFW_VERSION_MINOR >= 1 + if (event->type == GLEQ_FILE_DROPPED) + { + while (event->file.count--) + free(event->file.paths[event->file.count]); + + free(event->file.paths); + } +#endif + + memset(event, 0, sizeof(GLEQevent)); +} + +#endif /* GLEQ_IMPLEMENTATION */ + +#endif /* GLEQ_HEADER_FILE */ +#line 0 +#line 1 "3rd_lite_sys.h" +// lite editor, platform details +// - rlyeh, public domain + +#define LT_DATAPATH "/lite" + +#define lt_assert(x) ASSERT(x) + +#define lt_realpath(p, q) file_pathabs(p) +#define lt_realpath_free(p) + +#define lt_malloc(n) MALLOC(n) +#define lt_calloc(n,m) CALLOC(n,m) +#define lt_free(p) FREE(p) +#define lt_memcpy(d,s,c) memcpy(d,s,c) +#define lt_memset(p,ch,c) memset(p,ch,c) + +#define lt_time_ms() time_ms() +#define lt_sleep_ms(ms) sleep_ms(ms) + +#define lt_getclipboard(w) window_clipboard() +#define lt_setclipboard(w,s) window_setclipboard(s) + +#define lt_window() window_handle() +#define lt_setwindowmode(m) window_fullscreen(m == 2), (m < 2 && (window_maximize(m),1)) // 0:normal,1:maximized,2:fullscreen +#define lt_setwindowtitle(t) //window_title(t) +#define lt_haswindowfocus() window_has_focus() +#define lt_setcursor(shape) window_cursor_shape(lt_events & (1<<31) ? CURSOR_SW_AUTO : shape+1) // 0:arrow,1:ibeam,2:sizeh,3:sizev,4:hand + +#define lt_prompt(msg,title) ifndef(win32, 0, (MessageBoxA(0, msg, title, MB_YESNO | MB_ICONWARNING) == IDYES)) + +unsigned lt_events = ~0u; +int lt_mx = 0, lt_my = 0, lt_wx = 0, lt_wy = 0, lt_ww = 0, lt_wh = 0; + +typedef struct lt_surface { + unsigned w, h; + void *pixels; + texture_t t; +} lt_surface; + +typedef struct lt_rect { + int x, y, width, height; +} lt_rect; + +lt_surface *lt_getsurface(void *window) { + static lt_surface s = {0}; + return &s; +} +void lt_updatesurfacerects(lt_surface *s, lt_rect* rects, unsigned count) { + if(0) + for( int i = 0; i < count; ++i ) { + memset( (unsigned*)s->pixels + (rects[i].x + rects[i].y * s->w), 0xFF, rects[i].width*4 ); + memset( (unsigned*)s->pixels + (rects[i].x + (rects[i].y + (rects[i].height-1)) * s->w), 0xFF, rects[i].width*4 ); + for( int y = 1; y < (rects[i].height-1); ++y ) { + ((unsigned*)s->pixels)[ rects[i].x + y * s->w ] = + ((unsigned*)s->pixels)[ rects[i].x + (rects[i].width-1) + y * s->w ] = 0xFFFFFFFF; + } + } + + // update contents + texture_update(&s->t, s->w, s->h, 4, s->pixels, TEXTURE_LINEAR|TEXTURE_BGRA); +} + +void ren_set_clip_rect(struct lt_rect rect); +void rencache_invalidate(void); +int lt_resizesurface(lt_surface *s, int ww, int wh) { + s->w = ww, s->h = wh; + if( s->t.id == 0 || s->w != s->t.w || s->h != s->t.h ) { + // invalidate tiles + ren_set_clip_rect( (lt_rect) { 0, 0, s->w, s->h } ); + rencache_invalidate(); + + // texture clear + if( !s->t.id ) s->t = texture_create(1, 1, 4, " ", TEXTURE_LINEAR|TEXTURE_RGBA|TEXTURE_BYTE ); + s->pixels = REALLOC(s->pixels, s->w * s->h * 4); + memset(s->pixels, 0, s->w * s->h * 4); + + // texture update + lt_updatesurfacerects(s,0,0); + return 1; // resized + } + return 0; // unchanged +} + +void *lt_load_file(const char *filename, int *size) { + int datalen; char *data = file_load(filename, &datalen); + if( !data || !datalen ) { + filename = (const char *)file_normalize(filename); + if( strbegi(filename, app_path()) ) filename += strlen(app_path()); + data = vfs_load(filename, &datalen); + } + if (size) *size = 0; + if (!data) { return NULL; } + if (size) *size = datalen; + // return permanent buffers here, as file_load() and vfs_load() do return temporaries + data = memcpy(MALLOC(datalen+1), data, datalen); + data[datalen] = 0; + return data; +} + +const char* lt_button_name(int button) { + if(button == GLFW_MOUSE_BUTTON_LEFT) return "left"; + if(button == GLFW_MOUSE_BUTTON_RIGHT) return "right"; + if(button == GLFW_MOUSE_BUTTON_MIDDLE) return "middle"; + return "?"; +} + +char* lt_key_name(char *dst, int key, int vk, int mods) { + // @todo: "altgr" -> left ctrl + right alt + + if( key == GLFW_KEY_UP ) return "up"; + if( key == GLFW_KEY_DOWN ) return "down"; + if( key == GLFW_KEY_LEFT ) return "left"; + if( key == GLFW_KEY_RIGHT ) return "right"; + if( key == GLFW_KEY_LEFT_ALT ) return "left alt"; + if( key == GLFW_KEY_RIGHT_ALT ) return "right alt"; + if( key == GLFW_KEY_LEFT_SHIFT ) return "left shift"; + if( key == GLFW_KEY_RIGHT_SHIFT ) return "right shift"; + if( key == GLFW_KEY_LEFT_CONTROL ) return "left ctrl"; + if( key == GLFW_KEY_RIGHT_CONTROL ) return "right ctrl"; + if( key == GLFW_KEY_LEFT_SUPER ) return "left windows"; + if( key == GLFW_KEY_RIGHT_SUPER ) return "left windows"; + if( key == GLFW_KEY_MENU ) return "menu"; + + if( key == GLFW_KEY_ESCAPE ) return "escape"; + if( key == GLFW_KEY_BACKSPACE ) return "backspace"; + if( key == GLFW_KEY_ENTER ) return "return"; + if( key == GLFW_KEY_KP_ENTER ) return "keypad enter"; + if( key == GLFW_KEY_TAB ) return "tab"; + if( key == GLFW_KEY_CAPS_LOCK ) return "capslock"; + + if( key == GLFW_KEY_HOME ) return "home"; + if( key == GLFW_KEY_END ) return "end"; + if( key == GLFW_KEY_INSERT ) return "insert"; + if( key == GLFW_KEY_DELETE ) return "delete"; + if( key == GLFW_KEY_PAGE_UP ) return "pageup"; + if( key == GLFW_KEY_PAGE_DOWN ) return "pagedown"; + + if( key == GLFW_KEY_F1 ) return "f1"; + if( key == GLFW_KEY_F2 ) return "f2"; + if( key == GLFW_KEY_F3 ) return "f3"; + if( key == GLFW_KEY_F4 ) return "f4"; + if( key == GLFW_KEY_F5 ) return "f5"; + if( key == GLFW_KEY_F6 ) return "f6"; + if( key == GLFW_KEY_F7 ) return "f7"; + if( key == GLFW_KEY_F8 ) return "f8"; + if( key == GLFW_KEY_F9 ) return "f9"; + if( key == GLFW_KEY_F10 ) return "f10"; + if( key == GLFW_KEY_F11 ) return "f11"; + if( key == GLFW_KEY_F12 ) return "f12"; + + const char *name = glfwGetKeyName(key, vk); + strcpy(dst, name ? name : ""); + char *p = dst; + while (*p) { + *p = tolower(*p); + p++; + } + return dst; +} + +void lt_globpath(struct lua_State*L, const char *path) { + unsigned j = 0; + + if(!strend(path, "/")) path = (const char *)va("%s/", path); + for( dir *d = dir_open(path, ""); d; dir_close(d), d = 0 ) { + for( unsigned i = 0, end = dir_count(d); i < end; ++i ) { + char *name = dir_name(d,i); + char *last = name + strlen(name) - 1; + if( *last == '/' ) *last = '\0'; + name = file_name(name); + lua_pushstring(L, name); + lua_rawseti(L, -2, ++j); + } + } + + for( const char *section = strstri(path, LT_DATAPATH); section && section[sizeof(LT_DATAPATH)-1] == '/'; section = 0) { + array(char*) list = vfs_list("**"); + for( unsigned i = 0, end = array_count(list); i < end; ++i ) { + char *name = list[i]; + if( !strstri(name, section+1) ) continue; + lua_pushstring(L, file_name(name)); + lua_rawseti(L, -2, ++j); + } + if( array_count(list) ) return; + } +} + +int lt_emit_event(lua_State *L, const char *event_name, const char *event_fmt, ...) { + int count = 0; + lua_pushstring(L, event_name); + if( event_fmt ) { + va_list va; + va_start(va, event_fmt); + for( ; event_fmt[count]; ++count ) { + /**/ if( event_fmt[count] == 'd' ) { int d = va_arg(va, int); lua_pushnumber(L, d); } + else if( event_fmt[count] == 'f' ) { double f = va_arg(va, double); lua_pushnumber(L, f); } + else if( event_fmt[count] == 's' ) { const char *s = va_arg(va, const char *); lua_pushstring(L, s); } + } + va_end(va); + } + return 1+count; +} + +int printi(int i) { + // printf("clicks: %d\n", i); + return i; +} + +static const char* codepoint_to_utf8(unsigned c); +int lt_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = 0; + char buf[16]; + static int prevx = 0, prevy = 0; + + static unsigned clicks_time = 0, clicks = 0; + if( (lt_time_ms() - clicks_time) > 400 ) clicks = 0; + + // + + for( GLEQevent e; gleqNextEvent(&e); gleqFreeEvent(&e) ) + if( lt_events & e.type ) + switch (e.type) { + default: + break; case GLEQ_WINDOW_CLOSED: // it used to be ok. depends on window_swap() flow + rc += lt_emit_event(L, "quit", NULL); + return rc; + + break; case GLEQ_WINDOW_MOVED: + lt_wx = e.pos.x; + lt_wy = e.pos.y; + + break; case GLEQ_WINDOW_RESIZED: + rc += lt_emit_event(L, "resized", "dd", lt_ww = e.size.width, lt_wh = e.size.height); + lt_resizesurface(lt_getsurface(lt_window()), lt_ww, lt_wh); + + break; case GLEQ_WINDOW_REFRESH: + rc += lt_emit_event(L, "exposed", NULL); + rencache_invalidate(); + + break; case GLEQ_FILE_DROPPED: + rc += lt_emit_event(L, "filedropped", "sdd", e.file.paths[0], lt_mx, lt_my); + + break; case GLEQ_KEY_PRESSED: + case GLEQ_KEY_REPEATED: + rc += lt_emit_event(L, "keypressed", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_KEY_RELEASED: + rc += lt_emit_event(L, "keyreleased", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_CODEPOINT_INPUT: + rc += lt_emit_event(L, "textinput", "s", codepoint_to_utf8(e.codepoint)); + + break; case GLEQ_BUTTON_PRESSED: + rc += lt_emit_event(L, "mousepressed", "sddd", lt_button_name(e.mouse.button), lt_mx, lt_my, printi(1 + clicks)); + + break; case GLEQ_BUTTON_RELEASED: + clicks += e.mouse.button == GLFW_MOUSE_BUTTON_1; + clicks_time = lt_time_ms(); + rc += lt_emit_event(L, "mousereleased", "sdd", lt_button_name(e.mouse.button), lt_mx, lt_my); + + break; case GLEQ_CURSOR_MOVED: + lt_mx = e.pos.x - lt_wx, lt_my = e.pos.y - lt_wy; + rc += lt_emit_event(L, "mousemoved", "dddd", lt_mx, lt_my, lt_mx - prevx, lt_my - prevy); + prevx = lt_mx, prevy = lt_my; + + break; case GLEQ_SCROLLED: + rc += lt_emit_event(L, "mousewheel", "f", e.scroll.y); + } + +bottom:; + + return rc; +} +#line 0 +#line 1 "3rd_lite.h" +// Copyright (c) 2020 rxi +// +// 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. + +// [doc] https://rxi.github.io/lite_an_implementation_overview.html +// [chg] differences from https://github.com/rxi/lite listed below: +// +// a) amalgamated as single-file source. +// b) platform agnostic now (no more specific SDL calls; tested with GLFW backend). +// c) specific `lt_` platform bits have been moved out to an external file (lite_sys.h) +// d) lua, stb-truetype and lite_sys headers *must be included* beforehand. +// e) embeddable: reverted loop handler from framework to library mode. see: lt_init/lt_tick +// f) data folders reorganized as data/themes, data/languages/ and data/plugins/. +// g) DATADIR path can be specified now and no longer forced to be EXEDIR/data/. +// h) packaged with a bunch of handy plugins from https://github.com/rxi/lite-plugins +// i) packaged with all color themes from https://github.com/rxi/lite-colors +// j) merged a few pending PRs and pending fixes from original repo. +// k) Lua sources fixed for Lua >= 5.2 +// +// All contributions released under same MIT licensing terms than original code. +// - rlyeh. + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +// ---------------------------------------------------------------------------- +// lite/api.h + +#define API_TYPE_FONT "Font" + +// ---------------------------------------------------------------------------- +// lite/renderer.h + +typedef struct RenImage RenImage; +typedef struct RenFont RenFont; + +typedef struct { uint8_t b, g, r, a; } RenColor; +//typedef struct { int x, y, width, height; } RenRect; +typedef lt_rect RenRect; + + +void ren_init(void *win); +void ren_update_rects(RenRect *rects, int count); +void ren_set_clip_rect(RenRect rect); +void ren_get_size(int *x, int *y); + +RenImage* ren_new_image(int width, int height); +void ren_free_image(RenImage *image); + +RenFont* ren_load_font(const char *filename, float size); +void ren_free_font(RenFont *font); +void ren_set_font_tab_width(RenFont *font, int n); +int ren_get_font_tab_width(RenFont *font); +int ren_get_font_width(RenFont *font, const char *text); +int ren_get_font_height(RenFont *font); + +void ren_draw_rect(RenRect rect, RenColor color); +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color); +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); + +// ---------------------------------------------------------------------------- +// lite/rencache.h + +void rencache_show_debug(bool enable); +void rencache_free_font(RenFont *font); +void rencache_set_clip_rect(RenRect rect); +void rencache_draw_rect(RenRect rect, RenColor color); +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); +void rencache_invalidate(void); +void rencache_begin_frame(void); +void rencache_end_frame(void); + +// ---------------------------------------------------------------------------- +// lite/renderer.c + +#define MAX_GLYPHSET 256 + +struct RenImage { + RenColor *pixels; + int width, height; +}; + +typedef struct { + RenImage *image; + stbtt_bakedchar glyphs[256]; +} GlyphSet; + +struct RenFont { + void *data; + stbtt_fontinfo stbfont; + GlyphSet *sets[MAX_GLYPHSET]; + float size; + int height; +}; + +static struct { int left, top, right, bottom; } lt_clip; + +static const char* codepoint_to_utf8(unsigned c) { //< @r-lyeh + static char s[4+1]; + lt_memset(s, 0, 5); + /**/ if (c < 0x80) s[0] = c, s[1] = 0; + else if (c < 0x800) s[0] = 0xC0 | ((c >> 6) & 0x1F), s[1] = 0x80 | ( c & 0x3F), s[2] = 0; + else if (c < 0x10000) s[0] = 0xE0 | ((c >> 12) & 0x0F), s[1] = 0x80 | ((c >> 6) & 0x3F), s[2] = 0x80 | ( c & 0x3F), s[3] = 0; + else if (c < 0x110000) s[0] = 0xF0 | ((c >> 18) & 0x07), s[1] = 0x80 | ((c >> 12) & 0x3F), s[2] = 0x80 | ((c >> 6) & 0x3F), s[3] = 0x80 | (c & 0x3F), s[4] = 0; + return s; +} +static const char* utf8_to_codepoint(const char *p, unsigned *dst) { + unsigned res, n; + switch (*p & 0xf0) { + case 0xf0 : res = *p & 0x07; n = 3; break; + case 0xe0 : res = *p & 0x0f; n = 2; break; + case 0xd0 : + case 0xc0 : res = *p & 0x1f; n = 1; break; + default : res = *p; n = 0; break; + } + while (n-- && *p++) { //< https://github.com/rxi/lite/issues/262 + res = (res << 6) | (*p & 0x3f); //< https://github.com/rxi/lite/issues/262 + } + *dst = res; + return p + 1; +} + +void ren_init(void *win) { + lt_surface *surf = lt_getsurface(lt_window()); + ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } ); +} + + +void ren_update_rects(RenRect *rects, int count) { + lt_updatesurfacerects(lt_getsurface(lt_window()), (lt_rect*) rects, count); +} + + +void ren_set_clip_rect(RenRect rect) { + lt_clip.left = rect.x; + lt_clip.top = rect.y; + lt_clip.right = rect.x + rect.width; + lt_clip.bottom = rect.y + rect.height; +} + + +void ren_get_size(int *x, int *y) { + lt_surface *surf = lt_getsurface(lt_window()); + *x = surf->w; + *y = surf->h; +} + + +RenImage* ren_new_image(int width, int height) { + lt_assert(width > 0 && height > 0); + RenImage *image = lt_malloc(sizeof(RenImage) + width * height * sizeof(RenColor)); + image->pixels = (void*) (image + 1); + image->width = width; + image->height = height; + return image; +} + + +void ren_free_image(RenImage *image) { + lt_free(image); +} + + +static GlyphSet* load_glyphset(RenFont *font, int idx) { + GlyphSet *set = lt_calloc(1, sizeof(GlyphSet)); + + /* init image */ + int width = 128; + int height = 128; +retry: + set->image = ren_new_image(width, height); + + /* load glyphs */ + float s = + stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) / + stbtt_ScaleForPixelHeight(&font->stbfont, 1); + int res = stbtt_BakeFontBitmap( + font->data, 0, font->size * s, (void*) set->image->pixels, + width, height, idx * 256, 256, set->glyphs); + + /* retry with a larger image buffer if the buffer wasn't large enough */ + if (res < 0) { + width *= 2; + height *= 2; + ren_free_image(set->image); + goto retry; + } + + /* adjust glyph yoffsets and xadvance */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size); + int scaled_ascent = ascent * scale + 0.5; + for (int i = 0; i < 256; i++) { + set->glyphs[i].yoff += scaled_ascent; + set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance); + } + + /* convert 8bit data to 32bit */ + for (int i = width * height - 1; i >= 0; i--) { + uint8_t n = *((uint8_t*) set->image->pixels + i); + set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n }; + } + + return set; +} + + +static GlyphSet* get_glyphset(RenFont *font, int codepoint) { + int idx = (codepoint >> 8) % MAX_GLYPHSET; + if (!font->sets[idx]) { + font->sets[idx] = load_glyphset(font, idx); + } + return font->sets[idx]; +} + + +RenFont* ren_load_font(const char *filename, float size) { + /* load font into buffer */ //< @r-lyeh: load font file before allocating `font` + char *fontdata = lt_load_file(filename, NULL); + if( !fontdata ) return NULL; + + RenFont *font = NULL; + + /* init font */ + font = lt_calloc(1, sizeof(RenFont)); + font->size = size; + font->data = fontdata; + + /* init stbfont */ + int ok = stbtt_InitFont(&font->stbfont, font->data, 0); + if (!ok) { + if (font) { lt_free(font->data); } + lt_free(font); + return NULL; + } + + /* get height and scale */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size); + font->height = (ascent - descent + linegap) * scale + 0.5; + + /* make tab and newline glyphs invisible */ + stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs; + g['\t'].x1 = g['\t'].x0; + g['\n'].x1 = g['\n'].x0; + + return font; +} + + +void ren_free_font(RenFont *font) { + for (int i = 0; i < MAX_GLYPHSET; i++) { + GlyphSet *set = font->sets[i]; + if (set) { + ren_free_image(set->image); + lt_free(set); + } + } + lt_free(font->data); + lt_free(font); +} + + +void ren_set_font_tab_width(RenFont *font, int n) { + GlyphSet *set = get_glyphset(font, '\t'); + set->glyphs['\t'].xadvance = n; +} + + +int ren_get_font_tab_width(RenFont *font) { + GlyphSet *set = get_glyphset(font, '\t'); + return set->glyphs['\t'].xadvance; +} + + +int ren_get_font_width(RenFont *font, const char *text) { + int x = 0; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + x += g->xadvance; + } + return x; +} + + +int ren_get_font_height(RenFont *font) { + return font->height; +} + + +static inline RenColor blend_pixel(RenColor dst, RenColor src) { + int ia = 0xff - src.a; + dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8; + dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8; + dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8; + return dst; +} + + +static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) { + src.a = (src.a * color.a) >> 8; + int ia = 0xff - src.a; + dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8); + dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8); + dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8); + return dst; +} + + +#define rect_draw_loop(expr) \ + for (int j = y1; j < y2; j++) { \ + for (int i = x1; i < x2; i++) { \ + *d = expr; \ + d++; \ + } \ + d += dr; \ + } + +void ren_draw_rect(RenRect rect, RenColor color) { + if (color.a == 0) { return; } + + int x1 = rect.x < lt_clip.left ? lt_clip.left : rect.x; + int y1 = rect.y < lt_clip.top ? lt_clip.top : rect.y; + int x2 = rect.x + rect.width; + int y2 = rect.y + rect.height; + x2 = x2 > lt_clip.right ? lt_clip.right : x2; + y2 = y2 > lt_clip.bottom ? lt_clip.bottom : y2; + + lt_surface *surf = lt_getsurface(lt_window()); + RenColor *d = (RenColor*) surf->pixels; + d += x1 + y1 * surf->w; + int dr = surf->w - (x2 - x1); + + if (color.a == 0xff) { + rect_draw_loop(color); + } else { + rect_draw_loop(blend_pixel(*d, color)); + } +} + + +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) { + if (color.a == 0) { return; } + + /* clip */ + int n; + if ((n = lt_clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; } + if ((n = lt_clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; } + if ((n = x + sub->width - lt_clip.right ) > 0) { sub->width -= n; } + if ((n = y + sub->height - lt_clip.bottom) > 0) { sub->height -= n; } + + if (sub->width <= 0 || sub->height <= 0) { + return; + } + + /* draw */ + lt_surface *surf = lt_getsurface(lt_window()); + RenColor *s = image->pixels; + RenColor *d = (RenColor*) surf->pixels; + s += sub->x + sub->y * image->width; + d += x + y * surf->w; + int sr = image->width - sub->width; + int dr = surf->w - sub->width; + + for (int j = 0; j < sub->height; j++) { + for (int i = 0; i < sub->width; i++) { + *d = blend_pixel2(*d, *s, color); + d++; + s++; + } + d += dr; + s += sr; + } +} + + +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + rect.x = g->x0; + rect.y = g->y0; + rect.width = g->x1 - g->x0; + rect.height = g->y1 - g->y0; + ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color); + x += g->xadvance; + } + return x; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_font.c + +static int f_load(lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + float size = luaL_checknumber(L, 2); + RenFont **self = lua_newuserdata(L, sizeof(*self)); + luaL_setmetatable(L, API_TYPE_FONT); + *self = ren_load_font(filename, size); + if (!*self) { luaL_error(L, "failed to load font"); } + return 1; +} + + +static int f_set_tab_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + int n = luaL_checknumber(L, 2); + ren_set_font_tab_width(*self, n); + return 0; +} + + +static int f_GC(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + if (*self) { rencache_free_font(*self); } + return 0; +} + + +static int f_get_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + lua_pushnumber(L, ren_get_font_width(*self, text) ); + return 1; +} + + +static int f_get_height(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + lua_pushnumber(L, ren_get_font_height(*self) ); + return 1; +} + + +int luaopen_renderer_font(lua_State *L) { + static const luaL_Reg lib[] = { + { "__gc", f_GC }, + { "load", f_load }, + { "set_tab_width", f_set_tab_width }, + { "get_width", f_get_width }, + { "get_height", f_get_height }, + { NULL, NULL } + }; + luaL_newmetatable(L, API_TYPE_FONT); + luaL_setfuncs(L, lib, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_api.c + +static RenColor checkcolor(lua_State *L, int idx, int def) { + RenColor color; + if (lua_isnoneornil(L, idx)) { + return (RenColor) { def, def, def, 255 }; + } + lua_rawgeti(L, idx, 1); + lua_rawgeti(L, idx, 2); + lua_rawgeti(L, idx, 3); + lua_rawgeti(L, idx, 4); + color.r = luaL_checknumber(L, -4); + color.g = luaL_checknumber(L, -3); + color.b = luaL_checknumber(L, -2); + color.a = luaL_optnumber(L, -1, 255); + lua_pop(L, 4); + return color; +} + + +static int f_show_debug(lua_State *L) { + luaL_checkany(L, 1); + rencache_show_debug(lua_toboolean(L, 1)); + return 0; +} + + +static int f_get_size(lua_State *L) { + int w, h; + ren_get_size(&w, &h); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + return 2; +} + + +static int f_begin_frame(lua_State *L) { + rencache_begin_frame(); + return 0; +} + + +static int f_end_frame(lua_State *L) { + rencache_end_frame(); + return 0; +} + + +static int f_set_clip_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + rencache_set_clip_rect(rect); + return 0; +} + + +static int f_draw_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + rencache_draw_rect(rect, color); + return 0; +} + + +static int f_draw_text(lua_State *L) { + RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + int x = luaL_checknumber(L, 3); + int y = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + x = rencache_draw_text(*font, text, x, y, color); + lua_pushnumber(L, x); + return 1; +} + +int luaopen_renderer(lua_State *L) { + static const luaL_Reg lib[] = { + { "show_debug", f_show_debug }, + { "get_size", f_get_size }, + { "begin_frame", f_begin_frame }, + { "end_frame", f_end_frame }, + { "set_clip_rect", f_set_clip_rect }, + { "draw_rect", f_draw_rect }, + { "draw_text", f_draw_text }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + luaopen_renderer_font(L); + lua_setfield(L, -2, "font"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/rencache.c + +/* a cache over the software renderer -- all drawing operations are stored as +** commands when issued. At the end of the frame we write the commands to a grid +** of hash values, take the cells that have changed since the previous frame, +** merge them into dirty rectangles and redraw only those regions */ + +#define CELLS_X 80 +#define CELLS_Y 50 +#define CELL_SIZE 96 +#define COMMAND_BUF_SIZE (1024 * 512) + +enum { FREE_FONT, SET_CLIP, DRAW_TEXT, DRAW_RECT }; + +typedef struct { + int type, size; + RenRect rect; + RenColor color; + RenFont *font; + int tab_width; + char text[0]; +} Command; + + +static unsigned cells_buf1[CELLS_X * CELLS_Y]; +static unsigned cells_buf2[CELLS_X * CELLS_Y]; +static unsigned *cells_prev = cells_buf1; +static unsigned *cells = cells_buf2; +static RenRect rect_buf[CELLS_X * CELLS_Y / 2]; +static char command_buf[COMMAND_BUF_SIZE]; +static int command_buf_idx; +static RenRect screen_rect; +static bool show_debug; + + +/* 32bit fnv-1a hash */ +#define HASH_INITIAL 2166136261 + +static void hash(unsigned *h, const void *data, int size) { + const unsigned char *p = data; + while (size--) { + *h = (*h ^ *p++) * 16777619; + } +} + + +static inline int cell_idx(int x, int y) { + return x + y * CELLS_X; +} + + +static inline bool rects_overlap(RenRect a, RenRect b) { + return b.x + b.width >= a.x && b.x <= a.x + a.width + && b.y + b.height >= a.y && b.y <= a.y + a.height; +} + + +static RenRect intersect_rects(RenRect a, RenRect b) { + int x1 = maxi(a.x, b.x); + int y1 = maxi(a.y, b.y); + int x2 = mini(a.x + a.width, b.x + b.width); + int y2 = mini(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, max(0, x2 - x1), max(0, y2 - y1) }; +} + + +static RenRect merge_rects(RenRect a, RenRect b) { + int x1 = mini(a.x, b.x); + int y1 = mini(a.y, b.y); + int x2 = maxi(a.x + a.width, b.x + b.width); + int y2 = maxi(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, x2 - x1, y2 - y1 }; +} + + +static Command* push_command(int type, int size) { + size_t alignment = 7; // alignof(max_align_t) - 1; //< C11 https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + size = (size + alignment) & ~alignment; //< https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + Command *cmd = (Command*) (command_buf + command_buf_idx); + int n = command_buf_idx + size; + if (n > COMMAND_BUF_SIZE) { + fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n"); + return NULL; + } + command_buf_idx = n; + lt_memset(cmd, 0, sizeof(Command)); + cmd->type = type; + cmd->size = size; + return cmd; +} + + +static bool next_command(Command **prev) { + if (*prev == NULL) { + *prev = (Command*) command_buf; + } else { + *prev = (Command*) (((char*) *prev) + (*prev)->size); + } + return *prev != ((Command*) (command_buf + command_buf_idx)); +} + + +void rencache_show_debug(bool enable) { + show_debug = enable; +} + + +void rencache_free_font(RenFont *font) { + Command *cmd = push_command(FREE_FONT, sizeof(Command)); + if (cmd) { cmd->font = font; } +} + + +void rencache_set_clip_rect(RenRect rect) { + Command *cmd = push_command(SET_CLIP, sizeof(Command)); + if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); } +} + + +void rencache_draw_rect(RenRect rect, RenColor color) { + if (!rects_overlap(screen_rect, rect)) { return; } + Command *cmd = push_command(DRAW_RECT, sizeof(Command)); + if (cmd) { + cmd->rect = rect; + cmd->color = color; + } +} + + +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + rect.x = x; + rect.y = y; + rect.width = ren_get_font_width(font, text); + rect.height = ren_get_font_height(font); + + if (rects_overlap(screen_rect, rect)) { + int sz = strlen(text) + 1; + Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz); + if (cmd) { + memcpy(cmd->text, text, sz); + cmd->color = color; + cmd->font = font; + cmd->rect = rect; + cmd->tab_width = ren_get_font_tab_width(font); + } + } + + return x + rect.width; +} + + +void rencache_invalidate(void) { + lt_memset(cells_prev, 0xff, sizeof(cells_buf1)); +} + + +void rencache_begin_frame(void) { + /* reset all cells if the screen width/height has changed */ + int w, h; + ren_get_size(&w, &h); + if (screen_rect.width != w || h != screen_rect.height) { + screen_rect.width = w; + screen_rect.height = h; + rencache_invalidate(); + } +} + + +static void update_overlapping_cells(RenRect r, unsigned h) { + int x1 = r.x / CELL_SIZE; + int y1 = r.y / CELL_SIZE; + int x2 = (r.x + r.width) / CELL_SIZE; + int y2 = (r.y + r.height) / CELL_SIZE; + + for (int y = y1; y <= y2; y++) { + for (int x = x1; x <= x2; x++) { + int idx = cell_idx(x, y); + hash(&cells[idx], &h, sizeof(h)); + } + } +} + + +static void push_rect(RenRect r, int *count) { + /* try to merge with existing rectangle */ + for (int i = *count - 1; i >= 0; i--) { + RenRect *rp = &rect_buf[i]; + if (rects_overlap(*rp, r)) { + *rp = merge_rects(*rp, r); + return; + } + } + /* couldn't merge with previous rectangle: push */ + rect_buf[(*count)++] = r; +} + + +void rencache_end_frame(void) { + /* update cells from commands */ + Command *cmd = NULL; + RenRect cr = screen_rect; + while (next_command(&cmd)) { + if (cmd->type == SET_CLIP) { cr = cmd->rect; } + RenRect r = intersect_rects(cmd->rect, cr); + if (r.width == 0 || r.height == 0) { continue; } + unsigned h = HASH_INITIAL; + hash(&h, cmd, cmd->size); + update_overlapping_cells(r, h); + } + + /* push rects for all cells changed from last frame, reset cells */ + int rect_count = 0; + int max_x = screen_rect.width / CELL_SIZE + 1; + int max_y = screen_rect.height / CELL_SIZE + 1; + for (int y = 0; y < max_y; y++) { + for (int x = 0; x < max_x; x++) { + /* compare previous and current cell for change */ + int idx = cell_idx(x, y); + if (cells[idx] != cells_prev[idx]) { + push_rect((RenRect) { x, y, 1, 1 }, &rect_count); + } + cells_prev[idx] = HASH_INITIAL; + } + } + + /* expand rects from cells to pixels */ + for (int i = 0; i < rect_count; i++) { + RenRect *r = &rect_buf[i]; + r->x *= CELL_SIZE; + r->y *= CELL_SIZE; + r->width *= CELL_SIZE; + r->height *= CELL_SIZE; + *r = intersect_rects(*r, screen_rect); + } + + /* redraw updated regions */ + bool has_free_commands = false; + for (int i = 0; i < rect_count; i++) { + /* draw */ + RenRect r = rect_buf[i]; + ren_set_clip_rect(r); + + cmd = NULL; + while (next_command(&cmd)) { + switch (cmd->type) { + case FREE_FONT: + has_free_commands = true; + break; + case SET_CLIP: + ren_set_clip_rect(intersect_rects(cmd->rect, r)); + break; + case DRAW_RECT: + ren_draw_rect(cmd->rect, cmd->color); + break; + case DRAW_TEXT: + ren_set_font_tab_width(cmd->font, cmd->tab_width); + ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color); + break; + } + } + + if (show_debug) { + RenColor color = { rand(), rand(), rand(), 50 }; + ren_draw_rect(r, color); + } + } + + /* update dirty rects */ + if (rect_count > 0) { + ren_update_rects(rect_buf, rect_count); + } + + /* free fonts */ + if (has_free_commands) { + cmd = NULL; + while (next_command(&cmd)) { + if (cmd->type == FREE_FONT) { + ren_free_font(cmd->font); + } + } + } + + /* swap cell buffer and reset */ + unsigned *tmp = cells; + cells = cells_prev; + cells_prev = tmp; + command_buf_idx = 0; +} + +// ---------------------------------------------------------------------------- +// lite/system.c + +static int f_set_cursor(lua_State *L) { + static const char *cursor_opts[] = { + "arrow", + "ibeam", + "sizeh", + "sizev", + "hand", + NULL + }; + int n = luaL_checkoption(L, 1, "arrow", cursor_opts); + lt_setcursor(n); + return 0; +} + +static int f_set_window_title(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + lt_setwindowtitle(title); + return 0; +} +static int f_set_window_mode(lua_State *L) { + static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 }; + enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN }; + int n = luaL_checkoption(L, 1, "normal", window_opts); + lt_setwindowmode(n); + return 0; +} +static int f_window_has_focus(lua_State *L) { + unsigned flags = lt_haswindowfocus(); + lua_pushboolean(L, flags); + return 1; +} + +static int f_show_confirm_dialog(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + const char *msg = luaL_checkstring(L, 2); + int id = lt_prompt(msg, title); // 0:no, 1:yes + lua_pushboolean(L, !!id); + return 1; +} + +static int f_chdir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + int err = chdir(path); + if (err) { luaL_error(L, "chdir() failed"); } + return 0; +} +static int f_list_dir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + lua_newtable(L); + lt_globpath(L, path); + return 1; +} +static int f_absolute_path(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + char *res = lt_realpath(path, NULL); + if (!res) { return 0; } + lua_pushstring(L, res); + lt_realpath_free(res); + return 1; +} +static int f_get_file_info(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + struct stat s; + int err = stat(path, &s); + if (err < 0) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; + } + + lua_newtable(L); + lua_pushnumber(L, s.st_mtime); + lua_setfield(L, -2, "modified"); + + lua_pushnumber(L, s.st_size); + lua_setfield(L, -2, "size"); + + if (S_ISREG(s.st_mode)) { + lua_pushstring(L, "file"); + } else if (S_ISDIR(s.st_mode)) { + lua_pushstring(L, "dir"); + } else { + lua_pushnil(L); + } + lua_setfield(L, -2, "type"); + + return 1; +} + + +static int f_get_clipboard(lua_State *L) { + const char *text = lt_getclipboard(lt_window()); + if (!text) { return 0; } + lua_pushstring(L, text); + return 1; +} +static int f_set_clipboard(lua_State *L) { + const char *text = luaL_checkstring(L, 1); + lt_setclipboard(lt_window(), text); + return 0; +} + + +static int f_get_time(lua_State *L) { + double ss = lt_time_ms() / 1000.0; + lua_pushnumber(L, ss); + return 1; +} +static int f_sleep(lua_State *L) { + double ss = luaL_checknumber(L, 1); + lt_sleep_ms(ss * 1000); + return 0; +} + + +static int f_exec(lua_State *L) { + size_t len; + const char *cmd = luaL_checklstring(L, 1, &len); + char *buf = lt_malloc(len + 32); + if (!buf) { luaL_error(L, "buffer allocation failed"); } +#if _WIN32 + sprintf(buf, "cmd /c \"%s\"", cmd); + WinExec(buf, SW_HIDE); +#else + sprintf(buf, "%s &", cmd); + int res = system(buf); +#endif + lt_free(buf); + return 0; +} + + +static int f_fuzzy_match(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + const char *ptn = luaL_checkstring(L, 2); + int score = 0; + int run = 0; + + while (*str && *ptn) { + while (*str == ' ') { str++; } + while (*ptn == ' ') { ptn++; } + if (tolower(*str) == tolower(*ptn)) { + score += run * 10 - (*str != *ptn); + run++; + ptn++; + } else { + score -= 10; + run = 0; + } + str++; + } + if (*ptn) { return 0; } + + lua_pushnumber(L, score - (int) strlen(str)); + return 1; +} + +static int f_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = lt_poll_event(L); + return rc; +} + +int luaopen_system(lua_State *L) { + static const luaL_Reg lib[] = { + { "poll_event", f_poll_event }, + { "set_cursor", f_set_cursor }, + { "set_window_title", f_set_window_title }, + { "set_window_mode", f_set_window_mode }, + { "window_has_focus", f_window_has_focus }, + { "show_confirm_dialog", f_show_confirm_dialog }, + { "chdir", f_chdir }, + { "list_dir", f_list_dir }, + { "absolute_path", f_absolute_path }, + { "get_file_info", f_get_file_info }, + { "get_clipboard", f_get_clipboard }, + { "set_clipboard", f_set_clipboard }, + { "get_time", f_get_time }, + { "sleep", f_sleep }, + { "exec", f_exec }, + { "fuzzy_match", f_fuzzy_match }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/api/api.c + +void api_load_libs(lua_State *L) { + static const luaL_Reg libs[] = { + { "system", luaopen_system }, + { "renderer", luaopen_renderer }, + { NULL, NULL } + }; + for (int i = 0; libs[i].name; i++) { + luaL_requiref(L, libs[i].name, libs[i].func, 1); + } +} + +// ---------------------------------------------------------------------------- +// lite/main.c + +void lt_init(lua_State *L, void *handle, const char *pathdata, int argc, char **argv, float scale, const char *platform, const char *pathexe) { + // setup renderer + ren_init(handle); + + // setup lua context + api_load_libs(L); + + lua_newtable(L); + for (int i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setglobal(L, "ARGS"); + + lua_pushstring(L, "1.11"); + lua_setglobal(L, "VERSION"); + + lua_pushstring(L, platform); + lua_setglobal(L, "PLATFORM"); + + lua_pushnumber(L, scale); + lua_setglobal(L, "SCALE"); + + lua_pushstring(L, pathdata); + lua_setglobal(L, "DATADIR"); + + lua_pushstring(L, pathexe); + lua_setglobal(L, "EXEFILE"); + + // init lite + luaL_dostring(L, "core = {}"); + luaL_dostring(L, + "xpcall(function()\n" + " SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n" + " PATHSEP = package.config:sub(1, 1)\n" + " EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n" + " USERDIR = EXEDIR .. 'data/user/'\n" + " package.path = EXEDIR .. '/data/?.lua;' .. package.path\n" + " package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n" + " core = require('core')\n" + " core.init()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} +void lt_tick(struct lua_State *L) { + luaL_dostring(L, + "xpcall(function()\n" + " core.run1()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} +#line 0 + #endif // V4K_3RD /* game framework. * - rlyeh, public domain @@ -334170,7 +347747,7 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft //----------------------------------------------------------------------------- // C files -#line 1 "engine/split/v4k_begin.c" +#line 1 "v4k_begin.c" #define do_threadlock(mutexptr) \ for( int init_ = !!(mutexptr) || (thread_mutex_init( (mutexptr) = CALLOC(1, sizeof(thread_mutex_t)) ), 1); init_; init_ = 0) \ for( int lock_ = (thread_mutex_lock( mutexptr ), 1); lock_; lock_ = (thread_mutex_unlock( mutexptr ), 0) ) @@ -334179,7 +347756,7 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft ((struct nk_color){ ((color>>0))&255,((color>>8))&255,((color>>16))&255,((color>>24))&255 }) #line 0 -#line 1 "engine/split/v4k_ds.c" +#line 1 "v4k_ds.c" // ----------------------------------------------------------------------------- // sort/less @@ -334569,7 +348146,7 @@ void (set_free)(set* m) { } #line 0 -#line 1 "engine/split/v4k_string.c" +#line 1 "v4k_string.c" #include char* tempvl(const char *fmt, va_list vl) { @@ -334990,9 +348567,158 @@ AUTORUN { test( !strcmp("Hello happy world.", buf) ); } #endif + +// ---------------------------------------------------------------------------- +// localization kit + +static const char *kit_lang = "enUS", *kit_langs = + "enUS,enGB," + "frFR," + "esES,esAR,esMX," + "deDE,deCH,deAT," + "itIT,itCH," + "ptBR,ptPT," + "zhCN,zhSG,zhTW,zhHK,zhMO," + "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," + "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" +; + +static map(char*,char*) kit_ids; +static map(char*,char*) kit_vars; + +#ifndef KIT_FMT_ID2 +#define KIT_FMT_ID2 "%s.%s" +#endif + +void kit_init() { + do_once map_init(kit_ids, less_str, hash_str); + do_once map_init(kit_vars, less_str, hash_str); +} + +void kit_insert( const char *id, const char *translation) { + char *id2 = va(KIT_FMT_ID2, kit_lang, id); + + char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); + if(*found) FREE(*found); + *found = STRDUP(translation); +} + +bool kit_merge( const char *filename ) { + // @todo: xlsx2ini + return false; +} + +void kit_clear() { + map_clear(kit_ids); +} + +bool kit_load( const char *filename ) { + return kit_clear(), kit_merge( filename ); +} + +void kit_set( const char *key, const char *value ) { + value = value && value[0] ? value : ""; + + char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); + if(*found) FREE(*found); + *found = STRDUP(value); +} + +void kit_reset() { + map_clear(kit_vars); +} + +char *kit_translate2( const char *id, const char *lang ) { + char *id2 = va(KIT_FMT_ID2, lang, id); + + char **found = map_find(kit_ids, id2); + + // return original [[ID]] if no translation is found + if( !found ) return va("[[%s]]", id); + + // return translation if no {{moustaches}} are found + if( !strstr(*found, "{{") ) return *found; + + // else replace all found {{moustaches}} with context vars + { + // make room + static __thread char *results[16] = {0}; + static __thread unsigned counter = 0; counter = (counter+1) % 16; + + char *buffer = results[ counter ]; + if( buffer ) FREE(buffer), buffer = 0; + + // iterate moustaches + const char *begin, *end, *text = *found; + while( NULL != (begin = strstr(text, "{{")) ) { + end = strstr(begin+2, "}}"); + if( end ) { + char *var = va("%.*s", (int)(end - (begin+2)), begin+2); + char **found_var = map_find(kit_vars, var); + + if( found_var && 0[*found_var] ) { + strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); + } else { + strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); + } + + text = end+2; + } else { + strcatf(&buffer, "%.*s", (int)(begin - text), text); + + text = begin+2; + } + } + + strcatf(&buffer, "%s", text); + return buffer; + } +} + +char *kit_translate( const char *id ) { + return kit_translate2( id, kit_lang ); +} + +void kit_locale( const char *lang ) { + kit_lang = STRDUP(lang); // @leak +} + +void kit_dump_state( FILE *fp ) { + for each_map(kit_ids, char *, k, char *, v) { + fprintf(fp, "[ID ] %s=%s\n", k, v); + } + for each_map(kit_vars, char *, k, char *, v) { + fprintf(fp, "[VAR] %s=%s\n", k, v); + } +} + +/* +int main() { + kit_init(); + + kit_locale("enUS"); + kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Nice to meet you."); + + kit_locale("esES"); + kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Un placer conoceros."); + + kit_locale("enUS"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. + + kit_locale("esES"); + kit_set("PLAYER1", "John"); + kit_set("PLAYER2", "Karl"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. + + assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] + assert(~puts("Ok")); +} +*/ #line 0 -#line 1 "engine/split/v4k_compat.c" +#line 1 "v4k_compat.c" //----------------------------------------------------------------------------- // compat (unix & stdio.h) @@ -335111,7 +348837,7 @@ static void v4k_pre_init(); static void v4k_post_init(float); #line 0 -#line 1 "engine/split/v4k_ui.c" +#line 1 "v4k_ui.c" // ---------------------------------------------------------------------------------------- // ui extensions first @@ -337015,8 +350741,8 @@ int ui_color4f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3] }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), clampf(color[3],0,1) }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), clampf(after.a,0,1) }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -337103,8 +350829,8 @@ int ui_color3f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, ui_alpha }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), 1 }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), ui_alpha }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -337147,7 +350873,7 @@ int ui_color3(const char *label, unsigned *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { r*ui_alpha, g*ui_alpha, b*ui_alpha, 1 }, before = after; + struct nk_colorf after = { r*ui_alpha/255, g*ui_alpha/255, b*ui_alpha/255, ui_alpha }, before = after; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(after), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -337809,8 +351535,10 @@ int ui_demo(int do_windows) { static float float2[2] = {1,2}; static float float3[3] = {1,2,3}; static float float4[4] = {1,2,3,4}; - static float rgb[3] = {0.84,0.67,0.17}; - static float rgba[4] = {0.67,0.90,0.12,1}; + static float rgbf[3] = {0.84,0.67,0.17}; + static float rgbaf[4] = {0.67,0.90,0.12,1}; + static unsigned rgb = CYAN; + static unsigned rgba = PINK; static float slider = 0.5f; static float slider2 = 0.5f; static char string[64] = "hello world 123"; @@ -337854,8 +351582,10 @@ int ui_demo(int do_windows) { if( ui_list("my list", list, 3, &item ) ) puts("list changed"); if( ui_section("Colors")) {} - if( ui_color3f("my color3", rgb) ) puts("color3 changed"); - if( ui_color4f("my color4@this is a tooltip", rgba) ) puts("color4 changed"); + if( ui_color3("my color3", &rgb) ) puts("color3 changed"); + if( ui_color4("my color4@this is a tooltip", &rgba) ) puts("color4 changed"); + if( ui_color3f("my color3f", rgbf) ) puts("color3f changed"); + if( ui_color4f("my color4f@this is a tooltip", rgbaf) ) puts("color4f changed"); if( ui_section("Sliders")) {} if( ui_slider("my slider", &slider)) puts("slider changed"); @@ -337968,7 +351698,7 @@ int ui_demo(int do_windows) { #line 0 -#line 1 "engine/split/v4k_audio.c" +#line 1 "v4k_audio.c" // @fixme: really shutdown audio & related threads before quitting. ma_dr_wav crashes. @@ -338561,7 +352291,7 @@ int ui_audio() { } #line 0 -#line 1 "engine/split/v4k_collide.c" +#line 1 "v4k_collide.c" /* poly */ poly poly_alloc(int cnt) { poly p = {0}; @@ -339989,7 +353719,7 @@ void collide_demo() { // debug draw collisions // @fixme: fix leaks: poly_free() } #line 0 -#line 1 "engine/split/v4k_cook.c" +#line 1 "v4k_cook.c" // data pipeline // - rlyeh, public domain. // ---------------------------------------------------------------------------- @@ -340003,7 +353733,7 @@ void collide_demo() { // debug draw collisions // @fixme: fix leaks: poly_free() const char *ART = "art/"; const char *TOOLS = "tools/bin/"; -const char *EDITOR = "tools/editor/"; +const char *EDITOR = "tools/"; const char *COOK_INI = "tools/cook.ini"; static unsigned ART_SKIP_ROOT; // number of chars to skip the base root in ART folder @@ -340500,11 +354230,14 @@ int cook(void *userdata) { fclose(in); } +// if(array_count(uncooked)) +// PRINTF("cook_jobs[%d]=%d\n", job->threadid, array_count(uncooked)); + // generate cook metrics. you usually do `game.exe --cook-stats && (type *.csv | sort /R > cook.csv)` static __thread FILE *statsfile = 0; if(flag("--cook-stats")) fseek(statsfile = fopen(va("cook%d.csv",job->threadid), "a+t"), 0L, SEEK_END); - if(statsfile && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); + if(statsfile && !job->threadid && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); // added or changed files for( int i = 0, end = array_count(uncooked); i < end && !cook_cancelling; ++i ) { @@ -340817,10 +354550,8 @@ void cook_stop() { int cook_progress() { int count = 0, sum = 0; for( int i = 0, end = cook_jobs(); i < end; ++i ) { -// if( jobs[i].progress >= 0 ) { sum += jobs[i].progress; ++count; -// } } return cook_jobs() ? sum / (count+!count) : 100; } @@ -340848,7 +354579,7 @@ bool have_tools() { } #line 0 -#line 1 "engine/split/v4k_data.c" +#line 1 "v4k_data.c" static array(json5) roots; static array(char*) sources; @@ -341078,7 +354809,7 @@ bool data_tests() { } #line 0 -#line 1 "engine/split/v4k_extend.c" +#line 1 "v4k_extend.c" // dll ------------------------------------------------------------------------ /* deprecated @@ -341369,7 +355100,7 @@ void *script_init_env(unsigned flags) { } #line 0 -#line 1 "engine/split/v4k_file.c" +#line 1 "v4k_file.c" // ----------------------------------------------------------------------------- // file @@ -342256,7 +355987,7 @@ if( found && *found == 0 ) { char *cmd = va("%scook" ifdef(osx,".osx",ifdef(linux,".linux",".exe"))" %s %s --cook-ini=%s --cook-additive --cook-jobs=1 --quiet", TOOLS, group1, group2, COOK_INI); // cook groups - int rc = atoi(app_exec(cmd)); + int rc = system(cmd); // atoi(app_exec(cmd)); if(rc < 0) PANIC("cannot invoke `%scook` (return code %d)", TOOLS, rc); vfs_reload(); // @todo: optimize me. it is waaay inefficent to reload the whole VFS layout after cooking a single asset @@ -342522,7 +356253,7 @@ bool ini_write(const char *filename, const char *section, const char *key, const #line 0 -#line 1 "engine/split/v4k_font.c" +#line 1 "v4k_font.c" // font framework. original code by Vassvik (UNLICENSED) // - rlyeh, public domain. // @@ -344876,7 +358607,7 @@ vec2 font_rect(const char *str) { } #line 0 -#line 1 "engine/split/v4k_input.c" +#line 1 "v4k_input.c" // input framework // - rlyeh, public domain // @@ -345641,7 +359372,7 @@ int ui_gamepads() { } #line 0 -#line 1 "engine/split/v4k_math.c" +#line 1 "v4k_math.c" // ----------------------------------------------------------------------------- // math framework: rand, ease, vec2, vec3, vec4, quat, mat2, mat33, mat34, mat4 // - rlyeh, public domain @@ -346521,7 +360252,7 @@ AUTORUN { } #line 0 -#line 1 "engine/split/v4k_memory.c" +#line 1 "v4k_memory.c" size_t dlmalloc_usable_size(void*); // __ANDROID_API__ #if is(bsd) || is(osx) // bsd or osx @@ -346530,9 +360261,10 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ # include #endif -#ifndef SYS_REALLOC -#define SYS_REALLOC realloc -#define SYS_MSIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ +#ifndef SYS_MEM_INIT +#define SYS_MEM_INIT() +#define SYS_MEM_REALLOC realloc +#define SYS_MEM_SIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ ifdef(osx, malloc_size, ifdef(bsd, malloc_size, \ ifdef(win32, _msize, malloc_usable_size))) #endif @@ -346542,10 +360274,12 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ static __thread uint64_t xstats_current = 0, xstats_total = 0, xstats_allocs = 0; void* xrealloc(void* oldptr, size_t size) { + static __thread int once = 0; for(;!once;once = 1) SYS_MEM_INIT(); + // for stats size_t oldsize = xsize(oldptr); - void *ptr = SYS_REALLOC(oldptr, size); + void *ptr = SYS_MEM_REALLOC(oldptr, size); if( !ptr && size ) { PANIC("Not memory enough (trying to allocate %u bytes)", (unsigned)size); } @@ -346570,7 +360304,7 @@ void* xrealloc(void* oldptr, size_t size) { return ptr; } size_t xsize(void* p) { - if( p ) return SYS_MSIZE(p); + if( p ) return SYS_MEM_SIZE(p); return 0; } char *xstats(void) { @@ -346622,7 +360356,7 @@ void* forget( void *ptr ) { } #line 0 -#line 1 "engine/split/v4k_network.c" +#line 1 "v4k_network.c" #if is(tcc) && is(win32) // @fixme: https lib is broken with tcc. replaced with InternetReadFile() api for now @@ -346919,7 +360653,7 @@ static void network_init() { } #line 0 -#line 1 "engine/split/v4k_track.c" +#line 1 "v4k_track.c" static __thread int track__sock = -1; //~ Lifecycle methods @@ -347056,7 +360790,7 @@ int track_event_props(char const *event_id, char const *user_id, const track_pro #undef TRACK__APPEND_SAFE_EX #line 0 -#line 1 "engine/split/v4k_netsync.c" +#line 1 "v4k_netsync.c" typedef void* (*rpc_function)(); typedef struct rpc_call { @@ -347742,7 +361476,7 @@ void network_rpc_send(unsigned id, const char *cmdline) { } #line 0 -#line 1 "engine/split/v4k_pack.c" +#line 1 "v4k_pack.c" // ----------------------------------------------------------------------------- // semantic versioning in a single byte (octal) // - rlyeh, public domain. @@ -350115,7 +363849,7 @@ AUTORUN { #endif #line 0 -#line 1 "engine/split/v4k_reflect.c" +#line 1 "v4k_reflect.c" // C reflection: enums, functions, structs, members and anotations. // - rlyeh, public domain // @@ -350309,7 +364043,7 @@ AUTOTEST { } #line 0 -#line 1 "engine/split/v4k_render.c" +#line 1 "v4k_render.c" // ----------------------------------------------------------------------------- // opengl @@ -351741,1110 +365475,6 @@ void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } -// ---------------------------------------------------------------------------- -// sprites - -typedef struct sprite_t { - float px, py, pz; // origin x, y, depth - float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree - float sx, sy; // scale x,y - uint32_t rgba; // vertex color - float cellw, cellh; // dimensions of any cell in spritesheet - - union { - struct { - int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet - }; - struct { - float x, y, w, h; // normalized[0..1] within texture bounds - }; - }; -} sprite_t; - -// sprite batching -typedef struct batch_t { array(sprite_t) sprites; mesh_t mesh; int dirty; } batch_t; -typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon - -// sprite stream -typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; -typedef struct sprite_index { GLuint triangle[3]; } sprite_index; - -#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) -#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) - -// sprite impl -static int sprite_count = 0; -static int sprite_program = -1; -static array(sprite_index) sprite_indices = 0; -static array(sprite_vertex) sprite_vertices = 0; -static batch_group_t sprite_additive_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_translucent_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_00_translucent_group = {0}; // (0,0) centered - -void sprite( texture_t texture, float position[3], float rotation, uint32_t color ) { - float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; - sprite_sheet( texture, spritesheet, position, rotation, offset, scale, 0, color, false ); -} - -// rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scalex,scaley), rotation (degrees), color (rgba) -void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba) { - // do not queue if either alpha or scale is zero - if( 0 == (pos.z * pos.w * ((tint_rgba>>24) & 255)) ) return; - - sprite_t s = {0}; - - s.px = pos.x, s.py = pos.y, s.pz = zindex; - s.sx = pos.z, s.sy = pos.w; - - s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; - s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; - - s.rgba = tint_rgba; - s.ox = 0/*ox*/ * s.sx; - s.oy = 0/*oy*/ * s.sy; - if( tilt_deg ) { - tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); - s.cos = cosf(tilt_deg); - s.sin = sinf(tilt_deg); - } else { - s.cos = 1; - s.sin = 0; - } - - batch_group_t *batches = &sprite_00_translucent_group; - batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); - - array_push(found->sprites, s); -} - -void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant) { - const float px = position[0], py = position[1], pz = position[2]; - const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; - const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; - - if (frame < 0) return; - if (frame > 0 && frame >= (xcells * ycells)) return; - - // no need to queue if alpha or scale are zero - if( sx && sy && alpha(rgba) ) { - vec3 bak = camera_get_active()->position; - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - } - - sprite_t s; - s.px = px; - s.py = py; - s.pz = pz; - s.frame = frame; - s.ncx = xcells ? xcells : 1; - s.ncy = ycells ? ycells : 1; - s.sx = sx; - s.sy = sy; - s.ox = ox * sx; - s.oy = oy * sy; - s.cellw = (texture.x * sx / s.ncx); - s.cellh = (texture.y * sy / s.ncy); - s.rgba = rgba; - s.cos = 1; - s.sin = 0; - if(rotation) { - rotation = (rotation + 0) * ((float)C_PI / 180); - s.cos = cosf(rotation); - s.sin = sinf(rotation); - } - - batch_group_t *batches = is_additive ? &sprite_additive_group : &sprite_translucent_group; -#if 0 - batch_t *found = map_find(*batches, texture.id); - if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); -#else - batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); -#endif - - array_push(found->sprites, s); - - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = bak; - } - } -} - -static void sprite_rebuild_meshes() { - sprite_count = 0; - - batch_group_t* list[] = { &sprite_additive_group, &sprite_translucent_group }; - for( int l = 0; l < countof(list); ++l) { - for each_map_ptr(*list[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float cx = (1.0f / it->ncx) - 1e-9f; - float cy = (1.0f / it->ncy) - 1e-9f; - int idx = (int)it->frame; - int px = idx % it->ncx; - int py = idx / it->ncx; - - float ux = px * cx, uy = py * cy; - float vx = ux + cx, vy = uy + cy; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } - - batch_group_t* list2[] = { &sprite_00_translucent_group }; - for( int l = 0; l < countof(list2); ++l) { - for each_map_ptr(*list2[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float ux = it->x, vx = ux + it->w; - float uy = it->y, vy = uy + it->h; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } -} - -static void sprite_render_meshes() { - if( map_count(sprite_additive_group) <= 0 ) - if( map_count(sprite_translucent_group) <= 0 ) - if( map_count(sprite_00_translucent_group) <= 0 ) - return; - - if( sprite_program < 0 ) { - sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), - "att_Position,att_TexCoord,att_Color", - "fragColor", NULL - ); - } - - // use the shader and bind the texture @ unit 0 - shader_bind(sprite_program); - glActiveTexture(GL_TEXTURE0); - - // setup rendering state - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glDepthFunc(GL_LEQUAL); // try to help with zfighting - - // update camera - // camera_fps(camera_get_active(), 0,0); - vec3 pos = camera_get_active()->position; - float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); - float width = window_width(); - float height = window_height(); - - // set mvp in the uniform. (0,0) is center of screen. - mat44 mvp2d; - float zdepth_max = window_height(); // 1; - float l = pos.x - width * zoom / 2; - float r = pos.x + width * zoom / 2; - float b = pos.y + height * zoom / 2; - float t = pos.y - height * zoom / 2; - ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); - - shader_mat44("u_mvp", mvp2d); - - // set (unit 0) in the uniform texture sampler, and render batch - // for all additive then translucent groups - - if( map_count(sprite_additive_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); - for each_map_ptr(sprite_additive_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_additive_group); - } - - if( map_count(sprite_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_translucent_group); - } - - if( map_count(sprite_00_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_00_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_00_translucent_group); - } - - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glDepthFunc(GL_LESS); - glUseProgram(0); -} - -static void sprite_init() { - do_once { - map_init(sprite_00_translucent_group, less_int, hash_int); - map_init(sprite_translucent_group, less_int, hash_int); - map_init(sprite_additive_group, less_int, hash_int); - } -} - -void sprite_flush() { - profile("Sprite.rebuild_time") { - sprite_rebuild_meshes(); - } - profile("Sprite.render_time") { - sprite_render_meshes(); - } -} - -// ----------------------------------------------------------------------------- -// tilemaps - -tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { - tilemap_t t = {0}; - t.tint = ~0u; // WHITE - t.blank_chr = blank_chr; - for( ; *map ; ++map ) { - if( map[0] == linefeed_chr ) ++t.rows; - else { - array_push(t.map, map[0]); - ++t.cols; - } - } - return t; -} - -void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { - vec3 old_pos = camera_get_active()->position; - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - - float scale[2] = {xy_zoom[2], xy_zoom[2]}; - xy_zoom[2] = zindex; - - float offset[2] = {0,0}; - float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) - - for( unsigned y = 0, c = 0; y < m.rows; ++y ) { - for( unsigned x = 0; x < m.cols; ++x, ++c ) { - if( m.map[c] != m.blank_chr ) { - spritesheet[0] = m.map[c]; - sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, is_additive, tint, false); - } - offset[0] += t.tile_w; - } - offset[0] = 0, offset[1] += t.tile_h; - } - - sprite_flush(); - camera_get_active()->position = old_pos; -} - -void tilemap_render( tilemap_t map, tileset_t set ) { - map.position.x += set.tile_w; - map.position.y += set.tile_h; - tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); -} - -tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { - tileset_t t = {0}; - t.tex = tex; - t.cols = cols, t.rows = rows; - t.tile_w = tile_w, t.tile_h = tile_h; - return t; -} - -int ui_tileset( tileset_t t ) { - ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); - int choice; - if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { - int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; - int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; - t.selected = px + py * t.cols; - } - // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} - return t.selected; -} - -// ----------------------------------------------------------------------------- -// tiled - -tiled_t tiled(const char *file_tmx) { - tiled_t zero = {0}, ti = zero; - - // read file and parse json - if( !xml_push(file_tmx) ) return zero; - - // sanity checks - bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); - if( !supported ) return xml_pop(), zero; - - // tileset - const char *file_tsx = xml_string("/map/tileset/@source"); - if( !xml_push(vfs_read(file_tsx)) ) return zero; - const char *set_src = xml_string("/tileset/image/@source"); - int set_w = xml_int("/tileset/@tilewidth"); - int set_h = xml_int("/tileset/@tileheight"); - int set_c = xml_int("/tileset/@columns"); - int set_r = xml_int("/tileset/@tilecount") / set_c; - tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); - xml_pop(); - - // actual parsing - ti.w = xml_int("/map/@width"); - ti.h = xml_int("/map/@height"); - ti.tilew = xml_int("/map/@tilewidth"); - ti.tileh = xml_int("/map/@tileheight"); - ti.first_gid = xml_int("/map/tileset/@firstgid"); - ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak - - for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { - if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { - PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); - continue; - } - - int cols = xml_int("/map/layer[%d]/@width",l); - int rows = xml_int("/map/layer[%d]/@height",l); - - tilemap_t tm = tilemap("", ' ', '\n'); - tm.blank_chr = ~0u; //ti.first_gid - 1; - tm.cols = cols; - tm.rows = rows; - array_resize(tm.map, tm.cols * tm.rows); - memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); - - for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { - int cw, ch; - int cx, cy; - array(char) b64 = 0; - - if( !chunks ) { // non-infinite mode - b64 = xml_blob("/map/layer[%d]/data/$",l); - cw = tm.cols, ch = tm.rows; - cx = 0, cy = 0; - } else { // infinite mode - b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); - cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 - cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) - cx = abs(cx), cy = abs(cy); - } - - int outlen = cw * ch * 4; - static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak - if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { - for( int y = 0, p = 0; y < ch; ++y ) { - for( int x = 0; x < cw; ++x, ++p ) { - if( out[p] >= ti.first_gid ) { - int offset = (x + cx) + (y + cy) * tm.cols; - if( offset >= 0 && offset < (cw * ch) ) - tm.map[ offset ] = out[ p ] - ti.first_gid; - } - } - } - } - else { - PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); - } - - array_free(b64); - } - - array_push(ti.layers, tm); - array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); - array_push(ti.visible, true); - array_push(ti.sets, set); - } - - xml_pop(); - return ti; -} - -void tiled_render(tiled_t tmx, vec3 pos) { - for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { - tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); - if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); - if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); - } -} - -void ui_tiled(tiled_t *t) { - ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); - ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); - ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); - ui_separator(); - ui_bool("Parallax", &t->parallax); - ui_separator(); - ui_label2("Layers", va("%d", array_count(t->layers))); - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF - t->visible[i] ^= true; - } - } - ui_separator(); - if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { - t->sets[i].selected = ui_tileset( t->sets[i] ); - ui_collapse_end(); - } - } - ui_collapse_end(); - } -} - -// ----------------------------------------------------------------------------- -// spine json loader (wip) -// - rlyeh, public domain -// -// [ref] http://es.esotericsoftware.com/spine-json-format -// -// notable misses: -// - mesh deforms -// - cubic beziers -// - shears -// - bounding boxes - -enum { SPINE_MAX_BONES = 64 }; // max bones - -typedef struct spine_bone_t { - char *name, *parent; - struct spine_bone_t *parent_bone; - - float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) - - float len; - float x, y, deg; // base - float x2, y2, deg2; // accum / temporaries during bone transform time - float x3, y3, deg3; // values from timeline - - unsigned rect_id; - unsigned atlas_id; -} spine_bone_t; - -typedef struct spine_slot_t { - char *name, *bone, *attach; -} spine_slot_t; - -typedef struct spine_rect_t { - char *name; - float x,y,w,h,sx,sy,deg; -} spine_rect_t; - -typedef struct spine_skin_t { - char *name; - array(spine_rect_t) rects; -} spine_skin_t; - -typedef struct spine_animkey_t { // offline; only during loading - float time, curve[4]; // time is mandatory, curve is optional - union { - char *name; // type: attachment (mode-1) - struct { float deg; }; // type: rotate (mode-2) - struct { float x,y; }; // type: translate (mode-3) - }; -} spine_animkey_t; - -#if 0 -typedef struct spine_pose_t { // runtime; only during playing - unsigned frame; - array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) -} spine_pose_t; -#endif - -typedef struct spine_anim_t { - char *name; - union { -#if 0 - struct { - unsigned frames; - array(spine_pose_t) poses; - }; -#endif - struct { - array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; - }; - }; -} spine_anim_t; - -typedef struct spine_atlas_t { - char *name; - float x,y,w,h,deg; -} spine_atlas_t; - -typedef struct spine_t { - char *name; - texture_t texture; - unsigned skin; - array(spine_bone_t) bones; - array(spine_slot_t) slots; - array(spine_skin_t) skins; - array(spine_anim_t) anims; - array(spine_atlas_t) atlas; - // anim controller - unsigned inuse; - float time, maxtime; - unsigned debug_atlas_id; -} spine_t; - -// --- - -static -void spine_convert_animkeys_to_animpose(spine_anim_t *input) { - spine_anim_t copy = *input; // @todo - // @leak: attach/rot/tra keys -} - -static -int find_bone_id(spine_t *s, const char *bone_name) { - for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) - if( !strcmp(s->bones[i].name, bone_name)) return i; - return -1; -} -static -spine_bone_t *find_bone(spine_t *s, const char *bone_name) { - int bone_id = find_bone_id(s, bone_name); - return bone_id >= 0 ? &s->bones[bone_id] : NULL; -} - -void spine_skin(spine_t *p, unsigned skin) { - if( !p->texture.id ) return; - if( skin >= array_count(p->skins) ) return; - - p->skin = skin; - - char *skin_name = va("%s/", p->skins[skin].name); - int header = strlen(skin_name); - - for( int i = 0; i < array_count(p->atlas); ++i) { - if(!strbeg(p->atlas[i].name, skin_name)) continue; - - int bone_id = find_bone_id(p, p->atlas[i].name+header ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].atlas_id = i; - } - - for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { - int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].rect_id = i; - } -} - -static -bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { - char *atlas = vfs_read(file_atlas); - if(!atlas || !atlas[0]) return false; - - memset(t, 0, sizeof(spine_t)); - - // goblins.png - // size: 1024, 128 - // filter: Linear, Linear - // pma: true - // dagger - // bounds: 2, 18, 26, 108 - // goblin/eyes-closed - // bounds: 2, 4, 34, 12 - spine_atlas_t *sa = 0; - const char *last_id = 0; - const char *texture_name = 0; - const char *texture_filter = 0; - const char *texture_format = 0; - const char *texture_repeat = 0; - float texture_width = 0, texture_height = 0, temp; - for each_substring(atlas, "\r\n", it) { - it += strspn(it, " \t\f\v"); - /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored - else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); - else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) - else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string - else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string - else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string - else if( strbeg(it, "bounds:" ) ) { - sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); - } - else if( !texture_name ) texture_name = va("%s", it); - else { - array_push(t->atlas, ((spine_atlas_t){0}) ); - sa = &t->atlas[array_count(t->atlas) - 1]; - sa->name = STRDUP(it); - } - } - for( int i = 0; i < array_count(t->atlas); ++i ) { - sa = &t->atlas[i]; - sa->x /= texture_width, sa->y /= texture_height; - sa->w /= texture_width, sa->h /= texture_height; - } - - if(!texture_name) return false; - - t->texture = texture(texture_name, TEXTURE_LINEAR); - - json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? - - array_resize(t->bones, json_count("/bones")); - array_reserve(t->slots, json_count("/slots")); - array_resize(t->skins, json_count("/skins")); - array_resize(t->anims, json_count("/animations")); - - for( int i = 0, end = json_count("/bones"); i < end; ++i ) { - spine_bone_t v = {0}; - v.name = STRDUP(json_string("/bones[%d]/name", i)); - v.parent = STRDUP(json_string("/bones[%d]/parent", i)); - v.x = json_float("/bones[%d]/x", i); - v.y = json_float("/bones[%d]/y", i); - v.z = i; - v.len = json_float("/bones[%d]/length", i); - v.deg = json_float("/bones[%d]/rotation", i); - t->bones[i] = v; - - for( int j = i-1; j > 0; --j ) { - if( strcmp(t->bones[j].name,v.parent) ) continue; - t->bones[i].parent_bone = &t->bones[j]; - break; - } - } - - for( int i = 0, end = json_count("/slots"); i < end; ++i ) { - spine_slot_t v = {0}; - v.name = STRDUP(json_string("/slots[%d]/name", i)); - v.bone = STRDUP(json_string("/slots[%d]/bone", i)); - v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); - - array_push(t->slots, v); - - // slots define draw-order. so, update draw-order/zindex in bone - spine_bone_t *b = find_bone(t, v.name); - if( b ) b->z = i; - } - - for( int i = 0, end = json_count("/skins"); i < end; ++i ) { - spine_skin_t v = {0}; - v.name = STRDUP(json_string("/skins[%d]/name", i)); - - for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ - for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ - spine_rect_t r = {0}; - r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); - r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); - r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); - r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; - r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; - r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); - r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); - r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); - array_push(v.rects, r); - } - - t->skins[i] = v; - } - -#if 1 - // simplify: - // merge /skins/default into existing /skins/*, then delete /skins/default - if( array_count(t->skins) > 1 ) { - for( int i = 1; i < array_count(t->skins); ++i ) { - for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { - array_push(t->skins[i].rects, t->skins[0].rects[j]); - } - } - // @leak @fixme: FREE(t->skins[0]) - for( int i = 0; i < array_count(t->skins)-1; ++i ) { - t->skins[i] = t->skins[i+1]; - } - array_pop(t->skins); - } -#endif - - for( int i = 0, end = json_count("/animations"); i < end; ++i ) { - int id; - const char *name; - - spine_anim_t v = {0}; - v.name = STRDUP(json_key("/animations[%d]", i)); - - // slots / attachments - - for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) - for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids - { - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - spine_animkey_t key = {0}; - - key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); - key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); - } - - // @todo: convert name to id - // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) - // printf("%s vs %s\n", key.name, t->bones[id].name); - - array_push(v.attach_keys[bone_id], key); - } - } - - // bones - - for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones - for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - // parse bones - for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); - int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; - if( !track ) continue; - - spine_animkey_t key = {0}; - - key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); - } - - if( track == 1 ) - key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" - array_push(v.rotate_keys[bone_id], key); - else - key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), - key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), - array_push(v.translate_keys[bone_id], key); - } - } - - t->anims[i] = v; - } - - json_pop(); - - spine_skin(t, 0); - - return true; -} - -spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { - spine_t *t = MALLOC(sizeof(spine_t)); - if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; - return t; -} - -void spine_render(spine_t *p, vec3 offset, unsigned flags) { - if( !p->texture.id ) return; - if( !flags ) return; - - ddraw_push_2d(); - // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); - // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); - - // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches - - for( int i = 1; i < array_count(p->bones); ++i ) { - spine_bone_t *self = &p->bones[i]; - if( !self->rect_id ) continue; - - int num_bones = 0; - static array(spine_bone_t*) chain = 0; array_resize(chain, 0); - for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { - array_push(chain, next); - } - - vec3 target = {0}, prev = {0}; - for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction - int j_opposite = end - 1 - j; - - spine_bone_t *b = chain[j_opposite]; // bone - spine_bone_t *pb = b->parent_bone; // parent bone - - float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; - if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; - - const float deg2rad = C_PI / 180; - b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); - b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); - b->deg2 = -b->deg3 + pb_deg2 - b->deg; - - prev = target; - target = vec3(b->x2,b->y2,b->deg2); - } - - target.z = 0; - target = add3(target, offset); - prev.z = 0; - prev = add3(prev, offset); - - if( flags & 2 ) { - ddraw_point( target ); - ddraw_text( target, -0.25f, self->name ); - ddraw_bone( prev, target ); // from parent to bone - } - if( flags & 1 ) { - spine_atlas_t *a = &p->atlas[self->atlas_id]; - spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; - - vec4 rect = ptr4(&a->x); - float zindex = self->z; - float offsx = 0; - float offsy = 0; - float tilt = self->deg2 + (a->deg - r->deg); - unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; - - if( 1 ) { - vec3 dir = vec3(r->x,r->y,0); - dir = rotatez3(dir, self->deg2); - offsx = dir.x * r->sx; - offsy = dir.y * r->sy; - } - - sprite_rect(p->texture, rect, zindex, add4(vec4(target.x,target.y,1,1),vec4(offsx,offsy,0,0)), tilt, tint); - } - } - - ddraw_pop_2d(); - ddraw_flush(); -} - -static -void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { - if( !p->texture.id ) return; - - if( delta > 1/120.f ) delta = 1/120.f; - if( *time >= *maxtime ) *time = 0; else *time += delta; - - // reset root // needed? - p->bones[0].x2 = 0; - p->bones[0].y2 = 0; - p->bones[0].deg2 = 0; - p->bones[0].x3 = 0; - p->bones[0].y3 = 0; - p->bones[0].deg3 = 0; - - for( int i = 0, end = array_count(p->bones); i < end; ++i) { - // @todo: attach channel - // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} - for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].deg3 = r->deg; - } - } - for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].x3 = r->x; - p->bones[i].y3 = r->y; - } - } - } -} - -void spine_animate(spine_t *p, float delta) { - spine_animate_(p, &p->time, &p->maxtime, delta); -} - -void ui_spine(spine_t *p) { - if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { - for each_array_ptr(p->anims, spine_anim_t, q) { - if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { - spine_animate(p, 0); - } - - int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); - if( choice == 1 ) window_pause( 0 ); // play - if( choice == 2 ) window_pause( 1 ); // pause - - for( int i = 0; i < SPINE_MAX_BONES; ++i ) { - ui_separator(); - ui_label(va("Bone %d: Attachment keys", i)); - for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); - } - ui_label(va("Bone %d: Rotate keys", i)); - for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); - } - ui_label(va("Bone %d: Translate keys", i)); - for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); - } - } - } - ui_collapse_end(); - } - if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { - for each_array_ptr(p->bones, spine_bone_t, q) - if( ui_collapse(q->name, va("%p-b2", q)) ) { - ui_label2("Parent:", q->parent); - ui_label2("X:", va("%.2f", q->x)); - ui_label2("Y:", va("%.2f", q->y)); - ui_label2("Length:", va("%.2f", q->len)); - ui_label2("Rotation:", va("%.2f", q->deg)); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { - for each_array_ptr(p->slots, spine_slot_t, q) - if( ui_collapse(q->name, va("%p-s2", q)) ) { - ui_label2("Bone:", q->bone); - ui_label2("Attachment:", q->attach); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { - for each_array_ptr(p->skins, spine_skin_t, q) - if( ui_collapse(q->name, va("%p-k2", q)) ) { - for each_array_ptr(q->rects, spine_rect_t, r) - if( ui_collapse(r->name, va("%p-k3", r)) ) { - ui_label2("X:", va("%.2f", r->x)); - ui_label2("Y:", va("%.2f", r->y)); - ui_label2("Scale X:", va("%.2f", r->sx)); - ui_label2("Scale Y:", va("%.2f", r->sy)); - ui_label2("Width:", va("%.2f", r->w)); - ui_label2("Height:", va("%.2f", r->h)); - ui_label2("Rotation:", va("%.2f", r->deg)); - ui_collapse_end(); - - spine_bone_t *b = find_bone(p, r->name); - if( b ) { - p->debug_atlas_id = b->atlas_id; - - static float tilt = 0; - if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; - spine_atlas_t *r = p->atlas + b->atlas_id; - sprite_flush(); - camera_get_active()->position = vec3(0,0,2); - vec4 rect = ptr4(&r->x); float zindex = 0; vec3 xy_zoom = vec3(0,0,0); unsigned tint = ~0u; - sprite_rect(p->texture, - // rect: vec4(r->x*1.0/p->texture.w,r->y*1.0/p->texture.h,(r->x+r->w)*1.0/p->texture.w,(r->y+r->h)*1.0/p->texture.h), - ptr4(&r->x), // atlas - 0, vec4(0,0,1,1), r->deg + tilt, tint); - sprite_flush(); - camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); - } - } - ui_collapse_end(); - } - ui_collapse_end(); - } - - if( ui_int("Use skin", &p->skin) ) { - p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); - spine_skin(p, p->skin); - } - - if( p->texture.id ) ui_texture(0, p->texture); -} - // ----------------------------------------------------------------------------- // cubemaps @@ -355123,7 +367753,7 @@ anims_t animations(const char *pathfile, int flags) { } #line 0 -#line 1 "engine/split/v4k_renderdd.c" +#line 1 "v4k_renderdd.c" static const char *dd_vs = "//" FILELINE "\n" "in vec3 att_position;\n" "uniform mat4 u_MVP;\n" @@ -355971,7 +368601,7 @@ void ddraw_demo() { } #line 0 -#line 1 "engine/split/v4k_scene.c" +#line 1 "v4k_scene.c" // // @todo: remove explicit GL code from here @@ -356543,7 +369173,1476 @@ void scene_render(int flags) { } #line 0 -#line 1 "engine/split/v4k_system.c" +#line 1 "v4k_sprite.c" +// ---------------------------------------------------------------------------- +// sprites + +typedef struct sprite_static_t { + float px, py, pz; // origin x, y, depth + float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree + float sx, sy; // scale x,y + float cellw, cellh; // dimensions of any cell in spritesheet + + union { + struct { + int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet + }; + struct { + float x, y, w, h; // normalized[0..1] within texture bounds + }; + }; + + uint32_t rgba, flags; // vertex color and flags +} sprite_static_t; + +// sprite batching +typedef struct batch_t { array(sprite_static_t) sprites; mesh_t mesh; int dirty; } batch_t; +typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon + +// sprite stream +typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; +typedef struct sprite_index { GLuint triangle[3]; } sprite_index; + +#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) +#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) + +// sprite impl +static int sprite_count = 0; +static int sprite_program = -1; +static array(sprite_index) sprite_indices = 0; +static array(sprite_vertex) sprite_vertices = 0; + +// center_wh << 2 | additive << 1 | projected << 0 +static batch_group_t sprite_group[8] = {0}; + +// rect(x,y,w,h) is [0..1] normalized, pos(xyz,z-index), scale_offset(sx,sy,offx,offy), rotation (degrees), color (rgba) +void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scale_offset, float tilt_deg, unsigned tint_rgba, unsigned flags) { + float zindex = pos.w; + float scalex = scale_offset.x; + float scaley = scale_offset.y; + float offsetx = scale_offset.z; + float offsety = scale_offset.w; + + // do not queue if either scales or alpha are zero + if( 0 == (scalex * scaley * ((tint_rgba>>24) & 255)) ) return; + + ASSERT( (flags & SPRITE_CENTERED) == 0 ); + if( flags & SPRITE_PROJECTED ) { + tilt_deg += 180, scalex = -scalex; // flip texture Y on mvp3d (same than turn 180º then flip X) + } + + sprite_static_t s = {0}; + + s.px = pos.x, s.py = pos.y, s.pz = pos.z - zindex; + s.sx = scalex, s.sy = scaley; + + s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; + s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; + + s.rgba = tint_rgba; + s.flags = flags; + +#if 0 + s.ox = 0/*ox*/ * s.sx; + s.oy = 0/*oy*/ * s.sy; +#else + s.ox += offsetx * scalex; + s.oy += offsety * scaley; +#endif + + if( tilt_deg ) { + tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); + s.cos = cosf(tilt_deg); + s.sin = sinf(tilt_deg); + } else { + s.cos = 1; + s.sin = 0; + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; + batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); + + array_push(found->sprites, s); +} + +void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags) { + flags |= SPRITE_CENTERED; + ASSERT( flags & SPRITE_CENTERED ); + + const float px = position[0], py = position[1], pz = position[2]; + const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; + const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; + + if (frame < 0) return; + if (frame > 0 && frame >= (xcells * ycells)) return; + + // no need to queue if alpha or scale are zero + if( sx && sy && alpha(rgba) ) { + vec3 bak = camera_get_active()->position; + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + } + + sprite_static_t s; + s.px = px; + s.py = py; + s.pz = pz; + s.frame = frame; + s.ncx = xcells ? xcells : 1; + s.ncy = ycells ? ycells : 1; + s.sx = sx; + s.sy = sy; + s.ox = ox * sx; + s.oy = oy * sy; + s.cellw = (texture.x * sx / s.ncx); + s.cellh = (texture.y * sy / s.ncy); + s.rgba = rgba; + s.flags = flags; + s.cos = 1; + s.sin = 0; + if(rotation) { + rotation = (rotation + 0) * ((float)C_PI / 180); + s.cos = cosf(rotation); + s.sin = sinf(rotation); + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; +#if 0 + batch_t *found = map_find(*batches, texture.id); + if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); +#else + batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); +#endif + + array_push(found->sprites, s); + + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = bak; + } + } +} + +void sprite( texture_t texture, float position[3], float rotation, unsigned color, unsigned flags) { + float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; + sprite_sheet( texture, spritesheet, position, rotation, offset, scale, color, flags ); +} + +static void sprite_rebuild_meshes() { + sprite_count = 0; + + // w/2,h/2 centered + for( int l = countof(sprite_group) / 2; l < countof(sprite_group); ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float cx = (1.0f / it->ncx) - 1e-9f; + float cy = (1.0f / it->ncy) - 1e-9f; + int idx = (int)it->frame; + int px = idx % it->ncx; + int py = idx / it->ncx; + + float ux = px * cx, uy = py * cy; + float vx = ux + cx, vy = uy + cy; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } + + // (0,0) centered + for( int l = 0; l < countof(sprite_group) / 2; ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float ux = it->x, vx = ux + it->w; + float uy = it->y, vy = uy + it->h; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } +} + +static void sprite_render_meshes_group(batch_group_t* sprites, int alpha_key, int alpha_value, float mvp[16]) { + if( map_count(*sprites) > 0 ) { + // setup shader + if( sprite_program < 0 ) { + sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), + "att_Position,att_TexCoord,att_Color", + "fragColor", NULL + ); + } + shader_bind(sprite_program); + shader_mat44("u_mvp", mvp); + + // set (unit 0) in the uniform texture sampler, and render batch + glActiveTexture(GL_TEXTURE0); + glBlendFunc( alpha_key, alpha_value ); + + for each_map_ptr(*sprites, int,texture_id, batch_t,bt) { + if( bt->dirty ) { + shader_texture_unit("u_texture", *texture_id, 0); + mesh_render(&bt->mesh); + } + } +// map_clear(*sprites); + } +} + +static void sprite_init() { + do_once for(int i = 0; i < countof(sprite_group); ++i) { + map_init(sprite_group[i], less_int, hash_int); + } +} + +void sprite_flush() { + profile("Sprite.rebuild_time") { + sprite_rebuild_meshes(); + } + profile("Sprite.render_time") { + // setup rendering state + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glDepthFunc(GL_LEQUAL); // try to help with zfighting + + // 3d + mat44 mvp3d; multiply44x2(mvp3d, camera_get_active()->proj, camera_get_active()->view); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + + // 2d: (0,0) is center of screen + mat44 mvp2d; + vec3 pos = camera_get_active()->position; + float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); + float zdepth_max = window_height(); // 1; + float l = pos.x - window_width() * zoom / 2; + float r = pos.x + window_width() * zoom / 2; + float b = pos.y + window_height() * zoom / 2; + float t = pos.y - window_height() * zoom / 2; + ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[0], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + + // restore rendering state + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDepthFunc(GL_LESS); + glUseProgram(0); + } +} + +// ----------------------------------------------------------------------------- +// tilemaps + +tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { + tilemap_t t = {0}; + t.tint = ~0u; // WHITE + t.blank_chr = blank_chr; + for( ; *map ; ++map ) { + if( map[0] == linefeed_chr ) ++t.rows; + else { + array_push(t.map, map[0]); + ++t.cols; + } + } + return t; +} + +void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { + vec3 old_pos = camera_get_active()->position; + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + + float scale[2] = {xy_zoom[2], xy_zoom[2]}; + xy_zoom[2] = zindex; + + float offset[2] = {0,0}; + float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) + + for( unsigned y = 0, c = 0; y < m.rows; ++y ) { + for( unsigned x = 0; x < m.cols; ++x, ++c ) { + if( m.map[c] != m.blank_chr ) { + spritesheet[0] = m.map[c]; + sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, tint, is_additive ? SPRITE_ADDITIVE : 0); + } + offset[0] += t.tile_w; + } + offset[0] = 0, offset[1] += t.tile_h; + } + + sprite_flush(); + camera_get_active()->position = old_pos; +} + +void tilemap_render( tilemap_t map, tileset_t set ) { + map.position.x += set.tile_w; + map.position.y += set.tile_h; + tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); +} + +tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { + tileset_t t = {0}; + t.tex = tex; + t.cols = cols, t.rows = rows; + t.tile_w = tile_w, t.tile_h = tile_h; + return t; +} + +int ui_tileset( tileset_t t ) { + ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); + int choice; + if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { + int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; + int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; + t.selected = px + py * t.cols; + } + // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} + return t.selected; +} + +// ----------------------------------------------------------------------------- +// tiled + +tiled_t tiled(const char *file_tmx) { + tiled_t zero = {0}, ti = zero; + + // read file and parse json + if( !xml_push(file_tmx) ) return zero; + + // sanity checks + bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); + if( !supported ) return xml_pop(), zero; + + // tileset + const char *file_tsx = xml_string("/map/tileset/@source"); + if( !xml_push(vfs_read(file_tsx)) ) return zero; + const char *set_src = xml_string("/tileset/image/@source"); + int set_w = xml_int("/tileset/@tilewidth"); + int set_h = xml_int("/tileset/@tileheight"); + int set_c = xml_int("/tileset/@columns"); + int set_r = xml_int("/tileset/@tilecount") / set_c; + tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); + xml_pop(); + + // actual parsing + ti.w = xml_int("/map/@width"); + ti.h = xml_int("/map/@height"); + ti.tilew = xml_int("/map/@tilewidth"); + ti.tileh = xml_int("/map/@tileheight"); + ti.first_gid = xml_int("/map/tileset/@firstgid"); + ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak + + for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { + if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { + PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); + continue; + } + + int cols = xml_int("/map/layer[%d]/@width",l); + int rows = xml_int("/map/layer[%d]/@height",l); + + tilemap_t tm = tilemap("", ' ', '\n'); + tm.blank_chr = ~0u; //ti.first_gid - 1; + tm.cols = cols; + tm.rows = rows; + array_resize(tm.map, tm.cols * tm.rows); + memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); + + for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { + int cw, ch; + int cx, cy; + array(char) b64 = 0; + + if( !chunks ) { // non-infinite mode + b64 = xml_blob("/map/layer[%d]/data/$",l); + cw = tm.cols, ch = tm.rows; + cx = 0, cy = 0; + } else { // infinite mode + b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); + cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 + cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) + cx = abs(cx), cy = abs(cy); + } + + int outlen = cw * ch * 4; + static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak + if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { + for( int y = 0, p = 0; y < ch; ++y ) { + for( int x = 0; x < cw; ++x, ++p ) { + if( out[p] >= ti.first_gid ) { + int offset = (x + cx) + (y + cy) * tm.cols; + if( offset >= 0 && offset < (cw * ch) ) + tm.map[ offset ] = out[ p ] - ti.first_gid; + } + } + } + } + else { + PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); + } + + array_free(b64); + } + + array_push(ti.layers, tm); + array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); + array_push(ti.visible, true); + array_push(ti.sets, set); + } + + xml_pop(); + return ti; +} + +void tiled_render(tiled_t tmx, vec3 pos) { + for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { + tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); + if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); + if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); + } +} + +void ui_tiled(tiled_t *t) { + ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); + ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); + ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); + ui_separator(); + ui_bool("Parallax", &t->parallax); + ui_separator(); + ui_label2("Layers", va("%d", array_count(t->layers))); + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF + t->visible[i] ^= true; + } + } + ui_separator(); + if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { + t->sets[i].selected = ui_tileset( t->sets[i] ); + ui_collapse_end(); + } + } + ui_collapse_end(); + } +} + +// ----------------------------------------------------------------------------- +// spine json loader (wip) +// - rlyeh, public domain +// +// [ref] http://es.esotericsoftware.com/spine-json-format +// +// notable misses: +// - mesh deforms +// - cubic beziers +// - shears +// - bounding boxes + +enum { SPINE_MAX_BONES = 64 }; // max bones + +typedef struct spine_bone_t { + char *name, *parent; + struct spine_bone_t *parent_bone; + + float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) + + float len; + float x, y, deg; // base + float x2, y2, deg2; // accum / temporaries during bone transform time + float x3, y3, deg3; // values from timeline + + unsigned rect_id; + unsigned atlas_id; +} spine_bone_t; + +typedef struct spine_slot_t { + char *name, *bone, *attach; +} spine_slot_t; + +typedef struct spine_rect_t { + char *name; + float x,y,w,h,sx,sy,deg; +} spine_rect_t; + +typedef struct spine_skin_t { + char *name; + array(spine_rect_t) rects; +} spine_skin_t; + +typedef struct spine_animkey_t { // offline; only during loading + float time, curve[4]; // time is mandatory, curve is optional + union { + char *name; // type: attachment (mode-1) + struct { float deg; }; // type: rotate (mode-2) + struct { float x,y; }; // type: translate (mode-3) + }; +} spine_animkey_t; + +#if 0 +typedef struct spine_pose_t { // runtime; only during playing + unsigned frame; + array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) +} spine_pose_t; +#endif + +typedef struct spine_anim_t { + char *name; + union { +#if 0 + struct { + unsigned frames; + array(spine_pose_t) poses; + }; +#endif + struct { + array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; + }; + }; +} spine_anim_t; + +typedef struct spine_atlas_t { + char *name; + float x,y,w,h,deg; +} spine_atlas_t; + +typedef struct spine_t { + char *name; + texture_t texture; + unsigned skin; + array(spine_bone_t) bones; + array(spine_slot_t) slots; + array(spine_skin_t) skins; + array(spine_anim_t) anims; + array(spine_atlas_t) atlas; + // anim controller + unsigned inuse; + float time, maxtime; + unsigned debug_atlas_id; +} spine_t; + +// --- + +static +void spine_convert_animkeys_to_animpose(spine_anim_t *input) { + spine_anim_t copy = *input; // @todo + // @leak: attach/rot/tra keys +} + +static +int find_bone_id(spine_t *s, const char *bone_name) { + for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) + if( !strcmp(s->bones[i].name, bone_name)) return i; + return -1; +} +static +spine_bone_t *find_bone(spine_t *s, const char *bone_name) { + int bone_id = find_bone_id(s, bone_name); + return bone_id >= 0 ? &s->bones[bone_id] : NULL; +} + +void spine_skin(spine_t *p, unsigned skin) { + if( !p->texture.id ) return; + if( skin >= array_count(p->skins) ) return; + + p->skin = skin; + + char *skin_name = va("%s/", p->skins[skin].name); + int header = strlen(skin_name); + + for( int i = 0; i < array_count(p->atlas); ++i) { + if(!strbeg(p->atlas[i].name, skin_name)) continue; + + int bone_id = find_bone_id(p, p->atlas[i].name+header ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].atlas_id = i; + } + + for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { + int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].rect_id = i; + } +} + +static +bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { + char *atlas = vfs_read(file_atlas); + if(!atlas || !atlas[0]) return false; + + memset(t, 0, sizeof(spine_t)); + + // goblins.png + // size: 1024, 128 + // filter: Linear, Linear + // pma: true + // dagger + // bounds: 2, 18, 26, 108 + // goblin/eyes-closed + // bounds: 2, 4, 34, 12 + spine_atlas_t *sa = 0; + const char *last_id = 0; + const char *texture_name = 0; + const char *texture_filter = 0; + const char *texture_format = 0; + const char *texture_repeat = 0; + float texture_width = 0, texture_height = 0, temp; + for each_substring(atlas, "\r\n", it) { + it += strspn(it, " \t\f\v"); + /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored + else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); + else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) + else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string + else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string + else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string + else if( strbeg(it, "bounds:" ) ) { + sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); + } + else if( !texture_name ) texture_name = va("%s", it); + else { + array_push(t->atlas, ((spine_atlas_t){0}) ); + sa = &t->atlas[array_count(t->atlas) - 1]; + sa->name = STRDUP(it); + } + } + for( int i = 0; i < array_count(t->atlas); ++i ) { + sa = &t->atlas[i]; + sa->x /= texture_width, sa->y /= texture_height; + sa->w /= texture_width, sa->h /= texture_height; + } + + if(!texture_name) return false; + + t->texture = texture(texture_name, TEXTURE_LINEAR); + + json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? + + array_resize(t->bones, json_count("/bones")); + array_reserve(t->slots, json_count("/slots")); + array_resize(t->skins, json_count("/skins")); + array_resize(t->anims, json_count("/animations")); + + for( int i = 0, end = json_count("/bones"); i < end; ++i ) { + spine_bone_t v = {0}; + v.name = STRDUP(json_string("/bones[%d]/name", i)); + v.parent = STRDUP(json_string("/bones[%d]/parent", i)); + v.x = json_float("/bones[%d]/x", i); + v.y = json_float("/bones[%d]/y", i); + v.z = i; + v.len = json_float("/bones[%d]/length", i); + v.deg = json_float("/bones[%d]/rotation", i); + t->bones[i] = v; + + for( int j = i-1; j > 0; --j ) { + if( strcmp(t->bones[j].name,v.parent) ) continue; + t->bones[i].parent_bone = &t->bones[j]; + break; + } + } + + for( int i = 0, end = json_count("/slots"); i < end; ++i ) { + spine_slot_t v = {0}; + v.name = STRDUP(json_string("/slots[%d]/name", i)); + v.bone = STRDUP(json_string("/slots[%d]/bone", i)); + v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); + + array_push(t->slots, v); + + // slots define draw-order. so, update draw-order/zindex in bone + spine_bone_t *b = find_bone(t, v.name); + if( b ) b->z = i; + } + + for( int i = 0, end = json_count("/skins"); i < end; ++i ) { + spine_skin_t v = {0}; + v.name = STRDUP(json_string("/skins[%d]/name", i)); + + for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ + for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ + spine_rect_t r = {0}; + r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); + r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); + r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); + r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; + r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; + r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); + r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); + r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); + array_push(v.rects, r); + } + + t->skins[i] = v; + } + +#if 1 + // simplify: + // merge /skins/default into existing /skins/*, then delete /skins/default + if( array_count(t->skins) > 1 ) { + for( int i = 1; i < array_count(t->skins); ++i ) { + for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { + array_push(t->skins[i].rects, t->skins[0].rects[j]); + } + } + // @leak @fixme: FREE(t->skins[0]) + for( int i = 0; i < array_count(t->skins)-1; ++i ) { + t->skins[i] = t->skins[i+1]; + } + array_pop(t->skins); + } +#endif + + for( int i = 0, end = json_count("/animations"); i < end; ++i ) { + int id; + const char *name; + + spine_anim_t v = {0}; + v.name = STRDUP(json_key("/animations[%d]", i)); + + // slots / attachments + + for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) + for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids + { + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + spine_animkey_t key = {0}; + + key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); + key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); + } + + // @todo: convert name to id + // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) + // printf("%s vs %s\n", key.name, t->bones[id].name); + + array_push(v.attach_keys[bone_id], key); + } + } + + // bones + + for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones + for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + // parse bones + for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); + int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; + if( !track ) continue; + + spine_animkey_t key = {0}; + + key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); + } + + if( track == 1 ) + key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" + array_push(v.rotate_keys[bone_id], key); + else + key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), + key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), + array_push(v.translate_keys[bone_id], key); + } + } + + t->anims[i] = v; + } + + json_pop(); + + spine_skin(t, 0); + + return true; +} + +spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { + spine_t *t = MALLOC(sizeof(spine_t)); + if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; + return t; +} + +void spine_render(spine_t *p, vec3 offset, unsigned flags) { + if( !p->texture.id ) return; + if( !flags ) return; + + ddraw_push_2d(); + // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); + // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); + + // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches + + for( int i = 1; i < array_count(p->bones); ++i ) { + spine_bone_t *self = &p->bones[i]; + if( !self->rect_id ) continue; + + int num_bones = 0; + static array(spine_bone_t*) chain = 0; array_resize(chain, 0); + for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { + array_push(chain, next); + } + + vec3 target = {0}, prev = {0}; + for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction + int j_opposite = end - 1 - j; + + spine_bone_t *b = chain[j_opposite]; // bone + spine_bone_t *pb = b->parent_bone; // parent bone + + float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; + if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; + + const float deg2rad = C_PI / 180; + b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); + b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); + b->deg2 = -b->deg3 + pb_deg2 - b->deg; + + prev = target; + target = vec3(b->x2,b->y2,b->deg2); + } + + target.z = 0; + target = add3(target, offset); + prev.z = 0; + prev = add3(prev, offset); + + if( flags & 2 ) { + ddraw_point( target ); + ddraw_text( target, -0.25f, self->name ); + ddraw_bone( prev, target ); // from parent to bone + } + if( flags & 1 ) { + spine_atlas_t *a = &p->atlas[self->atlas_id]; + spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; + + vec4 rect = ptr4(&a->x); + float zindex = self->z; + float offsx = 0; + float offsy = 0; + float tilt = self->deg2 + (a->deg - r->deg); + unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; + + if( 1 ) { + vec3 dir = vec3(r->x,r->y,0); + dir = rotatez3(dir, self->deg2); + offsx = dir.x * r->sx; + offsy = dir.y * r->sy; + } + + sprite_rect(p->texture, rect, vec4(target.x,target.y,0,zindex), vec4(1,1,offsx,offsy), tilt, tint, 0); + } + } + + ddraw_pop_2d(); + ddraw_flush(); +} + +static +void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { + if( !p->texture.id ) return; + + if( delta > 1/120.f ) delta = 1/120.f; + if( *time >= *maxtime ) *time = 0; else *time += delta; + + // reset root // needed? + p->bones[0].x2 = 0; + p->bones[0].y2 = 0; + p->bones[0].deg2 = 0; + p->bones[0].x3 = 0; + p->bones[0].y3 = 0; + p->bones[0].deg3 = 0; + + for( int i = 0, end = array_count(p->bones); i < end; ++i) { + // @todo: attach channel + // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} + for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].deg3 = r->deg; + } + } + for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].x3 = r->x; + p->bones[i].y3 = r->y; + } + } + } +} + +void spine_animate(spine_t *p, float delta) { + spine_animate_(p, &p->time, &p->maxtime, delta); +} + +void ui_spine(spine_t *p) { + if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { + for each_array_ptr(p->anims, spine_anim_t, q) { + if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { + spine_animate(p, 0); + } + + int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); + if( choice == 1 ) window_pause( 0 ); // play + if( choice == 2 ) window_pause( 1 ); // pause + + for( int i = 0; i < SPINE_MAX_BONES; ++i ) { + ui_separator(); + ui_label(va("Bone %d: Attachment keys", i)); + for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); + } + ui_label(va("Bone %d: Rotate keys", i)); + for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); + } + ui_label(va("Bone %d: Translate keys", i)); + for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); + } + } + } + ui_collapse_end(); + } + if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { + for each_array_ptr(p->bones, spine_bone_t, q) + if( ui_collapse(q->name, va("%p-b2", q)) ) { + ui_label2("Parent:", q->parent); + ui_label2("X:", va("%.2f", q->x)); + ui_label2("Y:", va("%.2f", q->y)); + ui_label2("Length:", va("%.2f", q->len)); + ui_label2("Rotation:", va("%.2f", q->deg)); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { + for each_array_ptr(p->slots, spine_slot_t, q) + if( ui_collapse(q->name, va("%p-s2", q)) ) { + ui_label2("Bone:", q->bone); + ui_label2("Attachment:", q->attach); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { + for each_array_ptr(p->skins, spine_skin_t, q) + if( ui_collapse(q->name, va("%p-k2", q)) ) { + for each_array_ptr(q->rects, spine_rect_t, r) + if( ui_collapse(r->name, va("%p-k3", r)) ) { + ui_label2("X:", va("%.2f", r->x)); + ui_label2("Y:", va("%.2f", r->y)); + ui_label2("Scale X:", va("%.2f", r->sx)); + ui_label2("Scale Y:", va("%.2f", r->sy)); + ui_label2("Width:", va("%.2f", r->w)); + ui_label2("Height:", va("%.2f", r->h)); + ui_label2("Rotation:", va("%.2f", r->deg)); + ui_collapse_end(); + + spine_bone_t *b = find_bone(p, r->name); + if( b ) { + p->debug_atlas_id = b->atlas_id; + + static float tilt = 0; + if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; + spine_atlas_t *r = p->atlas + b->atlas_id; + sprite_flush(); + camera_get_active()->position = vec3(0,0,2); + vec4 rect = ptr4(&r->x); float zindex = 0; vec4 scale_offset = vec4(1,1,0,0); + sprite_rect(p->texture, ptr4(&r->x), vec4(0,0,0,zindex), scale_offset, r->deg + tilt, ~0u, 0); + sprite_flush(); + camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); + } + } + ui_collapse_end(); + } + ui_collapse_end(); + } + + if( ui_int("Use skin", &p->skin) ) { + p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); + spine_skin(p, p->skin); + } + + if( p->texture.id ) ui_texture(0, p->texture); +} + +// ---------------------------------------------------------------------------- + +// texture_t texture_createclip(unsigned cx,unsigned cy,unsigned cw,unsigned ch, unsigned tw,unsigned th,unsigned tn,void *pixels, unsigned flags) { +// return texture_create(tw,th,tn,pixels,flags); +// static array(unsigned) clip = 0; +// array_resize(clip, cw*ch*4); +// for( unsigned y = 0; y < ch; ++y ) +// memcpy((char *)clip + (0+(0+y)*cw)*tn, (char*)pixels + (cx+(cy+y)*tw)*tn, cw*tn); +// return texture_create(cw,ch,tn,clip,flags); +// } + +typedef unsigned quark_t; + +#define array_reserve_(arr,x) (array_count(arr) > (x) ? (arr) : array_resize(arr, 1+(x))) + +#define ui_array(label,type,ptr) do { \ + int changed = 0; \ + if( ui_collapse(label, va(#type "%p",ptr)) ) { \ + char label_ex[8]; \ + for( int idx = 0, iend = array_count(*(ptr)); idx < iend; ++idx ) { \ + type* it = *(ptr) + idx; \ + snprintf(label_ex, sizeof(label_ex), "[%d]", idx); \ + changed |= ui_##type(label_ex, it); \ + } \ + ui_collapse_end(); \ + } \ +} while(0) + +int ui_vec2i(const char *label, vec2i *v) { return ui_unsigned2(label, (unsigned*)v); } +int ui_vec3i(const char *label, vec3i *v) { return ui_unsigned3(label, (unsigned*)v); } +int ui_vec2(const char *label, vec2 *v) { return ui_float2(label, (float*)v); } +int ui_vec3(const char *label, vec3 *v) { return ui_float3(label, (float*)v); } +int ui_vec4(const char *label, vec4 *v) { return ui_float4(label, (float*)v); } + +char *trimspace(char *str) { + for( char *s = str; *s; ++s ) + if(*s <= 32) memmove(s, s+1, strlen(s)); + return str; +} + +char *file_parent(const char *f) { // folder/folder/abc + char *p = file_path(f); // folder/folder/ + char *last = strrchr(p, '/'); // ^ + if( !last ) return p; // return parent if no sep + *last = '\0'; // folder/folder + last = strrchr(p, '/'); // ^ + return last ? last + 1 : p; // return parent if no sep +} + +int ui_obj(const char *fmt, obj *o) { + int changed = 0, item = 1; + for each_objmember(o, TYPE,NAME,PTR) { + char *label = va(fmt, NAME); + /**/ if(!strcmp(TYPE,"float")) { if(ui_float(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"int")) { if(ui_int(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"unsigned")) { if(ui_unsigned(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec2")) { if(ui_float2(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec3")) { if(ui_float3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec4")) { if(ui_float4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgb")) { if(ui_color3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgba")) { if(ui_color4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color3f")) { if(ui_color3f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color4f")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"char*")) { if(ui_string(label, PTR)) changed = item; } + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + ++item; + } + return changed; +} + +#define OBJTYPEDEF2(...) OBJTYPEDEF(__VA_ARGS__); AUTORUN + +// ---------------------------------------------------------------------------- +// atlas + +typedef struct atlas_frame_t { + unsigned delay; + vec4 sheet; + vec2 anchor; // @todo + array(vec3i) indices; + array(vec2) coords; + array(vec2) uvs; +} atlas_frame_t; + +typedef struct atlas_anim_t { + quark_t name; + array(unsigned) frames; +} atlas_anim_t; + +typedef struct atlas_t { + texture_t tex; + + array(atlas_frame_t) frames; + array(atlas_anim_t) anims; + + quarks_db db; +} atlas_t; + +int ui_atlas_frame(atlas_frame_t *f) { + ui_unsigned("delay", &f->delay); + ui_vec4("sheet", &f->sheet); + ui_array("indices", vec3i, &f->indices); + ui_array("coords", vec2, &f->coords); + ui_array("uvs", vec2, &f->uvs); + return 0; +} + +int ui_atlas(atlas_t *a) { + int changed = 0; + ui_texture(NULL, a->tex); + for( int i = 0; i < array_count(a->anims); ++i ) { + if( ui_collapse(quark_string(&a->db, a->anims[i].name), va("%p%d", a, a->anims[i].name) ) ) { + changed = i+1; + for( int j = 0; j < array_count(a->anims[i].frames); ++j ) { + if( ui_collapse(va("[%d]",j), va("%p%d.%d", a, a->anims[i].name,j) ) ) { + ui_unsigned("Frame", &a->anims[i].frames[j]); + ui_atlas_frame(a->frames + a->anims[i].frames[j]); + ui_collapse_end(); + } + } + ui_collapse_end(); + } + } + return changed; +} + +void atlas_destroy(atlas_t *a) { + if( a ) { + texture_destroy(&a->tex); + memset(a, 0, sizeof(atlas_t)); + } +} +atlas_t atlas_create(const char *inifile, unsigned flags) { + atlas_t a = {0}; + int padding = 0, border = 0; + + ini_t kv = ini(inifile); + for each_map(kv, char*,k, char*,v ) { + unsigned index = atoi(k); + /**/ if( strend(k, ".name") ) { + array_reserve_(a.anims, index); + + a.anims[index].name = quark_intern(&a.db, v); + } + else if( strend(k, ".frames") ) { + array_reserve_(a.anims, index); + + array(char*) pairs = strsplit(v, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned frame = atoi(pairs[i]); + unsigned delay = atoi(pairs[i+1]); + + array_reserve_(a.frames, frame); + a.frames[frame].delay = delay; + + array_push(a.anims[index].frames, frame); + } + } + else if( strend(k, ".sheet") ) { + array_reserve_(a.frames, index); + + vec4 sheet = atof4(v); //x,y,x2+2,y2+2 -> x,y,w,h (for 2,2 padding) + a.frames[index].sheet = vec4(sheet.x,sheet.y,sheet.z-sheet.x,sheet.w-sheet.y); + } + else if( strend(k, ".indices") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) tuples = strsplit(text, ","); + for( int i = 0, end = array_count(tuples); i < end; i += 3 ) { + unsigned p1 = atoi(tuples[i]); + unsigned p2 = atoi(tuples[i+1]); + unsigned p3 = atoi(tuples[i+2]); + array_push(a.frames[index].indices, vec3i(p1,p2,p3)); + } + } + else if( strend(k, ".coords") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned x = atoi(pairs[i]); + unsigned y = atoi(pairs[i+1]); + array_push(a.frames[index].coords, vec2(x,y)); + } + } + else if( strend(k, ".uvs") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned u = atoi(pairs[i]); + unsigned v = atoi(pairs[i+1]); + array_push(a.frames[index].uvs, vec2(u,v)); + } + } + else if( strend(k, "padding") ) { + padding = atoi(v); + } + else if( strend(k, "border") ) { + border = atoi(v); + } + else if( strend(k, "file") ) { + a.tex = texture(v, 0); + } + else if( strend(k, "bitmap") ) { + const char *text = v; + array(char) bin = base64_decode(text, strlen(text)); + a.tex = texture_from_mem(bin, array_count(bin), 0); + array_free(bin); + } +#if 0 + else if( strend(k, ".frame") ) { + array_reserve_(a.frames, index); + puts(k), puts(v); + } +#endif + } + + // post-process: normalize uvs and coords into [0..1] ranges + for each_array_ptr(a.frames, atlas_frame_t, f) { + for each_array_ptr(f->uvs, vec2, uv) { + uv->x /= a.tex.w; + uv->y /= a.tex.h; + } + for each_array_ptr(f->coords, vec2, xy) { + xy->x /= a.tex.w; + xy->y /= a.tex.h; + } + // @todo: adjust padding/border + } +#if 0 + // post-process: specify an anchor for each anim based on 1st frame dims + for each_array_ptr(a.anims, atlas_anim_t, anim) { + atlas_frame_t *first = a.frames + *anim->frames; + for( int i = 0; i < array_count(anim->frames); i += 2) { + atlas_frame_t *ff = a.frames + anim->frames[ i ]; + ff->anchor.x = (ff->sheet.z - first->sheet.z) / 2; + ff->anchor.y = (ff->sheet.w - first->sheet.w) / 2; + } + } +#endif + + return a; +} + +// ---------------------------------------------------------------------------- +// sprite v2 + +void sprite_ctor(sprite_t *s) { + s->tint = WHITE; + s->timer_ms = 100; + s->flipped = 1; + s->sca.x += !s->sca.x; + s->sca.y += !s->sca.y; +} +void sprite_dtor(sprite_t *s) { + memset(s, 0, sizeof(*s)); +} +void sprite_tick(sprite_t *s) { + int right = input(s->gamepad.array[3]) - input(s->gamepad.array[2]); // RIGHT - LEFT + int forward = input(s->gamepad.array[1]) - input(s->gamepad.array[0]); // DOWN - UP + int move = right || forward; + int dt = 16; // window_delta() * 1000; + + unsigned over = (s->timer - dt) > s->timer; + if(!s->paused) s->timer -= dt; + if( over ) { + int len = array_count(s->a->anims[s->play].frames); + unsigned next = (s->frame + 1) % (len + !len); + unsigned eoa = next < s->frame; + s->frame = next; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + s->timer_ms = f->delay; + s->timer += s->timer_ms; + } + + if( s->play == 0 && move ) sprite_setanim(s, 1); + if( s->play == 1 ) { //< + if(right) s->flip_ = right < 0, sprite_setanim(s, 1); + if(!right && !forward) sprite_setanim(s, 0); + + float speed = s->sca.x*2; + s->pos = add4(s->pos, scale4(norm4(vec4(right,0,forward,0)),speed)); + } +} +void sprite_draw(sprite_t *s) { + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + +#if 1 + // @todo { + unsigned sample = s->a->anims[s->play].frames[s->frame]; + sample = 0; + f->anchor.x = (-s->a->frames[sample].sheet.z + f->sheet.z) / 2; + f->anchor.y = (+s->a->frames[sample].sheet.w - f->sheet.w) / 2; + // } +#endif + + // rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scale), rotation (degrees), color (rgba) + vec4 rect = { f->sheet.x / s->a->tex.w, f->sheet.y / s->a->tex.h, f->sheet.z / s->a->tex.w, f->sheet.w / s->a->tex.h }; + sprite_rect(s->a->tex, rect, s->pos, vec4(s->flip_ ^ s->flipped?s->sca.x:-s->sca.x,s->sca.y,f->anchor.x,f->anchor.y), s->tilt, s->tint, 0|SPRITE_PROJECTED); +} +void sprite_edit(sprite_t *s) { + const char *name = obj_name(s); + const char *id = vac("%p", s); + if( s && ui_collapse(name ? name : id, id) ) { + ui_obj("%s", (obj*)s); + + ui_bool("paused", &s->paused); + ui_label(va("frame anim [%d]", s->a->anims[s->play].frames[s->frame])); + + int k = s->play; + if( ui_int("anim", &k) ) { + sprite_setanim(s, k); + } + + int selected = ui_atlas(s->a); + if( selected ) sprite_setanim(s, selected - 1); + + ui_collapse_end(); + } +} + +sprite_t* sprite_new(const char *ase, int bindings[6]) { + sprite_t *s = obj_new(sprite_t, {bindings[0],bindings[1],bindings[2],bindings[3]}, {bindings[4],bindings[5]}); + atlas_t own = atlas_create(ase, 0); + memcpy(s->a = MALLOC(sizeof(atlas_t)), &own, sizeof(atlas_t)); // s->a = &s->own; + return s; +} +void sprite_del(sprite_t *s) { + if( s ) { + if( s->a ) atlas_destroy(s->a), FREE(s->a); // if( s->a == &s->own ) + obj_free(s); + memset(s, 0, sizeof(sprite_t)); + } +} +void sprite_setanim(sprite_t *s, unsigned name) { + if( s->play != name ) { + s->play = name; + s->frame = 0; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + + s->timer_ms = f->delay; + s->timer = s->timer_ms; + } +} + +AUTORUN { + STRUCT(sprite_t, vec4, pos); + STRUCT(sprite_t, vec2, sca); + STRUCT(sprite_t, float, tilt); + STRUCT(sprite_t, vec4, gamepad); + STRUCT(sprite_t, vec2, fire); + STRUCT(sprite_t, rgba, tint); + STRUCT(sprite_t, unsigned, frame); + STRUCT(sprite_t, unsigned, timer); + STRUCT(sprite_t, unsigned, timer_ms); + STRUCT(sprite_t, unsigned, flipped); + STRUCT(sprite_t, unsigned, play); + EXTEND_T(sprite, ctor,edit,draw,tick); +} +#line 0 + +#line 1 "v4k_system.c" #if (is(tcc) && is(linux)) || (is(gcc) && !is(mingw)) // || is(clang) int __argc; char **__argv; #if !is(ems) @@ -356746,8 +370845,8 @@ static char **backtrace_symbols(void *const *list,int size) { static __thread char **symbols = 0; //[32][64] = {0}; if( !symbols ) { - symbols = SYS_REALLOC(0, 128 * sizeof(char*)); - for( int i = 0; i < 128; ++i) symbols[i] = SYS_REALLOC(0, 128 * sizeof(char)); + symbols = SYS_MEM_REALLOC(0, 128 * sizeof(char*)); + for( int i = 0; i < 128; ++i) symbols[i] = SYS_MEM_REALLOC(0, 128 * sizeof(char)); } if(size > 128) size = 128; @@ -356780,7 +370879,7 @@ static char **backtrace_symbols(void *const *sym,int num) { return 0; } char *callstack( int traces ) { static __thread char *output = 0; - if(!output ) output = SYS_REALLOC( 0, 128 * (64+2) ); + if(!output ) output = SYS_MEM_REALLOC( 0, 128 * (64+2) ); if( output ) output[0] = '\0'; char *ptr = output; @@ -357339,7 +371438,7 @@ int (PRINTF)(const char *text, const char *stack, const char *file, int line, co static void *panic_oom_reserve; // for out-of-memory recovery int (PANIC)(const char *error, const char *file, int line) { - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 0); + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 0); tty_color(RED); @@ -357515,7 +371614,7 @@ int (test)(const char *file, int line, const char *expr, bool result) { } #line 0 -#line 1 "engine/split/v4k_time.c" +#line 1 "v4k_time.c" // ---------------------------------------------------------------------------- // time @@ -358155,7 +372254,7 @@ void curve_destroy(curve_t *c) { } #line 0 -#line 1 "engine/split/v4k_profile.c" +#line 1 "v4k_profile.c" #if ENABLE_PROFILER profiler_t profiler; int profiler_enabled = 1; @@ -358213,7 +372312,7 @@ void (ui_profiler)() { #endif #line 0 -#line 1 "engine/split/v4k_video.c" +#line 1 "v4k_video.c" // tip: convert video to x265/mp4. note: higher crf to increase compression (default crf is 28) // ffmpeg -i {{infile}} -c:v libx265 -crf 24 -c:a copy {{outfile}} @@ -358445,7 +372544,7 @@ void record_frame() { } #line 0 -#line 1 "engine/split/v4k_window.c" +#line 1 "v4k_window.c" //----------------------------------------------------------------------------- // fps locking @@ -358872,7 +372971,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) { #define ddraw_progress_bar(JOB_ID, JOB_MAX, PERCENT) do { \ /* NDC coordinates (2d): bottom-left(-1,-1), center(0,0), top-right(+1,+1) */ \ float progress = (PERCENT+1) / 100.f; if(progress > 1) progress = 1; \ - float speed = progress < 1 ? 0.2f : 0.5f; \ + float speed = progress < 1 ? 0.05f : 0.75f; \ float smooth = previous[JOB_ID] = progress * speed + previous[JOB_ID] * (1-speed); \ \ float pixel = 2.f / window_height(), dist = smooth*2-1, y = pixel*3*JOB_ID; \ @@ -359534,7 +373633,7 @@ double window_scale() { // ok? @testme } #line 0 -#line 1 "engine/split/v4k_obj.c" +#line 1 "v4k_obj.c" // ----------------------------------------------------------------------------- // factory of handle ids, based on code by randy gaul (PD/Zlib licensed) // - rlyeh, public domain @@ -360546,7 +374645,7 @@ void *obj_make(const char *str) { } #line 0 -#line 1 "engine/split/v4k_ai.c" +#line 1 "v4k_ai.c" // AI framework // - rlyeh, public domain. // @@ -361384,7 +375483,7 @@ int ui_bt(bt_t *b) { } #line 0 -#line 1 "engine/split/v4k_editor.c" +#line 1 "v4k_editor0.c" // editing: // nope > functions: add/rem property @@ -361917,158 +376016,9 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) { return modified; } -// -- localization kit - -static const char *kit_lang = "enUS", *kit_langs = - "enUS,enGB," - "frFR," - "esES,esAR,esMX," - "deDE,deCH,deAT," - "itIT,itCH," - "ptBR,ptPT," - "zhCN,zhSG,zhTW,zhHK,zhMO," - "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," - "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" -; - -static map(char*,char*) kit_ids; -static map(char*,char*) kit_vars; - -#ifndef KIT_FMT_ID2 -#define KIT_FMT_ID2 "%s.%s" -#endif - -void kit_init() { - do_once map_init(kit_ids, less_str, hash_str); - do_once map_init(kit_vars, less_str, hash_str); -} - -void kit_insert( const char *id, const char *translation) { - char *id2 = va(KIT_FMT_ID2, kit_lang, id); - - char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); - if(*found) FREE(*found); - *found = STRDUP(translation); -} - -bool kit_merge( const char *filename ) { - // @todo: xlsx2ini - return false; -} - -void kit_clear() { - map_clear(kit_ids); -} - -bool kit_load( const char *filename ) { - return kit_clear(), kit_merge( filename ); -} - -void kit_set( const char *key, const char *value ) { - value = value && value[0] ? value : ""; - - char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); - if(*found) FREE(*found); - *found = STRDUP(value); -} - -void kit_reset() { - map_clear(kit_vars); -} - -char *kit_translate2( const char *id, const char *lang ) { - char *id2 = va(KIT_FMT_ID2, lang, id); - - char **found = map_find(kit_ids, id2); - - // return original [[ID]] if no translation is found - if( !found ) return va("[[%s]]", id); - - // return translation if no {{moustaches}} are found - if( !strstr(*found, "{{") ) return *found; - - // else replace all found {{moustaches}} with context vars - { - // make room - static __thread char *results[16] = {0}; - static __thread unsigned counter = 0; counter = (counter+1) % 16; - - char *buffer = results[ counter ]; - if( buffer ) FREE(buffer), buffer = 0; - - // iterate moustaches - const char *begin, *end, *text = *found; - while( NULL != (begin = strstr(text, "{{")) ) { - end = strstr(begin+2, "}}"); - if( end ) { - char *var = va("%.*s", (int)(end - (begin+2)), begin+2); - char **found_var = map_find(kit_vars, var); - - if( found_var && 0[*found_var] ) { - strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); - } else { - strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); - } - - text = end+2; - } else { - strcatf(&buffer, "%.*s", (int)(begin - text), text); - - text = begin+2; - } - } - - strcatf(&buffer, "%s", text); - return buffer; - } -} - -char *kit_translate( const char *id ) { - return kit_translate2( id, kit_lang ); -} - -void kit_locale( const char *lang ) { - kit_lang = STRDUP(lang); // @leak -} - -void kit_dump_state( FILE *fp ) { - for each_map(kit_ids, char *, k, char *, v) { - fprintf(fp, "[ID ] %s=%s\n", k, v); - } - for each_map(kit_vars, char *, k, char *, v) { - fprintf(fp, "[VAR] %s=%s\n", k, v); - } -} - -/* -int main() { - kit_init(); - - kit_locale("enUS"); - kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Nice to meet you."); - - kit_locale("esES"); - kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Un placer conoceros."); - - kit_locale("enUS"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. - - kit_locale("esES"); - kit_set("PLAYER1", "John"); - kit_set("PLAYER2", "Karl"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. - - assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] - assert(~puts("Ok")); -} -*/ #line 0 -// editor is last in place, so it can use all internals from above headers - -#line 1 "engine/split/v4k_main.c" +#line 1 "v4k_main.c" // ---------------------------------------------------------------------------- static void v4k_pre_init() { @@ -362135,7 +376085,7 @@ void v4k_init() { ifdef(debug, trap_install()); // init panic handler - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 1<<20); // 1MiB + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 1<<20); // 1MiB // init glfw glfw_init(); @@ -362161,7 +376111,2155 @@ void v4k_init() { } #line 0 -#line 1 "engine/split/v4k_end.c" +// editor is last in place, so it can use all internals from above headers +#line 1 "v4k_editor.c" +// ## Editor long-term plan +// - editor = tree of nodes. levels and objects are nodes, and their widgets are also nodes +// - you can perform actions on nodes, with or without descendants, top-bottom or bottom-top +// - these operations include load/save, undo/redo, reset, play/render, ddraw, etc +// - nodes are saved to disk as a filesystem layout: parents are folders, and leafs are files +// - network replication can be done by external tools by comparing the filesystems and by sending the resulting diff zipped +// +// ## Editor roadmap +// - Gizmos?, scene tree, property editor?, load/save?, undo/redo?, copy/paste, on/off (vis,tick,ddraw,log), vcs. +// - Scenenode pass: node singleton display, node console, node labels, node outlines?. +// - Render pass: billboards?, materials, un/lit, cast shadows, wireframe, skybox?/mie?, fog/atmosphere +// - Level pass: volumes, triggers, platforms, level streaming, collide?, physics +// - Edit pass: Procedural content, brushes, noise and CSG. +// - GUI pass: timeline and data tracks, node graphs. + +// ## Alt plan +// editor is a database + window/tile manager + ui toolkit; all network driven. +// to be precise, editor is a dumb app and ... +// - does not know a thing about what it stores. +// - does not know how to render the game graphics. +// - does not know how to run the game logic. +// +// the editor will create a canvas for your game to render. +// your game will be responsible to tick the logic and render the window inside the editor. +// +// that being said, editor... +// - can store datas hierarchically. +// - can perform diffs and merges, and version the datas into repositories. +// - can be instructed to render UI on top of game and window views. +// - can download new .natvis and plugins quickly. +// - can dump whole project in a filesystem form (zip). + +// - editor reflects database contents up-to-date. +// - database can be queried and modified via OSC(UDP) commands. + +// editor database uses one table, and stores two kind of payload types: +// - classes: defines typename and dna. class names are prefixed by '@' +// - instances: defines typename and datas. instance names are as-is, not prefixed. +// +// every save contains 5Ws: what, who, when, where, how, +// every save can be diffed/merged. + +// ---------------------------------------------------------------------------- + +#define EDITOR_VERSION "2023.10" + +// ---------------------------------------------------------------------------- + +typedef struct editor_bind_t { + const char *command; + const char *bindings; + void (*fn)(); +} editor_bind_t; + +array(editor_bind_t) editor_binds; + +#define EDITOR_BIND(CMD,KEYS,...) void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); } + +// ---------------------------------------------------------------------------- + +typedef void (*editor_no_property)(void *); +array(void*) editor_persist_kv; +array(editor_no_property) editor_no_properties; + +#define EDITOR_PROPERTY(property_name,T,defaults) \ +typedef map(void*,T) editor_##property_name##_map_t; \ +editor_##property_name##_map_t *editor_##property_name##_map() { \ + static editor_##property_name##_map_t map = 0; do_once map_init_ptr(map); \ + return ↦ \ +} \ +T editor_##property_name(const void *obj) { \ + return *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ +} \ +void editor_set##property_name(const void *obj, T value) { \ + *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) value)) = ((T) value); \ +} \ +void editor_alt##property_name(const void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + *found = (T)(uintptr_t)!(*found); \ +} \ +void editor_no##property_name(void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + map_erase(*editor_##property_name##_map(), (void*)obj); \ +} \ +AUTORUN { array_push(editor_persist_kv, #T); array_push(editor_persist_kv, editor_##property_name##_map()); array_push(editor_no_properties, editor_no##property_name); } + +EDITOR_PROPERTY(open, int, 0); // whether object is tree opened in tree editor +EDITOR_PROPERTY(selected, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(changed, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(popup, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(visible, int, 0); +EDITOR_PROPERTY(script, int, 0); +EDITOR_PROPERTY(event, int, 0); +EDITOR_PROPERTY(iconinstance, char*, 0); +EDITOR_PROPERTY(iconclass, char*, 0); +EDITOR_PROPERTY(treeoffsety, int, 0); +// new prop: breakpoint: request to break on any given node +// new prop: persist: objects with this property will be saved on disk + +void editor_destroy_properties(void *o) { + for each_array(editor_no_properties,editor_no_property,fn) { + fn(o); + } +} + +void editor_load_on_boot(void) { +} +void editor_save_on_quit(void) { +} +AUTORUN { + editor_load_on_boot(); + (atexit)(editor_save_on_quit); +} + +// ---------------------------------------------------------------------------- + +typedef int(*subeditor)(int mode); + +struct editor_t { + // time + unsigned frame; + double t, dt, slomo; + // controls + int transparent; + int attached; + int active; // focus? does_grabinput instead? + int key; + vec2 mouse; // 2d coord for ray/picking + bool gamepad; // mask instead? |1|2|4|8 + int hz_high, hz_medium, hz_low; + int filter; + bool battery; // battery mode: low fps + bool unlit; + bool ddraw; + // event root nodes + obj* root; + obj* on_init; + obj* on_tick; + obj* on_draw; + obj* on_edit; + obj* on_quit; + // all of them (hierarchical) + array(obj*) objs; // @todo:set() world? + // all of them (flat) + set(obj*) world; + // + array(char*) cmds; + // subeditors + array(subeditor) subeditors; +} editor = { + .active = 1, + .gamepad = 1, + .hz_high = 60, .hz_medium = 18, .hz_low = 5, +}; + +enum { + EDITOR_PANEL, + EDITOR_WINDOW, + EDITOR_WINDOW_NK, + EDITOR_WINDOW_NK_SMALL, +}; + +int editor_begin(const char *title, int mode) { + if( mode == 0 ) return ui_panel(title, PANEL_OPEN); + if( mode == 1 ) return ui_window(title, 0); + + int ww = window_width(), w = ww * 0.66; + int hh = window_height(), h = hh * 0.66; + + struct nk_rect position = { (ww-w)/2,(hh-h)/2, w,h }; + nk_flags win_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER | + NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | + NK_WINDOW_CLOSABLE | NK_WINDOW_MINIMIZABLE | + // NK_WINDOW_SCALE_LEFT|NK_WINDOW_SCALE_TOP| //< @fixme: move this logic into nuklear + // NK_WINDOW_MAXIMIZABLE | NK_WINDOW_PINNABLE | + 0; // NK_WINDOW_SCROLL_AUTO_HIDE; + + if( mode == 3 ) { + mode = 2, position.x = input(MOUSE_X), position.w = w/3, win_flags = + NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE| + NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE| //< nuklear requires these two to `remember` popup rects + 0; + } + + if( mode == 2 || mode == 3 ) + if (nk_begin(ui_ctx, title, position, win_flags)) + return 1; + else + return nk_end(ui_ctx), 0; + + return 0; +} +int editor_end(int mode) { + if( mode == 0 ) return ui_panel_end(); + if( mode == 1 ) return ui_window_end(); + if( mode == 2 ) nk_end(ui_ctx); + if( mode == 3 ) nk_end(ui_ctx); + return 0; +} + +#if 0 // deprecate +bool editor_active() { + return ui_hover() || ui_active() || gizmo_active() ? editor.active : 0; +} +#endif + +int editor_filter() { + if( editor.filter ) { + if (nk_begin(ui_ctx, "Filter", nk_rect(window_width()-window_width()*0.33,32, window_width()*0.33, 40), + NK_WINDOW_NO_SCROLLBAR)) { + + char *bak = ui_filter; ui_filter = 0; + ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak); + ui_filter = bak; + + if( input(KEY_ESC) || ( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 )) { + if( ui_filter ) ui_filter[0] = '\0'; + editor.filter = 0; + } + } + nk_end(ui_ctx); + } + + return editor.filter; + } + +static +int editor_select_(void *o, const char *mask) { + int matches = 0; + int off = mask[0] == '!', inv = mask[0] == '~'; + int match = strmatchi(obj_type(o), mask+off+inv) || strmatchi(obj_name(o), mask+off+inv); + if( match ) { + editor_setselected(o, inv ? editor_selected(o) ^ 1 : !off); + ++matches; + } + for each_objchild(o, obj*, oo) { + matches += editor_select_(oo, mask); + } + return matches; +} +void editor_select(const char *mask) { + for each_array( editor.objs, obj*, o ) + editor_select_(o, mask); +} +void editor_unselect() { // same than editor_select("!**"); + for each_map_ptr(*editor_selected_map(), void*,o, int, k) { + if( *k ) *k = 0; + } + } + +void editor_select_aabb(aabb box) { + int is_inv = input_held(KEY_CTRL); + int is_add = input_held(KEY_SHIFT); + if( !is_inv && !is_add ) editor_unselect(); + + aabb item = {0}; + for each_set_ptr( editor.world, obj*, o ) { + if( obj_hasmethod(*o,aabb) && obj_aabb(*o, &item) ) { + if( aabb_test_aabb(item, box) ) { + if( is_inv ) + editor_altselected(*o); + else + editor_setselected(*o, 1); + } + } + } +} + +static obj* active_ = 0; +static void editor_selectgroup_(obj *o, obj *first, obj *last) { + // printf("%s (looking for %s in [%s..%s])\n", obj_name(o), active_ ? obj_name(active_) : "", obj_name(first), obj_name(last)); + if( !active_ ) if( o == first || o == last ) active_ = o == first ? last : first; + if( active_ ) editor_setselected(o, 1); + if( o == active_ ) active_ = 0; + for each_objchild(o, obj*, oo) { + editor_selectgroup_(oo, first, last); + } +} +void editor_selectgroup(obj *first, obj *last) { + if( last ) { + if( !first ) first = array_count(editor.objs) ? editor.objs[0] : NULL; + if( !first ) editor_setselected(last, 1); + else { + active_ = 0; + for each_array(editor.objs,obj*,o) { + editor_selectgroup_(o, first, last); + } + } + } + } + +static obj *find_any_selected_(obj *o) { + if( editor_selected(o) ) return o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_any_selected_(oo); + if( ooo ) + return ooo; + } + return 0; +} +void* editor_first_selected() { + for each_array(editor.objs,obj*,o) { + obj *oo = find_any_selected_(o); + // if( oo ) printf("1st found: %s\n", obj_name(oo)); + if( oo ) return oo; +} + return 0; +} + +static obj *find_last_selected_(obj *o) { + void *last = 0; + if( editor_selected(o) ) last = o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_last_selected_(oo); + if( ooo ) + last = ooo; +} + return last; +} +void* editor_last_selected() { + void *last = 0; + for each_array(editor.objs,obj*,o) { + obj *oo = find_last_selected_(o); + // if( oo ) printf("last found: %s\n", obj_name(oo)); + if( oo ) last = oo; +} + return last; +} + +// ---------------------------------------------------------------------------------------- + +void editor_addtoworld(obj *o) { + set_find_or_add(editor.world, o); + for each_objchild(o, obj*, oo) { + editor_addtoworld(oo); +} +} + +void editor_watch(const void *o) { + array_push(editor.objs, (obj*)o); + obj_push(o); // save state + + editor_addtoworld((obj*)o); +} +void* editor_spawn(const char *ini) { // deprecate? + obj *o = obj_make(ini); + editor_watch(o); + return o; +} +void editor_spawn1() { + obj *selected = editor_first_selected(); + obj *o = selected ? obj_make(obj_saveini(selected)) : obj_new(obj); + if( selected ) obj_attach(selected, o), editor_setopen(selected, 1); + else + editor_watch(o); + + editor_unselect(); + editor_setselected(o, 1); +} + +typedef set(obj*) set_objp_t; +static +void editor_glob_recurse(set_objp_t*list, obj *o) { + set_find_or_add(*list, o); + for each_objchild(o,obj*,oo) { + editor_glob_recurse(list, oo); + } +} +void editor_destroy_selected() { + set_objp_t list = 0; + set_init_ptr(list); + for each_map_ptr(*editor_selected_map(), obj*,o, int,selected) { + if( *selected ) { editor_glob_recurse(&list, *o); } + } + for each_set(list, obj*, o) { + obj_detach(o); + } + for each_set(list, obj*, o) { + // printf("deleting %p %s\n", o, obj_name(o)); + // remove from watched items + for (int i = 0, end = array_count(editor.objs); i < end; ++i) { + if (editor.objs[i] == o) { + editor.objs[i] = 0; + array_erase_slow(editor.objs, i); + --end; + --i; + } + } + // delete from world + set_erase(editor.world, o); + // delete properties + obj + editor_destroy_properties(o); + obj_free(o); + } + set_free(list); +} +void editor_inspect(obj *o) { + ui_section(va("%s (%s)", obj_type(o), obj_name(o))); + + if( obj_hasmethod(o, menu) ) { + obj_menu(o); + } + + for each_objmember(o,TYPE,NAME,PTR) { + if( !editor_changed(PTR) ) { + obj_push(o); + } + ui_label_icon_highlight = editor_changed(PTR); // @hack: remove ui_label_icon_highlight hack + char *label = va(ICON_MD_UNDO "%s", NAME); + int changed = 0; + /**/ if( !strcmp(TYPE,"float") ) changed = ui_float(label, PTR); + else if( !strcmp(TYPE,"int") ) changed = ui_int(label, PTR); + else if( !strcmp(TYPE,"vec2") ) changed = ui_float2(label, PTR); + else if( !strcmp(TYPE,"vec3") ) changed = ui_float3(label, PTR); + else if( !strcmp(TYPE,"vec4") ) changed = ui_float4(label, PTR); + else if( !strcmp(TYPE,"rgb") ) changed = ui_color3(label, PTR); + else if( !strcmp(TYPE,"rgba") ) changed = ui_color4(label, PTR); + else if( !strcmp(TYPE,"color") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"color3f") ) changed = ui_color3f(label, PTR); + else if( !strcmp(TYPE,"color4f") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"char*") ) changed = ui_string(label, PTR); + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + if( changed ) { + editor_setchanged(PTR, 1); + } + if( ui_label_icon_highlight ) + if( ui_label_icon_clicked_L.x >= 6 && ui_label_icon_clicked_L.x <= 26 ) { // @hack: if clicked on UNDO icon (1st icon) + editor_setchanged(PTR, 0); + } + if( !editor_changed(PTR) ) { + obj_pop(o); + } + } +} + +// ---------------------------------------------------------------------------------------- +// tty + +static thread_mutex_t *console_lock; +static array(char*) editor_jobs; +int editor_send(const char *cmd) { // return job-id + int skip = strspn(cmd, " \t\r\n"); + char *buf = STRDUP(cmd + skip); + strswap(buf, "\r\n", ""); + int jobid; + do_threadlock(console_lock) { + array_push(editor_jobs, buf); + jobid = array_count(editor_jobs) - 1; + } + return jobid; +} +const char* editor_recv(int jobid, double timeout_ss) { + char *answer = 0; + + while(!answer && timeout_ss >= 0 ) { + do_threadlock(console_lock) { + if( editor_jobs[jobid][0] == '\0' ) + answer = editor_jobs[jobid]; + } + timeout_ss -= 0.1; + if( timeout_ss > 0 ) sleep_ms(100); // thread_yield() + } + + return answer + 1; +} + +// plain and ctrl keys +EDITOR_BIND(play, "down(F5)", { window_pause(0); /* if(!editor.slomo) editor.active = 0; */ editor.slomo = 1; } ); +EDITOR_BIND(stop, "down(ESC)", { if(editor.t > 0) { window_pause(1), editor.frame = 0, editor.t = 0, editor.dt = 0, editor.slomo = 0, editor.active = 1; editor_select("**"); editor_destroy_selected(); }} ); +EDITOR_BIND(eject, "down(F1)", { /*window_pause(!editor.active); editor.slomo = !!editor.active;*/ editor.active ^= 1; } ); +EDITOR_BIND(pause, "(held(CTRL) & down(P)) | down(PAUSE)", { window_pause( window_has_pause() ^ 1 ); } ); +EDITOR_BIND(frame, "held(CTRL) & down(LEFT)", { window_pause(1); editor.frame++, editor.t += (editor.dt = 1/60.f); } ); +EDITOR_BIND(slomo, "held(CTRL) & down(RIGHT)", { window_pause(0); editor.slomo = maxf(fmod(editor.slomo * 2, 16), 0.125); } ); +EDITOR_BIND(reload, "held(CTRL) & down(F5)", { window_reload(); } ); +EDITOR_BIND(filter, "held(CTRL) & down(F)", { editor.filter ^= 1; } ); + +// alt keys +EDITOR_BIND(quit, "held(ALT) & down(F4)", { record_stop(), exit(0); } ); +EDITOR_BIND(mute, "held(ALT) & down(M)", { audio_volume_master( 1 ^ !!audio_volume_master(-1) ); } ); +EDITOR_BIND(gamepad, "held(ALT) & down(G)", { editor.gamepad ^= 1; } ); +EDITOR_BIND(transparent, "held(ALT) & down(T)", { editor.transparent ^= 1; } ); +EDITOR_BIND(record, "held(ALT) & down(Z)", { if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else { char *name = file_counter(va("%s.mp4",app_name())); app_beep(), window_record(name); } } ); +EDITOR_BIND(screenshot, "held(ALT) & down(S)", { char *name = file_counter(va("%s.png",app_name())); window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); } ); +EDITOR_BIND(battery, "held(ALT) & down(B)", { editor.battery ^= 1; } ); +EDITOR_BIND(outliner, "held(ALT) & down(O)", { ui_show("Outliner", ui_visible("Outliner") ^ true); } ); +EDITOR_BIND(profiler, "held(ALT) & down(P)", { ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); } ); +EDITOR_BIND(fullscreen, "(held(ALT)&down(ENTER))|down(F11)",{ record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); } ); // close any recording before framebuffer resizing, which would corrupt video stream +EDITOR_BIND(unlit, "held(ALT) & down(U)", { editor.unlit ^= 1; } ); +EDITOR_BIND(ddraw, "held(ALT) & down(D)", { editor.ddraw ^= 1; } ); + +void editor_pump() { + for each_array(editor_binds,editor_bind_t,b) { + if( input_eval(b.bindings) ) { + editor_send(b.command); + } + } + + do_threadlock(console_lock) { + for each_array_ptr(editor_jobs,char*,cmd) { + if( (*cmd)[0] ) { + int found = 0; + for each_array(editor_binds,editor_bind_t,b) { + if( !strcmpi(b.command, *cmd)) { + b.fn(); + found = 1; + break; + } + } + + if( !found ) { + // alert(va("Editor: could not handle `%s` command.", *cmd)); + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Err\n"); (*cmd)[0] = '\0'; + } + + if( (*cmd)[0] ) { + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Ok\n"); (*cmd)[0] = '\0'; + } + } + } + } +} + +// ---------------------------------------------------------------------------------------- + +void editor_symbol(int x, int y, const char *sym) { + #define FONT_SYMBOLS FONT_FACE2 + #define FONT_WHITE FONT_COLOR1 + #define FONT_YELLOW FONT_COLOR2 + #define FONT_ORANGE FONT_COLOR3 + #define FONT_CYAN FONT_COLOR4 + // style: atlas size, unicode ranges and 6 font faces max + do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); + // style: 10 colors max + do_once font_color(FONT_WHITE, WHITE); + do_once font_color(FONT_YELLOW, YELLOW); + do_once font_color(FONT_CYAN, CYAN); + do_once font_color(FONT_ORANGE, ORANGE); + font_goto(x,y); + font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym)); +} + +void editor_frame( void (*game)(unsigned, float, double) ) { + do_once { + set_init_ptr(editor.world); + //set_init_ptr(editor.selection); + profiler_enable( false ); + + window_pause( true ); + window_cursor_shape(CURSOR_SW_AUTO); + editor.hz_high = window_fps_target(); + + fx_load("editorOutline.fs"); + fx_enable(0, 1); + + obj_setname(editor.root = obj_new(obj), "Signals"); + obj_setname(editor.on_init = obj_new(obj), "onInit"); + obj_setname(editor.on_tick = obj_new(obj), "onTick"); + obj_setname(editor.on_draw = obj_new(obj), "onDraw"); + obj_setname(editor.on_edit = obj_new(obj), "onEdit"); + obj_setname(editor.on_quit = obj_new(obj), "onQuit"); + + obj_attach(editor.root, editor.on_init); + obj_attach(editor.root, editor.on_tick); + obj_attach(editor.root, editor.on_draw); + obj_attach(editor.root, editor.on_edit); + obj_attach(editor.root, editor.on_quit); + + editor_seticoninstance(editor.root, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_init, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_tick, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_draw, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_edit, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_quit, ICON_MDI_SIGNAL_VARIANT); + + editor_seticonclass(obj_type(editor.root), ICON_MDI_CUBE_OUTLINE); + } + + // game tick + game(editor.frame, editor.dt, editor.t); + + // timing + editor.dt = clampf(window_delta(), 0, 1/60.f) * !window_has_pause() * editor.slomo; + editor.t += editor.dt; + editor.frame += !window_has_pause(); + editor.frame += !editor.frame; + + // process inputs & messages + editor_pump(); + + // adaptive framerate + int app_on_background = !window_has_focus(); + int hz = app_on_background ? editor.hz_low : editor.battery ? editor.hz_medium : editor.hz_high; + window_fps_lock( hz < 5 ? 5 : hz ); + + // draw menubar + static int stats_mode = 1; + static double last_fps = 0; if(!window_has_pause()) last_fps = window_fps(); + const char *STATS = va("x%4.3f %03d.%03dss %02dF %s", + editor.slomo, (int)editor.t, (int)(1000 * (editor.t - (int)editor.t)), + (editor.frame-1) % ((int)window_fps_target() + !(int)window_fps_target()), + stats_mode == 1 ? va("%5.2f/%dfps", last_fps, (int)window_fps_target()) : stats_mode == 0 ? "0/0 KiB" : xstats()); + const char *ICON_PL4Y = window_has_pause() ? ICON_MDI_PLAY : ICON_MDI_PAUSE; + const char *ICON_SKIP = window_has_pause() ? ICON_MDI_STEP_FORWARD/*ICON_MDI_SKIP_NEXT*/ : ICON_MDI_FAST_FORWARD; + + int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED); + int ingame = !editor.active; + static double clicked_titlebar = 0; + UI_MENU(14+is_borderless, \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \ + UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \ + UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \ + UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \ + UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \ + UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \ + UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \ + UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \ + UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \ + UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \ + UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \ + UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \ + ); + + if( is_borderless ) { + static vec3 drag = {0}; + if( clicked_titlebar ) { + static double clicks = 0; + if( input_up(MOUSE_L) ) ++clicks; + if( input_up(MOUSE_L) && clicks == 2 ) window_visible(false), window_maximize( window_has_maximize() ^ 1 ), window_visible(true); + if( (time_ms() - clicked_titlebar) > 400 ) clicks = 0, clicked_titlebar = 0; + + if( input_down(MOUSE_L) ) drag = vec3(input(MOUSE_X), input(MOUSE_Y), 1); + } + if( drag.z *= !input_up(MOUSE_L) ) { + int wx = 0, wy = 0; + glfwGetWindowPos(window_handle(), &wx, &wy); + glfwSetWindowPos(window_handle(), wx + input(MOUSE_X) - drag.x, wy + input(MOUSE_Y) - drag.y); + } + } + + if( !editor.active ) return; + + // draw edit view (gizmos, position markers, etc). + for each_set_ptr(editor.world,obj*,o) { + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); + } +} + + // draw silhouettes + sprite_flush(); + fx_begin(); + for each_map_ptr(*editor_selected_map(),void*,o,int,selected) { + if( !*selected ) continue; + if( obj_hasmethod(*o,draw) ) { + obj_draw(*o); + } + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); +} +} + sprite_flush(); + fx_end(); + + // draw box selection + if( !ui_active() ) { //< check that we're not moving a window + static vec2 from = {0}, to = {0}; + if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to; + if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)); + if( len2sq(sub2(from,to)) > 0 ) { + vec2 a = min2(from, to), b = max2(from, to); + ddraw_push_2d(); + ddraw_color_push(YELLOW); + ddraw_line( vec3(a.x,a.y,0),vec3(b.x-1,a.y,0) ); + ddraw_line( vec3(b.x,a.y,0),vec3(b.x,b.y-1,0) ); + ddraw_line( vec3(b.x,b.y,0),vec3(a.x-1,b.y,0) ); + ddraw_line( vec3(a.x,b.y,0),vec3(a.x,a.y-1,0) ); + ddraw_color_pop(); + ddraw_pop_2d(); + } + if( input_up(MOUSE_L) ) { + vec2 a = min2(from, to), b = max2(from, to); + from = to = vec2(0,0); + + editor_select_aabb(aabb(vec3(a.x,a.y,0),vec3(b.x,b.y,0))); + } + } + + // draw mouse aabb + aabb mouse = { vec3(input(MOUSE_X),input(MOUSE_Y),0), vec3(input(MOUSE_X),input(MOUSE_Y),1)}; + if( 1 ) { + ddraw_color_push(YELLOW); + ddraw_push_2d(); + ddraw_aabb(mouse.min, mouse.max); + ddraw_pop_2d(); + ddraw_color_pop(); + } + + // tick mouse aabb selection and contextual tab (RMB) + aabb box = {0}; + for each_set(editor.world,obj*,o) { + if( !obj_hasmethod(o, aabb) ) continue; + if( !obj_aabb(o, &box) ) continue; + + // trigger contextual inspector + if( input_down(MOUSE_R) ) { + int is_selected = editor_selected(o); + editor_setpopup(o, is_selected); + } + + // draw contextual inspector + if( editor_popup(o) ) { + if( editor_begin(va("%s (%s)", obj_name(o), obj_type(o)),EDITOR_WINDOW_NK_SMALL) ) { + ui_label2(obj_name(o), obj_type(o)); + editor_inspect(o); + editor_end(EDITOR_WINDOW_NK_SMALL); + } else { + editor_setpopup(o, 0); + } + } +} + + + // draw subeditors + static int preferred_window_mode = EDITOR_WINDOW; + static struct nk_color bak, *on = 0; do_once bak = ui_ctx->style.window.fixed_background.data.color; // ui_ctx->style.window.fixed_background.data.color = !!(on = (on ? NULL : &bak)) ? AS_NKCOLOR(0) : bak; }; + if( editor.transparent ) ui_ctx->style.window.fixed_background.data.color = AS_NKCOLOR(0); + for each_array(editor.subeditors, subeditor, fn) { + fn(preferred_window_mode); + } + ui_ctx->style.window.fixed_background.data.color = bak; + + // draw ui filter (note: render at end-of-frame, so it's hopefully on-top) + editor_filter(); +} +#line 0 +#line 1 "v4k_editor_scene.h" +#define SCENE_ICON ICON_MDI_FILE_TREE +#define SCENE_TITLE "Scene " SCENE_ICON + +EDITOR_BIND(scene, "held(CTRL)&down(1)", { ui_show(SCENE_TITLE, ui_visible(SCENE_TITLE) ^ true); }); + +EDITOR_PROPERTY(bookmarked, int, 0); + +EDITOR_BIND(node_new, "down(INS)", { editor_spawn1(); } ); +EDITOR_BIND(node_del, "down(DEL)", { editor_destroy_selected(); } ); +EDITOR_BIND(node_save, "held(CTRL)&down(S)", { puts("@todo"); } ); +EDITOR_BIND(scene_save, "held(CTRL)&down(S)&held(SHIFT)",{ puts("@todo"); } ); +EDITOR_BIND(select_all, "held(CTRL) & down(A)", { editor_select("**"); } ); +EDITOR_BIND(select_none, "held(CTRL) & down(D)", { editor_select("!**"); } ); +EDITOR_BIND(select_invert, "held(CTRL) & down(I)", { editor_select("~**"); } ); +EDITOR_BIND(bookmark, "held(CTRL) & down(B)", { editor_selected_map_t *map = editor_selected_map(); \ + int on = 0; \ + for each_map_ptr(*map,void*,o,int,selected) if(*selected) on |= !editor_bookmarked(*o); \ + for each_map_ptr(*map,void*,o,int,selected) if(*selected) editor_setbookmarked(*o, on); \ +} ); + +enum { + SCENE_RECURSE = 1, + SCENE_SELECTION = 2, + SCENE_CHECKBOX = 4, + SCENE_INDENT = 8, + SCENE_ALL = ~0u +}; + +static +void editor_scene_(obj *o, unsigned flags) { + static unsigned tabs = ~0u; + ++tabs; + + if( o ) { + unsigned do_tags = 1; + unsigned do_indent = !!(flags & SCENE_INDENT); + unsigned do_checkbox = !!(flags & SCENE_CHECKBOX); + unsigned do_recurse = !!(flags & SCENE_RECURSE); + unsigned do_selection = !!(flags & SCENE_SELECTION); + + nk_layout_row_dynamic(ui_ctx, 25, 1); + + const char *objicon = editor_iconinstance(o); + if(!objicon) objicon = editor_iconclass(obj_type(o)); + if(!objicon) objicon = ICON_MDI_CUBE_OUTLINE; + + const char *objname = va("%s (%s)", obj_type(o), obj_name(o)); + + const char *objchevron = + !do_recurse || array_count(*obj_children(o)) <= 1 ? ICON_MDI_CIRCLE_SMALL : + editor_open(o) ? ICON_MDI_CHEVRON_DOWN : ICON_MDI_CHEVRON_RIGHT; + + char *label = va("%*s%s%s %s", do_indent*(4+2*tabs), "", objchevron, objicon, objname); + + const char *iconsL = + //editor_selected(o) ? ICON_MD_CHECK_BOX : ICON_MD_CHECK_BOX_OUTLINE_BLANK; + editor_selected(o) ? ICON_MDI_CHECKBOX_MARKED : ICON_MDI_CHECKBOX_BLANK_OUTLINE; + + const char *iconsR = va("%s%s%s", + editor_script(o) ? ICON_MDI_SCRIPT : ICON_MDI_CIRCLE_SMALL, + editor_event(o) ? ICON_MDI_CALENDAR : ICON_MDI_CIRCLE_SMALL, + editor_visible(o) ? ICON_MDI_EYE_OUTLINE : ICON_MDI_EYE_CLOSED ); + + UI_TOOLBAR_OVERLAY_DECLARE(int choiceL, choiceR); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); + + int clicked = nk_hovered_text(ui_ctx, label, strlen(label), NK_TEXT_LEFT, editor_selected(o)); + if( clicked && nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,bounds.w*0.66,bounds.h })) ) + editor_altselected( o ); + + vec2i offset_in_tree = {0}; + + if( do_indent ) { + float thickness = 2.f; + struct nk_color color = {255,255,255,64}; + + int offsx = 30; + int spacx = 10; + int lenx = (tabs+1)*spacx; + int halfy = bounds.h / 2; + int offsy = halfy + 2; + + offset_in_tree = vec2i(bounds.x+offsx+lenx-spacx,bounds.y+offsy); + + editor_settreeoffsety(o, offset_in_tree.y); + + for( obj *p = obj_parent(o); p ; p = 0 ) + nk_stroke_line(canvas, offset_in_tree.x-6,offset_in_tree.y, offset_in_tree.x-spacx,offset_in_tree.y, thickness, color), + nk_stroke_line(canvas, offset_in_tree.x-spacx,offset_in_tree.y,offset_in_tree.x-spacx,editor_treeoffsety(p)+4, thickness, color); + } + + if( ui_contextual() ) { + int choice = ui_label(ICON_MD_BOOKMARK_ADDED "Toggle bookmarks (CTRL+B)"); + if( choice & 1 ) editor_send("bookmark"); + + ui_contextual_end(!!choice); + } + + UI_TOOLBAR_OVERLAY(choiceL,iconsL,nk_rgba_f(1,1,1,do_checkbox*ui_alpha*0.65),NK_TEXT_LEFT); + + if( do_tags ) + UI_TOOLBAR_OVERLAY(choiceR,iconsR,nk_rgba_f(1,1,1,ui_alpha*0.65),NK_TEXT_RIGHT); + + if( choiceR == 3 ) editor_altscript( o ); + if( choiceR == 2 ) editor_altevent( o); + if( choiceR == 1 ) editor_altvisible( o ); + + if( do_recurse && editor_open(o) ) { + for each_objchild(o,obj*,oo) { + editor_scene_(oo,flags); + } + } + + if( clicked && !choiceL && !choiceR ) { + int is_picking = input(KEY_CTRL); + if( !is_picking ) { + if( input(KEY_SHIFT) ) { + editor_selectgroup( editor_first_selected(), editor_last_selected() ); + } else { + editor_unselect(); + editor_setselected(o, 1); + } + } + for( obj *p = obj_parent(o); p; p = obj_parent(p) ) { + editor_setopen(p, 1); + } + if( nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,offset_in_tree.x-bounds.x+UI_ICON_FONTSIZE/2,bounds.h })) ) { + editor_altopen( o ); + } + } + } + + --tabs; +} + +int editor_scene(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + + if( editor_begin(SCENE_TITLE, window_mode)) { + // #define HELP ICON_MDI_INFORMATION_OUTLINE "@-A\n-B\n-C\n" ";" + int choice = ui_toolbar(ICON_MDI_PLUS "@New node (CTRL+N);" ICON_MDI_DOWNLOAD "@Save node (CTRL+S);" ICON_MDI_DOWNLOAD "@Save scene (SHIFT+CTRL+S);" ICON_MD_BOOKMARK_ADDED "@Toggle Bookmark (CTRL+B);"); + if( choice == 1 ) editor_send("node_new"); + if( choice == 2 ) editor_send("node_save"); + if( choice == 3 ) editor_send("scene_save"); + if( choice == 4 ) editor_send("bookmark"); + + array(obj*) bookmarks = 0; + for each_map_ptr(*editor_bookmarked_map(), void*,o,int,bookmarked) { + if( *bookmarked ) { + array_push(bookmarks, *o); + } + } + if( ui_collapse("!" ICON_MD_BOOKMARK "Bookmarks", "DEBUG:BOOKMARK")) { + for each_array( bookmarks, obj*, o ) + editor_scene_( o, SCENE_ALL & ~(SCENE_RECURSE|SCENE_INDENT|SCENE_CHECKBOX) ); + ui_collapse_end(); + } + array_free(bookmarks); + + editor_scene_( editor.root, SCENE_ALL ); + + for each_array( editor.objs, obj*, o ) + editor_scene_( o, SCENE_ALL ); + + ui_separator(); + + // edit selection + for each_map(*editor_selected_map(), void*,o, int, k) { + if( k ) editor_inspect(o); + } + + editor_end(window_mode); + } + + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_scene); +} +#line 0 +#line 1 "v4k_editor_browser.h" +#define BROWSER_ICON ICON_MD_FOLDER_SPECIAL +#define BROWSER_TITLE "Browser " BROWSER_ICON + +EDITOR_BIND(browser, "held(CTRL)&down(2)", { ui_show(BROWSER_TITLE, ui_visible(BROWSER_TITLE) ^ true); }); + +int editor_browser(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + if( editor_begin(BROWSER_TITLE, window_mode) ) { + const char *file = 0; + if( ui_browse(&file, NULL) ) { + const char *sep = ifdef(win32, "\"", "'"); + app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep)); + } + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_browser); +} +#line 0 +#line 1 "v4k_editor_timeline.h" +#define TIMELINE_ICON ICON_MDI_CHART_TIMELINE +#define TIMELINE_TITLE "Timeline " TIMELINE_ICON + +EDITOR_BIND(timeline, "held(CTRL)&down(3)", { ui_show(TIMELINE_TITLE, ui_visible(TIMELINE_TITLE) ^ true); }); + +int ui_tween(const char *label, tween_t *t) { + if( ui_filter && ui_filter[0] ) if( !strstr(label, ui_filter) ) return 0; + + int expand_keys = label[0] == '!'; label += expand_keys; + const char *id = label; + if( strchr(id, '@') ) *strchr((char*)(id = (const char*)va("%s", label)), '@') = '\0'; + + enum { LABEL_SPACING = 250 }; + enum { ROUNDING = 0 }; + enum { THICKNESS = 1 }; + enum { PIXELS_PER_SECOND = 60 }; + enum { KEY_WIDTH = 5, KEY_HEIGHT = 5 }; + enum { TIMELINE_HEIGHT = 25 }; + enum { MARKER1_HEIGHT = 5, MARKER10_HEIGHT = 20, MARKER5_HEIGHT = (MARKER1_HEIGHT + MARKER10_HEIGHT) / 2 }; + unsigned base_color = WHITE; + unsigned time_color = YELLOW; + unsigned duration_color = ORANGE; + unsigned key_color = GREEN; + + int changed = 0; + +#if 0 + // two rows with height:30 composed of three widgets + nk_layout_row_template_begin(ui_ctx, 30); + nk_layout_row_template_push_variable(ui_ctx, t->duration * PIXELS_PER_SECOND); // min 80px. can grow + nk_layout_row_template_end(ui_ctx); +#endif + + char *sid = va("%s.%d", id, 0); + uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; + for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; + ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; + + ui_label(label); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); + bounds.y -= 30; + + struct nk_rect baseline = bounds; baseline.y += 30/2; + baseline.x += LABEL_SPACING; + baseline.w -= LABEL_SPACING; + + // tween duration + { + struct nk_rect pos = baseline; + pos.w = pos.x + t->duration * PIXELS_PER_SECOND; + pos.y -= TIMELINE_HEIGHT/2; + pos.h = TIMELINE_HEIGHT; + nk_stroke_rect(canvas, pos, ROUNDING, THICKNESS*2, AS_NKCOLOR(duration_color)); + } + + // tween ranges + for(int i = 0, end = array_count(t->keyframes) - 1; i < end; ++i) { + tween_keyframe_t *k = t->keyframes + i; + tween_keyframe_t *next = k + 1; + + struct nk_rect pos = baseline; + pos.x += k->t * PIXELS_PER_SECOND; + pos.w = (next->t - k->t) * PIXELS_PER_SECOND; + pos.y -= TIMELINE_HEIGHT/2; + pos.h = TIMELINE_HEIGHT; + + char *sid = va("%s.%d", id, i); + uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; + for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; + ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; + + struct nk_color c = nk_hsva_f(ui_hue, 0.75f, 0.8f, ui_alpha); + nk_fill_rect(canvas, pos, ROUNDING, k->ease == EASE_NOP ? AS_NKCOLOR(0) : c); // AS_NKCOLOR(track_color)); + } + + // horizontal line + nk_stroke_line(canvas, baseline.x, baseline.y, baseline.x+baseline.w,baseline.y, THICKNESS, AS_NKCOLOR(base_color)); + + // unit, 5-unit and 10-unit markers + for( float i = 0, j = 0; i < baseline.w; i += PIXELS_PER_SECOND/10, ++j ) { + int len = !((int)j%10) ? MARKER10_HEIGHT : !((int)j%5) ? MARKER5_HEIGHT : MARKER1_HEIGHT; + nk_stroke_line(canvas, baseline.x+i, baseline.y-len, baseline.x+i, baseline.y+len, THICKNESS, AS_NKCOLOR(base_color)); + } + + // time marker + float px = t->time * PIXELS_PER_SECOND; + nk_stroke_line(canvas, baseline.x+px, bounds.y, baseline.x+px, bounds.y+bounds.h, THICKNESS*2, AS_NKCOLOR(time_color)); + nk_draw_symbol(canvas, NK_SYMBOL_TRIANGLE_DOWN, ((struct nk_rect){ baseline.x+px-4,bounds.y-4-8,8,8}), /*bg*/AS_NKCOLOR(0), /*fg*/AS_NKCOLOR(time_color), 0.f/*border_width*/, ui_ctx->style.font); + + // key markers + for each_array_ptr(t->keyframes, tween_keyframe_t, k) { + struct nk_rect pos = baseline; + pos.x += k->t * PIXELS_PER_SECOND; + + vec2 romboid[] = { + {pos.x-KEY_WIDTH,pos.y}, {pos.x,pos.y-KEY_HEIGHT}, + {pos.x+KEY_WIDTH,pos.y}, {pos.x,pos.y+KEY_HEIGHT} + }; + + nk_fill_polygon(canvas, (float*)romboid, countof(romboid), AS_NKCOLOR(key_color)); + } + + // keys ui + if( expand_keys ) + for(int i = 0, end = array_count(t->keyframes); i < end; ++i) { + tween_keyframe_t *k = t->keyframes + i; + if( ui_collapse(va("Key %d", i), va("%s.%d", id, i))) { + changed |= ui_float("Time", &k->t); + changed |= ui_float3("Value", &k->v.x); + changed |= ui_list("Ease", ease_enums(), EASE_NUM, &k->ease ); + ui_collapse_end(); + } + } + + return changed; +} + +tween_t* rand_tween() { + tween_t demo = tween(); + int num_keys = randi(2,8); + double t = 0; + for( int i = 0; i < num_keys; ++i) { + tween_setkey(&demo, t, scale3(vec3(randf(),randf(),randf()),randi(-5,5)), randi(0,EASE_NUM) ); + t += randi(1,5) / ((float)(1 << randi(0,2))); + } + tween_t *p = CALLOC(1, sizeof(tween_t)); + memcpy(p, &demo, sizeof(tween_t)); + return p; +} + +int editor_timeline(int window_mode) { + static array(tween_t*) tweens = 0; + + do_once { + array_push(tweens, rand_tween()); + } + + if( editor.t == 0 ) + for each_array(tweens, tween_t*,t) { + tween_reset(t); + } + else + for each_array(tweens, tween_t*,t) { + tween_update(t, editor.dt); + } + + static void *selected = NULL; + if( editor_begin(TIMELINE_TITLE, window_mode) ) { + + int choice = ui_toolbar(ICON_MDI_PLUS ";" ICON_MDI_MINUS ); + if( choice == 1 ) array_push(tweens, rand_tween()); + if( choice == 2 && selected ) { + int target = -1; + for( int i = 0, end = array_count(tweens); i < end; ++i ) if( tweens[i] == selected ) { target = i; break; } + if( target >= 0 ) { array_erase_slow(tweens, target); selected = NULL; } + } + + for each_array(tweens, tween_t*,t) { + ui_tween(va("%s%p@%05.2fs Value: %s", t == selected ? "!":"", t, t->time, ftoa3(t->result)), t); + if(ui_label_icon_clicked_L.x) selected = (t != selected) ? t : NULL; + } + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_timeline); +} +#line 0 +#line 1 "v4k_editor_console.h" +#define CONSOLE_ICON ICON_MDI_CONSOLE +#define CONSOLE_TITLE "Console " CONSOLE_ICON + +EDITOR_BIND(console, "held(CTRL)&down(4)", { ui_show(CONSOLE_TITLE, ui_visible(CONSOLE_TITLE) ^ true); }); + +int editor_console(int window_mode) { + if( editor_begin(CONSOLE_TITLE, window_mode) ) { + + // peek complete window space + struct nk_rect bounds = nk_window_get_content_region(ui_ctx); + + enum { CONSOLE_LINE_HEIGHT = 20 }; + static array(char*) lines = 0; + do_once { + array_push(lines, stringf("> Editor v%s. Type `%s` for help.", EDITOR_VERSION, "")); + } + int max_lines = (bounds.h - UI_ROW_HEIGHT) / (CONSOLE_LINE_HEIGHT * 2); + if( max_lines >= 1 ) { + nk_layout_row_static(ui_ctx, bounds.h - UI_ROW_HEIGHT, bounds.w, 1); + if(nk_group_begin(ui_ctx, "console.group", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { + nk_layout_row_static(ui_ctx, CONSOLE_LINE_HEIGHT, bounds.w, 1); + for( int i = array_count(lines); i < max_lines; ++i ) + array_push_front(lines, 0); + for( int i = array_count(lines) - max_lines; i < array_count(lines); ++i ) { + if( !lines[i] ) { + #if 0 // debug + nk_label_wrap(ui_ctx, va("%d.A/%d",i+1,max_lines)); + nk_label_wrap(ui_ctx, va("%d.B/%d",i+1,max_lines)); + #else + nk_label_wrap(ui_ctx, ""); + nk_label_wrap(ui_ctx, ""); + #endif + } else { + nk_label_wrap(ui_ctx, lines[i]); + const char *answer = isdigit(*lines[i]) ? editor_recv( atoi(lines[i]), 0 ) : NULL; + nk_label_wrap(ui_ctx, answer ? answer : ""); + } + } + nk_group_end(ui_ctx); + } + } + static char *cmd = 0; + if( ui_string(NULL, &cmd) ) { + int jobid = editor_send(cmd); + array_push(lines, stringf("%d> %s", jobid, cmd)); + cmd[0] = 0; + } + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_console); +} +#line 0 +#line 1 "v4k_editor_nodes.h" +#define NODES_ICON ICON_MDI_GRAPH +#define NODES_TITLE "Nodes " NODES_ICON + +EDITOR_BIND(nodes, "held(CTRL)&down(5)", { ui_show(NODES_TITLE, ui_visible(NODES_TITLE) ^ true); }); + +/* +A basic node-based UI built with Nuklear. +Builds on the node editor example included in Nuklear v1.00, with the aim of +being used as a prototype for implementing a functioning node editor. + +Features: +- Nodes of different types. Currently their implementations are #included in + the main file, but they could easily be turned into eg. a plugin system. +- Pins/pins of different types -- currently float values and colors. +- Adding and removing nodes. +- Linking nodes, with validation (one link per input, only link similar pins). +- Detaching and moving links. +- Evaluation of output values of connected nodes. +- Memory management based on fixed size arrays for links and node pointers +- Multiple node types +- Multiple pin types +- Linking between pins of the same type +- Detaching and reattaching links +- Getting value from linked node if pin is connected + +Todo: +- Complete pin types. +- Allow dragging from output to input pin. +- Cut link by CTRL+clicking input pin. +- Cut link by drawing intersect line on a link. +- Group elemnts together with mouse, or LSHIFT+clicking. +- Drag groups. +- DEL elements. +- DEL groups. +- CTRL-C/CTRL-V/CTRL-X elements. +- CTRL-C/CTRL-V/CTRL-X groups. +- CTRL-Z,CTRL-Y. +- CTRL-N. +- CTRL-L,CTRL-S. +- CTRL-F. +- CTRL-Wheel Zooming. +- Allow to extend node types from Lua. + +Extra todo: +- Execution Flow (see: nk_stroke_triangle, nk_fill_triangle) +- Complete missing nodes (see: nk_draw_image, nk_draw_text) +- Right-click could visualize node/board diagram as Lua script. +- Once that done, copy/pasting scripts should work within editor. + +Sources: +- https://github.com/Immediate-Mode-UI/Nuklear/pull/561 +- https://github.com/vurtun/nuklear/blob/master/demo/node_editor.c +*/ + +typedef enum pin_type_t { + type_flow, + type_int,type_float, + type_block,type_texture,type_image, + type_color, + /* + type_bool, + type_char, type_string, + type_int2, type_int3, type_int4, + type_float2, type_float3, type_float4, + type_array, type_map, + */ + + type_total +} pin_type_t; + +struct node_pin { + pin_type_t pin_type; + nk_bool is_connected; + struct node* connected_node; + int connected_pin; +}; + +struct node { + int ID; + char name[32]; + struct nk_rect bounds; + int input_count; + int output_count; + struct node_pin *inputs; + struct node_pin *outputs; + struct { + float in_padding_x; + float in_padding_y; + float in_spacing_y; + float out_padding_x; + float out_padding_y; + float out_spacing_y; + } pin_spacing; /* Maybe this should be called "node_layout" and include the bounds? */ + struct node *next; /* Z ordering only */ + struct node *prev; /* Z ordering only */ + + void* (*eval_func)(struct node*, int oIndex); + void (*display_func)(struct nk_context*, struct node*); +}; + +struct node_link { + struct node* input_node; + int input_pin; + struct node* output_node; + int output_pin; + nk_bool is_active; +}; + +struct node_linking { + int active; + struct node *node; + int input_id; + int input_pin; +}; + +struct node_editor { + int initialized; + struct node *node_buf[32]; + struct node_link links[64]; + struct node *output_node; + struct node *begin; + struct node *end; + int node_count; + int link_count; + struct nk_rect bounds; + struct node *selected; + int show_grid; + struct nk_vec2 scrolling; + struct node_linking linking; +}; + +/* === PROTOTYPES === */ +/* The node implementations need these two functions. */ +/* These could/should go in a header file along with the node and node_pin structs and be #included in the node implementations */ + +struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count); +void* node_editor_eval_connected(struct node *node, int input_pin_number); +/* ================== */ + +/* === NODE TYPE IMPLEMENTATIONS === */ + +#define NODE_DEFAULT_ROW_HEIGHT 25 + + +// ---------------------------------------------------------------------------------------------------- +// #include "node_output.h" + +struct node_type_output { + struct node node; + struct nk_colorf input_val; +}; + +struct nk_colorf *node_output_get(struct node* node) { + struct node_type_output *output_node = (struct node_type_output*)node; + if (!node->inputs[0].is_connected) { + struct nk_colorf black = {0.0f, 0.0f, 0.0f, 0.0f}; + output_node->input_val = black; + } + return &output_node->input_val; +} + +static void node_output_display(struct nk_context *ctx, struct node *node) { + if (node->inputs[0].is_connected) { + struct node_type_output *output_node = (struct node_type_output*)node; + output_node->input_val = *(struct nk_colorf*)node_editor_eval_connected(node, 0); + nk_layout_row_dynamic(ctx, 60, 1); + nk_button_color(ctx, nk_rgba_cf(output_node->input_val)); + } +} + +struct node* node_output_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_output *output_node = (struct node_type_output*)node_editor_add(editor, sizeof(struct node_type_output), "Output", nk_rect(position.x, position.y, 100, 100), 1, 0); + if (output_node){ + output_node->node.inputs[0].pin_type = type_color; + output_node->node.display_func = node_output_display; + } + return (struct node*)output_node; +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_float.h" + +struct node_type_float { + struct node node; + float output_val; +}; + +static float *node_float_eval(struct node* node, int oIndex) { + struct node_type_float *float_node = (struct node_type_float*)node; + NK_ASSERT(oIndex == 0); + return &float_node->output_val; +} + +static void node_float_draw(struct nk_context *ctx, struct node *node) { + struct node_type_float *float_node = (struct node_type_float*)node; + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + float_node->output_val = nk_propertyf(ctx, "#Value:", 0.0f, float_node->output_val, 1.0f, 0.01f, 0.01f); +} + +void node_float_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_float *float_node = (struct node_type_float*)node_editor_add(editor, sizeof(struct node_type_float), "Float", nk_rect(position.x, position.y, 180, 75), 0, 1); + if (float_node) + { + float_node->output_val = 1.0f; + float_node->node.display_func = node_float_draw; + float_node->node.eval_func = (void*(*)(struct node*, int)) node_float_eval; + } +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_color.h" + +struct node_type_color { + struct node node; + float input_val[4]; + struct nk_colorf output_val; +}; + +static struct nk_colorf *node_color_eval(struct node* node, int oIndex) +{ + struct node_type_color *color_node = (struct node_type_color*)node; + NK_ASSERT(oIndex == 0); /* only one output connector */ + + return &color_node->output_val; +} + + +static void node_color_draw(struct nk_context *ctx, struct node *node) +{ + struct node_type_color *color_node = (struct node_type_color*)node; + float eval_result; /* Get the values from connected nodes into this so the inputs revert on disconnect */ + const char* labels[4] = {"#R:","#G:","#B:","#A:"}; + float color_val[4]; /* Because we can't just loop through the struct... */ + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + nk_button_color(ctx, nk_rgba_cf(color_node->output_val)); + + for (int i = 0; i < 4; i++) + { + if (color_node->node.inputs[i].is_connected) { + eval_result = *(float*)node_editor_eval_connected(node, i); + eval_result = nk_propertyf(ctx, labels[i], eval_result, eval_result, eval_result, 0.01f, 0.01f); + color_val[i] = eval_result; + } + else { + color_node->input_val[i] = nk_propertyf(ctx, labels[i], 0.0f, color_node->input_val[i], 1.0f, 0.01f, 0.01f); + color_val[i] = color_node->input_val[i]; + } + } + + color_node->output_val.r = color_val[0]; + color_node->output_val.g = color_val[1]; + color_node->output_val.b = color_val[2]; + color_node->output_val.a = color_val[3]; +} + +void node_color_create(struct node_editor *editor, struct nk_vec2 position) +{ + struct node_type_color *color_node = (struct node_type_color*)node_editor_add(editor, sizeof(struct node_type_color), "Color", nk_rect(position.x, position.y, 180, 190), 4, 1); + if (color_node) + { + const struct nk_colorf black = {0.0f, 0.0f, 0.0f, 1.0f}; + + for (int i = 0; i < color_node->node.input_count; i++) + color_node->node.inputs[i].pin_type = type_float; + color_node->node.outputs[0].pin_type = type_color; + + color_node->node.pin_spacing.in_padding_y += NODE_DEFAULT_ROW_HEIGHT; + + color_node->input_val[0] = 0.0f; + color_node->input_val[1] = 0.0f; + color_node->input_val[2] = 0.0f; + color_node->input_val[3] = 1.0f; + + color_node->output_val = black; + + color_node->node.display_func = node_color_draw; + color_node->node.eval_func = (void*(*)(struct node*, int)) node_color_eval; + } +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_blend.h" + +struct node_type_blend { + struct node node; + struct nk_colorf input_val[2]; + struct nk_colorf output_val; + float blend_val; +}; + +static struct nk_colorf *node_blend_eval(struct node *node, int oIndex) { + struct node_type_blend* blend_node = (struct node_type_blend*)node; + return &blend_node->output_val; +} + +static void node_blend_display(struct nk_context *ctx, struct node *node) { + struct node_type_blend *blend_node = (struct node_type_blend*)node; + const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; + float blend_amnt; + + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + for (int i = 0; i < 2; i++){ + if(node->inputs[i].is_connected) { + blend_node->input_val[i] = *(struct nk_colorf*)node_editor_eval_connected(node, i); + } + else { + blend_node->input_val[i] = blank; + } + nk_button_color(ctx, nk_rgba_cf(blend_node->input_val[i])); + } + + if (node->inputs[2].is_connected) { + blend_amnt = *(float*)node_editor_eval_connected(node, 2); + blend_amnt = nk_propertyf(ctx, "#Blend", blend_amnt, blend_amnt, blend_amnt, 0.01f, 0.01f); + } + else { + blend_node->blend_val = nk_propertyf(ctx, "#Blend", 0.0f, blend_node->blend_val, 1.0f, 0.01f, 0.01f); + blend_amnt = blend_node->blend_val; + } + + + if(node->inputs[0].is_connected && node->inputs[1].is_connected) { + blend_node->output_val.r = blend_node->input_val[0].r * (1.0f-blend_amnt) + blend_node->input_val[1].r * blend_amnt; + blend_node->output_val.g = blend_node->input_val[0].g * (1.0f-blend_amnt) + blend_node->input_val[1].g * blend_amnt; + blend_node->output_val.b = blend_node->input_val[0].b * (1.0f-blend_amnt) + blend_node->input_val[1].b * blend_amnt; + blend_node->output_val.a = blend_node->input_val[0].a * (1.0f-blend_amnt) + blend_node->input_val[1].a * blend_amnt; + } + else { + blend_node->output_val = blank; + } +} + +void node_blend_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_blend* blend_node = (struct node_type_blend*)node_editor_add(editor, sizeof(struct node_type_blend), "Blend", nk_rect(position.x, position.y, 180, 130), 3, 1); + if (blend_node) { + const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) + blend_node->node.inputs[i].pin_type = type_color; + blend_node->node.outputs[0].pin_type = type_color; + + // blend_node->node.pin_spacing.in_padding_y = 42.0f; + // blend_node->node.pin_spacing.in_spacing_y = 29.0f; + + for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) + blend_node->input_val[i] = blank; + blend_node->output_val = blank; + + blend_node->blend_val = 0.5f; + + blend_node->node.display_func = node_blend_display; + blend_node->node.eval_func = (void*(*)(struct node*, int)) node_blend_eval; + + } +} + +/* ================================= */ + +#define NK_RGB3(r,g,b) {r,g,b,255} +#define BG_COLOR ((struct nk_color){60,60,60,192}) // nk_rgba(0,0,0,192) + +static +struct editor_node_style { + int pin_type; + const char *shape; + struct nk_color color_idle; + struct nk_color color_hover; +} styles[] = { + // order matters: + { type_flow, "triangle_right", NK_RGB3(200,200,200), NK_RGB3(255,255,255) }, // if .num_links == 0 + { type_int, "circle", NK_RGB3(33,227,175), NK_RGB3(135,239,195) }, + { type_float, "circle", NK_RGB3(156,253,65), NK_RGB3(144,225,137) }, + { type_block, "circle", NK_RGB3(6,165,239), NK_RGB3(137,196,247) }, + { type_texture, "circle", NK_RGB3(148,0,0), NK_RGB3(183,137,137) }, + { type_image, "circle", NK_RGB3(200,130,255), NK_RGB3(220,170,255) }, + { type_color, "circle", NK_RGB3(252,200,35), NK_RGB3(255,217,140) }, +}; + +#define COLOR_FLOW_HI styles[type_flow].color_hover +#define COLOR_FLOW_LO styles[type_flow].color_idle + +#define GRID_SIZE 64.0f +#define GRID_COLOR ((struct nk_color)NK_RGB3(80,80,120)) +#define GRID_THICKNESS 1.0f + +// 4 colors: top-left, top-right, bottom-right, bottom-left +#define GRID_BG_COLORS ((struct nk_color){30,30,30,255}), ((struct nk_color){40,20,0,255}), ((struct nk_color){30,30,30,255}), ((struct nk_color){20,30,40,255}) + +#define LINK_THICKNESS 1.0f +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + nk_stroke_line(canvas, a.x, a.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) +#undef LINK_DRAW +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + nk_stroke_curve(canvas, a.x, a.y, a.x+50, a.y, b.x-50, b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) +#undef LINK_DRAW +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + float dist2 = len2( sub2( ptr2(&b.x), ptr2(&a.x) ) ); \ + vec2 mid_a = mix2( ptr2(&a.x), ptr2(&b.x), 0.25 ); mid_a.y += dist2/2; \ + vec2 mid_b = mix2( ptr2(&a.x), ptr2(&b.x), 0.75 ); mid_b.y += dist2/3; \ + nk_stroke_curve(canvas, a.x, a.y, mid_a.x, mid_a.y, mid_b.x, mid_b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) + + +#define PIN_RADIUS 12 +#define PIN_THICKNESS 1.0f +#define PIN_DRAW(PIN_ADDR,POINT,RADIUS) do { \ + circle.x = (POINT).x - (RADIUS) / 2; \ + circle.y = (POINT).y - (RADIUS) / 2; \ + circle.w = circle.h = (RADIUS); \ + struct nk_color color = node_get_type_color((PIN_ADDR).pin_type); \ + if((PIN_ADDR).is_connected) \ + nk_fill_circle(canvas, circle, color); \ + else \ + nk_stroke_circle(canvas, circle, PIN_THICKNESS, color); \ +} while(0) + + +static struct nk_color node_get_type_color(unsigned pin_type) { + for( int i = 0; i < type_total; ++i ) + if( styles[i].pin_type == pin_type ) + return styles[i].color_idle; + return ((struct nk_color)NK_RGB3(255,0,255)); +} + +static void node_editor_push(struct node_editor *editor, struct node *node) { + if (!editor->begin) { + node->next = NULL; + node->prev = NULL; + editor->begin = node; + editor->end = node; + } else { + node->prev = editor->end; + if (editor->end) + editor->end->next = node; + node->next = NULL; + editor->end = node; + } +} + +static void node_editor_pop(struct node_editor *editor, struct node *node) { + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + if (editor->end == node) + editor->end = node->prev; + if (editor->begin == node) + editor->begin = node->next; + node->next = NULL; + node->prev = NULL; +} + +static struct node* node_editor_find_by_id(struct node_editor *editor, int ID) { + struct node *iter = editor->begin; + while (iter) { + if (iter->ID == ID) + return iter; + iter = iter->next; + } + return NULL; +} + +static struct node_link* node_editor_find_link_by_output(struct node_editor *editor, struct node *output_node, int node_input_connector) { + for( int i = 0; i < editor->link_count; i++ ) { + if (editor->links[i].output_node == output_node && + editor->links[i].output_pin == node_input_connector && + editor->links[i].is_active == nk_true) { + return &editor->links[i]; + } + } + return NULL; +} + +static struct node_link* node_editor_find_link_by_input(struct node_editor *editor, struct node *input_node, int node_output_connector) { + for( int i = 0; i < editor->link_count; i++ ) { + if (editor->links[i].input_node == input_node && + editor->links[i].input_pin == node_output_connector && + editor->links[i].is_active == nk_true) { + return &editor->links[i]; + } + } + return NULL; +} + +static void node_editor_delete_link(struct node_link *link) { + link->is_active = nk_false; + link->input_node->outputs[link->input_pin].is_connected = nk_false; + link->output_node->inputs[link->output_pin].is_connected = nk_false; +} + +struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count) { + static int IDs = 0; + struct node *node = NULL; + + if ((nk_size)editor->node_count < NK_LEN(editor->node_buf)) { + /* node_buf has unused pins */ + node = MALLOC(nodeSize); + editor->node_buf[editor->node_count++] = node; + node->ID = IDs++; + } else { + /* check for freed up pins in node_buf */ + for (int i = 0; i < editor->node_count; i++) { + if (editor->node_buf[i] == NULL) { + node = MALLOC(nodeSize); + editor->node_buf[i] = node; + node->ID = i; + break; + } + } + } + if (node == NULL) { + puts("Node creation failed"); + return NULL; + } + + node->bounds = bounds; + + node->input_count = in_count; + node->output_count = out_count; + + node->inputs = MALLOC(node->input_count * sizeof(struct node_pin)); + node->outputs = MALLOC(node->output_count * sizeof(struct node_pin)); + + for (int i = 0; i < node->input_count; i++) { + node->inputs[i].is_connected = nk_false; + node->inputs[i].pin_type = type_float; /* default pin type */ + } + for (int i = 0; i < node->output_count; i++) { + node->outputs[i].is_connected = nk_false; + node->outputs[i].pin_type = type_float; /* default pin type */ + } + + /* default pin spacing */ + node->pin_spacing.in_padding_x = 2; + node->pin_spacing.in_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust + node->pin_spacing.in_spacing_y = 25; // row height+border + node->pin_spacing.out_padding_x = 3; + node->pin_spacing.out_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust + node->pin_spacing.out_spacing_y = 25; // row height+border + + strcpy(node->name, name); + node_editor_push(editor, node); + + return node; +} + +void *node_editor_eval_connected(struct node* node, int input_pin_number) { + NK_ASSERT(node->inputs[input_pin_number].is_connected); + return node->inputs[input_pin_number].connected_node->eval_func(node->inputs[input_pin_number].connected_node, node->inputs[input_pin_number].connected_pin); +} + +static void node_editor_link(struct node_editor *editor, struct node *in_node, int in_pin, struct node *out_node, int out_pin) { + /* Confusingly, in and out nodes/pins here refer to the inputs and outputs OF THE LINK ITSELF, not the nodes */ + struct node_link *link = NULL; + + if ((nk_size)editor->link_count < NK_LEN(editor->links)) { + link = &editor->links[editor->link_count++]; + } else { + for (int i = 0; i < (int)NK_LEN(editor->links); i++) + { + if (editor->links[i].is_active == nk_false) { + link = &editor->links[i]; + break; + } + } + } + if (link) { + out_node->inputs[out_pin].is_connected = nk_true; + in_node->outputs[in_pin].is_connected = nk_true; + out_node->inputs[out_pin].connected_node = in_node; + out_node->inputs[out_pin].connected_pin = in_pin; + + link->input_node = in_node; + link->input_pin = in_pin; + link->output_node = out_node; + link->output_pin = out_pin; + link->is_active = nk_true; + } else { + puts("Too many links"); + } +} + +static void node_editor_init(struct node_editor *editor) { + if (editor->initialized) return; + + struct nk_rect total_space = nk_window_get_content_region(ui_ctx); + struct nk_vec2 output_node_position = { total_space.w*2/3, total_space.h/3 }; + struct nk_vec2 color_node_position = { total_space.w*1/4, total_space.h/3 }; + + memset(editor, 0, sizeof(*editor)); + + editor->output_node = node_output_create(editor, output_node_position); + node_color_create(editor, color_node_position); + editor->show_grid = nk_true; + + editor->initialized = 1; +} + +static int node_editor(struct node_editor *editor) { + int n = 0; + struct nk_rect total_space; + const struct nk_input *in = &ui_ctx->input; + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct node *updated = 0; + + node_editor_init(editor); + + { + /* allocate complete window space */ + total_space = nk_window_get_content_region(ui_ctx); + nk_layout_space_begin(ui_ctx, NK_STATIC, total_space.h, editor->node_count); + { + struct node *it = editor->begin; + struct nk_rect size = nk_layout_space_bounds(ui_ctx); + struct nk_panel *nodePanel = 0; + + //nk_fill_rect(canvas, size, 0/*rounding*/, ((struct nk_color){30,30,30,255})); // 20,30,40,255 + nk_fill_rect_multi_color(canvas, size, GRID_BG_COLORS); + + if (editor->show_grid) { + /* display grid */ + for (float x = (float)fmod(size.x - editor->scrolling.x, GRID_SIZE); x < size.w; x += GRID_SIZE) + nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, GRID_THICKNESS, GRID_COLOR); + for (float y = (float)fmod(size.y - editor->scrolling.y, GRID_SIZE); y < size.h; y += GRID_SIZE) + nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, GRID_THICKNESS, GRID_COLOR); + } + + /* execute each node as a movable group */ + /* loop through nodes */ + while (it) { + /* Output node window should not have a close button */ + nk_flags nodePanel_flags = NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE; + if (it != editor->output_node) + nodePanel_flags |= NK_WINDOW_CLOSABLE; + + /* calculate scrolled node window position and size */ + nk_layout_space_push(ui_ctx, nk_rect(it->bounds.x - editor->scrolling.x, + it->bounds.y - editor->scrolling.y, it->bounds.w, it->bounds.h)); + + /* execute node window */ + char *name = va(" " ICON_MD_MENU " %s",it->name); //< @r-lyeh added some spacing+icon because of our UI customizations + +struct nk_color bak = ui_ctx->style.window.fixed_background.data.color; +ui_ctx->style.window.fixed_background.data.color = BG_COLOR; + + if (nk_group_begin(ui_ctx, name, nodePanel_flags)) + { + /* always have last selected node on top */ + + nodePanel = nk_window_get_panel(ui_ctx); + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nodePanel->bounds) && + (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT, + nk_layout_space_rect_to_screen(ui_ctx, nodePanel->bounds)))) && + editor->end != it) + { + updated = it; + } + + if ((nodePanel->flags & NK_WINDOW_HIDDEN)) /* Node close button has been clicked */ + { + /* Delete node */ + struct node_link *link_remove; + node_editor_pop(editor, it); + for (int n = 0; n < it->input_count; n++) { + if ((link_remove = node_editor_find_link_by_output(editor, it, n))) + { + node_editor_delete_link(link_remove); + } + } + for (int n = 0; n < it -> output_count; n++) { + while((link_remove = node_editor_find_link_by_input(editor, it, n))) + { + node_editor_delete_link(link_remove); + } + } + NK_ASSERT(editor->node_buf[it->ID] == it); + editor->node_buf[it->ID] = NULL; + FREE(it->inputs); + FREE(it->outputs); + FREE(it); + } + else { + + /* ================= NODE CONTENT ===================== */ + + it->display_func(ui_ctx, it); + + /* ==================================================== */ + + } + nk_group_end(ui_ctx); + + } + +ui_ctx->style.window.fixed_background.data.color = bak; + + if (!(nodePanel->flags & NK_WINDOW_HIDDEN)) + { + /* node pin and linking */ + struct nk_rect bounds; + bounds = nk_layout_space_rect_to_local(ui_ctx, nodePanel->bounds); + bounds.x += editor->scrolling.x; + bounds.y += editor->scrolling.y; + it->bounds = bounds; + + /* output pins */ + for (int n = 0; n < it->output_count; ++n) { + struct nk_rect circle; + struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; + pt.x += nodePanel->bounds.w - PIN_RADIUS / 2 + it->pin_spacing.out_padding_x; + pt.y += it->pin_spacing.out_padding_y + it->pin_spacing.out_spacing_y * (n); + PIN_DRAW(it->outputs[n],pt,PIN_RADIUS); + + /* start linking process */ + /* set linking active */ + if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) { + editor->linking.active = nk_true; + editor->linking.node = it; + editor->linking.input_id = it->ID; + editor->linking.input_pin = n; + } + + /* draw link being dragged (from linked pin to mouse position) */ + if (editor->linking.active && editor->linking.node == it && + editor->linking.input_pin == n) { + LINK_DRAW(vec2(circle.x+3,circle.y+3),ptr2(&in->mouse.pos.x),COLOR_FLOW_HI); + } + } + + /* input pins */ + for (int n = 0; n < it->input_count; ++n) { + struct nk_rect circle; + struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; + pt.x += it->pin_spacing.in_padding_x; + pt.y += it->pin_spacing.in_padding_y + it->pin_spacing.in_spacing_y * (n); + PIN_DRAW(it->inputs[n],pt,PIN_RADIUS); + + /* Detach link */ + if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true) && + editor->linking.active == nk_false && + it->inputs[n].is_connected == nk_true) { + struct node_link *node_relink = node_editor_find_link_by_output(editor, it, n); + editor->linking.active = nk_true; + editor->linking.node = node_relink->input_node; + editor->linking.input_id = node_relink->input_node->ID; + editor->linking.input_pin = node_relink->input_pin; + node_editor_delete_link(node_relink); + } + + /* Create link */ + if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) && + nk_input_is_mouse_hovering_rect(in, circle) && + editor->linking.active && + editor->linking.node != it && + it->inputs[n].pin_type == editor->linking.node->outputs[editor->linking.input_pin].pin_type && + it->inputs[n].is_connected != nk_true) { + editor->linking.active = nk_false; + + node_editor_link(editor, editor->linking.node, + editor->linking.input_pin, it, n); + } + } + } + it = it->next; + } + + /* reset (output) linking connection */ + if (editor->linking.active && (!!input(KEY_LCTRL) || !!input(KEY_RCTRL) || nk_input_is_mouse_released(in, NK_BUTTON_LEFT))) { + editor->linking.active = nk_false; + editor->linking.node = NULL; + } + + /* draw each static link */ + for (int n = 0; n < editor->link_count; ++n) { + struct node_link *link = &editor->links[n]; + if (link->is_active == nk_true){ + struct node *ni = link->input_node; + struct node *no = link->output_node; + struct nk_vec2 l0 = nk_layout_space_to_screen(ui_ctx, nk_vec2(ni->bounds.x + ni->bounds.w + ni->pin_spacing.out_padding_x, 3.0f + ni->bounds.y + ni->pin_spacing.out_padding_y + ni->pin_spacing.out_spacing_y * (link->input_pin))); + struct nk_vec2 l1 = nk_layout_space_to_screen(ui_ctx, nk_vec2(no->bounds.x + no->pin_spacing.in_padding_x, 3.0f + no->bounds.y + no->pin_spacing.in_padding_y + no->pin_spacing.in_spacing_y * (link->output_pin))); + + l0.x -= editor->scrolling.x; + l0.y -= editor->scrolling.y; + l1.x -= editor->scrolling.x; + l1.y -= editor->scrolling.y; + + struct nk_color color = node_get_type_color(no->inputs[link->output_pin].pin_type); + LINK_DRAW(ptr2(&l0.x), ptr2(&l1.x), color); + } + } + + if (updated) { + /* reshuffle nodes to have least recently selected node on top */ + node_editor_pop(editor, updated); + node_editor_push(editor, updated); + } + + /* node selection */ + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ui_ctx))) { + it = editor->begin; + editor->selected = NULL; + editor->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200); + while (it) { + struct nk_rect b = nk_layout_space_rect_to_screen(ui_ctx, it->bounds); + b.x -= editor->scrolling.x; + b.y -= editor->scrolling.y; + if (nk_input_is_mouse_hovering_rect(in, b)) + editor->selected = it; + it = it->next; + } + } + + /* contextual menu */ + if (nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 220), nk_window_get_bounds(ui_ctx))) { + struct nk_vec2 wincoords = { in->mouse.pos.x-total_space.x-50, in->mouse.pos.y-total_space.y-32 }; + +#if 1 + static char *filter = 0; + static int do_filter = 0; + if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1; + int choice = ui_toolbar(ICON_MD_SEARCH ";"); + if( choice == 1 ) do_filter = 1; + if( do_filter ) { + ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter); + if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon) + do_filter = 0; + } + } else { + if( filter ) filter[0] = '\0'; + } + char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*"; +#endif + + #define ui_label_filtered(lbl) (strmatchi(lbl,filter_mask) && ui_label(lbl)) + + int close = 0; + if (ui_label_filtered("=Add Color node")) close=1,node_color_create(editor, wincoords); + if (ui_label_filtered("=Add Float node")) close=1,node_float_create(editor, wincoords); + if (ui_label_filtered("=Add Blend Node")) close=1,node_blend_create(editor, wincoords); + if (ui_label_filtered(editor->show_grid ? "=Hide Grid" : "=Show Grid")) + close=1,editor->show_grid = !editor->show_grid; + if(close) do_filter = 0, (filter ? filter[0] = '\0' : '\0'), nk_contextual_close(ui_ctx); + nk_contextual_end(ui_ctx); + } + } + nk_layout_space_end(ui_ctx); + + /* window content scrolling */ + if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ui_ctx)) && + nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) { + editor->scrolling.x += in->mouse.delta.x; + editor->scrolling.y += in->mouse.delta.y; + } + } + + return !nk_window_is_closed(ui_ctx, "NodeEdit"); +} + +int editor_nodes(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + + if( editor_begin(NODES_TITLE, window_mode) ) { + + static struct node_editor nodeEditor = {0}; + node_editor(&nodeEditor); + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_nodes); +} +#line 0 +#line 1 "v4k_editor_script.h" + +int ui_texture_fit(texture_t t, struct nk_rect bounds) { + // allocate complete window space + struct nk_rect total_space = nk_window_get_content_region(ui_ctx); + nk_layout_space_begin(ui_ctx, NK_DYNAMIC, total_space.h - 4, 1); // -4 to hide scrollbar Y + nk_layout_space_push(ui_ctx, nk_rect(0,0,1,1)); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_image image = nk_image_id((int)t.id); + nk_draw_image(canvas, bounds, &image, nk_white); + + nk_layout_space_end(ui_ctx); + return 0; +} + +#define LITE_ICON ICON_MDI_SCRIPT_TEXT +#define LITE_TITLE "Script " LITE_ICON + +EDITOR_BIND(script, "held(CTRL)&down(6)", { ui_show(LITE_TITLE, ui_visible(LITE_TITLE) ^ true); }); + +int editor_scripted(int window_mode) { + window_mode = EDITOR_WINDOW; // force mode + + static lua_State *L = 0; + do_once { + L = script_init_env(SCRIPT_LUA|SCRIPT_DEBUGGER); + + const char *platform = "" // "Android" "FreeBSD" "OpenBSD" "NetBSD" + ifdef(ems, "Emscripten") + ifdef(linux, "Linux") + ifdef(osx, "macOS") + ifdef(win32, "Windows") + ; + const char *pathexe = vac("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")); + + gleqInit(); + gleqTrackWindow(window_handle()); + lt_init(L, window_handle(), LT_DATAPATH, __argc, __argv, window_scale(), platform, pathexe); + } + + unsigned lt_none = 0u; + unsigned lt_all = ~0u & ~(GLEQ_WINDOW_MOVED/*|GLEQ_WINDOW_RESIZED|GLEQ_WINDOW_REFRESH*/); + lt_events = lt_none; + + int mouse_in_rect = 0; + if( editor_begin(LITE_TITLE, window_mode) ) { + + lt_events = lt_all; + if( !nk_window_has_focus(ui_ctx) ) lt_events = lt_none; + + struct nk_rect bounds = nk_window_get_content_region(ui_ctx); + + lt_mx = input(MOUSE_X) - bounds.x; + lt_my = input(MOUSE_Y) - bounds.y; + lt_wx = bounds.x; + lt_wy = bounds.y; + lt_ww = bounds.w; + lt_wh = bounds.h; + + if( lt_resizesurface(lt_getsurface(0), lt_ww, lt_wh) ) { + gleq_window_refresh_callback(window_handle()); + } + // fullscreen_quad_rgb( lt_getsurface(0)->t, 1.2f ); + ui_texture_fit(lt_getsurface(0)->t, bounds); + + if( !!nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect){lt_wx+5,lt_wy+5,lt_ww-10,lt_wh-10})) ) { + lt_events &= ~(1<<31); // dont cursor shape + } + + editor_end(window_mode); + } + + lt_tick(L); + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_scripted); +} +#line 0 + +#line 1 "v4k_end.c" // Enable more performant GPUs on laptops. Does this work into a dll? // int NvOptimusEnablement = 1; // int AmdPowerXpressRequestHighPerformance = 1; diff --git a/engine/split/3rd_base64.h b/engine/split/3rd_base64.h index 60b29f3..90423fe 100644 --- a/engine/split/3rd_base64.h +++ b/engine/split/3rd_base64.h @@ -26,7 +26,7 @@ unsigned base64_bounds(unsigned size) { char* base64_encode(const void *inp, unsigned inlen) { // free() after use unsigned outlen = base64_bounds(inlen); - char *out_ = malloc(outlen); + char *out_ = MALLOC(outlen); out_[outlen] = 0; uint_least32_t v; @@ -43,21 +43,21 @@ char* base64_encode(const void *inp, unsigned inlen) { // free() after use while (rem >= 6) { rem -= 6; if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[(v >> rem) & 63]; } } if (rem) { v <<= (6 - rem); if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[v & 63]; } while(io&3) { - if(io>=outlen) return (free(out_), 0); /* truncation is failure */ + if(io>=outlen) return (FREE(out_), NULL); /* truncation is failure */ out[io++]='='; } - if(io>=outlen) return (free(out_), 0); /* no room for null terminator */ + if(io>=outlen) return (FREE(out_), NULL); /* no room for null terminator */ out[io]=0; return out_; } diff --git a/tools/editor/3rd_icon_mdi.h b/engine/split/3rd_icon_mdi.h similarity index 100% rename from tools/editor/3rd_icon_mdi.h rename to engine/split/3rd_icon_mdi.h diff --git a/tools/editor/3rd_lite.h b/engine/split/3rd_lite.h similarity index 97% rename from tools/editor/3rd_lite.h rename to engine/split/3rd_lite.h index 22c2a3b..dc7574a 100644 --- a/tools/editor/3rd_lite.h +++ b/engine/split/3rd_lite.h @@ -123,7 +123,7 @@ struct RenFont { int height; }; -static struct { int left, top, right, bottom; } clip; +static struct { int left, top, right, bottom; } lt_clip; static const char* codepoint_to_utf8(unsigned c) { //< @r-lyeh static char s[4+1]; @@ -162,15 +162,15 @@ void ren_update_rects(RenRect *rects, int count) { void ren_set_clip_rect(RenRect rect) { - clip.left = rect.x; - clip.top = rect.y; - clip.right = rect.x + rect.width; - clip.bottom = rect.y + rect.height; + lt_clip.left = rect.x; + lt_clip.top = rect.y; + lt_clip.right = rect.x + rect.width; + lt_clip.bottom = rect.y + rect.height; } void ren_get_size(int *x, int *y) { - lt_surface *surf = lt_getsurface(window); + lt_surface *surf = lt_getsurface(lt_window()); *x = surf->w; *y = surf->h; } @@ -355,14 +355,14 @@ static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) void ren_draw_rect(RenRect rect, RenColor color) { if (color.a == 0) { return; } - int x1 = rect.x < clip.left ? clip.left : rect.x; - int y1 = rect.y < clip.top ? clip.top : rect.y; + int x1 = rect.x < lt_clip.left ? lt_clip.left : rect.x; + int y1 = rect.y < lt_clip.top ? lt_clip.top : rect.y; int x2 = rect.x + rect.width; int y2 = rect.y + rect.height; - x2 = x2 > clip.right ? clip.right : x2; - y2 = y2 > clip.bottom ? clip.bottom : y2; + x2 = x2 > lt_clip.right ? lt_clip.right : x2; + y2 = y2 > lt_clip.bottom ? lt_clip.bottom : y2; - lt_surface *surf = lt_getsurface(window); + lt_surface *surf = lt_getsurface(lt_window()); RenColor *d = (RenColor*) surf->pixels; d += x1 + y1 * surf->w; int dr = surf->w - (x2 - x1); @@ -380,17 +380,17 @@ void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) /* clip */ int n; - if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; } - if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; } - if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; } - if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; } + if ((n = lt_clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; } + if ((n = lt_clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; } + if ((n = x + sub->width - lt_clip.right ) > 0) { sub->width -= n; } + if ((n = y + sub->height - lt_clip.bottom) > 0) { sub->height -= n; } if (sub->width <= 0 || sub->height <= 0) { return; } /* draw */ - lt_surface *surf = lt_getsurface(window); + lt_surface *surf = lt_getsurface(lt_window()); RenColor *s = image->pixels; RenColor *d = (RenColor*) surf->pixels; s += sub->x + sub->y * image->width; @@ -450,7 +450,7 @@ static int f_set_tab_width(lua_State *L) { } -static int f_gc(lua_State *L) { +static int f_GC(lua_State *L) { RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); if (*self) { rencache_free_font(*self); } return 0; @@ -474,7 +474,7 @@ static int f_get_height(lua_State *L) { int luaopen_renderer_font(lua_State *L) { static const luaL_Reg lib[] = { - { "__gc", f_gc }, + { "__gc", f_GC }, { "load", f_load }, { "set_tab_width", f_set_tab_width }, { "get_width", f_get_width }, diff --git a/tools/editor/3rd_lite_sys.h b/engine/split/3rd_lite_sys.h similarity index 94% rename from tools/editor/3rd_lite_sys.h rename to engine/split/3rd_lite_sys.h index a421e0f..475add4 100644 --- a/tools/editor/3rd_lite_sys.h +++ b/engine/split/3rd_lite_sys.h @@ -46,6 +46,16 @@ lt_surface *lt_getsurface(void *window) { return &s; } void lt_updatesurfacerects(lt_surface *s, lt_rect* rects, unsigned count) { + if(0) + for( int i = 0; i < count; ++i ) { + memset( (unsigned*)s->pixels + (rects[i].x + rects[i].y * s->w), 0xFF, rects[i].width*4 ); + memset( (unsigned*)s->pixels + (rects[i].x + (rects[i].y + (rects[i].height-1)) * s->w), 0xFF, rects[i].width*4 ); + for( int y = 1; y < (rects[i].height-1); ++y ) { + ((unsigned*)s->pixels)[ rects[i].x + y * s->w ] = + ((unsigned*)s->pixels)[ rects[i].x + (rects[i].width-1) + y * s->w ] = 0xFFFFFFFF; + } + } + // update contents texture_update(&s->t, s->w, s->h, 4, s->pixels, TEXTURE_LINEAR|TEXTURE_BGRA); } diff --git a/tools/editor/3rd_lite_sys_gleq.h b/engine/split/3rd_lite_sys_gleq.h similarity index 100% rename from tools/editor/3rd_lite_sys_gleq.h rename to engine/split/3rd_lite_sys_gleq.h diff --git a/engine/split/3rd_lua.h b/engine/split/3rd_lua.h index c4d7f9f..0fe51ae 100644 --- a/engine/split/3rd_lua.h +++ b/engine/split/3rd_lua.h @@ -2,7 +2,7 @@ minilua.h -- Lua in a single header Project URL: https://github.com/edubart/minilua - This is Lua 5.4.4 contained in a single header to be bundled in C/C++ applications with ease. + This is Lua 5.4.6 contained in a single header to be bundled in C/C++ applications with ease. Lua is a powerful, efficient, lightweight, embeddable scripting language. Do the following in *one* C file to create the implementation: @@ -22,7 +22,7 @@ */ /* detect system platform */ -#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) +#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) && !defined(LUA_USE_IOS) #if defined(_WIN32) #define LUA_USE_WINDOWS #elif defined(__linux__) @@ -158,6 +158,12 @@ extern "C" { #endif +#if defined(LUA_USE_IOS) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN +#endif + + /* @@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. */ @@ -816,7 +822,7 @@ extern "C" { ** CHANGE it if you need a different limit. This limit is arbitrary; ** its only purpose is to stop Lua from consuming unlimited stack ** space (and to reserve some numbers for pseudo-indices). -** (It must fit into max(size_t)/32.) +** (It must fit into max(size_t)/32 and max(int)/2.) */ #if LUAI_IS32INT #define LUAI_MAXSTACK 1000000 @@ -835,14 +841,15 @@ extern "C" { /* @@ LUA_IDSIZE gives the maximum size for the description of the source -@@ of a function in debug information. +** of a function in debug information. ** CHANGE it if you want a different size. */ #define LUA_IDSIZE 60 /* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +@@ LUAL_BUFFERSIZE is the initial buffer size used by the lauxlib +** buffer system. */ #define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) @@ -892,14 +899,14 @@ extern "C" { #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "4" +#define LUA_VERSION_RELEASE "6" #define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4) +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 6) #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio" +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" @@ -1005,6 +1012,16 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); +/* +** Type used by the debug API to collect debug information +*/ +typedef struct lua_Debug lua_Debug; + + +/* +** Functions to be called by the debugger in specific events +*/ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); /* @@ -1027,7 +1044,8 @@ extern const char lua_ident[]; LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); LUA_API void (lua_close) (lua_State *L); LUA_API lua_State *(lua_newthread) (lua_State *L); -LUA_API int (lua_resetthread) (lua_State *L); +LUA_API int (lua_closethread) (lua_State *L, lua_State *from); +LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); @@ -1316,12 +1334,6 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx); #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); @@ -1366,7 +1378,7 @@ struct lua_Debug { /****************************************************************************** -* Copyright (C) 1994-2022 Lua.org, PUC-Rio. +* Copyright (C) 1994-2023 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -1744,6 +1756,7 @@ LUALIB_API void (luaL_openlibs) (lua_State *L); #endif #ifdef LUA_IMPL +typedef struct CallInfo CallInfo; /* ** $Id: llimits.h $ ** Limits, basic types, and some other 'installation-dependent' definitions @@ -1817,11 +1830,24 @@ typedef signed char ls_byte; /* -** conversion of pointer to unsigned integer: -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value +** conversion of pointer to unsigned integer: this is for hashing only; +** there is no problem if the integer cannot hold the whole pointer +** value. (In strict ISO C this may cause undefined behavior, but no +** actual machine seems to bother.) */ -#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(UINTPTR_MAX) /* even in C99 this type is optional */ +#define L_P2I uintptr_t +#else /* no 'intptr'? */ +#define L_P2I uintmax_t /* use the largest available integer */ +#endif +#else /* C89 option */ +#define L_P2I size_t +#endif + +#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX)) @@ -2165,6 +2191,8 @@ typedef union Value { lua_CFunction f; /* light C functions */ lua_Integer i; /* integer numbers */ lua_Number n; /* float numbers */ + /* not used, but may avoid warnings for uninitialized value */ + lu_byte ub; } Value; @@ -2268,6 +2296,17 @@ typedef union StackValue { /* index to stack elements */ typedef StackValue *StkId; + +/* +** When reallocating the stack, change all pointers to the stack into +** proper offsets. +*/ +typedef union { + StkId p; /* actual pointer */ + ptrdiff_t offset; /* used while the stack is being reallocated */ +} StkIdRel; + + /* convert a 'StackValue' to a 'TValue' */ #define s2v(o) (&(o)->val) @@ -2728,8 +2767,10 @@ typedef struct Proto { */ typedef struct UpVal { CommonHeader; - lu_byte tbc; /* true if it represents a to-be-closed variable */ - TValue *v; /* points to stack or to its own value */ + union { + TValue *p; /* points to stack or to its own value */ + ptrdiff_t offset; /* used while the stack is being reallocated */ + } v; union { struct { /* (when open) */ struct UpVal *next; /* linked list */ @@ -3015,6 +3056,7 @@ LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); /*#include "lobject.h"*/ +/*#include "lstate.h"*/ /* @@ -3101,8 +3143,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, int inv, int isfloat, TMS event); LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, - struct CallInfo *ci, const Proto *p); -LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, + CallInfo *ci, const Proto *p); +LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted); @@ -3118,6 +3160,11 @@ LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, /*#include "lua.h"*/ + +/* Some header files included here need this definition */ +typedef struct CallInfo CallInfo; + + /*#include "lobject.h"*/ /*#include "ltm.h"*/ /*#include "lzio.h"*/ @@ -3248,7 +3295,7 @@ struct lua_longjmp; /* defined in ldo.c */ #define BASIC_STACK_SIZE (2*LUA_MINSTACK) -#define stacksize(th) cast_int((th)->stack_last - (th)->stack) +#define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p) /* kinds of Garbage Collection */ @@ -3278,9 +3325,9 @@ typedef struct stringtable { ** - field 'transferinfo' is used only during call/returnhooks, ** before the function starts or after it ends. */ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ +struct CallInfo { + StkIdRel func; /* function index in the stack */ + StkIdRel top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ union { struct { /* only for Lua functions */ @@ -3305,7 +3352,7 @@ typedef struct CallInfo { } u2; short nresults; /* expected number of results from this function */ unsigned short callstatus; -} CallInfo; +}; /* @@ -3400,7 +3447,7 @@ typedef struct global_State { struct lua_State *mainthread; TString *memerrmsg; /* message for memory-allocation errors */ TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ lua_WarnFunction warnf; /* warning function */ void *ud_warn; /* auxiliary data to 'warnf' */ @@ -3415,13 +3462,13 @@ struct lua_State { lu_byte status; lu_byte allowhook; unsigned short nci; /* number of items in 'ci' list */ - StkId top; /* first free slot in the stack */ + StkIdRel top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ - StkId stack_last; /* end of stack (last element + 1) */ - StkId stack; /* stack base */ + StkIdRel stack_last; /* end of stack (last element + 1) */ + StkIdRel stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ - StkId tbclist; /* list of to-be-closed variables */ + StkIdRel tbclist; /* list of to-be-closed variables */ GCObject *gclist; struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ @@ -3600,7 +3647,7 @@ iABC C(8) | B(8) |k| A(8) | Op(7) | iABx Bx(17) | A(8) | Op(7) | iAsBx sBx (signed)(17) | A(8) | Op(7) | iAx Ax(25) | Op(7) | -isJ sJ(25) | Op(7) | +isJ sJ (signed)(25) | Op(7) | A signed argument is represented in excess K: the represented value is the written unsigned value minus K, where K is half the maximum for the @@ -3999,7 +4046,7 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) /* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue(s2v((ci)->func))) +#define ci_func(ci) (clLvalue(s2v((ci)->func.p))) #define resethookcount(L) (L->hookcount = L->basehookcount) @@ -4055,6 +4102,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); #define ldo_h +/*#include "llimits.h"*/ /*#include "lobject.h"*/ /*#include "lstate.h"*/ /*#include "lzio.h"*/ @@ -4070,7 +4118,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); ** at every check. */ #define luaD_checkstackaux(L,n,pre,pos) \ - if (l_unlikely(L->stack_last - L->top <= (n))) \ + if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ { pre; luaD_growstack(L, n, 1); pos; } \ else { condmovestack(L,pre,pos); } @@ -4079,11 +4127,18 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((StkId)((char *)L->stack + (n))) +#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p)) +#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n)) /* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* macro to check stack size and GC, preserving 'p' */ #define checkstackGCp(L,n,p) \ luaD_checkstackaux(L, n, \ ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ @@ -4105,7 +4160,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); -LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta); +LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, + int narg1, int delta); LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); @@ -4298,24 +4354,27 @@ LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) -#define luaC_barrier(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) - -#define luaC_barrierback(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrierback_(L,p) : cast_void(0)) - #define luaC_objbarrier(L,p,o) ( \ (isblack(p) && iswhite(o)) ? \ luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) +#define luaC_barrier(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0)) + +#define luaC_objbarrierback(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : cast_void(0)) + LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, + size_t offset); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); @@ -4354,10 +4413,10 @@ LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); #define MAXUPVAL 255 -#define upisopen(up) ((up)->v != &(up)->u.value) +#define upisopen(up) ((up)->v.p != &(up)->u.value) -#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) +#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p)) /* @@ -4379,7 +4438,7 @@ LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); +LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); LUAI_FUNC void luaF_unlinkupval (UpVal *uv); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, @@ -4494,23 +4553,26 @@ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, /*#include "lstate.h"*/ -/* Increments 'L->top', checking for stack overflows */ -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} +/* Increments 'L->top.p', checking for stack overflows */ +#define api_incr_top(L) {L->top.p++; \ + api_check(L, L->top.p <= L->ci->top.p, \ + "stack overflow");} /* ** If a call returns too many multiple returns, the callee may not have ** stack space to accommodate all results. In this case, this macro -** increases its stack space ('L->ci->top'). +** increases its stack space ('L->ci->top.p'). */ #define adjustresults(L,nres) \ - { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + { if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \ + L->ci->top.p = L->top.p; } /* Ensure the stack has at least 'n' elements */ -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") +#define api_checknelems(L,n) \ + api_check(L, (n) < (L->top.p - L->ci->func.p), \ + "not enough elements in the stack") /* @@ -4681,7 +4743,6 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t); #if defined(LUA_DEBUG) LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (const Table *t); #endif @@ -5073,6 +5134,11 @@ typedef enum { luaC_barrierback(L, gcvalue(t), v); } +/* +** Shift right is the same as shift left with a negative 'y' +*/ +#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); @@ -5458,25 +5524,6 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { /*#include "lstate.h"*/ -#if defined(EMERGENCYGCTESTS) -/* -** First allocation will fail whenever not building initial state. -** (This fail will trigger 'tryagain' and a full GC cycle at every -** allocation.) -*/ -static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { - if (completestate(g) && ns > 0) /* frees never fail */ - return NULL; /* fail */ - else /* normal allocation */ - return (*g->frealloc)(g->ud, block, os, ns); -} -#else -#define firsttry(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) -#endif - - - - /* ** About the realloc function: @@ -5496,6 +5543,43 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { */ +/* +** Macro to call the allocation function. +*/ +#define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) + + +/* +** When an allocation fails, it will try again after an emergency +** collection, except when it cannot run a collection. The GC should +** not be called while the state is not fully built, as the collector +** is not yet fully initialized. Also, it should not be called when +** 'gcstopem' is true, because then the interpreter is in the middle of +** a collection step. +*/ +#define cantryagain(g) (completestate(g) && !g->gcstopem) + + + + +#if defined(EMERGENCYGCTESTS) +/* +** First allocation will fail except when freeing a block (frees never +** fail) and when it cannot try again; this fail will trigger 'tryagain' +** and a full GC cycle at every allocation. +*/ +static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { + if (ns > 0 && cantryagain(g)) + return NULL; /* fail */ + else /* normal allocation */ + return callfrealloc(g, block, os, ns); +} +#else +#define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns) +#endif + + + /* @@ -5568,7 +5652,7 @@ l_noret luaM_toobig (lua_State *L) { void luaM_free_ (lua_State *L, void *block, size_t osize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); - (*g->frealloc)(g->ud, block, osize, 0); + callfrealloc(g, block, osize, 0); g->GCdebt -= osize; } @@ -5576,19 +5660,15 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { /* ** In case of allocation fail, this function will do an emergency ** collection to free some memory and then try the allocation again. -** The GC should not be called while state is not fully built, as the -** collector is not yet fully initialized. Also, it should not be called -** when 'gcstopem' is true, because then the interpreter is in the -** middle of a collection step. */ static void *tryagain (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); - if (completestate(g) && !g->gcstopem) { + if (cantryagain(g)) { luaC_fullgc(L, 1); /* try to free some memory... */ - return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + return callfrealloc(g, block, osize, nsize); /* try again */ } - else return NULL; /* cannot free any memory without a full state */ + else return NULL; /* cannot run an emergency collection */ } @@ -5757,10 +5837,10 @@ static TString *loadStringN (LoadState *S, Proto *p) { } else { /* long string */ ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ + setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ luaD_inctop(L); loadVector(S, getstr(ts), size); /* load directly in final place */ - L->top--; /* pop string */ + L->top.p--; /* pop string */ } luaC_objbarrier(L, p, ts); return ts; @@ -5885,6 +5965,8 @@ static void loadDebug (LoadState *S, Proto *f) { f->locvars[i].endpc = loadInt(S); } n = loadInt(S); + if (n != 0) /* does it have debug information? */ + n = f->sizeupvalues; /* must be this many */ for (i = 0; i < n; i++) f->upvalues[i].name = loadStringN(S, f); } @@ -5958,7 +6040,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { S.Z = Z; checkHeader(&S); cl = luaF_newLclosure(L, loadByte(&S)); - setclLvalue2s(L, L->top, cl); + setclLvalue2s(L, L->top.p, cl); luaD_inctop(L); cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -5980,6 +6062,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { /*#include "lprefix.h"*/ +#include #include /*#include "lua.h"*/ @@ -6025,8 +6108,11 @@ static void dumpByte (DumpState *D, int y) { } -/* dumpInt Buff Size */ -#define DIBS ((sizeof(size_t) * 8 / 7) + 1) +/* +** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" +** rounds up the division.) +*/ +#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) static void dumpSize (DumpState *D, size_t x) { lu_byte buff[DIBS]; @@ -6376,33 +6462,33 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) { static void stack_init (lua_State *L1, lua_State *L) { int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); - L1->tbclist = L1->stack; + L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); + L1->tbclist.p = L1->stack.p; for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) - setnilvalue(s2v(L1->stack + i)); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + BASIC_STACK_SIZE; + setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ + L1->top.p = L1->stack.p; + L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; ci->callstatus = CIST_C; - ci->func = L1->top; + ci->func.p = L1->top.p; ci->u.c.k = NULL; ci->nresults = 0; - setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ - L1->top++; - ci->top = L1->top + LUA_MINSTACK; + setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ + L1->top.p++; + ci->top.p = L1->top.p + LUA_MINSTACK; L1->ci = ci; } static void freestack (lua_State *L) { - if (L->stack == NULL) + if (L->stack.p == NULL) return; /* stack not completely built yet */ L->ci = &L->base_ci; /* free the entire 'ci' list */ luaE_freeCI(L); lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ + luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ } @@ -6444,7 +6530,7 @@ static void f_luaopen (lua_State *L, void *ud) { */ static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; - L->stack = NULL; + L->stack.p = NULL; L->ci = NULL; L->nci = 0; L->twups = L; /* thread has no upvalues */ @@ -6480,20 +6566,16 @@ static void close_state (lua_State *L) { LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g; + global_State *g = G(L); + GCObject *o; lua_State *L1; lua_lock(L); - g = G(L); luaC_checkGC(L); /* create new thread */ - L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g); - L1->tt = LUA_VTHREAD; - /* link it on list 'allgc' */ - L1->next = g->allgc; - g->allgc = obj2gco(L1); + o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l)); + L1 = gco2th(o); /* anchor it on L stack */ - setthvalue2s(L, L->top, L1); + setthvalue2s(L, L->top.p, L1); api_incr_top(L); preinit_thread(L1, g); L1->hookmask = L->hookmask; @@ -6512,7 +6594,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { void luaE_freethread (lua_State *L, lua_State *L1) { LX *l = fromstate(L1); - luaF_closeupval(L1, L1->stack); /* close all upvalues */ + luaF_closeupval(L1, L1->stack.p); /* close all upvalues */ lua_assert(L1->openupval == NULL); luai_userstatefree(L, L1); freestack(L1); @@ -6522,32 +6604,41 @@ void luaE_freethread (lua_State *L, lua_State *L1) { int luaE_resetthread (lua_State *L, int status) { CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ - setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ - ci->func = L->stack; + setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ + ci->func.p = L->stack.p; ci->callstatus = CIST_C; if (status == LUA_YIELD) status = LUA_OK; L->status = LUA_OK; /* so it can run __close metamethods */ status = luaD_closeprotected(L, 1, status); if (status != LUA_OK) /* errors? */ - luaD_seterrorobj(L, status, L->stack + 1); + luaD_seterrorobj(L, status, L->stack.p + 1); else - L->top = L->stack + 1; - ci->top = L->top + LUA_MINSTACK; - luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); + L->top.p = L->stack.p + 1; + ci->top.p = L->top.p + LUA_MINSTACK; + luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); return status; } -LUA_API int lua_resetthread (lua_State *L) { +LUA_API int lua_closethread (lua_State *L, lua_State *from) { int status; lua_lock(L); + L->nCcalls = (from) ? getCcalls(from) : 0; status = luaE_resetthread(L, L->status); lua_unlock(L); return status; } +/* +** Deprecated! Use 'lua_closethread' instead. +*/ +LUA_API int lua_resetthread (lua_State *L) { + return lua_closethread(L, NULL); +} + + LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; @@ -6622,7 +6713,7 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) { ** Generate a warning from an error message */ void luaE_warnerror (lua_State *L, const char *where) { - TValue *errobj = s2v(L->top - 1); /* error object */ + TValue *errobj = s2v(L->top.p - 1); /* error object */ const char *msg = (ttisstring(errobj)) ? svalue(errobj) : "error object is not a string"; @@ -6888,12 +6979,13 @@ void luaC_fix (lua_State *L, GCObject *o) { /* -** create a new collectable object (with given type and size) and link -** it to 'allgc' list. +** create a new collectable object (with given type, size, and offset) +** and link it to 'allgc' list. */ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { +GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { global_State *g = G(L); - GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); + GCObject *o = cast(GCObject *, p + offset); o->marked = luaC_white(g); o->tt = tt; o->next = g->allgc; @@ -6901,6 +6993,11 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { return o; } + +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + return luaC_newobjdt(L, tt, sz, 0); +} + /* }====================================================== */ @@ -6937,7 +7034,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { set2gray(uv); /* open upvalues are kept gray */ else set2black(uv); /* closed upvalues are visited here */ - markvalue(g, uv->v); /* mark its content */ + markvalue(g, uv->v.p); /* mark its content */ break; } case LUA_VUSERDATA: { @@ -7012,7 +7109,7 @@ static int remarkupvals (global_State *g) { work++; if (!iswhite(uv)) { /* upvalue already visited? */ lua_assert(upisopen(uv) && isgray(uv)); - markvalue(g, uv->v); /* mark its value */ + markvalue(g, uv->v.p); /* mark its value */ } } } @@ -7256,19 +7353,19 @@ static int traverseLclosure (global_State *g, LClosure *cl) { */ static int traversethread (global_State *g, lua_State *th) { UpVal *uv; - StkId o = th->stack; + StkId o = th->stack.p; if (isold(th) || g->gcstate == GCSpropagate) linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ if (o == NULL) return 1; /* stack not completely built yet */ lua_assert(g->gcstate == GCSatomic || th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ + for (; o < th->top.p; o++) /* mark live elements in the stack */ markvalue(g, s2v(o)); for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ - for (; o < th->stack_last + EXTRA_STACK; o++) + for (; o < th->stack_last.p + EXTRA_STACK; o++) setnilvalue(s2v(o)); /* clear dead stack slice */ /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { @@ -7528,7 +7625,7 @@ static GCObject *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); + luaD_callnoyield(L, L->top.p - 2, 0); } @@ -7545,16 +7642,16 @@ static void GCTM (lua_State *L) { int oldgcstp = g->gcstp; g->gcstp |= GCSTPGC; /* avoid GC steps */ L->allowhook = 0; /* stop debug hooks during GC metamethod */ - setobj2s(L, L->top++, tm); /* push finalizer... */ - setobj2s(L, L->top++, &v); /* ... and its argument */ + setobj2s(L, L->top.p++, tm); /* push finalizer... */ + setobj2s(L, L->top.p++, &v); /* ... and its argument */ L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0); L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ g->gcstp = oldgcstp; /* restore state */ if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ luaE_warnerror(L, "__gc"); - L->top--; /* pops error object */ + L->top.p--; /* pops error object */ } } } @@ -7677,7 +7774,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** ======================================================= */ -static void setpause (global_State *g); + +/* +** Set the "time" to wait before starting a new GC cycle; cycle will +** start when memory use hits the threshold of ('estimate' * pause / +** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, +** because Lua cannot even start with less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + int pause = getgcparam(g->gcpause); + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (pause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * pause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + if (debt > 0) debt = 0; + luaE_setdebt(g, debt); +} /* @@ -7921,6 +8036,15 @@ static void atomic2gen (lua_State *L, global_State *g) { } +/* +** Set debt for the next minor collection, which will happen when +** memory grows 'genminormul'%. +*/ +static void setminordebt (global_State *g) { + luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); +} + + /* ** Enter generational mode. Must go until the end of an atomic cycle ** to ensure that all objects are correctly marked and weak tables @@ -7933,6 +8057,7 @@ static lu_mem entergen (lua_State *L, global_State *g) { luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ numobjs = atomic(L); /* propagates all and then do the atomic stuff */ atomic2gen(L, g); + setminordebt(g); /* set debt assuming next cycle will be minor */ return numobjs; } @@ -7978,15 +8103,6 @@ static lu_mem fullgen (lua_State *L, global_State *g) { } -/* -** Set debt for the next minor collection, which will happen when -** memory grows 'genminormul'%. -*/ -static void setminordebt (global_State *g) { - luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); -} - - /* ** Does a major collection after last collection was a "bad collection". ** @@ -8058,8 +8174,8 @@ static void genstep (lua_State *L, global_State *g) { lu_mem numobjs = fullgen(L, g); /* do a major collection */ if (gettotalbytes(g) < majorbase + (majorinc / 2)) { /* collected at least half of memory growth since last major - collection; keep doing minor collections */ - setminordebt(g); + collection; keep doing minor collections. */ + lua_assert(g->lastatomic == 0); } else { /* bad collection */ g->lastatomic = numobjs; /* signal that last collection was bad */ @@ -8085,26 +8201,6 @@ static void genstep (lua_State *L, global_State *g) { */ -/* -** Set the "time" to wait before starting a new GC cycle; cycle will -** start when memory use hits the threshold of ('estimate' * pause / -** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, -** because Lua cannot even start with less than PAUSEADJ bytes). -*/ -static void setpause (global_State *g) { - l_mem threshold, debt; - int pause = getgcparam(g->gcpause); - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (pause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * pause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - if (debt > 0) debt = 0; - luaE_setdebt(g, debt); -} - - /* ** Enter first sweep phase. ** The call to 'sweeptolive' makes the pointer point to an object @@ -8312,12 +8408,15 @@ static void incstep (lua_State *L, global_State *g) { } /* -** performs a basic GC step if collector is running +** Performs a basic GC step if collector is running. (If collector is +** not running, set a reasonable debt to avoid it being called at +** every single check.) */ void luaC_step (lua_State *L) { global_State *g = G(L); - lua_assert(!g->gcemergency); - if (gcrunning(g)) { /* running? */ + if (!gcrunning(g)) /* not running? */ + luaE_setdebt(g, -2000); + else { if(isdecGCmodegen(g)) genstep(L, g); else @@ -8495,7 +8594,7 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { ** ensuring there is only one copy of each unique string. The table ** here is used as a set: the string enters as the key, while its value ** is irrelevant. We use the string itself as the value only because it -** is a TValue readly available. Later, the code generation can change +** is a TValue readily available. Later, the code generation can change ** this value. */ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { @@ -8505,12 +8604,12 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { if (!ttisnil(o)) /* string already present? */ ts = keystrval(nodefromval(o)); /* get saved copy */ else { /* not in use yet */ - TValue *stv = s2v(L->top++); /* reserve stack space for string */ + TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ setsvalue(L, stv, ts); /* temporarily anchor the string */ luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ /* table is not a metatable, so it does not need to invalidate cache */ luaC_checkGC(L); - L->top--; /* remove string from stack */ + L->top.p--; /* remove string from stack */ } return ts; } @@ -10299,6 +10398,35 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, } +/* +** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) { + lua_assert(baser <= opr && + ((baser == OPR_ADD && opr <= OPR_SHR) || + (baser == OPR_LT && opr <= OPR_LE))); + return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base)); +} + + +/* +** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode unopr2op (UnOpr opr) { + return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) + + cast_int(OP_UNM)); +} + + +/* +** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM) +*/ +l_sinline TMS binopr2TM (BinOpr opr) { + lua_assert(OPR_ADD <= opr && opr <= OPR_SHR); + return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD)); +} + + /* ** Emit code for unary expressions that "produce values" ** (everything but 'not'). @@ -10337,12 +10465,15 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, ** Emit code for binary expressions that "produce values" over ** two registers. */ -static void codebinexpval (FuncState *fs, OpCode op, +static void codebinexpval (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { - int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADD); + int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */ + /* 'e1' must be already in a register or it is a constant */ + lua_assert((VNIL <= e1->k && e1->k <= VKSTR) || + e1->k == VNONRELOC || e1->k == VRELOC); lua_assert(OP_ADD <= op && op <= OP_SHR); - finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, - cast(TMS, (op - OP_ADD) + TM_ADD)); + finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr)); } @@ -10358,6 +10489,18 @@ static void codebini (FuncState *fs, OpCode op, } +/* +** Code binary operators with K operand. +*/ +static void codebinK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + TMS event = binopr2TM(opr); + int v2 = e2->u.info; /* K index */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); +} + + /* Try to code a binary operator negating its second operand. ** For the metamethod, 2nd operand must keep its original value. */ @@ -10385,24 +10528,27 @@ static void swapexps (expdesc *e1, expdesc *e2) { } +/* +** Code binary operators with no constant operand. +*/ +static void codebinNoK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + if (flip) + swapexps(e1, e2); /* back to original order */ + codebinexpval(fs, opr, e1, e2, line); /* use standard operators */ +} + + /* ** Code arithmetic operators ('+', '-', ...). If second operand is a ** constant in the proper range, use variant opcodes with K operands. */ static void codearith (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int flip, int line) { - TMS event = cast(TMS, opr + TM_ADD); - if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ - int v2 = e2->u.info; /* K index */ - OpCode op = cast(OpCode, opr + OP_ADDK); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); - } - else { /* 'e2' is neither an immediate nor a K operand */ - OpCode op = cast(OpCode, opr + OP_ADD); - if (flip) - swapexps(e1, e2); /* back to original order */ - codebinexpval(fs, op, e1, e2, line); /* use standard operators */ - } + if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* 'e2' is neither an immediate nor a K operand */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -10419,35 +10565,27 @@ static void codecommutative (FuncState *fs, BinOpr op, flip = 1; } if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ - codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); + codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD); else codearith(fs, op, e1, e2, flip, line); } /* -** Code bitwise operations; they are all associative, so the function +** Code bitwise operations; they are all commutative, so the function ** tries to put an integer constant as the 2nd operand (a K operand). */ static void codebitwise (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { int flip = 0; - int v2; - OpCode op; - if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { + if (e1->k == VKINT) { swapexps(e1, e2); /* 'e2' will be the constant operand */ flip = 1; } - else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ - op = cast(OpCode, opr + OP_ADD); - codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ - return; - } - v2 = e2->u.info; /* index in K array */ - op = cast(OpCode, opr + OP_ADDK); - lua_assert(ttisinteger(&fs->f->k[v2])); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, - cast(TMS, opr + TM_ADD)); + if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* no constants */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -10455,25 +10593,27 @@ static void codebitwise (FuncState *fs, BinOpr opr, ** Emit code for order comparisons. When using an immediate operand, ** 'isfloat' tells whether the original value was a float. */ -static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { +static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { int r1, r2; int im; int isfloat = 0; + OpCode op; if (isSCnumber(e2, &im, &isfloat)) { /* use immediate operand */ r1 = luaK_exp2anyreg(fs, e1); r2 = im; - op = cast(OpCode, (op - OP_LT) + OP_LTI); + op = binopr2op(opr, OPR_LT, OP_LTI); } else if (isSCnumber(e1, &im, &isfloat)) { /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ r1 = luaK_exp2anyreg(fs, e2); r2 = im; - op = (op == OP_LT) ? OP_GTI : OP_GEI; + op = binopr2op(opr, OPR_LT, OP_GTI); } else { /* regular case, compare two registers */ r1 = luaK_exp2anyreg(fs, e1); r2 = luaK_exp2anyreg(fs, e2); + op = binopr2op(opr, OPR_LT, OP_LT); } freeexps(fs, e1, e2); e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); @@ -10499,7 +10639,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { op = OP_EQI; r2 = im; /* immediate operand */ } - else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */ op = OP_EQK; r2 = e2->u.info; /* constant index */ } @@ -10516,16 +10656,16 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { /* ** Apply prefix operation 'op' to expression 'e'. */ -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { +void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) { static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; luaK_dischargevars(fs, e); - switch (op) { + switch (opr) { case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + if (constfolding(fs, opr + LUA_OPUNM, e, &ef)) break; /* else */ /* FALLTHROUGH */ case OPR_LEN: - codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + codeunexpval(fs, unopr2op(opr), e, line); break; case OPR_NOT: codenot(fs, e); break; default: lua_assert(0); @@ -10559,7 +10699,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { case OPR_SHL: case OPR_SHR: { if (!tonumeral(v, NULL)) luaK_exp2anyreg(fs, v); - /* else keep numeral, which may be folded with 2nd operand */ + /* else keep numeral, which may be folded or used as an immediate + operand */ break; } case OPR_EQ: case OPR_NE: { @@ -10654,30 +10795,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr, /* coded as (r1 >> -I) */; } else /* regular case (two registers) */ - codebinexpval(fs, OP_SHL, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_SHR: { if (isSCint(e2)) codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ else /* regular case (two registers) */ - codebinexpval(fs, OP_SHR, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_EQ: case OPR_NE: { codeeq(fs, opr, e1, e2); break; } - case OPR_LT: case OPR_LE: { - OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - codeorder(fs, op, e1, e2); - break; - } case OPR_GT: case OPR_GE: { /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ - OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); swapexps(e1, e2); - codeorder(fs, op, e1, e2); + opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT); + } /* FALLTHROUGH */ + case OPR_LT: case OPR_LE: { + codeorder(fs, opr, e1, e2); break; } default: lua_assert(0); @@ -11248,6 +11386,7 @@ static void singlevar (LexState *ls, expdesc *var) { expdesc key; singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ lua_assert(var->k != VVOID); /* this one must exist */ + luaK_exp2anyregup(fs, var); /* but could be a constant */ codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ } @@ -11300,12 +11439,12 @@ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { /* ** Solves the goto at index 'g' to given 'label' and removes it -** from the list of pending goto's. +** from the list of pending gotos. ** If it jumps into the scope of some variable, raises an error. */ static void solvegoto (LexState *ls, int g, Labeldesc *label) { int i; - Labellist *gl = &ls->dyd->gt; /* list of goto's */ + Labellist *gl = &ls->dyd->gt; /* list of gotos */ Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ lua_assert(eqstr(gt->name, label->name)); if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ @@ -11359,7 +11498,7 @@ static int newgotoentry (LexState *ls, TString *name, int line, int pc) { /* ** Solves forward jumps. Check whether new label 'lb' matches any ** pending gotos in current block and solves them. Return true -** if any of the goto's need to close upvalues. +** if any of the gotos need to close upvalues. */ static int solvegotos (LexState *ls, Labeldesc *lb) { Labellist *gl = &ls->dyd->gt; @@ -11380,7 +11519,7 @@ static int solvegotos (LexState *ls, Labeldesc *lb) { /* ** Create a new label with the given 'name' at the given 'line'. ** 'last' tells whether label is the last non-op statement in its -** block. Solves all pending goto's to this new label and adds +** block. Solves all pending gotos to this new label and adds ** a close instruction if necessary. ** Returns true iff it added a close instruction. */ @@ -11453,19 +11592,19 @@ static void leaveblock (FuncState *fs) { LexState *ls = fs->ls; int hasclose = 0; int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ - if (bl->isloop) /* fix pending breaks? */ + removevars(fs, bl->nactvar); /* remove block locals */ + lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ + if (bl->isloop) /* has to fix pending breaks? */ hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); - if (!hasclose && bl->previous && bl->upval) + if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */ luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); fs->freereg = stklevel; /* free registers */ ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ + fs->bl = bl->previous; /* current block now is previous one */ + if (bl->previous) /* was it a nested block? */ + movegotosout(fs, bl); /* update pending gotos to enclosing block */ else { - if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } } @@ -12723,10 +12862,10 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, LexState lexstate; FuncState funcstate; LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue2s(L, L->top, cl); /* anchor it (to avoid being collected) */ + setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ luaD_inctop(L); lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue2s(L, L->top, lexstate.h); /* anchor it */ + sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */ luaD_inctop(L); funcstate.f = cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -12740,7 +12879,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); /* all scopes should be correctly finished */ lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top--; /* remove scanner's table */ + L->top.p--; /* remove scanner's table */ return cl; /* closure is on the stack, too */ } @@ -12928,10 +13067,10 @@ static const char *upvalname (const Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func))->p->is_vararg) { + if (clLvalue(s2v(ci->func.p))->p->is_vararg) { int nextra = ci->u.l.nextraargs; if (n >= -nextra) { /* 'n' is negative */ - *pos = ci->func - nextra - (n + 1); + *pos = ci->func.p - nextra - (n + 1); return "(vararg)"; /* generic name for any vararg */ } } @@ -12940,7 +13079,7 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) { const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; const char *name = NULL; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ @@ -12949,7 +13088,7 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); } if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; + StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p; if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */ /* generic name for any valid slot */ name = isLua(ci) ? "(temporary)" : "(C temporary)"; @@ -12967,16 +13106,16 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */ + if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0); + name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0); } else { /* active function; get information through 'ar' */ StkId pos = NULL; /* to avoid warnings */ name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, L->top, pos); + setobjs2s(L, L->top.p, pos); api_incr_top(L); } } @@ -12991,8 +13130,8 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { lua_lock(L); name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ + setobjs2s(L, pos, L->top.p - 1); + L->top.p--; /* pop value */ } lua_unlock(L); return name; @@ -13035,7 +13174,7 @@ static int nextline (const Proto *p, int currentline, int pc) { static void collectvalidlines (lua_State *L, Closure *f) { if (noLuaClosure(f)) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); } else { @@ -13044,7 +13183,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { const Proto *p = f->l.p; int currentline = p->linedefined; Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue2s(L, L->top, t); /* push it on stack */ + sethvalue2s(L, L->top.p, t); /* push it on stack */ api_incr_top(L); setbtvalue(&v); /* boolean 'true' to be the value of all indices */ if (!p->is_vararg) /* regular function? */ @@ -13134,20 +13273,20 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { lua_lock(L); if (*what == '>') { ci = NULL; - func = s2v(L->top - 1); + func = s2v(L->top.p - 1); api_check(L, ttisfunction(func), "function expected"); what++; /* skip the '>' */ - L->top--; /* pop function */ + L->top.p--; /* pop function */ } else { ci = ar->i_ci; - func = s2v(ci->func); + func = s2v(ci->func.p); lua_assert(ttisfunction(func)); } cl = ttisclosure(func) ? clvalue(func) : NULL; status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - setobj2s(L, L->top, func); + setobj2s(L, L->top.p, func); api_incr_top(L); } if (strchr(what, 'L')) @@ -13402,18 +13541,19 @@ static const char *funcnamefromcall (lua_State *L, CallInfo *ci, /* -** Check whether pointer 'o' points to some value in the stack -** frame of the current function. Because 'o' may not point to a -** value in this stack, we cannot compare it with the region -** boundaries (undefined behaviour in ISO C). +** Check whether pointer 'o' points to some value in the stack frame of +** the current function and, if so, returns its index. Because 'o' may +** not point to a value in this stack, we cannot compare it with the +** region boundaries (undefined behavior in ISO C). */ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId pos; - for (pos = ci->func + 1; pos < ci->top; pos++) { - if (o == s2v(pos)) - return 1; +static int instack (CallInfo *ci, const TValue *o) { + int pos; + StkId base = ci->func.p + 1; + for (pos = 0; base + pos < ci->top.p; pos++) { + if (o == s2v(base + pos)) + return pos; } - return 0; /* not found */ + return -1; /* not found */ } @@ -13427,7 +13567,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, LClosure *c = ci_func(ci); int i; for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { + if (c->upvals[i]->v.p == o) { *name = upvalname(c->p, i); return "upvalue"; } @@ -13454,9 +13594,11 @@ static const char *varinfo (lua_State *L, const TValue *o) { const char *kind = NULL; if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(cast(StkId, o) - (ci->func + 1)), &name); + if (!kind) { /* not an upvalue? */ + int reg = instack(ci, o); /* try a register */ + if (reg >= 0) /* is 'o' a register? */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name); + } } return formatvarinfo(L, kind, name); } @@ -13553,10 +13695,10 @@ l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); lua_assert(ttisfunction(s2v(errfunc))); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top - 2, 1); /* call it */ + setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */ + setobjs2s(L, L->top.p - 1, errfunc); /* push function */ + L->top.p++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } @@ -13570,8 +13712,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ + if (isLua(ci)) { /* if Lua function, add source:line information */ luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); + setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ + L->top.p--; + } luaG_errormsg(L); } @@ -13588,7 +13733,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { if (p->lineinfo == NULL) /* no debug information? */ return 0; if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */ - int delta = 0; /* line diference */ + int delta = 0; /* line difference */ int pc = oldpc; for (;;) { int lineinfo = p->lineinfo[++pc]; @@ -13615,7 +13760,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { ** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc' ** at most causes an extra call to a line hook.) ** This function is not "Protected" when called, so it should correct -** 'L->top' before calling anything that can run the GC. +** 'L->top.p' before calling anything that can run the GC. */ int luaG_traceexec (lua_State *L, const Instruction *pc) { CallInfo *ci = L->ci; @@ -13638,7 +13783,7 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { return 1; /* do not call hook again (VM yielded, so it did not move) */ } if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ - L->top = ci->top; /* correct top */ + L->top.p = ci->top.p; /* correct top */ if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ if (mask & LUA_MASKLINE) { @@ -13714,8 +13859,8 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { for (i = 0; i < cl->nupvalues; i++) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); - uv->v = &uv->u.value; /* make it closed */ - setnilvalue(uv->v); + uv->v.p = &uv->u.value; /* make it closed */ + setnilvalue(uv->v.p); cl->upvals[i] = uv; luaC_objbarrier(L, cl, uv); } @@ -13726,12 +13871,11 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { ** Create a new upvalue at the given level, and link it to the list of ** open upvalues of 'L' after entry 'prev'. **/ -static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { +static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); UpVal *next = *prev; - uv->v = s2v(level); /* current value lives in the stack */ - uv->tbc = tbc; + uv->v.p = s2v(level); /* current value lives in the stack */ uv->u.open.next = next; /* link it to list of open upvalues */ uv->u.open.previous = prev; if (next) @@ -13760,7 +13904,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { pp = &p->u.open.next; } /* not found: create a new upvalue after 'pp' */ - return newupval(L, 0, level, pp); + return newupval(L, level, pp); } @@ -13770,12 +13914,12 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { ** (This function assumes EXTRA_STACK.) */ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { - StkId top = L->top; + StkId top = L->top.p; const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); setobj2s(L, top, tm); /* will call metamethod... */ setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ - L->top = top + 3; /* add function and arguments */ + L->top.p = top + 3; /* add function and arguments */ if (yy) luaD_call(L, top, 0); else @@ -13790,7 +13934,7 @@ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { static void checkclosemth (lua_State *L, StkId level) { const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); if (ttisnil(tm)) { /* no metamethod? */ - int idx = cast_int(level - L->ci->func); /* variable index */ + int idx = cast_int(level - L->ci->func.p); /* variable index */ const char *vname = luaG_findlocal(L, L->ci, idx, NULL); if (vname == NULL) vname = "?"; luaG_runerror(L, "variable '%s' got a non-closable value", vname); @@ -13824,23 +13968,23 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { ** is used.) */ #define MAXDELTA \ - ((256ul << ((sizeof(L->stack->tbclist.delta) - 1) * 8)) - 1) + ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) /* ** Insert a variable in the list of to-be-closed variables. */ void luaF_newtbcupval (lua_State *L, StkId level) { - lua_assert(level > L->tbclist); + lua_assert(level > L->tbclist.p); if (l_isfalse(s2v(level))) return; /* false doesn't need to be closed */ checkclosemth(L, level); /* value must have a close method */ - while (cast_uint(level - L->tbclist) > MAXDELTA) { - L->tbclist += MAXDELTA; /* create a dummy node at maximum delta */ - L->tbclist->tbclist.delta = 0; + while (cast_uint(level - L->tbclist.p) > MAXDELTA) { + L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ + L->tbclist.p->tbclist.delta = 0; } - level->tbclist.delta = cast(unsigned short, level - L->tbclist); - L->tbclist = level; + level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); + L->tbclist.p = level; } @@ -13860,10 +14004,10 @@ void luaF_closeupval (lua_State *L, StkId level) { StkId upl; /* stack index pointed by 'uv' */ while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { TValue *slot = &uv->u.value; /* new position for value */ - lua_assert(uplevel(uv) < L->top); + lua_assert(uplevel(uv) < L->top.p); luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ - setobj(L, slot, uv->v); /* move value to upvalue slot */ - uv->v = slot; /* now current value lives here */ + setobj(L, slot, uv->v.p); /* move value to upvalue slot */ + uv->v.p = slot; /* now current value lives here */ if (!iswhite(uv)) { /* neither white nor dead? */ nw2black(uv); /* closed upvalues cannot be gray */ luaC_barrier(L, uv, slot); @@ -13873,31 +14017,32 @@ void luaF_closeupval (lua_State *L, StkId level) { /* -** Remove firt element from the tbclist plus its dummy nodes. +** Remove first element from the tbclist plus its dummy nodes. */ static void poptbclist (lua_State *L) { - StkId tbc = L->tbclist; + StkId tbc = L->tbclist.p; lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ tbc -= tbc->tbclist.delta; - while (tbc > L->stack && tbc->tbclist.delta == 0) + while (tbc > L->stack.p && tbc->tbclist.delta == 0) tbc -= MAXDELTA; /* remove dummy nodes */ - L->tbclist = tbc; + L->tbclist.p = tbc; } /* ** Close all upvalues and to-be-closed variables up to the given stack -** level. +** level. Return restored 'level'. */ -void luaF_close (lua_State *L, StkId level, int status, int yy) { +StkId luaF_close (lua_State *L, StkId level, int status, int yy) { ptrdiff_t levelrel = savestack(L, level); luaF_closeupval(L, level); /* first, close the upvalues */ - while (L->tbclist >= level) { /* traverse tbc's down to that level */ - StkId tbc = L->tbclist; /* get variable index */ + while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ + StkId tbc = L->tbclist.p; /* get variable index */ poptbclist(L); /* remove it from list */ prepcallclosemth(L, tbc, status, yy); /* close variable */ level = restorestack(L, levelrel); } + return level; } @@ -14020,7 +14165,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, case LUA_OPBOR: return intop(|, v1, v2); case LUA_OPBXOR: return intop(^, v1, v2); case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPSHR: return luaV_shiftr(v1, v2); case LUA_OPUNM: return intop(-, 0, v1); case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); default: lua_assert(0); return 0; @@ -14344,29 +14489,39 @@ void luaO_tostring (lua_State *L, TValue *obj) { ** =================================================================== */ -/* size for buffer space used by 'luaO_pushvfstring' */ -#define BUFVFS 200 +/* +** Size for buffer space used by 'luaO_pushvfstring'. It should be +** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, +** so that 'luaG_addinfo' can work directly on the buffer. +*/ +#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) /* buffer used by 'luaO_pushvfstring' */ typedef struct BuffFS { lua_State *L; - int pushed; /* number of string pieces already on the stack */ + int pushed; /* true if there is a part of the result on the stack */ int blen; /* length of partial string in 'space' */ char space[BUFVFS]; /* holds last part of the result */ } BuffFS; /* -** Push given string to the stack, as part of the buffer, and -** join the partial strings in the stack into one. +** Push given string to the stack, as part of the result, and +** join it to previous partial result if there is one. +** It may call 'luaV_concat' while using one slot from EXTRA_STACK. +** This call cannot invoke metamethods, as both operands must be +** strings. It can, however, raise an error if the result is too +** long. In that case, 'luaV_concat' frees the extra slot before +** raising the error. */ -static void pushstr (BuffFS *buff, const char *str, size_t l) { +static void pushstr (BuffFS *buff, const char *str, size_t lstr) { lua_State *L = buff->L; - setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); - L->top++; /* may use one extra slot */ - buff->pushed++; - luaV_concat(L, buff->pushed); /* join partial results into one */ - buff->pushed = 1; + setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr)); + L->top.p++; /* may use one slot from EXTRA_STACK */ + if (!buff->pushed) /* no previous string on the stack? */ + buff->pushed = 1; /* now there is one */ + else /* join previous string with new one */ + luaV_concat(L, 2); } @@ -14412,7 +14567,7 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { /* -** Add a number to the buffer. +** Add a numeral to the buffer. */ static void addnum2buff (BuffFS *buff, TValue *num) { char *numbuff = getbuff(buff, MAXNUMBER2STR); @@ -14490,7 +14645,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ clearbuff(&buff); /* empty buffer into the stack */ lua_assert(buff.pushed == 1); - return svalue(s2v(L->top - 1)); + return svalue(s2v(L->top.p - 1)); } @@ -14652,12 +14807,12 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) { void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ setobj2s(L, func + 3, p3); /* 3rd argument */ - L->top = func + 4; + L->top.p = func + 4; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 0); @@ -14669,18 +14824,18 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top += 3; + L->top.p += 3; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 1); else luaD_callnoyield(L, func, 1); res = restorestack(L, result); - setobjs2s(L, res, --L->top); /* move result to its place */ + setobjs2s(L, res, --L->top.p); /* move result to its place */ } @@ -14715,7 +14870,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, void luaT_tryconcatTM (lua_State *L) { - StkId top = L->top; + StkId top = L->top.p; if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT))) luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); @@ -14750,15 +14905,15 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, */ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { - if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ - return !l_isfalse(s2v(L->top)); + if (callbinTM(L, p1, p2, L->top.p, event)) /* try original event */ + return !l_isfalse(s2v(L->top.p)); #if defined(LUA_COMPAT_LT_LE) else if (event == TM_LE) { /* try '!(p2 < p1)' for '(p1 <= p2)' */ L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - if (callbinTM(L, p2, p1, L->top, TM_LT)) { + if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - return l_isfalse(s2v(L->top)); + return l_isfalse(s2v(L->top.p)); } /* else error will remove this 'ci'; no need to clear mark */ } @@ -14788,20 +14943,20 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, const Proto *p) { int i; - int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ + int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */ int nextra = actual - nfixparams; /* number of extra arguments */ ci->u.l.nextraargs = nextra; luaD_checkstack(L, p->maxstacksize + 1); /* copy function to the top of the stack */ - setobjs2s(L, L->top++, ci->func); + setobjs2s(L, L->top.p++, ci->func.p); /* move fixed parameters to the top of the stack */ for (i = 1; i <= nfixparams; i++) { - setobjs2s(L, L->top++, ci->func + i); - setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */ + setobjs2s(L, L->top.p++, ci->func.p + i); + setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ } - ci->func += actual + 1; - ci->top += actual + 1; - lua_assert(L->top <= ci->top && ci->top <= L->stack_last); + ci->func.p += actual + 1; + ci->top.p += actual + 1; + lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); } @@ -14811,10 +14966,10 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { if (wanted < 0) { wanted = nextra; /* get all extra arguments available */ checkstackGCp(L, nextra, where); /* ensure stack space */ - L->top = where + nextra; /* next instruction will need top */ + L->top.p = where + nextra; /* next instruction will need top */ } for (i = 0; i < wanted && i < nextra; i++) - setobjs2s(L, where + i, ci->func - nextra + i); + setobjs2s(L, where + i, ci->func.p - nextra + i); for (; i < wanted; i++) /* complete required results with nil */ setnilvalue(s2v(where + i)); } @@ -15201,7 +15356,7 @@ static const TValue absentkey = {ABSTKEYCONSTANT}; */ static Node *hashint (const Table *t, lua_Integer i) { lua_Unsigned ui = l_castS2U(i); - if (ui <= (unsigned int)INT_MAX) + if (ui <= cast_uint(INT_MAX)) return hashmod(t, cast_int(ui)); else return hashmod(t, ui); @@ -15351,9 +15506,11 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) { size |= (size >> 2); size |= (size >> 4); size |= (size >> 8); +#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */ size |= (size >> 16); #if (UINT_MAX >> 30) > 3 size |= (size >> 32); /* unsigned int has more than 32 bits */ +#endif #endif size++; lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); @@ -15582,7 +15739,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { luaG_runerror(L, "table overflow"); size = twoto(lsize); t->node = luaM_newvector(L, size, Node); - for (i = 0; i < (int)size; i++) { + for (i = 0; i < cast_int(size); i++) { Node *n = gnode(t, i); gnext(n) = 0; setnilkey(n); @@ -16069,8 +16226,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainpositionTV(t, key); } -int luaH_isdummy (const Table *t) { return isdummy(t); } - #endif /* ** $Id: ldo.c $ @@ -16178,11 +16333,11 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { } default: { lua_assert(errorstatus(errcode)); /* real error */ - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ break; } } - L->top = oldtop + 1; + L->top.p = oldtop + 1; } @@ -16195,7 +16350,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { global_State *g = G(L); errcode = luaE_resetthread(L, errcode); /* close all upvalues */ if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ } else { /* no handler at all; abort */ @@ -16231,16 +16386,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ** Stack reallocation ** =================================================================== */ -static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { + + +/* +** Change all pointers to the stack into offsets. +*/ +static void relstack (lua_State *L) { CallInfo *ci; UpVal *up; - L->top = (L->top - oldstack) + newstack; - L->tbclist = (L->tbclist - oldstack) + newstack; + L->top.offset = savestack(L, L->top.p); + L->tbclist.offset = savestack(L, L->tbclist.p); for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v = s2v((uplevel(up) - oldstack) + newstack); + up->v.offset = savestack(L, uplevel(up)); for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + newstack; - ci->func = (ci->func - oldstack) + newstack; + ci->top.offset = savestack(L, ci->top.p); + ci->func.offset = savestack(L, ci->func.p); + } +} + + +/* +** Change back all offsets into pointers. +*/ +static void correctstack (lua_State *L) { + CallInfo *ci; + UpVal *up; + L->top.p = restorestack(L, L->top.offset); + L->tbclist.p = restorestack(L, L->tbclist.offset); + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v.p = s2v(restorestack(L, up->v.offset)); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top.p = restorestack(L, ci->top.offset); + ci->func.p = restorestack(L, ci->func.offset); if (isLua(ci)) ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ } @@ -16250,44 +16427,45 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { /* some space for error handling */ #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - /* -** Reallocate the stack to a new size, correcting all pointers into -** it. (There are pointers to a stack from its upvalues, from its list -** of call infos, plus a few individual pointers.) The reallocation is -** done in two steps (allocation + free) because the correction must be -** done while both addresses (the old stack and the new one) are valid. -** (In ISO C, any pointer use after the pointer has been deallocated is -** undefined behavior.) +** Reallocate the stack to a new size, correcting all pointers into it. +** In ISO C, any pointer use after the pointer has been deallocated is +** undefined behavior. So, before the reallocation, all pointers are +** changed to offsets, and after the reallocation they are changed back +** to pointers. As during the reallocation the pointers are invalid, the +** reallocation cannot run emergency collections. +** ** In case of allocation error, raise an error or return false according ** to 'raiseerror'. */ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { int oldsize = stacksize(L); int i; - StkId newstack = luaM_reallocvector(L, NULL, 0, - newsize + EXTRA_STACK, StackValue); + StkId newstack; + int oldgcstop = G(L)->gcstopem; lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + relstack(L); /* change pointers to offsets */ + G(L)->gcstopem = 1; /* stop emergency collection */ + newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, + newsize + EXTRA_STACK, StackValue); + G(L)->gcstopem = oldgcstop; /* restore emergency collection */ if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ + correctstack(L); /* change offsets back to pointers */ if (raiseerror) luaM_error(L); else return 0; /* do not raise an error */ } - /* number of elements to be copied to the new stack */ - i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK; - memcpy(newstack, L->stack, i * sizeof(StackValue)); - for (; i < newsize + EXTRA_STACK; i++) + L->stack.p = newstack; + correctstack(L); /* change offsets back to pointers */ + L->stack_last.p = L->stack.p + newsize; + for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) setnilvalue(s2v(newstack + i)); /* erase new segment */ - correctstack(L, L->stack, newstack); - luaM_freearray(L, L->stack, oldsize + EXTRA_STACK); - L->stack = newstack; - L->stack_last = L->stack + newsize; return 1; } /* -** Try to grow the stack by at least 'n' elements. when 'raiseerror' +** Try to grow the stack by at least 'n' elements. When 'raiseerror' ** is true, raises any error; otherwise, return 0 in case of errors. */ int luaD_growstack (lua_State *L, int n, int raiseerror) { @@ -16301,35 +16479,38 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { luaD_throw(L, LUA_ERRERR); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } - else { + else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ int newsize = 2 * size; /* tentative new size */ - int needed = cast_int(L->top - L->stack) + n; + int needed = cast_int(L->top.p - L->stack.p) + n; if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ newsize = LUAI_MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ newsize = needed; if (l_likely(newsize <= LUAI_MAXSTACK)) return luaD_reallocstack(L, newsize, raiseerror); - else { /* stack overflow */ - /* add extra size to be able to handle the error message */ - luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); - if (raiseerror) - luaG_runerror(L, "stack overflow"); - return 0; - } } + /* else stack overflow */ + /* add extra size to be able to handle the error message */ + luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); + if (raiseerror) + luaG_runerror(L, "stack overflow"); + return 0; } +/* +** Compute how much of the stack is being used, by computing the +** maximum top of all call frames in the stack and the current top. +*/ static int stackinuse (lua_State *L) { CallInfo *ci; int res; - StkId lim = L->top; + StkId lim = L->top.p; for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; + if (lim < ci->top.p) lim = ci->top.p; } - lua_assert(lim <= L->stack_last); - res = cast_int(lim - L->stack) + 1; /* part of stack in use */ + lua_assert(lim <= L->stack_last.p + EXTRA_STACK); + res = cast_int(lim - L->stack.p) + 1; /* part of stack in use */ if (res < LUA_MINSTACK) res = LUA_MINSTACK; /* ensure a minimum size */ return res; @@ -16347,17 +16528,13 @@ static int stackinuse (lua_State *L) { */ void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); - int nsize = inuse * 2; /* proposed new size */ - int max = inuse * 3; /* maximum "reasonable" size */ - if (max > LUAI_MAXSTACK) { - max = LUAI_MAXSTACK; /* respect stack limit */ - if (nsize > LUAI_MAXSTACK) - nsize = LUAI_MAXSTACK; - } + int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3; /* if thread is currently not handling a stack overflow and its size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) { + int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2; luaD_reallocstack(L, nsize, 0); /* ok if that fails */ + } else /* don't change stack */ condmovestack(L,{},{}); /* (change only for debugging) */ luaE_shrinkCI(L); /* shrink CI list */ @@ -16366,7 +16543,7 @@ void luaD_shrinkstack (lua_State *L) { void luaD_inctop (lua_State *L) { luaD_checkstack(L, 1); - L->top++; + L->top.p++; } /* }================================================================== */ @@ -16383,8 +16560,8 @@ void luaD_hook (lua_State *L, int event, int line, if (hook && L->allowhook) { /* make sure there is a hook */ int mask = CIST_HOOKED; CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); /* preserve original 'top' */ - ptrdiff_t ci_top = savestack(L, ci->top); /* idem for 'ci->top' */ + ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */ + ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */ lua_Debug ar; ar.event = event; ar.currentline = line; @@ -16394,11 +16571,11 @@ void luaD_hook (lua_State *L, int event, int line, ci->u2.transferinfo.ftransfer = ftransfer; ci->u2.transferinfo.ntransfer = ntransfer; } - if (isLua(ci) && L->top < ci->top) - L->top = ci->top; /* protect entire activation register */ + if (isLua(ci) && L->top.p < ci->top.p) + L->top.p = ci->top.p; /* protect entire activation register */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - if (ci->top < L->top + LUA_MINSTACK) - ci->top = L->top + LUA_MINSTACK; + if (ci->top.p < L->top.p + LUA_MINSTACK) + ci->top.p = L->top.p + LUA_MINSTACK; L->allowhook = 0; /* cannot call hooks inside a hook */ ci->callstatus |= mask; lua_unlock(L); @@ -16406,8 +16583,8 @@ void luaD_hook (lua_State *L, int event, int line, lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); + ci->top.p = restorestack(L, ci_top); + L->top.p = restorestack(L, top); ci->callstatus &= ~mask; } } @@ -16438,7 +16615,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { */ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ - StkId firstres = L->top - nres; /* index of first result */ + StkId firstres = L->top.p - nres; /* index of first result */ int delta = 0; /* correction for vararg functions */ int ftransfer; if (isLua(ci)) { @@ -16446,10 +16623,10 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (p->is_vararg) delta = ci->u.l.nextraargs + p->numparams + 1; } - ci->func += delta; /* if vararg, back to virtual 'func' */ - ftransfer = cast(unsigned short, firstres - ci->func); + ci->func.p += delta; /* if vararg, back to virtual 'func' */ + ftransfer = cast(unsigned short, firstres - ci->func.p); luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ - ci->func -= delta; + ci->func.p -= delta; } if (isLua(ci = ci->previous)) L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */ @@ -16468,9 +16645,9 @@ StkId luaD_tryfuncTM (lua_State *L, StkId func) { tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ if (l_unlikely(ttisnil(tm))) luaG_callerror(L, s2v(func)); /* nothing to call */ - for (p = L->top; p > func; p--) /* open space for metamethod */ + for (p = L->top.p; p > func; p--) /* open space for metamethod */ setobjs2s(L, p, p-1); - L->top++; /* stack space pre-allocated by the caller */ + L->top.p++; /* stack space pre-allocated by the caller */ setobj2s(L, func, tm); /* metamethod is the new function to be called */ return func; } @@ -16487,28 +16664,29 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { int i; switch (wanted) { /* handle typical cases separately */ case 0: /* no values needed */ - L->top = res; + L->top.p = res; return; case 1: /* one value needed */ if (nres == 0) /* no results? */ setnilvalue(s2v(res)); /* adjust with nil */ else /* at least one result */ - setobjs2s(L, res, L->top - nres); /* move it to proper place */ - L->top = res + 1; + setobjs2s(L, res, L->top.p - nres); /* move it to proper place */ + L->top.p = res + 1; return; case LUA_MULTRET: wanted = nres; /* we want all results */ break; default: /* two/more results and/or to-be-closed variables */ if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ - ptrdiff_t savedres = savestack(L, res); L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ L->ci->u2.nres = nres; - luaF_close(L, res, CLOSEKTOP, 1); + res = luaF_close(L, res, CLOSEKTOP, 1); L->ci->callstatus &= ~CIST_CLSRET; - if (L->hookmask) /* if needed, call hook after '__close's */ + if (L->hookmask) { /* if needed, call hook after '__close's */ + ptrdiff_t savedres = savestack(L, res); rethook(L, L->ci, nres); - res = restorestack(L, savedres); /* close and hook can move stack */ + res = restorestack(L, savedres); /* hook can move stack */ + } wanted = decodeNresults(wanted); if (wanted == LUA_MULTRET) wanted = nres; /* we want all results */ @@ -16516,14 +16694,14 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { break; } /* generic case */ - firstresult = L->top - nres; /* index of first result */ + firstresult = L->top.p - nres; /* index of first result */ if (nres > wanted) /* extra results? */ nres = wanted; /* don't need them */ for (i = 0; i < nres; i++) /* move all results to correct place */ setobjs2s(L, res + i, firstresult + i); for (; i < wanted; i++) /* complete wanted number of results */ setnilvalue(s2v(res + i)); - L->top = res + wanted; /* top points after the last result */ + L->top.p = res + wanted; /* top points after the last result */ } @@ -16538,7 +16716,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) rethook(L, ci, nres); /* move results to proper place */ - moveresults(L, ci->func, nres, wanted); + moveresults(L, ci->func.p, nres, wanted); /* function cannot be in any of these cases when returning */ lua_assert(!(ci->callstatus & (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); @@ -16553,10 +16731,10 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, int mask, StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ - ci->func = func; + ci->func.p = func; ci->nresults = nret; ci->callstatus = mask; - ci->top = top; + ci->top.p = top; return ci; } @@ -16570,10 +16748,10 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults, CallInfo *ci; checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, - L->top + LUA_MINSTACK); - lua_assert(ci->top <= L->stack_last); + L->top.p + LUA_MINSTACK); + lua_assert(ci->top.p <= L->stack_last.p); if (l_unlikely(L->hookmask & LUA_MASKCALL)) { - int narg = cast_int(L->top - func) - 1; + int narg = cast_int(L->top.p - func) - 1; luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); } lua_unlock(L); @@ -16605,17 +16783,17 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int nfixparams = p->numparams; int i; checkstackGCp(L, fsize - delta, func); - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ for (i = 0; i < narg1; i++) /* move down function and arguments */ - setobjs2s(L, ci->func + i, func + i); - func = ci->func; /* moved-down function */ + setobjs2s(L, ci->func.p + i, func + i); + func = ci->func.p; /* moved-down function */ for (; narg1 <= nfixparams; narg1++) setnilvalue(s2v(func + narg1)); /* complete missing arguments */ - ci->top = func + 1 + fsize; /* top for new function */ - lua_assert(ci->top <= L->stack_last); + ci->top.p = func + 1 + fsize; /* top for new function */ + lua_assert(ci->top.p <= L->stack_last.p); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus |= CIST_TAIL; - L->top = func + narg1; /* set top */ + L->top.p = func + narg1; /* set top */ return -1; } default: { /* not a function */ @@ -16648,15 +16826,15 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { case LUA_VLCL: { /* Lua function */ CallInfo *ci; Proto *p = clLvalue(s2v(func))->p; - int narg = cast_int(L->top - func) - 1; /* number of real arguments */ + int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ checkstackGCp(L, fsize, func); L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); ci->u.l.savedpc = p->code; /* starting point */ for (; narg < nfixparams; narg++) - setnilvalue(s2v(L->top++)); /* complete missing arguments */ - lua_assert(ci->top <= L->stack_last); + setnilvalue(s2v(L->top.p++)); /* complete missing arguments */ + lua_assert(ci->top.p <= L->stack_last.p); return ci; } default: { /* not a function */ @@ -16672,12 +16850,17 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { ** Call a function (C or Lua) through C. 'inc' can be 1 (increment ** number of recursive invocations in the C stack) or nyci (the same ** plus increment number of non-yieldable calls). +** This function can be called with some use of EXTRA_STACK, so it should +** check the stack before doing anything else. 'luaD_precall' already +** does that. */ -l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) { +l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { CallInfo *ci; L->nCcalls += inc; - if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) { + checkstackp(L, 0, func); /* free any use of EXTRA_STACK */ luaE_checkcstack(L); + } if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ luaV_execute(L, ci); /* call it */ @@ -16725,8 +16908,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) { else { /* error */ StkId func = restorestack(L, ci->u2.funcidx); L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ - luaF_close(L, func, status, 1); /* can yield or raise an error */ - func = restorestack(L, ci->u2.funcidx); /* stack may be moved */ + func = luaF_close(L, func, status, 1); /* can yield or raise an error */ luaD_seterrorobj(L, status, func); luaD_shrinkstack(L); /* restore stack size in case of overflow */ setcistrecst(ci, LUA_OK); /* clear original status */ @@ -16814,8 +16996,8 @@ static CallInfo *findpcall (lua_State *L) { ** coroutine error handler and should not kill the coroutine.) */ static int resume_error (lua_State *L, const char *msg, int narg) { - L->top -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + L->top.p -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ api_incr_top(L); lua_unlock(L); return LUA_ERRRUN; @@ -16831,7 +17013,7 @@ static int resume_error (lua_State *L, const char *msg, int narg) { */ static void resume (lua_State *L, void *ud) { int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top - n; /* first argument */ + StkId firstArg = L->top.p - n; /* first argument */ CallInfo *ci = L->ci; if (L->status == LUA_OK) /* starting a coroutine? */ ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */ @@ -16839,7 +17021,7 @@ static void resume (lua_State *L, void *ud) { lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ if (isLua(ci)) { /* yielded inside a hook? */ - L->top = firstArg; /* discard arguments */ + L->top.p = firstArg; /* discard arguments */ luaV_execute(L, ci); /* just continue running Lua code */ } else { /* 'common' yield */ @@ -16882,7 +17064,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, if (L->status == LUA_OK) { /* may be starting a coroutine */ if (L->ci != &L->base_ci) /* not in base level? */ return resume_error(L, "cannot resume non-suspended coroutine", nargs); - else if (L->top - (L->ci->func + 1) == nargs) /* no function? */ + else if (L->top.p - (L->ci->func.p + 1) == nargs) /* no function? */ return resume_error(L, "cannot resume dead coroutine", nargs); } else if (L->status != LUA_YIELD) /* ended with errors? */ @@ -16900,11 +17082,11 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, lua_assert(status == L->status); /* normal end or yield */ else { /* unrecoverable error */ L->status = cast_byte(status); /* mark thread as 'dead' */ - luaD_seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; + luaD_seterrorobj(L, status, L->top.p); /* push error message */ + L->ci->top.p = L->top.p; } *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield - : cast_int(L->top - (L->ci->func + 1)); + : cast_int(L->top.p - (L->ci->func.p + 1)); lua_unlock(L); return status; } @@ -17059,7 +17241,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; p.dyd.label.arr = NULL; p.dyd.label.size = 0; luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc); luaZ_freebuffer(L, &p.buff); luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); @@ -17679,8 +17861,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { if (tm == NULL) /* no TM? */ return 0; /* objects are different */ else { - luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ - return !l_isfalse(s2v(L->top)); + luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ + return !l_isfalse(s2v(L->top.p)); } } @@ -17704,17 +17886,17 @@ static void copy2buff (StkId top, int n, char *buff) { /* ** Main operation for concatenation: concat 'total' values in the stack, -** from 'L->top - total' up to 'L->top - 1'. +** from 'L->top.p - total' up to 'L->top.p - 1'. */ void luaV_concat (lua_State *L, int total) { if (total == 1) return; /* "all" values already concatenated */ do { - StkId top = L->top; + StkId top = L->top.p; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || !tostring(L, s2v(top - 1))) - luaT_tryconcatTM(L); + luaT_tryconcatTM(L); /* may invalidate 'top' */ else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ @@ -17727,8 +17909,10 @@ void luaV_concat (lua_State *L, int total) { /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { size_t l = vslen(s2v(top - n - 1)); - if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) + if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { + L->top.p = top - total; /* pop strings to avoid wasting stack */ luaG_runerror(L, "string length overflow"); + } tl += l; } if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ @@ -17742,8 +17926,8 @@ void luaV_concat (lua_State *L, int total) { } setsvalue2s(L, top - n, ts); /* create result */ } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ + total -= n - 1; /* got 'n' strings to create one new */ + L->top.p -= n - 1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ } @@ -17834,12 +18018,10 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { /* number of bits in an integer */ #define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + /* ** Shift left operation. (Shift right just negates 'y'.) */ -#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) - - lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { if (y < 0) { /* shift right? */ if (y <= -NBITS) return 0; @@ -17879,26 +18061,26 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, */ void luaV_finishOp (lua_State *L) { CallInfo *ci = L->ci; - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { - setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top); + setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top.p); break; } case OP_UNM: case OP_BNOT: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: case OP_GETFIELD: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); + setobjs2s(L, base + GETARG_A(inst), --L->top.p); break; } case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: case OP_GTI: case OP_GEI: case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ - int res = !l_isfalse(s2v(L->top - 1)); - L->top--; + int res = !l_isfalse(s2v(L->top.p - 1)); + L->top.p--; #if defined(LUA_COMPAT_LT_LE) if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ ci->callstatus ^= CIST_LEQ; /* clear mark */ @@ -17911,11 +18093,11 @@ void luaV_finishOp (lua_State *L) { break; } case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */ + StkId top = L->top.p - 1; /* top when 'luaT_tryconcatTM' was called */ int a = GETARG_A(inst); /* first element to concatenate */ int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ setobjs2s(L, top - 2, top); /* put TM result in proper position */ - L->top = top - 1; /* top is one after last element (at top-2) */ + L->top.p = top - 1; /* top is one after last element (at top-2) */ luaV_concat(L, total); /* concat them (may yield again) */ break; } @@ -17927,7 +18109,7 @@ void luaV_finishOp (lua_State *L) { StkId ra = base + GETARG_A(inst); /* adjust top to signal correct number of returns, in case the return is "up to top" ('isIT') */ - L->top = ra + ci->u2.nres; + L->top.p = ra + ci->u2.nres; /* repeat instruction to close other vars. and complete the return */ ci->u.l.savedpc--; break; @@ -17969,6 +18151,7 @@ void luaV_finishOp (lua_State *L) { ** operation, 'fop' is the float operation. */ #define op_arithI(L,iop,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ int imm = GETARG_sC(i); \ if (ttisinteger(v1)) { \ @@ -17997,6 +18180,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over floats and others with register operands. */ #define op_arithf(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ op_arithf_aux(L, v1, v2, fop); } @@ -18006,6 +18190,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations with K operands for floats. */ #define op_arithfK(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ op_arithf_aux(L, v1, v2, fop); } @@ -18015,6 +18200,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over integers and floats. */ #define op_arith_aux(L,v1,v2,iop,fop) { \ + StkId ra = RA(i); \ if (ttisinteger(v1) && ttisinteger(v2)) { \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ @@ -18044,6 +18230,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with constant operand. */ #define op_bitwiseK(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); \ lua_Integer i1; \ @@ -18057,6 +18244,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with register operands. */ #define op_bitwise(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ lua_Integer i1; lua_Integer i2; \ @@ -18071,18 +18259,19 @@ void luaV_finishOp (lua_State *L) { ** integers. */ #define op_order(L,opi,opn,other) { \ - int cond; \ - TValue *rb = vRB(i); \ - if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ - lua_Integer ia = ivalue(s2v(ra)); \ - lua_Integer ib = ivalue(rb); \ - cond = opi(ia, ib); \ - } \ - else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ - cond = opn(s2v(ra), rb); \ - else \ - Protect(cond = other(L, s2v(ra), rb)); \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + TValue *rb = vRB(i); \ + if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ + lua_Integer ia = ivalue(s2v(ra)); \ + lua_Integer ib = ivalue(rb); \ + cond = opi(ia, ib); \ + } \ + else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ + cond = opn(s2v(ra), rb); \ + else \ + Protect(cond = other(L, s2v(ra), rb)); \ + docondjump(); } /* @@ -18090,20 +18279,21 @@ void luaV_finishOp (lua_State *L) { ** always small enough to have an exact representation as a float.) */ #define op_orderI(L,opi,opf,inv,tm) { \ - int cond; \ - int im = GETARG_sB(i); \ - if (ttisinteger(s2v(ra))) \ - cond = opi(ivalue(s2v(ra)), im); \ - else if (ttisfloat(s2v(ra))) { \ - lua_Number fa = fltvalue(s2v(ra)); \ - lua_Number fim = cast_num(im); \ - cond = opf(fa, fim); \ - } \ - else { \ - int isf = GETARG_C(i); \ - Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ - } \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + int im = GETARG_sB(i); \ + if (ttisinteger(s2v(ra))) \ + cond = opi(ivalue(s2v(ra)), im); \ + else if (ttisfloat(s2v(ra))) { \ + lua_Number fa = fltvalue(s2v(ra)); \ + lua_Number fim = cast_num(im); \ + cond = opf(fa, fim); \ + } \ + else { \ + int isf = GETARG_C(i); \ + Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ + } \ + docondjump(); } /* }================================================================== */ @@ -18132,7 +18322,7 @@ void luaV_finishOp (lua_State *L) { #define updatetrap(ci) (trap = ci->u.l.trap) -#define updatebase(ci) (base = ci->func + 1) +#define updatebase(ci) (base = ci->func.p + 1) #define updatestack(ci) \ @@ -18167,7 +18357,7 @@ void luaV_finishOp (lua_State *L) { ** Whenever code can raise errors, the global 'pc' and the global ** 'top' must be correct to report occasional errors. */ -#define savestate(L,ci) (savepc(L), L->top = ci->top) +#define savestate(L,ci) (savepc(L), L->top.p = ci->top.p) /* @@ -18187,7 +18377,7 @@ void luaV_finishOp (lua_State *L) { /* 'c' is the limit of live values in the stack */ #define checkGC(L,c) \ - { luaC_condGC(L, (savepc(L), L->top = (c)), \ + { luaC_condGC(L, (savepc(L), L->top.p = (c)), \ updatetrap(ci)); \ luai_threadyield(L); } @@ -18199,7 +18389,6 @@ void luaV_finishOp (lua_State *L) { updatebase(ci); /* correct stack */ \ } \ i = *(pc++); \ - ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ } #define vmdispatch(o) switch(o) @@ -18331,7 +18520,7 @@ static const void *const disptab[NUM_OPCODES] = { startfunc: trap = L->hookmask; returning: /* trap already set */ - cl = clLvalue(s2v(ci->func)); + cl = clLvalue(s2v(ci->func.p)); k = cl->p->k; pc = ci->u.l.savedpc; if (l_unlikely(trap)) { @@ -18343,60 +18532,68 @@ static const void *const disptab[NUM_OPCODES] = { } ci->u.l.trap = 1; /* assume trap is on, for now */ } - base = ci->func + 1; + base = ci->func.p + 1; /* main loop of interpreter */ for (;;) { Instruction i; /* instruction being executed */ - StkId ra; /* instruction's A register */ vmfetch(); #if 0 /* low-level line tracing for debugging Lua */ printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); #endif - lua_assert(base == ci->func + 1); - lua_assert(base <= L->top && L->top < L->stack_last); + lua_assert(base == ci->func.p + 1); + lua_assert(base <= L->top.p && L->top.p <= L->stack_last.p); /* invalidate top for instructions not expecting it */ - lua_assert(isIT(i) || (cast_void(L->top = base), 1)); + lua_assert(isIT(i) || (cast_void(L->top.p = base), 1)); vmdispatch (GET_OPCODE(i)) { vmcase(OP_MOVE) { + StkId ra = RA(i); setobjs2s(L, ra, RB(i)); vmbreak; } vmcase(OP_LOADI) { + StkId ra = RA(i); lua_Integer b = GETARG_sBx(i); setivalue(s2v(ra), b); vmbreak; } vmcase(OP_LOADF) { + StkId ra = RA(i); int b = GETARG_sBx(i); setfltvalue(s2v(ra), cast_num(b)); vmbreak; } vmcase(OP_LOADK) { + StkId ra = RA(i); TValue *rb = k + GETARG_Bx(i); setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADKX) { + StkId ra = RA(i); TValue *rb; rb = k + GETARG_Ax(*pc); pc++; setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADFALSE) { + StkId ra = RA(i); setbfvalue(s2v(ra)); vmbreak; } vmcase(OP_LFALSESKIP) { + StkId ra = RA(i); setbfvalue(s2v(ra)); pc++; /* skip next instruction */ vmbreak; } vmcase(OP_LOADTRUE) { + StkId ra = RA(i); setbtvalue(s2v(ra)); vmbreak; } vmcase(OP_LOADNIL) { + StkId ra = RA(i); int b = GETARG_B(i); do { setnilvalue(s2v(ra++)); @@ -18404,19 +18601,22 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETUPVAL) { + StkId ra = RA(i); int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); + setobj2s(L, ra, cl->upvals[b]->v.p); vmbreak; } vmcase(OP_SETUPVAL) { + StkId ra = RA(i); UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, s2v(ra)); + setobj(L, uv->v.p, s2v(ra)); luaC_barrier(L, uv, s2v(ra)); vmbreak; } vmcase(OP_GETTABUP) { + StkId ra = RA(i); const TValue *slot; - TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *upval = cl->upvals[GETARG_B(i)]->v.p; TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a string */ if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { @@ -18427,6 +18627,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = vRC(i); @@ -18441,6 +18642,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETI) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); int c = GETARG_C(i); @@ -18455,6 +18657,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = KC(i); @@ -18468,7 +18671,7 @@ static const void *const disptab[NUM_OPCODES] = { } vmcase(OP_SETTABUP) { const TValue *slot; - TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *upval = cl->upvals[GETARG_A(i)]->v.p; TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a string */ @@ -18480,6 +18683,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); /* key (table is in 'ra') */ TValue *rc = RKC(i); /* value */ @@ -18494,6 +18698,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETI) { + StkId ra = RA(i); const TValue *slot; int c = GETARG_B(i); TValue *rc = RKC(i); @@ -18508,6 +18713,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = KB(i); TValue *rc = RKC(i); @@ -18520,6 +18726,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NEWTABLE) { + StkId ra = RA(i); int b = GETARG_B(i); /* log2(hash size) + 1 */ int c = GETARG_C(i); /* array size */ Table *t; @@ -18529,7 +18736,7 @@ static const void *const disptab[NUM_OPCODES] = { if (TESTARG_k(i)) /* non-zero extra argument? */ c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ pc++; /* skip extra argument */ - L->top = ra + 1; /* correct top in case of emergency GC */ + L->top.p = ra + 1; /* correct top in case of emergency GC */ t = luaH_new(L); /* memory allocation */ sethvalue2s(L, ra, t); if (b != 0 || c != 0) @@ -18538,6 +18745,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SELF) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = RKC(i); @@ -18567,6 +18775,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MODK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_mod, luaV_modf); vmbreak; } @@ -18579,6 +18788,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIVK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -18595,6 +18805,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHRI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -18604,6 +18815,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHLI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -18625,6 +18837,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MOD) { + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_mod, luaV_modf); vmbreak; } @@ -18637,6 +18850,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIV) { /* floor division */ + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -18661,6 +18875,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBIN) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *rb = vRB(i); TMS tm = (TMS)GETARG_C(i); @@ -18670,6 +18885,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINI) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ int imm = GETARG_sB(i); TMS tm = (TMS)GETARG_C(i); @@ -18679,6 +18895,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINK) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *imm = KB(i); TMS tm = (TMS)GETARG_C(i); @@ -18688,6 +18905,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_UNM) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Number nb; if (ttisinteger(rb)) { @@ -18702,6 +18920,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_BNOT) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Integer ib; if (tointegerns(rb, &ib)) { @@ -18712,6 +18931,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NOT) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb)) setbtvalue(s2v(ra)); @@ -18720,21 +18940,25 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_LEN) { + StkId ra = RA(i); Protect(luaV_objlen(L, ra, vRB(i))); vmbreak; } vmcase(OP_CONCAT) { + StkId ra = RA(i); int n = GETARG_B(i); /* number of elements to concatenate */ - L->top = ra + n; /* mark the end of concat operands */ + L->top.p = ra + n; /* mark the end of concat operands */ ProtectNT(luaV_concat(L, n)); - checkGC(L, L->top); /* 'luaV_concat' ensures correct top */ + checkGC(L, L->top.p); /* 'luaV_concat' ensures correct top */ vmbreak; } vmcase(OP_CLOSE) { + StkId ra = RA(i); Protect(luaF_close(L, ra, LUA_OK, 1)); vmbreak; } vmcase(OP_TBC) { + StkId ra = RA(i); /* create new to-be-closed upvalue */ halfProtect(luaF_newtbcupval(L, ra)); vmbreak; @@ -18744,6 +18968,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQ) { + StkId ra = RA(i); int cond; TValue *rb = vRB(i); Protect(cond = luaV_equalobj(L, s2v(ra), rb)); @@ -18759,6 +18984,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQK) { + StkId ra = RA(i); TValue *rb = KB(i); /* basic types do not use '__eq'; we can use raw equality */ int cond = luaV_rawequalobj(s2v(ra), rb); @@ -18766,6 +18992,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQI) { + StkId ra = RA(i); int cond; int im = GETARG_sB(i); if (ttisinteger(s2v(ra))) @@ -18794,11 +19021,13 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TEST) { + StkId ra = RA(i); int cond = !l_isfalse(s2v(ra)); docondjump(); vmbreak; } vmcase(OP_TESTSET) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb) == GETARG_k(i)) pc++; @@ -18809,11 +19038,12 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CALL) { + StkId ra = RA(i); CallInfo *newci; int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) /* fixed number of arguments? */ - L->top = ra + b; /* top signals number of arguments */ + L->top.p = ra + b; /* top signals number of arguments */ /* else previous instruction set top */ savepc(L); /* in case of errors */ if ((newci = luaD_precall(L, ra, nresults)) == NULL) @@ -18825,54 +19055,57 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TAILCALL) { + StkId ra = RA(i); int b = GETARG_B(i); /* number of arguments + 1 (function) */ int n; /* number of results when calling a C function */ int nparams1 = GETARG_C(i); /* delta is virtual 'func' - real 'func' (vararg functions) */ int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; if (b != 0) - L->top = ra + b; + L->top.p = ra + b; else /* previous instruction set top */ - b = cast_int(L->top - ra); + b = cast_int(L->top.p - ra); savepc(ci); /* several calls here can raise errors */ if (TESTARG_k(i)) { luaF_closeupval(L, base); /* close upvalues from current call */ - lua_assert(L->tbclist < base); /* no pending tbc variables */ - lua_assert(base == ci->func + 1); + lua_assert(L->tbclist.p < base); /* no pending tbc variables */ + lua_assert(base == ci->func.p + 1); } if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ goto startfunc; /* execute the callee */ else { /* C function? */ - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ luaD_poscall(L, ci, n); /* finish caller */ updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; /* caller returns after the tail call */ } } vmcase(OP_RETURN) { + StkId ra = RA(i); int n = GETARG_B(i) - 1; /* number of results */ int nparams1 = GETARG_C(i); if (n < 0) /* not fixed? */ - n = cast_int(L->top - ra); /* get what is available */ + n = cast_int(L->top.p - ra); /* get what is available */ savepc(ci); if (TESTARG_k(i)) { /* may there be open upvalues? */ ci->u2.nres = n; /* save number of returns */ - if (L->top < ci->top) - L->top = ci->top; + if (L->top.p < ci->top.p) + L->top.p = ci->top.p; luaF_close(L, base, CLOSEKTOP, 1); updatetrap(ci); updatestack(ci); } if (nparams1) /* vararg function? */ - ci->func -= ci->u.l.nextraargs + nparams1; - L->top = ra + n; /* set call for 'luaD_poscall' */ + ci->func.p -= ci->u.l.nextraargs + nparams1; + L->top.p = ra + n; /* set call for 'luaD_poscall' */ luaD_poscall(L, ci, n); updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; } vmcase(OP_RETURN0) { if (l_unlikely(L->hookmask)) { - L->top = ra; + StkId ra = RA(i); + L->top.p = ra; savepc(ci); luaD_poscall(L, ci, 0); /* no hurry... */ trap = 1; @@ -18880,15 +19113,16 @@ static const void *const disptab[NUM_OPCODES] = { else { /* do the 'poscall' here */ int nres; L->ci = ci->previous; /* back to caller */ - L->top = base - 1; + L->top.p = base - 1; for (nres = ci->nresults; l_unlikely(nres > 0); nres--) - setnilvalue(s2v(L->top++)); /* all results are nil */ + setnilvalue(s2v(L->top.p++)); /* all results are nil */ } goto ret; } vmcase(OP_RETURN1) { if (l_unlikely(L->hookmask)) { - L->top = ra + 1; + StkId ra = RA(i); + L->top.p = ra + 1; savepc(ci); luaD_poscall(L, ci, 1); /* no hurry... */ trap = 1; @@ -18897,12 +19131,13 @@ static const void *const disptab[NUM_OPCODES] = { int nres = ci->nresults; L->ci = ci->previous; /* back to caller */ if (nres == 0) - L->top = base - 1; /* asked for no results */ + L->top.p = base - 1; /* asked for no results */ else { + StkId ra = RA(i); setobjs2s(L, base - 1, ra); /* at least this result */ - L->top = base; + L->top.p = base; for (; l_unlikely(nres > 1); nres--) - setnilvalue(s2v(L->top++)); /* complete missing results */ + setnilvalue(s2v(L->top.p++)); /* complete missing results */ } } ret: /* return from a Lua function */ @@ -18914,6 +19149,7 @@ static const void *const disptab[NUM_OPCODES] = { } } vmcase(OP_FORLOOP) { + StkId ra = RA(i); if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); if (count > 0) { /* still more iterations? */ @@ -18932,12 +19168,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_FORPREP) { + StkId ra = RA(i); savestate(L, ci); /* in case of errors */ if (forprep(L, ra)) pc += GETARG_Bx(i) + 1; /* skip the loop */ vmbreak; } vmcase(OP_TFORPREP) { + StkId ra = RA(i); /* create to-be-closed upvalue (if needed) */ halfProtect(luaF_newtbcupval(L, ra + 3)); pc += GETARG_Bx(i); @@ -18946,7 +19184,8 @@ static const void *const disptab[NUM_OPCODES] = { goto l_tforcall; } vmcase(OP_TFORCALL) { - l_tforcall: + l_tforcall: { + StkId ra = RA(i); /* 'ra' has the iterator function, 'ra + 1' has the state, 'ra + 2' has the control variable, and 'ra + 3' has the to-be-closed variable. The call will use the stack after @@ -18954,29 +19193,31 @@ static const void *const disptab[NUM_OPCODES] = { */ /* push function, state, and control variable */ memcpy(ra + 4, ra, 3 * sizeof(*ra)); - L->top = ra + 4 + 3; + L->top.p = ra + 4 + 3; ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); goto l_tforloop; - } + }} vmcase(OP_TFORLOOP) { - l_tforloop: + l_tforloop: { + StkId ra = RA(i); if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ setobjs2s(L, ra + 2, ra + 4); /* save control variable */ pc -= GETARG_Bx(i); /* jump back */ } vmbreak; - } + }} vmcase(OP_SETLIST) { + StkId ra = RA(i); int n = GETARG_B(i); unsigned int last = GETARG_C(i); Table *h = hvalue(s2v(ra)); if (n == 0) - n = cast_int(L->top - ra) - 1; /* get up to the top */ + n = cast_int(L->top.p - ra) - 1; /* get up to the top */ else - L->top = ci->top; /* correct top in case of emergency GC */ + L->top.p = ci->top.p; /* correct top in case of emergency GC */ last += n; if (TESTARG_k(i)) { last += GETARG_Ax(*pc) * (MAXARG_C + 1); @@ -18993,12 +19234,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CLOSURE) { + StkId ra = RA(i); Proto *p = cl->p->p[GETARG_Bx(i)]; halfProtect(pushclosure(L, p, cl->upvals, base, ra)); checkGC(L, ra + 1); vmbreak; } vmcase(OP_VARARG) { + StkId ra = RA(i); int n = GETARG_C(i) - 1; /* required results */ Protect(luaT_getvarargs(L, ci, ra, n)); vmbreak; @@ -19083,27 +19326,28 @@ const char lua_ident[] = static TValue *index2value (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return &G(L)->nilvalue; + StkId o = ci->func.p + idx; + api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index"); + if (o >= L->top.p) return &G(L)->nilvalue; else return s2v(o); } else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return s2v(L->top + idx); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); + return s2v(L->top.p + idx); } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttisCclosure(s2v(ci->func))) { /* C closure? */ - CClosure *func = clCvalue(s2v(ci->func)); + if (ttisCclosure(s2v(ci->func.p))) { /* C closure? */ + CClosure *func = clCvalue(s2v(ci->func.p)); return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue; } else { /* light C function or Lua function (through a hook)?) */ - api_check(L, ttislcf(s2v(ci->func)), "caller not a C function"); + api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function"); return &G(L)->nilvalue; /* no upvalues */ } } @@ -19117,14 +19361,15 @@ static TValue *index2value (lua_State *L, int idx) { l_sinline StkId index2stack (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, o < L->top, "invalid index"); + StkId o = ci->func.p + idx; + api_check(L, o < L->top.p, "invalid index"); return o; } else { /* non-positive index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); api_check(L, !ispseudo(idx), "invalid index"); - return L->top + idx; + return L->top.p + idx; } } @@ -19135,17 +19380,12 @@ LUA_API int lua_checkstack (lua_State *L, int n) { lua_lock(L); ci = L->ci; api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ + if (L->stack_last.p - L->top.p > n) /* stack large enough? */ res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = luaD_growstack(L, n, 0); - } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ + else /* need to grow stack */ + res = luaD_growstack(L, n, 0); + if (res && ci->top.p < L->top.p + n) + ci->top.p = L->top.p + n; /* adjust frame top */ lua_unlock(L); return res; } @@ -19157,11 +19397,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); - from->top -= n; + api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); + from->top.p -= n; for (i = 0; i < n; i++) { - setobjs2s(to, to->top, from->top + i); - to->top++; /* stack already checked by previous 'api_check' */ + setobjs2s(to, to->top.p, from->top.p + i); + to->top.p++; /* stack already checked by previous 'api_check' */ } lua_unlock(to); } @@ -19195,12 +19435,12 @@ LUA_API lua_Number lua_version (lua_State *L) { LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx - : cast_int(L->top - L->ci->func) + idx; + : cast_int(L->top.p - L->ci->func.p) + idx; } LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); + return cast_int(L->top.p - (L->ci->func.p + 1)); } @@ -19210,24 +19450,24 @@ LUA_API void lua_settop (lua_State *L, int idx) { ptrdiff_t diff; /* difference for new top */ lua_lock(L); ci = L->ci; - func = ci->func; + func = ci->func.p; if (idx >= 0) { - api_check(L, idx <= ci->top - (func + 1), "new top too large"); - diff = ((func + 1) + idx) - L->top; + api_check(L, idx <= ci->top.p - (func + 1), "new top too large"); + diff = ((func + 1) + idx) - L->top.p; for (; diff > 0; diff--) - setnilvalue(s2v(L->top++)); /* clear new slots */ + setnilvalue(s2v(L->top.p++)); /* clear new slots */ } else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); diff = idx + 1; /* will "subtract" index (as it is negative) */ } - api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot"); - newtop = L->top + diff; - if (diff < 0 && L->tbclist >= newtop) { + api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot"); + newtop = L->top.p + diff; + if (diff < 0 && L->tbclist.p >= newtop) { lua_assert(hastocloseCfunc(ci->nresults)); - luaF_close(L, newtop, CLOSEKTOP, 0); + newtop = luaF_close(L, newtop, CLOSEKTOP, 0); } - L->top = newtop; /* correct top only after closing any upvalue */ + L->top.p = newtop; /* correct top only after closing any upvalue */ lua_unlock(L); } @@ -19236,10 +19476,9 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { StkId level; lua_lock(L); level = index2stack(L, idx); - api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level, + api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level, "no variable to close at given level"); - luaF_close(L, level, CLOSEKTOP, 0); - level = index2stack(L, idx); /* stack may be moved */ + level = luaF_close(L, level, CLOSEKTOP, 0); setnilvalue(s2v(level)); lua_unlock(L); } @@ -19268,7 +19507,7 @@ l_sinline void reverse (lua_State *L, StkId from, StkId to) { LUA_API void lua_rotate (lua_State *L, int idx, int n) { StkId p, t, m; lua_lock(L); - t = L->top - 1; /* end of stack segment being rotated */ + t = L->top.p - 1; /* end of stack segment being rotated */ p = index2stack(L, idx); /* start of segment */ api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ @@ -19287,7 +19526,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { api_check(L, isvalid(L, to), "invalid index"); setobj(L, to, fr); if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); + luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr); /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ lua_unlock(L); @@ -19296,7 +19535,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2value(L, idx)); + setobj2s(L, L->top.p, index2value(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -19365,12 +19604,12 @@ LUA_API void lua_arith (lua_State *L, int op) { api_checknelems(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); + setobjs2s(L, L->top.p, L->top.p - 1); api_incr_top(L); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); - L->top--; /* remove second operand */ + luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); + L->top.p--; /* remove second operand */ lua_unlock(L); } @@ -19396,7 +19635,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, s2v(L->top)); + size_t sz = luaO_str2num(s, s2v(L->top.p)); if (sz != 0) api_incr_top(L); return sz; @@ -19523,7 +19762,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -19531,7 +19770,7 @@ LUA_API void lua_pushnil (lua_State *L) { LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); - setfltvalue(s2v(L->top), n); + setfltvalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -19539,7 +19778,7 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); - setivalue(s2v(L->top), n); + setivalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -19554,7 +19793,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -19565,11 +19804,11 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushstring (lua_State *L, const char *s) { lua_lock(L); if (s == NULL) - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else { TString *ts; ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); s = getstr(ts); /* internal copy's address */ } api_incr_top(L); @@ -19606,7 +19845,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { - setfvalue(s2v(L->top), fn); + setfvalue(s2v(L->top.p), fn); api_incr_top(L); } else { @@ -19615,13 +19854,13 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { api_check(L, n <= MAXUPVAL, "upvalue index too large"); cl = luaF_newCclosure(L, n); cl->f = fn; - L->top -= n; + L->top.p -= n; while (n--) { - setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); + setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n)); /* does not need barrier because closure is white */ lua_assert(iswhite(cl)); } - setclCvalue(L, s2v(L->top), cl); + setclCvalue(L, s2v(L->top.p), cl); api_incr_top(L); luaC_checkGC(L); } @@ -19632,9 +19871,9 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); if (b) - setbtvalue(s2v(L->top)); + setbtvalue(s2v(L->top.p)); else - setbfvalue(s2v(L->top)); + setbfvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -19642,7 +19881,7 @@ LUA_API void lua_pushboolean (lua_State *L, int b) { LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); - setpvalue(s2v(L->top), p); + setpvalue(s2v(L->top.p), p); api_incr_top(L); lua_unlock(L); } @@ -19650,7 +19889,7 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); - setthvalue(L, s2v(L->top), L); + setthvalue(L, s2v(L->top.p), L); api_incr_top(L); lua_unlock(L); return (G(L)->mainthread == L); @@ -19667,16 +19906,16 @@ l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { const TValue *slot; TString *str = luaS_new(L, k); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); api_incr_top(L); } else { - setsvalue2s(L, L->top, str); + setsvalue2s(L, L->top.p, str); api_incr_top(L); - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); } lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -19703,13 +19942,13 @@ LUA_API int lua_gettable (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { - setobj2s(L, L->top - 1, slot); + if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { + setobj2s(L, L->top.p - 1, slot); } else - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -19725,27 +19964,27 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); } else { TValue aux; setivalue(&aux, n); - luaV_finishget(L, t, &aux, L->top, slot); + luaV_finishget(L, t, &aux, L->top.p, slot); } api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } l_sinline int finishrawget (lua_State *L, const TValue *val) { if (isempty(val)) /* avoid copying empty items to the stack */ - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -19762,8 +20001,8 @@ LUA_API int lua_rawget (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - val = luaH_get(t, s2v(L->top - 1)); - L->top--; /* remove key */ + val = luaH_get(t, s2v(L->top.p - 1)); + L->top.p--; /* remove key */ return finishrawget(L, val); } @@ -19790,7 +20029,7 @@ LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { Table *t; lua_lock(L); t = luaH_new(L); - sethvalue2s(L, L->top, t); + sethvalue2s(L, L->top.p, t); api_incr_top(L); if (narray > 0 || nrec > 0) luaH_resize(L, t, narray, nrec); @@ -19817,7 +20056,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { break; } if (mt != NULL) { - sethvalue2s(L, L->top, mt); + sethvalue2s(L, L->top.p, mt); api_incr_top(L); res = 1; } @@ -19833,12 +20072,12 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { o = index2value(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); if (n <= 0 || n > uvalue(o)->nuvalue) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); t = LUA_TNONE; } else { - setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); - t = ttype(s2v(L->top)); + setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv); + t = ttype(s2v(L->top.p)); } api_incr_top(L); lua_unlock(L); @@ -19858,14 +20097,14 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { TString *str = luaS_new(L, k); api_checknelems(L, 1); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); - L->top--; /* pop value */ + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); + L->top.p--; /* pop value */ } else { - setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ api_incr_top(L); - luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); - L->top -= 2; /* pop value and key */ + luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); + L->top.p -= 2; /* pop value and key */ } lua_unlock(L); /* lock done by caller */ } @@ -19885,12 +20124,12 @@ LUA_API void lua_settable (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 2); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else - luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); - L->top -= 2; /* pop index and value */ + luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); + L->top.p -= 2; /* pop index and value */ lua_unlock(L); } @@ -19908,14 +20147,14 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { api_checknelems(L, 1); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else { TValue aux; setivalue(&aux, n); - luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); + luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); } - L->top--; /* pop value */ + L->top.p--; /* pop value */ lua_unlock(L); } @@ -19925,16 +20164,16 @@ static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { lua_lock(L); api_checknelems(L, n); t = gettable(L, idx); - luaH_set(L, t, key, s2v(L->top - 1)); + luaH_set(L, t, key, s2v(L->top.p - 1)); invalidateTMcache(t); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top -= n; + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p -= n; lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { - aux_rawset(L, idx, s2v(L->top - 2), 2); + aux_rawset(L, idx, s2v(L->top.p - 2), 2); } @@ -19950,9 +20189,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - luaH_setint(L, t, n, s2v(L->top - 1)); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top--; + luaH_setint(L, t, n, s2v(L->top.p - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p--; lua_unlock(L); } @@ -19963,11 +20202,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { lua_lock(L); api_checknelems(L, 1); obj = index2value(L, objindex); - if (ttisnil(s2v(L->top - 1))) + if (ttisnil(s2v(L->top.p - 1))) mt = NULL; else { - api_check(L, ttistable(s2v(L->top - 1)), "table expected"); - mt = hvalue(s2v(L->top - 1)); + api_check(L, ttistable(s2v(L->top.p - 1)), "table expected"); + mt = hvalue(s2v(L->top.p - 1)); } switch (ttype(obj)) { case LUA_TTABLE: { @@ -19991,7 +20230,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { break; } } - L->top--; + L->top.p--; lua_unlock(L); return 1; } @@ -20007,11 +20246,11 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ else { - setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1)); res = 1; } - L->top--; + L->top.p--; lua_unlock(L); return res; } @@ -20023,7 +20262,8 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + api_check(L, (nr) == LUA_MULTRET \ + || (L->ci->top.p - L->top.p >= (nr) - (na)), \ "results from function overflow current stack size") @@ -20036,7 +20276,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); - func = L->top - (nargs+1); + func = L->top.p - (nargs+1); if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ @@ -20084,7 +20324,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); func = savestack(L, o); } - c.func = L->top - (nargs+1); /* function to be called */ + c.func = L->top.p - (nargs+1); /* function to be called */ if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ c.nresults = nresults; /* do a 'conventional' protected call */ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); @@ -20119,12 +20359,12 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, luaZ_init(L, &z, reader, data); status = luaD_protectedparser(L, &z, chunkname, mode); if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ + LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ if (f->nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ const TValue *gt = getGtable(L); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); + setobj(L, f->upvals[0]->v.p, gt); luaC_barrier(L, f->upvals[0], gt); } } @@ -20138,7 +20378,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { TValue *o; lua_lock(L); api_checknelems(L, 1); - o = s2v(L->top - 1); + o = s2v(L->top.p - 1); if (isLfunction(o)) status = luaU_dump(L, getproto(o), writer, data, strip); else @@ -20264,7 +20504,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { LUA_API int lua_error (lua_State *L) { TValue *errobj; lua_lock(L); - errobj = s2v(L->top - 1); + errobj = s2v(L->top.p - 1); api_checknelems(L, 1); /* error object is the memory error message? */ if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) @@ -20282,12 +20522,12 @@ LUA_API int lua_next (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - more = luaH_next(L, t, L->top - 1); + more = luaH_next(L, t, L->top.p - 1); if (more) { api_incr_top(L); } else /* no more elements */ - L->top -= 1; /* remove key */ + L->top.p -= 1; /* remove key */ lua_unlock(L); return more; } @@ -20299,7 +20539,7 @@ LUA_API void lua_toclose (lua_State *L, int idx) { lua_lock(L); o = index2stack(L, idx); nresults = L->ci->nresults; - api_check(L, L->tbclist < o, "given index below or equal a marked one"); + api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ if (!hastocloseCfunc(nresults)) /* function not marked yet? */ L->ci->nresults = codeNresults(nresults); /* mark it */ @@ -20314,7 +20554,7 @@ LUA_API void lua_concat (lua_State *L, int n) { if (n > 0) luaV_concat(L, n); else { /* nothing to concatenate */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ + setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ api_incr_top(L); } luaC_checkGC(L); @@ -20326,7 +20566,7 @@ LUA_API void lua_len (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - luaV_objlen(L, L->top, t); + luaV_objlen(L, L->top.p, t); api_incr_top(L); lua_unlock(L); } @@ -20371,7 +20611,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { lua_lock(L); api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); u = luaS_newudata(L, size, nuvalue); - setuvalue(L, s2v(L->top), u); + setuvalue(L, s2v(L->top.p), u); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -20397,7 +20637,7 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, Proto *p = f->p; if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) return NULL; /* 'n' not in [1, p->sizeupvalues] */ - *val = f->upvals[n-1]->v; + *val = f->upvals[n-1]->v.p; if (owner) *owner = obj2gco(f->upvals[n - 1]); name = p->upvalues[n-1].name; return (name == NULL) ? "(no name)" : getstr(name); @@ -20413,7 +20653,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { lua_lock(L); name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); if (name) { - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); } lua_unlock(L); @@ -20431,8 +20671,8 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { api_checknelems(L, 1); name = aux_upvalue(fi, n, &val, &owner); if (name) { - L->top--; - setobj(L, val, s2v(L->top)); + L->top.p--; + setobj(L, val, s2v(L->top.p)); luaC_barrier(L, owner, val); } lua_unlock(L); @@ -21015,13 +21255,14 @@ static void newbox (lua_State *L) { /* ** Compute new size for buffer 'B', enough to accommodate extra 'sz' -** bytes. +** bytes. (The test for "not big enough" also gets the case when the +** computation of 'newsize' overflows.) */ static size_t newbuffsize (luaL_Buffer *B, size_t sz) { - size_t newsize = B->size * 2; /* double buffer size */ + size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */ if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ return luaL_error(B->L, "buffer too large"); - if (newsize < B->n + sz) /* double is not big enough? */ + if (newsize < B->n + sz) /* not big enough? */ newsize = B->n + sz; return newsize; } @@ -21100,7 +21341,7 @@ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { ** box (if existent) is not on the top of the stack. So, instead of ** calling 'luaL_addlstring', it replicates the code using -2 as the ** last argument to 'prepbuffsize', signaling that the box is (or will -** be) bellow the string being added to the buffer. (Box creation can +** be) below the string being added to the buffer. (Box creation can ** trigger an emergency GC, so we should not remove the string from the ** stack before we have the space guaranteed.) */ @@ -21228,17 +21469,18 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { } -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ +/* +** Skip an optional BOM at the start of a stream. If there is an +** incomplete BOM (the first character is correct but the rest is +** not), returns the first character anyway to force an error +** (as no chunk can start with 0xEF). +*/ +static int skipBOM (FILE *f) { + int c = getc(f); /* read first character */ + if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF) /* correct BOM? */ + return getc(f); /* ignore BOM and return next char */ + else /* no (valid) BOM */ + return c; /* return first character */ } @@ -21249,13 +21491,13 @@ static int skipBOM (LoadF *lf) { ** first "valid" character of the file (after the optional BOM and ** a first-line comment). */ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); +static int skipcomment (FILE *f, int *cp) { + int c = *cp = skipBOM(f); if (c == '#') { /* first line is a comment (Unix exec. file)? */ do { /* skip first line */ - c = getc(lf->f); + c = getc(f); } while (c != EOF && c != '\n'); - *cp = getc(lf->f); /* skip end-of-line, if present */ + *cp = getc(f); /* next character after comment, if present */ return 1; /* there was a comment */ } else return 0; /* no comment */ @@ -21277,12 +21519,16 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ + lf.n = 0; + if (skipcomment(lf.f, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add newline to correct line numbers */ + if (c == LUA_SIGNATURE[0]) { /* binary file? */ + lf.n = 0; /* remove possible newline */ + if (filename) { /* "real" file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(lf.f, &c); /* re-read initial portion */ + } } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ @@ -22220,7 +22466,7 @@ static int luaB_auxwrap (lua_State *L) { if (l_unlikely(r < 0)) { /* error? */ int stat = lua_status(co); if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ - stat = lua_resetthread(co); /* close its tbc variables */ + stat = lua_closethread(co, L); /* close its tbc variables */ lua_assert(stat != LUA_OK); lua_xmove(co, L, 1); /* move error message to the caller */ } @@ -22316,7 +22562,7 @@ static int luaB_close (lua_State *L) { int status = auxstatus(L, co); switch (status) { case COS_DEAD: case COS_YIELD: { - status = lua_resetthread(co); + status = lua_closethread(co, L); if (status == LUA_OK) { lua_pushboolean(L, 1); return 1; @@ -23932,7 +24178,7 @@ static int math_type (lua_State *L) { /* try to find an integer type with at least 64 bits */ -#if (ULONG_MAX >> 31 >> 31) >= 3 +#if ((ULONG_MAX >> 31) >> 31) >= 3 /* 'long' has at least 64 bits */ #define Rand64 unsigned long @@ -23942,9 +24188,9 @@ static int math_type (lua_State *L) { /* there is a 'long long' type (which must have at least 64 bits) */ #define Rand64 unsigned long long -#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3 +#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 -/* 'lua_Integer' has at least 64 bits */ +/* 'lua_Unsigned' has at least 64 bits */ #define Rand64 lua_Unsigned #endif @@ -24165,12 +24411,12 @@ static lua_Number I2d (Rand64 x) { /* convert a 'Rand64' to a 'lua_Unsigned' */ static lua_Unsigned I2UInt (Rand64 x) { - return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l); + return (((lua_Unsigned)trim32(x.h) << 31) << 1) | (lua_Unsigned)trim32(x.l); } /* convert a 'lua_Unsigned' to a 'Rand64' */ static Rand64 Int2I (lua_Unsigned n) { - return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n); + return packI((lu_int32)((n >> 31) >> 1), (lu_int32)n); } #endif /* } */ @@ -25137,8 +25383,13 @@ static const luaL_Reg ll_funcs[] = { static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + static const lua_CFunction searchers[] = { + searcher_preload, + searcher_Lua, + searcher_C, + searcher_Croot, + NULL + }; int i; /* create 'searchers' table */ lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); @@ -25221,23 +25472,14 @@ LUAMOD_API int luaopen_package (lua_State *L) { */ #if !defined(LUA_STRFTIMEOPTIONS) /* { */ -/* options for ANSI C 89 (only 1-char options) */ -#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" - -/* options for ISO C 99 and POSIX */ -#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ - "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ - -/* options for Windows */ -#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ - "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ - #if defined(LUA_USE_WINDOWS) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN -#elif defined(LUA_USE_C89) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ +#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" #else /* C99 specification */ -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ #endif #endif /* } */ @@ -25329,12 +25571,21 @@ LUAMOD_API int luaopen_package (lua_State *L) { /* }================================================================== */ +#if !defined(l_system) +#if defined(LUA_USE_IOS) +/* Despite claiming to be ISO C, iOS does not implement 'system'. */ +#define l_system(cmd) ((cmd) == NULL ? 0 : -1) +#else +#define l_system(cmd) system(cmd) /* default definition */ +#endif +#endif + static int os_execute (lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); int stat; errno = 0; - stat = system(cmd); + stat = l_system(cmd); if (cmd != NULL) return luaL_execresult(L, stat); else { @@ -25451,9 +25702,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { res = d; } else { - /* unsigned avoids overflow when lua_Integer has 32 bits */ - if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta - : (lua_Integer)INT_MIN + delta <= res)) + if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) return luaL_error(L, "field '%s' is out-of-bound", key); res -= delta; } @@ -26191,7 +26440,7 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { if (l_unlikely(ms->matchdepth-- == 0)) luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ + init: /* using goto to optimize tail recursion */ if (p != ms->p_end) { /* end of pattern? */ switch (*p) { case '(': { /* start capture */ @@ -27588,7 +27837,7 @@ static int tremove (lua_State *L) { lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ /* check whether 'pos' is in [1, size + 1] */ - luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, + luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2, "position out of bounds"); lua_geti(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { @@ -27950,6 +28199,9 @@ LUAMOD_API int luaopen_table (lua_State *L) { #define MAXUTF 0x7FFFFFFFu + +#define MSGInvalid "invalid UTF-8 code" + /* ** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. */ @@ -27960,7 +28212,8 @@ typedef unsigned long utfint; #endif -#define iscont(p) ((*(p) & 0xC0) == 0x80) +#define iscont(c) (((c) & 0xC0) == 0x80) +#define iscontp(p) iscont(*(p)) /* from strlib */ @@ -27990,7 +28243,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { int count = 0; /* to count number of continuation bytes */ for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ unsigned int cc = (unsigned char)s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + if (!iscont(cc)) /* not a continuation byte? */ return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ } @@ -28065,7 +28318,7 @@ static int codepoint (lua_State *L) { utfint code; s = utf8_decode(s, &code, !lax); if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); + return luaL_error(L, MSGInvalid); lua_pushinteger(L, code); n++; } @@ -28115,16 +28368,16 @@ static int byteoffset (lua_State *L) { "position out of bounds"); if (n == 0) { /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; + while (posi > 0 && iscontp(s + posi)) posi--; } else { - if (iscont(s + posi)) + if (iscontp(s + posi)) return luaL_error(L, "initial position is a continuation byte"); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ do { /* find beginning of previous character */ posi--; - } while (posi > 0 && iscont(s + posi)); + } while (posi > 0 && iscontp(s + posi)); n++; } } @@ -28133,7 +28386,7 @@ static int byteoffset (lua_State *L) { while (n > 0 && posi < (lua_Integer)len) { do { /* find beginning of next character */ posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ + } while (iscontp(s + posi)); /* (cannot pass final '\0') */ n--; } } @@ -28151,15 +28404,15 @@ static int iter_aux (lua_State *L, int strict) { const char *s = luaL_checklstring(L, 1, &len); lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); if (n < len) { - while (iscont(s + n)) n++; /* skip continuation bytes */ + while (iscontp(s + n)) n++; /* go to next character */ } if (n >= len) /* (also handles original 'n' being negative) */ return 0; /* no more codepoints */ else { utfint code; const char *next = utf8_decode(s + n, &code, strict); - if (next == NULL) - return luaL_error(L, "invalid UTF-8 code"); + if (next == NULL || iscontp(next)) + return luaL_error(L, MSGInvalid); lua_pushinteger(L, n + 1); lua_pushinteger(L, code); return 2; @@ -28178,7 +28431,8 @@ static int iter_auxlax (lua_State *L) { static int iter_codes (lua_State *L) { int lax = lua_toboolean(L, 2); - luaL_checkstring(L, 1); + const char *s = luaL_checkstring(L, 1); + luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); lua_pushvalue(L, 1); lua_pushinteger(L, 0); @@ -28458,10 +28712,11 @@ static void print_version (void) { ** to the script (everything after 'script') go to positive indices; ** other arguments (before the script name) go to negative indices. ** If there is no script name, assume interpreter's name as base. +** (If there is no interpreter's name either, 'script' is -1, so +** table sizes are zero.) */ static void createargtable (lua_State *L, char **argv, int argc, int script) { int i, narg; - if (script == argc) script = 0; /* no script name? */ narg = argc - (script + 1); /* number of positive indices */ lua_createtable(L, narg, script + 1); for (i = 0; i < argc; i++) { @@ -28549,14 +28804,23 @@ static int handle_script (lua_State *L, char **argv) { /* ** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code (or an error code if it finds -** any invalid argument). 'first' returns the first not-handled argument -** (either the script name or a bad argument in case of error). +** needed before running any Lua code or an error code if it finds any +** invalid argument. In case of error, 'first' is the index of the bad +** argument. Otherwise, 'first' is -1 if there is no program name, +** 0 if there is no script name, or the index of the script name. */ static int collectargs (char **argv, int *first) { int args = 0; int i; - for (i = 1; argv[i] != NULL; i++) { + if (argv[0] != NULL) { /* is there a program name? */ + if (argv[0][0]) /* not empty? */ + progname = argv[0]; /* save it */ + } + else { /* no program name */ + *first = -1; + return 0; + } + for (i = 1; argv[i] != NULL; i++) { /* handle arguments */ *first = i; if (argv[i][0] != '-') /* not an option? */ return args; /* stop handling options */ @@ -28597,7 +28861,7 @@ static int collectargs (char **argv, int *first) { return has_error; } } - *first = i; /* no script name */ + *first = 0; /* no script name */ return args; } @@ -28890,8 +29154,8 @@ static int pmain (lua_State *L) { char **argv = (char **)lua_touserdata(L, 2); int script; int args = collectargs(argv, &script); + int optlim = (script > 0) ? script : argc; /* first argv not an option */ luaL_checkversion(L); /* check that interpreter has correct version */ - if (argv[0] && argv[0][0]) progname = argv[0]; if (args == has_error) { /* bad arg? */ print_usage(argv[script]); /* 'script' has index of bad arg. */ return 0; @@ -28904,19 +29168,21 @@ static int pmain (lua_State *L) { } luaL_openlibs(L); /* open standard libraries */ createargtable(L, argv, argc, script); /* create table 'arg' */ - lua_gc(L, LUA_GCGEN, 0, 0); /* GC in generational mode */ + lua_gc(L, LUA_GCRESTART); /* start GC... */ + lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ if (!(args & has_E)) { /* no option '-E'? */ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ return 0; /* error running LUA_INIT */ } - if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */ return 0; /* something failed */ - if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script) != LUA_OK) - return 0; + if (script > 0) { /* execute main script (if there is one) */ + if (handle_script(L, argv + script) != LUA_OK) + return 0; /* interrupt in case of error */ + } if (args & has_i) /* -i option? */ doREPL(L); /* do read-eval-print loop */ - else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */ if (lua_stdin_is_tty()) { /* running in interactive mode? */ print_version(); doREPL(L); /* do read-eval-print loop */ @@ -28935,6 +29201,7 @@ int main (int argc, char **argv) { l_message(argv[0], "cannot create state: not enough memory"); return EXIT_FAILURE; } + lua_gc(L, LUA_GCSTOP); /* stop GC while building state */ lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ lua_pushinteger(L, argc); /* 1st argument */ lua_pushlightuserdata(L, argv); /* 2nd argument */ @@ -28951,7 +29218,7 @@ int main (int argc, char **argv) { MIT License Copyright (c) 1994–2019 Lua.org, PUC-Rio. - Copyright (c) 2020-2022 Eduardo Bart (https://github.com/edubart). + Copyright (c) 2020-2023 Eduardo Bart (https://github.com/edubart). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/engine/split/3rd_rpmalloc.c b/engine/split/3rd_rpmalloc.c new file mode 100644 index 0000000..3b99b52 --- /dev/null +++ b/engine/split/3rd_rpmalloc.c @@ -0,0 +1,3629 @@ +/* rpmalloc.c - Memory allocator - Public Domain - 2016-2020 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +// #include "rpmalloc.h" //< @r-lyeh + +//////////// +/// +/// Build time configurable limits +/// +////// + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-macros" +#pragma clang diagnostic ignored "-Wunused-function" +#if __has_warning("-Wreserved-identifier") +#pragma clang diagnostic ignored "-Wreserved-identifier" +#endif +#if __has_warning("-Wstatic-in-inline") +#pragma clang diagnostic ignored "-Wstatic-in-inline" +#endif +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if !defined(__has_builtin) +#define __has_builtin(b) 0 +#endif + +#if defined(__GNUC__) || defined(__clang__) + +#if __has_builtin(__builtin_memcpy_inline) +#define _rpmalloc_memcpy_const(x, y, s) __builtin_memcpy_inline(x, y, s) +#else +#define _rpmalloc_memcpy_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memcpy(x, y, s); \ + } while (0) +#endif + +#if __has_builtin(__builtin_memset_inline) +#define _rpmalloc_memset_const(x, y, s) __builtin_memset_inline(x, y, s) +#else +#define _rpmalloc_memset_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memset(x, y, s); \ + } while (0) +#endif +#else +#define _rpmalloc_memcpy_const(x, y, s) memcpy(x, y, s) +#define _rpmalloc_memset_const(x, y, s) memset(x, y, s) +#endif + +#if __has_builtin(__builtin_assume) +#define rpmalloc_assume(cond) __builtin_assume(cond) +#elif defined(__GNUC__) +#define rpmalloc_assume(cond) \ + do { \ + if (!__builtin_expect(cond, 0)) \ + __builtin_unreachable(); \ + } while (0) +#elif defined(_MSC_VER) +#define rpmalloc_assume(cond) __assume(cond) +#else +#define rpmalloc_assume(cond) 0 +#endif + +#ifndef HEAP_ARRAY_SIZE +//! Size of heap hashmap +#define HEAP_ARRAY_SIZE 47 +#endif +#ifndef ENABLE_THREAD_CACHE +//! Enable per-thread cache +#define ENABLE_THREAD_CACHE 1 +#endif +#ifndef ENABLE_GLOBAL_CACHE +//! Enable global cache shared between all threads, requires thread cache +#define ENABLE_GLOBAL_CACHE 1 +#endif +#ifndef ENABLE_VALIDATE_ARGS +//! Enable validation of args to public entry points +#define ENABLE_VALIDATE_ARGS 0 +#endif +#ifndef ENABLE_STATISTICS +//! Enable statistics collection +#define ENABLE_STATISTICS 0 +#endif +#ifndef ENABLE_ASSERTS +//! Enable asserts +#define ENABLE_ASSERTS 0 +#endif +#ifndef ENABLE_OVERRIDE +//! Override standard library malloc/free and new/delete entry points +#define ENABLE_OVERRIDE 0 +#endif +#ifndef ENABLE_PRELOAD +//! Support preloading +#define ENABLE_PRELOAD 0 +#endif +#ifndef DISABLE_UNMAP +//! Disable unmapping memory pages (also enables unlimited cache) +#define DISABLE_UNMAP 0 +#endif +#ifndef ENABLE_UNLIMITED_CACHE +//! Enable unlimited global cache (no unmapping until finalization) +#define ENABLE_UNLIMITED_CACHE 0 +#endif +#ifndef ENABLE_ADAPTIVE_THREAD_CACHE +//! Enable adaptive thread cache size based on use heuristics +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif +#ifndef DEFAULT_SPAN_MAP_COUNT +//! Default number of spans to map in call to map more virtual memory (default values yield 4MiB here) +#define DEFAULT_SPAN_MAP_COUNT 64 +#endif +#ifndef GLOBAL_CACHE_MULTIPLIER +//! Multiplier for global cache +#define GLOBAL_CACHE_MULTIPLIER 8 +#endif + +#if DISABLE_UNMAP && !ENABLE_GLOBAL_CACHE +#error Must use global cache if unmap is disabled +#endif + +#if DISABLE_UNMAP +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 1 +#endif + +#if !ENABLE_GLOBAL_CACHE +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 0 +#endif + +#if !ENABLE_THREAD_CACHE +#undef ENABLE_ADAPTIVE_THREAD_CACHE +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) +# define PLATFORM_WINDOWS 1 +# define PLATFORM_POSIX 0 +#else +# define PLATFORM_WINDOWS 0 +# define PLATFORM_POSIX 1 +#endif + +/// Platform and arch specifics +#if defined(_MSC_VER) && !defined(__clang__) +# pragma warning (disable: 5105) +# ifndef FORCEINLINE +# define FORCEINLINE inline __forceinline +# endif +# define _Static_assert static_assert +#else +# ifndef FORCEINLINE +# define FORCEINLINE inline __attribute__((__always_inline__)) +# endif +#endif +#if PLATFORM_WINDOWS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if ENABLE_VALIDATE_ARGS +# include +# endif +#else +# include +# include +# include +# include +# if defined(__linux__) || defined(__ANDROID__) +# include +# if !defined(PR_SET_VMA) +# define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 +# endif +# endif +# if defined(__APPLE__) +# include +# if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +# include +# include +# endif +# include +# endif +# if defined(__HAIKU__) || defined(__TINYC__) +# include +# endif +#endif + +#include +#include +#include + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +#include +static DWORD fls_key; +#endif + +#if PLATFORM_POSIX +# include +# include +# ifdef __FreeBSD__ +# include +# define MAP_HUGETLB MAP_ALIGNED_SUPER +# ifndef PROT_MAX +# define PROT_MAX(f) 0 +# endif +# else +# define PROT_MAX(f) 0 +# endif +# ifdef __sun +extern int madvise(caddr_t, size_t, int); +# endif +# ifndef MAP_UNINITIALIZED +# define MAP_UNINITIALIZED 0 +# endif +#endif +#include + +#if ENABLE_ASSERTS +# undef NDEBUG +# if defined(_MSC_VER) && !defined(_DEBUG) +# define _DEBUG +# endif +# include +#define RPMALLOC_TOSTRING_M(x) #x +#define RPMALLOC_TOSTRING(x) RPMALLOC_TOSTRING_M(x) +#define rpmalloc_assert(truth, message) \ + do { \ + if (!(truth)) { \ + if (_memory_config.error_callback) { \ + _memory_config.error_callback( \ + message " (" RPMALLOC_TOSTRING(truth) ") at " __FILE__ ":" RPMALLOC_TOSTRING(__LINE__)); \ + } else { \ + assert((truth) && message); \ + } \ + } \ + } while (0) +#else +# define rpmalloc_assert(truth, message) do {} while(0) +#endif +#if ENABLE_STATISTICS +# include +#endif + +////// +/// +/// Atomic access abstraction (since MSVC does not do C11 yet) +/// +////// + +#if defined(_MSC_VER) && !defined(__clang__) + +typedef volatile long atomic32_t; +typedef volatile long long atomic64_t; +typedef volatile void* atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return *src; } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return (int32_t)InterlockedIncrement(val); } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return (int32_t)InterlockedDecrement(val); } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return (int32_t)InterlockedExchangeAdd(val, add) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return (InterlockedCompareExchange(dst, val, ref) == ref) ? 1 : 0; } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int64_t atomic_load64(atomic64_t* src) { return *src; } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return (int64_t)InterlockedExchangeAdd64(val, add) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return (void*)*src; } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return (void*)InterlockedExchangePointer((void* volatile*)dst, val); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return (InterlockedCompareExchangePointer((void* volatile*)dst, val, ref) == ref) ? 1 : 0; } + +#define EXPECTED(x) (x) +#define UNEXPECTED(x) (x) + +#else + +#include + +typedef volatile _Atomic(int32_t) atomic32_t; +typedef volatile _Atomic(int64_t) atomic64_t; +typedef volatile _Atomic(void*) atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, -1, memory_order_relaxed) - 1; } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_acquire, memory_order_relaxed); } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE int64_t atomic_load64(atomic64_t* val) { return atomic_load_explicit(val, memory_order_relaxed); } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return atomic_exchange_explicit(dst, val, memory_order_acquire); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_relaxed, memory_order_relaxed); } + +#define EXPECTED(x) __builtin_expect((x), 1) +#define UNEXPECTED(x) __builtin_expect((x), 0) + +#endif + +//////////// +/// +/// Statistics related functions (evaluate to nothing when statistics not enabled) +/// +////// + +#if ENABLE_STATISTICS +# define _rpmalloc_stat_inc(counter) atomic_incr32(counter) +# define _rpmalloc_stat_dec(counter) atomic_decr32(counter) +# define _rpmalloc_stat_add(counter, value) atomic_add32(counter, (int32_t)(value)) +# define _rpmalloc_stat_add64(counter, value) atomic_add64(counter, (int64_t)(value)) +# define _rpmalloc_stat_add_peak(counter, value, peak) do { int32_t _cur_count = atomic_add32(counter, (int32_t)(value)); if (_cur_count > (peak)) peak = _cur_count; } while (0) +# define _rpmalloc_stat_sub(counter, value) atomic_add32(counter, -(int32_t)(value)) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do { \ + int32_t alloc_current = atomic_incr32(&heap->size_class_use[class_idx].alloc_current); \ + if (alloc_current > heap->size_class_use[class_idx].alloc_peak) \ + heap->size_class_use[class_idx].alloc_peak = alloc_current; \ + atomic_incr32(&heap->size_class_use[class_idx].alloc_total); \ +} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do { \ + atomic_decr32(&heap->size_class_use[class_idx].alloc_current); \ + atomic_incr32(&heap->size_class_use[class_idx].free_total); \ +} while(0) +#else +# define _rpmalloc_stat_inc(counter) do {} while(0) +# define _rpmalloc_stat_dec(counter) do {} while(0) +# define _rpmalloc_stat_add(counter, value) do {} while(0) +# define _rpmalloc_stat_add64(counter, value) do {} while(0) +# define _rpmalloc_stat_add_peak(counter, value, peak) do {} while (0) +# define _rpmalloc_stat_sub(counter, value) do {} while(0) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do {} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do {} while(0) +#endif + + +/// +/// Preconfigured limits and sizes +/// + +//! Granularity of a small allocation block (must be power of two) +#define SMALL_GRANULARITY 16 +//! Small granularity shift count +#define SMALL_GRANULARITY_SHIFT 4 +//! Number of small block size classes +#define SMALL_CLASS_COUNT 65 +//! Maximum size of a small block +#define SMALL_SIZE_LIMIT (SMALL_GRANULARITY * (SMALL_CLASS_COUNT - 1)) +//! Granularity of a medium allocation block +#define MEDIUM_GRANULARITY 512 +//! Medium granularity shift count +#define MEDIUM_GRANULARITY_SHIFT 9 +//! Number of medium block size classes +#define MEDIUM_CLASS_COUNT 61 +//! Total number of small + medium size classes +#define SIZE_CLASS_COUNT (SMALL_CLASS_COUNT + MEDIUM_CLASS_COUNT) +//! Number of large block size classes +#define LARGE_CLASS_COUNT 63 +//! Maximum size of a medium block +#define MEDIUM_SIZE_LIMIT (SMALL_SIZE_LIMIT + (MEDIUM_GRANULARITY * MEDIUM_CLASS_COUNT)) +//! Maximum size of a large block +#define LARGE_SIZE_LIMIT ((LARGE_CLASS_COUNT * _memory_span_size) - SPAN_HEADER_SIZE) +//! Size of a span header (must be a multiple of SMALL_GRANULARITY and a power of two) +#define SPAN_HEADER_SIZE 128 +//! Number of spans in thread cache +#define MAX_THREAD_SPAN_CACHE 400 +//! Number of spans to transfer between thread and global cache +#define THREAD_SPAN_CACHE_TRANSFER 64 +//! Number of spans in thread cache for large spans (must be greater than LARGE_CLASS_COUNT / 2) +#define MAX_THREAD_SPAN_LARGE_CACHE 100 +//! Number of spans to transfer between thread and global cache for large spans +#define THREAD_SPAN_LARGE_CACHE_TRANSFER 6 + +_Static_assert((SMALL_GRANULARITY & (SMALL_GRANULARITY - 1)) == 0, "Small granularity must be power of two"); +_Static_assert((SPAN_HEADER_SIZE & (SPAN_HEADER_SIZE - 1)) == 0, "Span header size must be power of two"); + +#if ENABLE_VALIDATE_ARGS +//! Maximum allocation size to avoid integer overflow +#undef MAX_ALLOC_SIZE +#define MAX_ALLOC_SIZE (((size_t)-1) - _memory_span_size) +#endif + +#define pointer_offset(ptr, ofs) (void*)((char*)(ptr) + (ptrdiff_t)(ofs)) +#define pointer_diff(first, second) (ptrdiff_t)((const char*)(first) - (const char*)(second)) + +#define INVALID_POINTER ((void*)((uintptr_t)-1)) + +#define SIZE_CLASS_LARGE SIZE_CLASS_COUNT +#define SIZE_CLASS_HUGE ((uint32_t)-1) + +//////////// +/// +/// Data types +/// +////// + +//! A memory heap, per thread +typedef struct heap_t heap_t; +//! Span of memory pages +typedef struct span_t span_t; +//! Span list +typedef struct span_list_t span_list_t; +//! Span active data +typedef struct span_active_t span_active_t; +//! Size class definition +typedef struct size_class_t size_class_t; +//! Global cache +typedef struct global_cache_t global_cache_t; + +//! Flag indicating span is the first (master) span of a split superspan +#define SPAN_FLAG_MASTER 1U +//! Flag indicating span is a secondary (sub) span of a split superspan +#define SPAN_FLAG_SUBSPAN 2U +//! Flag indicating span has blocks with increased alignment +#define SPAN_FLAG_ALIGNED_BLOCKS 4U +//! Flag indicating an unmapped master span +#define SPAN_FLAG_UNMAPPED_MASTER 8U + +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS +struct span_use_t { + //! Current number of spans used (actually used, not in cache) + atomic32_t current; + //! High water mark of spans used + atomic32_t high; +#if ENABLE_STATISTICS + //! Number of spans in deferred list + atomic32_t spans_deferred; + //! Number of spans transitioned to global cache + atomic32_t spans_to_global; + //! Number of spans transitioned from global cache + atomic32_t spans_from_global; + //! Number of spans transitioned to thread cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from thread cache + atomic32_t spans_from_cache; + //! Number of spans transitioned to reserved state + atomic32_t spans_to_reserved; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of raw memory map calls + atomic32_t spans_map_calls; +#endif +}; +typedef struct span_use_t span_use_t; +#endif + +#if ENABLE_STATISTICS +struct size_class_use_t { + //! Current number of allocations + atomic32_t alloc_current; + //! Peak number of allocations + int32_t alloc_peak; + //! Total number of allocations + atomic32_t alloc_total; + //! Total number of frees + atomic32_t free_total; + //! Number of spans in use + atomic32_t spans_current; + //! Number of spans transitioned to cache + int32_t spans_peak; + //! Number of spans transitioned to cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from cache + atomic32_t spans_from_cache; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of spans mapped + atomic32_t spans_map_calls; + int32_t unused; +}; +typedef struct size_class_use_t size_class_use_t; +#endif + +// A span can either represent a single span of memory pages with size declared by span_map_count configuration variable, +// or a set of spans in a continuous region, a super span. Any reference to the term "span" usually refers to both a single +// span or a super span. A super span can further be divided into multiple spans (or this, super spans), where the first +// (super)span is the master and subsequent (super)spans are subspans. The master span keeps track of how many subspans +// that are still alive and mapped in virtual memory, and once all subspans and master have been unmapped the entire +// superspan region is released and unmapped (on Windows for example, the entire superspan range has to be released +// in the same call to release the virtual memory range, but individual subranges can be decommitted individually +// to reduce physical memory use). +struct span_t { + //! Free list + void* free_list; + //! Total block count of size class + uint32_t block_count; + //! Size class + uint32_t size_class; + //! Index of last block initialized in free list + uint32_t free_list_limit; + //! Number of used blocks remaining when in partial state + uint32_t used_count; + //! Deferred free list + atomicptr_t free_list_deferred; + //! Size of deferred free list, or list of spans when part of a cache list + uint32_t list_size; + //! Size of a block + uint32_t block_size; + //! Flags and counters + uint32_t flags; + //! Number of spans + uint32_t span_count; + //! Total span counter for master spans + uint32_t total_spans; + //! Offset from master span for subspans + uint32_t offset_from_master; + //! Remaining span counter, for master spans + atomic32_t remaining_spans; + //! Alignment offset + uint32_t align_offset; + //! Owning heap + heap_t* heap; + //! Next span + span_t* next; + //! Previous span + span_t* prev; +}; +_Static_assert(sizeof(span_t) <= SPAN_HEADER_SIZE, "span size mismatch"); + +struct span_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_CACHE]; +}; +typedef struct span_cache_t span_cache_t; + +struct span_large_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_LARGE_CACHE]; +}; +typedef struct span_large_cache_t span_large_cache_t; + +struct heap_size_class_t { + //! Free list of active span + void* free_list; + //! Double linked list of partially used spans with free blocks. + // Previous span pointer in head points to tail span of list. + span_t* partial_span; + //! Early level cache of fully free spans + span_t* cache; +}; +typedef struct heap_size_class_t heap_size_class_t; + +// Control structure for a heap, either a thread heap or a first class heap if enabled +struct heap_t { + //! Owning thread ID + uintptr_t owner_thread; + //! Free lists for each size class + heap_size_class_t size_class[SIZE_CLASS_COUNT]; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, single span + span_cache_t span_cache; +#endif + //! List of deferred free spans (single linked list) + atomicptr_t span_free_deferred; + //! Number of full spans + size_t full_span_count; + //! Mapped but unused spans + span_t* span_reserve; + //! Master span for mapped but unused spans + span_t* span_reserve_master; + //! Number of mapped but unused spans + uint32_t spans_reserved; + //! Child count + atomic32_t child_count; + //! Next heap in id list + heap_t* next_heap; + //! Next heap in orphan list + heap_t* next_orphan; + //! Heap ID + int32_t id; + //! Finalization state flag + int finalize; + //! Master heap owning the memory pages + heap_t* master_heap; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, large spans with > 1 span count + span_large_cache_t span_large_cache[LARGE_CLASS_COUNT - 1]; +#endif +#if RPMALLOC_FIRST_CLASS_HEAPS + //! Double linked list of fully utilized spans with free blocks for each size class. + // Previous span pointer in head points to tail span of list. + span_t* full_span[SIZE_CLASS_COUNT]; + //! Double linked list of large and huge spans allocated by this heap + span_t* large_huge_span; +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //! Current and high water mark of spans used per span count + span_use_t span_use[LARGE_CLASS_COUNT]; +#endif +#if ENABLE_STATISTICS + //! Allocation stats per size class + size_class_use_t size_class_use[SIZE_CLASS_COUNT + 1]; + //! Number of bytes transitioned thread -> global + atomic64_t thread_to_global; + //! Number of bytes transitioned global -> thread + atomic64_t global_to_thread; +#endif +}; + +// Size class for defining a block size bucket +struct size_class_t { + //! Size of blocks in this class + uint32_t block_size; + //! Number of blocks in each chunk + uint16_t block_count; + //! Class index this class is merged with + uint16_t class_idx; +}; +_Static_assert(sizeof(size_class_t) == 8, "Size class size mismatch"); + +struct global_cache_t { + //! Cache lock + atomic32_t lock; + //! Cache count + uint32_t count; +#if ENABLE_STATISTICS + //! Insert count + size_t insert_count; + //! Extract count + size_t extract_count; +#endif + //! Cached spans + span_t* span[GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE]; + //! Unlimited cache overflow + span_t* overflow; +}; + +//////////// +/// +/// Global data +/// +////// + +//! Default span size (64KiB) +#define _memory_default_span_size (64 * 1024) +#define _memory_default_span_size_shift 16 +#define _memory_default_span_mask (~((uintptr_t)(_memory_span_size - 1))) + +//! Initialized flag +static int _rpmalloc_initialized; +//! Main thread ID +static uintptr_t _rpmalloc_main_thread_id; +//! Configuration +static rpmalloc_config_t _memory_config; +//! Memory page size +static size_t _memory_page_size; +//! Shift to divide by page size +static size_t _memory_page_size_shift; +//! Granularity at which memory pages are mapped by OS +static size_t _memory_map_granularity; +#if RPMALLOC_CONFIGURABLE +//! Size of a span of memory pages +static size_t _memory_span_size; +//! Shift to divide by span size +static size_t _memory_span_size_shift; +//! Mask to get to start of a memory span +static uintptr_t _memory_span_mask; +#else +//! Hardwired span size +#define _memory_span_size _memory_default_span_size +#define _memory_span_size_shift _memory_default_span_size_shift +#define _memory_span_mask _memory_default_span_mask +#endif +//! Number of spans to map in each map call +static size_t _memory_span_map_count; +//! Number of spans to keep reserved in each heap +static size_t _memory_heap_reserve_count; +//! Global size classes +static size_class_t _memory_size_class[SIZE_CLASS_COUNT]; +//! Run-time size limit of medium blocks +static size_t _memory_medium_size_limit; +//! Heap ID counter +static atomic32_t _memory_heap_id; +//! Huge page support +static int _memory_huge_pages; +#if ENABLE_GLOBAL_CACHE +//! Global span cache +static global_cache_t _memory_span_cache[LARGE_CLASS_COUNT]; +#endif +//! Global reserved spans +static span_t* _memory_global_reserve; +//! Global reserved count +static size_t _memory_global_reserve_count; +//! Global reserved master +static span_t* _memory_global_reserve_master; +//! All heaps +static heap_t* _memory_heaps[HEAP_ARRAY_SIZE]; +//! Used to restrict access to mapping memory for huge pages +static atomic32_t _memory_global_lock; +//! Orphaned heaps +static heap_t* _memory_orphan_heaps; +#if RPMALLOC_FIRST_CLASS_HEAPS +//! Orphaned heaps (first class heaps) +static heap_t* _memory_first_class_orphan_heaps; +#endif +#if ENABLE_STATISTICS +//! Allocations counter +static atomic64_t _allocation_counter; +//! Deallocations counter +static atomic64_t _deallocation_counter; +//! Active heap count +static atomic32_t _memory_active_heaps; +//! Number of currently mapped memory pages +static atomic32_t _mapped_pages; +//! Peak number of concurrently mapped memory pages +static int32_t _mapped_pages_peak; +//! Number of mapped master spans +static atomic32_t _master_spans; +//! Number of unmapped dangling master spans +static atomic32_t _unmapped_master_spans; +//! Running counter of total number of mapped memory pages since start +static atomic32_t _mapped_total; +//! Running counter of total number of unmapped memory pages since start +static atomic32_t _unmapped_total; +//! Number of currently mapped memory pages in OS calls +static atomic32_t _mapped_pages_os; +//! Number of currently allocated pages in huge allocations +static atomic32_t _huge_pages_current; +//! Peak number of currently allocated pages in huge allocations +static int32_t _huge_pages_peak; +#endif + +//////////// +/// +/// Thread local heap and ID +/// +////// + +//! Current thread heap +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) +static pthread_key_t _memory_thread_heap; +#else +# ifdef _MSC_VER +# define _Thread_local __declspec(thread) +# define TLS_MODEL +# else +# ifndef __HAIKU__ +# define TLS_MODEL __attribute__((tls_model("initial-exec"))) +# else +# define TLS_MODEL +# endif +# if !defined(__clang__) && defined(__GNUC__) +# define _Thread_local __thread +# endif +# endif +static _Thread_local heap_t* _memory_thread_heap TLS_MODEL; +#endif + +static inline heap_t* +get_thread_heap_raw(void) { +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + return pthread_getspecific(_memory_thread_heap); +#else + return _memory_thread_heap; +#endif +} + +//! Get the current thread heap +static inline heap_t* +get_thread_heap(void) { + heap_t* heap = get_thread_heap_raw(); +#if ENABLE_PRELOAD + if (EXPECTED(heap != 0)) + return heap; + rpmalloc_initialize(); + return get_thread_heap_raw(); +#else + return heap; +#endif +} + +//! Fast thread ID +static inline uintptr_t +get_thread_id(void) { +#if defined(_WIN32) + return (uintptr_t)((void*)NtCurrentTeb()); +#elif (defined(__GNUC__) || defined(__clang__)) && !defined(__CYGWIN__) + uintptr_t tid; +# if defined(__i386__) + __asm__("movl %%gs:0, %0" : "=r" (tid) : : ); +# elif defined(__x86_64__) +# if defined(__MACH__) + __asm__("movq %%gs:0, %0" : "=r" (tid) : : ); +# else + __asm__("movq %%fs:0, %0" : "=r" (tid) : : ); +# endif +# elif defined(__arm__) + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid)); +# elif defined(__aarch64__) +# if defined(__MACH__) + // tpidr_el0 likely unused, always return 0 on iOS + __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tid)); +# else + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tid)); +# endif +# else +# error This platform needs implementation of get_thread_id() +# endif + return tid; +#else +# error This platform needs implementation of get_thread_id() +#endif +} + +//! Set the current thread heap +static void +set_thread_heap(heap_t* heap) { +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + pthread_setspecific(_memory_thread_heap, heap); +#else + _memory_thread_heap = heap; +#endif + if (heap) + heap->owner_thread = get_thread_id(); +} + +//! Set main thread ID +extern void +rpmalloc_set_main_thread(void); + +void +rpmalloc_set_main_thread(void) { + _rpmalloc_main_thread_id = get_thread_id(); +} + +static void +_rpmalloc_spin(void) { +#if defined(_MSC_VER) + _mm_pause(); +#elif defined(__x86_64__) || defined(__i386__) + __asm__ volatile("pause" ::: "memory"); +#elif defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH >= 7) + __asm__ volatile("yield" ::: "memory"); +#elif defined(__powerpc__) || defined(__powerpc64__) + // No idea if ever been compiled in such archs but ... as precaution + __asm__ volatile("or 27,27,27"); +#elif defined(__sparc__) + __asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0"); +#else + struct timespec ts = {0}; + nanosleep(&ts, 0); +#endif +} + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +static void NTAPI +_rpmalloc_thread_destructor(void* value) { +#if ENABLE_OVERRIDE + // If this is called on main thread it means rpmalloc_finalize + // has not been called and shutdown is forced (through _exit) or unclean + if (get_thread_id() == _rpmalloc_main_thread_id) + return; +#endif + if (value) + rpmalloc_thread_finalize(1); +} +#endif + + +//////////// +/// +/// Low level memory map/unmap +/// +////// + +static void +_rpmalloc_set_name(void* address, size_t size) { +#if defined(__linux__) || defined(__ANDROID__) + const char *name = _memory_huge_pages ? _memory_config.huge_page_name : _memory_config.page_name; + if (address == MAP_FAILED || !name) + return; + // If the kernel does not support CONFIG_ANON_VMA_NAME or if the call fails + // (e.g. invalid name) it is a no-op basically. + (void)prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)address, size, (uintptr_t)name); +#else + (void)sizeof(size); + (void)sizeof(address); +#endif +} + + +//! Map more virtual memory +// size is number of bytes to map +// offset receives the offset in bytes from start of mapped region +// returns address to start of mapped region to use +static void* +_rpmalloc_mmap(size_t size, size_t* offset) { + rpmalloc_assert(!(size % _memory_page_size), "Invalid mmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); + void* address = _memory_config.memory_map(size, offset); + if (EXPECTED(address != 0)) { + _rpmalloc_stat_add_peak(&_mapped_pages, (size >> _memory_page_size_shift), _mapped_pages_peak); + _rpmalloc_stat_add(&_mapped_total, (size >> _memory_page_size_shift)); + } + return address; +} + +//! Unmap virtual memory +// address is the memory address to unmap, as returned from _memory_map +// size is the number of bytes to unmap, which might be less than full region for a partial unmap +// offset is the offset in bytes to the actual mapped region, as set by _memory_map +// release is set to 0 for partial unmap, or size of entire range for a full unmap +static void +_rpmalloc_unmap(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(!release || (release >= size), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + if (release) { + rpmalloc_assert(!(release % _memory_page_size), "Invalid unmap size"); + _rpmalloc_stat_sub(&_mapped_pages, (release >> _memory_page_size_shift)); + _rpmalloc_stat_add(&_unmapped_total, (release >> _memory_page_size_shift)); + } + _memory_config.memory_unmap(address, size, offset, release); +} + +//! Default implementation to map new pages to virtual memory +static void* +_rpmalloc_mmap_os(size_t size, size_t* offset) { + //Either size is a heap (a single page) or a (multiple) span - we only need to align spans, and only if larger than map granularity + size_t padding = ((size >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) ? _memory_span_size : 0; + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); +#if PLATFORM_WINDOWS + //Ok to MEM_COMMIT - according to MSDN, "actual physical pages are not allocated unless/until the virtual addresses are actually accessed" + void* ptr = VirtualAlloc(0, size + padding, (_memory_huge_pages ? MEM_LARGE_PAGES : 0) | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (!ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else { + rpmalloc_assert(ptr, "Failed to map virtual memory block"); + } + return 0; + } +#else + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED; +# if defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + int fd = (int)VM_MAKE_TAG(240U); + if (_memory_huge_pages) + fd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, fd, 0); +# elif defined(MAP_HUGETLB) + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE | PROT_MAX(PROT_READ | PROT_WRITE), (_memory_huge_pages ? MAP_HUGETLB : 0) | flags, -1, 0); +# if defined(MADV_HUGEPAGE) + // In some configurations, huge pages allocations might fail thus + // we fallback to normal allocations and promote the region as transparent huge page + if ((ptr == MAP_FAILED || !ptr) && _memory_huge_pages) { + ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); + if (ptr && ptr != MAP_FAILED) { + int prm = madvise(ptr, size + padding, MADV_HUGEPAGE); + (void)prm; + rpmalloc_assert((prm == 0), "Failed to promote the page to THP"); + } + } +# endif + _rpmalloc_set_name(ptr, size + padding); +# elif defined(MAP_ALIGNED) + const size_t align = (sizeof(size_t) * 8) - (size_t)(__builtin_clzl(size - 1)); + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGNED(align) : 0) | flags, -1, 0); +# elif defined(MAP_ALIGN) + caddr_t base = (_memory_huge_pages ? (caddr_t)(4 << 20) : 0); + void* ptr = mmap(base, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGN : 0) | flags, -1, 0); +# else + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); +# endif + if ((ptr == MAP_FAILED) || !ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else if (errno != ENOMEM) { + rpmalloc_assert((ptr != MAP_FAILED) && ptr, "Failed to map virtual memory block"); + } + return 0; + } +#endif + _rpmalloc_stat_add(&_mapped_pages_os, (int32_t)((size + padding) >> _memory_page_size_shift)); + if (padding) { + size_t final_padding = padding - ((uintptr_t)ptr & ~_memory_span_mask); + rpmalloc_assert(final_padding <= _memory_span_size, "Internal failure in padding"); + rpmalloc_assert(final_padding <= padding, "Internal failure in padding"); + rpmalloc_assert(!(final_padding % 8), "Internal failure in padding"); + ptr = pointer_offset(ptr, final_padding); + *offset = final_padding >> 3; + } + rpmalloc_assert((size < _memory_span_size) || !((uintptr_t)ptr & ~_memory_span_mask), "Internal failure in padding"); + return ptr; +} + +//! Default implementation to unmap pages from virtual memory +static void +_rpmalloc_unmap_os(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(release || (offset == 0), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid unmap size"); + if (release && offset) { + offset <<= 3; + address = pointer_offset(address, -(int32_t)offset); + if ((release >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) { + //Padding is always one span size + release += _memory_span_size; + } + } +#if !DISABLE_UNMAP +#if PLATFORM_WINDOWS + if (!VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } +#else + if (release) { + if (munmap(address, release)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } + } else { +#if defined(MADV_FREE_REUSABLE) + int ret; + while ((ret = madvise(address, size, MADV_FREE_REUSABLE)) == -1 && (errno == EAGAIN)) + errno = 0; + if ((ret == -1) && (errno != 0)) { +#elif defined(MADV_DONTNEED) + if (madvise(address, size, MADV_DONTNEED)) { +#elif defined(MADV_PAGEOUT) + if (madvise(address, size, MADV_PAGEOUT)) { +#elif defined(MADV_FREE) + if (madvise(address, size, MADV_FREE)) { +#else + if (posix_madvise(address, size, POSIX_MADV_DONTNEED)) { +#endif + rpmalloc_assert(0, "Failed to madvise virtual memory block as free"); + } + } +#endif +#endif + if (release) + _rpmalloc_stat_sub(&_mapped_pages_os, release >> _memory_page_size_shift); +} + +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count); + +//! Use global reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_global_get_reserved_spans(size_t span_count) { + span_t* span = _memory_global_reserve; + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, span, span_count); + _memory_global_reserve_count -= span_count; + if (_memory_global_reserve_count) + _memory_global_reserve = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + else + _memory_global_reserve = 0; + return span; +} + +//! Store the given spans as global reserve (must only be called from within new heap allocation, not thread safe) +static void +_rpmalloc_global_set_reserved_spans(span_t* master, span_t* reserve, size_t reserve_span_count) { + _memory_global_reserve_master = master; + _memory_global_reserve_count = reserve_span_count; + _memory_global_reserve = reserve; +} + + +//////////// +/// +/// Span linked list management +/// +////// + +//! Add a span to double linked list at the head +static void +_rpmalloc_span_double_link_list_add(span_t** head, span_t* span) { + if (*head) + (*head)->prev = span; + span->next = *head; + *head = span; +} + +//! Pop head span from double linked list +static void +_rpmalloc_span_double_link_list_pop_head(span_t** head, span_t* span) { + rpmalloc_assert(*head == span, "Linked list corrupted"); + span = *head; + *head = span->next; +} + +//! Remove a span from double linked list +static void +_rpmalloc_span_double_link_list_remove(span_t** head, span_t* span) { + rpmalloc_assert(*head, "Linked list corrupted"); + if (*head == span) { + *head = span->next; + } else { + span_t* next_span = span->next; + span_t* prev_span = span->prev; + prev_span->next = next_span; + if (EXPECTED(next_span != 0)) + next_span->prev = prev_span; + } +} + + +//////////// +/// +/// Span control +/// +////// + +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span); + +static void +_rpmalloc_heap_finalize(heap_t* heap); + +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count); + +//! Declare the span to be a subspan and store distance from master span and span count +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count) { + rpmalloc_assert((subspan != master) || (subspan->flags & SPAN_FLAG_MASTER), "Span master pointer and/or flag mismatch"); + if (subspan != master) { + subspan->flags = SPAN_FLAG_SUBSPAN; + subspan->offset_from_master = (uint32_t)((uintptr_t)pointer_diff(subspan, master) >> _memory_span_size_shift); + subspan->align_offset = 0; + } + subspan->span_count = (uint32_t)span_count; +} + +//! Use reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_span_map_from_reserve(heap_t* heap, size_t span_count) { + //Update the heap span reserve + span_t* span = heap->span_reserve; + heap->span_reserve = (span_t*)pointer_offset(span, span_count * _memory_span_size); + heap->spans_reserved -= (uint32_t)span_count; + + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, span, span_count); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_reserved); + + return span; +} + +//! Get the aligned number of spans to map in based on wanted count, configured mapping granularity and the page size +static size_t +_rpmalloc_span_align_count(size_t span_count) { + size_t request_count = (span_count > _memory_span_map_count) ? span_count : _memory_span_map_count; + if ((_memory_page_size > _memory_span_size) && ((request_count * _memory_span_size) % _memory_page_size)) + request_count += _memory_span_map_count - (request_count % _memory_span_map_count); + return request_count; +} + +//! Setup a newly mapped span +static void +_rpmalloc_span_initialize(span_t* span, size_t total_span_count, size_t span_count, size_t align_offset) { + span->total_spans = (uint32_t)total_span_count; + span->span_count = (uint32_t)span_count; + span->align_offset = (uint32_t)align_offset; + span->flags = SPAN_FLAG_MASTER; + atomic_store32(&span->remaining_spans, (int32_t)total_span_count); +} + +static void +_rpmalloc_span_unmap(span_t* span); + +//! Map an aligned set of spans, taking configured mapping granularity and the page size into account +static span_t* +_rpmalloc_span_map_aligned_count(heap_t* heap, size_t span_count) { + //If we already have some, but not enough, reserved spans, release those to heap cache and map a new + //full set of spans. Otherwise we would waste memory if page size > span size (huge pages) + size_t aligned_span_count = _rpmalloc_span_align_count(span_count); + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(aligned_span_count * _memory_span_size, &align_offset); + if (!span) + return 0; + _rpmalloc_span_initialize(span, aligned_span_count, span_count, align_offset); + _rpmalloc_stat_inc(&_master_spans); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_map_calls); + if (aligned_span_count > span_count) { + span_t* reserved_spans = (span_t*)pointer_offset(span, span_count * _memory_span_size); + size_t reserved_count = aligned_span_count - span_count; + if (heap->spans_reserved) { + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, heap->span_reserve, heap->spans_reserved); + _rpmalloc_heap_cache_insert(heap, heap->span_reserve); + } + if (reserved_count > _memory_heap_reserve_count) { + // If huge pages or eager spam map count, the global reserve spin lock is held by caller, _rpmalloc_span_map + rpmalloc_assert(atomic_load32(&_memory_global_lock) == 1, "Global spin lock not held as expected"); + size_t remain_count = reserved_count - _memory_heap_reserve_count; + reserved_count = _memory_heap_reserve_count; + span_t* remain_span = (span_t*)pointer_offset(reserved_spans, reserved_count * _memory_span_size); + if (_memory_global_reserve) { + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, _memory_global_reserve, _memory_global_reserve_count); + _rpmalloc_span_unmap(_memory_global_reserve); + } + _rpmalloc_global_set_reserved_spans(span, remain_span, remain_count); + } + _rpmalloc_heap_set_reserved_spans(heap, span, reserved_spans, reserved_count); + } + return span; +} + +//! Map in memory pages for the given number of spans (or use previously reserved pages) +static span_t* +_rpmalloc_span_map(heap_t* heap, size_t span_count) { + if (span_count <= heap->spans_reserved) + return _rpmalloc_span_map_from_reserve(heap, span_count); + span_t* span = 0; + int use_global_reserve = (_memory_page_size > _memory_span_size) || (_memory_span_map_count > _memory_heap_reserve_count); + if (use_global_reserve) { + // If huge pages, make sure only one thread maps more memory to avoid bloat + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (_memory_global_reserve_count >= span_count) { + size_t reserve_count = (!heap->spans_reserved ? _memory_heap_reserve_count : span_count); + if (_memory_global_reserve_count < reserve_count) + reserve_count = _memory_global_reserve_count; + span = _rpmalloc_global_get_reserved_spans(reserve_count); + if (span) { + if (reserve_count > span_count) { + span_t* reserved_span = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + _rpmalloc_heap_set_reserved_spans(heap, _memory_global_reserve_master, reserved_span, reserve_count - span_count); + } + // Already marked as subspan in _rpmalloc_global_get_reserved_spans + span->span_count = (uint32_t)span_count; + } + } + } + if (!span) + span = _rpmalloc_span_map_aligned_count(heap, span_count); + if (use_global_reserve) + atomic_store32_release(&_memory_global_lock, 0); + return span; +} + +//! Unmap memory pages for the given number of spans (or mark as unused if no partial unmappings) +static void +_rpmalloc_span_unmap(span_t* span) { + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + + int is_master = !!(span->flags & SPAN_FLAG_MASTER); + span_t* master = is_master ? span : ((span_t*)pointer_offset(span, -(intptr_t)((uintptr_t)span->offset_from_master * _memory_span_size))); + rpmalloc_assert(is_master || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + + size_t span_count = span->span_count; + if (!is_master) { + //Directly unmap subspans (unless huge pages, in which case we defer and unmap entire page range with master) + rpmalloc_assert(span->align_offset == 0, "Span align offset corrupted"); + if (_memory_span_size >= _memory_page_size) + _rpmalloc_unmap(span, span_count * _memory_span_size, 0, 0); + } else { + //Special double flag to denote an unmapped master + //It must be kept in memory since span header must be used + span->flags |= SPAN_FLAG_MASTER | SPAN_FLAG_SUBSPAN | SPAN_FLAG_UNMAPPED_MASTER; + _rpmalloc_stat_add(&_unmapped_master_spans, 1); + } + + if (atomic_add32(&master->remaining_spans, -(int32_t)span_count) <= 0) { + //Everything unmapped, unmap the master span with release flag to unmap the entire range of the super span + rpmalloc_assert(!!(master->flags & SPAN_FLAG_MASTER) && !!(master->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + size_t unmap_count = master->span_count; + if (_memory_span_size < _memory_page_size) + unmap_count = master->total_spans; + _rpmalloc_stat_sub(&_master_spans, 1); + _rpmalloc_stat_sub(&_unmapped_master_spans, 1); + _rpmalloc_unmap(master, unmap_count * _memory_span_size, master->align_offset, (size_t)master->total_spans * _memory_span_size); + } +} + +//! Move the span (used for small or medium allocations) to the heap thread cache +static void +_rpmalloc_span_release_to_cache(heap_t* heap, span_t* span) { + rpmalloc_assert(heap == span->heap, "Span heap pointer corrupted"); + rpmalloc_assert(span->size_class < SIZE_CLASS_COUNT, "Invalid span size class"); + rpmalloc_assert(span->span_count == 1, "Invalid span count"); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + atomic_decr32(&heap->span_use[0].current); +#endif + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (!heap->finalize) { + _rpmalloc_stat_inc(&heap->span_use[0].spans_to_cache); + _rpmalloc_stat_inc(&heap->size_class_use[span->size_class].spans_to_cache); + if (heap->size_class[span->size_class].cache) + _rpmalloc_heap_cache_insert(heap, heap->size_class[span->size_class].cache); + heap->size_class[span->size_class].cache = span; + } else { + _rpmalloc_span_unmap(span); + } +} + +//! Initialize a (partial) free list up to next system memory page, while reserving the first block +//! as allocated, returning number of blocks in list +static uint32_t +free_list_partial_init(void** list, void** first_block, void* page_start, void* block_start, uint32_t block_count, uint32_t block_size) { + rpmalloc_assert(block_count, "Internal failure"); + *first_block = block_start; + if (block_count > 1) { + void* free_block = pointer_offset(block_start, block_size); + void* block_end = pointer_offset(block_start, (size_t)block_size * block_count); + //If block size is less than half a memory page, bound init to next memory page boundary + if (block_size < (_memory_page_size >> 1)) { + void* page_end = pointer_offset(page_start, _memory_page_size); + if (page_end < block_end) + block_end = page_end; + } + *list = free_block; + block_count = 2; + void* next_block = pointer_offset(free_block, block_size); + while (next_block < block_end) { + *((void**)free_block) = next_block; + free_block = next_block; + ++block_count; + next_block = pointer_offset(next_block, block_size); + } + *((void**)free_block) = 0; + } else { + *list = 0; + } + return block_count; +} + +//! Initialize an unused span (from cache or mapped) to be new active span, putting the initial free list in heap class free list +static void* +_rpmalloc_span_initialize_new(heap_t* heap, heap_size_class_t* heap_size_class, span_t* span, uint32_t class_idx) { + rpmalloc_assert(span->span_count == 1, "Internal failure"); + size_class_t* size_class = _memory_size_class + class_idx; + span->size_class = class_idx; + span->heap = heap; + span->flags &= ~SPAN_FLAG_ALIGNED_BLOCKS; + span->block_size = size_class->block_size; + span->block_count = size_class->block_count; + span->free_list = 0; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); + + //Setup free list. Only initialize one system page worth of free blocks in list + void* block; + span->free_list_limit = free_list_partial_init(&heap_size_class->free_list, &block, + span, pointer_offset(span, SPAN_HEADER_SIZE), size_class->block_count, size_class->block_size); + //Link span as partial if there remains blocks to be initialized as free list, or full if fully initialized + if (span->free_list_limit < span->block_count) { + _rpmalloc_span_double_link_list_add(&heap_size_class->partial_span, span); + span->used_count = span->free_list_limit; + } else { +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + span->used_count = span->block_count; + } + return block; +} + +static void +_rpmalloc_span_extract_free_list_deferred(span_t* span) { + // We need acquire semantics on the CAS operation since we are interested in the list size + // Refer to _rpmalloc_deallocate_defer_small_or_medium for further comments on this dependency + do { + span->free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (span->free_list == INVALID_POINTER); + span->used_count -= span->list_size; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); +} + +static int +_rpmalloc_span_is_fully_utilized(span_t* span) { + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span free list corrupted"); + return !span->free_list && (span->free_list_limit >= span->block_count); +} + +static int +_rpmalloc_span_finalize(heap_t* heap, size_t iclass, span_t* span, span_t** list_head) { + void* free_list = heap->size_class[iclass].free_list; + span_t* class_span = (span_t*)((uintptr_t)free_list & _memory_span_mask); + if (span == class_span) { + // Adopt the heap class free list back into the span free list + void* block = span->free_list; + void* last_block = 0; + while (block) { + last_block = block; + block = *((void**)block); + } + uint32_t free_count = 0; + block = free_list; + while (block) { + ++free_count; + block = *((void**)block); + } + if (last_block) { + *((void**)last_block) = free_list; + } else { + span->free_list = free_list; + } + heap->size_class[iclass].free_list = 0; + span->used_count -= free_count; + } + //If this assert triggers you have memory leaks + rpmalloc_assert(span->list_size == span->used_count, "Memory leak detected"); + if (span->list_size == span->used_count) { + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[iclass].spans_current); + // This function only used for spans in double linked lists + if (list_head) + _rpmalloc_span_double_link_list_remove(list_head, span); + _rpmalloc_span_unmap(span); + return 1; + } + return 0; +} + + +//////////// +/// +/// Global cache +/// +////// + +#if ENABLE_GLOBAL_CACHE + +//! Finalize a global cache +static void +_rpmalloc_global_cache_finalize(global_cache_t* cache) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + for (size_t ispan = 0; ispan < cache->count; ++ispan) + _rpmalloc_span_unmap(cache->span[ispan]); + cache->count = 0; + + while (cache->overflow) { + span_t* span = cache->overflow; + cache->overflow = span->next; + _rpmalloc_span_unmap(span); + } + + atomic_store32_release(&cache->lock, 0); +} + +static void +_rpmalloc_global_cache_insert_spans(span_t** span, size_t span_count, size_t count) { + const size_t cache_limit = (span_count == 1) ? + GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE : + GLOBAL_CACHE_MULTIPLIER * (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t insert_count = count; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->insert_count += count; +#endif + if ((cache->count + insert_count) > cache_limit) + insert_count = cache_limit - cache->count; + + memcpy(cache->span + cache->count, span, sizeof(span_t*) * insert_count); + cache->count += (uint32_t)insert_count; + +#if ENABLE_UNLIMITED_CACHE + while (insert_count < count) { +#else + // Enable unlimited cache if huge pages, or we will leak since it is unlikely that an entire huge page + // will be unmapped, and we're unable to partially decommit a huge page + while ((_memory_page_size > _memory_span_size) && (insert_count < count)) { +#endif + span_t* current_span = span[insert_count++]; + current_span->next = cache->overflow; + cache->overflow = current_span; + } + atomic_store32_release(&cache->lock, 0); + + span_t* keep = 0; + for (size_t ispan = insert_count; ispan < count; ++ispan) { + span_t* current_span = span[ispan]; + // Keep master spans that has remaining subspans to avoid dangling them + if ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) > (int32_t)current_span->span_count)) { + current_span->next = keep; + keep = current_span; + } else { + _rpmalloc_span_unmap(current_span); + } + } + + if (keep) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + size_t islot = 0; + while (keep) { + for (; islot < cache->count; ++islot) { + span_t* current_span = cache->span[islot]; + if (!(current_span->flags & SPAN_FLAG_MASTER) || ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) <= (int32_t)current_span->span_count))) { + _rpmalloc_span_unmap(current_span); + cache->span[islot] = keep; + break; + } + } + if (islot == cache->count) + break; + keep = keep->next; + } + + if (keep) { + span_t* tail = keep; + while (tail->next) + tail = tail->next; + tail->next = cache->overflow; + cache->overflow = keep; + } + + atomic_store32_release(&cache->lock, 0); + } +} + +static size_t +_rpmalloc_global_cache_extract_spans(span_t** span, size_t span_count, size_t count) { + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t extract_count = 0; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->extract_count += count; +#endif + size_t want = count - extract_count; + if (want > cache->count) + want = cache->count; + + memcpy(span + extract_count, cache->span + (cache->count - want), sizeof(span_t*) * want); + cache->count -= (uint32_t)want; + extract_count += want; + + while ((extract_count < count) && cache->overflow) { + span_t* current_span = cache->overflow; + span[extract_count++] = current_span; + cache->overflow = current_span->next; + } + +#if ENABLE_ASSERTS + for (size_t ispan = 0; ispan < extract_count; ++ispan) { + rpmalloc_assert(span[ispan]->span_count == span_count, "Global cache span count mismatch"); + } +#endif + + atomic_store32_release(&cache->lock, 0); + + return extract_count; +} + +#endif + +//////////// +/// +/// Heap control +/// +////// + +static void _rpmalloc_deallocate_huge(span_t*); + +//! Store the given spans as reserve in the given heap +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count) { + heap->span_reserve_master = master; + heap->span_reserve = reserve; + heap->spans_reserved = (uint32_t)reserve_span_count; +} + +//! Adopt the deferred span cache list, optionally extracting the first single span for immediate re-use +static void +_rpmalloc_heap_cache_adopt_deferred(heap_t* heap, span_t** single_span) { + span_t* span = (span_t*)((void*)atomic_exchange_ptr_acquire(&heap->span_free_deferred, 0)); + while (span) { + span_t* next_span = (span_t*)span->free_list; + rpmalloc_assert(span->heap == heap, "Span heap pointer corrupted"); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; + _rpmalloc_stat_dec(&heap->span_use[0].spans_deferred); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } else { + if (span->size_class == SIZE_CLASS_HUGE) { + _rpmalloc_deallocate_huge(span); + } else { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Span size class invalid"); + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->large_huge_span, span); +#endif + uint32_t idx = span->span_count - 1; + _rpmalloc_stat_dec(&heap->span_use[idx].spans_deferred); + _rpmalloc_stat_dec(&heap->span_use[idx].current); + if (!idx && single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } + } + span = next_span; + } +} + +static void +_rpmalloc_heap_unmap(heap_t* heap) { + if (!heap->master_heap) { + if ((heap->finalize > 1) && !atomic_load32(&heap->child_count)) { + span_t* span = (span_t*)((uintptr_t)heap & _memory_span_mask); + _rpmalloc_span_unmap(span); + } + } else { + if (atomic_decr32(&heap->master_heap->child_count) == 0) { + _rpmalloc_heap_unmap(heap->master_heap); + } + } +} + +static void +_rpmalloc_heap_global_finalize(heap_t* heap) { + if (heap->finalize++ > 1) { + --heap->finalize; + return; + } + + _rpmalloc_heap_finalize(heap); + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + + if (heap->full_span_count) { + --heap->finalize; + return; + } + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].free_list || heap->size_class[iclass].partial_span) { + --heap->finalize; + return; + } + } + //Heap is now completely free, unmap and remove from heap list + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap_t* list_heap = _memory_heaps[list_idx]; + if (list_heap == heap) { + _memory_heaps[list_idx] = heap->next_heap; + } else { + while (list_heap->next_heap != heap) + list_heap = list_heap->next_heap; + list_heap->next_heap = heap->next_heap; + } + + _rpmalloc_heap_unmap(heap); +} + +//! Insert a single span into thread heap cache, releasing to global cache if overflow +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span) { + if (UNEXPECTED(heap->finalize != 0)) { + _rpmalloc_span_unmap(span); + _rpmalloc_heap_global_finalize(heap); + return; + } +#if ENABLE_THREAD_CACHE + size_t span_count = span->span_count; + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_to_cache); + if (span_count == 1) { + span_cache_t* span_cache = &heap->span_cache; + span_cache->span[span_cache->count++] = span; + if (span_cache->count == MAX_THREAD_SPAN_CACHE) { + const size_t remain_count = MAX_THREAD_SPAN_CACHE - THREAD_SPAN_CACHE_TRANSFER; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, THREAD_SPAN_CACHE_TRANSFER * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, THREAD_SPAN_CACHE_TRANSFER); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, THREAD_SPAN_CACHE_TRANSFER); +#else + for (size_t ispan = 0; ispan < THREAD_SPAN_CACHE_TRANSFER; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } else { + size_t cache_idx = span_count - 2; + span_large_cache_t* span_cache = heap->span_large_cache + cache_idx; + span_cache->span[span_cache->count++] = span; + const size_t cache_limit = (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + if (span_cache->count == cache_limit) { + const size_t transfer_limit = 2 + (cache_limit >> 2); + const size_t transfer_count = (THREAD_SPAN_LARGE_CACHE_TRANSFER <= transfer_limit ? THREAD_SPAN_LARGE_CACHE_TRANSFER : transfer_limit); + const size_t remain_count = cache_limit - transfer_count; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, transfer_count * span_count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, transfer_count); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, transfer_count); +#else + for (size_t ispan = 0; ispan < transfer_count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } +#else + (void)sizeof(heap); + _rpmalloc_span_unmap(span); +#endif +} + +//! Extract the given number of spans from the different cache levels +static span_t* +_rpmalloc_heap_thread_cache_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + if (span_count == 1) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + if (span_cache->count) { + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_cache); + return span_cache->span[--span_cache->count]; + } +#endif + return span; +} + +static span_t* +_rpmalloc_heap_thread_cache_deferred_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; + if (span_count == 1) { + _rpmalloc_heap_cache_adopt_deferred(heap, &span); + } else { + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + } + return span; +} + +static span_t* +_rpmalloc_heap_reserved_extract(heap_t* heap, size_t span_count) { + if (heap->spans_reserved >= span_count) + return _rpmalloc_span_map(heap, span_count); + return 0; +} + +//! Extract a span from the global cache +static span_t* +_rpmalloc_heap_global_cache_extract(heap_t* heap, size_t span_count) { +#if ENABLE_GLOBAL_CACHE +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + size_t wanted_count; + if (span_count == 1) { + span_cache = &heap->span_cache; + wanted_count = THREAD_SPAN_CACHE_TRANSFER; + } else { + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + wanted_count = THREAD_SPAN_LARGE_CACHE_TRANSFER; + } + span_cache->count = _rpmalloc_global_cache_extract_spans(span_cache->span, span_count, wanted_count); + if (span_cache->count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * span_cache->count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, span_cache->count); + return span_cache->span[--span_cache->count]; + } +#else + span_t* span = 0; + size_t count = _rpmalloc_global_cache_extract_spans(&span, span_count, 1); + if (count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, count); + return span; + } +#endif +#endif + (void)sizeof(heap); + (void)sizeof(span_count); + return 0; +} + +static void +_rpmalloc_inc_span_statistics(heap_t* heap, size_t span_count, uint32_t class_idx) { + (void)sizeof(heap); + (void)sizeof(span_count); + (void)sizeof(class_idx); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + uint32_t idx = (uint32_t)span_count - 1; + uint32_t current_count = (uint32_t)atomic_incr32(&heap->span_use[idx].current); + if (current_count > (uint32_t)atomic_load32(&heap->span_use[idx].high)) + atomic_store32(&heap->span_use[idx].high, (int32_t)current_count); + _rpmalloc_stat_add_peak(&heap->size_class_use[class_idx].spans_current, 1, heap->size_class_use[class_idx].spans_peak); +#endif +} + +//! Get a span from one of the cache levels (thread cache, reserved, global cache) or fallback to mapping more memory +static span_t* +_rpmalloc_heap_extract_new_span(heap_t* heap, heap_size_class_t* heap_size_class, size_t span_count, uint32_t class_idx) { + span_t* span; +#if ENABLE_THREAD_CACHE + if (heap_size_class && heap_size_class->cache) { + span = heap_size_class->cache; + heap_size_class->cache = (heap->span_cache.count ? heap->span_cache.span[--heap->span_cache.count] : 0); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } +#endif + (void)sizeof(class_idx); + // Allow 50% overhead to increase cache hits + size_t base_span_count = span_count; + size_t limit_span_count = (span_count > 2) ? (span_count + (span_count >> 1)) : span_count; + if (limit_span_count > LARGE_CLASS_COUNT) + limit_span_count = LARGE_CLASS_COUNT; + do { + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_thread_cache_deferred_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_reserved_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_reserved); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_global_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + ++span_count; + } while (span_count <= limit_span_count); + //Final fallback, map in more virtual memory + span = _rpmalloc_span_map(heap, base_span_count); + _rpmalloc_inc_span_statistics(heap, base_span_count, class_idx); + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_map_calls); + return span; +} + +static void +_rpmalloc_heap_initialize(heap_t* heap) { + _rpmalloc_memset_const(heap, 0, sizeof(heap_t)); + //Get a new heap ID + heap->id = 1 + atomic_incr32(&_memory_heap_id); + + //Link in heap in heap ID map + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap->next_heap = _memory_heaps[list_idx]; + _memory_heaps[list_idx] = heap; +} + +static void +_rpmalloc_heap_orphan(heap_t* heap, int first_class) { + heap->owner_thread = (uintptr_t)-1; +#if RPMALLOC_FIRST_CLASS_HEAPS + heap_t** heap_list = (first_class ? &_memory_first_class_orphan_heaps : &_memory_orphan_heaps); +#else + (void)sizeof(first_class); + heap_t** heap_list = &_memory_orphan_heaps; +#endif + heap->next_orphan = *heap_list; + *heap_list = heap; +} + +//! Allocate a new heap from newly mapped memory pages +static heap_t* +_rpmalloc_heap_allocate_new(void) { + // Map in pages for a 16 heaps. If page size is greater than required size for this, map a page and + // use first part for heaps and remaining part for spans for allocations. Adds a lot of complexity, + // but saves a lot of memory on systems where page size > 64 spans (4MiB) + size_t heap_size = sizeof(heap_t); + size_t aligned_heap_size = 16 * ((heap_size + 15) / 16); + size_t request_heap_count = 16; + size_t heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + size_t block_size = _memory_span_size * heap_span_count; + size_t span_count = heap_span_count; + span_t* span = 0; + // If there are global reserved spans, use these first + if (_memory_global_reserve_count >= heap_span_count) { + span = _rpmalloc_global_get_reserved_spans(heap_span_count); + } + if (!span) { + if (_memory_page_size > block_size) { + span_count = _memory_page_size / _memory_span_size; + block_size = _memory_page_size; + // If using huge pages, make sure to grab enough heaps to avoid reallocating a huge page just to serve new heaps + size_t possible_heap_count = (block_size - sizeof(span_t)) / aligned_heap_size; + if (possible_heap_count >= (request_heap_count * 16)) + request_heap_count *= 16; + else if (possible_heap_count < request_heap_count) + request_heap_count = possible_heap_count; + heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + } + + size_t align_offset = 0; + span = (span_t*)_rpmalloc_mmap(block_size, &align_offset); + if (!span) + return 0; + + // Master span will contain the heaps + _rpmalloc_stat_inc(&_master_spans); + _rpmalloc_span_initialize(span, span_count, heap_span_count, align_offset); + } + + size_t remain_size = _memory_span_size - sizeof(span_t); + heap_t* heap = (heap_t*)pointer_offset(span, sizeof(span_t)); + _rpmalloc_heap_initialize(heap); + + // Put extra heaps as orphans + size_t num_heaps = remain_size / aligned_heap_size; + if (num_heaps < request_heap_count) + num_heaps = request_heap_count; + atomic_store32(&heap->child_count, (int32_t)num_heaps - 1); + heap_t* extra_heap = (heap_t*)pointer_offset(heap, aligned_heap_size); + while (num_heaps > 1) { + _rpmalloc_heap_initialize(extra_heap); + extra_heap->master_heap = heap; + _rpmalloc_heap_orphan(extra_heap, 1); + extra_heap = (heap_t*)pointer_offset(extra_heap, aligned_heap_size); + --num_heaps; + } + + if (span_count > heap_span_count) { + // Cap reserved spans + size_t remain_count = span_count - heap_span_count; + size_t reserve_count = (remain_count > _memory_heap_reserve_count ? _memory_heap_reserve_count : remain_count); + span_t* remain_span = (span_t*)pointer_offset(span, heap_span_count * _memory_span_size); + _rpmalloc_heap_set_reserved_spans(heap, span, remain_span, reserve_count); + + if (remain_count > reserve_count) { + // Set to global reserved spans + remain_span = (span_t*)pointer_offset(remain_span, reserve_count * _memory_span_size); + reserve_count = remain_count - reserve_count; + _rpmalloc_global_set_reserved_spans(span, remain_span, reserve_count); + } + } + + return heap; +} + +static heap_t* +_rpmalloc_heap_extract_orphan(heap_t** heap_list) { + heap_t* heap = *heap_list; + *heap_list = (heap ? heap->next_orphan : 0); + return heap; +} + +//! Allocate a new heap, potentially reusing a previously orphaned heap +static heap_t* +_rpmalloc_heap_allocate(int first_class) { + heap_t* heap = 0; + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (first_class == 0) + heap = _rpmalloc_heap_extract_orphan(&_memory_orphan_heaps); +#if RPMALLOC_FIRST_CLASS_HEAPS + if (!heap) + heap = _rpmalloc_heap_extract_orphan(&_memory_first_class_orphan_heaps); +#endif + if (!heap) + heap = _rpmalloc_heap_allocate_new(); + atomic_store32_release(&_memory_global_lock, 0); + if (heap) + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + return heap; +} + +static void +_rpmalloc_heap_release(void* heapptr, int first_class, int release_cache) { + heap_t* heap = (heap_t*)heapptr; + if (!heap) + return; + //Release thread cache spans back to global cache + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + if (release_cache || heap->finalize) { +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + if (heap->finalize) { + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + } else { + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); + } +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + } + + if (get_thread_heap_raw() == heap) + set_thread_heap(0); + +#if ENABLE_STATISTICS + atomic_decr32(&_memory_active_heaps); + rpmalloc_assert(atomic_load32(&_memory_active_heaps) >= 0, "Still active heaps during finalization"); +#endif + + // If we are forcibly terminating with _exit the state of the + // lock atomic is unknown and it's best to just go ahead and exit + if (get_thread_id() != _rpmalloc_main_thread_id) { + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + } + _rpmalloc_heap_orphan(heap, first_class); + atomic_store32_release(&_memory_global_lock, 0); +} + +static void +_rpmalloc_heap_release_raw(void* heapptr, int release_cache) { + _rpmalloc_heap_release(heapptr, 0, release_cache); +} + +static void +_rpmalloc_heap_release_raw_fc(void* heapptr) { + _rpmalloc_heap_release_raw(heapptr, 1); +} + +static void +_rpmalloc_heap_finalize(heap_t* heap) { + if (heap->spans_reserved) { + span_t* span = _rpmalloc_span_map(heap, heap->spans_reserved); + _rpmalloc_span_unmap(span); + heap->spans_reserved = 0; + } + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].cache) + _rpmalloc_span_unmap(heap->size_class[iclass].cache); + heap->size_class[iclass].cache = 0; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + span_t* next = span->next; + _rpmalloc_span_finalize(heap, iclass, span, &heap->size_class[iclass].partial_span); + span = next; + } + // If class still has a free list it must be a full span + if (heap->size_class[iclass].free_list) { + span_t* class_span = (span_t*)((uintptr_t)heap->size_class[iclass].free_list & _memory_span_mask); + span_t** list = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + list = &heap->full_span[iclass]; +#endif + --heap->full_span_count; + if (!_rpmalloc_span_finalize(heap, iclass, class_span, list)) { + if (list) + _rpmalloc_span_double_link_list_remove(list, class_span); + _rpmalloc_span_double_link_list_add(&heap->size_class[iclass].partial_span, class_span); + } + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + rpmalloc_assert(!atomic_load_ptr(&heap->span_free_deferred), "Heaps still active during finalization"); +} + + +//////////// +/// +/// Allocation entry points +/// +////// + +//! Pop first block from a free list +static void* +free_list_pop(void** list) { + void* block = *list; + *list = *((void**)block); + return block; +} + +//! Allocate a small/medium sized memory block from the given heap +static void* +_rpmalloc_allocate_from_heap_fallback(heap_t* heap, heap_size_class_t* heap_size_class, uint32_t class_idx) { + span_t* span = heap_size_class->partial_span; + rpmalloc_assume(heap != 0); + if (EXPECTED(span != 0)) { + rpmalloc_assert(span->block_count == _memory_size_class[span->size_class].block_count, "Span block count corrupted"); + rpmalloc_assert(!_rpmalloc_span_is_fully_utilized(span), "Internal failure"); + void* block; + if (span->free_list) { + //Span local free list is not empty, swap to size class free list + block = free_list_pop(&span->free_list); + heap_size_class->free_list = span->free_list; + span->free_list = 0; + } else { + //If the span did not fully initialize free list, link up another page worth of blocks + void* block_start = pointer_offset(span, SPAN_HEADER_SIZE + ((size_t)span->free_list_limit * span->block_size)); + span->free_list_limit += free_list_partial_init(&heap_size_class->free_list, &block, + (void*)((uintptr_t)block_start & ~(_memory_page_size - 1)), block_start, + span->block_count - span->free_list_limit, span->block_size); + } + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span block count corrupted"); + span->used_count = span->free_list_limit; + + //Swap in deferred free list if present + if (atomic_load_ptr(&span->free_list_deferred)) + _rpmalloc_span_extract_free_list_deferred(span); + + //If span is still not fully utilized keep it in partial list and early return block + if (!_rpmalloc_span_is_fully_utilized(span)) + return block; + + //The span is fully utilized, unlink from partial list and add to fully utilized list + _rpmalloc_span_double_link_list_pop_head(&heap_size_class->partial_span, span); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + return block; + } + + //Find a span in one of the cache levels + span = _rpmalloc_heap_extract_new_span(heap, heap_size_class, 1, class_idx); + if (EXPECTED(span != 0)) { + //Mark span as owned by this heap and set base data, return first block + return _rpmalloc_span_initialize_new(heap, heap_size_class, span, class_idx); + } + + return 0; +} + +//! Allocate a small sized memory block from the given heap +static void* +_rpmalloc_allocate_small(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Small sizes have unique size classes + const uint32_t class_idx = (uint32_t)((size + (SMALL_GRANULARITY - 1)) >> SMALL_GRANULARITY_SHIFT); + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a medium sized memory block from the given heap +static void* +_rpmalloc_allocate_medium(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate the size class index and do a dependent lookup of the final class index (in case of merged classes) + const uint32_t base_idx = (uint32_t)(SMALL_CLASS_COUNT + ((size - (SMALL_SIZE_LIMIT + 1)) >> MEDIUM_GRANULARITY_SHIFT)); + const uint32_t class_idx = _memory_size_class[base_idx].class_idx; + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a large sized memory block from the given heap +static void* +_rpmalloc_allocate_large(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate number of needed max sized spans (including header) + //Since this function is never called if size > LARGE_SIZE_LIMIT + //the span_count is guaranteed to be <= LARGE_CLASS_COUNT + size += SPAN_HEADER_SIZE; + size_t span_count = size >> _memory_span_size_shift; + if (size & (_memory_span_size - 1)) + ++span_count; + + //Find a span in one of the cache levels + span_t* span = _rpmalloc_heap_extract_new_span(heap, 0, span_count, SIZE_CLASS_LARGE); + if (!span) + return span; + + //Mark span as owned by this heap and set base data + rpmalloc_assert(span->span_count >= span_count, "Internal failure"); + span->size_class = SIZE_CLASS_LARGE; + span->heap = heap; + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a huge block by mapping memory pages directly +static void* +_rpmalloc_allocate_huge(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + size += SPAN_HEADER_SIZE; + size_t num_pages = size >> _memory_page_size_shift; + if (size & (_memory_page_size - 1)) + ++num_pages; + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(num_pages * _memory_page_size, &align_offset); + if (!span) + return span; + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a block of the given size +static void* +_rpmalloc_allocate(heap_t* heap, size_t size) { + _rpmalloc_stat_add64(&_allocation_counter, 1); + if (EXPECTED(size <= SMALL_SIZE_LIMIT)) + return _rpmalloc_allocate_small(heap, size); + else if (size <= _memory_medium_size_limit) + return _rpmalloc_allocate_medium(heap, size); + else if (size <= LARGE_SIZE_LIMIT) + return _rpmalloc_allocate_large(heap, size); + return _rpmalloc_allocate_huge(heap, size); +} + +static void* +_rpmalloc_aligned_allocate(heap_t* heap, size_t alignment, size_t size) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_allocate(heap, size); + +#if ENABLE_VALIDATE_ARGS + if ((size + alignment) < size) { + errno = EINVAL; + return 0; + } + if (alignment & (alignment - 1)) { + errno = EINVAL; + return 0; + } +#endif + + if ((alignment <= SPAN_HEADER_SIZE) && ((size + SPAN_HEADER_SIZE) < _memory_medium_size_limit)) { + // If alignment is less or equal to span header size (which is power of two), + // and size aligned to span header size multiples is less than size + alignment, + // then use natural alignment of blocks to provide alignment + size_t multiple_size = size ? (size + (SPAN_HEADER_SIZE - 1)) & ~(uintptr_t)(SPAN_HEADER_SIZE - 1) : SPAN_HEADER_SIZE; + rpmalloc_assert(!(multiple_size % SPAN_HEADER_SIZE), "Failed alignment calculation"); + if (multiple_size <= (size + alignment)) + return _rpmalloc_allocate(heap, multiple_size); + } + + void* ptr = 0; + size_t align_mask = alignment - 1; + if (alignment <= _memory_page_size) { + ptr = _rpmalloc_allocate(heap, size + alignment); + if ((uintptr_t)ptr & align_mask) { + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + //Mark as having aligned blocks + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + span->flags |= SPAN_FLAG_ALIGNED_BLOCKS; + } + return ptr; + } + + // Fallback to mapping new pages for this request. Since pointers passed + // to rpfree must be able to reach the start of the span by bitmasking of + // the address with the span size, the returned aligned pointer from this + // function must be with a span size of the start of the mapped area. + // In worst case this requires us to loop and map pages until we get a + // suitable memory address. It also means we can never align to span size + // or greater, since the span header will push alignment more than one + // span size away from span start (thus causing pointer mask to give us + // an invalid span start on free) + if (alignment & align_mask) { + errno = EINVAL; + return 0; + } + if (alignment >= _memory_span_size) { + errno = EINVAL; + return 0; + } + + size_t extra_pages = alignment / _memory_page_size; + + // Since each span has a header, we will at least need one extra memory page + size_t num_pages = 1 + (size / _memory_page_size); + if (size & (_memory_page_size - 1)) + ++num_pages; + + if (extra_pages > num_pages) + num_pages = 1 + extra_pages; + + size_t original_pages = num_pages; + size_t limit_pages = (_memory_span_size / _memory_page_size) * 2; + if (limit_pages < (original_pages * 2)) + limit_pages = original_pages * 2; + + size_t mapped_size, align_offset; + span_t* span; + +retry: + align_offset = 0; + mapped_size = num_pages * _memory_page_size; + + span = (span_t*)_rpmalloc_mmap(mapped_size, &align_offset); + if (!span) { + errno = ENOMEM; + return 0; + } + ptr = pointer_offset(span, SPAN_HEADER_SIZE); + + if ((uintptr_t)ptr & align_mask) + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + + if (((size_t)pointer_diff(ptr, span) >= _memory_span_size) || + (pointer_offset(ptr, size) > pointer_offset(span, mapped_size)) || + (((uintptr_t)ptr & _memory_span_mask) != (uintptr_t)span)) { + _rpmalloc_unmap(span, mapped_size, align_offset, mapped_size); + ++num_pages; + if (num_pages > limit_pages) { + errno = EINVAL; + return 0; + } + goto retry; + } + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + _rpmalloc_stat_add64(&_allocation_counter, 1); + + return ptr; +} + + +//////////// +/// +/// Deallocation entry points +/// +////// + +//! Deallocate the given small/medium memory block in the current thread local heap +static void +_rpmalloc_deallocate_direct_small_or_medium(span_t* span, void* block) { + heap_t* heap = span->heap; + rpmalloc_assert(heap->owner_thread == get_thread_id() || !heap->owner_thread || heap->finalize, "Internal failure"); + //Add block to free list + if (UNEXPECTED(_rpmalloc_span_is_fully_utilized(span))) { + span->used_count = span->block_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_span_double_link_list_add(&heap->size_class[span->size_class].partial_span, span); + --heap->full_span_count; + } + *((void**)block) = span->free_list; + --span->used_count; + span->free_list = block; + if (UNEXPECTED(span->used_count == span->list_size)) { + // If there are no used blocks it is guaranteed that no other external thread is accessing the span + if (span->used_count) { + // Make sure we have synchronized the deferred list and list size by using acquire semantics + // and guarantee that no external thread is accessing span concurrently + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + atomic_store_ptr_release(&span->free_list_deferred, free_list); + } + _rpmalloc_span_double_link_list_remove(&heap->size_class[span->size_class].partial_span, span); + _rpmalloc_span_release_to_cache(heap, span); + } +} + +static void +_rpmalloc_deallocate_defer_free_span(heap_t* heap, span_t* span) { + if (span->size_class != SIZE_CLASS_HUGE) + _rpmalloc_stat_inc(&heap->span_use[span->span_count - 1].spans_deferred); + //This list does not need ABA protection, no mutable side state + do { + span->free_list = (void*)atomic_load_ptr(&heap->span_free_deferred); + } while (!atomic_cas_ptr(&heap->span_free_deferred, span, span->free_list)); +} + +//! Put the block in the deferred free list of the owning span +static void +_rpmalloc_deallocate_defer_small_or_medium(span_t* span, void* block) { + // The memory ordering here is a bit tricky, to avoid having to ABA protect + // the deferred free list to avoid desynchronization of list and list size + // we need to have acquire semantics on successful CAS of the pointer to + // guarantee the list_size variable validity + release semantics on pointer store + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + *((void**)block) = free_list; + uint32_t free_count = ++span->list_size; + int all_deferred_free = (free_count == span->block_count); + atomic_store_ptr_release(&span->free_list_deferred, block); + if (all_deferred_free) { + // Span was completely freed by this block. Due to the INVALID_POINTER spin lock + // no other thread can reach this state simultaneously on this span. + // Safe to move to owner heap deferred cache + _rpmalloc_deallocate_defer_free_span(span->heap, span); + } +} + +static void +_rpmalloc_deallocate_small_or_medium(span_t* span, void* p) { + _rpmalloc_stat_inc_free(span->heap, span->size_class); + if (span->flags & SPAN_FLAG_ALIGNED_BLOCKS) { + //Realign pointer to block start + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + p = pointer_offset(p, -(int32_t)(block_offset % span->block_size)); + } + //Check if block belongs to this heap or if deallocation should be deferred +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (!defer) + _rpmalloc_deallocate_direct_small_or_medium(span, p); + else + _rpmalloc_deallocate_defer_small_or_medium(span, p); +} + +//! Deallocate the given large memory block to the current heap +static void +_rpmalloc_deallocate_large(span_t* span) { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Bad span size class"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + //We must always defer (unless finalizing) if from another heap since we cannot touch the list or counters of another heap +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //Decrease counter + size_t idx = span->span_count - 1; + atomic_decr32(&span->heap->span_use[idx].current); +#endif + heap_t* heap = span->heap; + rpmalloc_assert(heap, "No thread heap"); +#if ENABLE_THREAD_CACHE + const int set_as_reserved = ((span->span_count > 1) && (heap->span_cache.count == 0) && !heap->finalize && !heap->spans_reserved); +#else + const int set_as_reserved = ((span->span_count > 1) && !heap->finalize && !heap->spans_reserved); +#endif + if (set_as_reserved) { + heap->span_reserve = span; + heap->spans_reserved = span->span_count; + if (span->flags & SPAN_FLAG_MASTER) { + heap->span_reserve_master = span; + } else { //SPAN_FLAG_SUBSPAN + span_t* master = (span_t*)pointer_offset(span, -(intptr_t)((size_t)span->offset_from_master * _memory_span_size)); + heap->span_reserve_master = master; + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + rpmalloc_assert(atomic_load32(&master->remaining_spans) >= (int32_t)span->span_count, "Master span count corrupted"); + } + _rpmalloc_stat_inc(&heap->span_use[idx].spans_to_reserved); + } else { + //Insert into cache list + _rpmalloc_heap_cache_insert(heap, span); + } +} + +//! Deallocate the given huge span +static void +_rpmalloc_deallocate_huge(span_t* span) { + rpmalloc_assert(span->heap, "No span heap"); +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif + + //Oversized allocation, page count is stored in span_count + size_t num_pages = span->span_count; + _rpmalloc_unmap(span, num_pages * _memory_page_size, span->align_offset, num_pages * _memory_page_size); + _rpmalloc_stat_sub(&_huge_pages_current, num_pages); +} + +//! Deallocate the given block +static void +_rpmalloc_deallocate(void* p) { + _rpmalloc_stat_add64(&_deallocation_counter, 1); + //Grab the span (always at start of span, using span alignment) + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (UNEXPECTED(!span)) + return; + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) + _rpmalloc_deallocate_small_or_medium(span, p); + else if (span->size_class == SIZE_CLASS_LARGE) + _rpmalloc_deallocate_large(span); + else + _rpmalloc_deallocate_huge(span); +} + +//////////// +/// +/// Reallocation entry points +/// +////// + +static size_t +_rpmalloc_usable_size(void* p); + +//! Reallocate the given block to the given size +static void* +_rpmalloc_reallocate(heap_t* heap, void* p, size_t size, size_t oldsize, unsigned int flags) { + if (p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + //Small/medium sized block + rpmalloc_assert(span->span_count == 1, "Span counter corrupted"); + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + uint32_t block_idx = block_offset / span->block_size; + void* block = pointer_offset(blocks_start, (size_t)block_idx * span->block_size); + if (!oldsize) + oldsize = (size_t)((ptrdiff_t)span->block_size - pointer_diff(p, block)); + if ((size_t)span->block_size >= size) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_spans = total_size >> _memory_span_size_shift; + if (total_size & (_memory_span_mask - 1)) + ++num_spans; + size_t current_spans = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_spans * _memory_span_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_spans >= num_spans) && (total_size >= (oldsize / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else { + //Oversized block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_pages = total_size >> _memory_page_size_shift; + if (total_size & (_memory_page_size - 1)) + ++num_pages; + //Page count is stored in span_count + size_t current_pages = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_pages * _memory_page_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_pages >= num_pages) && (num_pages >= (current_pages / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } + } else { + oldsize = 0; + } + + if (!!(flags & RPMALLOC_GROW_OR_FAIL)) + return 0; + + //Size is greater than block size, need to allocate a new block and deallocate the old + //Avoid hysteresis by overallocating if increase is small (below 37%) + size_t lower_bound = oldsize + (oldsize >> 2) + (oldsize >> 3); + size_t new_size = (size > lower_bound) ? size : ((size > oldsize) ? lower_bound : size); + void* block = _rpmalloc_allocate(heap, new_size); + if (p && block) { + if (!(flags & RPMALLOC_NO_PRESERVE)) + memcpy(block, p, oldsize < new_size ? oldsize : new_size); + _rpmalloc_deallocate(p); + } + + return block; +} + +static void* +_rpmalloc_aligned_reallocate(heap_t* heap, void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_reallocate(heap, ptr, size, oldsize, flags); + + int no_alloc = !!(flags & RPMALLOC_GROW_OR_FAIL); + size_t usablesize = (ptr ? _rpmalloc_usable_size(ptr) : 0); + if ((usablesize >= size) && !((uintptr_t)ptr & (alignment - 1))) { + if (no_alloc || (size >= (usablesize / 2))) + return ptr; + } + // Aligned alloc marks span as having aligned blocks + void* block = (!no_alloc ? _rpmalloc_aligned_allocate(heap, alignment, size) : 0); + if (EXPECTED(block != 0)) { + if (!(flags & RPMALLOC_NO_PRESERVE) && ptr) { + if (!oldsize) + oldsize = usablesize; + memcpy(block, ptr, oldsize < size ? oldsize : size); + } + _rpmalloc_deallocate(ptr); + } + return block; +} + + +//////////// +/// +/// Initialization, finalization and utility +/// +////// + +//! Get the usable size of the given block +static size_t +_rpmalloc_usable_size(void* p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (span->size_class < SIZE_CLASS_COUNT) { + //Small/medium block + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + return span->block_size - ((size_t)pointer_diff(p, blocks_start) % span->block_size); + } + if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t current_spans = span->span_count; + return (current_spans * _memory_span_size) - (size_t)pointer_diff(p, span); + } + //Oversized block, page count is stored in span_count + size_t current_pages = span->span_count; + return (current_pages * _memory_page_size) - (size_t)pointer_diff(p, span); +} + +//! Adjust and optimize the size class properties for the given class +static void +_rpmalloc_adjust_size_class(size_t iclass) { + size_t block_size = _memory_size_class[iclass].block_size; + size_t block_count = (_memory_span_size - SPAN_HEADER_SIZE) / block_size; + + _memory_size_class[iclass].block_count = (uint16_t)block_count; + _memory_size_class[iclass].class_idx = (uint16_t)iclass; + + //Check if previous size classes can be merged + if (iclass >= SMALL_CLASS_COUNT) { + size_t prevclass = iclass; + while (prevclass > 0) { + --prevclass; + //A class can be merged if number of pages and number of blocks are equal + if (_memory_size_class[prevclass].block_count == _memory_size_class[iclass].block_count) + _rpmalloc_memcpy_const(_memory_size_class + prevclass, _memory_size_class + iclass, sizeof(_memory_size_class[iclass])); + else + break; + } + } +} + +//! Initialize the allocator and setup global data +extern inline int +rpmalloc_initialize(void) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + return rpmalloc_initialize_config(0); +} + +int +rpmalloc_initialize_config(const rpmalloc_config_t* config) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + _rpmalloc_initialized = 1; + + if (config) + memcpy(&_memory_config, config, sizeof(rpmalloc_config_t)); + else + _rpmalloc_memset_const(&_memory_config, 0, sizeof(rpmalloc_config_t)); + + if (!_memory_config.memory_map || !_memory_config.memory_unmap) { + _memory_config.memory_map = _rpmalloc_mmap_os; + _memory_config.memory_unmap = _rpmalloc_unmap_os; + } + +#if PLATFORM_WINDOWS + SYSTEM_INFO system_info; + memset(&system_info, 0, sizeof(system_info)); + GetSystemInfo(&system_info); + _memory_map_granularity = system_info.dwAllocationGranularity; +#else + _memory_map_granularity = (size_t)sysconf(_SC_PAGESIZE); +#endif + +#if RPMALLOC_CONFIGURABLE + _memory_page_size = _memory_config.page_size; +#else + _memory_page_size = 0; +#endif + _memory_huge_pages = 0; + if (!_memory_page_size) { +#if PLATFORM_WINDOWS + _memory_page_size = system_info.dwPageSize; +#else + _memory_page_size = _memory_map_granularity; + if (_memory_config.enable_huge_pages) { +#if defined(__linux__) + size_t huge_page_size = 0; + FILE* meminfo = fopen("/proc/meminfo", "r"); + if (meminfo) { + char line[128]; + while (!huge_page_size && fgets(line, sizeof(line) - 1, meminfo)) { + line[sizeof(line) - 1] = 0; + if (strstr(line, "Hugepagesize:")) + huge_page_size = (size_t)strtol(line + 13, 0, 10) * 1024; + } + fclose(meminfo); + } + if (huge_page_size) { + _memory_huge_pages = 1; + _memory_page_size = huge_page_size; + _memory_map_granularity = huge_page_size; + } +#elif defined(__FreeBSD__) + int rc; + size_t sz = sizeof(rc); + + if (sysctlbyname("vm.pmap.pg_ps_enabled", &rc, &sz, NULL, 0) == 0 && rc == 1) { + static size_t defsize = 2 * 1024 * 1024; + int nsize = 0; + size_t sizes[4] = {0}; + _memory_huge_pages = 1; + _memory_page_size = defsize; + if ((nsize = getpagesizes(sizes, 4)) >= 2) { + nsize --; + for (size_t csize = sizes[nsize]; nsize >= 0 && csize; --nsize, csize = sizes[nsize]) { + //! Unlikely, but as a precaution.. + rpmalloc_assert(!(csize & (csize -1)) && !(csize % 1024), "Invalid page size"); + if (defsize < csize) { + _memory_page_size = csize; + break; + } + } + } + _memory_map_granularity = _memory_page_size; + } +#elif defined(__APPLE__) || defined(__NetBSD__) + _memory_huge_pages = 1; + _memory_page_size = 2 * 1024 * 1024; + _memory_map_granularity = _memory_page_size; +#endif + } +#endif + } else { + if (_memory_config.enable_huge_pages) + _memory_huge_pages = 1; + } + +#if PLATFORM_WINDOWS + if (_memory_config.enable_huge_pages) { + HANDLE token = 0; + size_t large_page_minimum = GetLargePageMinimum(); + if (large_page_minimum) + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (token) { + LUID luid; + if (LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) { + TOKEN_PRIVILEGES token_privileges; + memset(&token_privileges, 0, sizeof(token_privileges)); + token_privileges.PrivilegeCount = 1; + token_privileges.Privileges[0].Luid = luid; + token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(token, FALSE, &token_privileges, 0, 0, 0)) { + if (GetLastError() == ERROR_SUCCESS) + _memory_huge_pages = 1; + } + } + CloseHandle(token); + } + if (_memory_huge_pages) { + if (large_page_minimum > _memory_page_size) + _memory_page_size = large_page_minimum; + if (large_page_minimum > _memory_map_granularity) + _memory_map_granularity = large_page_minimum; + } + } +#endif + + size_t min_span_size = 256; + size_t max_page_size; +#if UINTPTR_MAX > 0xFFFFFFFF + max_page_size = 4096ULL * 1024ULL * 1024ULL; +#else + max_page_size = 4 * 1024 * 1024; +#endif + if (_memory_page_size < min_span_size) + _memory_page_size = min_span_size; + if (_memory_page_size > max_page_size) + _memory_page_size = max_page_size; + _memory_page_size_shift = 0; + size_t page_size_bit = _memory_page_size; + while (page_size_bit != 1) { + ++_memory_page_size_shift; + page_size_bit >>= 1; + } + _memory_page_size = ((size_t)1 << _memory_page_size_shift); + +#if RPMALLOC_CONFIGURABLE + if (!_memory_config.span_size) { + _memory_span_size = _memory_default_span_size; + _memory_span_size_shift = _memory_default_span_size_shift; + _memory_span_mask = _memory_default_span_mask; + } else { + size_t span_size = _memory_config.span_size; + if (span_size > (256 * 1024)) + span_size = (256 * 1024); + _memory_span_size = 4096; + _memory_span_size_shift = 12; + while (_memory_span_size < span_size) { + _memory_span_size <<= 1; + ++_memory_span_size_shift; + } + _memory_span_mask = ~(uintptr_t)(_memory_span_size - 1); + } +#endif + + _memory_span_map_count = ( _memory_config.span_map_count ? _memory_config.span_map_count : DEFAULT_SPAN_MAP_COUNT); + if ((_memory_span_size * _memory_span_map_count) < _memory_page_size) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + if ((_memory_page_size >= _memory_span_size) && ((_memory_span_map_count * _memory_span_size) % _memory_page_size)) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + _memory_heap_reserve_count = (_memory_span_map_count > DEFAULT_SPAN_MAP_COUNT) ? DEFAULT_SPAN_MAP_COUNT : _memory_span_map_count; + + _memory_config.page_size = _memory_page_size; + _memory_config.span_size = _memory_span_size; + _memory_config.span_map_count = _memory_span_map_count; + _memory_config.enable_huge_pages = _memory_huge_pages; + +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + if (pthread_key_create(&_memory_thread_heap, _rpmalloc_heap_release_raw_fc)) + return -1; +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + fls_key = FlsAlloc(&_rpmalloc_thread_destructor); +#endif + + //Setup all small and medium size classes + size_t iclass = 0; + _memory_size_class[iclass].block_size = SMALL_GRANULARITY; + _rpmalloc_adjust_size_class(iclass); + for (iclass = 1; iclass < SMALL_CLASS_COUNT; ++iclass) { + size_t size = iclass * SMALL_GRANULARITY; + _memory_size_class[iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(iclass); + } + //At least two blocks per span, then fall back to large allocations + _memory_medium_size_limit = (_memory_span_size - SPAN_HEADER_SIZE) >> 1; + if (_memory_medium_size_limit > MEDIUM_SIZE_LIMIT) + _memory_medium_size_limit = MEDIUM_SIZE_LIMIT; + for (iclass = 0; iclass < MEDIUM_CLASS_COUNT; ++iclass) { + size_t size = SMALL_SIZE_LIMIT + ((iclass + 1) * MEDIUM_GRANULARITY); + if (size > _memory_medium_size_limit) { + _memory_medium_size_limit = SMALL_SIZE_LIMIT + (iclass * MEDIUM_GRANULARITY); + break; + } + _memory_size_class[SMALL_CLASS_COUNT + iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(SMALL_CLASS_COUNT + iclass); + } + + _memory_orphan_heaps = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + _memory_first_class_orphan_heaps = 0; +#endif +#if ENABLE_STATISTICS + atomic_store32(&_memory_active_heaps, 0); + atomic_store32(&_mapped_pages, 0); + _mapped_pages_peak = 0; + atomic_store32(&_master_spans, 0); + atomic_store32(&_mapped_total, 0); + atomic_store32(&_unmapped_total, 0); + atomic_store32(&_mapped_pages_os, 0); + atomic_store32(&_huge_pages_current, 0); + _huge_pages_peak = 0; +#endif + memset(_memory_heaps, 0, sizeof(_memory_heaps)); + atomic_store32_release(&_memory_global_lock, 0); + + rpmalloc_linker_reference(); + + //Initialize this thread + rpmalloc_thread_initialize(); + return 0; +} + +//! Finalize the allocator +void +rpmalloc_finalize(void) { + rpmalloc_thread_finalize(1); + //rpmalloc_dump_statistics(stdout); + + if (_memory_global_reserve) { + atomic_add32(&_memory_global_reserve_master->remaining_spans, -(int32_t)_memory_global_reserve_count); + _memory_global_reserve_master = 0; + _memory_global_reserve_count = 0; + _memory_global_reserve = 0; + } + atomic_store32_release(&_memory_global_lock, 0); + + //Free all thread caches and fully free spans + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + heap_t* next_heap = heap->next_heap; + heap->finalize = 1; + _rpmalloc_heap_global_finalize(heap); + heap = next_heap; + } + } + +#if ENABLE_GLOBAL_CACHE + //Free global caches + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) + _rpmalloc_global_cache_finalize(&_memory_span_cache[iclass]); +#endif + +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + pthread_key_delete(_memory_thread_heap); +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsFree(fls_key); + fls_key = 0; +#endif +#if ENABLE_STATISTICS + //If you hit these asserts you probably have memory leaks (perhaps global scope data doing dynamic allocations) or double frees in your code + rpmalloc_assert(atomic_load32(&_mapped_pages) == 0, "Memory leak detected"); + rpmalloc_assert(atomic_load32(&_mapped_pages_os) == 0, "Memory leak detected"); +#endif + + _rpmalloc_initialized = 0; +} + +//! Initialize thread, assign heap +extern inline void +rpmalloc_thread_initialize(void) { + if (!get_thread_heap_raw()) { + heap_t* heap = _rpmalloc_heap_allocate(0); + if (heap) { + _rpmalloc_stat_inc(&_memory_active_heaps); + set_thread_heap(heap); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, heap); +#endif + } + } +} + +//! Finalize thread, orphan heap +void +rpmalloc_thread_finalize(int release_caches) { + heap_t* heap = get_thread_heap_raw(); + if (heap) + _rpmalloc_heap_release_raw(heap, release_caches); + set_thread_heap(0); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, 0); +#endif +} + +int +rpmalloc_is_thread_initialized(void) { + return (get_thread_heap_raw() != 0) ? 1 : 0; +} + +const rpmalloc_config_t* +rpmalloc_config(void) { + return &_memory_config; +} + +// Extern interface + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_allocate(heap, size); +} + +extern inline void +rpfree(void* ptr) { + _rpmalloc_deallocate(ptr); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + heap_t* heap = get_thread_heap(); + void* block = _rpmalloc_allocate(heap, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_reallocate(heap, ptr, size, 0, 0); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, oldsize, flags); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) { + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = rpaligned_alloc(alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) { + return rpaligned_alloc(alignment, size); +} + +extern inline int +rpposix_memalign(void **memptr, size_t alignment, size_t size) { + if (memptr) + *memptr = rpaligned_alloc(alignment, size); + else + return EINVAL; + return *memptr ? 0 : ENOMEM; +} + +extern inline size_t +rpmalloc_usable_size(void* ptr) { + return (ptr ? _rpmalloc_usable_size(ptr) : 0); +} + +extern inline void +rpmalloc_thread_collect(void) { +} + +void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_thread_statistics_t)); + heap_t* heap = get_thread_heap_raw(); + if (!heap) + return; + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + size_class_t* size_class = _memory_size_class + iclass; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + size_t free_count = span->list_size; + size_t block_count = size_class->block_count; + if (span->free_list_limit < block_count) + block_count = span->free_list_limit; + free_count += (block_count - span->used_count); + stats->sizecache += free_count * size_class->block_size; + span = span->next; + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + stats->spancache += span_cache->count * (iclass + 1) * _memory_span_size; + } +#endif + + span_t* deferred = (span_t*)atomic_load_ptr(&heap->span_free_deferred); + while (deferred) { + if (deferred->size_class != SIZE_CLASS_HUGE) + stats->spancache += (size_t)deferred->span_count * _memory_span_size; + deferred = (span_t*)deferred->free_list; + } + +#if ENABLE_STATISTICS + stats->thread_to_global = (size_t)atomic_load64(&heap->thread_to_global); + stats->global_to_thread = (size_t)atomic_load64(&heap->global_to_thread); + + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + stats->span_use[iclass].current = (size_t)atomic_load32(&heap->span_use[iclass].current); + stats->span_use[iclass].peak = (size_t)atomic_load32(&heap->span_use[iclass].high); + stats->span_use[iclass].to_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_global); + stats->span_use[iclass].from_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_global); + stats->span_use[iclass].to_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache); + stats->span_use[iclass].from_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache); + stats->span_use[iclass].to_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved); + stats->span_use[iclass].from_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved); + stats->span_use[iclass].map_calls = (size_t)atomic_load32(&heap->span_use[iclass].spans_map_calls); + } + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + stats->size_use[iclass].alloc_current = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_current); + stats->size_use[iclass].alloc_peak = (size_t)heap->size_class_use[iclass].alloc_peak; + stats->size_use[iclass].alloc_total = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_total); + stats->size_use[iclass].free_total = (size_t)atomic_load32(&heap->size_class_use[iclass].free_total); + stats->size_use[iclass].spans_to_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache); + stats->size_use[iclass].spans_from_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache); + stats->size_use[iclass].spans_from_reserved = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved); + stats->size_use[iclass].map_calls = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_map_calls); + } +#endif +} + +void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_global_statistics_t)); +#if ENABLE_STATISTICS + stats->mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + stats->mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + stats->mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + stats->unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + stats->huge_alloc = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + stats->huge_alloc_peak = (size_t)_huge_pages_peak * _memory_page_size; +#endif +#if ENABLE_GLOBAL_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = &_memory_span_cache[iclass]; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + uint32_t count = cache->count; +#if ENABLE_UNLIMITED_CACHE + span_t* current_span = cache->overflow; + while (current_span) { + ++count; + current_span = current_span->next; + } +#endif + atomic_store32_release(&cache->lock, 0); + stats->cached += count * (iclass + 1) * _memory_span_size; + } +#endif +} + +#if ENABLE_STATISTICS + +static void +_memory_heap_dump_statistics(heap_t* heap, void* file) { + fprintf(file, "Heap %d stats:\n", heap->id); + fprintf(file, "Class CurAlloc PeakAlloc TotAlloc TotFree BlkSize BlkCount SpansCur SpansPeak PeakAllocMiB ToCacheMiB FromCacheMiB FromReserveMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) + continue; + fprintf(file, "%3u: %10u %10u %10u %10u %8u %8u %8d %9d %13zu %11zu %12zu %14zu %9u\n", (uint32_t)iclass, + atomic_load32(&heap->size_class_use[iclass].alloc_current), + heap->size_class_use[iclass].alloc_peak, + atomic_load32(&heap->size_class_use[iclass].alloc_total), + atomic_load32(&heap->size_class_use[iclass].free_total), + _memory_size_class[iclass].block_size, + _memory_size_class[iclass].block_count, + atomic_load32(&heap->size_class_use[iclass].spans_current), + heap->size_class_use[iclass].spans_peak, + ((size_t)heap->size_class_use[iclass].alloc_peak * (size_t)_memory_size_class[iclass].block_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved) * _memory_span_size) / (size_t)(1024 * 1024), + atomic_load32(&heap->size_class_use[iclass].spans_map_calls)); + } + fprintf(file, "Spans Current Peak Deferred PeakMiB Cached ToCacheMiB FromCacheMiB ToReserveMiB FromReserveMiB ToGlobalMiB FromGlobalMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + fprintf(file, "%4u: %8d %8u %8u %8zu %7u %11zu %12zu %12zu %14zu %11zu %13zu %10u\n", (uint32_t)(iclass + 1), + atomic_load32(&heap->span_use[iclass].current), + atomic_load32(&heap->span_use[iclass].high), + atomic_load32(&heap->span_use[iclass].spans_deferred), + ((size_t)atomic_load32(&heap->span_use[iclass].high) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), +#if ENABLE_THREAD_CACHE + (unsigned int)(!iclass ? heap->span_cache.count : heap->span_large_cache[iclass - 1].count), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), +#else + 0, (size_t)0, (size_t)0, +#endif + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + atomic_load32(&heap->span_use[iclass].spans_map_calls)); + } + fprintf(file, "Full spans: %zu\n", heap->full_span_count); + fprintf(file, "ThreadToGlobalMiB GlobalToThreadMiB\n"); + fprintf(file, "%17zu %17zu\n", (size_t)atomic_load64(&heap->thread_to_global) / (size_t)(1024 * 1024), (size_t)atomic_load64(&heap->global_to_thread) / (size_t)(1024 * 1024)); +} + +#endif + +void +rpmalloc_dump_statistics(void* file) { +#if ENABLE_STATISTICS + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + int need_dump = 0; + for (size_t iclass = 0; !need_dump && (iclass < SIZE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) { + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].free_total), "Heap statistics counter mismatch"); + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].spans_map_calls), "Heap statistics counter mismatch"); + continue; + } + need_dump = 1; + } + for (size_t iclass = 0; !need_dump && (iclass < LARGE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + need_dump = 1; + } + if (need_dump) + _memory_heap_dump_statistics(heap, file); + heap = heap->next_heap; + } + } + fprintf(file, "Global stats:\n"); + size_t huge_current = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + size_t huge_peak = (size_t)_huge_pages_peak * _memory_page_size; + fprintf(file, "HugeCurrentMiB HugePeakMiB\n"); + fprintf(file, "%14zu %11zu\n", huge_current / (size_t)(1024 * 1024), huge_peak / (size_t)(1024 * 1024)); + +#if ENABLE_GLOBAL_CACHE + fprintf(file, "GlobalCacheMiB\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = _memory_span_cache + iclass; + size_t global_cache = (size_t)cache->count * iclass * _memory_span_size; + + size_t global_overflow_cache = 0; + span_t* span = cache->overflow; + while (span) { + global_overflow_cache += iclass * _memory_span_size; + span = span->next; + } + if (global_cache || global_overflow_cache || cache->insert_count || cache->extract_count) + fprintf(file, "%4zu: %8zuMiB (%8zuMiB overflow) %14zu insert %14zu extract\n", iclass + 1, global_cache / (size_t)(1024 * 1024), global_overflow_cache / (size_t)(1024 * 1024), cache->insert_count, cache->extract_count); + } +#endif + + size_t mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + size_t mapped_os = (size_t)atomic_load32(&_mapped_pages_os) * _memory_page_size; + size_t mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + size_t mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + size_t unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + fprintf(file, "MappedMiB MappedOSMiB MappedPeakMiB MappedTotalMiB UnmappedTotalMiB\n"); + fprintf(file, "%9zu %11zu %13zu %14zu %16zu\n", + mapped / (size_t)(1024 * 1024), + mapped_os / (size_t)(1024 * 1024), + mapped_peak / (size_t)(1024 * 1024), + mapped_total / (size_t)(1024 * 1024), + unmapped_total / (size_t)(1024 * 1024)); + + fprintf(file, "\n"); +#if 0 + int64_t allocated = atomic_load64(&_allocation_counter); + int64_t deallocated = atomic_load64(&_deallocation_counter); + fprintf(file, "Allocation count: %lli\n", allocated); + fprintf(file, "Deallocation count: %lli\n", deallocated); + fprintf(file, "Current allocations: %lli\n", (allocated - deallocated)); + fprintf(file, "Master spans: %d\n", atomic_load32(&_master_spans)); + fprintf(file, "Dangling master spans: %d\n", atomic_load32(&_unmapped_master_spans)); +#endif +#endif + (void)sizeof(file); +} + +#if RPMALLOC_FIRST_CLASS_HEAPS + +extern inline rpmalloc_heap_t* +rpmalloc_heap_acquire(void) { + // Must be a pristine heap from newly mapped memory pages, or else memory blocks + // could already be allocated from the heap which would (wrongly) be released when + // heap is cleared with rpmalloc_heap_free_all(). Also heaps guaranteed to be + // pristine from the dedicated orphan list can be used. + heap_t* heap = _rpmalloc_heap_allocate(1); + rpmalloc_assume(heap != NULL); + heap->owner_thread = 0; + _rpmalloc_stat_inc(&_memory_active_heaps); + return heap; +} + +extern inline void +rpmalloc_heap_release(rpmalloc_heap_t* heap) { + if (heap) + _rpmalloc_heap_release(heap, 1, 1); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_allocate(heap, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) { + return rpmalloc_heap_aligned_calloc(heap, 0, num, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = _rpmalloc_aligned_allocate(heap, alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + return _rpmalloc_reallocate(heap, ptr, size, 0, flags); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, 0, flags); +} + +extern inline void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr) { + (void)sizeof(heap); + _rpmalloc_deallocate(ptr); +} + +extern inline void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap) { + span_t* span; + span_t* next_span; + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + span = heap->size_class[iclass].partial_span; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->size_class[iclass].partial_span = 0; + span = heap->full_span[iclass]; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + } + memset(heap->size_class, 0, sizeof(heap->size_class)); + memset(heap->full_span, 0, sizeof(heap->full_span)); + + span = heap->large_huge_span; + while (span) { + next_span = span->next; + if (UNEXPECTED(span->size_class == SIZE_CLASS_HUGE)) + _rpmalloc_deallocate_huge(span); + else + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->large_huge_span = 0; + heap->full_span_count = 0; + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + +#if ENABLE_STATISTICS + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->size_class_use[iclass].alloc_current, 0); + atomic_store32(&heap->size_class_use[iclass].spans_current, 0); + } + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->span_use[iclass].current, 0); + } +#endif +} + +extern inline void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap) { + heap_t* prev_heap = get_thread_heap_raw(); + if (prev_heap != heap) { + set_thread_heap(heap); + if (prev_heap) + rpmalloc_heap_release(prev_heap); + } +} + +extern inline rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr) +{ + //Grab the span, and then the heap from the span + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + if (span) + { + return span->heap; + } + return 0; +} + +#endif + +#if ENABLE_PRELOAD || ENABLE_OVERRIDE + +#include "malloc.c" + +#endif + +void +rpmalloc_linker_reference(void) { + (void)sizeof(_rpmalloc_initialized); +} diff --git a/engine/split/3rd_rpmalloc.h b/engine/split/3rd_rpmalloc.h new file mode 100644 index 0000000..db5be48 --- /dev/null +++ b/engine/split/3rd_rpmalloc.h @@ -0,0 +1,373 @@ +/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__clang__) || defined(__GNUC__) +# define RPMALLOC_EXPORT __attribute__((visibility("default"))) +# define RPMALLOC_ALLOCATOR +# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) +# else +# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__)) +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size))) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size))) +# endif +# define RPMALLOC_CDECL +#elif defined(_MSC_VER) +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL __cdecl +#else +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL +#endif + +//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce +// a very small overhead due to some size calculations not being compile time constants +#ifndef RPMALLOC_CONFIGURABLE +#define RPMALLOC_CONFIGURABLE 0 +#endif + +//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions). +// Will introduce a very small overhead to track fully allocated spans in heaps +#ifndef RPMALLOC_FIRST_CLASS_HEAPS +#define RPMALLOC_FIRST_CLASS_HEAPS 0 +#endif + +//! Flag to rpaligned_realloc to not preserve content in reallocation +#define RPMALLOC_NO_PRESERVE 1 +//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place, +// in which case the original pointer is still valid (just like a call to realloc which failes to allocate +// a new block). +#define RPMALLOC_GROW_OR_FAIL 2 + +typedef struct rpmalloc_global_statistics_t { + //! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped; + //! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped_peak; + //! Current amount of memory in global caches for small and medium sizes (<32KiB) + size_t cached; + //! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc; + //! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc_peak; + //! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1) + size_t mapped_total; + //! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1) + size_t unmapped_total; +} rpmalloc_global_statistics_t; + +typedef struct rpmalloc_thread_statistics_t { + //! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB) + size_t sizecache; + //! Current number of bytes available in thread span caches for small and medium sizes (<32KiB) + size_t spancache; + //! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1) + size_t thread_to_global; + //! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1) + size_t global_to_thread; + //! Per span count statistics (only if ENABLE_STATISTICS=1) + struct { + //! Currently used number of spans + size_t current; + //! High water mark of spans used + size_t peak; + //! Number of spans transitioned to global cache + size_t to_global; + //! Number of spans transitioned from global cache + size_t from_global; + //! Number of spans transitioned to thread cache + size_t to_cache; + //! Number of spans transitioned from thread cache + size_t from_cache; + //! Number of spans transitioned to reserved state + size_t to_reserved; + //! Number of spans transitioned from reserved state + size_t from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } span_use[64]; + //! Per size class statistics (only if ENABLE_STATISTICS=1) + struct { + //! Current number of allocations + size_t alloc_current; + //! Peak number of allocations + size_t alloc_peak; + //! Total number of allocations + size_t alloc_total; + //! Total number of frees + size_t free_total; + //! Number of spans transitioned to cache + size_t spans_to_cache; + //! Number of spans transitioned from cache + size_t spans_from_cache; + //! Number of spans transitioned from reserved state + size_t spans_from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } size_use[128]; +} rpmalloc_thread_statistics_t; + +typedef struct rpmalloc_config_t { + //! Map memory pages for the given number of bytes. The returned address MUST be + // aligned to the rpmalloc span size, which will always be a power of two. + // Optionally the function can store an alignment offset in the offset variable + // in case it performs alignment and the returned pointer is offset from the + // actual start of the memory region due to this alignment. The alignment offset + // will be passed to the memory unmap function. The alignment offset MUST NOT be + // larger than 65535 (storable in an uint16_t), if it is you must use natural + // alignment to shift it into 16 bits. If you set a memory_map function, you + // must also set a memory_unmap function or else the default implementation will + // be used for both. This function must be thread safe, it can be called by + // multiple threads simultaneously. + void* (*memory_map)(size_t size, size_t* offset); + //! Unmap the memory pages starting at address and spanning the given number of bytes. + // If release is set to non-zero, the unmap is for an entire span range as returned by + // a previous call to memory_map and that the entire range should be released. The + // release argument holds the size of the entire span range. If release is set to 0, + // the unmap is a partial decommit of a subset of the mapped memory range. + // If you set a memory_unmap function, you must also set a memory_map function or + // else the default implementation will be used for both. This function must be thread + // safe, it can be called by multiple threads simultaneously. + void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release); + //! Called when an assert fails, if asserts are enabled. Will use the standard assert() + // if this is not set. + void (*error_callback)(const char* message); + //! Called when a call to map memory pages fails (out of memory). If this callback is + // not set or returns zero the library will return a null pointer in the allocation + // call. If this callback returns non-zero the map call will be retried. The argument + // passed is the number of bytes that was requested in the map call. Only used if + // the default system memory map function is used (memory_map callback is not set). + int (*map_fail_callback)(size_t size); + //! Size of memory pages. The page size MUST be a power of two. All memory mapping + // requests to memory_map will be made with size set to a multiple of the page size. + // Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used. + size_t page_size; + //! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144] + // range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE + // is defined to 1. + size_t span_size; + //! Number of spans to map at each request to map new virtual memory blocks. This can + // be used to minimize the system call overhead at the cost of virtual memory address + // space. The extra mapped pages will not be written until actually used, so physical + // committed memory should not be affected in the default implementation. Will be + // aligned to a multiple of spans that match memory page size in case of huge pages. + size_t span_map_count; + //! Enable use of large/huge pages. If this flag is set to non-zero and page size is + // zero, the allocator will try to enable huge pages and auto detect the configuration. + // If this is set to non-zero and page_size is also non-zero, the allocator will + // assume huge pages have been configured and enabled prior to initializing the + // allocator. + // For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support + // For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt + int enable_huge_pages; + //! Respectively allocated pages and huge allocated pages names for systems + // supporting it to be able to distinguish among anonymous regions. + const char *page_name; + const char *huge_page_name; +} rpmalloc_config_t; + +//! Initialize allocator with default configuration +RPMALLOC_EXPORT int +rpmalloc_initialize(void); + +//! Initialize allocator with given configuration +RPMALLOC_EXPORT int +rpmalloc_initialize_config(const rpmalloc_config_t* config); + +//! Get allocator configuration +RPMALLOC_EXPORT const rpmalloc_config_t* +rpmalloc_config(void); + +//! Finalize allocator +RPMALLOC_EXPORT void +rpmalloc_finalize(void); + +//! Initialize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_initialize(void); + +//! Finalize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_finalize(int release_caches); + +//! Perform deferred deallocations pending for the calling thread heap +RPMALLOC_EXPORT void +rpmalloc_thread_collect(void); + +//! Query if allocator is initialized for calling thread +RPMALLOC_EXPORT int +rpmalloc_is_thread_initialized(void); + +//! Get per-thread statistics +RPMALLOC_EXPORT void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats); + +//! Get global statistics +RPMALLOC_EXPORT void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats); + +//! Dump all statistics in human readable format to file (should be a FILE*) +RPMALLOC_EXPORT void +rpmalloc_dump_statistics(void* file); + +//! Allocate a memory block of at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1); + +//! Free the given memory block +RPMALLOC_EXPORT void +rpfree(void* ptr); + +//! Allocate a memory block of at least the given size and zero initialize it +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2); + +//! Reallocate the given block to at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Reallocate the given block to at least the given size and alignment, +// with optional control flags (see RPMALLOC_NO_PRESERVE). +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment, and zero initialize it. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT int +rpposix_memalign(void** memptr, size_t alignment, size_t size); + +//! Query the usable size of the given memory block (from given pointer to the end of block) +RPMALLOC_EXPORT size_t +rpmalloc_usable_size(void* ptr); + +//! Dummy empty function for forcing linker symbol inclusion +RPMALLOC_EXPORT void +rpmalloc_linker_reference(void); + +#if RPMALLOC_FIRST_CLASS_HEAPS + +//! Heap type +typedef struct heap_t rpmalloc_heap_t; + +//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap +// if none available. Heap API is implemented with the strict assumption that only one single +// thread will call heap functions for a given heap at any given time, no functions are thread safe. +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_heap_acquire(void); + +//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap). +// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer. +RPMALLOC_EXPORT void +rpmalloc_heap_release(rpmalloc_heap_t* heap); + +//! Allocate a memory block of at least the given size using the given heap. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size using the given heap. The returned +// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned +// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. The returned block will have the requested alignment. +// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be +// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than +// the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4); + +//! Free the given memory block from the given heap. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr); + +//! Free all memory allocated by the heap +RPMALLOC_EXPORT void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap); + +//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap +// for a single thread, a heap can never be shared between multiple threads. The previous +// current heap for the calling thread is released to be reused by other threads. +RPMALLOC_EXPORT void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap); + +//! Returns which heap the given pointer is allocated on +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr); + +#endif + +#ifdef __cplusplus +} +#endif diff --git a/engine/split/3rd_rpmalloci.c b/engine/split/3rd_rpmalloci.c new file mode 100644 index 0000000..8724288 --- /dev/null +++ b/engine/split/3rd_rpmalloci.c @@ -0,0 +1,488 @@ +/* malloc.c - Memory allocator - Public Domain - 2016 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +// +// This file provides overrides for the standard library malloc entry points for C and new/delete operators for C++ +// It also provides automatic initialization/finalization of process and threads +// +#if defined(__TINYC__) +#include +#endif + +#ifndef ARCH_64BIT +# if defined(__LLP64__) || defined(__LP64__) || defined(_WIN64) +# define ARCH_64BIT 1 +typedef struct { int pass_static_assert : sizeof(size_t) == 8; } static_assert_data_type_size_mismatch1; //< @r-lyeh +typedef struct { int pass_static_assert : sizeof(void*) == 8; } static_assert_data_type_size_mismatch2; //< @r-lyeh +# else +# define ARCH_64BIT 0 +typedef struct { int pass_static_assert : sizeof(size_t) == 4; } static_assert_data_type_size_mismatch1; //< @r-lyeh +typedef struct { int pass_static_assert : sizeof(void*) == 4; } static_assert_data_type_size_mismatch2; //< @r-lyeh +# endif +#endif + +#if (defined(__GNUC__) || defined(__clang__)) +#pragma GCC visibility push(default) +#endif + +#define USE_IMPLEMENT 1 +#define USE_INTERPOSE 0 +#define USE_ALIAS 0 + +#if defined(__APPLE__) +#undef USE_INTERPOSE +#define USE_INTERPOSE 1 + +typedef struct interpose_t { + void* new_func; + void* orig_func; +} interpose_t; + +#define MAC_INTERPOSE_PAIR(newf, oldf) { (void*)newf, (void*)oldf } +#define MAC_INTERPOSE_SINGLE(newf, oldf) \ +__attribute__((used)) static const interpose_t macinterpose##newf##oldf \ +__attribute__ ((section("__DATA, __interpose"))) = MAC_INTERPOSE_PAIR(newf, oldf) + +#endif + +#if !defined(_WIN32) && !defined(__APPLE__) +#undef USE_IMPLEMENT +#undef USE_ALIAS +#define USE_IMPLEMENT 0 +#define USE_ALIAS 1 +#endif + +#ifdef _MSC_VER +#pragma warning (disable : 4100) +#undef malloc +#undef free +#undef calloc +#define RPMALLOC_RESTRICT __declspec(restrict) +#else +#define RPMALLOC_RESTRICT +#endif + +#if ENABLE_OVERRIDE + +typedef struct rp_nothrow_t { int __dummy; } rp_nothrow_t; + +#if USE_IMPLEMENT + +extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL malloc(size_t size) { return rpmalloc(size); } +extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL calloc(size_t count, size_t size) { return rpcalloc(count, size); } +extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL realloc(void* ptr, size_t size) { return rprealloc(ptr, size); } +extern inline void* RPMALLOC_CDECL reallocf(void* ptr, size_t size) { return rprealloc(ptr, size); } +extern inline void* RPMALLOC_CDECL aligned_alloc(size_t alignment, size_t size) { return rpaligned_alloc(alignment, size); } +extern inline void* RPMALLOC_CDECL memalign(size_t alignment, size_t size) { return rpmemalign(alignment, size); } +extern inline int RPMALLOC_CDECL posix_memalign(void** memptr, size_t alignment, size_t size) { return rpposix_memalign(memptr, alignment, size); } +extern inline void RPMALLOC_CDECL free(void* ptr) { rpfree(ptr); } +extern inline void RPMALLOC_CDECL cfree(void* ptr) { rpfree(ptr); } +extern inline size_t RPMALLOC_CDECL malloc_usable_size(void* ptr) { return rpmalloc_usable_size(ptr); } +extern inline size_t RPMALLOC_CDECL malloc_size(void* ptr) { return rpmalloc_usable_size(ptr); } + +#ifdef _WIN32 +// For Windows, #include in one source file to get the C++ operator overrides implemented in your module +#else +// Overload the C++ operators using the mangled names (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling) +// operators delete and delete[] +#define RPDEFVIS __attribute__((visibility("default"))) +extern void _ZdlPv(void* p); void RPDEFVIS _ZdlPv(void* p) { rpfree(p); } +extern void _ZdaPv(void* p); void RPDEFVIS _ZdaPv(void* p) { rpfree(p); } +#if ARCH_64BIT +// 64-bit operators new and new[], normal and aligned +extern void* _Znwm(uint64_t size); void* RPDEFVIS _Znwm(uint64_t size) { return rpmalloc(size); } +extern void* _Znam(uint64_t size); void* RPDEFVIS _Znam(uint64_t size) { return rpmalloc(size); } +extern void* _Znwmm(uint64_t size, uint64_t align); void* RPDEFVIS _Znwmm(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } +extern void* _Znamm(uint64_t size, uint64_t align); void* RPDEFVIS _Znamm(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnwmSt11align_val_t(uint64_t size, uint64_t align); void* RPDEFVIS _ZnwmSt11align_val_t(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnamSt11align_val_t(uint64_t size, uint64_t align); void* RPDEFVIS _ZnamSt11align_val_t(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnwmRKSt9nothrow_t(uint64_t size, rp_nothrow_t t); void* RPDEFVIS _ZnwmRKSt9nothrow_t(uint64_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } +extern void* _ZnamRKSt9nothrow_t(uint64_t size, rp_nothrow_t t); void* RPDEFVIS _ZnamRKSt9nothrow_t(uint64_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } +extern void* _ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t); void* RPDEFVIS _ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } +extern void* _ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t); void* RPDEFVIS _ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } +// 64-bit operators sized delete and delete[], normal and aligned +extern void _ZdlPvm(void* p, uint64_t size); void RPDEFVIS _ZdlPvm(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } +extern void _ZdaPvm(void* p, uint64_t size); void RPDEFVIS _ZdaPvm(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } +extern void _ZdlPvSt11align_val_t(void* p, uint64_t align); void RPDEFVIS _ZdlPvSt11align_val_t(void* p, uint64_t align) { rpfree(p); (void)sizeof(align); } +extern void _ZdaPvSt11align_val_t(void* p, uint64_t align); void RPDEFVIS _ZdaPvSt11align_val_t(void* p, uint64_t align) { rpfree(p); (void)sizeof(align); } +extern void _ZdlPvmSt11align_val_t(void* p, uint64_t size, uint64_t align); void RPDEFVIS _ZdlPvmSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(align); } +extern void _ZdaPvmSt11align_val_t(void* p, uint64_t size, uint64_t align); void RPDEFVIS _ZdaPvmSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(align); } +#else +// 32-bit operators new and new[], normal and aligned +extern void* _Znwj(uint32_t size); void* RPDEFVIS _Znwj(uint32_t size) { return rpmalloc(size); } +extern void* _Znaj(uint32_t size); void* RPDEFVIS _Znaj(uint32_t size) { return rpmalloc(size); } +extern void* _Znwjj(uint32_t size, uint32_t align); void* RPDEFVIS _Znwjj(uint32_t size, uint32_t align) { return rpaligned_alloc(align, size); } +extern void* _Znajj(uint32_t size, uint32_t align); void* RPDEFVIS _Znajj(uint32_t size, uint32_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnwjSt11align_val_t(size_t size, size_t align); void* RPDEFVIS _ZnwjSt11align_val_t(size_t size, size_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnajSt11align_val_t(size_t size, size_t align); void* RPDEFVIS _ZnajSt11align_val_t(size_t size, size_t align) { return rpaligned_alloc(align, size); } +extern void* _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t); void* RPDEFVIS _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } +extern void* _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t); void* RPDEFVIS _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } +extern void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t); void* RPDEFVIS _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } +extern void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t); void* RPDEFVIS _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } +// 32-bit operators sized delete and delete[], normal and aligned +extern void _ZdlPvj(void* p, uint64_t size); void RPDEFVIS _ZdlPvj(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } +extern void _ZdaPvj(void* p, uint64_t size); void RPDEFVIS _ZdaPvj(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } +extern void _ZdlPvSt11align_val_t(void* p, uint32_t align); void RPDEFVIS _ZdlPvSt11align_val_t(void* p, uint64_t a) { rpfree(p); (void)sizeof(align); } +extern void _ZdaPvSt11align_val_t(void* p, uint32_t align); void RPDEFVIS _ZdaPvSt11align_val_t(void* p, uint64_t a) { rpfree(p); (void)sizeof(align); } +extern void _ZdlPvjSt11align_val_t(void* p, uint32_t size, uint32_t align); void RPDEFVIS _ZdlPvjSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(a); } +extern void _ZdaPvjSt11align_val_t(void* p, uint32_t size, uint32_t align); void RPDEFVIS _ZdaPvjSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(a); } +#endif +#endif +#endif + +#if USE_INTERPOSE || USE_ALIAS + +static void* rpmalloc_nothrow(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } +static void* rpaligned_alloc_reverse(size_t size, size_t align) { return rpaligned_alloc(align, size); } +static void* rpaligned_alloc_reverse_nothrow(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } +static void rpfree_size(void* p, size_t size) { (void)sizeof(size); rpfree(p); } +static void rpfree_aligned(void* p, size_t align) { (void)sizeof(align); rpfree(p); } +static void rpfree_size_aligned(void* p, size_t size, size_t align) { (void)sizeof(size); (void)sizeof(align); rpfree(p); } + +#endif + +#if USE_INTERPOSE + +__attribute__((used)) static const interpose_t macinterpose_malloc[] +__attribute__ ((section("__DATA, __interpose"))) = { + //new and new[] + MAC_INTERPOSE_PAIR(rpmalloc, _Znwm), + MAC_INTERPOSE_PAIR(rpmalloc, _Znam), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _Znwmm), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _Znamm), + MAC_INTERPOSE_PAIR(rpmalloc_nothrow, _ZnwmRKSt9nothrow_t), + MAC_INTERPOSE_PAIR(rpmalloc_nothrow, _ZnamRKSt9nothrow_t), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _ZnwmSt11align_val_t), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _ZnamSt11align_val_t), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow, _ZnwmSt11align_val_tRKSt9nothrow_t), + MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow, _ZnamSt11align_val_tRKSt9nothrow_t), + //delete and delete[] + MAC_INTERPOSE_PAIR(rpfree, _ZdlPv), + MAC_INTERPOSE_PAIR(rpfree, _ZdaPv), + MAC_INTERPOSE_PAIR(rpfree_size, _ZdlPvm), + MAC_INTERPOSE_PAIR(rpfree_size, _ZdaPvm), + MAC_INTERPOSE_PAIR(rpfree_aligned, _ZdlPvSt11align_val_t), + MAC_INTERPOSE_PAIR(rpfree_aligned, _ZdaPvSt11align_val_t), + MAC_INTERPOSE_PAIR(rpfree_size_aligned, _ZdlPvmSt11align_val_t), + MAC_INTERPOSE_PAIR(rpfree_size_aligned, _ZdaPvmSt11align_val_t), + //libc entry points + MAC_INTERPOSE_PAIR(rpmalloc, malloc), + MAC_INTERPOSE_PAIR(rpmalloc, calloc), + MAC_INTERPOSE_PAIR(rprealloc, realloc), + MAC_INTERPOSE_PAIR(rprealloc, reallocf), +#if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15 + MAC_INTERPOSE_PAIR(rpaligned_alloc, aligned_alloc), +#endif + MAC_INTERPOSE_PAIR(rpmemalign, memalign), + MAC_INTERPOSE_PAIR(rpposix_memalign, posix_memalign), + MAC_INTERPOSE_PAIR(rpfree, free), + MAC_INTERPOSE_PAIR(rpfree, cfree), + MAC_INTERPOSE_PAIR(rpmalloc_usable_size, malloc_usable_size), + MAC_INTERPOSE_PAIR(rpmalloc_usable_size, malloc_size) +}; + +#endif + +#if USE_ALIAS + +#define RPALIAS(fn) __attribute__((alias(#fn), used, visibility("default"))); + +// Alias the C++ operators using the mangled names (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling) + +// operators delete and delete[] +void _ZdlPv(void* p) RPALIAS(rpfree) +void _ZdaPv(void* p) RPALIAS(rpfree) + +#if ARCH_64BIT +// 64-bit operators new and new[], normal and aligned +void* _Znwm(uint64_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* _Znam(uint64_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* _Znwmm(uint64_t size, uint64_t align) RPALIAS(rpaligned_alloc_reverse) +void* _Znamm(uint64_t size, uint64_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnwmSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnamSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnwmRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) +void* _ZnamRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) +void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) +void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) +// 64-bit operators delete and delete[], sized and aligned +void _ZdlPvm(void* p, size_t n) RPALIAS(rpfree_size) +void _ZdaPvm(void* p, size_t n) RPALIAS(rpfree_size) +void _ZdlPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) +void _ZdaPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) +void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) +void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) +#else +// 32-bit operators new and new[], normal and aligned +void* _Znwj(uint32_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* _Znaj(uint32_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* _Znwjj(uint32_t size, uint32_t align) RPALIAS(rpaligned_alloc_reverse) +void* _Znajj(uint32_t size, uint32_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnwjSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnajSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) +void* _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) +void* _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) +void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) +void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) +// 32-bit operators delete and delete[], sized and aligned +void _ZdlPvj(void* p, size_t n) RPALIAS(rpfree_size) +void _ZdaPvj(void* p, size_t n) RPALIAS(rpfree_size) +void _ZdlPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) +void _ZdaPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) +void _ZdlPvjSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) +void _ZdaPvjSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) +#endif + +void* malloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* calloc(size_t count, size_t size) RPALIAS(rpcalloc) +void* realloc(void* ptr, size_t size) RPALIAS(rprealloc) +void* reallocf(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rprealloc) +void* aligned_alloc(size_t alignment, size_t size) RPALIAS(rpaligned_alloc) +void* memalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rpmemalign) +int posix_memalign(void** memptr, size_t alignment, size_t size) RPALIAS(rpposix_memalign) +void free(void* ptr) RPALIAS(rpfree) +void cfree(void* ptr) RPALIAS(rpfree) +#if defined(__ANDROID__) || defined(__FreeBSD__) +size_t malloc_usable_size(const void* ptr) RPALIAS(rpmalloc_usable_size) +#else +size_t malloc_usable_size(void* ptr) RPALIAS(rpmalloc_usable_size) +#endif +size_t malloc_size(void* ptr) RPALIAS(rpmalloc_usable_size) + +#endif + +static inline size_t +_rpmalloc_page_size(void) { + return _memory_page_size; +} + +extern void* RPMALLOC_CDECL +reallocarray(void* ptr, size_t count, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#ifdef _MSC_VER + int err = SizeTMult(count, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(count, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = count * size; +#endif + return realloc(ptr, total); +} + +extern inline void* RPMALLOC_CDECL +valloc(size_t size) { + get_thread_heap(); + return rpaligned_alloc(_rpmalloc_page_size(), size); +} + +extern inline void* RPMALLOC_CDECL +pvalloc(size_t size) { + get_thread_heap(); + const size_t page_size = _rpmalloc_page_size(); + const size_t aligned_size = ((size + page_size - 1) / page_size) * page_size; +#if ENABLE_VALIDATE_ARGS + if (aligned_size < size) { + errno = EINVAL; + return 0; + } +#endif + return rpaligned_alloc(_rpmalloc_page_size(), aligned_size); +} + +#endif // ENABLE_OVERRIDE + +#if ENABLE_PRELOAD + +#ifdef _WIN32 + +#if defined(BUILD_DYNAMIC_LINK) && BUILD_DYNAMIC_LINK + +extern __declspec(dllexport) BOOL WINAPI +DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved); + +extern __declspec(dllexport) BOOL WINAPI +DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { + (void)sizeof(reserved); + (void)sizeof(instance); + if (reason == DLL_PROCESS_ATTACH) + rpmalloc_initialize(); + else if (reason == DLL_PROCESS_DETACH) + rpmalloc_finalize(); + else if (reason == DLL_THREAD_ATTACH) + rpmalloc_thread_initialize(); + else if (reason == DLL_THREAD_DETACH) + rpmalloc_thread_finalize(1); + return TRUE; +} + +//end BUILD_DYNAMIC_LINK +#else + +extern void +_global_rpmalloc_init(void) { + rpmalloc_set_main_thread(); + rpmalloc_initialize(); +} + +#if defined(__clang__) || defined(__GNUC__) + +static void __attribute__((constructor)) +initializer(void) { + _global_rpmalloc_init(); +} + +#elif defined(_MSC_VER) + +#pragma section(".CRT$XIB",read) +__declspec(allocate(".CRT$XIB")) void (*_rpmalloc_module_init)(void) = _global_rpmalloc_init; +#pragma comment(linker, "/include:_rpmalloc_module_init") + +#endif + +//end !BUILD_DYNAMIC_LINK +#endif + +#else + +#include +#include +#include +#include + +extern void +rpmalloc_set_main_thread(void); + +static pthread_key_t destructor_key; + +static void +thread_destructor(void*); + +static void __attribute__((constructor)) +initializer(void) { + rpmalloc_set_main_thread(); + rpmalloc_initialize(); + pthread_key_create(&destructor_key, thread_destructor); +} + +static void __attribute__((destructor)) +finalizer(void) { + rpmalloc_finalize(); +} + +typedef struct { + void* (*real_start)(void*); + void* real_arg; +} thread_starter_arg; + +static void* +thread_starter(void* argptr) { + thread_starter_arg* arg = argptr; + void* (*real_start)(void*) = arg->real_start; + void* real_arg = arg->real_arg; + rpmalloc_thread_initialize(); + rpfree(argptr); + pthread_setspecific(destructor_key, (void*)1); + return (*real_start)(real_arg); +} + +static void +thread_destructor(void* value) { + (void)sizeof(value); + rpmalloc_thread_finalize(1); +} + +#ifdef __APPLE__ + +static int +pthread_create_proxy(pthread_t* thread, + const pthread_attr_t* attr, + void* (*start_routine)(void*), + void* arg) { + rpmalloc_initialize(); + thread_starter_arg* starter_arg = rpmalloc(sizeof(thread_starter_arg)); + starter_arg->real_start = start_routine; + starter_arg->real_arg = arg; + return pthread_create(thread, attr, thread_starter, starter_arg); +} + +MAC_INTERPOSE_SINGLE(pthread_create_proxy, pthread_create); + +#else + +#include + +int +pthread_create(pthread_t* thread, + const pthread_attr_t* attr, + void* (*start_routine)(void*), + void* arg) { +#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__APPLE__) || defined(__HAIKU__) + char fname[] = "pthread_create"; +#else + char fname[] = "_pthread_create"; +#endif + void* real_pthread_create = dlsym(RTLD_NEXT, fname); + rpmalloc_thread_initialize(); + thread_starter_arg* starter_arg = rpmalloc(sizeof(thread_starter_arg)); + starter_arg->real_start = start_routine; + starter_arg->real_arg = arg; + return (*(int (*)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*))real_pthread_create)(thread, attr, thread_starter, starter_arg); +} + +#endif + +#endif + +#endif + +#if ENABLE_OVERRIDE + +#if defined(__GLIBC__) && defined(__linux__) + +void* __libc_malloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) +void* __libc_calloc(size_t count, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2) RPALIAS(rpcalloc) +void* __libc_realloc(void* p, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rprealloc) +void __libc_free(void* p) RPALIAS(rpfree) +void __libc_cfree(void* p) RPALIAS(rpfree) +void* __libc_memalign(size_t align, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rpmemalign) +int __posix_memalign(void** p, size_t align, size_t size) RPALIAS(rpposix_memalign) + +extern void* __libc_valloc(size_t size); +extern void* __libc_pvalloc(size_t size); + +void* +__libc_valloc(size_t size) { + return valloc(size); +} + +void* +__libc_pvalloc(size_t size) { + return pvalloc(size); +} + +#endif + +#endif + +#if (defined(__GNUC__) || defined(__clang__)) +#pragma GCC visibility pop +#endif diff --git a/engine/split/v4k.c.inl b/engine/split/v4k.c.inl index 0b980be..291e241 100644 --- a/engine/split/v4k.c.inl +++ b/engine/split/v4k.c.inl @@ -148,6 +148,8 @@ {{FILE:v4k_scene.c}} +{{FILE:v4k_sprite.c}} + {{FILE:v4k_system.c}} {{FILE:v4k_time.c}} @@ -162,10 +164,17 @@ {{FILE:v4k_ai.c}} -{{FILE:v4k_editor.c}} - -// editor is last in place, so it can use all internals from above headers +{{FILE:v4k_editor0.c}} {{FILE:v4k_main.c}} +// editor is last in place, so it can use all internals from above headers +{{FILE:v4k_editor.c}} +{{FILE:v4k_editor_scene.h}} +{{FILE:v4k_editor_browser.h}} +{{FILE:v4k_editor_timeline.h}} +{{FILE:v4k_editor_console.h}} +{{FILE:v4k_editor_nodes.h}} +{{FILE:v4k_editor_script.h}} + {{FILE:v4k_end.c}} diff --git a/engine/split/v4k.h.inl b/engine/split/v4k.h.inl index 2fb6359..5887804 100644 --- a/engine/split/v4k.h.inl +++ b/engine/split/v4k.h.inl @@ -116,8 +116,6 @@ extern "C" { {{FILE:v4k_extend.h}} -{{FILE:v4k_editor.h}} - {{FILE:v4k_file.h}} {{FILE:v4k_font.h}} @@ -144,6 +142,8 @@ extern "C" { {{FILE:v4k_scene.h}} +{{FILE:v4k_sprite.h}} + {{FILE:v4k_string.h}} {{FILE:v4k_system.h}} @@ -158,6 +158,10 @@ extern "C" { // ---- +{{FILE:v4k_editor.h}} + +// ---- + #if is(cpp) } // extern "C" #endif diff --git a/engine/split/v4k.x.inl b/engine/split/v4k.x.inl index 2516ef4..0e2c85d 100644 --- a/engine/split/v4k.x.inl +++ b/engine/split/v4k.x.inl @@ -184,6 +184,16 @@ static char *ui_filter = 0; {{FILE:3rd_eval.h}} {{FILE:3rd_luadebugger.h}} {{FILE:3rd_base64.h}} + +#if ENABLE_RPMALLOC +{{FILE:3rd_rpmalloc.h}} +{{FILE:3rd_rpmalloc.c}} +//{{FILE: 3rd_rpmalloci.c}} +#define SYS_MEM_INIT() rpmalloc_initialize() +#define SYS_MEM_REALLOC rprealloc +#define SYS_MEM_SIZE rpmalloc_usable_size +#endif + //#define SQLITE_OMIT_LOAD_EXTENSION //#define SQLITE_CORE 1 //#define SQLITE_DEBUG 1 @@ -197,4 +207,13 @@ static char *ui_filter = 0; //#undef rehash //#undef NB //#undef threadid + +// editor +{{FILE:3rd_icon_mdi.h}} +// editor_script +#define GLEQ_IMPLEMENTATION +{{FILE:3rd_lite_sys_gleq.h}} +{{FILE:3rd_lite_sys.h}} +{{FILE:3rd_lite.h}} + #endif // V4K_3RD diff --git a/engine/split/v4k_cook.c b/engine/split/v4k_cook.c index f2dd7e1..db9288f 100644 --- a/engine/split/v4k_cook.c +++ b/engine/split/v4k_cook.c @@ -11,7 +11,7 @@ const char *ART = "art/"; const char *TOOLS = "tools/bin/"; -const char *EDITOR = "tools/editor/"; +const char *EDITOR = "tools/"; const char *COOK_INI = "tools/cook.ini"; static unsigned ART_SKIP_ROOT; // number of chars to skip the base root in ART folder @@ -508,11 +508,14 @@ int cook(void *userdata) { fclose(in); } +// if(array_count(uncooked)) +// PRINTF("cook_jobs[%d]=%d\n", job->threadid, array_count(uncooked)); + // generate cook metrics. you usually do `game.exe --cook-stats && (type *.csv | sort /R > cook.csv)` static __thread FILE *statsfile = 0; if(flag("--cook-stats")) fseek(statsfile = fopen(va("cook%d.csv",job->threadid), "a+t"), 0L, SEEK_END); - if(statsfile && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); + if(statsfile && !job->threadid && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); // added or changed files for( int i = 0, end = array_count(uncooked); i < end && !cook_cancelling; ++i ) { @@ -825,10 +828,8 @@ void cook_stop() { int cook_progress() { int count = 0, sum = 0; for( int i = 0, end = cook_jobs(); i < end; ++i ) { -// if( jobs[i].progress >= 0 ) { sum += jobs[i].progress; ++count; -// } } return cook_jobs() ? sum / (count+!count) : 100; } diff --git a/engine/split/v4k_editor.c b/engine/split/v4k_editor.c index 21e812c..62d80ff 100644 --- a/engine/split/v4k_editor.c +++ b/engine/split/v4k_editor.c @@ -1,679 +1,741 @@ -// editing: -// nope > functions: add/rem property +// ## Editor long-term plan +// - editor = tree of nodes. levels and objects are nodes, and their widgets are also nodes +// - you can perform actions on nodes, with or without descendants, top-bottom or bottom-top +// - these operations include load/save, undo/redo, reset, play/render, ddraw, etc +// - nodes are saved to disk as a filesystem layout: parents are folders, and leafs are files +// - network replication can be done by external tools by comparing the filesystems and by sending the resulting diff zipped +// +// ## Editor roadmap +// - Gizmos?, scene tree, property editor?, load/save?, undo/redo?, copy/paste, on/off (vis,tick,ddraw,log), vcs. +// - Scenenode pass: node singleton display, node console, node labels, node outlines?. +// - Render pass: billboards?, materials, un/lit, cast shadows, wireframe, skybox?/mie?, fog/atmosphere +// - Level pass: volumes, triggers, platforms, level streaming, collide?, physics +// - Edit pass: Procedural content, brushes, noise and CSG. +// - GUI pass: timeline and data tracks, node graphs. -#define ICON_PLAY ICON_MD_PLAY_ARROW -#define ICON_PAUSE ICON_MD_PAUSE -#define ICON_STOP ICON_MD_STOP -#define ICON_CANCEL ICON_MD_CLOSE +// ## Alt plan +// editor is a database + window/tile manager + ui toolkit; all network driven. +// to be precise, editor is a dumb app and ... +// - does not know a thing about what it stores. +// - does not know how to render the game graphics. +// - does not know how to run the game logic. +// +// the editor will create a canvas for your game to render. +// your game will be responsible to tick the logic and render the window inside the editor. +// +// that being said, editor... +// - can store datas hierarchically. +// - can perform diffs and merges, and version the datas into repositories. +// - can be instructed to render UI on top of game and window views. +// - can download new .natvis and plugins quickly. +// - can dump whole project in a filesystem form (zip). -#define ICON_WARNING ICON_MD_WARNING -#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL -#define ICON_OUTLINER ICON_MD_VIEW_IN_AR -#define ICON_BUILD ICON_MD_BUILD -#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA -#define ICON_CAMERA_ON ICON_MD_VIDEOCAM -#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF -#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET -#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF -#define ICON_AUDIO_ON ICON_MD_VOLUME_UP -#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF -#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT -#define ICON_FULLSCREEN ICON_MD_FULLSCREEN -#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB -#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE -#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH -#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO +// - editor reflects database contents up-to-date. +// - database can be queried and modified via OSC(UDP) commands. -#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT -#define ICON_DISK ICON_MD_STORAGE -#define ICON_RATE ICON_MD_SPEED +// editor database uses one table, and stores two kind of payload types: +// - classes: defines typename and dna. class names are prefixed by '@' +// - instances: defines typename and datas. instance names are as-is, not prefixed. +// +// every save contains 5Ws: what, who, when, where, how, +// every save can be diffed/merged. -#define ICON_CLOCK ICON_MD_TODAY -#define ICON_CHRONO ICON_MD_TIMELAPSE +// ---------------------------------------------------------------------------- -#define ICON_SETTINGS ICON_MD_SETTINGS -#define ICON_LANGUAGE ICON_MD_G_TRANSLATE -#define ICON_PERSONA ICON_MD_FACE -#define ICON_SOCIAL ICON_MD_MESSAGE -#define ICON_GAME ICON_MD_ROCKET_LAUNCH -#define ICON_KEYBOARD ICON_MD_KEYBOARD -#define ICON_MOUSE ICON_MD_MOUSE -#define ICON_GAMEPAD ICON_MD_GAMEPAD -#define ICON_MONITOR ICON_MD_MONITOR -#define ICON_WIFI ICON_MD_WIFI -#define ICON_BUDGET ICON_MD_SAVINGS -#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER -#define ICON_PLUGIN ICON_MD_EXTENSION -#define ICON_RESTART ICON_MD_REPLAY -#define ICON_QUIT ICON_MD_CLOSE +#define EDITOR_VERSION "2023.10" -#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER -#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL -#define ICON_BATTERY_LEVELS \ - ICON_MD_BATTERY_ALERT, \ - ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \ - ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \ - ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \ - ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL +// ---------------------------------------------------------------------------- -char *editor_path(const char *path) { - return va("%s/%s", EDITOR, path); +typedef struct editor_bind_t { + const char *command; + const char *bindings; + void (*fn)(); +} editor_bind_t; + +array(editor_bind_t) editor_binds; + +#define EDITOR_BIND(CMD,KEYS,...) void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); } + +// ---------------------------------------------------------------------------- + +typedef void (*editor_no_property)(void *); +array(void*) editor_persist_kv; +array(editor_no_property) editor_no_properties; + +#define EDITOR_PROPERTY(property_name,T,defaults) \ +typedef map(void*,T) editor_##property_name##_map_t; \ +editor_##property_name##_map_t *editor_##property_name##_map() { \ + static editor_##property_name##_map_t map = 0; do_once map_init_ptr(map); \ + return ↦ \ +} \ +T editor_##property_name(const void *obj) { \ + return *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ +} \ +void editor_set##property_name(const void *obj, T value) { \ + *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) value)) = ((T) value); \ +} \ +void editor_alt##property_name(const void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + *found = (T)(uintptr_t)!(*found); \ +} \ +void editor_no##property_name(void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + map_erase(*editor_##property_name##_map(), (void*)obj); \ +} \ +AUTORUN { array_push(editor_persist_kv, #T); array_push(editor_persist_kv, editor_##property_name##_map()); array_push(editor_no_properties, editor_no##property_name); } + +EDITOR_PROPERTY(open, int, 0); // whether object is tree opened in tree editor +EDITOR_PROPERTY(selected, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(changed, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(popup, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(visible, int, 0); +EDITOR_PROPERTY(script, int, 0); +EDITOR_PROPERTY(event, int, 0); +EDITOR_PROPERTY(iconinstance, char*, 0); +EDITOR_PROPERTY(iconclass, char*, 0); +EDITOR_PROPERTY(treeoffsety, int, 0); +// new prop: breakpoint: request to break on any given node +// new prop: persist: objects with this property will be saved on disk + +void editor_destroy_properties(void *o) { + for each_array(editor_no_properties,editor_no_property,fn) { + fn(o); + } } -vec3 editor_pick(float mouse_x, float mouse_y) { -#if 0 - // unproject 2d coord as 3d coord - camera_t *camera = camera_get_active(); - vec3 out, xyd = vec3(mouse_x,window_height()-mouse_y,1); // usually x:mouse_x,y:window_height()-mouse_y,d:0=znear/1=zfar - mat44 mvp, model; identity44(model); multiply44x3(mvp, camera->proj, camera->view, model); - bool ok = unproject44(&out, xyd, vec4(0,0,window_width(),window_height()), mvp); - return out; -#else - // unproject 2d coord as 3d coord - vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1)); - camera_t *camera = camera_get_active(); - float x = (2.0f * mouse_x) / (dpi.x * window_width()) - 1.0f; - float y = 1.0f - (2.0f * mouse_y) / (dpi.y * window_height()); - float z = 1.0f; - vec3 ray_nds = vec3(x, y, z); - vec4 ray_clip = vec4(ray_nds.x, ray_nds.y, -1.0, 1.0); - mat44 inv_proj; invert44(inv_proj, camera->proj); - mat44 inv_view; invert44(inv_view, camera->view); - vec4 p = transform444(inv_proj, ray_clip); - vec4 eye = vec4(p.x, p.y, -1.0, 0.0); - vec4 wld = norm4(transform444(inv_view, eye)); - return vec3(wld.x, wld.y, wld.z); -#endif +void editor_load_on_boot(void) { +} +void editor_save_on_quit(void) { +} +AUTORUN { + editor_load_on_boot(); + (atexit)(editor_save_on_quit); } -#if 0 -int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate - int clicked = 0; - uint8_t copy = *enabled; +// ---------------------------------------------------------------------------- - // @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive - nk_layout_row_dynamic(ui_ctx, 1, 1); - struct nk_rect bounds = nk_widget_bounds(ui_ctx); +typedef int(*subeditor)(int mode); - // actual widget: label + 8 checkboxes - enum { HEIGHT = 18, BITS = 8, SPAN = 118 }; // bits widget below needs at least 118px wide - nk_layout_row_begin(ui_ctx, NK_STATIC, HEIGHT, 1+BITS); +struct editor_t { + // time + unsigned frame; + double t, dt, slomo; + // controls + int transparent; + int attached; + int active; // focus? does_grabinput instead? + int key; + vec2 mouse; // 2d coord for ray/picking + bool gamepad; // mask instead? |1|2|4|8 + int hz_high, hz_medium, hz_low; + int filter; + bool battery; // battery mode: low fps + bool unlit; + bool ddraw; + // event root nodes + obj* root; + obj* on_init; + obj* on_tick; + obj* on_draw; + obj* on_edit; + obj* on_quit; + // all of them (hierarchical) + array(obj*) objs; // @todo:set() world? + // all of them (flat) + set(obj*) world; + // + array(char*) cmds; + // subeditors + array(subeditor) subeditors; +} editor = { + .active = 1, + .gamepad = 1, + .hz_high = 60, .hz_medium = 18, .hz_low = 5, +}; - int offset = bounds.w > SPAN ? bounds.w - SPAN : 0; - nk_layout_row_push(ui_ctx, offset); - if( ui_label_(label, NK_TEXT_LEFT) ) clicked = 1<<31; +enum { + EDITOR_PANEL, + EDITOR_WINDOW, + EDITOR_WINDOW_NK, + EDITOR_WINDOW_NK_SMALL, +}; - for( int i = 0; i < BITS; ++i ) { - nk_layout_row_push(ui_ctx, 10); - // bit - int val = (*enabled >> i) & 1; - int chg = nk_checkbox_label(ui_ctx, "", &val); - *enabled = (*enabled & ~(1 << i)) | ((!!val) << i); - // tooltip - struct nk_rect bb = { offset + 10 + i * 14, bounds.y, 14, HEIGHT }; // 10:padding,14:width - if (nk_input_is_mouse_hovering_rect(&ui_ctx->input, bb) && !ui_popups()) { - const char *tips[BITS] = {"Init","Tick","Draw","Quit","","","",""}; - if(tips[i][0]) nk_tooltipf(ui_ctx, "%s", tips[i]); - } - } +int editor_begin(const char *title, int mode) { + if( mode == 0 ) return ui_panel(title, PANEL_OPEN); + if( mode == 1 ) return ui_window(title, 0); - nk_layout_row_end(ui_ctx); - return clicked | (copy ^ *enabled); -} -#endif + int ww = window_width(), w = ww * 0.66; + int hh = window_height(), h = hh * 0.66; + struct nk_rect position = { (ww-w)/2,(hh-h)/2, w,h }; + nk_flags win_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER | + NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | + NK_WINDOW_CLOSABLE | NK_WINDOW_MINIMIZABLE | + // NK_WINDOW_SCALE_LEFT|NK_WINDOW_SCALE_TOP| //< @fixme: move this logic into nuklear + // NK_WINDOW_MAXIMIZABLE | NK_WINDOW_PINNABLE | + 0; // NK_WINDOW_SCROLL_AUTO_HIDE; -typedef union engine_var { - int i; - float f; - char *s; -} engine_var; -static map(char*,engine_var) engine_vars; -float *engine_getf(const char *key) { - if(!engine_vars) map_init_str(engine_vars); - engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); - return &found->f; -} -int *engine_geti(const char *key) { - if(!engine_vars) map_init_str(engine_vars); - engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); - return &found->i; -} -char **engine_gets(const char *key) { - if(!engine_vars) map_init_str(engine_vars); - engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); - if(!found->s) found->s = stringf("%s",""); - return &found->s; -} - -int engine_send(const char *cmd, const char *optional_value) { - unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... - unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes - float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) - unsigned *powersave = engine_geti("powersave"); - - char *name; - /**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0); - else if( !strcmp(cmd, "key_stop" )) window_pause(1); - else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) ); - else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 ); - else if( !strcmp(cmd, "key_reload" )) window_reload(); - else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1; - else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true); - else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true); - else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else - app_beep(), name = file_counter(va("%s.mp4",app_name())), window_record(name); - else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); - else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); - else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand - else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1); - else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1); - else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2); - else alert(va("editor could not handle `%s` command.", cmd)); - - return 0; -} - -int engine_tick() { - enum { engine_hz = 60 }; - enum { engine_hz_mid = 18 }; - enum { engine_hz_low = 5 }; - if( *engine_geti("powersave") ) { - // adaptive framerate - int app_on_background = !window_has_focus(); - int hz = app_on_background ? engine_hz_low : engine_hz_mid; - window_fps_lock( hz < 5 ? 5 : hz ); - } else { - // window_fps_lock( editor_hz ); + if( mode == 3 ) { + mode = 2, position.x = input(MOUSE_X), position.w = w/3, win_flags = + NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE| + NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE| //< nuklear requires these two to `remember` popup rects + 0; } + if( mode == 2 || mode == 3 ) + if (nk_begin(ui_ctx, title, position, win_flags)) + return 1; + else + return nk_end(ui_ctx), 0; + + return 0; +} +int editor_end(int mode) { + if( mode == 0 ) return ui_panel_end(); + if( mode == 1 ) return ui_window_end(); + if( mode == 2 ) nk_end(ui_ctx); + if( mode == 3 ) nk_end(ui_ctx); return 0; } -int ui_debug() { - static int time_factor = 0; - static int playing = 0; - static int paused = 0; - int advance_frame = 0; +#if 0 // deprecate +bool editor_active() { + return ui_hover() || ui_active() || gizmo_active() ? editor.active : 0; +} +#endif -#if 0 - static int do_filter = 0; - static int do_profile = 0; - static int do_extra = 0; +int editor_filter() { + if( editor.filter ) { + if (nk_begin(ui_ctx, "Filter", nk_rect(window_width()-window_width()*0.33,32, window_width()*0.33, 40), + NK_WINDOW_NO_SCROLLBAR)) { - char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s", - do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH, - ICON_MD_PLAY_ARROW, - paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE, - ICON_MD_FAST_FORWARD, - ICON_MD_STOP, - ICON_MD_REPLAY, - ICON_MD_FACE, - ICON_MD_MENU - ); - - if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1; - int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS); - if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0; - if( choice == 2 ) playing = 1, paused = 0; - if( choice == 3 ) advance_frame = !!paused, paused = 1; - if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4; - if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0; - if( choice == 6 ) window_reload(); - if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0; - if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1; - - if( do_filter ) { char *bak = ui_filter; ui_filter = 0; ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak); ui_filter = bak; - if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon) - do_filter = 0; - } - } else { - if( ui_filter ) ui_filter[0] = '\0'; - } - char *filter_mask = ui_filter && ui_filter[0] ? va("*%s*", ui_filter) : "*"; - static char *username = 0; - static char *userpass = 0; - if( do_profile ) { - ui_string(ICON_MD_FACE " Username", &username); - ui_string(ICON_MD_FACE " Password", &userpass); + if( input(KEY_ESC) || ( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 )) { + if( ui_filter ) ui_filter[0] = '\0'; + editor.filter = 0; + } + } + nk_end(ui_ctx); } - if( do_extra ) { - int choice2 = ui_label2_toolbar(NULL, - ICON_MD_VIEW_IN_AR - ICON_MD_MESSAGE - ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE - ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO - ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF - - ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0 - - ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU - ); + return editor.filter; } -#endif - int open = 0, clicked_or_toggled = 0; +static +int editor_select_(void *o, const char *mask) { + int matches = 0; + int off = mask[0] == '!', inv = mask[0] == '~'; + int match = strmatchi(obj_type(o), mask+off+inv) || strmatchi(obj_name(o), mask+off+inv); + if( match ) { + editor_setselected(o, inv ? editor_selected(o) ^ 1 : !off); + ++matches; + } + for each_objchild(o, obj*, oo) { + matches += editor_select_(oo, mask); + } + return matches; +} +void editor_select(const char *mask) { + for each_array( editor.objs, obj*, o ) + editor_select_(o, mask); +} +void editor_unselect() { // same than editor_select("!**"); + for each_map_ptr(*editor_selected_map(), void*,o, int, k) { + if( *k ) *k = 0; + } + } +void editor_select_aabb(aabb box) { + int is_inv = input_held(KEY_CTRL); + int is_add = input_held(KEY_SHIFT); + if( !is_inv && !is_add ) editor_unselect(); - #define EDITOR_UI_COLLAPSE(f,...) \ - for( int macro(p) = (open = ui_collapse(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0) - - EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " Windows", "Debug.Windows") { - int choice = ui_toolbar(ICON_MD_RECYCLING "@Reset layout;" ICON_MD_SAVE_AS "@Save layout"); - if( choice == 1 ) ui_layout_all_reset("*"); - if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*"); - - for each_map_ptr_sorted(ui_windows, char*, k, unsigned, v) { - bool visible = ui_visible(*k); - if( ui_bool( *k, &visible ) ) { - ui_show( *k, ui_visible(*k) ^ true ); + aabb item = {0}; + for each_set_ptr( editor.world, obj*, o ) { + if( obj_hasmethod(*o,aabb) && obj_aabb(*o, &item) ) { + if( aabb_test_aabb(item, box) ) { + if( is_inv ) + editor_altselected(*o); + else + editor_setselected(*o, 1); } } } +} - EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") { - // @todo. parse /bugs.ini, includes saved screenshots & videos. - // @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini) +static obj* active_ = 0; +static void editor_selectgroup_(obj *o, obj *first, obj *last) { + // printf("%s (looking for %s in [%s..%s])\n", obj_name(o), active_ ? obj_name(active_) : "", obj_name(first), obj_name(last)); + if( !active_ ) if( o == first || o == last ) active_ = o == first ? last : first; + if( active_ ) editor_setselected(o, 1); + if( o == active_ ) active_ = 0; + for each_objchild(o, obj*, oo) { + editor_selectgroup_(oo, first, last); } - - - // Art and bookmarks - EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") { - bool inlined = true; - const char *file = 0; - if( ui_browse(&file, &inlined) ) { - const char *sep = ifdef(win32, "\"", "'"); - app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep)); - } - } - EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ } - - - // E,C,S,W - EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") { - EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ } - EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ } - EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ } - EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") { - //node_edit(editor.edit.down,&editor.edit); - } - - //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ } - //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ } - //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ } - //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ } - //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ } - - // node_edit(&editor.init,&editor.init); - // node_edit(&editor.draw,&editor.draw); - // node_edit(&editor.tick,&editor.tick); - // node_edit(&editor.edit,&editor.edit); - // node_edit(&editor.quit,&editor.quit); - } - - EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") { - // @todo - } - EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") { - ui_audio(); - } - EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") { - ui_camera( camera_get_active() ); - } - EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") { - // @todo: fps lock, fps target, aspect ratio, fullscreen - char *text = va("%s;%s;%s", - window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN, - ICON_MD_PHOTO_CAMERA, - record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM - ); - - int choice = ui_toolbar(text); - if( choice == 1 ) engine_send("key_fullscreen",0); - if( choice == 2 ) engine_send("key_screenshot",0); - if( choice == 3 ) engine_send("key_record",0); - } - EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") { - ui_keyboard(); - } - EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") { - ui_mouse(); - } - EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") { - for( int q = 0; q < 4; ++q ) { - for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) { - ui_gamepad(q); +} +void editor_selectgroup(obj *first, obj *last) { + if( last ) { + if( !first ) first = array_count(editor.objs) ? editor.objs[0] : NULL; + if( !first ) editor_setselected(last, 1); + else { + active_ = 0; + for each_array(editor.objs,obj*,o) { + editor_selectgroup_(o, first, last); } } - } - - - EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") { - // @todo - } - EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") { - ui_shaders(); - } - EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") { - ui_fxs(); - } - - - EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") { - // @todo. // mem,fps,gfx,net,hdd,... also logging - } - EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") { - // @todo - // SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR - } - EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") { - ui_profiler(); - } - EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") { - // @todo - } - - - - // logic: either plug icon (power saving off) or one of the following ones (power saving on): - // if 0% batt (no batt): battery alert - // if discharging: battery levels [alert,0..6,full] - // if charging: battery charging - int battery_read = app_battery(); - int battery_level = abs(battery_read); - int battery_discharging = battery_read < 0 && battery_level < 100; - const char *power_icon_label = ICON_MD_POWER " Power"; - if( battery_level ) { - const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ? - ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, - ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR, - ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL, - }; - power_icon_label = (const char*)va("%s Power %d%%", - battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL, - battery_level); - } - - EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") { - int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT ); - if( choice == 1 ) engine_send("key_battery","0"); - if( choice == 2 ) engine_send("key_battery","1"); - } - - EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") { - ui_reflect("*"); - } - - EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") { - // @todo. include VCS - EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") { - // @todo } } +static obj *find_any_selected_(obj *o) { + if( editor_selected(o) ) return o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_any_selected_(oo); + if( ooo ) + return ooo; + } + return 0; +} +void* editor_first_selected() { + for each_array(editor.objs,obj*,o) { + obj *oo = find_any_selected_(o); + // if( oo ) printf("1st found: %s\n", obj_name(oo)); + if( oo ) return oo; +} return 0; } -static int gizmo__mode; -static int gizmo__active; -static int gizmo__hover; -bool gizmo_active() { - return gizmo__active; +static obj *find_last_selected_(obj *o) { + void *last = 0; + if( editor_selected(o) ) last = o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_last_selected_(oo); + if( ooo ) + last = ooo; } -bool gizmo_hover() { - return gizmo__hover; + return last; } -int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) { -#if 0 - ddraw_flush(); - mat44 copy; copy44(copy, camera_get_active()->view); - if( 1 ) { - float *mv = camera_get_active()->view; - float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]); - if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0; - if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0; - if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d; +void* editor_last_selected() { + void *last = 0; + for each_array(editor.objs,obj*,o) { + obj *oo = find_last_selected_(o); + // if( oo ) printf("last found: %s\n", obj_name(oo)); + if( oo ) last = oo; +} + return last; +} + +// ---------------------------------------------------------------------------------------- + +void editor_addtoworld(obj *o) { + set_find_or_add(editor.world, o); + for each_objchild(o, obj*, oo) { + editor_addtoworld(oo); +} +} + +void editor_watch(const void *o) { + array_push(editor.objs, (obj*)o); + obj_push(o); // save state + + editor_addtoworld((obj*)o); +} +void* editor_spawn(const char *ini) { // deprecate? + obj *o = obj_make(ini); + editor_watch(o); + return o; +} +void editor_spawn1() { + obj *selected = editor_first_selected(); + obj *o = selected ? obj_make(obj_saveini(selected)) : obj_new(obj); + if( selected ) obj_attach(selected, o), editor_setopen(selected, 1); + else + editor_watch(o); + + editor_unselect(); + editor_setselected(o, 1); +} + +typedef set(obj*) set_objp_t; +static +void editor_glob_recurse(set_objp_t*list, obj *o) { + set_find_or_add(*list, o); + for each_objchild(o,obj*,oo) { + editor_glob_recurse(list, oo); } -#endif - - ddraw_color_push(dd_color); - ddraw_ontop_push(1); - - int enabled = !ui_active() && !ui_hover(); - vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l - vec3 from = camera_get_active()->position; - vec3 to = editor_pick(mouse.x, mouse.y); - ray r = ray(from, to); - - static vec3 src3, hit3, off3; static vec2 src2; - #define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \ - vec3 dir = vec3(X,Y,Z); \ - line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \ - plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \ - vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \ - aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \ - hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \ - ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \ - DRAWCMD; \ - if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \ - if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \ - if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \ - } while(0) - #define gizmo_translate(X,Y,Z,COLOR) \ - on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \ - *pos = add3(line_closest_point(axis, hit_ground->p), off3); \ - } ) - #define gizmo_scale(X,Y,Z,COLOR) \ - on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \ - int component = (X*1+Y*2+Z*3)-1; \ - float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \ - float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \ - float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \ - float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \ - sca->v3[component] -= sgn * mag * 0.01; \ - src2 = vec2(mouse.x, mouse.y); \ - } ) - #define gizmo_rotate(X,Y,Z,COLOR) do { \ - vec3 dir = vec3(X,Y,Z); \ - line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \ - plane ground = { vec3(0,0,0), vec3(0,1,0) }; \ - vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \ - aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \ - hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \ - int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \ - if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ - else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ - else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ - if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \ - if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \ - if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \ - int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \ - float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \ - float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \ - float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \ - float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \ - rot->v3[component] += sgn * mag; \ - /*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \ - src2 = vec2(mouse.x, mouse.y); \ - \ - } \ - gizmo__active *= enabled && !!input(MOUSE_L); \ - } while(0) - - gizmo__hover = 0; - - int modified = 0; - if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3; - if(gizmo__mode == 0) gizmo_translate(1,0,0, RED); - if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN); - if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE); - if(gizmo__mode == 1) gizmo_scale(1,0,0, RED); - if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN); - if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE); - if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED); - if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN); - if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE); - -#if 0 - ddraw_flush(); - copy44(camera_get_active()->view, copy); -#endif - - ddraw_ontop_pop(); - ddraw_color_pop(); - - return modified; } - -// -- localization kit - -static const char *kit_lang = "enUS", *kit_langs = - "enUS,enGB," - "frFR," - "esES,esAR,esMX," - "deDE,deCH,deAT," - "itIT,itCH," - "ptBR,ptPT," - "zhCN,zhSG,zhTW,zhHK,zhMO," - "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," - "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" -; - -static map(char*,char*) kit_ids; -static map(char*,char*) kit_vars; - -#ifndef KIT_FMT_ID2 -#define KIT_FMT_ID2 "%s.%s" -#endif - -void kit_init() { - do_once map_init(kit_ids, less_str, hash_str); - do_once map_init(kit_vars, less_str, hash_str); -} - -void kit_insert( const char *id, const char *translation) { - char *id2 = va(KIT_FMT_ID2, kit_lang, id); - - char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); - if(*found) FREE(*found); - *found = STRDUP(translation); -} - -bool kit_merge( const char *filename ) { - // @todo: xlsx2ini - return false; -} - -void kit_clear() { - map_clear(kit_ids); -} - -bool kit_load( const char *filename ) { - return kit_clear(), kit_merge( filename ); -} - -void kit_set( const char *key, const char *value ) { - value = value && value[0] ? value : ""; - - char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); - if(*found) FREE(*found); - *found = STRDUP(value); -} - -void kit_reset() { - map_clear(kit_vars); -} - -char *kit_translate2( const char *id, const char *lang ) { - char *id2 = va(KIT_FMT_ID2, lang, id); - - char **found = map_find(kit_ids, id2); - - // return original [[ID]] if no translation is found - if( !found ) return va("[[%s]]", id); - - // return translation if no {{moustaches}} are found - if( !strstr(*found, "{{") ) return *found; - - // else replace all found {{moustaches}} with context vars - { - // make room - static __thread char *results[16] = {0}; - static __thread unsigned counter = 0; counter = (counter+1) % 16; - - char *buffer = results[ counter ]; - if( buffer ) FREE(buffer), buffer = 0; - - // iterate moustaches - const char *begin, *end, *text = *found; - while( NULL != (begin = strstr(text, "{{")) ) { - end = strstr(begin+2, "}}"); - if( end ) { - char *var = va("%.*s", (int)(end - (begin+2)), begin+2); - char **found_var = map_find(kit_vars, var); - - if( found_var && 0[*found_var] ) { - strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); - } else { - strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); - } - - text = end+2; - } else { - strcatf(&buffer, "%.*s", (int)(begin - text), text); - - text = begin+2; +void editor_destroy_selected() { + set_objp_t list = 0; + set_init_ptr(list); + for each_map_ptr(*editor_selected_map(), obj*,o, int,selected) { + if( *selected ) { editor_glob_recurse(&list, *o); } + } + for each_set(list, obj*, o) { + obj_detach(o); + } + for each_set(list, obj*, o) { + // printf("deleting %p %s\n", o, obj_name(o)); + // remove from watched items + for (int i = 0, end = array_count(editor.objs); i < end; ++i) { + if (editor.objs[i] == o) { + editor.objs[i] = 0; + array_erase_slow(editor.objs, i); + --end; + --i; } } + // delete from world + set_erase(editor.world, o); + // delete properties + obj + editor_destroy_properties(o); + obj_free(o); + } + set_free(list); +} +void editor_inspect(obj *o) { + ui_section(va("%s (%s)", obj_type(o), obj_name(o))); - strcatf(&buffer, "%s", text); - return buffer; + if( obj_hasmethod(o, menu) ) { + obj_menu(o); + } + + for each_objmember(o,TYPE,NAME,PTR) { + if( !editor_changed(PTR) ) { + obj_push(o); + } + ui_label_icon_highlight = editor_changed(PTR); // @hack: remove ui_label_icon_highlight hack + char *label = va(ICON_MD_UNDO "%s", NAME); + int changed = 0; + /**/ if( !strcmp(TYPE,"float") ) changed = ui_float(label, PTR); + else if( !strcmp(TYPE,"int") ) changed = ui_int(label, PTR); + else if( !strcmp(TYPE,"vec2") ) changed = ui_float2(label, PTR); + else if( !strcmp(TYPE,"vec3") ) changed = ui_float3(label, PTR); + else if( !strcmp(TYPE,"vec4") ) changed = ui_float4(label, PTR); + else if( !strcmp(TYPE,"rgb") ) changed = ui_color3(label, PTR); + else if( !strcmp(TYPE,"rgba") ) changed = ui_color4(label, PTR); + else if( !strcmp(TYPE,"color") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"color3f") ) changed = ui_color3f(label, PTR); + else if( !strcmp(TYPE,"color4f") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"char*") ) changed = ui_string(label, PTR); + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + if( changed ) { + editor_setchanged(PTR, 1); + } + if( ui_label_icon_highlight ) + if( ui_label_icon_clicked_L.x >= 6 && ui_label_icon_clicked_L.x <= 26 ) { // @hack: if clicked on UNDO icon (1st icon) + editor_setchanged(PTR, 0); + } + if( !editor_changed(PTR) ) { + obj_pop(o); + } } } -char *kit_translate( const char *id ) { - return kit_translate2( id, kit_lang ); -} +// ---------------------------------------------------------------------------------------- +// tty -void kit_locale( const char *lang ) { - kit_lang = STRDUP(lang); // @leak -} - -void kit_dump_state( FILE *fp ) { - for each_map(kit_ids, char *, k, char *, v) { - fprintf(fp, "[ID ] %s=%s\n", k, v); +static thread_mutex_t *console_lock; +static array(char*) editor_jobs; +int editor_send(const char *cmd) { // return job-id + int skip = strspn(cmd, " \t\r\n"); + char *buf = STRDUP(cmd + skip); + strswap(buf, "\r\n", ""); + int jobid; + do_threadlock(console_lock) { + array_push(editor_jobs, buf); + jobid = array_count(editor_jobs) - 1; } - for each_map(kit_vars, char *, k, char *, v) { - fprintf(fp, "[VAR] %s=%s\n", k, v); + return jobid; +} +const char* editor_recv(int jobid, double timeout_ss) { + char *answer = 0; + + while(!answer && timeout_ss >= 0 ) { + do_threadlock(console_lock) { + if( editor_jobs[jobid][0] == '\0' ) + answer = editor_jobs[jobid]; + } + timeout_ss -= 0.1; + if( timeout_ss > 0 ) sleep_ms(100); // thread_yield() + } + + return answer + 1; +} + +// plain and ctrl keys +EDITOR_BIND(play, "down(F5)", { window_pause(0); /* if(!editor.slomo) editor.active = 0; */ editor.slomo = 1; } ); +EDITOR_BIND(stop, "down(ESC)", { if(editor.t > 0) { window_pause(1), editor.frame = 0, editor.t = 0, editor.dt = 0, editor.slomo = 0, editor.active = 1; editor_select("**"); editor_destroy_selected(); }} ); +EDITOR_BIND(eject, "down(F1)", { /*window_pause(!editor.active); editor.slomo = !!editor.active;*/ editor.active ^= 1; } ); +EDITOR_BIND(pause, "(held(CTRL) & down(P)) | down(PAUSE)", { window_pause( window_has_pause() ^ 1 ); } ); +EDITOR_BIND(frame, "held(CTRL) & down(LEFT)", { window_pause(1); editor.frame++, editor.t += (editor.dt = 1/60.f); } ); +EDITOR_BIND(slomo, "held(CTRL) & down(RIGHT)", { window_pause(0); editor.slomo = maxf(fmod(editor.slomo * 2, 16), 0.125); } ); +EDITOR_BIND(reload, "held(CTRL) & down(F5)", { window_reload(); } ); +EDITOR_BIND(filter, "held(CTRL) & down(F)", { editor.filter ^= 1; } ); + +// alt keys +EDITOR_BIND(quit, "held(ALT) & down(F4)", { record_stop(), exit(0); } ); +EDITOR_BIND(mute, "held(ALT) & down(M)", { audio_volume_master( 1 ^ !!audio_volume_master(-1) ); } ); +EDITOR_BIND(gamepad, "held(ALT) & down(G)", { editor.gamepad ^= 1; } ); +EDITOR_BIND(transparent, "held(ALT) & down(T)", { editor.transparent ^= 1; } ); +EDITOR_BIND(record, "held(ALT) & down(Z)", { if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else { char *name = file_counter(va("%s.mp4",app_name())); app_beep(), window_record(name); } } ); +EDITOR_BIND(screenshot, "held(ALT) & down(S)", { char *name = file_counter(va("%s.png",app_name())); window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); } ); +EDITOR_BIND(battery, "held(ALT) & down(B)", { editor.battery ^= 1; } ); +EDITOR_BIND(outliner, "held(ALT) & down(O)", { ui_show("Outliner", ui_visible("Outliner") ^ true); } ); +EDITOR_BIND(profiler, "held(ALT) & down(P)", { ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); } ); +EDITOR_BIND(fullscreen, "(held(ALT)&down(ENTER))|down(F11)",{ record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); } ); // close any recording before framebuffer resizing, which would corrupt video stream +EDITOR_BIND(unlit, "held(ALT) & down(U)", { editor.unlit ^= 1; } ); +EDITOR_BIND(ddraw, "held(ALT) & down(D)", { editor.ddraw ^= 1; } ); + +void editor_pump() { + for each_array(editor_binds,editor_bind_t,b) { + if( input_eval(b.bindings) ) { + editor_send(b.command); + } + } + + do_threadlock(console_lock) { + for each_array_ptr(editor_jobs,char*,cmd) { + if( (*cmd)[0] ) { + int found = 0; + for each_array(editor_binds,editor_bind_t,b) { + if( !strcmpi(b.command, *cmd)) { + b.fn(); + found = 1; + break; + } + } + + if( !found ) { + // alert(va("Editor: could not handle `%s` command.", *cmd)); + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Err\n"); (*cmd)[0] = '\0'; + } + + if( (*cmd)[0] ) { + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Ok\n"); (*cmd)[0] = '\0'; + } + } + } } } -/* -int main() { - kit_init(); +// ---------------------------------------------------------------------------------------- - kit_locale("enUS"); - kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Nice to meet you."); - - kit_locale("esES"); - kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Un placer conoceros."); - - kit_locale("enUS"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. - - kit_locale("esES"); - kit_set("PLAYER1", "John"); - kit_set("PLAYER2", "Karl"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. - - assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] - assert(~puts("Ok")); +void editor_symbol(int x, int y, const char *sym) { + #define FONT_SYMBOLS FONT_FACE2 + #define FONT_WHITE FONT_COLOR1 + #define FONT_YELLOW FONT_COLOR2 + #define FONT_ORANGE FONT_COLOR3 + #define FONT_CYAN FONT_COLOR4 + // style: atlas size, unicode ranges and 6 font faces max + do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); + // style: 10 colors max + do_once font_color(FONT_WHITE, WHITE); + do_once font_color(FONT_YELLOW, YELLOW); + do_once font_color(FONT_CYAN, CYAN); + do_once font_color(FONT_ORANGE, ORANGE); + font_goto(x,y); + font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym)); +} + +void editor_frame( void (*game)(unsigned, float, double) ) { + do_once { + set_init_ptr(editor.world); + //set_init_ptr(editor.selection); + profiler_enable( false ); + + window_pause( true ); + window_cursor_shape(CURSOR_SW_AUTO); + editor.hz_high = window_fps_target(); + + fx_load("editorOutline.fs"); + fx_enable(0, 1); + + obj_setname(editor.root = obj_new(obj), "Signals"); + obj_setname(editor.on_init = obj_new(obj), "onInit"); + obj_setname(editor.on_tick = obj_new(obj), "onTick"); + obj_setname(editor.on_draw = obj_new(obj), "onDraw"); + obj_setname(editor.on_edit = obj_new(obj), "onEdit"); + obj_setname(editor.on_quit = obj_new(obj), "onQuit"); + + obj_attach(editor.root, editor.on_init); + obj_attach(editor.root, editor.on_tick); + obj_attach(editor.root, editor.on_draw); + obj_attach(editor.root, editor.on_edit); + obj_attach(editor.root, editor.on_quit); + + editor_seticoninstance(editor.root, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_init, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_tick, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_draw, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_edit, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_quit, ICON_MDI_SIGNAL_VARIANT); + + editor_seticonclass(obj_type(editor.root), ICON_MDI_CUBE_OUTLINE); + } + + // game tick + game(editor.frame, editor.dt, editor.t); + + // timing + editor.dt = clampf(window_delta(), 0, 1/60.f) * !window_has_pause() * editor.slomo; + editor.t += editor.dt; + editor.frame += !window_has_pause(); + editor.frame += !editor.frame; + + // process inputs & messages + editor_pump(); + + // adaptive framerate + int app_on_background = !window_has_focus(); + int hz = app_on_background ? editor.hz_low : editor.battery ? editor.hz_medium : editor.hz_high; + window_fps_lock( hz < 5 ? 5 : hz ); + + // draw menubar + static int stats_mode = 1; + static double last_fps = 0; if(!window_has_pause()) last_fps = window_fps(); + const char *STATS = va("x%4.3f %03d.%03dss %02dF %s", + editor.slomo, (int)editor.t, (int)(1000 * (editor.t - (int)editor.t)), + (editor.frame-1) % ((int)window_fps_target() + !(int)window_fps_target()), + stats_mode == 1 ? va("%5.2f/%dfps", last_fps, (int)window_fps_target()) : stats_mode == 0 ? "0/0 KiB" : xstats()); + const char *ICON_PL4Y = window_has_pause() ? ICON_MDI_PLAY : ICON_MDI_PAUSE; + const char *ICON_SKIP = window_has_pause() ? ICON_MDI_STEP_FORWARD/*ICON_MDI_SKIP_NEXT*/ : ICON_MDI_FAST_FORWARD; + + int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED); + int ingame = !editor.active; + static double clicked_titlebar = 0; + UI_MENU(14+is_borderless, \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \ + UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \ + UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \ + UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \ + UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \ + UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \ + UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \ + UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \ + UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \ + UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \ + UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \ + UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \ + ); + + if( is_borderless ) { + static vec3 drag = {0}; + if( clicked_titlebar ) { + static double clicks = 0; + if( input_up(MOUSE_L) ) ++clicks; + if( input_up(MOUSE_L) && clicks == 2 ) window_visible(false), window_maximize( window_has_maximize() ^ 1 ), window_visible(true); + if( (time_ms() - clicked_titlebar) > 400 ) clicks = 0, clicked_titlebar = 0; + + if( input_down(MOUSE_L) ) drag = vec3(input(MOUSE_X), input(MOUSE_Y), 1); + } + if( drag.z *= !input_up(MOUSE_L) ) { + int wx = 0, wy = 0; + glfwGetWindowPos(window_handle(), &wx, &wy); + glfwSetWindowPos(window_handle(), wx + input(MOUSE_X) - drag.x, wy + input(MOUSE_Y) - drag.y); + } + } + + if( !editor.active ) return; + + // draw edit view (gizmos, position markers, etc). + for each_set_ptr(editor.world,obj*,o) { + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); + } +} + + // draw silhouettes + sprite_flush(); + fx_begin(); + for each_map_ptr(*editor_selected_map(),void*,o,int,selected) { + if( !*selected ) continue; + if( obj_hasmethod(*o,draw) ) { + obj_draw(*o); + } + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); +} +} + sprite_flush(); + fx_end(); + + // draw box selection + if( !ui_active() ) { //< check that we're not moving a window + static vec2 from = {0}, to = {0}; + if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to; + if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)); + if( len2sq(sub2(from,to)) > 0 ) { + vec2 a = min2(from, to), b = max2(from, to); + ddraw_push_2d(); + ddraw_color_push(YELLOW); + ddraw_line( vec3(a.x,a.y,0),vec3(b.x-1,a.y,0) ); + ddraw_line( vec3(b.x,a.y,0),vec3(b.x,b.y-1,0) ); + ddraw_line( vec3(b.x,b.y,0),vec3(a.x-1,b.y,0) ); + ddraw_line( vec3(a.x,b.y,0),vec3(a.x,a.y-1,0) ); + ddraw_color_pop(); + ddraw_pop_2d(); + } + if( input_up(MOUSE_L) ) { + vec2 a = min2(from, to), b = max2(from, to); + from = to = vec2(0,0); + + editor_select_aabb(aabb(vec3(a.x,a.y,0),vec3(b.x,b.y,0))); + } + } + + // draw mouse aabb + aabb mouse = { vec3(input(MOUSE_X),input(MOUSE_Y),0), vec3(input(MOUSE_X),input(MOUSE_Y),1)}; + if( 1 ) { + ddraw_color_push(YELLOW); + ddraw_push_2d(); + ddraw_aabb(mouse.min, mouse.max); + ddraw_pop_2d(); + ddraw_color_pop(); + } + + // tick mouse aabb selection and contextual tab (RMB) + aabb box = {0}; + for each_set(editor.world,obj*,o) { + if( !obj_hasmethod(o, aabb) ) continue; + if( !obj_aabb(o, &box) ) continue; + + // trigger contextual inspector + if( input_down(MOUSE_R) ) { + int is_selected = editor_selected(o); + editor_setpopup(o, is_selected); + } + + // draw contextual inspector + if( editor_popup(o) ) { + if( editor_begin(va("%s (%s)", obj_name(o), obj_type(o)),EDITOR_WINDOW_NK_SMALL) ) { + ui_label2(obj_name(o), obj_type(o)); + editor_inspect(o); + editor_end(EDITOR_WINDOW_NK_SMALL); + } else { + editor_setpopup(o, 0); + } + } +} + + + // draw subeditors + static int preferred_window_mode = EDITOR_WINDOW; + static struct nk_color bak, *on = 0; do_once bak = ui_ctx->style.window.fixed_background.data.color; // ui_ctx->style.window.fixed_background.data.color = !!(on = (on ? NULL : &bak)) ? AS_NKCOLOR(0) : bak; }; + if( editor.transparent ) ui_ctx->style.window.fixed_background.data.color = AS_NKCOLOR(0); + for each_array(editor.subeditors, subeditor, fn) { + fn(preferred_window_mode); + } + ui_ctx->style.window.fixed_background.data.color = bak; + + // draw ui filter (note: render at end-of-frame, so it's hopefully on-top) + editor_filter(); } -*/ diff --git a/engine/split/v4k_editor.h b/engine/split/v4k_editor.h index 4aa5356..d1f5bd4 100644 --- a/engine/split/v4k_editor.h +++ b/engine/split/v4k_editor.h @@ -1,8 +1,8 @@ // ----------------------------------------------------------------------------- // in-game editor // - rlyeh, public domain. -// -// @todo: merge editor1.c and editor3.c internals into this api + +API int editor_send(const char *command); //API void editor(); //API bool editor_active(); @@ -26,19 +26,3 @@ API char* dialog_save(); API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); API bool gizmo_active(); API bool gizmo_hover(); - -// localization kit (I18N, L10N) - -API bool kit_load( const char *filename ); // load translations file (xlsx) -API bool kit_merge( const char *filename ); // merge translations file into existing context -API void kit_insert( const char *id, const char *translation ); // insert single translation unit -API void kit_clear(); // delete all translations - -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context -API void kit_dump_state( FILE *fp ); // debug - -API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale - -API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... -API char* kit_translate( const char *id ); // perform a translation, given current locale diff --git a/engine/split/v4k_editor0.c b/engine/split/v4k_editor0.c new file mode 100644 index 0000000..08289a3 --- /dev/null +++ b/engine/split/v4k_editor0.c @@ -0,0 +1,532 @@ +// editing: +// nope > functions: add/rem property + +#define ICON_PLAY ICON_MD_PLAY_ARROW +#define ICON_PAUSE ICON_MD_PAUSE +#define ICON_STOP ICON_MD_STOP +#define ICON_CANCEL ICON_MD_CLOSE + +#define ICON_WARNING ICON_MD_WARNING +#define ICON_BROWSER ICON_MD_FOLDER_SPECIAL +#define ICON_OUTLINER ICON_MD_VIEW_IN_AR +#define ICON_BUILD ICON_MD_BUILD +#define ICON_SCREENSHOT ICON_MD_PHOTO_CAMERA +#define ICON_CAMERA_ON ICON_MD_VIDEOCAM +#define ICON_CAMERA_OFF ICON_MD_VIDEOCAM_OFF +#define ICON_GAMEPAD_ON ICON_MD_VIDEOGAME_ASSET +#define ICON_GAMEPAD_OFF ICON_MD_VIDEOGAME_ASSET_OFF +#define ICON_AUDIO_ON ICON_MD_VOLUME_UP +#define ICON_AUDIO_OFF ICON_MD_VOLUME_OFF +#define ICON_WINDOWED ICON_MD_FULLSCREEN_EXIT +#define ICON_FULLSCREEN ICON_MD_FULLSCREEN +#define ICON_LIGHTS_ON ICON_MD_LIGHTBULB +#define ICON_LIGHTS_OFF ICON_MD_LIGHTBULB_OUTLINE +#define ICON_RENDER_BASIC ICON_MD_IMAGE_SEARCH +#define ICON_RENDER_FULL ICON_MD_INSERT_PHOTO + +#define ICON_SIGNAL ICON_MD_SIGNAL_CELLULAR_ALT +#define ICON_DISK ICON_MD_STORAGE +#define ICON_RATE ICON_MD_SPEED + +#define ICON_CLOCK ICON_MD_TODAY +#define ICON_CHRONO ICON_MD_TIMELAPSE + +#define ICON_SETTINGS ICON_MD_SETTINGS +#define ICON_LANGUAGE ICON_MD_G_TRANSLATE +#define ICON_PERSONA ICON_MD_FACE +#define ICON_SOCIAL ICON_MD_MESSAGE +#define ICON_GAME ICON_MD_ROCKET_LAUNCH +#define ICON_KEYBOARD ICON_MD_KEYBOARD +#define ICON_MOUSE ICON_MD_MOUSE +#define ICON_GAMEPAD ICON_MD_GAMEPAD +#define ICON_MONITOR ICON_MD_MONITOR +#define ICON_WIFI ICON_MD_WIFI +#define ICON_BUDGET ICON_MD_SAVINGS +#define ICON_NEW_FOLDER ICON_MD_CREATE_NEW_FOLDER +#define ICON_PLUGIN ICON_MD_EXTENSION +#define ICON_RESTART ICON_MD_REPLAY +#define ICON_QUIT ICON_MD_CLOSE + +#define ICON_POWER ICON_MD_BOLT // ICON_MD_POWER +#define ICON_BATTERY_CHARGING ICON_MD_BATTERY_CHARGING_FULL +#define ICON_BATTERY_LEVELS \ + ICON_MD_BATTERY_ALERT, \ + ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, \ + ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR, \ + ICON_MD_BATTERY_4_BAR,ICON_MD_BATTERY_5_BAR, \ + ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL + +char *editor_path(const char *path) { + return va("%s/%s", EDITOR, path); +} + +vec3 editor_pick(float mouse_x, float mouse_y) { +#if 0 + // unproject 2d coord as 3d coord + camera_t *camera = camera_get_active(); + vec3 out, xyd = vec3(mouse_x,window_height()-mouse_y,1); // usually x:mouse_x,y:window_height()-mouse_y,d:0=znear/1=zfar + mat44 mvp, model; identity44(model); multiply44x3(mvp, camera->proj, camera->view, model); + bool ok = unproject44(&out, xyd, vec4(0,0,window_width(),window_height()), mvp); + return out; +#else + // unproject 2d coord as 3d coord + vec2 dpi = ifdef(osx, window_dpi(), vec2(1,1)); + camera_t *camera = camera_get_active(); + float x = (2.0f * mouse_x) / (dpi.x * window_width()) - 1.0f; + float y = 1.0f - (2.0f * mouse_y) / (dpi.y * window_height()); + float z = 1.0f; + vec3 ray_nds = vec3(x, y, z); + vec4 ray_clip = vec4(ray_nds.x, ray_nds.y, -1.0, 1.0); + mat44 inv_proj; invert44(inv_proj, camera->proj); + mat44 inv_view; invert44(inv_view, camera->view); + vec4 p = transform444(inv_proj, ray_clip); + vec4 eye = vec4(p.x, p.y, -1.0, 0.0); + vec4 wld = norm4(transform444(inv_view, eye)); + return vec3(wld.x, wld.y, wld.z); +#endif +} + +#if 0 +int editor_ui_bits8(const char *label, uint8_t *enabled) { // @to deprecate + int clicked = 0; + uint8_t copy = *enabled; + + // @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive + nk_layout_row_dynamic(ui_ctx, 1, 1); + struct nk_rect bounds = nk_widget_bounds(ui_ctx); + + // actual widget: label + 8 checkboxes + enum { HEIGHT = 18, BITS = 8, SPAN = 118 }; // bits widget below needs at least 118px wide + nk_layout_row_begin(ui_ctx, NK_STATIC, HEIGHT, 1+BITS); + + int offset = bounds.w > SPAN ? bounds.w - SPAN : 0; + nk_layout_row_push(ui_ctx, offset); + if( ui_label_(label, NK_TEXT_LEFT) ) clicked = 1<<31; + + for( int i = 0; i < BITS; ++i ) { + nk_layout_row_push(ui_ctx, 10); + // bit + int val = (*enabled >> i) & 1; + int chg = nk_checkbox_label(ui_ctx, "", &val); + *enabled = (*enabled & ~(1 << i)) | ((!!val) << i); + // tooltip + struct nk_rect bb = { offset + 10 + i * 14, bounds.y, 14, HEIGHT }; // 10:padding,14:width + if (nk_input_is_mouse_hovering_rect(&ui_ctx->input, bb) && !ui_popups()) { + const char *tips[BITS] = {"Init","Tick","Draw","Quit","","","",""}; + if(tips[i][0]) nk_tooltipf(ui_ctx, "%s", tips[i]); + } + } + + nk_layout_row_end(ui_ctx); + return clicked | (copy ^ *enabled); +} +#endif + + +typedef union engine_var { + int i; + float f; + char *s; +} engine_var; +static map(char*,engine_var) engine_vars; +float *engine_getf(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); + return &found->f; +} +int *engine_geti(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); + return &found->i; +} +char **engine_gets(const char *key) { + if(!engine_vars) map_init_str(engine_vars); + engine_var *found = map_find_or_add(engine_vars, (char*)key, ((engine_var){0}) ); + if(!found->s) found->s = stringf("%s",""); + return &found->s; +} + +int engine_send(const char *cmd, const char *optional_value) { + unsigned *gamepads = engine_geti("gamepads"); // 0 off, mask gamepad1(1), gamepad2(2), gamepad3(4), gamepad4(8)... + unsigned *renders = engine_geti("renders"); // 0 off, mask: 1=lit, 2=ddraw, 3=whiteboxes + float *speed = engine_getf("speed"); // <0 num of frames to advance, 0 paused, [0..1] slomo, 1 play regular speed, >1 fast-forward (x2/x4/x8) + unsigned *powersave = engine_geti("powersave"); + + char *name; + /**/ if( !strcmp(cmd, "key_quit" )) record_stop(), exit(0); + else if( !strcmp(cmd, "key_stop" )) window_pause(1); + else if( !strcmp(cmd, "key_mute" )) audio_volume_master( 1 ^ !!audio_volume_master(-1) ); + else if( !strcmp(cmd, "key_pause" )) window_pause( window_has_pause() ^ 1 ); + else if( !strcmp(cmd, "key_reload" )) window_reload(); + else if( !strcmp(cmd, "key_battery" )) *powersave = optional_value ? !!atoi(optional_value) : *powersave ^ 1; + else if( !strcmp(cmd, "key_browser" )) ui_show("File Browser", ui_visible("File Browser") ^ true); + else if( !strcmp(cmd, "key_outliner" )) ui_show("Outliner", ui_visible("Outliner") ^ true); + else if( !strcmp(cmd, "key_record" )) if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else + app_beep(), name = file_counter(va("%s.mp4",app_name())), window_record(name); + else if( !strcmp(cmd, "key_screenshot" )) name = file_counter(va("%s.png",app_name())), window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); + else if( !strcmp(cmd, "key_profiler" )) ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); + else if( !strcmp(cmd, "key_fullscreen" )) record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); // framebuffer resizing corrupts video stream, so stop any recording beforehand + else if( !strcmp(cmd, "key_gamepad" )) *gamepads = (*gamepads & ~1u) | ((*gamepads & 1) ^ 1); + else if( !strcmp(cmd, "key_lit" )) *renders = (*renders & ~1u) | ((*renders & 1) ^ 1); + else if( !strcmp(cmd, "key_ddraw" )) *renders = (*renders & ~2u) | ((*renders & 2) ^ 2); + else alert(va("editor could not handle `%s` command.", cmd)); + + return 0; +} + +int engine_tick() { + enum { engine_hz = 60 }; + enum { engine_hz_mid = 18 }; + enum { engine_hz_low = 5 }; + if( *engine_geti("powersave") ) { + // adaptive framerate + int app_on_background = !window_has_focus(); + int hz = app_on_background ? engine_hz_low : engine_hz_mid; + window_fps_lock( hz < 5 ? 5 : hz ); + } else { + // window_fps_lock( editor_hz ); + } + + return 0; +} + +int ui_debug() { + static int time_factor = 0; + static int playing = 0; + static int paused = 0; + int advance_frame = 0; + +#if 0 + static int do_filter = 0; + static int do_profile = 0; + static int do_extra = 0; + + char *EDITOR_TOOLBAR_ICONS = va("%s;%s;%s;%s;%s;%s;%s;%s", + do_filter ? ICON_MD_CLOSE : ICON_MD_SEARCH, + ICON_MD_PLAY_ARROW, + paused ? ICON_MD_SKIP_NEXT : ICON_MD_PAUSE, + ICON_MD_FAST_FORWARD, + ICON_MD_STOP, + ICON_MD_REPLAY, + ICON_MD_FACE, + ICON_MD_MENU + ); + + if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1; + int choice = ui_toolbar(EDITOR_TOOLBAR_ICONS); + if( choice == 1 ) do_filter ^= 1, do_profile = 0, do_extra = 0; + if( choice == 2 ) playing = 1, paused = 0; + if( choice == 3 ) advance_frame = !!paused, paused = 1; + if( choice == 4 ) paused = 0, time_factor = (++time_factor) % 4; + if( choice == 5 ) playing = 0, paused = 0, advance_frame = 0, time_factor = 0; + if( choice == 6 ) window_reload(); + if( choice == 7 ) do_filter = 0, do_profile ^= 1, do_extra = 0; + if( choice == 8 ) do_filter = 0, do_profile = 0, do_extra ^= 1; + + if( do_filter ) { + char *bak = ui_filter; ui_filter = 0; + ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak); + ui_filter = bak; + if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon) + do_filter = 0; + } + } else { + if( ui_filter ) ui_filter[0] = '\0'; + } + char *filter_mask = ui_filter && ui_filter[0] ? va("*%s*", ui_filter) : "*"; + + static char *username = 0; + static char *userpass = 0; + if( do_profile ) { + ui_string(ICON_MD_FACE " Username", &username); + ui_string(ICON_MD_FACE " Password", &userpass); + } + + if( do_extra ) { + int choice2 = ui_label2_toolbar(NULL, + ICON_MD_VIEW_IN_AR + ICON_MD_MESSAGE + ICON_MD_TIPS_AND_UPDATES ICON_MD_LIGHTBULB ICON_MD_LIGHTBULB_OUTLINE + ICON_MD_IMAGE_SEARCH ICON_MD_INSERT_PHOTO + ICON_MD_VIDEOGAME_ASSET ICON_MD_VIDEOGAME_ASSET_OFF + + ICON_MD_VOLUME_UP ICON_MD_VOLUME_OFF // audio_volume_master(-1) > 0 + + ICON_MD_TROUBLESHOOT ICON_MD_SCHEMA ICON_MD_MENU + ); + } +#endif + + int open = 0, clicked_or_toggled = 0; + + + #define EDITOR_UI_COLLAPSE(f,...) \ + for( int macro(p) = (open = ui_collapse(f,__VA_ARGS__)), macro(dummy) = (clicked_or_toggled = ui_collapse_clicked()); macro(p); ui_collapse_end(), macro(p) = 0) + + EDITOR_UI_COLLAPSE(ICON_MD_VIEW_QUILT " Windows", "Debug.Windows") { + int choice = ui_toolbar(ICON_MD_RECYCLING "@Reset layout;" ICON_MD_SAVE_AS "@Save layout"); + if( choice == 1 ) ui_layout_all_reset("*"); + if( choice == 2 ) file_delete(WINDOWS_INI), ui_layout_all_save_disk("*"); + + for each_map_ptr_sorted(ui_windows, char*, k, unsigned, v) { + bool visible = ui_visible(*k); + if( ui_bool( *k, &visible ) ) { + ui_show( *k, ui_visible(*k) ^ true ); + } + } + } + + EDITOR_UI_COLLAPSE(ICON_MD_BUG_REPORT " Bugs 0", "Debug.Bugs") { + // @todo. parse /bugs.ini, includes saved screenshots & videos. + // @todo. screenshot include parseable level, position screen markers (same info as /bugs.ini) + } + + + // Art and bookmarks + EDITOR_UI_COLLAPSE(ICON_MD_FOLDER_SPECIAL " Art", "Debug.Art") { + bool inlined = true; + const char *file = 0; + if( ui_browse(&file, &inlined) ) { + const char *sep = ifdef(win32, "\"", "'"); + app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep)); + } + } + EDITOR_UI_COLLAPSE(ICON_MD_BOOKMARK " Bookmarks", "Debug.Bookmarks") { /* @todo */ } + + + // E,C,S,W + EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Scene", "Debug.Scene") { + EDITOR_UI_COLLAPSE(ICON_MD_BUBBLE_CHART/*ICON_MD_SCATTER_PLOT*/ " Entities", "Debug.Entities") { /* @todo */ } + EDITOR_UI_COLLAPSE(ICON_MD_TUNE " Components", "Debug.Components") { /* @todo */ } + EDITOR_UI_COLLAPSE(ICON_MD_PRECISION_MANUFACTURING " Systems", "Debug.Systems") { /* @todo */ } + EDITOR_UI_COLLAPSE(ICON_MD_PUBLIC " Levels", "Debug.Levels") { + //node_edit(editor.edit.down,&editor.edit); + } + + //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Init", "Debug.HierarchyInit") { /* @todo */ } + //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Draw", "Debug.HierarchyDraw") { /* @todo */ } + //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Tick", "Debug.HierarchyTick") { /* @todo */ } + //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Edit", "Debug.HierarchyEdit") { /* @todo */ } + //EDITOR_UI_COLLAPSE(ICON_MD_ACCOUNT_TREE " Quit", "Debug.HierarchyQuit") { /* @todo */ } + + // node_edit(&editor.init,&editor.init); + // node_edit(&editor.draw,&editor.draw); + // node_edit(&editor.tick,&editor.tick); + // node_edit(&editor.edit,&editor.edit); + // node_edit(&editor.quit,&editor.quit); + } + + EDITOR_UI_COLLAPSE(ICON_MD_ROCKET_LAUNCH " AI", "Debug.AI") { + // @todo + } + EDITOR_UI_COLLAPSE(ICON_MD_VOLUME_UP " Audio", "Debug.Audio") { + ui_audio(); + } + EDITOR_UI_COLLAPSE(ICON_MD_VIDEOCAM " Camera", "Debug.Camera") { + ui_camera( camera_get_active() ); + } + EDITOR_UI_COLLAPSE(ICON_MD_MONITOR " Display", "Debug.Display") { + // @todo: fps lock, fps target, aspect ratio, fullscreen + char *text = va("%s;%s;%s", + window_has_fullscreen() ? ICON_MD_FULLSCREEN_EXIT : ICON_MD_FULLSCREEN, + ICON_MD_PHOTO_CAMERA, + record_active() ? ICON_MD_VIDEOCAM_OFF : ICON_MD_VIDEOCAM + ); + + int choice = ui_toolbar(text); + if( choice == 1 ) engine_send("key_fullscreen",0); + if( choice == 2 ) engine_send("key_screenshot",0); + if( choice == 3 ) engine_send("key_record",0); + } + EDITOR_UI_COLLAPSE(ICON_MD_KEYBOARD " Keyboard", "Debug.Keyboard") { + ui_keyboard(); + } + EDITOR_UI_COLLAPSE(ICON_MD_MOUSE " Mouse", "Debug.Mouse") { + ui_mouse(); + } + EDITOR_UI_COLLAPSE(ICON_MD_GAMEPAD " Gamepads", "Debug.Gamepads") { + for( int q = 0; q < 4; ++q ) { + for( int r = (open = ui_collapse(va("Gamepad #%d",q+1), va("Debug.Gamepads%d",q))), dummy = (clicked_or_toggled = ui_collapse_clicked()); r; ui_collapse_end(), r = 0) { + ui_gamepad(q); + } + } + } + + + EDITOR_UI_COLLAPSE(ICON_MD_CONTENT_PASTE " Scripts", "Debug.Scripts") { + // @todo + } + EDITOR_UI_COLLAPSE(ICON_MD_STAR_HALF " Shaders", "Debug.Shaders") { + ui_shaders(); + } + EDITOR_UI_COLLAPSE(ICON_MD_MOVIE " FXs", "Debug.FXs") { + ui_fxs(); + } + + + EDITOR_UI_COLLAPSE(ICON_MD_SAVINGS " Budgets", "Debug.Budgets") { + // @todo. // mem,fps,gfx,net,hdd,... also logging + } + EDITOR_UI_COLLAPSE(ICON_MD_WIFI/*ICON_MD_SIGNAL_CELLULAR_ALT*/ " Network 0/0 KiB", "Debug.Network") { + // @todo + // SIGNAL_CELLULAR_1_BAR SIGNAL_CELLULAR_2_BAR + } + EDITOR_UI_COLLAPSE(va(ICON_MD_SPEED " Profiler %5.2f/%dfps", window_fps(), (int)window_fps_target()), "Debug.Profiler") { + ui_profiler(); + } + EDITOR_UI_COLLAPSE(va(ICON_MD_STORAGE " Storage %s", xstats()), "Debug.Storage") { + // @todo + } + + + + // logic: either plug icon (power saving off) or one of the following ones (power saving on): + // if 0% batt (no batt): battery alert + // if discharging: battery levels [alert,0..6,full] + // if charging: battery charging + int battery_read = app_battery(); + int battery_level = abs(battery_read); + int battery_discharging = battery_read < 0 && battery_level < 100; + const char *power_icon_label = ICON_MD_POWER " Power"; + if( battery_level ) { + const char *battery_levels[9] = { // @todo: remap [7%..100%] -> [0..1] ? + ICON_MD_BATTERY_ALERT,ICON_MD_BATTERY_0_BAR,ICON_MD_BATTERY_1_BAR, + ICON_MD_BATTERY_2_BAR,ICON_MD_BATTERY_3_BAR,ICON_MD_BATTERY_4_BAR, + ICON_MD_BATTERY_5_BAR,ICON_MD_BATTERY_6_BAR,ICON_MD_BATTERY_FULL, + }; + power_icon_label = (const char*)va("%s Power %d%%", + battery_discharging ? battery_levels[(int)((9-1)*clampf(battery_level/100.f,0,1))] : ICON_MD_BATTERY_CHARGING_FULL, + battery_level); + } + + EDITOR_UI_COLLAPSE(power_icon_label, "Debug.Power") { + int choice = ui_toolbar( ICON_MD_POWER ";" ICON_MD_BOLT ); + if( choice == 1 ) engine_send("key_battery","0"); + if( choice == 2 ) engine_send("key_battery","1"); + } + + EDITOR_UI_COLLAPSE(ICON_MD_WATER " Reflection", "Debug.Reflect") { + ui_reflect("*"); + } + + EDITOR_UI_COLLAPSE(ICON_MD_EXTENSION " Plugins", "Debug.Plugins") { + // @todo. include VCS + EDITOR_UI_COLLAPSE(ICON_MD_BUILD " Cook", "Debug.Cook") { + // @todo + } + } + + return 0; +} + +static int gizmo__mode; +static int gizmo__active; +static int gizmo__hover; +bool gizmo_active() { + return gizmo__active; +} +bool gizmo_hover() { + return gizmo__hover; +} +int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) { +#if 0 + ddraw_flush(); + mat44 copy; copy44(copy, camera_get_active()->view); + if( 1 ) { + float *mv = camera_get_active()->view; + float d = sqrt(mv[4*0+0] * mv[4*0+0] + mv[4*1+1] * mv[4*1+1] + mv[4*2+2] * mv[4*2+2]); + if(4) mv[4*0+0] = d, mv[4*0+1] = 0, mv[4*0+2] = 0; + if(2) mv[4*1+0] = 0, mv[4*1+1] = d, mv[4*1+2] = 0; + if(1) mv[4*2+0] = 0, mv[4*2+1] = 0, mv[4*2+2] = d; + } +#endif + + ddraw_color_push(dd_color); + ddraw_ontop_push(1); + + int enabled = !ui_active() && !ui_hover(); + vec3 mouse = enabled ? vec3(input(MOUSE_X),input(MOUSE_Y),input_down(MOUSE_L)) : vec3(0,0,0); // x,y,l + vec3 from = camera_get_active()->position; + vec3 to = editor_pick(mouse.x, mouse.y); + ray r = ray(from, to); + + static vec3 src3, hit3, off3; static vec2 src2; + #define on_gizmo_dragged(X,Y,Z,COLOR,DRAWCMD, ...) do { \ + vec3 dir = vec3(X,Y,Z); \ + line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \ + plane ground = { vec3(0,0,0), vec3(Y?1:0,Y?0:1,0) }; \ + vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \ + aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \ + hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \ + ddraw_color( hit_arrow || gizmo__active == (X*4+Y*2+Z) ? gizmo__hover = 1, YELLOW : COLOR ); \ + DRAWCMD; \ + if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), src3 = *pos, hit3 = hit_ground->p, off3 = mul3(sub3(src3,hit3),vec3(X,Y,Z)), gizmo__active = X*4+Y*2+Z; \ + if( (gizmo__active && gizmo__active==(X*4+Y*2+Z)) || (!gizmo__active && hit_arrow) ) { ddraw_color( COLOR ); ( 1 ? ddraw_line : ddraw_line_dashed)(axis.a, axis.b); } \ + if( gizmo__active == (X*4+Y*2+Z) && hit_ground ) {{ __VA_ARGS__ }; modified = 1; gizmo__active *= !!input(MOUSE_L); } \ + } while(0) + #define gizmo_translate(X,Y,Z,COLOR) \ + on_gizmo_dragged(X,Y,Z,COLOR, ddraw_arrow(*pos,add3(*pos,vec3(X,Y,Z))), { \ + *pos = add3(line_closest_point(axis, hit_ground->p), off3); \ + } ) + #define gizmo_scale(X,Y,Z,COLOR) \ + on_gizmo_dragged(X,Y,Z,COLOR, (ddraw_line(*pos,add3(*pos,vec3(X,Y,Z))),ddraw_sphere(add3(*pos,vec3(X-0.1*X,Y-0.1*Y,Z-0.1*Z)),0.1)), { /*ddraw_aabb(arrow.min,arrow.max)*/ \ + int component = (X*1+Y*2+Z*3)-1; \ + float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \ + float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \ + float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \ + float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \ + sca->v3[component] -= sgn * mag * 0.01; \ + src2 = vec2(mouse.x, mouse.y); \ + } ) + #define gizmo_rotate(X,Y,Z,COLOR) do { \ + vec3 dir = vec3(X,Y,Z); \ + line axis = {add3(*pos, scale3(dir,100)), add3(*pos, scale3(dir,-100))}; \ + plane ground = { vec3(0,0,0), vec3(0,1,0) }; \ + vec3 unit = vec3(X+(1.0-X)*0.3,Y+(1.0-Y)*0.3,Z+(1.0-Z)*0.3); \ + aabb arrow = { sub3(*pos,unit), add3(*pos,unit) }; \ + hit *hit_arrow = ray_hit_aabb(r, arrow), *hit_ground = ray_hit_plane(r, ground); \ + int hover = (hit_arrow ? (X*4+Y*2+Z) : 0); \ + if( gizmo__active == (X*4+Y*2+Z) ) { ddraw_color(gizmo__active ? gizmo__hover = 1, YELLOW : WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ + else if( !gizmo__active && hover == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color(COLOR); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ + else if( !gizmo__active ) { ddraw_color(WHITE); ddraw_circle(*pos, vec3(X,Y,Z), 1); } \ + if( !gizmo__active && hit_arrow && mouse.z ) src2 = vec2(mouse.x,mouse.y), gizmo__active = hover; \ + if( (!gizmo__active && hover == (X*4+Y*2+Z)) || gizmo__active == (X*4+Y*2+Z) ) { gizmo__hover = 1; ddraw_color( COLOR ); ( 1 ? ddraw_line_thin : ddraw_line_dashed)(axis.a, axis.b); } \ + if( gizmo__active && gizmo__active == (X*4+Y*2+Z) && hit_ground && enabled ) { \ + int component = (Y*1+X*2+Z*3)-1; /*pitch,yaw,roll*/ \ + float mag = len2(sub2(vec2(mouse.x, mouse.y), src2)); \ + float magx = (mouse.x - src2.x) * (mouse.x - src2.x); \ + float magy = (mouse.y - src2.y) * (mouse.y - src2.y); \ + float sgn = (magx > magy ? mouse.x > src2.x : mouse.y > src2.y) ? 1 : -1; \ + rot->v3[component] += sgn * mag; \ + /*rot->v3[component] = clampf(rot->v3[component], -360, +360);*/ \ + src2 = vec2(mouse.x, mouse.y); \ + \ + } \ + gizmo__active *= enabled && !!input(MOUSE_L); \ + } while(0) + + gizmo__hover = 0; + + int modified = 0; + if(enabled && input_down(KEY_SPACE)) gizmo__active = 0, gizmo__mode = (gizmo__mode + 1) % 3; + if(gizmo__mode == 0) gizmo_translate(1,0,0, RED); + if(gizmo__mode == 0) gizmo_translate(0,1,0, GREEN); + if(gizmo__mode == 0) gizmo_translate(0,0,1, BLUE); + if(gizmo__mode == 1) gizmo_scale(1,0,0, RED); + if(gizmo__mode == 1) gizmo_scale(0,1,0, GREEN); + if(gizmo__mode == 1) gizmo_scale(0,0,1, BLUE); + if(gizmo__mode == 2) gizmo_rotate(1,0,0, RED); + if(gizmo__mode == 2) gizmo_rotate(0,1,0, GREEN); + if(gizmo__mode == 2) gizmo_rotate(0,0,1, BLUE); + +#if 0 + ddraw_flush(); + copy44(camera_get_active()->view, copy); +#endif + + ddraw_ontop_pop(); + ddraw_color_pop(); + + return modified; +} + diff --git a/tools/editor/v4k_editor2_browser.h b/engine/split/v4k_editor_browser.h similarity index 100% rename from tools/editor/v4k_editor2_browser.h rename to engine/split/v4k_editor_browser.h diff --git a/tools/editor/v4k_editor4_console.h b/engine/split/v4k_editor_console.h similarity index 100% rename from tools/editor/v4k_editor4_console.h rename to engine/split/v4k_editor_console.h diff --git a/tools/editor/v4k_editor5_nodes.h b/engine/split/v4k_editor_nodes.h similarity index 100% rename from tools/editor/v4k_editor5_nodes.h rename to engine/split/v4k_editor_nodes.h diff --git a/tools/editor/v4k_editor1_scene.h b/engine/split/v4k_editor_scene.h similarity index 99% rename from tools/editor/v4k_editor1_scene.h rename to engine/split/v4k_editor_scene.h index 2d9a590..4528b3d 100644 --- a/tools/editor/v4k_editor1_scene.h +++ b/engine/split/v4k_editor_scene.h @@ -92,8 +92,6 @@ void editor_scene_(obj *o, unsigned flags) { } if( ui_contextual() ) { - API int editor_send(const char *); - int choice = ui_label(ICON_MD_BOOKMARK_ADDED "Toggle bookmarks (CTRL+B)"); if( choice & 1 ) editor_send("bookmark"); diff --git a/tools/editor/v4k_editor6_script.h b/engine/split/v4k_editor_script.h similarity index 74% rename from tools/editor/v4k_editor6_script.h rename to engine/split/v4k_editor_script.h index c63c927..f7e2482 100644 --- a/tools/editor/v4k_editor6_script.h +++ b/engine/split/v4k_editor_script.h @@ -1,24 +1,3 @@ -// lite { -#define f_gc f_gc2 -#define clip clip2 -#define GLEQ_IMPLEMENTATION -#include "3rd_lite_sys_gleq.h" -#include "3rd_lite_sys.h" -#include "3rd_lite.h" -// } - -TODO("new: integrate with Art/ browser") -TODO("bug: lite key bindings are being sent to editor") -TODO("bug: not sending quit signal to lite neither at window close nor editor close (see: temporary files)") -TODO("bug: missing search results window") -TODO("bug: missing code completions popup") -// TODO("eval: https://github.com/drmargarido/linters") -// TODO("eval: https://github.com/monolifed/theme16") -// TODO("eval: https://github.com/vincens2005/lite-formatters") -// https://github.com/takase1121/lite-xl-img -// https://github.com/takase1121/lite-xl-finder -// https://github.com/rxi/lite/commit/236a585756cb9fa70130eee6c9a604780aced424 > suru.png -// https://github.com/rxi/lite/commit/f90b00748e1fe1cd2340aaa06d2526a1b2ea54ec int ui_texture_fit(texture_t t, struct nk_rect bounds) { // allocate complete window space diff --git a/tools/editor/v4k_editor3_timeline.h b/engine/split/v4k_editor_timeline.h similarity index 100% rename from tools/editor/v4k_editor3_timeline.h rename to engine/split/v4k_editor_timeline.h diff --git a/engine/split/v4k_file.c b/engine/split/v4k_file.c index 517c4f9..824e95c 100644 --- a/engine/split/v4k_file.c +++ b/engine/split/v4k_file.c @@ -884,7 +884,7 @@ if( found && *found == 0 ) { char *cmd = va("%scook" ifdef(osx,".osx",ifdef(linux,".linux",".exe"))" %s %s --cook-ini=%s --cook-additive --cook-jobs=1 --quiet", TOOLS, group1, group2, COOK_INI); // cook groups - int rc = atoi(app_exec(cmd)); + int rc = system(cmd); // atoi(app_exec(cmd)); if(rc < 0) PANIC("cannot invoke `%scook` (return code %d)", TOOLS, rc); vfs_reload(); // @todo: optimize me. it is waaay inefficent to reload the whole VFS layout after cooking a single asset diff --git a/engine/split/v4k_main.c b/engine/split/v4k_main.c index 749edf8..2e36d84 100644 --- a/engine/split/v4k_main.c +++ b/engine/split/v4k_main.c @@ -64,7 +64,7 @@ void v4k_init() { ifdef(debug, trap_install()); // init panic handler - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 1<<20); // 1MiB + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 1<<20); // 1MiB // init glfw glfw_init(); diff --git a/engine/split/v4k_memory.c b/engine/split/v4k_memory.c index 2c1eb98..4a92a19 100644 --- a/engine/split/v4k_memory.c +++ b/engine/split/v4k_memory.c @@ -6,9 +6,10 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ # include #endif -#ifndef SYS_REALLOC -#define SYS_REALLOC realloc -#define SYS_MSIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ +#ifndef SYS_MEM_INIT +#define SYS_MEM_INIT() +#define SYS_MEM_REALLOC realloc +#define SYS_MEM_SIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ ifdef(osx, malloc_size, ifdef(bsd, malloc_size, \ ifdef(win32, _msize, malloc_usable_size))) #endif @@ -18,10 +19,12 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ static __thread uint64_t xstats_current = 0, xstats_total = 0, xstats_allocs = 0; void* xrealloc(void* oldptr, size_t size) { + static __thread int once = 0; for(;!once;once = 1) SYS_MEM_INIT(); + // for stats size_t oldsize = xsize(oldptr); - void *ptr = SYS_REALLOC(oldptr, size); + void *ptr = SYS_MEM_REALLOC(oldptr, size); if( !ptr && size ) { PANIC("Not memory enough (trying to allocate %u bytes)", (unsigned)size); } @@ -46,7 +49,7 @@ void* xrealloc(void* oldptr, size_t size) { return ptr; } size_t xsize(void* p) { - if( p ) return SYS_MSIZE(p); + if( p ) return SYS_MEM_SIZE(p); return 0; } char *xstats(void) { diff --git a/engine/split/v4k_obj.h b/engine/split/v4k_obj.h index 80f5904..40361f4 100644 --- a/engine/split/v4k_obj.h +++ b/engine/split/v4k_obj.h @@ -161,6 +161,7 @@ void* obj_free(void *o); // --- syntax sugars #define obj_extend(T,method) (obj_##method[OBJTYPE(T)] = (void*)T##_##method) +#define obj_extend_t(T,method) (obj_##method[OBJTYPE(T##_t)] = (void*)T##_##method) #define obj_method(method,o,...) (obj_##method[((struct obj*)(o))->objtype](o,##__VA_ARGS__)) // (obj_##method[((struct obj*)(o))->objtype]((o), ##__VA_ARGS__)) #define obj_hasmethod(o,method) (obj_typeid(o)[obj_##method]) @@ -183,6 +184,17 @@ void* obj_free(void *o); #define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) #define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) +#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__) +#define EXTEND_T2(o,F1) obj_extend_t(o,F1) +#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) +#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) +#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) +#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) +#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) +#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) +#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) +#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) + // --- declare vtables API extern void (*obj_ctor[256])(); ///- @@ -201,6 +213,8 @@ API extern int (*obj_lerp[256])(); ///- API extern int (*obj_edit[256])(); ///- API extern int (*obj_aabb[256])(); ///- +API extern const char*OBJTYPES[256]; /// - + // ---------------------------------------------------------------------------- // core diff --git a/engine/split/v4k_pack.h b/engine/split/v4k_pack.h index 0ab83b0..8356140 100644 --- a/engine/split/v4k_pack.h +++ b/engine/split/v4k_pack.h @@ -126,25 +126,25 @@ typedef struct double2 { double x,y; } double2; typedef struct double3 { double x,y,z; } double3; typedef struct double4 { double x,y,z,w; } double4; -#define byte2(x,y) M_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) -#define byte3(x,y,z) M_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) -#define byte4(x,y,z,w) M_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) +#define byte2(x,y) C_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) +#define byte3(x,y,z) C_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) +#define byte4(x,y,z,w) C_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) -#define int2(x,y) M_CAST(int2, (int)(x), (int)(y) ) -#define int3(x,y,z) M_CAST(int3, (int)(x), (int)(y), (int)(z) ) -#define int4(x,y,z,w) M_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) +#define int2(x,y) C_CAST(int2, (int)(x), (int)(y) ) +#define int3(x,y,z) C_CAST(int3, (int)(x), (int)(y), (int)(z) ) +#define int4(x,y,z,w) C_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) -#define uint2(x,y) M_CAST(uint2, (unsigned)(x), (unsigned)(y) ) -#define uint3(x,y,z) M_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) -#define uint4(x,y,z,w) M_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) +#define uint2(x,y) C_CAST(uint2, (unsigned)(x), (unsigned)(y) ) +#define uint3(x,y,z) C_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) +#define uint4(x,y,z,w) C_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) -#define float2(x,y) M_CAST(float2, (float)(x), (float)(y) ) -#define float3(x,y,z) M_CAST(float3, (float)(x), (float)(y), (float)(z) ) -#define float4(x,y,z,w) M_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) +#define float2(x,y) C_CAST(float2, (float)(x), (float)(y) ) +#define float3(x,y,z) C_CAST(float3, (float)(x), (float)(y), (float)(z) ) +#define float4(x,y,z,w) C_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) -#define double2(x,y) M_CAST(double2, (double)(x), (double)(y) ) -#define double3(x,y,z) M_CAST(double3, (double)(x), (double)(y), (double)(z) ) -#define double4(x,y,z,w) M_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) +#define double2(x,y) C_CAST(double2, (double)(x), (double)(y) ) +#define double3(x,y,z) C_CAST(double3, (double)(x), (double)(y), (double)(z) ) +#define double4(x,y,z,w) C_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) // ----------------------------------------------------------------------------- // compile-time fourcc, eightcc diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index fa9f6df..80d2db6 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1429,1110 +1429,6 @@ void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } -// ---------------------------------------------------------------------------- -// sprites - -typedef struct sprite_t { - float px, py, pz; // origin x, y, depth - float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree - float sx, sy; // scale x,y - uint32_t rgba; // vertex color - float cellw, cellh; // dimensions of any cell in spritesheet - - union { - struct { - int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet - }; - struct { - float x, y, w, h; // normalized[0..1] within texture bounds - }; - }; -} sprite_t; - -// sprite batching -typedef struct batch_t { array(sprite_t) sprites; mesh_t mesh; int dirty; } batch_t; -typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon - -// sprite stream -typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; -typedef struct sprite_index { GLuint triangle[3]; } sprite_index; - -#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) -#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) - -// sprite impl -static int sprite_count = 0; -static int sprite_program = -1; -static array(sprite_index) sprite_indices = 0; -static array(sprite_vertex) sprite_vertices = 0; -static batch_group_t sprite_additive_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_translucent_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_00_translucent_group = {0}; // (0,0) centered - -void sprite( texture_t texture, float position[3], float rotation, uint32_t color ) { - float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; - sprite_sheet( texture, spritesheet, position, rotation, offset, scale, 0, color, false ); -} - -// rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scalex,scaley), rotation (degrees), color (rgba) -void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba) { - // do not queue if either alpha or scale is zero - if( 0 == (pos.z * pos.w * ((tint_rgba>>24) & 255)) ) return; - - sprite_t s = {0}; - - s.px = pos.x, s.py = pos.y, s.pz = zindex; - s.sx = pos.z, s.sy = pos.w; - - s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; - s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; - - s.rgba = tint_rgba; - s.ox = 0/*ox*/ * s.sx; - s.oy = 0/*oy*/ * s.sy; - if( tilt_deg ) { - tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); - s.cos = cosf(tilt_deg); - s.sin = sinf(tilt_deg); - } else { - s.cos = 1; - s.sin = 0; - } - - batch_group_t *batches = &sprite_00_translucent_group; - batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); - - array_push(found->sprites, s); -} - -void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant) { - const float px = position[0], py = position[1], pz = position[2]; - const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; - const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; - - if (frame < 0) return; - if (frame > 0 && frame >= (xcells * ycells)) return; - - // no need to queue if alpha or scale are zero - if( sx && sy && alpha(rgba) ) { - vec3 bak = camera_get_active()->position; - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - } - - sprite_t s; - s.px = px; - s.py = py; - s.pz = pz; - s.frame = frame; - s.ncx = xcells ? xcells : 1; - s.ncy = ycells ? ycells : 1; - s.sx = sx; - s.sy = sy; - s.ox = ox * sx; - s.oy = oy * sy; - s.cellw = (texture.x * sx / s.ncx); - s.cellh = (texture.y * sy / s.ncy); - s.rgba = rgba; - s.cos = 1; - s.sin = 0; - if(rotation) { - rotation = (rotation + 0) * ((float)C_PI / 180); - s.cos = cosf(rotation); - s.sin = sinf(rotation); - } - - batch_group_t *batches = is_additive ? &sprite_additive_group : &sprite_translucent_group; -#if 0 - batch_t *found = map_find(*batches, texture.id); - if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); -#else - batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); -#endif - - array_push(found->sprites, s); - - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = bak; - } - } -} - -static void sprite_rebuild_meshes() { - sprite_count = 0; - - batch_group_t* list[] = { &sprite_additive_group, &sprite_translucent_group }; - for( int l = 0; l < countof(list); ++l) { - for each_map_ptr(*list[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float cx = (1.0f / it->ncx) - 1e-9f; - float cy = (1.0f / it->ncy) - 1e-9f; - int idx = (int)it->frame; - int px = idx % it->ncx; - int py = idx / it->ncx; - - float ux = px * cx, uy = py * cy; - float vx = ux + cx, vy = uy + cy; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } - - batch_group_t* list2[] = { &sprite_00_translucent_group }; - for( int l = 0; l < countof(list2); ++l) { - for each_map_ptr(*list2[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float ux = it->x, vx = ux + it->w; - float uy = it->y, vy = uy + it->h; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } -} - -static void sprite_render_meshes() { - if( map_count(sprite_additive_group) <= 0 ) - if( map_count(sprite_translucent_group) <= 0 ) - if( map_count(sprite_00_translucent_group) <= 0 ) - return; - - if( sprite_program < 0 ) { - sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), - "att_Position,att_TexCoord,att_Color", - "fragColor", NULL - ); - } - - // use the shader and bind the texture @ unit 0 - shader_bind(sprite_program); - glActiveTexture(GL_TEXTURE0); - - // setup rendering state - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glDepthFunc(GL_LEQUAL); // try to help with zfighting - - // update camera - // camera_fps(camera_get_active(), 0,0); - vec3 pos = camera_get_active()->position; - float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); - float width = window_width(); - float height = window_height(); - - // set mvp in the uniform. (0,0) is center of screen. - mat44 mvp2d; - float zdepth_max = window_height(); // 1; - float l = pos.x - width * zoom / 2; - float r = pos.x + width * zoom / 2; - float b = pos.y + height * zoom / 2; - float t = pos.y - height * zoom / 2; - ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); - - shader_mat44("u_mvp", mvp2d); - - // set (unit 0) in the uniform texture sampler, and render batch - // for all additive then translucent groups - - if( map_count(sprite_additive_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); - for each_map_ptr(sprite_additive_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_additive_group); - } - - if( map_count(sprite_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_translucent_group); - } - - if( map_count(sprite_00_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_00_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_00_translucent_group); - } - - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glDepthFunc(GL_LESS); - glUseProgram(0); -} - -static void sprite_init() { - do_once { - map_init(sprite_00_translucent_group, less_int, hash_int); - map_init(sprite_translucent_group, less_int, hash_int); - map_init(sprite_additive_group, less_int, hash_int); - } -} - -void sprite_flush() { - profile("Sprite.rebuild_time") { - sprite_rebuild_meshes(); - } - profile("Sprite.render_time") { - sprite_render_meshes(); - } -} - -// ----------------------------------------------------------------------------- -// tilemaps - -tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { - tilemap_t t = {0}; - t.tint = ~0u; // WHITE - t.blank_chr = blank_chr; - for( ; *map ; ++map ) { - if( map[0] == linefeed_chr ) ++t.rows; - else { - array_push(t.map, map[0]); - ++t.cols; - } - } - return t; -} - -void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { - vec3 old_pos = camera_get_active()->position; - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - - float scale[2] = {xy_zoom[2], xy_zoom[2]}; - xy_zoom[2] = zindex; - - float offset[2] = {0,0}; - float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) - - for( unsigned y = 0, c = 0; y < m.rows; ++y ) { - for( unsigned x = 0; x < m.cols; ++x, ++c ) { - if( m.map[c] != m.blank_chr ) { - spritesheet[0] = m.map[c]; - sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, is_additive, tint, false); - } - offset[0] += t.tile_w; - } - offset[0] = 0, offset[1] += t.tile_h; - } - - sprite_flush(); - camera_get_active()->position = old_pos; -} - -void tilemap_render( tilemap_t map, tileset_t set ) { - map.position.x += set.tile_w; - map.position.y += set.tile_h; - tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); -} - -tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { - tileset_t t = {0}; - t.tex = tex; - t.cols = cols, t.rows = rows; - t.tile_w = tile_w, t.tile_h = tile_h; - return t; -} - -int ui_tileset( tileset_t t ) { - ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); - int choice; - if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { - int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; - int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; - t.selected = px + py * t.cols; - } - // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} - return t.selected; -} - -// ----------------------------------------------------------------------------- -// tiled - -tiled_t tiled(const char *file_tmx) { - tiled_t zero = {0}, ti = zero; - - // read file and parse json - if( !xml_push(file_tmx) ) return zero; - - // sanity checks - bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); - if( !supported ) return xml_pop(), zero; - - // tileset - const char *file_tsx = xml_string("/map/tileset/@source"); - if( !xml_push(vfs_read(file_tsx)) ) return zero; - const char *set_src = xml_string("/tileset/image/@source"); - int set_w = xml_int("/tileset/@tilewidth"); - int set_h = xml_int("/tileset/@tileheight"); - int set_c = xml_int("/tileset/@columns"); - int set_r = xml_int("/tileset/@tilecount") / set_c; - tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); - xml_pop(); - - // actual parsing - ti.w = xml_int("/map/@width"); - ti.h = xml_int("/map/@height"); - ti.tilew = xml_int("/map/@tilewidth"); - ti.tileh = xml_int("/map/@tileheight"); - ti.first_gid = xml_int("/map/tileset/@firstgid"); - ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak - - for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { - if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { - PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); - continue; - } - - int cols = xml_int("/map/layer[%d]/@width",l); - int rows = xml_int("/map/layer[%d]/@height",l); - - tilemap_t tm = tilemap("", ' ', '\n'); - tm.blank_chr = ~0u; //ti.first_gid - 1; - tm.cols = cols; - tm.rows = rows; - array_resize(tm.map, tm.cols * tm.rows); - memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); - - for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { - int cw, ch; - int cx, cy; - array(char) b64 = 0; - - if( !chunks ) { // non-infinite mode - b64 = xml_blob("/map/layer[%d]/data/$",l); - cw = tm.cols, ch = tm.rows; - cx = 0, cy = 0; - } else { // infinite mode - b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); - cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 - cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) - cx = abs(cx), cy = abs(cy); - } - - int outlen = cw * ch * 4; - static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak - if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { - for( int y = 0, p = 0; y < ch; ++y ) { - for( int x = 0; x < cw; ++x, ++p ) { - if( out[p] >= ti.first_gid ) { - int offset = (x + cx) + (y + cy) * tm.cols; - if( offset >= 0 && offset < (cw * ch) ) - tm.map[ offset ] = out[ p ] - ti.first_gid; - } - } - } - } - else { - PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); - } - - array_free(b64); - } - - array_push(ti.layers, tm); - array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); - array_push(ti.visible, true); - array_push(ti.sets, set); - } - - xml_pop(); - return ti; -} - -void tiled_render(tiled_t tmx, vec3 pos) { - for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { - tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); - if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); - if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); - } -} - -void ui_tiled(tiled_t *t) { - ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); - ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); - ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); - ui_separator(); - ui_bool("Parallax", &t->parallax); - ui_separator(); - ui_label2("Layers", va("%d", array_count(t->layers))); - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF - t->visible[i] ^= true; - } - } - ui_separator(); - if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { - t->sets[i].selected = ui_tileset( t->sets[i] ); - ui_collapse_end(); - } - } - ui_collapse_end(); - } -} - -// ----------------------------------------------------------------------------- -// spine json loader (wip) -// - rlyeh, public domain -// -// [ref] http://es.esotericsoftware.com/spine-json-format -// -// notable misses: -// - mesh deforms -// - cubic beziers -// - shears -// - bounding boxes - -enum { SPINE_MAX_BONES = 64 }; // max bones - -typedef struct spine_bone_t { - char *name, *parent; - struct spine_bone_t *parent_bone; - - float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) - - float len; - float x, y, deg; // base - float x2, y2, deg2; // accum / temporaries during bone transform time - float x3, y3, deg3; // values from timeline - - unsigned rect_id; - unsigned atlas_id; -} spine_bone_t; - -typedef struct spine_slot_t { - char *name, *bone, *attach; -} spine_slot_t; - -typedef struct spine_rect_t { - char *name; - float x,y,w,h,sx,sy,deg; -} spine_rect_t; - -typedef struct spine_skin_t { - char *name; - array(spine_rect_t) rects; -} spine_skin_t; - -typedef struct spine_animkey_t { // offline; only during loading - float time, curve[4]; // time is mandatory, curve is optional - union { - char *name; // type: attachment (mode-1) - struct { float deg; }; // type: rotate (mode-2) - struct { float x,y; }; // type: translate (mode-3) - }; -} spine_animkey_t; - -#if 0 -typedef struct spine_pose_t { // runtime; only during playing - unsigned frame; - array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) -} spine_pose_t; -#endif - -typedef struct spine_anim_t { - char *name; - union { -#if 0 - struct { - unsigned frames; - array(spine_pose_t) poses; - }; -#endif - struct { - array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; - }; - }; -} spine_anim_t; - -typedef struct spine_atlas_t { - char *name; - float x,y,w,h,deg; -} spine_atlas_t; - -typedef struct spine_t { - char *name; - texture_t texture; - unsigned skin; - array(spine_bone_t) bones; - array(spine_slot_t) slots; - array(spine_skin_t) skins; - array(spine_anim_t) anims; - array(spine_atlas_t) atlas; - // anim controller - unsigned inuse; - float time, maxtime; - unsigned debug_atlas_id; -} spine_t; - -// --- - -static -void spine_convert_animkeys_to_animpose(spine_anim_t *input) { - spine_anim_t copy = *input; // @todo - // @leak: attach/rot/tra keys -} - -static -int find_bone_id(spine_t *s, const char *bone_name) { - for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) - if( !strcmp(s->bones[i].name, bone_name)) return i; - return -1; -} -static -spine_bone_t *find_bone(spine_t *s, const char *bone_name) { - int bone_id = find_bone_id(s, bone_name); - return bone_id >= 0 ? &s->bones[bone_id] : NULL; -} - -void spine_skin(spine_t *p, unsigned skin) { - if( !p->texture.id ) return; - if( skin >= array_count(p->skins) ) return; - - p->skin = skin; - - char *skin_name = va("%s/", p->skins[skin].name); - int header = strlen(skin_name); - - for( int i = 0; i < array_count(p->atlas); ++i) { - if(!strbeg(p->atlas[i].name, skin_name)) continue; - - int bone_id = find_bone_id(p, p->atlas[i].name+header ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].atlas_id = i; - } - - for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { - int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].rect_id = i; - } -} - -static -bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { - char *atlas = vfs_read(file_atlas); - if(!atlas || !atlas[0]) return false; - - memset(t, 0, sizeof(spine_t)); - - // goblins.png - // size: 1024, 128 - // filter: Linear, Linear - // pma: true - // dagger - // bounds: 2, 18, 26, 108 - // goblin/eyes-closed - // bounds: 2, 4, 34, 12 - spine_atlas_t *sa = 0; - const char *last_id = 0; - const char *texture_name = 0; - const char *texture_filter = 0; - const char *texture_format = 0; - const char *texture_repeat = 0; - float texture_width = 0, texture_height = 0, temp; - for each_substring(atlas, "\r\n", it) { - it += strspn(it, " \t\f\v"); - /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored - else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); - else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) - else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string - else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string - else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string - else if( strbeg(it, "bounds:" ) ) { - sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); - } - else if( !texture_name ) texture_name = va("%s", it); - else { - array_push(t->atlas, ((spine_atlas_t){0}) ); - sa = &t->atlas[array_count(t->atlas) - 1]; - sa->name = STRDUP(it); - } - } - for( int i = 0; i < array_count(t->atlas); ++i ) { - sa = &t->atlas[i]; - sa->x /= texture_width, sa->y /= texture_height; - sa->w /= texture_width, sa->h /= texture_height; - } - - if(!texture_name) return false; - - t->texture = texture(texture_name, TEXTURE_LINEAR); - - json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? - - array_resize(t->bones, json_count("/bones")); - array_reserve(t->slots, json_count("/slots")); - array_resize(t->skins, json_count("/skins")); - array_resize(t->anims, json_count("/animations")); - - for( int i = 0, end = json_count("/bones"); i < end; ++i ) { - spine_bone_t v = {0}; - v.name = STRDUP(json_string("/bones[%d]/name", i)); - v.parent = STRDUP(json_string("/bones[%d]/parent", i)); - v.x = json_float("/bones[%d]/x", i); - v.y = json_float("/bones[%d]/y", i); - v.z = i; - v.len = json_float("/bones[%d]/length", i); - v.deg = json_float("/bones[%d]/rotation", i); - t->bones[i] = v; - - for( int j = i-1; j > 0; --j ) { - if( strcmp(t->bones[j].name,v.parent) ) continue; - t->bones[i].parent_bone = &t->bones[j]; - break; - } - } - - for( int i = 0, end = json_count("/slots"); i < end; ++i ) { - spine_slot_t v = {0}; - v.name = STRDUP(json_string("/slots[%d]/name", i)); - v.bone = STRDUP(json_string("/slots[%d]/bone", i)); - v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); - - array_push(t->slots, v); - - // slots define draw-order. so, update draw-order/zindex in bone - spine_bone_t *b = find_bone(t, v.name); - if( b ) b->z = i; - } - - for( int i = 0, end = json_count("/skins"); i < end; ++i ) { - spine_skin_t v = {0}; - v.name = STRDUP(json_string("/skins[%d]/name", i)); - - for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ - for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ - spine_rect_t r = {0}; - r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); - r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); - r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); - r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; - r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; - r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); - r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); - r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); - array_push(v.rects, r); - } - - t->skins[i] = v; - } - -#if 1 - // simplify: - // merge /skins/default into existing /skins/*, then delete /skins/default - if( array_count(t->skins) > 1 ) { - for( int i = 1; i < array_count(t->skins); ++i ) { - for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { - array_push(t->skins[i].rects, t->skins[0].rects[j]); - } - } - // @leak @fixme: FREE(t->skins[0]) - for( int i = 0; i < array_count(t->skins)-1; ++i ) { - t->skins[i] = t->skins[i+1]; - } - array_pop(t->skins); - } -#endif - - for( int i = 0, end = json_count("/animations"); i < end; ++i ) { - int id; - const char *name; - - spine_anim_t v = {0}; - v.name = STRDUP(json_key("/animations[%d]", i)); - - // slots / attachments - - for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) - for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids - { - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - spine_animkey_t key = {0}; - - key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); - key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); - } - - // @todo: convert name to id - // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) - // printf("%s vs %s\n", key.name, t->bones[id].name); - - array_push(v.attach_keys[bone_id], key); - } - } - - // bones - - for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones - for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - // parse bones - for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); - int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; - if( !track ) continue; - - spine_animkey_t key = {0}; - - key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); - } - - if( track == 1 ) - key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" - array_push(v.rotate_keys[bone_id], key); - else - key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), - key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), - array_push(v.translate_keys[bone_id], key); - } - } - - t->anims[i] = v; - } - - json_pop(); - - spine_skin(t, 0); - - return true; -} - -spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { - spine_t *t = MALLOC(sizeof(spine_t)); - if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; - return t; -} - -void spine_render(spine_t *p, vec3 offset, unsigned flags) { - if( !p->texture.id ) return; - if( !flags ) return; - - ddraw_push_2d(); - // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); - // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); - - // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches - - for( int i = 1; i < array_count(p->bones); ++i ) { - spine_bone_t *self = &p->bones[i]; - if( !self->rect_id ) continue; - - int num_bones = 0; - static array(spine_bone_t*) chain = 0; array_resize(chain, 0); - for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { - array_push(chain, next); - } - - vec3 target = {0}, prev = {0}; - for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction - int j_opposite = end - 1 - j; - - spine_bone_t *b = chain[j_opposite]; // bone - spine_bone_t *pb = b->parent_bone; // parent bone - - float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; - if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; - - const float deg2rad = C_PI / 180; - b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); - b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); - b->deg2 = -b->deg3 + pb_deg2 - b->deg; - - prev = target; - target = vec3(b->x2,b->y2,b->deg2); - } - - target.z = 0; - target = add3(target, offset); - prev.z = 0; - prev = add3(prev, offset); - - if( flags & 2 ) { - ddraw_point( target ); - ddraw_text( target, -0.25f, self->name ); - ddraw_bone( prev, target ); // from parent to bone - } - if( flags & 1 ) { - spine_atlas_t *a = &p->atlas[self->atlas_id]; - spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; - - vec4 rect = ptr4(&a->x); - float zindex = self->z; - float offsx = 0; - float offsy = 0; - float tilt = self->deg2 + (a->deg - r->deg); - unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; - - if( 1 ) { - vec3 dir = vec3(r->x,r->y,0); - dir = rotatez3(dir, self->deg2); - offsx = dir.x * r->sx; - offsy = dir.y * r->sy; - } - - sprite_rect(p->texture, rect, zindex, add4(vec4(target.x,target.y,1,1),vec4(offsx,offsy,0,0)), tilt, tint); - } - } - - ddraw_pop_2d(); - ddraw_flush(); -} - -static -void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { - if( !p->texture.id ) return; - - if( delta > 1/120.f ) delta = 1/120.f; - if( *time >= *maxtime ) *time = 0; else *time += delta; - - // reset root // needed? - p->bones[0].x2 = 0; - p->bones[0].y2 = 0; - p->bones[0].deg2 = 0; - p->bones[0].x3 = 0; - p->bones[0].y3 = 0; - p->bones[0].deg3 = 0; - - for( int i = 0, end = array_count(p->bones); i < end; ++i) { - // @todo: attach channel - // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} - for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].deg3 = r->deg; - } - } - for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].x3 = r->x; - p->bones[i].y3 = r->y; - } - } - } -} - -void spine_animate(spine_t *p, float delta) { - spine_animate_(p, &p->time, &p->maxtime, delta); -} - -void ui_spine(spine_t *p) { - if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { - for each_array_ptr(p->anims, spine_anim_t, q) { - if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { - spine_animate(p, 0); - } - - int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); - if( choice == 1 ) window_pause( 0 ); // play - if( choice == 2 ) window_pause( 1 ); // pause - - for( int i = 0; i < SPINE_MAX_BONES; ++i ) { - ui_separator(); - ui_label(va("Bone %d: Attachment keys", i)); - for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); - } - ui_label(va("Bone %d: Rotate keys", i)); - for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); - } - ui_label(va("Bone %d: Translate keys", i)); - for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); - } - } - } - ui_collapse_end(); - } - if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { - for each_array_ptr(p->bones, spine_bone_t, q) - if( ui_collapse(q->name, va("%p-b2", q)) ) { - ui_label2("Parent:", q->parent); - ui_label2("X:", va("%.2f", q->x)); - ui_label2("Y:", va("%.2f", q->y)); - ui_label2("Length:", va("%.2f", q->len)); - ui_label2("Rotation:", va("%.2f", q->deg)); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { - for each_array_ptr(p->slots, spine_slot_t, q) - if( ui_collapse(q->name, va("%p-s2", q)) ) { - ui_label2("Bone:", q->bone); - ui_label2("Attachment:", q->attach); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { - for each_array_ptr(p->skins, spine_skin_t, q) - if( ui_collapse(q->name, va("%p-k2", q)) ) { - for each_array_ptr(q->rects, spine_rect_t, r) - if( ui_collapse(r->name, va("%p-k3", r)) ) { - ui_label2("X:", va("%.2f", r->x)); - ui_label2("Y:", va("%.2f", r->y)); - ui_label2("Scale X:", va("%.2f", r->sx)); - ui_label2("Scale Y:", va("%.2f", r->sy)); - ui_label2("Width:", va("%.2f", r->w)); - ui_label2("Height:", va("%.2f", r->h)); - ui_label2("Rotation:", va("%.2f", r->deg)); - ui_collapse_end(); - - spine_bone_t *b = find_bone(p, r->name); - if( b ) { - p->debug_atlas_id = b->atlas_id; - - static float tilt = 0; - if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; - spine_atlas_t *r = p->atlas + b->atlas_id; - sprite_flush(); - camera_get_active()->position = vec3(0,0,2); - vec4 rect = ptr4(&r->x); float zindex = 0; vec3 xy_zoom = vec3(0,0,0); unsigned tint = ~0u; - sprite_rect(p->texture, - // rect: vec4(r->x*1.0/p->texture.w,r->y*1.0/p->texture.h,(r->x+r->w)*1.0/p->texture.w,(r->y+r->h)*1.0/p->texture.h), - ptr4(&r->x), // atlas - 0, vec4(0,0,1,1), r->deg + tilt, tint); - sprite_flush(); - camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); - } - } - ui_collapse_end(); - } - ui_collapse_end(); - } - - if( ui_int("Use skin", &p->skin) ) { - p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); - spine_skin(p, p->skin); - } - - if( p->texture.id ) ui_texture(0, p->texture); -} - // ----------------------------------------------------------------------------- // cubemaps diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index ed42aa3..4f62d92 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -183,82 +183,6 @@ API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); -// ----------------------------------------------------------------------------- -// sprites - -// texture id, position(x,y,depth sort), tint color, rotation angle -API void sprite( texture_t texture, float position[3], float rotation /*0*/, uint32_t color /*~0u*/); - -// texture id, rect(x,y,w,h) is [0..1] normalized, z-index, pos(xy,scale.xy), rotation (degrees), color (rgba) -API void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba); - -// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color -API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant); - -API void sprite_flush(); - -// ----------------------------------------------------------------------------- -// tilemaps - -typedef struct tileset_t { - texture_t tex; // spritesheet - unsigned tile_w, tile_h; // dimensions per tile in pixels - unsigned cols, rows; // tileset num_cols, num_rows - unsigned selected; // active tile (while editing) -} tileset_t; - -API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); - -API int ui_tileset( tileset_t t ); - -typedef struct tilemap_t { - int blank_chr; // transparent tile - unsigned cols, rows; // map dimensions (in tiles) - array(int) map; - - vec3 position; // x,y,scale - float zindex; - float tilt; - unsigned tint; - bool is_additive; -} tilemap_t; - -API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); -API void tilemap_render( tilemap_t m, tileset_t style ); -API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); - -// ----------------------------------------------------------------------------- -// tiled maps - -typedef struct tiled_t { - char *map_name; - unsigned first_gid, tilew, tileh, w, h; - - bool parallax; - vec3 position; - array(bool) visible; - array(tilemap_t) layers; - array(tileset_t) sets; - array(char*) names; -} tiled_t; - -API tiled_t tiled(const char *file_tmx); -API void tiled_render(tiled_t tmx, vec3 pos); - -API void ui_tiled(tiled_t *t); - -// ----------------------------------------------------------------------------- -// spines - -typedef struct spine_t spine_t; - -API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); -API void spine_skin(spine_t *p, unsigned skin); -API void spine_render(spine_t *p, vec3 offset, unsigned flags); -API void spine_animate(spine_t *p, float delta); - -API void ui_spine(spine_t *p); - // ----------------------------------------------------------------------------- // cubemaps diff --git a/engine/split/v4k_sprite.c b/engine/split/v4k_sprite.c new file mode 100644 index 0000000..ad3d181 --- /dev/null +++ b/engine/split/v4k_sprite.c @@ -0,0 +1,1466 @@ +// ---------------------------------------------------------------------------- +// sprites + +typedef struct sprite_static_t { + float px, py, pz; // origin x, y, depth + float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree + float sx, sy; // scale x,y + float cellw, cellh; // dimensions of any cell in spritesheet + + union { + struct { + int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet + }; + struct { + float x, y, w, h; // normalized[0..1] within texture bounds + }; + }; + + uint32_t rgba, flags; // vertex color and flags +} sprite_static_t; + +// sprite batching +typedef struct batch_t { array(sprite_static_t) sprites; mesh_t mesh; int dirty; } batch_t; +typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon + +// sprite stream +typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; +typedef struct sprite_index { GLuint triangle[3]; } sprite_index; + +#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) +#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) + +// sprite impl +static int sprite_count = 0; +static int sprite_program = -1; +static array(sprite_index) sprite_indices = 0; +static array(sprite_vertex) sprite_vertices = 0; + +// center_wh << 2 | additive << 1 | projected << 0 +static batch_group_t sprite_group[8] = {0}; + +// rect(x,y,w,h) is [0..1] normalized, pos(xyz,z-index), scale_offset(sx,sy,offx,offy), rotation (degrees), color (rgba) +void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scale_offset, float tilt_deg, unsigned tint_rgba, unsigned flags) { + float zindex = pos.w; + float scalex = scale_offset.x; + float scaley = scale_offset.y; + float offsetx = scale_offset.z; + float offsety = scale_offset.w; + + // do not queue if either scales or alpha are zero + if( 0 == (scalex * scaley * ((tint_rgba>>24) & 255)) ) return; + + ASSERT( (flags & SPRITE_CENTERED) == 0 ); + if( flags & SPRITE_PROJECTED ) { + tilt_deg += 180, scalex = -scalex; // flip texture Y on mvp3d (same than turn 180º then flip X) + } + + sprite_static_t s = {0}; + + s.px = pos.x, s.py = pos.y, s.pz = pos.z - zindex; + s.sx = scalex, s.sy = scaley; + + s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; + s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; + + s.rgba = tint_rgba; + s.flags = flags; + +#if 0 + s.ox = 0/*ox*/ * s.sx; + s.oy = 0/*oy*/ * s.sy; +#else + s.ox += offsetx * scalex; + s.oy += offsety * scaley; +#endif + + if( tilt_deg ) { + tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); + s.cos = cosf(tilt_deg); + s.sin = sinf(tilt_deg); + } else { + s.cos = 1; + s.sin = 0; + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; + batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); + + array_push(found->sprites, s); +} + +void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags) { + flags |= SPRITE_CENTERED; + ASSERT( flags & SPRITE_CENTERED ); + + const float px = position[0], py = position[1], pz = position[2]; + const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; + const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; + + if (frame < 0) return; + if (frame > 0 && frame >= (xcells * ycells)) return; + + // no need to queue if alpha or scale are zero + if( sx && sy && alpha(rgba) ) { + vec3 bak = camera_get_active()->position; + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + } + + sprite_static_t s; + s.px = px; + s.py = py; + s.pz = pz; + s.frame = frame; + s.ncx = xcells ? xcells : 1; + s.ncy = ycells ? ycells : 1; + s.sx = sx; + s.sy = sy; + s.ox = ox * sx; + s.oy = oy * sy; + s.cellw = (texture.x * sx / s.ncx); + s.cellh = (texture.y * sy / s.ncy); + s.rgba = rgba; + s.flags = flags; + s.cos = 1; + s.sin = 0; + if(rotation) { + rotation = (rotation + 0) * ((float)C_PI / 180); + s.cos = cosf(rotation); + s.sin = sinf(rotation); + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; +#if 0 + batch_t *found = map_find(*batches, texture.id); + if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); +#else + batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); +#endif + + array_push(found->sprites, s); + + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = bak; + } + } +} + +void sprite( texture_t texture, float position[3], float rotation, unsigned color, unsigned flags) { + float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; + sprite_sheet( texture, spritesheet, position, rotation, offset, scale, color, flags ); +} + +static void sprite_rebuild_meshes() { + sprite_count = 0; + + // w/2,h/2 centered + for( int l = countof(sprite_group) / 2; l < countof(sprite_group); ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float cx = (1.0f / it->ncx) - 1e-9f; + float cy = (1.0f / it->ncy) - 1e-9f; + int idx = (int)it->frame; + int px = idx % it->ncx; + int py = idx / it->ncx; + + float ux = px * cx, uy = py * cy; + float vx = ux + cx, vy = uy + cy; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } + + // (0,0) centered + for( int l = 0; l < countof(sprite_group) / 2; ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float ux = it->x, vx = ux + it->w; + float uy = it->y, vy = uy + it->h; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } +} + +static void sprite_render_meshes_group(batch_group_t* sprites, int alpha_key, int alpha_value, float mvp[16]) { + if( map_count(*sprites) > 0 ) { + // setup shader + if( sprite_program < 0 ) { + sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), + "att_Position,att_TexCoord,att_Color", + "fragColor", NULL + ); + } + shader_bind(sprite_program); + shader_mat44("u_mvp", mvp); + + // set (unit 0) in the uniform texture sampler, and render batch + glActiveTexture(GL_TEXTURE0); + glBlendFunc( alpha_key, alpha_value ); + + for each_map_ptr(*sprites, int,texture_id, batch_t,bt) { + if( bt->dirty ) { + shader_texture_unit("u_texture", *texture_id, 0); + mesh_render(&bt->mesh); + } + } +// map_clear(*sprites); + } +} + +static void sprite_init() { + do_once for(int i = 0; i < countof(sprite_group); ++i) { + map_init(sprite_group[i], less_int, hash_int); + } +} + +void sprite_flush() { + profile("Sprite.rebuild_time") { + sprite_rebuild_meshes(); + } + profile("Sprite.render_time") { + // setup rendering state + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glDepthFunc(GL_LEQUAL); // try to help with zfighting + + // 3d + mat44 mvp3d; multiply44x2(mvp3d, camera_get_active()->proj, camera_get_active()->view); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + + // 2d: (0,0) is center of screen + mat44 mvp2d; + vec3 pos = camera_get_active()->position; + float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); + float zdepth_max = window_height(); // 1; + float l = pos.x - window_width() * zoom / 2; + float r = pos.x + window_width() * zoom / 2; + float b = pos.y + window_height() * zoom / 2; + float t = pos.y - window_height() * zoom / 2; + ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[0], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + + // restore rendering state + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDepthFunc(GL_LESS); + glUseProgram(0); + } +} + +// ----------------------------------------------------------------------------- +// tilemaps + +tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { + tilemap_t t = {0}; + t.tint = ~0u; // WHITE + t.blank_chr = blank_chr; + for( ; *map ; ++map ) { + if( map[0] == linefeed_chr ) ++t.rows; + else { + array_push(t.map, map[0]); + ++t.cols; + } + } + return t; +} + +void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { + vec3 old_pos = camera_get_active()->position; + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + + float scale[2] = {xy_zoom[2], xy_zoom[2]}; + xy_zoom[2] = zindex; + + float offset[2] = {0,0}; + float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) + + for( unsigned y = 0, c = 0; y < m.rows; ++y ) { + for( unsigned x = 0; x < m.cols; ++x, ++c ) { + if( m.map[c] != m.blank_chr ) { + spritesheet[0] = m.map[c]; + sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, tint, is_additive ? SPRITE_ADDITIVE : 0); + } + offset[0] += t.tile_w; + } + offset[0] = 0, offset[1] += t.tile_h; + } + + sprite_flush(); + camera_get_active()->position = old_pos; +} + +void tilemap_render( tilemap_t map, tileset_t set ) { + map.position.x += set.tile_w; + map.position.y += set.tile_h; + tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); +} + +tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { + tileset_t t = {0}; + t.tex = tex; + t.cols = cols, t.rows = rows; + t.tile_w = tile_w, t.tile_h = tile_h; + return t; +} + +int ui_tileset( tileset_t t ) { + ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); + int choice; + if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { + int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; + int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; + t.selected = px + py * t.cols; + } + // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} + return t.selected; +} + +// ----------------------------------------------------------------------------- +// tiled + +tiled_t tiled(const char *file_tmx) { + tiled_t zero = {0}, ti = zero; + + // read file and parse json + if( !xml_push(file_tmx) ) return zero; + + // sanity checks + bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); + if( !supported ) return xml_pop(), zero; + + // tileset + const char *file_tsx = xml_string("/map/tileset/@source"); + if( !xml_push(vfs_read(file_tsx)) ) return zero; + const char *set_src = xml_string("/tileset/image/@source"); + int set_w = xml_int("/tileset/@tilewidth"); + int set_h = xml_int("/tileset/@tileheight"); + int set_c = xml_int("/tileset/@columns"); + int set_r = xml_int("/tileset/@tilecount") / set_c; + tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); + xml_pop(); + + // actual parsing + ti.w = xml_int("/map/@width"); + ti.h = xml_int("/map/@height"); + ti.tilew = xml_int("/map/@tilewidth"); + ti.tileh = xml_int("/map/@tileheight"); + ti.first_gid = xml_int("/map/tileset/@firstgid"); + ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak + + for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { + if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { + PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); + continue; + } + + int cols = xml_int("/map/layer[%d]/@width",l); + int rows = xml_int("/map/layer[%d]/@height",l); + + tilemap_t tm = tilemap("", ' ', '\n'); + tm.blank_chr = ~0u; //ti.first_gid - 1; + tm.cols = cols; + tm.rows = rows; + array_resize(tm.map, tm.cols * tm.rows); + memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); + + for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { + int cw, ch; + int cx, cy; + array(char) b64 = 0; + + if( !chunks ) { // non-infinite mode + b64 = xml_blob("/map/layer[%d]/data/$",l); + cw = tm.cols, ch = tm.rows; + cx = 0, cy = 0; + } else { // infinite mode + b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); + cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 + cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) + cx = abs(cx), cy = abs(cy); + } + + int outlen = cw * ch * 4; + static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak + if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { + for( int y = 0, p = 0; y < ch; ++y ) { + for( int x = 0; x < cw; ++x, ++p ) { + if( out[p] >= ti.first_gid ) { + int offset = (x + cx) + (y + cy) * tm.cols; + if( offset >= 0 && offset < (cw * ch) ) + tm.map[ offset ] = out[ p ] - ti.first_gid; + } + } + } + } + else { + PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); + } + + array_free(b64); + } + + array_push(ti.layers, tm); + array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); + array_push(ti.visible, true); + array_push(ti.sets, set); + } + + xml_pop(); + return ti; +} + +void tiled_render(tiled_t tmx, vec3 pos) { + for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { + tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); + if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); + if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); + } +} + +void ui_tiled(tiled_t *t) { + ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); + ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); + ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); + ui_separator(); + ui_bool("Parallax", &t->parallax); + ui_separator(); + ui_label2("Layers", va("%d", array_count(t->layers))); + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF + t->visible[i] ^= true; + } + } + ui_separator(); + if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { + t->sets[i].selected = ui_tileset( t->sets[i] ); + ui_collapse_end(); + } + } + ui_collapse_end(); + } +} + +// ----------------------------------------------------------------------------- +// spine json loader (wip) +// - rlyeh, public domain +// +// [ref] http://es.esotericsoftware.com/spine-json-format +// +// notable misses: +// - mesh deforms +// - cubic beziers +// - shears +// - bounding boxes + +enum { SPINE_MAX_BONES = 64 }; // max bones + +typedef struct spine_bone_t { + char *name, *parent; + struct spine_bone_t *parent_bone; + + float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) + + float len; + float x, y, deg; // base + float x2, y2, deg2; // accum / temporaries during bone transform time + float x3, y3, deg3; // values from timeline + + unsigned rect_id; + unsigned atlas_id; +} spine_bone_t; + +typedef struct spine_slot_t { + char *name, *bone, *attach; +} spine_slot_t; + +typedef struct spine_rect_t { + char *name; + float x,y,w,h,sx,sy,deg; +} spine_rect_t; + +typedef struct spine_skin_t { + char *name; + array(spine_rect_t) rects; +} spine_skin_t; + +typedef struct spine_animkey_t { // offline; only during loading + float time, curve[4]; // time is mandatory, curve is optional + union { + char *name; // type: attachment (mode-1) + struct { float deg; }; // type: rotate (mode-2) + struct { float x,y; }; // type: translate (mode-3) + }; +} spine_animkey_t; + +#if 0 +typedef struct spine_pose_t { // runtime; only during playing + unsigned frame; + array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) +} spine_pose_t; +#endif + +typedef struct spine_anim_t { + char *name; + union { +#if 0 + struct { + unsigned frames; + array(spine_pose_t) poses; + }; +#endif + struct { + array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; + }; + }; +} spine_anim_t; + +typedef struct spine_atlas_t { + char *name; + float x,y,w,h,deg; +} spine_atlas_t; + +typedef struct spine_t { + char *name; + texture_t texture; + unsigned skin; + array(spine_bone_t) bones; + array(spine_slot_t) slots; + array(spine_skin_t) skins; + array(spine_anim_t) anims; + array(spine_atlas_t) atlas; + // anim controller + unsigned inuse; + float time, maxtime; + unsigned debug_atlas_id; +} spine_t; + +// --- + +static +void spine_convert_animkeys_to_animpose(spine_anim_t *input) { + spine_anim_t copy = *input; // @todo + // @leak: attach/rot/tra keys +} + +static +int find_bone_id(spine_t *s, const char *bone_name) { + for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) + if( !strcmp(s->bones[i].name, bone_name)) return i; + return -1; +} +static +spine_bone_t *find_bone(spine_t *s, const char *bone_name) { + int bone_id = find_bone_id(s, bone_name); + return bone_id >= 0 ? &s->bones[bone_id] : NULL; +} + +void spine_skin(spine_t *p, unsigned skin) { + if( !p->texture.id ) return; + if( skin >= array_count(p->skins) ) return; + + p->skin = skin; + + char *skin_name = va("%s/", p->skins[skin].name); + int header = strlen(skin_name); + + for( int i = 0; i < array_count(p->atlas); ++i) { + if(!strbeg(p->atlas[i].name, skin_name)) continue; + + int bone_id = find_bone_id(p, p->atlas[i].name+header ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].atlas_id = i; + } + + for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { + int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].rect_id = i; + } +} + +static +bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { + char *atlas = vfs_read(file_atlas); + if(!atlas || !atlas[0]) return false; + + memset(t, 0, sizeof(spine_t)); + + // goblins.png + // size: 1024, 128 + // filter: Linear, Linear + // pma: true + // dagger + // bounds: 2, 18, 26, 108 + // goblin/eyes-closed + // bounds: 2, 4, 34, 12 + spine_atlas_t *sa = 0; + const char *last_id = 0; + const char *texture_name = 0; + const char *texture_filter = 0; + const char *texture_format = 0; + const char *texture_repeat = 0; + float texture_width = 0, texture_height = 0, temp; + for each_substring(atlas, "\r\n", it) { + it += strspn(it, " \t\f\v"); + /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored + else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); + else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) + else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string + else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string + else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string + else if( strbeg(it, "bounds:" ) ) { + sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); + } + else if( !texture_name ) texture_name = va("%s", it); + else { + array_push(t->atlas, ((spine_atlas_t){0}) ); + sa = &t->atlas[array_count(t->atlas) - 1]; + sa->name = STRDUP(it); + } + } + for( int i = 0; i < array_count(t->atlas); ++i ) { + sa = &t->atlas[i]; + sa->x /= texture_width, sa->y /= texture_height; + sa->w /= texture_width, sa->h /= texture_height; + } + + if(!texture_name) return false; + + t->texture = texture(texture_name, TEXTURE_LINEAR); + + json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? + + array_resize(t->bones, json_count("/bones")); + array_reserve(t->slots, json_count("/slots")); + array_resize(t->skins, json_count("/skins")); + array_resize(t->anims, json_count("/animations")); + + for( int i = 0, end = json_count("/bones"); i < end; ++i ) { + spine_bone_t v = {0}; + v.name = STRDUP(json_string("/bones[%d]/name", i)); + v.parent = STRDUP(json_string("/bones[%d]/parent", i)); + v.x = json_float("/bones[%d]/x", i); + v.y = json_float("/bones[%d]/y", i); + v.z = i; + v.len = json_float("/bones[%d]/length", i); + v.deg = json_float("/bones[%d]/rotation", i); + t->bones[i] = v; + + for( int j = i-1; j > 0; --j ) { + if( strcmp(t->bones[j].name,v.parent) ) continue; + t->bones[i].parent_bone = &t->bones[j]; + break; + } + } + + for( int i = 0, end = json_count("/slots"); i < end; ++i ) { + spine_slot_t v = {0}; + v.name = STRDUP(json_string("/slots[%d]/name", i)); + v.bone = STRDUP(json_string("/slots[%d]/bone", i)); + v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); + + array_push(t->slots, v); + + // slots define draw-order. so, update draw-order/zindex in bone + spine_bone_t *b = find_bone(t, v.name); + if( b ) b->z = i; + } + + for( int i = 0, end = json_count("/skins"); i < end; ++i ) { + spine_skin_t v = {0}; + v.name = STRDUP(json_string("/skins[%d]/name", i)); + + for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ + for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ + spine_rect_t r = {0}; + r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); + r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); + r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); + r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; + r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; + r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); + r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); + r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); + array_push(v.rects, r); + } + + t->skins[i] = v; + } + +#if 1 + // simplify: + // merge /skins/default into existing /skins/*, then delete /skins/default + if( array_count(t->skins) > 1 ) { + for( int i = 1; i < array_count(t->skins); ++i ) { + for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { + array_push(t->skins[i].rects, t->skins[0].rects[j]); + } + } + // @leak @fixme: FREE(t->skins[0]) + for( int i = 0; i < array_count(t->skins)-1; ++i ) { + t->skins[i] = t->skins[i+1]; + } + array_pop(t->skins); + } +#endif + + for( int i = 0, end = json_count("/animations"); i < end; ++i ) { + int id; + const char *name; + + spine_anim_t v = {0}; + v.name = STRDUP(json_key("/animations[%d]", i)); + + // slots / attachments + + for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) + for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids + { + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + spine_animkey_t key = {0}; + + key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); + key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); + } + + // @todo: convert name to id + // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) + // printf("%s vs %s\n", key.name, t->bones[id].name); + + array_push(v.attach_keys[bone_id], key); + } + } + + // bones + + for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones + for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + // parse bones + for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); + int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; + if( !track ) continue; + + spine_animkey_t key = {0}; + + key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); + } + + if( track == 1 ) + key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" + array_push(v.rotate_keys[bone_id], key); + else + key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), + key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), + array_push(v.translate_keys[bone_id], key); + } + } + + t->anims[i] = v; + } + + json_pop(); + + spine_skin(t, 0); + + return true; +} + +spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { + spine_t *t = MALLOC(sizeof(spine_t)); + if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; + return t; +} + +void spine_render(spine_t *p, vec3 offset, unsigned flags) { + if( !p->texture.id ) return; + if( !flags ) return; + + ddraw_push_2d(); + // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); + // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); + + // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches + + for( int i = 1; i < array_count(p->bones); ++i ) { + spine_bone_t *self = &p->bones[i]; + if( !self->rect_id ) continue; + + int num_bones = 0; + static array(spine_bone_t*) chain = 0; array_resize(chain, 0); + for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { + array_push(chain, next); + } + + vec3 target = {0}, prev = {0}; + for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction + int j_opposite = end - 1 - j; + + spine_bone_t *b = chain[j_opposite]; // bone + spine_bone_t *pb = b->parent_bone; // parent bone + + float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; + if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; + + const float deg2rad = C_PI / 180; + b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); + b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); + b->deg2 = -b->deg3 + pb_deg2 - b->deg; + + prev = target; + target = vec3(b->x2,b->y2,b->deg2); + } + + target.z = 0; + target = add3(target, offset); + prev.z = 0; + prev = add3(prev, offset); + + if( flags & 2 ) { + ddraw_point( target ); + ddraw_text( target, -0.25f, self->name ); + ddraw_bone( prev, target ); // from parent to bone + } + if( flags & 1 ) { + spine_atlas_t *a = &p->atlas[self->atlas_id]; + spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; + + vec4 rect = ptr4(&a->x); + float zindex = self->z; + float offsx = 0; + float offsy = 0; + float tilt = self->deg2 + (a->deg - r->deg); + unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; + + if( 1 ) { + vec3 dir = vec3(r->x,r->y,0); + dir = rotatez3(dir, self->deg2); + offsx = dir.x * r->sx; + offsy = dir.y * r->sy; + } + + sprite_rect(p->texture, rect, vec4(target.x,target.y,0,zindex), vec4(1,1,offsx,offsy), tilt, tint, 0); + } + } + + ddraw_pop_2d(); + ddraw_flush(); +} + +static +void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { + if( !p->texture.id ) return; + + if( delta > 1/120.f ) delta = 1/120.f; + if( *time >= *maxtime ) *time = 0; else *time += delta; + + // reset root // needed? + p->bones[0].x2 = 0; + p->bones[0].y2 = 0; + p->bones[0].deg2 = 0; + p->bones[0].x3 = 0; + p->bones[0].y3 = 0; + p->bones[0].deg3 = 0; + + for( int i = 0, end = array_count(p->bones); i < end; ++i) { + // @todo: attach channel + // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} + for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].deg3 = r->deg; + } + } + for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].x3 = r->x; + p->bones[i].y3 = r->y; + } + } + } +} + +void spine_animate(spine_t *p, float delta) { + spine_animate_(p, &p->time, &p->maxtime, delta); +} + +void ui_spine(spine_t *p) { + if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { + for each_array_ptr(p->anims, spine_anim_t, q) { + if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { + spine_animate(p, 0); + } + + int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); + if( choice == 1 ) window_pause( 0 ); // play + if( choice == 2 ) window_pause( 1 ); // pause + + for( int i = 0; i < SPINE_MAX_BONES; ++i ) { + ui_separator(); + ui_label(va("Bone %d: Attachment keys", i)); + for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); + } + ui_label(va("Bone %d: Rotate keys", i)); + for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); + } + ui_label(va("Bone %d: Translate keys", i)); + for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); + } + } + } + ui_collapse_end(); + } + if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { + for each_array_ptr(p->bones, spine_bone_t, q) + if( ui_collapse(q->name, va("%p-b2", q)) ) { + ui_label2("Parent:", q->parent); + ui_label2("X:", va("%.2f", q->x)); + ui_label2("Y:", va("%.2f", q->y)); + ui_label2("Length:", va("%.2f", q->len)); + ui_label2("Rotation:", va("%.2f", q->deg)); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { + for each_array_ptr(p->slots, spine_slot_t, q) + if( ui_collapse(q->name, va("%p-s2", q)) ) { + ui_label2("Bone:", q->bone); + ui_label2("Attachment:", q->attach); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { + for each_array_ptr(p->skins, spine_skin_t, q) + if( ui_collapse(q->name, va("%p-k2", q)) ) { + for each_array_ptr(q->rects, spine_rect_t, r) + if( ui_collapse(r->name, va("%p-k3", r)) ) { + ui_label2("X:", va("%.2f", r->x)); + ui_label2("Y:", va("%.2f", r->y)); + ui_label2("Scale X:", va("%.2f", r->sx)); + ui_label2("Scale Y:", va("%.2f", r->sy)); + ui_label2("Width:", va("%.2f", r->w)); + ui_label2("Height:", va("%.2f", r->h)); + ui_label2("Rotation:", va("%.2f", r->deg)); + ui_collapse_end(); + + spine_bone_t *b = find_bone(p, r->name); + if( b ) { + p->debug_atlas_id = b->atlas_id; + + static float tilt = 0; + if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; + spine_atlas_t *r = p->atlas + b->atlas_id; + sprite_flush(); + camera_get_active()->position = vec3(0,0,2); + vec4 rect = ptr4(&r->x); float zindex = 0; vec4 scale_offset = vec4(1,1,0,0); + sprite_rect(p->texture, ptr4(&r->x), vec4(0,0,0,zindex), scale_offset, r->deg + tilt, ~0u, 0); + sprite_flush(); + camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); + } + } + ui_collapse_end(); + } + ui_collapse_end(); + } + + if( ui_int("Use skin", &p->skin) ) { + p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); + spine_skin(p, p->skin); + } + + if( p->texture.id ) ui_texture(0, p->texture); +} + +// ---------------------------------------------------------------------------- + +// texture_t texture_createclip(unsigned cx,unsigned cy,unsigned cw,unsigned ch, unsigned tw,unsigned th,unsigned tn,void *pixels, unsigned flags) { +// return texture_create(tw,th,tn,pixels,flags); +// static array(unsigned) clip = 0; +// array_resize(clip, cw*ch*4); +// for( unsigned y = 0; y < ch; ++y ) +// memcpy((char *)clip + (0+(0+y)*cw)*tn, (char*)pixels + (cx+(cy+y)*tw)*tn, cw*tn); +// return texture_create(cw,ch,tn,clip,flags); +// } + +typedef unsigned quark_t; + +#define array_reserve_(arr,x) (array_count(arr) > (x) ? (arr) : array_resize(arr, 1+(x))) + +#define ui_array(label,type,ptr) do { \ + int changed = 0; \ + if( ui_collapse(label, va(#type "%p",ptr)) ) { \ + char label_ex[8]; \ + for( int idx = 0, iend = array_count(*(ptr)); idx < iend; ++idx ) { \ + type* it = *(ptr) + idx; \ + snprintf(label_ex, sizeof(label_ex), "[%d]", idx); \ + changed |= ui_##type(label_ex, it); \ + } \ + ui_collapse_end(); \ + } \ +} while(0) + +int ui_vec2i(const char *label, vec2i *v) { return ui_unsigned2(label, (unsigned*)v); } +int ui_vec3i(const char *label, vec3i *v) { return ui_unsigned3(label, (unsigned*)v); } +int ui_vec2(const char *label, vec2 *v) { return ui_float2(label, (float*)v); } +int ui_vec3(const char *label, vec3 *v) { return ui_float3(label, (float*)v); } +int ui_vec4(const char *label, vec4 *v) { return ui_float4(label, (float*)v); } + +char *trimspace(char *str) { + for( char *s = str; *s; ++s ) + if(*s <= 32) memmove(s, s+1, strlen(s)); + return str; +} + +char *file_parent(const char *f) { // folder/folder/abc + char *p = file_path(f); // folder/folder/ + char *last = strrchr(p, '/'); // ^ + if( !last ) return p; // return parent if no sep + *last = '\0'; // folder/folder + last = strrchr(p, '/'); // ^ + return last ? last + 1 : p; // return parent if no sep +} + +int ui_obj(const char *fmt, obj *o) { + int changed = 0, item = 1; + for each_objmember(o, TYPE,NAME,PTR) { + char *label = va(fmt, NAME); + /**/ if(!strcmp(TYPE,"float")) { if(ui_float(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"int")) { if(ui_int(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"unsigned")) { if(ui_unsigned(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec2")) { if(ui_float2(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec3")) { if(ui_float3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec4")) { if(ui_float4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgb")) { if(ui_color3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgba")) { if(ui_color4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color3f")) { if(ui_color3f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color4f")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"char*")) { if(ui_string(label, PTR)) changed = item; } + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + ++item; + } + return changed; +} + +#define OBJTYPEDEF2(...) OBJTYPEDEF(__VA_ARGS__); AUTORUN + +// ---------------------------------------------------------------------------- +// atlas + +typedef struct atlas_frame_t { + unsigned delay; + vec4 sheet; + vec2 anchor; // @todo + array(vec3i) indices; + array(vec2) coords; + array(vec2) uvs; +} atlas_frame_t; + +typedef struct atlas_anim_t { + quark_t name; + array(unsigned) frames; +} atlas_anim_t; + +typedef struct atlas_t { + texture_t tex; + + array(atlas_frame_t) frames; + array(atlas_anim_t) anims; + + quarks_db db; +} atlas_t; + +int ui_atlas_frame(atlas_frame_t *f) { + ui_unsigned("delay", &f->delay); + ui_vec4("sheet", &f->sheet); + ui_array("indices", vec3i, &f->indices); + ui_array("coords", vec2, &f->coords); + ui_array("uvs", vec2, &f->uvs); + return 0; +} + +int ui_atlas(atlas_t *a) { + int changed = 0; + ui_texture(NULL, a->tex); + for( int i = 0; i < array_count(a->anims); ++i ) { + if( ui_collapse(quark_string(&a->db, a->anims[i].name), va("%p%d", a, a->anims[i].name) ) ) { + changed = i+1; + for( int j = 0; j < array_count(a->anims[i].frames); ++j ) { + if( ui_collapse(va("[%d]",j), va("%p%d.%d", a, a->anims[i].name,j) ) ) { + ui_unsigned("Frame", &a->anims[i].frames[j]); + ui_atlas_frame(a->frames + a->anims[i].frames[j]); + ui_collapse_end(); + } + } + ui_collapse_end(); + } + } + return changed; +} + +void atlas_destroy(atlas_t *a) { + if( a ) { + texture_destroy(&a->tex); + memset(a, 0, sizeof(atlas_t)); + } +} +atlas_t atlas_create(const char *inifile, unsigned flags) { + atlas_t a = {0}; + int padding = 0, border = 0; + + ini_t kv = ini(inifile); + for each_map(kv, char*,k, char*,v ) { + unsigned index = atoi(k); + /**/ if( strend(k, ".name") ) { + array_reserve_(a.anims, index); + + a.anims[index].name = quark_intern(&a.db, v); + } + else if( strend(k, ".frames") ) { + array_reserve_(a.anims, index); + + array(char*) pairs = strsplit(v, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned frame = atoi(pairs[i]); + unsigned delay = atoi(pairs[i+1]); + + array_reserve_(a.frames, frame); + a.frames[frame].delay = delay; + + array_push(a.anims[index].frames, frame); + } + } + else if( strend(k, ".sheet") ) { + array_reserve_(a.frames, index); + + vec4 sheet = atof4(v); //x,y,x2+2,y2+2 -> x,y,w,h (for 2,2 padding) + a.frames[index].sheet = vec4(sheet.x,sheet.y,sheet.z-sheet.x,sheet.w-sheet.y); + } + else if( strend(k, ".indices") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) tuples = strsplit(text, ","); + for( int i = 0, end = array_count(tuples); i < end; i += 3 ) { + unsigned p1 = atoi(tuples[i]); + unsigned p2 = atoi(tuples[i+1]); + unsigned p3 = atoi(tuples[i+2]); + array_push(a.frames[index].indices, vec3i(p1,p2,p3)); + } + } + else if( strend(k, ".coords") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned x = atoi(pairs[i]); + unsigned y = atoi(pairs[i+1]); + array_push(a.frames[index].coords, vec2(x,y)); + } + } + else if( strend(k, ".uvs") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned u = atoi(pairs[i]); + unsigned v = atoi(pairs[i+1]); + array_push(a.frames[index].uvs, vec2(u,v)); + } + } + else if( strend(k, "padding") ) { + padding = atoi(v); + } + else if( strend(k, "border") ) { + border = atoi(v); + } + else if( strend(k, "file") ) { + a.tex = texture(v, 0); + } + else if( strend(k, "bitmap") ) { + const char *text = v; + array(char) bin = base64_decode(text, strlen(text)); + a.tex = texture_from_mem(bin, array_count(bin), 0); + array_free(bin); + } +#if 0 + else if( strend(k, ".frame") ) { + array_reserve_(a.frames, index); + puts(k), puts(v); + } +#endif + } + + // post-process: normalize uvs and coords into [0..1] ranges + for each_array_ptr(a.frames, atlas_frame_t, f) { + for each_array_ptr(f->uvs, vec2, uv) { + uv->x /= a.tex.w; + uv->y /= a.tex.h; + } + for each_array_ptr(f->coords, vec2, xy) { + xy->x /= a.tex.w; + xy->y /= a.tex.h; + } + // @todo: adjust padding/border + } +#if 0 + // post-process: specify an anchor for each anim based on 1st frame dims + for each_array_ptr(a.anims, atlas_anim_t, anim) { + atlas_frame_t *first = a.frames + *anim->frames; + for( int i = 0; i < array_count(anim->frames); i += 2) { + atlas_frame_t *ff = a.frames + anim->frames[ i ]; + ff->anchor.x = (ff->sheet.z - first->sheet.z) / 2; + ff->anchor.y = (ff->sheet.w - first->sheet.w) / 2; + } + } +#endif + + return a; +} + +// ---------------------------------------------------------------------------- +// sprite v2 + +void sprite_ctor(sprite_t *s) { + s->tint = WHITE; + s->timer_ms = 100; + s->flipped = 1; + s->sca.x += !s->sca.x; + s->sca.y += !s->sca.y; +} +void sprite_dtor(sprite_t *s) { + memset(s, 0, sizeof(*s)); +} +void sprite_tick(sprite_t *s) { + int right = input(s->gamepad.array[3]) - input(s->gamepad.array[2]); // RIGHT - LEFT + int forward = input(s->gamepad.array[1]) - input(s->gamepad.array[0]); // DOWN - UP + int move = right || forward; + int dt = 16; // window_delta() * 1000; + + unsigned over = (s->timer - dt) > s->timer; + if(!s->paused) s->timer -= dt; + if( over ) { + int len = array_count(s->a->anims[s->play].frames); + unsigned next = (s->frame + 1) % (len + !len); + unsigned eoa = next < s->frame; + s->frame = next; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + s->timer_ms = f->delay; + s->timer += s->timer_ms; + } + + if( s->play == 0 && move ) sprite_setanim(s, 1); + if( s->play == 1 ) { //< + if(right) s->flip_ = right < 0, sprite_setanim(s, 1); + if(!right && !forward) sprite_setanim(s, 0); + + float speed = s->sca.x*2; + s->pos = add4(s->pos, scale4(norm4(vec4(right,0,forward,0)),speed)); + } +} +void sprite_draw(sprite_t *s) { + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + +#if 1 + // @todo { + unsigned sample = s->a->anims[s->play].frames[s->frame]; + sample = 0; + f->anchor.x = (-s->a->frames[sample].sheet.z + f->sheet.z) / 2; + f->anchor.y = (+s->a->frames[sample].sheet.w - f->sheet.w) / 2; + // } +#endif + + // rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scale), rotation (degrees), color (rgba) + vec4 rect = { f->sheet.x / s->a->tex.w, f->sheet.y / s->a->tex.h, f->sheet.z / s->a->tex.w, f->sheet.w / s->a->tex.h }; + sprite_rect(s->a->tex, rect, s->pos, vec4(s->flip_ ^ s->flipped?s->sca.x:-s->sca.x,s->sca.y,f->anchor.x,f->anchor.y), s->tilt, s->tint, 0|SPRITE_PROJECTED); +} +void sprite_edit(sprite_t *s) { + const char *name = obj_name(s); + const char *id = vac("%p", s); + if( s && ui_collapse(name ? name : id, id) ) { + ui_obj("%s", (obj*)s); + + ui_bool("paused", &s->paused); + ui_label(va("frame anim [%d]", s->a->anims[s->play].frames[s->frame])); + + int k = s->play; + if( ui_int("anim", &k) ) { + sprite_setanim(s, k); + } + + int selected = ui_atlas(s->a); + if( selected ) sprite_setanim(s, selected - 1); + + ui_collapse_end(); + } +} + +sprite_t* sprite_new(const char *ase, int bindings[6]) { + sprite_t *s = obj_new(sprite_t, {bindings[0],bindings[1],bindings[2],bindings[3]}, {bindings[4],bindings[5]}); + atlas_t own = atlas_create(ase, 0); + memcpy(s->a = MALLOC(sizeof(atlas_t)), &own, sizeof(atlas_t)); // s->a = &s->own; + return s; +} +void sprite_del(sprite_t *s) { + if( s ) { + if( s->a ) atlas_destroy(s->a), FREE(s->a); // if( s->a == &s->own ) + obj_free(s); + memset(s, 0, sizeof(sprite_t)); + } +} +void sprite_setanim(sprite_t *s, unsigned name) { + if( s->play != name ) { + s->play = name; + s->frame = 0; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + + s->timer_ms = f->delay; + s->timer = s->timer_ms; + } +} + +AUTORUN { + STRUCT(sprite_t, vec4, pos); + STRUCT(sprite_t, vec2, sca); + STRUCT(sprite_t, float, tilt); + STRUCT(sprite_t, vec4, gamepad); + STRUCT(sprite_t, vec2, fire); + STRUCT(sprite_t, rgba, tint); + STRUCT(sprite_t, unsigned, frame); + STRUCT(sprite_t, unsigned, timer); + STRUCT(sprite_t, unsigned, timer_ms); + STRUCT(sprite_t, unsigned, flipped); + STRUCT(sprite_t, unsigned, play); + EXTEND_T(sprite, ctor,edit,draw,tick); +} diff --git a/engine/split/v4k_sprite.h b/engine/split/v4k_sprite.h new file mode 100644 index 0000000..97c5a5e --- /dev/null +++ b/engine/split/v4k_sprite.h @@ -0,0 +1,114 @@ +// ----------------------------------------------------------------------------- +// sprites + +typedef enum SPRITE_FLAGS { + SPRITE_PROJECTED = 1, + SPRITE_ADDITIVE = 2, + SPRITE_CENTERED = 4, + SPRITE_RESOLUTION_INDEPENDANT = 128, +} SPRITE_FLAGS; + +// texture id, position(x,y,depth sort), tint color, rotation angle +API void sprite( texture_t texture, float position[3], float rotation /*0*/, unsigned color /*~0u*/, unsigned flags); + +// texture id, rect(x,y,w,h) is [0..1] normalized, then: pos(xyz,z-index), (scale.xy,offset.xy), rotation (degrees), color (rgba) +API void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scaleoff, float tilt_deg, unsigned tint_rgba, unsigned flags); + +// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color +API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags); + +API void sprite_flush(); + +// ----------------------------------------------------------------------------- +// tilemaps + +typedef struct tileset_t { + texture_t tex; // spritesheet + unsigned tile_w, tile_h; // dimensions per tile in pixels + unsigned cols, rows; // tileset num_cols, num_rows + unsigned selected; // active tile (while editing) +} tileset_t; + +API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); + +API int ui_tileset( tileset_t t ); + +typedef struct tilemap_t { + int blank_chr; // transparent tile + unsigned cols, rows; // map dimensions (in tiles) + array(int) map; + + vec3 position; // x,y,scale + float zindex; + float tilt; + unsigned tint; + bool is_additive; +} tilemap_t; + +API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); +API void tilemap_render( tilemap_t m, tileset_t style ); +API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); + +// ----------------------------------------------------------------------------- +// tiled maps + +typedef struct tiled_t { + char *map_name; + unsigned first_gid, tilew, tileh, w, h; + + bool parallax; + vec3 position; + array(bool) visible; + array(tilemap_t) layers; + array(tileset_t) sets; + array(char*) names; +} tiled_t; + +API tiled_t tiled(const char *file_tmx); +API void tiled_render(tiled_t tmx, vec3 pos); + +API void ui_tiled(tiled_t *t); + +// ----------------------------------------------------------------------------- +// spines + +typedef struct spine_t spine_t; + +API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); +API void spine_skin(spine_t *p, unsigned skin); +API void spine_render(spine_t *p, vec3 offset, unsigned flags); +API void spine_animate(spine_t *p, float delta); + +API void ui_spine(spine_t *p); + +// ---------------------------------------------------------------------------- +// sprite v2 api + +typedef struct sprite_t { OBJ + vec4 gamepad; // up,down,left,right + vec2 fire; // a,b + + vec4 pos; + vec2 sca; + float tilt; + unsigned tint; + unsigned frame; + unsigned timer, timer_ms; + unsigned flip_, flipped; + unsigned play; + bool paused; + // array(unsigned) play_queue; or unsigned play_next; + struct atlas_t *a; // shared + //atlas_t own; // owned +} sprite_t; + +OBJTYPEDEF(sprite_t,10); +API void sprite_ctor(sprite_t *s); +API void sprite_dtor(sprite_t *s); +API void sprite_tick(sprite_t *s); +API void sprite_draw(sprite_t *s); +API void sprite_edit(sprite_t *s); + +API sprite_t*sprite_new(const char *ase, int bindings[6]); +API void sprite_del(sprite_t *s); +API void sprite_setanim(sprite_t *s, unsigned name); diff --git a/engine/split/v4k_string.c b/engine/split/v4k_string.c index f185c28..addce48 100644 --- a/engine/split/v4k_string.c +++ b/engine/split/v4k_string.c @@ -418,3 +418,152 @@ AUTORUN { test( !strcmp("Hello happy world.", buf) ); } #endif + +// ---------------------------------------------------------------------------- +// localization kit + +static const char *kit_lang = "enUS", *kit_langs = + "enUS,enGB," + "frFR," + "esES,esAR,esMX," + "deDE,deCH,deAT," + "itIT,itCH," + "ptBR,ptPT," + "zhCN,zhSG,zhTW,zhHK,zhMO," + "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," + "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" +; + +static map(char*,char*) kit_ids; +static map(char*,char*) kit_vars; + +#ifndef KIT_FMT_ID2 +#define KIT_FMT_ID2 "%s.%s" +#endif + +void kit_init() { + do_once map_init(kit_ids, less_str, hash_str); + do_once map_init(kit_vars, less_str, hash_str); +} + +void kit_insert( const char *id, const char *translation) { + char *id2 = va(KIT_FMT_ID2, kit_lang, id); + + char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); + if(*found) FREE(*found); + *found = STRDUP(translation); +} + +bool kit_merge( const char *filename ) { + // @todo: xlsx2ini + return false; +} + +void kit_clear() { + map_clear(kit_ids); +} + +bool kit_load( const char *filename ) { + return kit_clear(), kit_merge( filename ); +} + +void kit_set( const char *key, const char *value ) { + value = value && value[0] ? value : ""; + + char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); + if(*found) FREE(*found); + *found = STRDUP(value); +} + +void kit_reset() { + map_clear(kit_vars); +} + +char *kit_translate2( const char *id, const char *lang ) { + char *id2 = va(KIT_FMT_ID2, lang, id); + + char **found = map_find(kit_ids, id2); + + // return original [[ID]] if no translation is found + if( !found ) return va("[[%s]]", id); + + // return translation if no {{moustaches}} are found + if( !strstr(*found, "{{") ) return *found; + + // else replace all found {{moustaches}} with context vars + { + // make room + static __thread char *results[16] = {0}; + static __thread unsigned counter = 0; counter = (counter+1) % 16; + + char *buffer = results[ counter ]; + if( buffer ) FREE(buffer), buffer = 0; + + // iterate moustaches + const char *begin, *end, *text = *found; + while( NULL != (begin = strstr(text, "{{")) ) { + end = strstr(begin+2, "}}"); + if( end ) { + char *var = va("%.*s", (int)(end - (begin+2)), begin+2); + char **found_var = map_find(kit_vars, var); + + if( found_var && 0[*found_var] ) { + strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); + } else { + strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); + } + + text = end+2; + } else { + strcatf(&buffer, "%.*s", (int)(begin - text), text); + + text = begin+2; + } + } + + strcatf(&buffer, "%s", text); + return buffer; + } +} + +char *kit_translate( const char *id ) { + return kit_translate2( id, kit_lang ); +} + +void kit_locale( const char *lang ) { + kit_lang = STRDUP(lang); // @leak +} + +void kit_dump_state( FILE *fp ) { + for each_map(kit_ids, char *, k, char *, v) { + fprintf(fp, "[ID ] %s=%s\n", k, v); + } + for each_map(kit_vars, char *, k, char *, v) { + fprintf(fp, "[VAR] %s=%s\n", k, v); + } +} + +/* +int main() { + kit_init(); + + kit_locale("enUS"); + kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Nice to meet you."); + + kit_locale("esES"); + kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Un placer conoceros."); + + kit_locale("enUS"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. + + kit_locale("esES"); + kit_set("PLAYER1", "John"); + kit_set("PLAYER2", "Karl"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. + + assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] + assert(~puts("Ok")); +} +*/ diff --git a/engine/split/v4k_string.h b/engine/split/v4k_string.h index 439f962..44b97fe 100644 --- a/engine/split/v4k_string.h +++ b/engine/split/v4k_string.h @@ -90,3 +90,20 @@ typedef struct quarks_db { API unsigned quark_intern( quarks_db*, const char *string ); API const char *quark_string( quarks_db*, unsigned key ); + +// ----------------------------------------------------------------------------- +// ## localization kit (I18N, L10N) + +API bool kit_load( const char *filename ); // load translations file (xlsx) +API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit +API void kit_clear(); // delete all translations + +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + +API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale + +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale diff --git a/engine/split/v4k_system.c b/engine/split/v4k_system.c index b378e89..bb4f446 100644 --- a/engine/split/v4k_system.c +++ b/engine/split/v4k_system.c @@ -200,8 +200,8 @@ static char **backtrace_symbols(void *const *list,int size) { static __thread char **symbols = 0; //[32][64] = {0}; if( !symbols ) { - symbols = SYS_REALLOC(0, 128 * sizeof(char*)); - for( int i = 0; i < 128; ++i) symbols[i] = SYS_REALLOC(0, 128 * sizeof(char)); + symbols = SYS_MEM_REALLOC(0, 128 * sizeof(char*)); + for( int i = 0; i < 128; ++i) symbols[i] = SYS_MEM_REALLOC(0, 128 * sizeof(char)); } if(size > 128) size = 128; @@ -234,7 +234,7 @@ static char **backtrace_symbols(void *const *sym,int num) { return 0; } char *callstack( int traces ) { static __thread char *output = 0; - if(!output ) output = SYS_REALLOC( 0, 128 * (64+2) ); + if(!output ) output = SYS_MEM_REALLOC( 0, 128 * (64+2) ); if( output ) output[0] = '\0'; char *ptr = output; @@ -793,7 +793,7 @@ int (PRINTF)(const char *text, const char *stack, const char *file, int line, co static void *panic_oom_reserve; // for out-of-memory recovery int (PANIC)(const char *error, const char *file, int line) { - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 0); + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 0); tty_color(RED); diff --git a/engine/split/v4k_ui.c b/engine/split/v4k_ui.c index 4e75c69..ae60b9f 100644 --- a/engine/split/v4k_ui.c +++ b/engine/split/v4k_ui.c @@ -1901,8 +1901,8 @@ int ui_color4f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3] }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), clampf(color[3],0,1) }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), clampf(after.a,0,1) }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -1989,8 +1989,8 @@ int ui_color3f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, ui_alpha }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), 1 }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), ui_alpha }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -2033,7 +2033,7 @@ int ui_color3(const char *label, unsigned *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { r*ui_alpha, g*ui_alpha, b*ui_alpha, 1 }, before = after; + struct nk_colorf after = { r*ui_alpha/255, g*ui_alpha/255, b*ui_alpha/255, ui_alpha }, before = after; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(after), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -2695,8 +2695,10 @@ int ui_demo(int do_windows) { static float float2[2] = {1,2}; static float float3[3] = {1,2,3}; static float float4[4] = {1,2,3,4}; - static float rgb[3] = {0.84,0.67,0.17}; - static float rgba[4] = {0.67,0.90,0.12,1}; + static float rgbf[3] = {0.84,0.67,0.17}; + static float rgbaf[4] = {0.67,0.90,0.12,1}; + static unsigned rgb = CYAN; + static unsigned rgba = PINK; static float slider = 0.5f; static float slider2 = 0.5f; static char string[64] = "hello world 123"; @@ -2740,8 +2742,10 @@ int ui_demo(int do_windows) { if( ui_list("my list", list, 3, &item ) ) puts("list changed"); if( ui_section("Colors")) {} - if( ui_color3f("my color3", rgb) ) puts("color3 changed"); - if( ui_color4f("my color4@this is a tooltip", rgba) ) puts("color4 changed"); + if( ui_color3("my color3", &rgb) ) puts("color3 changed"); + if( ui_color4("my color4@this is a tooltip", &rgba) ) puts("color4 changed"); + if( ui_color3f("my color3f", rgbf) ) puts("color3f changed"); + if( ui_color4f("my color4f@this is a tooltip", rgbaf) ) puts("color4f changed"); if( ui_section("Sliders")) {} if( ui_slider("my slider", &slider)) puts("slider changed"); diff --git a/engine/split/v4k_window.c b/engine/split/v4k_window.c index 0d19068..1a21661 100644 --- a/engine/split/v4k_window.c +++ b/engine/split/v4k_window.c @@ -424,7 +424,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) { #define ddraw_progress_bar(JOB_ID, JOB_MAX, PERCENT) do { \ /* NDC coordinates (2d): bottom-left(-1,-1), center(0,0), top-right(+1,+1) */ \ float progress = (PERCENT+1) / 100.f; if(progress > 1) progress = 1; \ - float speed = progress < 1 ? 0.2f : 0.5f; \ + float speed = progress < 1 ? 0.05f : 0.75f; \ float smooth = previous[JOB_ID] = progress * speed + previous[JOB_ID] * (1-speed); \ \ float pixel = 2.f / window_height(), dist = smooth*2-1, y = pixel*3*JOB_ID; \ diff --git a/engine/v4k b/engine/v4k index e6fe7cf..41bc0c4 100644 --- a/engine/v4k +++ b/engine/v4k @@ -6,7 +6,7 @@ #define GLAD_GL_IMPLEMENTATION // glad #endif -#line 1 "engine/split/3rd_glad.h" +#line 1 "3rd_glad.h" #ifndef __EMSCRIPTEN__ #ifndef _GNU_SOURCE // juicy linux headers @@ -11688,7 +11688,7 @@ int gladLoadGL( GLADloadfunc load) { #endif /* __EMSCRIPTEN__ */ #line 0 -#line 1 "engine/split/3rd_icon_md.h" +#line 1 "3rd_icon_md.h" // Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++ // from https://github.com/google/material-design-icons/raw/master/font/MaterialIcons-Regular.codepoints // for use with https://github.com/google/material-design-icons/blob/master/font/MaterialIcons-Regular.ttf @@ -14032,7 +14032,7 @@ errno_t fopen_s( #endif //--- -#line 1 "engine/split/3rd_glfw3.h" +#line 1 "3rd_glfw3.h" #ifndef __EMSCRIPTEN__ // forked from https://github.com/SasLuca/glfw-single-header (CC0-1.0 licensed) @@ -53229,7 +53229,7 @@ uint32_t _glfwKeySym2Unicode(unsigned int keysym) #line 0 #undef timeGetTime //--- -#line 1 "engine/split/3rd_swrap.h" +#line 1 "3rd_swrap.h" // https://github.com/BareRose/swrap/blob/master/swrap.h /* @@ -53522,7 +53522,7 @@ SWDEF int swrapMultiSelect (int* socks, size_t socks_size, double timeout) { #endif //SWRAP_H #line 0 //--- -#line 1 "engine/split/3rd_jo_mp1.h" +#line 1 "3rd_jo_mp1.h" /* public domain Simple, Minimalistic MPEG Layer 1 decoder - http://jonolick.com * * Revision History: @@ -53933,7 +53933,7 @@ bool jo_read_mp1(const void *input, int inputSize, short **output_, int *outputS #line 0 #define get_bits stb_vorbis_get_bits #define error stb_vorbis_error -#line 1 "engine/split/3rd_stb_vorbis.h" +#line 1 "3rd_stb_vorbis.h" // Ogg Vorbis audio decoder - v1.22 - public domain // http://nothings.org/stb_vorbis/ // @@ -59521,7 +59521,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #line 0 #undef error #undef DEBUG -#line 1 "engine/split/3rd_sts_mixer.h" +#line 1 "3rd_sts_mixer.h" /////////////////////////////////////////////////////////////////////////////// // sts_mixer.h - v0.02 // written 2016 by Sebastian Steinhauer @@ -60034,7 +60034,7 @@ int main(int argc, char *argv[]) { For more information, please refer to */ #line 0 -#line 1 "engine/split/3rd_miniaudio.h" +#line 1 "3rd_miniaudio.h" /* Audio playback and capture library. Choice of public domain or MIT-0. See license statements at the end of this file. miniaudio - v0.11.18 - 2023-08-07 @@ -152579,12 +152579,12 @@ SOFTWARE. #undef R #define error l_error #define panic l_panic -#line 1 "engine/split/3rd_lua.h" +#line 1 "3rd_lua.h" /* minilua.h -- Lua in a single header Project URL: https://github.com/edubart/minilua - This is Lua 5.4.4 contained in a single header to be bundled in C/C++ applications with ease. + This is Lua 5.4.6 contained in a single header to be bundled in C/C++ applications with ease. Lua is a powerful, efficient, lightweight, embeddable scripting language. Do the following in *one* C file to create the implementation: @@ -152604,7 +152604,7 @@ SOFTWARE. */ /* detect system platform */ -#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) +#if !defined(LUA_USE_WINDOWS) && !defined(LUA_USE_LINUX) && !defined(LUA_USE_MACOSX) && !defined(LUA_USE_POSIX) && !defined(LUA_USE_C89) && !defined(LUA_USE_IOS) #if defined(_WIN32) #define LUA_USE_WINDOWS #elif defined(__linux__) @@ -152740,6 +152740,12 @@ extern "C" { #endif +#if defined(LUA_USE_IOS) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN +#endif + + /* @@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. */ @@ -153398,7 +153404,7 @@ extern "C" { ** CHANGE it if you need a different limit. This limit is arbitrary; ** its only purpose is to stop Lua from consuming unlimited stack ** space (and to reserve some numbers for pseudo-indices). -** (It must fit into max(size_t)/32.) +** (It must fit into max(size_t)/32 and max(int)/2.) */ #if LUAI_IS32INT #define LUAI_MAXSTACK 1000000 @@ -153417,14 +153423,15 @@ extern "C" { /* @@ LUA_IDSIZE gives the maximum size for the description of the source -@@ of a function in debug information. +** of a function in debug information. ** CHANGE it if you want a different size. */ #define LUA_IDSIZE 60 /* -@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +@@ LUAL_BUFFERSIZE is the initial buffer size used by the lauxlib +** buffer system. */ #define LUAL_BUFFERSIZE ((int)(16 * sizeof(void*) * sizeof(lua_Number))) @@ -153474,14 +153481,14 @@ extern "C" { #define LUA_VERSION_MAJOR "5" #define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "4" +#define LUA_VERSION_RELEASE "6" #define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 4) +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 6) #define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR #define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2022 Lua.org, PUC-Rio" +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2023 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" @@ -153587,6 +153594,16 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); typedef void (*lua_WarnFunction) (void *ud, const char *msg, int tocont); +/* +** Type used by the debug API to collect debug information +*/ +typedef struct lua_Debug lua_Debug; + + +/* +** Functions to be called by the debugger in specific events +*/ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); /* @@ -153609,7 +153626,8 @@ extern const char lua_ident[]; LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); LUA_API void (lua_close) (lua_State *L); LUA_API lua_State *(lua_newthread) (lua_State *L); -LUA_API int (lua_resetthread) (lua_State *L); +LUA_API int (lua_closethread) (lua_State *L, lua_State *from); +LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); @@ -153898,12 +153916,6 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx); #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) -typedef struct lua_Debug lua_Debug; /* activation record */ - - -/* Functions to be called by the debugger in specific events */ -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); @@ -153948,7 +153960,7 @@ struct lua_Debug { /****************************************************************************** -* Copyright (C) 1994-2022 Lua.org, PUC-Rio. +* Copyright (C) 1994-2023 Lua.org, PUC-Rio. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -154326,6 +154338,7 @@ LUALIB_API void (luaL_openlibs) (lua_State *L); #endif #ifdef LUA_IMPL +typedef struct CallInfo CallInfo; /* ** $Id: llimits.h $ ** Limits, basic types, and some other 'installation-dependent' definitions @@ -154399,11 +154412,24 @@ typedef signed char ls_byte; /* -** conversion of pointer to unsigned integer: -** this is for hashing only; there is no problem if the integer -** cannot hold the whole pointer value +** conversion of pointer to unsigned integer: this is for hashing only; +** there is no problem if the integer cannot hold the whole pointer +** value. (In strict ISO C this may cause undefined behavior, but no +** actual machine seems to bother.) */ -#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(UINTPTR_MAX) /* even in C99 this type is optional */ +#define L_P2I uintptr_t +#else /* no 'intptr'? */ +#define L_P2I uintmax_t /* use the largest available integer */ +#endif +#else /* C89 option */ +#define L_P2I size_t +#endif + +#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX)) @@ -154747,6 +154773,8 @@ typedef union Value { lua_CFunction f; /* light C functions */ lua_Integer i; /* integer numbers */ lua_Number n; /* float numbers */ + /* not used, but may avoid warnings for uninitialized value */ + lu_byte ub; } Value; @@ -154850,6 +154878,17 @@ typedef union StackValue { /* index to stack elements */ typedef StackValue *StkId; + +/* +** When reallocating the stack, change all pointers to the stack into +** proper offsets. +*/ +typedef union { + StkId p; /* actual pointer */ + ptrdiff_t offset; /* used while the stack is being reallocated */ +} StkIdRel; + + /* convert a 'StackValue' to a 'TValue' */ #define s2v(o) (&(o)->val) @@ -155310,8 +155349,10 @@ typedef struct Proto { */ typedef struct UpVal { CommonHeader; - lu_byte tbc; /* true if it represents a to-be-closed variable */ - TValue *v; /* points to stack or to its own value */ + union { + TValue *p; /* points to stack or to its own value */ + ptrdiff_t offset; /* used while the stack is being reallocated */ + } v; union { struct { /* (when open) */ struct UpVal *next; /* linked list */ @@ -155597,6 +155638,7 @@ LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); /*#include "lobject.h"*/ +/*#include "lstate.h"*/ /* @@ -155683,8 +155725,8 @@ LUAI_FUNC int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, int inv, int isfloat, TMS event); LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams, - struct CallInfo *ci, const Proto *p); -LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, + CallInfo *ci, const Proto *p); +LUAI_FUNC void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted); @@ -155700,6 +155742,11 @@ LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci, /*#include "lua.h"*/ + +/* Some header files included here need this definition */ +typedef struct CallInfo CallInfo; + + /*#include "lobject.h"*/ /*#include "ltm.h"*/ /*#include "lzio.h"*/ @@ -155830,7 +155877,7 @@ struct lua_longjmp; /* defined in ldo.c */ #define BASIC_STACK_SIZE (2*LUA_MINSTACK) -#define stacksize(th) cast_int((th)->stack_last - (th)->stack) +#define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p) /* kinds of Garbage Collection */ @@ -155860,9 +155907,9 @@ typedef struct stringtable { ** - field 'transferinfo' is used only during call/returnhooks, ** before the function starts or after it ends. */ -typedef struct CallInfo { - StkId func; /* function index in the stack */ - StkId top; /* top for this function */ +struct CallInfo { + StkIdRel func; /* function index in the stack */ + StkIdRel top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ union { struct { /* only for Lua functions */ @@ -155887,7 +155934,7 @@ typedef struct CallInfo { } u2; short nresults; /* expected number of results from this function */ unsigned short callstatus; -} CallInfo; +}; /* @@ -155982,7 +156029,7 @@ typedef struct global_State { struct lua_State *mainthread; TString *memerrmsg; /* message for memory-allocation errors */ TString *tmname[TM_N]; /* array with tag-method names */ - struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ lua_WarnFunction warnf; /* warning function */ void *ud_warn; /* auxiliary data to 'warnf' */ @@ -155997,13 +156044,13 @@ struct lua_State { lu_byte status; lu_byte allowhook; unsigned short nci; /* number of items in 'ci' list */ - StkId top; /* first free slot in the stack */ + StkIdRel top; /* first free slot in the stack */ global_State *l_G; CallInfo *ci; /* call info for current function */ - StkId stack_last; /* end of stack (last element + 1) */ - StkId stack; /* stack base */ + StkIdRel stack_last; /* end of stack (last element + 1) */ + StkIdRel stack; /* stack base */ UpVal *openupval; /* list of open upvalues in this stack */ - StkId tbclist; /* list of to-be-closed variables */ + StkIdRel tbclist; /* list of to-be-closed variables */ GCObject *gclist; struct lua_State *twups; /* list of threads with open upvalues */ struct lua_longjmp *errorJmp; /* current error recover point */ @@ -156182,7 +156229,7 @@ iABC C(8) | B(8) |k| A(8) | Op(7) | iABx Bx(17) | A(8) | Op(7) | iAsBx sBx (signed)(17) | A(8) | Op(7) | iAx Ax(25) | Op(7) | -isJ sJ(25) | Op(7) | +isJ sJ (signed)(25) | Op(7) | A signed argument is represented in excess K: the represented value is the written unsigned value minus K, where K is half the maximum for the @@ -156581,7 +156628,7 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) /* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue(s2v((ci)->func))) +#define ci_func(ci) (clLvalue(s2v((ci)->func.p))) #define resethookcount(L) (L->hookcount = L->basehookcount) @@ -156637,6 +156684,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); #define ldo_h +/*#include "llimits.h"*/ /*#include "lobject.h"*/ /*#include "lstate.h"*/ /*#include "lzio.h"*/ @@ -156652,7 +156700,7 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); ** at every check. */ #define luaD_checkstackaux(L,n,pre,pos) \ - if (l_unlikely(L->stack_last - L->top <= (n))) \ + if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ { pre; luaD_growstack(L, n, 1); pos; } \ else { condmovestack(L,pre,pos); } @@ -156661,11 +156709,18 @@ LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc); -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((StkId)((char *)L->stack + (n))) +#define savestack(L,pt) (cast_charp(pt) - cast_charp(L->stack.p)) +#define restorestack(L,n) cast(StkId, cast_charp(L->stack.p) + (n)) /* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p), /* save 'p' */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* macro to check stack size and GC, preserving 'p' */ #define checkstackGCp(L,n,p) \ luaD_checkstackaux(L, n, \ ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ @@ -156687,7 +156742,8 @@ LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); LUAI_FUNC void luaD_hookcall (lua_State *L, CallInfo *ci); -LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta); +LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, + int narg1, int delta); LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); @@ -156880,24 +156936,27 @@ LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) -#define luaC_barrier(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) - -#define luaC_barrierback(L,p,v) ( \ - (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ - luaC_barrierback_(L,p) : cast_void(0)) - #define luaC_objbarrier(L,p,o) ( \ (isblack(p) && iswhite(o)) ? \ luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) +#define luaC_barrier(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrier(L,p,gcvalue(v)) : cast_void(0)) + +#define luaC_objbarrierback(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + iscollectable(v) ? luaC_objbarrierback(L, p, gcvalue(v)) : cast_void(0)) + LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, + size_t offset); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); @@ -156936,10 +156995,10 @@ LUAI_FUNC void luaC_changemode (lua_State *L, int newmode); #define MAXUPVAL 255 -#define upisopen(up) ((up)->v != &(up)->u.value) +#define upisopen(up) ((up)->v.p != &(up)->u.value) -#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v)) +#define uplevel(up) check_exp(upisopen(up), cast(StkId, (up)->v.p)) /* @@ -156961,7 +157020,7 @@ LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); -LUAI_FUNC void luaF_close (lua_State *L, StkId level, int status, int yy); +LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); LUAI_FUNC void luaF_unlinkupval (UpVal *uv); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, @@ -157076,23 +157135,26 @@ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, /*#include "lstate.h"*/ -/* Increments 'L->top', checking for stack overflows */ -#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} +/* Increments 'L->top.p', checking for stack overflows */ +#define api_incr_top(L) {L->top.p++; \ + api_check(L, L->top.p <= L->ci->top.p, \ + "stack overflow");} /* ** If a call returns too many multiple returns, the callee may not have ** stack space to accommodate all results. In this case, this macro -** increases its stack space ('L->ci->top'). +** increases its stack space ('L->ci->top.p'). */ #define adjustresults(L,nres) \ - { if ((nres) <= LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + { if ((nres) <= LUA_MULTRET && L->ci->top.p < L->top.p) \ + L->ci->top.p = L->top.p; } /* Ensure the stack has at least 'n' elements */ -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") +#define api_checknelems(L,n) \ + api_check(L, (n) < (L->top.p - L->ci->func.p), \ + "not enough elements in the stack") /* @@ -157263,7 +157325,6 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t); #if defined(LUA_DEBUG) LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); -LUAI_FUNC int luaH_isdummy (const Table *t); #endif @@ -157655,6 +157716,11 @@ typedef enum { luaC_barrierback(L, gcvalue(t), v); } +/* +** Shift right is the same as shift left with a negative 'y' +*/ +#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) + LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); @@ -158040,25 +158106,6 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { /*#include "lstate.h"*/ -#if defined(EMERGENCYGCTESTS) -/* -** First allocation will fail whenever not building initial state. -** (This fail will trigger 'tryagain' and a full GC cycle at every -** allocation.) -*/ -static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { - if (completestate(g) && ns > 0) /* frees never fail */ - return NULL; /* fail */ - else /* normal allocation */ - return (*g->frealloc)(g->ud, block, os, ns); -} -#else -#define firsttry(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) -#endif - - - - /* ** About the realloc function: @@ -158078,6 +158125,43 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { */ +/* +** Macro to call the allocation function. +*/ +#define callfrealloc(g,block,os,ns) ((*g->frealloc)(g->ud, block, os, ns)) + + +/* +** When an allocation fails, it will try again after an emergency +** collection, except when it cannot run a collection. The GC should +** not be called while the state is not fully built, as the collector +** is not yet fully initialized. Also, it should not be called when +** 'gcstopem' is true, because then the interpreter is in the middle of +** a collection step. +*/ +#define cantryagain(g) (completestate(g) && !g->gcstopem) + + + + +#if defined(EMERGENCYGCTESTS) +/* +** First allocation will fail except when freeing a block (frees never +** fail) and when it cannot try again; this fail will trigger 'tryagain' +** and a full GC cycle at every allocation. +*/ +static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { + if (ns > 0 && cantryagain(g)) + return NULL; /* fail */ + else /* normal allocation */ + return callfrealloc(g, block, os, ns); +} +#else +#define firsttry(g,block,os,ns) callfrealloc(g, block, os, ns) +#endif + + + /* @@ -158150,7 +158234,7 @@ l_noret luaM_toobig (lua_State *L) { void luaM_free_ (lua_State *L, void *block, size_t osize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); - (*g->frealloc)(g->ud, block, osize, 0); + callfrealloc(g, block, osize, 0); g->GCdebt -= osize; } @@ -158158,19 +158242,15 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { /* ** In case of allocation fail, this function will do an emergency ** collection to free some memory and then try the allocation again. -** The GC should not be called while state is not fully built, as the -** collector is not yet fully initialized. Also, it should not be called -** when 'gcstopem' is true, because then the interpreter is in the -** middle of a collection step. */ static void *tryagain (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); - if (completestate(g) && !g->gcstopem) { + if (cantryagain(g)) { luaC_fullgc(L, 1); /* try to free some memory... */ - return (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + return callfrealloc(g, block, osize, nsize); /* try again */ } - else return NULL; /* cannot free any memory without a full state */ + else return NULL; /* cannot run an emergency collection */ } @@ -158339,10 +158419,10 @@ static TString *loadStringN (LoadState *S, Proto *p) { } else { /* long string */ ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ + setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ luaD_inctop(L); loadVector(S, getstr(ts), size); /* load directly in final place */ - L->top--; /* pop string */ + L->top.p--; /* pop string */ } luaC_objbarrier(L, p, ts); return ts; @@ -158467,6 +158547,8 @@ static void loadDebug (LoadState *S, Proto *f) { f->locvars[i].endpc = loadInt(S); } n = loadInt(S); + if (n != 0) /* does it have debug information? */ + n = f->sizeupvalues; /* must be this many */ for (i = 0; i < n; i++) f->upvalues[i].name = loadStringN(S, f); } @@ -158540,7 +158622,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { S.Z = Z; checkHeader(&S); cl = luaF_newLclosure(L, loadByte(&S)); - setclLvalue2s(L, L->top, cl); + setclLvalue2s(L, L->top.p, cl); luaD_inctop(L); cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -158562,6 +158644,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { /*#include "lprefix.h"*/ +#include #include /*#include "lua.h"*/ @@ -158607,8 +158690,11 @@ static void dumpByte (DumpState *D, int y) { } -/* dumpInt Buff Size */ -#define DIBS ((sizeof(size_t) * 8 / 7) + 1) +/* +** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" +** rounds up the division.) +*/ +#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) static void dumpSize (DumpState *D, size_t x) { lu_byte buff[DIBS]; @@ -158958,33 +159044,33 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) { static void stack_init (lua_State *L1, lua_State *L) { int i; CallInfo *ci; /* initialize stack array */ - L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); - L1->tbclist = L1->stack; + L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); + L1->tbclist.p = L1->stack.p; for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) - setnilvalue(s2v(L1->stack + i)); /* erase new stack */ - L1->top = L1->stack; - L1->stack_last = L1->stack + BASIC_STACK_SIZE; + setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ + L1->top.p = L1->stack.p; + L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; /* initialize first ci */ ci = &L1->base_ci; ci->next = ci->previous = NULL; ci->callstatus = CIST_C; - ci->func = L1->top; + ci->func.p = L1->top.p; ci->u.c.k = NULL; ci->nresults = 0; - setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ - L1->top++; - ci->top = L1->top + LUA_MINSTACK; + setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ + L1->top.p++; + ci->top.p = L1->top.p + LUA_MINSTACK; L1->ci = ci; } static void freestack (lua_State *L) { - if (L->stack == NULL) + if (L->stack.p == NULL) return; /* stack not completely built yet */ L->ci = &L->base_ci; /* free the entire 'ci' list */ luaE_freeCI(L); lua_assert(L->nci == 0); - luaM_freearray(L, L->stack, stacksize(L) + EXTRA_STACK); /* free stack */ + luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ } @@ -159026,7 +159112,7 @@ static void f_luaopen (lua_State *L, void *ud) { */ static void preinit_thread (lua_State *L, global_State *g) { G(L) = g; - L->stack = NULL; + L->stack.p = NULL; L->ci = NULL; L->nci = 0; L->twups = L; /* thread has no upvalues */ @@ -159062,20 +159148,16 @@ static void close_state (lua_State *L) { LUA_API lua_State *lua_newthread (lua_State *L) { - global_State *g; + global_State *g = G(L); + GCObject *o; lua_State *L1; lua_lock(L); - g = G(L); luaC_checkGC(L); /* create new thread */ - L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; - L1->marked = luaC_white(g); - L1->tt = LUA_VTHREAD; - /* link it on list 'allgc' */ - L1->next = g->allgc; - g->allgc = obj2gco(L1); + o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l)); + L1 = gco2th(o); /* anchor it on L stack */ - setthvalue2s(L, L->top, L1); + setthvalue2s(L, L->top.p, L1); api_incr_top(L); preinit_thread(L1, g); L1->hookmask = L->hookmask; @@ -159094,7 +159176,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { void luaE_freethread (lua_State *L, lua_State *L1) { LX *l = fromstate(L1); - luaF_closeupval(L1, L1->stack); /* close all upvalues */ + luaF_closeupval(L1, L1->stack.p); /* close all upvalues */ lua_assert(L1->openupval == NULL); luai_userstatefree(L, L1); freestack(L1); @@ -159104,32 +159186,41 @@ void luaE_freethread (lua_State *L, lua_State *L1) { int luaE_resetthread (lua_State *L, int status) { CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ - setnilvalue(s2v(L->stack)); /* 'function' entry for basic 'ci' */ - ci->func = L->stack; + setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ + ci->func.p = L->stack.p; ci->callstatus = CIST_C; if (status == LUA_YIELD) status = LUA_OK; L->status = LUA_OK; /* so it can run __close metamethods */ status = luaD_closeprotected(L, 1, status); if (status != LUA_OK) /* errors? */ - luaD_seterrorobj(L, status, L->stack + 1); + luaD_seterrorobj(L, status, L->stack.p + 1); else - L->top = L->stack + 1; - ci->top = L->top + LUA_MINSTACK; - luaD_reallocstack(L, cast_int(ci->top - L->stack), 0); + L->top.p = L->stack.p + 1; + ci->top.p = L->top.p + LUA_MINSTACK; + luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); return status; } -LUA_API int lua_resetthread (lua_State *L) { +LUA_API int lua_closethread (lua_State *L, lua_State *from) { int status; lua_lock(L); + L->nCcalls = (from) ? getCcalls(from) : 0; status = luaE_resetthread(L, L->status); lua_unlock(L); return status; } +/* +** Deprecated! Use 'lua_closethread' instead. +*/ +LUA_API int lua_resetthread (lua_State *L) { + return lua_closethread(L, NULL); +} + + LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; @@ -159204,7 +159295,7 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) { ** Generate a warning from an error message */ void luaE_warnerror (lua_State *L, const char *where) { - TValue *errobj = s2v(L->top - 1); /* error object */ + TValue *errobj = s2v(L->top.p - 1); /* error object */ const char *msg = (ttisstring(errobj)) ? svalue(errobj) : "error object is not a string"; @@ -159470,12 +159561,13 @@ void luaC_fix (lua_State *L, GCObject *o) { /* -** create a new collectable object (with given type and size) and link -** it to 'allgc' list. +** create a new collectable object (with given type, size, and offset) +** and link it to 'allgc' list. */ -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { +GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { global_State *g = G(L); - GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); + GCObject *o = cast(GCObject *, p + offset); o->marked = luaC_white(g); o->tt = tt; o->next = g->allgc; @@ -159483,6 +159575,11 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { return o; } + +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + return luaC_newobjdt(L, tt, sz, 0); +} + /* }====================================================== */ @@ -159519,7 +159616,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { set2gray(uv); /* open upvalues are kept gray */ else set2black(uv); /* closed upvalues are visited here */ - markvalue(g, uv->v); /* mark its content */ + markvalue(g, uv->v.p); /* mark its content */ break; } case LUA_VUSERDATA: { @@ -159594,7 +159691,7 @@ static int remarkupvals (global_State *g) { work++; if (!iswhite(uv)) { /* upvalue already visited? */ lua_assert(upisopen(uv) && isgray(uv)); - markvalue(g, uv->v); /* mark its value */ + markvalue(g, uv->v.p); /* mark its value */ } } } @@ -159838,19 +159935,19 @@ static int traverseLclosure (global_State *g, LClosure *cl) { */ static int traversethread (global_State *g, lua_State *th) { UpVal *uv; - StkId o = th->stack; + StkId o = th->stack.p; if (isold(th) || g->gcstate == GCSpropagate) linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ if (o == NULL) return 1; /* stack not completely built yet */ lua_assert(g->gcstate == GCSatomic || th->openupval == NULL || isintwups(th)); - for (; o < th->top; o++) /* mark live elements in the stack */ + for (; o < th->top.p; o++) /* mark live elements in the stack */ markvalue(g, s2v(o)); for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) markobject(g, uv); /* open upvalues cannot be collected */ if (g->gcstate == GCSatomic) { /* final traversal? */ - for (; o < th->stack_last + EXTRA_STACK; o++) + for (; o < th->stack_last.p + EXTRA_STACK; o++) setnilvalue(s2v(o)); /* clear dead stack slice */ /* 'remarkupvals' may have removed thread from 'twups' list */ if (!isintwups(th) && th->openupval != NULL) { @@ -160110,7 +160207,7 @@ static GCObject *udata2finalize (global_State *g) { static void dothecall (lua_State *L, void *ud) { UNUSED(ud); - luaD_callnoyield(L, L->top - 2, 0); + luaD_callnoyield(L, L->top.p - 2, 0); } @@ -160127,16 +160224,16 @@ static void GCTM (lua_State *L) { int oldgcstp = g->gcstp; g->gcstp |= GCSTPGC; /* avoid GC steps */ L->allowhook = 0; /* stop debug hooks during GC metamethod */ - setobj2s(L, L->top++, tm); /* push finalizer... */ - setobj2s(L, L->top++, &v); /* ... and its argument */ + setobj2s(L, L->top.p++, tm); /* push finalizer... */ + setobj2s(L, L->top.p++, &v); /* ... and its argument */ L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ - status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top.p - 2), 0); L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ L->allowhook = oldah; /* restore hooks */ g->gcstp = oldgcstp; /* restore state */ if (l_unlikely(status != LUA_OK)) { /* error while running __gc? */ luaE_warnerror(L, "__gc"); - L->top--; /* pops error object */ + L->top.p--; /* pops error object */ } } } @@ -160259,7 +160356,25 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** ======================================================= */ -static void setpause (global_State *g); + +/* +** Set the "time" to wait before starting a new GC cycle; cycle will +** start when memory use hits the threshold of ('estimate' * pause / +** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, +** because Lua cannot even start with less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + int pause = getgcparam(g->gcpause); + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (pause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * pause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + if (debt > 0) debt = 0; + luaE_setdebt(g, debt); +} /* @@ -160503,6 +160618,15 @@ static void atomic2gen (lua_State *L, global_State *g) { } +/* +** Set debt for the next minor collection, which will happen when +** memory grows 'genminormul'%. +*/ +static void setminordebt (global_State *g) { + luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); +} + + /* ** Enter generational mode. Must go until the end of an atomic cycle ** to ensure that all objects are correctly marked and weak tables @@ -160515,6 +160639,7 @@ static lu_mem entergen (lua_State *L, global_State *g) { luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ numobjs = atomic(L); /* propagates all and then do the atomic stuff */ atomic2gen(L, g); + setminordebt(g); /* set debt assuming next cycle will be minor */ return numobjs; } @@ -160560,15 +160685,6 @@ static lu_mem fullgen (lua_State *L, global_State *g) { } -/* -** Set debt for the next minor collection, which will happen when -** memory grows 'genminormul'%. -*/ -static void setminordebt (global_State *g) { - luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); -} - - /* ** Does a major collection after last collection was a "bad collection". ** @@ -160640,8 +160756,8 @@ static void genstep (lua_State *L, global_State *g) { lu_mem numobjs = fullgen(L, g); /* do a major collection */ if (gettotalbytes(g) < majorbase + (majorinc / 2)) { /* collected at least half of memory growth since last major - collection; keep doing minor collections */ - setminordebt(g); + collection; keep doing minor collections. */ + lua_assert(g->lastatomic == 0); } else { /* bad collection */ g->lastatomic = numobjs; /* signal that last collection was bad */ @@ -160667,26 +160783,6 @@ static void genstep (lua_State *L, global_State *g) { */ -/* -** Set the "time" to wait before starting a new GC cycle; cycle will -** start when memory use hits the threshold of ('estimate' * pause / -** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, -** because Lua cannot even start with less than PAUSEADJ bytes). -*/ -static void setpause (global_State *g) { - l_mem threshold, debt; - int pause = getgcparam(g->gcpause); - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (pause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * pause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - if (debt > 0) debt = 0; - luaE_setdebt(g, debt); -} - - /* ** Enter first sweep phase. ** The call to 'sweeptolive' makes the pointer point to an object @@ -160894,12 +160990,15 @@ static void incstep (lua_State *L, global_State *g) { } /* -** performs a basic GC step if collector is running +** Performs a basic GC step if collector is running. (If collector is +** not running, set a reasonable debt to avoid it being called at +** every single check.) */ void luaC_step (lua_State *L) { global_State *g = G(L); - lua_assert(!g->gcemergency); - if (gcrunning(g)) { /* running? */ + if (!gcrunning(g)) /* not running? */ + luaE_setdebt(g, -2000); + else { if(isdecGCmodegen(g)) genstep(L, g); else @@ -161077,7 +161176,7 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { ** ensuring there is only one copy of each unique string. The table ** here is used as a set: the string enters as the key, while its value ** is irrelevant. We use the string itself as the value only because it -** is a TValue readly available. Later, the code generation can change +** is a TValue readily available. Later, the code generation can change ** this value. */ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { @@ -161087,12 +161186,12 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) { if (!ttisnil(o)) /* string already present? */ ts = keystrval(nodefromval(o)); /* get saved copy */ else { /* not in use yet */ - TValue *stv = s2v(L->top++); /* reserve stack space for string */ + TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ setsvalue(L, stv, ts); /* temporarily anchor the string */ luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ /* table is not a metatable, so it does not need to invalidate cache */ luaC_checkGC(L); - L->top--; /* remove string from stack */ + L->top.p--; /* remove string from stack */ } return ts; } @@ -162881,6 +162980,35 @@ static int constfolding (FuncState *fs, int op, expdesc *e1, } +/* +** Convert a BinOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode binopr2op (BinOpr opr, BinOpr baser, OpCode base) { + lua_assert(baser <= opr && + ((baser == OPR_ADD && opr <= OPR_SHR) || + (baser == OPR_LT && opr <= OPR_LE))); + return cast(OpCode, (cast_int(opr) - cast_int(baser)) + cast_int(base)); +} + + +/* +** Convert a UnOpr to an OpCode (ORDER OPR - ORDER OP) +*/ +l_sinline OpCode unopr2op (UnOpr opr) { + return cast(OpCode, (cast_int(opr) - cast_int(OPR_MINUS)) + + cast_int(OP_UNM)); +} + + +/* +** Convert a BinOpr to a tag method (ORDER OPR - ORDER TM) +*/ +l_sinline TMS binopr2TM (BinOpr opr) { + lua_assert(OPR_ADD <= opr && opr <= OPR_SHR); + return cast(TMS, (cast_int(opr) - cast_int(OPR_ADD)) + cast_int(TM_ADD)); +} + + /* ** Emit code for unary expressions that "produce values" ** (everything but 'not'). @@ -162919,12 +163047,15 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, ** Emit code for binary expressions that "produce values" over ** two registers. */ -static void codebinexpval (FuncState *fs, OpCode op, +static void codebinexpval (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { - int v2 = luaK_exp2anyreg(fs, e2); /* both operands are in registers */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADD); + int v2 = luaK_exp2anyreg(fs, e2); /* make sure 'e2' is in a register */ + /* 'e1' must be already in a register or it is a constant */ + lua_assert((VNIL <= e1->k && e1->k <= VKSTR) || + e1->k == VNONRELOC || e1->k == VRELOC); lua_assert(OP_ADD <= op && op <= OP_SHR); - finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, - cast(TMS, (op - OP_ADD) + TM_ADD)); + finishbinexpval(fs, e1, e2, op, v2, 0, line, OP_MMBIN, binopr2TM(opr)); } @@ -162940,6 +163071,18 @@ static void codebini (FuncState *fs, OpCode op, } +/* +** Code binary operators with K operand. +*/ +static void codebinK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + TMS event = binopr2TM(opr); + int v2 = e2->u.info; /* K index */ + OpCode op = binopr2op(opr, OPR_ADD, OP_ADDK); + finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); +} + + /* Try to code a binary operator negating its second operand. ** For the metamethod, 2nd operand must keep its original value. */ @@ -162967,24 +163110,27 @@ static void swapexps (expdesc *e1, expdesc *e2) { } +/* +** Code binary operators with no constant operand. +*/ +static void codebinNoK (FuncState *fs, BinOpr opr, + expdesc *e1, expdesc *e2, int flip, int line) { + if (flip) + swapexps(e1, e2); /* back to original order */ + codebinexpval(fs, opr, e1, e2, line); /* use standard operators */ +} + + /* ** Code arithmetic operators ('+', '-', ...). If second operand is a ** constant in the proper range, use variant opcodes with K operands. */ static void codearith (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int flip, int line) { - TMS event = cast(TMS, opr + TM_ADD); - if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) { /* K operand? */ - int v2 = e2->u.info; /* K index */ - OpCode op = cast(OpCode, opr + OP_ADDK); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, event); - } - else { /* 'e2' is neither an immediate nor a K operand */ - OpCode op = cast(OpCode, opr + OP_ADD); - if (flip) - swapexps(e1, e2); /* back to original order */ - codebinexpval(fs, op, e1, e2, line); /* use standard operators */ - } + if (tonumeral(e2, NULL) && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* 'e2' is neither an immediate nor a K operand */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -163001,35 +163147,27 @@ static void codecommutative (FuncState *fs, BinOpr op, flip = 1; } if (op == OPR_ADD && isSCint(e2)) /* immediate operand? */ - codebini(fs, cast(OpCode, OP_ADDI), e1, e2, flip, line, TM_ADD); + codebini(fs, OP_ADDI, e1, e2, flip, line, TM_ADD); else codearith(fs, op, e1, e2, flip, line); } /* -** Code bitwise operations; they are all associative, so the function +** Code bitwise operations; they are all commutative, so the function ** tries to put an integer constant as the 2nd operand (a K operand). */ static void codebitwise (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { int flip = 0; - int v2; - OpCode op; - if (e1->k == VKINT && luaK_exp2RK(fs, e1)) { + if (e1->k == VKINT) { swapexps(e1, e2); /* 'e2' will be the constant operand */ flip = 1; } - else if (!(e2->k == VKINT && luaK_exp2RK(fs, e2))) { /* no constants? */ - op = cast(OpCode, opr + OP_ADD); - codebinexpval(fs, op, e1, e2, line); /* all-register opcodes */ - return; - } - v2 = e2->u.info; /* index in K array */ - op = cast(OpCode, opr + OP_ADDK); - lua_assert(ttisinteger(&fs->f->k[v2])); - finishbinexpval(fs, e1, e2, op, v2, flip, line, OP_MMBINK, - cast(TMS, opr + TM_ADD)); + if (e2->k == VKINT && luaK_exp2K(fs, e2)) /* K operand? */ + codebinK(fs, opr, e1, e2, flip, line); + else /* no constants */ + codebinNoK(fs, opr, e1, e2, flip, line); } @@ -163037,25 +163175,27 @@ static void codebitwise (FuncState *fs, BinOpr opr, ** Emit code for order comparisons. When using an immediate operand, ** 'isfloat' tells whether the original value was a float. */ -static void codeorder (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { +static void codeorder (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { int r1, r2; int im; int isfloat = 0; + OpCode op; if (isSCnumber(e2, &im, &isfloat)) { /* use immediate operand */ r1 = luaK_exp2anyreg(fs, e1); r2 = im; - op = cast(OpCode, (op - OP_LT) + OP_LTI); + op = binopr2op(opr, OPR_LT, OP_LTI); } else if (isSCnumber(e1, &im, &isfloat)) { /* transform (A < B) to (B > A) and (A <= B) to (B >= A) */ r1 = luaK_exp2anyreg(fs, e2); r2 = im; - op = (op == OP_LT) ? OP_GTI : OP_GEI; + op = binopr2op(opr, OPR_LT, OP_GTI); } else { /* regular case, compare two registers */ r1 = luaK_exp2anyreg(fs, e1); r2 = luaK_exp2anyreg(fs, e2); + op = binopr2op(opr, OPR_LT, OP_LT); } freeexps(fs, e1, e2); e1->u.info = condjump(fs, op, r1, r2, isfloat, 1); @@ -163081,7 +163221,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { op = OP_EQI; r2 = im; /* immediate operand */ } - else if (luaK_exp2RK(fs, e2)) { /* 1st expression is constant? */ + else if (luaK_exp2RK(fs, e2)) { /* 2nd expression is constant? */ op = OP_EQK; r2 = e2->u.info; /* constant index */ } @@ -163098,16 +163238,16 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { /* ** Apply prefix operation 'op' to expression 'e'. */ -void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { +void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) { static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; luaK_dischargevars(fs, e); - switch (op) { + switch (opr) { case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + if (constfolding(fs, opr + LUA_OPUNM, e, &ef)) break; /* else */ /* FALLTHROUGH */ case OPR_LEN: - codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + codeunexpval(fs, unopr2op(opr), e, line); break; case OPR_NOT: codenot(fs, e); break; default: lua_assert(0); @@ -163141,7 +163281,8 @@ void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { case OPR_SHL: case OPR_SHR: { if (!tonumeral(v, NULL)) luaK_exp2anyreg(fs, v); - /* else keep numeral, which may be folded with 2nd operand */ + /* else keep numeral, which may be folded or used as an immediate + operand */ break; } case OPR_EQ: case OPR_NE: { @@ -163236,30 +163377,27 @@ void luaK_posfix (FuncState *fs, BinOpr opr, /* coded as (r1 >> -I) */; } else /* regular case (two registers) */ - codebinexpval(fs, OP_SHL, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_SHR: { if (isSCint(e2)) codebini(fs, OP_SHRI, e1, e2, 0, line, TM_SHR); /* r1 >> I */ else /* regular case (two registers) */ - codebinexpval(fs, OP_SHR, e1, e2, line); + codebinexpval(fs, opr, e1, e2, line); break; } case OPR_EQ: case OPR_NE: { codeeq(fs, opr, e1, e2); break; } - case OPR_LT: case OPR_LE: { - OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); - codeorder(fs, op, e1, e2); - break; - } case OPR_GT: case OPR_GE: { /* '(a > b)' <=> '(b < a)'; '(a >= b)' <=> '(b <= a)' */ - OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); swapexps(e1, e2); - codeorder(fs, op, e1, e2); + opr = cast(BinOpr, (opr - OPR_GT) + OPR_LT); + } /* FALLTHROUGH */ + case OPR_LT: case OPR_LE: { + codeorder(fs, opr, e1, e2); break; } default: lua_assert(0); @@ -163830,6 +163968,7 @@ static void singlevar (LexState *ls, expdesc *var) { expdesc key; singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ lua_assert(var->k != VVOID); /* this one must exist */ + luaK_exp2anyregup(fs, var); /* but could be a constant */ codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ } @@ -163882,12 +164021,12 @@ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { /* ** Solves the goto at index 'g' to given 'label' and removes it -** from the list of pending goto's. +** from the list of pending gotos. ** If it jumps into the scope of some variable, raises an error. */ static void solvegoto (LexState *ls, int g, Labeldesc *label) { int i; - Labellist *gl = &ls->dyd->gt; /* list of goto's */ + Labellist *gl = &ls->dyd->gt; /* list of gotos */ Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ lua_assert(eqstr(gt->name, label->name)); if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ @@ -163941,7 +164080,7 @@ static int newgotoentry (LexState *ls, TString *name, int line, int pc) { /* ** Solves forward jumps. Check whether new label 'lb' matches any ** pending gotos in current block and solves them. Return true -** if any of the goto's need to close upvalues. +** if any of the gotos need to close upvalues. */ static int solvegotos (LexState *ls, Labeldesc *lb) { Labellist *gl = &ls->dyd->gt; @@ -163962,7 +164101,7 @@ static int solvegotos (LexState *ls, Labeldesc *lb) { /* ** Create a new label with the given 'name' at the given 'line'. ** 'last' tells whether label is the last non-op statement in its -** block. Solves all pending goto's to this new label and adds +** block. Solves all pending gotos to this new label and adds ** a close instruction if necessary. ** Returns true iff it added a close instruction. */ @@ -164035,19 +164174,19 @@ static void leaveblock (FuncState *fs) { LexState *ls = fs->ls; int hasclose = 0; int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ - if (bl->isloop) /* fix pending breaks? */ + removevars(fs, bl->nactvar); /* remove block locals */ + lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ + if (bl->isloop) /* has to fix pending breaks? */ hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); - if (!hasclose && bl->previous && bl->upval) + if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */ luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); - fs->bl = bl->previous; - removevars(fs, bl->nactvar); - lua_assert(bl->nactvar == fs->nactvar); fs->freereg = stklevel; /* free registers */ ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - if (bl->previous) /* inner block? */ - movegotosout(fs, bl); /* update pending gotos to outer block */ + fs->bl = bl->previous; /* current block now is previous one */ + if (bl->previous) /* was it a nested block? */ + movegotosout(fs, bl); /* update pending gotos to enclosing block */ else { - if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } } @@ -165305,10 +165444,10 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, LexState lexstate; FuncState funcstate; LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ - setclLvalue2s(L, L->top, cl); /* anchor it (to avoid being collected) */ + setclLvalue2s(L, L->top.p, cl); /* anchor it (to avoid being collected) */ luaD_inctop(L); lexstate.h = luaH_new(L); /* create table for scanner */ - sethvalue2s(L, L->top, lexstate.h); /* anchor it */ + sethvalue2s(L, L->top.p, lexstate.h); /* anchor it */ luaD_inctop(L); funcstate.f = cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); @@ -165322,7 +165461,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); /* all scopes should be correctly finished */ lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); - L->top--; /* remove scanner's table */ + L->top.p--; /* remove scanner's table */ return cl; /* closure is on the stack, too */ } @@ -165510,10 +165649,10 @@ static const char *upvalname (const Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func))->p->is_vararg) { + if (clLvalue(s2v(ci->func.p))->p->is_vararg) { int nextra = ci->u.l.nextraargs; if (n >= -nextra) { /* 'n' is negative */ - *pos = ci->func - nextra - (n + 1); + *pos = ci->func.p - nextra - (n + 1); return "(vararg)"; /* generic name for any vararg */ } } @@ -165522,7 +165661,7 @@ static const char *findvararg (CallInfo *ci, int n, StkId *pos) { const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; const char *name = NULL; if (isLua(ci)) { if (n < 0) /* access to vararg values? */ @@ -165531,7 +165670,7 @@ const char *luaG_findlocal (lua_State *L, CallInfo *ci, int n, StkId *pos) { name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); } if (name == NULL) { /* no 'standard' name? */ - StkId limit = (ci == L->ci) ? L->top : ci->next->func; + StkId limit = (ci == L->ci) ? L->top.p : ci->next->func.p; if (limit - base >= n && n > 0) { /* is 'n' inside 'ci' stack? */ /* generic name for any valid slot */ name = isLua(ci) ? "(temporary)" : "(C temporary)"; @@ -165549,16 +165688,16 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { const char *name; lua_lock(L); if (ar == NULL) { /* information about non-active function? */ - if (!isLfunction(s2v(L->top - 1))) /* not a Lua function? */ + if (!isLfunction(s2v(L->top.p - 1))) /* not a Lua function? */ name = NULL; else /* consider live variables at function start (parameters) */ - name = luaF_getlocalname(clLvalue(s2v(L->top - 1))->p, n, 0); + name = luaF_getlocalname(clLvalue(s2v(L->top.p - 1))->p, n, 0); } else { /* active function; get information through 'ar' */ StkId pos = NULL; /* to avoid warnings */ name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, L->top, pos); + setobjs2s(L, L->top.p, pos); api_incr_top(L); } } @@ -165573,8 +165712,8 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { lua_lock(L); name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { - setobjs2s(L, pos, L->top - 1); - L->top--; /* pop value */ + setobjs2s(L, pos, L->top.p - 1); + L->top.p--; /* pop value */ } lua_unlock(L); return name; @@ -165617,7 +165756,7 @@ static int nextline (const Proto *p, int currentline, int pc) { static void collectvalidlines (lua_State *L, Closure *f) { if (noLuaClosure(f)) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); } else { @@ -165626,7 +165765,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { const Proto *p = f->l.p; int currentline = p->linedefined; Table *t = luaH_new(L); /* new table to store active lines */ - sethvalue2s(L, L->top, t); /* push it on stack */ + sethvalue2s(L, L->top.p, t); /* push it on stack */ api_incr_top(L); setbtvalue(&v); /* boolean 'true' to be the value of all indices */ if (!p->is_vararg) /* regular function? */ @@ -165716,20 +165855,20 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { lua_lock(L); if (*what == '>') { ci = NULL; - func = s2v(L->top - 1); + func = s2v(L->top.p - 1); api_check(L, ttisfunction(func), "function expected"); what++; /* skip the '>' */ - L->top--; /* pop function */ + L->top.p--; /* pop function */ } else { ci = ar->i_ci; - func = s2v(ci->func); + func = s2v(ci->func.p); lua_assert(ttisfunction(func)); } cl = ttisclosure(func) ? clvalue(func) : NULL; status = auxgetinfo(L, what, ar, cl, ci); if (strchr(what, 'f')) { - setobj2s(L, L->top, func); + setobj2s(L, L->top.p, func); api_incr_top(L); } if (strchr(what, 'L')) @@ -165984,18 +166123,19 @@ static const char *funcnamefromcall (lua_State *L, CallInfo *ci, /* -** Check whether pointer 'o' points to some value in the stack -** frame of the current function. Because 'o' may not point to a -** value in this stack, we cannot compare it with the region -** boundaries (undefined behaviour in ISO C). +** Check whether pointer 'o' points to some value in the stack frame of +** the current function and, if so, returns its index. Because 'o' may +** not point to a value in this stack, we cannot compare it with the +** region boundaries (undefined behavior in ISO C). */ -static int isinstack (CallInfo *ci, const TValue *o) { - StkId pos; - for (pos = ci->func + 1; pos < ci->top; pos++) { - if (o == s2v(pos)) - return 1; +static int instack (CallInfo *ci, const TValue *o) { + int pos; + StkId base = ci->func.p + 1; + for (pos = 0; base + pos < ci->top.p; pos++) { + if (o == s2v(base + pos)) + return pos; } - return 0; /* not found */ + return -1; /* not found */ } @@ -166009,7 +166149,7 @@ static const char *getupvalname (CallInfo *ci, const TValue *o, LClosure *c = ci_func(ci); int i; for (i = 0; i < c->nupvalues; i++) { - if (c->upvals[i]->v == o) { + if (c->upvals[i]->v.p == o) { *name = upvalname(c->p, i); return "upvalue"; } @@ -166036,9 +166176,11 @@ static const char *varinfo (lua_State *L, const TValue *o) { const char *kind = NULL; if (isLua(ci)) { kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ - if (!kind && isinstack(ci, o)) /* no? try a register */ - kind = getobjname(ci_func(ci)->p, currentpc(ci), - cast_int(cast(StkId, o) - (ci->func + 1)), &name); + if (!kind) { /* not an upvalue? */ + int reg = instack(ci, o); /* try a register */ + if (reg >= 0) /* is 'o' a register? */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), reg, &name); + } } return formatvarinfo(L, kind, name); } @@ -166135,10 +166277,10 @@ l_noret luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); lua_assert(ttisfunction(s2v(errfunc))); - setobjs2s(L, L->top, L->top - 1); /* move argument */ - setobjs2s(L, L->top - 1, errfunc); /* push function */ - L->top++; /* assume EXTRA_STACK */ - luaD_callnoyield(L, L->top - 2, 1); /* call it */ + setobjs2s(L, L->top.p, L->top.p - 1); /* move argument */ + setobjs2s(L, L->top.p - 1, errfunc); /* push function */ + L->top.p++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } @@ -166152,8 +166294,11 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); /* format message */ va_end(argp); - if (isLua(ci)) /* if Lua function, add source:line information */ + if (isLua(ci)) { /* if Lua function, add source:line information */ luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); + setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ + L->top.p--; + } luaG_errormsg(L); } @@ -166170,7 +166315,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { if (p->lineinfo == NULL) /* no debug information? */ return 0; if (newpc - oldpc < MAXIWTHABS / 2) { /* not too far apart? */ - int delta = 0; /* line diference */ + int delta = 0; /* line difference */ int pc = oldpc; for (;;) { int lineinfo = p->lineinfo[++pc]; @@ -166197,7 +166342,7 @@ static int changedline (const Proto *p, int oldpc, int newpc) { ** invalid; if so, use zero as a valid value. (A wrong but valid 'oldpc' ** at most causes an extra call to a line hook.) ** This function is not "Protected" when called, so it should correct -** 'L->top' before calling anything that can run the GC. +** 'L->top.p' before calling anything that can run the GC. */ int luaG_traceexec (lua_State *L, const Instruction *pc) { CallInfo *ci = L->ci; @@ -166220,7 +166365,7 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { return 1; /* do not call hook again (VM yielded, so it did not move) */ } if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ - L->top = ci->top; /* correct top */ + L->top.p = ci->top.p; /* correct top */ if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ if (mask & LUA_MASKLINE) { @@ -166296,8 +166441,8 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { for (i = 0; i < cl->nupvalues; i++) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); - uv->v = &uv->u.value; /* make it closed */ - setnilvalue(uv->v); + uv->v.p = &uv->u.value; /* make it closed */ + setnilvalue(uv->v.p); cl->upvals[i] = uv; luaC_objbarrier(L, cl, uv); } @@ -166308,12 +166453,11 @@ void luaF_initupvals (lua_State *L, LClosure *cl) { ** Create a new upvalue at the given level, and link it to the list of ** open upvalues of 'L' after entry 'prev'. **/ -static UpVal *newupval (lua_State *L, int tbc, StkId level, UpVal **prev) { +static UpVal *newupval (lua_State *L, StkId level, UpVal **prev) { GCObject *o = luaC_newobj(L, LUA_VUPVAL, sizeof(UpVal)); UpVal *uv = gco2upv(o); UpVal *next = *prev; - uv->v = s2v(level); /* current value lives in the stack */ - uv->tbc = tbc; + uv->v.p = s2v(level); /* current value lives in the stack */ uv->u.open.next = next; /* link it to list of open upvalues */ uv->u.open.previous = prev; if (next) @@ -166342,7 +166486,7 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { pp = &p->u.open.next; } /* not found: create a new upvalue after 'pp' */ - return newupval(L, 0, level, pp); + return newupval(L, level, pp); } @@ -166352,12 +166496,12 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { ** (This function assumes EXTRA_STACK.) */ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { - StkId top = L->top; + StkId top = L->top.p; const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); setobj2s(L, top, tm); /* will call metamethod... */ setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ - L->top = top + 3; /* add function and arguments */ + L->top.p = top + 3; /* add function and arguments */ if (yy) luaD_call(L, top, 0); else @@ -166372,7 +166516,7 @@ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { static void checkclosemth (lua_State *L, StkId level) { const TValue *tm = luaT_gettmbyobj(L, s2v(level), TM_CLOSE); if (ttisnil(tm)) { /* no metamethod? */ - int idx = cast_int(level - L->ci->func); /* variable index */ + int idx = cast_int(level - L->ci->func.p); /* variable index */ const char *vname = luaG_findlocal(L, L->ci, idx, NULL); if (vname == NULL) vname = "?"; luaG_runerror(L, "variable '%s' got a non-closable value", vname); @@ -166406,23 +166550,23 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { ** is used.) */ #define MAXDELTA \ - ((256ul << ((sizeof(L->stack->tbclist.delta) - 1) * 8)) - 1) + ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) /* ** Insert a variable in the list of to-be-closed variables. */ void luaF_newtbcupval (lua_State *L, StkId level) { - lua_assert(level > L->tbclist); + lua_assert(level > L->tbclist.p); if (l_isfalse(s2v(level))) return; /* false doesn't need to be closed */ checkclosemth(L, level); /* value must have a close method */ - while (cast_uint(level - L->tbclist) > MAXDELTA) { - L->tbclist += MAXDELTA; /* create a dummy node at maximum delta */ - L->tbclist->tbclist.delta = 0; + while (cast_uint(level - L->tbclist.p) > MAXDELTA) { + L->tbclist.p += MAXDELTA; /* create a dummy node at maximum delta */ + L->tbclist.p->tbclist.delta = 0; } - level->tbclist.delta = cast(unsigned short, level - L->tbclist); - L->tbclist = level; + level->tbclist.delta = cast(unsigned short, level - L->tbclist.p); + L->tbclist.p = level; } @@ -166442,10 +166586,10 @@ void luaF_closeupval (lua_State *L, StkId level) { StkId upl; /* stack index pointed by 'uv' */ while ((uv = L->openupval) != NULL && (upl = uplevel(uv)) >= level) { TValue *slot = &uv->u.value; /* new position for value */ - lua_assert(uplevel(uv) < L->top); + lua_assert(uplevel(uv) < L->top.p); luaF_unlinkupval(uv); /* remove upvalue from 'openupval' list */ - setobj(L, slot, uv->v); /* move value to upvalue slot */ - uv->v = slot; /* now current value lives here */ + setobj(L, slot, uv->v.p); /* move value to upvalue slot */ + uv->v.p = slot; /* now current value lives here */ if (!iswhite(uv)) { /* neither white nor dead? */ nw2black(uv); /* closed upvalues cannot be gray */ luaC_barrier(L, uv, slot); @@ -166455,31 +166599,32 @@ void luaF_closeupval (lua_State *L, StkId level) { /* -** Remove firt element from the tbclist plus its dummy nodes. +** Remove first element from the tbclist plus its dummy nodes. */ static void poptbclist (lua_State *L) { - StkId tbc = L->tbclist; + StkId tbc = L->tbclist.p; lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */ tbc -= tbc->tbclist.delta; - while (tbc > L->stack && tbc->tbclist.delta == 0) + while (tbc > L->stack.p && tbc->tbclist.delta == 0) tbc -= MAXDELTA; /* remove dummy nodes */ - L->tbclist = tbc; + L->tbclist.p = tbc; } /* ** Close all upvalues and to-be-closed variables up to the given stack -** level. +** level. Return restored 'level'. */ -void luaF_close (lua_State *L, StkId level, int status, int yy) { +StkId luaF_close (lua_State *L, StkId level, int status, int yy) { ptrdiff_t levelrel = savestack(L, level); luaF_closeupval(L, level); /* first, close the upvalues */ - while (L->tbclist >= level) { /* traverse tbc's down to that level */ - StkId tbc = L->tbclist; /* get variable index */ + while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ + StkId tbc = L->tbclist.p; /* get variable index */ poptbclist(L); /* remove it from list */ prepcallclosemth(L, tbc, status, yy); /* close variable */ level = restorestack(L, levelrel); } + return level; } @@ -166602,7 +166747,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, case LUA_OPBOR: return intop(|, v1, v2); case LUA_OPBXOR: return intop(^, v1, v2); case LUA_OPSHL: return luaV_shiftl(v1, v2); - case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPSHR: return luaV_shiftr(v1, v2); case LUA_OPUNM: return intop(-, 0, v1); case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); default: lua_assert(0); return 0; @@ -166926,29 +167071,39 @@ void luaO_tostring (lua_State *L, TValue *obj) { ** =================================================================== */ -/* size for buffer space used by 'luaO_pushvfstring' */ -#define BUFVFS 200 +/* +** Size for buffer space used by 'luaO_pushvfstring'. It should be +** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, +** so that 'luaG_addinfo' can work directly on the buffer. +*/ +#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) /* buffer used by 'luaO_pushvfstring' */ typedef struct BuffFS { lua_State *L; - int pushed; /* number of string pieces already on the stack */ + int pushed; /* true if there is a part of the result on the stack */ int blen; /* length of partial string in 'space' */ char space[BUFVFS]; /* holds last part of the result */ } BuffFS; /* -** Push given string to the stack, as part of the buffer, and -** join the partial strings in the stack into one. +** Push given string to the stack, as part of the result, and +** join it to previous partial result if there is one. +** It may call 'luaV_concat' while using one slot from EXTRA_STACK. +** This call cannot invoke metamethods, as both operands must be +** strings. It can, however, raise an error if the result is too +** long. In that case, 'luaV_concat' frees the extra slot before +** raising the error. */ -static void pushstr (BuffFS *buff, const char *str, size_t l) { +static void pushstr (BuffFS *buff, const char *str, size_t lstr) { lua_State *L = buff->L; - setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); - L->top++; /* may use one extra slot */ - buff->pushed++; - luaV_concat(L, buff->pushed); /* join partial results into one */ - buff->pushed = 1; + setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr)); + L->top.p++; /* may use one slot from EXTRA_STACK */ + if (!buff->pushed) /* no previous string on the stack? */ + buff->pushed = 1; /* now there is one */ + else /* join previous string with new one */ + luaV_concat(L, 2); } @@ -166994,7 +167149,7 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { /* -** Add a number to the buffer. +** Add a numeral to the buffer. */ static void addnum2buff (BuffFS *buff, TValue *num) { char *numbuff = getbuff(buff, MAXNUMBER2STR); @@ -167072,7 +167227,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ clearbuff(&buff); /* empty buffer into the stack */ lua_assert(buff.pushed == 1); - return svalue(s2v(L->top - 1)); + return svalue(s2v(L->top.p - 1)); } @@ -167234,12 +167389,12 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) { void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ setobj2s(L, func + 3, p3); /* 3rd argument */ - L->top = func + 4; + L->top.p = func + 4; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 0); @@ -167251,18 +167406,18 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); - StkId func = L->top; + StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, func + 1, p1); /* 1st argument */ setobj2s(L, func + 2, p2); /* 2nd argument */ - L->top += 3; + L->top.p += 3; /* metamethod may yield only when called from Lua code */ if (isLuacode(L->ci)) luaD_call(L, func, 1); else luaD_callnoyield(L, func, 1); res = restorestack(L, result); - setobjs2s(L, res, --L->top); /* move result to its place */ + setobjs2s(L, res, --L->top.p); /* move result to its place */ } @@ -167297,7 +167452,7 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, void luaT_tryconcatTM (lua_State *L) { - StkId top = L->top; + StkId top = L->top.p; if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, TM_CONCAT))) luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); @@ -167332,15 +167487,15 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, */ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { - if (callbinTM(L, p1, p2, L->top, event)) /* try original event */ - return !l_isfalse(s2v(L->top)); + if (callbinTM(L, p1, p2, L->top.p, event)) /* try original event */ + return !l_isfalse(s2v(L->top.p)); #if defined(LUA_COMPAT_LT_LE) else if (event == TM_LE) { /* try '!(p2 < p1)' for '(p1 <= p2)' */ L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - if (callbinTM(L, p2, p1, L->top, TM_LT)) { + if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - return l_isfalse(s2v(L->top)); + return l_isfalse(s2v(L->top.p)); } /* else error will remove this 'ci'; no need to clear mark */ } @@ -167370,20 +167525,20 @@ int luaT_callorderiTM (lua_State *L, const TValue *p1, int v2, void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci, const Proto *p) { int i; - int actual = cast_int(L->top - ci->func) - 1; /* number of arguments */ + int actual = cast_int(L->top.p - ci->func.p) - 1; /* number of arguments */ int nextra = actual - nfixparams; /* number of extra arguments */ ci->u.l.nextraargs = nextra; luaD_checkstack(L, p->maxstacksize + 1); /* copy function to the top of the stack */ - setobjs2s(L, L->top++, ci->func); + setobjs2s(L, L->top.p++, ci->func.p); /* move fixed parameters to the top of the stack */ for (i = 1; i <= nfixparams; i++) { - setobjs2s(L, L->top++, ci->func + i); - setnilvalue(s2v(ci->func + i)); /* erase original parameter (for GC) */ + setobjs2s(L, L->top.p++, ci->func.p + i); + setnilvalue(s2v(ci->func.p + i)); /* erase original parameter (for GC) */ } - ci->func += actual + 1; - ci->top += actual + 1; - lua_assert(L->top <= ci->top && ci->top <= L->stack_last); + ci->func.p += actual + 1; + ci->top.p += actual + 1; + lua_assert(L->top.p <= ci->top.p && ci->top.p <= L->stack_last.p); } @@ -167393,10 +167548,10 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { if (wanted < 0) { wanted = nextra; /* get all extra arguments available */ checkstackGCp(L, nextra, where); /* ensure stack space */ - L->top = where + nextra; /* next instruction will need top */ + L->top.p = where + nextra; /* next instruction will need top */ } for (i = 0; i < wanted && i < nextra; i++) - setobjs2s(L, where + i, ci->func - nextra + i); + setobjs2s(L, where + i, ci->func.p - nextra + i); for (; i < wanted; i++) /* complete required results with nil */ setnilvalue(s2v(where + i)); } @@ -167783,7 +167938,7 @@ static const TValue absentkey = {ABSTKEYCONSTANT}; */ static Node *hashint (const Table *t, lua_Integer i) { lua_Unsigned ui = l_castS2U(i); - if (ui <= (unsigned int)INT_MAX) + if (ui <= cast_uint(INT_MAX)) return hashmod(t, cast_int(ui)); else return hashmod(t, ui); @@ -167933,9 +168088,11 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) { size |= (size >> 2); size |= (size >> 4); size |= (size >> 8); +#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */ size |= (size >> 16); #if (UINT_MAX >> 30) > 3 size |= (size >> 32); /* unsigned int has more than 32 bits */ +#endif #endif size++; lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); @@ -168164,7 +168321,7 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { luaG_runerror(L, "table overflow"); size = twoto(lsize); t->node = luaM_newvector(L, size, Node); - for (i = 0; i < (int)size; i++) { + for (i = 0; i < cast_int(size); i++) { Node *n = gnode(t, i); gnext(n) = 0; setnilkey(n); @@ -168651,8 +168808,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainpositionTV(t, key); } -int luaH_isdummy (const Table *t) { return isdummy(t); } - #endif /* ** $Id: ldo.c $ @@ -168760,11 +168915,11 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { } default: { lua_assert(errorstatus(errcode)); /* real error */ - setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ break; } } - L->top = oldtop + 1; + L->top.p = oldtop + 1; } @@ -168777,7 +168932,7 @@ l_noret luaD_throw (lua_State *L, int errcode) { global_State *g = G(L); errcode = luaE_resetthread(L, errcode); /* close all upvalues */ if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ } else { /* no handler at all; abort */ @@ -168813,16 +168968,38 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ** Stack reallocation ** =================================================================== */ -static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { + + +/* +** Change all pointers to the stack into offsets. +*/ +static void relstack (lua_State *L) { CallInfo *ci; UpVal *up; - L->top = (L->top - oldstack) + newstack; - L->tbclist = (L->tbclist - oldstack) + newstack; + L->top.offset = savestack(L, L->top.p); + L->tbclist.offset = savestack(L, L->tbclist.p); for (up = L->openupval; up != NULL; up = up->u.open.next) - up->v = s2v((uplevel(up) - oldstack) + newstack); + up->v.offset = savestack(L, uplevel(up)); for (ci = L->ci; ci != NULL; ci = ci->previous) { - ci->top = (ci->top - oldstack) + newstack; - ci->func = (ci->func - oldstack) + newstack; + ci->top.offset = savestack(L, ci->top.p); + ci->func.offset = savestack(L, ci->func.p); + } +} + + +/* +** Change back all offsets into pointers. +*/ +static void correctstack (lua_State *L) { + CallInfo *ci; + UpVal *up; + L->top.p = restorestack(L, L->top.offset); + L->tbclist.p = restorestack(L, L->tbclist.offset); + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v.p = s2v(restorestack(L, up->v.offset)); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top.p = restorestack(L, ci->top.offset); + ci->func.p = restorestack(L, ci->func.offset); if (isLua(ci)) ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ } @@ -168832,44 +169009,45 @@ static void correctstack (lua_State *L, StkId oldstack, StkId newstack) { /* some space for error handling */ #define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) - /* -** Reallocate the stack to a new size, correcting all pointers into -** it. (There are pointers to a stack from its upvalues, from its list -** of call infos, plus a few individual pointers.) The reallocation is -** done in two steps (allocation + free) because the correction must be -** done while both addresses (the old stack and the new one) are valid. -** (In ISO C, any pointer use after the pointer has been deallocated is -** undefined behavior.) +** Reallocate the stack to a new size, correcting all pointers into it. +** In ISO C, any pointer use after the pointer has been deallocated is +** undefined behavior. So, before the reallocation, all pointers are +** changed to offsets, and after the reallocation they are changed back +** to pointers. As during the reallocation the pointers are invalid, the +** reallocation cannot run emergency collections. +** ** In case of allocation error, raise an error or return false according ** to 'raiseerror'. */ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { int oldsize = stacksize(L); int i; - StkId newstack = luaM_reallocvector(L, NULL, 0, - newsize + EXTRA_STACK, StackValue); + StkId newstack; + int oldgcstop = G(L)->gcstopem; lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + relstack(L); /* change pointers to offsets */ + G(L)->gcstopem = 1; /* stop emergency collection */ + newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, + newsize + EXTRA_STACK, StackValue); + G(L)->gcstopem = oldgcstop; /* restore emergency collection */ if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ + correctstack(L); /* change offsets back to pointers */ if (raiseerror) luaM_error(L); else return 0; /* do not raise an error */ } - /* number of elements to be copied to the new stack */ - i = ((oldsize <= newsize) ? oldsize : newsize) + EXTRA_STACK; - memcpy(newstack, L->stack, i * sizeof(StackValue)); - for (; i < newsize + EXTRA_STACK; i++) + L->stack.p = newstack; + correctstack(L); /* change offsets back to pointers */ + L->stack_last.p = L->stack.p + newsize; + for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) setnilvalue(s2v(newstack + i)); /* erase new segment */ - correctstack(L, L->stack, newstack); - luaM_freearray(L, L->stack, oldsize + EXTRA_STACK); - L->stack = newstack; - L->stack_last = L->stack + newsize; return 1; } /* -** Try to grow the stack by at least 'n' elements. when 'raiseerror' +** Try to grow the stack by at least 'n' elements. When 'raiseerror' ** is true, raises any error; otherwise, return 0 in case of errors. */ int luaD_growstack (lua_State *L, int n, int raiseerror) { @@ -168883,35 +169061,38 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { luaD_throw(L, LUA_ERRERR); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } - else { + else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ int newsize = 2 * size; /* tentative new size */ - int needed = cast_int(L->top - L->stack) + n; + int needed = cast_int(L->top.p - L->stack.p) + n; if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ newsize = LUAI_MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ newsize = needed; if (l_likely(newsize <= LUAI_MAXSTACK)) return luaD_reallocstack(L, newsize, raiseerror); - else { /* stack overflow */ - /* add extra size to be able to handle the error message */ - luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); - if (raiseerror) - luaG_runerror(L, "stack overflow"); - return 0; - } } + /* else stack overflow */ + /* add extra size to be able to handle the error message */ + luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror); + if (raiseerror) + luaG_runerror(L, "stack overflow"); + return 0; } +/* +** Compute how much of the stack is being used, by computing the +** maximum top of all call frames in the stack and the current top. +*/ static int stackinuse (lua_State *L) { CallInfo *ci; int res; - StkId lim = L->top; + StkId lim = L->top.p; for (ci = L->ci; ci != NULL; ci = ci->previous) { - if (lim < ci->top) lim = ci->top; + if (lim < ci->top.p) lim = ci->top.p; } - lua_assert(lim <= L->stack_last); - res = cast_int(lim - L->stack) + 1; /* part of stack in use */ + lua_assert(lim <= L->stack_last.p + EXTRA_STACK); + res = cast_int(lim - L->stack.p) + 1; /* part of stack in use */ if (res < LUA_MINSTACK) res = LUA_MINSTACK; /* ensure a minimum size */ return res; @@ -168929,17 +169110,13 @@ static int stackinuse (lua_State *L) { */ void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); - int nsize = inuse * 2; /* proposed new size */ - int max = inuse * 3; /* maximum "reasonable" size */ - if (max > LUAI_MAXSTACK) { - max = LUAI_MAXSTACK; /* respect stack limit */ - if (nsize > LUAI_MAXSTACK) - nsize = LUAI_MAXSTACK; - } + int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3; /* if thread is currently not handling a stack overflow and its size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) + if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) { + int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2; luaD_reallocstack(L, nsize, 0); /* ok if that fails */ + } else /* don't change stack */ condmovestack(L,{},{}); /* (change only for debugging) */ luaE_shrinkCI(L); /* shrink CI list */ @@ -168948,7 +169125,7 @@ void luaD_shrinkstack (lua_State *L) { void luaD_inctop (lua_State *L) { luaD_checkstack(L, 1); - L->top++; + L->top.p++; } /* }================================================================== */ @@ -168965,8 +169142,8 @@ void luaD_hook (lua_State *L, int event, int line, if (hook && L->allowhook) { /* make sure there is a hook */ int mask = CIST_HOOKED; CallInfo *ci = L->ci; - ptrdiff_t top = savestack(L, L->top); /* preserve original 'top' */ - ptrdiff_t ci_top = savestack(L, ci->top); /* idem for 'ci->top' */ + ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */ + ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */ lua_Debug ar; ar.event = event; ar.currentline = line; @@ -168976,11 +169153,11 @@ void luaD_hook (lua_State *L, int event, int line, ci->u2.transferinfo.ftransfer = ftransfer; ci->u2.transferinfo.ntransfer = ntransfer; } - if (isLua(ci) && L->top < ci->top) - L->top = ci->top; /* protect entire activation register */ + if (isLua(ci) && L->top.p < ci->top.p) + L->top.p = ci->top.p; /* protect entire activation register */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - if (ci->top < L->top + LUA_MINSTACK) - ci->top = L->top + LUA_MINSTACK; + if (ci->top.p < L->top.p + LUA_MINSTACK) + ci->top.p = L->top.p + LUA_MINSTACK; L->allowhook = 0; /* cannot call hooks inside a hook */ ci->callstatus |= mask; lua_unlock(L); @@ -168988,8 +169165,8 @@ void luaD_hook (lua_State *L, int event, int line, lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; - ci->top = restorestack(L, ci_top); - L->top = restorestack(L, top); + ci->top.p = restorestack(L, ci_top); + L->top.p = restorestack(L, top); ci->callstatus &= ~mask; } } @@ -169020,7 +169197,7 @@ void luaD_hookcall (lua_State *L, CallInfo *ci) { */ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (L->hookmask & LUA_MASKRET) { /* is return hook on? */ - StkId firstres = L->top - nres; /* index of first result */ + StkId firstres = L->top.p - nres; /* index of first result */ int delta = 0; /* correction for vararg functions */ int ftransfer; if (isLua(ci)) { @@ -169028,10 +169205,10 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { if (p->is_vararg) delta = ci->u.l.nextraargs + p->numparams + 1; } - ci->func += delta; /* if vararg, back to virtual 'func' */ - ftransfer = cast(unsigned short, firstres - ci->func); + ci->func.p += delta; /* if vararg, back to virtual 'func' */ + ftransfer = cast(unsigned short, firstres - ci->func.p); luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ - ci->func -= delta; + ci->func.p -= delta; } if (isLua(ci = ci->previous)) L->oldpc = pcRel(ci->u.l.savedpc, ci_func(ci)->p); /* set 'oldpc' */ @@ -169050,9 +169227,9 @@ StkId luaD_tryfuncTM (lua_State *L, StkId func) { tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ if (l_unlikely(ttisnil(tm))) luaG_callerror(L, s2v(func)); /* nothing to call */ - for (p = L->top; p > func; p--) /* open space for metamethod */ + for (p = L->top.p; p > func; p--) /* open space for metamethod */ setobjs2s(L, p, p-1); - L->top++; /* stack space pre-allocated by the caller */ + L->top.p++; /* stack space pre-allocated by the caller */ setobj2s(L, func, tm); /* metamethod is the new function to be called */ return func; } @@ -169069,28 +169246,29 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { int i; switch (wanted) { /* handle typical cases separately */ case 0: /* no values needed */ - L->top = res; + L->top.p = res; return; case 1: /* one value needed */ if (nres == 0) /* no results? */ setnilvalue(s2v(res)); /* adjust with nil */ else /* at least one result */ - setobjs2s(L, res, L->top - nres); /* move it to proper place */ - L->top = res + 1; + setobjs2s(L, res, L->top.p - nres); /* move it to proper place */ + L->top.p = res + 1; return; case LUA_MULTRET: wanted = nres; /* we want all results */ break; default: /* two/more results and/or to-be-closed variables */ if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ - ptrdiff_t savedres = savestack(L, res); L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ L->ci->u2.nres = nres; - luaF_close(L, res, CLOSEKTOP, 1); + res = luaF_close(L, res, CLOSEKTOP, 1); L->ci->callstatus &= ~CIST_CLSRET; - if (L->hookmask) /* if needed, call hook after '__close's */ + if (L->hookmask) { /* if needed, call hook after '__close's */ + ptrdiff_t savedres = savestack(L, res); rethook(L, L->ci, nres); - res = restorestack(L, savedres); /* close and hook can move stack */ + res = restorestack(L, savedres); /* hook can move stack */ + } wanted = decodeNresults(wanted); if (wanted == LUA_MULTRET) wanted = nres; /* we want all results */ @@ -169098,14 +169276,14 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { break; } /* generic case */ - firstresult = L->top - nres; /* index of first result */ + firstresult = L->top.p - nres; /* index of first result */ if (nres > wanted) /* extra results? */ nres = wanted; /* don't need them */ for (i = 0; i < nres; i++) /* move all results to correct place */ setobjs2s(L, res + i, firstresult + i); for (; i < wanted; i++) /* complete wanted number of results */ setnilvalue(s2v(res + i)); - L->top = res + wanted; /* top points after the last result */ + L->top.p = res + wanted; /* top points after the last result */ } @@ -169120,7 +169298,7 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) rethook(L, ci, nres); /* move results to proper place */ - moveresults(L, ci->func, nres, wanted); + moveresults(L, ci->func.p, nres, wanted); /* function cannot be in any of these cases when returning */ lua_assert(!(ci->callstatus & (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); @@ -169135,10 +169313,10 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, int mask, StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ - ci->func = func; + ci->func.p = func; ci->nresults = nret; ci->callstatus = mask; - ci->top = top; + ci->top.p = top; return ci; } @@ -169152,10 +169330,10 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults, CallInfo *ci; checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, - L->top + LUA_MINSTACK); - lua_assert(ci->top <= L->stack_last); + L->top.p + LUA_MINSTACK); + lua_assert(ci->top.p <= L->stack_last.p); if (l_unlikely(L->hookmask & LUA_MASKCALL)) { - int narg = cast_int(L->top - func) - 1; + int narg = cast_int(L->top.p - func) - 1; luaD_hook(L, LUA_HOOKCALL, -1, 1, narg); } lua_unlock(L); @@ -169187,17 +169365,17 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int nfixparams = p->numparams; int i; checkstackGCp(L, fsize - delta, func); - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ for (i = 0; i < narg1; i++) /* move down function and arguments */ - setobjs2s(L, ci->func + i, func + i); - func = ci->func; /* moved-down function */ + setobjs2s(L, ci->func.p + i, func + i); + func = ci->func.p; /* moved-down function */ for (; narg1 <= nfixparams; narg1++) setnilvalue(s2v(func + narg1)); /* complete missing arguments */ - ci->top = func + 1 + fsize; /* top for new function */ - lua_assert(ci->top <= L->stack_last); + ci->top.p = func + 1 + fsize; /* top for new function */ + lua_assert(ci->top.p <= L->stack_last.p); ci->u.l.savedpc = p->code; /* starting point */ ci->callstatus |= CIST_TAIL; - L->top = func + narg1; /* set top */ + L->top.p = func + narg1; /* set top */ return -1; } default: { /* not a function */ @@ -169230,15 +169408,15 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { case LUA_VLCL: { /* Lua function */ CallInfo *ci; Proto *p = clLvalue(s2v(func))->p; - int narg = cast_int(L->top - func) - 1; /* number of real arguments */ + int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ checkstackGCp(L, fsize, func); L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); ci->u.l.savedpc = p->code; /* starting point */ for (; narg < nfixparams; narg++) - setnilvalue(s2v(L->top++)); /* complete missing arguments */ - lua_assert(ci->top <= L->stack_last); + setnilvalue(s2v(L->top.p++)); /* complete missing arguments */ + lua_assert(ci->top.p <= L->stack_last.p); return ci; } default: { /* not a function */ @@ -169254,12 +169432,17 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { ** Call a function (C or Lua) through C. 'inc' can be 1 (increment ** number of recursive invocations in the C stack) or nyci (the same ** plus increment number of non-yieldable calls). +** This function can be called with some use of EXTRA_STACK, so it should +** check the stack before doing anything else. 'luaD_precall' already +** does that. */ -l_sinline void ccall (lua_State *L, StkId func, int nResults, int inc) { +l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { CallInfo *ci; L->nCcalls += inc; - if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) + if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) { + checkstackp(L, 0, func); /* free any use of EXTRA_STACK */ luaE_checkcstack(L); + } if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ luaV_execute(L, ci); /* call it */ @@ -169307,8 +169490,7 @@ static int finishpcallk (lua_State *L, CallInfo *ci) { else { /* error */ StkId func = restorestack(L, ci->u2.funcidx); L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ - luaF_close(L, func, status, 1); /* can yield or raise an error */ - func = restorestack(L, ci->u2.funcidx); /* stack may be moved */ + func = luaF_close(L, func, status, 1); /* can yield or raise an error */ luaD_seterrorobj(L, status, func); luaD_shrinkstack(L); /* restore stack size in case of overflow */ setcistrecst(ci, LUA_OK); /* clear original status */ @@ -169396,8 +169578,8 @@ static CallInfo *findpcall (lua_State *L) { ** coroutine error handler and should not kill the coroutine.) */ static int resume_error (lua_State *L, const char *msg, int narg) { - L->top -= narg; /* remove args from the stack */ - setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + L->top.p -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ api_incr_top(L); lua_unlock(L); return LUA_ERRRUN; @@ -169413,7 +169595,7 @@ static int resume_error (lua_State *L, const char *msg, int narg) { */ static void resume (lua_State *L, void *ud) { int n = *(cast(int*, ud)); /* number of arguments */ - StkId firstArg = L->top - n; /* first argument */ + StkId firstArg = L->top.p - n; /* first argument */ CallInfo *ci = L->ci; if (L->status == LUA_OK) /* starting a coroutine? */ ccall(L, firstArg - 1, LUA_MULTRET, 0); /* just call its body */ @@ -169421,7 +169603,7 @@ static void resume (lua_State *L, void *ud) { lua_assert(L->status == LUA_YIELD); L->status = LUA_OK; /* mark that it is running (again) */ if (isLua(ci)) { /* yielded inside a hook? */ - L->top = firstArg; /* discard arguments */ + L->top.p = firstArg; /* discard arguments */ luaV_execute(L, ci); /* just continue running Lua code */ } else { /* 'common' yield */ @@ -169464,7 +169646,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, if (L->status == LUA_OK) { /* may be starting a coroutine */ if (L->ci != &L->base_ci) /* not in base level? */ return resume_error(L, "cannot resume non-suspended coroutine", nargs); - else if (L->top - (L->ci->func + 1) == nargs) /* no function? */ + else if (L->top.p - (L->ci->func.p + 1) == nargs) /* no function? */ return resume_error(L, "cannot resume dead coroutine", nargs); } else if (L->status != LUA_YIELD) /* ended with errors? */ @@ -169482,11 +169664,11 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, lua_assert(status == L->status); /* normal end or yield */ else { /* unrecoverable error */ L->status = cast_byte(status); /* mark thread as 'dead' */ - luaD_seterrorobj(L, status, L->top); /* push error message */ - L->ci->top = L->top; + luaD_seterrorobj(L, status, L->top.p); /* push error message */ + L->ci->top.p = L->top.p; } *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield - : cast_int(L->top - (L->ci->func + 1)); + : cast_int(L->top.p - (L->ci->func.p + 1)); lua_unlock(L); return status; } @@ -169641,7 +169823,7 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; p.dyd.label.arr = NULL; p.dyd.label.size = 0; luaZ_initbuffer(L, &p.buff); - status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc); luaZ_freebuffer(L, &p.buff); luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); @@ -170261,8 +170443,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { if (tm == NULL) /* no TM? */ return 0; /* objects are different */ else { - luaT_callTMres(L, tm, t1, t2, L->top); /* call TM */ - return !l_isfalse(s2v(L->top)); + luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ + return !l_isfalse(s2v(L->top.p)); } } @@ -170286,17 +170468,17 @@ static void copy2buff (StkId top, int n, char *buff) { /* ** Main operation for concatenation: concat 'total' values in the stack, -** from 'L->top - total' up to 'L->top - 1'. +** from 'L->top.p - total' up to 'L->top.p - 1'. */ void luaV_concat (lua_State *L, int total) { if (total == 1) return; /* "all" values already concatenated */ do { - StkId top = L->top; + StkId top = L->top.p; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(s2v(top - 2)) || cvt2str(s2v(top - 2))) || !tostring(L, s2v(top - 1))) - luaT_tryconcatTM(L); + luaT_tryconcatTM(L); /* may invalidate 'top' */ else if (isemptystr(s2v(top - 1))) /* second operand is empty? */ cast_void(tostring(L, s2v(top - 2))); /* result is first operand */ else if (isemptystr(s2v(top - 2))) { /* first operand is empty string? */ @@ -170309,8 +170491,10 @@ void luaV_concat (lua_State *L, int total) { /* collect total length and number of strings */ for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) { size_t l = vslen(s2v(top - n - 1)); - if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) + if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) { + L->top.p = top - total; /* pop strings to avoid wasting stack */ luaG_runerror(L, "string length overflow"); + } tl += l; } if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ @@ -170324,8 +170508,8 @@ void luaV_concat (lua_State *L, int total) { } setsvalue2s(L, top - n, ts); /* create result */ } - total -= n-1; /* got 'n' strings to create 1 new */ - L->top -= n-1; /* popped 'n' strings and pushed one */ + total -= n - 1; /* got 'n' strings to create one new */ + L->top.p -= n - 1; /* popped 'n' strings and pushed one */ } while (total > 1); /* repeat until only 1 result left */ } @@ -170416,12 +170600,10 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { /* number of bits in an integer */ #define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + /* ** Shift left operation. (Shift right just negates 'y'.) */ -#define luaV_shiftr(x,y) luaV_shiftl(x,intop(-, 0, y)) - - lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { if (y < 0) { /* shift right? */ if (y <= -NBITS) return 0; @@ -170461,26 +170643,26 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, */ void luaV_finishOp (lua_State *L) { CallInfo *ci = L->ci; - StkId base = ci->func + 1; + StkId base = ci->func.p + 1; Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ OpCode op = GET_OPCODE(inst); switch (op) { /* finish its execution */ case OP_MMBIN: case OP_MMBINI: case OP_MMBINK: { - setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top); + setobjs2s(L, base + GETARG_A(*(ci->u.l.savedpc - 2)), --L->top.p); break; } case OP_UNM: case OP_BNOT: case OP_LEN: case OP_GETTABUP: case OP_GETTABLE: case OP_GETI: case OP_GETFIELD: case OP_SELF: { - setobjs2s(L, base + GETARG_A(inst), --L->top); + setobjs2s(L, base + GETARG_A(inst), --L->top.p); break; } case OP_LT: case OP_LE: case OP_LTI: case OP_LEI: case OP_GTI: case OP_GEI: case OP_EQ: { /* note that 'OP_EQI'/'OP_EQK' cannot yield */ - int res = !l_isfalse(s2v(L->top - 1)); - L->top--; + int res = !l_isfalse(s2v(L->top.p - 1)); + L->top.p--; #if defined(LUA_COMPAT_LT_LE) if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ ci->callstatus ^= CIST_LEQ; /* clear mark */ @@ -170493,11 +170675,11 @@ void luaV_finishOp (lua_State *L) { break; } case OP_CONCAT: { - StkId top = L->top - 1; /* top when 'luaT_tryconcatTM' was called */ + StkId top = L->top.p - 1; /* top when 'luaT_tryconcatTM' was called */ int a = GETARG_A(inst); /* first element to concatenate */ int total = cast_int(top - 1 - (base + a)); /* yet to concatenate */ setobjs2s(L, top - 2, top); /* put TM result in proper position */ - L->top = top - 1; /* top is one after last element (at top-2) */ + L->top.p = top - 1; /* top is one after last element (at top-2) */ luaV_concat(L, total); /* concat them (may yield again) */ break; } @@ -170509,7 +170691,7 @@ void luaV_finishOp (lua_State *L) { StkId ra = base + GETARG_A(inst); /* adjust top to signal correct number of returns, in case the return is "up to top" ('isIT') */ - L->top = ra + ci->u2.nres; + L->top.p = ra + ci->u2.nres; /* repeat instruction to close other vars. and complete the return */ ci->u.l.savedpc--; break; @@ -170551,6 +170733,7 @@ void luaV_finishOp (lua_State *L) { ** operation, 'fop' is the float operation. */ #define op_arithI(L,iop,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ int imm = GETARG_sC(i); \ if (ttisinteger(v1)) { \ @@ -170579,6 +170762,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over floats and others with register operands. */ #define op_arithf(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ op_arithf_aux(L, v1, v2, fop); } @@ -170588,6 +170772,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations with K operands for floats. */ #define op_arithfK(L,fop) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); lua_assert(ttisnumber(v2)); \ op_arithf_aux(L, v1, v2, fop); } @@ -170597,6 +170782,7 @@ void luaV_finishOp (lua_State *L) { ** Arithmetic operations over integers and floats. */ #define op_arith_aux(L,v1,v2,iop,fop) { \ + StkId ra = RA(i); \ if (ttisinteger(v1) && ttisinteger(v2)) { \ lua_Integer i1 = ivalue(v1); lua_Integer i2 = ivalue(v2); \ pc++; setivalue(s2v(ra), iop(L, i1, i2)); \ @@ -170626,6 +170812,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with constant operand. */ #define op_bitwiseK(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = KC(i); \ lua_Integer i1; \ @@ -170639,6 +170826,7 @@ void luaV_finishOp (lua_State *L) { ** Bitwise operations with register operands. */ #define op_bitwise(L,op) { \ + StkId ra = RA(i); \ TValue *v1 = vRB(i); \ TValue *v2 = vRC(i); \ lua_Integer i1; lua_Integer i2; \ @@ -170653,18 +170841,19 @@ void luaV_finishOp (lua_State *L) { ** integers. */ #define op_order(L,opi,opn,other) { \ - int cond; \ - TValue *rb = vRB(i); \ - if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ - lua_Integer ia = ivalue(s2v(ra)); \ - lua_Integer ib = ivalue(rb); \ - cond = opi(ia, ib); \ - } \ - else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ - cond = opn(s2v(ra), rb); \ - else \ - Protect(cond = other(L, s2v(ra), rb)); \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + TValue *rb = vRB(i); \ + if (ttisinteger(s2v(ra)) && ttisinteger(rb)) { \ + lua_Integer ia = ivalue(s2v(ra)); \ + lua_Integer ib = ivalue(rb); \ + cond = opi(ia, ib); \ + } \ + else if (ttisnumber(s2v(ra)) && ttisnumber(rb)) \ + cond = opn(s2v(ra), rb); \ + else \ + Protect(cond = other(L, s2v(ra), rb)); \ + docondjump(); } /* @@ -170672,20 +170861,21 @@ void luaV_finishOp (lua_State *L) { ** always small enough to have an exact representation as a float.) */ #define op_orderI(L,opi,opf,inv,tm) { \ - int cond; \ - int im = GETARG_sB(i); \ - if (ttisinteger(s2v(ra))) \ - cond = opi(ivalue(s2v(ra)), im); \ - else if (ttisfloat(s2v(ra))) { \ - lua_Number fa = fltvalue(s2v(ra)); \ - lua_Number fim = cast_num(im); \ - cond = opf(fa, fim); \ - } \ - else { \ - int isf = GETARG_C(i); \ - Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ - } \ - docondjump(); } + StkId ra = RA(i); \ + int cond; \ + int im = GETARG_sB(i); \ + if (ttisinteger(s2v(ra))) \ + cond = opi(ivalue(s2v(ra)), im); \ + else if (ttisfloat(s2v(ra))) { \ + lua_Number fa = fltvalue(s2v(ra)); \ + lua_Number fim = cast_num(im); \ + cond = opf(fa, fim); \ + } \ + else { \ + int isf = GETARG_C(i); \ + Protect(cond = luaT_callorderiTM(L, s2v(ra), im, inv, isf, tm)); \ + } \ + docondjump(); } /* }================================================================== */ @@ -170714,7 +170904,7 @@ void luaV_finishOp (lua_State *L) { #define updatetrap(ci) (trap = ci->u.l.trap) -#define updatebase(ci) (base = ci->func + 1) +#define updatebase(ci) (base = ci->func.p + 1) #define updatestack(ci) \ @@ -170749,7 +170939,7 @@ void luaV_finishOp (lua_State *L) { ** Whenever code can raise errors, the global 'pc' and the global ** 'top' must be correct to report occasional errors. */ -#define savestate(L,ci) (savepc(L), L->top = ci->top) +#define savestate(L,ci) (savepc(L), L->top.p = ci->top.p) /* @@ -170769,7 +170959,7 @@ void luaV_finishOp (lua_State *L) { /* 'c' is the limit of live values in the stack */ #define checkGC(L,c) \ - { luaC_condGC(L, (savepc(L), L->top = (c)), \ + { luaC_condGC(L, (savepc(L), L->top.p = (c)), \ updatetrap(ci)); \ luai_threadyield(L); } @@ -170781,7 +170971,6 @@ void luaV_finishOp (lua_State *L) { updatebase(ci); /* correct stack */ \ } \ i = *(pc++); \ - ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ } #define vmdispatch(o) switch(o) @@ -170913,7 +171102,7 @@ static const void *const disptab[NUM_OPCODES] = { startfunc: trap = L->hookmask; returning: /* trap already set */ - cl = clLvalue(s2v(ci->func)); + cl = clLvalue(s2v(ci->func.p)); k = cl->p->k; pc = ci->u.l.savedpc; if (l_unlikely(trap)) { @@ -170925,60 +171114,68 @@ static const void *const disptab[NUM_OPCODES] = { } ci->u.l.trap = 1; /* assume trap is on, for now */ } - base = ci->func + 1; + base = ci->func.p + 1; /* main loop of interpreter */ for (;;) { Instruction i; /* instruction being executed */ - StkId ra; /* instruction's A register */ vmfetch(); #if 0 /* low-level line tracing for debugging Lua */ printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); #endif - lua_assert(base == ci->func + 1); - lua_assert(base <= L->top && L->top < L->stack_last); + lua_assert(base == ci->func.p + 1); + lua_assert(base <= L->top.p && L->top.p <= L->stack_last.p); /* invalidate top for instructions not expecting it */ - lua_assert(isIT(i) || (cast_void(L->top = base), 1)); + lua_assert(isIT(i) || (cast_void(L->top.p = base), 1)); vmdispatch (GET_OPCODE(i)) { vmcase(OP_MOVE) { + StkId ra = RA(i); setobjs2s(L, ra, RB(i)); vmbreak; } vmcase(OP_LOADI) { + StkId ra = RA(i); lua_Integer b = GETARG_sBx(i); setivalue(s2v(ra), b); vmbreak; } vmcase(OP_LOADF) { + StkId ra = RA(i); int b = GETARG_sBx(i); setfltvalue(s2v(ra), cast_num(b)); vmbreak; } vmcase(OP_LOADK) { + StkId ra = RA(i); TValue *rb = k + GETARG_Bx(i); setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADKX) { + StkId ra = RA(i); TValue *rb; rb = k + GETARG_Ax(*pc); pc++; setobj2s(L, ra, rb); vmbreak; } vmcase(OP_LOADFALSE) { + StkId ra = RA(i); setbfvalue(s2v(ra)); vmbreak; } vmcase(OP_LFALSESKIP) { + StkId ra = RA(i); setbfvalue(s2v(ra)); pc++; /* skip next instruction */ vmbreak; } vmcase(OP_LOADTRUE) { + StkId ra = RA(i); setbtvalue(s2v(ra)); vmbreak; } vmcase(OP_LOADNIL) { + StkId ra = RA(i); int b = GETARG_B(i); do { setnilvalue(s2v(ra++)); @@ -170986,19 +171183,22 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETUPVAL) { + StkId ra = RA(i); int b = GETARG_B(i); - setobj2s(L, ra, cl->upvals[b]->v); + setobj2s(L, ra, cl->upvals[b]->v.p); vmbreak; } vmcase(OP_SETUPVAL) { + StkId ra = RA(i); UpVal *uv = cl->upvals[GETARG_B(i)]; - setobj(L, uv->v, s2v(ra)); + setobj(L, uv->v.p, s2v(ra)); luaC_barrier(L, uv, s2v(ra)); vmbreak; } vmcase(OP_GETTABUP) { + StkId ra = RA(i); const TValue *slot; - TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *upval = cl->upvals[GETARG_B(i)]->v.p; TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a string */ if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { @@ -171009,6 +171209,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = vRC(i); @@ -171023,6 +171224,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETI) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); int c = GETARG_C(i); @@ -171037,6 +171239,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_GETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = KC(i); @@ -171050,7 +171253,7 @@ static const void *const disptab[NUM_OPCODES] = { } vmcase(OP_SETTABUP) { const TValue *slot; - TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *upval = cl->upvals[GETARG_A(i)]->v.p; TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a string */ @@ -171062,6 +171265,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETTABLE) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); /* key (table is in 'ra') */ TValue *rc = RKC(i); /* value */ @@ -171076,6 +171280,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETI) { + StkId ra = RA(i); const TValue *slot; int c = GETARG_B(i); TValue *rc = RKC(i); @@ -171090,6 +171295,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SETFIELD) { + StkId ra = RA(i); const TValue *slot; TValue *rb = KB(i); TValue *rc = RKC(i); @@ -171102,6 +171308,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NEWTABLE) { + StkId ra = RA(i); int b = GETARG_B(i); /* log2(hash size) + 1 */ int c = GETARG_C(i); /* array size */ Table *t; @@ -171111,7 +171318,7 @@ static const void *const disptab[NUM_OPCODES] = { if (TESTARG_k(i)) /* non-zero extra argument? */ c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ pc++; /* skip extra argument */ - L->top = ra + 1; /* correct top in case of emergency GC */ + L->top.p = ra + 1; /* correct top in case of emergency GC */ t = luaH_new(L); /* memory allocation */ sethvalue2s(L, ra, t); if (b != 0 || c != 0) @@ -171120,6 +171327,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SELF) { + StkId ra = RA(i); const TValue *slot; TValue *rb = vRB(i); TValue *rc = RKC(i); @@ -171149,6 +171357,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MODK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_mod, luaV_modf); vmbreak; } @@ -171161,6 +171370,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIVK) { + savestate(L, ci); /* in case of division by 0 */ op_arithK(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -171177,6 +171387,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHRI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -171186,6 +171397,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_SHLI) { + StkId ra = RA(i); TValue *rb = vRB(i); int ic = GETARG_sC(i); lua_Integer ib; @@ -171207,6 +171419,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MOD) { + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_mod, luaV_modf); vmbreak; } @@ -171219,6 +171432,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_IDIV) { /* floor division */ + savestate(L, ci); /* in case of division by 0 */ op_arith(L, luaV_idiv, luai_numidiv); vmbreak; } @@ -171243,6 +171457,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBIN) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *rb = vRB(i); TMS tm = (TMS)GETARG_C(i); @@ -171252,6 +171467,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINI) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ int imm = GETARG_sB(i); TMS tm = (TMS)GETARG_C(i); @@ -171261,6 +171477,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_MMBINK) { + StkId ra = RA(i); Instruction pi = *(pc - 2); /* original arith. expression */ TValue *imm = KB(i); TMS tm = (TMS)GETARG_C(i); @@ -171270,6 +171487,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_UNM) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Number nb; if (ttisinteger(rb)) { @@ -171284,6 +171502,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_BNOT) { + StkId ra = RA(i); TValue *rb = vRB(i); lua_Integer ib; if (tointegerns(rb, &ib)) { @@ -171294,6 +171513,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_NOT) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb)) setbtvalue(s2v(ra)); @@ -171302,21 +171522,25 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_LEN) { + StkId ra = RA(i); Protect(luaV_objlen(L, ra, vRB(i))); vmbreak; } vmcase(OP_CONCAT) { + StkId ra = RA(i); int n = GETARG_B(i); /* number of elements to concatenate */ - L->top = ra + n; /* mark the end of concat operands */ + L->top.p = ra + n; /* mark the end of concat operands */ ProtectNT(luaV_concat(L, n)); - checkGC(L, L->top); /* 'luaV_concat' ensures correct top */ + checkGC(L, L->top.p); /* 'luaV_concat' ensures correct top */ vmbreak; } vmcase(OP_CLOSE) { + StkId ra = RA(i); Protect(luaF_close(L, ra, LUA_OK, 1)); vmbreak; } vmcase(OP_TBC) { + StkId ra = RA(i); /* create new to-be-closed upvalue */ halfProtect(luaF_newtbcupval(L, ra)); vmbreak; @@ -171326,6 +171550,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQ) { + StkId ra = RA(i); int cond; TValue *rb = vRB(i); Protect(cond = luaV_equalobj(L, s2v(ra), rb)); @@ -171341,6 +171566,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQK) { + StkId ra = RA(i); TValue *rb = KB(i); /* basic types do not use '__eq'; we can use raw equality */ int cond = luaV_rawequalobj(s2v(ra), rb); @@ -171348,6 +171574,7 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_EQI) { + StkId ra = RA(i); int cond; int im = GETARG_sB(i); if (ttisinteger(s2v(ra))) @@ -171376,11 +171603,13 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TEST) { + StkId ra = RA(i); int cond = !l_isfalse(s2v(ra)); docondjump(); vmbreak; } vmcase(OP_TESTSET) { + StkId ra = RA(i); TValue *rb = vRB(i); if (l_isfalse(rb) == GETARG_k(i)) pc++; @@ -171391,11 +171620,12 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CALL) { + StkId ra = RA(i); CallInfo *newci; int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) /* fixed number of arguments? */ - L->top = ra + b; /* top signals number of arguments */ + L->top.p = ra + b; /* top signals number of arguments */ /* else previous instruction set top */ savepc(L); /* in case of errors */ if ((newci = luaD_precall(L, ra, nresults)) == NULL) @@ -171407,54 +171637,57 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_TAILCALL) { + StkId ra = RA(i); int b = GETARG_B(i); /* number of arguments + 1 (function) */ int n; /* number of results when calling a C function */ int nparams1 = GETARG_C(i); /* delta is virtual 'func' - real 'func' (vararg functions) */ int delta = (nparams1) ? ci->u.l.nextraargs + nparams1 : 0; if (b != 0) - L->top = ra + b; + L->top.p = ra + b; else /* previous instruction set top */ - b = cast_int(L->top - ra); + b = cast_int(L->top.p - ra); savepc(ci); /* several calls here can raise errors */ if (TESTARG_k(i)) { luaF_closeupval(L, base); /* close upvalues from current call */ - lua_assert(L->tbclist < base); /* no pending tbc variables */ - lua_assert(base == ci->func + 1); + lua_assert(L->tbclist.p < base); /* no pending tbc variables */ + lua_assert(base == ci->func.p + 1); } if ((n = luaD_pretailcall(L, ci, ra, b, delta)) < 0) /* Lua function? */ goto startfunc; /* execute the callee */ else { /* C function? */ - ci->func -= delta; /* restore 'func' (if vararg) */ + ci->func.p -= delta; /* restore 'func' (if vararg) */ luaD_poscall(L, ci, n); /* finish caller */ updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; /* caller returns after the tail call */ } } vmcase(OP_RETURN) { + StkId ra = RA(i); int n = GETARG_B(i) - 1; /* number of results */ int nparams1 = GETARG_C(i); if (n < 0) /* not fixed? */ - n = cast_int(L->top - ra); /* get what is available */ + n = cast_int(L->top.p - ra); /* get what is available */ savepc(ci); if (TESTARG_k(i)) { /* may there be open upvalues? */ ci->u2.nres = n; /* save number of returns */ - if (L->top < ci->top) - L->top = ci->top; + if (L->top.p < ci->top.p) + L->top.p = ci->top.p; luaF_close(L, base, CLOSEKTOP, 1); updatetrap(ci); updatestack(ci); } if (nparams1) /* vararg function? */ - ci->func -= ci->u.l.nextraargs + nparams1; - L->top = ra + n; /* set call for 'luaD_poscall' */ + ci->func.p -= ci->u.l.nextraargs + nparams1; + L->top.p = ra + n; /* set call for 'luaD_poscall' */ luaD_poscall(L, ci, n); updatetrap(ci); /* 'luaD_poscall' can change hooks */ goto ret; } vmcase(OP_RETURN0) { if (l_unlikely(L->hookmask)) { - L->top = ra; + StkId ra = RA(i); + L->top.p = ra; savepc(ci); luaD_poscall(L, ci, 0); /* no hurry... */ trap = 1; @@ -171462,15 +171695,16 @@ static const void *const disptab[NUM_OPCODES] = { else { /* do the 'poscall' here */ int nres; L->ci = ci->previous; /* back to caller */ - L->top = base - 1; + L->top.p = base - 1; for (nres = ci->nresults; l_unlikely(nres > 0); nres--) - setnilvalue(s2v(L->top++)); /* all results are nil */ + setnilvalue(s2v(L->top.p++)); /* all results are nil */ } goto ret; } vmcase(OP_RETURN1) { if (l_unlikely(L->hookmask)) { - L->top = ra + 1; + StkId ra = RA(i); + L->top.p = ra + 1; savepc(ci); luaD_poscall(L, ci, 1); /* no hurry... */ trap = 1; @@ -171479,12 +171713,13 @@ static const void *const disptab[NUM_OPCODES] = { int nres = ci->nresults; L->ci = ci->previous; /* back to caller */ if (nres == 0) - L->top = base - 1; /* asked for no results */ + L->top.p = base - 1; /* asked for no results */ else { + StkId ra = RA(i); setobjs2s(L, base - 1, ra); /* at least this result */ - L->top = base; + L->top.p = base; for (; l_unlikely(nres > 1); nres--) - setnilvalue(s2v(L->top++)); /* complete missing results */ + setnilvalue(s2v(L->top.p++)); /* complete missing results */ } } ret: /* return from a Lua function */ @@ -171496,6 +171731,7 @@ static const void *const disptab[NUM_OPCODES] = { } } vmcase(OP_FORLOOP) { + StkId ra = RA(i); if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); if (count > 0) { /* still more iterations? */ @@ -171514,12 +171750,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_FORPREP) { + StkId ra = RA(i); savestate(L, ci); /* in case of errors */ if (forprep(L, ra)) pc += GETARG_Bx(i) + 1; /* skip the loop */ vmbreak; } vmcase(OP_TFORPREP) { + StkId ra = RA(i); /* create to-be-closed upvalue (if needed) */ halfProtect(luaF_newtbcupval(L, ra + 3)); pc += GETARG_Bx(i); @@ -171528,7 +171766,8 @@ static const void *const disptab[NUM_OPCODES] = { goto l_tforcall; } vmcase(OP_TFORCALL) { - l_tforcall: + l_tforcall: { + StkId ra = RA(i); /* 'ra' has the iterator function, 'ra + 1' has the state, 'ra + 2' has the control variable, and 'ra + 3' has the to-be-closed variable. The call will use the stack after @@ -171536,29 +171775,31 @@ static const void *const disptab[NUM_OPCODES] = { */ /* push function, state, and control variable */ memcpy(ra + 4, ra, 3 * sizeof(*ra)); - L->top = ra + 4 + 3; + L->top.p = ra + 4 + 3; ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); goto l_tforloop; - } + }} vmcase(OP_TFORLOOP) { - l_tforloop: + l_tforloop: { + StkId ra = RA(i); if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ setobjs2s(L, ra + 2, ra + 4); /* save control variable */ pc -= GETARG_Bx(i); /* jump back */ } vmbreak; - } + }} vmcase(OP_SETLIST) { + StkId ra = RA(i); int n = GETARG_B(i); unsigned int last = GETARG_C(i); Table *h = hvalue(s2v(ra)); if (n == 0) - n = cast_int(L->top - ra) - 1; /* get up to the top */ + n = cast_int(L->top.p - ra) - 1; /* get up to the top */ else - L->top = ci->top; /* correct top in case of emergency GC */ + L->top.p = ci->top.p; /* correct top in case of emergency GC */ last += n; if (TESTARG_k(i)) { last += GETARG_Ax(*pc) * (MAXARG_C + 1); @@ -171575,12 +171816,14 @@ static const void *const disptab[NUM_OPCODES] = { vmbreak; } vmcase(OP_CLOSURE) { + StkId ra = RA(i); Proto *p = cl->p->p[GETARG_Bx(i)]; halfProtect(pushclosure(L, p, cl->upvals, base, ra)); checkGC(L, ra + 1); vmbreak; } vmcase(OP_VARARG) { + StkId ra = RA(i); int n = GETARG_C(i) - 1; /* required results */ Protect(luaT_getvarargs(L, ci, ra, n)); vmbreak; @@ -171665,27 +171908,28 @@ const char lua_ident[] = static TValue *index2value (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index"); - if (o >= L->top) return &G(L)->nilvalue; + StkId o = ci->func.p + idx; + api_check(L, idx <= ci->top.p - (ci->func.p + 1), "unacceptable index"); + if (o >= L->top.p) return &G(L)->nilvalue; else return s2v(o); } else if (!ispseudo(idx)) { /* negative index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); - return s2v(L->top + idx); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); + return s2v(L->top.p + idx); } else if (idx == LUA_REGISTRYINDEX) return &G(L)->l_registry; else { /* upvalues */ idx = LUA_REGISTRYINDEX - idx; api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); - if (ttisCclosure(s2v(ci->func))) { /* C closure? */ - CClosure *func = clCvalue(s2v(ci->func)); + if (ttisCclosure(s2v(ci->func.p))) { /* C closure? */ + CClosure *func = clCvalue(s2v(ci->func.p)); return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue; } else { /* light C function or Lua function (through a hook)?) */ - api_check(L, ttislcf(s2v(ci->func)), "caller not a C function"); + api_check(L, ttislcf(s2v(ci->func.p)), "caller not a C function"); return &G(L)->nilvalue; /* no upvalues */ } } @@ -171699,14 +171943,15 @@ static TValue *index2value (lua_State *L, int idx) { l_sinline StkId index2stack (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { - StkId o = ci->func + idx; - api_check(L, o < L->top, "invalid index"); + StkId o = ci->func.p + idx; + api_check(L, o < L->top.p, "invalid index"); return o; } else { /* non-positive index */ - api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + api_check(L, idx != 0 && -idx <= L->top.p - (ci->func.p + 1), + "invalid index"); api_check(L, !ispseudo(idx), "invalid index"); - return L->top + idx; + return L->top.p + idx; } } @@ -171717,17 +171962,12 @@ LUA_API int lua_checkstack (lua_State *L, int n) { lua_lock(L); ci = L->ci; api_check(L, n >= 0, "negative 'n'"); - if (L->stack_last - L->top > n) /* stack large enough? */ + if (L->stack_last.p - L->top.p > n) /* stack large enough? */ res = 1; /* yes; check is OK */ - else { /* no; need to grow stack */ - int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; - if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ - res = 0; /* no */ - else /* try to grow stack */ - res = luaD_growstack(L, n, 0); - } - if (res && ci->top < L->top + n) - ci->top = L->top + n; /* adjust frame top */ + else /* need to grow stack */ + res = luaD_growstack(L, n, 0); + if (res && ci->top.p < L->top.p + n) + ci->top.p = L->top.p + n; /* adjust frame top */ lua_unlock(L); return res; } @@ -171739,11 +171979,11 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to), "moving among independent states"); - api_check(from, to->ci->top - to->top >= n, "stack overflow"); - from->top -= n; + api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); + from->top.p -= n; for (i = 0; i < n; i++) { - setobjs2s(to, to->top, from->top + i); - to->top++; /* stack already checked by previous 'api_check' */ + setobjs2s(to, to->top.p, from->top.p + i); + to->top.p++; /* stack already checked by previous 'api_check' */ } lua_unlock(to); } @@ -171777,12 +172017,12 @@ LUA_API lua_Number lua_version (lua_State *L) { LUA_API int lua_absindex (lua_State *L, int idx) { return (idx > 0 || ispseudo(idx)) ? idx - : cast_int(L->top - L->ci->func) + idx; + : cast_int(L->top.p - L->ci->func.p) + idx; } LUA_API int lua_gettop (lua_State *L) { - return cast_int(L->top - (L->ci->func + 1)); + return cast_int(L->top.p - (L->ci->func.p + 1)); } @@ -171792,24 +172032,24 @@ LUA_API void lua_settop (lua_State *L, int idx) { ptrdiff_t diff; /* difference for new top */ lua_lock(L); ci = L->ci; - func = ci->func; + func = ci->func.p; if (idx >= 0) { - api_check(L, idx <= ci->top - (func + 1), "new top too large"); - diff = ((func + 1) + idx) - L->top; + api_check(L, idx <= ci->top.p - (func + 1), "new top too large"); + diff = ((func + 1) + idx) - L->top.p; for (; diff > 0; diff--) - setnilvalue(s2v(L->top++)); /* clear new slots */ + setnilvalue(s2v(L->top.p++)); /* clear new slots */ } else { - api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); diff = idx + 1; /* will "subtract" index (as it is negative) */ } - api_check(L, L->tbclist < L->top, "previous pop of an unclosed slot"); - newtop = L->top + diff; - if (diff < 0 && L->tbclist >= newtop) { + api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot"); + newtop = L->top.p + diff; + if (diff < 0 && L->tbclist.p >= newtop) { lua_assert(hastocloseCfunc(ci->nresults)); - luaF_close(L, newtop, CLOSEKTOP, 0); + newtop = luaF_close(L, newtop, CLOSEKTOP, 0); } - L->top = newtop; /* correct top only after closing any upvalue */ + L->top.p = newtop; /* correct top only after closing any upvalue */ lua_unlock(L); } @@ -171818,10 +172058,9 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { StkId level; lua_lock(L); level = index2stack(L, idx); - api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist == level, + api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level, "no variable to close at given level"); - luaF_close(L, level, CLOSEKTOP, 0); - level = index2stack(L, idx); /* stack may be moved */ + level = luaF_close(L, level, CLOSEKTOP, 0); setnilvalue(s2v(level)); lua_unlock(L); } @@ -171850,7 +172089,7 @@ l_sinline void reverse (lua_State *L, StkId from, StkId to) { LUA_API void lua_rotate (lua_State *L, int idx, int n) { StkId p, t, m; lua_lock(L); - t = L->top - 1; /* end of stack segment being rotated */ + t = L->top.p - 1; /* end of stack segment being rotated */ p = index2stack(L, idx); /* start of segment */ api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ @@ -171869,7 +172108,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { api_check(L, isvalid(L, to), "invalid index"); setobj(L, to, fr); if (isupvalue(toidx)) /* function upvalue? */ - luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr); + luaC_barrier(L, clCvalue(s2v(L->ci->func.p)), fr); /* LUA_REGISTRYINDEX does not need gc barrier (collector revisits it before finishing collection) */ lua_unlock(L); @@ -171878,7 +172117,7 @@ LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); - setobj2s(L, L->top, index2value(L, idx)); + setobj2s(L, L->top.p, index2value(L, idx)); api_incr_top(L); lua_unlock(L); } @@ -171947,12 +172186,12 @@ LUA_API void lua_arith (lua_State *L, int op) { api_checknelems(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ api_checknelems(L, 1); - setobjs2s(L, L->top, L->top - 1); + setobjs2s(L, L->top.p, L->top.p - 1); api_incr_top(L); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ - luaO_arith(L, op, s2v(L->top - 2), s2v(L->top - 1), L->top - 2); - L->top--; /* remove second operand */ + luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); + L->top.p--; /* remove second operand */ lua_unlock(L); } @@ -171978,7 +172217,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { - size_t sz = luaO_str2num(s, s2v(L->top)); + size_t sz = luaO_str2num(s, s2v(L->top.p)); if (sz != 0) api_incr_top(L); return sz; @@ -172105,7 +172344,7 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) { LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -172113,7 +172352,7 @@ LUA_API void lua_pushnil (lua_State *L) { LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); - setfltvalue(s2v(L->top), n); + setfltvalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -172121,7 +172360,7 @@ LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); - setivalue(s2v(L->top), n); + setivalue(s2v(L->top.p), n); api_incr_top(L); lua_unlock(L); } @@ -172136,7 +172375,7 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { TString *ts; lua_lock(L); ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -172147,11 +172386,11 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { LUA_API const char *lua_pushstring (lua_State *L, const char *s) { lua_lock(L); if (s == NULL) - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else { TString *ts; ts = luaS_new(L, s); - setsvalue2s(L, L->top, ts); + setsvalue2s(L, L->top.p, ts); s = getstr(ts); /* internal copy's address */ } api_incr_top(L); @@ -172188,7 +172427,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { lua_lock(L); if (n == 0) { - setfvalue(s2v(L->top), fn); + setfvalue(s2v(L->top.p), fn); api_incr_top(L); } else { @@ -172197,13 +172436,13 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { api_check(L, n <= MAXUPVAL, "upvalue index too large"); cl = luaF_newCclosure(L, n); cl->f = fn; - L->top -= n; + L->top.p -= n; while (n--) { - setobj2n(L, &cl->upvalue[n], s2v(L->top + n)); + setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n)); /* does not need barrier because closure is white */ lua_assert(iswhite(cl)); } - setclCvalue(L, s2v(L->top), cl); + setclCvalue(L, s2v(L->top.p), cl); api_incr_top(L); luaC_checkGC(L); } @@ -172214,9 +172453,9 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); if (b) - setbtvalue(s2v(L->top)); + setbtvalue(s2v(L->top.p)); else - setbfvalue(s2v(L->top)); + setbfvalue(s2v(L->top.p)); api_incr_top(L); lua_unlock(L); } @@ -172224,7 +172463,7 @@ LUA_API void lua_pushboolean (lua_State *L, int b) { LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); - setpvalue(s2v(L->top), p); + setpvalue(s2v(L->top.p), p); api_incr_top(L); lua_unlock(L); } @@ -172232,7 +172471,7 @@ LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); - setthvalue(L, s2v(L->top), L); + setthvalue(L, s2v(L->top.p), L); api_incr_top(L); lua_unlock(L); return (G(L)->mainthread == L); @@ -172249,16 +172488,16 @@ l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { const TValue *slot; TString *str = luaS_new(L, k); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); api_incr_top(L); } else { - setsvalue2s(L, L->top, str); + setsvalue2s(L, L->top.p, str); api_incr_top(L); - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); } lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -172285,13 +172524,13 @@ LUA_API int lua_gettable (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 1), slot, luaH_get)) { - setobj2s(L, L->top - 1, slot); + if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { + setobj2s(L, L->top.p - 1, slot); } else - luaV_finishget(L, t, s2v(L->top - 1), L->top - 1, slot); + luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -172307,27 +172546,27 @@ LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - setobj2s(L, L->top, slot); + setobj2s(L, L->top.p, slot); } else { TValue aux; setivalue(&aux, n); - luaV_finishget(L, t, &aux, L->top, slot); + luaV_finishget(L, t, &aux, L->top.p, slot); } api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } l_sinline int finishrawget (lua_State *L, const TValue *val) { if (isempty(val)) /* avoid copying empty items to the stack */ - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); else - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top - 1)); + return ttype(s2v(L->top.p - 1)); } @@ -172344,8 +172583,8 @@ LUA_API int lua_rawget (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - val = luaH_get(t, s2v(L->top - 1)); - L->top--; /* remove key */ + val = luaH_get(t, s2v(L->top.p - 1)); + L->top.p--; /* remove key */ return finishrawget(L, val); } @@ -172372,7 +172611,7 @@ LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { Table *t; lua_lock(L); t = luaH_new(L); - sethvalue2s(L, L->top, t); + sethvalue2s(L, L->top.p, t); api_incr_top(L); if (narray > 0 || nrec > 0) luaH_resize(L, t, narray, nrec); @@ -172399,7 +172638,7 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { break; } if (mt != NULL) { - sethvalue2s(L, L->top, mt); + sethvalue2s(L, L->top.p, mt); api_incr_top(L); res = 1; } @@ -172415,12 +172654,12 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { o = index2value(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); if (n <= 0 || n > uvalue(o)->nuvalue) { - setnilvalue(s2v(L->top)); + setnilvalue(s2v(L->top.p)); t = LUA_TNONE; } else { - setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); - t = ttype(s2v(L->top)); + setobj2s(L, L->top.p, &uvalue(o)->uv[n - 1].uv); + t = ttype(s2v(L->top.p)); } api_incr_top(L); lua_unlock(L); @@ -172440,14 +172679,14 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { TString *str = luaS_new(L, k); api_checknelems(L, 1); if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); - L->top--; /* pop value */ + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); + L->top.p--; /* pop value */ } else { - setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ api_incr_top(L); - luaV_finishset(L, t, s2v(L->top - 1), s2v(L->top - 2), slot); - L->top -= 2; /* pop value and key */ + luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); + L->top.p -= 2; /* pop value and key */ } lua_unlock(L); /* lock done by caller */ } @@ -172467,12 +172706,12 @@ LUA_API void lua_settable (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 2); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top - 2), slot, luaH_get)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else - luaV_finishset(L, t, s2v(L->top - 2), s2v(L->top - 1), slot); - L->top -= 2; /* pop index and value */ + luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); + L->top.p -= 2; /* pop index and value */ lua_unlock(L); } @@ -172490,14 +172729,14 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { api_checknelems(L, 1); t = index2value(L, idx); if (luaV_fastgeti(L, t, n, slot)) { - luaV_finishfastset(L, t, slot, s2v(L->top - 1)); + luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); } else { TValue aux; setivalue(&aux, n); - luaV_finishset(L, t, &aux, s2v(L->top - 1), slot); + luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); } - L->top--; /* pop value */ + L->top.p--; /* pop value */ lua_unlock(L); } @@ -172507,16 +172746,16 @@ static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { lua_lock(L); api_checknelems(L, n); t = gettable(L, idx); - luaH_set(L, t, key, s2v(L->top - 1)); + luaH_set(L, t, key, s2v(L->top.p - 1)); invalidateTMcache(t); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top -= n; + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p -= n; lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { - aux_rawset(L, idx, s2v(L->top - 2), 2); + aux_rawset(L, idx, s2v(L->top.p - 2), 2); } @@ -172532,9 +172771,9 @@ LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - luaH_setint(L, t, n, s2v(L->top - 1)); - luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); - L->top--; + luaH_setint(L, t, n, s2v(L->top.p - 1)); + luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); + L->top.p--; lua_unlock(L); } @@ -172545,11 +172784,11 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { lua_lock(L); api_checknelems(L, 1); obj = index2value(L, objindex); - if (ttisnil(s2v(L->top - 1))) + if (ttisnil(s2v(L->top.p - 1))) mt = NULL; else { - api_check(L, ttistable(s2v(L->top - 1)), "table expected"); - mt = hvalue(s2v(L->top - 1)); + api_check(L, ttistable(s2v(L->top.p - 1)), "table expected"); + mt = hvalue(s2v(L->top.p - 1)); } switch (ttype(obj)) { case LUA_TTABLE: { @@ -172573,7 +172812,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { break; } } - L->top--; + L->top.p--; lua_unlock(L); return 1; } @@ -172589,11 +172828,11 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) res = 0; /* 'n' not in [1, uvalue(o)->nuvalue] */ else { - setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); - luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); + setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top.p - 1)); + luaC_barrierback(L, gcvalue(o), s2v(L->top.p - 1)); res = 1; } - L->top--; + L->top.p--; lua_unlock(L); return res; } @@ -172605,7 +172844,8 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + api_check(L, (nr) == LUA_MULTRET \ + || (L->ci->top.p - L->top.p >= (nr) - (na)), \ "results from function overflow current stack size") @@ -172618,7 +172858,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, api_checknelems(L, nargs+1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); - func = L->top - (nargs+1); + func = L->top.p - (nargs+1); if (k != NULL && yieldable(L)) { /* need to prepare continuation? */ L->ci->u.c.k = k; /* save continuation */ L->ci->u.c.ctx = ctx; /* save context */ @@ -172666,7 +172906,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, api_check(L, ttisfunction(s2v(o)), "error handler must be a function"); func = savestack(L, o); } - c.func = L->top - (nargs+1); /* function to be called */ + c.func = L->top.p - (nargs+1); /* function to be called */ if (k == NULL || !yieldable(L)) { /* no continuation or no yieldable? */ c.nresults = nresults; /* do a 'conventional' protected call */ status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); @@ -172701,12 +172941,12 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, luaZ_init(L, &z, reader, data); status = luaD_protectedparser(L, &z, chunkname, mode); if (status == LUA_OK) { /* no errors? */ - LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ + LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ if (f->nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ const TValue *gt = getGtable(L); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v, gt); + setobj(L, f->upvals[0]->v.p, gt); luaC_barrier(L, f->upvals[0], gt); } } @@ -172720,7 +172960,7 @@ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { TValue *o; lua_lock(L); api_checknelems(L, 1); - o = s2v(L->top - 1); + o = s2v(L->top.p - 1); if (isLfunction(o)) status = luaU_dump(L, getproto(o), writer, data, strip); else @@ -172846,7 +173086,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { LUA_API int lua_error (lua_State *L) { TValue *errobj; lua_lock(L); - errobj = s2v(L->top - 1); + errobj = s2v(L->top.p - 1); api_checknelems(L, 1); /* error object is the memory error message? */ if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) @@ -172864,12 +173104,12 @@ LUA_API int lua_next (lua_State *L, int idx) { lua_lock(L); api_checknelems(L, 1); t = gettable(L, idx); - more = luaH_next(L, t, L->top - 1); + more = luaH_next(L, t, L->top.p - 1); if (more) { api_incr_top(L); } else /* no more elements */ - L->top -= 1; /* remove key */ + L->top.p -= 1; /* remove key */ lua_unlock(L); return more; } @@ -172881,7 +173121,7 @@ LUA_API void lua_toclose (lua_State *L, int idx) { lua_lock(L); o = index2stack(L, idx); nresults = L->ci->nresults; - api_check(L, L->tbclist < o, "given index below or equal a marked one"); + api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ if (!hastocloseCfunc(nresults)) /* function not marked yet? */ L->ci->nresults = codeNresults(nresults); /* mark it */ @@ -172896,7 +173136,7 @@ LUA_API void lua_concat (lua_State *L, int n) { if (n > 0) luaV_concat(L, n); else { /* nothing to concatenate */ - setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); /* push empty string */ + setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ api_incr_top(L); } luaC_checkGC(L); @@ -172908,7 +173148,7 @@ LUA_API void lua_len (lua_State *L, int idx) { TValue *t; lua_lock(L); t = index2value(L, idx); - luaV_objlen(L, L->top, t); + luaV_objlen(L, L->top.p, t); api_incr_top(L); lua_unlock(L); } @@ -172953,7 +173193,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { lua_lock(L); api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); u = luaS_newudata(L, size, nuvalue); - setuvalue(L, s2v(L->top), u); + setuvalue(L, s2v(L->top.p), u); api_incr_top(L); luaC_checkGC(L); lua_unlock(L); @@ -172979,7 +173219,7 @@ static const char *aux_upvalue (TValue *fi, int n, TValue **val, Proto *p = f->p; if (!(cast_uint(n) - 1u < cast_uint(p->sizeupvalues))) return NULL; /* 'n' not in [1, p->sizeupvalues] */ - *val = f->upvals[n-1]->v; + *val = f->upvals[n-1]->v.p; if (owner) *owner = obj2gco(f->upvals[n - 1]); name = p->upvalues[n-1].name; return (name == NULL) ? "(no name)" : getstr(name); @@ -172995,7 +173235,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { lua_lock(L); name = aux_upvalue(index2value(L, funcindex), n, &val, NULL); if (name) { - setobj2s(L, L->top, val); + setobj2s(L, L->top.p, val); api_incr_top(L); } lua_unlock(L); @@ -173013,8 +173253,8 @@ LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { api_checknelems(L, 1); name = aux_upvalue(fi, n, &val, &owner); if (name) { - L->top--; - setobj(L, val, s2v(L->top)); + L->top.p--; + setobj(L, val, s2v(L->top.p)); luaC_barrier(L, owner, val); } lua_unlock(L); @@ -173597,13 +173837,14 @@ static void newbox (lua_State *L) { /* ** Compute new size for buffer 'B', enough to accommodate extra 'sz' -** bytes. +** bytes. (The test for "not big enough" also gets the case when the +** computation of 'newsize' overflows.) */ static size_t newbuffsize (luaL_Buffer *B, size_t sz) { - size_t newsize = B->size * 2; /* double buffer size */ + size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */ if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ return luaL_error(B->L, "buffer too large"); - if (newsize < B->n + sz) /* double is not big enough? */ + if (newsize < B->n + sz) /* not big enough? */ newsize = B->n + sz; return newsize; } @@ -173682,7 +173923,7 @@ LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { ** box (if existent) is not on the top of the stack. So, instead of ** calling 'luaL_addlstring', it replicates the code using -2 as the ** last argument to 'prepbuffsize', signaling that the box is (or will -** be) bellow the string being added to the buffer. (Box creation can +** be) below the string being added to the buffer. (Box creation can ** trigger an emergency GC, so we should not remove the string from the ** stack before we have the space guaranteed.) */ @@ -173810,17 +174051,18 @@ static int errfile (lua_State *L, const char *what, int fnameindex) { } -static int skipBOM (LoadF *lf) { - const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ - int c; - lf->n = 0; - do { - c = getc(lf->f); - if (c == EOF || c != *(const unsigned char *)p++) return c; - lf->buff[lf->n++] = c; /* to be read by the parser */ - } while (*p != '\0'); - lf->n = 0; /* prefix matched; discard it */ - return getc(lf->f); /* return next character */ +/* +** Skip an optional BOM at the start of a stream. If there is an +** incomplete BOM (the first character is correct but the rest is +** not), returns the first character anyway to force an error +** (as no chunk can start with 0xEF). +*/ +static int skipBOM (FILE *f) { + int c = getc(f); /* read first character */ + if (c == 0xEF && getc(f) == 0xBB && getc(f) == 0xBF) /* correct BOM? */ + return getc(f); /* ignore BOM and return next char */ + else /* no (valid) BOM */ + return c; /* return first character */ } @@ -173831,13 +174073,13 @@ static int skipBOM (LoadF *lf) { ** first "valid" character of the file (after the optional BOM and ** a first-line comment). */ -static int skipcomment (LoadF *lf, int *cp) { - int c = *cp = skipBOM(lf); +static int skipcomment (FILE *f, int *cp) { + int c = *cp = skipBOM(f); if (c == '#') { /* first line is a comment (Unix exec. file)? */ do { /* skip first line */ - c = getc(lf->f); + c = getc(f); } while (c != EOF && c != '\n'); - *cp = getc(lf->f); /* skip end-of-line, if present */ + *cp = getc(f); /* next character after comment, if present */ return 1; /* there was a comment */ } else return 0; /* no comment */ @@ -173859,12 +174101,16 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } - if (skipcomment(&lf, &c)) /* read initial portion */ - lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ - if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ - lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ - if (lf.f == NULL) return errfile(L, "reopen", fnameindex); - skipcomment(&lf, &c); /* re-read initial portion */ + lf.n = 0; + if (skipcomment(lf.f, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add newline to correct line numbers */ + if (c == LUA_SIGNATURE[0]) { /* binary file? */ + lf.n = 0; /* remove possible newline */ + if (filename) { /* "real" file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(lf.f, &c); /* re-read initial portion */ + } } if (c != EOF) lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ @@ -174802,7 +175048,7 @@ static int luaB_auxwrap (lua_State *L) { if (l_unlikely(r < 0)) { /* error? */ int stat = lua_status(co); if (stat != LUA_OK && stat != LUA_YIELD) { /* error in the coroutine? */ - stat = lua_resetthread(co); /* close its tbc variables */ + stat = lua_closethread(co, L); /* close its tbc variables */ lua_assert(stat != LUA_OK); lua_xmove(co, L, 1); /* move error message to the caller */ } @@ -174898,7 +175144,7 @@ static int luaB_close (lua_State *L) { int status = auxstatus(L, co); switch (status) { case COS_DEAD: case COS_YIELD: { - status = lua_resetthread(co); + status = lua_closethread(co, L); if (status == LUA_OK) { lua_pushboolean(L, 1); return 1; @@ -176514,7 +176760,7 @@ static int math_type (lua_State *L) { /* try to find an integer type with at least 64 bits */ -#if (ULONG_MAX >> 31 >> 31) >= 3 +#if ((ULONG_MAX >> 31) >> 31) >= 3 /* 'long' has at least 64 bits */ #define Rand64 unsigned long @@ -176524,9 +176770,9 @@ static int math_type (lua_State *L) { /* there is a 'long long' type (which must have at least 64 bits) */ #define Rand64 unsigned long long -#elif (LUA_MAXUNSIGNED >> 31 >> 31) >= 3 +#elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 -/* 'lua_Integer' has at least 64 bits */ +/* 'lua_Unsigned' has at least 64 bits */ #define Rand64 lua_Unsigned #endif @@ -176747,12 +176993,12 @@ static lua_Number I2d (Rand64 x) { /* convert a 'Rand64' to a 'lua_Unsigned' */ static lua_Unsigned I2UInt (Rand64 x) { - return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l); + return (((lua_Unsigned)trim32(x.h) << 31) << 1) | (lua_Unsigned)trim32(x.l); } /* convert a 'lua_Unsigned' to a 'Rand64' */ static Rand64 Int2I (lua_Unsigned n) { - return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n); + return packI((lu_int32)((n >> 31) >> 1), (lu_int32)n); } #endif /* } */ @@ -177719,8 +177965,13 @@ static const luaL_Reg ll_funcs[] = { static void createsearcherstable (lua_State *L) { - static const lua_CFunction searchers[] = - {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + static const lua_CFunction searchers[] = { + searcher_preload, + searcher_Lua, + searcher_C, + searcher_Croot, + NULL + }; int i; /* create 'searchers' table */ lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); @@ -177803,23 +178054,14 @@ LUAMOD_API int luaopen_package (lua_State *L) { */ #if !defined(LUA_STRFTIMEOPTIONS) /* { */ -/* options for ANSI C 89 (only 1-char options) */ -#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" - -/* options for ISO C 99 and POSIX */ -#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ - "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ - -/* options for Windows */ -#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ - "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ - #if defined(LUA_USE_WINDOWS) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN -#elif defined(LUA_USE_C89) -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ +#elif defined(LUA_USE_C89) /* ANSI C 89 (only 1-char options) */ +#define LUA_STRFTIMEOPTIONS "aAbBcdHIjmMpSUwWxXyYZ%" #else /* C99 specification */ -#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#define LUA_STRFTIMEOPTIONS "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ #endif #endif /* } */ @@ -177911,12 +178153,21 @@ LUAMOD_API int luaopen_package (lua_State *L) { /* }================================================================== */ +#if !defined(l_system) +#if defined(LUA_USE_IOS) +/* Despite claiming to be ISO C, iOS does not implement 'system'. */ +#define l_system(cmd) ((cmd) == NULL ? 0 : -1) +#else +#define l_system(cmd) system(cmd) /* default definition */ +#endif +#endif + static int os_execute (lua_State *L) { const char *cmd = luaL_optstring(L, 1, NULL); int stat; errno = 0; - stat = system(cmd); + stat = l_system(cmd); if (cmd != NULL) return luaL_execresult(L, stat); else { @@ -178033,9 +178284,7 @@ static int getfield (lua_State *L, const char *key, int d, int delta) { res = d; } else { - /* unsigned avoids overflow when lua_Integer has 32 bits */ - if (!(res >= 0 ? (lua_Unsigned)res <= (lua_Unsigned)INT_MAX + delta - : (lua_Integer)INT_MIN + delta <= res)) + if (!(res >= 0 ? res - delta <= INT_MAX : INT_MIN + delta <= res)) return luaL_error(L, "field '%s' is out-of-bound", key); res -= delta; } @@ -178773,7 +179022,7 @@ static const char *match_capture (MatchState *ms, const char *s, int l) { static const char *match (MatchState *ms, const char *s, const char *p) { if (l_unlikely(ms->matchdepth-- == 0)) luaL_error(ms->L, "pattern too complex"); - init: /* using goto's to optimize tail recursion */ + init: /* using goto to optimize tail recursion */ if (p != ms->p_end) { /* end of pattern? */ switch (*p) { case '(': { /* start capture */ @@ -180170,7 +180419,7 @@ static int tremove (lua_State *L) { lua_Integer pos = luaL_optinteger(L, 2, size); if (pos != size) /* validate 'pos' if given */ /* check whether 'pos' is in [1, size + 1] */ - luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 1, + luaL_argcheck(L, (lua_Unsigned)pos - 1u <= (lua_Unsigned)size, 2, "position out of bounds"); lua_geti(L, 1, pos); /* result = t[pos] */ for ( ; pos < size; pos++) { @@ -180532,6 +180781,9 @@ LUAMOD_API int luaopen_table (lua_State *L) { #define MAXUTF 0x7FFFFFFFu + +#define MSGInvalid "invalid UTF-8 code" + /* ** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. */ @@ -180542,7 +180794,8 @@ typedef unsigned long utfint; #endif -#define iscont(p) ((*(p) & 0xC0) == 0x80) +#define iscont(c) (((c) & 0xC0) == 0x80) +#define iscontp(p) iscont(*(p)) /* from strlib */ @@ -180572,7 +180825,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { int count = 0; /* to count number of continuation bytes */ for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ unsigned int cc = (unsigned char)s[++count]; /* read next byte */ - if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + if (!iscont(cc)) /* not a continuation byte? */ return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ } @@ -180647,7 +180900,7 @@ static int codepoint (lua_State *L) { utfint code; s = utf8_decode(s, &code, !lax); if (s == NULL) - return luaL_error(L, "invalid UTF-8 code"); + return luaL_error(L, MSGInvalid); lua_pushinteger(L, code); n++; } @@ -180697,16 +180950,16 @@ static int byteoffset (lua_State *L) { "position out of bounds"); if (n == 0) { /* find beginning of current byte sequence */ - while (posi > 0 && iscont(s + posi)) posi--; + while (posi > 0 && iscontp(s + posi)) posi--; } else { - if (iscont(s + posi)) + if (iscontp(s + posi)) return luaL_error(L, "initial position is a continuation byte"); if (n < 0) { while (n < 0 && posi > 0) { /* move back */ do { /* find beginning of previous character */ posi--; - } while (posi > 0 && iscont(s + posi)); + } while (posi > 0 && iscontp(s + posi)); n++; } } @@ -180715,7 +180968,7 @@ static int byteoffset (lua_State *L) { while (n > 0 && posi < (lua_Integer)len) { do { /* find beginning of next character */ posi++; - } while (iscont(s + posi)); /* (cannot pass final '\0') */ + } while (iscontp(s + posi)); /* (cannot pass final '\0') */ n--; } } @@ -180733,15 +180986,15 @@ static int iter_aux (lua_State *L, int strict) { const char *s = luaL_checklstring(L, 1, &len); lua_Unsigned n = (lua_Unsigned)lua_tointeger(L, 2); if (n < len) { - while (iscont(s + n)) n++; /* skip continuation bytes */ + while (iscontp(s + n)) n++; /* go to next character */ } if (n >= len) /* (also handles original 'n' being negative) */ return 0; /* no more codepoints */ else { utfint code; const char *next = utf8_decode(s + n, &code, strict); - if (next == NULL) - return luaL_error(L, "invalid UTF-8 code"); + if (next == NULL || iscontp(next)) + return luaL_error(L, MSGInvalid); lua_pushinteger(L, n + 1); lua_pushinteger(L, code); return 2; @@ -180760,7 +181013,8 @@ static int iter_auxlax (lua_State *L) { static int iter_codes (lua_State *L) { int lax = lua_toboolean(L, 2); - luaL_checkstring(L, 1); + const char *s = luaL_checkstring(L, 1); + luaL_argcheck(L, !iscontp(s), 1, MSGInvalid); lua_pushcfunction(L, lax ? iter_auxlax : iter_auxstrict); lua_pushvalue(L, 1); lua_pushinteger(L, 0); @@ -181040,10 +181294,11 @@ static void print_version (void) { ** to the script (everything after 'script') go to positive indices; ** other arguments (before the script name) go to negative indices. ** If there is no script name, assume interpreter's name as base. +** (If there is no interpreter's name either, 'script' is -1, so +** table sizes are zero.) */ static void createargtable (lua_State *L, char **argv, int argc, int script) { int i, narg; - if (script == argc) script = 0; /* no script name? */ narg = argc - (script + 1); /* number of positive indices */ lua_createtable(L, narg, script + 1); for (i = 0; i < argc; i++) { @@ -181131,14 +181386,23 @@ static int handle_script (lua_State *L, char **argv) { /* ** Traverses all arguments from 'argv', returning a mask with those -** needed before running any Lua code (or an error code if it finds -** any invalid argument). 'first' returns the first not-handled argument -** (either the script name or a bad argument in case of error). +** needed before running any Lua code or an error code if it finds any +** invalid argument. In case of error, 'first' is the index of the bad +** argument. Otherwise, 'first' is -1 if there is no program name, +** 0 if there is no script name, or the index of the script name. */ static int collectargs (char **argv, int *first) { int args = 0; int i; - for (i = 1; argv[i] != NULL; i++) { + if (argv[0] != NULL) { /* is there a program name? */ + if (argv[0][0]) /* not empty? */ + progname = argv[0]; /* save it */ + } + else { /* no program name */ + *first = -1; + return 0; + } + for (i = 1; argv[i] != NULL; i++) { /* handle arguments */ *first = i; if (argv[i][0] != '-') /* not an option? */ return args; /* stop handling options */ @@ -181179,7 +181443,7 @@ static int collectargs (char **argv, int *first) { return has_error; } } - *first = i; /* no script name */ + *first = 0; /* no script name */ return args; } @@ -181472,8 +181736,8 @@ static int pmain (lua_State *L) { char **argv = (char **)lua_touserdata(L, 2); int script; int args = collectargs(argv, &script); + int optlim = (script > 0) ? script : argc; /* first argv not an option */ luaL_checkversion(L); /* check that interpreter has correct version */ - if (argv[0] && argv[0][0]) progname = argv[0]; if (args == has_error) { /* bad arg? */ print_usage(argv[script]); /* 'script' has index of bad arg. */ return 0; @@ -181486,19 +181750,21 @@ static int pmain (lua_State *L) { } luaL_openlibs(L); /* open standard libraries */ createargtable(L, argv, argc, script); /* create table 'arg' */ - lua_gc(L, LUA_GCGEN, 0, 0); /* GC in generational mode */ + lua_gc(L, LUA_GCRESTART); /* start GC... */ + lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ if (!(args & has_E)) { /* no option '-E'? */ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ return 0; /* error running LUA_INIT */ } - if (!runargs(L, argv, script)) /* execute arguments -e and -l */ + if (!runargs(L, argv, optlim)) /* execute arguments -e and -l */ return 0; /* something failed */ - if (script < argc && /* execute main script (if there is one) */ - handle_script(L, argv + script) != LUA_OK) - return 0; + if (script > 0) { /* execute main script (if there is one) */ + if (handle_script(L, argv + script) != LUA_OK) + return 0; /* interrupt in case of error */ + } if (args & has_i) /* -i option? */ doREPL(L); /* do read-eval-print loop */ - else if (script == argc && !(args & (has_e | has_v))) { /* no arguments? */ + else if (script < 1 && !(args & (has_e | has_v))) { /* no active option? */ if (lua_stdin_is_tty()) { /* running in interactive mode? */ print_version(); doREPL(L); /* do read-eval-print loop */ @@ -181517,6 +181783,7 @@ int main (int argc, char **argv) { l_message(argv[0], "cannot create state: not enough memory"); return EXIT_FAILURE; } + lua_gc(L, LUA_GCSTOP); /* stop GC while building state */ lua_pushcfunction(L, &pmain); /* to call 'pmain' in protected mode */ lua_pushinteger(L, argc); /* 1st argument */ lua_pushlightuserdata(L, argv); /* 2nd argument */ @@ -181533,7 +181800,7 @@ int main (int argc, char **argv) { MIT License Copyright (c) 1994–2019 Lua.org, PUC-Rio. - Copyright (c) 2020-2022 Eduardo Bart (https://github.com/edubart). + Copyright (c) 2020-2023 Eduardo Bart (https://github.com/edubart). Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -181557,7 +181824,7 @@ int main (int argc, char **argv) { #undef cast #undef G //--- -#line 1 "engine/split/3rd_stb_image.h" +#line 1 "3rd_stb_image.h" /* stb_image - v2.28 - public domain image loader - http://nothings.org/stb no warranty implied; use at your own risk @@ -189546,7 +189813,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ #line 0 -#line 1 "engine/split/3rd_stb_image_write.h" +#line 1 "3rd_stb_image_write.h" /* stb_image_write - v1.16 - public domain - http://nothings.org/stb writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 no warranty implied; use at your own risk @@ -191278,7 +191545,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define STBTT_free(x,u) ((void)(u),FREE(x)) #define NK_ASSERT ASSERT #define NK_DTOA(s,n) strcpy(s, va("%f", n)) // override cos built-in nk_dtoa() will freeze while parsing UINT_MAX otherwise -#line 1 "engine/split/3rd_nuklear.h" +#line 1 "3rd_nuklear.h" /* /// # Nuklear /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) @@ -221650,7 +221917,7 @@ nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) /// for his single header file packer. */ #line 0 -#line 1 "engine/split/3rd_nuklear_glfw_gl3.h" +#line 1 "3rd_nuklear_glfw_gl3.h" /* * Nuklear - 1.32.0 - public domain @@ -222205,7 +222472,7 @@ void nk_glfw3_shutdown(struct nk_glfw* glfw) #endif #line 0 static char *ui_filter = 0; -#line 1 "engine/split/3rd_nuklear_filebrowser.h" +#line 1 "3rd_nuklear_filebrowser.h" // file browser for nuklear, based on https://github.com/vurtun/nuklear/blob/master/example/file_browser.c (public domain) // - rlyeh, public domain // @@ -222698,7 +222965,7 @@ static struct nk_image icon_load_rect(unsigned id, unsigned w, unsigned h, unsig //#include "3rd_assimp/postprocess.h" //#pragma comment(lib, "3rd/3rd_assimp/x64/assimp") #endif -#line 1 "engine/split/3rd_json5.h" +#line 1 "3rd_json5.h" // JSON5 + SJSON parser module // // License: @@ -223140,7 +223407,7 @@ int main() { #endif // JSON5_C #line 0 -#line 1 "engine/split/3rd_gjk.h" +#line 1 "3rd_gjk.h" // GJK distance algorithm. original code by @vurtun and @randygaul, public domain. // [src] https://gist.github.com/vurtun/29727217c269a2fbf4c0ed9a1d11cb40 // - rlyeh, public domain. @@ -223749,7 +224016,7 @@ gjk_result gjk_quad(float a_radius, float b_radius) { #endif #line 0 -#line 1 "engine/split/3rd_compress.h" +#line 1 "3rd_compress.h" // compress.c de/compressors into a single-file header // - rlyeh, public domain // @@ -234590,7 +234857,7 @@ unsigned file_decode(FILE* in, FILE* out, FILE *logfile) { // multi decoder #endif // COMPRESS_C #line 0 -#line 1 "engine/split/3rd_archive.h" +#line 1 "3rd_archive.h" // archive.c pak/zip/tar/dir archivers // - rlyeh, public domain @@ -236219,7 +236486,7 @@ int main( int argc, char **argv ) { #if is(win32) #include // timeapi.h #endif -#line 1 "engine/split/3rd_thread.h" +#line 1 "3rd_thread.h" /* ------------------------------------------------------------------------------ Licensing information can be found at the end of the file. @@ -237949,7 +238216,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ #line 0 -#line 1 "engine/split/3rd_plmpeg.h" +#line 1 "3rd_plmpeg.h" /* PL_MPEG - MPEG1 Video decoder, MP2 Audio decoder, MPEG-PS demuxer @@ -242215,7 +242482,7 @@ void plm_audio_matrix_transform(int s[32][3], int ss, float *d, int dp) { #endif // PL_MPEG_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_jo_mpeg.h" +#line 1 "3rd_jo_mpeg.h" /* public domain Simple, Minimalistic, No Allocations MPEG writer - http://jonolick.com * * Latest revisions: @@ -242482,7 +242749,7 @@ void jo_write_mpeg(FILE *fp, const unsigned char *bgrx, int width, int height, i #endif #line 0 //#define _RTL_RUN_ONCE _RTL_RUN_ONCE2 // __MINGW64__ -#line 1 "engine/split/3rd_https.h" +#line 1 "3rd_https.h" /* ------------------------------------------------------------------------------ Licensing information can be found at the end of the file. @@ -289465,7 +289732,7 @@ int main() { #line 0 #undef F2 #undef F3 -#line 1 "engine/split/3rd_enet.h" +#line 1 "3rd_enet.h" /** * include/enet.h - a Single-Header auto-generated variant of enet.h library. * @@ -295606,7 +295873,7 @@ extern "C" { #endif // ENET_INCLUDE_H #line 0 #define tls_init tls_init2 -#line 1 "engine/split/3rd_bq_websocket.h" +#line 1 "3rd_bq_websocket.h" /* ------------------------------------------------------------------------------ This software is available under 2 licenses -- choose whichever you prefer. @@ -301969,7 +302236,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #endif // BQ_PLATFORM_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_simplex.h" +#line 1 "3rd_simplex.h" /** 1D, 2D, 3D and 4D float Perlin Simplex noise */ /** Original code, stefan gustavson (PD). */ @@ -302452,7 +302719,7 @@ float snoise4(float x, float y, float z, float w) { #endif #line 0 -#line 1 "engine/split/3rd_tfd.h" +#line 1 "3rd_tfd.h" /* If you are using a C++ compiler to compile tinyfiledialogs.c (maybe renamed with an extension ".cpp") then comment out << extern "C" >> bellow in this header file) */ @@ -310512,7 +310779,7 @@ tinyfd_messageBox("The selected hexcolor is", #endif // TFD_IMPLEMENTATION #line 0 -#line 1 "engine/split/3rd_stb_sprintf.h" +#line 1 "3rd_stb_sprintf.h" // stb_sprintf - v1.10 - public domain snprintf() implementation // originally by Jeff Roberts / RAD Game Tools, 2015/10/20 // http://github.com/nothings/stb @@ -312421,7 +312688,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #line 0 #define g g2 -#line 1 "engine/split/3rd_xml.h" +#line 1 "3rd_xml.h" // original xml.h/xml.c files by tor andersson, public domain #ifndef xml_h @@ -312952,7 +313219,7 @@ struct xml *xml_parse(char *s, int preserve_white, char **errorp) #endif #line 0 #undef g -#line 1 "engine/split/3rd_polychop.h" +#line 1 "3rd_polychop.h" /* Progressive Mesh type Polygon Reduction Algorithm * * 1998: Original version by Stan Melax (c) 1998 @@ -313373,7 +313640,7 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, else if(!strcmp(id, "held") && nargs ==1) push(ev, input_held(pop(ev))); \ else if(!strcmp(id, "up") && nargs ==1) push(ev, input_up(pop(ev))); \ else if(!strcmp(id, "idle") && nargs ==1) push(ev, input_idle(pop(ev))); -#line 1 "engine/split/3rd_eval.h" +#line 1 "3rd_eval.h" /* A mathematical expression evaluator. * It uses a recursive descent parser internally. * Author: Werner Stoop @@ -313883,7 +314150,7 @@ int main() { } #endif #line 0 -#line 1 "engine/split/3rd_luadebugger.h" +#line 1 "3rd_luadebugger.h" /* Copyright (c) 2023 Scott Lembcke and Howling Moon Software @@ -315363,7 +315630,7 @@ int dbg_pcall(lua_State *lua, int nargs, int nresults, int msgh){ return err; } #line 0 -#line 1 "engine/split/3rd_base64.h" +#line 1 "3rd_base64.h" // base64 de/encoder. Based on code by Jon Mayo - November 13, 2003 (PUBLIC DOMAIN). // - rlyeh, public domain @@ -315392,7 +315659,7 @@ unsigned base64_bounds(unsigned size) { char* base64_encode(const void *inp, unsigned inlen) { // free() after use unsigned outlen = base64_bounds(inlen); - char *out_ = malloc(outlen); + char *out_ = MALLOC(outlen); out_[outlen] = 0; uint_least32_t v; @@ -315409,21 +315676,21 @@ char* base64_encode(const void *inp, unsigned inlen) { // free() after use while (rem >= 6) { rem -= 6; if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[(v >> rem) & 63]; } } if (rem) { v <<= (6 - rem); if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ + return (FREE(out_), NULL); /* truncation is failure */ out[io ++] = base64enc_tab[v & 63]; } while(io&3) { - if(io>=outlen) return (free(out_), 0); /* truncation is failure */ + if(io>=outlen) return (FREE(out_), NULL); /* truncation is failure */ out[io++]='='; } - if(io>=outlen) return (free(out_), 0); /* no room for null terminator */ + if(io>=outlen) return (FREE(out_), NULL); /* no room for null terminator */ out[io]=0; return out_; } @@ -315505,6 +315772,4020 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft #endif // array_resize #endif // BASE64_C #line 0 + +#if ENABLE_RPMALLOC +#line 1 "3rd_rpmalloc.h" +/* rpmalloc.h - Memory allocator - Public Domain - 2016 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__clang__) || defined(__GNUC__) +# define RPMALLOC_EXPORT __attribute__((visibility("default"))) +# define RPMALLOC_ALLOCATOR +# if (defined(__clang_major__) && (__clang_major__ < 4)) || (defined(__GNUC__) && defined(ENABLE_PRELOAD) && ENABLE_PRELOAD) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) +# else +# define RPMALLOC_ATTRIB_MALLOC __attribute__((__malloc__)) +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) __attribute__((alloc_size(size))) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size) __attribute__((alloc_size(count, size))) +# endif +# define RPMALLOC_CDECL +#elif defined(_MSC_VER) +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR __declspec(allocator) __declspec(restrict) +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL __cdecl +#else +# define RPMALLOC_EXPORT +# define RPMALLOC_ALLOCATOR +# define RPMALLOC_ATTRIB_MALLOC +# define RPMALLOC_ATTRIB_ALLOC_SIZE(size) +# define RPMALLOC_ATTRIB_ALLOC_SIZE2(count,size) +# define RPMALLOC_CDECL +#endif + +//! Define RPMALLOC_CONFIGURABLE to enable configuring sizes. Will introduce +// a very small overhead due to some size calculations not being compile time constants +#ifndef RPMALLOC_CONFIGURABLE +#define RPMALLOC_CONFIGURABLE 0 +#endif + +//! Define RPMALLOC_FIRST_CLASS_HEAPS to enable heap based API (rpmalloc_heap_* functions). +// Will introduce a very small overhead to track fully allocated spans in heaps +#ifndef RPMALLOC_FIRST_CLASS_HEAPS +#define RPMALLOC_FIRST_CLASS_HEAPS 0 +#endif + +//! Flag to rpaligned_realloc to not preserve content in reallocation +#define RPMALLOC_NO_PRESERVE 1 +//! Flag to rpaligned_realloc to fail and return null pointer if grow cannot be done in-place, +// in which case the original pointer is still valid (just like a call to realloc which failes to allocate +// a new block). +#define RPMALLOC_GROW_OR_FAIL 2 + +typedef struct rpmalloc_global_statistics_t { + //! Current amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped; + //! Peak amount of virtual memory mapped, all of which might not have been committed (only if ENABLE_STATISTICS=1) + size_t mapped_peak; + //! Current amount of memory in global caches for small and medium sizes (<32KiB) + size_t cached; + //! Current amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc; + //! Peak amount of memory allocated in huge allocations, i.e larger than LARGE_SIZE_LIMIT which is 2MiB by default (only if ENABLE_STATISTICS=1) + size_t huge_alloc_peak; + //! Total amount of memory mapped since initialization (only if ENABLE_STATISTICS=1) + size_t mapped_total; + //! Total amount of memory unmapped since initialization (only if ENABLE_STATISTICS=1) + size_t unmapped_total; +} rpmalloc_global_statistics_t; + +typedef struct rpmalloc_thread_statistics_t { + //! Current number of bytes available in thread size class caches for small and medium sizes (<32KiB) + size_t sizecache; + //! Current number of bytes available in thread span caches for small and medium sizes (<32KiB) + size_t spancache; + //! Total number of bytes transitioned from thread cache to global cache (only if ENABLE_STATISTICS=1) + size_t thread_to_global; + //! Total number of bytes transitioned from global cache to thread cache (only if ENABLE_STATISTICS=1) + size_t global_to_thread; + //! Per span count statistics (only if ENABLE_STATISTICS=1) + struct { + //! Currently used number of spans + size_t current; + //! High water mark of spans used + size_t peak; + //! Number of spans transitioned to global cache + size_t to_global; + //! Number of spans transitioned from global cache + size_t from_global; + //! Number of spans transitioned to thread cache + size_t to_cache; + //! Number of spans transitioned from thread cache + size_t from_cache; + //! Number of spans transitioned to reserved state + size_t to_reserved; + //! Number of spans transitioned from reserved state + size_t from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } span_use[64]; + //! Per size class statistics (only if ENABLE_STATISTICS=1) + struct { + //! Current number of allocations + size_t alloc_current; + //! Peak number of allocations + size_t alloc_peak; + //! Total number of allocations + size_t alloc_total; + //! Total number of frees + size_t free_total; + //! Number of spans transitioned to cache + size_t spans_to_cache; + //! Number of spans transitioned from cache + size_t spans_from_cache; + //! Number of spans transitioned from reserved state + size_t spans_from_reserved; + //! Number of raw memory map calls (not hitting the reserve spans but resulting in actual OS mmap calls) + size_t map_calls; + } size_use[128]; +} rpmalloc_thread_statistics_t; + +typedef struct rpmalloc_config_t { + //! Map memory pages for the given number of bytes. The returned address MUST be + // aligned to the rpmalloc span size, which will always be a power of two. + // Optionally the function can store an alignment offset in the offset variable + // in case it performs alignment and the returned pointer is offset from the + // actual start of the memory region due to this alignment. The alignment offset + // will be passed to the memory unmap function. The alignment offset MUST NOT be + // larger than 65535 (storable in an uint16_t), if it is you must use natural + // alignment to shift it into 16 bits. If you set a memory_map function, you + // must also set a memory_unmap function or else the default implementation will + // be used for both. This function must be thread safe, it can be called by + // multiple threads simultaneously. + void* (*memory_map)(size_t size, size_t* offset); + //! Unmap the memory pages starting at address and spanning the given number of bytes. + // If release is set to non-zero, the unmap is for an entire span range as returned by + // a previous call to memory_map and that the entire range should be released. The + // release argument holds the size of the entire span range. If release is set to 0, + // the unmap is a partial decommit of a subset of the mapped memory range. + // If you set a memory_unmap function, you must also set a memory_map function or + // else the default implementation will be used for both. This function must be thread + // safe, it can be called by multiple threads simultaneously. + void (*memory_unmap)(void* address, size_t size, size_t offset, size_t release); + //! Called when an assert fails, if asserts are enabled. Will use the standard assert() + // if this is not set. + void (*error_callback)(const char* message); + //! Called when a call to map memory pages fails (out of memory). If this callback is + // not set or returns zero the library will return a null pointer in the allocation + // call. If this callback returns non-zero the map call will be retried. The argument + // passed is the number of bytes that was requested in the map call. Only used if + // the default system memory map function is used (memory_map callback is not set). + int (*map_fail_callback)(size_t size); + //! Size of memory pages. The page size MUST be a power of two. All memory mapping + // requests to memory_map will be made with size set to a multiple of the page size. + // Used if RPMALLOC_CONFIGURABLE is defined to 1, otherwise system page size is used. + size_t page_size; + //! Size of a span of memory blocks. MUST be a power of two, and in [4096,262144] + // range (unless 0 - set to 0 to use the default span size). Used if RPMALLOC_CONFIGURABLE + // is defined to 1. + size_t span_size; + //! Number of spans to map at each request to map new virtual memory blocks. This can + // be used to minimize the system call overhead at the cost of virtual memory address + // space. The extra mapped pages will not be written until actually used, so physical + // committed memory should not be affected in the default implementation. Will be + // aligned to a multiple of spans that match memory page size in case of huge pages. + size_t span_map_count; + //! Enable use of large/huge pages. If this flag is set to non-zero and page size is + // zero, the allocator will try to enable huge pages and auto detect the configuration. + // If this is set to non-zero and page_size is also non-zero, the allocator will + // assume huge pages have been configured and enabled prior to initializing the + // allocator. + // For Windows, see https://docs.microsoft.com/en-us/windows/desktop/memory/large-page-support + // For Linux, see https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt + int enable_huge_pages; + //! Respectively allocated pages and huge allocated pages names for systems + // supporting it to be able to distinguish among anonymous regions. + const char *page_name; + const char *huge_page_name; +} rpmalloc_config_t; + +//! Initialize allocator with default configuration +RPMALLOC_EXPORT int +rpmalloc_initialize(void); + +//! Initialize allocator with given configuration +RPMALLOC_EXPORT int +rpmalloc_initialize_config(const rpmalloc_config_t* config); + +//! Get allocator configuration +RPMALLOC_EXPORT const rpmalloc_config_t* +rpmalloc_config(void); + +//! Finalize allocator +RPMALLOC_EXPORT void +rpmalloc_finalize(void); + +//! Initialize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_initialize(void); + +//! Finalize allocator for calling thread +RPMALLOC_EXPORT void +rpmalloc_thread_finalize(int release_caches); + +//! Perform deferred deallocations pending for the calling thread heap +RPMALLOC_EXPORT void +rpmalloc_thread_collect(void); + +//! Query if allocator is initialized for calling thread +RPMALLOC_EXPORT int +rpmalloc_is_thread_initialized(void); + +//! Get per-thread statistics +RPMALLOC_EXPORT void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats); + +//! Get global statistics +RPMALLOC_EXPORT void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats); + +//! Dump all statistics in human readable format to file (should be a FILE*) +RPMALLOC_EXPORT void +rpmalloc_dump_statistics(void* file); + +//! Allocate a memory block of at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1); + +//! Free the given memory block +RPMALLOC_EXPORT void +rpfree(void* ptr); + +//! Allocate a memory block of at least the given size and zero initialize it +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2); + +//! Reallocate the given block to at least the given size +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Reallocate the given block to at least the given size and alignment, +// with optional control flags (see RPMALLOC_NO_PRESERVE). +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment, and zero initialize it. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size and alignment. +// Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB) +RPMALLOC_EXPORT int +rpposix_memalign(void** memptr, size_t alignment, size_t size); + +//! Query the usable size of the given memory block (from given pointer to the end of block) +RPMALLOC_EXPORT size_t +rpmalloc_usable_size(void* ptr); + +//! Dummy empty function for forcing linker symbol inclusion +RPMALLOC_EXPORT void +rpmalloc_linker_reference(void); + +#if RPMALLOC_FIRST_CLASS_HEAPS + +//! Heap type +typedef struct heap_t rpmalloc_heap_t; + +//! Acquire a new heap. Will reuse existing released heaps or allocate memory for a new heap +// if none available. Heap API is implemented with the strict assumption that only one single +// thread will call heap functions for a given heap at any given time, no functions are thread safe. +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_heap_acquire(void); + +//! Release a heap (does NOT free the memory allocated by the heap, use rpmalloc_heap_free_all before destroying the heap). +// Releasing a heap will enable it to be reused by other threads. Safe to pass a null pointer. +RPMALLOC_EXPORT void +rpmalloc_heap_release(rpmalloc_heap_t* heap); + +//! Allocate a memory block of at least the given size using the given heap. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2); + +//! Allocate a memory block of at least the given size using the given heap. The returned +// block will have the requested alignment. Alignment must be a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Allocate a memory block of at least the given size using the given heap and zero initialize it. The returned +// block will have the requested alignment. Alignment must either be zero, or a power of two and a multiple of sizeof(void*), +// and should ideally be less than memory page size. A caveat of rpmalloc +// internals is that this must also be strictly less than the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(2, 3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(3); + +//! Reallocate the given block to at least the given size. The memory block MUST be allocated +// by the same heap given to this function. The returned block will have the requested alignment. +// Alignment must be either zero, or a power of two and a multiple of sizeof(void*), and should ideally be +// less than memory page size. A caveat of rpmalloc internals is that this must also be strictly less than +// the span size (default 64KiB). +RPMALLOC_EXPORT RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(4); + +//! Free the given memory block from the given heap. The memory block MUST be allocated +// by the same heap given to this function. +RPMALLOC_EXPORT void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr); + +//! Free all memory allocated by the heap +RPMALLOC_EXPORT void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap); + +//! Set the given heap as the current heap for the calling thread. A heap MUST only be current heap +// for a single thread, a heap can never be shared between multiple threads. The previous +// current heap for the calling thread is released to be reused by other threads. +RPMALLOC_EXPORT void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap); + +//! Returns which heap the given pointer is allocated on +RPMALLOC_EXPORT rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr); + +#endif + +#ifdef __cplusplus +} +#endif +#line 0 +#line 1 "3rd_rpmalloc.c" +/* rpmalloc.c - Memory allocator - Public Domain - 2016-2020 Mattias Jansson + * + * This library provides a cross-platform lock free thread caching malloc implementation in C11. + * The latest source code is always available at + * + * https://github.com/mjansson/rpmalloc + * + * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * + */ + +// #include "rpmalloc.h" //< @r-lyeh + +//////////// +/// +/// Build time configurable limits +/// +////// + +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wunused-macros" +#pragma clang diagnostic ignored "-Wunused-function" +#if __has_warning("-Wreserved-identifier") +#pragma clang diagnostic ignored "-Wreserved-identifier" +#endif +#if __has_warning("-Wstatic-in-inline") +#pragma clang diagnostic ignored "-Wstatic-in-inline" +#endif +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-macros" +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#if !defined(__has_builtin) +#define __has_builtin(b) 0 +#endif + +#if defined(__GNUC__) || defined(__clang__) + +#if __has_builtin(__builtin_memcpy_inline) +#define _rpmalloc_memcpy_const(x, y, s) __builtin_memcpy_inline(x, y, s) +#else +#define _rpmalloc_memcpy_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memcpy(x, y, s); \ + } while (0) +#endif + +#if __has_builtin(__builtin_memset_inline) +#define _rpmalloc_memset_const(x, y, s) __builtin_memset_inline(x, y, s) +#else +#define _rpmalloc_memset_const(x, y, s) \ + do { \ + _Static_assert(__builtin_choose_expr(__builtin_constant_p(s), 1, 0), "len must be a constant integer"); \ + memset(x, y, s); \ + } while (0) +#endif +#else +#define _rpmalloc_memcpy_const(x, y, s) memcpy(x, y, s) +#define _rpmalloc_memset_const(x, y, s) memset(x, y, s) +#endif + +#if __has_builtin(__builtin_assume) +#define rpmalloc_assume(cond) __builtin_assume(cond) +#elif defined(__GNUC__) +#define rpmalloc_assume(cond) \ + do { \ + if (!__builtin_expect(cond, 0)) \ + __builtin_unreachable(); \ + } while (0) +#elif defined(_MSC_VER) +#define rpmalloc_assume(cond) __assume(cond) +#else +#define rpmalloc_assume(cond) 0 +#endif + +#ifndef HEAP_ARRAY_SIZE +//! Size of heap hashmap +#define HEAP_ARRAY_SIZE 47 +#endif +#ifndef ENABLE_THREAD_CACHE +//! Enable per-thread cache +#define ENABLE_THREAD_CACHE 1 +#endif +#ifndef ENABLE_GLOBAL_CACHE +//! Enable global cache shared between all threads, requires thread cache +#define ENABLE_GLOBAL_CACHE 1 +#endif +#ifndef ENABLE_VALIDATE_ARGS +//! Enable validation of args to public entry points +#define ENABLE_VALIDATE_ARGS 0 +#endif +#ifndef ENABLE_STATISTICS +//! Enable statistics collection +#define ENABLE_STATISTICS 0 +#endif +#ifndef ENABLE_ASSERTS +//! Enable asserts +#define ENABLE_ASSERTS 0 +#endif +#ifndef ENABLE_OVERRIDE +//! Override standard library malloc/free and new/delete entry points +#define ENABLE_OVERRIDE 0 +#endif +#ifndef ENABLE_PRELOAD +//! Support preloading +#define ENABLE_PRELOAD 0 +#endif +#ifndef DISABLE_UNMAP +//! Disable unmapping memory pages (also enables unlimited cache) +#define DISABLE_UNMAP 0 +#endif +#ifndef ENABLE_UNLIMITED_CACHE +//! Enable unlimited global cache (no unmapping until finalization) +#define ENABLE_UNLIMITED_CACHE 0 +#endif +#ifndef ENABLE_ADAPTIVE_THREAD_CACHE +//! Enable adaptive thread cache size based on use heuristics +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif +#ifndef DEFAULT_SPAN_MAP_COUNT +//! Default number of spans to map in call to map more virtual memory (default values yield 4MiB here) +#define DEFAULT_SPAN_MAP_COUNT 64 +#endif +#ifndef GLOBAL_CACHE_MULTIPLIER +//! Multiplier for global cache +#define GLOBAL_CACHE_MULTIPLIER 8 +#endif + +#if DISABLE_UNMAP && !ENABLE_GLOBAL_CACHE +#error Must use global cache if unmap is disabled +#endif + +#if DISABLE_UNMAP +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 1 +#endif + +#if !ENABLE_GLOBAL_CACHE +#undef ENABLE_UNLIMITED_CACHE +#define ENABLE_UNLIMITED_CACHE 0 +#endif + +#if !ENABLE_THREAD_CACHE +#undef ENABLE_ADAPTIVE_THREAD_CACHE +#define ENABLE_ADAPTIVE_THREAD_CACHE 0 +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) +# define PLATFORM_WINDOWS 1 +# define PLATFORM_POSIX 0 +#else +# define PLATFORM_WINDOWS 0 +# define PLATFORM_POSIX 1 +#endif + +/// Platform and arch specifics +#if defined(_MSC_VER) && !defined(__clang__) +# pragma warning (disable: 5105) +# ifndef FORCEINLINE +# define FORCEINLINE inline __forceinline +# endif +# define _Static_assert static_assert +#else +# ifndef FORCEINLINE +# define FORCEINLINE inline __attribute__((__always_inline__)) +# endif +#endif +#if PLATFORM_WINDOWS +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +# if ENABLE_VALIDATE_ARGS +# include +# endif +#else +# include +# include +# include +# include +# if defined(__linux__) || defined(__ANDROID__) +# include +# if !defined(PR_SET_VMA) +# define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 +# endif +# endif +# if defined(__APPLE__) +# include +# if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR +# include +# include +# endif +# include +# endif +# if defined(__HAIKU__) || defined(__TINYC__) +# include +# endif +#endif + +#include +#include +#include + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +#include +static DWORD fls_key; +#endif + +#if PLATFORM_POSIX +# include +# include +# ifdef __FreeBSD__ +# include +# define MAP_HUGETLB MAP_ALIGNED_SUPER +# ifndef PROT_MAX +# define PROT_MAX(f) 0 +# endif +# else +# define PROT_MAX(f) 0 +# endif +# ifdef __sun +extern int madvise(caddr_t, size_t, int); +# endif +# ifndef MAP_UNINITIALIZED +# define MAP_UNINITIALIZED 0 +# endif +#endif +#include + +#if ENABLE_ASSERTS +# undef NDEBUG +# if defined(_MSC_VER) && !defined(_DEBUG) +# define _DEBUG +# endif +# include +#define RPMALLOC_TOSTRING_M(x) #x +#define RPMALLOC_TOSTRING(x) RPMALLOC_TOSTRING_M(x) +#define rpmalloc_assert(truth, message) \ + do { \ + if (!(truth)) { \ + if (_memory_config.error_callback) { \ + _memory_config.error_callback( \ + message " (" RPMALLOC_TOSTRING(truth) ") at " __FILE__ ":" RPMALLOC_TOSTRING(__LINE__)); \ + } else { \ + assert((truth) && message); \ + } \ + } \ + } while (0) +#else +# define rpmalloc_assert(truth, message) do {} while(0) +#endif +#if ENABLE_STATISTICS +# include +#endif + +////// +/// +/// Atomic access abstraction (since MSVC does not do C11 yet) +/// +////// + +#if defined(_MSC_VER) && !defined(__clang__) + +typedef volatile long atomic32_t; +typedef volatile long long atomic64_t; +typedef volatile void* atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return *src; } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return (int32_t)InterlockedIncrement(val); } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return (int32_t)InterlockedDecrement(val); } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return (int32_t)InterlockedExchangeAdd(val, add) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return (InterlockedCompareExchange(dst, val, ref) == ref) ? 1 : 0; } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { *dst = val; } +static FORCEINLINE int64_t atomic_load64(atomic64_t* src) { return *src; } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return (int64_t)InterlockedExchangeAdd64(val, add) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return (void*)*src; } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { *dst = val; } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return (void*)InterlockedExchangePointer((void* volatile*)dst, val); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return (InterlockedCompareExchangePointer((void* volatile*)dst, val, ref) == ref) ? 1 : 0; } + +#define EXPECTED(x) (x) +#define UNEXPECTED(x) (x) + +#else + +#include + +typedef volatile _Atomic(int32_t) atomic32_t; +typedef volatile _Atomic(int64_t) atomic64_t; +typedef volatile _Atomic(void*) atomicptr_t; + +static FORCEINLINE int32_t atomic_load32(atomic32_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store32(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE int32_t atomic_incr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1; } +static FORCEINLINE int32_t atomic_decr32(atomic32_t* val) { return atomic_fetch_add_explicit(val, -1, memory_order_relaxed) - 1; } +static FORCEINLINE int32_t atomic_add32(atomic32_t* val, int32_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE int atomic_cas32_acquire(atomic32_t* dst, int32_t val, int32_t ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_acquire, memory_order_relaxed); } +static FORCEINLINE void atomic_store32_release(atomic32_t* dst, int32_t val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE int64_t atomic_load64(atomic64_t* val) { return atomic_load_explicit(val, memory_order_relaxed); } +static FORCEINLINE int64_t atomic_add64(atomic64_t* val, int64_t add) { return atomic_fetch_add_explicit(val, add, memory_order_relaxed) + add; } +static FORCEINLINE void* atomic_load_ptr(atomicptr_t* src) { return atomic_load_explicit(src, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_relaxed); } +static FORCEINLINE void atomic_store_ptr_release(atomicptr_t* dst, void* val) { atomic_store_explicit(dst, val, memory_order_release); } +static FORCEINLINE void* atomic_exchange_ptr_acquire(atomicptr_t* dst, void* val) { return atomic_exchange_explicit(dst, val, memory_order_acquire); } +static FORCEINLINE int atomic_cas_ptr(atomicptr_t* dst, void* val, void* ref) { return atomic_compare_exchange_weak_explicit(dst, &ref, val, memory_order_relaxed, memory_order_relaxed); } + +#define EXPECTED(x) __builtin_expect((x), 1) +#define UNEXPECTED(x) __builtin_expect((x), 0) + +#endif + +//////////// +/// +/// Statistics related functions (evaluate to nothing when statistics not enabled) +/// +////// + +#if ENABLE_STATISTICS +# define _rpmalloc_stat_inc(counter) atomic_incr32(counter) +# define _rpmalloc_stat_dec(counter) atomic_decr32(counter) +# define _rpmalloc_stat_add(counter, value) atomic_add32(counter, (int32_t)(value)) +# define _rpmalloc_stat_add64(counter, value) atomic_add64(counter, (int64_t)(value)) +# define _rpmalloc_stat_add_peak(counter, value, peak) do { int32_t _cur_count = atomic_add32(counter, (int32_t)(value)); if (_cur_count > (peak)) peak = _cur_count; } while (0) +# define _rpmalloc_stat_sub(counter, value) atomic_add32(counter, -(int32_t)(value)) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do { \ + int32_t alloc_current = atomic_incr32(&heap->size_class_use[class_idx].alloc_current); \ + if (alloc_current > heap->size_class_use[class_idx].alloc_peak) \ + heap->size_class_use[class_idx].alloc_peak = alloc_current; \ + atomic_incr32(&heap->size_class_use[class_idx].alloc_total); \ +} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do { \ + atomic_decr32(&heap->size_class_use[class_idx].alloc_current); \ + atomic_incr32(&heap->size_class_use[class_idx].free_total); \ +} while(0) +#else +# define _rpmalloc_stat_inc(counter) do {} while(0) +# define _rpmalloc_stat_dec(counter) do {} while(0) +# define _rpmalloc_stat_add(counter, value) do {} while(0) +# define _rpmalloc_stat_add64(counter, value) do {} while(0) +# define _rpmalloc_stat_add_peak(counter, value, peak) do {} while (0) +# define _rpmalloc_stat_sub(counter, value) do {} while(0) +# define _rpmalloc_stat_inc_alloc(heap, class_idx) do {} while(0) +# define _rpmalloc_stat_inc_free(heap, class_idx) do {} while(0) +#endif + + +/// +/// Preconfigured limits and sizes +/// + +//! Granularity of a small allocation block (must be power of two) +#define SMALL_GRANULARITY 16 +//! Small granularity shift count +#define SMALL_GRANULARITY_SHIFT 4 +//! Number of small block size classes +#define SMALL_CLASS_COUNT 65 +//! Maximum size of a small block +#define SMALL_SIZE_LIMIT (SMALL_GRANULARITY * (SMALL_CLASS_COUNT - 1)) +//! Granularity of a medium allocation block +#define MEDIUM_GRANULARITY 512 +//! Medium granularity shift count +#define MEDIUM_GRANULARITY_SHIFT 9 +//! Number of medium block size classes +#define MEDIUM_CLASS_COUNT 61 +//! Total number of small + medium size classes +#define SIZE_CLASS_COUNT (SMALL_CLASS_COUNT + MEDIUM_CLASS_COUNT) +//! Number of large block size classes +#define LARGE_CLASS_COUNT 63 +//! Maximum size of a medium block +#define MEDIUM_SIZE_LIMIT (SMALL_SIZE_LIMIT + (MEDIUM_GRANULARITY * MEDIUM_CLASS_COUNT)) +//! Maximum size of a large block +#define LARGE_SIZE_LIMIT ((LARGE_CLASS_COUNT * _memory_span_size) - SPAN_HEADER_SIZE) +//! Size of a span header (must be a multiple of SMALL_GRANULARITY and a power of two) +#define SPAN_HEADER_SIZE 128 +//! Number of spans in thread cache +#define MAX_THREAD_SPAN_CACHE 400 +//! Number of spans to transfer between thread and global cache +#define THREAD_SPAN_CACHE_TRANSFER 64 +//! Number of spans in thread cache for large spans (must be greater than LARGE_CLASS_COUNT / 2) +#define MAX_THREAD_SPAN_LARGE_CACHE 100 +//! Number of spans to transfer between thread and global cache for large spans +#define THREAD_SPAN_LARGE_CACHE_TRANSFER 6 + +_Static_assert((SMALL_GRANULARITY & (SMALL_GRANULARITY - 1)) == 0, "Small granularity must be power of two"); +_Static_assert((SPAN_HEADER_SIZE & (SPAN_HEADER_SIZE - 1)) == 0, "Span header size must be power of two"); + +#if ENABLE_VALIDATE_ARGS +//! Maximum allocation size to avoid integer overflow +#undef MAX_ALLOC_SIZE +#define MAX_ALLOC_SIZE (((size_t)-1) - _memory_span_size) +#endif + +#define pointer_offset(ptr, ofs) (void*)((char*)(ptr) + (ptrdiff_t)(ofs)) +#define pointer_diff(first, second) (ptrdiff_t)((const char*)(first) - (const char*)(second)) + +#define INVALID_POINTER ((void*)((uintptr_t)-1)) + +#define SIZE_CLASS_LARGE SIZE_CLASS_COUNT +#define SIZE_CLASS_HUGE ((uint32_t)-1) + +//////////// +/// +/// Data types +/// +////// + +//! A memory heap, per thread +typedef struct heap_t heap_t; +//! Span of memory pages +typedef struct span_t span_t; +//! Span list +typedef struct span_list_t span_list_t; +//! Span active data +typedef struct span_active_t span_active_t; +//! Size class definition +typedef struct size_class_t size_class_t; +//! Global cache +typedef struct global_cache_t global_cache_t; + +//! Flag indicating span is the first (master) span of a split superspan +#define SPAN_FLAG_MASTER 1U +//! Flag indicating span is a secondary (sub) span of a split superspan +#define SPAN_FLAG_SUBSPAN 2U +//! Flag indicating span has blocks with increased alignment +#define SPAN_FLAG_ALIGNED_BLOCKS 4U +//! Flag indicating an unmapped master span +#define SPAN_FLAG_UNMAPPED_MASTER 8U + +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS +struct span_use_t { + //! Current number of spans used (actually used, not in cache) + atomic32_t current; + //! High water mark of spans used + atomic32_t high; +#if ENABLE_STATISTICS + //! Number of spans in deferred list + atomic32_t spans_deferred; + //! Number of spans transitioned to global cache + atomic32_t spans_to_global; + //! Number of spans transitioned from global cache + atomic32_t spans_from_global; + //! Number of spans transitioned to thread cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from thread cache + atomic32_t spans_from_cache; + //! Number of spans transitioned to reserved state + atomic32_t spans_to_reserved; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of raw memory map calls + atomic32_t spans_map_calls; +#endif +}; +typedef struct span_use_t span_use_t; +#endif + +#if ENABLE_STATISTICS +struct size_class_use_t { + //! Current number of allocations + atomic32_t alloc_current; + //! Peak number of allocations + int32_t alloc_peak; + //! Total number of allocations + atomic32_t alloc_total; + //! Total number of frees + atomic32_t free_total; + //! Number of spans in use + atomic32_t spans_current; + //! Number of spans transitioned to cache + int32_t spans_peak; + //! Number of spans transitioned to cache + atomic32_t spans_to_cache; + //! Number of spans transitioned from cache + atomic32_t spans_from_cache; + //! Number of spans transitioned from reserved state + atomic32_t spans_from_reserved; + //! Number of spans mapped + atomic32_t spans_map_calls; + int32_t unused; +}; +typedef struct size_class_use_t size_class_use_t; +#endif + +// A span can either represent a single span of memory pages with size declared by span_map_count configuration variable, +// or a set of spans in a continuous region, a super span. Any reference to the term "span" usually refers to both a single +// span or a super span. A super span can further be divided into multiple spans (or this, super spans), where the first +// (super)span is the master and subsequent (super)spans are subspans. The master span keeps track of how many subspans +// that are still alive and mapped in virtual memory, and once all subspans and master have been unmapped the entire +// superspan region is released and unmapped (on Windows for example, the entire superspan range has to be released +// in the same call to release the virtual memory range, but individual subranges can be decommitted individually +// to reduce physical memory use). +struct span_t { + //! Free list + void* free_list; + //! Total block count of size class + uint32_t block_count; + //! Size class + uint32_t size_class; + //! Index of last block initialized in free list + uint32_t free_list_limit; + //! Number of used blocks remaining when in partial state + uint32_t used_count; + //! Deferred free list + atomicptr_t free_list_deferred; + //! Size of deferred free list, or list of spans when part of a cache list + uint32_t list_size; + //! Size of a block + uint32_t block_size; + //! Flags and counters + uint32_t flags; + //! Number of spans + uint32_t span_count; + //! Total span counter for master spans + uint32_t total_spans; + //! Offset from master span for subspans + uint32_t offset_from_master; + //! Remaining span counter, for master spans + atomic32_t remaining_spans; + //! Alignment offset + uint32_t align_offset; + //! Owning heap + heap_t* heap; + //! Next span + span_t* next; + //! Previous span + span_t* prev; +}; +_Static_assert(sizeof(span_t) <= SPAN_HEADER_SIZE, "span size mismatch"); + +struct span_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_CACHE]; +}; +typedef struct span_cache_t span_cache_t; + +struct span_large_cache_t { + size_t count; + span_t* span[MAX_THREAD_SPAN_LARGE_CACHE]; +}; +typedef struct span_large_cache_t span_large_cache_t; + +struct heap_size_class_t { + //! Free list of active span + void* free_list; + //! Double linked list of partially used spans with free blocks. + // Previous span pointer in head points to tail span of list. + span_t* partial_span; + //! Early level cache of fully free spans + span_t* cache; +}; +typedef struct heap_size_class_t heap_size_class_t; + +// Control structure for a heap, either a thread heap or a first class heap if enabled +struct heap_t { + //! Owning thread ID + uintptr_t owner_thread; + //! Free lists for each size class + heap_size_class_t size_class[SIZE_CLASS_COUNT]; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, single span + span_cache_t span_cache; +#endif + //! List of deferred free spans (single linked list) + atomicptr_t span_free_deferred; + //! Number of full spans + size_t full_span_count; + //! Mapped but unused spans + span_t* span_reserve; + //! Master span for mapped but unused spans + span_t* span_reserve_master; + //! Number of mapped but unused spans + uint32_t spans_reserved; + //! Child count + atomic32_t child_count; + //! Next heap in id list + heap_t* next_heap; + //! Next heap in orphan list + heap_t* next_orphan; + //! Heap ID + int32_t id; + //! Finalization state flag + int finalize; + //! Master heap owning the memory pages + heap_t* master_heap; +#if ENABLE_THREAD_CACHE + //! Arrays of fully freed spans, large spans with > 1 span count + span_large_cache_t span_large_cache[LARGE_CLASS_COUNT - 1]; +#endif +#if RPMALLOC_FIRST_CLASS_HEAPS + //! Double linked list of fully utilized spans with free blocks for each size class. + // Previous span pointer in head points to tail span of list. + span_t* full_span[SIZE_CLASS_COUNT]; + //! Double linked list of large and huge spans allocated by this heap + span_t* large_huge_span; +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //! Current and high water mark of spans used per span count + span_use_t span_use[LARGE_CLASS_COUNT]; +#endif +#if ENABLE_STATISTICS + //! Allocation stats per size class + size_class_use_t size_class_use[SIZE_CLASS_COUNT + 1]; + //! Number of bytes transitioned thread -> global + atomic64_t thread_to_global; + //! Number of bytes transitioned global -> thread + atomic64_t global_to_thread; +#endif +}; + +// Size class for defining a block size bucket +struct size_class_t { + //! Size of blocks in this class + uint32_t block_size; + //! Number of blocks in each chunk + uint16_t block_count; + //! Class index this class is merged with + uint16_t class_idx; +}; +_Static_assert(sizeof(size_class_t) == 8, "Size class size mismatch"); + +struct global_cache_t { + //! Cache lock + atomic32_t lock; + //! Cache count + uint32_t count; +#if ENABLE_STATISTICS + //! Insert count + size_t insert_count; + //! Extract count + size_t extract_count; +#endif + //! Cached spans + span_t* span[GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE]; + //! Unlimited cache overflow + span_t* overflow; +}; + +//////////// +/// +/// Global data +/// +////// + +//! Default span size (64KiB) +#define _memory_default_span_size (64 * 1024) +#define _memory_default_span_size_shift 16 +#define _memory_default_span_mask (~((uintptr_t)(_memory_span_size - 1))) + +//! Initialized flag +static int _rpmalloc_initialized; +//! Main thread ID +static uintptr_t _rpmalloc_main_thread_id; +//! Configuration +static rpmalloc_config_t _memory_config; +//! Memory page size +static size_t _memory_page_size; +//! Shift to divide by page size +static size_t _memory_page_size_shift; +//! Granularity at which memory pages are mapped by OS +static size_t _memory_map_granularity; +#if RPMALLOC_CONFIGURABLE +//! Size of a span of memory pages +static size_t _memory_span_size; +//! Shift to divide by span size +static size_t _memory_span_size_shift; +//! Mask to get to start of a memory span +static uintptr_t _memory_span_mask; +#else +//! Hardwired span size +#define _memory_span_size _memory_default_span_size +#define _memory_span_size_shift _memory_default_span_size_shift +#define _memory_span_mask _memory_default_span_mask +#endif +//! Number of spans to map in each map call +static size_t _memory_span_map_count; +//! Number of spans to keep reserved in each heap +static size_t _memory_heap_reserve_count; +//! Global size classes +static size_class_t _memory_size_class[SIZE_CLASS_COUNT]; +//! Run-time size limit of medium blocks +static size_t _memory_medium_size_limit; +//! Heap ID counter +static atomic32_t _memory_heap_id; +//! Huge page support +static int _memory_huge_pages; +#if ENABLE_GLOBAL_CACHE +//! Global span cache +static global_cache_t _memory_span_cache[LARGE_CLASS_COUNT]; +#endif +//! Global reserved spans +static span_t* _memory_global_reserve; +//! Global reserved count +static size_t _memory_global_reserve_count; +//! Global reserved master +static span_t* _memory_global_reserve_master; +//! All heaps +static heap_t* _memory_heaps[HEAP_ARRAY_SIZE]; +//! Used to restrict access to mapping memory for huge pages +static atomic32_t _memory_global_lock; +//! Orphaned heaps +static heap_t* _memory_orphan_heaps; +#if RPMALLOC_FIRST_CLASS_HEAPS +//! Orphaned heaps (first class heaps) +static heap_t* _memory_first_class_orphan_heaps; +#endif +#if ENABLE_STATISTICS +//! Allocations counter +static atomic64_t _allocation_counter; +//! Deallocations counter +static atomic64_t _deallocation_counter; +//! Active heap count +static atomic32_t _memory_active_heaps; +//! Number of currently mapped memory pages +static atomic32_t _mapped_pages; +//! Peak number of concurrently mapped memory pages +static int32_t _mapped_pages_peak; +//! Number of mapped master spans +static atomic32_t _master_spans; +//! Number of unmapped dangling master spans +static atomic32_t _unmapped_master_spans; +//! Running counter of total number of mapped memory pages since start +static atomic32_t _mapped_total; +//! Running counter of total number of unmapped memory pages since start +static atomic32_t _unmapped_total; +//! Number of currently mapped memory pages in OS calls +static atomic32_t _mapped_pages_os; +//! Number of currently allocated pages in huge allocations +static atomic32_t _huge_pages_current; +//! Peak number of currently allocated pages in huge allocations +static int32_t _huge_pages_peak; +#endif + +//////////// +/// +/// Thread local heap and ID +/// +////// + +//! Current thread heap +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) +static pthread_key_t _memory_thread_heap; +#else +# ifdef _MSC_VER +# define _Thread_local __declspec(thread) +# define TLS_MODEL +# else +# ifndef __HAIKU__ +# define TLS_MODEL __attribute__((tls_model("initial-exec"))) +# else +# define TLS_MODEL +# endif +# if !defined(__clang__) && defined(__GNUC__) +# define _Thread_local __thread +# endif +# endif +static _Thread_local heap_t* _memory_thread_heap TLS_MODEL; +#endif + +static inline heap_t* +get_thread_heap_raw(void) { +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + return pthread_getspecific(_memory_thread_heap); +#else + return _memory_thread_heap; +#endif +} + +//! Get the current thread heap +static inline heap_t* +get_thread_heap(void) { + heap_t* heap = get_thread_heap_raw(); +#if ENABLE_PRELOAD + if (EXPECTED(heap != 0)) + return heap; + rpmalloc_initialize(); + return get_thread_heap_raw(); +#else + return heap; +#endif +} + +//! Fast thread ID +static inline uintptr_t +get_thread_id(void) { +#if defined(_WIN32) + return (uintptr_t)((void*)NtCurrentTeb()); +#elif (defined(__GNUC__) || defined(__clang__)) && !defined(__CYGWIN__) + uintptr_t tid; +# if defined(__i386__) + __asm__("movl %%gs:0, %0" : "=r" (tid) : : ); +# elif defined(__x86_64__) +# if defined(__MACH__) + __asm__("movq %%gs:0, %0" : "=r" (tid) : : ); +# else + __asm__("movq %%fs:0, %0" : "=r" (tid) : : ); +# endif +# elif defined(__arm__) + __asm__ volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (tid)); +# elif defined(__aarch64__) +# if defined(__MACH__) + // tpidr_el0 likely unused, always return 0 on iOS + __asm__ volatile ("mrs %0, tpidrro_el0" : "=r" (tid)); +# else + __asm__ volatile ("mrs %0, tpidr_el0" : "=r" (tid)); +# endif +# else +# error This platform needs implementation of get_thread_id() +# endif + return tid; +#else +# error This platform needs implementation of get_thread_id() +#endif +} + +//! Set the current thread heap +static void +set_thread_heap(heap_t* heap) { +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + pthread_setspecific(_memory_thread_heap, heap); +#else + _memory_thread_heap = heap; +#endif + if (heap) + heap->owner_thread = get_thread_id(); +} + +//! Set main thread ID +extern void +rpmalloc_set_main_thread(void); + +void +rpmalloc_set_main_thread(void) { + _rpmalloc_main_thread_id = get_thread_id(); +} + +static void +_rpmalloc_spin(void) { +#if defined(_MSC_VER) + _mm_pause(); +#elif defined(__x86_64__) || defined(__i386__) + __asm__ volatile("pause" ::: "memory"); +#elif defined(__aarch64__) || (defined(__arm__) && __ARM_ARCH >= 7) + __asm__ volatile("yield" ::: "memory"); +#elif defined(__powerpc__) || defined(__powerpc64__) + // No idea if ever been compiled in such archs but ... as precaution + __asm__ volatile("or 27,27,27"); +#elif defined(__sparc__) + __asm__ volatile("rd %ccr, %g0 \n\trd %ccr, %g0 \n\trd %ccr, %g0"); +#else + struct timespec ts = {0}; + nanosleep(&ts, 0); +#endif +} + +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) +static void NTAPI +_rpmalloc_thread_destructor(void* value) { +#if ENABLE_OVERRIDE + // If this is called on main thread it means rpmalloc_finalize + // has not been called and shutdown is forced (through _exit) or unclean + if (get_thread_id() == _rpmalloc_main_thread_id) + return; +#endif + if (value) + rpmalloc_thread_finalize(1); +} +#endif + + +//////////// +/// +/// Low level memory map/unmap +/// +////// + +static void +_rpmalloc_set_name(void* address, size_t size) { +#if defined(__linux__) || defined(__ANDROID__) + const char *name = _memory_huge_pages ? _memory_config.huge_page_name : _memory_config.page_name; + if (address == MAP_FAILED || !name) + return; + // If the kernel does not support CONFIG_ANON_VMA_NAME or if the call fails + // (e.g. invalid name) it is a no-op basically. + (void)prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (uintptr_t)address, size, (uintptr_t)name); +#else + (void)sizeof(size); + (void)sizeof(address); +#endif +} + + +//! Map more virtual memory +// size is number of bytes to map +// offset receives the offset in bytes from start of mapped region +// returns address to start of mapped region to use +static void* +_rpmalloc_mmap(size_t size, size_t* offset) { + rpmalloc_assert(!(size % _memory_page_size), "Invalid mmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); + void* address = _memory_config.memory_map(size, offset); + if (EXPECTED(address != 0)) { + _rpmalloc_stat_add_peak(&_mapped_pages, (size >> _memory_page_size_shift), _mapped_pages_peak); + _rpmalloc_stat_add(&_mapped_total, (size >> _memory_page_size_shift)); + } + return address; +} + +//! Unmap virtual memory +// address is the memory address to unmap, as returned from _memory_map +// size is the number of bytes to unmap, which might be less than full region for a partial unmap +// offset is the offset in bytes to the actual mapped region, as set by _memory_map +// release is set to 0 for partial unmap, or size of entire range for a full unmap +static void +_rpmalloc_unmap(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(!release || (release >= size), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + if (release) { + rpmalloc_assert(!(release % _memory_page_size), "Invalid unmap size"); + _rpmalloc_stat_sub(&_mapped_pages, (release >> _memory_page_size_shift)); + _rpmalloc_stat_add(&_unmapped_total, (release >> _memory_page_size_shift)); + } + _memory_config.memory_unmap(address, size, offset, release); +} + +//! Default implementation to map new pages to virtual memory +static void* +_rpmalloc_mmap_os(size_t size, size_t* offset) { + //Either size is a heap (a single page) or a (multiple) span - we only need to align spans, and only if larger than map granularity + size_t padding = ((size >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) ? _memory_span_size : 0; + rpmalloc_assert(size >= _memory_page_size, "Invalid mmap size"); +#if PLATFORM_WINDOWS + //Ok to MEM_COMMIT - according to MSDN, "actual physical pages are not allocated unless/until the virtual addresses are actually accessed" + void* ptr = VirtualAlloc(0, size + padding, (_memory_huge_pages ? MEM_LARGE_PAGES : 0) | MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + if (!ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else { + rpmalloc_assert(ptr, "Failed to map virtual memory block"); + } + return 0; + } +#else + int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED; +# if defined(__APPLE__) && !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR + int fd = (int)VM_MAKE_TAG(240U); + if (_memory_huge_pages) + fd |= VM_FLAGS_SUPERPAGE_SIZE_2MB; + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, fd, 0); +# elif defined(MAP_HUGETLB) + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE | PROT_MAX(PROT_READ | PROT_WRITE), (_memory_huge_pages ? MAP_HUGETLB : 0) | flags, -1, 0); +# if defined(MADV_HUGEPAGE) + // In some configurations, huge pages allocations might fail thus + // we fallback to normal allocations and promote the region as transparent huge page + if ((ptr == MAP_FAILED || !ptr) && _memory_huge_pages) { + ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); + if (ptr && ptr != MAP_FAILED) { + int prm = madvise(ptr, size + padding, MADV_HUGEPAGE); + (void)prm; + rpmalloc_assert((prm == 0), "Failed to promote the page to THP"); + } + } +# endif + _rpmalloc_set_name(ptr, size + padding); +# elif defined(MAP_ALIGNED) + const size_t align = (sizeof(size_t) * 8) - (size_t)(__builtin_clzl(size - 1)); + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGNED(align) : 0) | flags, -1, 0); +# elif defined(MAP_ALIGN) + caddr_t base = (_memory_huge_pages ? (caddr_t)(4 << 20) : 0); + void* ptr = mmap(base, size + padding, PROT_READ | PROT_WRITE, (_memory_huge_pages ? MAP_ALIGN : 0) | flags, -1, 0); +# else + void* ptr = mmap(0, size + padding, PROT_READ | PROT_WRITE, flags, -1, 0); +# endif + if ((ptr == MAP_FAILED) || !ptr) { + if (_memory_config.map_fail_callback) { + if (_memory_config.map_fail_callback(size + padding)) + return _rpmalloc_mmap_os(size, offset); + } else if (errno != ENOMEM) { + rpmalloc_assert((ptr != MAP_FAILED) && ptr, "Failed to map virtual memory block"); + } + return 0; + } +#endif + _rpmalloc_stat_add(&_mapped_pages_os, (int32_t)((size + padding) >> _memory_page_size_shift)); + if (padding) { + size_t final_padding = padding - ((uintptr_t)ptr & ~_memory_span_mask); + rpmalloc_assert(final_padding <= _memory_span_size, "Internal failure in padding"); + rpmalloc_assert(final_padding <= padding, "Internal failure in padding"); + rpmalloc_assert(!(final_padding % 8), "Internal failure in padding"); + ptr = pointer_offset(ptr, final_padding); + *offset = final_padding >> 3; + } + rpmalloc_assert((size < _memory_span_size) || !((uintptr_t)ptr & ~_memory_span_mask), "Internal failure in padding"); + return ptr; +} + +//! Default implementation to unmap pages from virtual memory +static void +_rpmalloc_unmap_os(void* address, size_t size, size_t offset, size_t release) { + rpmalloc_assert(release || (offset == 0), "Invalid unmap size"); + rpmalloc_assert(!release || (release >= _memory_page_size), "Invalid unmap size"); + rpmalloc_assert(size >= _memory_page_size, "Invalid unmap size"); + if (release && offset) { + offset <<= 3; + address = pointer_offset(address, -(int32_t)offset); + if ((release >= _memory_span_size) && (_memory_span_size > _memory_map_granularity)) { + //Padding is always one span size + release += _memory_span_size; + } + } +#if !DISABLE_UNMAP +#if PLATFORM_WINDOWS + if (!VirtualFree(address, release ? 0 : size, release ? MEM_RELEASE : MEM_DECOMMIT)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } +#else + if (release) { + if (munmap(address, release)) { + rpmalloc_assert(0, "Failed to unmap virtual memory block"); + } + } else { +#if defined(MADV_FREE_REUSABLE) + int ret; + while ((ret = madvise(address, size, MADV_FREE_REUSABLE)) == -1 && (errno == EAGAIN)) + errno = 0; + if ((ret == -1) && (errno != 0)) { +#elif defined(MADV_DONTNEED) + if (madvise(address, size, MADV_DONTNEED)) { +#elif defined(MADV_PAGEOUT) + if (madvise(address, size, MADV_PAGEOUT)) { +#elif defined(MADV_FREE) + if (madvise(address, size, MADV_FREE)) { +#else + if (posix_madvise(address, size, POSIX_MADV_DONTNEED)) { +#endif + rpmalloc_assert(0, "Failed to madvise virtual memory block as free"); + } + } +#endif +#endif + if (release) + _rpmalloc_stat_sub(&_mapped_pages_os, release >> _memory_page_size_shift); +} + +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count); + +//! Use global reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_global_get_reserved_spans(size_t span_count) { + span_t* span = _memory_global_reserve; + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, span, span_count); + _memory_global_reserve_count -= span_count; + if (_memory_global_reserve_count) + _memory_global_reserve = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + else + _memory_global_reserve = 0; + return span; +} + +//! Store the given spans as global reserve (must only be called from within new heap allocation, not thread safe) +static void +_rpmalloc_global_set_reserved_spans(span_t* master, span_t* reserve, size_t reserve_span_count) { + _memory_global_reserve_master = master; + _memory_global_reserve_count = reserve_span_count; + _memory_global_reserve = reserve; +} + + +//////////// +/// +/// Span linked list management +/// +////// + +//! Add a span to double linked list at the head +static void +_rpmalloc_span_double_link_list_add(span_t** head, span_t* span) { + if (*head) + (*head)->prev = span; + span->next = *head; + *head = span; +} + +//! Pop head span from double linked list +static void +_rpmalloc_span_double_link_list_pop_head(span_t** head, span_t* span) { + rpmalloc_assert(*head == span, "Linked list corrupted"); + span = *head; + *head = span->next; +} + +//! Remove a span from double linked list +static void +_rpmalloc_span_double_link_list_remove(span_t** head, span_t* span) { + rpmalloc_assert(*head, "Linked list corrupted"); + if (*head == span) { + *head = span->next; + } else { + span_t* next_span = span->next; + span_t* prev_span = span->prev; + prev_span->next = next_span; + if (EXPECTED(next_span != 0)) + next_span->prev = prev_span; + } +} + + +//////////// +/// +/// Span control +/// +////// + +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span); + +static void +_rpmalloc_heap_finalize(heap_t* heap); + +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count); + +//! Declare the span to be a subspan and store distance from master span and span count +static void +_rpmalloc_span_mark_as_subspan_unless_master(span_t* master, span_t* subspan, size_t span_count) { + rpmalloc_assert((subspan != master) || (subspan->flags & SPAN_FLAG_MASTER), "Span master pointer and/or flag mismatch"); + if (subspan != master) { + subspan->flags = SPAN_FLAG_SUBSPAN; + subspan->offset_from_master = (uint32_t)((uintptr_t)pointer_diff(subspan, master) >> _memory_span_size_shift); + subspan->align_offset = 0; + } + subspan->span_count = (uint32_t)span_count; +} + +//! Use reserved spans to fulfill a memory map request (reserve size must be checked by caller) +static span_t* +_rpmalloc_span_map_from_reserve(heap_t* heap, size_t span_count) { + //Update the heap span reserve + span_t* span = heap->span_reserve; + heap->span_reserve = (span_t*)pointer_offset(span, span_count * _memory_span_size); + heap->spans_reserved -= (uint32_t)span_count; + + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, span, span_count); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_reserved); + + return span; +} + +//! Get the aligned number of spans to map in based on wanted count, configured mapping granularity and the page size +static size_t +_rpmalloc_span_align_count(size_t span_count) { + size_t request_count = (span_count > _memory_span_map_count) ? span_count : _memory_span_map_count; + if ((_memory_page_size > _memory_span_size) && ((request_count * _memory_span_size) % _memory_page_size)) + request_count += _memory_span_map_count - (request_count % _memory_span_map_count); + return request_count; +} + +//! Setup a newly mapped span +static void +_rpmalloc_span_initialize(span_t* span, size_t total_span_count, size_t span_count, size_t align_offset) { + span->total_spans = (uint32_t)total_span_count; + span->span_count = (uint32_t)span_count; + span->align_offset = (uint32_t)align_offset; + span->flags = SPAN_FLAG_MASTER; + atomic_store32(&span->remaining_spans, (int32_t)total_span_count); +} + +static void +_rpmalloc_span_unmap(span_t* span); + +//! Map an aligned set of spans, taking configured mapping granularity and the page size into account +static span_t* +_rpmalloc_span_map_aligned_count(heap_t* heap, size_t span_count) { + //If we already have some, but not enough, reserved spans, release those to heap cache and map a new + //full set of spans. Otherwise we would waste memory if page size > span size (huge pages) + size_t aligned_span_count = _rpmalloc_span_align_count(span_count); + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(aligned_span_count * _memory_span_size, &align_offset); + if (!span) + return 0; + _rpmalloc_span_initialize(span, aligned_span_count, span_count, align_offset); + _rpmalloc_stat_inc(&_master_spans); + if (span_count <= LARGE_CLASS_COUNT) + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_map_calls); + if (aligned_span_count > span_count) { + span_t* reserved_spans = (span_t*)pointer_offset(span, span_count * _memory_span_size); + size_t reserved_count = aligned_span_count - span_count; + if (heap->spans_reserved) { + _rpmalloc_span_mark_as_subspan_unless_master(heap->span_reserve_master, heap->span_reserve, heap->spans_reserved); + _rpmalloc_heap_cache_insert(heap, heap->span_reserve); + } + if (reserved_count > _memory_heap_reserve_count) { + // If huge pages or eager spam map count, the global reserve spin lock is held by caller, _rpmalloc_span_map + rpmalloc_assert(atomic_load32(&_memory_global_lock) == 1, "Global spin lock not held as expected"); + size_t remain_count = reserved_count - _memory_heap_reserve_count; + reserved_count = _memory_heap_reserve_count; + span_t* remain_span = (span_t*)pointer_offset(reserved_spans, reserved_count * _memory_span_size); + if (_memory_global_reserve) { + _rpmalloc_span_mark_as_subspan_unless_master(_memory_global_reserve_master, _memory_global_reserve, _memory_global_reserve_count); + _rpmalloc_span_unmap(_memory_global_reserve); + } + _rpmalloc_global_set_reserved_spans(span, remain_span, remain_count); + } + _rpmalloc_heap_set_reserved_spans(heap, span, reserved_spans, reserved_count); + } + return span; +} + +//! Map in memory pages for the given number of spans (or use previously reserved pages) +static span_t* +_rpmalloc_span_map(heap_t* heap, size_t span_count) { + if (span_count <= heap->spans_reserved) + return _rpmalloc_span_map_from_reserve(heap, span_count); + span_t* span = 0; + int use_global_reserve = (_memory_page_size > _memory_span_size) || (_memory_span_map_count > _memory_heap_reserve_count); + if (use_global_reserve) { + // If huge pages, make sure only one thread maps more memory to avoid bloat + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (_memory_global_reserve_count >= span_count) { + size_t reserve_count = (!heap->spans_reserved ? _memory_heap_reserve_count : span_count); + if (_memory_global_reserve_count < reserve_count) + reserve_count = _memory_global_reserve_count; + span = _rpmalloc_global_get_reserved_spans(reserve_count); + if (span) { + if (reserve_count > span_count) { + span_t* reserved_span = (span_t*)pointer_offset(span, span_count << _memory_span_size_shift); + _rpmalloc_heap_set_reserved_spans(heap, _memory_global_reserve_master, reserved_span, reserve_count - span_count); + } + // Already marked as subspan in _rpmalloc_global_get_reserved_spans + span->span_count = (uint32_t)span_count; + } + } + } + if (!span) + span = _rpmalloc_span_map_aligned_count(heap, span_count); + if (use_global_reserve) + atomic_store32_release(&_memory_global_lock, 0); + return span; +} + +//! Unmap memory pages for the given number of spans (or mark as unused if no partial unmappings) +static void +_rpmalloc_span_unmap(span_t* span) { + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + + int is_master = !!(span->flags & SPAN_FLAG_MASTER); + span_t* master = is_master ? span : ((span_t*)pointer_offset(span, -(intptr_t)((uintptr_t)span->offset_from_master * _memory_span_size))); + rpmalloc_assert(is_master || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + + size_t span_count = span->span_count; + if (!is_master) { + //Directly unmap subspans (unless huge pages, in which case we defer and unmap entire page range with master) + rpmalloc_assert(span->align_offset == 0, "Span align offset corrupted"); + if (_memory_span_size >= _memory_page_size) + _rpmalloc_unmap(span, span_count * _memory_span_size, 0, 0); + } else { + //Special double flag to denote an unmapped master + //It must be kept in memory since span header must be used + span->flags |= SPAN_FLAG_MASTER | SPAN_FLAG_SUBSPAN | SPAN_FLAG_UNMAPPED_MASTER; + _rpmalloc_stat_add(&_unmapped_master_spans, 1); + } + + if (atomic_add32(&master->remaining_spans, -(int32_t)span_count) <= 0) { + //Everything unmapped, unmap the master span with release flag to unmap the entire range of the super span + rpmalloc_assert(!!(master->flags & SPAN_FLAG_MASTER) && !!(master->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + size_t unmap_count = master->span_count; + if (_memory_span_size < _memory_page_size) + unmap_count = master->total_spans; + _rpmalloc_stat_sub(&_master_spans, 1); + _rpmalloc_stat_sub(&_unmapped_master_spans, 1); + _rpmalloc_unmap(master, unmap_count * _memory_span_size, master->align_offset, (size_t)master->total_spans * _memory_span_size); + } +} + +//! Move the span (used for small or medium allocations) to the heap thread cache +static void +_rpmalloc_span_release_to_cache(heap_t* heap, span_t* span) { + rpmalloc_assert(heap == span->heap, "Span heap pointer corrupted"); + rpmalloc_assert(span->size_class < SIZE_CLASS_COUNT, "Invalid span size class"); + rpmalloc_assert(span->span_count == 1, "Invalid span count"); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + atomic_decr32(&heap->span_use[0].current); +#endif + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (!heap->finalize) { + _rpmalloc_stat_inc(&heap->span_use[0].spans_to_cache); + _rpmalloc_stat_inc(&heap->size_class_use[span->size_class].spans_to_cache); + if (heap->size_class[span->size_class].cache) + _rpmalloc_heap_cache_insert(heap, heap->size_class[span->size_class].cache); + heap->size_class[span->size_class].cache = span; + } else { + _rpmalloc_span_unmap(span); + } +} + +//! Initialize a (partial) free list up to next system memory page, while reserving the first block +//! as allocated, returning number of blocks in list +static uint32_t +free_list_partial_init(void** list, void** first_block, void* page_start, void* block_start, uint32_t block_count, uint32_t block_size) { + rpmalloc_assert(block_count, "Internal failure"); + *first_block = block_start; + if (block_count > 1) { + void* free_block = pointer_offset(block_start, block_size); + void* block_end = pointer_offset(block_start, (size_t)block_size * block_count); + //If block size is less than half a memory page, bound init to next memory page boundary + if (block_size < (_memory_page_size >> 1)) { + void* page_end = pointer_offset(page_start, _memory_page_size); + if (page_end < block_end) + block_end = page_end; + } + *list = free_block; + block_count = 2; + void* next_block = pointer_offset(free_block, block_size); + while (next_block < block_end) { + *((void**)free_block) = next_block; + free_block = next_block; + ++block_count; + next_block = pointer_offset(next_block, block_size); + } + *((void**)free_block) = 0; + } else { + *list = 0; + } + return block_count; +} + +//! Initialize an unused span (from cache or mapped) to be new active span, putting the initial free list in heap class free list +static void* +_rpmalloc_span_initialize_new(heap_t* heap, heap_size_class_t* heap_size_class, span_t* span, uint32_t class_idx) { + rpmalloc_assert(span->span_count == 1, "Internal failure"); + size_class_t* size_class = _memory_size_class + class_idx; + span->size_class = class_idx; + span->heap = heap; + span->flags &= ~SPAN_FLAG_ALIGNED_BLOCKS; + span->block_size = size_class->block_size; + span->block_count = size_class->block_count; + span->free_list = 0; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); + + //Setup free list. Only initialize one system page worth of free blocks in list + void* block; + span->free_list_limit = free_list_partial_init(&heap_size_class->free_list, &block, + span, pointer_offset(span, SPAN_HEADER_SIZE), size_class->block_count, size_class->block_size); + //Link span as partial if there remains blocks to be initialized as free list, or full if fully initialized + if (span->free_list_limit < span->block_count) { + _rpmalloc_span_double_link_list_add(&heap_size_class->partial_span, span); + span->used_count = span->free_list_limit; + } else { +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + span->used_count = span->block_count; + } + return block; +} + +static void +_rpmalloc_span_extract_free_list_deferred(span_t* span) { + // We need acquire semantics on the CAS operation since we are interested in the list size + // Refer to _rpmalloc_deallocate_defer_small_or_medium for further comments on this dependency + do { + span->free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (span->free_list == INVALID_POINTER); + span->used_count -= span->list_size; + span->list_size = 0; + atomic_store_ptr_release(&span->free_list_deferred, 0); +} + +static int +_rpmalloc_span_is_fully_utilized(span_t* span) { + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span free list corrupted"); + return !span->free_list && (span->free_list_limit >= span->block_count); +} + +static int +_rpmalloc_span_finalize(heap_t* heap, size_t iclass, span_t* span, span_t** list_head) { + void* free_list = heap->size_class[iclass].free_list; + span_t* class_span = (span_t*)((uintptr_t)free_list & _memory_span_mask); + if (span == class_span) { + // Adopt the heap class free list back into the span free list + void* block = span->free_list; + void* last_block = 0; + while (block) { + last_block = block; + block = *((void**)block); + } + uint32_t free_count = 0; + block = free_list; + while (block) { + ++free_count; + block = *((void**)block); + } + if (last_block) { + *((void**)last_block) = free_list; + } else { + span->free_list = free_list; + } + heap->size_class[iclass].free_list = 0; + span->used_count -= free_count; + } + //If this assert triggers you have memory leaks + rpmalloc_assert(span->list_size == span->used_count, "Memory leak detected"); + if (span->list_size == span->used_count) { + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[iclass].spans_current); + // This function only used for spans in double linked lists + if (list_head) + _rpmalloc_span_double_link_list_remove(list_head, span); + _rpmalloc_span_unmap(span); + return 1; + } + return 0; +} + + +//////////// +/// +/// Global cache +/// +////// + +#if ENABLE_GLOBAL_CACHE + +//! Finalize a global cache +static void +_rpmalloc_global_cache_finalize(global_cache_t* cache) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + for (size_t ispan = 0; ispan < cache->count; ++ispan) + _rpmalloc_span_unmap(cache->span[ispan]); + cache->count = 0; + + while (cache->overflow) { + span_t* span = cache->overflow; + cache->overflow = span->next; + _rpmalloc_span_unmap(span); + } + + atomic_store32_release(&cache->lock, 0); +} + +static void +_rpmalloc_global_cache_insert_spans(span_t** span, size_t span_count, size_t count) { + const size_t cache_limit = (span_count == 1) ? + GLOBAL_CACHE_MULTIPLIER * MAX_THREAD_SPAN_CACHE : + GLOBAL_CACHE_MULTIPLIER * (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t insert_count = count; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->insert_count += count; +#endif + if ((cache->count + insert_count) > cache_limit) + insert_count = cache_limit - cache->count; + + memcpy(cache->span + cache->count, span, sizeof(span_t*) * insert_count); + cache->count += (uint32_t)insert_count; + +#if ENABLE_UNLIMITED_CACHE + while (insert_count < count) { +#else + // Enable unlimited cache if huge pages, or we will leak since it is unlikely that an entire huge page + // will be unmapped, and we're unable to partially decommit a huge page + while ((_memory_page_size > _memory_span_size) && (insert_count < count)) { +#endif + span_t* current_span = span[insert_count++]; + current_span->next = cache->overflow; + cache->overflow = current_span; + } + atomic_store32_release(&cache->lock, 0); + + span_t* keep = 0; + for (size_t ispan = insert_count; ispan < count; ++ispan) { + span_t* current_span = span[ispan]; + // Keep master spans that has remaining subspans to avoid dangling them + if ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) > (int32_t)current_span->span_count)) { + current_span->next = keep; + keep = current_span; + } else { + _rpmalloc_span_unmap(current_span); + } + } + + if (keep) { + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + + size_t islot = 0; + while (keep) { + for (; islot < cache->count; ++islot) { + span_t* current_span = cache->span[islot]; + if (!(current_span->flags & SPAN_FLAG_MASTER) || ((current_span->flags & SPAN_FLAG_MASTER) && + (atomic_load32(¤t_span->remaining_spans) <= (int32_t)current_span->span_count))) { + _rpmalloc_span_unmap(current_span); + cache->span[islot] = keep; + break; + } + } + if (islot == cache->count) + break; + keep = keep->next; + } + + if (keep) { + span_t* tail = keep; + while (tail->next) + tail = tail->next; + tail->next = cache->overflow; + cache->overflow = keep; + } + + atomic_store32_release(&cache->lock, 0); + } +} + +static size_t +_rpmalloc_global_cache_extract_spans(span_t** span, size_t span_count, size_t count) { + global_cache_t* cache = &_memory_span_cache[span_count - 1]; + + size_t extract_count = 0; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + +#if ENABLE_STATISTICS + cache->extract_count += count; +#endif + size_t want = count - extract_count; + if (want > cache->count) + want = cache->count; + + memcpy(span + extract_count, cache->span + (cache->count - want), sizeof(span_t*) * want); + cache->count -= (uint32_t)want; + extract_count += want; + + while ((extract_count < count) && cache->overflow) { + span_t* current_span = cache->overflow; + span[extract_count++] = current_span; + cache->overflow = current_span->next; + } + +#if ENABLE_ASSERTS + for (size_t ispan = 0; ispan < extract_count; ++ispan) { + rpmalloc_assert(span[ispan]->span_count == span_count, "Global cache span count mismatch"); + } +#endif + + atomic_store32_release(&cache->lock, 0); + + return extract_count; +} + +#endif + +//////////// +/// +/// Heap control +/// +////// + +static void _rpmalloc_deallocate_huge(span_t*); + +//! Store the given spans as reserve in the given heap +static void +_rpmalloc_heap_set_reserved_spans(heap_t* heap, span_t* master, span_t* reserve, size_t reserve_span_count) { + heap->span_reserve_master = master; + heap->span_reserve = reserve; + heap->spans_reserved = (uint32_t)reserve_span_count; +} + +//! Adopt the deferred span cache list, optionally extracting the first single span for immediate re-use +static void +_rpmalloc_heap_cache_adopt_deferred(heap_t* heap, span_t** single_span) { + span_t* span = (span_t*)((void*)atomic_exchange_ptr_acquire(&heap->span_free_deferred, 0)); + while (span) { + span_t* next_span = (span_t*)span->free_list; + rpmalloc_assert(span->heap == heap, "Span heap pointer corrupted"); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; + _rpmalloc_stat_dec(&heap->span_use[0].spans_deferred); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_stat_dec(&heap->span_use[0].current); + _rpmalloc_stat_dec(&heap->size_class_use[span->size_class].spans_current); + if (single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } else { + if (span->size_class == SIZE_CLASS_HUGE) { + _rpmalloc_deallocate_huge(span); + } else { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Span size class invalid"); + rpmalloc_assert(heap->full_span_count, "Heap span counter corrupted"); + --heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->large_huge_span, span); +#endif + uint32_t idx = span->span_count - 1; + _rpmalloc_stat_dec(&heap->span_use[idx].spans_deferred); + _rpmalloc_stat_dec(&heap->span_use[idx].current); + if (!idx && single_span && !*single_span) + *single_span = span; + else + _rpmalloc_heap_cache_insert(heap, span); + } + } + span = next_span; + } +} + +static void +_rpmalloc_heap_unmap(heap_t* heap) { + if (!heap->master_heap) { + if ((heap->finalize > 1) && !atomic_load32(&heap->child_count)) { + span_t* span = (span_t*)((uintptr_t)heap & _memory_span_mask); + _rpmalloc_span_unmap(span); + } + } else { + if (atomic_decr32(&heap->master_heap->child_count) == 0) { + _rpmalloc_heap_unmap(heap->master_heap); + } + } +} + +static void +_rpmalloc_heap_global_finalize(heap_t* heap) { + if (heap->finalize++ > 1) { + --heap->finalize; + return; + } + + _rpmalloc_heap_finalize(heap); + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + + if (heap->full_span_count) { + --heap->finalize; + return; + } + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].free_list || heap->size_class[iclass].partial_span) { + --heap->finalize; + return; + } + } + //Heap is now completely free, unmap and remove from heap list + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap_t* list_heap = _memory_heaps[list_idx]; + if (list_heap == heap) { + _memory_heaps[list_idx] = heap->next_heap; + } else { + while (list_heap->next_heap != heap) + list_heap = list_heap->next_heap; + list_heap->next_heap = heap->next_heap; + } + + _rpmalloc_heap_unmap(heap); +} + +//! Insert a single span into thread heap cache, releasing to global cache if overflow +static void +_rpmalloc_heap_cache_insert(heap_t* heap, span_t* span) { + if (UNEXPECTED(heap->finalize != 0)) { + _rpmalloc_span_unmap(span); + _rpmalloc_heap_global_finalize(heap); + return; + } +#if ENABLE_THREAD_CACHE + size_t span_count = span->span_count; + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_to_cache); + if (span_count == 1) { + span_cache_t* span_cache = &heap->span_cache; + span_cache->span[span_cache->count++] = span; + if (span_cache->count == MAX_THREAD_SPAN_CACHE) { + const size_t remain_count = MAX_THREAD_SPAN_CACHE - THREAD_SPAN_CACHE_TRANSFER; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, THREAD_SPAN_CACHE_TRANSFER * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, THREAD_SPAN_CACHE_TRANSFER); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, THREAD_SPAN_CACHE_TRANSFER); +#else + for (size_t ispan = 0; ispan < THREAD_SPAN_CACHE_TRANSFER; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } else { + size_t cache_idx = span_count - 2; + span_large_cache_t* span_cache = heap->span_large_cache + cache_idx; + span_cache->span[span_cache->count++] = span; + const size_t cache_limit = (MAX_THREAD_SPAN_LARGE_CACHE - (span_count >> 1)); + if (span_cache->count == cache_limit) { + const size_t transfer_limit = 2 + (cache_limit >> 2); + const size_t transfer_count = (THREAD_SPAN_LARGE_CACHE_TRANSFER <= transfer_limit ? THREAD_SPAN_LARGE_CACHE_TRANSFER : transfer_limit); + const size_t remain_count = cache_limit - transfer_count; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, transfer_count * span_count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_to_global, transfer_count); + _rpmalloc_global_cache_insert_spans(span_cache->span + remain_count, span_count, transfer_count); +#else + for (size_t ispan = 0; ispan < transfer_count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[remain_count + ispan]); +#endif + span_cache->count = remain_count; + } + } +#else + (void)sizeof(heap); + _rpmalloc_span_unmap(span); +#endif +} + +//! Extract the given number of spans from the different cache levels +static span_t* +_rpmalloc_heap_thread_cache_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + if (span_count == 1) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + if (span_cache->count) { + _rpmalloc_stat_inc(&heap->span_use[span_count - 1].spans_from_cache); + return span_cache->span[--span_cache->count]; + } +#endif + return span; +} + +static span_t* +_rpmalloc_heap_thread_cache_deferred_extract(heap_t* heap, size_t span_count) { + span_t* span = 0; + if (span_count == 1) { + _rpmalloc_heap_cache_adopt_deferred(heap, &span); + } else { + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + } + return span; +} + +static span_t* +_rpmalloc_heap_reserved_extract(heap_t* heap, size_t span_count) { + if (heap->spans_reserved >= span_count) + return _rpmalloc_span_map(heap, span_count); + return 0; +} + +//! Extract a span from the global cache +static span_t* +_rpmalloc_heap_global_cache_extract(heap_t* heap, size_t span_count) { +#if ENABLE_GLOBAL_CACHE +#if ENABLE_THREAD_CACHE + span_cache_t* span_cache; + size_t wanted_count; + if (span_count == 1) { + span_cache = &heap->span_cache; + wanted_count = THREAD_SPAN_CACHE_TRANSFER; + } else { + span_cache = (span_cache_t*)(heap->span_large_cache + (span_count - 2)); + wanted_count = THREAD_SPAN_LARGE_CACHE_TRANSFER; + } + span_cache->count = _rpmalloc_global_cache_extract_spans(span_cache->span, span_count, wanted_count); + if (span_cache->count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * span_cache->count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, span_cache->count); + return span_cache->span[--span_cache->count]; + } +#else + span_t* span = 0; + size_t count = _rpmalloc_global_cache_extract_spans(&span, span_count, 1); + if (count) { + _rpmalloc_stat_add64(&heap->global_to_thread, span_count * count * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[span_count - 1].spans_from_global, count); + return span; + } +#endif +#endif + (void)sizeof(heap); + (void)sizeof(span_count); + return 0; +} + +static void +_rpmalloc_inc_span_statistics(heap_t* heap, size_t span_count, uint32_t class_idx) { + (void)sizeof(heap); + (void)sizeof(span_count); + (void)sizeof(class_idx); +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + uint32_t idx = (uint32_t)span_count - 1; + uint32_t current_count = (uint32_t)atomic_incr32(&heap->span_use[idx].current); + if (current_count > (uint32_t)atomic_load32(&heap->span_use[idx].high)) + atomic_store32(&heap->span_use[idx].high, (int32_t)current_count); + _rpmalloc_stat_add_peak(&heap->size_class_use[class_idx].spans_current, 1, heap->size_class_use[class_idx].spans_peak); +#endif +} + +//! Get a span from one of the cache levels (thread cache, reserved, global cache) or fallback to mapping more memory +static span_t* +_rpmalloc_heap_extract_new_span(heap_t* heap, heap_size_class_t* heap_size_class, size_t span_count, uint32_t class_idx) { + span_t* span; +#if ENABLE_THREAD_CACHE + if (heap_size_class && heap_size_class->cache) { + span = heap_size_class->cache; + heap_size_class->cache = (heap->span_cache.count ? heap->span_cache.span[--heap->span_cache.count] : 0); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } +#endif + (void)sizeof(class_idx); + // Allow 50% overhead to increase cache hits + size_t base_span_count = span_count; + size_t limit_span_count = (span_count > 2) ? (span_count + (span_count >> 1)) : span_count; + if (limit_span_count > LARGE_CLASS_COUNT) + limit_span_count = LARGE_CLASS_COUNT; + do { + span = _rpmalloc_heap_thread_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_thread_cache_deferred_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_reserved_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_reserved); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + span = _rpmalloc_heap_global_cache_extract(heap, span_count); + if (EXPECTED(span != 0)) { + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_from_cache); + _rpmalloc_inc_span_statistics(heap, span_count, class_idx); + return span; + } + ++span_count; + } while (span_count <= limit_span_count); + //Final fallback, map in more virtual memory + span = _rpmalloc_span_map(heap, base_span_count); + _rpmalloc_inc_span_statistics(heap, base_span_count, class_idx); + _rpmalloc_stat_inc(&heap->size_class_use[class_idx].spans_map_calls); + return span; +} + +static void +_rpmalloc_heap_initialize(heap_t* heap) { + _rpmalloc_memset_const(heap, 0, sizeof(heap_t)); + //Get a new heap ID + heap->id = 1 + atomic_incr32(&_memory_heap_id); + + //Link in heap in heap ID map + size_t list_idx = (size_t)heap->id % HEAP_ARRAY_SIZE; + heap->next_heap = _memory_heaps[list_idx]; + _memory_heaps[list_idx] = heap; +} + +static void +_rpmalloc_heap_orphan(heap_t* heap, int first_class) { + heap->owner_thread = (uintptr_t)-1; +#if RPMALLOC_FIRST_CLASS_HEAPS + heap_t** heap_list = (first_class ? &_memory_first_class_orphan_heaps : &_memory_orphan_heaps); +#else + (void)sizeof(first_class); + heap_t** heap_list = &_memory_orphan_heaps; +#endif + heap->next_orphan = *heap_list; + *heap_list = heap; +} + +//! Allocate a new heap from newly mapped memory pages +static heap_t* +_rpmalloc_heap_allocate_new(void) { + // Map in pages for a 16 heaps. If page size is greater than required size for this, map a page and + // use first part for heaps and remaining part for spans for allocations. Adds a lot of complexity, + // but saves a lot of memory on systems where page size > 64 spans (4MiB) + size_t heap_size = sizeof(heap_t); + size_t aligned_heap_size = 16 * ((heap_size + 15) / 16); + size_t request_heap_count = 16; + size_t heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + size_t block_size = _memory_span_size * heap_span_count; + size_t span_count = heap_span_count; + span_t* span = 0; + // If there are global reserved spans, use these first + if (_memory_global_reserve_count >= heap_span_count) { + span = _rpmalloc_global_get_reserved_spans(heap_span_count); + } + if (!span) { + if (_memory_page_size > block_size) { + span_count = _memory_page_size / _memory_span_size; + block_size = _memory_page_size; + // If using huge pages, make sure to grab enough heaps to avoid reallocating a huge page just to serve new heaps + size_t possible_heap_count = (block_size - sizeof(span_t)) / aligned_heap_size; + if (possible_heap_count >= (request_heap_count * 16)) + request_heap_count *= 16; + else if (possible_heap_count < request_heap_count) + request_heap_count = possible_heap_count; + heap_span_count = ((aligned_heap_size * request_heap_count) + sizeof(span_t) + _memory_span_size - 1) / _memory_span_size; + } + + size_t align_offset = 0; + span = (span_t*)_rpmalloc_mmap(block_size, &align_offset); + if (!span) + return 0; + + // Master span will contain the heaps + _rpmalloc_stat_inc(&_master_spans); + _rpmalloc_span_initialize(span, span_count, heap_span_count, align_offset); + } + + size_t remain_size = _memory_span_size - sizeof(span_t); + heap_t* heap = (heap_t*)pointer_offset(span, sizeof(span_t)); + _rpmalloc_heap_initialize(heap); + + // Put extra heaps as orphans + size_t num_heaps = remain_size / aligned_heap_size; + if (num_heaps < request_heap_count) + num_heaps = request_heap_count; + atomic_store32(&heap->child_count, (int32_t)num_heaps - 1); + heap_t* extra_heap = (heap_t*)pointer_offset(heap, aligned_heap_size); + while (num_heaps > 1) { + _rpmalloc_heap_initialize(extra_heap); + extra_heap->master_heap = heap; + _rpmalloc_heap_orphan(extra_heap, 1); + extra_heap = (heap_t*)pointer_offset(extra_heap, aligned_heap_size); + --num_heaps; + } + + if (span_count > heap_span_count) { + // Cap reserved spans + size_t remain_count = span_count - heap_span_count; + size_t reserve_count = (remain_count > _memory_heap_reserve_count ? _memory_heap_reserve_count : remain_count); + span_t* remain_span = (span_t*)pointer_offset(span, heap_span_count * _memory_span_size); + _rpmalloc_heap_set_reserved_spans(heap, span, remain_span, reserve_count); + + if (remain_count > reserve_count) { + // Set to global reserved spans + remain_span = (span_t*)pointer_offset(remain_span, reserve_count * _memory_span_size); + reserve_count = remain_count - reserve_count; + _rpmalloc_global_set_reserved_spans(span, remain_span, reserve_count); + } + } + + return heap; +} + +static heap_t* +_rpmalloc_heap_extract_orphan(heap_t** heap_list) { + heap_t* heap = *heap_list; + *heap_list = (heap ? heap->next_orphan : 0); + return heap; +} + +//! Allocate a new heap, potentially reusing a previously orphaned heap +static heap_t* +_rpmalloc_heap_allocate(int first_class) { + heap_t* heap = 0; + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + if (first_class == 0) + heap = _rpmalloc_heap_extract_orphan(&_memory_orphan_heaps); +#if RPMALLOC_FIRST_CLASS_HEAPS + if (!heap) + heap = _rpmalloc_heap_extract_orphan(&_memory_first_class_orphan_heaps); +#endif + if (!heap) + heap = _rpmalloc_heap_allocate_new(); + atomic_store32_release(&_memory_global_lock, 0); + if (heap) + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + return heap; +} + +static void +_rpmalloc_heap_release(void* heapptr, int first_class, int release_cache) { + heap_t* heap = (heap_t*)heapptr; + if (!heap) + return; + //Release thread cache spans back to global cache + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + if (release_cache || heap->finalize) { +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + if (heap->finalize) { + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + } else { + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); + } +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + } + + if (get_thread_heap_raw() == heap) + set_thread_heap(0); + +#if ENABLE_STATISTICS + atomic_decr32(&_memory_active_heaps); + rpmalloc_assert(atomic_load32(&_memory_active_heaps) >= 0, "Still active heaps during finalization"); +#endif + + // If we are forcibly terminating with _exit the state of the + // lock atomic is unknown and it's best to just go ahead and exit + if (get_thread_id() != _rpmalloc_main_thread_id) { + while (!atomic_cas32_acquire(&_memory_global_lock, 1, 0)) + _rpmalloc_spin(); + } + _rpmalloc_heap_orphan(heap, first_class); + atomic_store32_release(&_memory_global_lock, 0); +} + +static void +_rpmalloc_heap_release_raw(void* heapptr, int release_cache) { + _rpmalloc_heap_release(heapptr, 0, release_cache); +} + +static void +_rpmalloc_heap_release_raw_fc(void* heapptr) { + _rpmalloc_heap_release_raw(heapptr, 1); +} + +static void +_rpmalloc_heap_finalize(heap_t* heap) { + if (heap->spans_reserved) { + span_t* span = _rpmalloc_span_map(heap, heap->spans_reserved); + _rpmalloc_span_unmap(span); + heap->spans_reserved = 0; + } + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (heap->size_class[iclass].cache) + _rpmalloc_span_unmap(heap->size_class[iclass].cache); + heap->size_class[iclass].cache = 0; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + span_t* next = span->next; + _rpmalloc_span_finalize(heap, iclass, span, &heap->size_class[iclass].partial_span); + span = next; + } + // If class still has a free list it must be a full span + if (heap->size_class[iclass].free_list) { + span_t* class_span = (span_t*)((uintptr_t)heap->size_class[iclass].free_list & _memory_span_mask); + span_t** list = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + list = &heap->full_span[iclass]; +#endif + --heap->full_span_count; + if (!_rpmalloc_span_finalize(heap, iclass, class_span, list)) { + if (list) + _rpmalloc_span_double_link_list_remove(list, class_span); + _rpmalloc_span_double_link_list_add(&heap->size_class[iclass].partial_span, class_span); + } + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); + span_cache->count = 0; + } +#endif + rpmalloc_assert(!atomic_load_ptr(&heap->span_free_deferred), "Heaps still active during finalization"); +} + + +//////////// +/// +/// Allocation entry points +/// +////// + +//! Pop first block from a free list +static void* +free_list_pop(void** list) { + void* block = *list; + *list = *((void**)block); + return block; +} + +//! Allocate a small/medium sized memory block from the given heap +static void* +_rpmalloc_allocate_from_heap_fallback(heap_t* heap, heap_size_class_t* heap_size_class, uint32_t class_idx) { + span_t* span = heap_size_class->partial_span; + rpmalloc_assume(heap != 0); + if (EXPECTED(span != 0)) { + rpmalloc_assert(span->block_count == _memory_size_class[span->size_class].block_count, "Span block count corrupted"); + rpmalloc_assert(!_rpmalloc_span_is_fully_utilized(span), "Internal failure"); + void* block; + if (span->free_list) { + //Span local free list is not empty, swap to size class free list + block = free_list_pop(&span->free_list); + heap_size_class->free_list = span->free_list; + span->free_list = 0; + } else { + //If the span did not fully initialize free list, link up another page worth of blocks + void* block_start = pointer_offset(span, SPAN_HEADER_SIZE + ((size_t)span->free_list_limit * span->block_size)); + span->free_list_limit += free_list_partial_init(&heap_size_class->free_list, &block, + (void*)((uintptr_t)block_start & ~(_memory_page_size - 1)), block_start, + span->block_count - span->free_list_limit, span->block_size); + } + rpmalloc_assert(span->free_list_limit <= span->block_count, "Span block count corrupted"); + span->used_count = span->free_list_limit; + + //Swap in deferred free list if present + if (atomic_load_ptr(&span->free_list_deferred)) + _rpmalloc_span_extract_free_list_deferred(span); + + //If span is still not fully utilized keep it in partial list and early return block + if (!_rpmalloc_span_is_fully_utilized(span)) + return block; + + //The span is fully utilized, unlink from partial list and add to fully utilized list + _rpmalloc_span_double_link_list_pop_head(&heap_size_class->partial_span, span); +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->full_span[class_idx], span); +#endif + ++heap->full_span_count; + return block; + } + + //Find a span in one of the cache levels + span = _rpmalloc_heap_extract_new_span(heap, heap_size_class, 1, class_idx); + if (EXPECTED(span != 0)) { + //Mark span as owned by this heap and set base data, return first block + return _rpmalloc_span_initialize_new(heap, heap_size_class, span, class_idx); + } + + return 0; +} + +//! Allocate a small sized memory block from the given heap +static void* +_rpmalloc_allocate_small(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Small sizes have unique size classes + const uint32_t class_idx = (uint32_t)((size + (SMALL_GRANULARITY - 1)) >> SMALL_GRANULARITY_SHIFT); + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a medium sized memory block from the given heap +static void* +_rpmalloc_allocate_medium(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate the size class index and do a dependent lookup of the final class index (in case of merged classes) + const uint32_t base_idx = (uint32_t)(SMALL_CLASS_COUNT + ((size - (SMALL_SIZE_LIMIT + 1)) >> MEDIUM_GRANULARITY_SHIFT)); + const uint32_t class_idx = _memory_size_class[base_idx].class_idx; + heap_size_class_t* heap_size_class = heap->size_class + class_idx; + _rpmalloc_stat_inc_alloc(heap, class_idx); + if (EXPECTED(heap_size_class->free_list != 0)) + return free_list_pop(&heap_size_class->free_list); + return _rpmalloc_allocate_from_heap_fallback(heap, heap_size_class, class_idx); +} + +//! Allocate a large sized memory block from the given heap +static void* +_rpmalloc_allocate_large(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + //Calculate number of needed max sized spans (including header) + //Since this function is never called if size > LARGE_SIZE_LIMIT + //the span_count is guaranteed to be <= LARGE_CLASS_COUNT + size += SPAN_HEADER_SIZE; + size_t span_count = size >> _memory_span_size_shift; + if (size & (_memory_span_size - 1)) + ++span_count; + + //Find a span in one of the cache levels + span_t* span = _rpmalloc_heap_extract_new_span(heap, 0, span_count, SIZE_CLASS_LARGE); + if (!span) + return span; + + //Mark span as owned by this heap and set base data + rpmalloc_assert(span->span_count >= span_count, "Internal failure"); + span->size_class = SIZE_CLASS_LARGE; + span->heap = heap; + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a huge block by mapping memory pages directly +static void* +_rpmalloc_allocate_huge(heap_t* heap, size_t size) { + rpmalloc_assert(heap, "No thread heap"); + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + size += SPAN_HEADER_SIZE; + size_t num_pages = size >> _memory_page_size_shift; + if (size & (_memory_page_size - 1)) + ++num_pages; + size_t align_offset = 0; + span_t* span = (span_t*)_rpmalloc_mmap(num_pages * _memory_page_size, &align_offset); + if (!span) + return span; + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + return pointer_offset(span, SPAN_HEADER_SIZE); +} + +//! Allocate a block of the given size +static void* +_rpmalloc_allocate(heap_t* heap, size_t size) { + _rpmalloc_stat_add64(&_allocation_counter, 1); + if (EXPECTED(size <= SMALL_SIZE_LIMIT)) + return _rpmalloc_allocate_small(heap, size); + else if (size <= _memory_medium_size_limit) + return _rpmalloc_allocate_medium(heap, size); + else if (size <= LARGE_SIZE_LIMIT) + return _rpmalloc_allocate_large(heap, size); + return _rpmalloc_allocate_huge(heap, size); +} + +static void* +_rpmalloc_aligned_allocate(heap_t* heap, size_t alignment, size_t size) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_allocate(heap, size); + +#if ENABLE_VALIDATE_ARGS + if ((size + alignment) < size) { + errno = EINVAL; + return 0; + } + if (alignment & (alignment - 1)) { + errno = EINVAL; + return 0; + } +#endif + + if ((alignment <= SPAN_HEADER_SIZE) && ((size + SPAN_HEADER_SIZE) < _memory_medium_size_limit)) { + // If alignment is less or equal to span header size (which is power of two), + // and size aligned to span header size multiples is less than size + alignment, + // then use natural alignment of blocks to provide alignment + size_t multiple_size = size ? (size + (SPAN_HEADER_SIZE - 1)) & ~(uintptr_t)(SPAN_HEADER_SIZE - 1) : SPAN_HEADER_SIZE; + rpmalloc_assert(!(multiple_size % SPAN_HEADER_SIZE), "Failed alignment calculation"); + if (multiple_size <= (size + alignment)) + return _rpmalloc_allocate(heap, multiple_size); + } + + void* ptr = 0; + size_t align_mask = alignment - 1; + if (alignment <= _memory_page_size) { + ptr = _rpmalloc_allocate(heap, size + alignment); + if ((uintptr_t)ptr & align_mask) { + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + //Mark as having aligned blocks + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + span->flags |= SPAN_FLAG_ALIGNED_BLOCKS; + } + return ptr; + } + + // Fallback to mapping new pages for this request. Since pointers passed + // to rpfree must be able to reach the start of the span by bitmasking of + // the address with the span size, the returned aligned pointer from this + // function must be with a span size of the start of the mapped area. + // In worst case this requires us to loop and map pages until we get a + // suitable memory address. It also means we can never align to span size + // or greater, since the span header will push alignment more than one + // span size away from span start (thus causing pointer mask to give us + // an invalid span start on free) + if (alignment & align_mask) { + errno = EINVAL; + return 0; + } + if (alignment >= _memory_span_size) { + errno = EINVAL; + return 0; + } + + size_t extra_pages = alignment / _memory_page_size; + + // Since each span has a header, we will at least need one extra memory page + size_t num_pages = 1 + (size / _memory_page_size); + if (size & (_memory_page_size - 1)) + ++num_pages; + + if (extra_pages > num_pages) + num_pages = 1 + extra_pages; + + size_t original_pages = num_pages; + size_t limit_pages = (_memory_span_size / _memory_page_size) * 2; + if (limit_pages < (original_pages * 2)) + limit_pages = original_pages * 2; + + size_t mapped_size, align_offset; + span_t* span; + +retry: + align_offset = 0; + mapped_size = num_pages * _memory_page_size; + + span = (span_t*)_rpmalloc_mmap(mapped_size, &align_offset); + if (!span) { + errno = ENOMEM; + return 0; + } + ptr = pointer_offset(span, SPAN_HEADER_SIZE); + + if ((uintptr_t)ptr & align_mask) + ptr = (void*)(((uintptr_t)ptr & ~(uintptr_t)align_mask) + alignment); + + if (((size_t)pointer_diff(ptr, span) >= _memory_span_size) || + (pointer_offset(ptr, size) > pointer_offset(span, mapped_size)) || + (((uintptr_t)ptr & _memory_span_mask) != (uintptr_t)span)) { + _rpmalloc_unmap(span, mapped_size, align_offset, mapped_size); + ++num_pages; + if (num_pages > limit_pages) { + errno = EINVAL; + return 0; + } + goto retry; + } + + //Store page count in span_count + span->size_class = SIZE_CLASS_HUGE; + span->span_count = (uint32_t)num_pages; + span->align_offset = (uint32_t)align_offset; + span->heap = heap; + _rpmalloc_stat_add_peak(&_huge_pages_current, num_pages, _huge_pages_peak); + +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_add(&heap->large_huge_span, span); +#endif + ++heap->full_span_count; + + _rpmalloc_stat_add64(&_allocation_counter, 1); + + return ptr; +} + + +//////////// +/// +/// Deallocation entry points +/// +////// + +//! Deallocate the given small/medium memory block in the current thread local heap +static void +_rpmalloc_deallocate_direct_small_or_medium(span_t* span, void* block) { + heap_t* heap = span->heap; + rpmalloc_assert(heap->owner_thread == get_thread_id() || !heap->owner_thread || heap->finalize, "Internal failure"); + //Add block to free list + if (UNEXPECTED(_rpmalloc_span_is_fully_utilized(span))) { + span->used_count = span->block_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&heap->full_span[span->size_class], span); +#endif + _rpmalloc_span_double_link_list_add(&heap->size_class[span->size_class].partial_span, span); + --heap->full_span_count; + } + *((void**)block) = span->free_list; + --span->used_count; + span->free_list = block; + if (UNEXPECTED(span->used_count == span->list_size)) { + // If there are no used blocks it is guaranteed that no other external thread is accessing the span + if (span->used_count) { + // Make sure we have synchronized the deferred list and list size by using acquire semantics + // and guarantee that no external thread is accessing span concurrently + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + atomic_store_ptr_release(&span->free_list_deferred, free_list); + } + _rpmalloc_span_double_link_list_remove(&heap->size_class[span->size_class].partial_span, span); + _rpmalloc_span_release_to_cache(heap, span); + } +} + +static void +_rpmalloc_deallocate_defer_free_span(heap_t* heap, span_t* span) { + if (span->size_class != SIZE_CLASS_HUGE) + _rpmalloc_stat_inc(&heap->span_use[span->span_count - 1].spans_deferred); + //This list does not need ABA protection, no mutable side state + do { + span->free_list = (void*)atomic_load_ptr(&heap->span_free_deferred); + } while (!atomic_cas_ptr(&heap->span_free_deferred, span, span->free_list)); +} + +//! Put the block in the deferred free list of the owning span +static void +_rpmalloc_deallocate_defer_small_or_medium(span_t* span, void* block) { + // The memory ordering here is a bit tricky, to avoid having to ABA protect + // the deferred free list to avoid desynchronization of list and list size + // we need to have acquire semantics on successful CAS of the pointer to + // guarantee the list_size variable validity + release semantics on pointer store + void* free_list; + do { + free_list = atomic_exchange_ptr_acquire(&span->free_list_deferred, INVALID_POINTER); + } while (free_list == INVALID_POINTER); + *((void**)block) = free_list; + uint32_t free_count = ++span->list_size; + int all_deferred_free = (free_count == span->block_count); + atomic_store_ptr_release(&span->free_list_deferred, block); + if (all_deferred_free) { + // Span was completely freed by this block. Due to the INVALID_POINTER spin lock + // no other thread can reach this state simultaneously on this span. + // Safe to move to owner heap deferred cache + _rpmalloc_deallocate_defer_free_span(span->heap, span); + } +} + +static void +_rpmalloc_deallocate_small_or_medium(span_t* span, void* p) { + _rpmalloc_stat_inc_free(span->heap, span->size_class); + if (span->flags & SPAN_FLAG_ALIGNED_BLOCKS) { + //Realign pointer to block start + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + p = pointer_offset(p, -(int32_t)(block_offset % span->block_size)); + } + //Check if block belongs to this heap or if deallocation should be deferred +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (!defer) + _rpmalloc_deallocate_direct_small_or_medium(span, p); + else + _rpmalloc_deallocate_defer_small_or_medium(span, p); +} + +//! Deallocate the given large memory block to the current heap +static void +_rpmalloc_deallocate_large(span_t* span) { + rpmalloc_assert(span->size_class == SIZE_CLASS_LARGE, "Bad span size class"); + rpmalloc_assert(!(span->flags & SPAN_FLAG_MASTER) || !(span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + rpmalloc_assert((span->flags & SPAN_FLAG_MASTER) || (span->flags & SPAN_FLAG_SUBSPAN), "Span flag corrupted"); + //We must always defer (unless finalizing) if from another heap since we cannot touch the list or counters of another heap +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif +#if ENABLE_ADAPTIVE_THREAD_CACHE || ENABLE_STATISTICS + //Decrease counter + size_t idx = span->span_count - 1; + atomic_decr32(&span->heap->span_use[idx].current); +#endif + heap_t* heap = span->heap; + rpmalloc_assert(heap, "No thread heap"); +#if ENABLE_THREAD_CACHE + const int set_as_reserved = ((span->span_count > 1) && (heap->span_cache.count == 0) && !heap->finalize && !heap->spans_reserved); +#else + const int set_as_reserved = ((span->span_count > 1) && !heap->finalize && !heap->spans_reserved); +#endif + if (set_as_reserved) { + heap->span_reserve = span; + heap->spans_reserved = span->span_count; + if (span->flags & SPAN_FLAG_MASTER) { + heap->span_reserve_master = span; + } else { //SPAN_FLAG_SUBSPAN + span_t* master = (span_t*)pointer_offset(span, -(intptr_t)((size_t)span->offset_from_master * _memory_span_size)); + heap->span_reserve_master = master; + rpmalloc_assert(master->flags & SPAN_FLAG_MASTER, "Span flag corrupted"); + rpmalloc_assert(atomic_load32(&master->remaining_spans) >= (int32_t)span->span_count, "Master span count corrupted"); + } + _rpmalloc_stat_inc(&heap->span_use[idx].spans_to_reserved); + } else { + //Insert into cache list + _rpmalloc_heap_cache_insert(heap, span); + } +} + +//! Deallocate the given huge span +static void +_rpmalloc_deallocate_huge(span_t* span) { + rpmalloc_assert(span->heap, "No span heap"); +#if RPMALLOC_FIRST_CLASS_HEAPS + int defer = (span->heap->owner_thread && (span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#else + int defer = ((span->heap->owner_thread != get_thread_id()) && !span->heap->finalize); +#endif + if (defer) { + _rpmalloc_deallocate_defer_free_span(span->heap, span); + return; + } + rpmalloc_assert(span->heap->full_span_count, "Heap span counter corrupted"); + --span->heap->full_span_count; +#if RPMALLOC_FIRST_CLASS_HEAPS + _rpmalloc_span_double_link_list_remove(&span->heap->large_huge_span, span); +#endif + + //Oversized allocation, page count is stored in span_count + size_t num_pages = span->span_count; + _rpmalloc_unmap(span, num_pages * _memory_page_size, span->align_offset, num_pages * _memory_page_size); + _rpmalloc_stat_sub(&_huge_pages_current, num_pages); +} + +//! Deallocate the given block +static void +_rpmalloc_deallocate(void* p) { + _rpmalloc_stat_add64(&_deallocation_counter, 1); + //Grab the span (always at start of span, using span alignment) + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (UNEXPECTED(!span)) + return; + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) + _rpmalloc_deallocate_small_or_medium(span, p); + else if (span->size_class == SIZE_CLASS_LARGE) + _rpmalloc_deallocate_large(span); + else + _rpmalloc_deallocate_huge(span); +} + +//////////// +/// +/// Reallocation entry points +/// +////// + +static size_t +_rpmalloc_usable_size(void* p); + +//! Reallocate the given block to the given size +static void* +_rpmalloc_reallocate(heap_t* heap, void* p, size_t size, size_t oldsize, unsigned int flags) { + if (p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (EXPECTED(span->size_class < SIZE_CLASS_COUNT)) { + //Small/medium sized block + rpmalloc_assert(span->span_count == 1, "Span counter corrupted"); + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + uint32_t block_offset = (uint32_t)pointer_diff(p, blocks_start); + uint32_t block_idx = block_offset / span->block_size; + void* block = pointer_offset(blocks_start, (size_t)block_idx * span->block_size); + if (!oldsize) + oldsize = (size_t)((ptrdiff_t)span->block_size - pointer_diff(p, block)); + if ((size_t)span->block_size >= size) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_spans = total_size >> _memory_span_size_shift; + if (total_size & (_memory_span_mask - 1)) + ++num_spans; + size_t current_spans = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_spans * _memory_span_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_spans >= num_spans) && (total_size >= (oldsize / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } else { + //Oversized block + size_t total_size = size + SPAN_HEADER_SIZE; + size_t num_pages = total_size >> _memory_page_size_shift; + if (total_size & (_memory_page_size - 1)) + ++num_pages; + //Page count is stored in span_count + size_t current_pages = span->span_count; + void* block = pointer_offset(span, SPAN_HEADER_SIZE); + if (!oldsize) + oldsize = (current_pages * _memory_page_size) - (size_t)pointer_diff(p, block) - SPAN_HEADER_SIZE; + if ((current_pages >= num_pages) && (num_pages >= (current_pages / 2))) { + //Still fits in block, never mind trying to save memory, but preserve data if alignment changed + if ((p != block) && !(flags & RPMALLOC_NO_PRESERVE)) + memmove(block, p, oldsize); + return block; + } + } + } else { + oldsize = 0; + } + + if (!!(flags & RPMALLOC_GROW_OR_FAIL)) + return 0; + + //Size is greater than block size, need to allocate a new block and deallocate the old + //Avoid hysteresis by overallocating if increase is small (below 37%) + size_t lower_bound = oldsize + (oldsize >> 2) + (oldsize >> 3); + size_t new_size = (size > lower_bound) ? size : ((size > oldsize) ? lower_bound : size); + void* block = _rpmalloc_allocate(heap, new_size); + if (p && block) { + if (!(flags & RPMALLOC_NO_PRESERVE)) + memcpy(block, p, oldsize < new_size ? oldsize : new_size); + _rpmalloc_deallocate(p); + } + + return block; +} + +static void* +_rpmalloc_aligned_reallocate(heap_t* heap, void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { + if (alignment <= SMALL_GRANULARITY) + return _rpmalloc_reallocate(heap, ptr, size, oldsize, flags); + + int no_alloc = !!(flags & RPMALLOC_GROW_OR_FAIL); + size_t usablesize = (ptr ? _rpmalloc_usable_size(ptr) : 0); + if ((usablesize >= size) && !((uintptr_t)ptr & (alignment - 1))) { + if (no_alloc || (size >= (usablesize / 2))) + return ptr; + } + // Aligned alloc marks span as having aligned blocks + void* block = (!no_alloc ? _rpmalloc_aligned_allocate(heap, alignment, size) : 0); + if (EXPECTED(block != 0)) { + if (!(flags & RPMALLOC_NO_PRESERVE) && ptr) { + if (!oldsize) + oldsize = usablesize; + memcpy(block, ptr, oldsize < size ? oldsize : size); + } + _rpmalloc_deallocate(ptr); + } + return block; +} + + +//////////// +/// +/// Initialization, finalization and utility +/// +////// + +//! Get the usable size of the given block +static size_t +_rpmalloc_usable_size(void* p) { + //Grab the span using guaranteed span alignment + span_t* span = (span_t*)((uintptr_t)p & _memory_span_mask); + if (span->size_class < SIZE_CLASS_COUNT) { + //Small/medium block + void* blocks_start = pointer_offset(span, SPAN_HEADER_SIZE); + return span->block_size - ((size_t)pointer_diff(p, blocks_start) % span->block_size); + } + if (span->size_class == SIZE_CLASS_LARGE) { + //Large block + size_t current_spans = span->span_count; + return (current_spans * _memory_span_size) - (size_t)pointer_diff(p, span); + } + //Oversized block, page count is stored in span_count + size_t current_pages = span->span_count; + return (current_pages * _memory_page_size) - (size_t)pointer_diff(p, span); +} + +//! Adjust and optimize the size class properties for the given class +static void +_rpmalloc_adjust_size_class(size_t iclass) { + size_t block_size = _memory_size_class[iclass].block_size; + size_t block_count = (_memory_span_size - SPAN_HEADER_SIZE) / block_size; + + _memory_size_class[iclass].block_count = (uint16_t)block_count; + _memory_size_class[iclass].class_idx = (uint16_t)iclass; + + //Check if previous size classes can be merged + if (iclass >= SMALL_CLASS_COUNT) { + size_t prevclass = iclass; + while (prevclass > 0) { + --prevclass; + //A class can be merged if number of pages and number of blocks are equal + if (_memory_size_class[prevclass].block_count == _memory_size_class[iclass].block_count) + _rpmalloc_memcpy_const(_memory_size_class + prevclass, _memory_size_class + iclass, sizeof(_memory_size_class[iclass])); + else + break; + } + } +} + +//! Initialize the allocator and setup global data +extern inline int +rpmalloc_initialize(void) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + return rpmalloc_initialize_config(0); +} + +int +rpmalloc_initialize_config(const rpmalloc_config_t* config) { + if (_rpmalloc_initialized) { + rpmalloc_thread_initialize(); + return 0; + } + _rpmalloc_initialized = 1; + + if (config) + memcpy(&_memory_config, config, sizeof(rpmalloc_config_t)); + else + _rpmalloc_memset_const(&_memory_config, 0, sizeof(rpmalloc_config_t)); + + if (!_memory_config.memory_map || !_memory_config.memory_unmap) { + _memory_config.memory_map = _rpmalloc_mmap_os; + _memory_config.memory_unmap = _rpmalloc_unmap_os; + } + +#if PLATFORM_WINDOWS + SYSTEM_INFO system_info; + memset(&system_info, 0, sizeof(system_info)); + GetSystemInfo(&system_info); + _memory_map_granularity = system_info.dwAllocationGranularity; +#else + _memory_map_granularity = (size_t)sysconf(_SC_PAGESIZE); +#endif + +#if RPMALLOC_CONFIGURABLE + _memory_page_size = _memory_config.page_size; +#else + _memory_page_size = 0; +#endif + _memory_huge_pages = 0; + if (!_memory_page_size) { +#if PLATFORM_WINDOWS + _memory_page_size = system_info.dwPageSize; +#else + _memory_page_size = _memory_map_granularity; + if (_memory_config.enable_huge_pages) { +#if defined(__linux__) + size_t huge_page_size = 0; + FILE* meminfo = fopen("/proc/meminfo", "r"); + if (meminfo) { + char line[128]; + while (!huge_page_size && fgets(line, sizeof(line) - 1, meminfo)) { + line[sizeof(line) - 1] = 0; + if (strstr(line, "Hugepagesize:")) + huge_page_size = (size_t)strtol(line + 13, 0, 10) * 1024; + } + fclose(meminfo); + } + if (huge_page_size) { + _memory_huge_pages = 1; + _memory_page_size = huge_page_size; + _memory_map_granularity = huge_page_size; + } +#elif defined(__FreeBSD__) + int rc; + size_t sz = sizeof(rc); + + if (sysctlbyname("vm.pmap.pg_ps_enabled", &rc, &sz, NULL, 0) == 0 && rc == 1) { + static size_t defsize = 2 * 1024 * 1024; + int nsize = 0; + size_t sizes[4] = {0}; + _memory_huge_pages = 1; + _memory_page_size = defsize; + if ((nsize = getpagesizes(sizes, 4)) >= 2) { + nsize --; + for (size_t csize = sizes[nsize]; nsize >= 0 && csize; --nsize, csize = sizes[nsize]) { + //! Unlikely, but as a precaution.. + rpmalloc_assert(!(csize & (csize -1)) && !(csize % 1024), "Invalid page size"); + if (defsize < csize) { + _memory_page_size = csize; + break; + } + } + } + _memory_map_granularity = _memory_page_size; + } +#elif defined(__APPLE__) || defined(__NetBSD__) + _memory_huge_pages = 1; + _memory_page_size = 2 * 1024 * 1024; + _memory_map_granularity = _memory_page_size; +#endif + } +#endif + } else { + if (_memory_config.enable_huge_pages) + _memory_huge_pages = 1; + } + +#if PLATFORM_WINDOWS + if (_memory_config.enable_huge_pages) { + HANDLE token = 0; + size_t large_page_minimum = GetLargePageMinimum(); + if (large_page_minimum) + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token); + if (token) { + LUID luid; + if (LookupPrivilegeValue(0, SE_LOCK_MEMORY_NAME, &luid)) { + TOKEN_PRIVILEGES token_privileges; + memset(&token_privileges, 0, sizeof(token_privileges)); + token_privileges.PrivilegeCount = 1; + token_privileges.Privileges[0].Luid = luid; + token_privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (AdjustTokenPrivileges(token, FALSE, &token_privileges, 0, 0, 0)) { + if (GetLastError() == ERROR_SUCCESS) + _memory_huge_pages = 1; + } + } + CloseHandle(token); + } + if (_memory_huge_pages) { + if (large_page_minimum > _memory_page_size) + _memory_page_size = large_page_minimum; + if (large_page_minimum > _memory_map_granularity) + _memory_map_granularity = large_page_minimum; + } + } +#endif + + size_t min_span_size = 256; + size_t max_page_size; +#if UINTPTR_MAX > 0xFFFFFFFF + max_page_size = 4096ULL * 1024ULL * 1024ULL; +#else + max_page_size = 4 * 1024 * 1024; +#endif + if (_memory_page_size < min_span_size) + _memory_page_size = min_span_size; + if (_memory_page_size > max_page_size) + _memory_page_size = max_page_size; + _memory_page_size_shift = 0; + size_t page_size_bit = _memory_page_size; + while (page_size_bit != 1) { + ++_memory_page_size_shift; + page_size_bit >>= 1; + } + _memory_page_size = ((size_t)1 << _memory_page_size_shift); + +#if RPMALLOC_CONFIGURABLE + if (!_memory_config.span_size) { + _memory_span_size = _memory_default_span_size; + _memory_span_size_shift = _memory_default_span_size_shift; + _memory_span_mask = _memory_default_span_mask; + } else { + size_t span_size = _memory_config.span_size; + if (span_size > (256 * 1024)) + span_size = (256 * 1024); + _memory_span_size = 4096; + _memory_span_size_shift = 12; + while (_memory_span_size < span_size) { + _memory_span_size <<= 1; + ++_memory_span_size_shift; + } + _memory_span_mask = ~(uintptr_t)(_memory_span_size - 1); + } +#endif + + _memory_span_map_count = ( _memory_config.span_map_count ? _memory_config.span_map_count : DEFAULT_SPAN_MAP_COUNT); + if ((_memory_span_size * _memory_span_map_count) < _memory_page_size) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + if ((_memory_page_size >= _memory_span_size) && ((_memory_span_map_count * _memory_span_size) % _memory_page_size)) + _memory_span_map_count = (_memory_page_size / _memory_span_size); + _memory_heap_reserve_count = (_memory_span_map_count > DEFAULT_SPAN_MAP_COUNT) ? DEFAULT_SPAN_MAP_COUNT : _memory_span_map_count; + + _memory_config.page_size = _memory_page_size; + _memory_config.span_size = _memory_span_size; + _memory_config.span_map_count = _memory_span_map_count; + _memory_config.enable_huge_pages = _memory_huge_pages; + +#if ((defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD) || defined(__TINYC__) + if (pthread_key_create(&_memory_thread_heap, _rpmalloc_heap_release_raw_fc)) + return -1; +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + fls_key = FlsAlloc(&_rpmalloc_thread_destructor); +#endif + + //Setup all small and medium size classes + size_t iclass = 0; + _memory_size_class[iclass].block_size = SMALL_GRANULARITY; + _rpmalloc_adjust_size_class(iclass); + for (iclass = 1; iclass < SMALL_CLASS_COUNT; ++iclass) { + size_t size = iclass * SMALL_GRANULARITY; + _memory_size_class[iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(iclass); + } + //At least two blocks per span, then fall back to large allocations + _memory_medium_size_limit = (_memory_span_size - SPAN_HEADER_SIZE) >> 1; + if (_memory_medium_size_limit > MEDIUM_SIZE_LIMIT) + _memory_medium_size_limit = MEDIUM_SIZE_LIMIT; + for (iclass = 0; iclass < MEDIUM_CLASS_COUNT; ++iclass) { + size_t size = SMALL_SIZE_LIMIT + ((iclass + 1) * MEDIUM_GRANULARITY); + if (size > _memory_medium_size_limit) { + _memory_medium_size_limit = SMALL_SIZE_LIMIT + (iclass * MEDIUM_GRANULARITY); + break; + } + _memory_size_class[SMALL_CLASS_COUNT + iclass].block_size = (uint32_t)size; + _rpmalloc_adjust_size_class(SMALL_CLASS_COUNT + iclass); + } + + _memory_orphan_heaps = 0; +#if RPMALLOC_FIRST_CLASS_HEAPS + _memory_first_class_orphan_heaps = 0; +#endif +#if ENABLE_STATISTICS + atomic_store32(&_memory_active_heaps, 0); + atomic_store32(&_mapped_pages, 0); + _mapped_pages_peak = 0; + atomic_store32(&_master_spans, 0); + atomic_store32(&_mapped_total, 0); + atomic_store32(&_unmapped_total, 0); + atomic_store32(&_mapped_pages_os, 0); + atomic_store32(&_huge_pages_current, 0); + _huge_pages_peak = 0; +#endif + memset(_memory_heaps, 0, sizeof(_memory_heaps)); + atomic_store32_release(&_memory_global_lock, 0); + + rpmalloc_linker_reference(); + + //Initialize this thread + rpmalloc_thread_initialize(); + return 0; +} + +//! Finalize the allocator +void +rpmalloc_finalize(void) { + rpmalloc_thread_finalize(1); + //rpmalloc_dump_statistics(stdout); + + if (_memory_global_reserve) { + atomic_add32(&_memory_global_reserve_master->remaining_spans, -(int32_t)_memory_global_reserve_count); + _memory_global_reserve_master = 0; + _memory_global_reserve_count = 0; + _memory_global_reserve = 0; + } + atomic_store32_release(&_memory_global_lock, 0); + + //Free all thread caches and fully free spans + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + heap_t* next_heap = heap->next_heap; + heap->finalize = 1; + _rpmalloc_heap_global_finalize(heap); + heap = next_heap; + } + } + +#if ENABLE_GLOBAL_CACHE + //Free global caches + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) + _rpmalloc_global_cache_finalize(&_memory_span_cache[iclass]); +#endif + +#if (defined(__APPLE__) || defined(__HAIKU__)) && ENABLE_PRELOAD + pthread_key_delete(_memory_thread_heap); +#endif +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsFree(fls_key); + fls_key = 0; +#endif +#if ENABLE_STATISTICS + //If you hit these asserts you probably have memory leaks (perhaps global scope data doing dynamic allocations) or double frees in your code + rpmalloc_assert(atomic_load32(&_mapped_pages) == 0, "Memory leak detected"); + rpmalloc_assert(atomic_load32(&_mapped_pages_os) == 0, "Memory leak detected"); +#endif + + _rpmalloc_initialized = 0; +} + +//! Initialize thread, assign heap +extern inline void +rpmalloc_thread_initialize(void) { + if (!get_thread_heap_raw()) { + heap_t* heap = _rpmalloc_heap_allocate(0); + if (heap) { + _rpmalloc_stat_inc(&_memory_active_heaps); + set_thread_heap(heap); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, heap); +#endif + } + } +} + +//! Finalize thread, orphan heap +void +rpmalloc_thread_finalize(int release_caches) { + heap_t* heap = get_thread_heap_raw(); + if (heap) + _rpmalloc_heap_release_raw(heap, release_caches); + set_thread_heap(0); +#if defined(_WIN32) && (!defined(BUILD_DYNAMIC_LINK) || !BUILD_DYNAMIC_LINK) + FlsSetValue(fls_key, 0); +#endif +} + +int +rpmalloc_is_thread_initialized(void) { + return (get_thread_heap_raw() != 0) ? 1 : 0; +} + +const rpmalloc_config_t* +rpmalloc_config(void) { + return &_memory_config; +} + +// Extern interface + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc(size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_allocate(heap, size); +} + +extern inline void +rpfree(void* ptr) { + _rpmalloc_deallocate(ptr); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpcalloc(size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + heap_t* heap = get_thread_heap(); + void* block = _rpmalloc_allocate(heap, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rprealloc(void* ptr, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_reallocate(heap, ptr, size, 0, 0); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_realloc(void* ptr, size_t alignment, size_t size, size_t oldsize, + unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, oldsize, flags); +} + +extern RPMALLOC_ALLOCATOR void* +rpaligned_alloc(size_t alignment, size_t size) { + heap_t* heap = get_thread_heap(); + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpaligned_calloc(size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = rpaligned_alloc(alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmemalign(size_t alignment, size_t size) { + return rpaligned_alloc(alignment, size); +} + +extern inline int +rpposix_memalign(void **memptr, size_t alignment, size_t size) { + if (memptr) + *memptr = rpaligned_alloc(alignment, size); + else + return EINVAL; + return *memptr ? 0 : ENOMEM; +} + +extern inline size_t +rpmalloc_usable_size(void* ptr) { + return (ptr ? _rpmalloc_usable_size(ptr) : 0); +} + +extern inline void +rpmalloc_thread_collect(void) { +} + +void +rpmalloc_thread_statistics(rpmalloc_thread_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_thread_statistics_t)); + heap_t* heap = get_thread_heap_raw(); + if (!heap) + return; + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + size_class_t* size_class = _memory_size_class + iclass; + span_t* span = heap->size_class[iclass].partial_span; + while (span) { + size_t free_count = span->list_size; + size_t block_count = size_class->block_count; + if (span->free_list_limit < block_count) + block_count = span->free_list_limit; + free_count += (block_count - span->used_count); + stats->sizecache += free_count * size_class->block_size; + span = span->next; + } + } + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + stats->spancache += span_cache->count * (iclass + 1) * _memory_span_size; + } +#endif + + span_t* deferred = (span_t*)atomic_load_ptr(&heap->span_free_deferred); + while (deferred) { + if (deferred->size_class != SIZE_CLASS_HUGE) + stats->spancache += (size_t)deferred->span_count * _memory_span_size; + deferred = (span_t*)deferred->free_list; + } + +#if ENABLE_STATISTICS + stats->thread_to_global = (size_t)atomic_load64(&heap->thread_to_global); + stats->global_to_thread = (size_t)atomic_load64(&heap->global_to_thread); + + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + stats->span_use[iclass].current = (size_t)atomic_load32(&heap->span_use[iclass].current); + stats->span_use[iclass].peak = (size_t)atomic_load32(&heap->span_use[iclass].high); + stats->span_use[iclass].to_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_global); + stats->span_use[iclass].from_global = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_global); + stats->span_use[iclass].to_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache); + stats->span_use[iclass].from_cache = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache); + stats->span_use[iclass].to_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved); + stats->span_use[iclass].from_reserved = (size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved); + stats->span_use[iclass].map_calls = (size_t)atomic_load32(&heap->span_use[iclass].spans_map_calls); + } + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + stats->size_use[iclass].alloc_current = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_current); + stats->size_use[iclass].alloc_peak = (size_t)heap->size_class_use[iclass].alloc_peak; + stats->size_use[iclass].alloc_total = (size_t)atomic_load32(&heap->size_class_use[iclass].alloc_total); + stats->size_use[iclass].free_total = (size_t)atomic_load32(&heap->size_class_use[iclass].free_total); + stats->size_use[iclass].spans_to_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache); + stats->size_use[iclass].spans_from_cache = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache); + stats->size_use[iclass].spans_from_reserved = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved); + stats->size_use[iclass].map_calls = (size_t)atomic_load32(&heap->size_class_use[iclass].spans_map_calls); + } +#endif +} + +void +rpmalloc_global_statistics(rpmalloc_global_statistics_t* stats) { + memset(stats, 0, sizeof(rpmalloc_global_statistics_t)); +#if ENABLE_STATISTICS + stats->mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + stats->mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + stats->mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + stats->unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + stats->huge_alloc = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + stats->huge_alloc_peak = (size_t)_huge_pages_peak * _memory_page_size; +#endif +#if ENABLE_GLOBAL_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = &_memory_span_cache[iclass]; + while (!atomic_cas32_acquire(&cache->lock, 1, 0)) + _rpmalloc_spin(); + uint32_t count = cache->count; +#if ENABLE_UNLIMITED_CACHE + span_t* current_span = cache->overflow; + while (current_span) { + ++count; + current_span = current_span->next; + } +#endif + atomic_store32_release(&cache->lock, 0); + stats->cached += count * (iclass + 1) * _memory_span_size; + } +#endif +} + +#if ENABLE_STATISTICS + +static void +_memory_heap_dump_statistics(heap_t* heap, void* file) { + fprintf(file, "Heap %d stats:\n", heap->id); + fprintf(file, "Class CurAlloc PeakAlloc TotAlloc TotFree BlkSize BlkCount SpansCur SpansPeak PeakAllocMiB ToCacheMiB FromCacheMiB FromReserveMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) + continue; + fprintf(file, "%3u: %10u %10u %10u %10u %8u %8u %8d %9d %13zu %11zu %12zu %14zu %9u\n", (uint32_t)iclass, + atomic_load32(&heap->size_class_use[iclass].alloc_current), + heap->size_class_use[iclass].alloc_peak, + atomic_load32(&heap->size_class_use[iclass].alloc_total), + atomic_load32(&heap->size_class_use[iclass].free_total), + _memory_size_class[iclass].block_size, + _memory_size_class[iclass].block_count, + atomic_load32(&heap->size_class_use[iclass].spans_current), + heap->size_class_use[iclass].spans_peak, + ((size_t)heap->size_class_use[iclass].alloc_peak * (size_t)_memory_size_class[iclass].block_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_to_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_cache) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->size_class_use[iclass].spans_from_reserved) * _memory_span_size) / (size_t)(1024 * 1024), + atomic_load32(&heap->size_class_use[iclass].spans_map_calls)); + } + fprintf(file, "Spans Current Peak Deferred PeakMiB Cached ToCacheMiB FromCacheMiB ToReserveMiB FromReserveMiB ToGlobalMiB FromGlobalMiB MmapCalls\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + fprintf(file, "%4u: %8d %8u %8u %8zu %7u %11zu %12zu %12zu %14zu %11zu %13zu %10u\n", (uint32_t)(iclass + 1), + atomic_load32(&heap->span_use[iclass].current), + atomic_load32(&heap->span_use[iclass].high), + atomic_load32(&heap->span_use[iclass].spans_deferred), + ((size_t)atomic_load32(&heap->span_use[iclass].high) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), +#if ENABLE_THREAD_CACHE + (unsigned int)(!iclass ? heap->span_cache.count : heap->span_large_cache[iclass - 1].count), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_cache) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), +#else + 0, (size_t)0, (size_t)0, +#endif + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_reserved) * (iclass + 1) * _memory_span_size) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_to_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + ((size_t)atomic_load32(&heap->span_use[iclass].spans_from_global) * (size_t)_memory_span_size * (iclass + 1)) / (size_t)(1024 * 1024), + atomic_load32(&heap->span_use[iclass].spans_map_calls)); + } + fprintf(file, "Full spans: %zu\n", heap->full_span_count); + fprintf(file, "ThreadToGlobalMiB GlobalToThreadMiB\n"); + fprintf(file, "%17zu %17zu\n", (size_t)atomic_load64(&heap->thread_to_global) / (size_t)(1024 * 1024), (size_t)atomic_load64(&heap->global_to_thread) / (size_t)(1024 * 1024)); +} + +#endif + +void +rpmalloc_dump_statistics(void* file) { +#if ENABLE_STATISTICS + for (size_t list_idx = 0; list_idx < HEAP_ARRAY_SIZE; ++list_idx) { + heap_t* heap = _memory_heaps[list_idx]; + while (heap) { + int need_dump = 0; + for (size_t iclass = 0; !need_dump && (iclass < SIZE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->size_class_use[iclass].alloc_total)) { + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].free_total), "Heap statistics counter mismatch"); + rpmalloc_assert(!atomic_load32(&heap->size_class_use[iclass].spans_map_calls), "Heap statistics counter mismatch"); + continue; + } + need_dump = 1; + } + for (size_t iclass = 0; !need_dump && (iclass < LARGE_CLASS_COUNT); ++iclass) { + if (!atomic_load32(&heap->span_use[iclass].high) && !atomic_load32(&heap->span_use[iclass].spans_map_calls)) + continue; + need_dump = 1; + } + if (need_dump) + _memory_heap_dump_statistics(heap, file); + heap = heap->next_heap; + } + } + fprintf(file, "Global stats:\n"); + size_t huge_current = (size_t)atomic_load32(&_huge_pages_current) * _memory_page_size; + size_t huge_peak = (size_t)_huge_pages_peak * _memory_page_size; + fprintf(file, "HugeCurrentMiB HugePeakMiB\n"); + fprintf(file, "%14zu %11zu\n", huge_current / (size_t)(1024 * 1024), huge_peak / (size_t)(1024 * 1024)); + +#if ENABLE_GLOBAL_CACHE + fprintf(file, "GlobalCacheMiB\n"); + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + global_cache_t* cache = _memory_span_cache + iclass; + size_t global_cache = (size_t)cache->count * iclass * _memory_span_size; + + size_t global_overflow_cache = 0; + span_t* span = cache->overflow; + while (span) { + global_overflow_cache += iclass * _memory_span_size; + span = span->next; + } + if (global_cache || global_overflow_cache || cache->insert_count || cache->extract_count) + fprintf(file, "%4zu: %8zuMiB (%8zuMiB overflow) %14zu insert %14zu extract\n", iclass + 1, global_cache / (size_t)(1024 * 1024), global_overflow_cache / (size_t)(1024 * 1024), cache->insert_count, cache->extract_count); + } +#endif + + size_t mapped = (size_t)atomic_load32(&_mapped_pages) * _memory_page_size; + size_t mapped_os = (size_t)atomic_load32(&_mapped_pages_os) * _memory_page_size; + size_t mapped_peak = (size_t)_mapped_pages_peak * _memory_page_size; + size_t mapped_total = (size_t)atomic_load32(&_mapped_total) * _memory_page_size; + size_t unmapped_total = (size_t)atomic_load32(&_unmapped_total) * _memory_page_size; + fprintf(file, "MappedMiB MappedOSMiB MappedPeakMiB MappedTotalMiB UnmappedTotalMiB\n"); + fprintf(file, "%9zu %11zu %13zu %14zu %16zu\n", + mapped / (size_t)(1024 * 1024), + mapped_os / (size_t)(1024 * 1024), + mapped_peak / (size_t)(1024 * 1024), + mapped_total / (size_t)(1024 * 1024), + unmapped_total / (size_t)(1024 * 1024)); + + fprintf(file, "\n"); +#if 0 + int64_t allocated = atomic_load64(&_allocation_counter); + int64_t deallocated = atomic_load64(&_deallocation_counter); + fprintf(file, "Allocation count: %lli\n", allocated); + fprintf(file, "Deallocation count: %lli\n", deallocated); + fprintf(file, "Current allocations: %lli\n", (allocated - deallocated)); + fprintf(file, "Master spans: %d\n", atomic_load32(&_master_spans)); + fprintf(file, "Dangling master spans: %d\n", atomic_load32(&_unmapped_master_spans)); +#endif +#endif + (void)sizeof(file); +} + +#if RPMALLOC_FIRST_CLASS_HEAPS + +extern inline rpmalloc_heap_t* +rpmalloc_heap_acquire(void) { + // Must be a pristine heap from newly mapped memory pages, or else memory blocks + // could already be allocated from the heap which would (wrongly) be released when + // heap is cleared with rpmalloc_heap_free_all(). Also heaps guaranteed to be + // pristine from the dedicated orphan list can be used. + heap_t* heap = _rpmalloc_heap_allocate(1); + rpmalloc_assume(heap != NULL); + heap->owner_thread = 0; + _rpmalloc_stat_inc(&_memory_active_heaps); + return heap; +} + +extern inline void +rpmalloc_heap_release(rpmalloc_heap_t* heap) { + if (heap) + _rpmalloc_heap_release(heap, 1, 1); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_alloc(rpmalloc_heap_t* heap, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_allocate(heap, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_alloc(rpmalloc_heap_t* heap, size_t alignment, size_t size) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_allocate(heap, alignment, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_calloc(rpmalloc_heap_t* heap, size_t num, size_t size) { + return rpmalloc_heap_aligned_calloc(heap, 0, num, size); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_calloc(rpmalloc_heap_t* heap, size_t alignment, size_t num, size_t size) { + size_t total; +#if ENABLE_VALIDATE_ARGS +#if PLATFORM_WINDOWS + int err = SizeTMult(num, size, &total); + if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#else + int err = __builtin_umull_overflow(num, size, &total); + if (err || (total >= MAX_ALLOC_SIZE)) { + errno = EINVAL; + return 0; + } +#endif +#else + total = num * size; +#endif + void* block = _rpmalloc_aligned_allocate(heap, alignment, total); + if (block) + memset(block, 0, total); + return block; +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_realloc(rpmalloc_heap_t* heap, void* ptr, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if (size >= MAX_ALLOC_SIZE) { + errno = EINVAL; + return ptr; + } +#endif + return _rpmalloc_reallocate(heap, ptr, size, 0, flags); +} + +extern inline RPMALLOC_ALLOCATOR void* +rpmalloc_heap_aligned_realloc(rpmalloc_heap_t* heap, void* ptr, size_t alignment, size_t size, unsigned int flags) { +#if ENABLE_VALIDATE_ARGS + if ((size + alignment < size) || (alignment > _memory_page_size)) { + errno = EINVAL; + return 0; + } +#endif + return _rpmalloc_aligned_reallocate(heap, ptr, alignment, size, 0, flags); +} + +extern inline void +rpmalloc_heap_free(rpmalloc_heap_t* heap, void* ptr) { + (void)sizeof(heap); + _rpmalloc_deallocate(ptr); +} + +extern inline void +rpmalloc_heap_free_all(rpmalloc_heap_t* heap) { + span_t* span; + span_t* next_span; + + _rpmalloc_heap_cache_adopt_deferred(heap, 0); + + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + span = heap->size_class[iclass].partial_span; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->size_class[iclass].partial_span = 0; + span = heap->full_span[iclass]; + while (span) { + next_span = span->next; + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + } + memset(heap->size_class, 0, sizeof(heap->size_class)); + memset(heap->full_span, 0, sizeof(heap->full_span)); + + span = heap->large_huge_span; + while (span) { + next_span = span->next; + if (UNEXPECTED(span->size_class == SIZE_CLASS_HUGE)) + _rpmalloc_deallocate_huge(span); + else + _rpmalloc_heap_cache_insert(heap, span); + span = next_span; + } + heap->large_huge_span = 0; + heap->full_span_count = 0; + +#if ENABLE_THREAD_CACHE + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + span_cache_t* span_cache; + if (!iclass) + span_cache = &heap->span_cache; + else + span_cache = (span_cache_t*)(heap->span_large_cache + (iclass - 1)); + if (!span_cache->count) + continue; +#if ENABLE_GLOBAL_CACHE + _rpmalloc_stat_add64(&heap->thread_to_global, span_cache->count * (iclass + 1) * _memory_span_size); + _rpmalloc_stat_add(&heap->span_use[iclass].spans_to_global, span_cache->count); + _rpmalloc_global_cache_insert_spans(span_cache->span, iclass + 1, span_cache->count); +#else + for (size_t ispan = 0; ispan < span_cache->count; ++ispan) + _rpmalloc_span_unmap(span_cache->span[ispan]); +#endif + span_cache->count = 0; + } +#endif + +#if ENABLE_STATISTICS + for (size_t iclass = 0; iclass < SIZE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->size_class_use[iclass].alloc_current, 0); + atomic_store32(&heap->size_class_use[iclass].spans_current, 0); + } + for (size_t iclass = 0; iclass < LARGE_CLASS_COUNT; ++iclass) { + atomic_store32(&heap->span_use[iclass].current, 0); + } +#endif +} + +extern inline void +rpmalloc_heap_thread_set_current(rpmalloc_heap_t* heap) { + heap_t* prev_heap = get_thread_heap_raw(); + if (prev_heap != heap) { + set_thread_heap(heap); + if (prev_heap) + rpmalloc_heap_release(prev_heap); + } +} + +extern inline rpmalloc_heap_t* +rpmalloc_get_heap_for_ptr(void* ptr) +{ + //Grab the span, and then the heap from the span + span_t* span = (span_t*)((uintptr_t)ptr & _memory_span_mask); + if (span) + { + return span->heap; + } + return 0; +} + +#endif + +#if ENABLE_PRELOAD || ENABLE_OVERRIDE + +#include "malloc.c" + +#endif + +void +rpmalloc_linker_reference(void) { + (void)sizeof(_rpmalloc_initialized); +} +#line 0 +//{{FILE: 3rd_rpmalloci.c}} +#define SYS_MEM_INIT() rpmalloc_initialize() +#define SYS_MEM_REALLOC rprealloc +#define SYS_MEM_SIZE rpmalloc_usable_size +#endif + //#define SQLITE_OMIT_LOAD_EXTENSION //#define SQLITE_CORE 1 //#define SQLITE_DEBUG 1 @@ -315518,4 +319799,9242 @@ array(char) base64_decode(const char *inp, unsigned inlen) { // array_free() aft //#undef rehash //#undef NB //#undef threadid + +// editor +#line 1 "3rd_icon_mdi.h" +// Generated by https://github.com/juliettef/IconFontCppHeaders script GenerateIconFontCppHeaders.py for languages C and C++ +// from https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/css/materialdesignicons.css +// for use with https://github.com/Templarian/MaterialDesign-Webfont/raw/master/fonts/materialdesignicons-webfont.ttf +#pragma once + +#define FONT_ICON_FILE_NAME_MDI "materialdesignicons-webfont.ttf" + +#define ICON_MIN_MDI 0xF68C +#define ICON_MAX_16_MDI 0xF68C +#define ICON_MAX_MDI 0xF1CC7 +#define ICON_MDI_AB_TESTING "\xf3\xb0\x87\x89" // U+F01C9 +#define ICON_MDI_ABACUS "\xf3\xb1\x9b\xa0" // U+F16E0 +#define ICON_MDI_ABJAD_ARABIC "\xf3\xb1\x8c\xa8" // U+F1328 +#define ICON_MDI_ABJAD_HEBREW "\xf3\xb1\x8c\xa9" // U+F1329 +#define ICON_MDI_ABUGIDA_DEVANAGARI "\xf3\xb1\x8c\xaa" // U+F132A +#define ICON_MDI_ABUGIDA_THAI "\xf3\xb1\x8c\xab" // U+F132B +#define ICON_MDI_ACCESS_POINT "\xf3\xb0\x80\x83" // U+F0003 +#define ICON_MDI_ACCESS_POINT_CHECK "\xf3\xb1\x94\xb8" // U+F1538 +#define ICON_MDI_ACCESS_POINT_MINUS "\xf3\xb1\x94\xb9" // U+F1539 +#define ICON_MDI_ACCESS_POINT_NETWORK "\xf3\xb0\x80\x82" // U+F0002 +#define ICON_MDI_ACCESS_POINT_NETWORK_OFF "\xf3\xb0\xaf\xa1" // U+F0BE1 +#define ICON_MDI_ACCESS_POINT_OFF "\xf3\xb1\x94\x91" // U+F1511 +#define ICON_MDI_ACCESS_POINT_PLUS "\xf3\xb1\x94\xba" // U+F153A +#define ICON_MDI_ACCESS_POINT_REMOVE "\xf3\xb1\x94\xbb" // U+F153B +#define ICON_MDI_ACCOUNT "\xf3\xb0\x80\x84" // U+F0004 +#define ICON_MDI_ACCOUNT_ALERT "\xf3\xb0\x80\x85" // U+F0005 +#define ICON_MDI_ACCOUNT_ALERT_OUTLINE "\xf3\xb0\xad\x90" // U+F0B50 +#define ICON_MDI_ACCOUNT_ARROW_DOWN "\xf3\xb1\xa1\xa8" // U+F1868 +#define ICON_MDI_ACCOUNT_ARROW_DOWN_OUTLINE "\xf3\xb1\xa1\xa9" // U+F1869 +#define ICON_MDI_ACCOUNT_ARROW_LEFT "\xf3\xb0\xad\x91" // U+F0B51 +#define ICON_MDI_ACCOUNT_ARROW_LEFT_OUTLINE "\xf3\xb0\xad\x92" // U+F0B52 +#define ICON_MDI_ACCOUNT_ARROW_RIGHT "\xf3\xb0\xad\x93" // U+F0B53 +#define ICON_MDI_ACCOUNT_ARROW_RIGHT_OUTLINE "\xf3\xb0\xad\x94" // U+F0B54 +#define ICON_MDI_ACCOUNT_ARROW_UP "\xf3\xb1\xa1\xa7" // U+F1867 +#define ICON_MDI_ACCOUNT_ARROW_UP_OUTLINE "\xf3\xb1\xa1\xaa" // U+F186A +#define ICON_MDI_ACCOUNT_BADGE "\xf3\xb1\xac\x8a" // U+F1B0A +#define ICON_MDI_ACCOUNT_BADGE_OUTLINE "\xf3\xb1\xac\x8b" // U+F1B0B +#define ICON_MDI_ACCOUNT_BOX "\xf3\xb0\x80\x86" // U+F0006 +#define ICON_MDI_ACCOUNT_BOX_MULTIPLE "\xf3\xb0\xa4\xb4" // U+F0934 +#define ICON_MDI_ACCOUNT_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x80\x8a" // U+F100A +#define ICON_MDI_ACCOUNT_BOX_OUTLINE "\xf3\xb0\x80\x87" // U+F0007 +#define ICON_MDI_ACCOUNT_CANCEL "\xf3\xb1\x8b\x9f" // U+F12DF +#define ICON_MDI_ACCOUNT_CANCEL_OUTLINE "\xf3\xb1\x8b\xa0" // U+F12E0 +#define ICON_MDI_ACCOUNT_CARD "\xf3\xb1\xae\xa4" // U+F1BA4 +#define ICON_MDI_ACCOUNT_CARD_OUTLINE "\xf3\xb1\xae\xa5" // U+F1BA5 +#define ICON_MDI_ACCOUNT_CASH "\xf3\xb1\x82\x97" // U+F1097 +#define ICON_MDI_ACCOUNT_CASH_OUTLINE "\xf3\xb1\x82\x98" // U+F1098 +#define ICON_MDI_ACCOUNT_CHECK "\xf3\xb0\x80\x88" // U+F0008 +#define ICON_MDI_ACCOUNT_CHECK_OUTLINE "\xf3\xb0\xaf\xa2" // U+F0BE2 +#define ICON_MDI_ACCOUNT_CHILD "\xf3\xb0\xaa\x89" // U+F0A89 +#define ICON_MDI_ACCOUNT_CHILD_CIRCLE "\xf3\xb0\xaa\x8a" // U+F0A8A +#define ICON_MDI_ACCOUNT_CHILD_OUTLINE "\xf3\xb1\x83\x88" // U+F10C8 +#define ICON_MDI_ACCOUNT_CIRCLE "\xf3\xb0\x80\x89" // U+F0009 +#define ICON_MDI_ACCOUNT_CIRCLE_OUTLINE "\xf3\xb0\xad\x95" // U+F0B55 +#define ICON_MDI_ACCOUNT_CLOCK "\xf3\xb0\xad\x96" // U+F0B56 +#define ICON_MDI_ACCOUNT_CLOCK_OUTLINE "\xf3\xb0\xad\x97" // U+F0B57 +#define ICON_MDI_ACCOUNT_COG "\xf3\xb1\x8d\xb0" // U+F1370 +#define ICON_MDI_ACCOUNT_COG_OUTLINE "\xf3\xb1\x8d\xb1" // U+F1371 +#define ICON_MDI_ACCOUNT_CONVERT "\xf3\xb0\x80\x8a" // U+F000A +#define ICON_MDI_ACCOUNT_CONVERT_OUTLINE "\xf3\xb1\x8c\x81" // U+F1301 +#define ICON_MDI_ACCOUNT_COWBOY_HAT "\xf3\xb0\xba\x9b" // U+F0E9B +#define ICON_MDI_ACCOUNT_COWBOY_HAT_OUTLINE "\xf3\xb1\x9f\xb3" // U+F17F3 +#define ICON_MDI_ACCOUNT_CREDIT_CARD "\xf3\xb1\xae\xa6" // U+F1BA6 +#define ICON_MDI_ACCOUNT_CREDIT_CARD_OUTLINE "\xf3\xb1\xae\xa7" // U+F1BA7 +#define ICON_MDI_ACCOUNT_DETAILS "\xf3\xb0\x98\xb1" // U+F0631 +#define ICON_MDI_ACCOUNT_DETAILS_OUTLINE "\xf3\xb1\x8d\xb2" // U+F1372 +#define ICON_MDI_ACCOUNT_EDIT "\xf3\xb0\x9a\xbc" // U+F06BC +#define ICON_MDI_ACCOUNT_EDIT_OUTLINE "\xf3\xb0\xbf\xbb" // U+F0FFB +#define ICON_MDI_ACCOUNT_EYE "\xf3\xb0\x90\xa0" // U+F0420 +#define ICON_MDI_ACCOUNT_EYE_OUTLINE "\xf3\xb1\x89\xbb" // U+F127B +#define ICON_MDI_ACCOUNT_FILE "\xf3\xb1\xb2\xa7" // U+F1CA7 +#define ICON_MDI_ACCOUNT_FILE_OUTLINE "\xf3\xb1\xb2\xa8" // U+F1CA8 +#define ICON_MDI_ACCOUNT_FILE_TEXT "\xf3\xb1\xb2\xa9" // U+F1CA9 +#define ICON_MDI_ACCOUNT_FILE_TEXT_OUTLINE "\xf3\xb1\xb2\xaa" // U+F1CAA +#define ICON_MDI_ACCOUNT_FILTER "\xf3\xb0\xa4\xb6" // U+F0936 +#define ICON_MDI_ACCOUNT_FILTER_OUTLINE "\xf3\xb0\xbe\x9d" // U+F0F9D +#define ICON_MDI_ACCOUNT_GROUP "\xf3\xb0\xa1\x89" // U+F0849 +#define ICON_MDI_ACCOUNT_GROUP_OUTLINE "\xf3\xb0\xad\x98" // U+F0B58 +#define ICON_MDI_ACCOUNT_HARD_HAT "\xf3\xb0\x96\xb5" // U+F05B5 +#define ICON_MDI_ACCOUNT_HARD_HAT_OUTLINE "\xf3\xb1\xa8\x9f" // U+F1A1F +#define ICON_MDI_ACCOUNT_HEART "\xf3\xb0\xa2\x99" // U+F0899 +#define ICON_MDI_ACCOUNT_HEART_OUTLINE "\xf3\xb0\xaf\xa3" // U+F0BE3 +#define ICON_MDI_ACCOUNT_INJURY "\xf3\xb1\xa0\x95" // U+F1815 +#define ICON_MDI_ACCOUNT_INJURY_OUTLINE "\xf3\xb1\xa0\x96" // U+F1816 +#define ICON_MDI_ACCOUNT_KEY "\xf3\xb0\x80\x8b" // U+F000B +#define ICON_MDI_ACCOUNT_KEY_OUTLINE "\xf3\xb0\xaf\xa4" // U+F0BE4 +#define ICON_MDI_ACCOUNT_LOCK "\xf3\xb1\x85\x9e" // U+F115E +#define ICON_MDI_ACCOUNT_LOCK_OPEN "\xf3\xb1\xa5\xa0" // U+F1960 +#define ICON_MDI_ACCOUNT_LOCK_OPEN_OUTLINE "\xf3\xb1\xa5\xa1" // U+F1961 +#define ICON_MDI_ACCOUNT_LOCK_OUTLINE "\xf3\xb1\x85\x9f" // U+F115F +#define ICON_MDI_ACCOUNT_MINUS "\xf3\xb0\x80\x8d" // U+F000D +#define ICON_MDI_ACCOUNT_MINUS_OUTLINE "\xf3\xb0\xab\xac" // U+F0AEC +#define ICON_MDI_ACCOUNT_MULTIPLE "\xf3\xb0\x80\x8e" // U+F000E +#define ICON_MDI_ACCOUNT_MULTIPLE_CHECK "\xf3\xb0\xa3\x85" // U+F08C5 +#define ICON_MDI_ACCOUNT_MULTIPLE_CHECK_OUTLINE "\xf3\xb1\x87\xbe" // U+F11FE +#define ICON_MDI_ACCOUNT_MULTIPLE_MINUS "\xf3\xb0\x97\x93" // U+F05D3 +#define ICON_MDI_ACCOUNT_MULTIPLE_MINUS_OUTLINE "\xf3\xb0\xaf\xa5" // U+F0BE5 +#define ICON_MDI_ACCOUNT_MULTIPLE_OUTLINE "\xf3\xb0\x80\x8f" // U+F000F +#define ICON_MDI_ACCOUNT_MULTIPLE_PLUS "\xf3\xb0\x80\x90" // U+F0010 +#define ICON_MDI_ACCOUNT_MULTIPLE_PLUS_OUTLINE "\xf3\xb0\xa0\x80" // U+F0800 +#define ICON_MDI_ACCOUNT_MULTIPLE_REMOVE "\xf3\xb1\x88\x8a" // U+F120A +#define ICON_MDI_ACCOUNT_MULTIPLE_REMOVE_OUTLINE "\xf3\xb1\x88\x8b" // U+F120B +#define ICON_MDI_ACCOUNT_MUSIC "\xf3\xb0\xa0\x83" // U+F0803 +#define ICON_MDI_ACCOUNT_MUSIC_OUTLINE "\xf3\xb0\xb3\xa9" // U+F0CE9 +#define ICON_MDI_ACCOUNT_NETWORK "\xf3\xb0\x80\x91" // U+F0011 +#define ICON_MDI_ACCOUNT_NETWORK_OFF "\xf3\xb1\xab\xb1" // U+F1AF1 +#define ICON_MDI_ACCOUNT_NETWORK_OFF_OUTLINE "\xf3\xb1\xab\xb2" // U+F1AF2 +#define ICON_MDI_ACCOUNT_NETWORK_OUTLINE "\xf3\xb0\xaf\xa6" // U+F0BE6 +#define ICON_MDI_ACCOUNT_OFF "\xf3\xb0\x80\x92" // U+F0012 +#define ICON_MDI_ACCOUNT_OFF_OUTLINE "\xf3\xb0\xaf\xa7" // U+F0BE7 +#define ICON_MDI_ACCOUNT_OUTLINE "\xf3\xb0\x80\x93" // U+F0013 +#define ICON_MDI_ACCOUNT_PLUS "\xf3\xb0\x80\x94" // U+F0014 +#define ICON_MDI_ACCOUNT_PLUS_OUTLINE "\xf3\xb0\xa0\x81" // U+F0801 +#define ICON_MDI_ACCOUNT_QUESTION "\xf3\xb0\xad\x99" // U+F0B59 +#define ICON_MDI_ACCOUNT_QUESTION_OUTLINE "\xf3\xb0\xad\x9a" // U+F0B5A +#define ICON_MDI_ACCOUNT_REACTIVATE "\xf3\xb1\x94\xab" // U+F152B +#define ICON_MDI_ACCOUNT_REACTIVATE_OUTLINE "\xf3\xb1\x94\xac" // U+F152C +#define ICON_MDI_ACCOUNT_REMOVE "\xf3\xb0\x80\x95" // U+F0015 +#define ICON_MDI_ACCOUNT_REMOVE_OUTLINE "\xf3\xb0\xab\xad" // U+F0AED +#define ICON_MDI_ACCOUNT_SCHOOL "\xf3\xb1\xa8\xa0" // U+F1A20 +#define ICON_MDI_ACCOUNT_SCHOOL_OUTLINE "\xf3\xb1\xa8\xa1" // U+F1A21 +#define ICON_MDI_ACCOUNT_SEARCH "\xf3\xb0\x80\x96" // U+F0016 +#define ICON_MDI_ACCOUNT_SEARCH_OUTLINE "\xf3\xb0\xa4\xb5" // U+F0935 +#define ICON_MDI_ACCOUNT_SETTINGS "\xf3\xb0\x98\xb0" // U+F0630 +#define ICON_MDI_ACCOUNT_SETTINGS_OUTLINE "\xf3\xb1\x83\x89" // U+F10C9 +#define ICON_MDI_ACCOUNT_STAR "\xf3\xb0\x80\x97" // U+F0017 +#define ICON_MDI_ACCOUNT_STAR_OUTLINE "\xf3\xb0\xaf\xa8" // U+F0BE8 +#define ICON_MDI_ACCOUNT_SUPERVISOR "\xf3\xb0\xaa\x8b" // U+F0A8B +#define ICON_MDI_ACCOUNT_SUPERVISOR_CIRCLE "\xf3\xb0\xaa\x8c" // U+F0A8C +#define ICON_MDI_ACCOUNT_SUPERVISOR_CIRCLE_OUTLINE "\xf3\xb1\x93\xac" // U+F14EC +#define ICON_MDI_ACCOUNT_SUPERVISOR_OUTLINE "\xf3\xb1\x84\xad" // U+F112D +#define ICON_MDI_ACCOUNT_SWITCH "\xf3\xb0\x80\x99" // U+F0019 +#define ICON_MDI_ACCOUNT_SWITCH_OUTLINE "\xf3\xb0\x93\x8b" // U+F04CB +#define ICON_MDI_ACCOUNT_SYNC "\xf3\xb1\xa4\x9b" // U+F191B +#define ICON_MDI_ACCOUNT_SYNC_OUTLINE "\xf3\xb1\xa4\x9c" // U+F191C +#define ICON_MDI_ACCOUNT_TAG "\xf3\xb1\xb0\x9b" // U+F1C1B +#define ICON_MDI_ACCOUNT_TAG_OUTLINE "\xf3\xb1\xb0\x9c" // U+F1C1C +#define ICON_MDI_ACCOUNT_TIE "\xf3\xb0\xb3\xa3" // U+F0CE3 +#define ICON_MDI_ACCOUNT_TIE_HAT "\xf3\xb1\xa2\x98" // U+F1898 +#define ICON_MDI_ACCOUNT_TIE_HAT_OUTLINE "\xf3\xb1\xa2\x99" // U+F1899 +#define ICON_MDI_ACCOUNT_TIE_OUTLINE "\xf3\xb1\x83\x8a" // U+F10CA +#define ICON_MDI_ACCOUNT_TIE_VOICE "\xf3\xb1\x8c\x88" // U+F1308 +#define ICON_MDI_ACCOUNT_TIE_VOICE_OFF "\xf3\xb1\x8c\x8a" // U+F130A +#define ICON_MDI_ACCOUNT_TIE_VOICE_OFF_OUTLINE "\xf3\xb1\x8c\x8b" // U+F130B +#define ICON_MDI_ACCOUNT_TIE_VOICE_OUTLINE "\xf3\xb1\x8c\x89" // U+F1309 +#define ICON_MDI_ACCOUNT_TIE_WOMAN "\xf3\xb1\xaa\x8c" // U+F1A8C +#define ICON_MDI_ACCOUNT_VOICE "\xf3\xb0\x97\x8b" // U+F05CB +#define ICON_MDI_ACCOUNT_VOICE_OFF "\xf3\xb0\xbb\x94" // U+F0ED4 +#define ICON_MDI_ACCOUNT_WRENCH "\xf3\xb1\xa2\x9a" // U+F189A +#define ICON_MDI_ACCOUNT_WRENCH_OUTLINE "\xf3\xb1\xa2\x9b" // U+F189B +#define ICON_MDI_ADJUST "\xf3\xb0\x80\x9a" // U+F001A +#define ICON_MDI_ADVERTISEMENTS "\xf3\xb1\xa4\xaa" // U+F192A +#define ICON_MDI_ADVERTISEMENTS_OFF "\xf3\xb1\xa4\xab" // U+F192B +#define ICON_MDI_AIR_CONDITIONER "\xf3\xb0\x80\x9b" // U+F001B +#define ICON_MDI_AIR_FILTER "\xf3\xb0\xb5\x83" // U+F0D43 +#define ICON_MDI_AIR_HORN "\xf3\xb0\xb6\xac" // U+F0DAC +#define ICON_MDI_AIR_HUMIDIFIER "\xf3\xb1\x82\x99" // U+F1099 +#define ICON_MDI_AIR_HUMIDIFIER_OFF "\xf3\xb1\x91\xa6" // U+F1466 +#define ICON_MDI_AIR_PURIFIER "\xf3\xb0\xb5\x84" // U+F0D44 +#define ICON_MDI_AIR_PURIFIER_OFF "\xf3\xb1\xad\x97" // U+F1B57 +#define ICON_MDI_AIRBAG "\xf3\xb0\xaf\xa9" // U+F0BE9 +#define ICON_MDI_AIRBALLOON "\xf3\xb0\x80\x9c" // U+F001C +#define ICON_MDI_AIRBALLOON_OUTLINE "\xf3\xb1\x80\x8b" // U+F100B +#define ICON_MDI_AIRPLANE "\xf3\xb0\x80\x9d" // U+F001D +#define ICON_MDI_AIRPLANE_ALERT "\xf3\xb1\xa1\xba" // U+F187A +#define ICON_MDI_AIRPLANE_CHECK "\xf3\xb1\xa1\xbb" // U+F187B +#define ICON_MDI_AIRPLANE_CLOCK "\xf3\xb1\xa1\xbc" // U+F187C +#define ICON_MDI_AIRPLANE_COG "\xf3\xb1\xa1\xbd" // U+F187D +#define ICON_MDI_AIRPLANE_EDIT "\xf3\xb1\xa1\xbe" // U+F187E +#define ICON_MDI_AIRPLANE_LANDING "\xf3\xb0\x97\x94" // U+F05D4 +#define ICON_MDI_AIRPLANE_MARKER "\xf3\xb1\xa1\xbf" // U+F187F +#define ICON_MDI_AIRPLANE_MINUS "\xf3\xb1\xa2\x80" // U+F1880 +#define ICON_MDI_AIRPLANE_OFF "\xf3\xb0\x80\x9e" // U+F001E +#define ICON_MDI_AIRPLANE_PLUS "\xf3\xb1\xa2\x81" // U+F1881 +#define ICON_MDI_AIRPLANE_REMOVE "\xf3\xb1\xa2\x82" // U+F1882 +#define ICON_MDI_AIRPLANE_SEARCH "\xf3\xb1\xa2\x83" // U+F1883 +#define ICON_MDI_AIRPLANE_SETTINGS "\xf3\xb1\xa2\x84" // U+F1884 +#define ICON_MDI_AIRPLANE_TAKEOFF "\xf3\xb0\x97\x95" // U+F05D5 +#define ICON_MDI_AIRPORT "\xf3\xb0\xa1\x8b" // U+F084B +#define ICON_MDI_ALARM "\xf3\xb0\x80\xa0" // U+F0020 +#define ICON_MDI_ALARM_BELL "\xf3\xb0\x9e\x8e" // U+F078E +#define ICON_MDI_ALARM_CHECK "\xf3\xb0\x80\xa1" // U+F0021 +#define ICON_MDI_ALARM_LIGHT "\xf3\xb0\x9e\x8f" // U+F078F +#define ICON_MDI_ALARM_LIGHT_OFF "\xf3\xb1\x9c\x9e" // U+F171E +#define ICON_MDI_ALARM_LIGHT_OFF_OUTLINE "\xf3\xb1\x9c\x9f" // U+F171F +#define ICON_MDI_ALARM_LIGHT_OUTLINE "\xf3\xb0\xaf\xaa" // U+F0BEA +#define ICON_MDI_ALARM_MULTIPLE "\xf3\xb0\x80\xa2" // U+F0022 +#define ICON_MDI_ALARM_NOTE "\xf3\xb0\xb9\xb1" // U+F0E71 +#define ICON_MDI_ALARM_NOTE_OFF "\xf3\xb0\xb9\xb2" // U+F0E72 +#define ICON_MDI_ALARM_OFF "\xf3\xb0\x80\xa3" // U+F0023 +#define ICON_MDI_ALARM_PANEL "\xf3\xb1\x97\x84" // U+F15C4 +#define ICON_MDI_ALARM_PANEL_OUTLINE "\xf3\xb1\x97\x85" // U+F15C5 +#define ICON_MDI_ALARM_PLUS "\xf3\xb0\x80\xa4" // U+F0024 +#define ICON_MDI_ALARM_SNOOZE "\xf3\xb0\x9a\x8e" // U+F068E +#define ICON_MDI_ALBUM "\xf3\xb0\x80\xa5" // U+F0025 +#define ICON_MDI_ALERT "\xf3\xb0\x80\xa6" // U+F0026 +#define ICON_MDI_ALERT_BOX "\xf3\xb0\x80\xa7" // U+F0027 +#define ICON_MDI_ALERT_BOX_OUTLINE "\xf3\xb0\xb3\xa4" // U+F0CE4 +#define ICON_MDI_ALERT_CIRCLE "\xf3\xb0\x80\xa8" // U+F0028 +#define ICON_MDI_ALERT_CIRCLE_CHECK "\xf3\xb1\x87\xad" // U+F11ED +#define ICON_MDI_ALERT_CIRCLE_CHECK_OUTLINE "\xf3\xb1\x87\xae" // U+F11EE +#define ICON_MDI_ALERT_CIRCLE_OUTLINE "\xf3\xb0\x97\x96" // U+F05D6 +#define ICON_MDI_ALERT_DECAGRAM "\xf3\xb0\x9a\xbd" // U+F06BD +#define ICON_MDI_ALERT_DECAGRAM_OUTLINE "\xf3\xb0\xb3\xa5" // U+F0CE5 +#define ICON_MDI_ALERT_MINUS "\xf3\xb1\x92\xbb" // U+F14BB +#define ICON_MDI_ALERT_MINUS_OUTLINE "\xf3\xb1\x92\xbe" // U+F14BE +#define ICON_MDI_ALERT_OCTAGON "\xf3\xb0\x80\xa9" // U+F0029 +#define ICON_MDI_ALERT_OCTAGON_OUTLINE "\xf3\xb0\xb3\xa6" // U+F0CE6 +#define ICON_MDI_ALERT_OCTAGRAM "\xf3\xb0\x9d\xa7" // U+F0767 +#define ICON_MDI_ALERT_OCTAGRAM_OUTLINE "\xf3\xb0\xb3\xa7" // U+F0CE7 +#define ICON_MDI_ALERT_OUTLINE "\xf3\xb0\x80\xaa" // U+F002A +#define ICON_MDI_ALERT_PLUS "\xf3\xb1\x92\xba" // U+F14BA +#define ICON_MDI_ALERT_PLUS_OUTLINE "\xf3\xb1\x92\xbd" // U+F14BD +#define ICON_MDI_ALERT_REMOVE "\xf3\xb1\x92\xbc" // U+F14BC +#define ICON_MDI_ALERT_REMOVE_OUTLINE "\xf3\xb1\x92\xbf" // U+F14BF +#define ICON_MDI_ALERT_RHOMBUS "\xf3\xb1\x87\x8e" // U+F11CE +#define ICON_MDI_ALERT_RHOMBUS_OUTLINE "\xf3\xb1\x87\x8f" // U+F11CF +#define ICON_MDI_ALIEN "\xf3\xb0\xa2\x9a" // U+F089A +#define ICON_MDI_ALIEN_OUTLINE "\xf3\xb1\x83\x8b" // U+F10CB +#define ICON_MDI_ALIGN_HORIZONTAL_CENTER "\xf3\xb1\x87\x83" // U+F11C3 +#define ICON_MDI_ALIGN_HORIZONTAL_DISTRIBUTE "\xf3\xb1\xa5\xa2" // U+F1962 +#define ICON_MDI_ALIGN_HORIZONTAL_LEFT "\xf3\xb1\x87\x82" // U+F11C2 +#define ICON_MDI_ALIGN_HORIZONTAL_RIGHT "\xf3\xb1\x87\x84" // U+F11C4 +#define ICON_MDI_ALIGN_VERTICAL_BOTTOM "\xf3\xb1\x87\x85" // U+F11C5 +#define ICON_MDI_ALIGN_VERTICAL_CENTER "\xf3\xb1\x87\x86" // U+F11C6 +#define ICON_MDI_ALIGN_VERTICAL_DISTRIBUTE "\xf3\xb1\xa5\xa3" // U+F1963 +#define ICON_MDI_ALIGN_VERTICAL_TOP "\xf3\xb1\x87\x87" // U+F11C7 +#define ICON_MDI_ALL_INCLUSIVE "\xf3\xb0\x9a\xbe" // U+F06BE +#define ICON_MDI_ALL_INCLUSIVE_BOX "\xf3\xb1\xa2\x8d" // U+F188D +#define ICON_MDI_ALL_INCLUSIVE_BOX_OUTLINE "\xf3\xb1\xa2\x8e" // U+F188E +#define ICON_MDI_ALLERGY "\xf3\xb1\x89\x98" // U+F1258 +#define ICON_MDI_ALPHA "\xf3\xb0\x80\xab" // U+F002B +#define ICON_MDI_ALPHA_A "\xf3\xb0\xab\xae" // U+F0AEE +#define ICON_MDI_ALPHA_A_BOX "\xf3\xb0\xac\x88" // U+F0B08 +#define ICON_MDI_ALPHA_A_BOX_OUTLINE "\xf3\xb0\xaf\xab" // U+F0BEB +#define ICON_MDI_ALPHA_A_CIRCLE "\xf3\xb0\xaf\xac" // U+F0BEC +#define ICON_MDI_ALPHA_A_CIRCLE_OUTLINE "\xf3\xb0\xaf\xad" // U+F0BED +#define ICON_MDI_ALPHA_B "\xf3\xb0\xab\xaf" // U+F0AEF +#define ICON_MDI_ALPHA_B_BOX "\xf3\xb0\xac\x89" // U+F0B09 +#define ICON_MDI_ALPHA_B_BOX_OUTLINE "\xf3\xb0\xaf\xae" // U+F0BEE +#define ICON_MDI_ALPHA_B_CIRCLE "\xf3\xb0\xaf\xaf" // U+F0BEF +#define ICON_MDI_ALPHA_B_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb0" // U+F0BF0 +#define ICON_MDI_ALPHA_C "\xf3\xb0\xab\xb0" // U+F0AF0 +#define ICON_MDI_ALPHA_C_BOX "\xf3\xb0\xac\x8a" // U+F0B0A +#define ICON_MDI_ALPHA_C_BOX_OUTLINE "\xf3\xb0\xaf\xb1" // U+F0BF1 +#define ICON_MDI_ALPHA_C_CIRCLE "\xf3\xb0\xaf\xb2" // U+F0BF2 +#define ICON_MDI_ALPHA_C_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb3" // U+F0BF3 +#define ICON_MDI_ALPHA_D "\xf3\xb0\xab\xb1" // U+F0AF1 +#define ICON_MDI_ALPHA_D_BOX "\xf3\xb0\xac\x8b" // U+F0B0B +#define ICON_MDI_ALPHA_D_BOX_OUTLINE "\xf3\xb0\xaf\xb4" // U+F0BF4 +#define ICON_MDI_ALPHA_D_CIRCLE "\xf3\xb0\xaf\xb5" // U+F0BF5 +#define ICON_MDI_ALPHA_D_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb6" // U+F0BF6 +#define ICON_MDI_ALPHA_E "\xf3\xb0\xab\xb2" // U+F0AF2 +#define ICON_MDI_ALPHA_E_BOX "\xf3\xb0\xac\x8c" // U+F0B0C +#define ICON_MDI_ALPHA_E_BOX_OUTLINE "\xf3\xb0\xaf\xb7" // U+F0BF7 +#define ICON_MDI_ALPHA_E_CIRCLE "\xf3\xb0\xaf\xb8" // U+F0BF8 +#define ICON_MDI_ALPHA_E_CIRCLE_OUTLINE "\xf3\xb0\xaf\xb9" // U+F0BF9 +#define ICON_MDI_ALPHA_F "\xf3\xb0\xab\xb3" // U+F0AF3 +#define ICON_MDI_ALPHA_F_BOX "\xf3\xb0\xac\x8d" // U+F0B0D +#define ICON_MDI_ALPHA_F_BOX_OUTLINE "\xf3\xb0\xaf\xba" // U+F0BFA +#define ICON_MDI_ALPHA_F_CIRCLE "\xf3\xb0\xaf\xbb" // U+F0BFB +#define ICON_MDI_ALPHA_F_CIRCLE_OUTLINE "\xf3\xb0\xaf\xbc" // U+F0BFC +#define ICON_MDI_ALPHA_G "\xf3\xb0\xab\xb4" // U+F0AF4 +#define ICON_MDI_ALPHA_G_BOX "\xf3\xb0\xac\x8e" // U+F0B0E +#define ICON_MDI_ALPHA_G_BOX_OUTLINE "\xf3\xb0\xaf\xbd" // U+F0BFD +#define ICON_MDI_ALPHA_G_CIRCLE "\xf3\xb0\xaf\xbe" // U+F0BFE +#define ICON_MDI_ALPHA_G_CIRCLE_OUTLINE "\xf3\xb0\xaf\xbf" // U+F0BFF +#define ICON_MDI_ALPHA_H "\xf3\xb0\xab\xb5" // U+F0AF5 +#define ICON_MDI_ALPHA_H_BOX "\xf3\xb0\xac\x8f" // U+F0B0F +#define ICON_MDI_ALPHA_H_BOX_OUTLINE "\xf3\xb0\xb0\x80" // U+F0C00 +#define ICON_MDI_ALPHA_H_CIRCLE "\xf3\xb0\xb0\x81" // U+F0C01 +#define ICON_MDI_ALPHA_H_CIRCLE_OUTLINE "\xf3\xb0\xb0\x82" // U+F0C02 +#define ICON_MDI_ALPHA_I "\xf3\xb0\xab\xb6" // U+F0AF6 +#define ICON_MDI_ALPHA_I_BOX "\xf3\xb0\xac\x90" // U+F0B10 +#define ICON_MDI_ALPHA_I_BOX_OUTLINE "\xf3\xb0\xb0\x83" // U+F0C03 +#define ICON_MDI_ALPHA_I_CIRCLE "\xf3\xb0\xb0\x84" // U+F0C04 +#define ICON_MDI_ALPHA_I_CIRCLE_OUTLINE "\xf3\xb0\xb0\x85" // U+F0C05 +#define ICON_MDI_ALPHA_J "\xf3\xb0\xab\xb7" // U+F0AF7 +#define ICON_MDI_ALPHA_J_BOX "\xf3\xb0\xac\x91" // U+F0B11 +#define ICON_MDI_ALPHA_J_BOX_OUTLINE "\xf3\xb0\xb0\x86" // U+F0C06 +#define ICON_MDI_ALPHA_J_CIRCLE "\xf3\xb0\xb0\x87" // U+F0C07 +#define ICON_MDI_ALPHA_J_CIRCLE_OUTLINE "\xf3\xb0\xb0\x88" // U+F0C08 +#define ICON_MDI_ALPHA_K "\xf3\xb0\xab\xb8" // U+F0AF8 +#define ICON_MDI_ALPHA_K_BOX "\xf3\xb0\xac\x92" // U+F0B12 +#define ICON_MDI_ALPHA_K_BOX_OUTLINE "\xf3\xb0\xb0\x89" // U+F0C09 +#define ICON_MDI_ALPHA_K_CIRCLE "\xf3\xb0\xb0\x8a" // U+F0C0A +#define ICON_MDI_ALPHA_K_CIRCLE_OUTLINE "\xf3\xb0\xb0\x8b" // U+F0C0B +#define ICON_MDI_ALPHA_L "\xf3\xb0\xab\xb9" // U+F0AF9 +#define ICON_MDI_ALPHA_L_BOX "\xf3\xb0\xac\x93" // U+F0B13 +#define ICON_MDI_ALPHA_L_BOX_OUTLINE "\xf3\xb0\xb0\x8c" // U+F0C0C +#define ICON_MDI_ALPHA_L_CIRCLE "\xf3\xb0\xb0\x8d" // U+F0C0D +#define ICON_MDI_ALPHA_L_CIRCLE_OUTLINE "\xf3\xb0\xb0\x8e" // U+F0C0E +#define ICON_MDI_ALPHA_M "\xf3\xb0\xab\xba" // U+F0AFA +#define ICON_MDI_ALPHA_M_BOX "\xf3\xb0\xac\x94" // U+F0B14 +#define ICON_MDI_ALPHA_M_BOX_OUTLINE "\xf3\xb0\xb0\x8f" // U+F0C0F +#define ICON_MDI_ALPHA_M_CIRCLE "\xf3\xb0\xb0\x90" // U+F0C10 +#define ICON_MDI_ALPHA_M_CIRCLE_OUTLINE "\xf3\xb0\xb0\x91" // U+F0C11 +#define ICON_MDI_ALPHA_N "\xf3\xb0\xab\xbb" // U+F0AFB +#define ICON_MDI_ALPHA_N_BOX "\xf3\xb0\xac\x95" // U+F0B15 +#define ICON_MDI_ALPHA_N_BOX_OUTLINE "\xf3\xb0\xb0\x92" // U+F0C12 +#define ICON_MDI_ALPHA_N_CIRCLE "\xf3\xb0\xb0\x93" // U+F0C13 +#define ICON_MDI_ALPHA_N_CIRCLE_OUTLINE "\xf3\xb0\xb0\x94" // U+F0C14 +#define ICON_MDI_ALPHA_O "\xf3\xb0\xab\xbc" // U+F0AFC +#define ICON_MDI_ALPHA_O_BOX "\xf3\xb0\xac\x96" // U+F0B16 +#define ICON_MDI_ALPHA_O_BOX_OUTLINE "\xf3\xb0\xb0\x95" // U+F0C15 +#define ICON_MDI_ALPHA_O_CIRCLE "\xf3\xb0\xb0\x96" // U+F0C16 +#define ICON_MDI_ALPHA_O_CIRCLE_OUTLINE "\xf3\xb0\xb0\x97" // U+F0C17 +#define ICON_MDI_ALPHA_P "\xf3\xb0\xab\xbd" // U+F0AFD +#define ICON_MDI_ALPHA_P_BOX "\xf3\xb0\xac\x97" // U+F0B17 +#define ICON_MDI_ALPHA_P_BOX_OUTLINE "\xf3\xb0\xb0\x98" // U+F0C18 +#define ICON_MDI_ALPHA_P_CIRCLE "\xf3\xb0\xb0\x99" // U+F0C19 +#define ICON_MDI_ALPHA_P_CIRCLE_OUTLINE "\xf3\xb0\xb0\x9a" // U+F0C1A +#define ICON_MDI_ALPHA_Q "\xf3\xb0\xab\xbe" // U+F0AFE +#define ICON_MDI_ALPHA_Q_BOX "\xf3\xb0\xac\x98" // U+F0B18 +#define ICON_MDI_ALPHA_Q_BOX_OUTLINE "\xf3\xb0\xb0\x9b" // U+F0C1B +#define ICON_MDI_ALPHA_Q_CIRCLE "\xf3\xb0\xb0\x9c" // U+F0C1C +#define ICON_MDI_ALPHA_Q_CIRCLE_OUTLINE "\xf3\xb0\xb0\x9d" // U+F0C1D +#define ICON_MDI_ALPHA_R "\xf3\xb0\xab\xbf" // U+F0AFF +#define ICON_MDI_ALPHA_R_BOX "\xf3\xb0\xac\x99" // U+F0B19 +#define ICON_MDI_ALPHA_R_BOX_OUTLINE "\xf3\xb0\xb0\x9e" // U+F0C1E +#define ICON_MDI_ALPHA_R_CIRCLE "\xf3\xb0\xb0\x9f" // U+F0C1F +#define ICON_MDI_ALPHA_R_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa0" // U+F0C20 +#define ICON_MDI_ALPHA_S "\xf3\xb0\xac\x80" // U+F0B00 +#define ICON_MDI_ALPHA_S_BOX "\xf3\xb0\xac\x9a" // U+F0B1A +#define ICON_MDI_ALPHA_S_BOX_OUTLINE "\xf3\xb0\xb0\xa1" // U+F0C21 +#define ICON_MDI_ALPHA_S_CIRCLE "\xf3\xb0\xb0\xa2" // U+F0C22 +#define ICON_MDI_ALPHA_S_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa3" // U+F0C23 +#define ICON_MDI_ALPHA_T "\xf3\xb0\xac\x81" // U+F0B01 +#define ICON_MDI_ALPHA_T_BOX "\xf3\xb0\xac\x9b" // U+F0B1B +#define ICON_MDI_ALPHA_T_BOX_OUTLINE "\xf3\xb0\xb0\xa4" // U+F0C24 +#define ICON_MDI_ALPHA_T_CIRCLE "\xf3\xb0\xb0\xa5" // U+F0C25 +#define ICON_MDI_ALPHA_T_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa6" // U+F0C26 +#define ICON_MDI_ALPHA_U "\xf3\xb0\xac\x82" // U+F0B02 +#define ICON_MDI_ALPHA_U_BOX "\xf3\xb0\xac\x9c" // U+F0B1C +#define ICON_MDI_ALPHA_U_BOX_OUTLINE "\xf3\xb0\xb0\xa7" // U+F0C27 +#define ICON_MDI_ALPHA_U_CIRCLE "\xf3\xb0\xb0\xa8" // U+F0C28 +#define ICON_MDI_ALPHA_U_CIRCLE_OUTLINE "\xf3\xb0\xb0\xa9" // U+F0C29 +#define ICON_MDI_ALPHA_V "\xf3\xb0\xac\x83" // U+F0B03 +#define ICON_MDI_ALPHA_V_BOX "\xf3\xb0\xac\x9d" // U+F0B1D +#define ICON_MDI_ALPHA_V_BOX_OUTLINE "\xf3\xb0\xb0\xaa" // U+F0C2A +#define ICON_MDI_ALPHA_V_CIRCLE "\xf3\xb0\xb0\xab" // U+F0C2B +#define ICON_MDI_ALPHA_V_CIRCLE_OUTLINE "\xf3\xb0\xb0\xac" // U+F0C2C +#define ICON_MDI_ALPHA_W "\xf3\xb0\xac\x84" // U+F0B04 +#define ICON_MDI_ALPHA_W_BOX "\xf3\xb0\xac\x9e" // U+F0B1E +#define ICON_MDI_ALPHA_W_BOX_OUTLINE "\xf3\xb0\xb0\xad" // U+F0C2D +#define ICON_MDI_ALPHA_W_CIRCLE "\xf3\xb0\xb0\xae" // U+F0C2E +#define ICON_MDI_ALPHA_W_CIRCLE_OUTLINE "\xf3\xb0\xb0\xaf" // U+F0C2F +#define ICON_MDI_ALPHA_X "\xf3\xb0\xac\x85" // U+F0B05 +#define ICON_MDI_ALPHA_X_BOX "\xf3\xb0\xac\x9f" // U+F0B1F +#define ICON_MDI_ALPHA_X_BOX_OUTLINE "\xf3\xb0\xb0\xb0" // U+F0C30 +#define ICON_MDI_ALPHA_X_CIRCLE "\xf3\xb0\xb0\xb1" // U+F0C31 +#define ICON_MDI_ALPHA_X_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb2" // U+F0C32 +#define ICON_MDI_ALPHA_Y "\xf3\xb0\xac\x86" // U+F0B06 +#define ICON_MDI_ALPHA_Y_BOX "\xf3\xb0\xac\xa0" // U+F0B20 +#define ICON_MDI_ALPHA_Y_BOX_OUTLINE "\xf3\xb0\xb0\xb3" // U+F0C33 +#define ICON_MDI_ALPHA_Y_CIRCLE "\xf3\xb0\xb0\xb4" // U+F0C34 +#define ICON_MDI_ALPHA_Y_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb5" // U+F0C35 +#define ICON_MDI_ALPHA_Z "\xf3\xb0\xac\x87" // U+F0B07 +#define ICON_MDI_ALPHA_Z_BOX "\xf3\xb0\xac\xa1" // U+F0B21 +#define ICON_MDI_ALPHA_Z_BOX_OUTLINE "\xf3\xb0\xb0\xb6" // U+F0C36 +#define ICON_MDI_ALPHA_Z_CIRCLE "\xf3\xb0\xb0\xb7" // U+F0C37 +#define ICON_MDI_ALPHA_Z_CIRCLE_OUTLINE "\xf3\xb0\xb0\xb8" // U+F0C38 +#define ICON_MDI_ALPHABET_AUREBESH "\xf3\xb1\x8c\xac" // U+F132C +#define ICON_MDI_ALPHABET_CYRILLIC "\xf3\xb1\x8c\xad" // U+F132D +#define ICON_MDI_ALPHABET_GREEK "\xf3\xb1\x8c\xae" // U+F132E +#define ICON_MDI_ALPHABET_LATIN "\xf3\xb1\x8c\xaf" // U+F132F +#define ICON_MDI_ALPHABET_PIQAD "\xf3\xb1\x8c\xb0" // U+F1330 +#define ICON_MDI_ALPHABET_TENGWAR "\xf3\xb1\x8c\xb7" // U+F1337 +#define ICON_MDI_ALPHABETICAL "\xf3\xb0\x80\xac" // U+F002C +#define ICON_MDI_ALPHABETICAL_OFF "\xf3\xb1\x80\x8c" // U+F100C +#define ICON_MDI_ALPHABETICAL_VARIANT "\xf3\xb1\x80\x8d" // U+F100D +#define ICON_MDI_ALPHABETICAL_VARIANT_OFF "\xf3\xb1\x80\x8e" // U+F100E +#define ICON_MDI_ALTIMETER "\xf3\xb0\x97\x97" // U+F05D7 +#define ICON_MDI_AMBULANCE "\xf3\xb0\x80\xaf" // U+F002F +#define ICON_MDI_AMMUNITION "\xf3\xb0\xb3\xa8" // U+F0CE8 +#define ICON_MDI_AMPERSAND "\xf3\xb0\xaa\x8d" // U+F0A8D +#define ICON_MDI_AMPLIFIER "\xf3\xb0\x80\xb0" // U+F0030 +#define ICON_MDI_AMPLIFIER_OFF "\xf3\xb1\x86\xb5" // U+F11B5 +#define ICON_MDI_ANCHOR "\xf3\xb0\x80\xb1" // U+F0031 +#define ICON_MDI_ANDROID "\xf3\xb0\x80\xb2" // U+F0032 +#define ICON_MDI_ANDROID_STUDIO "\xf3\xb0\x80\xb4" // U+F0034 +#define ICON_MDI_ANGLE_ACUTE "\xf3\xb0\xa4\xb7" // U+F0937 +#define ICON_MDI_ANGLE_OBTUSE "\xf3\xb0\xa4\xb8" // U+F0938 +#define ICON_MDI_ANGLE_RIGHT "\xf3\xb0\xa4\xb9" // U+F0939 +#define ICON_MDI_ANGULAR "\xf3\xb0\x9a\xb2" // U+F06B2 +#define ICON_MDI_ANGULARJS "\xf3\xb0\x9a\xbf" // U+F06BF +#define ICON_MDI_ANIMATION "\xf3\xb0\x97\x98" // U+F05D8 +#define ICON_MDI_ANIMATION_OUTLINE "\xf3\xb0\xaa\x8f" // U+F0A8F +#define ICON_MDI_ANIMATION_PLAY "\xf3\xb0\xa4\xba" // U+F093A +#define ICON_MDI_ANIMATION_PLAY_OUTLINE "\xf3\xb0\xaa\x90" // U+F0A90 +#define ICON_MDI_ANSIBLE "\xf3\xb1\x82\x9a" // U+F109A +#define ICON_MDI_ANTENNA "\xf3\xb1\x84\x99" // U+F1119 +#define ICON_MDI_ANVIL "\xf3\xb0\xa2\x9b" // U+F089B +#define ICON_MDI_APACHE_KAFKA "\xf3\xb1\x80\x8f" // U+F100F +#define ICON_MDI_API "\xf3\xb1\x82\x9b" // U+F109B +#define ICON_MDI_API_OFF "\xf3\xb1\x89\x97" // U+F1257 +#define ICON_MDI_APPLE "\xf3\xb0\x80\xb5" // U+F0035 +#define ICON_MDI_APPLE_FINDER "\xf3\xb0\x80\xb6" // U+F0036 +#define ICON_MDI_APPLE_ICLOUD "\xf3\xb0\x80\xb8" // U+F0038 +#define ICON_MDI_APPLE_IOS "\xf3\xb0\x80\xb7" // U+F0037 +#define ICON_MDI_APPLE_KEYBOARD_CAPS "\xf3\xb0\x98\xb2" // U+F0632 +#define ICON_MDI_APPLE_KEYBOARD_COMMAND "\xf3\xb0\x98\xb3" // U+F0633 +#define ICON_MDI_APPLE_KEYBOARD_CONTROL "\xf3\xb0\x98\xb4" // U+F0634 +#define ICON_MDI_APPLE_KEYBOARD_OPTION "\xf3\xb0\x98\xb5" // U+F0635 +#define ICON_MDI_APPLE_KEYBOARD_SHIFT "\xf3\xb0\x98\xb6" // U+F0636 +#define ICON_MDI_APPLE_SAFARI "\xf3\xb0\x80\xb9" // U+F0039 +#define ICON_MDI_APPLICATION "\xf3\xb0\xa3\x86" // U+F08C6 +#define ICON_MDI_APPLICATION_ARRAY "\xf3\xb1\x83\xb5" // U+F10F5 +#define ICON_MDI_APPLICATION_ARRAY_OUTLINE "\xf3\xb1\x83\xb6" // U+F10F6 +#define ICON_MDI_APPLICATION_BRACES "\xf3\xb1\x83\xb7" // U+F10F7 +#define ICON_MDI_APPLICATION_BRACES_OUTLINE "\xf3\xb1\x83\xb8" // U+F10F8 +#define ICON_MDI_APPLICATION_BRACKETS "\xf3\xb0\xb2\x8b" // U+F0C8B +#define ICON_MDI_APPLICATION_BRACKETS_OUTLINE "\xf3\xb0\xb2\x8c" // U+F0C8C +#define ICON_MDI_APPLICATION_COG "\xf3\xb0\x99\xb5" // U+F0675 +#define ICON_MDI_APPLICATION_COG_OUTLINE "\xf3\xb1\x95\xb7" // U+F1577 +#define ICON_MDI_APPLICATION_EDIT "\xf3\xb0\x82\xae" // U+F00AE +#define ICON_MDI_APPLICATION_EDIT_OUTLINE "\xf3\xb0\x98\x99" // U+F0619 +#define ICON_MDI_APPLICATION_EXPORT "\xf3\xb0\xb6\xad" // U+F0DAD +#define ICON_MDI_APPLICATION_IMPORT "\xf3\xb0\xb6\xae" // U+F0DAE +#define ICON_MDI_APPLICATION_OUTLINE "\xf3\xb0\x98\x94" // U+F0614 +#define ICON_MDI_APPLICATION_PARENTHESES "\xf3\xb1\x83\xb9" // U+F10F9 +#define ICON_MDI_APPLICATION_PARENTHESES_OUTLINE "\xf3\xb1\x83\xba" // U+F10FA +#define ICON_MDI_APPLICATION_SETTINGS "\xf3\xb0\xad\xa0" // U+F0B60 +#define ICON_MDI_APPLICATION_SETTINGS_OUTLINE "\xf3\xb1\x95\x95" // U+F1555 +#define ICON_MDI_APPLICATION_VARIABLE "\xf3\xb1\x83\xbb" // U+F10FB +#define ICON_MDI_APPLICATION_VARIABLE_OUTLINE "\xf3\xb1\x83\xbc" // U+F10FC +#define ICON_MDI_APPROXIMATELY_EQUAL "\xf3\xb0\xbe\x9e" // U+F0F9E +#define ICON_MDI_APPROXIMATELY_EQUAL_BOX "\xf3\xb0\xbe\x9f" // U+F0F9F +#define ICON_MDI_APPS "\xf3\xb0\x80\xbb" // U+F003B +#define ICON_MDI_APPS_BOX "\xf3\xb0\xb5\x86" // U+F0D46 +#define ICON_MDI_ARCH "\xf3\xb0\xa3\x87" // U+F08C7 +#define ICON_MDI_ARCHIVE "\xf3\xb0\x80\xbc" // U+F003C +#define ICON_MDI_ARCHIVE_ALERT "\xf3\xb1\x93\xbd" // U+F14FD +#define ICON_MDI_ARCHIVE_ALERT_OUTLINE "\xf3\xb1\x93\xbe" // U+F14FE +#define ICON_MDI_ARCHIVE_ARROW_DOWN "\xf3\xb1\x89\x99" // U+F1259 +#define ICON_MDI_ARCHIVE_ARROW_DOWN_OUTLINE "\xf3\xb1\x89\x9a" // U+F125A +#define ICON_MDI_ARCHIVE_ARROW_UP "\xf3\xb1\x89\x9b" // U+F125B +#define ICON_MDI_ARCHIVE_ARROW_UP_OUTLINE "\xf3\xb1\x89\x9c" // U+F125C +#define ICON_MDI_ARCHIVE_CANCEL "\xf3\xb1\x9d\x8b" // U+F174B +#define ICON_MDI_ARCHIVE_CANCEL_OUTLINE "\xf3\xb1\x9d\x8c" // U+F174C +#define ICON_MDI_ARCHIVE_CHECK "\xf3\xb1\x9d\x8d" // U+F174D +#define ICON_MDI_ARCHIVE_CHECK_OUTLINE "\xf3\xb1\x9d\x8e" // U+F174E +#define ICON_MDI_ARCHIVE_CLOCK "\xf3\xb1\x9d\x8f" // U+F174F +#define ICON_MDI_ARCHIVE_CLOCK_OUTLINE "\xf3\xb1\x9d\x90" // U+F1750 +#define ICON_MDI_ARCHIVE_COG "\xf3\xb1\x9d\x91" // U+F1751 +#define ICON_MDI_ARCHIVE_COG_OUTLINE "\xf3\xb1\x9d\x92" // U+F1752 +#define ICON_MDI_ARCHIVE_EDIT "\xf3\xb1\x9d\x93" // U+F1753 +#define ICON_MDI_ARCHIVE_EDIT_OUTLINE "\xf3\xb1\x9d\x94" // U+F1754 +#define ICON_MDI_ARCHIVE_EYE "\xf3\xb1\x9d\x95" // U+F1755 +#define ICON_MDI_ARCHIVE_EYE_OUTLINE "\xf3\xb1\x9d\x96" // U+F1756 +#define ICON_MDI_ARCHIVE_LOCK "\xf3\xb1\x9d\x97" // U+F1757 +#define ICON_MDI_ARCHIVE_LOCK_OPEN "\xf3\xb1\x9d\x98" // U+F1758 +#define ICON_MDI_ARCHIVE_LOCK_OPEN_OUTLINE "\xf3\xb1\x9d\x99" // U+F1759 +#define ICON_MDI_ARCHIVE_LOCK_OUTLINE "\xf3\xb1\x9d\x9a" // U+F175A +#define ICON_MDI_ARCHIVE_MARKER "\xf3\xb1\x9d\x9b" // U+F175B +#define ICON_MDI_ARCHIVE_MARKER_OUTLINE "\xf3\xb1\x9d\x9c" // U+F175C +#define ICON_MDI_ARCHIVE_MINUS "\xf3\xb1\x9d\x9d" // U+F175D +#define ICON_MDI_ARCHIVE_MINUS_OUTLINE "\xf3\xb1\x9d\x9e" // U+F175E +#define ICON_MDI_ARCHIVE_MUSIC "\xf3\xb1\x9d\x9f" // U+F175F +#define ICON_MDI_ARCHIVE_MUSIC_OUTLINE "\xf3\xb1\x9d\xa0" // U+F1760 +#define ICON_MDI_ARCHIVE_OFF "\xf3\xb1\x9d\xa1" // U+F1761 +#define ICON_MDI_ARCHIVE_OFF_OUTLINE "\xf3\xb1\x9d\xa2" // U+F1762 +#define ICON_MDI_ARCHIVE_OUTLINE "\xf3\xb1\x88\x8e" // U+F120E +#define ICON_MDI_ARCHIVE_PLUS "\xf3\xb1\x9d\xa3" // U+F1763 +#define ICON_MDI_ARCHIVE_PLUS_OUTLINE "\xf3\xb1\x9d\xa4" // U+F1764 +#define ICON_MDI_ARCHIVE_REFRESH "\xf3\xb1\x9d\xa5" // U+F1765 +#define ICON_MDI_ARCHIVE_REFRESH_OUTLINE "\xf3\xb1\x9d\xa6" // U+F1766 +#define ICON_MDI_ARCHIVE_REMOVE "\xf3\xb1\x9d\xa7" // U+F1767 +#define ICON_MDI_ARCHIVE_REMOVE_OUTLINE "\xf3\xb1\x9d\xa8" // U+F1768 +#define ICON_MDI_ARCHIVE_SEARCH "\xf3\xb1\x9d\xa9" // U+F1769 +#define ICON_MDI_ARCHIVE_SEARCH_OUTLINE "\xf3\xb1\x9d\xaa" // U+F176A +#define ICON_MDI_ARCHIVE_SETTINGS "\xf3\xb1\x9d\xab" // U+F176B +#define ICON_MDI_ARCHIVE_SETTINGS_OUTLINE "\xf3\xb1\x9d\xac" // U+F176C +#define ICON_MDI_ARCHIVE_STAR "\xf3\xb1\x9d\xad" // U+F176D +#define ICON_MDI_ARCHIVE_STAR_OUTLINE "\xf3\xb1\x9d\xae" // U+F176E +#define ICON_MDI_ARCHIVE_SYNC "\xf3\xb1\x9d\xaf" // U+F176F +#define ICON_MDI_ARCHIVE_SYNC_OUTLINE "\xf3\xb1\x9d\xb0" // U+F1770 +#define ICON_MDI_ARM_FLEX "\xf3\xb0\xbf\x97" // U+F0FD7 +#define ICON_MDI_ARM_FLEX_OUTLINE "\xf3\xb0\xbf\x96" // U+F0FD6 +#define ICON_MDI_ARRANGE_BRING_FORWARD "\xf3\xb0\x80\xbd" // U+F003D +#define ICON_MDI_ARRANGE_BRING_TO_FRONT "\xf3\xb0\x80\xbe" // U+F003E +#define ICON_MDI_ARRANGE_SEND_BACKWARD "\xf3\xb0\x80\xbf" // U+F003F +#define ICON_MDI_ARRANGE_SEND_TO_BACK "\xf3\xb0\x81\x80" // U+F0040 +#define ICON_MDI_ARROW_ALL "\xf3\xb0\x81\x81" // U+F0041 +#define ICON_MDI_ARROW_BOTTOM_LEFT "\xf3\xb0\x81\x82" // U+F0042 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_BOX "\xf3\xb1\xa5\xa4" // U+F1964 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa5" // U+F1965 +#define ICON_MDI_ARROW_BOTTOM_LEFT_BOLD_OUTLINE "\xf3\xb0\xa6\xb7" // U+F09B7 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THICK "\xf3\xb0\xa6\xb8" // U+F09B8 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THIN "\xf3\xb1\xa6\xb6" // U+F19B6 +#define ICON_MDI_ARROW_BOTTOM_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x96" // U+F1596 +#define ICON_MDI_ARROW_BOTTOM_RIGHT "\xf3\xb0\x81\x83" // U+F0043 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_BOX "\xf3\xb1\xa5\xa6" // U+F1966 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa7" // U+F1967 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa6\xb9" // U+F09B9 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THICK "\xf3\xb0\xa6\xba" // U+F09BA +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THIN "\xf3\xb1\xa6\xb7" // U+F19B7 +#define ICON_MDI_ARROW_BOTTOM_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x95" // U+F1595 +#define ICON_MDI_ARROW_COLLAPSE "\xf3\xb0\x98\x95" // U+F0615 +#define ICON_MDI_ARROW_COLLAPSE_ALL "\xf3\xb0\x81\x84" // U+F0044 +#define ICON_MDI_ARROW_COLLAPSE_DOWN "\xf3\xb0\x9e\x92" // U+F0792 +#define ICON_MDI_ARROW_COLLAPSE_HORIZONTAL "\xf3\xb0\xa1\x8c" // U+F084C +#define ICON_MDI_ARROW_COLLAPSE_LEFT "\xf3\xb0\x9e\x93" // U+F0793 +#define ICON_MDI_ARROW_COLLAPSE_RIGHT "\xf3\xb0\x9e\x94" // U+F0794 +#define ICON_MDI_ARROW_COLLAPSE_UP "\xf3\xb0\x9e\x95" // U+F0795 +#define ICON_MDI_ARROW_COLLAPSE_VERTICAL "\xf3\xb0\xa1\x8d" // U+F084D +#define ICON_MDI_ARROW_DECISION "\xf3\xb0\xa6\xbb" // U+F09BB +#define ICON_MDI_ARROW_DECISION_AUTO "\xf3\xb0\xa6\xbc" // U+F09BC +#define ICON_MDI_ARROW_DECISION_AUTO_OUTLINE "\xf3\xb0\xa6\xbd" // U+F09BD +#define ICON_MDI_ARROW_DECISION_OUTLINE "\xf3\xb0\xa6\xbe" // U+F09BE +#define ICON_MDI_ARROW_DOWN "\xf3\xb0\x81\x85" // U+F0045 +#define ICON_MDI_ARROW_DOWN_BOLD "\xf3\xb0\x9c\xae" // U+F072E +#define ICON_MDI_ARROW_DOWN_BOLD_BOX "\xf3\xb0\x9c\xaf" // U+F072F +#define ICON_MDI_ARROW_DOWN_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb0" // U+F0730 +#define ICON_MDI_ARROW_DOWN_BOLD_CIRCLE "\xf3\xb0\x81\x87" // U+F0047 +#define ICON_MDI_ARROW_DOWN_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x88" // U+F0048 +#define ICON_MDI_ARROW_DOWN_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x89" // U+F0049 +#define ICON_MDI_ARROW_DOWN_BOLD_OUTLINE "\xf3\xb0\xa6\xbf" // U+F09BF +#define ICON_MDI_ARROW_DOWN_BOX "\xf3\xb0\x9b\x80" // U+F06C0 +#define ICON_MDI_ARROW_DOWN_CIRCLE "\xf3\xb0\xb3\x9b" // U+F0CDB +#define ICON_MDI_ARROW_DOWN_CIRCLE_OUTLINE "\xf3\xb0\xb3\x9c" // U+F0CDC +#define ICON_MDI_ARROW_DOWN_DROP_CIRCLE "\xf3\xb0\x81\x8a" // U+F004A +#define ICON_MDI_ARROW_DOWN_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x8b" // U+F004B +#define ICON_MDI_ARROW_DOWN_LEFT "\xf3\xb1\x9e\xa1" // U+F17A1 +#define ICON_MDI_ARROW_DOWN_LEFT_BOLD "\xf3\xb1\x9e\xa2" // U+F17A2 +#define ICON_MDI_ARROW_DOWN_RIGHT "\xf3\xb1\x9e\xa3" // U+F17A3 +#define ICON_MDI_ARROW_DOWN_RIGHT_BOLD "\xf3\xb1\x9e\xa4" // U+F17A4 +#define ICON_MDI_ARROW_DOWN_THICK "\xf3\xb0\x81\x86" // U+F0046 +#define ICON_MDI_ARROW_DOWN_THIN "\xf3\xb1\xa6\xb3" // U+F19B3 +#define ICON_MDI_ARROW_DOWN_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x99" // U+F1599 +#define ICON_MDI_ARROW_EXPAND "\xf3\xb0\x98\x96" // U+F0616 +#define ICON_MDI_ARROW_EXPAND_ALL "\xf3\xb0\x81\x8c" // U+F004C +#define ICON_MDI_ARROW_EXPAND_DOWN "\xf3\xb0\x9e\x96" // U+F0796 +#define ICON_MDI_ARROW_EXPAND_HORIZONTAL "\xf3\xb0\xa1\x8e" // U+F084E +#define ICON_MDI_ARROW_EXPAND_LEFT "\xf3\xb0\x9e\x97" // U+F0797 +#define ICON_MDI_ARROW_EXPAND_RIGHT "\xf3\xb0\x9e\x98" // U+F0798 +#define ICON_MDI_ARROW_EXPAND_UP "\xf3\xb0\x9e\x99" // U+F0799 +#define ICON_MDI_ARROW_EXPAND_VERTICAL "\xf3\xb0\xa1\x8f" // U+F084F +#define ICON_MDI_ARROW_HORIZONTAL_LOCK "\xf3\xb1\x85\x9b" // U+F115B +#define ICON_MDI_ARROW_LEFT "\xf3\xb0\x81\x8d" // U+F004D +#define ICON_MDI_ARROW_LEFT_BOLD "\xf3\xb0\x9c\xb1" // U+F0731 +#define ICON_MDI_ARROW_LEFT_BOLD_BOX "\xf3\xb0\x9c\xb2" // U+F0732 +#define ICON_MDI_ARROW_LEFT_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb3" // U+F0733 +#define ICON_MDI_ARROW_LEFT_BOLD_CIRCLE "\xf3\xb0\x81\x8f" // U+F004F +#define ICON_MDI_ARROW_LEFT_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x90" // U+F0050 +#define ICON_MDI_ARROW_LEFT_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x91" // U+F0051 +#define ICON_MDI_ARROW_LEFT_BOLD_OUTLINE "\xf3\xb0\xa7\x80" // U+F09C0 +#define ICON_MDI_ARROW_LEFT_BOTTOM "\xf3\xb1\x9e\xa5" // U+F17A5 +#define ICON_MDI_ARROW_LEFT_BOTTOM_BOLD "\xf3\xb1\x9e\xa6" // U+F17A6 +#define ICON_MDI_ARROW_LEFT_BOX "\xf3\xb0\x9b\x81" // U+F06C1 +#define ICON_MDI_ARROW_LEFT_CIRCLE "\xf3\xb0\xb3\x9d" // U+F0CDD +#define ICON_MDI_ARROW_LEFT_CIRCLE_OUTLINE "\xf3\xb0\xb3\x9e" // U+F0CDE +#define ICON_MDI_ARROW_LEFT_DROP_CIRCLE "\xf3\xb0\x81\x92" // U+F0052 +#define ICON_MDI_ARROW_LEFT_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x93" // U+F0053 +#define ICON_MDI_ARROW_LEFT_RIGHT "\xf3\xb0\xb9\xb3" // U+F0E73 +#define ICON_MDI_ARROW_LEFT_RIGHT_BOLD "\xf3\xb0\xb9\xb4" // U+F0E74 +#define ICON_MDI_ARROW_LEFT_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x81" // U+F09C1 +#define ICON_MDI_ARROW_LEFT_THICK "\xf3\xb0\x81\x8e" // U+F004E +#define ICON_MDI_ARROW_LEFT_THIN "\xf3\xb1\xa6\xb1" // U+F19B1 +#define ICON_MDI_ARROW_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x9a" // U+F159A +#define ICON_MDI_ARROW_LEFT_TOP "\xf3\xb1\x9e\xa7" // U+F17A7 +#define ICON_MDI_ARROW_LEFT_TOP_BOLD "\xf3\xb1\x9e\xa8" // U+F17A8 +#define ICON_MDI_ARROW_OSCILLATING "\xf3\xb1\xb2\x91" // U+F1C91 +#define ICON_MDI_ARROW_OSCILLATING_OFF "\xf3\xb1\xb2\x92" // U+F1C92 +#define ICON_MDI_ARROW_PROJECTILE "\xf3\xb1\xa1\x80" // U+F1840 +#define ICON_MDI_ARROW_PROJECTILE_MULTIPLE "\xf3\xb1\xa0\xbf" // U+F183F +#define ICON_MDI_ARROW_RIGHT "\xf3\xb0\x81\x94" // U+F0054 +#define ICON_MDI_ARROW_RIGHT_BOLD "\xf3\xb0\x9c\xb4" // U+F0734 +#define ICON_MDI_ARROW_RIGHT_BOLD_BOX "\xf3\xb0\x9c\xb5" // U+F0735 +#define ICON_MDI_ARROW_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb6" // U+F0736 +#define ICON_MDI_ARROW_RIGHT_BOLD_CIRCLE "\xf3\xb0\x81\x96" // U+F0056 +#define ICON_MDI_ARROW_RIGHT_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\x97" // U+F0057 +#define ICON_MDI_ARROW_RIGHT_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\x98" // U+F0058 +#define ICON_MDI_ARROW_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x82" // U+F09C2 +#define ICON_MDI_ARROW_RIGHT_BOTTOM "\xf3\xb1\x9e\xa9" // U+F17A9 +#define ICON_MDI_ARROW_RIGHT_BOTTOM_BOLD "\xf3\xb1\x9e\xaa" // U+F17AA +#define ICON_MDI_ARROW_RIGHT_BOX "\xf3\xb0\x9b\x82" // U+F06C2 +#define ICON_MDI_ARROW_RIGHT_CIRCLE "\xf3\xb0\xb3\x9f" // U+F0CDF +#define ICON_MDI_ARROW_RIGHT_CIRCLE_OUTLINE "\xf3\xb0\xb3\xa0" // U+F0CE0 +#define ICON_MDI_ARROW_RIGHT_DROP_CIRCLE "\xf3\xb0\x81\x99" // U+F0059 +#define ICON_MDI_ARROW_RIGHT_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\x9a" // U+F005A +#define ICON_MDI_ARROW_RIGHT_THICK "\xf3\xb0\x81\x95" // U+F0055 +#define ICON_MDI_ARROW_RIGHT_THIN "\xf3\xb1\xa6\xb0" // U+F19B0 +#define ICON_MDI_ARROW_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x98" // U+F1598 +#define ICON_MDI_ARROW_RIGHT_TOP "\xf3\xb1\x9e\xab" // U+F17AB +#define ICON_MDI_ARROW_RIGHT_TOP_BOLD "\xf3\xb1\x9e\xac" // U+F17AC +#define ICON_MDI_ARROW_SPLIT_HORIZONTAL "\xf3\xb0\xa4\xbb" // U+F093B +#define ICON_MDI_ARROW_SPLIT_VERTICAL "\xf3\xb0\xa4\xbc" // U+F093C +#define ICON_MDI_ARROW_TOP_LEFT "\xf3\xb0\x81\x9b" // U+F005B +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_BOX "\xf3\xb1\xa5\xa8" // U+F1968 +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xa9" // U+F1969 +#define ICON_MDI_ARROW_TOP_LEFT_BOLD_OUTLINE "\xf3\xb0\xa7\x83" // U+F09C3 +#define ICON_MDI_ARROW_TOP_LEFT_BOTTOM_RIGHT "\xf3\xb0\xb9\xb5" // U+F0E75 +#define ICON_MDI_ARROW_TOP_LEFT_BOTTOM_RIGHT_BOLD "\xf3\xb0\xb9\xb6" // U+F0E76 +#define ICON_MDI_ARROW_TOP_LEFT_THICK "\xf3\xb0\xa7\x84" // U+F09C4 +#define ICON_MDI_ARROW_TOP_LEFT_THIN "\xf3\xb1\xa6\xb5" // U+F19B5 +#define ICON_MDI_ARROW_TOP_LEFT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x93" // U+F1593 +#define ICON_MDI_ARROW_TOP_RIGHT "\xf3\xb0\x81\x9c" // U+F005C +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_BOX "\xf3\xb1\xa5\xaa" // U+F196A +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_BOX_OUTLINE "\xf3\xb1\xa5\xab" // U+F196B +#define ICON_MDI_ARROW_TOP_RIGHT_BOLD_OUTLINE "\xf3\xb0\xa7\x85" // U+F09C5 +#define ICON_MDI_ARROW_TOP_RIGHT_BOTTOM_LEFT "\xf3\xb0\xb9\xb7" // U+F0E77 +#define ICON_MDI_ARROW_TOP_RIGHT_BOTTOM_LEFT_BOLD "\xf3\xb0\xb9\xb8" // U+F0E78 +#define ICON_MDI_ARROW_TOP_RIGHT_THICK "\xf3\xb0\xa7\x86" // U+F09C6 +#define ICON_MDI_ARROW_TOP_RIGHT_THIN "\xf3\xb1\xa6\xb4" // U+F19B4 +#define ICON_MDI_ARROW_TOP_RIGHT_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x94" // U+F1594 +#define ICON_MDI_ARROW_U_DOWN_LEFT "\xf3\xb1\x9e\xad" // U+F17AD +#define ICON_MDI_ARROW_U_DOWN_LEFT_BOLD "\xf3\xb1\x9e\xae" // U+F17AE +#define ICON_MDI_ARROW_U_DOWN_RIGHT "\xf3\xb1\x9e\xaf" // U+F17AF +#define ICON_MDI_ARROW_U_DOWN_RIGHT_BOLD "\xf3\xb1\x9e\xb0" // U+F17B0 +#define ICON_MDI_ARROW_U_LEFT_BOTTOM "\xf3\xb1\x9e\xb1" // U+F17B1 +#define ICON_MDI_ARROW_U_LEFT_BOTTOM_BOLD "\xf3\xb1\x9e\xb2" // U+F17B2 +#define ICON_MDI_ARROW_U_LEFT_TOP "\xf3\xb1\x9e\xb3" // U+F17B3 +#define ICON_MDI_ARROW_U_LEFT_TOP_BOLD "\xf3\xb1\x9e\xb4" // U+F17B4 +#define ICON_MDI_ARROW_U_RIGHT_BOTTOM "\xf3\xb1\x9e\xb5" // U+F17B5 +#define ICON_MDI_ARROW_U_RIGHT_BOTTOM_BOLD "\xf3\xb1\x9e\xb6" // U+F17B6 +#define ICON_MDI_ARROW_U_RIGHT_TOP "\xf3\xb1\x9e\xb7" // U+F17B7 +#define ICON_MDI_ARROW_U_RIGHT_TOP_BOLD "\xf3\xb1\x9e\xb8" // U+F17B8 +#define ICON_MDI_ARROW_U_UP_LEFT "\xf3\xb1\x9e\xb9" // U+F17B9 +#define ICON_MDI_ARROW_U_UP_LEFT_BOLD "\xf3\xb1\x9e\xba" // U+F17BA +#define ICON_MDI_ARROW_U_UP_RIGHT "\xf3\xb1\x9e\xbb" // U+F17BB +#define ICON_MDI_ARROW_U_UP_RIGHT_BOLD "\xf3\xb1\x9e\xbc" // U+F17BC +#define ICON_MDI_ARROW_UP "\xf3\xb0\x81\x9d" // U+F005D +#define ICON_MDI_ARROW_UP_BOLD "\xf3\xb0\x9c\xb7" // U+F0737 +#define ICON_MDI_ARROW_UP_BOLD_BOX "\xf3\xb0\x9c\xb8" // U+F0738 +#define ICON_MDI_ARROW_UP_BOLD_BOX_OUTLINE "\xf3\xb0\x9c\xb9" // U+F0739 +#define ICON_MDI_ARROW_UP_BOLD_CIRCLE "\xf3\xb0\x81\x9f" // U+F005F +#define ICON_MDI_ARROW_UP_BOLD_CIRCLE_OUTLINE "\xf3\xb0\x81\xa0" // U+F0060 +#define ICON_MDI_ARROW_UP_BOLD_HEXAGON_OUTLINE "\xf3\xb0\x81\xa1" // U+F0061 +#define ICON_MDI_ARROW_UP_BOLD_OUTLINE "\xf3\xb0\xa7\x87" // U+F09C7 +#define ICON_MDI_ARROW_UP_BOX "\xf3\xb0\x9b\x83" // U+F06C3 +#define ICON_MDI_ARROW_UP_CIRCLE "\xf3\xb0\xb3\xa1" // U+F0CE1 +#define ICON_MDI_ARROW_UP_CIRCLE_OUTLINE "\xf3\xb0\xb3\xa2" // U+F0CE2 +#define ICON_MDI_ARROW_UP_DOWN "\xf3\xb0\xb9\xb9" // U+F0E79 +#define ICON_MDI_ARROW_UP_DOWN_BOLD "\xf3\xb0\xb9\xba" // U+F0E7A +#define ICON_MDI_ARROW_UP_DOWN_BOLD_OUTLINE "\xf3\xb0\xa7\x88" // U+F09C8 +#define ICON_MDI_ARROW_UP_DROP_CIRCLE "\xf3\xb0\x81\xa2" // U+F0062 +#define ICON_MDI_ARROW_UP_DROP_CIRCLE_OUTLINE "\xf3\xb0\x81\xa3" // U+F0063 +#define ICON_MDI_ARROW_UP_LEFT "\xf3\xb1\x9e\xbd" // U+F17BD +#define ICON_MDI_ARROW_UP_LEFT_BOLD "\xf3\xb1\x9e\xbe" // U+F17BE +#define ICON_MDI_ARROW_UP_RIGHT "\xf3\xb1\x9e\xbf" // U+F17BF +#define ICON_MDI_ARROW_UP_RIGHT_BOLD "\xf3\xb1\x9f\x80" // U+F17C0 +#define ICON_MDI_ARROW_UP_THICK "\xf3\xb0\x81\x9e" // U+F005E +#define ICON_MDI_ARROW_UP_THIN "\xf3\xb1\xa6\xb2" // U+F19B2 +#define ICON_MDI_ARROW_UP_THIN_CIRCLE_OUTLINE "\xf3\xb1\x96\x97" // U+F1597 +#define ICON_MDI_ARROW_VERTICAL_LOCK "\xf3\xb1\x85\x9c" // U+F115C +#define ICON_MDI_ARTBOARD "\xf3\xb1\xae\x9a" // U+F1B9A +#define ICON_MDI_ARTSTATION "\xf3\xb0\xad\x9b" // U+F0B5B +#define ICON_MDI_ASPECT_RATIO "\xf3\xb0\xa8\xa4" // U+F0A24 +#define ICON_MDI_ASSISTANT "\xf3\xb0\x81\xa4" // U+F0064 +#define ICON_MDI_ASTERISK "\xf3\xb0\x9b\x84" // U+F06C4 +#define ICON_MDI_ASTERISK_CIRCLE_OUTLINE "\xf3\xb1\xa8\xa7" // U+F1A27 +#define ICON_MDI_AT "\xf3\xb0\x81\xa5" // U+F0065 +#define ICON_MDI_ATLASSIAN "\xf3\xb0\xa0\x84" // U+F0804 +#define ICON_MDI_ATM "\xf3\xb0\xb5\x87" // U+F0D47 +#define ICON_MDI_ATOM "\xf3\xb0\x9d\xa8" // U+F0768 +#define ICON_MDI_ATOM_VARIANT "\xf3\xb0\xb9\xbb" // U+F0E7B +#define ICON_MDI_ATTACHMENT "\xf3\xb0\x81\xa6" // U+F0066 +#define ICON_MDI_ATTACHMENT_CHECK "\xf3\xb1\xab\x81" // U+F1AC1 +#define ICON_MDI_ATTACHMENT_LOCK "\xf3\xb1\xa7\x84" // U+F19C4 +#define ICON_MDI_ATTACHMENT_MINUS "\xf3\xb1\xab\x82" // U+F1AC2 +#define ICON_MDI_ATTACHMENT_OFF "\xf3\xb1\xab\x83" // U+F1AC3 +#define ICON_MDI_ATTACHMENT_PLUS "\xf3\xb1\xab\x84" // U+F1AC4 +#define ICON_MDI_ATTACHMENT_REMOVE "\xf3\xb1\xab\x85" // U+F1AC5 +#define ICON_MDI_ATV "\xf3\xb1\xad\xb0" // U+F1B70 +#define ICON_MDI_AUDIO_INPUT_RCA "\xf3\xb1\xa1\xab" // U+F186B +#define ICON_MDI_AUDIO_INPUT_STEREO_MINIJACK "\xf3\xb1\xa1\xac" // U+F186C +#define ICON_MDI_AUDIO_INPUT_XLR "\xf3\xb1\xa1\xad" // U+F186D +#define ICON_MDI_AUDIO_VIDEO "\xf3\xb0\xa4\xbd" // U+F093D +#define ICON_MDI_AUDIO_VIDEO_OFF "\xf3\xb1\x86\xb6" // U+F11B6 +#define ICON_MDI_AUGMENTED_REALITY "\xf3\xb0\xa1\x90" // U+F0850 +#define ICON_MDI_AURORA "\xf3\xb1\xae\xb9" // U+F1BB9 +#define ICON_MDI_AUTO_DOWNLOAD "\xf3\xb1\x8d\xbe" // U+F137E +#define ICON_MDI_AUTO_FIX "\xf3\xb0\x81\xa8" // U+F0068 +#define ICON_MDI_AUTO_MODE "\xf3\xb1\xb0\xa0" // U+F1C20 +#define ICON_MDI_AUTO_UPLOAD "\xf3\xb0\x81\xa9" // U+F0069 +#define ICON_MDI_AUTORENEW "\xf3\xb0\x81\xaa" // U+F006A +#define ICON_MDI_AUTORENEW_OFF "\xf3\xb1\xa7\xa7" // U+F19E7 +#define ICON_MDI_AV_TIMER "\xf3\xb0\x81\xab" // U+F006B +#define ICON_MDI_AWNING "\xf3\xb1\xae\x87" // U+F1B87 +#define ICON_MDI_AWNING_OUTLINE "\xf3\xb1\xae\x88" // U+F1B88 +#define ICON_MDI_AWS "\xf3\xb0\xb8\x8f" // U+F0E0F +#define ICON_MDI_AXE "\xf3\xb0\xa3\x88" // U+F08C8 +#define ICON_MDI_AXE_BATTLE "\xf3\xb1\xa1\x82" // U+F1842 +#define ICON_MDI_AXIS "\xf3\xb0\xb5\x88" // U+F0D48 +#define ICON_MDI_AXIS_ARROW "\xf3\xb0\xb5\x89" // U+F0D49 +#define ICON_MDI_AXIS_ARROW_INFO "\xf3\xb1\x90\x8e" // U+F140E +#define ICON_MDI_AXIS_ARROW_LOCK "\xf3\xb0\xb5\x8a" // U+F0D4A +#define ICON_MDI_AXIS_LOCK "\xf3\xb0\xb5\x8b" // U+F0D4B +#define ICON_MDI_AXIS_X_ARROW "\xf3\xb0\xb5\x8c" // U+F0D4C +#define ICON_MDI_AXIS_X_ARROW_LOCK "\xf3\xb0\xb5\x8d" // U+F0D4D +#define ICON_MDI_AXIS_X_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x8e" // U+F0D4E +#define ICON_MDI_AXIS_X_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x8f" // U+F0D4F +#define ICON_MDI_AXIS_X_Y_ARROW_LOCK "\xf3\xb0\xb5\x90" // U+F0D50 +#define ICON_MDI_AXIS_Y_ARROW "\xf3\xb0\xb5\x91" // U+F0D51 +#define ICON_MDI_AXIS_Y_ARROW_LOCK "\xf3\xb0\xb5\x92" // U+F0D52 +#define ICON_MDI_AXIS_Y_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x93" // U+F0D53 +#define ICON_MDI_AXIS_Y_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x94" // U+F0D54 +#define ICON_MDI_AXIS_Z_ARROW "\xf3\xb0\xb5\x95" // U+F0D55 +#define ICON_MDI_AXIS_Z_ARROW_LOCK "\xf3\xb0\xb5\x96" // U+F0D56 +#define ICON_MDI_AXIS_Z_ROTATE_CLOCKWISE "\xf3\xb0\xb5\x97" // U+F0D57 +#define ICON_MDI_AXIS_Z_ROTATE_COUNTERCLOCKWISE "\xf3\xb0\xb5\x98" // U+F0D58 +#define ICON_MDI_BABEL "\xf3\xb0\xa8\xa5" // U+F0A25 +#define ICON_MDI_BABY "\xf3\xb0\x81\xac" // U+F006C +#define ICON_MDI_BABY_BOTTLE "\xf3\xb0\xbc\xb9" // U+F0F39 +#define ICON_MDI_BABY_BOTTLE_OUTLINE "\xf3\xb0\xbc\xba" // U+F0F3A +#define ICON_MDI_BABY_BUGGY "\xf3\xb1\x8f\xa0" // U+F13E0 +#define ICON_MDI_BABY_BUGGY_OFF "\xf3\xb1\xab\xb3" // U+F1AF3 +#define ICON_MDI_BABY_CARRIAGE "\xf3\xb0\x9a\x8f" // U+F068F +#define ICON_MDI_BABY_CARRIAGE_OFF "\xf3\xb0\xbe\xa0" // U+F0FA0 +#define ICON_MDI_BABY_FACE "\xf3\xb0\xb9\xbc" // U+F0E7C +#define ICON_MDI_BABY_FACE_OUTLINE "\xf3\xb0\xb9\xbd" // U+F0E7D +#define ICON_MDI_BACKBURGER "\xf3\xb0\x81\xad" // U+F006D +#define ICON_MDI_BACKSPACE "\xf3\xb0\x81\xae" // U+F006E +#define ICON_MDI_BACKSPACE_OUTLINE "\xf3\xb0\xad\x9c" // U+F0B5C +#define ICON_MDI_BACKSPACE_REVERSE "\xf3\xb0\xb9\xbe" // U+F0E7E +#define ICON_MDI_BACKSPACE_REVERSE_OUTLINE "\xf3\xb0\xb9\xbf" // U+F0E7F +#define ICON_MDI_BACKUP_RESTORE "\xf3\xb0\x81\xaf" // U+F006F +#define ICON_MDI_BACTERIA "\xf3\xb0\xbb\x95" // U+F0ED5 +#define ICON_MDI_BACTERIA_OUTLINE "\xf3\xb0\xbb\x96" // U+F0ED6 +#define ICON_MDI_BADGE_ACCOUNT "\xf3\xb0\xb6\xa7" // U+F0DA7 +#define ICON_MDI_BADGE_ACCOUNT_ALERT "\xf3\xb0\xb6\xa8" // U+F0DA8 +#define ICON_MDI_BADGE_ACCOUNT_ALERT_OUTLINE "\xf3\xb0\xb6\xa9" // U+F0DA9 +#define ICON_MDI_BADGE_ACCOUNT_HORIZONTAL "\xf3\xb0\xb8\x8d" // U+F0E0D +#define ICON_MDI_BADGE_ACCOUNT_HORIZONTAL_OUTLINE "\xf3\xb0\xb8\x8e" // U+F0E0E +#define ICON_MDI_BADGE_ACCOUNT_OUTLINE "\xf3\xb0\xb6\xaa" // U+F0DAA +#define ICON_MDI_BADMINTON "\xf3\xb0\xa1\x91" // U+F0851 +#define ICON_MDI_BAG_CARRY_ON "\xf3\xb0\xbc\xbb" // U+F0F3B +#define ICON_MDI_BAG_CARRY_ON_CHECK "\xf3\xb0\xb5\xa5" // U+F0D65 +#define ICON_MDI_BAG_CARRY_ON_OFF "\xf3\xb0\xbc\xbc" // U+F0F3C +#define ICON_MDI_BAG_CHECKED "\xf3\xb0\xbc\xbd" // U+F0F3D +#define ICON_MDI_BAG_PERSONAL "\xf3\xb0\xb8\x90" // U+F0E10 +#define ICON_MDI_BAG_PERSONAL_OFF "\xf3\xb0\xb8\x91" // U+F0E11 +#define ICON_MDI_BAG_PERSONAL_OFF_OUTLINE "\xf3\xb0\xb8\x92" // U+F0E12 +#define ICON_MDI_BAG_PERSONAL_OUTLINE "\xf3\xb0\xb8\x93" // U+F0E13 +#define ICON_MDI_BAG_PERSONAL_PLUS "\xf3\xb1\xb2\xa4" // U+F1CA4 +#define ICON_MDI_BAG_PERSONAL_PLUS_OUTLINE "\xf3\xb1\xb2\xa5" // U+F1CA5 +#define ICON_MDI_BAG_PERSONAL_TAG "\xf3\xb1\xac\x8c" // U+F1B0C +#define ICON_MDI_BAG_PERSONAL_TAG_OUTLINE "\xf3\xb1\xac\x8d" // U+F1B0D +#define ICON_MDI_BAG_SUITCASE "\xf3\xb1\x96\x8b" // U+F158B +#define ICON_MDI_BAG_SUITCASE_OFF "\xf3\xb1\x96\x8d" // U+F158D +#define ICON_MDI_BAG_SUITCASE_OFF_OUTLINE "\xf3\xb1\x96\x8e" // U+F158E +#define ICON_MDI_BAG_SUITCASE_OUTLINE "\xf3\xb1\x96\x8c" // U+F158C +#define ICON_MDI_BAGUETTE "\xf3\xb0\xbc\xbe" // U+F0F3E +#define ICON_MDI_BALCONY "\xf3\xb1\xa0\x97" // U+F1817 +#define ICON_MDI_BALLOON "\xf3\xb0\xa8\xa6" // U+F0A26 +#define ICON_MDI_BALLOT "\xf3\xb0\xa7\x89" // U+F09C9 +#define ICON_MDI_BALLOT_OUTLINE "\xf3\xb0\xa7\x8a" // U+F09CA +#define ICON_MDI_BALLOT_RECOUNT "\xf3\xb0\xb0\xb9" // U+F0C39 +#define ICON_MDI_BALLOT_RECOUNT_OUTLINE "\xf3\xb0\xb0\xba" // U+F0C3A +#define ICON_MDI_BANDAGE "\xf3\xb0\xb6\xaf" // U+F0DAF +#define ICON_MDI_BANK "\xf3\xb0\x81\xb0" // U+F0070 +#define ICON_MDI_BANK_CHECK "\xf3\xb1\x99\x95" // U+F1655 +#define ICON_MDI_BANK_CIRCLE "\xf3\xb1\xb0\x83" // U+F1C03 +#define ICON_MDI_BANK_CIRCLE_OUTLINE "\xf3\xb1\xb0\x84" // U+F1C04 +#define ICON_MDI_BANK_MINUS "\xf3\xb0\xb6\xb0" // U+F0DB0 +#define ICON_MDI_BANK_OFF "\xf3\xb1\x99\x96" // U+F1656 +#define ICON_MDI_BANK_OFF_OUTLINE "\xf3\xb1\x99\x97" // U+F1657 +#define ICON_MDI_BANK_OUTLINE "\xf3\xb0\xba\x80" // U+F0E80 +#define ICON_MDI_BANK_PLUS "\xf3\xb0\xb6\xb1" // U+F0DB1 +#define ICON_MDI_BANK_REMOVE "\xf3\xb0\xb6\xb2" // U+F0DB2 +#define ICON_MDI_BANK_TRANSFER "\xf3\xb0\xa8\xa7" // U+F0A27 +#define ICON_MDI_BANK_TRANSFER_IN "\xf3\xb0\xa8\xa8" // U+F0A28 +#define ICON_MDI_BANK_TRANSFER_OUT "\xf3\xb0\xa8\xa9" // U+F0A29 +#define ICON_MDI_BARCODE "\xf3\xb0\x81\xb1" // U+F0071 +#define ICON_MDI_BARCODE_OFF "\xf3\xb1\x88\xb6" // U+F1236 +#define ICON_MDI_BARCODE_SCAN "\xf3\xb0\x81\xb2" // U+F0072 +#define ICON_MDI_BARLEY "\xf3\xb0\x81\xb3" // U+F0073 +#define ICON_MDI_BARLEY_OFF "\xf3\xb0\xad\x9d" // U+F0B5D +#define ICON_MDI_BARN "\xf3\xb0\xad\x9e" // U+F0B5E +#define ICON_MDI_BARREL "\xf3\xb0\x81\xb4" // U+F0074 +#define ICON_MDI_BARREL_OUTLINE "\xf3\xb1\xa8\xa8" // U+F1A28 +#define ICON_MDI_BASEBALL "\xf3\xb0\xa1\x92" // U+F0852 +#define ICON_MDI_BASEBALL_BAT "\xf3\xb0\xa1\x93" // U+F0853 +#define ICON_MDI_BASEBALL_DIAMOND "\xf3\xb1\x97\xac" // U+F15EC +#define ICON_MDI_BASEBALL_DIAMOND_OUTLINE "\xf3\xb1\x97\xad" // U+F15ED +#define ICON_MDI_BASEBALL_OUTLINE "\xf3\xb1\xb1\x9a" // U+F1C5A +#define ICON_MDI_BASH "\xf3\xb1\x86\x83" // U+F1183 +#define ICON_MDI_BASKET "\xf3\xb0\x81\xb6" // U+F0076 +#define ICON_MDI_BASKET_CHECK "\xf3\xb1\xa3\xa5" // U+F18E5 +#define ICON_MDI_BASKET_CHECK_OUTLINE "\xf3\xb1\xa3\xa6" // U+F18E6 +#define ICON_MDI_BASKET_FILL "\xf3\xb0\x81\xb7" // U+F0077 +#define ICON_MDI_BASKET_MINUS "\xf3\xb1\x94\xa3" // U+F1523 +#define ICON_MDI_BASKET_MINUS_OUTLINE "\xf3\xb1\x94\xa4" // U+F1524 +#define ICON_MDI_BASKET_OFF "\xf3\xb1\x94\xa5" // U+F1525 +#define ICON_MDI_BASKET_OFF_OUTLINE "\xf3\xb1\x94\xa6" // U+F1526 +#define ICON_MDI_BASKET_OUTLINE "\xf3\xb1\x86\x81" // U+F1181 +#define ICON_MDI_BASKET_PLUS "\xf3\xb1\x94\xa7" // U+F1527 +#define ICON_MDI_BASKET_PLUS_OUTLINE "\xf3\xb1\x94\xa8" // U+F1528 +#define ICON_MDI_BASKET_REMOVE "\xf3\xb1\x94\xa9" // U+F1529 +#define ICON_MDI_BASKET_REMOVE_OUTLINE "\xf3\xb1\x94\xaa" // U+F152A +#define ICON_MDI_BASKET_UNFILL "\xf3\xb0\x81\xb8" // U+F0078 +#define ICON_MDI_BASKETBALL "\xf3\xb0\xa0\x86" // U+F0806 +#define ICON_MDI_BASKETBALL_HOOP "\xf3\xb0\xb0\xbb" // U+F0C3B +#define ICON_MDI_BASKETBALL_HOOP_OUTLINE "\xf3\xb0\xb0\xbc" // U+F0C3C +#define ICON_MDI_BAT "\xf3\xb0\xad\x9f" // U+F0B5F +#define ICON_MDI_BATHTUB "\xf3\xb1\xa0\x98" // U+F1818 +#define ICON_MDI_BATHTUB_OUTLINE "\xf3\xb1\xa0\x99" // U+F1819 +#define ICON_MDI_BATTERY "\xf3\xb0\x81\xb9" // U+F0079 +#define ICON_MDI_BATTERY_10 "\xf3\xb0\x81\xba" // U+F007A +#define ICON_MDI_BATTERY_10_BLUETOOTH "\xf3\xb0\xa4\xbe" // U+F093E +#define ICON_MDI_BATTERY_20 "\xf3\xb0\x81\xbb" // U+F007B +#define ICON_MDI_BATTERY_20_BLUETOOTH "\xf3\xb0\xa4\xbf" // U+F093F +#define ICON_MDI_BATTERY_30 "\xf3\xb0\x81\xbc" // U+F007C +#define ICON_MDI_BATTERY_30_BLUETOOTH "\xf3\xb0\xa5\x80" // U+F0940 +#define ICON_MDI_BATTERY_40 "\xf3\xb0\x81\xbd" // U+F007D +#define ICON_MDI_BATTERY_40_BLUETOOTH "\xf3\xb0\xa5\x81" // U+F0941 +#define ICON_MDI_BATTERY_50 "\xf3\xb0\x81\xbe" // U+F007E +#define ICON_MDI_BATTERY_50_BLUETOOTH "\xf3\xb0\xa5\x82" // U+F0942 +#define ICON_MDI_BATTERY_60 "\xf3\xb0\x81\xbf" // U+F007F +#define ICON_MDI_BATTERY_60_BLUETOOTH "\xf3\xb0\xa5\x83" // U+F0943 +#define ICON_MDI_BATTERY_70 "\xf3\xb0\x82\x80" // U+F0080 +#define ICON_MDI_BATTERY_70_BLUETOOTH "\xf3\xb0\xa5\x84" // U+F0944 +#define ICON_MDI_BATTERY_80 "\xf3\xb0\x82\x81" // U+F0081 +#define ICON_MDI_BATTERY_80_BLUETOOTH "\xf3\xb0\xa5\x85" // U+F0945 +#define ICON_MDI_BATTERY_90 "\xf3\xb0\x82\x82" // U+F0082 +#define ICON_MDI_BATTERY_90_BLUETOOTH "\xf3\xb0\xa5\x86" // U+F0946 +#define ICON_MDI_BATTERY_ALERT "\xf3\xb0\x82\x83" // U+F0083 +#define ICON_MDI_BATTERY_ALERT_BLUETOOTH "\xf3\xb0\xa5\x87" // U+F0947 +#define ICON_MDI_BATTERY_ALERT_VARIANT "\xf3\xb1\x83\x8c" // U+F10CC +#define ICON_MDI_BATTERY_ALERT_VARIANT_OUTLINE "\xf3\xb1\x83\x8d" // U+F10CD +#define ICON_MDI_BATTERY_ARROW_DOWN "\xf3\xb1\x9f\x9e" // U+F17DE +#define ICON_MDI_BATTERY_ARROW_DOWN_OUTLINE "\xf3\xb1\x9f\x9f" // U+F17DF +#define ICON_MDI_BATTERY_ARROW_UP "\xf3\xb1\x9f\xa0" // U+F17E0 +#define ICON_MDI_BATTERY_ARROW_UP_OUTLINE "\xf3\xb1\x9f\xa1" // U+F17E1 +#define ICON_MDI_BATTERY_BLUETOOTH "\xf3\xb0\xa5\x88" // U+F0948 +#define ICON_MDI_BATTERY_BLUETOOTH_VARIANT "\xf3\xb0\xa5\x89" // U+F0949 +#define ICON_MDI_BATTERY_CHARGING "\xf3\xb0\x82\x84" // U+F0084 +#define ICON_MDI_BATTERY_CHARGING_10 "\xf3\xb0\xa2\x9c" // U+F089C +#define ICON_MDI_BATTERY_CHARGING_100 "\xf3\xb0\x82\x85" // U+F0085 +#define ICON_MDI_BATTERY_CHARGING_20 "\xf3\xb0\x82\x86" // U+F0086 +#define ICON_MDI_BATTERY_CHARGING_30 "\xf3\xb0\x82\x87" // U+F0087 +#define ICON_MDI_BATTERY_CHARGING_40 "\xf3\xb0\x82\x88" // U+F0088 +#define ICON_MDI_BATTERY_CHARGING_50 "\xf3\xb0\xa2\x9d" // U+F089D +#define ICON_MDI_BATTERY_CHARGING_60 "\xf3\xb0\x82\x89" // U+F0089 +#define ICON_MDI_BATTERY_CHARGING_70 "\xf3\xb0\xa2\x9e" // U+F089E +#define ICON_MDI_BATTERY_CHARGING_80 "\xf3\xb0\x82\x8a" // U+F008A +#define ICON_MDI_BATTERY_CHARGING_90 "\xf3\xb0\x82\x8b" // U+F008B +#define ICON_MDI_BATTERY_CHARGING_HIGH "\xf3\xb1\x8a\xa6" // U+F12A6 +#define ICON_MDI_BATTERY_CHARGING_LOW "\xf3\xb1\x8a\xa4" // U+F12A4 +#define ICON_MDI_BATTERY_CHARGING_MEDIUM "\xf3\xb1\x8a\xa5" // U+F12A5 +#define ICON_MDI_BATTERY_CHARGING_OUTLINE "\xf3\xb0\xa2\x9f" // U+F089F +#define ICON_MDI_BATTERY_CHARGING_WIRELESS "\xf3\xb0\xa0\x87" // U+F0807 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_10 "\xf3\xb0\xa0\x88" // U+F0808 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_20 "\xf3\xb0\xa0\x89" // U+F0809 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_30 "\xf3\xb0\xa0\x8a" // U+F080A +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_40 "\xf3\xb0\xa0\x8b" // U+F080B +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_50 "\xf3\xb0\xa0\x8c" // U+F080C +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_60 "\xf3\xb0\xa0\x8d" // U+F080D +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_70 "\xf3\xb0\xa0\x8e" // U+F080E +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_80 "\xf3\xb0\xa0\x8f" // U+F080F +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_90 "\xf3\xb0\xa0\x90" // U+F0810 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_ALERT "\xf3\xb0\xa0\x91" // U+F0811 +#define ICON_MDI_BATTERY_CHARGING_WIRELESS_OUTLINE "\xf3\xb0\xa0\x92" // U+F0812 +#define ICON_MDI_BATTERY_CHECK "\xf3\xb1\x9f\xa2" // U+F17E2 +#define ICON_MDI_BATTERY_CHECK_OUTLINE "\xf3\xb1\x9f\xa3" // U+F17E3 +#define ICON_MDI_BATTERY_CLOCK "\xf3\xb1\xa7\xa5" // U+F19E5 +#define ICON_MDI_BATTERY_CLOCK_OUTLINE "\xf3\xb1\xa7\xa6" // U+F19E6 +#define ICON_MDI_BATTERY_HEART "\xf3\xb1\x88\x8f" // U+F120F +#define ICON_MDI_BATTERY_HEART_OUTLINE "\xf3\xb1\x88\x90" // U+F1210 +#define ICON_MDI_BATTERY_HEART_VARIANT "\xf3\xb1\x88\x91" // U+F1211 +#define ICON_MDI_BATTERY_HIGH "\xf3\xb1\x8a\xa3" // U+F12A3 +#define ICON_MDI_BATTERY_LOCK "\xf3\xb1\x9e\x9c" // U+F179C +#define ICON_MDI_BATTERY_LOCK_OPEN "\xf3\xb1\x9e\x9d" // U+F179D +#define ICON_MDI_BATTERY_LOW "\xf3\xb1\x8a\xa1" // U+F12A1 +#define ICON_MDI_BATTERY_MEDIUM "\xf3\xb1\x8a\xa2" // U+F12A2 +#define ICON_MDI_BATTERY_MINUS "\xf3\xb1\x9f\xa4" // U+F17E4 +#define ICON_MDI_BATTERY_MINUS_OUTLINE "\xf3\xb1\x9f\xa5" // U+F17E5 +#define ICON_MDI_BATTERY_MINUS_VARIANT "\xf3\xb0\x82\x8c" // U+F008C +#define ICON_MDI_BATTERY_NEGATIVE "\xf3\xb0\x82\x8d" // U+F008D +#define ICON_MDI_BATTERY_OFF "\xf3\xb1\x89\x9d" // U+F125D +#define ICON_MDI_BATTERY_OFF_OUTLINE "\xf3\xb1\x89\x9e" // U+F125E +#define ICON_MDI_BATTERY_OUTLINE "\xf3\xb0\x82\x8e" // U+F008E +#define ICON_MDI_BATTERY_PLUS "\xf3\xb1\x9f\xa6" // U+F17E6 +#define ICON_MDI_BATTERY_PLUS_OUTLINE "\xf3\xb1\x9f\xa7" // U+F17E7 +#define ICON_MDI_BATTERY_PLUS_VARIANT "\xf3\xb0\x82\x8f" // U+F008F +#define ICON_MDI_BATTERY_POSITIVE "\xf3\xb0\x82\x90" // U+F0090 +#define ICON_MDI_BATTERY_REMOVE "\xf3\xb1\x9f\xa8" // U+F17E8 +#define ICON_MDI_BATTERY_REMOVE_OUTLINE "\xf3\xb1\x9f\xa9" // U+F17E9 +#define ICON_MDI_BATTERY_SYNC "\xf3\xb1\xa0\xb4" // U+F1834 +#define ICON_MDI_BATTERY_SYNC_OUTLINE "\xf3\xb1\xa0\xb5" // U+F1835 +#define ICON_MDI_BATTERY_UNKNOWN "\xf3\xb0\x82\x91" // U+F0091 +#define ICON_MDI_BATTERY_UNKNOWN_BLUETOOTH "\xf3\xb0\xa5\x8a" // U+F094A +#define ICON_MDI_BEACH "\xf3\xb0\x82\x92" // U+F0092 +#define ICON_MDI_BEAKER "\xf3\xb0\xb3\xaa" // U+F0CEA +#define ICON_MDI_BEAKER_ALERT "\xf3\xb1\x88\xa9" // U+F1229 +#define ICON_MDI_BEAKER_ALERT_OUTLINE "\xf3\xb1\x88\xaa" // U+F122A +#define ICON_MDI_BEAKER_CHECK "\xf3\xb1\x88\xab" // U+F122B +#define ICON_MDI_BEAKER_CHECK_OUTLINE "\xf3\xb1\x88\xac" // U+F122C +#define ICON_MDI_BEAKER_MINUS "\xf3\xb1\x88\xad" // U+F122D +#define ICON_MDI_BEAKER_MINUS_OUTLINE "\xf3\xb1\x88\xae" // U+F122E +#define ICON_MDI_BEAKER_OUTLINE "\xf3\xb0\x9a\x90" // U+F0690 +#define ICON_MDI_BEAKER_PLUS "\xf3\xb1\x88\xaf" // U+F122F +#define ICON_MDI_BEAKER_PLUS_OUTLINE "\xf3\xb1\x88\xb0" // U+F1230 +#define ICON_MDI_BEAKER_QUESTION "\xf3\xb1\x88\xb1" // U+F1231 +#define ICON_MDI_BEAKER_QUESTION_OUTLINE "\xf3\xb1\x88\xb2" // U+F1232 +#define ICON_MDI_BEAKER_REMOVE "\xf3\xb1\x88\xb3" // U+F1233 +#define ICON_MDI_BEAKER_REMOVE_OUTLINE "\xf3\xb1\x88\xb4" // U+F1234 +#define ICON_MDI_BED "\xf3\xb0\x8b\xa3" // U+F02E3 +#define ICON_MDI_BED_CLOCK "\xf3\xb1\xae\x94" // U+F1B94 +#define ICON_MDI_BED_DOUBLE "\xf3\xb0\xbf\x94" // U+F0FD4 +#define ICON_MDI_BED_DOUBLE_OUTLINE "\xf3\xb0\xbf\x93" // U+F0FD3 +#define ICON_MDI_BED_EMPTY "\xf3\xb0\xa2\xa0" // U+F08A0 +#define ICON_MDI_BED_KING "\xf3\xb0\xbf\x92" // U+F0FD2 +#define ICON_MDI_BED_KING_OUTLINE "\xf3\xb0\xbf\x91" // U+F0FD1 +#define ICON_MDI_BED_OUTLINE "\xf3\xb0\x82\x99" // U+F0099 +#define ICON_MDI_BED_QUEEN "\xf3\xb0\xbf\x90" // U+F0FD0 +#define ICON_MDI_BED_QUEEN_OUTLINE "\xf3\xb0\xbf\x9b" // U+F0FDB +#define ICON_MDI_BED_SINGLE "\xf3\xb1\x81\xad" // U+F106D +#define ICON_MDI_BED_SINGLE_OUTLINE "\xf3\xb1\x81\xae" // U+F106E +#define ICON_MDI_BEE "\xf3\xb0\xbe\xa1" // U+F0FA1 +#define ICON_MDI_BEE_FLOWER "\xf3\xb0\xbe\xa2" // U+F0FA2 +#define ICON_MDI_BEEHIVE_OFF_OUTLINE "\xf3\xb1\x8f\xad" // U+F13ED +#define ICON_MDI_BEEHIVE_OUTLINE "\xf3\xb1\x83\x8e" // U+F10CE +#define ICON_MDI_BEEKEEPER "\xf3\xb1\x93\xa2" // U+F14E2 +#define ICON_MDI_BEER "\xf3\xb0\x82\x98" // U+F0098 +#define ICON_MDI_BEER_OUTLINE "\xf3\xb1\x8c\x8c" // U+F130C +#define ICON_MDI_BELL "\xf3\xb0\x82\x9a" // U+F009A +#define ICON_MDI_BELL_ALERT "\xf3\xb0\xb5\x99" // U+F0D59 +#define ICON_MDI_BELL_ALERT_OUTLINE "\xf3\xb0\xba\x81" // U+F0E81 +#define ICON_MDI_BELL_BADGE "\xf3\xb1\x85\xab" // U+F116B +#define ICON_MDI_BELL_BADGE_OUTLINE "\xf3\xb0\x85\xb8" // U+F0178 +#define ICON_MDI_BELL_CANCEL "\xf3\xb1\x8f\xa7" // U+F13E7 +#define ICON_MDI_BELL_CANCEL_OUTLINE "\xf3\xb1\x8f\xa8" // U+F13E8 +#define ICON_MDI_BELL_CHECK "\xf3\xb1\x87\xa5" // U+F11E5 +#define ICON_MDI_BELL_CHECK_OUTLINE "\xf3\xb1\x87\xa6" // U+F11E6 +#define ICON_MDI_BELL_CIRCLE "\xf3\xb0\xb5\x9a" // U+F0D5A +#define ICON_MDI_BELL_CIRCLE_OUTLINE "\xf3\xb0\xb5\x9b" // U+F0D5B +#define ICON_MDI_BELL_COG "\xf3\xb1\xa8\xa9" // U+F1A29 +#define ICON_MDI_BELL_COG_OUTLINE "\xf3\xb1\xa8\xaa" // U+F1A2A +#define ICON_MDI_BELL_MINUS "\xf3\xb1\x8f\xa9" // U+F13E9 +#define ICON_MDI_BELL_MINUS_OUTLINE "\xf3\xb1\x8f\xaa" // U+F13EA +#define ICON_MDI_BELL_OFF "\xf3\xb0\x82\x9b" // U+F009B +#define ICON_MDI_BELL_OFF_OUTLINE "\xf3\xb0\xaa\x91" // U+F0A91 +#define ICON_MDI_BELL_OUTLINE "\xf3\xb0\x82\x9c" // U+F009C +#define ICON_MDI_BELL_PLUS "\xf3\xb0\x82\x9d" // U+F009D +#define ICON_MDI_BELL_PLUS_OUTLINE "\xf3\xb0\xaa\x92" // U+F0A92 +#define ICON_MDI_BELL_REMOVE "\xf3\xb1\x8f\xab" // U+F13EB +#define ICON_MDI_BELL_REMOVE_OUTLINE "\xf3\xb1\x8f\xac" // U+F13EC +#define ICON_MDI_BELL_RING "\xf3\xb0\x82\x9e" // U+F009E +#define ICON_MDI_BELL_RING_OUTLINE "\xf3\xb0\x82\x9f" // U+F009F +#define ICON_MDI_BELL_SLEEP "\xf3\xb0\x82\xa0" // U+F00A0 +#define ICON_MDI_BELL_SLEEP_OUTLINE "\xf3\xb0\xaa\x93" // U+F0A93 +#define ICON_MDI_BENCH "\xf3\xb1\xb0\xa1" // U+F1C21 +#define ICON_MDI_BENCH_BACK "\xf3\xb1\xb0\xa2" // U+F1C22 +#define ICON_MDI_BETA "\xf3\xb0\x82\xa1" // U+F00A1 +#define ICON_MDI_BETAMAX "\xf3\xb0\xa7\x8b" // U+F09CB +#define ICON_MDI_BIATHLON "\xf3\xb0\xb8\x94" // U+F0E14 +#define ICON_MDI_BICYCLE "\xf3\xb1\x82\x9c" // U+F109C +#define ICON_MDI_BICYCLE_BASKET "\xf3\xb1\x88\xb5" // U+F1235 +#define ICON_MDI_BICYCLE_CARGO "\xf3\xb1\xa2\x9c" // U+F189C +#define ICON_MDI_BICYCLE_ELECTRIC "\xf3\xb1\x96\xb4" // U+F15B4 +#define ICON_MDI_BICYCLE_PENNY_FARTHING "\xf3\xb1\x97\xa9" // U+F15E9 +#define ICON_MDI_BIKE "\xf3\xb0\x82\xa3" // U+F00A3 +#define ICON_MDI_BIKE_FAST "\xf3\xb1\x84\x9f" // U+F111F +#define ICON_MDI_BIKE_PEDAL "\xf3\xb1\xb0\xa3" // U+F1C23 +#define ICON_MDI_BIKE_PEDAL_CLIPLESS "\xf3\xb1\xb0\xa4" // U+F1C24 +#define ICON_MDI_BIKE_PEDAL_MOUNTAIN "\xf3\xb1\xb0\xa5" // U+F1C25 +#define ICON_MDI_BILLBOARD "\xf3\xb1\x80\x90" // U+F1010 +#define ICON_MDI_BILLIARDS "\xf3\xb0\xad\xa1" // U+F0B61 +#define ICON_MDI_BILLIARDS_RACK "\xf3\xb0\xad\xa2" // U+F0B62 +#define ICON_MDI_BINOCULARS "\xf3\xb0\x82\xa5" // U+F00A5 +#define ICON_MDI_BIO "\xf3\xb0\x82\xa6" // U+F00A6 +#define ICON_MDI_BIOHAZARD "\xf3\xb0\x82\xa7" // U+F00A7 +#define ICON_MDI_BIRD "\xf3\xb1\x97\x86" // U+F15C6 +#define ICON_MDI_BITBUCKET "\xf3\xb0\x82\xa8" // U+F00A8 +#define ICON_MDI_BITCOIN "\xf3\xb0\xa0\x93" // U+F0813 +#define ICON_MDI_BLACK_MESA "\xf3\xb0\x82\xa9" // U+F00A9 +#define ICON_MDI_BLENDER "\xf3\xb0\xb3\xab" // U+F0CEB +#define ICON_MDI_BLENDER_OUTLINE "\xf3\xb1\xa0\x9a" // U+F181A +#define ICON_MDI_BLENDER_SOFTWARE "\xf3\xb0\x82\xab" // U+F00AB +#define ICON_MDI_BLINDS "\xf3\xb0\x82\xac" // U+F00AC +#define ICON_MDI_BLINDS_HORIZONTAL "\xf3\xb1\xa8\xab" // U+F1A2B +#define ICON_MDI_BLINDS_HORIZONTAL_CLOSED "\xf3\xb1\xa8\xac" // U+F1A2C +#define ICON_MDI_BLINDS_OPEN "\xf3\xb1\x80\x91" // U+F1011 +#define ICON_MDI_BLINDS_VERTICAL "\xf3\xb1\xa8\xad" // U+F1A2D +#define ICON_MDI_BLINDS_VERTICAL_CLOSED "\xf3\xb1\xa8\xae" // U+F1A2E +#define ICON_MDI_BLOCK_HELPER "\xf3\xb0\x82\xad" // U+F00AD +#define ICON_MDI_BLOOD_BAG "\xf3\xb0\xb3\xac" // U+F0CEC +#define ICON_MDI_BLUETOOTH "\xf3\xb0\x82\xaf" // U+F00AF +#define ICON_MDI_BLUETOOTH_AUDIO "\xf3\xb0\x82\xb0" // U+F00B0 +#define ICON_MDI_BLUETOOTH_CONNECT "\xf3\xb0\x82\xb1" // U+F00B1 +#define ICON_MDI_BLUETOOTH_OFF "\xf3\xb0\x82\xb2" // U+F00B2 +#define ICON_MDI_BLUETOOTH_SETTINGS "\xf3\xb0\x82\xb3" // U+F00B3 +#define ICON_MDI_BLUETOOTH_TRANSFER "\xf3\xb0\x82\xb4" // U+F00B4 +#define ICON_MDI_BLUR "\xf3\xb0\x82\xb5" // U+F00B5 +#define ICON_MDI_BLUR_LINEAR "\xf3\xb0\x82\xb6" // U+F00B6 +#define ICON_MDI_BLUR_OFF "\xf3\xb0\x82\xb7" // U+F00B7 +#define ICON_MDI_BLUR_RADIAL "\xf3\xb0\x82\xb8" // U+F00B8 +#define ICON_MDI_BOLT "\xf3\xb0\xb6\xb3" // U+F0DB3 +#define ICON_MDI_BOMB "\xf3\xb0\x9a\x91" // U+F0691 +#define ICON_MDI_BOMB_OFF "\xf3\xb0\x9b\x85" // U+F06C5 +#define ICON_MDI_BONE "\xf3\xb0\x82\xb9" // U+F00B9 +#define ICON_MDI_BONE_OFF "\xf3\xb1\xa7\xa0" // U+F19E0 +#define ICON_MDI_BOOK "\xf3\xb0\x82\xba" // U+F00BA +#define ICON_MDI_BOOK_ACCOUNT "\xf3\xb1\x8e\xad" // U+F13AD +#define ICON_MDI_BOOK_ACCOUNT_OUTLINE "\xf3\xb1\x8e\xae" // U+F13AE +#define ICON_MDI_BOOK_ALERT "\xf3\xb1\x99\xbc" // U+F167C +#define ICON_MDI_BOOK_ALERT_OUTLINE "\xf3\xb1\x99\xbd" // U+F167D +#define ICON_MDI_BOOK_ALPHABET "\xf3\xb0\x98\x9d" // U+F061D +#define ICON_MDI_BOOK_ARROW_DOWN "\xf3\xb1\x99\xbe" // U+F167E +#define ICON_MDI_BOOK_ARROW_DOWN_OUTLINE "\xf3\xb1\x99\xbf" // U+F167F +#define ICON_MDI_BOOK_ARROW_LEFT "\xf3\xb1\x9a\x80" // U+F1680 +#define ICON_MDI_BOOK_ARROW_LEFT_OUTLINE "\xf3\xb1\x9a\x81" // U+F1681 +#define ICON_MDI_BOOK_ARROW_RIGHT "\xf3\xb1\x9a\x82" // U+F1682 +#define ICON_MDI_BOOK_ARROW_RIGHT_OUTLINE "\xf3\xb1\x9a\x83" // U+F1683 +#define ICON_MDI_BOOK_ARROW_UP "\xf3\xb1\x9a\x84" // U+F1684 +#define ICON_MDI_BOOK_ARROW_UP_OUTLINE "\xf3\xb1\x9a\x85" // U+F1685 +#define ICON_MDI_BOOK_CANCEL "\xf3\xb1\x9a\x86" // U+F1686 +#define ICON_MDI_BOOK_CANCEL_OUTLINE "\xf3\xb1\x9a\x87" // U+F1687 +#define ICON_MDI_BOOK_CHECK "\xf3\xb1\x93\xb3" // U+F14F3 +#define ICON_MDI_BOOK_CHECK_OUTLINE "\xf3\xb1\x93\xb4" // U+F14F4 +#define ICON_MDI_BOOK_CLOCK "\xf3\xb1\x9a\x88" // U+F1688 +#define ICON_MDI_BOOK_CLOCK_OUTLINE "\xf3\xb1\x9a\x89" // U+F1689 +#define ICON_MDI_BOOK_COG "\xf3\xb1\x9a\x8a" // U+F168A +#define ICON_MDI_BOOK_COG_OUTLINE "\xf3\xb1\x9a\x8b" // U+F168B +#define ICON_MDI_BOOK_CROSS "\xf3\xb0\x82\xa2" // U+F00A2 +#define ICON_MDI_BOOK_EDIT "\xf3\xb1\x9a\x8c" // U+F168C +#define ICON_MDI_BOOK_EDIT_OUTLINE "\xf3\xb1\x9a\x8d" // U+F168D +#define ICON_MDI_BOOK_EDUCATION "\xf3\xb1\x9b\x89" // U+F16C9 +#define ICON_MDI_BOOK_EDUCATION_OUTLINE "\xf3\xb1\x9b\x8a" // U+F16CA +#define ICON_MDI_BOOK_HEART "\xf3\xb1\xa8\x9d" // U+F1A1D +#define ICON_MDI_BOOK_HEART_OUTLINE "\xf3\xb1\xa8\x9e" // U+F1A1E +#define ICON_MDI_BOOK_INFORMATION_VARIANT "\xf3\xb1\x81\xaf" // U+F106F +#define ICON_MDI_BOOK_LOCK "\xf3\xb0\x9e\x9a" // U+F079A +#define ICON_MDI_BOOK_LOCK_OPEN "\xf3\xb0\x9e\x9b" // U+F079B +#define ICON_MDI_BOOK_LOCK_OPEN_OUTLINE "\xf3\xb1\x9a\x8e" // U+F168E +#define ICON_MDI_BOOK_LOCK_OUTLINE "\xf3\xb1\x9a\x8f" // U+F168F +#define ICON_MDI_BOOK_MARKER "\xf3\xb1\x9a\x90" // U+F1690 +#define ICON_MDI_BOOK_MARKER_OUTLINE "\xf3\xb1\x9a\x91" // U+F1691 +#define ICON_MDI_BOOK_MINUS "\xf3\xb0\x97\x99" // U+F05D9 +#define ICON_MDI_BOOK_MINUS_MULTIPLE "\xf3\xb0\xaa\x94" // U+F0A94 +#define ICON_MDI_BOOK_MINUS_MULTIPLE_OUTLINE "\xf3\xb0\xa4\x8b" // U+F090B +#define ICON_MDI_BOOK_MINUS_OUTLINE "\xf3\xb1\x9a\x92" // U+F1692 +#define ICON_MDI_BOOK_MULTIPLE "\xf3\xb0\x82\xbb" // U+F00BB +#define ICON_MDI_BOOK_MULTIPLE_OUTLINE "\xf3\xb0\x90\xb6" // U+F0436 +#define ICON_MDI_BOOK_MUSIC "\xf3\xb0\x81\xa7" // U+F0067 +#define ICON_MDI_BOOK_MUSIC_OUTLINE "\xf3\xb1\x9a\x93" // U+F1693 +#define ICON_MDI_BOOK_OFF "\xf3\xb1\x9a\x94" // U+F1694 +#define ICON_MDI_BOOK_OFF_OUTLINE "\xf3\xb1\x9a\x95" // U+F1695 +#define ICON_MDI_BOOK_OPEN "\xf3\xb0\x82\xbd" // U+F00BD +#define ICON_MDI_BOOK_OPEN_BLANK_VARIANT "\xf3\xb0\x82\xbe" // U+F00BE +#define ICON_MDI_BOOK_OPEN_OUTLINE "\xf3\xb0\xad\xa3" // U+F0B63 +#define ICON_MDI_BOOK_OPEN_PAGE_VARIANT "\xf3\xb0\x97\x9a" // U+F05DA +#define ICON_MDI_BOOK_OPEN_PAGE_VARIANT_OUTLINE "\xf3\xb1\x97\x96" // U+F15D6 +#define ICON_MDI_BOOK_OPEN_VARIANT "\xf3\xb1\x93\xb7" // U+F14F7 +#define ICON_MDI_BOOK_OUTLINE "\xf3\xb0\xad\xa4" // U+F0B64 +#define ICON_MDI_BOOK_PLAY "\xf3\xb0\xba\x82" // U+F0E82 +#define ICON_MDI_BOOK_PLAY_OUTLINE "\xf3\xb0\xba\x83" // U+F0E83 +#define ICON_MDI_BOOK_PLUS "\xf3\xb0\x97\x9b" // U+F05DB +#define ICON_MDI_BOOK_PLUS_MULTIPLE "\xf3\xb0\xaa\x95" // U+F0A95 +#define ICON_MDI_BOOK_PLUS_MULTIPLE_OUTLINE "\xf3\xb0\xab\x9e" // U+F0ADE +#define ICON_MDI_BOOK_PLUS_OUTLINE "\xf3\xb1\x9a\x96" // U+F1696 +#define ICON_MDI_BOOK_REFRESH "\xf3\xb1\x9a\x97" // U+F1697 +#define ICON_MDI_BOOK_REFRESH_OUTLINE "\xf3\xb1\x9a\x98" // U+F1698 +#define ICON_MDI_BOOK_REMOVE "\xf3\xb0\xaa\x97" // U+F0A97 +#define ICON_MDI_BOOK_REMOVE_MULTIPLE "\xf3\xb0\xaa\x96" // U+F0A96 +#define ICON_MDI_BOOK_REMOVE_MULTIPLE_OUTLINE "\xf3\xb0\x93\x8a" // U+F04CA +#define ICON_MDI_BOOK_REMOVE_OUTLINE "\xf3\xb1\x9a\x99" // U+F1699 +#define ICON_MDI_BOOK_SEARCH "\xf3\xb0\xba\x84" // U+F0E84 +#define ICON_MDI_BOOK_SEARCH_OUTLINE "\xf3\xb0\xba\x85" // U+F0E85 +#define ICON_MDI_BOOK_SETTINGS "\xf3\xb1\x9a\x9a" // U+F169A +#define ICON_MDI_BOOK_SETTINGS_OUTLINE "\xf3\xb1\x9a\x9b" // U+F169B +#define ICON_MDI_BOOK_SYNC "\xf3\xb1\x9a\x9c" // U+F169C +#define ICON_MDI_BOOK_SYNC_OUTLINE "\xf3\xb1\x9b\x88" // U+F16C8 +#define ICON_MDI_BOOK_VARIANT "\xf3\xb0\x82\xbf" // U+F00BF +#define ICON_MDI_BOOKMARK "\xf3\xb0\x83\x80" // U+F00C0 +#define ICON_MDI_BOOKMARK_BOX "\xf3\xb1\xad\xb5" // U+F1B75 +#define ICON_MDI_BOOKMARK_BOX_MULTIPLE "\xf3\xb1\xa5\xac" // U+F196C +#define ICON_MDI_BOOKMARK_BOX_MULTIPLE_OUTLINE "\xf3\xb1\xa5\xad" // U+F196D +#define ICON_MDI_BOOKMARK_BOX_OUTLINE "\xf3\xb1\xad\xb6" // U+F1B76 +#define ICON_MDI_BOOKMARK_CHECK "\xf3\xb0\x83\x81" // U+F00C1 +#define ICON_MDI_BOOKMARK_CHECK_OUTLINE "\xf3\xb1\x8d\xbb" // U+F137B +#define ICON_MDI_BOOKMARK_MINUS "\xf3\xb0\xa7\x8c" // U+F09CC +#define ICON_MDI_BOOKMARK_MINUS_OUTLINE "\xf3\xb0\xa7\x8d" // U+F09CD +#define ICON_MDI_BOOKMARK_MULTIPLE "\xf3\xb0\xb8\x95" // U+F0E15 +#define ICON_MDI_BOOKMARK_MULTIPLE_OUTLINE "\xf3\xb0\xb8\x96" // U+F0E16 +#define ICON_MDI_BOOKMARK_MUSIC "\xf3\xb0\x83\x82" // U+F00C2 +#define ICON_MDI_BOOKMARK_MUSIC_OUTLINE "\xf3\xb1\x8d\xb9" // U+F1379 +#define ICON_MDI_BOOKMARK_OFF "\xf3\xb0\xa7\x8e" // U+F09CE +#define ICON_MDI_BOOKMARK_OFF_OUTLINE "\xf3\xb0\xa7\x8f" // U+F09CF +#define ICON_MDI_BOOKMARK_OUTLINE "\xf3\xb0\x83\x83" // U+F00C3 +#define ICON_MDI_BOOKMARK_PLUS "\xf3\xb0\x83\x85" // U+F00C5 +#define ICON_MDI_BOOKMARK_PLUS_OUTLINE "\xf3\xb0\x83\x84" // U+F00C4 +#define ICON_MDI_BOOKMARK_REMOVE "\xf3\xb0\x83\x86" // U+F00C6 +#define ICON_MDI_BOOKMARK_REMOVE_OUTLINE "\xf3\xb1\x8d\xba" // U+F137A +#define ICON_MDI_BOOKSHELF "\xf3\xb1\x89\x9f" // U+F125F +#define ICON_MDI_BOOM_GATE "\xf3\xb0\xba\x86" // U+F0E86 +#define ICON_MDI_BOOM_GATE_ALERT "\xf3\xb0\xba\x87" // U+F0E87 +#define ICON_MDI_BOOM_GATE_ALERT_OUTLINE "\xf3\xb0\xba\x88" // U+F0E88 +#define ICON_MDI_BOOM_GATE_ARROW_DOWN "\xf3\xb0\xba\x89" // U+F0E89 +#define ICON_MDI_BOOM_GATE_ARROW_DOWN_OUTLINE "\xf3\xb0\xba\x8a" // U+F0E8A +#define ICON_MDI_BOOM_GATE_ARROW_UP "\xf3\xb0\xba\x8c" // U+F0E8C +#define ICON_MDI_BOOM_GATE_ARROW_UP_OUTLINE "\xf3\xb0\xba\x8d" // U+F0E8D +#define ICON_MDI_BOOM_GATE_OUTLINE "\xf3\xb0\xba\x8b" // U+F0E8B +#define ICON_MDI_BOOM_GATE_UP "\xf3\xb1\x9f\xb9" // U+F17F9 +#define ICON_MDI_BOOM_GATE_UP_OUTLINE "\xf3\xb1\x9f\xba" // U+F17FA +#define ICON_MDI_BOOMBOX "\xf3\xb0\x97\x9c" // U+F05DC +#define ICON_MDI_BOOMERANG "\xf3\xb1\x83\x8f" // U+F10CF +#define ICON_MDI_BOOTSTRAP "\xf3\xb0\x9b\x86" // U+F06C6 +#define ICON_MDI_BORDER_ALL "\xf3\xb0\x83\x87" // U+F00C7 +#define ICON_MDI_BORDER_ALL_VARIANT "\xf3\xb0\xa2\xa1" // U+F08A1 +#define ICON_MDI_BORDER_BOTTOM "\xf3\xb0\x83\x88" // U+F00C8 +#define ICON_MDI_BORDER_BOTTOM_VARIANT "\xf3\xb0\xa2\xa2" // U+F08A2 +#define ICON_MDI_BORDER_COLOR "\xf3\xb0\x83\x89" // U+F00C9 +#define ICON_MDI_BORDER_HORIZONTAL "\xf3\xb0\x83\x8a" // U+F00CA +#define ICON_MDI_BORDER_INSIDE "\xf3\xb0\x83\x8b" // U+F00CB +#define ICON_MDI_BORDER_LEFT "\xf3\xb0\x83\x8c" // U+F00CC +#define ICON_MDI_BORDER_LEFT_VARIANT "\xf3\xb0\xa2\xa3" // U+F08A3 +#define ICON_MDI_BORDER_NONE "\xf3\xb0\x83\x8d" // U+F00CD +#define ICON_MDI_BORDER_NONE_VARIANT "\xf3\xb0\xa2\xa4" // U+F08A4 +#define ICON_MDI_BORDER_OUTSIDE "\xf3\xb0\x83\x8e" // U+F00CE +#define ICON_MDI_BORDER_RADIUS "\xf3\xb1\xab\xb4" // U+F1AF4 +#define ICON_MDI_BORDER_RIGHT "\xf3\xb0\x83\x8f" // U+F00CF +#define ICON_MDI_BORDER_RIGHT_VARIANT "\xf3\xb0\xa2\xa5" // U+F08A5 +#define ICON_MDI_BORDER_STYLE "\xf3\xb0\x83\x90" // U+F00D0 +#define ICON_MDI_BORDER_TOP "\xf3\xb0\x83\x91" // U+F00D1 +#define ICON_MDI_BORDER_TOP_VARIANT "\xf3\xb0\xa2\xa6" // U+F08A6 +#define ICON_MDI_BORDER_VERTICAL "\xf3\xb0\x83\x92" // U+F00D2 +#define ICON_MDI_BOTTLE_SODA "\xf3\xb1\x81\xb0" // U+F1070 +#define ICON_MDI_BOTTLE_SODA_CLASSIC "\xf3\xb1\x81\xb1" // U+F1071 +#define ICON_MDI_BOTTLE_SODA_CLASSIC_OUTLINE "\xf3\xb1\x8d\xa3" // U+F1363 +#define ICON_MDI_BOTTLE_SODA_OUTLINE "\xf3\xb1\x81\xb2" // U+F1072 +#define ICON_MDI_BOTTLE_TONIC "\xf3\xb1\x84\xae" // U+F112E +#define ICON_MDI_BOTTLE_TONIC_OUTLINE "\xf3\xb1\x84\xaf" // U+F112F +#define ICON_MDI_BOTTLE_TONIC_PLUS "\xf3\xb1\x84\xb0" // U+F1130 +#define ICON_MDI_BOTTLE_TONIC_PLUS_OUTLINE "\xf3\xb1\x84\xb1" // U+F1131 +#define ICON_MDI_BOTTLE_TONIC_SKULL "\xf3\xb1\x84\xb2" // U+F1132 +#define ICON_MDI_BOTTLE_TONIC_SKULL_OUTLINE "\xf3\xb1\x84\xb3" // U+F1133 +#define ICON_MDI_BOTTLE_WINE "\xf3\xb0\xa1\x94" // U+F0854 +#define ICON_MDI_BOTTLE_WINE_OUTLINE "\xf3\xb1\x8c\x90" // U+F1310 +#define ICON_MDI_BOW_ARROW "\xf3\xb1\xa1\x81" // U+F1841 +#define ICON_MDI_BOW_TIE "\xf3\xb0\x99\xb8" // U+F0678 +#define ICON_MDI_BOWL "\xf3\xb0\x8a\x8e" // U+F028E +#define ICON_MDI_BOWL_MIX "\xf3\xb0\x98\x97" // U+F0617 +#define ICON_MDI_BOWL_MIX_OUTLINE "\xf3\xb0\x8b\xa4" // U+F02E4 +#define ICON_MDI_BOWL_OUTLINE "\xf3\xb0\x8a\xa9" // U+F02A9 +#define ICON_MDI_BOWLING "\xf3\xb0\x83\x93" // U+F00D3 +#define ICON_MDI_BOX "\xf3\xb0\x83\x94" // U+F00D4 +#define ICON_MDI_BOX_CUTTER "\xf3\xb0\x83\x95" // U+F00D5 +#define ICON_MDI_BOX_CUTTER_OFF "\xf3\xb0\xad\x8a" // U+F0B4A +#define ICON_MDI_BOX_SHADOW "\xf3\xb0\x98\xb7" // U+F0637 +#define ICON_MDI_BOXING_GLOVE "\xf3\xb0\xad\xa5" // U+F0B65 +#define ICON_MDI_BRAILLE "\xf3\xb0\xa7\x90" // U+F09D0 +#define ICON_MDI_BRAIN "\xf3\xb0\xa7\x91" // U+F09D1 +#define ICON_MDI_BREAD_SLICE "\xf3\xb0\xb3\xae" // U+F0CEE +#define ICON_MDI_BREAD_SLICE_OUTLINE "\xf3\xb0\xb3\xaf" // U+F0CEF +#define ICON_MDI_BRIDGE "\xf3\xb0\x98\x98" // U+F0618 +#define ICON_MDI_BRIEFCASE "\xf3\xb0\x83\x96" // U+F00D6 +#define ICON_MDI_BRIEFCASE_ACCOUNT "\xf3\xb0\xb3\xb0" // U+F0CF0 +#define ICON_MDI_BRIEFCASE_ACCOUNT_OUTLINE "\xf3\xb0\xb3\xb1" // U+F0CF1 +#define ICON_MDI_BRIEFCASE_ARROW_LEFT_RIGHT "\xf3\xb1\xaa\x8d" // U+F1A8D +#define ICON_MDI_BRIEFCASE_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xaa\x8e" // U+F1A8E +#define ICON_MDI_BRIEFCASE_ARROW_UP_DOWN "\xf3\xb1\xaa\x8f" // U+F1A8F +#define ICON_MDI_BRIEFCASE_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xaa\x90" // U+F1A90 +#define ICON_MDI_BRIEFCASE_CHECK "\xf3\xb0\x83\x97" // U+F00D7 +#define ICON_MDI_BRIEFCASE_CHECK_OUTLINE "\xf3\xb1\x8c\x9e" // U+F131E +#define ICON_MDI_BRIEFCASE_CLOCK "\xf3\xb1\x83\x90" // U+F10D0 +#define ICON_MDI_BRIEFCASE_CLOCK_OUTLINE "\xf3\xb1\x83\x91" // U+F10D1 +#define ICON_MDI_BRIEFCASE_DOWNLOAD "\xf3\xb0\x83\x98" // U+F00D8 +#define ICON_MDI_BRIEFCASE_DOWNLOAD_OUTLINE "\xf3\xb0\xb0\xbd" // U+F0C3D +#define ICON_MDI_BRIEFCASE_EDIT "\xf3\xb0\xaa\x98" // U+F0A98 +#define ICON_MDI_BRIEFCASE_EDIT_OUTLINE "\xf3\xb0\xb0\xbe" // U+F0C3E +#define ICON_MDI_BRIEFCASE_EYE "\xf3\xb1\x9f\x99" // U+F17D9 +#define ICON_MDI_BRIEFCASE_EYE_OUTLINE "\xf3\xb1\x9f\x9a" // U+F17DA +#define ICON_MDI_BRIEFCASE_MINUS "\xf3\xb0\xa8\xaa" // U+F0A2A +#define ICON_MDI_BRIEFCASE_MINUS_OUTLINE "\xf3\xb0\xb0\xbf" // U+F0C3F +#define ICON_MDI_BRIEFCASE_OFF "\xf3\xb1\x99\x98" // U+F1658 +#define ICON_MDI_BRIEFCASE_OFF_OUTLINE "\xf3\xb1\x99\x99" // U+F1659 +#define ICON_MDI_BRIEFCASE_OUTLINE "\xf3\xb0\xa0\x94" // U+F0814 +#define ICON_MDI_BRIEFCASE_PLUS "\xf3\xb0\xa8\xab" // U+F0A2B +#define ICON_MDI_BRIEFCASE_PLUS_OUTLINE "\xf3\xb0\xb1\x80" // U+F0C40 +#define ICON_MDI_BRIEFCASE_REMOVE "\xf3\xb0\xa8\xac" // U+F0A2C +#define ICON_MDI_BRIEFCASE_REMOVE_OUTLINE "\xf3\xb0\xb1\x81" // U+F0C41 +#define ICON_MDI_BRIEFCASE_SEARCH "\xf3\xb0\xa8\xad" // U+F0A2D +#define ICON_MDI_BRIEFCASE_SEARCH_OUTLINE "\xf3\xb0\xb1\x82" // U+F0C42 +#define ICON_MDI_BRIEFCASE_UPLOAD "\xf3\xb0\x83\x99" // U+F00D9 +#define ICON_MDI_BRIEFCASE_UPLOAD_OUTLINE "\xf3\xb0\xb1\x83" // U+F0C43 +#define ICON_MDI_BRIEFCASE_VARIANT "\xf3\xb1\x92\x94" // U+F1494 +#define ICON_MDI_BRIEFCASE_VARIANT_OFF "\xf3\xb1\x99\x9a" // U+F165A +#define ICON_MDI_BRIEFCASE_VARIANT_OFF_OUTLINE "\xf3\xb1\x99\x9b" // U+F165B +#define ICON_MDI_BRIEFCASE_VARIANT_OUTLINE "\xf3\xb1\x92\x95" // U+F1495 +#define ICON_MDI_BRIGHTNESS_1 "\xf3\xb0\x83\x9a" // U+F00DA +#define ICON_MDI_BRIGHTNESS_2 "\xf3\xb0\x83\x9b" // U+F00DB +#define ICON_MDI_BRIGHTNESS_3 "\xf3\xb0\x83\x9c" // U+F00DC +#define ICON_MDI_BRIGHTNESS_4 "\xf3\xb0\x83\x9d" // U+F00DD +#define ICON_MDI_BRIGHTNESS_5 "\xf3\xb0\x83\x9e" // U+F00DE +#define ICON_MDI_BRIGHTNESS_6 "\xf3\xb0\x83\x9f" // U+F00DF +#define ICON_MDI_BRIGHTNESS_7 "\xf3\xb0\x83\xa0" // U+F00E0 +#define ICON_MDI_BRIGHTNESS_AUTO "\xf3\xb0\x83\xa1" // U+F00E1 +#define ICON_MDI_BRIGHTNESS_PERCENT "\xf3\xb0\xb3\xb2" // U+F0CF2 +#define ICON_MDI_BROADCAST "\xf3\xb1\x9c\xa0" // U+F1720 +#define ICON_MDI_BROADCAST_OFF "\xf3\xb1\x9c\xa1" // U+F1721 +#define ICON_MDI_BROOM "\xf3\xb0\x83\xa2" // U+F00E2 +#define ICON_MDI_BRUSH "\xf3\xb0\x83\xa3" // U+F00E3 +#define ICON_MDI_BRUSH_OFF "\xf3\xb1\x9d\xb1" // U+F1771 +#define ICON_MDI_BRUSH_OUTLINE "\xf3\xb1\xa8\x8d" // U+F1A0D +#define ICON_MDI_BRUSH_VARIANT "\xf3\xb1\xa0\x93" // U+F1813 +#define ICON_MDI_BUCKET "\xf3\xb1\x90\x95" // U+F1415 +#define ICON_MDI_BUCKET_OUTLINE "\xf3\xb1\x90\x96" // U+F1416 +#define ICON_MDI_BUFFET "\xf3\xb0\x95\xb8" // U+F0578 +#define ICON_MDI_BUG "\xf3\xb0\x83\xa4" // U+F00E4 +#define ICON_MDI_BUG_CHECK "\xf3\xb0\xa8\xae" // U+F0A2E +#define ICON_MDI_BUG_CHECK_OUTLINE "\xf3\xb0\xa8\xaf" // U+F0A2F +#define ICON_MDI_BUG_OUTLINE "\xf3\xb0\xa8\xb0" // U+F0A30 +#define ICON_MDI_BUG_PAUSE "\xf3\xb1\xab\xb5" // U+F1AF5 +#define ICON_MDI_BUG_PAUSE_OUTLINE "\xf3\xb1\xab\xb6" // U+F1AF6 +#define ICON_MDI_BUG_PLAY "\xf3\xb1\xab\xb7" // U+F1AF7 +#define ICON_MDI_BUG_PLAY_OUTLINE "\xf3\xb1\xab\xb8" // U+F1AF8 +#define ICON_MDI_BUG_STOP "\xf3\xb1\xab\xb9" // U+F1AF9 +#define ICON_MDI_BUG_STOP_OUTLINE "\xf3\xb1\xab\xba" // U+F1AFA +#define ICON_MDI_BUGLE "\xf3\xb0\xb6\xb4" // U+F0DB4 +#define ICON_MDI_BULKHEAD_LIGHT "\xf3\xb1\xa8\xaf" // U+F1A2F +#define ICON_MDI_BULLDOZER "\xf3\xb0\xac\xa2" // U+F0B22 +#define ICON_MDI_BULLET "\xf3\xb0\xb3\xb3" // U+F0CF3 +#define ICON_MDI_BULLETIN_BOARD "\xf3\xb0\x83\xa5" // U+F00E5 +#define ICON_MDI_BULLHORN "\xf3\xb0\x83\xa6" // U+F00E6 +#define ICON_MDI_BULLHORN_OUTLINE "\xf3\xb0\xac\xa3" // U+F0B23 +#define ICON_MDI_BULLHORN_VARIANT "\xf3\xb1\xa5\xae" // U+F196E +#define ICON_MDI_BULLHORN_VARIANT_OUTLINE "\xf3\xb1\xa5\xaf" // U+F196F +#define ICON_MDI_BULLSEYE "\xf3\xb0\x97\x9d" // U+F05DD +#define ICON_MDI_BULLSEYE_ARROW "\xf3\xb0\xa3\x89" // U+F08C9 +#define ICON_MDI_BULMA "\xf3\xb1\x8b\xa7" // U+F12E7 +#define ICON_MDI_BUNK_BED "\xf3\xb1\x8c\x82" // U+F1302 +#define ICON_MDI_BUNK_BED_OUTLINE "\xf3\xb0\x82\x97" // U+F0097 +#define ICON_MDI_BUS "\xf3\xb0\x83\xa7" // U+F00E7 +#define ICON_MDI_BUS_ALERT "\xf3\xb0\xaa\x99" // U+F0A99 +#define ICON_MDI_BUS_ARTICULATED_END "\xf3\xb0\x9e\x9c" // U+F079C +#define ICON_MDI_BUS_ARTICULATED_FRONT "\xf3\xb0\x9e\x9d" // U+F079D +#define ICON_MDI_BUS_CLOCK "\xf3\xb0\xa3\x8a" // U+F08CA +#define ICON_MDI_BUS_DOUBLE_DECKER "\xf3\xb0\x9e\x9e" // U+F079E +#define ICON_MDI_BUS_ELECTRIC "\xf3\xb1\xa4\x9d" // U+F191D +#define ICON_MDI_BUS_MARKER "\xf3\xb1\x88\x92" // U+F1212 +#define ICON_MDI_BUS_MULTIPLE "\xf3\xb0\xbc\xbf" // U+F0F3F +#define ICON_MDI_BUS_SCHOOL "\xf3\xb0\x9e\x9f" // U+F079F +#define ICON_MDI_BUS_SIDE "\xf3\xb0\x9e\xa0" // U+F07A0 +#define ICON_MDI_BUS_SIGN "\xf3\xb1\xb3\x81" // U+F1CC1 +#define ICON_MDI_BUS_STOP "\xf3\xb1\x80\x92" // U+F1012 +#define ICON_MDI_BUS_STOP_COVERED "\xf3\xb1\x80\x93" // U+F1013 +#define ICON_MDI_BUS_STOP_UNCOVERED "\xf3\xb1\x80\x94" // U+F1014 +#define ICON_MDI_BUS_WRENCH "\xf3\xb1\xb3\x82" // U+F1CC2 +#define ICON_MDI_BUTTERFLY "\xf3\xb1\x96\x89" // U+F1589 +#define ICON_MDI_BUTTERFLY_OUTLINE "\xf3\xb1\x96\x8a" // U+F158A +#define ICON_MDI_BUTTON_CURSOR "\xf3\xb1\xad\x8f" // U+F1B4F +#define ICON_MDI_BUTTON_POINTER "\xf3\xb1\xad\x90" // U+F1B50 +#define ICON_MDI_CABIN_A_FRAME "\xf3\xb1\xa2\x8c" // U+F188C +#define ICON_MDI_CABLE_DATA "\xf3\xb1\x8e\x94" // U+F1394 +#define ICON_MDI_CACHED "\xf3\xb0\x83\xa8" // U+F00E8 +#define ICON_MDI_CACTUS "\xf3\xb0\xb6\xb5" // U+F0DB5 +#define ICON_MDI_CAKE "\xf3\xb0\x83\xa9" // U+F00E9 +#define ICON_MDI_CAKE_LAYERED "\xf3\xb0\x83\xaa" // U+F00EA +#define ICON_MDI_CAKE_VARIANT "\xf3\xb0\x83\xab" // U+F00EB +#define ICON_MDI_CAKE_VARIANT_OUTLINE "\xf3\xb1\x9f\xb0" // U+F17F0 +#define ICON_MDI_CALCULATOR "\xf3\xb0\x83\xac" // U+F00EC +#define ICON_MDI_CALCULATOR_VARIANT "\xf3\xb0\xaa\x9a" // U+F0A9A +#define ICON_MDI_CALCULATOR_VARIANT_OUTLINE "\xf3\xb1\x96\xa6" // U+F15A6 +#define ICON_MDI_CALENDAR "\xf3\xb0\x83\xad" // U+F00ED +#define ICON_MDI_CALENDAR_ACCOUNT "\xf3\xb0\xbb\x97" // U+F0ED7 +#define ICON_MDI_CALENDAR_ACCOUNT_OUTLINE "\xf3\xb0\xbb\x98" // U+F0ED8 +#define ICON_MDI_CALENDAR_ALERT "\xf3\xb0\xa8\xb1" // U+F0A31 +#define ICON_MDI_CALENDAR_ALERT_OUTLINE "\xf3\xb1\xad\xa2" // U+F1B62 +#define ICON_MDI_CALENDAR_ARROW_LEFT "\xf3\xb1\x84\xb4" // U+F1134 +#define ICON_MDI_CALENDAR_ARROW_RIGHT "\xf3\xb1\x84\xb5" // U+F1135 +#define ICON_MDI_CALENDAR_BADGE "\xf3\xb1\xae\x9d" // U+F1B9D +#define ICON_MDI_CALENDAR_BADGE_OUTLINE "\xf3\xb1\xae\x9e" // U+F1B9E +#define ICON_MDI_CALENDAR_BLANK "\xf3\xb0\x83\xae" // U+F00EE +#define ICON_MDI_CALENDAR_BLANK_MULTIPLE "\xf3\xb1\x81\xb3" // U+F1073 +#define ICON_MDI_CALENDAR_BLANK_OUTLINE "\xf3\xb0\xad\xa6" // U+F0B66 +#define ICON_MDI_CALENDAR_CHECK "\xf3\xb0\x83\xaf" // U+F00EF +#define ICON_MDI_CALENDAR_CHECK_OUTLINE "\xf3\xb0\xb1\x84" // U+F0C44 +#define ICON_MDI_CALENDAR_CLOCK "\xf3\xb0\x83\xb0" // U+F00F0 +#define ICON_MDI_CALENDAR_CLOCK_OUTLINE "\xf3\xb1\x9b\xa1" // U+F16E1 +#define ICON_MDI_CALENDAR_COLLAPSE_HORIZONTAL "\xf3\xb1\xa2\x9d" // U+F189D +#define ICON_MDI_CALENDAR_COLLAPSE_HORIZONTAL_OUTLINE "\xf3\xb1\xad\xa3" // U+F1B63 +#define ICON_MDI_CALENDAR_CURSOR "\xf3\xb1\x95\xbb" // U+F157B +#define ICON_MDI_CALENDAR_CURSOR_OUTLINE "\xf3\xb1\xad\xa4" // U+F1B64 +#define ICON_MDI_CALENDAR_EDIT "\xf3\xb0\xa2\xa7" // U+F08A7 +#define ICON_MDI_CALENDAR_EDIT_OUTLINE "\xf3\xb1\xad\xa5" // U+F1B65 +#define ICON_MDI_CALENDAR_END "\xf3\xb1\x99\xac" // U+F166C +#define ICON_MDI_CALENDAR_END_OUTLINE "\xf3\xb1\xad\xa6" // U+F1B66 +#define ICON_MDI_CALENDAR_EXPAND_HORIZONTAL "\xf3\xb1\xa2\x9e" // U+F189E +#define ICON_MDI_CALENDAR_EXPAND_HORIZONTAL_OUTLINE "\xf3\xb1\xad\xa7" // U+F1B67 +#define ICON_MDI_CALENDAR_EXPORT "\xf3\xb0\xac\xa4" // U+F0B24 +#define ICON_MDI_CALENDAR_EXPORT_OUTLINE "\xf3\xb1\xad\xa8" // U+F1B68 +#define ICON_MDI_CALENDAR_FILTER "\xf3\xb1\xa8\xb2" // U+F1A32 +#define ICON_MDI_CALENDAR_FILTER_OUTLINE "\xf3\xb1\xa8\xb3" // U+F1A33 +#define ICON_MDI_CALENDAR_HEART "\xf3\xb0\xa7\x92" // U+F09D2 +#define ICON_MDI_CALENDAR_HEART_OUTLINE "\xf3\xb1\xad\xa9" // U+F1B69 +#define ICON_MDI_CALENDAR_IMPORT "\xf3\xb0\xac\xa5" // U+F0B25 +#define ICON_MDI_CALENDAR_IMPORT_OUTLINE "\xf3\xb1\xad\xaa" // U+F1B6A +#define ICON_MDI_CALENDAR_LOCK "\xf3\xb1\x99\x81" // U+F1641 +#define ICON_MDI_CALENDAR_LOCK_OPEN "\xf3\xb1\xad\x9b" // U+F1B5B +#define ICON_MDI_CALENDAR_LOCK_OPEN_OUTLINE "\xf3\xb1\xad\x9c" // U+F1B5C +#define ICON_MDI_CALENDAR_LOCK_OUTLINE "\xf3\xb1\x99\x82" // U+F1642 +#define ICON_MDI_CALENDAR_MINUS "\xf3\xb0\xb5\x9c" // U+F0D5C +#define ICON_MDI_CALENDAR_MINUS_OUTLINE "\xf3\xb1\xad\xab" // U+F1B6B +#define ICON_MDI_CALENDAR_MONTH "\xf3\xb0\xb8\x97" // U+F0E17 +#define ICON_MDI_CALENDAR_MONTH_OUTLINE "\xf3\xb0\xb8\x98" // U+F0E18 +#define ICON_MDI_CALENDAR_MULTIPLE "\xf3\xb0\x83\xb1" // U+F00F1 +#define ICON_MDI_CALENDAR_MULTIPLE_CHECK "\xf3\xb0\x83\xb2" // U+F00F2 +#define ICON_MDI_CALENDAR_MULTISELECT "\xf3\xb0\xa8\xb2" // U+F0A32 +#define ICON_MDI_CALENDAR_MULTISELECT_OUTLINE "\xf3\xb1\xad\x95" // U+F1B55 +#define ICON_MDI_CALENDAR_OUTLINE "\xf3\xb0\xad\xa7" // U+F0B67 +#define ICON_MDI_CALENDAR_PLUS "\xf3\xb0\x83\xb3" // U+F00F3 +#define ICON_MDI_CALENDAR_PLUS_OUTLINE "\xf3\xb1\xad\xac" // U+F1B6C +#define ICON_MDI_CALENDAR_QUESTION "\xf3\xb0\x9a\x92" // U+F0692 +#define ICON_MDI_CALENDAR_QUESTION_OUTLINE "\xf3\xb1\xad\xad" // U+F1B6D +#define ICON_MDI_CALENDAR_RANGE "\xf3\xb0\x99\xb9" // U+F0679 +#define ICON_MDI_CALENDAR_RANGE_OUTLINE "\xf3\xb0\xad\xa8" // U+F0B68 +#define ICON_MDI_CALENDAR_REFRESH "\xf3\xb0\x87\xa1" // U+F01E1 +#define ICON_MDI_CALENDAR_REFRESH_OUTLINE "\xf3\xb0\x88\x83" // U+F0203 +#define ICON_MDI_CALENDAR_REMOVE "\xf3\xb0\x83\xb4" // U+F00F4 +#define ICON_MDI_CALENDAR_REMOVE_OUTLINE "\xf3\xb0\xb1\x85" // U+F0C45 +#define ICON_MDI_CALENDAR_SEARCH "\xf3\xb0\xa5\x8c" // U+F094C +#define ICON_MDI_CALENDAR_SEARCH_OUTLINE "\xf3\xb1\xad\xae" // U+F1B6E +#define ICON_MDI_CALENDAR_STAR "\xf3\xb0\xa7\x93" // U+F09D3 +#define ICON_MDI_CALENDAR_STAR_FOUR_POINTS "\xf3\xb1\xb0\x9f" // U+F1C1F +#define ICON_MDI_CALENDAR_STAR_OUTLINE "\xf3\xb1\xad\x93" // U+F1B53 +#define ICON_MDI_CALENDAR_START "\xf3\xb1\x99\xad" // U+F166D +#define ICON_MDI_CALENDAR_START_OUTLINE "\xf3\xb1\xad\xaf" // U+F1B6F +#define ICON_MDI_CALENDAR_SYNC "\xf3\xb0\xba\x8e" // U+F0E8E +#define ICON_MDI_CALENDAR_SYNC_OUTLINE "\xf3\xb0\xba\x8f" // U+F0E8F +#define ICON_MDI_CALENDAR_TEXT "\xf3\xb0\x83\xb5" // U+F00F5 +#define ICON_MDI_CALENDAR_TEXT_OUTLINE "\xf3\xb0\xb1\x86" // U+F0C46 +#define ICON_MDI_CALENDAR_TODAY "\xf3\xb0\x83\xb6" // U+F00F6 +#define ICON_MDI_CALENDAR_TODAY_OUTLINE "\xf3\xb1\xa8\xb0" // U+F1A30 +#define ICON_MDI_CALENDAR_WEEK "\xf3\xb0\xa8\xb3" // U+F0A33 +#define ICON_MDI_CALENDAR_WEEK_BEGIN "\xf3\xb0\xa8\xb4" // U+F0A34 +#define ICON_MDI_CALENDAR_WEEK_BEGIN_OUTLINE "\xf3\xb1\xa8\xb1" // U+F1A31 +#define ICON_MDI_CALENDAR_WEEK_OUTLINE "\xf3\xb1\xa8\xb4" // U+F1A34 +#define ICON_MDI_CALENDAR_WEEKEND "\xf3\xb0\xbb\x99" // U+F0ED9 +#define ICON_MDI_CALENDAR_WEEKEND_OUTLINE "\xf3\xb0\xbb\x9a" // U+F0EDA +#define ICON_MDI_CALL_MADE "\xf3\xb0\x83\xb7" // U+F00F7 +#define ICON_MDI_CALL_MERGE "\xf3\xb0\x83\xb8" // U+F00F8 +#define ICON_MDI_CALL_MISSED "\xf3\xb0\x83\xb9" // U+F00F9 +#define ICON_MDI_CALL_RECEIVED "\xf3\xb0\x83\xba" // U+F00FA +#define ICON_MDI_CALL_SPLIT "\xf3\xb0\x83\xbb" // U+F00FB +#define ICON_MDI_CAMCORDER "\xf3\xb0\x83\xbc" // U+F00FC +#define ICON_MDI_CAMCORDER_OFF "\xf3\xb0\x83\xbf" // U+F00FF +#define ICON_MDI_CAMERA "\xf3\xb0\x84\x80" // U+F0100 +#define ICON_MDI_CAMERA_ACCOUNT "\xf3\xb0\xa3\x8b" // U+F08CB +#define ICON_MDI_CAMERA_BURST "\xf3\xb0\x9a\x93" // U+F0693 +#define ICON_MDI_CAMERA_CONTROL "\xf3\xb0\xad\xa9" // U+F0B69 +#define ICON_MDI_CAMERA_DOCUMENT "\xf3\xb1\xa1\xb1" // U+F1871 +#define ICON_MDI_CAMERA_DOCUMENT_OFF "\xf3\xb1\xa1\xb2" // U+F1872 +#define ICON_MDI_CAMERA_ENHANCE "\xf3\xb0\x84\x81" // U+F0101 +#define ICON_MDI_CAMERA_ENHANCE_OUTLINE "\xf3\xb0\xad\xaa" // U+F0B6A +#define ICON_MDI_CAMERA_FLIP "\xf3\xb1\x97\x99" // U+F15D9 +#define ICON_MDI_CAMERA_FLIP_OUTLINE "\xf3\xb1\x97\x9a" // U+F15DA +#define ICON_MDI_CAMERA_FRONT "\xf3\xb0\x84\x82" // U+F0102 +#define ICON_MDI_CAMERA_FRONT_VARIANT "\xf3\xb0\x84\x83" // U+F0103 +#define ICON_MDI_CAMERA_GOPRO "\xf3\xb0\x9e\xa1" // U+F07A1 +#define ICON_MDI_CAMERA_IMAGE "\xf3\xb0\xa3\x8c" // U+F08CC +#define ICON_MDI_CAMERA_IRIS "\xf3\xb0\x84\x84" // U+F0104 +#define ICON_MDI_CAMERA_LOCK "\xf3\xb1\xa8\x94" // U+F1A14 +#define ICON_MDI_CAMERA_LOCK_OPEN "\xf3\xb1\xb0\x8d" // U+F1C0D +#define ICON_MDI_CAMERA_LOCK_OPEN_OUTLINE "\xf3\xb1\xb0\x8e" // U+F1C0E +#define ICON_MDI_CAMERA_LOCK_OUTLINE "\xf3\xb1\xa8\x95" // U+F1A15 +#define ICON_MDI_CAMERA_MARKER "\xf3\xb1\xa6\xa7" // U+F19A7 +#define ICON_MDI_CAMERA_MARKER_OUTLINE "\xf3\xb1\xa6\xa8" // U+F19A8 +#define ICON_MDI_CAMERA_METERING_CENTER "\xf3\xb0\x9e\xa2" // U+F07A2 +#define ICON_MDI_CAMERA_METERING_MATRIX "\xf3\xb0\x9e\xa3" // U+F07A3 +#define ICON_MDI_CAMERA_METERING_PARTIAL "\xf3\xb0\x9e\xa4" // U+F07A4 +#define ICON_MDI_CAMERA_METERING_SPOT "\xf3\xb0\x9e\xa5" // U+F07A5 +#define ICON_MDI_CAMERA_OFF "\xf3\xb0\x97\x9f" // U+F05DF +#define ICON_MDI_CAMERA_OFF_OUTLINE "\xf3\xb1\xa6\xbf" // U+F19BF +#define ICON_MDI_CAMERA_OUTLINE "\xf3\xb0\xb5\x9d" // U+F0D5D +#define ICON_MDI_CAMERA_PARTY_MODE "\xf3\xb0\x84\x85" // U+F0105 +#define ICON_MDI_CAMERA_PLUS "\xf3\xb0\xbb\x9b" // U+F0EDB +#define ICON_MDI_CAMERA_PLUS_OUTLINE "\xf3\xb0\xbb\x9c" // U+F0EDC +#define ICON_MDI_CAMERA_REAR "\xf3\xb0\x84\x86" // U+F0106 +#define ICON_MDI_CAMERA_REAR_VARIANT "\xf3\xb0\x84\x87" // U+F0107 +#define ICON_MDI_CAMERA_RETAKE "\xf3\xb0\xb8\x99" // U+F0E19 +#define ICON_MDI_CAMERA_RETAKE_OUTLINE "\xf3\xb0\xb8\x9a" // U+F0E1A +#define ICON_MDI_CAMERA_SWITCH "\xf3\xb0\x84\x88" // U+F0108 +#define ICON_MDI_CAMERA_SWITCH_OUTLINE "\xf3\xb0\xa1\x8a" // U+F084A +#define ICON_MDI_CAMERA_TIMER "\xf3\xb0\x84\x89" // U+F0109 +#define ICON_MDI_CAMERA_WIRELESS "\xf3\xb0\xb6\xb6" // U+F0DB6 +#define ICON_MDI_CAMERA_WIRELESS_OUTLINE "\xf3\xb0\xb6\xb7" // U+F0DB7 +#define ICON_MDI_CAMPFIRE "\xf3\xb0\xbb\x9d" // U+F0EDD +#define ICON_MDI_CANCEL "\xf3\xb0\x9c\xba" // U+F073A +#define ICON_MDI_CANDELABRA "\xf3\xb1\x9f\x92" // U+F17D2 +#define ICON_MDI_CANDELABRA_FIRE "\xf3\xb1\x9f\x93" // U+F17D3 +#define ICON_MDI_CANDLE "\xf3\xb0\x97\xa2" // U+F05E2 +#define ICON_MDI_CANDY "\xf3\xb1\xa5\xb0" // U+F1970 +#define ICON_MDI_CANDY_OFF "\xf3\xb1\xa5\xb1" // U+F1971 +#define ICON_MDI_CANDY_OFF_OUTLINE "\xf3\xb1\xa5\xb2" // U+F1972 +#define ICON_MDI_CANDY_OUTLINE "\xf3\xb1\xa5\xb3" // U+F1973 +#define ICON_MDI_CANDYCANE "\xf3\xb0\x84\x8a" // U+F010A +#define ICON_MDI_CANNABIS "\xf3\xb0\x9e\xa6" // U+F07A6 +#define ICON_MDI_CANNABIS_OFF "\xf3\xb1\x99\xae" // U+F166E +#define ICON_MDI_CAPS_LOCK "\xf3\xb0\xaa\x9b" // U+F0A9B +#define ICON_MDI_CAR "\xf3\xb0\x84\x8b" // U+F010B +#define ICON_MDI_CAR_2_PLUS "\xf3\xb1\x80\x95" // U+F1015 +#define ICON_MDI_CAR_3_PLUS "\xf3\xb1\x80\x96" // U+F1016 +#define ICON_MDI_CAR_ARROW_LEFT "\xf3\xb1\x8e\xb2" // U+F13B2 +#define ICON_MDI_CAR_ARROW_RIGHT "\xf3\xb1\x8e\xb3" // U+F13B3 +#define ICON_MDI_CAR_BACK "\xf3\xb0\xb8\x9b" // U+F0E1B +#define ICON_MDI_CAR_BATTERY "\xf3\xb0\x84\x8c" // U+F010C +#define ICON_MDI_CAR_BRAKE_ABS "\xf3\xb0\xb1\x87" // U+F0C47 +#define ICON_MDI_CAR_BRAKE_ALERT "\xf3\xb0\xb1\x88" // U+F0C48 +#define ICON_MDI_CAR_BRAKE_FLUID_LEVEL "\xf3\xb1\xa4\x89" // U+F1909 +#define ICON_MDI_CAR_BRAKE_HOLD "\xf3\xb0\xb5\x9e" // U+F0D5E +#define ICON_MDI_CAR_BRAKE_LOW_PRESSURE "\xf3\xb1\xa4\x8a" // U+F190A +#define ICON_MDI_CAR_BRAKE_PARKING "\xf3\xb0\xb5\x9f" // U+F0D5F +#define ICON_MDI_CAR_BRAKE_RETARDER "\xf3\xb1\x80\x97" // U+F1017 +#define ICON_MDI_CAR_BRAKE_TEMPERATURE "\xf3\xb1\xa4\x8b" // U+F190B +#define ICON_MDI_CAR_BRAKE_WORN_LININGS "\xf3\xb1\xa4\x8c" // U+F190C +#define ICON_MDI_CAR_CHILD_SEAT "\xf3\xb0\xbe\xa3" // U+F0FA3 +#define ICON_MDI_CAR_CLOCK "\xf3\xb1\xa5\xb4" // U+F1974 +#define ICON_MDI_CAR_CLUTCH "\xf3\xb1\x80\x98" // U+F1018 +#define ICON_MDI_CAR_COG "\xf3\xb1\x8f\x8c" // U+F13CC +#define ICON_MDI_CAR_CONNECTED "\xf3\xb0\x84\x8d" // U+F010D +#define ICON_MDI_CAR_CONVERTIBLE "\xf3\xb0\x9e\xa7" // U+F07A7 +#define ICON_MDI_CAR_COOLANT_LEVEL "\xf3\xb1\x80\x99" // U+F1019 +#define ICON_MDI_CAR_CRUISE_CONTROL "\xf3\xb0\xb5\xa0" // U+F0D60 +#define ICON_MDI_CAR_DEFROST_FRONT "\xf3\xb0\xb5\xa1" // U+F0D61 +#define ICON_MDI_CAR_DEFROST_REAR "\xf3\xb0\xb5\xa2" // U+F0D62 +#define ICON_MDI_CAR_DOOR "\xf3\xb0\xad\xab" // U+F0B6B +#define ICON_MDI_CAR_DOOR_LOCK "\xf3\xb1\x82\x9d" // U+F109D +#define ICON_MDI_CAR_DOOR_LOCK_OPEN "\xf3\xb1\xb2\x81" // U+F1C81 +#define ICON_MDI_CAR_ELECTRIC "\xf3\xb0\xad\xac" // U+F0B6C +#define ICON_MDI_CAR_ELECTRIC_OUTLINE "\xf3\xb1\x96\xb5" // U+F15B5 +#define ICON_MDI_CAR_EMERGENCY "\xf3\xb1\x98\x8f" // U+F160F +#define ICON_MDI_CAR_ESP "\xf3\xb0\xb1\x89" // U+F0C49 +#define ICON_MDI_CAR_ESTATE "\xf3\xb0\x9e\xa8" // U+F07A8 +#define ICON_MDI_CAR_HATCHBACK "\xf3\xb0\x9e\xa9" // U+F07A9 +#define ICON_MDI_CAR_INFO "\xf3\xb1\x86\xbe" // U+F11BE +#define ICON_MDI_CAR_KEY "\xf3\xb0\xad\xad" // U+F0B6D +#define ICON_MDI_CAR_LIFTED_PICKUP "\xf3\xb1\x94\xad" // U+F152D +#define ICON_MDI_CAR_LIGHT_ALERT "\xf3\xb1\xa4\x8d" // U+F190D +#define ICON_MDI_CAR_LIGHT_DIMMED "\xf3\xb0\xb1\x8a" // U+F0C4A +#define ICON_MDI_CAR_LIGHT_FOG "\xf3\xb0\xb1\x8b" // U+F0C4B +#define ICON_MDI_CAR_LIGHT_HIGH "\xf3\xb0\xb1\x8c" // U+F0C4C +#define ICON_MDI_CAR_LIMOUSINE "\xf3\xb0\xa3\x8d" // U+F08CD +#define ICON_MDI_CAR_MULTIPLE "\xf3\xb0\xad\xae" // U+F0B6E +#define ICON_MDI_CAR_OFF "\xf3\xb0\xb8\x9c" // U+F0E1C +#define ICON_MDI_CAR_OUTLINE "\xf3\xb1\x93\xad" // U+F14ED +#define ICON_MDI_CAR_PARKING_LIGHTS "\xf3\xb0\xb5\xa3" // U+F0D63 +#define ICON_MDI_CAR_PICKUP "\xf3\xb0\x9e\xaa" // U+F07AA +#define ICON_MDI_CAR_SEARCH "\xf3\xb1\xae\x8d" // U+F1B8D +#define ICON_MDI_CAR_SEARCH_OUTLINE "\xf3\xb1\xae\x8e" // U+F1B8E +#define ICON_MDI_CAR_SEAT "\xf3\xb0\xbe\xa4" // U+F0FA4 +#define ICON_MDI_CAR_SEAT_COOLER "\xf3\xb0\xbe\xa5" // U+F0FA5 +#define ICON_MDI_CAR_SEAT_HEATER "\xf3\xb0\xbe\xa6" // U+F0FA6 +#define ICON_MDI_CAR_SELECT "\xf3\xb1\xa1\xb9" // U+F1879 +#define ICON_MDI_CAR_SETTINGS "\xf3\xb1\x8f\x8d" // U+F13CD +#define ICON_MDI_CAR_SHIFT_PATTERN "\xf3\xb0\xbd\x80" // U+F0F40 +#define ICON_MDI_CAR_SIDE "\xf3\xb0\x9e\xab" // U+F07AB +#define ICON_MDI_CAR_SPEED_LIMITER "\xf3\xb1\xa4\x8e" // U+F190E +#define ICON_MDI_CAR_SPORTS "\xf3\xb0\x9e\xac" // U+F07AC +#define ICON_MDI_CAR_TIRE_ALERT "\xf3\xb0\xb1\x8d" // U+F0C4D +#define ICON_MDI_CAR_TRACTION_CONTROL "\xf3\xb0\xb5\xa4" // U+F0D64 +#define ICON_MDI_CAR_TURBOCHARGER "\xf3\xb1\x80\x9a" // U+F101A +#define ICON_MDI_CAR_WASH "\xf3\xb0\x84\x8e" // U+F010E +#define ICON_MDI_CAR_WINDSHIELD "\xf3\xb1\x80\x9b" // U+F101B +#define ICON_MDI_CAR_WINDSHIELD_OUTLINE "\xf3\xb1\x80\x9c" // U+F101C +#define ICON_MDI_CAR_WIRELESS "\xf3\xb1\xa1\xb8" // U+F1878 +#define ICON_MDI_CAR_WRENCH "\xf3\xb1\xa0\x94" // U+F1814 +#define ICON_MDI_CARABINER "\xf3\xb1\x93\x80" // U+F14C0 +#define ICON_MDI_CARAVAN "\xf3\xb0\x9e\xad" // U+F07AD +#define ICON_MDI_CARD "\xf3\xb0\xad\xaf" // U+F0B6F +#define ICON_MDI_CARD_ACCOUNT_DETAILS "\xf3\xb0\x97\x92" // U+F05D2 +#define ICON_MDI_CARD_ACCOUNT_DETAILS_OUTLINE "\xf3\xb0\xb6\xab" // U+F0DAB +#define ICON_MDI_CARD_ACCOUNT_DETAILS_STAR "\xf3\xb0\x8a\xa3" // U+F02A3 +#define ICON_MDI_CARD_ACCOUNT_DETAILS_STAR_OUTLINE "\xf3\xb0\x9b\x9b" // U+F06DB +#define ICON_MDI_CARD_ACCOUNT_MAIL "\xf3\xb0\x86\x8e" // U+F018E +#define ICON_MDI_CARD_ACCOUNT_MAIL_OUTLINE "\xf3\xb0\xba\x98" // U+F0E98 +#define ICON_MDI_CARD_ACCOUNT_PHONE "\xf3\xb0\xba\x99" // U+F0E99 +#define ICON_MDI_CARD_ACCOUNT_PHONE_OUTLINE "\xf3\xb0\xba\x9a" // U+F0E9A +#define ICON_MDI_CARD_BULLETED "\xf3\xb0\xad\xb0" // U+F0B70 +#define ICON_MDI_CARD_BULLETED_OFF "\xf3\xb0\xad\xb1" // U+F0B71 +#define ICON_MDI_CARD_BULLETED_OFF_OUTLINE "\xf3\xb0\xad\xb2" // U+F0B72 +#define ICON_MDI_CARD_BULLETED_OUTLINE "\xf3\xb0\xad\xb3" // U+F0B73 +#define ICON_MDI_CARD_BULLETED_SETTINGS "\xf3\xb0\xad\xb4" // U+F0B74 +#define ICON_MDI_CARD_BULLETED_SETTINGS_OUTLINE "\xf3\xb0\xad\xb5" // U+F0B75 +#define ICON_MDI_CARD_MINUS "\xf3\xb1\x98\x80" // U+F1600 +#define ICON_MDI_CARD_MINUS_OUTLINE "\xf3\xb1\x98\x81" // U+F1601 +#define ICON_MDI_CARD_MULTIPLE "\xf3\xb1\x9f\xb1" // U+F17F1 +#define ICON_MDI_CARD_MULTIPLE_OUTLINE "\xf3\xb1\x9f\xb2" // U+F17F2 +#define ICON_MDI_CARD_OFF "\xf3\xb1\x98\x82" // U+F1602 +#define ICON_MDI_CARD_OFF_OUTLINE "\xf3\xb1\x98\x83" // U+F1603 +#define ICON_MDI_CARD_OUTLINE "\xf3\xb0\xad\xb6" // U+F0B76 +#define ICON_MDI_CARD_PLUS "\xf3\xb1\x87\xbf" // U+F11FF +#define ICON_MDI_CARD_PLUS_OUTLINE "\xf3\xb1\x88\x80" // U+F1200 +#define ICON_MDI_CARD_REMOVE "\xf3\xb1\x98\x84" // U+F1604 +#define ICON_MDI_CARD_REMOVE_OUTLINE "\xf3\xb1\x98\x85" // U+F1605 +#define ICON_MDI_CARD_SEARCH "\xf3\xb1\x81\xb4" // U+F1074 +#define ICON_MDI_CARD_SEARCH_OUTLINE "\xf3\xb1\x81\xb5" // U+F1075 +#define ICON_MDI_CARD_TEXT "\xf3\xb0\xad\xb7" // U+F0B77 +#define ICON_MDI_CARD_TEXT_OUTLINE "\xf3\xb0\xad\xb8" // U+F0B78 +#define ICON_MDI_CARDS "\xf3\xb0\x98\xb8" // U+F0638 +#define ICON_MDI_CARDS_CLUB "\xf3\xb0\xa3\x8e" // U+F08CE +#define ICON_MDI_CARDS_CLUB_OUTLINE "\xf3\xb1\xa2\x9f" // U+F189F +#define ICON_MDI_CARDS_DIAMOND "\xf3\xb0\xa3\x8f" // U+F08CF +#define ICON_MDI_CARDS_DIAMOND_OUTLINE "\xf3\xb1\x80\x9d" // U+F101D +#define ICON_MDI_CARDS_HEART "\xf3\xb0\xa3\x90" // U+F08D0 +#define ICON_MDI_CARDS_HEART_OUTLINE "\xf3\xb1\xa2\xa0" // U+F18A0 +#define ICON_MDI_CARDS_OUTLINE "\xf3\xb0\x98\xb9" // U+F0639 +#define ICON_MDI_CARDS_PLAYING "\xf3\xb1\xa2\xa1" // U+F18A1 +#define ICON_MDI_CARDS_PLAYING_CLUB "\xf3\xb1\xa2\xa2" // U+F18A2 +#define ICON_MDI_CARDS_PLAYING_CLUB_MULTIPLE "\xf3\xb1\xa2\xa3" // U+F18A3 +#define ICON_MDI_CARDS_PLAYING_CLUB_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xa4" // U+F18A4 +#define ICON_MDI_CARDS_PLAYING_CLUB_OUTLINE "\xf3\xb1\xa2\xa5" // U+F18A5 +#define ICON_MDI_CARDS_PLAYING_DIAMOND "\xf3\xb1\xa2\xa6" // U+F18A6 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_MULTIPLE "\xf3\xb1\xa2\xa7" // U+F18A7 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xa8" // U+F18A8 +#define ICON_MDI_CARDS_PLAYING_DIAMOND_OUTLINE "\xf3\xb1\xa2\xa9" // U+F18A9 +#define ICON_MDI_CARDS_PLAYING_HEART "\xf3\xb1\xa2\xaa" // U+F18AA +#define ICON_MDI_CARDS_PLAYING_HEART_MULTIPLE "\xf3\xb1\xa2\xab" // U+F18AB +#define ICON_MDI_CARDS_PLAYING_HEART_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xac" // U+F18AC +#define ICON_MDI_CARDS_PLAYING_HEART_OUTLINE "\xf3\xb1\xa2\xad" // U+F18AD +#define ICON_MDI_CARDS_PLAYING_OUTLINE "\xf3\xb0\x98\xba" // U+F063A +#define ICON_MDI_CARDS_PLAYING_SPADE "\xf3\xb1\xa2\xae" // U+F18AE +#define ICON_MDI_CARDS_PLAYING_SPADE_MULTIPLE "\xf3\xb1\xa2\xaf" // U+F18AF +#define ICON_MDI_CARDS_PLAYING_SPADE_MULTIPLE_OUTLINE "\xf3\xb1\xa2\xb0" // U+F18B0 +#define ICON_MDI_CARDS_PLAYING_SPADE_OUTLINE "\xf3\xb1\xa2\xb1" // U+F18B1 +#define ICON_MDI_CARDS_SPADE "\xf3\xb0\xa3\x91" // U+F08D1 +#define ICON_MDI_CARDS_SPADE_OUTLINE "\xf3\xb1\xa2\xb2" // U+F18B2 +#define ICON_MDI_CARDS_VARIANT "\xf3\xb0\x9b\x87" // U+F06C7 +#define ICON_MDI_CARROT "\xf3\xb0\x84\x8f" // U+F010F +#define ICON_MDI_CART "\xf3\xb0\x84\x90" // U+F0110 +#define ICON_MDI_CART_ARROW_DOWN "\xf3\xb0\xb5\xa6" // U+F0D66 +#define ICON_MDI_CART_ARROW_RIGHT "\xf3\xb0\xb1\x8e" // U+F0C4E +#define ICON_MDI_CART_ARROW_UP "\xf3\xb0\xb5\xa7" // U+F0D67 +#define ICON_MDI_CART_CHECK "\xf3\xb1\x97\xaa" // U+F15EA +#define ICON_MDI_CART_HEART "\xf3\xb1\xa3\xa0" // U+F18E0 +#define ICON_MDI_CART_MINUS "\xf3\xb0\xb5\xa8" // U+F0D68 +#define ICON_MDI_CART_OFF "\xf3\xb0\x99\xab" // U+F066B +#define ICON_MDI_CART_OUTLINE "\xf3\xb0\x84\x91" // U+F0111 +#define ICON_MDI_CART_PERCENT "\xf3\xb1\xae\xae" // U+F1BAE +#define ICON_MDI_CART_PLUS "\xf3\xb0\x84\x92" // U+F0112 +#define ICON_MDI_CART_REMOVE "\xf3\xb0\xb5\xa9" // U+F0D69 +#define ICON_MDI_CART_VARIANT "\xf3\xb1\x97\xab" // U+F15EB +#define ICON_MDI_CASE_SENSITIVE_ALT "\xf3\xb0\x84\x93" // U+F0113 +#define ICON_MDI_CASH "\xf3\xb0\x84\x94" // U+F0114 +#define ICON_MDI_CASH_100 "\xf3\xb0\x84\x95" // U+F0115 +#define ICON_MDI_CASH_CHECK "\xf3\xb1\x93\xae" // U+F14EE +#define ICON_MDI_CASH_CLOCK "\xf3\xb1\xaa\x91" // U+F1A91 +#define ICON_MDI_CASH_EDIT "\xf3\xb1\xb2\xab" // U+F1CAB +#define ICON_MDI_CASH_FAST "\xf3\xb1\xa1\x9c" // U+F185C +#define ICON_MDI_CASH_LOCK "\xf3\xb1\x93\xaa" // U+F14EA +#define ICON_MDI_CASH_LOCK_OPEN "\xf3\xb1\x93\xab" // U+F14EB +#define ICON_MDI_CASH_MARKER "\xf3\xb0\xb6\xb8" // U+F0DB8 +#define ICON_MDI_CASH_MINUS "\xf3\xb1\x89\xa0" // U+F1260 +#define ICON_MDI_CASH_MULTIPLE "\xf3\xb0\x84\x96" // U+F0116 +#define ICON_MDI_CASH_OFF "\xf3\xb1\xb1\xb9" // U+F1C79 +#define ICON_MDI_CASH_PLUS "\xf3\xb1\x89\xa1" // U+F1261 +#define ICON_MDI_CASH_REFUND "\xf3\xb0\xaa\x9c" // U+F0A9C +#define ICON_MDI_CASH_REGISTER "\xf3\xb0\xb3\xb4" // U+F0CF4 +#define ICON_MDI_CASH_REMOVE "\xf3\xb1\x89\xa2" // U+F1262 +#define ICON_MDI_CASH_SYNC "\xf3\xb1\xaa\x92" // U+F1A92 +#define ICON_MDI_CASSETTE "\xf3\xb0\xa7\x94" // U+F09D4 +#define ICON_MDI_CAST "\xf3\xb0\x84\x98" // U+F0118 +#define ICON_MDI_CAST_AUDIO "\xf3\xb1\x80\x9e" // U+F101E +#define ICON_MDI_CAST_AUDIO_VARIANT "\xf3\xb1\x9d\x89" // U+F1749 +#define ICON_MDI_CAST_CONNECTED "\xf3\xb0\x84\x99" // U+F0119 +#define ICON_MDI_CAST_EDUCATION "\xf3\xb0\xb8\x9d" // U+F0E1D +#define ICON_MDI_CAST_OFF "\xf3\xb0\x9e\x8a" // U+F078A +#define ICON_MDI_CAST_VARIANT "\xf3\xb0\x80\x9f" // U+F001F +#define ICON_MDI_CASTLE "\xf3\xb0\x84\x9a" // U+F011A +#define ICON_MDI_CAT "\xf3\xb0\x84\x9b" // U+F011B +#define ICON_MDI_CCTV "\xf3\xb0\x9e\xae" // U+F07AE +#define ICON_MDI_CCTV_OFF "\xf3\xb1\xa1\x9f" // U+F185F +#define ICON_MDI_CEILING_FAN "\xf3\xb1\x9e\x97" // U+F1797 +#define ICON_MDI_CEILING_FAN_LIGHT "\xf3\xb1\x9e\x98" // U+F1798 +#define ICON_MDI_CEILING_LIGHT "\xf3\xb0\x9d\xa9" // U+F0769 +#define ICON_MDI_CEILING_LIGHT_MULTIPLE "\xf3\xb1\xa3\x9d" // U+F18DD +#define ICON_MDI_CEILING_LIGHT_MULTIPLE_OUTLINE "\xf3\xb1\xa3\x9e" // U+F18DE +#define ICON_MDI_CEILING_LIGHT_OUTLINE "\xf3\xb1\x9f\x87" // U+F17C7 +#define ICON_MDI_CELLPHONE "\xf3\xb0\x84\x9c" // U+F011C +#define ICON_MDI_CELLPHONE_ARROW_DOWN "\xf3\xb0\xa7\x95" // U+F09D5 +#define ICON_MDI_CELLPHONE_ARROW_DOWN_VARIANT "\xf3\xb1\xa7\x85" // U+F19C5 +#define ICON_MDI_CELLPHONE_BASIC "\xf3\xb0\x84\x9e" // U+F011E +#define ICON_MDI_CELLPHONE_CHARGING "\xf3\xb1\x8e\x97" // U+F1397 +#define ICON_MDI_CELLPHONE_CHECK "\xf3\xb1\x9f\xbd" // U+F17FD +#define ICON_MDI_CELLPHONE_COG "\xf3\xb0\xa5\x91" // U+F0951 +#define ICON_MDI_CELLPHONE_DOCK "\xf3\xb0\x84\x9f" // U+F011F +#define ICON_MDI_CELLPHONE_INFORMATION "\xf3\xb0\xbd\x81" // U+F0F41 +#define ICON_MDI_CELLPHONE_KEY "\xf3\xb0\xa5\x8e" // U+F094E +#define ICON_MDI_CELLPHONE_LINK "\xf3\xb0\x84\xa1" // U+F0121 +#define ICON_MDI_CELLPHONE_LINK_OFF "\xf3\xb0\x84\xa2" // U+F0122 +#define ICON_MDI_CELLPHONE_LOCK "\xf3\xb0\xa5\x8f" // U+F094F +#define ICON_MDI_CELLPHONE_MARKER "\xf3\xb1\xa0\xba" // U+F183A +#define ICON_MDI_CELLPHONE_MESSAGE "\xf3\xb0\xa3\x93" // U+F08D3 +#define ICON_MDI_CELLPHONE_MESSAGE_OFF "\xf3\xb1\x83\x92" // U+F10D2 +#define ICON_MDI_CELLPHONE_NFC "\xf3\xb0\xba\x90" // U+F0E90 +#define ICON_MDI_CELLPHONE_NFC_OFF "\xf3\xb1\x8b\x98" // U+F12D8 +#define ICON_MDI_CELLPHONE_OFF "\xf3\xb0\xa5\x90" // U+F0950 +#define ICON_MDI_CELLPHONE_PLAY "\xf3\xb1\x80\x9f" // U+F101F +#define ICON_MDI_CELLPHONE_REMOVE "\xf3\xb0\xa5\x8d" // U+F094D +#define ICON_MDI_CELLPHONE_SCREENSHOT "\xf3\xb0\xa8\xb5" // U+F0A35 +#define ICON_MDI_CELLPHONE_SETTINGS "\xf3\xb0\x84\xa3" // U+F0123 +#define ICON_MDI_CELLPHONE_SOUND "\xf3\xb0\xa5\x92" // U+F0952 +#define ICON_MDI_CELLPHONE_TEXT "\xf3\xb0\xa3\x92" // U+F08D2 +#define ICON_MDI_CELLPHONE_WIRELESS "\xf3\xb0\xa0\x95" // U+F0815 +#define ICON_MDI_CENTOS "\xf3\xb1\x84\x9a" // U+F111A +#define ICON_MDI_CERTIFICATE "\xf3\xb0\x84\xa4" // U+F0124 +#define ICON_MDI_CERTIFICATE_OUTLINE "\xf3\xb1\x86\x88" // U+F1188 +#define ICON_MDI_CHAIR_ROLLING "\xf3\xb0\xbd\x88" // U+F0F48 +#define ICON_MDI_CHAIR_SCHOOL "\xf3\xb0\x84\xa5" // U+F0125 +#define ICON_MDI_CHANDELIER "\xf3\xb1\x9e\x93" // U+F1793 +#define ICON_MDI_CHARITY "\xf3\xb0\xb1\x8f" // U+F0C4F +#define ICON_MDI_CHARITY_SEARCH "\xf3\xb1\xb2\x82" // U+F1C82 +#define ICON_MDI_CHART_ARC "\xf3\xb0\x84\xa6" // U+F0126 +#define ICON_MDI_CHART_AREASPLINE "\xf3\xb0\x84\xa7" // U+F0127 +#define ICON_MDI_CHART_AREASPLINE_VARIANT "\xf3\xb0\xba\x91" // U+F0E91 +#define ICON_MDI_CHART_BAR "\xf3\xb0\x84\xa8" // U+F0128 +#define ICON_MDI_CHART_BAR_STACKED "\xf3\xb0\x9d\xaa" // U+F076A +#define ICON_MDI_CHART_BELL_CURVE "\xf3\xb0\xb1\x90" // U+F0C50 +#define ICON_MDI_CHART_BELL_CURVE_CUMULATIVE "\xf3\xb0\xbe\xa7" // U+F0FA7 +#define ICON_MDI_CHART_BOX "\xf3\xb1\x95\x8d" // U+F154D +#define ICON_MDI_CHART_BOX_OUTLINE "\xf3\xb1\x95\x8e" // U+F154E +#define ICON_MDI_CHART_BOX_PLUS_OUTLINE "\xf3\xb1\x95\x8f" // U+F154F +#define ICON_MDI_CHART_BUBBLE "\xf3\xb0\x97\xa3" // U+F05E3 +#define ICON_MDI_CHART_DONUT "\xf3\xb0\x9e\xaf" // U+F07AF +#define ICON_MDI_CHART_DONUT_VARIANT "\xf3\xb0\x9e\xb0" // U+F07B0 +#define ICON_MDI_CHART_GANTT "\xf3\xb0\x99\xac" // U+F066C +#define ICON_MDI_CHART_HISTOGRAM "\xf3\xb0\x84\xa9" // U+F0129 +#define ICON_MDI_CHART_LINE "\xf3\xb0\x84\xaa" // U+F012A +#define ICON_MDI_CHART_LINE_STACKED "\xf3\xb0\x9d\xab" // U+F076B +#define ICON_MDI_CHART_LINE_VARIANT "\xf3\xb0\x9e\xb1" // U+F07B1 +#define ICON_MDI_CHART_MULTILINE "\xf3\xb0\xa3\x94" // U+F08D4 +#define ICON_MDI_CHART_MULTIPLE "\xf3\xb1\x88\x93" // U+F1213 +#define ICON_MDI_CHART_PIE "\xf3\xb0\x84\xab" // U+F012B +#define ICON_MDI_CHART_PIE_OUTLINE "\xf3\xb1\xaf\x9f" // U+F1BDF +#define ICON_MDI_CHART_PPF "\xf3\xb1\x8e\x80" // U+F1380 +#define ICON_MDI_CHART_SANKEY "\xf3\xb1\x87\x9f" // U+F11DF +#define ICON_MDI_CHART_SANKEY_VARIANT "\xf3\xb1\x87\xa0" // U+F11E0 +#define ICON_MDI_CHART_SCATTER_PLOT "\xf3\xb0\xba\x92" // U+F0E92 +#define ICON_MDI_CHART_SCATTER_PLOT_HEXBIN "\xf3\xb0\x99\xad" // U+F066D +#define ICON_MDI_CHART_TIMELINE "\xf3\xb0\x99\xae" // U+F066E +#define ICON_MDI_CHART_TIMELINE_VARIANT "\xf3\xb0\xba\x93" // U+F0E93 +#define ICON_MDI_CHART_TIMELINE_VARIANT_SHIMMER "\xf3\xb1\x96\xb6" // U+F15B6 +#define ICON_MDI_CHART_TREE "\xf3\xb0\xba\x94" // U+F0E94 +#define ICON_MDI_CHART_WATERFALL "\xf3\xb1\xa4\x98" // U+F1918 +#define ICON_MDI_CHAT "\xf3\xb0\xad\xb9" // U+F0B79 +#define ICON_MDI_CHAT_ALERT "\xf3\xb0\xad\xba" // U+F0B7A +#define ICON_MDI_CHAT_ALERT_OUTLINE "\xf3\xb1\x8b\x89" // U+F12C9 +#define ICON_MDI_CHAT_MINUS "\xf3\xb1\x90\x90" // U+F1410 +#define ICON_MDI_CHAT_MINUS_OUTLINE "\xf3\xb1\x90\x93" // U+F1413 +#define ICON_MDI_CHAT_OUTLINE "\xf3\xb0\xbb\x9e" // U+F0EDE +#define ICON_MDI_CHAT_PLUS "\xf3\xb1\x90\x8f" // U+F140F +#define ICON_MDI_CHAT_PLUS_OUTLINE "\xf3\xb1\x90\x92" // U+F1412 +#define ICON_MDI_CHAT_PROCESSING "\xf3\xb0\xad\xbb" // U+F0B7B +#define ICON_MDI_CHAT_PROCESSING_OUTLINE "\xf3\xb1\x8b\x8a" // U+F12CA +#define ICON_MDI_CHAT_QUESTION "\xf3\xb1\x9c\xb8" // U+F1738 +#define ICON_MDI_CHAT_QUESTION_OUTLINE "\xf3\xb1\x9c\xb9" // U+F1739 +#define ICON_MDI_CHAT_REMOVE "\xf3\xb1\x90\x91" // U+F1411 +#define ICON_MDI_CHAT_REMOVE_OUTLINE "\xf3\xb1\x90\x94" // U+F1414 +#define ICON_MDI_CHAT_SLEEP "\xf3\xb1\x8b\x91" // U+F12D1 +#define ICON_MDI_CHAT_SLEEP_OUTLINE "\xf3\xb1\x8b\x92" // U+F12D2 +#define ICON_MDI_CHECK "\xf3\xb0\x84\xac" // U+F012C +#define ICON_MDI_CHECK_ALL "\xf3\xb0\x84\xad" // U+F012D +#define ICON_MDI_CHECK_BOLD "\xf3\xb0\xb8\x9e" // U+F0E1E +#define ICON_MDI_CHECK_CIRCLE "\xf3\xb0\x97\xa0" // U+F05E0 +#define ICON_MDI_CHECK_CIRCLE_OUTLINE "\xf3\xb0\x97\xa1" // U+F05E1 +#define ICON_MDI_CHECK_DECAGRAM "\xf3\xb0\x9e\x91" // U+F0791 +#define ICON_MDI_CHECK_DECAGRAM_OUTLINE "\xf3\xb1\x9d\x80" // U+F1740 +#define ICON_MDI_CHECK_NETWORK "\xf3\xb0\xb1\x93" // U+F0C53 +#define ICON_MDI_CHECK_NETWORK_OUTLINE "\xf3\xb0\xb1\x94" // U+F0C54 +#define ICON_MDI_CHECK_OUTLINE "\xf3\xb0\xa1\x95" // U+F0855 +#define ICON_MDI_CHECK_UNDERLINE "\xf3\xb0\xb8\x9f" // U+F0E1F +#define ICON_MDI_CHECK_UNDERLINE_CIRCLE "\xf3\xb0\xb8\xa0" // U+F0E20 +#define ICON_MDI_CHECK_UNDERLINE_CIRCLE_OUTLINE "\xf3\xb0\xb8\xa1" // U+F0E21 +#define ICON_MDI_CHECKBOOK "\xf3\xb0\xaa\x9d" // U+F0A9D +#define ICON_MDI_CHECKBOOK_ARROW_LEFT "\xf3\xb1\xb0\x9d" // U+F1C1D +#define ICON_MDI_CHECKBOOK_ARROW_RIGHT "\xf3\xb1\xb0\x9e" // U+F1C1E +#define ICON_MDI_CHECKBOX_BLANK "\xf3\xb0\x84\xae" // U+F012E +#define ICON_MDI_CHECKBOX_BLANK_BADGE "\xf3\xb1\x85\xb6" // U+F1176 +#define ICON_MDI_CHECKBOX_BLANK_BADGE_OUTLINE "\xf3\xb0\x84\x97" // U+F0117 +#define ICON_MDI_CHECKBOX_BLANK_CIRCLE "\xf3\xb0\x84\xaf" // U+F012F +#define ICON_MDI_CHECKBOX_BLANK_CIRCLE_OUTLINE "\xf3\xb0\x84\xb0" // U+F0130 +#define ICON_MDI_CHECKBOX_BLANK_OFF "\xf3\xb1\x8b\xac" // U+F12EC +#define ICON_MDI_CHECKBOX_BLANK_OFF_OUTLINE "\xf3\xb1\x8b\xad" // U+F12ED +#define ICON_MDI_CHECKBOX_BLANK_OUTLINE "\xf3\xb0\x84\xb1" // U+F0131 +#define ICON_MDI_CHECKBOX_INTERMEDIATE "\xf3\xb0\xa1\x96" // U+F0856 +#define ICON_MDI_CHECKBOX_INTERMEDIATE_VARIANT "\xf3\xb1\xad\x94" // U+F1B54 +#define ICON_MDI_CHECKBOX_MARKED "\xf3\xb0\x84\xb2" // U+F0132 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE "\xf3\xb0\x84\xb3" // U+F0133 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_AUTO_OUTLINE "\xf3\xb1\xb0\xa6" // U+F1C26 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_MINUS_OUTLINE "\xf3\xb1\xb0\xa7" // U+F1C27 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_OUTLINE "\xf3\xb0\x84\xb4" // U+F0134 +#define ICON_MDI_CHECKBOX_MARKED_CIRCLE_PLUS_OUTLINE "\xf3\xb1\xa4\xa7" // U+F1927 +#define ICON_MDI_CHECKBOX_MARKED_OUTLINE "\xf3\xb0\x84\xb5" // U+F0135 +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK "\xf3\xb0\x84\xb6" // U+F0136 +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_CIRCLE "\xf3\xb0\x98\xbb" // U+F063B +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_CIRCLE_OUTLINE "\xf3\xb0\x98\xbc" // U+F063C +#define ICON_MDI_CHECKBOX_MULTIPLE_BLANK_OUTLINE "\xf3\xb0\x84\xb7" // U+F0137 +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED "\xf3\xb0\x84\xb8" // U+F0138 +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_CIRCLE "\xf3\xb0\x98\xbd" // U+F063D +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_CIRCLE_OUTLINE "\xf3\xb0\x98\xbe" // U+F063E +#define ICON_MDI_CHECKBOX_MULTIPLE_MARKED_OUTLINE "\xf3\xb0\x84\xb9" // U+F0139 +#define ICON_MDI_CHECKBOX_MULTIPLE_OUTLINE "\xf3\xb0\xb1\x91" // U+F0C51 +#define ICON_MDI_CHECKBOX_OUTLINE "\xf3\xb0\xb1\x92" // U+F0C52 +#define ICON_MDI_CHECKERBOARD "\xf3\xb0\x84\xba" // U+F013A +#define ICON_MDI_CHECKERBOARD_MINUS "\xf3\xb1\x88\x82" // U+F1202 +#define ICON_MDI_CHECKERBOARD_PLUS "\xf3\xb1\x88\x81" // U+F1201 +#define ICON_MDI_CHECKERBOARD_REMOVE "\xf3\xb1\x88\x83" // U+F1203 +#define ICON_MDI_CHEESE "\xf3\xb1\x8a\xb9" // U+F12B9 +#define ICON_MDI_CHEESE_OFF "\xf3\xb1\x8f\xae" // U+F13EE +#define ICON_MDI_CHEF_HAT "\xf3\xb0\xad\xbc" // U+F0B7C +#define ICON_MDI_CHEMICAL_WEAPON "\xf3\xb0\x84\xbb" // U+F013B +#define ICON_MDI_CHESS_BISHOP "\xf3\xb0\xa1\x9c" // U+F085C +#define ICON_MDI_CHESS_KING "\xf3\xb0\xa1\x97" // U+F0857 +#define ICON_MDI_CHESS_KNIGHT "\xf3\xb0\xa1\x98" // U+F0858 +#define ICON_MDI_CHESS_PAWN "\xf3\xb0\xa1\x99" // U+F0859 +#define ICON_MDI_CHESS_QUEEN "\xf3\xb0\xa1\x9a" // U+F085A +#define ICON_MDI_CHESS_ROOK "\xf3\xb0\xa1\x9b" // U+F085B +#define ICON_MDI_CHEVRON_DOUBLE_DOWN "\xf3\xb0\x84\xbc" // U+F013C +#define ICON_MDI_CHEVRON_DOUBLE_LEFT "\xf3\xb0\x84\xbd" // U+F013D +#define ICON_MDI_CHEVRON_DOUBLE_RIGHT "\xf3\xb0\x84\xbe" // U+F013E +#define ICON_MDI_CHEVRON_DOUBLE_UP "\xf3\xb0\x84\xbf" // U+F013F +#define ICON_MDI_CHEVRON_DOWN "\xf3\xb0\x85\x80" // U+F0140 +#define ICON_MDI_CHEVRON_DOWN_BOX "\xf3\xb0\xa7\x96" // U+F09D6 +#define ICON_MDI_CHEVRON_DOWN_BOX_OUTLINE "\xf3\xb0\xa7\x97" // U+F09D7 +#define ICON_MDI_CHEVRON_DOWN_CIRCLE "\xf3\xb0\xac\xa6" // U+F0B26 +#define ICON_MDI_CHEVRON_DOWN_CIRCLE_OUTLINE "\xf3\xb0\xac\xa7" // U+F0B27 +#define ICON_MDI_CHEVRON_LEFT "\xf3\xb0\x85\x81" // U+F0141 +#define ICON_MDI_CHEVRON_LEFT_BOX "\xf3\xb0\xa7\x98" // U+F09D8 +#define ICON_MDI_CHEVRON_LEFT_BOX_OUTLINE "\xf3\xb0\xa7\x99" // U+F09D9 +#define ICON_MDI_CHEVRON_LEFT_CIRCLE "\xf3\xb0\xac\xa8" // U+F0B28 +#define ICON_MDI_CHEVRON_LEFT_CIRCLE_OUTLINE "\xf3\xb0\xac\xa9" // U+F0B29 +#define ICON_MDI_CHEVRON_RIGHT "\xf3\xb0\x85\x82" // U+F0142 +#define ICON_MDI_CHEVRON_RIGHT_BOX "\xf3\xb0\xa7\x9a" // U+F09DA +#define ICON_MDI_CHEVRON_RIGHT_BOX_OUTLINE "\xf3\xb0\xa7\x9b" // U+F09DB +#define ICON_MDI_CHEVRON_RIGHT_CIRCLE "\xf3\xb0\xac\xaa" // U+F0B2A +#define ICON_MDI_CHEVRON_RIGHT_CIRCLE_OUTLINE "\xf3\xb0\xac\xab" // U+F0B2B +#define ICON_MDI_CHEVRON_TRIPLE_DOWN "\xf3\xb0\xb6\xb9" // U+F0DB9 +#define ICON_MDI_CHEVRON_TRIPLE_LEFT "\xf3\xb0\xb6\xba" // U+F0DBA +#define ICON_MDI_CHEVRON_TRIPLE_RIGHT "\xf3\xb0\xb6\xbb" // U+F0DBB +#define ICON_MDI_CHEVRON_TRIPLE_UP "\xf3\xb0\xb6\xbc" // U+F0DBC +#define ICON_MDI_CHEVRON_UP "\xf3\xb0\x85\x83" // U+F0143 +#define ICON_MDI_CHEVRON_UP_BOX "\xf3\xb0\xa7\x9c" // U+F09DC +#define ICON_MDI_CHEVRON_UP_BOX_OUTLINE "\xf3\xb0\xa7\x9d" // U+F09DD +#define ICON_MDI_CHEVRON_UP_CIRCLE "\xf3\xb0\xac\xac" // U+F0B2C +#define ICON_MDI_CHEVRON_UP_CIRCLE_OUTLINE "\xf3\xb0\xac\xad" // U+F0B2D +#define ICON_MDI_CHILI_ALERT "\xf3\xb1\x9f\xaa" // U+F17EA +#define ICON_MDI_CHILI_ALERT_OUTLINE "\xf3\xb1\x9f\xab" // U+F17EB +#define ICON_MDI_CHILI_HOT "\xf3\xb0\x9e\xb2" // U+F07B2 +#define ICON_MDI_CHILI_HOT_OUTLINE "\xf3\xb1\x9f\xac" // U+F17EC +#define ICON_MDI_CHILI_MEDIUM "\xf3\xb0\x9e\xb3" // U+F07B3 +#define ICON_MDI_CHILI_MEDIUM_OUTLINE "\xf3\xb1\x9f\xad" // U+F17ED +#define ICON_MDI_CHILI_MILD "\xf3\xb0\x9e\xb4" // U+F07B4 +#define ICON_MDI_CHILI_MILD_OUTLINE "\xf3\xb1\x9f\xae" // U+F17EE +#define ICON_MDI_CHILI_OFF "\xf3\xb1\x91\xa7" // U+F1467 +#define ICON_MDI_CHILI_OFF_OUTLINE "\xf3\xb1\x9f\xaf" // U+F17EF +#define ICON_MDI_CHIP "\xf3\xb0\x98\x9a" // U+F061A +#define ICON_MDI_CHURCH "\xf3\xb0\x85\x84" // U+F0144 +#define ICON_MDI_CHURCH_OUTLINE "\xf3\xb1\xac\x82" // U+F1B02 +#define ICON_MDI_CIGAR "\xf3\xb1\x86\x89" // U+F1189 +#define ICON_MDI_CIGAR_OFF "\xf3\xb1\x90\x9b" // U+F141B +#define ICON_MDI_CIRCLE "\xf3\xb0\x9d\xa5" // U+F0765 +#define ICON_MDI_CIRCLE_BOX "\xf3\xb1\x97\x9c" // U+F15DC +#define ICON_MDI_CIRCLE_BOX_OUTLINE "\xf3\xb1\x97\x9d" // U+F15DD +#define ICON_MDI_CIRCLE_DOUBLE "\xf3\xb0\xba\x95" // U+F0E95 +#define ICON_MDI_CIRCLE_EDIT_OUTLINE "\xf3\xb0\xa3\x95" // U+F08D5 +#define ICON_MDI_CIRCLE_EXPAND "\xf3\xb0\xba\x96" // U+F0E96 +#define ICON_MDI_CIRCLE_HALF "\xf3\xb1\x8e\x95" // U+F1395 +#define ICON_MDI_CIRCLE_HALF_FULL "\xf3\xb1\x8e\x96" // U+F1396 +#define ICON_MDI_CIRCLE_MEDIUM "\xf3\xb0\xa7\x9e" // U+F09DE +#define ICON_MDI_CIRCLE_MULTIPLE "\xf3\xb0\xac\xb8" // U+F0B38 +#define ICON_MDI_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\x9a\x95" // U+F0695 +#define ICON_MDI_CIRCLE_OFF_OUTLINE "\xf3\xb1\x83\x93" // U+F10D3 +#define ICON_MDI_CIRCLE_OPACITY "\xf3\xb1\xa1\x93" // U+F1853 +#define ICON_MDI_CIRCLE_OUTLINE "\xf3\xb0\x9d\xa6" // U+F0766 +#define ICON_MDI_CIRCLE_SLICE_1 "\xf3\xb0\xaa\x9e" // U+F0A9E +#define ICON_MDI_CIRCLE_SLICE_2 "\xf3\xb0\xaa\x9f" // U+F0A9F +#define ICON_MDI_CIRCLE_SLICE_3 "\xf3\xb0\xaa\xa0" // U+F0AA0 +#define ICON_MDI_CIRCLE_SLICE_4 "\xf3\xb0\xaa\xa1" // U+F0AA1 +#define ICON_MDI_CIRCLE_SLICE_5 "\xf3\xb0\xaa\xa2" // U+F0AA2 +#define ICON_MDI_CIRCLE_SLICE_6 "\xf3\xb0\xaa\xa3" // U+F0AA3 +#define ICON_MDI_CIRCLE_SLICE_7 "\xf3\xb0\xaa\xa4" // U+F0AA4 +#define ICON_MDI_CIRCLE_SLICE_8 "\xf3\xb0\xaa\xa5" // U+F0AA5 +#define ICON_MDI_CIRCLE_SMALL "\xf3\xb0\xa7\x9f" // U+F09DF +#define ICON_MDI_CIRCULAR_SAW "\xf3\xb0\xb8\xa2" // U+F0E22 +#define ICON_MDI_CITY "\xf3\xb0\x85\x86" // U+F0146 +#define ICON_MDI_CITY_SWITCH "\xf3\xb1\xb0\xa8" // U+F1C28 +#define ICON_MDI_CITY_VARIANT "\xf3\xb0\xa8\xb6" // U+F0A36 +#define ICON_MDI_CITY_VARIANT_OUTLINE "\xf3\xb0\xa8\xb7" // U+F0A37 +#define ICON_MDI_CLIPBOARD "\xf3\xb0\x85\x87" // U+F0147 +#define ICON_MDI_CLIPBOARD_ACCOUNT "\xf3\xb0\x85\x88" // U+F0148 +#define ICON_MDI_CLIPBOARD_ACCOUNT_OUTLINE "\xf3\xb0\xb1\x95" // U+F0C55 +#define ICON_MDI_CLIPBOARD_ALERT "\xf3\xb0\x85\x89" // U+F0149 +#define ICON_MDI_CLIPBOARD_ALERT_OUTLINE "\xf3\xb0\xb3\xb7" // U+F0CF7 +#define ICON_MDI_CLIPBOARD_ARROW_DOWN "\xf3\xb0\x85\x8a" // U+F014A +#define ICON_MDI_CLIPBOARD_ARROW_DOWN_OUTLINE "\xf3\xb0\xb1\x96" // U+F0C56 +#define ICON_MDI_CLIPBOARD_ARROW_LEFT "\xf3\xb0\x85\x8b" // U+F014B +#define ICON_MDI_CLIPBOARD_ARROW_LEFT_OUTLINE "\xf3\xb0\xb3\xb8" // U+F0CF8 +#define ICON_MDI_CLIPBOARD_ARROW_RIGHT "\xf3\xb0\xb3\xb9" // U+F0CF9 +#define ICON_MDI_CLIPBOARD_ARROW_RIGHT_OUTLINE "\xf3\xb0\xb3\xba" // U+F0CFA +#define ICON_MDI_CLIPBOARD_ARROW_UP "\xf3\xb0\xb1\x97" // U+F0C57 +#define ICON_MDI_CLIPBOARD_ARROW_UP_OUTLINE "\xf3\xb0\xb1\x98" // U+F0C58 +#define ICON_MDI_CLIPBOARD_CHECK "\xf3\xb0\x85\x8e" // U+F014E +#define ICON_MDI_CLIPBOARD_CHECK_MULTIPLE "\xf3\xb1\x89\xa3" // U+F1263 +#define ICON_MDI_CLIPBOARD_CHECK_MULTIPLE_OUTLINE "\xf3\xb1\x89\xa4" // U+F1264 +#define ICON_MDI_CLIPBOARD_CHECK_OUTLINE "\xf3\xb0\xa2\xa8" // U+F08A8 +#define ICON_MDI_CLIPBOARD_CLOCK "\xf3\xb1\x9b\xa2" // U+F16E2 +#define ICON_MDI_CLIPBOARD_CLOCK_OUTLINE "\xf3\xb1\x9b\xa3" // U+F16E3 +#define ICON_MDI_CLIPBOARD_EDIT "\xf3\xb1\x93\xa5" // U+F14E5 +#define ICON_MDI_CLIPBOARD_EDIT_OUTLINE "\xf3\xb1\x93\xa6" // U+F14E6 +#define ICON_MDI_CLIPBOARD_FILE "\xf3\xb1\x89\xa5" // U+F1265 +#define ICON_MDI_CLIPBOARD_FILE_OUTLINE "\xf3\xb1\x89\xa6" // U+F1266 +#define ICON_MDI_CLIPBOARD_FLOW "\xf3\xb0\x9b\x88" // U+F06C8 +#define ICON_MDI_CLIPBOARD_FLOW_OUTLINE "\xf3\xb1\x84\x97" // U+F1117 +#define ICON_MDI_CLIPBOARD_LIST "\xf3\xb1\x83\x94" // U+F10D4 +#define ICON_MDI_CLIPBOARD_LIST_OUTLINE "\xf3\xb1\x83\x95" // U+F10D5 +#define ICON_MDI_CLIPBOARD_MINUS "\xf3\xb1\x98\x98" // U+F1618 +#define ICON_MDI_CLIPBOARD_MINUS_OUTLINE "\xf3\xb1\x98\x99" // U+F1619 +#define ICON_MDI_CLIPBOARD_MULTIPLE "\xf3\xb1\x89\xa7" // U+F1267 +#define ICON_MDI_CLIPBOARD_MULTIPLE_OUTLINE "\xf3\xb1\x89\xa8" // U+F1268 +#define ICON_MDI_CLIPBOARD_OFF "\xf3\xb1\x98\x9a" // U+F161A +#define ICON_MDI_CLIPBOARD_OFF_OUTLINE "\xf3\xb1\x98\x9b" // U+F161B +#define ICON_MDI_CLIPBOARD_OUTLINE "\xf3\xb0\x85\x8c" // U+F014C +#define ICON_MDI_CLIPBOARD_PLAY "\xf3\xb0\xb1\x99" // U+F0C59 +#define ICON_MDI_CLIPBOARD_PLAY_MULTIPLE "\xf3\xb1\x89\xa9" // U+F1269 +#define ICON_MDI_CLIPBOARD_PLAY_MULTIPLE_OUTLINE "\xf3\xb1\x89\xaa" // U+F126A +#define ICON_MDI_CLIPBOARD_PLAY_OUTLINE "\xf3\xb0\xb1\x9a" // U+F0C5A +#define ICON_MDI_CLIPBOARD_PLUS "\xf3\xb0\x9d\x91" // U+F0751 +#define ICON_MDI_CLIPBOARD_PLUS_OUTLINE "\xf3\xb1\x8c\x9f" // U+F131F +#define ICON_MDI_CLIPBOARD_PULSE "\xf3\xb0\xa1\x9d" // U+F085D +#define ICON_MDI_CLIPBOARD_PULSE_OUTLINE "\xf3\xb0\xa1\x9e" // U+F085E +#define ICON_MDI_CLIPBOARD_REMOVE "\xf3\xb1\x98\x9c" // U+F161C +#define ICON_MDI_CLIPBOARD_REMOVE_OUTLINE "\xf3\xb1\x98\x9d" // U+F161D +#define ICON_MDI_CLIPBOARD_SEARCH "\xf3\xb1\x98\x9e" // U+F161E +#define ICON_MDI_CLIPBOARD_SEARCH_OUTLINE "\xf3\xb1\x98\x9f" // U+F161F +#define ICON_MDI_CLIPBOARD_TEXT "\xf3\xb0\x85\x8d" // U+F014D +#define ICON_MDI_CLIPBOARD_TEXT_CLOCK "\xf3\xb1\xa3\xb9" // U+F18F9 +#define ICON_MDI_CLIPBOARD_TEXT_CLOCK_OUTLINE "\xf3\xb1\xa3\xba" // U+F18FA +#define ICON_MDI_CLIPBOARD_TEXT_MULTIPLE "\xf3\xb1\x89\xab" // U+F126B +#define ICON_MDI_CLIPBOARD_TEXT_MULTIPLE_OUTLINE "\xf3\xb1\x89\xac" // U+F126C +#define ICON_MDI_CLIPBOARD_TEXT_OFF "\xf3\xb1\x98\xa0" // U+F1620 +#define ICON_MDI_CLIPBOARD_TEXT_OFF_OUTLINE "\xf3\xb1\x98\xa1" // U+F1621 +#define ICON_MDI_CLIPBOARD_TEXT_OUTLINE "\xf3\xb0\xa8\xb8" // U+F0A38 +#define ICON_MDI_CLIPBOARD_TEXT_PLAY "\xf3\xb0\xb1\x9b" // U+F0C5B +#define ICON_MDI_CLIPBOARD_TEXT_PLAY_OUTLINE "\xf3\xb0\xb1\x9c" // U+F0C5C +#define ICON_MDI_CLIPBOARD_TEXT_SEARCH "\xf3\xb1\x98\xa2" // U+F1622 +#define ICON_MDI_CLIPBOARD_TEXT_SEARCH_OUTLINE "\xf3\xb1\x98\xa3" // U+F1623 +#define ICON_MDI_CLIPPY "\xf3\xb0\x85\x8f" // U+F014F +#define ICON_MDI_CLOCK "\xf3\xb0\xa5\x94" // U+F0954 +#define ICON_MDI_CLOCK_ALERT "\xf3\xb0\xa5\x95" // U+F0955 +#define ICON_MDI_CLOCK_ALERT_OUTLINE "\xf3\xb0\x97\x8e" // U+F05CE +#define ICON_MDI_CLOCK_CHECK "\xf3\xb0\xbe\xa8" // U+F0FA8 +#define ICON_MDI_CLOCK_CHECK_OUTLINE "\xf3\xb0\xbe\xa9" // U+F0FA9 +#define ICON_MDI_CLOCK_DIGITAL "\xf3\xb0\xba\x97" // U+F0E97 +#define ICON_MDI_CLOCK_EDIT "\xf3\xb1\xa6\xba" // U+F19BA +#define ICON_MDI_CLOCK_EDIT_OUTLINE "\xf3\xb1\xa6\xbb" // U+F19BB +#define ICON_MDI_CLOCK_END "\xf3\xb0\x85\x91" // U+F0151 +#define ICON_MDI_CLOCK_FAST "\xf3\xb0\x85\x92" // U+F0152 +#define ICON_MDI_CLOCK_IN "\xf3\xb0\x85\x93" // U+F0153 +#define ICON_MDI_CLOCK_MINUS "\xf3\xb1\xa1\xa3" // U+F1863 +#define ICON_MDI_CLOCK_MINUS_OUTLINE "\xf3\xb1\xa1\xa4" // U+F1864 +#define ICON_MDI_CLOCK_OUT "\xf3\xb0\x85\x94" // U+F0154 +#define ICON_MDI_CLOCK_OUTLINE "\xf3\xb0\x85\x90" // U+F0150 +#define ICON_MDI_CLOCK_PLUS "\xf3\xb1\xa1\xa1" // U+F1861 +#define ICON_MDI_CLOCK_PLUS_OUTLINE "\xf3\xb1\xa1\xa2" // U+F1862 +#define ICON_MDI_CLOCK_REMOVE "\xf3\xb1\xa1\xa5" // U+F1865 +#define ICON_MDI_CLOCK_REMOVE_OUTLINE "\xf3\xb1\xa1\xa6" // U+F1866 +#define ICON_MDI_CLOCK_STAR_FOUR_POINTS "\xf3\xb1\xb0\xa9" // U+F1C29 +#define ICON_MDI_CLOCK_STAR_FOUR_POINTS_OUTLINE "\xf3\xb1\xb0\xaa" // U+F1C2A +#define ICON_MDI_CLOCK_START "\xf3\xb0\x85\x95" // U+F0155 +#define ICON_MDI_CLOCK_TIME_EIGHT "\xf3\xb1\x91\x86" // U+F1446 +#define ICON_MDI_CLOCK_TIME_EIGHT_OUTLINE "\xf3\xb1\x91\x92" // U+F1452 +#define ICON_MDI_CLOCK_TIME_ELEVEN "\xf3\xb1\x91\x89" // U+F1449 +#define ICON_MDI_CLOCK_TIME_ELEVEN_OUTLINE "\xf3\xb1\x91\x95" // U+F1455 +#define ICON_MDI_CLOCK_TIME_FIVE "\xf3\xb1\x91\x83" // U+F1443 +#define ICON_MDI_CLOCK_TIME_FIVE_OUTLINE "\xf3\xb1\x91\x8f" // U+F144F +#define ICON_MDI_CLOCK_TIME_FOUR "\xf3\xb1\x91\x82" // U+F1442 +#define ICON_MDI_CLOCK_TIME_FOUR_OUTLINE "\xf3\xb1\x91\x8e" // U+F144E +#define ICON_MDI_CLOCK_TIME_NINE "\xf3\xb1\x91\x87" // U+F1447 +#define ICON_MDI_CLOCK_TIME_NINE_OUTLINE "\xf3\xb1\x91\x93" // U+F1453 +#define ICON_MDI_CLOCK_TIME_ONE "\xf3\xb1\x90\xbf" // U+F143F +#define ICON_MDI_CLOCK_TIME_ONE_OUTLINE "\xf3\xb1\x91\x8b" // U+F144B +#define ICON_MDI_CLOCK_TIME_SEVEN "\xf3\xb1\x91\x85" // U+F1445 +#define ICON_MDI_CLOCK_TIME_SEVEN_OUTLINE "\xf3\xb1\x91\x91" // U+F1451 +#define ICON_MDI_CLOCK_TIME_SIX "\xf3\xb1\x91\x84" // U+F1444 +#define ICON_MDI_CLOCK_TIME_SIX_OUTLINE "\xf3\xb1\x91\x90" // U+F1450 +#define ICON_MDI_CLOCK_TIME_TEN "\xf3\xb1\x91\x88" // U+F1448 +#define ICON_MDI_CLOCK_TIME_TEN_OUTLINE "\xf3\xb1\x91\x94" // U+F1454 +#define ICON_MDI_CLOCK_TIME_THREE "\xf3\xb1\x91\x81" // U+F1441 +#define ICON_MDI_CLOCK_TIME_THREE_OUTLINE "\xf3\xb1\x91\x8d" // U+F144D +#define ICON_MDI_CLOCK_TIME_TWELVE "\xf3\xb1\x91\x8a" // U+F144A +#define ICON_MDI_CLOCK_TIME_TWELVE_OUTLINE "\xf3\xb1\x91\x96" // U+F1456 +#define ICON_MDI_CLOCK_TIME_TWO "\xf3\xb1\x91\x80" // U+F1440 +#define ICON_MDI_CLOCK_TIME_TWO_OUTLINE "\xf3\xb1\x91\x8c" // U+F144C +#define ICON_MDI_CLOSE "\xf3\xb0\x85\x96" // U+F0156 +#define ICON_MDI_CLOSE_BOX "\xf3\xb0\x85\x97" // U+F0157 +#define ICON_MDI_CLOSE_BOX_MULTIPLE "\xf3\xb0\xb1\x9d" // U+F0C5D +#define ICON_MDI_CLOSE_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xb1\x9e" // U+F0C5E +#define ICON_MDI_CLOSE_BOX_OUTLINE "\xf3\xb0\x85\x98" // U+F0158 +#define ICON_MDI_CLOSE_CIRCLE "\xf3\xb0\x85\x99" // U+F0159 +#define ICON_MDI_CLOSE_CIRCLE_MULTIPLE "\xf3\xb0\x98\xaa" // U+F062A +#define ICON_MDI_CLOSE_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\xa2\x83" // U+F0883 +#define ICON_MDI_CLOSE_CIRCLE_OUTLINE "\xf3\xb0\x85\x9a" // U+F015A +#define ICON_MDI_CLOSE_NETWORK "\xf3\xb0\x85\x9b" // U+F015B +#define ICON_MDI_CLOSE_NETWORK_OUTLINE "\xf3\xb0\xb1\x9f" // U+F0C5F +#define ICON_MDI_CLOSE_OCTAGON "\xf3\xb0\x85\x9c" // U+F015C +#define ICON_MDI_CLOSE_OCTAGON_OUTLINE "\xf3\xb0\x85\x9d" // U+F015D +#define ICON_MDI_CLOSE_OUTLINE "\xf3\xb0\x9b\x89" // U+F06C9 +#define ICON_MDI_CLOSE_THICK "\xf3\xb1\x8e\x98" // U+F1398 +#define ICON_MDI_CLOSED_CAPTION "\xf3\xb0\x85\x9e" // U+F015E +#define ICON_MDI_CLOSED_CAPTION_OUTLINE "\xf3\xb0\xb6\xbd" // U+F0DBD +#define ICON_MDI_CLOUD "\xf3\xb0\x85\x9f" // U+F015F +#define ICON_MDI_CLOUD_ALERT "\xf3\xb0\xa7\xa0" // U+F09E0 +#define ICON_MDI_CLOUD_ALERT_OUTLINE "\xf3\xb1\xaf\xa0" // U+F1BE0 +#define ICON_MDI_CLOUD_ARROW_DOWN "\xf3\xb1\xaf\xa1" // U+F1BE1 +#define ICON_MDI_CLOUD_ARROW_DOWN_OUTLINE "\xf3\xb1\xaf\xa2" // U+F1BE2 +#define ICON_MDI_CLOUD_ARROW_LEFT "\xf3\xb1\xaf\xa3" // U+F1BE3 +#define ICON_MDI_CLOUD_ARROW_LEFT_OUTLINE "\xf3\xb1\xaf\xa4" // U+F1BE4 +#define ICON_MDI_CLOUD_ARROW_RIGHT "\xf3\xb1\xaf\xa5" // U+F1BE5 +#define ICON_MDI_CLOUD_ARROW_RIGHT_OUTLINE "\xf3\xb1\xaf\xa6" // U+F1BE6 +#define ICON_MDI_CLOUD_ARROW_UP "\xf3\xb1\xaf\xa7" // U+F1BE7 +#define ICON_MDI_CLOUD_ARROW_UP_OUTLINE "\xf3\xb1\xaf\xa8" // U+F1BE8 +#define ICON_MDI_CLOUD_BRACES "\xf3\xb0\x9e\xb5" // U+F07B5 +#define ICON_MDI_CLOUD_CANCEL "\xf3\xb1\xaf\xa9" // U+F1BE9 +#define ICON_MDI_CLOUD_CANCEL_OUTLINE "\xf3\xb1\xaf\xaa" // U+F1BEA +#define ICON_MDI_CLOUD_CHECK "\xf3\xb1\xaf\xab" // U+F1BEB +#define ICON_MDI_CLOUD_CHECK_OUTLINE "\xf3\xb1\xaf\xac" // U+F1BEC +#define ICON_MDI_CLOUD_CHECK_VARIANT "\xf3\xb0\x85\xa0" // U+F0160 +#define ICON_MDI_CLOUD_CHECK_VARIANT_OUTLINE "\xf3\xb1\x8b\x8c" // U+F12CC +#define ICON_MDI_CLOUD_CIRCLE "\xf3\xb0\x85\xa1" // U+F0161 +#define ICON_MDI_CLOUD_CIRCLE_OUTLINE "\xf3\xb1\xaf\xad" // U+F1BED +#define ICON_MDI_CLOUD_CLOCK "\xf3\xb1\xaf\xae" // U+F1BEE +#define ICON_MDI_CLOUD_CLOCK_OUTLINE "\xf3\xb1\xaf\xaf" // U+F1BEF +#define ICON_MDI_CLOUD_COG "\xf3\xb1\xaf\xb0" // U+F1BF0 +#define ICON_MDI_CLOUD_COG_OUTLINE "\xf3\xb1\xaf\xb1" // U+F1BF1 +#define ICON_MDI_CLOUD_DOWNLOAD "\xf3\xb0\x85\xa2" // U+F0162 +#define ICON_MDI_CLOUD_DOWNLOAD_OUTLINE "\xf3\xb0\xad\xbd" // U+F0B7D +#define ICON_MDI_CLOUD_KEY "\xf3\xb1\xb2\xa1" // U+F1CA1 +#define ICON_MDI_CLOUD_KEY_OUTLINE "\xf3\xb1\xb2\xa2" // U+F1CA2 +#define ICON_MDI_CLOUD_LOCK "\xf3\xb1\x87\xb1" // U+F11F1 +#define ICON_MDI_CLOUD_LOCK_OPEN "\xf3\xb1\xaf\xb2" // U+F1BF2 +#define ICON_MDI_CLOUD_LOCK_OPEN_OUTLINE "\xf3\xb1\xaf\xb3" // U+F1BF3 +#define ICON_MDI_CLOUD_LOCK_OUTLINE "\xf3\xb1\x87\xb2" // U+F11F2 +#define ICON_MDI_CLOUD_MINUS "\xf3\xb1\xaf\xb4" // U+F1BF4 +#define ICON_MDI_CLOUD_MINUS_OUTLINE "\xf3\xb1\xaf\xb5" // U+F1BF5 +#define ICON_MDI_CLOUD_OFF "\xf3\xb1\xaf\xb6" // U+F1BF6 +#define ICON_MDI_CLOUD_OFF_OUTLINE "\xf3\xb0\x85\xa4" // U+F0164 +#define ICON_MDI_CLOUD_OUTLINE "\xf3\xb0\x85\xa3" // U+F0163 +#define ICON_MDI_CLOUD_PERCENT "\xf3\xb1\xa8\xb5" // U+F1A35 +#define ICON_MDI_CLOUD_PERCENT_OUTLINE "\xf3\xb1\xa8\xb6" // U+F1A36 +#define ICON_MDI_CLOUD_PLUS "\xf3\xb1\xaf\xb7" // U+F1BF7 +#define ICON_MDI_CLOUD_PLUS_OUTLINE "\xf3\xb1\xaf\xb8" // U+F1BF8 +#define ICON_MDI_CLOUD_PRINT "\xf3\xb0\x85\xa5" // U+F0165 +#define ICON_MDI_CLOUD_PRINT_OUTLINE "\xf3\xb0\x85\xa6" // U+F0166 +#define ICON_MDI_CLOUD_QUESTION "\xf3\xb0\xa8\xb9" // U+F0A39 +#define ICON_MDI_CLOUD_QUESTION_OUTLINE "\xf3\xb1\xaf\xb9" // U+F1BF9 +#define ICON_MDI_CLOUD_REFRESH "\xf3\xb1\xaf\xba" // U+F1BFA +#define ICON_MDI_CLOUD_REFRESH_OUTLINE "\xf3\xb1\xaf\xbb" // U+F1BFB +#define ICON_MDI_CLOUD_REFRESH_VARIANT "\xf3\xb0\x94\xaa" // U+F052A +#define ICON_MDI_CLOUD_REFRESH_VARIANT_OUTLINE "\xf3\xb1\xaf\xbc" // U+F1BFC +#define ICON_MDI_CLOUD_REMOVE "\xf3\xb1\xaf\xbd" // U+F1BFD +#define ICON_MDI_CLOUD_REMOVE_OUTLINE "\xf3\xb1\xaf\xbe" // U+F1BFE +#define ICON_MDI_CLOUD_SEARCH "\xf3\xb0\xa5\x96" // U+F0956 +#define ICON_MDI_CLOUD_SEARCH_OUTLINE "\xf3\xb0\xa5\x97" // U+F0957 +#define ICON_MDI_CLOUD_SYNC "\xf3\xb0\x98\xbf" // U+F063F +#define ICON_MDI_CLOUD_SYNC_OUTLINE "\xf3\xb1\x8b\x96" // U+F12D6 +#define ICON_MDI_CLOUD_TAGS "\xf3\xb0\x9e\xb6" // U+F07B6 +#define ICON_MDI_CLOUD_UPLOAD "\xf3\xb0\x85\xa7" // U+F0167 +#define ICON_MDI_CLOUD_UPLOAD_OUTLINE "\xf3\xb0\xad\xbe" // U+F0B7E +#define ICON_MDI_CLOUDS "\xf3\xb1\xae\x95" // U+F1B95 +#define ICON_MDI_CLOVER "\xf3\xb0\xa0\x96" // U+F0816 +#define ICON_MDI_CLOVER_OUTLINE "\xf3\xb1\xb1\xa2" // U+F1C62 +#define ICON_MDI_COACH_LAMP "\xf3\xb1\x80\xa0" // U+F1020 +#define ICON_MDI_COACH_LAMP_VARIANT "\xf3\xb1\xa8\xb7" // U+F1A37 +#define ICON_MDI_COAT_RACK "\xf3\xb1\x82\x9e" // U+F109E +#define ICON_MDI_CODE_ARRAY "\xf3\xb0\x85\xa8" // U+F0168 +#define ICON_MDI_CODE_BLOCK_BRACES "\xf3\xb1\xb2\x83" // U+F1C83 +#define ICON_MDI_CODE_BLOCK_BRACKETS "\xf3\xb1\xb2\x84" // U+F1C84 +#define ICON_MDI_CODE_BLOCK_PARENTHESES "\xf3\xb1\xb2\x85" // U+F1C85 +#define ICON_MDI_CODE_BLOCK_TAGS "\xf3\xb1\xb2\x86" // U+F1C86 +#define ICON_MDI_CODE_BRACES "\xf3\xb0\x85\xa9" // U+F0169 +#define ICON_MDI_CODE_BRACES_BOX "\xf3\xb1\x83\x96" // U+F10D6 +#define ICON_MDI_CODE_BRACKETS "\xf3\xb0\x85\xaa" // U+F016A +#define ICON_MDI_CODE_EQUAL "\xf3\xb0\x85\xab" // U+F016B +#define ICON_MDI_CODE_GREATER_THAN "\xf3\xb0\x85\xac" // U+F016C +#define ICON_MDI_CODE_GREATER_THAN_OR_EQUAL "\xf3\xb0\x85\xad" // U+F016D +#define ICON_MDI_CODE_JSON "\xf3\xb0\x98\xa6" // U+F0626 +#define ICON_MDI_CODE_LESS_THAN "\xf3\xb0\x85\xae" // U+F016E +#define ICON_MDI_CODE_LESS_THAN_OR_EQUAL "\xf3\xb0\x85\xaf" // U+F016F +#define ICON_MDI_CODE_NOT_EQUAL "\xf3\xb0\x85\xb0" // U+F0170 +#define ICON_MDI_CODE_NOT_EQUAL_VARIANT "\xf3\xb0\x85\xb1" // U+F0171 +#define ICON_MDI_CODE_PARENTHESES "\xf3\xb0\x85\xb2" // U+F0172 +#define ICON_MDI_CODE_PARENTHESES_BOX "\xf3\xb1\x83\x97" // U+F10D7 +#define ICON_MDI_CODE_STRING "\xf3\xb0\x85\xb3" // U+F0173 +#define ICON_MDI_CODE_TAGS "\xf3\xb0\x85\xb4" // U+F0174 +#define ICON_MDI_CODE_TAGS_CHECK "\xf3\xb0\x9a\x94" // U+F0694 +#define ICON_MDI_CODEPEN "\xf3\xb0\x85\xb5" // U+F0175 +#define ICON_MDI_COFFEE "\xf3\xb0\x85\xb6" // U+F0176 +#define ICON_MDI_COFFEE_MAKER "\xf3\xb1\x82\x9f" // U+F109F +#define ICON_MDI_COFFEE_MAKER_CHECK "\xf3\xb1\xa4\xb1" // U+F1931 +#define ICON_MDI_COFFEE_MAKER_CHECK_OUTLINE "\xf3\xb1\xa4\xb2" // U+F1932 +#define ICON_MDI_COFFEE_MAKER_OUTLINE "\xf3\xb1\xa0\x9b" // U+F181B +#define ICON_MDI_COFFEE_OFF "\xf3\xb0\xbe\xaa" // U+F0FAA +#define ICON_MDI_COFFEE_OFF_OUTLINE "\xf3\xb0\xbe\xab" // U+F0FAB +#define ICON_MDI_COFFEE_OUTLINE "\xf3\xb0\x9b\x8a" // U+F06CA +#define ICON_MDI_COFFEE_TO_GO "\xf3\xb0\x85\xb7" // U+F0177 +#define ICON_MDI_COFFEE_TO_GO_OUTLINE "\xf3\xb1\x8c\x8e" // U+F130E +#define ICON_MDI_COFFIN "\xf3\xb0\xad\xbf" // U+F0B7F +#define ICON_MDI_COG "\xf3\xb0\x92\x93" // U+F0493 +#define ICON_MDI_COG_BOX "\xf3\xb0\x92\x94" // U+F0494 +#define ICON_MDI_COG_CLOCKWISE "\xf3\xb1\x87\x9d" // U+F11DD +#define ICON_MDI_COG_COUNTERCLOCKWISE "\xf3\xb1\x87\x9e" // U+F11DE +#define ICON_MDI_COG_OFF "\xf3\xb1\x8f\x8e" // U+F13CE +#define ICON_MDI_COG_OFF_OUTLINE "\xf3\xb1\x8f\x8f" // U+F13CF +#define ICON_MDI_COG_OUTLINE "\xf3\xb0\xa2\xbb" // U+F08BB +#define ICON_MDI_COG_PAUSE "\xf3\xb1\xa4\xb3" // U+F1933 +#define ICON_MDI_COG_PAUSE_OUTLINE "\xf3\xb1\xa4\xb4" // U+F1934 +#define ICON_MDI_COG_PLAY "\xf3\xb1\xa4\xb5" // U+F1935 +#define ICON_MDI_COG_PLAY_OUTLINE "\xf3\xb1\xa4\xb6" // U+F1936 +#define ICON_MDI_COG_REFRESH "\xf3\xb1\x91\x9e" // U+F145E +#define ICON_MDI_COG_REFRESH_OUTLINE "\xf3\xb1\x91\x9f" // U+F145F +#define ICON_MDI_COG_STOP "\xf3\xb1\xa4\xb7" // U+F1937 +#define ICON_MDI_COG_STOP_OUTLINE "\xf3\xb1\xa4\xb8" // U+F1938 +#define ICON_MDI_COG_SYNC "\xf3\xb1\x91\xa0" // U+F1460 +#define ICON_MDI_COG_SYNC_OUTLINE "\xf3\xb1\x91\xa1" // U+F1461 +#define ICON_MDI_COG_TRANSFER "\xf3\xb1\x81\x9b" // U+F105B +#define ICON_MDI_COG_TRANSFER_OUTLINE "\xf3\xb1\x81\x9c" // U+F105C +#define ICON_MDI_COGS "\xf3\xb0\xa3\x96" // U+F08D6 +#define ICON_MDI_COLLAGE "\xf3\xb0\x99\x80" // U+F0640 +#define ICON_MDI_COLLAPSE_ALL "\xf3\xb0\xaa\xa6" // U+F0AA6 +#define ICON_MDI_COLLAPSE_ALL_OUTLINE "\xf3\xb0\xaa\xa7" // U+F0AA7 +#define ICON_MDI_COLOR_HELPER "\xf3\xb0\x85\xb9" // U+F0179 +#define ICON_MDI_COMMA "\xf3\xb0\xb8\xa3" // U+F0E23 +#define ICON_MDI_COMMA_BOX "\xf3\xb0\xb8\xab" // U+F0E2B +#define ICON_MDI_COMMA_BOX_OUTLINE "\xf3\xb0\xb8\xa4" // U+F0E24 +#define ICON_MDI_COMMA_CIRCLE "\xf3\xb0\xb8\xa5" // U+F0E25 +#define ICON_MDI_COMMA_CIRCLE_OUTLINE "\xf3\xb0\xb8\xa6" // U+F0E26 +#define ICON_MDI_COMMENT "\xf3\xb0\x85\xba" // U+F017A +#define ICON_MDI_COMMENT_ACCOUNT "\xf3\xb0\x85\xbb" // U+F017B +#define ICON_MDI_COMMENT_ACCOUNT_OUTLINE "\xf3\xb0\x85\xbc" // U+F017C +#define ICON_MDI_COMMENT_ALERT "\xf3\xb0\x85\xbd" // U+F017D +#define ICON_MDI_COMMENT_ALERT_OUTLINE "\xf3\xb0\x85\xbe" // U+F017E +#define ICON_MDI_COMMENT_ARROW_LEFT "\xf3\xb0\xa7\xa1" // U+F09E1 +#define ICON_MDI_COMMENT_ARROW_LEFT_OUTLINE "\xf3\xb0\xa7\xa2" // U+F09E2 +#define ICON_MDI_COMMENT_ARROW_RIGHT "\xf3\xb0\xa7\xa3" // U+F09E3 +#define ICON_MDI_COMMENT_ARROW_RIGHT_OUTLINE "\xf3\xb0\xa7\xa4" // U+F09E4 +#define ICON_MDI_COMMENT_BOOKMARK "\xf3\xb1\x96\xae" // U+F15AE +#define ICON_MDI_COMMENT_BOOKMARK_OUTLINE "\xf3\xb1\x96\xaf" // U+F15AF +#define ICON_MDI_COMMENT_CHECK "\xf3\xb0\x85\xbf" // U+F017F +#define ICON_MDI_COMMENT_CHECK_OUTLINE "\xf3\xb0\x86\x80" // U+F0180 +#define ICON_MDI_COMMENT_EDIT "\xf3\xb1\x86\xbf" // U+F11BF +#define ICON_MDI_COMMENT_EDIT_OUTLINE "\xf3\xb1\x8b\x84" // U+F12C4 +#define ICON_MDI_COMMENT_EYE "\xf3\xb0\xa8\xba" // U+F0A3A +#define ICON_MDI_COMMENT_EYE_OUTLINE "\xf3\xb0\xa8\xbb" // U+F0A3B +#define ICON_MDI_COMMENT_FLASH "\xf3\xb1\x96\xb0" // U+F15B0 +#define ICON_MDI_COMMENT_FLASH_OUTLINE "\xf3\xb1\x96\xb1" // U+F15B1 +#define ICON_MDI_COMMENT_MINUS "\xf3\xb1\x97\x9f" // U+F15DF +#define ICON_MDI_COMMENT_MINUS_OUTLINE "\xf3\xb1\x97\xa0" // U+F15E0 +#define ICON_MDI_COMMENT_MULTIPLE "\xf3\xb0\xa1\x9f" // U+F085F +#define ICON_MDI_COMMENT_MULTIPLE_OUTLINE "\xf3\xb0\x86\x81" // U+F0181 +#define ICON_MDI_COMMENT_OFF "\xf3\xb1\x97\xa1" // U+F15E1 +#define ICON_MDI_COMMENT_OFF_OUTLINE "\xf3\xb1\x97\xa2" // U+F15E2 +#define ICON_MDI_COMMENT_OUTLINE "\xf3\xb0\x86\x82" // U+F0182 +#define ICON_MDI_COMMENT_PLUS "\xf3\xb0\xa7\xa5" // U+F09E5 +#define ICON_MDI_COMMENT_PLUS_OUTLINE "\xf3\xb0\x86\x83" // U+F0183 +#define ICON_MDI_COMMENT_PROCESSING "\xf3\xb0\x86\x84" // U+F0184 +#define ICON_MDI_COMMENT_PROCESSING_OUTLINE "\xf3\xb0\x86\x85" // U+F0185 +#define ICON_MDI_COMMENT_QUESTION "\xf3\xb0\xa0\x97" // U+F0817 +#define ICON_MDI_COMMENT_QUESTION_OUTLINE "\xf3\xb0\x86\x86" // U+F0186 +#define ICON_MDI_COMMENT_QUOTE "\xf3\xb1\x80\xa1" // U+F1021 +#define ICON_MDI_COMMENT_QUOTE_OUTLINE "\xf3\xb1\x80\xa2" // U+F1022 +#define ICON_MDI_COMMENT_REMOVE "\xf3\xb0\x97\x9e" // U+F05DE +#define ICON_MDI_COMMENT_REMOVE_OUTLINE "\xf3\xb0\x86\x87" // U+F0187 +#define ICON_MDI_COMMENT_SEARCH "\xf3\xb0\xa8\xbc" // U+F0A3C +#define ICON_MDI_COMMENT_SEARCH_OUTLINE "\xf3\xb0\xa8\xbd" // U+F0A3D +#define ICON_MDI_COMMENT_TEXT "\xf3\xb0\x86\x88" // U+F0188 +#define ICON_MDI_COMMENT_TEXT_MULTIPLE "\xf3\xb0\xa1\xa0" // U+F0860 +#define ICON_MDI_COMMENT_TEXT_MULTIPLE_OUTLINE "\xf3\xb0\xa1\xa1" // U+F0861 +#define ICON_MDI_COMMENT_TEXT_OUTLINE "\xf3\xb0\x86\x89" // U+F0189 +#define ICON_MDI_COMPARE "\xf3\xb0\x86\x8a" // U+F018A +#define ICON_MDI_COMPARE_HORIZONTAL "\xf3\xb1\x92\x92" // U+F1492 +#define ICON_MDI_COMPARE_REMOVE "\xf3\xb1\xa2\xb3" // U+F18B3 +#define ICON_MDI_COMPARE_VERTICAL "\xf3\xb1\x92\x93" // U+F1493 +#define ICON_MDI_COMPASS "\xf3\xb0\x86\x8b" // U+F018B +#define ICON_MDI_COMPASS_OFF "\xf3\xb0\xae\x80" // U+F0B80 +#define ICON_MDI_COMPASS_OFF_OUTLINE "\xf3\xb0\xae\x81" // U+F0B81 +#define ICON_MDI_COMPASS_OUTLINE "\xf3\xb0\x86\x8c" // U+F018C +#define ICON_MDI_COMPASS_ROSE "\xf3\xb1\x8e\x82" // U+F1382 +#define ICON_MDI_COMPOST "\xf3\xb1\xa8\xb8" // U+F1A38 +#define ICON_MDI_CONE "\xf3\xb1\xa5\x8c" // U+F194C +#define ICON_MDI_CONE_OFF "\xf3\xb1\xa5\x8d" // U+F194D +#define ICON_MDI_CONNECTION "\xf3\xb1\x98\x96" // U+F1616 +#define ICON_MDI_CONSOLE "\xf3\xb0\x86\x8d" // U+F018D +#define ICON_MDI_CONSOLE_LINE "\xf3\xb0\x9e\xb7" // U+F07B7 +#define ICON_MDI_CONSOLE_NETWORK "\xf3\xb0\xa2\xa9" // U+F08A9 +#define ICON_MDI_CONSOLE_NETWORK_OUTLINE "\xf3\xb0\xb1\xa0" // U+F0C60 +#define ICON_MDI_CONSOLIDATE "\xf3\xb1\x83\x98" // U+F10D8 +#define ICON_MDI_CONTACTLESS_PAYMENT "\xf3\xb0\xb5\xaa" // U+F0D6A +#define ICON_MDI_CONTACTLESS_PAYMENT_CIRCLE "\xf3\xb0\x8c\xa1" // U+F0321 +#define ICON_MDI_CONTACTLESS_PAYMENT_CIRCLE_OUTLINE "\xf3\xb0\x90\x88" // U+F0408 +#define ICON_MDI_CONTACTS "\xf3\xb0\x9b\x8b" // U+F06CB +#define ICON_MDI_CONTACTS_OUTLINE "\xf3\xb0\x96\xb8" // U+F05B8 +#define ICON_MDI_CONTAIN "\xf3\xb0\xa8\xbe" // U+F0A3E +#define ICON_MDI_CONTAIN_END "\xf3\xb0\xa8\xbf" // U+F0A3F +#define ICON_MDI_CONTAIN_START "\xf3\xb0\xa9\x80" // U+F0A40 +#define ICON_MDI_CONTENT_COPY "\xf3\xb0\x86\x8f" // U+F018F +#define ICON_MDI_CONTENT_CUT "\xf3\xb0\x86\x90" // U+F0190 +#define ICON_MDI_CONTENT_DUPLICATE "\xf3\xb0\x86\x91" // U+F0191 +#define ICON_MDI_CONTENT_PASTE "\xf3\xb0\x86\x92" // U+F0192 +#define ICON_MDI_CONTENT_SAVE "\xf3\xb0\x86\x93" // U+F0193 +#define ICON_MDI_CONTENT_SAVE_ALERT "\xf3\xb0\xbd\x82" // U+F0F42 +#define ICON_MDI_CONTENT_SAVE_ALERT_OUTLINE "\xf3\xb0\xbd\x83" // U+F0F43 +#define ICON_MDI_CONTENT_SAVE_ALL "\xf3\xb0\x86\x94" // U+F0194 +#define ICON_MDI_CONTENT_SAVE_ALL_OUTLINE "\xf3\xb0\xbd\x84" // U+F0F44 +#define ICON_MDI_CONTENT_SAVE_CHECK "\xf3\xb1\xa3\xaa" // U+F18EA +#define ICON_MDI_CONTENT_SAVE_CHECK_OUTLINE "\xf3\xb1\xa3\xab" // U+F18EB +#define ICON_MDI_CONTENT_SAVE_COG "\xf3\xb1\x91\x9b" // U+F145B +#define ICON_MDI_CONTENT_SAVE_COG_OUTLINE "\xf3\xb1\x91\x9c" // U+F145C +#define ICON_MDI_CONTENT_SAVE_EDIT "\xf3\xb0\xb3\xbb" // U+F0CFB +#define ICON_MDI_CONTENT_SAVE_EDIT_OUTLINE "\xf3\xb0\xb3\xbc" // U+F0CFC +#define ICON_MDI_CONTENT_SAVE_MINUS "\xf3\xb1\xad\x83" // U+F1B43 +#define ICON_MDI_CONTENT_SAVE_MINUS_OUTLINE "\xf3\xb1\xad\x84" // U+F1B44 +#define ICON_MDI_CONTENT_SAVE_MOVE "\xf3\xb0\xb8\xa7" // U+F0E27 +#define ICON_MDI_CONTENT_SAVE_MOVE_OUTLINE "\xf3\xb0\xb8\xa8" // U+F0E28 +#define ICON_MDI_CONTENT_SAVE_OFF "\xf3\xb1\x99\x83" // U+F1643 +#define ICON_MDI_CONTENT_SAVE_OFF_OUTLINE "\xf3\xb1\x99\x84" // U+F1644 +#define ICON_MDI_CONTENT_SAVE_OUTLINE "\xf3\xb0\xa0\x98" // U+F0818 +#define ICON_MDI_CONTENT_SAVE_PLUS "\xf3\xb1\xad\x81" // U+F1B41 +#define ICON_MDI_CONTENT_SAVE_PLUS_OUTLINE "\xf3\xb1\xad\x82" // U+F1B42 +#define ICON_MDI_CONTENT_SAVE_SETTINGS "\xf3\xb0\x98\x9b" // U+F061B +#define ICON_MDI_CONTENT_SAVE_SETTINGS_OUTLINE "\xf3\xb0\xac\xae" // U+F0B2E +#define ICON_MDI_CONTRAST "\xf3\xb0\x86\x95" // U+F0195 +#define ICON_MDI_CONTRAST_BOX "\xf3\xb0\x86\x96" // U+F0196 +#define ICON_MDI_CONTRAST_CIRCLE "\xf3\xb0\x86\x97" // U+F0197 +#define ICON_MDI_CONTROLLER "\xf3\xb0\x8a\xb4" // U+F02B4 +#define ICON_MDI_CONTROLLER_CLASSIC "\xf3\xb0\xae\x82" // U+F0B82 +#define ICON_MDI_CONTROLLER_CLASSIC_OUTLINE "\xf3\xb0\xae\x83" // U+F0B83 +#define ICON_MDI_CONTROLLER_OFF "\xf3\xb0\x8a\xb5" // U+F02B5 +#define ICON_MDI_COOKIE "\xf3\xb0\x86\x98" // U+F0198 +#define ICON_MDI_COOKIE_ALERT "\xf3\xb1\x9b\x90" // U+F16D0 +#define ICON_MDI_COOKIE_ALERT_OUTLINE "\xf3\xb1\x9b\x91" // U+F16D1 +#define ICON_MDI_COOKIE_CHECK "\xf3\xb1\x9b\x92" // U+F16D2 +#define ICON_MDI_COOKIE_CHECK_OUTLINE "\xf3\xb1\x9b\x93" // U+F16D3 +#define ICON_MDI_COOKIE_CLOCK "\xf3\xb1\x9b\xa4" // U+F16E4 +#define ICON_MDI_COOKIE_CLOCK_OUTLINE "\xf3\xb1\x9b\xa5" // U+F16E5 +#define ICON_MDI_COOKIE_COG "\xf3\xb1\x9b\x94" // U+F16D4 +#define ICON_MDI_COOKIE_COG_OUTLINE "\xf3\xb1\x9b\x95" // U+F16D5 +#define ICON_MDI_COOKIE_EDIT "\xf3\xb1\x9b\xa6" // U+F16E6 +#define ICON_MDI_COOKIE_EDIT_OUTLINE "\xf3\xb1\x9b\xa7" // U+F16E7 +#define ICON_MDI_COOKIE_LOCK "\xf3\xb1\x9b\xa8" // U+F16E8 +#define ICON_MDI_COOKIE_LOCK_OUTLINE "\xf3\xb1\x9b\xa9" // U+F16E9 +#define ICON_MDI_COOKIE_MINUS "\xf3\xb1\x9b\x9a" // U+F16DA +#define ICON_MDI_COOKIE_MINUS_OUTLINE "\xf3\xb1\x9b\x9b" // U+F16DB +#define ICON_MDI_COOKIE_OFF "\xf3\xb1\x9b\xaa" // U+F16EA +#define ICON_MDI_COOKIE_OFF_OUTLINE "\xf3\xb1\x9b\xab" // U+F16EB +#define ICON_MDI_COOKIE_OUTLINE "\xf3\xb1\x9b\x9e" // U+F16DE +#define ICON_MDI_COOKIE_PLUS "\xf3\xb1\x9b\x96" // U+F16D6 +#define ICON_MDI_COOKIE_PLUS_OUTLINE "\xf3\xb1\x9b\x97" // U+F16D7 +#define ICON_MDI_COOKIE_REFRESH "\xf3\xb1\x9b\xac" // U+F16EC +#define ICON_MDI_COOKIE_REFRESH_OUTLINE "\xf3\xb1\x9b\xad" // U+F16ED +#define ICON_MDI_COOKIE_REMOVE "\xf3\xb1\x9b\x98" // U+F16D8 +#define ICON_MDI_COOKIE_REMOVE_OUTLINE "\xf3\xb1\x9b\x99" // U+F16D9 +#define ICON_MDI_COOKIE_SETTINGS "\xf3\xb1\x9b\x9c" // U+F16DC +#define ICON_MDI_COOKIE_SETTINGS_OUTLINE "\xf3\xb1\x9b\x9d" // U+F16DD +#define ICON_MDI_COOLANT_TEMPERATURE "\xf3\xb0\x8f\x88" // U+F03C8 +#define ICON_MDI_COPYLEFT "\xf3\xb1\xa4\xb9" // U+F1939 +#define ICON_MDI_COPYRIGHT "\xf3\xb0\x97\xa6" // U+F05E6 +#define ICON_MDI_CORDOVA "\xf3\xb0\xa5\x98" // U+F0958 +#define ICON_MDI_CORN "\xf3\xb0\x9e\xb8" // U+F07B8 +#define ICON_MDI_CORN_OFF "\xf3\xb1\x8f\xaf" // U+F13EF +#define ICON_MDI_COSINE_WAVE "\xf3\xb1\x91\xb9" // U+F1479 +#define ICON_MDI_COUNTER "\xf3\xb0\x86\x99" // U+F0199 +#define ICON_MDI_COUNTERTOP "\xf3\xb1\xa0\x9c" // U+F181C +#define ICON_MDI_COUNTERTOP_OUTLINE "\xf3\xb1\xa0\x9d" // U+F181D +#define ICON_MDI_COW "\xf3\xb0\x86\x9a" // U+F019A +#define ICON_MDI_COW_OFF "\xf3\xb1\xa3\xbc" // U+F18FC +#define ICON_MDI_CPU_32_BIT "\xf3\xb0\xbb\x9f" // U+F0EDF +#define ICON_MDI_CPU_64_BIT "\xf3\xb0\xbb\xa0" // U+F0EE0 +#define ICON_MDI_CRADLE "\xf3\xb1\xa6\x8b" // U+F198B +#define ICON_MDI_CRADLE_OUTLINE "\xf3\xb1\xa6\x91" // U+F1991 +#define ICON_MDI_CRANE "\xf3\xb0\xa1\xa2" // U+F0862 +#define ICON_MDI_CREATION "\xf3\xb0\x99\xb4" // U+F0674 +#define ICON_MDI_CREATION_OUTLINE "\xf3\xb1\xb0\xab" // U+F1C2B +#define ICON_MDI_CREATIVE_COMMONS "\xf3\xb0\xb5\xab" // U+F0D6B +#define ICON_MDI_CREDIT_CARD "\xf3\xb0\xbf\xaf" // U+F0FEF +#define ICON_MDI_CREDIT_CARD_CHECK "\xf3\xb1\x8f\x90" // U+F13D0 +#define ICON_MDI_CREDIT_CARD_CHECK_OUTLINE "\xf3\xb1\x8f\x91" // U+F13D1 +#define ICON_MDI_CREDIT_CARD_CHIP "\xf3\xb1\xa4\x8f" // U+F190F +#define ICON_MDI_CREDIT_CARD_CHIP_OUTLINE "\xf3\xb1\xa4\x90" // U+F1910 +#define ICON_MDI_CREDIT_CARD_CLOCK "\xf3\xb0\xbb\xa1" // U+F0EE1 +#define ICON_MDI_CREDIT_CARD_CLOCK_OUTLINE "\xf3\xb0\xbb\xa2" // U+F0EE2 +#define ICON_MDI_CREDIT_CARD_EDIT "\xf3\xb1\x9f\x97" // U+F17D7 +#define ICON_MDI_CREDIT_CARD_EDIT_OUTLINE "\xf3\xb1\x9f\x98" // U+F17D8 +#define ICON_MDI_CREDIT_CARD_FAST "\xf3\xb1\xa4\x91" // U+F1911 +#define ICON_MDI_CREDIT_CARD_FAST_OUTLINE "\xf3\xb1\xa4\x92" // U+F1912 +#define ICON_MDI_CREDIT_CARD_LOCK "\xf3\xb1\xa3\xa7" // U+F18E7 +#define ICON_MDI_CREDIT_CARD_LOCK_OUTLINE "\xf3\xb1\xa3\xa8" // U+F18E8 +#define ICON_MDI_CREDIT_CARD_MARKER "\xf3\xb0\x9a\xa8" // U+F06A8 +#define ICON_MDI_CREDIT_CARD_MARKER_OUTLINE "\xf3\xb0\xb6\xbe" // U+F0DBE +#define ICON_MDI_CREDIT_CARD_MINUS "\xf3\xb0\xbe\xac" // U+F0FAC +#define ICON_MDI_CREDIT_CARD_MINUS_OUTLINE "\xf3\xb0\xbe\xad" // U+F0FAD +#define ICON_MDI_CREDIT_CARD_MULTIPLE "\xf3\xb0\xbf\xb0" // U+F0FF0 +#define ICON_MDI_CREDIT_CARD_MULTIPLE_OUTLINE "\xf3\xb0\x86\x9c" // U+F019C +#define ICON_MDI_CREDIT_CARD_OFF "\xf3\xb0\xbf\xb1" // U+F0FF1 +#define ICON_MDI_CREDIT_CARD_OFF_OUTLINE "\xf3\xb0\x97\xa4" // U+F05E4 +#define ICON_MDI_CREDIT_CARD_OUTLINE "\xf3\xb0\x86\x9b" // U+F019B +#define ICON_MDI_CREDIT_CARD_PLUS "\xf3\xb0\xbf\xb2" // U+F0FF2 +#define ICON_MDI_CREDIT_CARD_PLUS_OUTLINE "\xf3\xb0\x99\xb6" // U+F0676 +#define ICON_MDI_CREDIT_CARD_REFRESH "\xf3\xb1\x99\x85" // U+F1645 +#define ICON_MDI_CREDIT_CARD_REFRESH_OUTLINE "\xf3\xb1\x99\x86" // U+F1646 +#define ICON_MDI_CREDIT_CARD_REFUND "\xf3\xb0\xbf\xb3" // U+F0FF3 +#define ICON_MDI_CREDIT_CARD_REFUND_OUTLINE "\xf3\xb0\xaa\xa8" // U+F0AA8 +#define ICON_MDI_CREDIT_CARD_REMOVE "\xf3\xb0\xbe\xae" // U+F0FAE +#define ICON_MDI_CREDIT_CARD_REMOVE_OUTLINE "\xf3\xb0\xbe\xaf" // U+F0FAF +#define ICON_MDI_CREDIT_CARD_SCAN "\xf3\xb0\xbf\xb4" // U+F0FF4 +#define ICON_MDI_CREDIT_CARD_SCAN_OUTLINE "\xf3\xb0\x86\x9d" // U+F019D +#define ICON_MDI_CREDIT_CARD_SEARCH "\xf3\xb1\x99\x87" // U+F1647 +#define ICON_MDI_CREDIT_CARD_SEARCH_OUTLINE "\xf3\xb1\x99\x88" // U+F1648 +#define ICON_MDI_CREDIT_CARD_SETTINGS "\xf3\xb0\xbf\xb5" // U+F0FF5 +#define ICON_MDI_CREDIT_CARD_SETTINGS_OUTLINE "\xf3\xb0\xa3\x97" // U+F08D7 +#define ICON_MDI_CREDIT_CARD_SYNC "\xf3\xb1\x99\x89" // U+F1649 +#define ICON_MDI_CREDIT_CARD_SYNC_OUTLINE "\xf3\xb1\x99\x8a" // U+F164A +#define ICON_MDI_CREDIT_CARD_WIRELESS "\xf3\xb0\xa0\x82" // U+F0802 +#define ICON_MDI_CREDIT_CARD_WIRELESS_OFF "\xf3\xb0\x95\xba" // U+F057A +#define ICON_MDI_CREDIT_CARD_WIRELESS_OFF_OUTLINE "\xf3\xb0\x95\xbb" // U+F057B +#define ICON_MDI_CREDIT_CARD_WIRELESS_OUTLINE "\xf3\xb0\xb5\xac" // U+F0D6C +#define ICON_MDI_CRICKET "\xf3\xb0\xb5\xad" // U+F0D6D +#define ICON_MDI_CROP "\xf3\xb0\x86\x9e" // U+F019E +#define ICON_MDI_CROP_FREE "\xf3\xb0\x86\x9f" // U+F019F +#define ICON_MDI_CROP_LANDSCAPE "\xf3\xb0\x86\xa0" // U+F01A0 +#define ICON_MDI_CROP_PORTRAIT "\xf3\xb0\x86\xa1" // U+F01A1 +#define ICON_MDI_CROP_ROTATE "\xf3\xb0\x9a\x96" // U+F0696 +#define ICON_MDI_CROP_SQUARE "\xf3\xb0\x86\xa2" // U+F01A2 +#define ICON_MDI_CROSS "\xf3\xb0\xa5\x93" // U+F0953 +#define ICON_MDI_CROSS_BOLNISI "\xf3\xb0\xb3\xad" // U+F0CED +#define ICON_MDI_CROSS_CELTIC "\xf3\xb0\xb3\xb5" // U+F0CF5 +#define ICON_MDI_CROSS_OUTLINE "\xf3\xb0\xb3\xb6" // U+F0CF6 +#define ICON_MDI_CROSSHAIRS "\xf3\xb0\x86\xa3" // U+F01A3 +#define ICON_MDI_CROSSHAIRS_GPS "\xf3\xb0\x86\xa4" // U+F01A4 +#define ICON_MDI_CROSSHAIRS_OFF "\xf3\xb0\xbd\x85" // U+F0F45 +#define ICON_MDI_CROSSHAIRS_QUESTION "\xf3\xb1\x84\xb6" // U+F1136 +#define ICON_MDI_CROWD "\xf3\xb1\xa5\xb5" // U+F1975 +#define ICON_MDI_CROWN "\xf3\xb0\x86\xa5" // U+F01A5 +#define ICON_MDI_CROWN_CIRCLE "\xf3\xb1\x9f\x9c" // U+F17DC +#define ICON_MDI_CROWN_CIRCLE_OUTLINE "\xf3\xb1\x9f\x9d" // U+F17DD +#define ICON_MDI_CROWN_OUTLINE "\xf3\xb1\x87\x90" // U+F11D0 +#define ICON_MDI_CRYENGINE "\xf3\xb0\xa5\x99" // U+F0959 +#define ICON_MDI_CRYSTAL_BALL "\xf3\xb0\xac\xaf" // U+F0B2F +#define ICON_MDI_CUBE "\xf3\xb0\x86\xa6" // U+F01A6 +#define ICON_MDI_CUBE_OFF "\xf3\xb1\x90\x9c" // U+F141C +#define ICON_MDI_CUBE_OFF_OUTLINE "\xf3\xb1\x90\x9d" // U+F141D +#define ICON_MDI_CUBE_OUTLINE "\xf3\xb0\x86\xa7" // U+F01A7 +#define ICON_MDI_CUBE_SCAN "\xf3\xb0\xae\x84" // U+F0B84 +#define ICON_MDI_CUBE_SEND "\xf3\xb0\x86\xa8" // U+F01A8 +#define ICON_MDI_CUBE_UNFOLDED "\xf3\xb0\x86\xa9" // U+F01A9 +#define ICON_MDI_CUP "\xf3\xb0\x86\xaa" // U+F01AA +#define ICON_MDI_CUP_OFF "\xf3\xb0\x97\xa5" // U+F05E5 +#define ICON_MDI_CUP_OFF_OUTLINE "\xf3\xb1\x8d\xbd" // U+F137D +#define ICON_MDI_CUP_OUTLINE "\xf3\xb1\x8c\x8f" // U+F130F +#define ICON_MDI_CUP_WATER "\xf3\xb0\x86\xab" // U+F01AB +#define ICON_MDI_CUPBOARD "\xf3\xb0\xbd\x86" // U+F0F46 +#define ICON_MDI_CUPBOARD_OUTLINE "\xf3\xb0\xbd\x87" // U+F0F47 +#define ICON_MDI_CUPCAKE "\xf3\xb0\xa5\x9a" // U+F095A +#define ICON_MDI_CURLING "\xf3\xb0\xa1\xa3" // U+F0863 +#define ICON_MDI_CURRENCY_BDT "\xf3\xb0\xa1\xa4" // U+F0864 +#define ICON_MDI_CURRENCY_BRL "\xf3\xb0\xae\x85" // U+F0B85 +#define ICON_MDI_CURRENCY_BTC "\xf3\xb0\x86\xac" // U+F01AC +#define ICON_MDI_CURRENCY_CNY "\xf3\xb0\x9e\xba" // U+F07BA +#define ICON_MDI_CURRENCY_ETH "\xf3\xb0\x9e\xbb" // U+F07BB +#define ICON_MDI_CURRENCY_EUR "\xf3\xb0\x86\xad" // U+F01AD +#define ICON_MDI_CURRENCY_EUR_OFF "\xf3\xb1\x8c\x95" // U+F1315 +#define ICON_MDI_CURRENCY_FRA "\xf3\xb1\xa8\xb9" // U+F1A39 +#define ICON_MDI_CURRENCY_GBP "\xf3\xb0\x86\xae" // U+F01AE +#define ICON_MDI_CURRENCY_ILS "\xf3\xb0\xb1\xa1" // U+F0C61 +#define ICON_MDI_CURRENCY_INR "\xf3\xb0\x86\xaf" // U+F01AF +#define ICON_MDI_CURRENCY_JPY "\xf3\xb0\x9e\xbc" // U+F07BC +#define ICON_MDI_CURRENCY_KRW "\xf3\xb0\x9e\xbd" // U+F07BD +#define ICON_MDI_CURRENCY_KZT "\xf3\xb0\xa1\xa5" // U+F0865 +#define ICON_MDI_CURRENCY_MNT "\xf3\xb1\x94\x92" // U+F1512 +#define ICON_MDI_CURRENCY_NGN "\xf3\xb0\x86\xb0" // U+F01B0 +#define ICON_MDI_CURRENCY_PHP "\xf3\xb0\xa7\xa6" // U+F09E6 +#define ICON_MDI_CURRENCY_RIAL "\xf3\xb0\xba\x9c" // U+F0E9C +#define ICON_MDI_CURRENCY_RUB "\xf3\xb0\x86\xb1" // U+F01B1 +#define ICON_MDI_CURRENCY_RUPEE "\xf3\xb1\xa5\xb6" // U+F1976 +#define ICON_MDI_CURRENCY_SIGN "\xf3\xb0\x9e\xbe" // U+F07BE +#define ICON_MDI_CURRENCY_THB "\xf3\xb1\xb0\x85" // U+F1C05 +#define ICON_MDI_CURRENCY_TRY "\xf3\xb0\x86\xb2" // U+F01B2 +#define ICON_MDI_CURRENCY_TWD "\xf3\xb0\x9e\xbf" // U+F07BF +#define ICON_MDI_CURRENCY_UAH "\xf3\xb1\xae\x9b" // U+F1B9B +#define ICON_MDI_CURRENCY_USD "\xf3\xb0\x87\x81" // U+F01C1 +#define ICON_MDI_CURRENCY_USD_OFF "\xf3\xb0\x99\xba" // U+F067A +#define ICON_MDI_CURRENT_AC "\xf3\xb1\x92\x80" // U+F1480 +#define ICON_MDI_CURRENT_DC "\xf3\xb0\xa5\x9c" // U+F095C +#define ICON_MDI_CURSOR_DEFAULT "\xf3\xb0\x87\x80" // U+F01C0 +#define ICON_MDI_CURSOR_DEFAULT_CLICK "\xf3\xb0\xb3\xbd" // U+F0CFD +#define ICON_MDI_CURSOR_DEFAULT_CLICK_OUTLINE "\xf3\xb0\xb3\xbe" // U+F0CFE +#define ICON_MDI_CURSOR_DEFAULT_GESTURE "\xf3\xb1\x84\xa7" // U+F1127 +#define ICON_MDI_CURSOR_DEFAULT_GESTURE_OUTLINE "\xf3\xb1\x84\xa8" // U+F1128 +#define ICON_MDI_CURSOR_DEFAULT_OUTLINE "\xf3\xb0\x86\xbf" // U+F01BF +#define ICON_MDI_CURSOR_MOVE "\xf3\xb0\x86\xbe" // U+F01BE +#define ICON_MDI_CURSOR_POINTER "\xf3\xb0\x86\xbd" // U+F01BD +#define ICON_MDI_CURSOR_TEXT "\xf3\xb0\x97\xa7" // U+F05E7 +#define ICON_MDI_CURTAINS "\xf3\xb1\xa1\x86" // U+F1846 +#define ICON_MDI_CURTAINS_CLOSED "\xf3\xb1\xa1\x87" // U+F1847 +#define ICON_MDI_CYLINDER "\xf3\xb1\xa5\x8e" // U+F194E +#define ICON_MDI_CYLINDER_OFF "\xf3\xb1\xa5\x8f" // U+F194F +#define ICON_MDI_DANCE_BALLROOM "\xf3\xb1\x97\xbb" // U+F15FB +#define ICON_MDI_DANCE_POLE "\xf3\xb1\x95\xb8" // U+F1578 +#define ICON_MDI_DATA_MATRIX "\xf3\xb1\x94\xbc" // U+F153C +#define ICON_MDI_DATA_MATRIX_EDIT "\xf3\xb1\x94\xbd" // U+F153D +#define ICON_MDI_DATA_MATRIX_MINUS "\xf3\xb1\x94\xbe" // U+F153E +#define ICON_MDI_DATA_MATRIX_PLUS "\xf3\xb1\x94\xbf" // U+F153F +#define ICON_MDI_DATA_MATRIX_REMOVE "\xf3\xb1\x95\x80" // U+F1540 +#define ICON_MDI_DATA_MATRIX_SCAN "\xf3\xb1\x95\x81" // U+F1541 +#define ICON_MDI_DATABASE "\xf3\xb0\x86\xbc" // U+F01BC +#define ICON_MDI_DATABASE_ALERT "\xf3\xb1\x98\xba" // U+F163A +#define ICON_MDI_DATABASE_ALERT_OUTLINE "\xf3\xb1\x98\xa4" // U+F1624 +#define ICON_MDI_DATABASE_ARROW_DOWN "\xf3\xb1\x98\xbb" // U+F163B +#define ICON_MDI_DATABASE_ARROW_DOWN_OUTLINE "\xf3\xb1\x98\xa5" // U+F1625 +#define ICON_MDI_DATABASE_ARROW_LEFT "\xf3\xb1\x98\xbc" // U+F163C +#define ICON_MDI_DATABASE_ARROW_LEFT_OUTLINE "\xf3\xb1\x98\xa6" // U+F1626 +#define ICON_MDI_DATABASE_ARROW_RIGHT "\xf3\xb1\x98\xbd" // U+F163D +#define ICON_MDI_DATABASE_ARROW_RIGHT_OUTLINE "\xf3\xb1\x98\xa7" // U+F1627 +#define ICON_MDI_DATABASE_ARROW_UP "\xf3\xb1\x98\xbe" // U+F163E +#define ICON_MDI_DATABASE_ARROW_UP_OUTLINE "\xf3\xb1\x98\xa8" // U+F1628 +#define ICON_MDI_DATABASE_CHECK "\xf3\xb0\xaa\xa9" // U+F0AA9 +#define ICON_MDI_DATABASE_CHECK_OUTLINE "\xf3\xb1\x98\xa9" // U+F1629 +#define ICON_MDI_DATABASE_CLOCK "\xf3\xb1\x98\xbf" // U+F163F +#define ICON_MDI_DATABASE_CLOCK_OUTLINE "\xf3\xb1\x98\xaa" // U+F162A +#define ICON_MDI_DATABASE_COG "\xf3\xb1\x99\x8b" // U+F164B +#define ICON_MDI_DATABASE_COG_OUTLINE "\xf3\xb1\x99\x8c" // U+F164C +#define ICON_MDI_DATABASE_EDIT "\xf3\xb0\xae\x86" // U+F0B86 +#define ICON_MDI_DATABASE_EDIT_OUTLINE "\xf3\xb1\x98\xab" // U+F162B +#define ICON_MDI_DATABASE_EXPORT "\xf3\xb0\xa5\x9e" // U+F095E +#define ICON_MDI_DATABASE_EXPORT_OUTLINE "\xf3\xb1\x98\xac" // U+F162C +#define ICON_MDI_DATABASE_EYE "\xf3\xb1\xa4\x9f" // U+F191F +#define ICON_MDI_DATABASE_EYE_OFF "\xf3\xb1\xa4\xa0" // U+F1920 +#define ICON_MDI_DATABASE_EYE_OFF_OUTLINE "\xf3\xb1\xa4\xa1" // U+F1921 +#define ICON_MDI_DATABASE_EYE_OUTLINE "\xf3\xb1\xa4\xa2" // U+F1922 +#define ICON_MDI_DATABASE_IMPORT "\xf3\xb0\xa5\x9d" // U+F095D +#define ICON_MDI_DATABASE_IMPORT_OUTLINE "\xf3\xb1\x98\xad" // U+F162D +#define ICON_MDI_DATABASE_LOCK "\xf3\xb0\xaa\xaa" // U+F0AAA +#define ICON_MDI_DATABASE_LOCK_OUTLINE "\xf3\xb1\x98\xae" // U+F162E +#define ICON_MDI_DATABASE_MARKER "\xf3\xb1\x8b\xb6" // U+F12F6 +#define ICON_MDI_DATABASE_MARKER_OUTLINE "\xf3\xb1\x98\xaf" // U+F162F +#define ICON_MDI_DATABASE_MINUS "\xf3\xb0\x86\xbb" // U+F01BB +#define ICON_MDI_DATABASE_MINUS_OUTLINE "\xf3\xb1\x98\xb0" // U+F1630 +#define ICON_MDI_DATABASE_OFF "\xf3\xb1\x99\x80" // U+F1640 +#define ICON_MDI_DATABASE_OFF_OUTLINE "\xf3\xb1\x98\xb1" // U+F1631 +#define ICON_MDI_DATABASE_OUTLINE "\xf3\xb1\x98\xb2" // U+F1632 +#define ICON_MDI_DATABASE_PLUS "\xf3\xb0\x86\xba" // U+F01BA +#define ICON_MDI_DATABASE_PLUS_OUTLINE "\xf3\xb1\x98\xb3" // U+F1633 +#define ICON_MDI_DATABASE_REFRESH "\xf3\xb0\x97\x82" // U+F05C2 +#define ICON_MDI_DATABASE_REFRESH_OUTLINE "\xf3\xb1\x98\xb4" // U+F1634 +#define ICON_MDI_DATABASE_REMOVE "\xf3\xb0\xb4\x80" // U+F0D00 +#define ICON_MDI_DATABASE_REMOVE_OUTLINE "\xf3\xb1\x98\xb5" // U+F1635 +#define ICON_MDI_DATABASE_SEARCH "\xf3\xb0\xa1\xa6" // U+F0866 +#define ICON_MDI_DATABASE_SEARCH_OUTLINE "\xf3\xb1\x98\xb6" // U+F1636 +#define ICON_MDI_DATABASE_SETTINGS "\xf3\xb0\xb4\x81" // U+F0D01 +#define ICON_MDI_DATABASE_SETTINGS_OUTLINE "\xf3\xb1\x98\xb7" // U+F1637 +#define ICON_MDI_DATABASE_SYNC "\xf3\xb0\xb3\xbf" // U+F0CFF +#define ICON_MDI_DATABASE_SYNC_OUTLINE "\xf3\xb1\x98\xb8" // U+F1638 +#define ICON_MDI_DEATH_STAR "\xf3\xb0\xa3\x98" // U+F08D8 +#define ICON_MDI_DEATH_STAR_VARIANT "\xf3\xb0\xa3\x99" // U+F08D9 +#define ICON_MDI_DEATHLY_HALLOWS "\xf3\xb0\xae\x87" // U+F0B87 +#define ICON_MDI_DEBIAN "\xf3\xb0\xa3\x9a" // U+F08DA +#define ICON_MDI_DEBUG_STEP_INTO "\xf3\xb0\x86\xb9" // U+F01B9 +#define ICON_MDI_DEBUG_STEP_OUT "\xf3\xb0\x86\xb8" // U+F01B8 +#define ICON_MDI_DEBUG_STEP_OVER "\xf3\xb0\x86\xb7" // U+F01B7 +#define ICON_MDI_DECAGRAM "\xf3\xb0\x9d\xac" // U+F076C +#define ICON_MDI_DECAGRAM_OUTLINE "\xf3\xb0\x9d\xad" // U+F076D +#define ICON_MDI_DECIMAL "\xf3\xb1\x82\xa1" // U+F10A1 +#define ICON_MDI_DECIMAL_COMMA "\xf3\xb1\x82\xa2" // U+F10A2 +#define ICON_MDI_DECIMAL_COMMA_DECREASE "\xf3\xb1\x82\xa3" // U+F10A3 +#define ICON_MDI_DECIMAL_COMMA_INCREASE "\xf3\xb1\x82\xa4" // U+F10A4 +#define ICON_MDI_DECIMAL_DECREASE "\xf3\xb0\x86\xb6" // U+F01B6 +#define ICON_MDI_DECIMAL_INCREASE "\xf3\xb0\x86\xb5" // U+F01B5 +#define ICON_MDI_DELETE "\xf3\xb0\x86\xb4" // U+F01B4 +#define ICON_MDI_DELETE_ALERT "\xf3\xb1\x82\xa5" // U+F10A5 +#define ICON_MDI_DELETE_ALERT_OUTLINE "\xf3\xb1\x82\xa6" // U+F10A6 +#define ICON_MDI_DELETE_CIRCLE "\xf3\xb0\x9a\x83" // U+F0683 +#define ICON_MDI_DELETE_CIRCLE_OUTLINE "\xf3\xb0\xae\x88" // U+F0B88 +#define ICON_MDI_DELETE_CLOCK "\xf3\xb1\x95\x96" // U+F1556 +#define ICON_MDI_DELETE_CLOCK_OUTLINE "\xf3\xb1\x95\x97" // U+F1557 +#define ICON_MDI_DELETE_EMPTY "\xf3\xb0\x9b\x8c" // U+F06CC +#define ICON_MDI_DELETE_EMPTY_OUTLINE "\xf3\xb0\xba\x9d" // U+F0E9D +#define ICON_MDI_DELETE_FOREVER "\xf3\xb0\x97\xa8" // U+F05E8 +#define ICON_MDI_DELETE_FOREVER_OUTLINE "\xf3\xb0\xae\x89" // U+F0B89 +#define ICON_MDI_DELETE_OFF "\xf3\xb1\x82\xa7" // U+F10A7 +#define ICON_MDI_DELETE_OFF_OUTLINE "\xf3\xb1\x82\xa8" // U+F10A8 +#define ICON_MDI_DELETE_OUTLINE "\xf3\xb0\xa7\xa7" // U+F09E7 +#define ICON_MDI_DELETE_RESTORE "\xf3\xb0\xa0\x99" // U+F0819 +#define ICON_MDI_DELETE_SWEEP "\xf3\xb0\x97\xa9" // U+F05E9 +#define ICON_MDI_DELETE_SWEEP_OUTLINE "\xf3\xb0\xb1\xa2" // U+F0C62 +#define ICON_MDI_DELETE_VARIANT "\xf3\xb0\x86\xb3" // U+F01B3 +#define ICON_MDI_DELTA "\xf3\xb0\x87\x82" // U+F01C2 +#define ICON_MDI_DESK "\xf3\xb1\x88\xb9" // U+F1239 +#define ICON_MDI_DESK_LAMP "\xf3\xb0\xa5\x9f" // U+F095F +#define ICON_MDI_DESK_LAMP_OFF "\xf3\xb1\xac\x9f" // U+F1B1F +#define ICON_MDI_DESK_LAMP_ON "\xf3\xb1\xac\xa0" // U+F1B20 +#define ICON_MDI_DESKPHONE "\xf3\xb0\x87\x83" // U+F01C3 +#define ICON_MDI_DESKTOP_CLASSIC "\xf3\xb0\x9f\x80" // U+F07C0 +#define ICON_MDI_DESKTOP_TOWER "\xf3\xb0\x87\x85" // U+F01C5 +#define ICON_MDI_DESKTOP_TOWER_MONITOR "\xf3\xb0\xaa\xab" // U+F0AAB +#define ICON_MDI_DETAILS "\xf3\xb0\x87\x86" // U+F01C6 +#define ICON_MDI_DEV_TO "\xf3\xb0\xb5\xae" // U+F0D6E +#define ICON_MDI_DEVELOPER_BOARD "\xf3\xb0\x9a\x97" // U+F0697 +#define ICON_MDI_DEVIANTART "\xf3\xb0\x87\x87" // U+F01C7 +#define ICON_MDI_DEVICES "\xf3\xb0\xbe\xb0" // U+F0FB0 +#define ICON_MDI_DHARMACHAKRA "\xf3\xb0\xa5\x8b" // U+F094B +#define ICON_MDI_DIABETES "\xf3\xb1\x84\xa6" // U+F1126 +#define ICON_MDI_DIALPAD "\xf3\xb0\x98\x9c" // U+F061C +#define ICON_MDI_DIAMETER "\xf3\xb0\xb1\xa3" // U+F0C63 +#define ICON_MDI_DIAMETER_OUTLINE "\xf3\xb0\xb1\xa4" // U+F0C64 +#define ICON_MDI_DIAMETER_VARIANT "\xf3\xb0\xb1\xa5" // U+F0C65 +#define ICON_MDI_DIAMOND "\xf3\xb0\xae\x8a" // U+F0B8A +#define ICON_MDI_DIAMOND_OUTLINE "\xf3\xb0\xae\x8b" // U+F0B8B +#define ICON_MDI_DIAMOND_STONE "\xf3\xb0\x87\x88" // U+F01C8 +#define ICON_MDI_DICE_1 "\xf3\xb0\x87\x8a" // U+F01CA +#define ICON_MDI_DICE_1_OUTLINE "\xf3\xb1\x85\x8a" // U+F114A +#define ICON_MDI_DICE_2 "\xf3\xb0\x87\x8b" // U+F01CB +#define ICON_MDI_DICE_2_OUTLINE "\xf3\xb1\x85\x8b" // U+F114B +#define ICON_MDI_DICE_3 "\xf3\xb0\x87\x8c" // U+F01CC +#define ICON_MDI_DICE_3_OUTLINE "\xf3\xb1\x85\x8c" // U+F114C +#define ICON_MDI_DICE_4 "\xf3\xb0\x87\x8d" // U+F01CD +#define ICON_MDI_DICE_4_OUTLINE "\xf3\xb1\x85\x8d" // U+F114D +#define ICON_MDI_DICE_5 "\xf3\xb0\x87\x8e" // U+F01CE +#define ICON_MDI_DICE_5_OUTLINE "\xf3\xb1\x85\x8e" // U+F114E +#define ICON_MDI_DICE_6 "\xf3\xb0\x87\x8f" // U+F01CF +#define ICON_MDI_DICE_6_OUTLINE "\xf3\xb1\x85\x8f" // U+F114F +#define ICON_MDI_DICE_D10 "\xf3\xb1\x85\x93" // U+F1153 +#define ICON_MDI_DICE_D10_OUTLINE "\xf3\xb0\x9d\xaf" // U+F076F +#define ICON_MDI_DICE_D12 "\xf3\xb1\x85\x94" // U+F1154 +#define ICON_MDI_DICE_D12_OUTLINE "\xf3\xb0\xa1\xa7" // U+F0867 +#define ICON_MDI_DICE_D20 "\xf3\xb1\x85\x95" // U+F1155 +#define ICON_MDI_DICE_D20_OUTLINE "\xf3\xb0\x97\xaa" // U+F05EA +#define ICON_MDI_DICE_D4 "\xf3\xb1\x85\x90" // U+F1150 +#define ICON_MDI_DICE_D4_OUTLINE "\xf3\xb0\x97\xab" // U+F05EB +#define ICON_MDI_DICE_D6 "\xf3\xb1\x85\x91" // U+F1151 +#define ICON_MDI_DICE_D6_OUTLINE "\xf3\xb0\x97\xad" // U+F05ED +#define ICON_MDI_DICE_D8 "\xf3\xb1\x85\x92" // U+F1152 +#define ICON_MDI_DICE_D8_OUTLINE "\xf3\xb0\x97\xac" // U+F05EC +#define ICON_MDI_DICE_MULTIPLE "\xf3\xb0\x9d\xae" // U+F076E +#define ICON_MDI_DICE_MULTIPLE_OUTLINE "\xf3\xb1\x85\x96" // U+F1156 +#define ICON_MDI_DIGITAL_OCEAN "\xf3\xb1\x88\xb7" // U+F1237 +#define ICON_MDI_DIP_SWITCH "\xf3\xb0\x9f\x81" // U+F07C1 +#define ICON_MDI_DIRECTIONS "\xf3\xb0\x87\x90" // U+F01D0 +#define ICON_MDI_DIRECTIONS_FORK "\xf3\xb0\x99\x81" // U+F0641 +#define ICON_MDI_DISC "\xf3\xb0\x97\xae" // U+F05EE +#define ICON_MDI_DISC_ALERT "\xf3\xb0\x87\x91" // U+F01D1 +#define ICON_MDI_DISC_PLAYER "\xf3\xb0\xa5\xa0" // U+F0960 +#define ICON_MDI_DISHWASHER "\xf3\xb0\xaa\xac" // U+F0AAC +#define ICON_MDI_DISHWASHER_ALERT "\xf3\xb1\x86\xb8" // U+F11B8 +#define ICON_MDI_DISHWASHER_OFF "\xf3\xb1\x86\xb9" // U+F11B9 +#define ICON_MDI_DISQUS "\xf3\xb0\x87\x92" // U+F01D2 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_CENTER "\xf3\xb1\x87\x89" // U+F11C9 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_LEFT "\xf3\xb1\x87\x88" // U+F11C8 +#define ICON_MDI_DISTRIBUTE_HORIZONTAL_RIGHT "\xf3\xb1\x87\x8a" // U+F11CA +#define ICON_MDI_DISTRIBUTE_VERTICAL_BOTTOM "\xf3\xb1\x87\x8b" // U+F11CB +#define ICON_MDI_DISTRIBUTE_VERTICAL_CENTER "\xf3\xb1\x87\x8c" // U+F11CC +#define ICON_MDI_DISTRIBUTE_VERTICAL_TOP "\xf3\xb1\x87\x8d" // U+F11CD +#define ICON_MDI_DIVERSIFY "\xf3\xb1\xa1\xb7" // U+F1877 +#define ICON_MDI_DIVING "\xf3\xb1\xa5\xb7" // U+F1977 +#define ICON_MDI_DIVING_FLIPPERS "\xf3\xb0\xb6\xbf" // U+F0DBF +#define ICON_MDI_DIVING_HELMET "\xf3\xb0\xb7\x80" // U+F0DC0 +#define ICON_MDI_DIVING_SCUBA "\xf3\xb1\xad\xb7" // U+F1B77 +#define ICON_MDI_DIVING_SCUBA_FLAG "\xf3\xb0\xb7\x82" // U+F0DC2 +#define ICON_MDI_DIVING_SCUBA_MASK "\xf3\xb0\xb7\x81" // U+F0DC1 +#define ICON_MDI_DIVING_SCUBA_TANK "\xf3\xb0\xb7\x83" // U+F0DC3 +#define ICON_MDI_DIVING_SCUBA_TANK_MULTIPLE "\xf3\xb0\xb7\x84" // U+F0DC4 +#define ICON_MDI_DIVING_SNORKEL "\xf3\xb0\xb7\x85" // U+F0DC5 +#define ICON_MDI_DIVISION "\xf3\xb0\x87\x94" // U+F01D4 +#define ICON_MDI_DIVISION_BOX "\xf3\xb0\x87\x95" // U+F01D5 +#define ICON_MDI_DLNA "\xf3\xb0\xa9\x81" // U+F0A41 +#define ICON_MDI_DNA "\xf3\xb0\x9a\x84" // U+F0684 +#define ICON_MDI_DNS "\xf3\xb0\x87\x96" // U+F01D6 +#define ICON_MDI_DNS_OUTLINE "\xf3\xb0\xae\x8c" // U+F0B8C +#define ICON_MDI_DOCK_BOTTOM "\xf3\xb1\x82\xa9" // U+F10A9 +#define ICON_MDI_DOCK_LEFT "\xf3\xb1\x82\xaa" // U+F10AA +#define ICON_MDI_DOCK_RIGHT "\xf3\xb1\x82\xab" // U+F10AB +#define ICON_MDI_DOCK_TOP "\xf3\xb1\x94\x93" // U+F1513 +#define ICON_MDI_DOCK_WINDOW "\xf3\xb1\x82\xac" // U+F10AC +#define ICON_MDI_DOCKER "\xf3\xb0\xa1\xa8" // U+F0868 +#define ICON_MDI_DOCTOR "\xf3\xb0\xa9\x82" // U+F0A42 +#define ICON_MDI_DOG "\xf3\xb0\xa9\x83" // U+F0A43 +#define ICON_MDI_DOG_SERVICE "\xf3\xb0\xaa\xad" // U+F0AAD +#define ICON_MDI_DOG_SIDE "\xf3\xb0\xa9\x84" // U+F0A44 +#define ICON_MDI_DOG_SIDE_OFF "\xf3\xb1\x9b\xae" // U+F16EE +#define ICON_MDI_DOLBY "\xf3\xb0\x9a\xb3" // U+F06B3 +#define ICON_MDI_DOLLY "\xf3\xb0\xba\x9e" // U+F0E9E +#define ICON_MDI_DOLPHIN "\xf3\xb1\xa2\xb4" // U+F18B4 +#define ICON_MDI_DOMAIN "\xf3\xb0\x87\x97" // U+F01D7 +#define ICON_MDI_DOMAIN_OFF "\xf3\xb0\xb5\xaf" // U+F0D6F +#define ICON_MDI_DOMAIN_PLUS "\xf3\xb1\x82\xad" // U+F10AD +#define ICON_MDI_DOMAIN_REMOVE "\xf3\xb1\x82\xae" // U+F10AE +#define ICON_MDI_DOMAIN_SWITCH "\xf3\xb1\xb0\xac" // U+F1C2C +#define ICON_MDI_DOME_LIGHT "\xf3\xb1\x90\x9e" // U+F141E +#define ICON_MDI_DOMINO_MASK "\xf3\xb1\x80\xa3" // U+F1023 +#define ICON_MDI_DONKEY "\xf3\xb0\x9f\x82" // U+F07C2 +#define ICON_MDI_DOOR "\xf3\xb0\xa0\x9a" // U+F081A +#define ICON_MDI_DOOR_CLOSED "\xf3\xb0\xa0\x9b" // U+F081B +#define ICON_MDI_DOOR_CLOSED_CANCEL "\xf3\xb1\xb2\x93" // U+F1C93 +#define ICON_MDI_DOOR_CLOSED_LOCK "\xf3\xb1\x82\xaf" // U+F10AF +#define ICON_MDI_DOOR_OPEN "\xf3\xb0\xa0\x9c" // U+F081C +#define ICON_MDI_DOOR_SLIDING "\xf3\xb1\xa0\x9e" // U+F181E +#define ICON_MDI_DOOR_SLIDING_LOCK "\xf3\xb1\xa0\x9f" // U+F181F +#define ICON_MDI_DOOR_SLIDING_OPEN "\xf3\xb1\xa0\xa0" // U+F1820 +#define ICON_MDI_DOORBELL "\xf3\xb1\x8b\xa6" // U+F12E6 +#define ICON_MDI_DOORBELL_VIDEO "\xf3\xb0\xa1\xa9" // U+F0869 +#define ICON_MDI_DOT_NET "\xf3\xb0\xaa\xae" // U+F0AAE +#define ICON_MDI_DOTS_CIRCLE "\xf3\xb1\xa5\xb8" // U+F1978 +#define ICON_MDI_DOTS_GRID "\xf3\xb1\x97\xbc" // U+F15FC +#define ICON_MDI_DOTS_HEXAGON "\xf3\xb1\x97\xbf" // U+F15FF +#define ICON_MDI_DOTS_HORIZONTAL "\xf3\xb0\x87\x98" // U+F01D8 +#define ICON_MDI_DOTS_HORIZONTAL_CIRCLE "\xf3\xb0\x9f\x83" // U+F07C3 +#define ICON_MDI_DOTS_HORIZONTAL_CIRCLE_OUTLINE "\xf3\xb0\xae\x8d" // U+F0B8D +#define ICON_MDI_DOTS_SQUARE "\xf3\xb1\x97\xbd" // U+F15FD +#define ICON_MDI_DOTS_TRIANGLE "\xf3\xb1\x97\xbe" // U+F15FE +#define ICON_MDI_DOTS_VERTICAL "\xf3\xb0\x87\x99" // U+F01D9 +#define ICON_MDI_DOTS_VERTICAL_CIRCLE "\xf3\xb0\x9f\x84" // U+F07C4 +#define ICON_MDI_DOTS_VERTICAL_CIRCLE_OUTLINE "\xf3\xb0\xae\x8e" // U+F0B8E +#define ICON_MDI_DOWNLOAD "\xf3\xb0\x87\x9a" // U+F01DA +#define ICON_MDI_DOWNLOAD_BOX "\xf3\xb1\x91\xa2" // U+F1462 +#define ICON_MDI_DOWNLOAD_BOX_OUTLINE "\xf3\xb1\x91\xa3" // U+F1463 +#define ICON_MDI_DOWNLOAD_CIRCLE "\xf3\xb1\x91\xa4" // U+F1464 +#define ICON_MDI_DOWNLOAD_CIRCLE_OUTLINE "\xf3\xb1\x91\xa5" // U+F1465 +#define ICON_MDI_DOWNLOAD_LOCK "\xf3\xb1\x8c\xa0" // U+F1320 +#define ICON_MDI_DOWNLOAD_LOCK_OUTLINE "\xf3\xb1\x8c\xa1" // U+F1321 +#define ICON_MDI_DOWNLOAD_MULTIPLE "\xf3\xb0\xa7\xa9" // U+F09E9 +#define ICON_MDI_DOWNLOAD_NETWORK "\xf3\xb0\x9b\xb4" // U+F06F4 +#define ICON_MDI_DOWNLOAD_NETWORK_OUTLINE "\xf3\xb0\xb1\xa6" // U+F0C66 +#define ICON_MDI_DOWNLOAD_OFF "\xf3\xb1\x82\xb0" // U+F10B0 +#define ICON_MDI_DOWNLOAD_OFF_OUTLINE "\xf3\xb1\x82\xb1" // U+F10B1 +#define ICON_MDI_DOWNLOAD_OUTLINE "\xf3\xb0\xae\x8f" // U+F0B8F +#define ICON_MDI_DRAG "\xf3\xb0\x87\x9b" // U+F01DB +#define ICON_MDI_DRAG_HORIZONTAL "\xf3\xb0\x87\x9c" // U+F01DC +#define ICON_MDI_DRAG_HORIZONTAL_VARIANT "\xf3\xb1\x8b\xb0" // U+F12F0 +#define ICON_MDI_DRAG_VARIANT "\xf3\xb0\xae\x90" // U+F0B90 +#define ICON_MDI_DRAG_VERTICAL "\xf3\xb0\x87\x9d" // U+F01DD +#define ICON_MDI_DRAG_VERTICAL_VARIANT "\xf3\xb1\x8b\xb1" // U+F12F1 +#define ICON_MDI_DRAMA_MASKS "\xf3\xb0\xb4\x82" // U+F0D02 +#define ICON_MDI_DRAW "\xf3\xb0\xbd\x89" // U+F0F49 +#define ICON_MDI_DRAW_PEN "\xf3\xb1\xa6\xb9" // U+F19B9 +#define ICON_MDI_DRAWING "\xf3\xb0\x87\x9e" // U+F01DE +#define ICON_MDI_DRAWING_BOX "\xf3\xb0\x87\x9f" // U+F01DF +#define ICON_MDI_DRESSER "\xf3\xb0\xbd\x8a" // U+F0F4A +#define ICON_MDI_DRESSER_OUTLINE "\xf3\xb0\xbd\x8b" // U+F0F4B +#define ICON_MDI_DRONE "\xf3\xb0\x87\xa2" // U+F01E2 +#define ICON_MDI_DROPBOX "\xf3\xb0\x87\xa3" // U+F01E3 +#define ICON_MDI_DRUPAL "\xf3\xb0\x87\xa4" // U+F01E4 +#define ICON_MDI_DUCK "\xf3\xb0\x87\xa5" // U+F01E5 +#define ICON_MDI_DUMBBELL "\xf3\xb0\x87\xa6" // U+F01E6 +#define ICON_MDI_DUMP_TRUCK "\xf3\xb0\xb1\xa7" // U+F0C67 +#define ICON_MDI_EAR_HEARING "\xf3\xb0\x9f\x85" // U+F07C5 +#define ICON_MDI_EAR_HEARING_LOOP "\xf3\xb1\xab\xae" // U+F1AEE +#define ICON_MDI_EAR_HEARING_OFF "\xf3\xb0\xa9\x85" // U+F0A45 +#define ICON_MDI_EARBUDS "\xf3\xb1\xa1\x8f" // U+F184F +#define ICON_MDI_EARBUDS_OFF "\xf3\xb1\xa1\x90" // U+F1850 +#define ICON_MDI_EARBUDS_OFF_OUTLINE "\xf3\xb1\xa1\x91" // U+F1851 +#define ICON_MDI_EARBUDS_OUTLINE "\xf3\xb1\xa1\x92" // U+F1852 +#define ICON_MDI_EARTH "\xf3\xb0\x87\xa7" // U+F01E7 +#define ICON_MDI_EARTH_ARROW_DOWN "\xf3\xb1\xb2\x87" // U+F1C87 +#define ICON_MDI_EARTH_ARROW_LEFT "\xf3\xb1\xb2\x88" // U+F1C88 +#define ICON_MDI_EARTH_ARROW_RIGHT "\xf3\xb1\x8c\x91" // U+F1311 +#define ICON_MDI_EARTH_ARROW_UP "\xf3\xb1\xb2\x89" // U+F1C89 +#define ICON_MDI_EARTH_BOX "\xf3\xb0\x9b\x8d" // U+F06CD +#define ICON_MDI_EARTH_BOX_MINUS "\xf3\xb1\x90\x87" // U+F1407 +#define ICON_MDI_EARTH_BOX_OFF "\xf3\xb0\x9b\x8e" // U+F06CE +#define ICON_MDI_EARTH_BOX_PLUS "\xf3\xb1\x90\x86" // U+F1406 +#define ICON_MDI_EARTH_BOX_REMOVE "\xf3\xb1\x90\x88" // U+F1408 +#define ICON_MDI_EARTH_MINUS "\xf3\xb1\x90\x84" // U+F1404 +#define ICON_MDI_EARTH_OFF "\xf3\xb0\x87\xa8" // U+F01E8 +#define ICON_MDI_EARTH_PLUS "\xf3\xb1\x90\x83" // U+F1403 +#define ICON_MDI_EARTH_REMOVE "\xf3\xb1\x90\x85" // U+F1405 +#define ICON_MDI_EGG "\xf3\xb0\xaa\xaf" // U+F0AAF +#define ICON_MDI_EGG_EASTER "\xf3\xb0\xaa\xb0" // U+F0AB0 +#define ICON_MDI_EGG_FRIED "\xf3\xb1\xa1\x8a" // U+F184A +#define ICON_MDI_EGG_OFF "\xf3\xb1\x8f\xb0" // U+F13F0 +#define ICON_MDI_EGG_OFF_OUTLINE "\xf3\xb1\x8f\xb1" // U+F13F1 +#define ICON_MDI_EGG_OUTLINE "\xf3\xb1\x8f\xb2" // U+F13F2 +#define ICON_MDI_EIFFEL_TOWER "\xf3\xb1\x95\xab" // U+F156B +#define ICON_MDI_EIGHT_TRACK "\xf3\xb0\xa7\xaa" // U+F09EA +#define ICON_MDI_EJECT "\xf3\xb0\x87\xaa" // U+F01EA +#define ICON_MDI_EJECT_CIRCLE "\xf3\xb1\xac\xa3" // U+F1B23 +#define ICON_MDI_EJECT_CIRCLE_OUTLINE "\xf3\xb1\xac\xa4" // U+F1B24 +#define ICON_MDI_EJECT_OUTLINE "\xf3\xb0\xae\x91" // U+F0B91 +#define ICON_MDI_ELECTRIC_SWITCH "\xf3\xb0\xba\x9f" // U+F0E9F +#define ICON_MDI_ELECTRIC_SWITCH_CLOSED "\xf3\xb1\x83\x99" // U+F10D9 +#define ICON_MDI_ELECTRON_FRAMEWORK "\xf3\xb1\x80\xa4" // U+F1024 +#define ICON_MDI_ELEPHANT "\xf3\xb0\x9f\x86" // U+F07C6 +#define ICON_MDI_ELEVATION_DECLINE "\xf3\xb0\x87\xab" // U+F01EB +#define ICON_MDI_ELEVATION_RISE "\xf3\xb0\x87\xac" // U+F01EC +#define ICON_MDI_ELEVATOR "\xf3\xb0\x87\xad" // U+F01ED +#define ICON_MDI_ELEVATOR_DOWN "\xf3\xb1\x8b\x82" // U+F12C2 +#define ICON_MDI_ELEVATOR_PASSENGER "\xf3\xb1\x8e\x81" // U+F1381 +#define ICON_MDI_ELEVATOR_PASSENGER_OFF "\xf3\xb1\xa5\xb9" // U+F1979 +#define ICON_MDI_ELEVATOR_PASSENGER_OFF_OUTLINE "\xf3\xb1\xa5\xba" // U+F197A +#define ICON_MDI_ELEVATOR_PASSENGER_OUTLINE "\xf3\xb1\xa5\xbb" // U+F197B +#define ICON_MDI_ELEVATOR_UP "\xf3\xb1\x8b\x81" // U+F12C1 +#define ICON_MDI_ELLIPSE "\xf3\xb0\xba\xa0" // U+F0EA0 +#define ICON_MDI_ELLIPSE_OUTLINE "\xf3\xb0\xba\xa1" // U+F0EA1 +#define ICON_MDI_EMAIL "\xf3\xb0\x87\xae" // U+F01EE +#define ICON_MDI_EMAIL_ALERT "\xf3\xb0\x9b\x8f" // U+F06CF +#define ICON_MDI_EMAIL_ALERT_OUTLINE "\xf3\xb0\xb5\x82" // U+F0D42 +#define ICON_MDI_EMAIL_ARROW_LEFT "\xf3\xb1\x83\x9a" // U+F10DA +#define ICON_MDI_EMAIL_ARROW_LEFT_OUTLINE "\xf3\xb1\x83\x9b" // U+F10DB +#define ICON_MDI_EMAIL_ARROW_RIGHT "\xf3\xb1\x83\x9c" // U+F10DC +#define ICON_MDI_EMAIL_ARROW_RIGHT_OUTLINE "\xf3\xb1\x83\x9d" // U+F10DD +#define ICON_MDI_EMAIL_BOX "\xf3\xb0\xb4\x83" // U+F0D03 +#define ICON_MDI_EMAIL_CHECK "\xf3\xb0\xaa\xb1" // U+F0AB1 +#define ICON_MDI_EMAIL_CHECK_OUTLINE "\xf3\xb0\xaa\xb2" // U+F0AB2 +#define ICON_MDI_EMAIL_EDIT "\xf3\xb0\xbb\xa3" // U+F0EE3 +#define ICON_MDI_EMAIL_EDIT_OUTLINE "\xf3\xb0\xbb\xa4" // U+F0EE4 +#define ICON_MDI_EMAIL_FAST "\xf3\xb1\xa1\xaf" // U+F186F +#define ICON_MDI_EMAIL_FAST_OUTLINE "\xf3\xb1\xa1\xb0" // U+F1870 +#define ICON_MDI_EMAIL_HEART_OUTLINE "\xf3\xb1\xb1\x9b" // U+F1C5B +#define ICON_MDI_EMAIL_LOCK "\xf3\xb0\x87\xb1" // U+F01F1 +#define ICON_MDI_EMAIL_LOCK_OUTLINE "\xf3\xb1\xad\xa1" // U+F1B61 +#define ICON_MDI_EMAIL_MARK_AS_UNREAD "\xf3\xb0\xae\x92" // U+F0B92 +#define ICON_MDI_EMAIL_MINUS "\xf3\xb0\xbb\xa5" // U+F0EE5 +#define ICON_MDI_EMAIL_MINUS_OUTLINE "\xf3\xb0\xbb\xa6" // U+F0EE6 +#define ICON_MDI_EMAIL_MULTIPLE "\xf3\xb0\xbb\xa7" // U+F0EE7 +#define ICON_MDI_EMAIL_MULTIPLE_OUTLINE "\xf3\xb0\xbb\xa8" // U+F0EE8 +#define ICON_MDI_EMAIL_NEWSLETTER "\xf3\xb0\xbe\xb1" // U+F0FB1 +#define ICON_MDI_EMAIL_OFF "\xf3\xb1\x8f\xa3" // U+F13E3 +#define ICON_MDI_EMAIL_OFF_OUTLINE "\xf3\xb1\x8f\xa4" // U+F13E4 +#define ICON_MDI_EMAIL_OPEN "\xf3\xb0\x87\xaf" // U+F01EF +#define ICON_MDI_EMAIL_OPEN_HEART_OUTLINE "\xf3\xb1\xb1\x9c" // U+F1C5C +#define ICON_MDI_EMAIL_OPEN_MULTIPLE "\xf3\xb0\xbb\xa9" // U+F0EE9 +#define ICON_MDI_EMAIL_OPEN_MULTIPLE_OUTLINE "\xf3\xb0\xbb\xaa" // U+F0EEA +#define ICON_MDI_EMAIL_OPEN_OUTLINE "\xf3\xb0\x97\xaf" // U+F05EF +#define ICON_MDI_EMAIL_OUTLINE "\xf3\xb0\x87\xb0" // U+F01F0 +#define ICON_MDI_EMAIL_PLUS "\xf3\xb0\xa7\xab" // U+F09EB +#define ICON_MDI_EMAIL_PLUS_OUTLINE "\xf3\xb0\xa7\xac" // U+F09EC +#define ICON_MDI_EMAIL_REMOVE "\xf3\xb1\x99\xa1" // U+F1661 +#define ICON_MDI_EMAIL_REMOVE_OUTLINE "\xf3\xb1\x99\xa2" // U+F1662 +#define ICON_MDI_EMAIL_SEAL "\xf3\xb1\xa5\x9b" // U+F195B +#define ICON_MDI_EMAIL_SEAL_OUTLINE "\xf3\xb1\xa5\x9c" // U+F195C +#define ICON_MDI_EMAIL_SEARCH "\xf3\xb0\xa5\xa1" // U+F0961 +#define ICON_MDI_EMAIL_SEARCH_OUTLINE "\xf3\xb0\xa5\xa2" // U+F0962 +#define ICON_MDI_EMAIL_SYNC "\xf3\xb1\x8b\x87" // U+F12C7 +#define ICON_MDI_EMAIL_SYNC_OUTLINE "\xf3\xb1\x8b\x88" // U+F12C8 +#define ICON_MDI_EMAIL_VARIANT "\xf3\xb0\x97\xb0" // U+F05F0 +#define ICON_MDI_EMBER "\xf3\xb0\xac\xb0" // U+F0B30 +#define ICON_MDI_EMBY "\xf3\xb0\x9a\xb4" // U+F06B4 +#define ICON_MDI_EMOTICON "\xf3\xb0\xb1\xa8" // U+F0C68 +#define ICON_MDI_EMOTICON_ANGRY "\xf3\xb0\xb1\xa9" // U+F0C69 +#define ICON_MDI_EMOTICON_ANGRY_OUTLINE "\xf3\xb0\xb1\xaa" // U+F0C6A +#define ICON_MDI_EMOTICON_CONFUSED "\xf3\xb1\x83\x9e" // U+F10DE +#define ICON_MDI_EMOTICON_CONFUSED_OUTLINE "\xf3\xb1\x83\x9f" // U+F10DF +#define ICON_MDI_EMOTICON_COOL "\xf3\xb0\xb1\xab" // U+F0C6B +#define ICON_MDI_EMOTICON_COOL_OUTLINE "\xf3\xb0\x87\xb3" // U+F01F3 +#define ICON_MDI_EMOTICON_CRY "\xf3\xb0\xb1\xac" // U+F0C6C +#define ICON_MDI_EMOTICON_CRY_OUTLINE "\xf3\xb0\xb1\xad" // U+F0C6D +#define ICON_MDI_EMOTICON_DEAD "\xf3\xb0\xb1\xae" // U+F0C6E +#define ICON_MDI_EMOTICON_DEAD_OUTLINE "\xf3\xb0\x9a\x9b" // U+F069B +#define ICON_MDI_EMOTICON_DEVIL "\xf3\xb0\xb1\xaf" // U+F0C6F +#define ICON_MDI_EMOTICON_DEVIL_OUTLINE "\xf3\xb0\x87\xb4" // U+F01F4 +#define ICON_MDI_EMOTICON_EXCITED "\xf3\xb0\xb1\xb0" // U+F0C70 +#define ICON_MDI_EMOTICON_EXCITED_OUTLINE "\xf3\xb0\x9a\x9c" // U+F069C +#define ICON_MDI_EMOTICON_FROWN "\xf3\xb0\xbd\x8c" // U+F0F4C +#define ICON_MDI_EMOTICON_FROWN_OUTLINE "\xf3\xb0\xbd\x8d" // U+F0F4D +#define ICON_MDI_EMOTICON_HAPPY "\xf3\xb0\xb1\xb1" // U+F0C71 +#define ICON_MDI_EMOTICON_HAPPY_OUTLINE "\xf3\xb0\x87\xb5" // U+F01F5 +#define ICON_MDI_EMOTICON_KISS "\xf3\xb0\xb1\xb2" // U+F0C72 +#define ICON_MDI_EMOTICON_KISS_OUTLINE "\xf3\xb0\xb1\xb3" // U+F0C73 +#define ICON_MDI_EMOTICON_LOL "\xf3\xb1\x88\x94" // U+F1214 +#define ICON_MDI_EMOTICON_LOL_OUTLINE "\xf3\xb1\x88\x95" // U+F1215 +#define ICON_MDI_EMOTICON_MINUS "\xf3\xb1\xb2\xb2" // U+F1CB2 +#define ICON_MDI_EMOTICON_MINUS_OUTLINE "\xf3\xb1\xb2\xb3" // U+F1CB3 +#define ICON_MDI_EMOTICON_NEUTRAL "\xf3\xb0\xb1\xb4" // U+F0C74 +#define ICON_MDI_EMOTICON_NEUTRAL_OUTLINE "\xf3\xb0\x87\xb6" // U+F01F6 +#define ICON_MDI_EMOTICON_OUTLINE "\xf3\xb0\x87\xb2" // U+F01F2 +#define ICON_MDI_EMOTICON_PLUS "\xf3\xb1\xb2\xb4" // U+F1CB4 +#define ICON_MDI_EMOTICON_PLUS_OUTLINE "\xf3\xb1\xb2\xb5" // U+F1CB5 +#define ICON_MDI_EMOTICON_POOP "\xf3\xb0\x87\xb7" // U+F01F7 +#define ICON_MDI_EMOTICON_POOP_OUTLINE "\xf3\xb0\xb1\xb5" // U+F0C75 +#define ICON_MDI_EMOTICON_REMOVE "\xf3\xb1\xb2\xb6" // U+F1CB6 +#define ICON_MDI_EMOTICON_REMOVE_OUTLINE "\xf3\xb1\xb2\xb7" // U+F1CB7 +#define ICON_MDI_EMOTICON_SAD "\xf3\xb0\xb1\xb6" // U+F0C76 +#define ICON_MDI_EMOTICON_SAD_OUTLINE "\xf3\xb0\x87\xb8" // U+F01F8 +#define ICON_MDI_EMOTICON_SICK "\xf3\xb1\x95\xbc" // U+F157C +#define ICON_MDI_EMOTICON_SICK_OUTLINE "\xf3\xb1\x95\xbd" // U+F157D +#define ICON_MDI_EMOTICON_TONGUE "\xf3\xb0\x87\xb9" // U+F01F9 +#define ICON_MDI_EMOTICON_TONGUE_OUTLINE "\xf3\xb0\xb1\xb7" // U+F0C77 +#define ICON_MDI_EMOTICON_WINK "\xf3\xb0\xb1\xb8" // U+F0C78 +#define ICON_MDI_EMOTICON_WINK_OUTLINE "\xf3\xb0\xb1\xb9" // U+F0C79 +#define ICON_MDI_ENGINE "\xf3\xb0\x87\xba" // U+F01FA +#define ICON_MDI_ENGINE_OFF "\xf3\xb0\xa9\x86" // U+F0A46 +#define ICON_MDI_ENGINE_OFF_OUTLINE "\xf3\xb0\xa9\x87" // U+F0A47 +#define ICON_MDI_ENGINE_OUTLINE "\xf3\xb0\x87\xbb" // U+F01FB +#define ICON_MDI_EPSILON "\xf3\xb1\x83\xa0" // U+F10E0 +#define ICON_MDI_EQUAL "\xf3\xb0\x87\xbc" // U+F01FC +#define ICON_MDI_EQUAL_BOX "\xf3\xb0\x87\xbd" // U+F01FD +#define ICON_MDI_EQUALIZER "\xf3\xb0\xba\xa2" // U+F0EA2 +#define ICON_MDI_EQUALIZER_OUTLINE "\xf3\xb0\xba\xa3" // U+F0EA3 +#define ICON_MDI_ERASER "\xf3\xb0\x87\xbe" // U+F01FE +#define ICON_MDI_ERASER_VARIANT "\xf3\xb0\x99\x82" // U+F0642 +#define ICON_MDI_ESCALATOR "\xf3\xb0\x87\xbf" // U+F01FF +#define ICON_MDI_ESCALATOR_BOX "\xf3\xb1\x8e\x99" // U+F1399 +#define ICON_MDI_ESCALATOR_DOWN "\xf3\xb1\x8b\x80" // U+F12C0 +#define ICON_MDI_ESCALATOR_UP "\xf3\xb1\x8a\xbf" // U+F12BF +#define ICON_MDI_ESLINT "\xf3\xb0\xb1\xba" // U+F0C7A +#define ICON_MDI_ET "\xf3\xb0\xaa\xb3" // U+F0AB3 +#define ICON_MDI_ETHEREUM "\xf3\xb0\xa1\xaa" // U+F086A +#define ICON_MDI_ETHERNET "\xf3\xb0\x88\x80" // U+F0200 +#define ICON_MDI_ETHERNET_CABLE "\xf3\xb0\x88\x81" // U+F0201 +#define ICON_MDI_ETHERNET_CABLE_OFF "\xf3\xb0\x88\x82" // U+F0202 +#define ICON_MDI_EV_PLUG_CCS1 "\xf3\xb1\x94\x99" // U+F1519 +#define ICON_MDI_EV_PLUG_CCS2 "\xf3\xb1\x94\x9a" // U+F151A +#define ICON_MDI_EV_PLUG_CHADEMO "\xf3\xb1\x94\x9b" // U+F151B +#define ICON_MDI_EV_PLUG_TESLA "\xf3\xb1\x94\x9c" // U+F151C +#define ICON_MDI_EV_PLUG_TYPE1 "\xf3\xb1\x94\x9d" // U+F151D +#define ICON_MDI_EV_PLUG_TYPE2 "\xf3\xb1\x94\x9e" // U+F151E +#define ICON_MDI_EV_STATION "\xf3\xb0\x97\xb1" // U+F05F1 +#define ICON_MDI_EVERNOTE "\xf3\xb0\x88\x84" // U+F0204 +#define ICON_MDI_EXCAVATOR "\xf3\xb1\x80\xa5" // U+F1025 +#define ICON_MDI_EXCLAMATION "\xf3\xb0\x88\x85" // U+F0205 +#define ICON_MDI_EXCLAMATION_THICK "\xf3\xb1\x88\xb8" // U+F1238 +#define ICON_MDI_EXIT_RUN "\xf3\xb0\xa9\x88" // U+F0A48 +#define ICON_MDI_EXIT_TO_APP "\xf3\xb0\x88\x86" // U+F0206 +#define ICON_MDI_EXPAND_ALL "\xf3\xb0\xaa\xb4" // U+F0AB4 +#define ICON_MDI_EXPAND_ALL_OUTLINE "\xf3\xb0\xaa\xb5" // U+F0AB5 +#define ICON_MDI_EXPANSION_CARD "\xf3\xb0\xa2\xae" // U+F08AE +#define ICON_MDI_EXPANSION_CARD_VARIANT "\xf3\xb0\xbe\xb2" // U+F0FB2 +#define ICON_MDI_EXPONENT "\xf3\xb0\xa5\xa3" // U+F0963 +#define ICON_MDI_EXPONENT_BOX "\xf3\xb0\xa5\xa4" // U+F0964 +#define ICON_MDI_EXPORT "\xf3\xb0\x88\x87" // U+F0207 +#define ICON_MDI_EXPORT_VARIANT "\xf3\xb0\xae\x93" // U+F0B93 +#define ICON_MDI_EYE "\xf3\xb0\x88\x88" // U+F0208 +#define ICON_MDI_EYE_ARROW_LEFT "\xf3\xb1\xa3\xbd" // U+F18FD +#define ICON_MDI_EYE_ARROW_LEFT_OUTLINE "\xf3\xb1\xa3\xbe" // U+F18FE +#define ICON_MDI_EYE_ARROW_RIGHT "\xf3\xb1\xa3\xbf" // U+F18FF +#define ICON_MDI_EYE_ARROW_RIGHT_OUTLINE "\xf3\xb1\xa4\x80" // U+F1900 +#define ICON_MDI_EYE_CHECK "\xf3\xb0\xb4\x84" // U+F0D04 +#define ICON_MDI_EYE_CHECK_OUTLINE "\xf3\xb0\xb4\x85" // U+F0D05 +#define ICON_MDI_EYE_CIRCLE "\xf3\xb0\xae\x94" // U+F0B94 +#define ICON_MDI_EYE_CIRCLE_OUTLINE "\xf3\xb0\xae\x95" // U+F0B95 +#define ICON_MDI_EYE_CLOSED "\xf3\xb1\xb2\xa3" // U+F1CA3 +#define ICON_MDI_EYE_LOCK "\xf3\xb1\xb0\x86" // U+F1C06 +#define ICON_MDI_EYE_LOCK_OPEN "\xf3\xb1\xb0\x87" // U+F1C07 +#define ICON_MDI_EYE_LOCK_OPEN_OUTLINE "\xf3\xb1\xb0\x88" // U+F1C08 +#define ICON_MDI_EYE_LOCK_OUTLINE "\xf3\xb1\xb0\x89" // U+F1C09 +#define ICON_MDI_EYE_MINUS "\xf3\xb1\x80\xa6" // U+F1026 +#define ICON_MDI_EYE_MINUS_OUTLINE "\xf3\xb1\x80\xa7" // U+F1027 +#define ICON_MDI_EYE_OFF "\xf3\xb0\x88\x89" // U+F0209 +#define ICON_MDI_EYE_OFF_OUTLINE "\xf3\xb0\x9b\x91" // U+F06D1 +#define ICON_MDI_EYE_OUTLINE "\xf3\xb0\x9b\x90" // U+F06D0 +#define ICON_MDI_EYE_PLUS "\xf3\xb0\xa1\xab" // U+F086B +#define ICON_MDI_EYE_PLUS_OUTLINE "\xf3\xb0\xa1\xac" // U+F086C +#define ICON_MDI_EYE_REFRESH "\xf3\xb1\xa5\xbc" // U+F197C +#define ICON_MDI_EYE_REFRESH_OUTLINE "\xf3\xb1\xa5\xbd" // U+F197D +#define ICON_MDI_EYE_REMOVE "\xf3\xb1\x97\xa3" // U+F15E3 +#define ICON_MDI_EYE_REMOVE_OUTLINE "\xf3\xb1\x97\xa4" // U+F15E4 +#define ICON_MDI_EYE_SETTINGS "\xf3\xb0\xa1\xad" // U+F086D +#define ICON_MDI_EYE_SETTINGS_OUTLINE "\xf3\xb0\xa1\xae" // U+F086E +#define ICON_MDI_EYEDROPPER "\xf3\xb0\x88\x8a" // U+F020A +#define ICON_MDI_EYEDROPPER_MINUS "\xf3\xb1\x8f\x9d" // U+F13DD +#define ICON_MDI_EYEDROPPER_OFF "\xf3\xb1\x8f\x9f" // U+F13DF +#define ICON_MDI_EYEDROPPER_PLUS "\xf3\xb1\x8f\x9c" // U+F13DC +#define ICON_MDI_EYEDROPPER_REMOVE "\xf3\xb1\x8f\x9e" // U+F13DE +#define ICON_MDI_EYEDROPPER_VARIANT "\xf3\xb0\x88\x8b" // U+F020B +#define ICON_MDI_FACE_AGENT "\xf3\xb0\xb5\xb0" // U+F0D70 +#define ICON_MDI_FACE_MAN "\xf3\xb0\x99\x83" // U+F0643 +#define ICON_MDI_FACE_MAN_OUTLINE "\xf3\xb0\xae\x96" // U+F0B96 +#define ICON_MDI_FACE_MAN_PROFILE "\xf3\xb0\x99\x84" // U+F0644 +#define ICON_MDI_FACE_MAN_SHIMMER "\xf3\xb1\x97\x8c" // U+F15CC +#define ICON_MDI_FACE_MAN_SHIMMER_OUTLINE "\xf3\xb1\x97\x8d" // U+F15CD +#define ICON_MDI_FACE_MASK "\xf3\xb1\x96\x86" // U+F1586 +#define ICON_MDI_FACE_MASK_OUTLINE "\xf3\xb1\x96\x87" // U+F1587 +#define ICON_MDI_FACE_RECOGNITION "\xf3\xb0\xb1\xbb" // U+F0C7B +#define ICON_MDI_FACE_WOMAN "\xf3\xb1\x81\xb7" // U+F1077 +#define ICON_MDI_FACE_WOMAN_OUTLINE "\xf3\xb1\x81\xb8" // U+F1078 +#define ICON_MDI_FACE_WOMAN_PROFILE "\xf3\xb1\x81\xb6" // U+F1076 +#define ICON_MDI_FACE_WOMAN_SHIMMER "\xf3\xb1\x97\x8e" // U+F15CE +#define ICON_MDI_FACE_WOMAN_SHIMMER_OUTLINE "\xf3\xb1\x97\x8f" // U+F15CF +#define ICON_MDI_FACEBOOK "\xf3\xb0\x88\x8c" // U+F020C +#define ICON_MDI_FACEBOOK_GAMING "\xf3\xb0\x9f\x9d" // U+F07DD +#define ICON_MDI_FACEBOOK_MESSENGER "\xf3\xb0\x88\x8e" // U+F020E +#define ICON_MDI_FACEBOOK_WORKPLACE "\xf3\xb0\xac\xb1" // U+F0B31 +#define ICON_MDI_FACTORY "\xf3\xb0\x88\x8f" // U+F020F +#define ICON_MDI_FAMILY_TREE "\xf3\xb1\x98\x8e" // U+F160E +#define ICON_MDI_FAN "\xf3\xb0\x88\x90" // U+F0210 +#define ICON_MDI_FAN_ALERT "\xf3\xb1\x91\xac" // U+F146C +#define ICON_MDI_FAN_AUTO "\xf3\xb1\x9c\x9d" // U+F171D +#define ICON_MDI_FAN_CHEVRON_DOWN "\xf3\xb1\x91\xad" // U+F146D +#define ICON_MDI_FAN_CHEVRON_UP "\xf3\xb1\x91\xae" // U+F146E +#define ICON_MDI_FAN_CLOCK "\xf3\xb1\xa8\xba" // U+F1A3A +#define ICON_MDI_FAN_MINUS "\xf3\xb1\x91\xb0" // U+F1470 +#define ICON_MDI_FAN_OFF "\xf3\xb0\xa0\x9d" // U+F081D +#define ICON_MDI_FAN_PLUS "\xf3\xb1\x91\xaf" // U+F146F +#define ICON_MDI_FAN_REMOVE "\xf3\xb1\x91\xb1" // U+F1471 +#define ICON_MDI_FAN_SPEED_1 "\xf3\xb1\x91\xb2" // U+F1472 +#define ICON_MDI_FAN_SPEED_2 "\xf3\xb1\x91\xb3" // U+F1473 +#define ICON_MDI_FAN_SPEED_3 "\xf3\xb1\x91\xb4" // U+F1474 +#define ICON_MDI_FAST_FORWARD "\xf3\xb0\x88\x91" // U+F0211 +#define ICON_MDI_FAST_FORWARD_10 "\xf3\xb0\xb5\xb1" // U+F0D71 +#define ICON_MDI_FAST_FORWARD_15 "\xf3\xb1\xa4\xba" // U+F193A +#define ICON_MDI_FAST_FORWARD_30 "\xf3\xb0\xb4\x86" // U+F0D06 +#define ICON_MDI_FAST_FORWARD_45 "\xf3\xb1\xac\x92" // U+F1B12 +#define ICON_MDI_FAST_FORWARD_5 "\xf3\xb1\x87\xb8" // U+F11F8 +#define ICON_MDI_FAST_FORWARD_60 "\xf3\xb1\x98\x8b" // U+F160B +#define ICON_MDI_FAST_FORWARD_OUTLINE "\xf3\xb0\x9b\x92" // U+F06D2 +#define ICON_MDI_FAUCET "\xf3\xb1\xac\xa9" // U+F1B29 +#define ICON_MDI_FAUCET_VARIANT "\xf3\xb1\xac\xaa" // U+F1B2A +#define ICON_MDI_FAX "\xf3\xb0\x88\x92" // U+F0212 +#define ICON_MDI_FEATHER "\xf3\xb0\x9b\x93" // U+F06D3 +#define ICON_MDI_FEATURE_SEARCH "\xf3\xb0\xa9\x89" // U+F0A49 +#define ICON_MDI_FEATURE_SEARCH_OUTLINE "\xf3\xb0\xa9\x8a" // U+F0A4A +#define ICON_MDI_FEDORA "\xf3\xb0\xa3\x9b" // U+F08DB +#define ICON_MDI_FENCE "\xf3\xb1\x9e\x9a" // U+F179A +#define ICON_MDI_FENCE_ELECTRIC "\xf3\xb1\x9f\xb6" // U+F17F6 +#define ICON_MDI_FENCING "\xf3\xb1\x93\x81" // U+F14C1 +#define ICON_MDI_FERRIS_WHEEL "\xf3\xb0\xba\xa4" // U+F0EA4 +#define ICON_MDI_FERRY "\xf3\xb0\x88\x93" // U+F0213 +#define ICON_MDI_FILE "\xf3\xb0\x88\x94" // U+F0214 +#define ICON_MDI_FILE_ACCOUNT "\xf3\xb0\x9c\xbb" // U+F073B +#define ICON_MDI_FILE_ACCOUNT_OUTLINE "\xf3\xb1\x80\xa8" // U+F1028 +#define ICON_MDI_FILE_ALERT "\xf3\xb0\xa9\x8b" // U+F0A4B +#define ICON_MDI_FILE_ALERT_OUTLINE "\xf3\xb0\xa9\x8c" // U+F0A4C +#define ICON_MDI_FILE_ARROW_LEFT_RIGHT "\xf3\xb1\xaa\x93" // U+F1A93 +#define ICON_MDI_FILE_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xaa\x94" // U+F1A94 +#define ICON_MDI_FILE_ARROW_UP_DOWN "\xf3\xb1\xaa\x95" // U+F1A95 +#define ICON_MDI_FILE_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xaa\x96" // U+F1A96 +#define ICON_MDI_FILE_CABINET "\xf3\xb0\xaa\xb6" // U+F0AB6 +#define ICON_MDI_FILE_CAD "\xf3\xb0\xbb\xab" // U+F0EEB +#define ICON_MDI_FILE_CAD_BOX "\xf3\xb0\xbb\xac" // U+F0EEC +#define ICON_MDI_FILE_CANCEL "\xf3\xb0\xb7\x86" // U+F0DC6 +#define ICON_MDI_FILE_CANCEL_OUTLINE "\xf3\xb0\xb7\x87" // U+F0DC7 +#define ICON_MDI_FILE_CERTIFICATE "\xf3\xb1\x86\x86" // U+F1186 +#define ICON_MDI_FILE_CERTIFICATE_OUTLINE "\xf3\xb1\x86\x87" // U+F1187 +#define ICON_MDI_FILE_CHART "\xf3\xb0\x88\x95" // U+F0215 +#define ICON_MDI_FILE_CHART_CHECK "\xf3\xb1\xa7\x86" // U+F19C6 +#define ICON_MDI_FILE_CHART_CHECK_OUTLINE "\xf3\xb1\xa7\x87" // U+F19C7 +#define ICON_MDI_FILE_CHART_OUTLINE "\xf3\xb1\x80\xa9" // U+F1029 +#define ICON_MDI_FILE_CHECK "\xf3\xb0\x88\x96" // U+F0216 +#define ICON_MDI_FILE_CHECK_OUTLINE "\xf3\xb0\xb8\xa9" // U+F0E29 +#define ICON_MDI_FILE_CLOCK "\xf3\xb1\x8b\xa1" // U+F12E1 +#define ICON_MDI_FILE_CLOCK_OUTLINE "\xf3\xb1\x8b\xa2" // U+F12E2 +#define ICON_MDI_FILE_CLOUD "\xf3\xb0\x88\x97" // U+F0217 +#define ICON_MDI_FILE_CLOUD_OUTLINE "\xf3\xb1\x80\xaa" // U+F102A +#define ICON_MDI_FILE_CODE "\xf3\xb0\x88\xae" // U+F022E +#define ICON_MDI_FILE_CODE_OUTLINE "\xf3\xb1\x80\xab" // U+F102B +#define ICON_MDI_FILE_COG "\xf3\xb1\x81\xbb" // U+F107B +#define ICON_MDI_FILE_COG_OUTLINE "\xf3\xb1\x81\xbc" // U+F107C +#define ICON_MDI_FILE_COMPARE "\xf3\xb0\xa2\xaa" // U+F08AA +#define ICON_MDI_FILE_DELIMITED "\xf3\xb0\x88\x98" // U+F0218 +#define ICON_MDI_FILE_DELIMITED_OUTLINE "\xf3\xb0\xba\xa5" // U+F0EA5 +#define ICON_MDI_FILE_DOCUMENT "\xf3\xb0\x88\x99" // U+F0219 +#define ICON_MDI_FILE_DOCUMENT_ALERT "\xf3\xb1\xaa\x97" // U+F1A97 +#define ICON_MDI_FILE_DOCUMENT_ALERT_OUTLINE "\xf3\xb1\xaa\x98" // U+F1A98 +#define ICON_MDI_FILE_DOCUMENT_ARROW_RIGHT "\xf3\xb1\xb0\x8f" // U+F1C0F +#define ICON_MDI_FILE_DOCUMENT_ARROW_RIGHT_OUTLINE "\xf3\xb1\xb0\x90" // U+F1C10 +#define ICON_MDI_FILE_DOCUMENT_CHECK "\xf3\xb1\xaa\x99" // U+F1A99 +#define ICON_MDI_FILE_DOCUMENT_CHECK_OUTLINE "\xf3\xb1\xaa\x9a" // U+F1A9A +#define ICON_MDI_FILE_DOCUMENT_EDIT "\xf3\xb0\xb7\x88" // U+F0DC8 +#define ICON_MDI_FILE_DOCUMENT_EDIT_OUTLINE "\xf3\xb0\xb7\x89" // U+F0DC9 +#define ICON_MDI_FILE_DOCUMENT_MINUS "\xf3\xb1\xaa\x9b" // U+F1A9B +#define ICON_MDI_FILE_DOCUMENT_MINUS_OUTLINE "\xf3\xb1\xaa\x9c" // U+F1A9C +#define ICON_MDI_FILE_DOCUMENT_MULTIPLE "\xf3\xb1\x94\x97" // U+F1517 +#define ICON_MDI_FILE_DOCUMENT_MULTIPLE_OUTLINE "\xf3\xb1\x94\x98" // U+F1518 +#define ICON_MDI_FILE_DOCUMENT_OUTLINE "\xf3\xb0\xa7\xae" // U+F09EE +#define ICON_MDI_FILE_DOCUMENT_PLUS "\xf3\xb1\xaa\x9d" // U+F1A9D +#define ICON_MDI_FILE_DOCUMENT_PLUS_OUTLINE "\xf3\xb1\xaa\x9e" // U+F1A9E +#define ICON_MDI_FILE_DOCUMENT_REFRESH "\xf3\xb1\xb1\xba" // U+F1C7A +#define ICON_MDI_FILE_DOCUMENT_REFRESH_OUTLINE "\xf3\xb1\xb1\xbb" // U+F1C7B +#define ICON_MDI_FILE_DOCUMENT_REMOVE "\xf3\xb1\xaa\x9f" // U+F1A9F +#define ICON_MDI_FILE_DOCUMENT_REMOVE_OUTLINE "\xf3\xb1\xaa\xa0" // U+F1AA0 +#define ICON_MDI_FILE_DOWNLOAD "\xf3\xb0\xa5\xa5" // U+F0965 +#define ICON_MDI_FILE_DOWNLOAD_OUTLINE "\xf3\xb0\xa5\xa6" // U+F0966 +#define ICON_MDI_FILE_EDIT "\xf3\xb1\x87\xa7" // U+F11E7 +#define ICON_MDI_FILE_EDIT_OUTLINE "\xf3\xb1\x87\xa8" // U+F11E8 +#define ICON_MDI_FILE_EXCEL "\xf3\xb0\x88\x9b" // U+F021B +#define ICON_MDI_FILE_EXCEL_BOX "\xf3\xb0\x88\x9c" // U+F021C +#define ICON_MDI_FILE_EXCEL_BOX_OUTLINE "\xf3\xb1\x80\xac" // U+F102C +#define ICON_MDI_FILE_EXCEL_OUTLINE "\xf3\xb1\x80\xad" // U+F102D +#define ICON_MDI_FILE_EXPORT "\xf3\xb0\x88\x9d" // U+F021D +#define ICON_MDI_FILE_EXPORT_OUTLINE "\xf3\xb1\x80\xae" // U+F102E +#define ICON_MDI_FILE_EYE "\xf3\xb0\xb7\x8a" // U+F0DCA +#define ICON_MDI_FILE_EYE_OUTLINE "\xf3\xb0\xb7\x8b" // U+F0DCB +#define ICON_MDI_FILE_FIND "\xf3\xb0\x88\x9e" // U+F021E +#define ICON_MDI_FILE_FIND_OUTLINE "\xf3\xb0\xae\x97" // U+F0B97 +#define ICON_MDI_FILE_GIF_BOX "\xf3\xb0\xb5\xb8" // U+F0D78 +#define ICON_MDI_FILE_HIDDEN "\xf3\xb0\x98\x93" // U+F0613 +#define ICON_MDI_FILE_IMAGE "\xf3\xb0\x88\x9f" // U+F021F +#define ICON_MDI_FILE_IMAGE_MARKER "\xf3\xb1\x9d\xb2" // U+F1772 +#define ICON_MDI_FILE_IMAGE_MARKER_OUTLINE "\xf3\xb1\x9d\xb3" // U+F1773 +#define ICON_MDI_FILE_IMAGE_MINUS "\xf3\xb1\xa4\xbb" // U+F193B +#define ICON_MDI_FILE_IMAGE_MINUS_OUTLINE "\xf3\xb1\xa4\xbc" // U+F193C +#define ICON_MDI_FILE_IMAGE_OUTLINE "\xf3\xb0\xba\xb0" // U+F0EB0 +#define ICON_MDI_FILE_IMAGE_PLUS "\xf3\xb1\xa4\xbd" // U+F193D +#define ICON_MDI_FILE_IMAGE_PLUS_OUTLINE "\xf3\xb1\xa4\xbe" // U+F193E +#define ICON_MDI_FILE_IMAGE_REMOVE "\xf3\xb1\xa4\xbf" // U+F193F +#define ICON_MDI_FILE_IMAGE_REMOVE_OUTLINE "\xf3\xb1\xa5\x80" // U+F1940 +#define ICON_MDI_FILE_IMPORT "\xf3\xb0\x88\xa0" // U+F0220 +#define ICON_MDI_FILE_IMPORT_OUTLINE "\xf3\xb1\x80\xaf" // U+F102F +#define ICON_MDI_FILE_JPG_BOX "\xf3\xb0\x88\xa5" // U+F0225 +#define ICON_MDI_FILE_KEY "\xf3\xb1\x86\x84" // U+F1184 +#define ICON_MDI_FILE_KEY_OUTLINE "\xf3\xb1\x86\x85" // U+F1185 +#define ICON_MDI_FILE_LINK "\xf3\xb1\x85\xb7" // U+F1177 +#define ICON_MDI_FILE_LINK_OUTLINE "\xf3\xb1\x85\xb8" // U+F1178 +#define ICON_MDI_FILE_LOCK "\xf3\xb0\x88\xa1" // U+F0221 +#define ICON_MDI_FILE_LOCK_OPEN "\xf3\xb1\xa7\x88" // U+F19C8 +#define ICON_MDI_FILE_LOCK_OPEN_OUTLINE "\xf3\xb1\xa7\x89" // U+F19C9 +#define ICON_MDI_FILE_LOCK_OUTLINE "\xf3\xb1\x80\xb0" // U+F1030 +#define ICON_MDI_FILE_MARKER "\xf3\xb1\x9d\xb4" // U+F1774 +#define ICON_MDI_FILE_MARKER_OUTLINE "\xf3\xb1\x9d\xb5" // U+F1775 +#define ICON_MDI_FILE_MINUS "\xf3\xb1\xaa\xa1" // U+F1AA1 +#define ICON_MDI_FILE_MINUS_OUTLINE "\xf3\xb1\xaa\xa2" // U+F1AA2 +#define ICON_MDI_FILE_MOVE "\xf3\xb0\xaa\xb9" // U+F0AB9 +#define ICON_MDI_FILE_MOVE_OUTLINE "\xf3\xb1\x80\xb1" // U+F1031 +#define ICON_MDI_FILE_MULTIPLE "\xf3\xb0\x88\xa2" // U+F0222 +#define ICON_MDI_FILE_MULTIPLE_OUTLINE "\xf3\xb1\x80\xb2" // U+F1032 +#define ICON_MDI_FILE_MUSIC "\xf3\xb0\x88\xa3" // U+F0223 +#define ICON_MDI_FILE_MUSIC_OUTLINE "\xf3\xb0\xb8\xaa" // U+F0E2A +#define ICON_MDI_FILE_OUTLINE "\xf3\xb0\x88\xa4" // U+F0224 +#define ICON_MDI_FILE_PDF_BOX "\xf3\xb0\x88\xa6" // U+F0226 +#define ICON_MDI_FILE_PERCENT "\xf3\xb0\xa0\x9e" // U+F081E +#define ICON_MDI_FILE_PERCENT_OUTLINE "\xf3\xb1\x80\xb3" // U+F1033 +#define ICON_MDI_FILE_PHONE "\xf3\xb1\x85\xb9" // U+F1179 +#define ICON_MDI_FILE_PHONE_OUTLINE "\xf3\xb1\x85\xba" // U+F117A +#define ICON_MDI_FILE_PLUS "\xf3\xb0\x9d\x92" // U+F0752 +#define ICON_MDI_FILE_PLUS_OUTLINE "\xf3\xb0\xbb\xad" // U+F0EED +#define ICON_MDI_FILE_PNG_BOX "\xf3\xb0\xb8\xad" // U+F0E2D +#define ICON_MDI_FILE_POWERPOINT "\xf3\xb0\x88\xa7" // U+F0227 +#define ICON_MDI_FILE_POWERPOINT_BOX "\xf3\xb0\x88\xa8" // U+F0228 +#define ICON_MDI_FILE_POWERPOINT_BOX_OUTLINE "\xf3\xb1\x80\xb4" // U+F1034 +#define ICON_MDI_FILE_POWERPOINT_OUTLINE "\xf3\xb1\x80\xb5" // U+F1035 +#define ICON_MDI_FILE_PRESENTATION_BOX "\xf3\xb0\x88\xa9" // U+F0229 +#define ICON_MDI_FILE_QUESTION "\xf3\xb0\xa1\xaf" // U+F086F +#define ICON_MDI_FILE_QUESTION_OUTLINE "\xf3\xb1\x80\xb6" // U+F1036 +#define ICON_MDI_FILE_REFRESH "\xf3\xb0\xa4\x98" // U+F0918 +#define ICON_MDI_FILE_REFRESH_OUTLINE "\xf3\xb0\x95\x81" // U+F0541 +#define ICON_MDI_FILE_REMOVE "\xf3\xb0\xae\x98" // U+F0B98 +#define ICON_MDI_FILE_REMOVE_OUTLINE "\xf3\xb1\x80\xb7" // U+F1037 +#define ICON_MDI_FILE_REPLACE "\xf3\xb0\xac\xb2" // U+F0B32 +#define ICON_MDI_FILE_REPLACE_OUTLINE "\xf3\xb0\xac\xb3" // U+F0B33 +#define ICON_MDI_FILE_RESTORE "\xf3\xb0\x99\xb0" // U+F0670 +#define ICON_MDI_FILE_RESTORE_OUTLINE "\xf3\xb1\x80\xb8" // U+F1038 +#define ICON_MDI_FILE_ROTATE_LEFT "\xf3\xb1\xa8\xbb" // U+F1A3B +#define ICON_MDI_FILE_ROTATE_LEFT_OUTLINE "\xf3\xb1\xa8\xbc" // U+F1A3C +#define ICON_MDI_FILE_ROTATE_RIGHT "\xf3\xb1\xa8\xbd" // U+F1A3D +#define ICON_MDI_FILE_ROTATE_RIGHT_OUTLINE "\xf3\xb1\xa8\xbe" // U+F1A3E +#define ICON_MDI_FILE_SEARCH "\xf3\xb0\xb1\xbc" // U+F0C7C +#define ICON_MDI_FILE_SEARCH_OUTLINE "\xf3\xb0\xb1\xbd" // U+F0C7D +#define ICON_MDI_FILE_SEND "\xf3\xb0\x88\xaa" // U+F022A +#define ICON_MDI_FILE_SEND_OUTLINE "\xf3\xb1\x80\xb9" // U+F1039 +#define ICON_MDI_FILE_SETTINGS "\xf3\xb1\x81\xb9" // U+F1079 +#define ICON_MDI_FILE_SETTINGS_OUTLINE "\xf3\xb1\x81\xba" // U+F107A +#define ICON_MDI_FILE_SIGN "\xf3\xb1\xa7\x83" // U+F19C3 +#define ICON_MDI_FILE_STAR "\xf3\xb1\x80\xba" // U+F103A +#define ICON_MDI_FILE_STAR_FOUR_POINTS "\xf3\xb1\xb0\xad" // U+F1C2D +#define ICON_MDI_FILE_STAR_FOUR_POINTS_OUTLINE "\xf3\xb1\xb0\xae" // U+F1C2E +#define ICON_MDI_FILE_STAR_OUTLINE "\xf3\xb1\x80\xbb" // U+F103B +#define ICON_MDI_FILE_SWAP "\xf3\xb0\xbe\xb4" // U+F0FB4 +#define ICON_MDI_FILE_SWAP_OUTLINE "\xf3\xb0\xbe\xb5" // U+F0FB5 +#define ICON_MDI_FILE_SYNC "\xf3\xb1\x88\x96" // U+F1216 +#define ICON_MDI_FILE_SYNC_OUTLINE "\xf3\xb1\x88\x97" // U+F1217 +#define ICON_MDI_FILE_TABLE "\xf3\xb0\xb1\xbe" // U+F0C7E +#define ICON_MDI_FILE_TABLE_BOX "\xf3\xb1\x83\xa1" // U+F10E1 +#define ICON_MDI_FILE_TABLE_BOX_MULTIPLE "\xf3\xb1\x83\xa2" // U+F10E2 +#define ICON_MDI_FILE_TABLE_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x83\xa3" // U+F10E3 +#define ICON_MDI_FILE_TABLE_BOX_OUTLINE "\xf3\xb1\x83\xa4" // U+F10E4 +#define ICON_MDI_FILE_TABLE_OUTLINE "\xf3\xb0\xb1\xbf" // U+F0C7F +#define ICON_MDI_FILE_TREE "\xf3\xb0\x99\x85" // U+F0645 +#define ICON_MDI_FILE_TREE_OUTLINE "\xf3\xb1\x8f\x92" // U+F13D2 +#define ICON_MDI_FILE_UNDO "\xf3\xb0\xa3\x9c" // U+F08DC +#define ICON_MDI_FILE_UNDO_OUTLINE "\xf3\xb1\x80\xbc" // U+F103C +#define ICON_MDI_FILE_UPLOAD "\xf3\xb0\xa9\x8d" // U+F0A4D +#define ICON_MDI_FILE_UPLOAD_OUTLINE "\xf3\xb0\xa9\x8e" // U+F0A4E +#define ICON_MDI_FILE_VIDEO "\xf3\xb0\x88\xab" // U+F022B +#define ICON_MDI_FILE_VIDEO_OUTLINE "\xf3\xb0\xb8\xac" // U+F0E2C +#define ICON_MDI_FILE_WORD "\xf3\xb0\x88\xac" // U+F022C +#define ICON_MDI_FILE_WORD_BOX "\xf3\xb0\x88\xad" // U+F022D +#define ICON_MDI_FILE_WORD_BOX_OUTLINE "\xf3\xb1\x80\xbd" // U+F103D +#define ICON_MDI_FILE_WORD_OUTLINE "\xf3\xb1\x80\xbe" // U+F103E +#define ICON_MDI_FILE_XML_BOX "\xf3\xb1\xad\x8b" // U+F1B4B +#define ICON_MDI_FILM "\xf3\xb0\x88\xaf" // U+F022F +#define ICON_MDI_FILMSTRIP "\xf3\xb0\x88\xb0" // U+F0230 +#define ICON_MDI_FILMSTRIP_BOX "\xf3\xb0\x8c\xb2" // U+F0332 +#define ICON_MDI_FILMSTRIP_BOX_MULTIPLE "\xf3\xb0\xb4\x98" // U+F0D18 +#define ICON_MDI_FILMSTRIP_OFF "\xf3\xb0\x88\xb1" // U+F0231 +#define ICON_MDI_FILTER "\xf3\xb0\x88\xb2" // U+F0232 +#define ICON_MDI_FILTER_CHECK "\xf3\xb1\xa3\xac" // U+F18EC +#define ICON_MDI_FILTER_CHECK_OUTLINE "\xf3\xb1\xa3\xad" // U+F18ED +#define ICON_MDI_FILTER_COG "\xf3\xb1\xaa\xa3" // U+F1AA3 +#define ICON_MDI_FILTER_COG_OUTLINE "\xf3\xb1\xaa\xa4" // U+F1AA4 +#define ICON_MDI_FILTER_MENU "\xf3\xb1\x83\xa5" // U+F10E5 +#define ICON_MDI_FILTER_MENU_OUTLINE "\xf3\xb1\x83\xa6" // U+F10E6 +#define ICON_MDI_FILTER_MINUS "\xf3\xb0\xbb\xae" // U+F0EEE +#define ICON_MDI_FILTER_MINUS_OUTLINE "\xf3\xb0\xbb\xaf" // U+F0EEF +#define ICON_MDI_FILTER_MULTIPLE "\xf3\xb1\xa8\xbf" // U+F1A3F +#define ICON_MDI_FILTER_MULTIPLE_OUTLINE "\xf3\xb1\xa9\x80" // U+F1A40 +#define ICON_MDI_FILTER_OFF "\xf3\xb1\x93\xaf" // U+F14EF +#define ICON_MDI_FILTER_OFF_OUTLINE "\xf3\xb1\x93\xb0" // U+F14F0 +#define ICON_MDI_FILTER_OUTLINE "\xf3\xb0\x88\xb3" // U+F0233 +#define ICON_MDI_FILTER_PLUS "\xf3\xb0\xbb\xb0" // U+F0EF0 +#define ICON_MDI_FILTER_PLUS_OUTLINE "\xf3\xb0\xbb\xb1" // U+F0EF1 +#define ICON_MDI_FILTER_REMOVE "\xf3\xb0\x88\xb4" // U+F0234 +#define ICON_MDI_FILTER_REMOVE_OUTLINE "\xf3\xb0\x88\xb5" // U+F0235 +#define ICON_MDI_FILTER_SETTINGS "\xf3\xb1\xaa\xa5" // U+F1AA5 +#define ICON_MDI_FILTER_SETTINGS_OUTLINE "\xf3\xb1\xaa\xa6" // U+F1AA6 +#define ICON_MDI_FILTER_VARIANT "\xf3\xb0\x88\xb6" // U+F0236 +#define ICON_MDI_FILTER_VARIANT_MINUS "\xf3\xb1\x84\x92" // U+F1112 +#define ICON_MDI_FILTER_VARIANT_PLUS "\xf3\xb1\x84\x93" // U+F1113 +#define ICON_MDI_FILTER_VARIANT_REMOVE "\xf3\xb1\x80\xbf" // U+F103F +#define ICON_MDI_FINANCE "\xf3\xb0\xa0\x9f" // U+F081F +#define ICON_MDI_FIND_REPLACE "\xf3\xb0\x9b\x94" // U+F06D4 +#define ICON_MDI_FINGERPRINT "\xf3\xb0\x88\xb7" // U+F0237 +#define ICON_MDI_FINGERPRINT_OFF "\xf3\xb0\xba\xb1" // U+F0EB1 +#define ICON_MDI_FIRE "\xf3\xb0\x88\xb8" // U+F0238 +#define ICON_MDI_FIRE_ALERT "\xf3\xb1\x97\x97" // U+F15D7 +#define ICON_MDI_FIRE_CIRCLE "\xf3\xb1\xa0\x87" // U+F1807 +#define ICON_MDI_FIRE_EXTINGUISHER "\xf3\xb0\xbb\xb2" // U+F0EF2 +#define ICON_MDI_FIRE_HYDRANT "\xf3\xb1\x84\xb7" // U+F1137 +#define ICON_MDI_FIRE_HYDRANT_ALERT "\xf3\xb1\x84\xb8" // U+F1138 +#define ICON_MDI_FIRE_HYDRANT_OFF "\xf3\xb1\x84\xb9" // U+F1139 +#define ICON_MDI_FIRE_OFF "\xf3\xb1\x9c\xa2" // U+F1722 +#define ICON_MDI_FIRE_STATION "\xf3\xb1\xb3\x83" // U+F1CC3 +#define ICON_MDI_FIRE_TRUCK "\xf3\xb0\xa2\xab" // U+F08AB +#define ICON_MDI_FIREBASE "\xf3\xb0\xa5\xa7" // U+F0967 +#define ICON_MDI_FIREFOX "\xf3\xb0\x88\xb9" // U+F0239 +#define ICON_MDI_FIREPLACE "\xf3\xb0\xb8\xae" // U+F0E2E +#define ICON_MDI_FIREPLACE_OFF "\xf3\xb0\xb8\xaf" // U+F0E2F +#define ICON_MDI_FIREWIRE "\xf3\xb0\x96\xbe" // U+F05BE +#define ICON_MDI_FIREWORK "\xf3\xb0\xb8\xb0" // U+F0E30 +#define ICON_MDI_FIREWORK_OFF "\xf3\xb1\x9c\xa3" // U+F1723 +#define ICON_MDI_FISH "\xf3\xb0\x88\xba" // U+F023A +#define ICON_MDI_FISH_OFF "\xf3\xb1\x8f\xb3" // U+F13F3 +#define ICON_MDI_FISHBOWL "\xf3\xb0\xbb\xb3" // U+F0EF3 +#define ICON_MDI_FISHBOWL_OUTLINE "\xf3\xb0\xbb\xb4" // U+F0EF4 +#define ICON_MDI_FIT_TO_PAGE "\xf3\xb0\xbb\xb5" // U+F0EF5 +#define ICON_MDI_FIT_TO_PAGE_OUTLINE "\xf3\xb0\xbb\xb6" // U+F0EF6 +#define ICON_MDI_FIT_TO_SCREEN "\xf3\xb1\xa3\xb4" // U+F18F4 +#define ICON_MDI_FIT_TO_SCREEN_OUTLINE "\xf3\xb1\xa3\xb5" // U+F18F5 +#define ICON_MDI_FLAG "\xf3\xb0\x88\xbb" // U+F023B +#define ICON_MDI_FLAG_CHECKERED "\xf3\xb0\x88\xbc" // U+F023C +#define ICON_MDI_FLAG_MINUS "\xf3\xb0\xae\x99" // U+F0B99 +#define ICON_MDI_FLAG_MINUS_OUTLINE "\xf3\xb1\x82\xb2" // U+F10B2 +#define ICON_MDI_FLAG_OFF "\xf3\xb1\xa3\xae" // U+F18EE +#define ICON_MDI_FLAG_OFF_OUTLINE "\xf3\xb1\xa3\xaf" // U+F18EF +#define ICON_MDI_FLAG_OUTLINE "\xf3\xb0\x88\xbd" // U+F023D +#define ICON_MDI_FLAG_PLUS "\xf3\xb0\xae\x9a" // U+F0B9A +#define ICON_MDI_FLAG_PLUS_OUTLINE "\xf3\xb1\x82\xb3" // U+F10B3 +#define ICON_MDI_FLAG_REMOVE "\xf3\xb0\xae\x9b" // U+F0B9B +#define ICON_MDI_FLAG_REMOVE_OUTLINE "\xf3\xb1\x82\xb4" // U+F10B4 +#define ICON_MDI_FLAG_TRIANGLE "\xf3\xb0\x88\xbf" // U+F023F +#define ICON_MDI_FLAG_VARIANT "\xf3\xb0\x89\x80" // U+F0240 +#define ICON_MDI_FLAG_VARIANT_MINUS "\xf3\xb1\xae\xb4" // U+F1BB4 +#define ICON_MDI_FLAG_VARIANT_MINUS_OUTLINE "\xf3\xb1\xae\xb5" // U+F1BB5 +#define ICON_MDI_FLAG_VARIANT_OFF "\xf3\xb1\xae\xb0" // U+F1BB0 +#define ICON_MDI_FLAG_VARIANT_OFF_OUTLINE "\xf3\xb1\xae\xb1" // U+F1BB1 +#define ICON_MDI_FLAG_VARIANT_OUTLINE "\xf3\xb0\x88\xbe" // U+F023E +#define ICON_MDI_FLAG_VARIANT_PLUS "\xf3\xb1\xae\xb2" // U+F1BB2 +#define ICON_MDI_FLAG_VARIANT_PLUS_OUTLINE "\xf3\xb1\xae\xb3" // U+F1BB3 +#define ICON_MDI_FLAG_VARIANT_REMOVE "\xf3\xb1\xae\xb6" // U+F1BB6 +#define ICON_MDI_FLAG_VARIANT_REMOVE_OUTLINE "\xf3\xb1\xae\xb7" // U+F1BB7 +#define ICON_MDI_FLARE "\xf3\xb0\xb5\xb2" // U+F0D72 +#define ICON_MDI_FLASH "\xf3\xb0\x89\x81" // U+F0241 +#define ICON_MDI_FLASH_ALERT "\xf3\xb0\xbb\xb7" // U+F0EF7 +#define ICON_MDI_FLASH_ALERT_OUTLINE "\xf3\xb0\xbb\xb8" // U+F0EF8 +#define ICON_MDI_FLASH_AUTO "\xf3\xb0\x89\x82" // U+F0242 +#define ICON_MDI_FLASH_OFF "\xf3\xb0\x89\x83" // U+F0243 +#define ICON_MDI_FLASH_OFF_OUTLINE "\xf3\xb1\xad\x85" // U+F1B45 +#define ICON_MDI_FLASH_OUTLINE "\xf3\xb0\x9b\x95" // U+F06D5 +#define ICON_MDI_FLASH_RED_EYE "\xf3\xb0\x99\xbb" // U+F067B +#define ICON_MDI_FLASH_TRIANGLE "\xf3\xb1\xac\x9d" // U+F1B1D +#define ICON_MDI_FLASH_TRIANGLE_OUTLINE "\xf3\xb1\xac\x9e" // U+F1B1E +#define ICON_MDI_FLASHLIGHT "\xf3\xb0\x89\x84" // U+F0244 +#define ICON_MDI_FLASHLIGHT_OFF "\xf3\xb0\x89\x85" // U+F0245 +#define ICON_MDI_FLASK "\xf3\xb0\x82\x93" // U+F0093 +#define ICON_MDI_FLASK_EMPTY "\xf3\xb0\x82\x94" // U+F0094 +#define ICON_MDI_FLASK_EMPTY_MINUS "\xf3\xb1\x88\xba" // U+F123A +#define ICON_MDI_FLASK_EMPTY_MINUS_OUTLINE "\xf3\xb1\x88\xbb" // U+F123B +#define ICON_MDI_FLASK_EMPTY_OFF "\xf3\xb1\x8f\xb4" // U+F13F4 +#define ICON_MDI_FLASK_EMPTY_OFF_OUTLINE "\xf3\xb1\x8f\xb5" // U+F13F5 +#define ICON_MDI_FLASK_EMPTY_OUTLINE "\xf3\xb0\x82\x95" // U+F0095 +#define ICON_MDI_FLASK_EMPTY_PLUS "\xf3\xb1\x88\xbc" // U+F123C +#define ICON_MDI_FLASK_EMPTY_PLUS_OUTLINE "\xf3\xb1\x88\xbd" // U+F123D +#define ICON_MDI_FLASK_EMPTY_REMOVE "\xf3\xb1\x88\xbe" // U+F123E +#define ICON_MDI_FLASK_EMPTY_REMOVE_OUTLINE "\xf3\xb1\x88\xbf" // U+F123F +#define ICON_MDI_FLASK_MINUS "\xf3\xb1\x89\x80" // U+F1240 +#define ICON_MDI_FLASK_MINUS_OUTLINE "\xf3\xb1\x89\x81" // U+F1241 +#define ICON_MDI_FLASK_OFF "\xf3\xb1\x8f\xb6" // U+F13F6 +#define ICON_MDI_FLASK_OFF_OUTLINE "\xf3\xb1\x8f\xb7" // U+F13F7 +#define ICON_MDI_FLASK_OUTLINE "\xf3\xb0\x82\x96" // U+F0096 +#define ICON_MDI_FLASK_PLUS "\xf3\xb1\x89\x82" // U+F1242 +#define ICON_MDI_FLASK_PLUS_OUTLINE "\xf3\xb1\x89\x83" // U+F1243 +#define ICON_MDI_FLASK_REMOVE "\xf3\xb1\x89\x84" // U+F1244 +#define ICON_MDI_FLASK_REMOVE_OUTLINE "\xf3\xb1\x89\x85" // U+F1245 +#define ICON_MDI_FLASK_ROUND_BOTTOM "\xf3\xb1\x89\x8b" // U+F124B +#define ICON_MDI_FLASK_ROUND_BOTTOM_EMPTY "\xf3\xb1\x89\x8c" // U+F124C +#define ICON_MDI_FLASK_ROUND_BOTTOM_EMPTY_OUTLINE "\xf3\xb1\x89\x8d" // U+F124D +#define ICON_MDI_FLASK_ROUND_BOTTOM_OUTLINE "\xf3\xb1\x89\x8e" // U+F124E +#define ICON_MDI_FLEUR_DE_LIS "\xf3\xb1\x8c\x83" // U+F1303 +#define ICON_MDI_FLIP_HORIZONTAL "\xf3\xb1\x83\xa7" // U+F10E7 +#define ICON_MDI_FLIP_TO_BACK "\xf3\xb0\x89\x87" // U+F0247 +#define ICON_MDI_FLIP_TO_FRONT "\xf3\xb0\x89\x88" // U+F0248 +#define ICON_MDI_FLIP_VERTICAL "\xf3\xb1\x83\xa8" // U+F10E8 +#define ICON_MDI_FLOOR_LAMP "\xf3\xb0\xa3\x9d" // U+F08DD +#define ICON_MDI_FLOOR_LAMP_DUAL "\xf3\xb1\x81\x80" // U+F1040 +#define ICON_MDI_FLOOR_LAMP_DUAL_OUTLINE "\xf3\xb1\x9f\x8e" // U+F17CE +#define ICON_MDI_FLOOR_LAMP_OUTLINE "\xf3\xb1\x9f\x88" // U+F17C8 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE "\xf3\xb1\x9d\x87" // U+F1747 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_OUTLINE "\xf3\xb1\x9f\x96" // U+F17D6 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_VARIANT "\xf3\xb1\x81\x81" // U+F1041 +#define ICON_MDI_FLOOR_LAMP_TORCHIERE_VARIANT_OUTLINE "\xf3\xb1\x9f\x8f" // U+F17CF +#define ICON_MDI_FLOOR_PLAN "\xf3\xb0\xa0\xa1" // U+F0821 +#define ICON_MDI_FLOPPY "\xf3\xb0\x89\x89" // U+F0249 +#define ICON_MDI_FLOPPY_VARIANT "\xf3\xb0\xa7\xaf" // U+F09EF +#define ICON_MDI_FLOWER "\xf3\xb0\x89\x8a" // U+F024A +#define ICON_MDI_FLOWER_OUTLINE "\xf3\xb0\xa7\xb0" // U+F09F0 +#define ICON_MDI_FLOWER_POLLEN "\xf3\xb1\xa2\x85" // U+F1885 +#define ICON_MDI_FLOWER_POLLEN_OUTLINE "\xf3\xb1\xa2\x86" // U+F1886 +#define ICON_MDI_FLOWER_POPPY "\xf3\xb0\xb4\x88" // U+F0D08 +#define ICON_MDI_FLOWER_TULIP "\xf3\xb0\xa7\xb1" // U+F09F1 +#define ICON_MDI_FLOWER_TULIP_OUTLINE "\xf3\xb0\xa7\xb2" // U+F09F2 +#define ICON_MDI_FOCUS_AUTO "\xf3\xb0\xbd\x8e" // U+F0F4E +#define ICON_MDI_FOCUS_FIELD "\xf3\xb0\xbd\x8f" // U+F0F4F +#define ICON_MDI_FOCUS_FIELD_HORIZONTAL "\xf3\xb0\xbd\x90" // U+F0F50 +#define ICON_MDI_FOCUS_FIELD_VERTICAL "\xf3\xb0\xbd\x91" // U+F0F51 +#define ICON_MDI_FOLDER "\xf3\xb0\x89\x8b" // U+F024B +#define ICON_MDI_FOLDER_ACCOUNT "\xf3\xb0\x89\x8c" // U+F024C +#define ICON_MDI_FOLDER_ACCOUNT_OUTLINE "\xf3\xb0\xae\x9c" // U+F0B9C +#define ICON_MDI_FOLDER_ALERT "\xf3\xb0\xb7\x8c" // U+F0DCC +#define ICON_MDI_FOLDER_ALERT_OUTLINE "\xf3\xb0\xb7\x8d" // U+F0DCD +#define ICON_MDI_FOLDER_ARROW_DOWN "\xf3\xb1\xa7\xa8" // U+F19E8 +#define ICON_MDI_FOLDER_ARROW_DOWN_OUTLINE "\xf3\xb1\xa7\xa9" // U+F19E9 +#define ICON_MDI_FOLDER_ARROW_LEFT "\xf3\xb1\xa7\xaa" // U+F19EA +#define ICON_MDI_FOLDER_ARROW_LEFT_OUTLINE "\xf3\xb1\xa7\xab" // U+F19EB +#define ICON_MDI_FOLDER_ARROW_LEFT_RIGHT "\xf3\xb1\xa7\xac" // U+F19EC +#define ICON_MDI_FOLDER_ARROW_LEFT_RIGHT_OUTLINE "\xf3\xb1\xa7\xad" // U+F19ED +#define ICON_MDI_FOLDER_ARROW_RIGHT "\xf3\xb1\xa7\xae" // U+F19EE +#define ICON_MDI_FOLDER_ARROW_RIGHT_OUTLINE "\xf3\xb1\xa7\xaf" // U+F19EF +#define ICON_MDI_FOLDER_ARROW_UP "\xf3\xb1\xa7\xb0" // U+F19F0 +#define ICON_MDI_FOLDER_ARROW_UP_DOWN "\xf3\xb1\xa7\xb1" // U+F19F1 +#define ICON_MDI_FOLDER_ARROW_UP_DOWN_OUTLINE "\xf3\xb1\xa7\xb2" // U+F19F2 +#define ICON_MDI_FOLDER_ARROW_UP_OUTLINE "\xf3\xb1\xa7\xb3" // U+F19F3 +#define ICON_MDI_FOLDER_CANCEL "\xf3\xb1\xa7\xb4" // U+F19F4 +#define ICON_MDI_FOLDER_CANCEL_OUTLINE "\xf3\xb1\xa7\xb5" // U+F19F5 +#define ICON_MDI_FOLDER_CHECK "\xf3\xb1\xa5\xbe" // U+F197E +#define ICON_MDI_FOLDER_CHECK_OUTLINE "\xf3\xb1\xa5\xbf" // U+F197F +#define ICON_MDI_FOLDER_CLOCK "\xf3\xb0\xaa\xba" // U+F0ABA +#define ICON_MDI_FOLDER_CLOCK_OUTLINE "\xf3\xb0\xaa\xbb" // U+F0ABB +#define ICON_MDI_FOLDER_COG "\xf3\xb1\x81\xbf" // U+F107F +#define ICON_MDI_FOLDER_COG_OUTLINE "\xf3\xb1\x82\x80" // U+F1080 +#define ICON_MDI_FOLDER_DOWNLOAD "\xf3\xb0\x89\x8d" // U+F024D +#define ICON_MDI_FOLDER_DOWNLOAD_OUTLINE "\xf3\xb1\x83\xa9" // U+F10E9 +#define ICON_MDI_FOLDER_EDIT "\xf3\xb0\xa3\x9e" // U+F08DE +#define ICON_MDI_FOLDER_EDIT_OUTLINE "\xf3\xb0\xb7\x8e" // U+F0DCE +#define ICON_MDI_FOLDER_EYE "\xf3\xb1\x9e\x8a" // U+F178A +#define ICON_MDI_FOLDER_EYE_OUTLINE "\xf3\xb1\x9e\x8b" // U+F178B +#define ICON_MDI_FOLDER_FILE "\xf3\xb1\xa7\xb6" // U+F19F6 +#define ICON_MDI_FOLDER_FILE_OUTLINE "\xf3\xb1\xa7\xb7" // U+F19F7 +#define ICON_MDI_FOLDER_GOOGLE_DRIVE "\xf3\xb0\x89\x8e" // U+F024E +#define ICON_MDI_FOLDER_HEART "\xf3\xb1\x83\xaa" // U+F10EA +#define ICON_MDI_FOLDER_HEART_OUTLINE "\xf3\xb1\x83\xab" // U+F10EB +#define ICON_MDI_FOLDER_HIDDEN "\xf3\xb1\x9e\x9e" // U+F179E +#define ICON_MDI_FOLDER_HOME "\xf3\xb1\x82\xb5" // U+F10B5 +#define ICON_MDI_FOLDER_HOME_OUTLINE "\xf3\xb1\x82\xb6" // U+F10B6 +#define ICON_MDI_FOLDER_IMAGE "\xf3\xb0\x89\x8f" // U+F024F +#define ICON_MDI_FOLDER_INFORMATION "\xf3\xb1\x82\xb7" // U+F10B7 +#define ICON_MDI_FOLDER_INFORMATION_OUTLINE "\xf3\xb1\x82\xb8" // U+F10B8 +#define ICON_MDI_FOLDER_KEY "\xf3\xb0\xa2\xac" // U+F08AC +#define ICON_MDI_FOLDER_KEY_NETWORK "\xf3\xb0\xa2\xad" // U+F08AD +#define ICON_MDI_FOLDER_KEY_NETWORK_OUTLINE "\xf3\xb0\xb2\x80" // U+F0C80 +#define ICON_MDI_FOLDER_KEY_OUTLINE "\xf3\xb1\x83\xac" // U+F10EC +#define ICON_MDI_FOLDER_LOCK "\xf3\xb0\x89\x90" // U+F0250 +#define ICON_MDI_FOLDER_LOCK_OPEN "\xf3\xb0\x89\x91" // U+F0251 +#define ICON_MDI_FOLDER_LOCK_OPEN_OUTLINE "\xf3\xb1\xaa\xa7" // U+F1AA7 +#define ICON_MDI_FOLDER_LOCK_OUTLINE "\xf3\xb1\xaa\xa8" // U+F1AA8 +#define ICON_MDI_FOLDER_MARKER "\xf3\xb1\x89\xad" // U+F126D +#define ICON_MDI_FOLDER_MARKER_OUTLINE "\xf3\xb1\x89\xae" // U+F126E +#define ICON_MDI_FOLDER_MINUS "\xf3\xb1\xad\x89" // U+F1B49 +#define ICON_MDI_FOLDER_MINUS_OUTLINE "\xf3\xb1\xad\x8a" // U+F1B4A +#define ICON_MDI_FOLDER_MOVE "\xf3\xb0\x89\x92" // U+F0252 +#define ICON_MDI_FOLDER_MOVE_OUTLINE "\xf3\xb1\x89\x86" // U+F1246 +#define ICON_MDI_FOLDER_MULTIPLE "\xf3\xb0\x89\x93" // U+F0253 +#define ICON_MDI_FOLDER_MULTIPLE_IMAGE "\xf3\xb0\x89\x94" // U+F0254 +#define ICON_MDI_FOLDER_MULTIPLE_OUTLINE "\xf3\xb0\x89\x95" // U+F0255 +#define ICON_MDI_FOLDER_MULTIPLE_PLUS "\xf3\xb1\x91\xbe" // U+F147E +#define ICON_MDI_FOLDER_MULTIPLE_PLUS_OUTLINE "\xf3\xb1\x91\xbf" // U+F147F +#define ICON_MDI_FOLDER_MUSIC "\xf3\xb1\x8d\x99" // U+F1359 +#define ICON_MDI_FOLDER_MUSIC_OUTLINE "\xf3\xb1\x8d\x9a" // U+F135A +#define ICON_MDI_FOLDER_NETWORK "\xf3\xb0\xa1\xb0" // U+F0870 +#define ICON_MDI_FOLDER_NETWORK_OUTLINE "\xf3\xb0\xb2\x81" // U+F0C81 +#define ICON_MDI_FOLDER_OFF "\xf3\xb1\xa7\xb8" // U+F19F8 +#define ICON_MDI_FOLDER_OFF_OUTLINE "\xf3\xb1\xa7\xb9" // U+F19F9 +#define ICON_MDI_FOLDER_OPEN "\xf3\xb0\x9d\xb0" // U+F0770 +#define ICON_MDI_FOLDER_OPEN_OUTLINE "\xf3\xb0\xb7\x8f" // U+F0DCF +#define ICON_MDI_FOLDER_OUTLINE "\xf3\xb0\x89\x96" // U+F0256 +#define ICON_MDI_FOLDER_PLAY "\xf3\xb1\xa7\xba" // U+F19FA +#define ICON_MDI_FOLDER_PLAY_OUTLINE "\xf3\xb1\xa7\xbb" // U+F19FB +#define ICON_MDI_FOLDER_PLUS "\xf3\xb0\x89\x97" // U+F0257 +#define ICON_MDI_FOLDER_PLUS_OUTLINE "\xf3\xb0\xae\x9d" // U+F0B9D +#define ICON_MDI_FOLDER_POUND "\xf3\xb0\xb4\x89" // U+F0D09 +#define ICON_MDI_FOLDER_POUND_OUTLINE "\xf3\xb0\xb4\x8a" // U+F0D0A +#define ICON_MDI_FOLDER_QUESTION "\xf3\xb1\xa7\x8a" // U+F19CA +#define ICON_MDI_FOLDER_QUESTION_OUTLINE "\xf3\xb1\xa7\x8b" // U+F19CB +#define ICON_MDI_FOLDER_REFRESH "\xf3\xb0\x9d\x89" // U+F0749 +#define ICON_MDI_FOLDER_REFRESH_OUTLINE "\xf3\xb0\x95\x82" // U+F0542 +#define ICON_MDI_FOLDER_REMOVE "\xf3\xb0\x89\x98" // U+F0258 +#define ICON_MDI_FOLDER_REMOVE_OUTLINE "\xf3\xb0\xae\x9e" // U+F0B9E +#define ICON_MDI_FOLDER_SEARCH "\xf3\xb0\xa5\xa8" // U+F0968 +#define ICON_MDI_FOLDER_SEARCH_OUTLINE "\xf3\xb0\xa5\xa9" // U+F0969 +#define ICON_MDI_FOLDER_SETTINGS "\xf3\xb1\x81\xbd" // U+F107D +#define ICON_MDI_FOLDER_SETTINGS_OUTLINE "\xf3\xb1\x81\xbe" // U+F107E +#define ICON_MDI_FOLDER_STAR "\xf3\xb0\x9a\x9d" // U+F069D +#define ICON_MDI_FOLDER_STAR_MULTIPLE "\xf3\xb1\x8f\x93" // U+F13D3 +#define ICON_MDI_FOLDER_STAR_MULTIPLE_OUTLINE "\xf3\xb1\x8f\x94" // U+F13D4 +#define ICON_MDI_FOLDER_STAR_OUTLINE "\xf3\xb0\xae\x9f" // U+F0B9F +#define ICON_MDI_FOLDER_SWAP "\xf3\xb0\xbe\xb6" // U+F0FB6 +#define ICON_MDI_FOLDER_SWAP_OUTLINE "\xf3\xb0\xbe\xb7" // U+F0FB7 +#define ICON_MDI_FOLDER_SYNC "\xf3\xb0\xb4\x8b" // U+F0D0B +#define ICON_MDI_FOLDER_SYNC_OUTLINE "\xf3\xb0\xb4\x8c" // U+F0D0C +#define ICON_MDI_FOLDER_TABLE "\xf3\xb1\x8b\xa3" // U+F12E3 +#define ICON_MDI_FOLDER_TABLE_OUTLINE "\xf3\xb1\x8b\xa4" // U+F12E4 +#define ICON_MDI_FOLDER_TEXT "\xf3\xb0\xb2\x82" // U+F0C82 +#define ICON_MDI_FOLDER_TEXT_OUTLINE "\xf3\xb0\xb2\x83" // U+F0C83 +#define ICON_MDI_FOLDER_UPLOAD "\xf3\xb0\x89\x99" // U+F0259 +#define ICON_MDI_FOLDER_UPLOAD_OUTLINE "\xf3\xb1\x83\xad" // U+F10ED +#define ICON_MDI_FOLDER_WRENCH "\xf3\xb1\xa7\xbc" // U+F19FC +#define ICON_MDI_FOLDER_WRENCH_OUTLINE "\xf3\xb1\xa7\xbd" // U+F19FD +#define ICON_MDI_FOLDER_ZIP "\xf3\xb0\x9b\xab" // U+F06EB +#define ICON_MDI_FOLDER_ZIP_OUTLINE "\xf3\xb0\x9e\xb9" // U+F07B9 +#define ICON_MDI_FONT_AWESOME "\xf3\xb0\x80\xba" // U+F003A +#define ICON_MDI_FOOD "\xf3\xb0\x89\x9a" // U+F025A +#define ICON_MDI_FOOD_APPLE "\xf3\xb0\x89\x9b" // U+F025B +#define ICON_MDI_FOOD_APPLE_OUTLINE "\xf3\xb0\xb2\x84" // U+F0C84 +#define ICON_MDI_FOOD_CROISSANT "\xf3\xb0\x9f\x88" // U+F07C8 +#define ICON_MDI_FOOD_DRUMSTICK "\xf3\xb1\x90\x9f" // U+F141F +#define ICON_MDI_FOOD_DRUMSTICK_OFF "\xf3\xb1\x91\xa8" // U+F1468 +#define ICON_MDI_FOOD_DRUMSTICK_OFF_OUTLINE "\xf3\xb1\x91\xa9" // U+F1469 +#define ICON_MDI_FOOD_DRUMSTICK_OUTLINE "\xf3\xb1\x90\xa0" // U+F1420 +#define ICON_MDI_FOOD_FORK_DRINK "\xf3\xb0\x97\xb2" // U+F05F2 +#define ICON_MDI_FOOD_HALAL "\xf3\xb1\x95\xb2" // U+F1572 +#define ICON_MDI_FOOD_HOT_DOG "\xf3\xb1\xa1\x8b" // U+F184B +#define ICON_MDI_FOOD_KOSHER "\xf3\xb1\x95\xb3" // U+F1573 +#define ICON_MDI_FOOD_OFF "\xf3\xb0\x97\xb3" // U+F05F3 +#define ICON_MDI_FOOD_OFF_OUTLINE "\xf3\xb1\xa4\x95" // U+F1915 +#define ICON_MDI_FOOD_OUTLINE "\xf3\xb1\xa4\x96" // U+F1916 +#define ICON_MDI_FOOD_STEAK "\xf3\xb1\x91\xaa" // U+F146A +#define ICON_MDI_FOOD_STEAK_OFF "\xf3\xb1\x91\xab" // U+F146B +#define ICON_MDI_FOOD_TAKEOUT_BOX "\xf3\xb1\xa0\xb6" // U+F1836 +#define ICON_MDI_FOOD_TAKEOUT_BOX_OUTLINE "\xf3\xb1\xa0\xb7" // U+F1837 +#define ICON_MDI_FOOD_TURKEY "\xf3\xb1\x9c\x9c" // U+F171C +#define ICON_MDI_FOOD_VARIANT "\xf3\xb0\x89\x9c" // U+F025C +#define ICON_MDI_FOOD_VARIANT_OFF "\xf3\xb1\x8f\xa5" // U+F13E5 +#define ICON_MDI_FOOT_PRINT "\xf3\xb0\xbd\x92" // U+F0F52 +#define ICON_MDI_FOOTBALL "\xf3\xb0\x89\x9d" // U+F025D +#define ICON_MDI_FOOTBALL_AUSTRALIAN "\xf3\xb0\x89\x9e" // U+F025E +#define ICON_MDI_FOOTBALL_HELMET "\xf3\xb0\x89\x9f" // U+F025F +#define ICON_MDI_FOREST "\xf3\xb1\xa2\x97" // U+F1897 +#define ICON_MDI_FOREST_OUTLINE "\xf3\xb1\xb1\xa3" // U+F1C63 +#define ICON_MDI_FORKLIFT "\xf3\xb0\x9f\x89" // U+F07C9 +#define ICON_MDI_FORM_DROPDOWN "\xf3\xb1\x90\x80" // U+F1400 +#define ICON_MDI_FORM_SELECT "\xf3\xb1\x90\x81" // U+F1401 +#define ICON_MDI_FORM_TEXTAREA "\xf3\xb1\x82\x95" // U+F1095 +#define ICON_MDI_FORM_TEXTBOX "\xf3\xb0\x98\x8e" // U+F060E +#define ICON_MDI_FORM_TEXTBOX_LOCK "\xf3\xb1\x8d\x9d" // U+F135D +#define ICON_MDI_FORM_TEXTBOX_PASSWORD "\xf3\xb0\x9f\xb5" // U+F07F5 +#define ICON_MDI_FORMAT_ALIGN_BOTTOM "\xf3\xb0\x9d\x93" // U+F0753 +#define ICON_MDI_FORMAT_ALIGN_CENTER "\xf3\xb0\x89\xa0" // U+F0260 +#define ICON_MDI_FORMAT_ALIGN_JUSTIFY "\xf3\xb0\x89\xa1" // U+F0261 +#define ICON_MDI_FORMAT_ALIGN_LEFT "\xf3\xb0\x89\xa2" // U+F0262 +#define ICON_MDI_FORMAT_ALIGN_MIDDLE "\xf3\xb0\x9d\x94" // U+F0754 +#define ICON_MDI_FORMAT_ALIGN_RIGHT "\xf3\xb0\x89\xa3" // U+F0263 +#define ICON_MDI_FORMAT_ALIGN_TOP "\xf3\xb0\x9d\x95" // U+F0755 +#define ICON_MDI_FORMAT_ANNOTATION_MINUS "\xf3\xb0\xaa\xbc" // U+F0ABC +#define ICON_MDI_FORMAT_ANNOTATION_PLUS "\xf3\xb0\x99\x86" // U+F0646 +#define ICON_MDI_FORMAT_BOLD "\xf3\xb0\x89\xa4" // U+F0264 +#define ICON_MDI_FORMAT_CLEAR "\xf3\xb0\x89\xa5" // U+F0265 +#define ICON_MDI_FORMAT_COLOR_FILL "\xf3\xb0\x89\xa6" // U+F0266 +#define ICON_MDI_FORMAT_COLOR_HIGHLIGHT "\xf3\xb0\xb8\xb1" // U+F0E31 +#define ICON_MDI_FORMAT_COLOR_MARKER_CANCEL "\xf3\xb1\x8c\x93" // U+F1313 +#define ICON_MDI_FORMAT_COLOR_TEXT "\xf3\xb0\x9a\x9e" // U+F069E +#define ICON_MDI_FORMAT_COLUMNS "\xf3\xb0\xa3\x9f" // U+F08DF +#define ICON_MDI_FORMAT_FLOAT_CENTER "\xf3\xb0\x89\xa7" // U+F0267 +#define ICON_MDI_FORMAT_FLOAT_LEFT "\xf3\xb0\x89\xa8" // U+F0268 +#define ICON_MDI_FORMAT_FLOAT_NONE "\xf3\xb0\x89\xa9" // U+F0269 +#define ICON_MDI_FORMAT_FLOAT_RIGHT "\xf3\xb0\x89\xaa" // U+F026A +#define ICON_MDI_FORMAT_FONT "\xf3\xb0\x9b\x96" // U+F06D6 +#define ICON_MDI_FORMAT_FONT_SIZE_DECREASE "\xf3\xb0\xa7\xb3" // U+F09F3 +#define ICON_MDI_FORMAT_FONT_SIZE_INCREASE "\xf3\xb0\xa7\xb4" // U+F09F4 +#define ICON_MDI_FORMAT_HEADER_1 "\xf3\xb0\x89\xab" // U+F026B +#define ICON_MDI_FORMAT_HEADER_2 "\xf3\xb0\x89\xac" // U+F026C +#define ICON_MDI_FORMAT_HEADER_3 "\xf3\xb0\x89\xad" // U+F026D +#define ICON_MDI_FORMAT_HEADER_4 "\xf3\xb0\x89\xae" // U+F026E +#define ICON_MDI_FORMAT_HEADER_5 "\xf3\xb0\x89\xaf" // U+F026F +#define ICON_MDI_FORMAT_HEADER_6 "\xf3\xb0\x89\xb0" // U+F0270 +#define ICON_MDI_FORMAT_HEADER_DECREASE "\xf3\xb0\x89\xb1" // U+F0271 +#define ICON_MDI_FORMAT_HEADER_EQUAL "\xf3\xb0\x89\xb2" // U+F0272 +#define ICON_MDI_FORMAT_HEADER_INCREASE "\xf3\xb0\x89\xb3" // U+F0273 +#define ICON_MDI_FORMAT_HEADER_POUND "\xf3\xb0\x89\xb4" // U+F0274 +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_CENTER "\xf3\xb0\x98\x9e" // U+F061E +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_LEFT "\xf3\xb0\x98\x9f" // U+F061F +#define ICON_MDI_FORMAT_HORIZONTAL_ALIGN_RIGHT "\xf3\xb0\x98\xa0" // U+F0620 +#define ICON_MDI_FORMAT_INDENT_DECREASE "\xf3\xb0\x89\xb5" // U+F0275 +#define ICON_MDI_FORMAT_INDENT_INCREASE "\xf3\xb0\x89\xb6" // U+F0276 +#define ICON_MDI_FORMAT_ITALIC "\xf3\xb0\x89\xb7" // U+F0277 +#define ICON_MDI_FORMAT_LETTER_CASE "\xf3\xb0\xac\xb4" // U+F0B34 +#define ICON_MDI_FORMAT_LETTER_CASE_LOWER "\xf3\xb0\xac\xb5" // U+F0B35 +#define ICON_MDI_FORMAT_LETTER_CASE_UPPER "\xf3\xb0\xac\xb6" // U+F0B36 +#define ICON_MDI_FORMAT_LETTER_ENDS_WITH "\xf3\xb0\xbe\xb8" // U+F0FB8 +#define ICON_MDI_FORMAT_LETTER_MATCHES "\xf3\xb0\xbe\xb9" // U+F0FB9 +#define ICON_MDI_FORMAT_LETTER_SPACING "\xf3\xb1\xa5\x96" // U+F1956 +#define ICON_MDI_FORMAT_LETTER_SPACING_VARIANT "\xf3\xb1\xab\xbb" // U+F1AFB +#define ICON_MDI_FORMAT_LETTER_STARTS_WITH "\xf3\xb0\xbe\xba" // U+F0FBA +#define ICON_MDI_FORMAT_LINE_HEIGHT "\xf3\xb1\xab\xbc" // U+F1AFC +#define ICON_MDI_FORMAT_LINE_SPACING "\xf3\xb0\x89\xb8" // U+F0278 +#define ICON_MDI_FORMAT_LINE_STYLE "\xf3\xb0\x97\x88" // U+F05C8 +#define ICON_MDI_FORMAT_LINE_WEIGHT "\xf3\xb0\x97\x89" // U+F05C9 +#define ICON_MDI_FORMAT_LIST_BULLETED "\xf3\xb0\x89\xb9" // U+F0279 +#define ICON_MDI_FORMAT_LIST_BULLETED_SQUARE "\xf3\xb0\xb7\x90" // U+F0DD0 +#define ICON_MDI_FORMAT_LIST_BULLETED_TRIANGLE "\xf3\xb0\xba\xb2" // U+F0EB2 +#define ICON_MDI_FORMAT_LIST_BULLETED_TYPE "\xf3\xb0\x89\xba" // U+F027A +#define ICON_MDI_FORMAT_LIST_CHECKBOX "\xf3\xb0\xa5\xaa" // U+F096A +#define ICON_MDI_FORMAT_LIST_CHECKS "\xf3\xb0\x9d\x96" // U+F0756 +#define ICON_MDI_FORMAT_LIST_GROUP "\xf3\xb1\xa1\xa0" // U+F1860 +#define ICON_MDI_FORMAT_LIST_GROUP_PLUS "\xf3\xb1\xad\x96" // U+F1B56 +#define ICON_MDI_FORMAT_LIST_NUMBERED "\xf3\xb0\x89\xbb" // U+F027B +#define ICON_MDI_FORMAT_LIST_NUMBERED_RTL "\xf3\xb0\xb4\x8d" // U+F0D0D +#define ICON_MDI_FORMAT_LIST_TEXT "\xf3\xb1\x89\xaf" // U+F126F +#define ICON_MDI_FORMAT_OVERLINE "\xf3\xb0\xba\xb3" // U+F0EB3 +#define ICON_MDI_FORMAT_PAGE_BREAK "\xf3\xb0\x9b\x97" // U+F06D7 +#define ICON_MDI_FORMAT_PAGE_SPLIT "\xf3\xb1\xa4\x97" // U+F1917 +#define ICON_MDI_FORMAT_PAINT "\xf3\xb0\x89\xbc" // U+F027C +#define ICON_MDI_FORMAT_PARAGRAPH "\xf3\xb0\x89\xbd" // U+F027D +#define ICON_MDI_FORMAT_PARAGRAPH_SPACING "\xf3\xb1\xab\xbd" // U+F1AFD +#define ICON_MDI_FORMAT_PILCROW "\xf3\xb0\x9b\x98" // U+F06D8 +#define ICON_MDI_FORMAT_PILCROW_ARROW_LEFT "\xf3\xb0\x8a\x86" // U+F0286 +#define ICON_MDI_FORMAT_PILCROW_ARROW_RIGHT "\xf3\xb0\x8a\x85" // U+F0285 +#define ICON_MDI_FORMAT_QUOTE_CLOSE "\xf3\xb0\x89\xbe" // U+F027E +#define ICON_MDI_FORMAT_QUOTE_CLOSE_OUTLINE "\xf3\xb1\x86\xa8" // U+F11A8 +#define ICON_MDI_FORMAT_QUOTE_OPEN "\xf3\xb0\x9d\x97" // U+F0757 +#define ICON_MDI_FORMAT_QUOTE_OPEN_OUTLINE "\xf3\xb1\x86\xa7" // U+F11A7 +#define ICON_MDI_FORMAT_ROTATE_90 "\xf3\xb0\x9a\xaa" // U+F06AA +#define ICON_MDI_FORMAT_SECTION "\xf3\xb0\x9a\x9f" // U+F069F +#define ICON_MDI_FORMAT_SIZE "\xf3\xb0\x89\xbf" // U+F027F +#define ICON_MDI_FORMAT_STRIKETHROUGH "\xf3\xb0\x8a\x80" // U+F0280 +#define ICON_MDI_FORMAT_STRIKETHROUGH_VARIANT "\xf3\xb0\x8a\x81" // U+F0281 +#define ICON_MDI_FORMAT_SUBSCRIPT "\xf3\xb0\x8a\x82" // U+F0282 +#define ICON_MDI_FORMAT_SUPERSCRIPT "\xf3\xb0\x8a\x83" // U+F0283 +#define ICON_MDI_FORMAT_TEXT "\xf3\xb0\x8a\x84" // U+F0284 +#define ICON_MDI_FORMAT_TEXT_ROTATION_ANGLE_DOWN "\xf3\xb0\xbe\xbb" // U+F0FBB +#define ICON_MDI_FORMAT_TEXT_ROTATION_ANGLE_UP "\xf3\xb0\xbe\xbc" // U+F0FBC +#define ICON_MDI_FORMAT_TEXT_ROTATION_DOWN "\xf3\xb0\xb5\xb3" // U+F0D73 +#define ICON_MDI_FORMAT_TEXT_ROTATION_DOWN_VERTICAL "\xf3\xb0\xbe\xbd" // U+F0FBD +#define ICON_MDI_FORMAT_TEXT_ROTATION_NONE "\xf3\xb0\xb5\xb4" // U+F0D74 +#define ICON_MDI_FORMAT_TEXT_ROTATION_UP "\xf3\xb0\xbe\xbe" // U+F0FBE +#define ICON_MDI_FORMAT_TEXT_ROTATION_VERTICAL "\xf3\xb0\xbe\xbf" // U+F0FBF +#define ICON_MDI_FORMAT_TEXT_VARIANT "\xf3\xb0\xb8\xb2" // U+F0E32 +#define ICON_MDI_FORMAT_TEXT_VARIANT_OUTLINE "\xf3\xb1\x94\x8f" // U+F150F +#define ICON_MDI_FORMAT_TEXT_WRAPPING_CLIP "\xf3\xb0\xb4\x8e" // U+F0D0E +#define ICON_MDI_FORMAT_TEXT_WRAPPING_OVERFLOW "\xf3\xb0\xb4\x8f" // U+F0D0F +#define ICON_MDI_FORMAT_TEXT_WRAPPING_WRAP "\xf3\xb0\xb4\x90" // U+F0D10 +#define ICON_MDI_FORMAT_TEXTBOX "\xf3\xb0\xb4\x91" // U+F0D11 +#define ICON_MDI_FORMAT_TITLE "\xf3\xb0\x97\xb4" // U+F05F4 +#define ICON_MDI_FORMAT_UNDERLINE "\xf3\xb0\x8a\x87" // U+F0287 +#define ICON_MDI_FORMAT_UNDERLINE_WAVY "\xf3\xb1\xa3\xa9" // U+F18E9 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_BOTTOM "\xf3\xb0\x98\xa1" // U+F0621 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_CENTER "\xf3\xb0\x98\xa2" // U+F0622 +#define ICON_MDI_FORMAT_VERTICAL_ALIGN_TOP "\xf3\xb0\x98\xa3" // U+F0623 +#define ICON_MDI_FORMAT_WRAP_INLINE "\xf3\xb0\x8a\x88" // U+F0288 +#define ICON_MDI_FORMAT_WRAP_SQUARE "\xf3\xb0\x8a\x89" // U+F0289 +#define ICON_MDI_FORMAT_WRAP_TIGHT "\xf3\xb0\x8a\x8a" // U+F028A +#define ICON_MDI_FORMAT_WRAP_TOP_BOTTOM "\xf3\xb0\x8a\x8b" // U+F028B +#define ICON_MDI_FORUM "\xf3\xb0\x8a\x8c" // U+F028C +#define ICON_MDI_FORUM_MINUS "\xf3\xb1\xaa\xa9" // U+F1AA9 +#define ICON_MDI_FORUM_MINUS_OUTLINE "\xf3\xb1\xaa\xaa" // U+F1AAA +#define ICON_MDI_FORUM_OUTLINE "\xf3\xb0\xa0\xa2" // U+F0822 +#define ICON_MDI_FORUM_PLUS "\xf3\xb1\xaa\xab" // U+F1AAB +#define ICON_MDI_FORUM_PLUS_OUTLINE "\xf3\xb1\xaa\xac" // U+F1AAC +#define ICON_MDI_FORUM_REMOVE "\xf3\xb1\xaa\xad" // U+F1AAD +#define ICON_MDI_FORUM_REMOVE_OUTLINE "\xf3\xb1\xaa\xae" // U+F1AAE +#define ICON_MDI_FORWARD "\xf3\xb0\x8a\x8d" // U+F028D +#define ICON_MDI_FORWARDBURGER "\xf3\xb0\xb5\xb5" // U+F0D75 +#define ICON_MDI_FOUNTAIN "\xf3\xb0\xa5\xab" // U+F096B +#define ICON_MDI_FOUNTAIN_PEN "\xf3\xb0\xb4\x92" // U+F0D12 +#define ICON_MDI_FOUNTAIN_PEN_TIP "\xf3\xb0\xb4\x93" // U+F0D13 +#define ICON_MDI_FRACTION_ONE_HALF "\xf3\xb1\xa6\x92" // U+F1992 +#define ICON_MDI_FREEBSD "\xf3\xb0\xa3\xa0" // U+F08E0 +#define ICON_MDI_FRENCH_FRIES "\xf3\xb1\xa5\x97" // U+F1957 +#define ICON_MDI_FREQUENTLY_ASKED_QUESTIONS "\xf3\xb0\xba\xb4" // U+F0EB4 +#define ICON_MDI_FRIDGE "\xf3\xb0\x8a\x90" // U+F0290 +#define ICON_MDI_FRIDGE_ALERT "\xf3\xb1\x86\xb1" // U+F11B1 +#define ICON_MDI_FRIDGE_ALERT_OUTLINE "\xf3\xb1\x86\xb2" // U+F11B2 +#define ICON_MDI_FRIDGE_BOTTOM "\xf3\xb0\x8a\x92" // U+F0292 +#define ICON_MDI_FRIDGE_INDUSTRIAL "\xf3\xb1\x97\xae" // U+F15EE +#define ICON_MDI_FRIDGE_INDUSTRIAL_ALERT "\xf3\xb1\x97\xaf" // U+F15EF +#define ICON_MDI_FRIDGE_INDUSTRIAL_ALERT_OUTLINE "\xf3\xb1\x97\xb0" // U+F15F0 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OFF "\xf3\xb1\x97\xb1" // U+F15F1 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OFF_OUTLINE "\xf3\xb1\x97\xb2" // U+F15F2 +#define ICON_MDI_FRIDGE_INDUSTRIAL_OUTLINE "\xf3\xb1\x97\xb3" // U+F15F3 +#define ICON_MDI_FRIDGE_OFF "\xf3\xb1\x86\xaf" // U+F11AF +#define ICON_MDI_FRIDGE_OFF_OUTLINE "\xf3\xb1\x86\xb0" // U+F11B0 +#define ICON_MDI_FRIDGE_OUTLINE "\xf3\xb0\x8a\x8f" // U+F028F +#define ICON_MDI_FRIDGE_TOP "\xf3\xb0\x8a\x91" // U+F0291 +#define ICON_MDI_FRIDGE_VARIANT "\xf3\xb1\x97\xb4" // U+F15F4 +#define ICON_MDI_FRIDGE_VARIANT_ALERT "\xf3\xb1\x97\xb5" // U+F15F5 +#define ICON_MDI_FRIDGE_VARIANT_ALERT_OUTLINE "\xf3\xb1\x97\xb6" // U+F15F6 +#define ICON_MDI_FRIDGE_VARIANT_OFF "\xf3\xb1\x97\xb7" // U+F15F7 +#define ICON_MDI_FRIDGE_VARIANT_OFF_OUTLINE "\xf3\xb1\x97\xb8" // U+F15F8 +#define ICON_MDI_FRIDGE_VARIANT_OUTLINE "\xf3\xb1\x97\xb9" // U+F15F9 +#define ICON_MDI_FRUIT_CHERRIES "\xf3\xb1\x81\x82" // U+F1042 +#define ICON_MDI_FRUIT_CHERRIES_OFF "\xf3\xb1\x8f\xb8" // U+F13F8 +#define ICON_MDI_FRUIT_CITRUS "\xf3\xb1\x81\x83" // U+F1043 +#define ICON_MDI_FRUIT_CITRUS_OFF "\xf3\xb1\x8f\xb9" // U+F13F9 +#define ICON_MDI_FRUIT_GRAPES "\xf3\xb1\x81\x84" // U+F1044 +#define ICON_MDI_FRUIT_GRAPES_OUTLINE "\xf3\xb1\x81\x85" // U+F1045 +#define ICON_MDI_FRUIT_PEAR "\xf3\xb1\xa8\x8e" // U+F1A0E +#define ICON_MDI_FRUIT_PINEAPPLE "\xf3\xb1\x81\x86" // U+F1046 +#define ICON_MDI_FRUIT_WATERMELON "\xf3\xb1\x81\x87" // U+F1047 +#define ICON_MDI_FUEL "\xf3\xb0\x9f\x8a" // U+F07CA +#define ICON_MDI_FUEL_CELL "\xf3\xb1\xa2\xb5" // U+F18B5 +#define ICON_MDI_FULLSCREEN "\xf3\xb0\x8a\x93" // U+F0293 +#define ICON_MDI_FULLSCREEN_EXIT "\xf3\xb0\x8a\x94" // U+F0294 +#define ICON_MDI_FUNCTION "\xf3\xb0\x8a\x95" // U+F0295 +#define ICON_MDI_FUNCTION_VARIANT "\xf3\xb0\xa1\xb1" // U+F0871 +#define ICON_MDI_FURIGANA_HORIZONTAL "\xf3\xb1\x82\x81" // U+F1081 +#define ICON_MDI_FURIGANA_VERTICAL "\xf3\xb1\x82\x82" // U+F1082 +#define ICON_MDI_FUSE "\xf3\xb0\xb2\x85" // U+F0C85 +#define ICON_MDI_FUSE_ALERT "\xf3\xb1\x90\xad" // U+F142D +#define ICON_MDI_FUSE_BLADE "\xf3\xb0\xb2\x86" // U+F0C86 +#define ICON_MDI_FUSE_OFF "\xf3\xb1\x90\xac" // U+F142C +#define ICON_MDI_GAMEPAD "\xf3\xb0\x8a\x96" // U+F0296 +#define ICON_MDI_GAMEPAD_CIRCLE "\xf3\xb0\xb8\xb3" // U+F0E33 +#define ICON_MDI_GAMEPAD_CIRCLE_DOWN "\xf3\xb0\xb8\xb4" // U+F0E34 +#define ICON_MDI_GAMEPAD_CIRCLE_LEFT "\xf3\xb0\xb8\xb5" // U+F0E35 +#define ICON_MDI_GAMEPAD_CIRCLE_OUTLINE "\xf3\xb0\xb8\xb6" // U+F0E36 +#define ICON_MDI_GAMEPAD_CIRCLE_RIGHT "\xf3\xb0\xb8\xb7" // U+F0E37 +#define ICON_MDI_GAMEPAD_CIRCLE_UP "\xf3\xb0\xb8\xb8" // U+F0E38 +#define ICON_MDI_GAMEPAD_DOWN "\xf3\xb0\xb8\xb9" // U+F0E39 +#define ICON_MDI_GAMEPAD_LEFT "\xf3\xb0\xb8\xba" // U+F0E3A +#define ICON_MDI_GAMEPAD_OUTLINE "\xf3\xb1\xa4\x99" // U+F1919 +#define ICON_MDI_GAMEPAD_RIGHT "\xf3\xb0\xb8\xbb" // U+F0E3B +#define ICON_MDI_GAMEPAD_ROUND "\xf3\xb0\xb8\xbc" // U+F0E3C +#define ICON_MDI_GAMEPAD_ROUND_DOWN "\xf3\xb0\xb8\xbd" // U+F0E3D +#define ICON_MDI_GAMEPAD_ROUND_LEFT "\xf3\xb0\xb8\xbe" // U+F0E3E +#define ICON_MDI_GAMEPAD_ROUND_OUTLINE "\xf3\xb0\xb8\xbf" // U+F0E3F +#define ICON_MDI_GAMEPAD_ROUND_RIGHT "\xf3\xb0\xb9\x80" // U+F0E40 +#define ICON_MDI_GAMEPAD_ROUND_UP "\xf3\xb0\xb9\x81" // U+F0E41 +#define ICON_MDI_GAMEPAD_SQUARE "\xf3\xb0\xba\xb5" // U+F0EB5 +#define ICON_MDI_GAMEPAD_SQUARE_OUTLINE "\xf3\xb0\xba\xb6" // U+F0EB6 +#define ICON_MDI_GAMEPAD_UP "\xf3\xb0\xb9\x82" // U+F0E42 +#define ICON_MDI_GAMEPAD_VARIANT "\xf3\xb0\x8a\x97" // U+F0297 +#define ICON_MDI_GAMEPAD_VARIANT_OUTLINE "\xf3\xb0\xba\xb7" // U+F0EB7 +#define ICON_MDI_GAMMA "\xf3\xb1\x83\xae" // U+F10EE +#define ICON_MDI_GANTRY_CRANE "\xf3\xb0\xb7\x91" // U+F0DD1 +#define ICON_MDI_GARAGE "\xf3\xb0\x9b\x99" // U+F06D9 +#define ICON_MDI_GARAGE_ALERT "\xf3\xb0\xa1\xb2" // U+F0872 +#define ICON_MDI_GARAGE_ALERT_VARIANT "\xf3\xb1\x8b\x95" // U+F12D5 +#define ICON_MDI_GARAGE_LOCK "\xf3\xb1\x9f\xbb" // U+F17FB +#define ICON_MDI_GARAGE_OPEN "\xf3\xb0\x9b\x9a" // U+F06DA +#define ICON_MDI_GARAGE_OPEN_VARIANT "\xf3\xb1\x8b\x94" // U+F12D4 +#define ICON_MDI_GARAGE_VARIANT "\xf3\xb1\x8b\x93" // U+F12D3 +#define ICON_MDI_GARAGE_VARIANT_LOCK "\xf3\xb1\x9f\xbc" // U+F17FC +#define ICON_MDI_GAS_BURNER "\xf3\xb1\xa8\x9b" // U+F1A1B +#define ICON_MDI_GAS_CYLINDER "\xf3\xb0\x99\x87" // U+F0647 +#define ICON_MDI_GAS_STATION "\xf3\xb0\x8a\x98" // U+F0298 +#define ICON_MDI_GAS_STATION_IN_USE "\xf3\xb1\xb3\x84" // U+F1CC4 +#define ICON_MDI_GAS_STATION_IN_USE_OUTLINE "\xf3\xb1\xb3\x85" // U+F1CC5 +#define ICON_MDI_GAS_STATION_OFF "\xf3\xb1\x90\x89" // U+F1409 +#define ICON_MDI_GAS_STATION_OFF_OUTLINE "\xf3\xb1\x90\x8a" // U+F140A +#define ICON_MDI_GAS_STATION_OUTLINE "\xf3\xb0\xba\xb8" // U+F0EB8 +#define ICON_MDI_GATE "\xf3\xb0\x8a\x99" // U+F0299 +#define ICON_MDI_GATE_ALERT "\xf3\xb1\x9f\xb8" // U+F17F8 +#define ICON_MDI_GATE_AND "\xf3\xb0\xa3\xa1" // U+F08E1 +#define ICON_MDI_GATE_ARROW_LEFT "\xf3\xb1\x9f\xb7" // U+F17F7 +#define ICON_MDI_GATE_ARROW_RIGHT "\xf3\xb1\x85\xa9" // U+F1169 +#define ICON_MDI_GATE_BUFFER "\xf3\xb1\xab\xbe" // U+F1AFE +#define ICON_MDI_GATE_NAND "\xf3\xb0\xa3\xa2" // U+F08E2 +#define ICON_MDI_GATE_NOR "\xf3\xb0\xa3\xa3" // U+F08E3 +#define ICON_MDI_GATE_NOT "\xf3\xb0\xa3\xa4" // U+F08E4 +#define ICON_MDI_GATE_OPEN "\xf3\xb1\x85\xaa" // U+F116A +#define ICON_MDI_GATE_OR "\xf3\xb0\xa3\xa5" // U+F08E5 +#define ICON_MDI_GATE_XNOR "\xf3\xb0\xa3\xa6" // U+F08E6 +#define ICON_MDI_GATE_XOR "\xf3\xb0\xa3\xa7" // U+F08E7 +#define ICON_MDI_GATSBY "\xf3\xb0\xb9\x83" // U+F0E43 +#define ICON_MDI_GAUGE "\xf3\xb0\x8a\x9a" // U+F029A +#define ICON_MDI_GAUGE_EMPTY "\xf3\xb0\xa1\xb3" // U+F0873 +#define ICON_MDI_GAUGE_FULL "\xf3\xb0\xa1\xb4" // U+F0874 +#define ICON_MDI_GAUGE_LOW "\xf3\xb0\xa1\xb5" // U+F0875 +#define ICON_MDI_GAVEL "\xf3\xb0\x8a\x9b" // U+F029B +#define ICON_MDI_GENDER_FEMALE "\xf3\xb0\x8a\x9c" // U+F029C +#define ICON_MDI_GENDER_MALE "\xf3\xb0\x8a\x9d" // U+F029D +#define ICON_MDI_GENDER_MALE_FEMALE "\xf3\xb0\x8a\x9e" // U+F029E +#define ICON_MDI_GENDER_MALE_FEMALE_VARIANT "\xf3\xb1\x84\xbf" // U+F113F +#define ICON_MDI_GENDER_NON_BINARY "\xf3\xb1\x85\x80" // U+F1140 +#define ICON_MDI_GENDER_TRANSGENDER "\xf3\xb0\x8a\x9f" // U+F029F +#define ICON_MDI_GENERATOR_MOBILE "\xf3\xb1\xb2\x8a" // U+F1C8A +#define ICON_MDI_GENERATOR_PORTABLE "\xf3\xb1\xb2\x8b" // U+F1C8B +#define ICON_MDI_GENERATOR_STATIONARY "\xf3\xb1\xb2\x8c" // U+F1C8C +#define ICON_MDI_GENTOO "\xf3\xb0\xa3\xa8" // U+F08E8 +#define ICON_MDI_GESTURE "\xf3\xb0\x9f\x8b" // U+F07CB +#define ICON_MDI_GESTURE_DOUBLE_TAP "\xf3\xb0\x9c\xbc" // U+F073C +#define ICON_MDI_GESTURE_PINCH "\xf3\xb0\xaa\xbd" // U+F0ABD +#define ICON_MDI_GESTURE_SPREAD "\xf3\xb0\xaa\xbe" // U+F0ABE +#define ICON_MDI_GESTURE_SWIPE "\xf3\xb0\xb5\xb6" // U+F0D76 +#define ICON_MDI_GESTURE_SWIPE_DOWN "\xf3\xb0\x9c\xbd" // U+F073D +#define ICON_MDI_GESTURE_SWIPE_HORIZONTAL "\xf3\xb0\xaa\xbf" // U+F0ABF +#define ICON_MDI_GESTURE_SWIPE_LEFT "\xf3\xb0\x9c\xbe" // U+F073E +#define ICON_MDI_GESTURE_SWIPE_RIGHT "\xf3\xb0\x9c\xbf" // U+F073F +#define ICON_MDI_GESTURE_SWIPE_UP "\xf3\xb0\x9d\x80" // U+F0740 +#define ICON_MDI_GESTURE_SWIPE_VERTICAL "\xf3\xb0\xab\x80" // U+F0AC0 +#define ICON_MDI_GESTURE_TAP "\xf3\xb0\x9d\x81" // U+F0741 +#define ICON_MDI_GESTURE_TAP_BOX "\xf3\xb1\x8a\xa9" // U+F12A9 +#define ICON_MDI_GESTURE_TAP_BUTTON "\xf3\xb1\x8a\xa8" // U+F12A8 +#define ICON_MDI_GESTURE_TAP_HOLD "\xf3\xb0\xb5\xb7" // U+F0D77 +#define ICON_MDI_GESTURE_TWO_DOUBLE_TAP "\xf3\xb0\x9d\x82" // U+F0742 +#define ICON_MDI_GESTURE_TWO_TAP "\xf3\xb0\x9d\x83" // U+F0743 +#define ICON_MDI_GHOST "\xf3\xb0\x8a\xa0" // U+F02A0 +#define ICON_MDI_GHOST_OFF "\xf3\xb0\xa7\xb5" // U+F09F5 +#define ICON_MDI_GHOST_OFF_OUTLINE "\xf3\xb1\x99\x9c" // U+F165C +#define ICON_MDI_GHOST_OUTLINE "\xf3\xb1\x99\x9d" // U+F165D +#define ICON_MDI_GIFT "\xf3\xb0\xb9\x84" // U+F0E44 +#define ICON_MDI_GIFT_OFF "\xf3\xb1\x9b\xaf" // U+F16EF +#define ICON_MDI_GIFT_OFF_OUTLINE "\xf3\xb1\x9b\xb0" // U+F16F0 +#define ICON_MDI_GIFT_OPEN "\xf3\xb1\x9b\xb1" // U+F16F1 +#define ICON_MDI_GIFT_OPEN_OUTLINE "\xf3\xb1\x9b\xb2" // U+F16F2 +#define ICON_MDI_GIFT_OUTLINE "\xf3\xb0\x8a\xa1" // U+F02A1 +#define ICON_MDI_GIT "\xf3\xb0\x8a\xa2" // U+F02A2 +#define ICON_MDI_GITHUB "\xf3\xb0\x8a\xa4" // U+F02A4 +#define ICON_MDI_GITLAB "\xf3\xb0\xae\xa0" // U+F0BA0 +#define ICON_MDI_GLASS_COCKTAIL "\xf3\xb0\x8d\x96" // U+F0356 +#define ICON_MDI_GLASS_COCKTAIL_OFF "\xf3\xb1\x97\xa6" // U+F15E6 +#define ICON_MDI_GLASS_FLUTE "\xf3\xb0\x8a\xa5" // U+F02A5 +#define ICON_MDI_GLASS_FRAGILE "\xf3\xb1\xa1\xb3" // U+F1873 +#define ICON_MDI_GLASS_MUG "\xf3\xb0\x8a\xa6" // U+F02A6 +#define ICON_MDI_GLASS_MUG_OFF "\xf3\xb1\x97\xa7" // U+F15E7 +#define ICON_MDI_GLASS_MUG_VARIANT "\xf3\xb1\x84\x96" // U+F1116 +#define ICON_MDI_GLASS_MUG_VARIANT_OFF "\xf3\xb1\x97\xa8" // U+F15E8 +#define ICON_MDI_GLASS_PINT_OUTLINE "\xf3\xb1\x8c\x8d" // U+F130D +#define ICON_MDI_GLASS_STANGE "\xf3\xb0\x8a\xa7" // U+F02A7 +#define ICON_MDI_GLASS_TULIP "\xf3\xb0\x8a\xa8" // U+F02A8 +#define ICON_MDI_GLASS_WINE "\xf3\xb0\xa1\xb6" // U+F0876 +#define ICON_MDI_GLASSES "\xf3\xb0\x8a\xaa" // U+F02AA +#define ICON_MDI_GLOBE_LIGHT "\xf3\xb0\x99\xaf" // U+F066F +#define ICON_MDI_GLOBE_LIGHT_OUTLINE "\xf3\xb1\x8b\x97" // U+F12D7 +#define ICON_MDI_GLOBE_MODEL "\xf3\xb0\xa3\xa9" // U+F08E9 +#define ICON_MDI_GMAIL "\xf3\xb0\x8a\xab" // U+F02AB +#define ICON_MDI_GNOME "\xf3\xb0\x8a\xac" // U+F02AC +#define ICON_MDI_GO_KART "\xf3\xb0\xb5\xb9" // U+F0D79 +#define ICON_MDI_GO_KART_TRACK "\xf3\xb0\xb5\xba" // U+F0D7A +#define ICON_MDI_GOG "\xf3\xb0\xae\xa1" // U+F0BA1 +#define ICON_MDI_GOLD "\xf3\xb1\x89\x8f" // U+F124F +#define ICON_MDI_GOLF "\xf3\xb0\xa0\xa3" // U+F0823 +#define ICON_MDI_GOLF_CART "\xf3\xb1\x86\xa4" // U+F11A4 +#define ICON_MDI_GOLF_TEE "\xf3\xb1\x82\x83" // U+F1083 +#define ICON_MDI_GONDOLA "\xf3\xb0\x9a\x86" // U+F0686 +#define ICON_MDI_GOODREADS "\xf3\xb0\xb5\xbb" // U+F0D7B +#define ICON_MDI_GOOGLE "\xf3\xb0\x8a\xad" // U+F02AD +#define ICON_MDI_GOOGLE_ADS "\xf3\xb0\xb2\x87" // U+F0C87 +#define ICON_MDI_GOOGLE_ANALYTICS "\xf3\xb0\x9f\x8c" // U+F07CC +#define ICON_MDI_GOOGLE_ASSISTANT "\xf3\xb0\x9f\x8d" // U+F07CD +#define ICON_MDI_GOOGLE_CARDBOARD "\xf3\xb0\x8a\xae" // U+F02AE +#define ICON_MDI_GOOGLE_CHROME "\xf3\xb0\x8a\xaf" // U+F02AF +#define ICON_MDI_GOOGLE_CIRCLES "\xf3\xb0\x8a\xb0" // U+F02B0 +#define ICON_MDI_GOOGLE_CIRCLES_COMMUNITIES "\xf3\xb0\x8a\xb1" // U+F02B1 +#define ICON_MDI_GOOGLE_CIRCLES_EXTENDED "\xf3\xb0\x8a\xb2" // U+F02B2 +#define ICON_MDI_GOOGLE_CIRCLES_GROUP "\xf3\xb0\x8a\xb3" // U+F02B3 +#define ICON_MDI_GOOGLE_CLASSROOM "\xf3\xb0\x8b\x80" // U+F02C0 +#define ICON_MDI_GOOGLE_CLOUD "\xf3\xb1\x87\xb6" // U+F11F6 +#define ICON_MDI_GOOGLE_DOWNASAUR "\xf3\xb1\x8d\xa2" // U+F1362 +#define ICON_MDI_GOOGLE_DRIVE "\xf3\xb0\x8a\xb6" // U+F02B6 +#define ICON_MDI_GOOGLE_EARTH "\xf3\xb0\x8a\xb7" // U+F02B7 +#define ICON_MDI_GOOGLE_FIT "\xf3\xb0\xa5\xac" // U+F096C +#define ICON_MDI_GOOGLE_GLASS "\xf3\xb0\x8a\xb8" // U+F02B8 +#define ICON_MDI_GOOGLE_HANGOUTS "\xf3\xb0\x8b\x89" // U+F02C9 +#define ICON_MDI_GOOGLE_KEEP "\xf3\xb0\x9b\x9c" // U+F06DC +#define ICON_MDI_GOOGLE_LENS "\xf3\xb0\xa7\xb6" // U+F09F6 +#define ICON_MDI_GOOGLE_MAPS "\xf3\xb0\x97\xb5" // U+F05F5 +#define ICON_MDI_GOOGLE_MY_BUSINESS "\xf3\xb1\x81\x88" // U+F1048 +#define ICON_MDI_GOOGLE_NEARBY "\xf3\xb0\x8a\xb9" // U+F02B9 +#define ICON_MDI_GOOGLE_PLAY "\xf3\xb0\x8a\xbc" // U+F02BC +#define ICON_MDI_GOOGLE_PLUS "\xf3\xb0\x8a\xbd" // U+F02BD +#define ICON_MDI_GOOGLE_PODCAST "\xf3\xb0\xba\xb9" // U+F0EB9 +#define ICON_MDI_GOOGLE_SPREADSHEET "\xf3\xb0\xa7\xb7" // U+F09F7 +#define ICON_MDI_GOOGLE_STREET_VIEW "\xf3\xb0\xb2\x88" // U+F0C88 +#define ICON_MDI_GOOGLE_TRANSLATE "\xf3\xb0\x8a\xbf" // U+F02BF +#define ICON_MDI_GRADIENT_HORIZONTAL "\xf3\xb1\x9d\x8a" // U+F174A +#define ICON_MDI_GRADIENT_VERTICAL "\xf3\xb0\x9a\xa0" // U+F06A0 +#define ICON_MDI_GRAIN "\xf3\xb0\xb5\xbc" // U+F0D7C +#define ICON_MDI_GRAPH "\xf3\xb1\x81\x89" // U+F1049 +#define ICON_MDI_GRAPH_OUTLINE "\xf3\xb1\x81\x8a" // U+F104A +#define ICON_MDI_GRAPHQL "\xf3\xb0\xa1\xb7" // U+F0877 +#define ICON_MDI_GRASS "\xf3\xb1\x94\x90" // U+F1510 +#define ICON_MDI_GRAVE_STONE "\xf3\xb0\xae\xa2" // U+F0BA2 +#define ICON_MDI_GREASE_PENCIL "\xf3\xb0\x99\x88" // U+F0648 +#define ICON_MDI_GREATER_THAN "\xf3\xb0\xa5\xad" // U+F096D +#define ICON_MDI_GREATER_THAN_OR_EQUAL "\xf3\xb0\xa5\xae" // U+F096E +#define ICON_MDI_GREENHOUSE "\xf3\xb0\x80\xad" // U+F002D +#define ICON_MDI_GRID "\xf3\xb0\x8b\x81" // U+F02C1 +#define ICON_MDI_GRID_LARGE "\xf3\xb0\x9d\x98" // U+F0758 +#define ICON_MDI_GRID_OFF "\xf3\xb0\x8b\x82" // U+F02C2 +#define ICON_MDI_GRILL "\xf3\xb0\xb9\x85" // U+F0E45 +#define ICON_MDI_GRILL_OUTLINE "\xf3\xb1\x86\x8a" // U+F118A +#define ICON_MDI_GROUP "\xf3\xb0\x8b\x83" // U+F02C3 +#define ICON_MDI_GUITAR_ACOUSTIC "\xf3\xb0\x9d\xb1" // U+F0771 +#define ICON_MDI_GUITAR_ELECTRIC "\xf3\xb0\x8b\x84" // U+F02C4 +#define ICON_MDI_GUITAR_PICK "\xf3\xb0\x8b\x85" // U+F02C5 +#define ICON_MDI_GUITAR_PICK_OUTLINE "\xf3\xb0\x8b\x86" // U+F02C6 +#define ICON_MDI_GUY_FAWKES_MASK "\xf3\xb0\xa0\xa5" // U+F0825 +#define ICON_MDI_GYMNASTICS "\xf3\xb1\xa9\x81" // U+F1A41 +#define ICON_MDI_HAIL "\xf3\xb0\xab\x81" // U+F0AC1 +#define ICON_MDI_HAIR_DRYER "\xf3\xb1\x83\xaf" // U+F10EF +#define ICON_MDI_HAIR_DRYER_OUTLINE "\xf3\xb1\x83\xb0" // U+F10F0 +#define ICON_MDI_HALLOWEEN "\xf3\xb0\xae\xa3" // U+F0BA3 +#define ICON_MDI_HAMBURGER "\xf3\xb0\x9a\x85" // U+F0685 +#define ICON_MDI_HAMBURGER_CHECK "\xf3\xb1\x9d\xb6" // U+F1776 +#define ICON_MDI_HAMBURGER_MINUS "\xf3\xb1\x9d\xb7" // U+F1777 +#define ICON_MDI_HAMBURGER_OFF "\xf3\xb1\x9d\xb8" // U+F1778 +#define ICON_MDI_HAMBURGER_PLUS "\xf3\xb1\x9d\xb9" // U+F1779 +#define ICON_MDI_HAMBURGER_REMOVE "\xf3\xb1\x9d\xba" // U+F177A +#define ICON_MDI_HAMMER "\xf3\xb0\xa3\xaa" // U+F08EA +#define ICON_MDI_HAMMER_SCREWDRIVER "\xf3\xb1\x8c\xa2" // U+F1322 +#define ICON_MDI_HAMMER_SICKLE "\xf3\xb1\xa2\x87" // U+F1887 +#define ICON_MDI_HAMMER_WRENCH "\xf3\xb1\x8c\xa3" // U+F1323 +#define ICON_MDI_HAND_BACK_LEFT "\xf3\xb0\xb9\x86" // U+F0E46 +#define ICON_MDI_HAND_BACK_LEFT_OFF "\xf3\xb1\xa0\xb0" // U+F1830 +#define ICON_MDI_HAND_BACK_LEFT_OFF_OUTLINE "\xf3\xb1\xa0\xb2" // U+F1832 +#define ICON_MDI_HAND_BACK_LEFT_OUTLINE "\xf3\xb1\xa0\xac" // U+F182C +#define ICON_MDI_HAND_BACK_RIGHT "\xf3\xb0\xb9\x87" // U+F0E47 +#define ICON_MDI_HAND_BACK_RIGHT_OFF "\xf3\xb1\xa0\xb1" // U+F1831 +#define ICON_MDI_HAND_BACK_RIGHT_OFF_OUTLINE "\xf3\xb1\xa0\xb3" // U+F1833 +#define ICON_MDI_HAND_BACK_RIGHT_OUTLINE "\xf3\xb1\xa0\xad" // U+F182D +#define ICON_MDI_HAND_CLAP "\xf3\xb1\xa5\x8b" // U+F194B +#define ICON_MDI_HAND_CLAP_OFF "\xf3\xb1\xa9\x82" // U+F1A42 +#define ICON_MDI_HAND_COIN "\xf3\xb1\xa2\x8f" // U+F188F +#define ICON_MDI_HAND_COIN_OUTLINE "\xf3\xb1\xa2\x90" // U+F1890 +#define ICON_MDI_HAND_CYCLE "\xf3\xb1\xae\x9c" // U+F1B9C +#define ICON_MDI_HAND_EXTENDED "\xf3\xb1\xa2\xb6" // U+F18B6 +#define ICON_MDI_HAND_EXTENDED_OUTLINE "\xf3\xb1\xa2\xb7" // U+F18B7 +#define ICON_MDI_HAND_FRONT_LEFT "\xf3\xb1\xa0\xab" // U+F182B +#define ICON_MDI_HAND_FRONT_LEFT_OUTLINE "\xf3\xb1\xa0\xae" // U+F182E +#define ICON_MDI_HAND_FRONT_RIGHT "\xf3\xb0\xa9\x8f" // U+F0A4F +#define ICON_MDI_HAND_FRONT_RIGHT_OUTLINE "\xf3\xb1\xa0\xaf" // U+F182F +#define ICON_MDI_HAND_HEART "\xf3\xb1\x83\xb1" // U+F10F1 +#define ICON_MDI_HAND_HEART_OUTLINE "\xf3\xb1\x95\xbe" // U+F157E +#define ICON_MDI_HAND_OKAY "\xf3\xb0\xa9\x90" // U+F0A50 +#define ICON_MDI_HAND_PEACE "\xf3\xb0\xa9\x91" // U+F0A51 +#define ICON_MDI_HAND_PEACE_VARIANT "\xf3\xb0\xa9\x92" // U+F0A52 +#define ICON_MDI_HAND_POINTING_DOWN "\xf3\xb0\xa9\x93" // U+F0A53 +#define ICON_MDI_HAND_POINTING_LEFT "\xf3\xb0\xa9\x94" // U+F0A54 +#define ICON_MDI_HAND_POINTING_RIGHT "\xf3\xb0\x8b\x87" // U+F02C7 +#define ICON_MDI_HAND_POINTING_UP "\xf3\xb0\xa9\x95" // U+F0A55 +#define ICON_MDI_HAND_SAW "\xf3\xb0\xb9\x88" // U+F0E48 +#define ICON_MDI_HAND_WASH "\xf3\xb1\x95\xbf" // U+F157F +#define ICON_MDI_HAND_WASH_OUTLINE "\xf3\xb1\x96\x80" // U+F1580 +#define ICON_MDI_HAND_WATER "\xf3\xb1\x8e\x9f" // U+F139F +#define ICON_MDI_HAND_WAVE "\xf3\xb1\xa0\xa1" // U+F1821 +#define ICON_MDI_HAND_WAVE_OUTLINE "\xf3\xb1\xa0\xa2" // U+F1822 +#define ICON_MDI_HANDBALL "\xf3\xb0\xbd\x93" // U+F0F53 +#define ICON_MDI_HANDCUFFS "\xf3\xb1\x84\xbe" // U+F113E +#define ICON_MDI_HANDS_PRAY "\xf3\xb0\x95\xb9" // U+F0579 +#define ICON_MDI_HANDSHAKE "\xf3\xb1\x88\x98" // U+F1218 +#define ICON_MDI_HANDSHAKE_OUTLINE "\xf3\xb1\x96\xa1" // U+F15A1 +#define ICON_MDI_HANGER "\xf3\xb0\x8b\x88" // U+F02C8 +#define ICON_MDI_HARD_HAT "\xf3\xb0\xa5\xaf" // U+F096F +#define ICON_MDI_HARDDISK "\xf3\xb0\x8b\x8a" // U+F02CA +#define ICON_MDI_HARDDISK_PLUS "\xf3\xb1\x81\x8b" // U+F104B +#define ICON_MDI_HARDDISK_REMOVE "\xf3\xb1\x81\x8c" // U+F104C +#define ICON_MDI_HAT_FEDORA "\xf3\xb0\xae\xa4" // U+F0BA4 +#define ICON_MDI_HAZARD_LIGHTS "\xf3\xb0\xb2\x89" // U+F0C89 +#define ICON_MDI_HDMI_PORT "\xf3\xb1\xae\xb8" // U+F1BB8 +#define ICON_MDI_HDR "\xf3\xb0\xb5\xbd" // U+F0D7D +#define ICON_MDI_HDR_OFF "\xf3\xb0\xb5\xbe" // U+F0D7E +#define ICON_MDI_HEAD "\xf3\xb1\x8d\x9e" // U+F135E +#define ICON_MDI_HEAD_ALERT "\xf3\xb1\x8c\xb8" // U+F1338 +#define ICON_MDI_HEAD_ALERT_OUTLINE "\xf3\xb1\x8c\xb9" // U+F1339 +#define ICON_MDI_HEAD_CHECK "\xf3\xb1\x8c\xba" // U+F133A +#define ICON_MDI_HEAD_CHECK_OUTLINE "\xf3\xb1\x8c\xbb" // U+F133B +#define ICON_MDI_HEAD_COG "\xf3\xb1\x8c\xbc" // U+F133C +#define ICON_MDI_HEAD_COG_OUTLINE "\xf3\xb1\x8c\xbd" // U+F133D +#define ICON_MDI_HEAD_DOTS_HORIZONTAL "\xf3\xb1\x8c\xbe" // U+F133E +#define ICON_MDI_HEAD_DOTS_HORIZONTAL_OUTLINE "\xf3\xb1\x8c\xbf" // U+F133F +#define ICON_MDI_HEAD_FLASH "\xf3\xb1\x8d\x80" // U+F1340 +#define ICON_MDI_HEAD_FLASH_OUTLINE "\xf3\xb1\x8d\x81" // U+F1341 +#define ICON_MDI_HEAD_HEART "\xf3\xb1\x8d\x82" // U+F1342 +#define ICON_MDI_HEAD_HEART_OUTLINE "\xf3\xb1\x8d\x83" // U+F1343 +#define ICON_MDI_HEAD_LIGHTBULB "\xf3\xb1\x8d\x84" // U+F1344 +#define ICON_MDI_HEAD_LIGHTBULB_OUTLINE "\xf3\xb1\x8d\x85" // U+F1345 +#define ICON_MDI_HEAD_MINUS "\xf3\xb1\x8d\x86" // U+F1346 +#define ICON_MDI_HEAD_MINUS_OUTLINE "\xf3\xb1\x8d\x87" // U+F1347 +#define ICON_MDI_HEAD_OUTLINE "\xf3\xb1\x8d\x9f" // U+F135F +#define ICON_MDI_HEAD_PLUS "\xf3\xb1\x8d\x88" // U+F1348 +#define ICON_MDI_HEAD_PLUS_OUTLINE "\xf3\xb1\x8d\x89" // U+F1349 +#define ICON_MDI_HEAD_QUESTION "\xf3\xb1\x8d\x8a" // U+F134A +#define ICON_MDI_HEAD_QUESTION_OUTLINE "\xf3\xb1\x8d\x8b" // U+F134B +#define ICON_MDI_HEAD_REMOVE "\xf3\xb1\x8d\x8c" // U+F134C +#define ICON_MDI_HEAD_REMOVE_OUTLINE "\xf3\xb1\x8d\x8d" // U+F134D +#define ICON_MDI_HEAD_SNOWFLAKE "\xf3\xb1\x8d\x8e" // U+F134E +#define ICON_MDI_HEAD_SNOWFLAKE_OUTLINE "\xf3\xb1\x8d\x8f" // U+F134F +#define ICON_MDI_HEAD_SYNC "\xf3\xb1\x8d\x90" // U+F1350 +#define ICON_MDI_HEAD_SYNC_OUTLINE "\xf3\xb1\x8d\x91" // U+F1351 +#define ICON_MDI_HEADPHONES "\xf3\xb0\x8b\x8b" // U+F02CB +#define ICON_MDI_HEADPHONES_BLUETOOTH "\xf3\xb0\xa5\xb0" // U+F0970 +#define ICON_MDI_HEADPHONES_BOX "\xf3\xb0\x8b\x8c" // U+F02CC +#define ICON_MDI_HEADPHONES_OFF "\xf3\xb0\x9f\x8e" // U+F07CE +#define ICON_MDI_HEADPHONES_SETTINGS "\xf3\xb0\x8b\x8d" // U+F02CD +#define ICON_MDI_HEADSET "\xf3\xb0\x8b\x8e" // U+F02CE +#define ICON_MDI_HEADSET_DOCK "\xf3\xb0\x8b\x8f" // U+F02CF +#define ICON_MDI_HEADSET_OFF "\xf3\xb0\x8b\x90" // U+F02D0 +#define ICON_MDI_HEART "\xf3\xb0\x8b\x91" // U+F02D1 +#define ICON_MDI_HEART_BOX "\xf3\xb0\x8b\x92" // U+F02D2 +#define ICON_MDI_HEART_BOX_OUTLINE "\xf3\xb0\x8b\x93" // U+F02D3 +#define ICON_MDI_HEART_BROKEN "\xf3\xb0\x8b\x94" // U+F02D4 +#define ICON_MDI_HEART_BROKEN_OUTLINE "\xf3\xb0\xb4\x94" // U+F0D14 +#define ICON_MDI_HEART_CIRCLE "\xf3\xb0\xa5\xb1" // U+F0971 +#define ICON_MDI_HEART_CIRCLE_OUTLINE "\xf3\xb0\xa5\xb2" // U+F0972 +#define ICON_MDI_HEART_COG "\xf3\xb1\x99\xa3" // U+F1663 +#define ICON_MDI_HEART_COG_OUTLINE "\xf3\xb1\x99\xa4" // U+F1664 +#define ICON_MDI_HEART_FLASH "\xf3\xb0\xbb\xb9" // U+F0EF9 +#define ICON_MDI_HEART_HALF "\xf3\xb0\x9b\x9f" // U+F06DF +#define ICON_MDI_HEART_HALF_FULL "\xf3\xb0\x9b\x9e" // U+F06DE +#define ICON_MDI_HEART_HALF_OUTLINE "\xf3\xb0\x9b\xa0" // U+F06E0 +#define ICON_MDI_HEART_MINUS "\xf3\xb1\x90\xaf" // U+F142F +#define ICON_MDI_HEART_MINUS_OUTLINE "\xf3\xb1\x90\xb2" // U+F1432 +#define ICON_MDI_HEART_MULTIPLE "\xf3\xb0\xa9\x96" // U+F0A56 +#define ICON_MDI_HEART_MULTIPLE_OUTLINE "\xf3\xb0\xa9\x97" // U+F0A57 +#define ICON_MDI_HEART_OFF "\xf3\xb0\x9d\x99" // U+F0759 +#define ICON_MDI_HEART_OFF_OUTLINE "\xf3\xb1\x90\xb4" // U+F1434 +#define ICON_MDI_HEART_OUTLINE "\xf3\xb0\x8b\x95" // U+F02D5 +#define ICON_MDI_HEART_PLUS "\xf3\xb1\x90\xae" // U+F142E +#define ICON_MDI_HEART_PLUS_OUTLINE "\xf3\xb1\x90\xb1" // U+F1431 +#define ICON_MDI_HEART_PULSE "\xf3\xb0\x97\xb6" // U+F05F6 +#define ICON_MDI_HEART_REMOVE "\xf3\xb1\x90\xb0" // U+F1430 +#define ICON_MDI_HEART_REMOVE_OUTLINE "\xf3\xb1\x90\xb3" // U+F1433 +#define ICON_MDI_HEART_SEARCH "\xf3\xb1\xb2\x8d" // U+F1C8D +#define ICON_MDI_HEART_SETTINGS "\xf3\xb1\x99\xa5" // U+F1665 +#define ICON_MDI_HEART_SETTINGS_OUTLINE "\xf3\xb1\x99\xa6" // U+F1666 +#define ICON_MDI_HEAT_PUMP "\xf3\xb1\xa9\x83" // U+F1A43 +#define ICON_MDI_HEAT_PUMP_OUTLINE "\xf3\xb1\xa9\x84" // U+F1A44 +#define ICON_MDI_HEAT_WAVE "\xf3\xb1\xa9\x85" // U+F1A45 +#define ICON_MDI_HEATING_COIL "\xf3\xb1\xaa\xaf" // U+F1AAF +#define ICON_MDI_HELICOPTER "\xf3\xb0\xab\x82" // U+F0AC2 +#define ICON_MDI_HELP "\xf3\xb0\x8b\x96" // U+F02D6 +#define ICON_MDI_HELP_BOX "\xf3\xb0\x9e\x8b" // U+F078B +#define ICON_MDI_HELP_BOX_MULTIPLE "\xf3\xb1\xb0\x8a" // U+F1C0A +#define ICON_MDI_HELP_BOX_MULTIPLE_OUTLINE "\xf3\xb1\xb0\x8b" // U+F1C0B +#define ICON_MDI_HELP_BOX_OUTLINE "\xf3\xb1\xb0\x8c" // U+F1C0C +#define ICON_MDI_HELP_CIRCLE "\xf3\xb0\x8b\x97" // U+F02D7 +#define ICON_MDI_HELP_CIRCLE_OUTLINE "\xf3\xb0\x98\xa5" // U+F0625 +#define ICON_MDI_HELP_NETWORK "\xf3\xb0\x9b\xb5" // U+F06F5 +#define ICON_MDI_HELP_NETWORK_OUTLINE "\xf3\xb0\xb2\x8a" // U+F0C8A +#define ICON_MDI_HELP_RHOMBUS "\xf3\xb0\xae\xa5" // U+F0BA5 +#define ICON_MDI_HELP_RHOMBUS_OUTLINE "\xf3\xb0\xae\xa6" // U+F0BA6 +#define ICON_MDI_HEXADECIMAL "\xf3\xb1\x8a\xa7" // U+F12A7 +#define ICON_MDI_HEXAGON "\xf3\xb0\x8b\x98" // U+F02D8 +#define ICON_MDI_HEXAGON_MULTIPLE "\xf3\xb0\x9b\xa1" // U+F06E1 +#define ICON_MDI_HEXAGON_MULTIPLE_OUTLINE "\xf3\xb1\x83\xb2" // U+F10F2 +#define ICON_MDI_HEXAGON_OUTLINE "\xf3\xb0\x8b\x99" // U+F02D9 +#define ICON_MDI_HEXAGON_SLICE_1 "\xf3\xb0\xab\x83" // U+F0AC3 +#define ICON_MDI_HEXAGON_SLICE_2 "\xf3\xb0\xab\x84" // U+F0AC4 +#define ICON_MDI_HEXAGON_SLICE_3 "\xf3\xb0\xab\x85" // U+F0AC5 +#define ICON_MDI_HEXAGON_SLICE_4 "\xf3\xb0\xab\x86" // U+F0AC6 +#define ICON_MDI_HEXAGON_SLICE_5 "\xf3\xb0\xab\x87" // U+F0AC7 +#define ICON_MDI_HEXAGON_SLICE_6 "\xf3\xb0\xab\x88" // U+F0AC8 +#define ICON_MDI_HEXAGRAM "\xf3\xb0\xab\x89" // U+F0AC9 +#define ICON_MDI_HEXAGRAM_OUTLINE "\xf3\xb0\xab\x8a" // U+F0ACA +#define ICON_MDI_HIGH_DEFINITION "\xf3\xb0\x9f\x8f" // U+F07CF +#define ICON_MDI_HIGH_DEFINITION_BOX "\xf3\xb0\xa1\xb8" // U+F0878 +#define ICON_MDI_HIGHWAY "\xf3\xb0\x97\xb7" // U+F05F7 +#define ICON_MDI_HIKING "\xf3\xb0\xb5\xbf" // U+F0D7F +#define ICON_MDI_HISTORY "\xf3\xb0\x8b\x9a" // U+F02DA +#define ICON_MDI_HOCKEY_PUCK "\xf3\xb0\xa1\xb9" // U+F0879 +#define ICON_MDI_HOCKEY_STICKS "\xf3\xb0\xa1\xba" // U+F087A +#define ICON_MDI_HOLOLENS "\xf3\xb0\x8b\x9b" // U+F02DB +#define ICON_MDI_HOME "\xf3\xb0\x8b\x9c" // U+F02DC +#define ICON_MDI_HOME_ACCOUNT "\xf3\xb0\xa0\xa6" // U+F0826 +#define ICON_MDI_HOME_ALERT "\xf3\xb0\xa1\xbb" // U+F087B +#define ICON_MDI_HOME_ALERT_OUTLINE "\xf3\xb1\x97\x90" // U+F15D0 +#define ICON_MDI_HOME_ANALYTICS "\xf3\xb0\xba\xba" // U+F0EBA +#define ICON_MDI_HOME_ASSISTANT "\xf3\xb0\x9f\x90" // U+F07D0 +#define ICON_MDI_HOME_AUTOMATION "\xf3\xb0\x9f\x91" // U+F07D1 +#define ICON_MDI_HOME_BATTERY "\xf3\xb1\xa4\x81" // U+F1901 +#define ICON_MDI_HOME_BATTERY_OUTLINE "\xf3\xb1\xa4\x82" // U+F1902 +#define ICON_MDI_HOME_CIRCLE "\xf3\xb0\x9f\x92" // U+F07D2 +#define ICON_MDI_HOME_CIRCLE_OUTLINE "\xf3\xb1\x81\x8d" // U+F104D +#define ICON_MDI_HOME_CITY "\xf3\xb0\xb4\x95" // U+F0D15 +#define ICON_MDI_HOME_CITY_OUTLINE "\xf3\xb0\xb4\x96" // U+F0D16 +#define ICON_MDI_HOME_CLOCK "\xf3\xb1\xa8\x92" // U+F1A12 +#define ICON_MDI_HOME_CLOCK_OUTLINE "\xf3\xb1\xa8\x93" // U+F1A13 +#define ICON_MDI_HOME_EDIT "\xf3\xb1\x85\x99" // U+F1159 +#define ICON_MDI_HOME_EDIT_OUTLINE "\xf3\xb1\x85\x9a" // U+F115A +#define ICON_MDI_HOME_EXPORT_OUTLINE "\xf3\xb0\xbe\x9b" // U+F0F9B +#define ICON_MDI_HOME_FLOOD "\xf3\xb0\xbb\xba" // U+F0EFA +#define ICON_MDI_HOME_FLOOR_0 "\xf3\xb0\xb7\x92" // U+F0DD2 +#define ICON_MDI_HOME_FLOOR_1 "\xf3\xb0\xb6\x80" // U+F0D80 +#define ICON_MDI_HOME_FLOOR_2 "\xf3\xb0\xb6\x81" // U+F0D81 +#define ICON_MDI_HOME_FLOOR_3 "\xf3\xb0\xb6\x82" // U+F0D82 +#define ICON_MDI_HOME_FLOOR_A "\xf3\xb0\xb6\x83" // U+F0D83 +#define ICON_MDI_HOME_FLOOR_B "\xf3\xb0\xb6\x84" // U+F0D84 +#define ICON_MDI_HOME_FLOOR_G "\xf3\xb0\xb6\x85" // U+F0D85 +#define ICON_MDI_HOME_FLOOR_L "\xf3\xb0\xb6\x86" // U+F0D86 +#define ICON_MDI_HOME_FLOOR_NEGATIVE_1 "\xf3\xb0\xb7\x93" // U+F0DD3 +#define ICON_MDI_HOME_GROUP "\xf3\xb0\xb7\x94" // U+F0DD4 +#define ICON_MDI_HOME_GROUP_MINUS "\xf3\xb1\xa7\x81" // U+F19C1 +#define ICON_MDI_HOME_GROUP_PLUS "\xf3\xb1\xa7\x80" // U+F19C0 +#define ICON_MDI_HOME_GROUP_REMOVE "\xf3\xb1\xa7\x82" // U+F19C2 +#define ICON_MDI_HOME_HEART "\xf3\xb0\xa0\xa7" // U+F0827 +#define ICON_MDI_HOME_IMPORT_OUTLINE "\xf3\xb0\xbe\x9c" // U+F0F9C +#define ICON_MDI_HOME_LIGHTBULB "\xf3\xb1\x89\x91" // U+F1251 +#define ICON_MDI_HOME_LIGHTBULB_OUTLINE "\xf3\xb1\x89\x92" // U+F1252 +#define ICON_MDI_HOME_LIGHTNING_BOLT "\xf3\xb1\xa4\x83" // U+F1903 +#define ICON_MDI_HOME_LIGHTNING_BOLT_OUTLINE "\xf3\xb1\xa4\x84" // U+F1904 +#define ICON_MDI_HOME_LOCK "\xf3\xb0\xa3\xab" // U+F08EB +#define ICON_MDI_HOME_LOCK_OPEN "\xf3\xb0\xa3\xac" // U+F08EC +#define ICON_MDI_HOME_MAP_MARKER "\xf3\xb0\x97\xb8" // U+F05F8 +#define ICON_MDI_HOME_MINUS "\xf3\xb0\xa5\xb4" // U+F0974 +#define ICON_MDI_HOME_MINUS_OUTLINE "\xf3\xb1\x8f\x95" // U+F13D5 +#define ICON_MDI_HOME_MODERN "\xf3\xb0\x8b\x9d" // U+F02DD +#define ICON_MDI_HOME_OFF "\xf3\xb1\xa9\x86" // U+F1A46 +#define ICON_MDI_HOME_OFF_OUTLINE "\xf3\xb1\xa9\x87" // U+F1A47 +#define ICON_MDI_HOME_OUTLINE "\xf3\xb0\x9a\xa1" // U+F06A1 +#define ICON_MDI_HOME_PERCENT "\xf3\xb1\xb1\xbc" // U+F1C7C +#define ICON_MDI_HOME_PERCENT_OUTLINE "\xf3\xb1\xb1\xbd" // U+F1C7D +#define ICON_MDI_HOME_PLUS "\xf3\xb0\xa5\xb5" // U+F0975 +#define ICON_MDI_HOME_PLUS_OUTLINE "\xf3\xb1\x8f\x96" // U+F13D6 +#define ICON_MDI_HOME_REMOVE "\xf3\xb1\x89\x87" // U+F1247 +#define ICON_MDI_HOME_REMOVE_OUTLINE "\xf3\xb1\x8f\x97" // U+F13D7 +#define ICON_MDI_HOME_ROOF "\xf3\xb1\x84\xab" // U+F112B +#define ICON_MDI_HOME_SEARCH "\xf3\xb1\x8e\xb0" // U+F13B0 +#define ICON_MDI_HOME_SEARCH_OUTLINE "\xf3\xb1\x8e\xb1" // U+F13B1 +#define ICON_MDI_HOME_SILO "\xf3\xb1\xae\xa0" // U+F1BA0 +#define ICON_MDI_HOME_SILO_OUTLINE "\xf3\xb1\xae\xa1" // U+F1BA1 +#define ICON_MDI_HOME_SOUND_IN "\xf3\xb1\xb0\xaf" // U+F1C2F +#define ICON_MDI_HOME_SOUND_IN_OUTLINE "\xf3\xb1\xb0\xb0" // U+F1C30 +#define ICON_MDI_HOME_SOUND_OUT "\xf3\xb1\xb0\xb1" // U+F1C31 +#define ICON_MDI_HOME_SOUND_OUT_OUTLINE "\xf3\xb1\xb0\xb2" // U+F1C32 +#define ICON_MDI_HOME_SWITCH "\xf3\xb1\x9e\x94" // U+F1794 +#define ICON_MDI_HOME_SWITCH_OUTLINE "\xf3\xb1\x9e\x95" // U+F1795 +#define ICON_MDI_HOME_THERMOMETER "\xf3\xb0\xbd\x94" // U+F0F54 +#define ICON_MDI_HOME_THERMOMETER_OUTLINE "\xf3\xb0\xbd\x95" // U+F0F55 +#define ICON_MDI_HOME_VARIANT "\xf3\xb0\x8b\x9e" // U+F02DE +#define ICON_MDI_HOME_VARIANT_OUTLINE "\xf3\xb0\xae\xa7" // U+F0BA7 +#define ICON_MDI_HOOK "\xf3\xb0\x9b\xa2" // U+F06E2 +#define ICON_MDI_HOOK_OFF "\xf3\xb0\x9b\xa3" // U+F06E3 +#define ICON_MDI_HOOP_HOUSE "\xf3\xb0\xb9\x96" // U+F0E56 +#define ICON_MDI_HOPS "\xf3\xb0\x8b\x9f" // U+F02DF +#define ICON_MDI_HORIZONTAL_ROTATE_CLOCKWISE "\xf3\xb1\x83\xb3" // U+F10F3 +#define ICON_MDI_HORIZONTAL_ROTATE_COUNTERCLOCKWISE "\xf3\xb1\x83\xb4" // U+F10F4 +#define ICON_MDI_HORSE "\xf3\xb1\x96\xbf" // U+F15BF +#define ICON_MDI_HORSE_HUMAN "\xf3\xb1\x97\x80" // U+F15C0 +#define ICON_MDI_HORSE_VARIANT "\xf3\xb1\x97\x81" // U+F15C1 +#define ICON_MDI_HORSE_VARIANT_FAST "\xf3\xb1\xa1\xae" // U+F186E +#define ICON_MDI_HORSESHOE "\xf3\xb0\xa9\x98" // U+F0A58 +#define ICON_MDI_HOSPITAL "\xf3\xb0\xbf\xb6" // U+F0FF6 +#define ICON_MDI_HOSPITAL_BOX "\xf3\xb0\x8b\xa0" // U+F02E0 +#define ICON_MDI_HOSPITAL_BOX_OUTLINE "\xf3\xb0\xbf\xb7" // U+F0FF7 +#define ICON_MDI_HOSPITAL_BUILDING "\xf3\xb0\x8b\xa1" // U+F02E1 +#define ICON_MDI_HOSPITAL_MARKER "\xf3\xb0\x8b\xa2" // U+F02E2 +#define ICON_MDI_HOT_TUB "\xf3\xb0\xa0\xa8" // U+F0828 +#define ICON_MDI_HOURS_12 "\xf3\xb1\xb2\x94" // U+F1C94 +#define ICON_MDI_HOURS_24 "\xf3\xb1\x91\xb8" // U+F1478 +#define ICON_MDI_HUB "\xf3\xb1\xb2\x95" // U+F1C95 +#define ICON_MDI_HUB_OUTLINE "\xf3\xb1\xb2\x96" // U+F1C96 +#define ICON_MDI_HUBSPOT "\xf3\xb0\xb4\x97" // U+F0D17 +#define ICON_MDI_HULU "\xf3\xb0\xa0\xa9" // U+F0829 +#define ICON_MDI_HUMAN "\xf3\xb0\x8b\xa6" // U+F02E6 +#define ICON_MDI_HUMAN_BABY_CHANGING_TABLE "\xf3\xb1\x8e\x8b" // U+F138B +#define ICON_MDI_HUMAN_CANE "\xf3\xb1\x96\x81" // U+F1581 +#define ICON_MDI_HUMAN_CAPACITY_DECREASE "\xf3\xb1\x96\x9b" // U+F159B +#define ICON_MDI_HUMAN_CAPACITY_INCREASE "\xf3\xb1\x96\x9c" // U+F159C +#define ICON_MDI_HUMAN_CHILD "\xf3\xb0\x8b\xa7" // U+F02E7 +#define ICON_MDI_HUMAN_DOLLY "\xf3\xb1\xa6\x80" // U+F1980 +#define ICON_MDI_HUMAN_EDIT "\xf3\xb1\x93\xa8" // U+F14E8 +#define ICON_MDI_HUMAN_FEMALE "\xf3\xb0\x99\x89" // U+F0649 +#define ICON_MDI_HUMAN_FEMALE_BOY "\xf3\xb0\xa9\x99" // U+F0A59 +#define ICON_MDI_HUMAN_FEMALE_DANCE "\xf3\xb1\x97\x89" // U+F15C9 +#define ICON_MDI_HUMAN_FEMALE_FEMALE "\xf3\xb0\xa9\x9a" // U+F0A5A +#define ICON_MDI_HUMAN_FEMALE_FEMALE_CHILD "\xf3\xb1\xb2\x8e" // U+F1C8E +#define ICON_MDI_HUMAN_FEMALE_GIRL "\xf3\xb0\xa9\x9b" // U+F0A5B +#define ICON_MDI_HUMAN_GREETING "\xf3\xb1\x9f\x84" // U+F17C4 +#define ICON_MDI_HUMAN_GREETING_PROXIMITY "\xf3\xb1\x96\x9d" // U+F159D +#define ICON_MDI_HUMAN_GREETING_VARIANT "\xf3\xb0\x99\x8a" // U+F064A +#define ICON_MDI_HUMAN_HANDSDOWN "\xf3\xb0\x99\x8b" // U+F064B +#define ICON_MDI_HUMAN_HANDSUP "\xf3\xb0\x99\x8c" // U+F064C +#define ICON_MDI_HUMAN_MALE "\xf3\xb0\x99\x8d" // U+F064D +#define ICON_MDI_HUMAN_MALE_BOARD "\xf3\xb0\xa2\x90" // U+F0890 +#define ICON_MDI_HUMAN_MALE_BOARD_POLL "\xf3\xb0\xa1\x86" // U+F0846 +#define ICON_MDI_HUMAN_MALE_BOY "\xf3\xb0\xa9\x9c" // U+F0A5C +#define ICON_MDI_HUMAN_MALE_CHILD "\xf3\xb1\x8e\x8c" // U+F138C +#define ICON_MDI_HUMAN_MALE_FEMALE "\xf3\xb0\x8b\xa8" // U+F02E8 +#define ICON_MDI_HUMAN_MALE_FEMALE_CHILD "\xf3\xb1\xa0\xa3" // U+F1823 +#define ICON_MDI_HUMAN_MALE_GIRL "\xf3\xb0\xa9\x9d" // U+F0A5D +#define ICON_MDI_HUMAN_MALE_HEIGHT "\xf3\xb0\xbb\xbb" // U+F0EFB +#define ICON_MDI_HUMAN_MALE_HEIGHT_VARIANT "\xf3\xb0\xbb\xbc" // U+F0EFC +#define ICON_MDI_HUMAN_MALE_MALE "\xf3\xb0\xa9\x9e" // U+F0A5E +#define ICON_MDI_HUMAN_MALE_MALE_CHILD "\xf3\xb1\xb2\x8f" // U+F1C8F +#define ICON_MDI_HUMAN_NON_BINARY "\xf3\xb1\xa1\x88" // U+F1848 +#define ICON_MDI_HUMAN_PREGNANT "\xf3\xb0\x97\x8f" // U+F05CF +#define ICON_MDI_HUMAN_QUEUE "\xf3\xb1\x95\xb1" // U+F1571 +#define ICON_MDI_HUMAN_SCOOTER "\xf3\xb1\x87\xa9" // U+F11E9 +#define ICON_MDI_HUMAN_WALKER "\xf3\xb1\xad\xb1" // U+F1B71 +#define ICON_MDI_HUMAN_WHEELCHAIR "\xf3\xb1\x8e\x8d" // U+F138D +#define ICON_MDI_HUMAN_WHITE_CANE "\xf3\xb1\xa6\x81" // U+F1981 +#define ICON_MDI_HUMBLE_BUNDLE "\xf3\xb0\x9d\x84" // U+F0744 +#define ICON_MDI_HVAC "\xf3\xb1\x8d\x92" // U+F1352 +#define ICON_MDI_HVAC_OFF "\xf3\xb1\x96\x9e" // U+F159E +#define ICON_MDI_HYDRAULIC_OIL_LEVEL "\xf3\xb1\x8c\xa4" // U+F1324 +#define ICON_MDI_HYDRAULIC_OIL_TEMPERATURE "\xf3\xb1\x8c\xa5" // U+F1325 +#define ICON_MDI_HYDRO_POWER "\xf3\xb1\x8b\xa5" // U+F12E5 +#define ICON_MDI_HYDROGEN_STATION "\xf3\xb1\xa2\x94" // U+F1894 +#define ICON_MDI_ICE_CREAM "\xf3\xb0\xa0\xaa" // U+F082A +#define ICON_MDI_ICE_CREAM_OFF "\xf3\xb0\xb9\x92" // U+F0E52 +#define ICON_MDI_ICE_POP "\xf3\xb0\xbb\xbd" // U+F0EFD +#define ICON_MDI_ID_CARD "\xf3\xb0\xbf\x80" // U+F0FC0 +#define ICON_MDI_IDENTIFIER "\xf3\xb0\xbb\xbe" // U+F0EFE +#define ICON_MDI_IDEOGRAM_CJK "\xf3\xb1\x8c\xb1" // U+F1331 +#define ICON_MDI_IDEOGRAM_CJK_VARIANT "\xf3\xb1\x8c\xb2" // U+F1332 +#define ICON_MDI_IMAGE "\xf3\xb0\x8b\xa9" // U+F02E9 +#define ICON_MDI_IMAGE_ALBUM "\xf3\xb0\x8b\xaa" // U+F02EA +#define ICON_MDI_IMAGE_AREA "\xf3\xb0\x8b\xab" // U+F02EB +#define ICON_MDI_IMAGE_AREA_CLOSE "\xf3\xb0\x8b\xac" // U+F02EC +#define ICON_MDI_IMAGE_AUTO_ADJUST "\xf3\xb0\xbf\x81" // U+F0FC1 +#define ICON_MDI_IMAGE_BROKEN "\xf3\xb0\x8b\xad" // U+F02ED +#define ICON_MDI_IMAGE_BROKEN_VARIANT "\xf3\xb0\x8b\xae" // U+F02EE +#define ICON_MDI_IMAGE_CHECK "\xf3\xb1\xac\xa5" // U+F1B25 +#define ICON_MDI_IMAGE_CHECK_OUTLINE "\xf3\xb1\xac\xa6" // U+F1B26 +#define ICON_MDI_IMAGE_EDIT "\xf3\xb1\x87\xa3" // U+F11E3 +#define ICON_MDI_IMAGE_EDIT_OUTLINE "\xf3\xb1\x87\xa4" // U+F11E4 +#define ICON_MDI_IMAGE_FILTER_BLACK_WHITE "\xf3\xb0\x8b\xb0" // U+F02F0 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS "\xf3\xb0\x8b\xb1" // U+F02F1 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_STRONG "\xf3\xb0\xbb\xbf" // U+F0EFF +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_STRONG_OUTLINE "\xf3\xb0\xbc\x80" // U+F0F00 +#define ICON_MDI_IMAGE_FILTER_CENTER_FOCUS_WEAK "\xf3\xb0\x8b\xb2" // U+F02F2 +#define ICON_MDI_IMAGE_FILTER_DRAMA "\xf3\xb0\x8b\xb3" // U+F02F3 +#define ICON_MDI_IMAGE_FILTER_DRAMA_OUTLINE "\xf3\xb1\xaf\xbf" // U+F1BFF +#define ICON_MDI_IMAGE_FILTER_FRAMES "\xf3\xb0\x8b\xb4" // U+F02F4 +#define ICON_MDI_IMAGE_FILTER_HDR "\xf3\xb0\x8b\xb5" // U+F02F5 +#define ICON_MDI_IMAGE_FILTER_HDR_OUTLINE "\xf3\xb1\xb1\xa4" // U+F1C64 +#define ICON_MDI_IMAGE_FILTER_NONE "\xf3\xb0\x8b\xb6" // U+F02F6 +#define ICON_MDI_IMAGE_FILTER_TILT_SHIFT "\xf3\xb0\x8b\xb7" // U+F02F7 +#define ICON_MDI_IMAGE_FILTER_VINTAGE "\xf3\xb0\x8b\xb8" // U+F02F8 +#define ICON_MDI_IMAGE_FRAME "\xf3\xb0\xb9\x89" // U+F0E49 +#define ICON_MDI_IMAGE_LOCK "\xf3\xb1\xaa\xb0" // U+F1AB0 +#define ICON_MDI_IMAGE_LOCK_OUTLINE "\xf3\xb1\xaa\xb1" // U+F1AB1 +#define ICON_MDI_IMAGE_MARKER "\xf3\xb1\x9d\xbb" // U+F177B +#define ICON_MDI_IMAGE_MARKER_OUTLINE "\xf3\xb1\x9d\xbc" // U+F177C +#define ICON_MDI_IMAGE_MINUS "\xf3\xb1\x90\x99" // U+F1419 +#define ICON_MDI_IMAGE_MINUS_OUTLINE "\xf3\xb1\xad\x87" // U+F1B47 +#define ICON_MDI_IMAGE_MOVE "\xf3\xb0\xa7\xb8" // U+F09F8 +#define ICON_MDI_IMAGE_MULTIPLE "\xf3\xb0\x8b\xb9" // U+F02F9 +#define ICON_MDI_IMAGE_MULTIPLE_OUTLINE "\xf3\xb0\x8b\xaf" // U+F02EF +#define ICON_MDI_IMAGE_OFF "\xf3\xb0\xa0\xab" // U+F082B +#define ICON_MDI_IMAGE_OFF_OUTLINE "\xf3\xb1\x87\x91" // U+F11D1 +#define ICON_MDI_IMAGE_OUTLINE "\xf3\xb0\xa5\xb6" // U+F0976 +#define ICON_MDI_IMAGE_PLUS "\xf3\xb0\xa1\xbc" // U+F087C +#define ICON_MDI_IMAGE_PLUS_OUTLINE "\xf3\xb1\xad\x86" // U+F1B46 +#define ICON_MDI_IMAGE_REFRESH "\xf3\xb1\xa7\xbe" // U+F19FE +#define ICON_MDI_IMAGE_REFRESH_OUTLINE "\xf3\xb1\xa7\xbf" // U+F19FF +#define ICON_MDI_IMAGE_REMOVE "\xf3\xb1\x90\x98" // U+F1418 +#define ICON_MDI_IMAGE_REMOVE_OUTLINE "\xf3\xb1\xad\x88" // U+F1B48 +#define ICON_MDI_IMAGE_SEARCH "\xf3\xb0\xa5\xb7" // U+F0977 +#define ICON_MDI_IMAGE_SEARCH_OUTLINE "\xf3\xb0\xa5\xb8" // U+F0978 +#define ICON_MDI_IMAGE_SIZE_SELECT_ACTUAL "\xf3\xb0\xb2\x8d" // U+F0C8D +#define ICON_MDI_IMAGE_SIZE_SELECT_LARGE "\xf3\xb0\xb2\x8e" // U+F0C8E +#define ICON_MDI_IMAGE_SIZE_SELECT_SMALL "\xf3\xb0\xb2\x8f" // U+F0C8F +#define ICON_MDI_IMAGE_SYNC "\xf3\xb1\xa8\x80" // U+F1A00 +#define ICON_MDI_IMAGE_SYNC_OUTLINE "\xf3\xb1\xa8\x81" // U+F1A01 +#define ICON_MDI_IMAGE_TEXT "\xf3\xb1\x98\x8d" // U+F160D +#define ICON_MDI_IMPORT "\xf3\xb0\x8b\xba" // U+F02FA +#define ICON_MDI_INBOX "\xf3\xb0\x9a\x87" // U+F0687 +#define ICON_MDI_INBOX_ARROW_DOWN "\xf3\xb0\x8b\xbb" // U+F02FB +#define ICON_MDI_INBOX_ARROW_DOWN_OUTLINE "\xf3\xb1\x89\xb0" // U+F1270 +#define ICON_MDI_INBOX_ARROW_UP "\xf3\xb0\x8f\x91" // U+F03D1 +#define ICON_MDI_INBOX_ARROW_UP_OUTLINE "\xf3\xb1\x89\xb1" // U+F1271 +#define ICON_MDI_INBOX_FULL "\xf3\xb1\x89\xb2" // U+F1272 +#define ICON_MDI_INBOX_FULL_OUTLINE "\xf3\xb1\x89\xb3" // U+F1273 +#define ICON_MDI_INBOX_MULTIPLE "\xf3\xb0\xa2\xb0" // U+F08B0 +#define ICON_MDI_INBOX_MULTIPLE_OUTLINE "\xf3\xb0\xae\xa8" // U+F0BA8 +#define ICON_MDI_INBOX_OUTLINE "\xf3\xb1\x89\xb4" // U+F1274 +#define ICON_MDI_INBOX_REMOVE "\xf3\xb1\x96\x9f" // U+F159F +#define ICON_MDI_INBOX_REMOVE_OUTLINE "\xf3\xb1\x96\xa0" // U+F15A0 +#define ICON_MDI_INCOGNITO "\xf3\xb0\x97\xb9" // U+F05F9 +#define ICON_MDI_INCOGNITO_CIRCLE "\xf3\xb1\x90\xa1" // U+F1421 +#define ICON_MDI_INCOGNITO_CIRCLE_OFF "\xf3\xb1\x90\xa2" // U+F1422 +#define ICON_MDI_INCOGNITO_OFF "\xf3\xb0\x81\xb5" // U+F0075 +#define ICON_MDI_INDUCTION "\xf3\xb1\xa1\x8c" // U+F184C +#define ICON_MDI_INFINITY "\xf3\xb0\x9b\xa4" // U+F06E4 +#define ICON_MDI_INFORMATION "\xf3\xb0\x8b\xbc" // U+F02FC +#define ICON_MDI_INFORMATION_BOX "\xf3\xb1\xb1\xa5" // U+F1C65 +#define ICON_MDI_INFORMATION_BOX_OUTLINE "\xf3\xb1\xb1\xa6" // U+F1C66 +#define ICON_MDI_INFORMATION_OFF "\xf3\xb1\x9e\x8c" // U+F178C +#define ICON_MDI_INFORMATION_OFF_OUTLINE "\xf3\xb1\x9e\x8d" // U+F178D +#define ICON_MDI_INFORMATION_OUTLINE "\xf3\xb0\x8b\xbd" // U+F02FD +#define ICON_MDI_INFORMATION_SLAB_BOX "\xf3\xb1\xb1\xa7" // U+F1C67 +#define ICON_MDI_INFORMATION_SLAB_BOX_OUTLINE "\xf3\xb1\xb1\xa8" // U+F1C68 +#define ICON_MDI_INFORMATION_SLAB_CIRCLE "\xf3\xb1\xb1\xa9" // U+F1C69 +#define ICON_MDI_INFORMATION_SLAB_CIRCLE_OUTLINE "\xf3\xb1\xb1\xaa" // U+F1C6A +#define ICON_MDI_INFORMATION_SLAB_SYMBOL "\xf3\xb1\xb1\xab" // U+F1C6B +#define ICON_MDI_INFORMATION_SYMBOL "\xf3\xb1\xb1\xac" // U+F1C6C +#define ICON_MDI_INFORMATION_VARIANT "\xf3\xb0\x99\x8e" // U+F064E +#define ICON_MDI_INFORMATION_VARIANT_BOX "\xf3\xb1\xb1\xad" // U+F1C6D +#define ICON_MDI_INFORMATION_VARIANT_BOX_OUTLINE "\xf3\xb1\xb1\xae" // U+F1C6E +#define ICON_MDI_INFORMATION_VARIANT_CIRCLE "\xf3\xb1\xb1\xaf" // U+F1C6F +#define ICON_MDI_INFORMATION_VARIANT_CIRCLE_OUTLINE "\xf3\xb1\xb1\xb0" // U+F1C70 +#define ICON_MDI_INSTAGRAM "\xf3\xb0\x8b\xbe" // U+F02FE +#define ICON_MDI_INSTRUMENT_TRIANGLE "\xf3\xb1\x81\x8e" // U+F104E +#define ICON_MDI_INTEGRATED_CIRCUIT_CHIP "\xf3\xb1\xa4\x93" // U+F1913 +#define ICON_MDI_INVERT_COLORS "\xf3\xb0\x8c\x81" // U+F0301 +#define ICON_MDI_INVERT_COLORS_OFF "\xf3\xb0\xb9\x8a" // U+F0E4A +#define ICON_MDI_IOBROKER "\xf3\xb1\x8b\xa8" // U+F12E8 +#define ICON_MDI_IP "\xf3\xb0\xa9\x9f" // U+F0A5F +#define ICON_MDI_IP_NETWORK "\xf3\xb0\xa9\xa0" // U+F0A60 +#define ICON_MDI_IP_NETWORK_OUTLINE "\xf3\xb0\xb2\x90" // U+F0C90 +#define ICON_MDI_IP_OUTLINE "\xf3\xb1\xa6\x82" // U+F1982 +#define ICON_MDI_IPOD "\xf3\xb0\xb2\x91" // U+F0C91 +#define ICON_MDI_IRON "\xf3\xb1\xa0\xa4" // U+F1824 +#define ICON_MDI_IRON_BOARD "\xf3\xb1\xa0\xb8" // U+F1838 +#define ICON_MDI_IRON_OUTLINE "\xf3\xb1\xa0\xa5" // U+F1825 +#define ICON_MDI_ISLAND "\xf3\xb1\x81\x8f" // U+F104F +#define ICON_MDI_ISLAND_VARIANT "\xf3\xb1\xb3\x86" // U+F1CC6 +#define ICON_MDI_IV_BAG "\xf3\xb1\x82\xb9" // U+F10B9 +#define ICON_MDI_JABBER "\xf3\xb0\xb7\x95" // U+F0DD5 +#define ICON_MDI_JEEPNEY "\xf3\xb0\x8c\x82" // U+F0302 +#define ICON_MDI_JELLYFISH "\xf3\xb0\xbc\x81" // U+F0F01 +#define ICON_MDI_JELLYFISH_OUTLINE "\xf3\xb0\xbc\x82" // U+F0F02 +#define ICON_MDI_JIRA "\xf3\xb0\x8c\x83" // U+F0303 +#define ICON_MDI_JQUERY "\xf3\xb0\xa1\xbd" // U+F087D +#define ICON_MDI_JSFIDDLE "\xf3\xb0\x8c\x84" // U+F0304 +#define ICON_MDI_JUMP_ROPE "\xf3\xb1\x8b\xbf" // U+F12FF +#define ICON_MDI_KABADDI "\xf3\xb0\xb6\x87" // U+F0D87 +#define ICON_MDI_KANGAROO "\xf3\xb1\x95\x98" // U+F1558 +#define ICON_MDI_KARATE "\xf3\xb0\xa0\xac" // U+F082C +#define ICON_MDI_KAYAKING "\xf3\xb0\xa2\xaf" // U+F08AF +#define ICON_MDI_KEG "\xf3\xb0\x8c\x85" // U+F0305 +#define ICON_MDI_KETTLE "\xf3\xb0\x97\xba" // U+F05FA +#define ICON_MDI_KETTLE_ALERT "\xf3\xb1\x8c\x97" // U+F1317 +#define ICON_MDI_KETTLE_ALERT_OUTLINE "\xf3\xb1\x8c\x98" // U+F1318 +#define ICON_MDI_KETTLE_OFF "\xf3\xb1\x8c\x9b" // U+F131B +#define ICON_MDI_KETTLE_OFF_OUTLINE "\xf3\xb1\x8c\x9c" // U+F131C +#define ICON_MDI_KETTLE_OUTLINE "\xf3\xb0\xbd\x96" // U+F0F56 +#define ICON_MDI_KETTLE_POUR_OVER "\xf3\xb1\x9c\xbc" // U+F173C +#define ICON_MDI_KETTLE_STEAM "\xf3\xb1\x8c\x99" // U+F1319 +#define ICON_MDI_KETTLE_STEAM_OUTLINE "\xf3\xb1\x8c\x9a" // U+F131A +#define ICON_MDI_KETTLEBELL "\xf3\xb1\x8c\x80" // U+F1300 +#define ICON_MDI_KEY "\xf3\xb0\x8c\x86" // U+F0306 +#define ICON_MDI_KEY_ALERT "\xf3\xb1\xa6\x83" // U+F1983 +#define ICON_MDI_KEY_ALERT_OUTLINE "\xf3\xb1\xa6\x84" // U+F1984 +#define ICON_MDI_KEY_ARROW_RIGHT "\xf3\xb1\x8c\x92" // U+F1312 +#define ICON_MDI_KEY_CHAIN "\xf3\xb1\x95\xb4" // U+F1574 +#define ICON_MDI_KEY_CHAIN_VARIANT "\xf3\xb1\x95\xb5" // U+F1575 +#define ICON_MDI_KEY_CHANGE "\xf3\xb0\x8c\x87" // U+F0307 +#define ICON_MDI_KEY_LINK "\xf3\xb1\x86\x9f" // U+F119F +#define ICON_MDI_KEY_MINUS "\xf3\xb0\x8c\x88" // U+F0308 +#define ICON_MDI_KEY_OUTLINE "\xf3\xb0\xb7\x96" // U+F0DD6 +#define ICON_MDI_KEY_PLUS "\xf3\xb0\x8c\x89" // U+F0309 +#define ICON_MDI_KEY_REMOVE "\xf3\xb0\x8c\x8a" // U+F030A +#define ICON_MDI_KEY_STAR "\xf3\xb1\x86\x9e" // U+F119E +#define ICON_MDI_KEY_VARIANT "\xf3\xb0\x8c\x8b" // U+F030B +#define ICON_MDI_KEY_WIRELESS "\xf3\xb0\xbf\x82" // U+F0FC2 +#define ICON_MDI_KEYBOARD "\xf3\xb0\x8c\x8c" // U+F030C +#define ICON_MDI_KEYBOARD_BACKSPACE "\xf3\xb0\x8c\x8d" // U+F030D +#define ICON_MDI_KEYBOARD_CAPS "\xf3\xb0\x8c\x8e" // U+F030E +#define ICON_MDI_KEYBOARD_CLOSE "\xf3\xb0\x8c\x8f" // U+F030F +#define ICON_MDI_KEYBOARD_CLOSE_OUTLINE "\xf3\xb1\xb0\x80" // U+F1C00 +#define ICON_MDI_KEYBOARD_ESC "\xf3\xb1\x8a\xb7" // U+F12B7 +#define ICON_MDI_KEYBOARD_F1 "\xf3\xb1\x8a\xab" // U+F12AB +#define ICON_MDI_KEYBOARD_F10 "\xf3\xb1\x8a\xb4" // U+F12B4 +#define ICON_MDI_KEYBOARD_F11 "\xf3\xb1\x8a\xb5" // U+F12B5 +#define ICON_MDI_KEYBOARD_F12 "\xf3\xb1\x8a\xb6" // U+F12B6 +#define ICON_MDI_KEYBOARD_F2 "\xf3\xb1\x8a\xac" // U+F12AC +#define ICON_MDI_KEYBOARD_F3 "\xf3\xb1\x8a\xad" // U+F12AD +#define ICON_MDI_KEYBOARD_F4 "\xf3\xb1\x8a\xae" // U+F12AE +#define ICON_MDI_KEYBOARD_F5 "\xf3\xb1\x8a\xaf" // U+F12AF +#define ICON_MDI_KEYBOARD_F6 "\xf3\xb1\x8a\xb0" // U+F12B0 +#define ICON_MDI_KEYBOARD_F7 "\xf3\xb1\x8a\xb1" // U+F12B1 +#define ICON_MDI_KEYBOARD_F8 "\xf3\xb1\x8a\xb2" // U+F12B2 +#define ICON_MDI_KEYBOARD_F9 "\xf3\xb1\x8a\xb3" // U+F12B3 +#define ICON_MDI_KEYBOARD_OFF "\xf3\xb0\x8c\x90" // U+F0310 +#define ICON_MDI_KEYBOARD_OFF_OUTLINE "\xf3\xb0\xb9\x8b" // U+F0E4B +#define ICON_MDI_KEYBOARD_OUTLINE "\xf3\xb0\xa5\xbb" // U+F097B +#define ICON_MDI_KEYBOARD_RETURN "\xf3\xb0\x8c\x91" // U+F0311 +#define ICON_MDI_KEYBOARD_SETTINGS "\xf3\xb0\xa7\xb9" // U+F09F9 +#define ICON_MDI_KEYBOARD_SETTINGS_OUTLINE "\xf3\xb0\xa7\xba" // U+F09FA +#define ICON_MDI_KEYBOARD_SPACE "\xf3\xb1\x81\x90" // U+F1050 +#define ICON_MDI_KEYBOARD_TAB "\xf3\xb0\x8c\x92" // U+F0312 +#define ICON_MDI_KEYBOARD_TAB_REVERSE "\xf3\xb0\x8c\xa5" // U+F0325 +#define ICON_MDI_KEYBOARD_VARIANT "\xf3\xb0\x8c\x93" // U+F0313 +#define ICON_MDI_KHANDA "\xf3\xb1\x83\xbd" // U+F10FD +#define ICON_MDI_KICKSTARTER "\xf3\xb0\x9d\x85" // U+F0745 +#define ICON_MDI_KITE "\xf3\xb1\xa6\x85" // U+F1985 +#define ICON_MDI_KITE_OUTLINE "\xf3\xb1\xa6\x86" // U+F1986 +#define ICON_MDI_KITESURFING "\xf3\xb1\x9d\x84" // U+F1744 +#define ICON_MDI_KLINGON "\xf3\xb1\x8d\x9b" // U+F135B +#define ICON_MDI_KNIFE "\xf3\xb0\xa7\xbb" // U+F09FB +#define ICON_MDI_KNIFE_MILITARY "\xf3\xb0\xa7\xbc" // U+F09FC +#define ICON_MDI_KNOB "\xf3\xb1\xae\x96" // U+F1B96 +#define ICON_MDI_KOALA "\xf3\xb1\x9c\xbf" // U+F173F +#define ICON_MDI_KODI "\xf3\xb0\x8c\x94" // U+F0314 +#define ICON_MDI_KUBERNETES "\xf3\xb1\x83\xbe" // U+F10FE +#define ICON_MDI_LABEL "\xf3\xb0\x8c\x95" // U+F0315 +#define ICON_MDI_LABEL_MULTIPLE "\xf3\xb1\x8d\xb5" // U+F1375 +#define ICON_MDI_LABEL_MULTIPLE_OUTLINE "\xf3\xb1\x8d\xb6" // U+F1376 +#define ICON_MDI_LABEL_OFF "\xf3\xb0\xab\x8b" // U+F0ACB +#define ICON_MDI_LABEL_OFF_OUTLINE "\xf3\xb0\xab\x8c" // U+F0ACC +#define ICON_MDI_LABEL_OUTLINE "\xf3\xb0\x8c\x96" // U+F0316 +#define ICON_MDI_LABEL_PERCENT "\xf3\xb1\x8b\xaa" // U+F12EA +#define ICON_MDI_LABEL_PERCENT_OUTLINE "\xf3\xb1\x8b\xab" // U+F12EB +#define ICON_MDI_LABEL_VARIANT "\xf3\xb0\xab\x8d" // U+F0ACD +#define ICON_MDI_LABEL_VARIANT_OUTLINE "\xf3\xb0\xab\x8e" // U+F0ACE +#define ICON_MDI_LADDER "\xf3\xb1\x96\xa2" // U+F15A2 +#define ICON_MDI_LADYBUG "\xf3\xb0\xa0\xad" // U+F082D +#define ICON_MDI_LAMBDA "\xf3\xb0\x98\xa7" // U+F0627 +#define ICON_MDI_LAMP "\xf3\xb0\x9a\xb5" // U+F06B5 +#define ICON_MDI_LAMP_OUTLINE "\xf3\xb1\x9f\x90" // U+F17D0 +#define ICON_MDI_LAMPS "\xf3\xb1\x95\xb6" // U+F1576 +#define ICON_MDI_LAMPS_OUTLINE "\xf3\xb1\x9f\x91" // U+F17D1 +#define ICON_MDI_LAN "\xf3\xb0\x8c\x97" // U+F0317 +#define ICON_MDI_LAN_CHECK "\xf3\xb1\x8a\xaa" // U+F12AA +#define ICON_MDI_LAN_CONNECT "\xf3\xb0\x8c\x98" // U+F0318 +#define ICON_MDI_LAN_DISCONNECT "\xf3\xb0\x8c\x99" // U+F0319 +#define ICON_MDI_LAN_PENDING "\xf3\xb0\x8c\x9a" // U+F031A +#define ICON_MDI_LAND_FIELDS "\xf3\xb1\xaa\xb2" // U+F1AB2 +#define ICON_MDI_LAND_PLOTS "\xf3\xb1\xaa\xb3" // U+F1AB3 +#define ICON_MDI_LAND_PLOTS_CIRCLE "\xf3\xb1\xaa\xb4" // U+F1AB4 +#define ICON_MDI_LAND_PLOTS_CIRCLE_VARIANT "\xf3\xb1\xaa\xb5" // U+F1AB5 +#define ICON_MDI_LAND_PLOTS_MARKER "\xf3\xb1\xb1\x9d" // U+F1C5D +#define ICON_MDI_LAND_ROWS_HORIZONTAL "\xf3\xb1\xaa\xb6" // U+F1AB6 +#define ICON_MDI_LAND_ROWS_VERTICAL "\xf3\xb1\xaa\xb7" // U+F1AB7 +#define ICON_MDI_LANDSLIDE "\xf3\xb1\xa9\x88" // U+F1A48 +#define ICON_MDI_LANDSLIDE_OUTLINE "\xf3\xb1\xa9\x89" // U+F1A49 +#define ICON_MDI_LANGUAGE_C "\xf3\xb0\x99\xb1" // U+F0671 +#define ICON_MDI_LANGUAGE_CPP "\xf3\xb0\x99\xb2" // U+F0672 +#define ICON_MDI_LANGUAGE_CSHARP "\xf3\xb0\x8c\x9b" // U+F031B +#define ICON_MDI_LANGUAGE_CSS3 "\xf3\xb0\x8c\x9c" // U+F031C +#define ICON_MDI_LANGUAGE_FORTRAN "\xf3\xb1\x88\x9a" // U+F121A +#define ICON_MDI_LANGUAGE_GO "\xf3\xb0\x9f\x93" // U+F07D3 +#define ICON_MDI_LANGUAGE_HASKELL "\xf3\xb0\xb2\x92" // U+F0C92 +#define ICON_MDI_LANGUAGE_HTML5 "\xf3\xb0\x8c\x9d" // U+F031D +#define ICON_MDI_LANGUAGE_JAVA "\xf3\xb0\xac\xb7" // U+F0B37 +#define ICON_MDI_LANGUAGE_JAVASCRIPT "\xf3\xb0\x8c\x9e" // U+F031E +#define ICON_MDI_LANGUAGE_KOTLIN "\xf3\xb1\x88\x99" // U+F1219 +#define ICON_MDI_LANGUAGE_LUA "\xf3\xb0\xa2\xb1" // U+F08B1 +#define ICON_MDI_LANGUAGE_MARKDOWN "\xf3\xb0\x8d\x94" // U+F0354 +#define ICON_MDI_LANGUAGE_MARKDOWN_OUTLINE "\xf3\xb0\xbd\x9b" // U+F0F5B +#define ICON_MDI_LANGUAGE_PHP "\xf3\xb0\x8c\x9f" // U+F031F +#define ICON_MDI_LANGUAGE_PYTHON "\xf3\xb0\x8c\xa0" // U+F0320 +#define ICON_MDI_LANGUAGE_R "\xf3\xb0\x9f\x94" // U+F07D4 +#define ICON_MDI_LANGUAGE_RUBY "\xf3\xb0\xb4\xad" // U+F0D2D +#define ICON_MDI_LANGUAGE_RUBY_ON_RAILS "\xf3\xb0\xab\x8f" // U+F0ACF +#define ICON_MDI_LANGUAGE_RUST "\xf3\xb1\x98\x97" // U+F1617 +#define ICON_MDI_LANGUAGE_SWIFT "\xf3\xb0\x9b\xa5" // U+F06E5 +#define ICON_MDI_LANGUAGE_TYPESCRIPT "\xf3\xb0\x9b\xa6" // U+F06E6 +#define ICON_MDI_LANGUAGE_XAML "\xf3\xb0\x99\xb3" // U+F0673 +#define ICON_MDI_LAPTOP "\xf3\xb0\x8c\xa2" // U+F0322 +#define ICON_MDI_LAPTOP_ACCOUNT "\xf3\xb1\xa9\x8a" // U+F1A4A +#define ICON_MDI_LAPTOP_OFF "\xf3\xb0\x9b\xa7" // U+F06E7 +#define ICON_MDI_LARAVEL "\xf3\xb0\xab\x90" // U+F0AD0 +#define ICON_MDI_LASER_POINTER "\xf3\xb1\x92\x84" // U+F1484 +#define ICON_MDI_LASSO "\xf3\xb0\xbc\x83" // U+F0F03 +#define ICON_MDI_LASTPASS "\xf3\xb0\x91\x86" // U+F0446 +#define ICON_MDI_LATITUDE "\xf3\xb0\xbd\x97" // U+F0F57 +#define ICON_MDI_LAUNCH "\xf3\xb0\x8c\xa7" // U+F0327 +#define ICON_MDI_LAVA_LAMP "\xf3\xb0\x9f\x95" // U+F07D5 +#define ICON_MDI_LAYERS "\xf3\xb0\x8c\xa8" // U+F0328 +#define ICON_MDI_LAYERS_EDIT "\xf3\xb1\xa2\x92" // U+F1892 +#define ICON_MDI_LAYERS_MINUS "\xf3\xb0\xb9\x8c" // U+F0E4C +#define ICON_MDI_LAYERS_OFF "\xf3\xb0\x8c\xa9" // U+F0329 +#define ICON_MDI_LAYERS_OFF_OUTLINE "\xf3\xb0\xa7\xbd" // U+F09FD +#define ICON_MDI_LAYERS_OUTLINE "\xf3\xb0\xa7\xbe" // U+F09FE +#define ICON_MDI_LAYERS_PLUS "\xf3\xb0\xb9\x8d" // U+F0E4D +#define ICON_MDI_LAYERS_REMOVE "\xf3\xb0\xb9\x8e" // U+F0E4E +#define ICON_MDI_LAYERS_SEARCH "\xf3\xb1\x88\x86" // U+F1206 +#define ICON_MDI_LAYERS_SEARCH_OUTLINE "\xf3\xb1\x88\x87" // U+F1207 +#define ICON_MDI_LAYERS_TRIPLE "\xf3\xb0\xbd\x98" // U+F0F58 +#define ICON_MDI_LAYERS_TRIPLE_OUTLINE "\xf3\xb0\xbd\x99" // U+F0F59 +#define ICON_MDI_LEAD_PENCIL "\xf3\xb0\x99\x8f" // U+F064F +#define ICON_MDI_LEAF "\xf3\xb0\x8c\xaa" // U+F032A +#define ICON_MDI_LEAF_CIRCLE "\xf3\xb1\xa4\x85" // U+F1905 +#define ICON_MDI_LEAF_CIRCLE_OUTLINE "\xf3\xb1\xa4\x86" // U+F1906 +#define ICON_MDI_LEAF_MAPLE "\xf3\xb0\xb2\x93" // U+F0C93 +#define ICON_MDI_LEAF_MAPLE_OFF "\xf3\xb1\x8b\x9a" // U+F12DA +#define ICON_MDI_LEAF_OFF "\xf3\xb1\x8b\x99" // U+F12D9 +#define ICON_MDI_LEAK "\xf3\xb0\xb7\x97" // U+F0DD7 +#define ICON_MDI_LEAK_OFF "\xf3\xb0\xb7\x98" // U+F0DD8 +#define ICON_MDI_LECTERN "\xf3\xb1\xab\xb0" // U+F1AF0 +#define ICON_MDI_LED_OFF "\xf3\xb0\x8c\xab" // U+F032B +#define ICON_MDI_LED_ON "\xf3\xb0\x8c\xac" // U+F032C +#define ICON_MDI_LED_OUTLINE "\xf3\xb0\x8c\xad" // U+F032D +#define ICON_MDI_LED_STRIP "\xf3\xb0\x9f\x96" // U+F07D6 +#define ICON_MDI_LED_STRIP_VARIANT "\xf3\xb1\x81\x91" // U+F1051 +#define ICON_MDI_LED_STRIP_VARIANT_OFF "\xf3\xb1\xa9\x8b" // U+F1A4B +#define ICON_MDI_LED_VARIANT_OFF "\xf3\xb0\x8c\xae" // U+F032E +#define ICON_MDI_LED_VARIANT_ON "\xf3\xb0\x8c\xaf" // U+F032F +#define ICON_MDI_LED_VARIANT_OUTLINE "\xf3\xb0\x8c\xb0" // U+F0330 +#define ICON_MDI_LEEK "\xf3\xb1\x85\xbd" // U+F117D +#define ICON_MDI_LESS_THAN "\xf3\xb0\xa5\xbc" // U+F097C +#define ICON_MDI_LESS_THAN_OR_EQUAL "\xf3\xb0\xa5\xbd" // U+F097D +#define ICON_MDI_LIBRARY "\xf3\xb0\x8c\xb1" // U+F0331 +#define ICON_MDI_LIBRARY_OUTLINE "\xf3\xb1\xa8\xa2" // U+F1A22 +#define ICON_MDI_LIBRARY_SHELVES "\xf3\xb0\xae\xa9" // U+F0BA9 +#define ICON_MDI_LICENSE "\xf3\xb0\xbf\x83" // U+F0FC3 +#define ICON_MDI_LIFEBUOY "\xf3\xb0\xa1\xbe" // U+F087E +#define ICON_MDI_LIGHT_FLOOD_DOWN "\xf3\xb1\xa6\x87" // U+F1987 +#define ICON_MDI_LIGHT_FLOOD_UP "\xf3\xb1\xa6\x88" // U+F1988 +#define ICON_MDI_LIGHT_RECESSED "\xf3\xb1\x9e\x9b" // U+F179B +#define ICON_MDI_LIGHT_SWITCH "\xf3\xb0\xa5\xbe" // U+F097E +#define ICON_MDI_LIGHT_SWITCH_OFF "\xf3\xb1\xa8\xa4" // U+F1A24 +#define ICON_MDI_LIGHTBULB "\xf3\xb0\x8c\xb5" // U+F0335 +#define ICON_MDI_LIGHTBULB_ALERT "\xf3\xb1\xa7\xa1" // U+F19E1 +#define ICON_MDI_LIGHTBULB_ALERT_OUTLINE "\xf3\xb1\xa7\xa2" // U+F19E2 +#define ICON_MDI_LIGHTBULB_AUTO "\xf3\xb1\xa0\x80" // U+F1800 +#define ICON_MDI_LIGHTBULB_AUTO_OUTLINE "\xf3\xb1\xa0\x81" // U+F1801 +#define ICON_MDI_LIGHTBULB_CFL "\xf3\xb1\x88\x88" // U+F1208 +#define ICON_MDI_LIGHTBULB_CFL_OFF "\xf3\xb1\x88\x89" // U+F1209 +#define ICON_MDI_LIGHTBULB_CFL_SPIRAL "\xf3\xb1\x89\xb5" // U+F1275 +#define ICON_MDI_LIGHTBULB_CFL_SPIRAL_OFF "\xf3\xb1\x8b\x83" // U+F12C3 +#define ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE "\xf3\xb1\xa0\x84" // U+F1804 +#define ICON_MDI_LIGHTBULB_FLUORESCENT_TUBE_OUTLINE "\xf3\xb1\xa0\x85" // U+F1805 +#define ICON_MDI_LIGHTBULB_GROUP "\xf3\xb1\x89\x93" // U+F1253 +#define ICON_MDI_LIGHTBULB_GROUP_OFF "\xf3\xb1\x8b\x8d" // U+F12CD +#define ICON_MDI_LIGHTBULB_GROUP_OFF_OUTLINE "\xf3\xb1\x8b\x8e" // U+F12CE +#define ICON_MDI_LIGHTBULB_GROUP_OUTLINE "\xf3\xb1\x89\x94" // U+F1254 +#define ICON_MDI_LIGHTBULB_MULTIPLE "\xf3\xb1\x89\x95" // U+F1255 +#define ICON_MDI_LIGHTBULB_MULTIPLE_OFF "\xf3\xb1\x8b\x8f" // U+F12CF +#define ICON_MDI_LIGHTBULB_MULTIPLE_OFF_OUTLINE "\xf3\xb1\x8b\x90" // U+F12D0 +#define ICON_MDI_LIGHTBULB_MULTIPLE_OUTLINE "\xf3\xb1\x89\x96" // U+F1256 +#define ICON_MDI_LIGHTBULB_NIGHT "\xf3\xb1\xa9\x8c" // U+F1A4C +#define ICON_MDI_LIGHTBULB_NIGHT_OUTLINE "\xf3\xb1\xa9\x8d" // U+F1A4D +#define ICON_MDI_LIGHTBULB_OFF "\xf3\xb0\xb9\x8f" // U+F0E4F +#define ICON_MDI_LIGHTBULB_OFF_OUTLINE "\xf3\xb0\xb9\x90" // U+F0E50 +#define ICON_MDI_LIGHTBULB_ON "\xf3\xb0\x9b\xa8" // U+F06E8 +#define ICON_MDI_LIGHTBULB_ON_10 "\xf3\xb1\xa9\x8e" // U+F1A4E +#define ICON_MDI_LIGHTBULB_ON_20 "\xf3\xb1\xa9\x8f" // U+F1A4F +#define ICON_MDI_LIGHTBULB_ON_30 "\xf3\xb1\xa9\x90" // U+F1A50 +#define ICON_MDI_LIGHTBULB_ON_40 "\xf3\xb1\xa9\x91" // U+F1A51 +#define ICON_MDI_LIGHTBULB_ON_50 "\xf3\xb1\xa9\x92" // U+F1A52 +#define ICON_MDI_LIGHTBULB_ON_60 "\xf3\xb1\xa9\x93" // U+F1A53 +#define ICON_MDI_LIGHTBULB_ON_70 "\xf3\xb1\xa9\x94" // U+F1A54 +#define ICON_MDI_LIGHTBULB_ON_80 "\xf3\xb1\xa9\x95" // U+F1A55 +#define ICON_MDI_LIGHTBULB_ON_90 "\xf3\xb1\xa9\x96" // U+F1A56 +#define ICON_MDI_LIGHTBULB_ON_OUTLINE "\xf3\xb0\x9b\xa9" // U+F06E9 +#define ICON_MDI_LIGHTBULB_OUTLINE "\xf3\xb0\x8c\xb6" // U+F0336 +#define ICON_MDI_LIGHTBULB_QUESTION "\xf3\xb1\xa7\xa3" // U+F19E3 +#define ICON_MDI_LIGHTBULB_QUESTION_OUTLINE "\xf3\xb1\xa7\xa4" // U+F19E4 +#define ICON_MDI_LIGHTBULB_SPOT "\xf3\xb1\x9f\xb4" // U+F17F4 +#define ICON_MDI_LIGHTBULB_SPOT_OFF "\xf3\xb1\x9f\xb5" // U+F17F5 +#define ICON_MDI_LIGHTBULB_VARIANT "\xf3\xb1\xa0\x82" // U+F1802 +#define ICON_MDI_LIGHTBULB_VARIANT_OUTLINE "\xf3\xb1\xa0\x83" // U+F1803 +#define ICON_MDI_LIGHTHOUSE "\xf3\xb0\xa7\xbf" // U+F09FF +#define ICON_MDI_LIGHTHOUSE_ON "\xf3\xb0\xa8\x80" // U+F0A00 +#define ICON_MDI_LIGHTNING_BOLT "\xf3\xb1\x90\x8b" // U+F140B +#define ICON_MDI_LIGHTNING_BOLT_CIRCLE "\xf3\xb0\xa0\xa0" // U+F0820 +#define ICON_MDI_LIGHTNING_BOLT_OUTLINE "\xf3\xb1\x90\x8c" // U+F140C +#define ICON_MDI_LINE_SCAN "\xf3\xb0\x98\xa4" // U+F0624 +#define ICON_MDI_LINGERIE "\xf3\xb1\x91\xb6" // U+F1476 +#define ICON_MDI_LINK "\xf3\xb0\x8c\xb7" // U+F0337 +#define ICON_MDI_LINK_BOX "\xf3\xb0\xb4\x9a" // U+F0D1A +#define ICON_MDI_LINK_BOX_OUTLINE "\xf3\xb0\xb4\x9b" // U+F0D1B +#define ICON_MDI_LINK_BOX_VARIANT "\xf3\xb0\xb4\x9c" // U+F0D1C +#define ICON_MDI_LINK_BOX_VARIANT_OUTLINE "\xf3\xb0\xb4\x9d" // U+F0D1D +#define ICON_MDI_LINK_CIRCLE "\xf3\xb1\xb2\xac" // U+F1CAC +#define ICON_MDI_LINK_CIRCLE_OUTLINE "\xf3\xb1\xb2\xad" // U+F1CAD +#define ICON_MDI_LINK_EDIT "\xf3\xb1\xb2\xae" // U+F1CAE +#define ICON_MDI_LINK_LOCK "\xf3\xb1\x82\xba" // U+F10BA +#define ICON_MDI_LINK_OFF "\xf3\xb0\x8c\xb8" // U+F0338 +#define ICON_MDI_LINK_PLUS "\xf3\xb0\xb2\x94" // U+F0C94 +#define ICON_MDI_LINK_VARIANT "\xf3\xb0\x8c\xb9" // U+F0339 +#define ICON_MDI_LINK_VARIANT_MINUS "\xf3\xb1\x83\xbf" // U+F10FF +#define ICON_MDI_LINK_VARIANT_OFF "\xf3\xb0\x8c\xba" // U+F033A +#define ICON_MDI_LINK_VARIANT_PLUS "\xf3\xb1\x84\x80" // U+F1100 +#define ICON_MDI_LINK_VARIANT_REMOVE "\xf3\xb1\x84\x81" // U+F1101 +#define ICON_MDI_LINKEDIN "\xf3\xb0\x8c\xbb" // U+F033B +#define ICON_MDI_LINUX "\xf3\xb0\x8c\xbd" // U+F033D +#define ICON_MDI_LINUX_MINT "\xf3\xb0\xa3\xad" // U+F08ED +#define ICON_MDI_LIPSTICK "\xf3\xb1\x8e\xb5" // U+F13B5 +#define ICON_MDI_LIQUID_SPOT "\xf3\xb1\xa0\xa6" // U+F1826 +#define ICON_MDI_LIQUOR "\xf3\xb1\xa4\x9e" // U+F191E +#define ICON_MDI_LIST_BOX "\xf3\xb1\xad\xbb" // U+F1B7B +#define ICON_MDI_LIST_BOX_OUTLINE "\xf3\xb1\xad\xbc" // U+F1B7C +#define ICON_MDI_LIST_STATUS "\xf3\xb1\x96\xab" // U+F15AB +#define ICON_MDI_LITECOIN "\xf3\xb0\xa9\xa1" // U+F0A61 +#define ICON_MDI_LOADING "\xf3\xb0\x9d\xb2" // U+F0772 +#define ICON_MDI_LOCATION_ENTER "\xf3\xb0\xbf\x84" // U+F0FC4 +#define ICON_MDI_LOCATION_EXIT "\xf3\xb0\xbf\x85" // U+F0FC5 +#define ICON_MDI_LOCK "\xf3\xb0\x8c\xbe" // U+F033E +#define ICON_MDI_LOCK_ALERT "\xf3\xb0\xa3\xae" // U+F08EE +#define ICON_MDI_LOCK_ALERT_OUTLINE "\xf3\xb1\x97\x91" // U+F15D1 +#define ICON_MDI_LOCK_CHECK "\xf3\xb1\x8e\x9a" // U+F139A +#define ICON_MDI_LOCK_CHECK_OUTLINE "\xf3\xb1\x9a\xa8" // U+F16A8 +#define ICON_MDI_LOCK_CLOCK "\xf3\xb0\xa5\xbf" // U+F097F +#define ICON_MDI_LOCK_MINUS "\xf3\xb1\x9a\xa9" // U+F16A9 +#define ICON_MDI_LOCK_MINUS_OUTLINE "\xf3\xb1\x9a\xaa" // U+F16AA +#define ICON_MDI_LOCK_OFF "\xf3\xb1\x99\xb1" // U+F1671 +#define ICON_MDI_LOCK_OFF_OUTLINE "\xf3\xb1\x99\xb2" // U+F1672 +#define ICON_MDI_LOCK_OPEN "\xf3\xb0\x8c\xbf" // U+F033F +#define ICON_MDI_LOCK_OPEN_ALERT "\xf3\xb1\x8e\x9b" // U+F139B +#define ICON_MDI_LOCK_OPEN_ALERT_OUTLINE "\xf3\xb1\x97\x92" // U+F15D2 +#define ICON_MDI_LOCK_OPEN_CHECK "\xf3\xb1\x8e\x9c" // U+F139C +#define ICON_MDI_LOCK_OPEN_CHECK_OUTLINE "\xf3\xb1\x9a\xab" // U+F16AB +#define ICON_MDI_LOCK_OPEN_MINUS "\xf3\xb1\x9a\xac" // U+F16AC +#define ICON_MDI_LOCK_OPEN_MINUS_OUTLINE "\xf3\xb1\x9a\xad" // U+F16AD +#define ICON_MDI_LOCK_OPEN_OUTLINE "\xf3\xb0\x8d\x80" // U+F0340 +#define ICON_MDI_LOCK_OPEN_PLUS "\xf3\xb1\x9a\xae" // U+F16AE +#define ICON_MDI_LOCK_OPEN_PLUS_OUTLINE "\xf3\xb1\x9a\xaf" // U+F16AF +#define ICON_MDI_LOCK_OPEN_REMOVE "\xf3\xb1\x9a\xb0" // U+F16B0 +#define ICON_MDI_LOCK_OPEN_REMOVE_OUTLINE "\xf3\xb1\x9a\xb1" // U+F16B1 +#define ICON_MDI_LOCK_OPEN_VARIANT "\xf3\xb0\xbf\x86" // U+F0FC6 +#define ICON_MDI_LOCK_OPEN_VARIANT_OUTLINE "\xf3\xb0\xbf\x87" // U+F0FC7 +#define ICON_MDI_LOCK_OUTLINE "\xf3\xb0\x8d\x81" // U+F0341 +#define ICON_MDI_LOCK_PATTERN "\xf3\xb0\x9b\xaa" // U+F06EA +#define ICON_MDI_LOCK_PERCENT "\xf3\xb1\xb0\x92" // U+F1C12 +#define ICON_MDI_LOCK_PERCENT_OPEN "\xf3\xb1\xb0\x93" // U+F1C13 +#define ICON_MDI_LOCK_PERCENT_OPEN_OUTLINE "\xf3\xb1\xb0\x94" // U+F1C14 +#define ICON_MDI_LOCK_PERCENT_OPEN_VARIANT "\xf3\xb1\xb0\x95" // U+F1C15 +#define ICON_MDI_LOCK_PERCENT_OPEN_VARIANT_OUTLINE "\xf3\xb1\xb0\x96" // U+F1C16 +#define ICON_MDI_LOCK_PERCENT_OUTLINE "\xf3\xb1\xb0\x97" // U+F1C17 +#define ICON_MDI_LOCK_PLUS "\xf3\xb0\x97\xbb" // U+F05FB +#define ICON_MDI_LOCK_PLUS_OUTLINE "\xf3\xb1\x9a\xb2" // U+F16B2 +#define ICON_MDI_LOCK_QUESTION "\xf3\xb0\xa3\xaf" // U+F08EF +#define ICON_MDI_LOCK_REMOVE "\xf3\xb1\x9a\xb3" // U+F16B3 +#define ICON_MDI_LOCK_REMOVE_OUTLINE "\xf3\xb1\x9a\xb4" // U+F16B4 +#define ICON_MDI_LOCK_RESET "\xf3\xb0\x9d\xb3" // U+F0773 +#define ICON_MDI_LOCK_SMART "\xf3\xb0\xa2\xb2" // U+F08B2 +#define ICON_MDI_LOCKER "\xf3\xb0\x9f\x97" // U+F07D7 +#define ICON_MDI_LOCKER_MULTIPLE "\xf3\xb0\x9f\x98" // U+F07D8 +#define ICON_MDI_LOGIN "\xf3\xb0\x8d\x82" // U+F0342 +#define ICON_MDI_LOGIN_VARIANT "\xf3\xb0\x97\xbc" // U+F05FC +#define ICON_MDI_LOGOUT "\xf3\xb0\x8d\x83" // U+F0343 +#define ICON_MDI_LOGOUT_VARIANT "\xf3\xb0\x97\xbd" // U+F05FD +#define ICON_MDI_LONGITUDE "\xf3\xb0\xbd\x9a" // U+F0F5A +#define ICON_MDI_LOOKS "\xf3\xb0\x8d\x84" // U+F0344 +#define ICON_MDI_LOTION "\xf3\xb1\x96\x82" // U+F1582 +#define ICON_MDI_LOTION_OUTLINE "\xf3\xb1\x96\x83" // U+F1583 +#define ICON_MDI_LOTION_PLUS "\xf3\xb1\x96\x84" // U+F1584 +#define ICON_MDI_LOTION_PLUS_OUTLINE "\xf3\xb1\x96\x85" // U+F1585 +#define ICON_MDI_LOUPE "\xf3\xb0\x8d\x85" // U+F0345 +#define ICON_MDI_LUMX "\xf3\xb0\x8d\x86" // U+F0346 +#define ICON_MDI_LUNGS "\xf3\xb1\x82\x84" // U+F1084 +#define ICON_MDI_MACE "\xf3\xb1\xa1\x83" // U+F1843 +#define ICON_MDI_MAGAZINE_PISTOL "\xf3\xb0\x8c\xa4" // U+F0324 +#define ICON_MDI_MAGAZINE_RIFLE "\xf3\xb0\x8c\xa3" // U+F0323 +#define ICON_MDI_MAGIC_STAFF "\xf3\xb1\xa1\x84" // U+F1844 +#define ICON_MDI_MAGNET "\xf3\xb0\x8d\x87" // U+F0347 +#define ICON_MDI_MAGNET_ON "\xf3\xb0\x8d\x88" // U+F0348 +#define ICON_MDI_MAGNIFY "\xf3\xb0\x8d\x89" // U+F0349 +#define ICON_MDI_MAGNIFY_CLOSE "\xf3\xb0\xa6\x80" // U+F0980 +#define ICON_MDI_MAGNIFY_EXPAND "\xf3\xb1\xa1\xb4" // U+F1874 +#define ICON_MDI_MAGNIFY_MINUS "\xf3\xb0\x8d\x8a" // U+F034A +#define ICON_MDI_MAGNIFY_MINUS_CURSOR "\xf3\xb0\xa9\xa2" // U+F0A62 +#define ICON_MDI_MAGNIFY_MINUS_OUTLINE "\xf3\xb0\x9b\xac" // U+F06EC +#define ICON_MDI_MAGNIFY_PLUS "\xf3\xb0\x8d\x8b" // U+F034B +#define ICON_MDI_MAGNIFY_PLUS_CURSOR "\xf3\xb0\xa9\xa3" // U+F0A63 +#define ICON_MDI_MAGNIFY_PLUS_OUTLINE "\xf3\xb0\x9b\xad" // U+F06ED +#define ICON_MDI_MAGNIFY_REMOVE_CURSOR "\xf3\xb1\x88\x8c" // U+F120C +#define ICON_MDI_MAGNIFY_REMOVE_OUTLINE "\xf3\xb1\x88\x8d" // U+F120D +#define ICON_MDI_MAGNIFY_SCAN "\xf3\xb1\x89\xb6" // U+F1276 +#define ICON_MDI_MAIL "\xf3\xb0\xba\xbb" // U+F0EBB +#define ICON_MDI_MAILBOX "\xf3\xb0\x9b\xae" // U+F06EE +#define ICON_MDI_MAILBOX_OPEN "\xf3\xb0\xb6\x88" // U+F0D88 +#define ICON_MDI_MAILBOX_OPEN_OUTLINE "\xf3\xb0\xb6\x89" // U+F0D89 +#define ICON_MDI_MAILBOX_OPEN_UP "\xf3\xb0\xb6\x8a" // U+F0D8A +#define ICON_MDI_MAILBOX_OPEN_UP_OUTLINE "\xf3\xb0\xb6\x8b" // U+F0D8B +#define ICON_MDI_MAILBOX_OUTLINE "\xf3\xb0\xb6\x8c" // U+F0D8C +#define ICON_MDI_MAILBOX_UP "\xf3\xb0\xb6\x8d" // U+F0D8D +#define ICON_MDI_MAILBOX_UP_OUTLINE "\xf3\xb0\xb6\x8e" // U+F0D8E +#define ICON_MDI_MANJARO "\xf3\xb1\x98\x8a" // U+F160A +#define ICON_MDI_MAP "\xf3\xb0\x8d\x8d" // U+F034D +#define ICON_MDI_MAP_CHECK "\xf3\xb0\xba\xbc" // U+F0EBC +#define ICON_MDI_MAP_CHECK_OUTLINE "\xf3\xb0\xba\xbd" // U+F0EBD +#define ICON_MDI_MAP_CLOCK "\xf3\xb0\xb4\x9e" // U+F0D1E +#define ICON_MDI_MAP_CLOCK_OUTLINE "\xf3\xb0\xb4\x9f" // U+F0D1F +#define ICON_MDI_MAP_LEGEND "\xf3\xb0\xa8\x81" // U+F0A01 +#define ICON_MDI_MAP_MARKER "\xf3\xb0\x8d\x8e" // U+F034E +#define ICON_MDI_MAP_MARKER_ACCOUNT "\xf3\xb1\xa3\xa3" // U+F18E3 +#define ICON_MDI_MAP_MARKER_ACCOUNT_OUTLINE "\xf3\xb1\xa3\xa4" // U+F18E4 +#define ICON_MDI_MAP_MARKER_ALERT "\xf3\xb0\xbc\x85" // U+F0F05 +#define ICON_MDI_MAP_MARKER_ALERT_OUTLINE "\xf3\xb0\xbc\x86" // U+F0F06 +#define ICON_MDI_MAP_MARKER_CHECK "\xf3\xb0\xb2\x95" // U+F0C95 +#define ICON_MDI_MAP_MARKER_CHECK_OUTLINE "\xf3\xb1\x8b\xbb" // U+F12FB +#define ICON_MDI_MAP_MARKER_CIRCLE "\xf3\xb0\x8d\x8f" // U+F034F +#define ICON_MDI_MAP_MARKER_DISTANCE "\xf3\xb0\xa3\xb0" // U+F08F0 +#define ICON_MDI_MAP_MARKER_DOWN "\xf3\xb1\x84\x82" // U+F1102 +#define ICON_MDI_MAP_MARKER_LEFT "\xf3\xb1\x8b\x9b" // U+F12DB +#define ICON_MDI_MAP_MARKER_LEFT_OUTLINE "\xf3\xb1\x8b\x9d" // U+F12DD +#define ICON_MDI_MAP_MARKER_MINUS "\xf3\xb0\x99\x90" // U+F0650 +#define ICON_MDI_MAP_MARKER_MINUS_OUTLINE "\xf3\xb1\x8b\xb9" // U+F12F9 +#define ICON_MDI_MAP_MARKER_MULTIPLE "\xf3\xb0\x8d\x90" // U+F0350 +#define ICON_MDI_MAP_MARKER_MULTIPLE_OUTLINE "\xf3\xb1\x89\xb7" // U+F1277 +#define ICON_MDI_MAP_MARKER_OFF "\xf3\xb0\x8d\x91" // U+F0351 +#define ICON_MDI_MAP_MARKER_OFF_OUTLINE "\xf3\xb1\x8b\xbd" // U+F12FD +#define ICON_MDI_MAP_MARKER_OUTLINE "\xf3\xb0\x9f\x99" // U+F07D9 +#define ICON_MDI_MAP_MARKER_PATH "\xf3\xb0\xb4\xa0" // U+F0D20 +#define ICON_MDI_MAP_MARKER_PLUS "\xf3\xb0\x99\x91" // U+F0651 +#define ICON_MDI_MAP_MARKER_PLUS_OUTLINE "\xf3\xb1\x8b\xb8" // U+F12F8 +#define ICON_MDI_MAP_MARKER_QUESTION "\xf3\xb0\xbc\x87" // U+F0F07 +#define ICON_MDI_MAP_MARKER_QUESTION_OUTLINE "\xf3\xb0\xbc\x88" // U+F0F08 +#define ICON_MDI_MAP_MARKER_RADIUS "\xf3\xb0\x8d\x92" // U+F0352 +#define ICON_MDI_MAP_MARKER_RADIUS_OUTLINE "\xf3\xb1\x8b\xbc" // U+F12FC +#define ICON_MDI_MAP_MARKER_REMOVE "\xf3\xb0\xbc\x89" // U+F0F09 +#define ICON_MDI_MAP_MARKER_REMOVE_OUTLINE "\xf3\xb1\x8b\xba" // U+F12FA +#define ICON_MDI_MAP_MARKER_REMOVE_VARIANT "\xf3\xb0\xbc\x8a" // U+F0F0A +#define ICON_MDI_MAP_MARKER_RIGHT "\xf3\xb1\x8b\x9c" // U+F12DC +#define ICON_MDI_MAP_MARKER_RIGHT_OUTLINE "\xf3\xb1\x8b\x9e" // U+F12DE +#define ICON_MDI_MAP_MARKER_STAR "\xf3\xb1\x98\x88" // U+F1608 +#define ICON_MDI_MAP_MARKER_STAR_OUTLINE "\xf3\xb1\x98\x89" // U+F1609 +#define ICON_MDI_MAP_MARKER_UP "\xf3\xb1\x84\x83" // U+F1103 +#define ICON_MDI_MAP_MINUS "\xf3\xb0\xa6\x81" // U+F0981 +#define ICON_MDI_MAP_OUTLINE "\xf3\xb0\xa6\x82" // U+F0982 +#define ICON_MDI_MAP_PLUS "\xf3\xb0\xa6\x83" // U+F0983 +#define ICON_MDI_MAP_SEARCH "\xf3\xb0\xa6\x84" // U+F0984 +#define ICON_MDI_MAP_SEARCH_OUTLINE "\xf3\xb0\xa6\x85" // U+F0985 +#define ICON_MDI_MAPBOX "\xf3\xb0\xae\xaa" // U+F0BAA +#define ICON_MDI_MARGIN "\xf3\xb0\x8d\x93" // U+F0353 +#define ICON_MDI_MARKER "\xf3\xb0\x99\x92" // U+F0652 +#define ICON_MDI_MARKER_CANCEL "\xf3\xb0\xb7\x99" // U+F0DD9 +#define ICON_MDI_MARKER_CHECK "\xf3\xb0\x8d\x95" // U+F0355 +#define ICON_MDI_MASTODON "\xf3\xb0\xab\x91" // U+F0AD1 +#define ICON_MDI_MATERIAL_DESIGN "\xf3\xb0\xa6\x86" // U+F0986 +#define ICON_MDI_MATERIAL_UI "\xf3\xb0\x8d\x97" // U+F0357 +#define ICON_MDI_MATH_COMPASS "\xf3\xb0\x8d\x98" // U+F0358 +#define ICON_MDI_MATH_COS "\xf3\xb0\xb2\x96" // U+F0C96 +#define ICON_MDI_MATH_INTEGRAL "\xf3\xb0\xbf\x88" // U+F0FC8 +#define ICON_MDI_MATH_INTEGRAL_BOX "\xf3\xb0\xbf\x89" // U+F0FC9 +#define ICON_MDI_MATH_LOG "\xf3\xb1\x82\x85" // U+F1085 +#define ICON_MDI_MATH_NORM "\xf3\xb0\xbf\x8a" // U+F0FCA +#define ICON_MDI_MATH_NORM_BOX "\xf3\xb0\xbf\x8b" // U+F0FCB +#define ICON_MDI_MATH_SIN "\xf3\xb0\xb2\x97" // U+F0C97 +#define ICON_MDI_MATH_TAN "\xf3\xb0\xb2\x98" // U+F0C98 +#define ICON_MDI_MATRIX "\xf3\xb0\x98\xa8" // U+F0628 +#define ICON_MDI_MEDAL "\xf3\xb0\xa6\x87" // U+F0987 +#define ICON_MDI_MEDAL_OUTLINE "\xf3\xb1\x8c\xa6" // U+F1326 +#define ICON_MDI_MEDICAL_BAG "\xf3\xb0\x9b\xaf" // U+F06EF +#define ICON_MDI_MEDICAL_COTTON_SWAB "\xf3\xb1\xaa\xb8" // U+F1AB8 +#define ICON_MDI_MEDICATION "\xf3\xb1\xac\x94" // U+F1B14 +#define ICON_MDI_MEDICATION_OUTLINE "\xf3\xb1\xac\x95" // U+F1B15 +#define ICON_MDI_MEDITATION "\xf3\xb1\x85\xbb" // U+F117B +#define ICON_MDI_MEMORY "\xf3\xb0\x8d\x9b" // U+F035B +#define ICON_MDI_MEMORY_ARROW_DOWN "\xf3\xb1\xb2\xa6" // U+F1CA6 +#define ICON_MDI_MENORAH "\xf3\xb1\x9f\x94" // U+F17D4 +#define ICON_MDI_MENORAH_FIRE "\xf3\xb1\x9f\x95" // U+F17D5 +#define ICON_MDI_MENU "\xf3\xb0\x8d\x9c" // U+F035C +#define ICON_MDI_MENU_CLOSE "\xf3\xb1\xb2\x90" // U+F1C90 +#define ICON_MDI_MENU_DOWN "\xf3\xb0\x8d\x9d" // U+F035D +#define ICON_MDI_MENU_DOWN_OUTLINE "\xf3\xb0\x9a\xb6" // U+F06B6 +#define ICON_MDI_MENU_LEFT "\xf3\xb0\x8d\x9e" // U+F035E +#define ICON_MDI_MENU_LEFT_OUTLINE "\xf3\xb0\xa8\x82" // U+F0A02 +#define ICON_MDI_MENU_OPEN "\xf3\xb0\xae\xab" // U+F0BAB +#define ICON_MDI_MENU_RIGHT "\xf3\xb0\x8d\x9f" // U+F035F +#define ICON_MDI_MENU_RIGHT_OUTLINE "\xf3\xb0\xa8\x83" // U+F0A03 +#define ICON_MDI_MENU_SWAP "\xf3\xb0\xa9\xa4" // U+F0A64 +#define ICON_MDI_MENU_SWAP_OUTLINE "\xf3\xb0\xa9\xa5" // U+F0A65 +#define ICON_MDI_MENU_UP "\xf3\xb0\x8d\xa0" // U+F0360 +#define ICON_MDI_MENU_UP_OUTLINE "\xf3\xb0\x9a\xb7" // U+F06B7 +#define ICON_MDI_MERGE "\xf3\xb0\xbd\x9c" // U+F0F5C +#define ICON_MDI_MESSAGE "\xf3\xb0\x8d\xa1" // U+F0361 +#define ICON_MDI_MESSAGE_ALERT "\xf3\xb0\x8d\xa2" // U+F0362 +#define ICON_MDI_MESSAGE_ALERT_OUTLINE "\xf3\xb0\xa8\x84" // U+F0A04 +#define ICON_MDI_MESSAGE_ARROW_LEFT "\xf3\xb1\x8b\xb2" // U+F12F2 +#define ICON_MDI_MESSAGE_ARROW_LEFT_OUTLINE "\xf3\xb1\x8b\xb3" // U+F12F3 +#define ICON_MDI_MESSAGE_ARROW_RIGHT "\xf3\xb1\x8b\xb4" // U+F12F4 +#define ICON_MDI_MESSAGE_ARROW_RIGHT_OUTLINE "\xf3\xb1\x8b\xb5" // U+F12F5 +#define ICON_MDI_MESSAGE_BADGE "\xf3\xb1\xa5\x81" // U+F1941 +#define ICON_MDI_MESSAGE_BADGE_OUTLINE "\xf3\xb1\xa5\x82" // U+F1942 +#define ICON_MDI_MESSAGE_BOOKMARK "\xf3\xb1\x96\xac" // U+F15AC +#define ICON_MDI_MESSAGE_BOOKMARK_OUTLINE "\xf3\xb1\x96\xad" // U+F15AD +#define ICON_MDI_MESSAGE_BULLETED "\xf3\xb0\x9a\xa2" // U+F06A2 +#define ICON_MDI_MESSAGE_BULLETED_OFF "\xf3\xb0\x9a\xa3" // U+F06A3 +#define ICON_MDI_MESSAGE_CHECK "\xf3\xb1\xae\x8a" // U+F1B8A +#define ICON_MDI_MESSAGE_CHECK_OUTLINE "\xf3\xb1\xae\x8b" // U+F1B8B +#define ICON_MDI_MESSAGE_COG "\xf3\xb0\x9b\xb1" // U+F06F1 +#define ICON_MDI_MESSAGE_COG_OUTLINE "\xf3\xb1\x85\xb2" // U+F1172 +#define ICON_MDI_MESSAGE_DRAW "\xf3\xb0\x8d\xa3" // U+F0363 +#define ICON_MDI_MESSAGE_FAST "\xf3\xb1\xa7\x8c" // U+F19CC +#define ICON_MDI_MESSAGE_FAST_OUTLINE "\xf3\xb1\xa7\x8d" // U+F19CD +#define ICON_MDI_MESSAGE_FLASH "\xf3\xb1\x96\xa9" // U+F15A9 +#define ICON_MDI_MESSAGE_FLASH_OUTLINE "\xf3\xb1\x96\xaa" // U+F15AA +#define ICON_MDI_MESSAGE_IMAGE "\xf3\xb0\x8d\xa4" // U+F0364 +#define ICON_MDI_MESSAGE_IMAGE_OUTLINE "\xf3\xb1\x85\xac" // U+F116C +#define ICON_MDI_MESSAGE_LOCK "\xf3\xb0\xbf\x8c" // U+F0FCC +#define ICON_MDI_MESSAGE_LOCK_OUTLINE "\xf3\xb1\x85\xad" // U+F116D +#define ICON_MDI_MESSAGE_MINUS "\xf3\xb1\x85\xae" // U+F116E +#define ICON_MDI_MESSAGE_MINUS_OUTLINE "\xf3\xb1\x85\xaf" // U+F116F +#define ICON_MDI_MESSAGE_OFF "\xf3\xb1\x99\x8d" // U+F164D +#define ICON_MDI_MESSAGE_OFF_OUTLINE "\xf3\xb1\x99\x8e" // U+F164E +#define ICON_MDI_MESSAGE_OUTLINE "\xf3\xb0\x8d\xa5" // U+F0365 +#define ICON_MDI_MESSAGE_PLUS "\xf3\xb0\x99\x93" // U+F0653 +#define ICON_MDI_MESSAGE_PLUS_OUTLINE "\xf3\xb1\x82\xbb" // U+F10BB +#define ICON_MDI_MESSAGE_PROCESSING "\xf3\xb0\x8d\xa6" // U+F0366 +#define ICON_MDI_MESSAGE_PROCESSING_OUTLINE "\xf3\xb1\x85\xb0" // U+F1170 +#define ICON_MDI_MESSAGE_QUESTION "\xf3\xb1\x9c\xba" // U+F173A +#define ICON_MDI_MESSAGE_QUESTION_OUTLINE "\xf3\xb1\x9c\xbb" // U+F173B +#define ICON_MDI_MESSAGE_REPLY "\xf3\xb0\x8d\xa7" // U+F0367 +#define ICON_MDI_MESSAGE_REPLY_OUTLINE "\xf3\xb1\x9c\xbd" // U+F173D +#define ICON_MDI_MESSAGE_REPLY_TEXT "\xf3\xb0\x8d\xa8" // U+F0368 +#define ICON_MDI_MESSAGE_REPLY_TEXT_OUTLINE "\xf3\xb1\x9c\xbe" // U+F173E +#define ICON_MDI_MESSAGE_SETTINGS "\xf3\xb0\x9b\xb0" // U+F06F0 +#define ICON_MDI_MESSAGE_SETTINGS_OUTLINE "\xf3\xb1\x85\xb1" // U+F1171 +#define ICON_MDI_MESSAGE_STAR "\xf3\xb0\x9a\x9a" // U+F069A +#define ICON_MDI_MESSAGE_STAR_OUTLINE "\xf3\xb1\x89\x90" // U+F1250 +#define ICON_MDI_MESSAGE_TEXT "\xf3\xb0\x8d\xa9" // U+F0369 +#define ICON_MDI_MESSAGE_TEXT_CLOCK "\xf3\xb1\x85\xb3" // U+F1173 +#define ICON_MDI_MESSAGE_TEXT_CLOCK_OUTLINE "\xf3\xb1\x85\xb4" // U+F1174 +#define ICON_MDI_MESSAGE_TEXT_FAST "\xf3\xb1\xa7\x8e" // U+F19CE +#define ICON_MDI_MESSAGE_TEXT_FAST_OUTLINE "\xf3\xb1\xa7\x8f" // U+F19CF +#define ICON_MDI_MESSAGE_TEXT_LOCK "\xf3\xb0\xbf\x8d" // U+F0FCD +#define ICON_MDI_MESSAGE_TEXT_LOCK_OUTLINE "\xf3\xb1\x85\xb5" // U+F1175 +#define ICON_MDI_MESSAGE_TEXT_OUTLINE "\xf3\xb0\x8d\xaa" // U+F036A +#define ICON_MDI_MESSAGE_VIDEO "\xf3\xb0\x8d\xab" // U+F036B +#define ICON_MDI_METEOR "\xf3\xb0\x98\xa9" // U+F0629 +#define ICON_MDI_METER_ELECTRIC "\xf3\xb1\xa9\x97" // U+F1A57 +#define ICON_MDI_METER_ELECTRIC_OUTLINE "\xf3\xb1\xa9\x98" // U+F1A58 +#define ICON_MDI_METER_GAS "\xf3\xb1\xa9\x99" // U+F1A59 +#define ICON_MDI_METER_GAS_OUTLINE "\xf3\xb1\xa9\x9a" // U+F1A5A +#define ICON_MDI_METRONOME "\xf3\xb0\x9f\x9a" // U+F07DA +#define ICON_MDI_METRONOME_TICK "\xf3\xb0\x9f\x9b" // U+F07DB +#define ICON_MDI_MICRO_SD "\xf3\xb0\x9f\x9c" // U+F07DC +#define ICON_MDI_MICROPHONE "\xf3\xb0\x8d\xac" // U+F036C +#define ICON_MDI_MICROPHONE_MESSAGE "\xf3\xb0\x94\x8a" // U+F050A +#define ICON_MDI_MICROPHONE_MESSAGE_OFF "\xf3\xb0\x94\x8b" // U+F050B +#define ICON_MDI_MICROPHONE_MINUS "\xf3\xb0\xa2\xb3" // U+F08B3 +#define ICON_MDI_MICROPHONE_OFF "\xf3\xb0\x8d\xad" // U+F036D +#define ICON_MDI_MICROPHONE_OUTLINE "\xf3\xb0\x8d\xae" // U+F036E +#define ICON_MDI_MICROPHONE_PLUS "\xf3\xb0\xa2\xb4" // U+F08B4 +#define ICON_MDI_MICROPHONE_QUESTION "\xf3\xb1\xa6\x89" // U+F1989 +#define ICON_MDI_MICROPHONE_QUESTION_OUTLINE "\xf3\xb1\xa6\x8a" // U+F198A +#define ICON_MDI_MICROPHONE_SETTINGS "\xf3\xb0\x8d\xaf" // U+F036F +#define ICON_MDI_MICROPHONE_VARIANT "\xf3\xb0\x8d\xb0" // U+F0370 +#define ICON_MDI_MICROPHONE_VARIANT_OFF "\xf3\xb0\x8d\xb1" // U+F0371 +#define ICON_MDI_MICROSCOPE "\xf3\xb0\x99\x94" // U+F0654 +#define ICON_MDI_MICROSOFT "\xf3\xb0\x8d\xb2" // U+F0372 +#define ICON_MDI_MICROSOFT_ACCESS "\xf3\xb1\x8e\x8e" // U+F138E +#define ICON_MDI_MICROSOFT_AZURE "\xf3\xb0\xa0\x85" // U+F0805 +#define ICON_MDI_MICROSOFT_AZURE_DEVOPS "\xf3\xb0\xbf\x95" // U+F0FD5 +#define ICON_MDI_MICROSOFT_BING "\xf3\xb0\x82\xa4" // U+F00A4 +#define ICON_MDI_MICROSOFT_DYNAMICS_365 "\xf3\xb0\xa6\x88" // U+F0988 +#define ICON_MDI_MICROSOFT_EDGE "\xf3\xb0\x87\xa9" // U+F01E9 +#define ICON_MDI_MICROSOFT_EXCEL "\xf3\xb1\x8e\x8f" // U+F138F +#define ICON_MDI_MICROSOFT_INTERNET_EXPLORER "\xf3\xb0\x8c\x80" // U+F0300 +#define ICON_MDI_MICROSOFT_OFFICE "\xf3\xb0\x8f\x86" // U+F03C6 +#define ICON_MDI_MICROSOFT_ONEDRIVE "\xf3\xb0\x8f\x8a" // U+F03CA +#define ICON_MDI_MICROSOFT_ONENOTE "\xf3\xb0\x9d\x87" // U+F0747 +#define ICON_MDI_MICROSOFT_OUTLOOK "\xf3\xb0\xb4\xa2" // U+F0D22 +#define ICON_MDI_MICROSOFT_POWERPOINT "\xf3\xb1\x8e\x90" // U+F1390 +#define ICON_MDI_MICROSOFT_SHAREPOINT "\xf3\xb1\x8e\x91" // U+F1391 +#define ICON_MDI_MICROSOFT_TEAMS "\xf3\xb0\x8a\xbb" // U+F02BB +#define ICON_MDI_MICROSOFT_VISUAL_STUDIO "\xf3\xb0\x98\x90" // U+F0610 +#define ICON_MDI_MICROSOFT_VISUAL_STUDIO_CODE "\xf3\xb0\xa8\x9e" // U+F0A1E +#define ICON_MDI_MICROSOFT_WINDOWS "\xf3\xb0\x96\xb3" // U+F05B3 +#define ICON_MDI_MICROSOFT_WINDOWS_CLASSIC "\xf3\xb0\xa8\xa1" // U+F0A21 +#define ICON_MDI_MICROSOFT_WORD "\xf3\xb1\x8e\x92" // U+F1392 +#define ICON_MDI_MICROSOFT_XBOX "\xf3\xb0\x96\xb9" // U+F05B9 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER "\xf3\xb0\x96\xba" // U+F05BA +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_ALERT "\xf3\xb0\x9d\x8b" // U+F074B +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_CHARGING "\xf3\xb0\xa8\xa2" // U+F0A22 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_EMPTY "\xf3\xb0\x9d\x8c" // U+F074C +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_FULL "\xf3\xb0\x9d\x8d" // U+F074D +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_LOW "\xf3\xb0\x9d\x8e" // U+F074E +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_MEDIUM "\xf3\xb0\x9d\x8f" // U+F074F +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_BATTERY_UNKNOWN "\xf3\xb0\x9d\x90" // U+F0750 +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_MENU "\xf3\xb0\xb9\xaf" // U+F0E6F +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_OFF "\xf3\xb0\x96\xbb" // U+F05BB +#define ICON_MDI_MICROSOFT_XBOX_CONTROLLER_VIEW "\xf3\xb0\xb9\xb0" // U+F0E70 +#define ICON_MDI_MICROWAVE "\xf3\xb0\xb2\x99" // U+F0C99 +#define ICON_MDI_MICROWAVE_OFF "\xf3\xb1\x90\xa3" // U+F1423 +#define ICON_MDI_MIDDLEWARE "\xf3\xb0\xbd\x9d" // U+F0F5D +#define ICON_MDI_MIDDLEWARE_OUTLINE "\xf3\xb0\xbd\x9e" // U+F0F5E +#define ICON_MDI_MIDI "\xf3\xb0\xa3\xb1" // U+F08F1 +#define ICON_MDI_MIDI_PORT "\xf3\xb0\xa3\xb2" // U+F08F2 +#define ICON_MDI_MINE "\xf3\xb0\xb7\x9a" // U+F0DDA +#define ICON_MDI_MINECRAFT "\xf3\xb0\x8d\xb3" // U+F0373 +#define ICON_MDI_MINI_SD "\xf3\xb0\xa8\x85" // U+F0A05 +#define ICON_MDI_MINIDISC "\xf3\xb0\xa8\x86" // U+F0A06 +#define ICON_MDI_MINUS "\xf3\xb0\x8d\xb4" // U+F0374 +#define ICON_MDI_MINUS_BOX "\xf3\xb0\x8d\xb5" // U+F0375 +#define ICON_MDI_MINUS_BOX_MULTIPLE "\xf3\xb1\x85\x81" // U+F1141 +#define ICON_MDI_MINUS_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x82" // U+F1142 +#define ICON_MDI_MINUS_BOX_OUTLINE "\xf3\xb0\x9b\xb2" // U+F06F2 +#define ICON_MDI_MINUS_CIRCLE "\xf3\xb0\x8d\xb6" // U+F0376 +#define ICON_MDI_MINUS_CIRCLE_MULTIPLE "\xf3\xb0\x8d\x9a" // U+F035A +#define ICON_MDI_MINUS_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\xab\x93" // U+F0AD3 +#define ICON_MDI_MINUS_CIRCLE_OFF "\xf3\xb1\x91\x99" // U+F1459 +#define ICON_MDI_MINUS_CIRCLE_OFF_OUTLINE "\xf3\xb1\x91\x9a" // U+F145A +#define ICON_MDI_MINUS_CIRCLE_OUTLINE "\xf3\xb0\x8d\xb7" // U+F0377 +#define ICON_MDI_MINUS_NETWORK "\xf3\xb0\x8d\xb8" // U+F0378 +#define ICON_MDI_MINUS_NETWORK_OUTLINE "\xf3\xb0\xb2\x9a" // U+F0C9A +#define ICON_MDI_MINUS_THICK "\xf3\xb1\x98\xb9" // U+F1639 +#define ICON_MDI_MIRROR "\xf3\xb1\x87\xbd" // U+F11FD +#define ICON_MDI_MIRROR_RECTANGLE "\xf3\xb1\x9e\x9f" // U+F179F +#define ICON_MDI_MIRROR_VARIANT "\xf3\xb1\x9e\xa0" // U+F17A0 +#define ICON_MDI_MIXED_MARTIAL_ARTS "\xf3\xb0\xb6\x8f" // U+F0D8F +#define ICON_MDI_MIXED_REALITY "\xf3\xb0\xa1\xbf" // U+F087F +#define ICON_MDI_MOLECULE "\xf3\xb0\xae\xac" // U+F0BAC +#define ICON_MDI_MOLECULE_CO "\xf3\xb1\x8b\xbe" // U+F12FE +#define ICON_MDI_MOLECULE_CO2 "\xf3\xb0\x9f\xa4" // U+F07E4 +#define ICON_MDI_MONITOR "\xf3\xb0\x8d\xb9" // U+F0379 +#define ICON_MDI_MONITOR_ACCOUNT "\xf3\xb1\xa9\x9b" // U+F1A5B +#define ICON_MDI_MONITOR_ARROW_DOWN "\xf3\xb1\xa7\x90" // U+F19D0 +#define ICON_MDI_MONITOR_ARROW_DOWN_VARIANT "\xf3\xb1\xa7\x91" // U+F19D1 +#define ICON_MDI_MONITOR_CELLPHONE "\xf3\xb0\xa6\x89" // U+F0989 +#define ICON_MDI_MONITOR_CELLPHONE_STAR "\xf3\xb0\xa6\x8a" // U+F098A +#define ICON_MDI_MONITOR_DASHBOARD "\xf3\xb0\xa8\x87" // U+F0A07 +#define ICON_MDI_MONITOR_EDIT "\xf3\xb1\x8b\x86" // U+F12C6 +#define ICON_MDI_MONITOR_EYE "\xf3\xb1\x8e\xb4" // U+F13B4 +#define ICON_MDI_MONITOR_LOCK "\xf3\xb0\xb7\x9b" // U+F0DDB +#define ICON_MDI_MONITOR_MULTIPLE "\xf3\xb0\x8d\xba" // U+F037A +#define ICON_MDI_MONITOR_OFF "\xf3\xb0\xb6\x90" // U+F0D90 +#define ICON_MDI_MONITOR_SCREENSHOT "\xf3\xb0\xb9\x91" // U+F0E51 +#define ICON_MDI_MONITOR_SHARE "\xf3\xb1\x92\x83" // U+F1483 +#define ICON_MDI_MONITOR_SHIMMER "\xf3\xb1\x84\x84" // U+F1104 +#define ICON_MDI_MONITOR_SMALL "\xf3\xb1\xa1\xb6" // U+F1876 +#define ICON_MDI_MONITOR_SPEAKER "\xf3\xb0\xbd\x9f" // U+F0F5F +#define ICON_MDI_MONITOR_SPEAKER_OFF "\xf3\xb0\xbd\xa0" // U+F0F60 +#define ICON_MDI_MONITOR_STAR "\xf3\xb0\xb7\x9c" // U+F0DDC +#define ICON_MDI_MONITOR_VERTICAL "\xf3\xb1\xb0\xb3" // U+F1C33 +#define ICON_MDI_MOON_FIRST_QUARTER "\xf3\xb0\xbd\xa1" // U+F0F61 +#define ICON_MDI_MOON_FULL "\xf3\xb0\xbd\xa2" // U+F0F62 +#define ICON_MDI_MOON_LAST_QUARTER "\xf3\xb0\xbd\xa3" // U+F0F63 +#define ICON_MDI_MOON_NEW "\xf3\xb0\xbd\xa4" // U+F0F64 +#define ICON_MDI_MOON_WANING_CRESCENT "\xf3\xb0\xbd\xa5" // U+F0F65 +#define ICON_MDI_MOON_WANING_GIBBOUS "\xf3\xb0\xbd\xa6" // U+F0F66 +#define ICON_MDI_MOON_WAXING_CRESCENT "\xf3\xb0\xbd\xa7" // U+F0F67 +#define ICON_MDI_MOON_WAXING_GIBBOUS "\xf3\xb0\xbd\xa8" // U+F0F68 +#define ICON_MDI_MOPED "\xf3\xb1\x82\x86" // U+F1086 +#define ICON_MDI_MOPED_ELECTRIC "\xf3\xb1\x96\xb7" // U+F15B7 +#define ICON_MDI_MOPED_ELECTRIC_OUTLINE "\xf3\xb1\x96\xb8" // U+F15B8 +#define ICON_MDI_MOPED_OUTLINE "\xf3\xb1\x96\xb9" // U+F15B9 +#define ICON_MDI_MORE "\xf3\xb0\x8d\xbb" // U+F037B +#define ICON_MDI_MORTAR_PESTLE "\xf3\xb1\x9d\x88" // U+F1748 +#define ICON_MDI_MORTAR_PESTLE_PLUS "\xf3\xb0\x8f\xb1" // U+F03F1 +#define ICON_MDI_MOSQUE "\xf3\xb0\xb5\x85" // U+F0D45 +#define ICON_MDI_MOSQUE_OUTLINE "\xf3\xb1\xa0\xa7" // U+F1827 +#define ICON_MDI_MOTHER_HEART "\xf3\xb1\x8c\x94" // U+F1314 +#define ICON_MDI_MOTHER_NURSE "\xf3\xb0\xb4\xa1" // U+F0D21 +#define ICON_MDI_MOTION "\xf3\xb1\x96\xb2" // U+F15B2 +#define ICON_MDI_MOTION_OUTLINE "\xf3\xb1\x96\xb3" // U+F15B3 +#define ICON_MDI_MOTION_PAUSE "\xf3\xb1\x96\x90" // U+F1590 +#define ICON_MDI_MOTION_PAUSE_OUTLINE "\xf3\xb1\x96\x92" // U+F1592 +#define ICON_MDI_MOTION_PLAY "\xf3\xb1\x96\x8f" // U+F158F +#define ICON_MDI_MOTION_PLAY_OUTLINE "\xf3\xb1\x96\x91" // U+F1591 +#define ICON_MDI_MOTION_SENSOR "\xf3\xb0\xb6\x91" // U+F0D91 +#define ICON_MDI_MOTION_SENSOR_OFF "\xf3\xb1\x90\xb5" // U+F1435 +#define ICON_MDI_MOTORBIKE "\xf3\xb0\x8d\xbc" // U+F037C +#define ICON_MDI_MOTORBIKE_ELECTRIC "\xf3\xb1\x96\xba" // U+F15BA +#define ICON_MDI_MOTORBIKE_OFF "\xf3\xb1\xac\x96" // U+F1B16 +#define ICON_MDI_MOUSE "\xf3\xb0\x8d\xbd" // U+F037D +#define ICON_MDI_MOUSE_BLUETOOTH "\xf3\xb0\xa6\x8b" // U+F098B +#define ICON_MDI_MOUSE_MOVE_DOWN "\xf3\xb1\x95\x90" // U+F1550 +#define ICON_MDI_MOUSE_MOVE_UP "\xf3\xb1\x95\x91" // U+F1551 +#define ICON_MDI_MOUSE_MOVE_VERTICAL "\xf3\xb1\x95\x92" // U+F1552 +#define ICON_MDI_MOUSE_OFF "\xf3\xb0\x8d\xbe" // U+F037E +#define ICON_MDI_MOUSE_VARIANT "\xf3\xb0\x8d\xbf" // U+F037F +#define ICON_MDI_MOUSE_VARIANT_OFF "\xf3\xb0\x8e\x80" // U+F0380 +#define ICON_MDI_MOVE_RESIZE "\xf3\xb0\x99\x95" // U+F0655 +#define ICON_MDI_MOVE_RESIZE_VARIANT "\xf3\xb0\x99\x96" // U+F0656 +#define ICON_MDI_MOVIE "\xf3\xb0\x8e\x81" // U+F0381 +#define ICON_MDI_MOVIE_CHECK "\xf3\xb1\x9b\xb3" // U+F16F3 +#define ICON_MDI_MOVIE_CHECK_OUTLINE "\xf3\xb1\x9b\xb4" // U+F16F4 +#define ICON_MDI_MOVIE_COG "\xf3\xb1\x9b\xb5" // U+F16F5 +#define ICON_MDI_MOVIE_COG_OUTLINE "\xf3\xb1\x9b\xb6" // U+F16F6 +#define ICON_MDI_MOVIE_EDIT "\xf3\xb1\x84\xa2" // U+F1122 +#define ICON_MDI_MOVIE_EDIT_OUTLINE "\xf3\xb1\x84\xa3" // U+F1123 +#define ICON_MDI_MOVIE_FILTER "\xf3\xb1\x84\xa4" // U+F1124 +#define ICON_MDI_MOVIE_FILTER_OUTLINE "\xf3\xb1\x84\xa5" // U+F1125 +#define ICON_MDI_MOVIE_MINUS "\xf3\xb1\x9b\xb7" // U+F16F7 +#define ICON_MDI_MOVIE_MINUS_OUTLINE "\xf3\xb1\x9b\xb8" // U+F16F8 +#define ICON_MDI_MOVIE_OFF "\xf3\xb1\x9b\xb9" // U+F16F9 +#define ICON_MDI_MOVIE_OFF_OUTLINE "\xf3\xb1\x9b\xba" // U+F16FA +#define ICON_MDI_MOVIE_OPEN "\xf3\xb0\xbf\x8e" // U+F0FCE +#define ICON_MDI_MOVIE_OPEN_CHECK "\xf3\xb1\x9b\xbb" // U+F16FB +#define ICON_MDI_MOVIE_OPEN_CHECK_OUTLINE "\xf3\xb1\x9b\xbc" // U+F16FC +#define ICON_MDI_MOVIE_OPEN_COG "\xf3\xb1\x9b\xbd" // U+F16FD +#define ICON_MDI_MOVIE_OPEN_COG_OUTLINE "\xf3\xb1\x9b\xbe" // U+F16FE +#define ICON_MDI_MOVIE_OPEN_EDIT "\xf3\xb1\x9b\xbf" // U+F16FF +#define ICON_MDI_MOVIE_OPEN_EDIT_OUTLINE "\xf3\xb1\x9c\x80" // U+F1700 +#define ICON_MDI_MOVIE_OPEN_MINUS "\xf3\xb1\x9c\x81" // U+F1701 +#define ICON_MDI_MOVIE_OPEN_MINUS_OUTLINE "\xf3\xb1\x9c\x82" // U+F1702 +#define ICON_MDI_MOVIE_OPEN_OFF "\xf3\xb1\x9c\x83" // U+F1703 +#define ICON_MDI_MOVIE_OPEN_OFF_OUTLINE "\xf3\xb1\x9c\x84" // U+F1704 +#define ICON_MDI_MOVIE_OPEN_OUTLINE "\xf3\xb0\xbf\x8f" // U+F0FCF +#define ICON_MDI_MOVIE_OPEN_PLAY "\xf3\xb1\x9c\x85" // U+F1705 +#define ICON_MDI_MOVIE_OPEN_PLAY_OUTLINE "\xf3\xb1\x9c\x86" // U+F1706 +#define ICON_MDI_MOVIE_OPEN_PLUS "\xf3\xb1\x9c\x87" // U+F1707 +#define ICON_MDI_MOVIE_OPEN_PLUS_OUTLINE "\xf3\xb1\x9c\x88" // U+F1708 +#define ICON_MDI_MOVIE_OPEN_REMOVE "\xf3\xb1\x9c\x89" // U+F1709 +#define ICON_MDI_MOVIE_OPEN_REMOVE_OUTLINE "\xf3\xb1\x9c\x8a" // U+F170A +#define ICON_MDI_MOVIE_OPEN_SETTINGS "\xf3\xb1\x9c\x8b" // U+F170B +#define ICON_MDI_MOVIE_OPEN_SETTINGS_OUTLINE "\xf3\xb1\x9c\x8c" // U+F170C +#define ICON_MDI_MOVIE_OPEN_STAR "\xf3\xb1\x9c\x8d" // U+F170D +#define ICON_MDI_MOVIE_OPEN_STAR_OUTLINE "\xf3\xb1\x9c\x8e" // U+F170E +#define ICON_MDI_MOVIE_OUTLINE "\xf3\xb0\xb7\x9d" // U+F0DDD +#define ICON_MDI_MOVIE_PLAY "\xf3\xb1\x9c\x8f" // U+F170F +#define ICON_MDI_MOVIE_PLAY_OUTLINE "\xf3\xb1\x9c\x90" // U+F1710 +#define ICON_MDI_MOVIE_PLUS "\xf3\xb1\x9c\x91" // U+F1711 +#define ICON_MDI_MOVIE_PLUS_OUTLINE "\xf3\xb1\x9c\x92" // U+F1712 +#define ICON_MDI_MOVIE_REMOVE "\xf3\xb1\x9c\x93" // U+F1713 +#define ICON_MDI_MOVIE_REMOVE_OUTLINE "\xf3\xb1\x9c\x94" // U+F1714 +#define ICON_MDI_MOVIE_ROLL "\xf3\xb0\x9f\x9e" // U+F07DE +#define ICON_MDI_MOVIE_SEARCH "\xf3\xb1\x87\x92" // U+F11D2 +#define ICON_MDI_MOVIE_SEARCH_OUTLINE "\xf3\xb1\x87\x93" // U+F11D3 +#define ICON_MDI_MOVIE_SETTINGS "\xf3\xb1\x9c\x95" // U+F1715 +#define ICON_MDI_MOVIE_SETTINGS_OUTLINE "\xf3\xb1\x9c\x96" // U+F1716 +#define ICON_MDI_MOVIE_STAR "\xf3\xb1\x9c\x97" // U+F1717 +#define ICON_MDI_MOVIE_STAR_OUTLINE "\xf3\xb1\x9c\x98" // U+F1718 +#define ICON_MDI_MOWER "\xf3\xb1\x99\xaf" // U+F166F +#define ICON_MDI_MOWER_BAG "\xf3\xb1\x99\xb0" // U+F1670 +#define ICON_MDI_MOWER_BAG_ON "\xf3\xb1\xad\xa0" // U+F1B60 +#define ICON_MDI_MOWER_ON "\xf3\xb1\xad\x9f" // U+F1B5F +#define ICON_MDI_MUFFIN "\xf3\xb0\xa6\x8c" // U+F098C +#define ICON_MDI_MULTICAST "\xf3\xb1\xa2\x93" // U+F1893 +#define ICON_MDI_MULTIMEDIA "\xf3\xb1\xae\x97" // U+F1B97 +#define ICON_MDI_MULTIPLICATION "\xf3\xb0\x8e\x82" // U+F0382 +#define ICON_MDI_MULTIPLICATION_BOX "\xf3\xb0\x8e\x83" // U+F0383 +#define ICON_MDI_MUSHROOM "\xf3\xb0\x9f\x9f" // U+F07DF +#define ICON_MDI_MUSHROOM_OFF "\xf3\xb1\x8f\xba" // U+F13FA +#define ICON_MDI_MUSHROOM_OFF_OUTLINE "\xf3\xb1\x8f\xbb" // U+F13FB +#define ICON_MDI_MUSHROOM_OUTLINE "\xf3\xb0\x9f\xa0" // U+F07E0 +#define ICON_MDI_MUSIC "\xf3\xb0\x9d\x9a" // U+F075A +#define ICON_MDI_MUSIC_ACCIDENTAL_DOUBLE_FLAT "\xf3\xb0\xbd\xa9" // U+F0F69 +#define ICON_MDI_MUSIC_ACCIDENTAL_DOUBLE_SHARP "\xf3\xb0\xbd\xaa" // U+F0F6A +#define ICON_MDI_MUSIC_ACCIDENTAL_FLAT "\xf3\xb0\xbd\xab" // U+F0F6B +#define ICON_MDI_MUSIC_ACCIDENTAL_NATURAL "\xf3\xb0\xbd\xac" // U+F0F6C +#define ICON_MDI_MUSIC_ACCIDENTAL_SHARP "\xf3\xb0\xbd\xad" // U+F0F6D +#define ICON_MDI_MUSIC_BOX "\xf3\xb0\x8e\x84" // U+F0384 +#define ICON_MDI_MUSIC_BOX_MULTIPLE "\xf3\xb0\x8c\xb3" // U+F0333 +#define ICON_MDI_MUSIC_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xbc\x84" // U+F0F04 +#define ICON_MDI_MUSIC_BOX_OUTLINE "\xf3\xb0\x8e\x85" // U+F0385 +#define ICON_MDI_MUSIC_CIRCLE "\xf3\xb0\x8e\x86" // U+F0386 +#define ICON_MDI_MUSIC_CIRCLE_OUTLINE "\xf3\xb0\xab\x94" // U+F0AD4 +#define ICON_MDI_MUSIC_CLEF_ALTO "\xf3\xb0\xbd\xae" // U+F0F6E +#define ICON_MDI_MUSIC_CLEF_BASS "\xf3\xb0\xbd\xaf" // U+F0F6F +#define ICON_MDI_MUSIC_CLEF_TREBLE "\xf3\xb0\xbd\xb0" // U+F0F70 +#define ICON_MDI_MUSIC_NOTE "\xf3\xb0\x8e\x87" // U+F0387 +#define ICON_MDI_MUSIC_NOTE_BLUETOOTH "\xf3\xb0\x97\xbe" // U+F05FE +#define ICON_MDI_MUSIC_NOTE_BLUETOOTH_OFF "\xf3\xb0\x97\xbf" // U+F05FF +#define ICON_MDI_MUSIC_NOTE_EIGHTH "\xf3\xb0\x8e\x88" // U+F0388 +#define ICON_MDI_MUSIC_NOTE_EIGHTH_DOTTED "\xf3\xb0\xbd\xb1" // U+F0F71 +#define ICON_MDI_MUSIC_NOTE_HALF "\xf3\xb0\x8e\x89" // U+F0389 +#define ICON_MDI_MUSIC_NOTE_HALF_DOTTED "\xf3\xb0\xbd\xb2" // U+F0F72 +#define ICON_MDI_MUSIC_NOTE_MINUS "\xf3\xb1\xae\x89" // U+F1B89 +#define ICON_MDI_MUSIC_NOTE_OFF "\xf3\xb0\x8e\x8a" // U+F038A +#define ICON_MDI_MUSIC_NOTE_OFF_OUTLINE "\xf3\xb0\xbd\xb3" // U+F0F73 +#define ICON_MDI_MUSIC_NOTE_OUTLINE "\xf3\xb0\xbd\xb4" // U+F0F74 +#define ICON_MDI_MUSIC_NOTE_PLUS "\xf3\xb0\xb7\x9e" // U+F0DDE +#define ICON_MDI_MUSIC_NOTE_QUARTER "\xf3\xb0\x8e\x8b" // U+F038B +#define ICON_MDI_MUSIC_NOTE_QUARTER_DOTTED "\xf3\xb0\xbd\xb5" // U+F0F75 +#define ICON_MDI_MUSIC_NOTE_SIXTEENTH "\xf3\xb0\x8e\x8c" // U+F038C +#define ICON_MDI_MUSIC_NOTE_SIXTEENTH_DOTTED "\xf3\xb0\xbd\xb6" // U+F0F76 +#define ICON_MDI_MUSIC_NOTE_WHOLE "\xf3\xb0\x8e\x8d" // U+F038D +#define ICON_MDI_MUSIC_NOTE_WHOLE_DOTTED "\xf3\xb0\xbd\xb7" // U+F0F77 +#define ICON_MDI_MUSIC_OFF "\xf3\xb0\x9d\x9b" // U+F075B +#define ICON_MDI_MUSIC_REST_EIGHTH "\xf3\xb0\xbd\xb8" // U+F0F78 +#define ICON_MDI_MUSIC_REST_HALF "\xf3\xb0\xbd\xb9" // U+F0F79 +#define ICON_MDI_MUSIC_REST_QUARTER "\xf3\xb0\xbd\xba" // U+F0F7A +#define ICON_MDI_MUSIC_REST_SIXTEENTH "\xf3\xb0\xbd\xbb" // U+F0F7B +#define ICON_MDI_MUSIC_REST_WHOLE "\xf3\xb0\xbd\xbc" // U+F0F7C +#define ICON_MDI_MUSTACHE "\xf3\xb1\x97\x9e" // U+F15DE +#define ICON_MDI_NAIL "\xf3\xb0\xb7\x9f" // U+F0DDF +#define ICON_MDI_NAS "\xf3\xb0\xa3\xb3" // U+F08F3 +#define ICON_MDI_NATIVESCRIPT "\xf3\xb0\xa2\x80" // U+F0880 +#define ICON_MDI_NATURE "\xf3\xb0\x8e\x8e" // U+F038E +#define ICON_MDI_NATURE_OUTLINE "\xf3\xb1\xb1\xb1" // U+F1C71 +#define ICON_MDI_NATURE_PEOPLE "\xf3\xb0\x8e\x8f" // U+F038F +#define ICON_MDI_NATURE_PEOPLE_OUTLINE "\xf3\xb1\xb1\xb2" // U+F1C72 +#define ICON_MDI_NAVIGATION "\xf3\xb0\x8e\x90" // U+F0390 +#define ICON_MDI_NAVIGATION_OUTLINE "\xf3\xb1\x98\x87" // U+F1607 +#define ICON_MDI_NAVIGATION_VARIANT "\xf3\xb1\xa3\xb0" // U+F18F0 +#define ICON_MDI_NAVIGATION_VARIANT_OUTLINE "\xf3\xb1\xa3\xb1" // U+F18F1 +#define ICON_MDI_NEAR_ME "\xf3\xb0\x97\x8d" // U+F05CD +#define ICON_MDI_NECKLACE "\xf3\xb0\xbc\x8b" // U+F0F0B +#define ICON_MDI_NEEDLE "\xf3\xb0\x8e\x91" // U+F0391 +#define ICON_MDI_NEEDLE_OFF "\xf3\xb1\xa7\x92" // U+F19D2 +#define ICON_MDI_NETFLIX "\xf3\xb0\x9d\x86" // U+F0746 +#define ICON_MDI_NETWORK "\xf3\xb0\x9b\xb3" // U+F06F3 +#define ICON_MDI_NETWORK_OFF "\xf3\xb0\xb2\x9b" // U+F0C9B +#define ICON_MDI_NETWORK_OFF_OUTLINE "\xf3\xb0\xb2\x9c" // U+F0C9C +#define ICON_MDI_NETWORK_OUTLINE "\xf3\xb0\xb2\x9d" // U+F0C9D +#define ICON_MDI_NETWORK_POS "\xf3\xb1\xab\x8b" // U+F1ACB +#define ICON_MDI_NETWORK_STRENGTH_1 "\xf3\xb0\xa3\xb4" // U+F08F4 +#define ICON_MDI_NETWORK_STRENGTH_1_ALERT "\xf3\xb0\xa3\xb5" // U+F08F5 +#define ICON_MDI_NETWORK_STRENGTH_2 "\xf3\xb0\xa3\xb6" // U+F08F6 +#define ICON_MDI_NETWORK_STRENGTH_2_ALERT "\xf3\xb0\xa3\xb7" // U+F08F7 +#define ICON_MDI_NETWORK_STRENGTH_3 "\xf3\xb0\xa3\xb8" // U+F08F8 +#define ICON_MDI_NETWORK_STRENGTH_3_ALERT "\xf3\xb0\xa3\xb9" // U+F08F9 +#define ICON_MDI_NETWORK_STRENGTH_4 "\xf3\xb0\xa3\xba" // U+F08FA +#define ICON_MDI_NETWORK_STRENGTH_4_ALERT "\xf3\xb0\xa3\xbb" // U+F08FB +#define ICON_MDI_NETWORK_STRENGTH_4_COG "\xf3\xb1\xa4\x9a" // U+F191A +#define ICON_MDI_NETWORK_STRENGTH_OFF "\xf3\xb0\xa3\xbc" // U+F08FC +#define ICON_MDI_NETWORK_STRENGTH_OFF_OUTLINE "\xf3\xb0\xa3\xbd" // U+F08FD +#define ICON_MDI_NETWORK_STRENGTH_OUTLINE "\xf3\xb0\xa3\xbe" // U+F08FE +#define ICON_MDI_NEW_BOX "\xf3\xb0\x8e\x94" // U+F0394 +#define ICON_MDI_NEWSPAPER "\xf3\xb0\x8e\x95" // U+F0395 +#define ICON_MDI_NEWSPAPER_CHECK "\xf3\xb1\xa5\x83" // U+F1943 +#define ICON_MDI_NEWSPAPER_MINUS "\xf3\xb0\xbc\x8c" // U+F0F0C +#define ICON_MDI_NEWSPAPER_PLUS "\xf3\xb0\xbc\x8d" // U+F0F0D +#define ICON_MDI_NEWSPAPER_REMOVE "\xf3\xb1\xa5\x84" // U+F1944 +#define ICON_MDI_NEWSPAPER_VARIANT "\xf3\xb1\x80\x81" // U+F1001 +#define ICON_MDI_NEWSPAPER_VARIANT_MULTIPLE "\xf3\xb1\x80\x82" // U+F1002 +#define ICON_MDI_NEWSPAPER_VARIANT_MULTIPLE_OUTLINE "\xf3\xb1\x80\x83" // U+F1003 +#define ICON_MDI_NEWSPAPER_VARIANT_OUTLINE "\xf3\xb1\x80\x84" // U+F1004 +#define ICON_MDI_NFC "\xf3\xb0\x8e\x96" // U+F0396 +#define ICON_MDI_NFC_SEARCH_VARIANT "\xf3\xb0\xb9\x93" // U+F0E53 +#define ICON_MDI_NFC_TAP "\xf3\xb0\x8e\x97" // U+F0397 +#define ICON_MDI_NFC_VARIANT "\xf3\xb0\x8e\x98" // U+F0398 +#define ICON_MDI_NFC_VARIANT_OFF "\xf3\xb0\xb9\x94" // U+F0E54 +#define ICON_MDI_NINJA "\xf3\xb0\x9d\xb4" // U+F0774 +#define ICON_MDI_NINTENDO_GAME_BOY "\xf3\xb1\x8e\x93" // U+F1393 +#define ICON_MDI_NINTENDO_SWITCH "\xf3\xb0\x9f\xa1" // U+F07E1 +#define ICON_MDI_NINTENDO_WII "\xf3\xb0\x96\xab" // U+F05AB +#define ICON_MDI_NINTENDO_WIIU "\xf3\xb0\x9c\xad" // U+F072D +#define ICON_MDI_NIX "\xf3\xb1\x84\x85" // U+F1105 +#define ICON_MDI_NODEJS "\xf3\xb0\x8e\x99" // U+F0399 +#define ICON_MDI_NOODLES "\xf3\xb1\x85\xbe" // U+F117E +#define ICON_MDI_NOT_EQUAL "\xf3\xb0\xa6\x8d" // U+F098D +#define ICON_MDI_NOT_EQUAL_VARIANT "\xf3\xb0\xa6\x8e" // U+F098E +#define ICON_MDI_NOTE "\xf3\xb0\x8e\x9a" // U+F039A +#define ICON_MDI_NOTE_ALERT "\xf3\xb1\x9d\xbd" // U+F177D +#define ICON_MDI_NOTE_ALERT_OUTLINE "\xf3\xb1\x9d\xbe" // U+F177E +#define ICON_MDI_NOTE_CHECK "\xf3\xb1\x9d\xbf" // U+F177F +#define ICON_MDI_NOTE_CHECK_OUTLINE "\xf3\xb1\x9e\x80" // U+F1780 +#define ICON_MDI_NOTE_EDIT "\xf3\xb1\x9e\x81" // U+F1781 +#define ICON_MDI_NOTE_EDIT_OUTLINE "\xf3\xb1\x9e\x82" // U+F1782 +#define ICON_MDI_NOTE_MINUS "\xf3\xb1\x99\x8f" // U+F164F +#define ICON_MDI_NOTE_MINUS_OUTLINE "\xf3\xb1\x99\x90" // U+F1650 +#define ICON_MDI_NOTE_MULTIPLE "\xf3\xb0\x9a\xb8" // U+F06B8 +#define ICON_MDI_NOTE_MULTIPLE_OUTLINE "\xf3\xb0\x9a\xb9" // U+F06B9 +#define ICON_MDI_NOTE_OFF "\xf3\xb1\x9e\x83" // U+F1783 +#define ICON_MDI_NOTE_OFF_OUTLINE "\xf3\xb1\x9e\x84" // U+F1784 +#define ICON_MDI_NOTE_OUTLINE "\xf3\xb0\x8e\x9b" // U+F039B +#define ICON_MDI_NOTE_PLUS "\xf3\xb0\x8e\x9c" // U+F039C +#define ICON_MDI_NOTE_PLUS_OUTLINE "\xf3\xb0\x8e\x9d" // U+F039D +#define ICON_MDI_NOTE_REMOVE "\xf3\xb1\x99\x91" // U+F1651 +#define ICON_MDI_NOTE_REMOVE_OUTLINE "\xf3\xb1\x99\x92" // U+F1652 +#define ICON_MDI_NOTE_SEARCH "\xf3\xb1\x99\x93" // U+F1653 +#define ICON_MDI_NOTE_SEARCH_OUTLINE "\xf3\xb1\x99\x94" // U+F1654 +#define ICON_MDI_NOTE_TEXT "\xf3\xb0\x8e\x9e" // U+F039E +#define ICON_MDI_NOTE_TEXT_OUTLINE "\xf3\xb1\x87\x97" // U+F11D7 +#define ICON_MDI_NOTEBOOK "\xf3\xb0\xa0\xae" // U+F082E +#define ICON_MDI_NOTEBOOK_CHECK "\xf3\xb1\x93\xb5" // U+F14F5 +#define ICON_MDI_NOTEBOOK_CHECK_OUTLINE "\xf3\xb1\x93\xb6" // U+F14F6 +#define ICON_MDI_NOTEBOOK_EDIT "\xf3\xb1\x93\xa7" // U+F14E7 +#define ICON_MDI_NOTEBOOK_EDIT_OUTLINE "\xf3\xb1\x93\xa9" // U+F14E9 +#define ICON_MDI_NOTEBOOK_HEART "\xf3\xb1\xa8\x8b" // U+F1A0B +#define ICON_MDI_NOTEBOOK_HEART_OUTLINE "\xf3\xb1\xa8\x8c" // U+F1A0C +#define ICON_MDI_NOTEBOOK_MINUS "\xf3\xb1\x98\x90" // U+F1610 +#define ICON_MDI_NOTEBOOK_MINUS_OUTLINE "\xf3\xb1\x98\x91" // U+F1611 +#define ICON_MDI_NOTEBOOK_MULTIPLE "\xf3\xb0\xb9\x95" // U+F0E55 +#define ICON_MDI_NOTEBOOK_OUTLINE "\xf3\xb0\xba\xbf" // U+F0EBF +#define ICON_MDI_NOTEBOOK_PLUS "\xf3\xb1\x98\x92" // U+F1612 +#define ICON_MDI_NOTEBOOK_PLUS_OUTLINE "\xf3\xb1\x98\x93" // U+F1613 +#define ICON_MDI_NOTEBOOK_REMOVE "\xf3\xb1\x98\x94" // U+F1614 +#define ICON_MDI_NOTEBOOK_REMOVE_OUTLINE "\xf3\xb1\x98\x95" // U+F1615 +#define ICON_MDI_NOTIFICATION_CLEAR_ALL "\xf3\xb0\x8e\x9f" // U+F039F +#define ICON_MDI_NPM "\xf3\xb0\x9b\xb7" // U+F06F7 +#define ICON_MDI_NUKE "\xf3\xb0\x9a\xa4" // U+F06A4 +#define ICON_MDI_NULL "\xf3\xb0\x9f\xa2" // U+F07E2 +#define ICON_MDI_NUMERIC "\xf3\xb0\x8e\xa0" // U+F03A0 +#define ICON_MDI_NUMERIC_0 "\xf3\xb0\xac\xb9" // U+F0B39 +#define ICON_MDI_NUMERIC_0_BOX "\xf3\xb0\x8e\xa1" // U+F03A1 +#define ICON_MDI_NUMERIC_0_BOX_MULTIPLE "\xf3\xb0\xbc\x8e" // U+F0F0E +#define ICON_MDI_NUMERIC_0_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa2" // U+F03A2 +#define ICON_MDI_NUMERIC_0_BOX_OUTLINE "\xf3\xb0\x8e\xa3" // U+F03A3 +#define ICON_MDI_NUMERIC_0_CIRCLE "\xf3\xb0\xb2\x9e" // U+F0C9E +#define ICON_MDI_NUMERIC_0_CIRCLE_OUTLINE "\xf3\xb0\xb2\x9f" // U+F0C9F +#define ICON_MDI_NUMERIC_1 "\xf3\xb0\xac\xba" // U+F0B3A +#define ICON_MDI_NUMERIC_1_BOX "\xf3\xb0\x8e\xa4" // U+F03A4 +#define ICON_MDI_NUMERIC_1_BOX_MULTIPLE "\xf3\xb0\xbc\x8f" // U+F0F0F +#define ICON_MDI_NUMERIC_1_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa5" // U+F03A5 +#define ICON_MDI_NUMERIC_1_BOX_OUTLINE "\xf3\xb0\x8e\xa6" // U+F03A6 +#define ICON_MDI_NUMERIC_1_CIRCLE "\xf3\xb0\xb2\xa0" // U+F0CA0 +#define ICON_MDI_NUMERIC_1_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa1" // U+F0CA1 +#define ICON_MDI_NUMERIC_10 "\xf3\xb0\xbf\xa9" // U+F0FE9 +#define ICON_MDI_NUMERIC_10_BOX "\xf3\xb0\xbd\xbd" // U+F0F7D +#define ICON_MDI_NUMERIC_10_BOX_MULTIPLE "\xf3\xb0\xbf\xaa" // U+F0FEA +#define ICON_MDI_NUMERIC_10_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xbf\xab" // U+F0FEB +#define ICON_MDI_NUMERIC_10_BOX_OUTLINE "\xf3\xb0\xbd\xbe" // U+F0F7E +#define ICON_MDI_NUMERIC_10_CIRCLE "\xf3\xb0\xbf\xac" // U+F0FEC +#define ICON_MDI_NUMERIC_10_CIRCLE_OUTLINE "\xf3\xb0\xbf\xad" // U+F0FED +#define ICON_MDI_NUMERIC_2 "\xf3\xb0\xac\xbb" // U+F0B3B +#define ICON_MDI_NUMERIC_2_BOX "\xf3\xb0\x8e\xa7" // U+F03A7 +#define ICON_MDI_NUMERIC_2_BOX_MULTIPLE "\xf3\xb0\xbc\x90" // U+F0F10 +#define ICON_MDI_NUMERIC_2_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xa8" // U+F03A8 +#define ICON_MDI_NUMERIC_2_BOX_OUTLINE "\xf3\xb0\x8e\xa9" // U+F03A9 +#define ICON_MDI_NUMERIC_2_CIRCLE "\xf3\xb0\xb2\xa2" // U+F0CA2 +#define ICON_MDI_NUMERIC_2_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa3" // U+F0CA3 +#define ICON_MDI_NUMERIC_3 "\xf3\xb0\xac\xbc" // U+F0B3C +#define ICON_MDI_NUMERIC_3_BOX "\xf3\xb0\x8e\xaa" // U+F03AA +#define ICON_MDI_NUMERIC_3_BOX_MULTIPLE "\xf3\xb0\xbc\x91" // U+F0F11 +#define ICON_MDI_NUMERIC_3_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xab" // U+F03AB +#define ICON_MDI_NUMERIC_3_BOX_OUTLINE "\xf3\xb0\x8e\xac" // U+F03AC +#define ICON_MDI_NUMERIC_3_CIRCLE "\xf3\xb0\xb2\xa4" // U+F0CA4 +#define ICON_MDI_NUMERIC_3_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa5" // U+F0CA5 +#define ICON_MDI_NUMERIC_4 "\xf3\xb0\xac\xbd" // U+F0B3D +#define ICON_MDI_NUMERIC_4_BOX "\xf3\xb0\x8e\xad" // U+F03AD +#define ICON_MDI_NUMERIC_4_BOX_MULTIPLE "\xf3\xb0\xbc\x92" // U+F0F12 +#define ICON_MDI_NUMERIC_4_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb2" // U+F03B2 +#define ICON_MDI_NUMERIC_4_BOX_OUTLINE "\xf3\xb0\x8e\xae" // U+F03AE +#define ICON_MDI_NUMERIC_4_CIRCLE "\xf3\xb0\xb2\xa6" // U+F0CA6 +#define ICON_MDI_NUMERIC_4_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa7" // U+F0CA7 +#define ICON_MDI_NUMERIC_5 "\xf3\xb0\xac\xbe" // U+F0B3E +#define ICON_MDI_NUMERIC_5_BOX "\xf3\xb0\x8e\xb1" // U+F03B1 +#define ICON_MDI_NUMERIC_5_BOX_MULTIPLE "\xf3\xb0\xbc\x93" // U+F0F13 +#define ICON_MDI_NUMERIC_5_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xaf" // U+F03AF +#define ICON_MDI_NUMERIC_5_BOX_OUTLINE "\xf3\xb0\x8e\xb0" // U+F03B0 +#define ICON_MDI_NUMERIC_5_CIRCLE "\xf3\xb0\xb2\xa8" // U+F0CA8 +#define ICON_MDI_NUMERIC_5_CIRCLE_OUTLINE "\xf3\xb0\xb2\xa9" // U+F0CA9 +#define ICON_MDI_NUMERIC_6 "\xf3\xb0\xac\xbf" // U+F0B3F +#define ICON_MDI_NUMERIC_6_BOX "\xf3\xb0\x8e\xb3" // U+F03B3 +#define ICON_MDI_NUMERIC_6_BOX_MULTIPLE "\xf3\xb0\xbc\x94" // U+F0F14 +#define ICON_MDI_NUMERIC_6_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb4" // U+F03B4 +#define ICON_MDI_NUMERIC_6_BOX_OUTLINE "\xf3\xb0\x8e\xb5" // U+F03B5 +#define ICON_MDI_NUMERIC_6_CIRCLE "\xf3\xb0\xb2\xaa" // U+F0CAA +#define ICON_MDI_NUMERIC_6_CIRCLE_OUTLINE "\xf3\xb0\xb2\xab" // U+F0CAB +#define ICON_MDI_NUMERIC_7 "\xf3\xb0\xad\x80" // U+F0B40 +#define ICON_MDI_NUMERIC_7_BOX "\xf3\xb0\x8e\xb6" // U+F03B6 +#define ICON_MDI_NUMERIC_7_BOX_MULTIPLE "\xf3\xb0\xbc\x95" // U+F0F15 +#define ICON_MDI_NUMERIC_7_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xb7" // U+F03B7 +#define ICON_MDI_NUMERIC_7_BOX_OUTLINE "\xf3\xb0\x8e\xb8" // U+F03B8 +#define ICON_MDI_NUMERIC_7_CIRCLE "\xf3\xb0\xb2\xac" // U+F0CAC +#define ICON_MDI_NUMERIC_7_CIRCLE_OUTLINE "\xf3\xb0\xb2\xad" // U+F0CAD +#define ICON_MDI_NUMERIC_8 "\xf3\xb0\xad\x81" // U+F0B41 +#define ICON_MDI_NUMERIC_8_BOX "\xf3\xb0\x8e\xb9" // U+F03B9 +#define ICON_MDI_NUMERIC_8_BOX_MULTIPLE "\xf3\xb0\xbc\x96" // U+F0F16 +#define ICON_MDI_NUMERIC_8_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xba" // U+F03BA +#define ICON_MDI_NUMERIC_8_BOX_OUTLINE "\xf3\xb0\x8e\xbb" // U+F03BB +#define ICON_MDI_NUMERIC_8_CIRCLE "\xf3\xb0\xb2\xae" // U+F0CAE +#define ICON_MDI_NUMERIC_8_CIRCLE_OUTLINE "\xf3\xb0\xb2\xaf" // U+F0CAF +#define ICON_MDI_NUMERIC_9 "\xf3\xb0\xad\x82" // U+F0B42 +#define ICON_MDI_NUMERIC_9_BOX "\xf3\xb0\x8e\xbc" // U+F03BC +#define ICON_MDI_NUMERIC_9_BOX_MULTIPLE "\xf3\xb0\xbc\x97" // U+F0F17 +#define ICON_MDI_NUMERIC_9_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8e\xbd" // U+F03BD +#define ICON_MDI_NUMERIC_9_BOX_OUTLINE "\xf3\xb0\x8e\xbe" // U+F03BE +#define ICON_MDI_NUMERIC_9_CIRCLE "\xf3\xb0\xb2\xb0" // U+F0CB0 +#define ICON_MDI_NUMERIC_9_CIRCLE_OUTLINE "\xf3\xb0\xb2\xb1" // U+F0CB1 +#define ICON_MDI_NUMERIC_9_PLUS "\xf3\xb0\xbf\xae" // U+F0FEE +#define ICON_MDI_NUMERIC_9_PLUS_BOX "\xf3\xb0\x8e\xbf" // U+F03BF +#define ICON_MDI_NUMERIC_9_PLUS_BOX_MULTIPLE "\xf3\xb0\xbc\x98" // U+F0F18 +#define ICON_MDI_NUMERIC_9_PLUS_BOX_MULTIPLE_OUTLINE "\xf3\xb0\x8f\x80" // U+F03C0 +#define ICON_MDI_NUMERIC_9_PLUS_BOX_OUTLINE "\xf3\xb0\x8f\x81" // U+F03C1 +#define ICON_MDI_NUMERIC_9_PLUS_CIRCLE "\xf3\xb0\xb2\xb2" // U+F0CB2 +#define ICON_MDI_NUMERIC_9_PLUS_CIRCLE_OUTLINE "\xf3\xb0\xb2\xb3" // U+F0CB3 +#define ICON_MDI_NUMERIC_NEGATIVE_1 "\xf3\xb1\x81\x92" // U+F1052 +#define ICON_MDI_NUMERIC_OFF "\xf3\xb1\xa7\x93" // U+F19D3 +#define ICON_MDI_NUMERIC_POSITIVE_1 "\xf3\xb1\x97\x8b" // U+F15CB +#define ICON_MDI_NUT "\xf3\xb0\x9b\xb8" // U+F06F8 +#define ICON_MDI_NUTRITION "\xf3\xb0\x8f\x82" // U+F03C2 +#define ICON_MDI_NUXT "\xf3\xb1\x84\x86" // U+F1106 +#define ICON_MDI_OAR "\xf3\xb0\x99\xbc" // U+F067C +#define ICON_MDI_OCARINA "\xf3\xb0\xb7\xa0" // U+F0DE0 +#define ICON_MDI_OCI "\xf3\xb1\x8b\xa9" // U+F12E9 +#define ICON_MDI_OCR "\xf3\xb1\x84\xba" // U+F113A +#define ICON_MDI_OCTAGON "\xf3\xb0\x8f\x83" // U+F03C3 +#define ICON_MDI_OCTAGON_OUTLINE "\xf3\xb0\x8f\x84" // U+F03C4 +#define ICON_MDI_OCTAGRAM "\xf3\xb0\x9b\xb9" // U+F06F9 +#define ICON_MDI_OCTAGRAM_EDIT "\xf3\xb1\xb0\xb4" // U+F1C34 +#define ICON_MDI_OCTAGRAM_EDIT_OUTLINE "\xf3\xb1\xb0\xb5" // U+F1C35 +#define ICON_MDI_OCTAGRAM_MINUS "\xf3\xb1\xb0\xb6" // U+F1C36 +#define ICON_MDI_OCTAGRAM_MINUS_OUTLINE "\xf3\xb1\xb0\xb7" // U+F1C37 +#define ICON_MDI_OCTAGRAM_OUTLINE "\xf3\xb0\x9d\xb5" // U+F0775 +#define ICON_MDI_OCTAGRAM_PLUS "\xf3\xb1\xb0\xb8" // U+F1C38 +#define ICON_MDI_OCTAGRAM_PLUS_OUTLINE "\xf3\xb1\xb0\xb9" // U+F1C39 +#define ICON_MDI_OCTAHEDRON "\xf3\xb1\xa5\x90" // U+F1950 +#define ICON_MDI_OCTAHEDRON_OFF "\xf3\xb1\xa5\x91" // U+F1951 +#define ICON_MDI_ODNOKLASSNIKI "\xf3\xb0\x8f\x85" // U+F03C5 +#define ICON_MDI_OFFER "\xf3\xb1\x88\x9b" // U+F121B +#define ICON_MDI_OFFICE_BUILDING "\xf3\xb0\xa6\x91" // U+F0991 +#define ICON_MDI_OFFICE_BUILDING_COG "\xf3\xb1\xa5\x89" // U+F1949 +#define ICON_MDI_OFFICE_BUILDING_COG_OUTLINE "\xf3\xb1\xa5\x8a" // U+F194A +#define ICON_MDI_OFFICE_BUILDING_MARKER "\xf3\xb1\x94\xa0" // U+F1520 +#define ICON_MDI_OFFICE_BUILDING_MARKER_OUTLINE "\xf3\xb1\x94\xa1" // U+F1521 +#define ICON_MDI_OFFICE_BUILDING_MINUS "\xf3\xb1\xae\xaa" // U+F1BAA +#define ICON_MDI_OFFICE_BUILDING_MINUS_OUTLINE "\xf3\xb1\xae\xab" // U+F1BAB +#define ICON_MDI_OFFICE_BUILDING_OUTLINE "\xf3\xb1\x94\x9f" // U+F151F +#define ICON_MDI_OFFICE_BUILDING_PLUS "\xf3\xb1\xae\xa8" // U+F1BA8 +#define ICON_MDI_OFFICE_BUILDING_PLUS_OUTLINE "\xf3\xb1\xae\xa9" // U+F1BA9 +#define ICON_MDI_OFFICE_BUILDING_REMOVE "\xf3\xb1\xae\xac" // U+F1BAC +#define ICON_MDI_OFFICE_BUILDING_REMOVE_OUTLINE "\xf3\xb1\xae\xad" // U+F1BAD +#define ICON_MDI_OIL "\xf3\xb0\x8f\x87" // U+F03C7 +#define ICON_MDI_OIL_LAMP "\xf3\xb0\xbc\x99" // U+F0F19 +#define ICON_MDI_OIL_LEVEL "\xf3\xb1\x81\x93" // U+F1053 +#define ICON_MDI_OIL_TEMPERATURE "\xf3\xb0\xbf\xb8" // U+F0FF8 +#define ICON_MDI_OM "\xf3\xb0\xa5\xb3" // U+F0973 +#define ICON_MDI_OMEGA "\xf3\xb0\x8f\x89" // U+F03C9 +#define ICON_MDI_ONE_UP "\xf3\xb0\xae\xad" // U+F0BAD +#define ICON_MDI_ONEPASSWORD "\xf3\xb0\xa2\x81" // U+F0881 +#define ICON_MDI_OPACITY "\xf3\xb0\x97\x8c" // U+F05CC +#define ICON_MDI_OPEN_IN_APP "\xf3\xb0\x8f\x8b" // U+F03CB +#define ICON_MDI_OPEN_IN_NEW "\xf3\xb0\x8f\x8c" // U+F03CC +#define ICON_MDI_OPEN_SOURCE_INITIATIVE "\xf3\xb0\xae\xae" // U+F0BAE +#define ICON_MDI_OPENID "\xf3\xb0\x8f\x8d" // U+F03CD +#define ICON_MDI_OPERA "\xf3\xb0\x8f\x8e" // U+F03CE +#define ICON_MDI_ORBIT "\xf3\xb0\x80\x98" // U+F0018 +#define ICON_MDI_ORBIT_VARIANT "\xf3\xb1\x97\x9b" // U+F15DB +#define ICON_MDI_ORDER_ALPHABETICAL_ASCENDING "\xf3\xb0\x88\x8d" // U+F020D +#define ICON_MDI_ORDER_ALPHABETICAL_DESCENDING "\xf3\xb0\xb4\x87" // U+F0D07 +#define ICON_MDI_ORDER_BOOL_ASCENDING "\xf3\xb0\x8a\xbe" // U+F02BE +#define ICON_MDI_ORDER_BOOL_ASCENDING_VARIANT "\xf3\xb0\xa6\x8f" // U+F098F +#define ICON_MDI_ORDER_BOOL_DESCENDING "\xf3\xb1\x8e\x84" // U+F1384 +#define ICON_MDI_ORDER_BOOL_DESCENDING_VARIANT "\xf3\xb0\xa6\x90" // U+F0990 +#define ICON_MDI_ORDER_NUMERIC_ASCENDING "\xf3\xb0\x95\x85" // U+F0545 +#define ICON_MDI_ORDER_NUMERIC_DESCENDING "\xf3\xb0\x95\x86" // U+F0546 +#define ICON_MDI_ORIGIN "\xf3\xb0\xad\x83" // U+F0B43 +#define ICON_MDI_ORNAMENT "\xf3\xb0\x8f\x8f" // U+F03CF +#define ICON_MDI_ORNAMENT_VARIANT "\xf3\xb0\x8f\x90" // U+F03D0 +#define ICON_MDI_OUTDOOR_LAMP "\xf3\xb1\x81\x94" // U+F1054 +#define ICON_MDI_OVERSCAN "\xf3\xb1\x80\x85" // U+F1005 +#define ICON_MDI_OWL "\xf3\xb0\x8f\x92" // U+F03D2 +#define ICON_MDI_PAC_MAN "\xf3\xb0\xae\xaf" // U+F0BAF +#define ICON_MDI_PACKAGE "\xf3\xb0\x8f\x93" // U+F03D3 +#define ICON_MDI_PACKAGE_CHECK "\xf3\xb1\xad\x91" // U+F1B51 +#define ICON_MDI_PACKAGE_DOWN "\xf3\xb0\x8f\x94" // U+F03D4 +#define ICON_MDI_PACKAGE_UP "\xf3\xb0\x8f\x95" // U+F03D5 +#define ICON_MDI_PACKAGE_VARIANT "\xf3\xb0\x8f\x96" // U+F03D6 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED "\xf3\xb0\x8f\x97" // U+F03D7 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_CHECK "\xf3\xb1\xad\x92" // U+F1B52 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_MINUS "\xf3\xb1\xa7\x94" // U+F19D4 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_PLUS "\xf3\xb1\xa7\x95" // U+F19D5 +#define ICON_MDI_PACKAGE_VARIANT_CLOSED_REMOVE "\xf3\xb1\xa7\x96" // U+F19D6 +#define ICON_MDI_PACKAGE_VARIANT_MINUS "\xf3\xb1\xa7\x97" // U+F19D7 +#define ICON_MDI_PACKAGE_VARIANT_PLUS "\xf3\xb1\xa7\x98" // U+F19D8 +#define ICON_MDI_PACKAGE_VARIANT_REMOVE "\xf3\xb1\xa7\x99" // U+F19D9 +#define ICON_MDI_PAGE_FIRST "\xf3\xb0\x98\x80" // U+F0600 +#define ICON_MDI_PAGE_LAST "\xf3\xb0\x98\x81" // U+F0601 +#define ICON_MDI_PAGE_LAYOUT_BODY "\xf3\xb0\x9b\xba" // U+F06FA +#define ICON_MDI_PAGE_LAYOUT_FOOTER "\xf3\xb0\x9b\xbb" // U+F06FB +#define ICON_MDI_PAGE_LAYOUT_HEADER "\xf3\xb0\x9b\xbc" // U+F06FC +#define ICON_MDI_PAGE_LAYOUT_HEADER_FOOTER "\xf3\xb0\xbd\xbf" // U+F0F7F +#define ICON_MDI_PAGE_LAYOUT_SIDEBAR_LEFT "\xf3\xb0\x9b\xbd" // U+F06FD +#define ICON_MDI_PAGE_LAYOUT_SIDEBAR_RIGHT "\xf3\xb0\x9b\xbe" // U+F06FE +#define ICON_MDI_PAGE_NEXT "\xf3\xb0\xae\xb0" // U+F0BB0 +#define ICON_MDI_PAGE_NEXT_OUTLINE "\xf3\xb0\xae\xb1" // U+F0BB1 +#define ICON_MDI_PAGE_PREVIOUS "\xf3\xb0\xae\xb2" // U+F0BB2 +#define ICON_MDI_PAGE_PREVIOUS_OUTLINE "\xf3\xb0\xae\xb3" // U+F0BB3 +#define ICON_MDI_PAIL "\xf3\xb1\x90\x97" // U+F1417 +#define ICON_MDI_PAIL_MINUS "\xf3\xb1\x90\xb7" // U+F1437 +#define ICON_MDI_PAIL_MINUS_OUTLINE "\xf3\xb1\x90\xbc" // U+F143C +#define ICON_MDI_PAIL_OFF "\xf3\xb1\x90\xb9" // U+F1439 +#define ICON_MDI_PAIL_OFF_OUTLINE "\xf3\xb1\x90\xbe" // U+F143E +#define ICON_MDI_PAIL_OUTLINE "\xf3\xb1\x90\xba" // U+F143A +#define ICON_MDI_PAIL_PLUS "\xf3\xb1\x90\xb6" // U+F1436 +#define ICON_MDI_PAIL_PLUS_OUTLINE "\xf3\xb1\x90\xbb" // U+F143B +#define ICON_MDI_PAIL_REMOVE "\xf3\xb1\x90\xb8" // U+F1438 +#define ICON_MDI_PAIL_REMOVE_OUTLINE "\xf3\xb1\x90\xbd" // U+F143D +#define ICON_MDI_PALETTE "\xf3\xb0\x8f\x98" // U+F03D8 +#define ICON_MDI_PALETTE_ADVANCED "\xf3\xb0\x8f\x99" // U+F03D9 +#define ICON_MDI_PALETTE_OUTLINE "\xf3\xb0\xb8\x8c" // U+F0E0C +#define ICON_MDI_PALETTE_SWATCH "\xf3\xb0\xa2\xb5" // U+F08B5 +#define ICON_MDI_PALETTE_SWATCH_OUTLINE "\xf3\xb1\x8d\x9c" // U+F135C +#define ICON_MDI_PALETTE_SWATCH_VARIANT "\xf3\xb1\xa5\x9a" // U+F195A +#define ICON_MDI_PALM_TREE "\xf3\xb1\x81\x95" // U+F1055 +#define ICON_MDI_PAN "\xf3\xb0\xae\xb4" // U+F0BB4 +#define ICON_MDI_PAN_BOTTOM_LEFT "\xf3\xb0\xae\xb5" // U+F0BB5 +#define ICON_MDI_PAN_BOTTOM_RIGHT "\xf3\xb0\xae\xb6" // U+F0BB6 +#define ICON_MDI_PAN_DOWN "\xf3\xb0\xae\xb7" // U+F0BB7 +#define ICON_MDI_PAN_HORIZONTAL "\xf3\xb0\xae\xb8" // U+F0BB8 +#define ICON_MDI_PAN_LEFT "\xf3\xb0\xae\xb9" // U+F0BB9 +#define ICON_MDI_PAN_RIGHT "\xf3\xb0\xae\xba" // U+F0BBA +#define ICON_MDI_PAN_TOP_LEFT "\xf3\xb0\xae\xbb" // U+F0BBB +#define ICON_MDI_PAN_TOP_RIGHT "\xf3\xb0\xae\xbc" // U+F0BBC +#define ICON_MDI_PAN_UP "\xf3\xb0\xae\xbd" // U+F0BBD +#define ICON_MDI_PAN_VERTICAL "\xf3\xb0\xae\xbe" // U+F0BBE +#define ICON_MDI_PANDA "\xf3\xb0\x8f\x9a" // U+F03DA +#define ICON_MDI_PANDORA "\xf3\xb0\x8f\x9b" // U+F03DB +#define ICON_MDI_PANORAMA "\xf3\xb0\x8f\x9c" // U+F03DC +#define ICON_MDI_PANORAMA_FISHEYE "\xf3\xb0\x8f\x9d" // U+F03DD +#define ICON_MDI_PANORAMA_HORIZONTAL "\xf3\xb1\xa4\xa8" // U+F1928 +#define ICON_MDI_PANORAMA_HORIZONTAL_OUTLINE "\xf3\xb0\x8f\x9e" // U+F03DE +#define ICON_MDI_PANORAMA_OUTLINE "\xf3\xb1\xa6\x8c" // U+F198C +#define ICON_MDI_PANORAMA_SPHERE "\xf3\xb1\xa6\x8d" // U+F198D +#define ICON_MDI_PANORAMA_SPHERE_OUTLINE "\xf3\xb1\xa6\x8e" // U+F198E +#define ICON_MDI_PANORAMA_VARIANT "\xf3\xb1\xa6\x8f" // U+F198F +#define ICON_MDI_PANORAMA_VARIANT_OUTLINE "\xf3\xb1\xa6\x90" // U+F1990 +#define ICON_MDI_PANORAMA_VERTICAL "\xf3\xb1\xa4\xa9" // U+F1929 +#define ICON_MDI_PANORAMA_VERTICAL_OUTLINE "\xf3\xb0\x8f\x9f" // U+F03DF +#define ICON_MDI_PANORAMA_WIDE_ANGLE "\xf3\xb1\xa5\x9f" // U+F195F +#define ICON_MDI_PANORAMA_WIDE_ANGLE_OUTLINE "\xf3\xb0\x8f\xa0" // U+F03E0 +#define ICON_MDI_PAPER_CUT_VERTICAL "\xf3\xb0\x8f\xa1" // U+F03E1 +#define ICON_MDI_PAPER_ROLL "\xf3\xb1\x85\x97" // U+F1157 +#define ICON_MDI_PAPER_ROLL_OUTLINE "\xf3\xb1\x85\x98" // U+F1158 +#define ICON_MDI_PAPERCLIP "\xf3\xb0\x8f\xa2" // U+F03E2 +#define ICON_MDI_PAPERCLIP_CHECK "\xf3\xb1\xab\x86" // U+F1AC6 +#define ICON_MDI_PAPERCLIP_LOCK "\xf3\xb1\xa7\x9a" // U+F19DA +#define ICON_MDI_PAPERCLIP_MINUS "\xf3\xb1\xab\x87" // U+F1AC7 +#define ICON_MDI_PAPERCLIP_OFF "\xf3\xb1\xab\x88" // U+F1AC8 +#define ICON_MDI_PAPERCLIP_PLUS "\xf3\xb1\xab\x89" // U+F1AC9 +#define ICON_MDI_PAPERCLIP_REMOVE "\xf3\xb1\xab\x8a" // U+F1ACA +#define ICON_MDI_PARACHUTE "\xf3\xb0\xb2\xb4" // U+F0CB4 +#define ICON_MDI_PARACHUTE_OUTLINE "\xf3\xb0\xb2\xb5" // U+F0CB5 +#define ICON_MDI_PARAGLIDING "\xf3\xb1\x9d\x85" // U+F1745 +#define ICON_MDI_PARKING "\xf3\xb0\x8f\xa3" // U+F03E3 +#define ICON_MDI_PARTY_POPPER "\xf3\xb1\x81\x96" // U+F1056 +#define ICON_MDI_PASSPORT "\xf3\xb0\x9f\xa3" // U+F07E3 +#define ICON_MDI_PASSPORT_ALERT "\xf3\xb1\xb2\xb8" // U+F1CB8 +#define ICON_MDI_PASSPORT_BIOMETRIC "\xf3\xb0\xb7\xa1" // U+F0DE1 +#define ICON_MDI_PASSPORT_CANCEL "\xf3\xb1\xb2\xb9" // U+F1CB9 +#define ICON_MDI_PASSPORT_CHECK "\xf3\xb1\xb2\xba" // U+F1CBA +#define ICON_MDI_PASSPORT_MINUS "\xf3\xb1\xb2\xbb" // U+F1CBB +#define ICON_MDI_PASSPORT_PLUS "\xf3\xb1\xb2\xbc" // U+F1CBC +#define ICON_MDI_PASSPORT_REMOVE "\xf3\xb1\xb2\xbd" // U+F1CBD +#define ICON_MDI_PASTA "\xf3\xb1\x85\xa0" // U+F1160 +#define ICON_MDI_PATIO_HEATER "\xf3\xb0\xbe\x80" // U+F0F80 +#define ICON_MDI_PATREON "\xf3\xb0\xa2\x82" // U+F0882 +#define ICON_MDI_PAUSE "\xf3\xb0\x8f\xa4" // U+F03E4 +#define ICON_MDI_PAUSE_BOX "\xf3\xb0\x82\xbc" // U+F00BC +#define ICON_MDI_PAUSE_BOX_OUTLINE "\xf3\xb1\xad\xba" // U+F1B7A +#define ICON_MDI_PAUSE_CIRCLE "\xf3\xb0\x8f\xa5" // U+F03E5 +#define ICON_MDI_PAUSE_CIRCLE_OUTLINE "\xf3\xb0\x8f\xa6" // U+F03E6 +#define ICON_MDI_PAUSE_OCTAGON "\xf3\xb0\x8f\xa7" // U+F03E7 +#define ICON_MDI_PAUSE_OCTAGON_OUTLINE "\xf3\xb0\x8f\xa8" // U+F03E8 +#define ICON_MDI_PAW "\xf3\xb0\x8f\xa9" // U+F03E9 +#define ICON_MDI_PAW_OFF "\xf3\xb0\x99\x97" // U+F0657 +#define ICON_MDI_PAW_OFF_OUTLINE "\xf3\xb1\x99\xb6" // U+F1676 +#define ICON_MDI_PAW_OUTLINE "\xf3\xb1\x99\xb5" // U+F1675 +#define ICON_MDI_PEACE "\xf3\xb0\xa2\x84" // U+F0884 +#define ICON_MDI_PEANUT "\xf3\xb0\xbf\xbc" // U+F0FFC +#define ICON_MDI_PEANUT_OFF "\xf3\xb0\xbf\xbd" // U+F0FFD +#define ICON_MDI_PEANUT_OFF_OUTLINE "\xf3\xb0\xbf\xbf" // U+F0FFF +#define ICON_MDI_PEANUT_OUTLINE "\xf3\xb0\xbf\xbe" // U+F0FFE +#define ICON_MDI_PEN "\xf3\xb0\x8f\xaa" // U+F03EA +#define ICON_MDI_PEN_LOCK "\xf3\xb0\xb7\xa2" // U+F0DE2 +#define ICON_MDI_PEN_MINUS "\xf3\xb0\xb7\xa3" // U+F0DE3 +#define ICON_MDI_PEN_OFF "\xf3\xb0\xb7\xa4" // U+F0DE4 +#define ICON_MDI_PEN_PLUS "\xf3\xb0\xb7\xa5" // U+F0DE5 +#define ICON_MDI_PEN_REMOVE "\xf3\xb0\xb7\xa6" // U+F0DE6 +#define ICON_MDI_PENCIL "\xf3\xb0\x8f\xab" // U+F03EB +#define ICON_MDI_PENCIL_BOX "\xf3\xb0\x8f\xac" // U+F03EC +#define ICON_MDI_PENCIL_BOX_MULTIPLE "\xf3\xb1\x85\x84" // U+F1144 +#define ICON_MDI_PENCIL_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x85" // U+F1145 +#define ICON_MDI_PENCIL_BOX_OUTLINE "\xf3\xb0\x8f\xad" // U+F03ED +#define ICON_MDI_PENCIL_CIRCLE "\xf3\xb0\x9b\xbf" // U+F06FF +#define ICON_MDI_PENCIL_CIRCLE_OUTLINE "\xf3\xb0\x9d\xb6" // U+F0776 +#define ICON_MDI_PENCIL_LOCK "\xf3\xb0\x8f\xae" // U+F03EE +#define ICON_MDI_PENCIL_LOCK_OUTLINE "\xf3\xb0\xb7\xa7" // U+F0DE7 +#define ICON_MDI_PENCIL_MINUS "\xf3\xb0\xb7\xa8" // U+F0DE8 +#define ICON_MDI_PENCIL_MINUS_OUTLINE "\xf3\xb0\xb7\xa9" // U+F0DE9 +#define ICON_MDI_PENCIL_OFF "\xf3\xb0\x8f\xaf" // U+F03EF +#define ICON_MDI_PENCIL_OFF_OUTLINE "\xf3\xb0\xb7\xaa" // U+F0DEA +#define ICON_MDI_PENCIL_OUTLINE "\xf3\xb0\xb2\xb6" // U+F0CB6 +#define ICON_MDI_PENCIL_PLUS "\xf3\xb0\xb7\xab" // U+F0DEB +#define ICON_MDI_PENCIL_PLUS_OUTLINE "\xf3\xb0\xb7\xac" // U+F0DEC +#define ICON_MDI_PENCIL_REMOVE "\xf3\xb0\xb7\xad" // U+F0DED +#define ICON_MDI_PENCIL_REMOVE_OUTLINE "\xf3\xb0\xb7\xae" // U+F0DEE +#define ICON_MDI_PENCIL_RULER "\xf3\xb1\x8d\x93" // U+F1353 +#define ICON_MDI_PENCIL_RULER_OUTLINE "\xf3\xb1\xb0\x91" // U+F1C11 +#define ICON_MDI_PENGUIN "\xf3\xb0\xbb\x80" // U+F0EC0 +#define ICON_MDI_PENTAGON "\xf3\xb0\x9c\x81" // U+F0701 +#define ICON_MDI_PENTAGON_OUTLINE "\xf3\xb0\x9c\x80" // U+F0700 +#define ICON_MDI_PENTAGRAM "\xf3\xb1\x99\xa7" // U+F1667 +#define ICON_MDI_PERCENT "\xf3\xb0\x8f\xb0" // U+F03F0 +#define ICON_MDI_PERCENT_BOX "\xf3\xb1\xa8\x82" // U+F1A02 +#define ICON_MDI_PERCENT_BOX_OUTLINE "\xf3\xb1\xa8\x83" // U+F1A03 +#define ICON_MDI_PERCENT_CIRCLE "\xf3\xb1\xa8\x84" // U+F1A04 +#define ICON_MDI_PERCENT_CIRCLE_OUTLINE "\xf3\xb1\xa8\x85" // U+F1A05 +#define ICON_MDI_PERCENT_OUTLINE "\xf3\xb1\x89\xb8" // U+F1278 +#define ICON_MDI_PERIODIC_TABLE "\xf3\xb0\xa2\xb6" // U+F08B6 +#define ICON_MDI_PERSPECTIVE_LESS "\xf3\xb0\xb4\xa3" // U+F0D23 +#define ICON_MDI_PERSPECTIVE_MORE "\xf3\xb0\xb4\xa4" // U+F0D24 +#define ICON_MDI_PH "\xf3\xb1\x9f\x85" // U+F17C5 +#define ICON_MDI_PHONE "\xf3\xb0\x8f\xb2" // U+F03F2 +#define ICON_MDI_PHONE_ALERT "\xf3\xb0\xbc\x9a" // U+F0F1A +#define ICON_MDI_PHONE_ALERT_OUTLINE "\xf3\xb1\x86\x8e" // U+F118E +#define ICON_MDI_PHONE_BLUETOOTH "\xf3\xb0\x8f\xb3" // U+F03F3 +#define ICON_MDI_PHONE_BLUETOOTH_OUTLINE "\xf3\xb1\x86\x8f" // U+F118F +#define ICON_MDI_PHONE_CANCEL "\xf3\xb1\x82\xbc" // U+F10BC +#define ICON_MDI_PHONE_CANCEL_OUTLINE "\xf3\xb1\x86\x90" // U+F1190 +#define ICON_MDI_PHONE_CHECK "\xf3\xb1\x86\xa9" // U+F11A9 +#define ICON_MDI_PHONE_CHECK_OUTLINE "\xf3\xb1\x86\xaa" // U+F11AA +#define ICON_MDI_PHONE_CLASSIC "\xf3\xb0\x98\x82" // U+F0602 +#define ICON_MDI_PHONE_CLASSIC_OFF "\xf3\xb1\x89\xb9" // U+F1279 +#define ICON_MDI_PHONE_CLOCK "\xf3\xb1\xa7\x9b" // U+F19DB +#define ICON_MDI_PHONE_DIAL "\xf3\xb1\x95\x99" // U+F1559 +#define ICON_MDI_PHONE_DIAL_OUTLINE "\xf3\xb1\x95\x9a" // U+F155A +#define ICON_MDI_PHONE_FORWARD "\xf3\xb0\x8f\xb4" // U+F03F4 +#define ICON_MDI_PHONE_FORWARD_OUTLINE "\xf3\xb1\x86\x91" // U+F1191 +#define ICON_MDI_PHONE_HANGUP "\xf3\xb0\x8f\xb5" // U+F03F5 +#define ICON_MDI_PHONE_HANGUP_OUTLINE "\xf3\xb1\x86\x92" // U+F1192 +#define ICON_MDI_PHONE_IN_TALK "\xf3\xb0\x8f\xb6" // U+F03F6 +#define ICON_MDI_PHONE_IN_TALK_OUTLINE "\xf3\xb1\x86\x82" // U+F1182 +#define ICON_MDI_PHONE_INCOMING "\xf3\xb0\x8f\xb7" // U+F03F7 +#define ICON_MDI_PHONE_INCOMING_OUTGOING "\xf3\xb1\xac\xbf" // U+F1B3F +#define ICON_MDI_PHONE_INCOMING_OUTGOING_OUTLINE "\xf3\xb1\xad\x80" // U+F1B40 +#define ICON_MDI_PHONE_INCOMING_OUTLINE "\xf3\xb1\x86\x93" // U+F1193 +#define ICON_MDI_PHONE_LOCK "\xf3\xb0\x8f\xb8" // U+F03F8 +#define ICON_MDI_PHONE_LOCK_OUTLINE "\xf3\xb1\x86\x94" // U+F1194 +#define ICON_MDI_PHONE_LOG "\xf3\xb0\x8f\xb9" // U+F03F9 +#define ICON_MDI_PHONE_LOG_OUTLINE "\xf3\xb1\x86\x95" // U+F1195 +#define ICON_MDI_PHONE_MESSAGE "\xf3\xb1\x86\x96" // U+F1196 +#define ICON_MDI_PHONE_MESSAGE_OUTLINE "\xf3\xb1\x86\x97" // U+F1197 +#define ICON_MDI_PHONE_MINUS "\xf3\xb0\x99\x98" // U+F0658 +#define ICON_MDI_PHONE_MINUS_OUTLINE "\xf3\xb1\x86\x98" // U+F1198 +#define ICON_MDI_PHONE_MISSED "\xf3\xb0\x8f\xba" // U+F03FA +#define ICON_MDI_PHONE_MISSED_OUTLINE "\xf3\xb1\x86\xa5" // U+F11A5 +#define ICON_MDI_PHONE_OFF "\xf3\xb0\xb7\xaf" // U+F0DEF +#define ICON_MDI_PHONE_OFF_OUTLINE "\xf3\xb1\x86\xa6" // U+F11A6 +#define ICON_MDI_PHONE_OUTGOING "\xf3\xb0\x8f\xbb" // U+F03FB +#define ICON_MDI_PHONE_OUTGOING_OUTLINE "\xf3\xb1\x86\x99" // U+F1199 +#define ICON_MDI_PHONE_OUTLINE "\xf3\xb0\xb7\xb0" // U+F0DF0 +#define ICON_MDI_PHONE_PAUSED "\xf3\xb0\x8f\xbc" // U+F03FC +#define ICON_MDI_PHONE_PAUSED_OUTLINE "\xf3\xb1\x86\x9a" // U+F119A +#define ICON_MDI_PHONE_PLUS "\xf3\xb0\x99\x99" // U+F0659 +#define ICON_MDI_PHONE_PLUS_OUTLINE "\xf3\xb1\x86\x9b" // U+F119B +#define ICON_MDI_PHONE_REFRESH "\xf3\xb1\xa6\x93" // U+F1993 +#define ICON_MDI_PHONE_REFRESH_OUTLINE "\xf3\xb1\xa6\x94" // U+F1994 +#define ICON_MDI_PHONE_REMOVE "\xf3\xb1\x94\xaf" // U+F152F +#define ICON_MDI_PHONE_REMOVE_OUTLINE "\xf3\xb1\x94\xb0" // U+F1530 +#define ICON_MDI_PHONE_RETURN "\xf3\xb0\xa0\xaf" // U+F082F +#define ICON_MDI_PHONE_RETURN_OUTLINE "\xf3\xb1\x86\x9c" // U+F119C +#define ICON_MDI_PHONE_RING "\xf3\xb1\x86\xab" // U+F11AB +#define ICON_MDI_PHONE_RING_OUTLINE "\xf3\xb1\x86\xac" // U+F11AC +#define ICON_MDI_PHONE_ROTATE_LANDSCAPE "\xf3\xb0\xa2\x85" // U+F0885 +#define ICON_MDI_PHONE_ROTATE_PORTRAIT "\xf3\xb0\xa2\x86" // U+F0886 +#define ICON_MDI_PHONE_SETTINGS "\xf3\xb0\x8f\xbd" // U+F03FD +#define ICON_MDI_PHONE_SETTINGS_OUTLINE "\xf3\xb1\x86\x9d" // U+F119D +#define ICON_MDI_PHONE_SYNC "\xf3\xb1\xa6\x95" // U+F1995 +#define ICON_MDI_PHONE_SYNC_OUTLINE "\xf3\xb1\xa6\x96" // U+F1996 +#define ICON_MDI_PHONE_VOIP "\xf3\xb0\x8f\xbe" // U+F03FE +#define ICON_MDI_PI "\xf3\xb0\x8f\xbf" // U+F03FF +#define ICON_MDI_PI_BOX "\xf3\xb0\x90\x80" // U+F0400 +#define ICON_MDI_PI_HOLE "\xf3\xb0\xb7\xb1" // U+F0DF1 +#define ICON_MDI_PIANO "\xf3\xb0\x99\xbd" // U+F067D +#define ICON_MDI_PIANO_OFF "\xf3\xb0\x9a\x98" // U+F0698 +#define ICON_MDI_PICKAXE "\xf3\xb0\xa2\xb7" // U+F08B7 +#define ICON_MDI_PICTURE_IN_PICTURE_BOTTOM_RIGHT "\xf3\xb0\xb9\x97" // U+F0E57 +#define ICON_MDI_PICTURE_IN_PICTURE_BOTTOM_RIGHT_OUTLINE "\xf3\xb0\xb9\x98" // U+F0E58 +#define ICON_MDI_PICTURE_IN_PICTURE_TOP_RIGHT "\xf3\xb0\xb9\x99" // U+F0E59 +#define ICON_MDI_PICTURE_IN_PICTURE_TOP_RIGHT_OUTLINE "\xf3\xb0\xb9\x9a" // U+F0E5A +#define ICON_MDI_PIER "\xf3\xb0\xa2\x87" // U+F0887 +#define ICON_MDI_PIER_CRANE "\xf3\xb0\xa2\x88" // U+F0888 +#define ICON_MDI_PIG "\xf3\xb0\x90\x81" // U+F0401 +#define ICON_MDI_PIG_VARIANT "\xf3\xb1\x80\x86" // U+F1006 +#define ICON_MDI_PIG_VARIANT_OUTLINE "\xf3\xb1\x99\xb8" // U+F1678 +#define ICON_MDI_PIGGY_BANK "\xf3\xb1\x80\x87" // U+F1007 +#define ICON_MDI_PIGGY_BANK_OUTLINE "\xf3\xb1\x99\xb9" // U+F1679 +#define ICON_MDI_PILL "\xf3\xb0\x90\x82" // U+F0402 +#define ICON_MDI_PILL_MULTIPLE "\xf3\xb1\xad\x8c" // U+F1B4C +#define ICON_MDI_PILL_OFF "\xf3\xb1\xa9\x9c" // U+F1A5C +#define ICON_MDI_PILLAR "\xf3\xb0\x9c\x82" // U+F0702 +#define ICON_MDI_PIN "\xf3\xb0\x90\x83" // U+F0403 +#define ICON_MDI_PIN_OFF "\xf3\xb0\x90\x84" // U+F0404 +#define ICON_MDI_PIN_OFF_OUTLINE "\xf3\xb0\xa4\xb0" // U+F0930 +#define ICON_MDI_PIN_OUTLINE "\xf3\xb0\xa4\xb1" // U+F0931 +#define ICON_MDI_PINE_TREE "\xf3\xb0\x90\x85" // U+F0405 +#define ICON_MDI_PINE_TREE_BOX "\xf3\xb0\x90\x86" // U+F0406 +#define ICON_MDI_PINE_TREE_FIRE "\xf3\xb1\x90\x9a" // U+F141A +#define ICON_MDI_PINE_TREE_VARIANT "\xf3\xb1\xb1\xb3" // U+F1C73 +#define ICON_MDI_PINE_TREE_VARIANT_OUTLINE "\xf3\xb1\xb1\xb4" // U+F1C74 +#define ICON_MDI_PINTEREST "\xf3\xb0\x90\x87" // U+F0407 +#define ICON_MDI_PINWHEEL "\xf3\xb0\xab\x95" // U+F0AD5 +#define ICON_MDI_PINWHEEL_OUTLINE "\xf3\xb0\xab\x96" // U+F0AD6 +#define ICON_MDI_PIPE "\xf3\xb0\x9f\xa5" // U+F07E5 +#define ICON_MDI_PIPE_DISCONNECTED "\xf3\xb0\x9f\xa6" // U+F07E6 +#define ICON_MDI_PIPE_LEAK "\xf3\xb0\xa2\x89" // U+F0889 +#define ICON_MDI_PIPE_VALVE "\xf3\xb1\xa1\x8d" // U+F184D +#define ICON_MDI_PIPE_WRENCH "\xf3\xb1\x8d\x94" // U+F1354 +#define ICON_MDI_PIRATE "\xf3\xb0\xa8\x88" // U+F0A08 +#define ICON_MDI_PISTOL "\xf3\xb0\x9c\x83" // U+F0703 +#define ICON_MDI_PISTON "\xf3\xb0\xa2\x8a" // U+F088A +#define ICON_MDI_PITCHFORK "\xf3\xb1\x95\x93" // U+F1553 +#define ICON_MDI_PIZZA "\xf3\xb0\x90\x89" // U+F0409 +#define ICON_MDI_PLANE_CAR "\xf3\xb1\xab\xbf" // U+F1AFF +#define ICON_MDI_PLANE_TRAIN "\xf3\xb1\xac\x80" // U+F1B00 +#define ICON_MDI_PLAY "\xf3\xb0\x90\x8a" // U+F040A +#define ICON_MDI_PLAY_BOX "\xf3\xb1\x89\xba" // U+F127A +#define ICON_MDI_PLAY_BOX_EDIT_OUTLINE "\xf3\xb1\xb0\xba" // U+F1C3A +#define ICON_MDI_PLAY_BOX_LOCK "\xf3\xb1\xa8\x96" // U+F1A16 +#define ICON_MDI_PLAY_BOX_LOCK_OPEN "\xf3\xb1\xa8\x97" // U+F1A17 +#define ICON_MDI_PLAY_BOX_LOCK_OPEN_OUTLINE "\xf3\xb1\xa8\x98" // U+F1A18 +#define ICON_MDI_PLAY_BOX_LOCK_OUTLINE "\xf3\xb1\xa8\x99" // U+F1A19 +#define ICON_MDI_PLAY_BOX_MULTIPLE "\xf3\xb0\xb4\x99" // U+F0D19 +#define ICON_MDI_PLAY_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x8f\xa6" // U+F13E6 +#define ICON_MDI_PLAY_BOX_OUTLINE "\xf3\xb0\x90\x8b" // U+F040B +#define ICON_MDI_PLAY_CIRCLE "\xf3\xb0\x90\x8c" // U+F040C +#define ICON_MDI_PLAY_CIRCLE_OUTLINE "\xf3\xb0\x90\x8d" // U+F040D +#define ICON_MDI_PLAY_NETWORK "\xf3\xb0\xa2\x8b" // U+F088B +#define ICON_MDI_PLAY_NETWORK_OUTLINE "\xf3\xb0\xb2\xb7" // U+F0CB7 +#define ICON_MDI_PLAY_OUTLINE "\xf3\xb0\xbc\x9b" // U+F0F1B +#define ICON_MDI_PLAY_PAUSE "\xf3\xb0\x90\x8e" // U+F040E +#define ICON_MDI_PLAY_PROTECTED_CONTENT "\xf3\xb0\x90\x8f" // U+F040F +#define ICON_MDI_PLAY_SPEED "\xf3\xb0\xa3\xbf" // U+F08FF +#define ICON_MDI_PLAYLIST_CHECK "\xf3\xb0\x97\x87" // U+F05C7 +#define ICON_MDI_PLAYLIST_EDIT "\xf3\xb0\xa4\x80" // U+F0900 +#define ICON_MDI_PLAYLIST_MINUS "\xf3\xb0\x90\x90" // U+F0410 +#define ICON_MDI_PLAYLIST_MUSIC "\xf3\xb0\xb2\xb8" // U+F0CB8 +#define ICON_MDI_PLAYLIST_MUSIC_OUTLINE "\xf3\xb0\xb2\xb9" // U+F0CB9 +#define ICON_MDI_PLAYLIST_PLAY "\xf3\xb0\x90\x91" // U+F0411 +#define ICON_MDI_PLAYLIST_PLUS "\xf3\xb0\x90\x92" // U+F0412 +#define ICON_MDI_PLAYLIST_REMOVE "\xf3\xb0\x90\x93" // U+F0413 +#define ICON_MDI_PLAYLIST_STAR "\xf3\xb0\xb7\xb2" // U+F0DF2 +#define ICON_MDI_PLEX "\xf3\xb0\x9a\xba" // U+F06BA +#define ICON_MDI_PLIERS "\xf3\xb1\xa6\xa4" // U+F19A4 +#define ICON_MDI_PLUS "\xf3\xb0\x90\x95" // U+F0415 +#define ICON_MDI_PLUS_BOX "\xf3\xb0\x90\x96" // U+F0416 +#define ICON_MDI_PLUS_BOX_MULTIPLE "\xf3\xb0\x8c\xb4" // U+F0334 +#define ICON_MDI_PLUS_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x85\x83" // U+F1143 +#define ICON_MDI_PLUS_BOX_OUTLINE "\xf3\xb0\x9c\x84" // U+F0704 +#define ICON_MDI_PLUS_CIRCLE "\xf3\xb0\x90\x97" // U+F0417 +#define ICON_MDI_PLUS_CIRCLE_MULTIPLE "\xf3\xb0\x8d\x8c" // U+F034C +#define ICON_MDI_PLUS_CIRCLE_MULTIPLE_OUTLINE "\xf3\xb0\x90\x98" // U+F0418 +#define ICON_MDI_PLUS_CIRCLE_OUTLINE "\xf3\xb0\x90\x99" // U+F0419 +#define ICON_MDI_PLUS_LOCK "\xf3\xb1\xa9\x9d" // U+F1A5D +#define ICON_MDI_PLUS_LOCK_OPEN "\xf3\xb1\xa9\x9e" // U+F1A5E +#define ICON_MDI_PLUS_MINUS "\xf3\xb0\xa6\x92" // U+F0992 +#define ICON_MDI_PLUS_MINUS_BOX "\xf3\xb0\xa6\x93" // U+F0993 +#define ICON_MDI_PLUS_MINUS_VARIANT "\xf3\xb1\x93\x89" // U+F14C9 +#define ICON_MDI_PLUS_NETWORK "\xf3\xb0\x90\x9a" // U+F041A +#define ICON_MDI_PLUS_NETWORK_OUTLINE "\xf3\xb0\xb2\xba" // U+F0CBA +#define ICON_MDI_PLUS_OUTLINE "\xf3\xb0\x9c\x85" // U+F0705 +#define ICON_MDI_PLUS_THICK "\xf3\xb1\x87\xac" // U+F11EC +#define ICON_MDI_POCKET "\xf3\xb1\xb2\xbe" // U+F1CBE +#define ICON_MDI_PODCAST "\xf3\xb0\xa6\x94" // U+F0994 +#define ICON_MDI_PODIUM "\xf3\xb0\xb4\xa5" // U+F0D25 +#define ICON_MDI_PODIUM_BRONZE "\xf3\xb0\xb4\xa6" // U+F0D26 +#define ICON_MDI_PODIUM_GOLD "\xf3\xb0\xb4\xa7" // U+F0D27 +#define ICON_MDI_PODIUM_SILVER "\xf3\xb0\xb4\xa8" // U+F0D28 +#define ICON_MDI_POINT_OF_SALE "\xf3\xb0\xb6\x92" // U+F0D92 +#define ICON_MDI_POKEBALL "\xf3\xb0\x90\x9d" // U+F041D +#define ICON_MDI_POKEMON_GO "\xf3\xb0\xa8\x89" // U+F0A09 +#define ICON_MDI_POKER_CHIP "\xf3\xb0\xa0\xb0" // U+F0830 +#define ICON_MDI_POLAROID "\xf3\xb0\x90\x9e" // U+F041E +#define ICON_MDI_POLICE_BADGE "\xf3\xb1\x85\xa7" // U+F1167 +#define ICON_MDI_POLICE_BADGE_OUTLINE "\xf3\xb1\x85\xa8" // U+F1168 +#define ICON_MDI_POLICE_STATION "\xf3\xb1\xa0\xb9" // U+F1839 +#define ICON_MDI_POLL "\xf3\xb0\x90\x9f" // U+F041F +#define ICON_MDI_POLO "\xf3\xb1\x93\x83" // U+F14C3 +#define ICON_MDI_POLYMER "\xf3\xb0\x90\xa1" // U+F0421 +#define ICON_MDI_POOL "\xf3\xb0\x98\x86" // U+F0606 +#define ICON_MDI_POOL_THERMOMETER "\xf3\xb1\xa9\x9f" // U+F1A5F +#define ICON_MDI_POPCORN "\xf3\xb0\x90\xa2" // U+F0422 +#define ICON_MDI_POST "\xf3\xb1\x80\x88" // U+F1008 +#define ICON_MDI_POST_LAMP "\xf3\xb1\xa9\xa0" // U+F1A60 +#define ICON_MDI_POST_OUTLINE "\xf3\xb1\x80\x89" // U+F1009 +#define ICON_MDI_POSTAGE_STAMP "\xf3\xb0\xb2\xbb" // U+F0CBB +#define ICON_MDI_POT "\xf3\xb0\x8b\xa5" // U+F02E5 +#define ICON_MDI_POT_MIX "\xf3\xb0\x99\x9b" // U+F065B +#define ICON_MDI_POT_MIX_OUTLINE "\xf3\xb0\x99\xb7" // U+F0677 +#define ICON_MDI_POT_OUTLINE "\xf3\xb0\x8b\xbf" // U+F02FF +#define ICON_MDI_POT_STEAM "\xf3\xb0\x99\x9a" // U+F065A +#define ICON_MDI_POT_STEAM_OUTLINE "\xf3\xb0\x8c\xa6" // U+F0326 +#define ICON_MDI_POUND "\xf3\xb0\x90\xa3" // U+F0423 +#define ICON_MDI_POUND_BOX "\xf3\xb0\x90\xa4" // U+F0424 +#define ICON_MDI_POUND_BOX_OUTLINE "\xf3\xb1\x85\xbf" // U+F117F +#define ICON_MDI_POWER "\xf3\xb0\x90\xa5" // U+F0425 +#define ICON_MDI_POWER_CYCLE "\xf3\xb0\xa4\x81" // U+F0901 +#define ICON_MDI_POWER_OFF "\xf3\xb0\xa4\x82" // U+F0902 +#define ICON_MDI_POWER_ON "\xf3\xb0\xa4\x83" // U+F0903 +#define ICON_MDI_POWER_PLUG "\xf3\xb0\x9a\xa5" // U+F06A5 +#define ICON_MDI_POWER_PLUG_BATTERY "\xf3\xb1\xb0\xbb" // U+F1C3B +#define ICON_MDI_POWER_PLUG_BATTERY_OUTLINE "\xf3\xb1\xb0\xbc" // U+F1C3C +#define ICON_MDI_POWER_PLUG_OFF "\xf3\xb0\x9a\xa6" // U+F06A6 +#define ICON_MDI_POWER_PLUG_OFF_OUTLINE "\xf3\xb1\x90\xa4" // U+F1424 +#define ICON_MDI_POWER_PLUG_OUTLINE "\xf3\xb1\x90\xa5" // U+F1425 +#define ICON_MDI_POWER_SETTINGS "\xf3\xb0\x90\xa6" // U+F0426 +#define ICON_MDI_POWER_SLEEP "\xf3\xb0\xa4\x84" // U+F0904 +#define ICON_MDI_POWER_SOCKET "\xf3\xb0\x90\xa7" // U+F0427 +#define ICON_MDI_POWER_SOCKET_AU "\xf3\xb0\xa4\x85" // U+F0905 +#define ICON_MDI_POWER_SOCKET_CH "\xf3\xb0\xbe\xb3" // U+F0FB3 +#define ICON_MDI_POWER_SOCKET_DE "\xf3\xb1\x84\x87" // U+F1107 +#define ICON_MDI_POWER_SOCKET_EU "\xf3\xb0\x9f\xa7" // U+F07E7 +#define ICON_MDI_POWER_SOCKET_FR "\xf3\xb1\x84\x88" // U+F1108 +#define ICON_MDI_POWER_SOCKET_IT "\xf3\xb1\x93\xbf" // U+F14FF +#define ICON_MDI_POWER_SOCKET_JP "\xf3\xb1\x84\x89" // U+F1109 +#define ICON_MDI_POWER_SOCKET_UK "\xf3\xb0\x9f\xa8" // U+F07E8 +#define ICON_MDI_POWER_SOCKET_US "\xf3\xb0\x9f\xa9" // U+F07E9 +#define ICON_MDI_POWER_STANDBY "\xf3\xb0\xa4\x86" // U+F0906 +#define ICON_MDI_POWERSHELL "\xf3\xb0\xa8\x8a" // U+F0A0A +#define ICON_MDI_PRESCRIPTION "\xf3\xb0\x9c\x86" // U+F0706 +#define ICON_MDI_PRESENTATION "\xf3\xb0\x90\xa8" // U+F0428 +#define ICON_MDI_PRESENTATION_PLAY "\xf3\xb0\x90\xa9" // U+F0429 +#define ICON_MDI_PRETZEL "\xf3\xb1\x95\xa2" // U+F1562 +#define ICON_MDI_PRINTER "\xf3\xb0\x90\xaa" // U+F042A +#define ICON_MDI_PRINTER_3D "\xf3\xb0\x90\xab" // U+F042B +#define ICON_MDI_PRINTER_3D_NOZZLE "\xf3\xb0\xb9\x9b" // U+F0E5B +#define ICON_MDI_PRINTER_3D_NOZZLE_ALERT "\xf3\xb1\x87\x80" // U+F11C0 +#define ICON_MDI_PRINTER_3D_NOZZLE_ALERT_OUTLINE "\xf3\xb1\x87\x81" // U+F11C1 +#define ICON_MDI_PRINTER_3D_NOZZLE_HEAT "\xf3\xb1\xa2\xb8" // U+F18B8 +#define ICON_MDI_PRINTER_3D_NOZZLE_HEAT_OUTLINE "\xf3\xb1\xa2\xb9" // U+F18B9 +#define ICON_MDI_PRINTER_3D_NOZZLE_OFF "\xf3\xb1\xac\x99" // U+F1B19 +#define ICON_MDI_PRINTER_3D_NOZZLE_OFF_OUTLINE "\xf3\xb1\xac\x9a" // U+F1B1A +#define ICON_MDI_PRINTER_3D_NOZZLE_OUTLINE "\xf3\xb0\xb9\x9c" // U+F0E5C +#define ICON_MDI_PRINTER_3D_OFF "\xf3\xb1\xac\x8e" // U+F1B0E +#define ICON_MDI_PRINTER_ALERT "\xf3\xb0\x90\xac" // U+F042C +#define ICON_MDI_PRINTER_CHECK "\xf3\xb1\x85\x86" // U+F1146 +#define ICON_MDI_PRINTER_EYE "\xf3\xb1\x91\x98" // U+F1458 +#define ICON_MDI_PRINTER_OFF "\xf3\xb0\xb9\x9d" // U+F0E5D +#define ICON_MDI_PRINTER_OFF_OUTLINE "\xf3\xb1\x9e\x85" // U+F1785 +#define ICON_MDI_PRINTER_OUTLINE "\xf3\xb1\x9e\x86" // U+F1786 +#define ICON_MDI_PRINTER_POS "\xf3\xb1\x81\x97" // U+F1057 +#define ICON_MDI_PRINTER_POS_ALERT "\xf3\xb1\xae\xbc" // U+F1BBC +#define ICON_MDI_PRINTER_POS_ALERT_OUTLINE "\xf3\xb1\xae\xbd" // U+F1BBD +#define ICON_MDI_PRINTER_POS_CANCEL "\xf3\xb1\xae\xbe" // U+F1BBE +#define ICON_MDI_PRINTER_POS_CANCEL_OUTLINE "\xf3\xb1\xae\xbf" // U+F1BBF +#define ICON_MDI_PRINTER_POS_CHECK "\xf3\xb1\xaf\x80" // U+F1BC0 +#define ICON_MDI_PRINTER_POS_CHECK_OUTLINE "\xf3\xb1\xaf\x81" // U+F1BC1 +#define ICON_MDI_PRINTER_POS_COG "\xf3\xb1\xaf\x82" // U+F1BC2 +#define ICON_MDI_PRINTER_POS_COG_OUTLINE "\xf3\xb1\xaf\x83" // U+F1BC3 +#define ICON_MDI_PRINTER_POS_EDIT "\xf3\xb1\xaf\x84" // U+F1BC4 +#define ICON_MDI_PRINTER_POS_EDIT_OUTLINE "\xf3\xb1\xaf\x85" // U+F1BC5 +#define ICON_MDI_PRINTER_POS_MINUS "\xf3\xb1\xaf\x86" // U+F1BC6 +#define ICON_MDI_PRINTER_POS_MINUS_OUTLINE "\xf3\xb1\xaf\x87" // U+F1BC7 +#define ICON_MDI_PRINTER_POS_NETWORK "\xf3\xb1\xaf\x88" // U+F1BC8 +#define ICON_MDI_PRINTER_POS_NETWORK_OUTLINE "\xf3\xb1\xaf\x89" // U+F1BC9 +#define ICON_MDI_PRINTER_POS_OFF "\xf3\xb1\xaf\x8a" // U+F1BCA +#define ICON_MDI_PRINTER_POS_OFF_OUTLINE "\xf3\xb1\xaf\x8b" // U+F1BCB +#define ICON_MDI_PRINTER_POS_OUTLINE "\xf3\xb1\xaf\x8c" // U+F1BCC +#define ICON_MDI_PRINTER_POS_PAUSE "\xf3\xb1\xaf\x8d" // U+F1BCD +#define ICON_MDI_PRINTER_POS_PAUSE_OUTLINE "\xf3\xb1\xaf\x8e" // U+F1BCE +#define ICON_MDI_PRINTER_POS_PLAY "\xf3\xb1\xaf\x8f" // U+F1BCF +#define ICON_MDI_PRINTER_POS_PLAY_OUTLINE "\xf3\xb1\xaf\x90" // U+F1BD0 +#define ICON_MDI_PRINTER_POS_PLUS "\xf3\xb1\xaf\x91" // U+F1BD1 +#define ICON_MDI_PRINTER_POS_PLUS_OUTLINE "\xf3\xb1\xaf\x92" // U+F1BD2 +#define ICON_MDI_PRINTER_POS_REFRESH "\xf3\xb1\xaf\x93" // U+F1BD3 +#define ICON_MDI_PRINTER_POS_REFRESH_OUTLINE "\xf3\xb1\xaf\x94" // U+F1BD4 +#define ICON_MDI_PRINTER_POS_REMOVE "\xf3\xb1\xaf\x95" // U+F1BD5 +#define ICON_MDI_PRINTER_POS_REMOVE_OUTLINE "\xf3\xb1\xaf\x96" // U+F1BD6 +#define ICON_MDI_PRINTER_POS_STAR "\xf3\xb1\xaf\x97" // U+F1BD7 +#define ICON_MDI_PRINTER_POS_STAR_OUTLINE "\xf3\xb1\xaf\x98" // U+F1BD8 +#define ICON_MDI_PRINTER_POS_STOP "\xf3\xb1\xaf\x99" // U+F1BD9 +#define ICON_MDI_PRINTER_POS_STOP_OUTLINE "\xf3\xb1\xaf\x9a" // U+F1BDA +#define ICON_MDI_PRINTER_POS_SYNC "\xf3\xb1\xaf\x9b" // U+F1BDB +#define ICON_MDI_PRINTER_POS_SYNC_OUTLINE "\xf3\xb1\xaf\x9c" // U+F1BDC +#define ICON_MDI_PRINTER_POS_WRENCH "\xf3\xb1\xaf\x9d" // U+F1BDD +#define ICON_MDI_PRINTER_POS_WRENCH_OUTLINE "\xf3\xb1\xaf\x9e" // U+F1BDE +#define ICON_MDI_PRINTER_SEARCH "\xf3\xb1\x91\x97" // U+F1457 +#define ICON_MDI_PRINTER_SETTINGS "\xf3\xb0\x9c\x87" // U+F0707 +#define ICON_MDI_PRINTER_WIRELESS "\xf3\xb0\xa8\x8b" // U+F0A0B +#define ICON_MDI_PRIORITY_HIGH "\xf3\xb0\x98\x83" // U+F0603 +#define ICON_MDI_PRIORITY_LOW "\xf3\xb0\x98\x84" // U+F0604 +#define ICON_MDI_PROFESSIONAL_HEXAGON "\xf3\xb0\x90\xad" // U+F042D +#define ICON_MDI_PROGRESS_ALERT "\xf3\xb0\xb2\xbc" // U+F0CBC +#define ICON_MDI_PROGRESS_CHECK "\xf3\xb0\xa6\x95" // U+F0995 +#define ICON_MDI_PROGRESS_CLOCK "\xf3\xb0\xa6\x96" // U+F0996 +#define ICON_MDI_PROGRESS_CLOSE "\xf3\xb1\x84\x8a" // U+F110A +#define ICON_MDI_PROGRESS_DOWNLOAD "\xf3\xb0\xa6\x97" // U+F0997 +#define ICON_MDI_PROGRESS_HELPER "\xf3\xb1\xae\xa2" // U+F1BA2 +#define ICON_MDI_PROGRESS_PENCIL "\xf3\xb1\x9e\x87" // U+F1787 +#define ICON_MDI_PROGRESS_QUESTION "\xf3\xb1\x94\xa2" // U+F1522 +#define ICON_MDI_PROGRESS_STAR "\xf3\xb1\x9e\x88" // U+F1788 +#define ICON_MDI_PROGRESS_STAR_FOUR_POINTS "\xf3\xb1\xb0\xbd" // U+F1C3D +#define ICON_MDI_PROGRESS_UPLOAD "\xf3\xb0\xa6\x98" // U+F0998 +#define ICON_MDI_PROGRESS_WRENCH "\xf3\xb0\xb2\xbd" // U+F0CBD +#define ICON_MDI_PROJECTOR "\xf3\xb0\x90\xae" // U+F042E +#define ICON_MDI_PROJECTOR_OFF "\xf3\xb1\xa8\xa3" // U+F1A23 +#define ICON_MDI_PROJECTOR_SCREEN "\xf3\xb0\x90\xaf" // U+F042F +#define ICON_MDI_PROJECTOR_SCREEN_OFF "\xf3\xb1\xa0\x8d" // U+F180D +#define ICON_MDI_PROJECTOR_SCREEN_OFF_OUTLINE "\xf3\xb1\xa0\x8e" // U+F180E +#define ICON_MDI_PROJECTOR_SCREEN_OUTLINE "\xf3\xb1\x9c\xa4" // U+F1724 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT "\xf3\xb1\xa0\x8f" // U+F180F +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OFF "\xf3\xb1\xa0\x90" // U+F1810 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OFF_OUTLINE "\xf3\xb1\xa0\x91" // U+F1811 +#define ICON_MDI_PROJECTOR_SCREEN_VARIANT_OUTLINE "\xf3\xb1\xa0\x92" // U+F1812 +#define ICON_MDI_PROPANE_TANK "\xf3\xb1\x8d\x97" // U+F1357 +#define ICON_MDI_PROPANE_TANK_OUTLINE "\xf3\xb1\x8d\x98" // U+F1358 +#define ICON_MDI_PROTOCOL "\xf3\xb0\xbf\x98" // U+F0FD8 +#define ICON_MDI_PUBLISH "\xf3\xb0\x9a\xa7" // U+F06A7 +#define ICON_MDI_PUBLISH_OFF "\xf3\xb1\xa5\x85" // U+F1945 +#define ICON_MDI_PULSE "\xf3\xb0\x90\xb0" // U+F0430 +#define ICON_MDI_PUMP "\xf3\xb1\x90\x82" // U+F1402 +#define ICON_MDI_PUMP_OFF "\xf3\xb1\xac\xa2" // U+F1B22 +#define ICON_MDI_PUMPKIN "\xf3\xb0\xae\xbf" // U+F0BBF +#define ICON_MDI_PURSE "\xf3\xb0\xbc\x9c" // U+F0F1C +#define ICON_MDI_PURSE_OUTLINE "\xf3\xb0\xbc\x9d" // U+F0F1D +#define ICON_MDI_PUZZLE "\xf3\xb0\x90\xb1" // U+F0431 +#define ICON_MDI_PUZZLE_CHECK "\xf3\xb1\x90\xa6" // U+F1426 +#define ICON_MDI_PUZZLE_CHECK_OUTLINE "\xf3\xb1\x90\xa7" // U+F1427 +#define ICON_MDI_PUZZLE_EDIT "\xf3\xb1\x93\x93" // U+F14D3 +#define ICON_MDI_PUZZLE_EDIT_OUTLINE "\xf3\xb1\x93\x99" // U+F14D9 +#define ICON_MDI_PUZZLE_HEART "\xf3\xb1\x93\x94" // U+F14D4 +#define ICON_MDI_PUZZLE_HEART_OUTLINE "\xf3\xb1\x93\x9a" // U+F14DA +#define ICON_MDI_PUZZLE_MINUS "\xf3\xb1\x93\x91" // U+F14D1 +#define ICON_MDI_PUZZLE_MINUS_OUTLINE "\xf3\xb1\x93\x97" // U+F14D7 +#define ICON_MDI_PUZZLE_OUTLINE "\xf3\xb0\xa9\xa6" // U+F0A66 +#define ICON_MDI_PUZZLE_PLUS "\xf3\xb1\x93\x90" // U+F14D0 +#define ICON_MDI_PUZZLE_PLUS_OUTLINE "\xf3\xb1\x93\x96" // U+F14D6 +#define ICON_MDI_PUZZLE_REMOVE "\xf3\xb1\x93\x92" // U+F14D2 +#define ICON_MDI_PUZZLE_REMOVE_OUTLINE "\xf3\xb1\x93\x98" // U+F14D8 +#define ICON_MDI_PUZZLE_STAR "\xf3\xb1\x93\x95" // U+F14D5 +#define ICON_MDI_PUZZLE_STAR_OUTLINE "\xf3\xb1\x93\x9b" // U+F14DB +#define ICON_MDI_PYRAMID "\xf3\xb1\xa5\x92" // U+F1952 +#define ICON_MDI_PYRAMID_OFF "\xf3\xb1\xa5\x93" // U+F1953 +#define ICON_MDI_QI "\xf3\xb0\xa6\x99" // U+F0999 +#define ICON_MDI_QQCHAT "\xf3\xb0\x98\x85" // U+F0605 +#define ICON_MDI_QRCODE "\xf3\xb0\x90\xb2" // U+F0432 +#define ICON_MDI_QRCODE_EDIT "\xf3\xb0\xa2\xb8" // U+F08B8 +#define ICON_MDI_QRCODE_MINUS "\xf3\xb1\x86\x8c" // U+F118C +#define ICON_MDI_QRCODE_PLUS "\xf3\xb1\x86\x8b" // U+F118B +#define ICON_MDI_QRCODE_REMOVE "\xf3\xb1\x86\x8d" // U+F118D +#define ICON_MDI_QRCODE_SCAN "\xf3\xb0\x90\xb3" // U+F0433 +#define ICON_MDI_QUADCOPTER "\xf3\xb0\x90\xb4" // U+F0434 +#define ICON_MDI_QUALITY_HIGH "\xf3\xb0\x90\xb5" // U+F0435 +#define ICON_MDI_QUALITY_LOW "\xf3\xb0\xa8\x8c" // U+F0A0C +#define ICON_MDI_QUALITY_MEDIUM "\xf3\xb0\xa8\x8d" // U+F0A0D +#define ICON_MDI_QUEUE_FIRST_IN_LAST_OUT "\xf3\xb1\xb2\xaf" // U+F1CAF +#define ICON_MDI_QUORA "\xf3\xb0\xb4\xa9" // U+F0D29 +#define ICON_MDI_RABBIT "\xf3\xb0\xa4\x87" // U+F0907 +#define ICON_MDI_RABBIT_VARIANT "\xf3\xb1\xa9\xa1" // U+F1A61 +#define ICON_MDI_RABBIT_VARIANT_OUTLINE "\xf3\xb1\xa9\xa2" // U+F1A62 +#define ICON_MDI_RACING_HELMET "\xf3\xb0\xb6\x93" // U+F0D93 +#define ICON_MDI_RACQUETBALL "\xf3\xb0\xb6\x94" // U+F0D94 +#define ICON_MDI_RADAR "\xf3\xb0\x90\xb7" // U+F0437 +#define ICON_MDI_RADIATOR "\xf3\xb0\x90\xb8" // U+F0438 +#define ICON_MDI_RADIATOR_DISABLED "\xf3\xb0\xab\x97" // U+F0AD7 +#define ICON_MDI_RADIATOR_OFF "\xf3\xb0\xab\x98" // U+F0AD8 +#define ICON_MDI_RADIO "\xf3\xb0\x90\xb9" // U+F0439 +#define ICON_MDI_RADIO_AM "\xf3\xb0\xb2\xbe" // U+F0CBE +#define ICON_MDI_RADIO_FM "\xf3\xb0\xb2\xbf" // U+F0CBF +#define ICON_MDI_RADIO_HANDHELD "\xf3\xb0\x90\xba" // U+F043A +#define ICON_MDI_RADIO_OFF "\xf3\xb1\x88\x9c" // U+F121C +#define ICON_MDI_RADIO_TOWER "\xf3\xb0\x90\xbb" // U+F043B +#define ICON_MDI_RADIOACTIVE "\xf3\xb0\x90\xbc" // U+F043C +#define ICON_MDI_RADIOACTIVE_CIRCLE "\xf3\xb1\xa1\x9d" // U+F185D +#define ICON_MDI_RADIOACTIVE_CIRCLE_OUTLINE "\xf3\xb1\xa1\x9e" // U+F185E +#define ICON_MDI_RADIOACTIVE_OFF "\xf3\xb0\xbb\x81" // U+F0EC1 +#define ICON_MDI_RADIOBOX_BLANK "\xf3\xb0\x90\xbd" // U+F043D +#define ICON_MDI_RADIOBOX_INDETERMINATE_VARIANT "\xf3\xb1\xb1\x9e" // U+F1C5E +#define ICON_MDI_RADIOBOX_MARKED "\xf3\xb0\x90\xbe" // U+F043E +#define ICON_MDI_RADIOLOGY_BOX "\xf3\xb1\x93\x85" // U+F14C5 +#define ICON_MDI_RADIOLOGY_BOX_OUTLINE "\xf3\xb1\x93\x86" // U+F14C6 +#define ICON_MDI_RADIUS "\xf3\xb0\xb3\x80" // U+F0CC0 +#define ICON_MDI_RADIUS_OUTLINE "\xf3\xb0\xb3\x81" // U+F0CC1 +#define ICON_MDI_RAILROAD_LIGHT "\xf3\xb0\xbc\x9e" // U+F0F1E +#define ICON_MDI_RAKE "\xf3\xb1\x95\x84" // U+F1544 +#define ICON_MDI_RASPBERRY_PI "\xf3\xb0\x90\xbf" // U+F043F +#define ICON_MDI_RAW "\xf3\xb1\xa8\x8f" // U+F1A0F +#define ICON_MDI_RAW_OFF "\xf3\xb1\xa8\x90" // U+F1A10 +#define ICON_MDI_RAY_END "\xf3\xb0\x91\x80" // U+F0440 +#define ICON_MDI_RAY_END_ARROW "\xf3\xb0\x91\x81" // U+F0441 +#define ICON_MDI_RAY_START "\xf3\xb0\x91\x82" // U+F0442 +#define ICON_MDI_RAY_START_ARROW "\xf3\xb0\x91\x83" // U+F0443 +#define ICON_MDI_RAY_START_END "\xf3\xb0\x91\x84" // U+F0444 +#define ICON_MDI_RAY_START_VERTEX_END "\xf3\xb1\x97\x98" // U+F15D8 +#define ICON_MDI_RAY_VERTEX "\xf3\xb0\x91\x85" // U+F0445 +#define ICON_MDI_RAZOR_DOUBLE_EDGE "\xf3\xb1\xa6\x97" // U+F1997 +#define ICON_MDI_RAZOR_SINGLE_EDGE "\xf3\xb1\xa6\x98" // U+F1998 +#define ICON_MDI_REACT "\xf3\xb0\x9c\x88" // U+F0708 +#define ICON_MDI_READ "\xf3\xb0\x91\x87" // U+F0447 +#define ICON_MDI_RECEIPT "\xf3\xb0\xa0\xa4" // U+F0824 +#define ICON_MDI_RECEIPT_CLOCK "\xf3\xb1\xb0\xbe" // U+F1C3E +#define ICON_MDI_RECEIPT_CLOCK_OUTLINE "\xf3\xb1\xb0\xbf" // U+F1C3F +#define ICON_MDI_RECEIPT_OUTLINE "\xf3\xb0\x93\xb7" // U+F04F7 +#define ICON_MDI_RECEIPT_SEND "\xf3\xb1\xb1\x80" // U+F1C40 +#define ICON_MDI_RECEIPT_SEND_OUTLINE "\xf3\xb1\xb1\x81" // U+F1C41 +#define ICON_MDI_RECEIPT_TEXT "\xf3\xb0\x91\x89" // U+F0449 +#define ICON_MDI_RECEIPT_TEXT_ARROW_LEFT "\xf3\xb1\xb1\x82" // U+F1C42 +#define ICON_MDI_RECEIPT_TEXT_ARROW_LEFT_OUTLINE "\xf3\xb1\xb1\x83" // U+F1C43 +#define ICON_MDI_RECEIPT_TEXT_ARROW_RIGHT "\xf3\xb1\xb1\x84" // U+F1C44 +#define ICON_MDI_RECEIPT_TEXT_ARROW_RIGHT_OUTLINE "\xf3\xb1\xb1\x85" // U+F1C45 +#define ICON_MDI_RECEIPT_TEXT_CHECK "\xf3\xb1\xa9\xa3" // U+F1A63 +#define ICON_MDI_RECEIPT_TEXT_CHECK_OUTLINE "\xf3\xb1\xa9\xa4" // U+F1A64 +#define ICON_MDI_RECEIPT_TEXT_CLOCK "\xf3\xb1\xb1\x86" // U+F1C46 +#define ICON_MDI_RECEIPT_TEXT_CLOCK_OUTLINE "\xf3\xb1\xb1\x87" // U+F1C47 +#define ICON_MDI_RECEIPT_TEXT_EDIT "\xf3\xb1\xb1\x88" // U+F1C48 +#define ICON_MDI_RECEIPT_TEXT_EDIT_OUTLINE "\xf3\xb1\xb1\x89" // U+F1C49 +#define ICON_MDI_RECEIPT_TEXT_MINUS "\xf3\xb1\xa9\xa5" // U+F1A65 +#define ICON_MDI_RECEIPT_TEXT_MINUS_OUTLINE "\xf3\xb1\xa9\xa6" // U+F1A66 +#define ICON_MDI_RECEIPT_TEXT_OUTLINE "\xf3\xb1\xa7\x9c" // U+F19DC +#define ICON_MDI_RECEIPT_TEXT_PLUS "\xf3\xb1\xa9\xa7" // U+F1A67 +#define ICON_MDI_RECEIPT_TEXT_PLUS_OUTLINE "\xf3\xb1\xa9\xa8" // U+F1A68 +#define ICON_MDI_RECEIPT_TEXT_REMOVE "\xf3\xb1\xa9\xa9" // U+F1A69 +#define ICON_MDI_RECEIPT_TEXT_REMOVE_OUTLINE "\xf3\xb1\xa9\xaa" // U+F1A6A +#define ICON_MDI_RECEIPT_TEXT_SEND "\xf3\xb1\xb1\x8a" // U+F1C4A +#define ICON_MDI_RECEIPT_TEXT_SEND_OUTLINE "\xf3\xb1\xb1\x8b" // U+F1C4B +#define ICON_MDI_RECORD "\xf3\xb0\x91\x8a" // U+F044A +#define ICON_MDI_RECORD_CIRCLE "\xf3\xb0\xbb\x82" // U+F0EC2 +#define ICON_MDI_RECORD_CIRCLE_OUTLINE "\xf3\xb0\xbb\x83" // U+F0EC3 +#define ICON_MDI_RECORD_PLAYER "\xf3\xb0\xa6\x9a" // U+F099A +#define ICON_MDI_RECORD_REC "\xf3\xb0\x91\x8b" // U+F044B +#define ICON_MDI_RECTANGLE "\xf3\xb0\xb9\x9e" // U+F0E5E +#define ICON_MDI_RECTANGLE_OUTLINE "\xf3\xb0\xb9\x9f" // U+F0E5F +#define ICON_MDI_RECYCLE "\xf3\xb0\x91\x8c" // U+F044C +#define ICON_MDI_RECYCLE_VARIANT "\xf3\xb1\x8e\x9d" // U+F139D +#define ICON_MDI_REDDIT "\xf3\xb0\x91\x8d" // U+F044D +#define ICON_MDI_REDHAT "\xf3\xb1\x84\x9b" // U+F111B +#define ICON_MDI_REDO "\xf3\xb0\x91\x8e" // U+F044E +#define ICON_MDI_REDO_VARIANT "\xf3\xb0\x91\x8f" // U+F044F +#define ICON_MDI_REFLECT_HORIZONTAL "\xf3\xb0\xa8\x8e" // U+F0A0E +#define ICON_MDI_REFLECT_VERTICAL "\xf3\xb0\xa8\x8f" // U+F0A0F +#define ICON_MDI_REFRESH "\xf3\xb0\x91\x90" // U+F0450 +#define ICON_MDI_REFRESH_AUTO "\xf3\xb1\xa3\xb2" // U+F18F2 +#define ICON_MDI_REFRESH_CIRCLE "\xf3\xb1\x8d\xb7" // U+F1377 +#define ICON_MDI_REGEX "\xf3\xb0\x91\x91" // U+F0451 +#define ICON_MDI_REGISTERED_TRADEMARK "\xf3\xb0\xa9\xa7" // U+F0A67 +#define ICON_MDI_REITERATE "\xf3\xb1\x96\x88" // U+F1588 +#define ICON_MDI_RELATION_MANY_TO_MANY "\xf3\xb1\x92\x96" // U+F1496 +#define ICON_MDI_RELATION_MANY_TO_ONE "\xf3\xb1\x92\x97" // U+F1497 +#define ICON_MDI_RELATION_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\x98" // U+F1498 +#define ICON_MDI_RELATION_MANY_TO_ONLY_ONE "\xf3\xb1\x92\x99" // U+F1499 +#define ICON_MDI_RELATION_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\x9a" // U+F149A +#define ICON_MDI_RELATION_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\x9b" // U+F149B +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_MANY "\xf3\xb1\x92\x9c" // U+F149C +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONE "\xf3\xb1\x92\x9d" // U+F149D +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\x9e" // U+F149E +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ONLY_ONE "\xf3\xb1\x92\x9f" // U+F149F +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\xa0" // U+F14A0 +#define ICON_MDI_RELATION_ONE_OR_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\xa1" // U+F14A1 +#define ICON_MDI_RELATION_ONE_TO_MANY "\xf3\xb1\x92\xa2" // U+F14A2 +#define ICON_MDI_RELATION_ONE_TO_ONE "\xf3\xb1\x92\xa3" // U+F14A3 +#define ICON_MDI_RELATION_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xa4" // U+F14A4 +#define ICON_MDI_RELATION_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xa5" // U+F14A5 +#define ICON_MDI_RELATION_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xa6" // U+F14A6 +#define ICON_MDI_RELATION_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xa7" // U+F14A7 +#define ICON_MDI_RELATION_ONLY_ONE_TO_MANY "\xf3\xb1\x92\xa8" // U+F14A8 +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONE "\xf3\xb1\x92\xa9" // U+F14A9 +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xaa" // U+F14AA +#define ICON_MDI_RELATION_ONLY_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xab" // U+F14AB +#define ICON_MDI_RELATION_ONLY_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xac" // U+F14AC +#define ICON_MDI_RELATION_ONLY_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xad" // U+F14AD +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_MANY "\xf3\xb1\x92\xae" // U+F14AE +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONE "\xf3\xb1\x92\xaf" // U+F14AF +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONE_OR_MANY "\xf3\xb1\x92\xb0" // U+F14B0 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ONLY_ONE "\xf3\xb1\x92\xb1" // U+F14B1 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ZERO_OR_MANY "\xf3\xb1\x92\xb2" // U+F14B2 +#define ICON_MDI_RELATION_ZERO_OR_MANY_TO_ZERO_OR_ONE "\xf3\xb1\x92\xb3" // U+F14B3 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_MANY "\xf3\xb1\x92\xb4" // U+F14B4 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONE "\xf3\xb1\x92\xb5" // U+F14B5 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONE_OR_MANY "\xf3\xb1\x92\xb6" // U+F14B6 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ONLY_ONE "\xf3\xb1\x92\xb7" // U+F14B7 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ZERO_OR_MANY "\xf3\xb1\x92\xb8" // U+F14B8 +#define ICON_MDI_RELATION_ZERO_OR_ONE_TO_ZERO_OR_ONE "\xf3\xb1\x92\xb9" // U+F14B9 +#define ICON_MDI_RELATIVE_SCALE "\xf3\xb0\x91\x92" // U+F0452 +#define ICON_MDI_RELOAD "\xf3\xb0\x91\x93" // U+F0453 +#define ICON_MDI_RELOAD_ALERT "\xf3\xb1\x84\x8b" // U+F110B +#define ICON_MDI_REMINDER "\xf3\xb0\xa2\x8c" // U+F088C +#define ICON_MDI_REMOTE "\xf3\xb0\x91\x94" // U+F0454 +#define ICON_MDI_REMOTE_DESKTOP "\xf3\xb0\xa2\xb9" // U+F08B9 +#define ICON_MDI_REMOTE_OFF "\xf3\xb0\xbb\x84" // U+F0EC4 +#define ICON_MDI_REMOTE_TV "\xf3\xb0\xbb\x85" // U+F0EC5 +#define ICON_MDI_REMOTE_TV_OFF "\xf3\xb0\xbb\x86" // U+F0EC6 +#define ICON_MDI_RENAME "\xf3\xb1\xb0\x98" // U+F1C18 +#define ICON_MDI_RENAME_BOX "\xf3\xb0\x91\x95" // U+F0455 +#define ICON_MDI_RENAME_BOX_OUTLINE "\xf3\xb1\xb0\x99" // U+F1C19 +#define ICON_MDI_RENAME_OUTLINE "\xf3\xb1\xb0\x9a" // U+F1C1A +#define ICON_MDI_REORDER_HORIZONTAL "\xf3\xb0\x9a\x88" // U+F0688 +#define ICON_MDI_REORDER_VERTICAL "\xf3\xb0\x9a\x89" // U+F0689 +#define ICON_MDI_REPEAT "\xf3\xb0\x91\x96" // U+F0456 +#define ICON_MDI_REPEAT_OFF "\xf3\xb0\x91\x97" // U+F0457 +#define ICON_MDI_REPEAT_ONCE "\xf3\xb0\x91\x98" // U+F0458 +#define ICON_MDI_REPEAT_VARIANT "\xf3\xb0\x95\x87" // U+F0547 +#define ICON_MDI_REPLAY "\xf3\xb0\x91\x99" // U+F0459 +#define ICON_MDI_REPLY "\xf3\xb0\x91\x9a" // U+F045A +#define ICON_MDI_REPLY_ALL "\xf3\xb0\x91\x9b" // U+F045B +#define ICON_MDI_REPLY_ALL_OUTLINE "\xf3\xb0\xbc\x9f" // U+F0F1F +#define ICON_MDI_REPLY_CIRCLE "\xf3\xb1\x86\xae" // U+F11AE +#define ICON_MDI_REPLY_OUTLINE "\xf3\xb0\xbc\xa0" // U+F0F20 +#define ICON_MDI_REPRODUCTION "\xf3\xb0\x91\x9c" // U+F045C +#define ICON_MDI_RESISTOR "\xf3\xb0\xad\x84" // U+F0B44 +#define ICON_MDI_RESISTOR_NODES "\xf3\xb0\xad\x85" // U+F0B45 +#define ICON_MDI_RESIZE "\xf3\xb0\xa9\xa8" // U+F0A68 +#define ICON_MDI_RESIZE_BOTTOM_RIGHT "\xf3\xb0\x91\x9d" // U+F045D +#define ICON_MDI_RESPONSIVE "\xf3\xb0\x91\x9e" // U+F045E +#define ICON_MDI_RESTART "\xf3\xb0\x9c\x89" // U+F0709 +#define ICON_MDI_RESTART_ALERT "\xf3\xb1\x84\x8c" // U+F110C +#define ICON_MDI_RESTART_OFF "\xf3\xb0\xb6\x95" // U+F0D95 +#define ICON_MDI_RESTORE "\xf3\xb0\xa6\x9b" // U+F099B +#define ICON_MDI_RESTORE_ALERT "\xf3\xb1\x84\x8d" // U+F110D +#define ICON_MDI_REWIND "\xf3\xb0\x91\x9f" // U+F045F +#define ICON_MDI_REWIND_10 "\xf3\xb0\xb4\xaa" // U+F0D2A +#define ICON_MDI_REWIND_15 "\xf3\xb1\xa5\x86" // U+F1946 +#define ICON_MDI_REWIND_30 "\xf3\xb0\xb6\x96" // U+F0D96 +#define ICON_MDI_REWIND_45 "\xf3\xb1\xac\x93" // U+F1B13 +#define ICON_MDI_REWIND_5 "\xf3\xb1\x87\xb9" // U+F11F9 +#define ICON_MDI_REWIND_60 "\xf3\xb1\x98\x8c" // U+F160C +#define ICON_MDI_REWIND_OUTLINE "\xf3\xb0\x9c\x8a" // U+F070A +#define ICON_MDI_RHOMBUS "\xf3\xb0\x9c\x8b" // U+F070B +#define ICON_MDI_RHOMBUS_MEDIUM "\xf3\xb0\xa8\x90" // U+F0A10 +#define ICON_MDI_RHOMBUS_MEDIUM_OUTLINE "\xf3\xb1\x93\x9c" // U+F14DC +#define ICON_MDI_RHOMBUS_OUTLINE "\xf3\xb0\x9c\x8c" // U+F070C +#define ICON_MDI_RHOMBUS_SPLIT "\xf3\xb0\xa8\x91" // U+F0A11 +#define ICON_MDI_RHOMBUS_SPLIT_OUTLINE "\xf3\xb1\x93\x9d" // U+F14DD +#define ICON_MDI_RIBBON "\xf3\xb0\x91\xa0" // U+F0460 +#define ICON_MDI_RICE "\xf3\xb0\x9f\xaa" // U+F07EA +#define ICON_MDI_RICKSHAW "\xf3\xb1\x96\xbb" // U+F15BB +#define ICON_MDI_RICKSHAW_ELECTRIC "\xf3\xb1\x96\xbc" // U+F15BC +#define ICON_MDI_RING "\xf3\xb0\x9f\xab" // U+F07EB +#define ICON_MDI_RIVET "\xf3\xb0\xb9\xa0" // U+F0E60 +#define ICON_MDI_ROAD "\xf3\xb0\x91\xa1" // U+F0461 +#define ICON_MDI_ROAD_VARIANT "\xf3\xb0\x91\xa2" // U+F0462 +#define ICON_MDI_ROBBER "\xf3\xb1\x81\x98" // U+F1058 +#define ICON_MDI_ROBOT "\xf3\xb0\x9a\xa9" // U+F06A9 +#define ICON_MDI_ROBOT_ANGRY "\xf3\xb1\x9a\x9d" // U+F169D +#define ICON_MDI_ROBOT_ANGRY_OUTLINE "\xf3\xb1\x9a\x9e" // U+F169E +#define ICON_MDI_ROBOT_CONFUSED "\xf3\xb1\x9a\x9f" // U+F169F +#define ICON_MDI_ROBOT_CONFUSED_OUTLINE "\xf3\xb1\x9a\xa0" // U+F16A0 +#define ICON_MDI_ROBOT_DEAD "\xf3\xb1\x9a\xa1" // U+F16A1 +#define ICON_MDI_ROBOT_DEAD_OUTLINE "\xf3\xb1\x9a\xa2" // U+F16A2 +#define ICON_MDI_ROBOT_EXCITED "\xf3\xb1\x9a\xa3" // U+F16A3 +#define ICON_MDI_ROBOT_EXCITED_OUTLINE "\xf3\xb1\x9a\xa4" // U+F16A4 +#define ICON_MDI_ROBOT_HAPPY "\xf3\xb1\x9c\x99" // U+F1719 +#define ICON_MDI_ROBOT_HAPPY_OUTLINE "\xf3\xb1\x9c\x9a" // U+F171A +#define ICON_MDI_ROBOT_INDUSTRIAL "\xf3\xb0\xad\x86" // U+F0B46 +#define ICON_MDI_ROBOT_INDUSTRIAL_OUTLINE "\xf3\xb1\xa8\x9a" // U+F1A1A +#define ICON_MDI_ROBOT_LOVE "\xf3\xb1\x9a\xa5" // U+F16A5 +#define ICON_MDI_ROBOT_LOVE_OUTLINE "\xf3\xb1\x9a\xa6" // U+F16A6 +#define ICON_MDI_ROBOT_MOWER "\xf3\xb1\x87\xb7" // U+F11F7 +#define ICON_MDI_ROBOT_MOWER_OUTLINE "\xf3\xb1\x87\xb3" // U+F11F3 +#define ICON_MDI_ROBOT_OFF "\xf3\xb1\x9a\xa7" // U+F16A7 +#define ICON_MDI_ROBOT_OFF_OUTLINE "\xf3\xb1\x99\xbb" // U+F167B +#define ICON_MDI_ROBOT_OUTLINE "\xf3\xb1\x99\xba" // U+F167A +#define ICON_MDI_ROBOT_VACUUM "\xf3\xb0\x9c\x8d" // U+F070D +#define ICON_MDI_ROBOT_VACUUM_ALERT "\xf3\xb1\xad\x9d" // U+F1B5D +#define ICON_MDI_ROBOT_VACUUM_OFF "\xf3\xb1\xb0\x81" // U+F1C01 +#define ICON_MDI_ROBOT_VACUUM_VARIANT "\xf3\xb0\xa4\x88" // U+F0908 +#define ICON_MDI_ROBOT_VACUUM_VARIANT_ALERT "\xf3\xb1\xad\x9e" // U+F1B5E +#define ICON_MDI_ROBOT_VACUUM_VARIANT_OFF "\xf3\xb1\xb0\x82" // U+F1C02 +#define ICON_MDI_ROCKET "\xf3\xb0\x91\xa3" // U+F0463 +#define ICON_MDI_ROCKET_LAUNCH "\xf3\xb1\x93\x9e" // U+F14DE +#define ICON_MDI_ROCKET_LAUNCH_OUTLINE "\xf3\xb1\x93\x9f" // U+F14DF +#define ICON_MDI_ROCKET_OUTLINE "\xf3\xb1\x8e\xaf" // U+F13AF +#define ICON_MDI_RODENT "\xf3\xb1\x8c\xa7" // U+F1327 +#define ICON_MDI_ROLLER_SHADE "\xf3\xb1\xa9\xab" // U+F1A6B +#define ICON_MDI_ROLLER_SHADE_CLOSED "\xf3\xb1\xa9\xac" // U+F1A6C +#define ICON_MDI_ROLLER_SKATE "\xf3\xb0\xb4\xab" // U+F0D2B +#define ICON_MDI_ROLLER_SKATE_OFF "\xf3\xb0\x85\x85" // U+F0145 +#define ICON_MDI_ROLLERBLADE "\xf3\xb0\xb4\xac" // U+F0D2C +#define ICON_MDI_ROLLERBLADE_OFF "\xf3\xb0\x80\xae" // U+F002E +#define ICON_MDI_ROLLUPJS "\xf3\xb0\xaf\x80" // U+F0BC0 +#define ICON_MDI_ROLODEX "\xf3\xb1\xaa\xb9" // U+F1AB9 +#define ICON_MDI_ROLODEX_OUTLINE "\xf3\xb1\xaa\xba" // U+F1ABA +#define ICON_MDI_ROMAN_NUMERAL_1 "\xf3\xb1\x82\x88" // U+F1088 +#define ICON_MDI_ROMAN_NUMERAL_10 "\xf3\xb1\x82\x91" // U+F1091 +#define ICON_MDI_ROMAN_NUMERAL_2 "\xf3\xb1\x82\x89" // U+F1089 +#define ICON_MDI_ROMAN_NUMERAL_3 "\xf3\xb1\x82\x8a" // U+F108A +#define ICON_MDI_ROMAN_NUMERAL_4 "\xf3\xb1\x82\x8b" // U+F108B +#define ICON_MDI_ROMAN_NUMERAL_5 "\xf3\xb1\x82\x8c" // U+F108C +#define ICON_MDI_ROMAN_NUMERAL_6 "\xf3\xb1\x82\x8d" // U+F108D +#define ICON_MDI_ROMAN_NUMERAL_7 "\xf3\xb1\x82\x8e" // U+F108E +#define ICON_MDI_ROMAN_NUMERAL_8 "\xf3\xb1\x82\x8f" // U+F108F +#define ICON_MDI_ROMAN_NUMERAL_9 "\xf3\xb1\x82\x90" // U+F1090 +#define ICON_MDI_ROOM_SERVICE "\xf3\xb0\xa2\x8d" // U+F088D +#define ICON_MDI_ROOM_SERVICE_OUTLINE "\xf3\xb0\xb6\x97" // U+F0D97 +#define ICON_MDI_ROTATE_360 "\xf3\xb1\xa6\x99" // U+F1999 +#define ICON_MDI_ROTATE_3D "\xf3\xb0\xbb\x87" // U+F0EC7 +#define ICON_MDI_ROTATE_3D_VARIANT "\xf3\xb0\x91\xa4" // U+F0464 +#define ICON_MDI_ROTATE_LEFT "\xf3\xb0\x91\xa5" // U+F0465 +#define ICON_MDI_ROTATE_LEFT_VARIANT "\xf3\xb0\x91\xa6" // U+F0466 +#define ICON_MDI_ROTATE_ORBIT "\xf3\xb0\xb6\x98" // U+F0D98 +#define ICON_MDI_ROTATE_RIGHT "\xf3\xb0\x91\xa7" // U+F0467 +#define ICON_MDI_ROTATE_RIGHT_VARIANT "\xf3\xb0\x91\xa8" // U+F0468 +#define ICON_MDI_ROUNDED_CORNER "\xf3\xb0\x98\x87" // U+F0607 +#define ICON_MDI_ROUTER "\xf3\xb1\x87\xa2" // U+F11E2 +#define ICON_MDI_ROUTER_NETWORK "\xf3\xb1\x82\x87" // U+F1087 +#define ICON_MDI_ROUTER_NETWORK_WIRELESS "\xf3\xb1\xb2\x97" // U+F1C97 +#define ICON_MDI_ROUTER_WIRELESS "\xf3\xb0\x91\xa9" // U+F0469 +#define ICON_MDI_ROUTER_WIRELESS_OFF "\xf3\xb1\x96\xa3" // U+F15A3 +#define ICON_MDI_ROUTER_WIRELESS_SETTINGS "\xf3\xb0\xa9\xa9" // U+F0A69 +#define ICON_MDI_ROUTES "\xf3\xb0\x91\xaa" // U+F046A +#define ICON_MDI_ROUTES_CLOCK "\xf3\xb1\x81\x99" // U+F1059 +#define ICON_MDI_ROWING "\xf3\xb0\x98\x88" // U+F0608 +#define ICON_MDI_RSS "\xf3\xb0\x91\xab" // U+F046B +#define ICON_MDI_RSS_BOX "\xf3\xb0\x91\xac" // U+F046C +#define ICON_MDI_RSS_OFF "\xf3\xb0\xbc\xa1" // U+F0F21 +#define ICON_MDI_RUG "\xf3\xb1\x91\xb5" // U+F1475 +#define ICON_MDI_RUGBY "\xf3\xb0\xb6\x99" // U+F0D99 +#define ICON_MDI_RULER "\xf3\xb0\x91\xad" // U+F046D +#define ICON_MDI_RULER_SQUARE "\xf3\xb0\xb3\x82" // U+F0CC2 +#define ICON_MDI_RULER_SQUARE_COMPASS "\xf3\xb0\xba\xbe" // U+F0EBE +#define ICON_MDI_RUN "\xf3\xb0\x9c\x8e" // U+F070E +#define ICON_MDI_RUN_FAST "\xf3\xb0\x91\xae" // U+F046E +#define ICON_MDI_RV_TRUCK "\xf3\xb1\x87\x94" // U+F11D4 +#define ICON_MDI_SACK "\xf3\xb0\xb4\xae" // U+F0D2E +#define ICON_MDI_SACK_OUTLINE "\xf3\xb1\xb1\x8c" // U+F1C4C +#define ICON_MDI_SACK_PERCENT "\xf3\xb0\xb4\xaf" // U+F0D2F +#define ICON_MDI_SAFE "\xf3\xb0\xa9\xaa" // U+F0A6A +#define ICON_MDI_SAFE_SQUARE "\xf3\xb1\x89\xbc" // U+F127C +#define ICON_MDI_SAFE_SQUARE_OUTLINE "\xf3\xb1\x89\xbd" // U+F127D +#define ICON_MDI_SAFETY_GOGGLES "\xf3\xb0\xb4\xb0" // U+F0D30 +#define ICON_MDI_SAIL_BOAT "\xf3\xb0\xbb\x88" // U+F0EC8 +#define ICON_MDI_SAIL_BOAT_SINK "\xf3\xb1\xab\xaf" // U+F1AEF +#define ICON_MDI_SALE "\xf3\xb0\x91\xaf" // U+F046F +#define ICON_MDI_SALE_OUTLINE "\xf3\xb1\xa8\x86" // U+F1A06 +#define ICON_MDI_SALESFORCE "\xf3\xb0\xa2\x8e" // U+F088E +#define ICON_MDI_SASS "\xf3\xb0\x9f\xac" // U+F07EC +#define ICON_MDI_SATELLITE "\xf3\xb0\x91\xb0" // U+F0470 +#define ICON_MDI_SATELLITE_UPLINK "\xf3\xb0\xa4\x89" // U+F0909 +#define ICON_MDI_SATELLITE_VARIANT "\xf3\xb0\x91\xb1" // U+F0471 +#define ICON_MDI_SAUSAGE "\xf3\xb0\xa2\xba" // U+F08BA +#define ICON_MDI_SAUSAGE_OFF "\xf3\xb1\x9e\x89" // U+F1789 +#define ICON_MDI_SAW_BLADE "\xf3\xb0\xb9\xa1" // U+F0E61 +#define ICON_MDI_SAWTOOTH_WAVE "\xf3\xb1\x91\xba" // U+F147A +#define ICON_MDI_SAXOPHONE "\xf3\xb0\x98\x89" // U+F0609 +#define ICON_MDI_SCALE "\xf3\xb0\x91\xb2" // U+F0472 +#define ICON_MDI_SCALE_BALANCE "\xf3\xb0\x97\x91" // U+F05D1 +#define ICON_MDI_SCALE_BATHROOM "\xf3\xb0\x91\xb3" // U+F0473 +#define ICON_MDI_SCALE_OFF "\xf3\xb1\x81\x9a" // U+F105A +#define ICON_MDI_SCALE_UNBALANCED "\xf3\xb1\xa6\xb8" // U+F19B8 +#define ICON_MDI_SCAN_HELPER "\xf3\xb1\x8f\x98" // U+F13D8 +#define ICON_MDI_SCANNER "\xf3\xb0\x9a\xab" // U+F06AB +#define ICON_MDI_SCANNER_OFF "\xf3\xb0\xa4\x8a" // U+F090A +#define ICON_MDI_SCATTER_PLOT "\xf3\xb0\xbb\x89" // U+F0EC9 +#define ICON_MDI_SCATTER_PLOT_OUTLINE "\xf3\xb0\xbb\x8a" // U+F0ECA +#define ICON_MDI_SCENT "\xf3\xb1\xa5\x98" // U+F1958 +#define ICON_MDI_SCENT_OFF "\xf3\xb1\xa5\x99" // U+F1959 +#define ICON_MDI_SCHOOL "\xf3\xb0\x91\xb4" // U+F0474 +#define ICON_MDI_SCHOOL_OUTLINE "\xf3\xb1\x86\x80" // U+F1180 +#define ICON_MDI_SCISSORS_CUTTING "\xf3\xb0\xa9\xab" // U+F0A6B +#define ICON_MDI_SCOOTER "\xf3\xb1\x96\xbd" // U+F15BD +#define ICON_MDI_SCOOTER_ELECTRIC "\xf3\xb1\x96\xbe" // U+F15BE +#define ICON_MDI_SCOREBOARD "\xf3\xb1\x89\xbe" // U+F127E +#define ICON_MDI_SCOREBOARD_OUTLINE "\xf3\xb1\x89\xbf" // U+F127F +#define ICON_MDI_SCREEN_ROTATION "\xf3\xb0\x91\xb5" // U+F0475 +#define ICON_MDI_SCREEN_ROTATION_LOCK "\xf3\xb0\x91\xb8" // U+F0478 +#define ICON_MDI_SCREW_FLAT_TOP "\xf3\xb0\xb7\xb3" // U+F0DF3 +#define ICON_MDI_SCREW_LAG "\xf3\xb0\xb7\xb4" // U+F0DF4 +#define ICON_MDI_SCREW_MACHINE_FLAT_TOP "\xf3\xb0\xb7\xb5" // U+F0DF5 +#define ICON_MDI_SCREW_MACHINE_ROUND_TOP "\xf3\xb0\xb7\xb6" // U+F0DF6 +#define ICON_MDI_SCREW_ROUND_TOP "\xf3\xb0\xb7\xb7" // U+F0DF7 +#define ICON_MDI_SCREWDRIVER "\xf3\xb0\x91\xb6" // U+F0476 +#define ICON_MDI_SCRIPT "\xf3\xb0\xaf\x81" // U+F0BC1 +#define ICON_MDI_SCRIPT_OUTLINE "\xf3\xb0\x91\xb7" // U+F0477 +#define ICON_MDI_SCRIPT_TEXT "\xf3\xb0\xaf\x82" // U+F0BC2 +#define ICON_MDI_SCRIPT_TEXT_KEY "\xf3\xb1\x9c\xa5" // U+F1725 +#define ICON_MDI_SCRIPT_TEXT_KEY_OUTLINE "\xf3\xb1\x9c\xa6" // U+F1726 +#define ICON_MDI_SCRIPT_TEXT_OUTLINE "\xf3\xb0\xaf\x83" // U+F0BC3 +#define ICON_MDI_SCRIPT_TEXT_PLAY "\xf3\xb1\x9c\xa7" // U+F1727 +#define ICON_MDI_SCRIPT_TEXT_PLAY_OUTLINE "\xf3\xb1\x9c\xa8" // U+F1728 +#define ICON_MDI_SD "\xf3\xb0\x91\xb9" // U+F0479 +#define ICON_MDI_SEAL "\xf3\xb0\x91\xba" // U+F047A +#define ICON_MDI_SEAL_VARIANT "\xf3\xb0\xbf\x99" // U+F0FD9 +#define ICON_MDI_SEARCH_WEB "\xf3\xb0\x9c\x8f" // U+F070F +#define ICON_MDI_SEAT "\xf3\xb0\xb3\x83" // U+F0CC3 +#define ICON_MDI_SEAT_FLAT "\xf3\xb0\x91\xbb" // U+F047B +#define ICON_MDI_SEAT_FLAT_ANGLED "\xf3\xb0\x91\xbc" // U+F047C +#define ICON_MDI_SEAT_INDIVIDUAL_SUITE "\xf3\xb0\x91\xbd" // U+F047D +#define ICON_MDI_SEAT_LEGROOM_EXTRA "\xf3\xb0\x91\xbe" // U+F047E +#define ICON_MDI_SEAT_LEGROOM_NORMAL "\xf3\xb0\x91\xbf" // U+F047F +#define ICON_MDI_SEAT_LEGROOM_REDUCED "\xf3\xb0\x92\x80" // U+F0480 +#define ICON_MDI_SEAT_OUTLINE "\xf3\xb0\xb3\x84" // U+F0CC4 +#define ICON_MDI_SEAT_PASSENGER "\xf3\xb1\x89\x89" // U+F1249 +#define ICON_MDI_SEAT_RECLINE_EXTRA "\xf3\xb0\x92\x81" // U+F0481 +#define ICON_MDI_SEAT_RECLINE_NORMAL "\xf3\xb0\x92\x82" // U+F0482 +#define ICON_MDI_SEATBELT "\xf3\xb0\xb3\x85" // U+F0CC5 +#define ICON_MDI_SECURITY "\xf3\xb0\x92\x83" // U+F0483 +#define ICON_MDI_SECURITY_NETWORK "\xf3\xb0\x92\x84" // U+F0484 +#define ICON_MDI_SEED "\xf3\xb0\xb9\xa2" // U+F0E62 +#define ICON_MDI_SEED_OFF "\xf3\xb1\x8f\xbd" // U+F13FD +#define ICON_MDI_SEED_OFF_OUTLINE "\xf3\xb1\x8f\xbe" // U+F13FE +#define ICON_MDI_SEED_OUTLINE "\xf3\xb0\xb9\xa3" // U+F0E63 +#define ICON_MDI_SEED_PLUS "\xf3\xb1\xa9\xad" // U+F1A6D +#define ICON_MDI_SEED_PLUS_OUTLINE "\xf3\xb1\xa9\xae" // U+F1A6E +#define ICON_MDI_SEESAW "\xf3\xb1\x96\xa4" // U+F15A4 +#define ICON_MDI_SEGMENT "\xf3\xb0\xbb\x8b" // U+F0ECB +#define ICON_MDI_SELECT "\xf3\xb0\x92\x85" // U+F0485 +#define ICON_MDI_SELECT_ALL "\xf3\xb0\x92\x86" // U+F0486 +#define ICON_MDI_SELECT_ARROW_DOWN "\xf3\xb1\xad\x99" // U+F1B59 +#define ICON_MDI_SELECT_ARROW_UP "\xf3\xb1\xad\x98" // U+F1B58 +#define ICON_MDI_SELECT_COLOR "\xf3\xb0\xb4\xb1" // U+F0D31 +#define ICON_MDI_SELECT_COMPARE "\xf3\xb0\xab\x99" // U+F0AD9 +#define ICON_MDI_SELECT_DRAG "\xf3\xb0\xa9\xac" // U+F0A6C +#define ICON_MDI_SELECT_GROUP "\xf3\xb0\xbe\x82" // U+F0F82 +#define ICON_MDI_SELECT_INVERSE "\xf3\xb0\x92\x87" // U+F0487 +#define ICON_MDI_SELECT_MARKER "\xf3\xb1\x8a\x80" // U+F1280 +#define ICON_MDI_SELECT_MULTIPLE "\xf3\xb1\x8a\x81" // U+F1281 +#define ICON_MDI_SELECT_MULTIPLE_MARKER "\xf3\xb1\x8a\x82" // U+F1282 +#define ICON_MDI_SELECT_OFF "\xf3\xb0\x92\x88" // U+F0488 +#define ICON_MDI_SELECT_PLACE "\xf3\xb0\xbf\x9a" // U+F0FDA +#define ICON_MDI_SELECT_REMOVE "\xf3\xb1\x9f\x81" // U+F17C1 +#define ICON_MDI_SELECT_SEARCH "\xf3\xb1\x88\x84" // U+F1204 +#define ICON_MDI_SELECTION "\xf3\xb0\x92\x89" // U+F0489 +#define ICON_MDI_SELECTION_DRAG "\xf3\xb0\xa9\xad" // U+F0A6D +#define ICON_MDI_SELECTION_ELLIPSE "\xf3\xb0\xb4\xb2" // U+F0D32 +#define ICON_MDI_SELECTION_ELLIPSE_ARROW_INSIDE "\xf3\xb0\xbc\xa2" // U+F0F22 +#define ICON_MDI_SELECTION_ELLIPSE_REMOVE "\xf3\xb1\x9f\x82" // U+F17C2 +#define ICON_MDI_SELECTION_MARKER "\xf3\xb1\x8a\x83" // U+F1283 +#define ICON_MDI_SELECTION_MULTIPLE "\xf3\xb1\x8a\x85" // U+F1285 +#define ICON_MDI_SELECTION_MULTIPLE_MARKER "\xf3\xb1\x8a\x84" // U+F1284 +#define ICON_MDI_SELECTION_OFF "\xf3\xb0\x9d\xb7" // U+F0777 +#define ICON_MDI_SELECTION_REMOVE "\xf3\xb1\x9f\x83" // U+F17C3 +#define ICON_MDI_SELECTION_SEARCH "\xf3\xb1\x88\x85" // U+F1205 +#define ICON_MDI_SEMANTIC_WEB "\xf3\xb1\x8c\x96" // U+F1316 +#define ICON_MDI_SEND "\xf3\xb0\x92\x8a" // U+F048A +#define ICON_MDI_SEND_CHECK "\xf3\xb1\x85\xa1" // U+F1161 +#define ICON_MDI_SEND_CHECK_OUTLINE "\xf3\xb1\x85\xa2" // U+F1162 +#define ICON_MDI_SEND_CIRCLE "\xf3\xb0\xb7\xb8" // U+F0DF8 +#define ICON_MDI_SEND_CIRCLE_OUTLINE "\xf3\xb0\xb7\xb9" // U+F0DF9 +#define ICON_MDI_SEND_CLOCK "\xf3\xb1\x85\xa3" // U+F1163 +#define ICON_MDI_SEND_CLOCK_OUTLINE "\xf3\xb1\x85\xa4" // U+F1164 +#define ICON_MDI_SEND_LOCK "\xf3\xb0\x9f\xad" // U+F07ED +#define ICON_MDI_SEND_LOCK_OUTLINE "\xf3\xb1\x85\xa6" // U+F1166 +#define ICON_MDI_SEND_OUTLINE "\xf3\xb1\x85\xa5" // U+F1165 +#define ICON_MDI_SEND_VARIANT "\xf3\xb1\xb1\x8d" // U+F1C4D +#define ICON_MDI_SEND_VARIANT_CLOCK "\xf3\xb1\xb1\xbe" // U+F1C7E +#define ICON_MDI_SEND_VARIANT_CLOCK_OUTLINE "\xf3\xb1\xb1\xbf" // U+F1C7F +#define ICON_MDI_SEND_VARIANT_OUTLINE "\xf3\xb1\xb1\x8e" // U+F1C4E +#define ICON_MDI_SERIAL_PORT "\xf3\xb0\x99\x9c" // U+F065C +#define ICON_MDI_SERVER "\xf3\xb0\x92\x8b" // U+F048B +#define ICON_MDI_SERVER_MINUS "\xf3\xb0\x92\x8c" // U+F048C +#define ICON_MDI_SERVER_MINUS_OUTLINE "\xf3\xb1\xb2\x98" // U+F1C98 +#define ICON_MDI_SERVER_NETWORK "\xf3\xb0\x92\x8d" // U+F048D +#define ICON_MDI_SERVER_NETWORK_OFF "\xf3\xb0\x92\x8e" // U+F048E +#define ICON_MDI_SERVER_NETWORK_OUTLINE "\xf3\xb1\xb2\x99" // U+F1C99 +#define ICON_MDI_SERVER_OFF "\xf3\xb0\x92\x8f" // U+F048F +#define ICON_MDI_SERVER_OUTLINE "\xf3\xb1\xb2\x9a" // U+F1C9A +#define ICON_MDI_SERVER_PLUS "\xf3\xb0\x92\x90" // U+F0490 +#define ICON_MDI_SERVER_PLUS_OUTLINE "\xf3\xb1\xb2\x9b" // U+F1C9B +#define ICON_MDI_SERVER_REMOVE "\xf3\xb0\x92\x91" // U+F0491 +#define ICON_MDI_SERVER_SECURITY "\xf3\xb0\x92\x92" // U+F0492 +#define ICON_MDI_SET_ALL "\xf3\xb0\x9d\xb8" // U+F0778 +#define ICON_MDI_SET_CENTER "\xf3\xb0\x9d\xb9" // U+F0779 +#define ICON_MDI_SET_CENTER_RIGHT "\xf3\xb0\x9d\xba" // U+F077A +#define ICON_MDI_SET_LEFT "\xf3\xb0\x9d\xbb" // U+F077B +#define ICON_MDI_SET_LEFT_CENTER "\xf3\xb0\x9d\xbc" // U+F077C +#define ICON_MDI_SET_LEFT_RIGHT "\xf3\xb0\x9d\xbd" // U+F077D +#define ICON_MDI_SET_MERGE "\xf3\xb1\x93\xa0" // U+F14E0 +#define ICON_MDI_SET_NONE "\xf3\xb0\x9d\xbe" // U+F077E +#define ICON_MDI_SET_RIGHT "\xf3\xb0\x9d\xbf" // U+F077F +#define ICON_MDI_SET_SPLIT "\xf3\xb1\x93\xa1" // U+F14E1 +#define ICON_MDI_SET_SQUARE "\xf3\xb1\x91\x9d" // U+F145D +#define ICON_MDI_SET_TOP_BOX "\xf3\xb0\xa6\x9f" // U+F099F +#define ICON_MDI_SETTINGS_HELPER "\xf3\xb0\xa9\xae" // U+F0A6E +#define ICON_MDI_SHAKER "\xf3\xb1\x84\x8e" // U+F110E +#define ICON_MDI_SHAKER_OUTLINE "\xf3\xb1\x84\x8f" // U+F110F +#define ICON_MDI_SHAPE "\xf3\xb0\xa0\xb1" // U+F0831 +#define ICON_MDI_SHAPE_CIRCLE_PLUS "\xf3\xb0\x99\x9d" // U+F065D +#define ICON_MDI_SHAPE_OUTLINE "\xf3\xb0\xa0\xb2" // U+F0832 +#define ICON_MDI_SHAPE_OVAL_PLUS "\xf3\xb1\x87\xba" // U+F11FA +#define ICON_MDI_SHAPE_PLUS "\xf3\xb0\x92\x95" // U+F0495 +#define ICON_MDI_SHAPE_PLUS_OUTLINE "\xf3\xb1\xb1\x8f" // U+F1C4F +#define ICON_MDI_SHAPE_POLYGON_PLUS "\xf3\xb0\x99\x9e" // U+F065E +#define ICON_MDI_SHAPE_RECTANGLE_PLUS "\xf3\xb0\x99\x9f" // U+F065F +#define ICON_MDI_SHAPE_SQUARE_PLUS "\xf3\xb0\x99\xa0" // U+F0660 +#define ICON_MDI_SHAPE_SQUARE_ROUNDED_PLUS "\xf3\xb1\x93\xba" // U+F14FA +#define ICON_MDI_SHARE "\xf3\xb0\x92\x96" // U+F0496 +#define ICON_MDI_SHARE_ALL "\xf3\xb1\x87\xb4" // U+F11F4 +#define ICON_MDI_SHARE_ALL_OUTLINE "\xf3\xb1\x87\xb5" // U+F11F5 +#define ICON_MDI_SHARE_CIRCLE "\xf3\xb1\x86\xad" // U+F11AD +#define ICON_MDI_SHARE_OFF "\xf3\xb0\xbc\xa3" // U+F0F23 +#define ICON_MDI_SHARE_OFF_OUTLINE "\xf3\xb0\xbc\xa4" // U+F0F24 +#define ICON_MDI_SHARE_OUTLINE "\xf3\xb0\xa4\xb2" // U+F0932 +#define ICON_MDI_SHARE_VARIANT "\xf3\xb0\x92\x97" // U+F0497 +#define ICON_MDI_SHARE_VARIANT_OUTLINE "\xf3\xb1\x94\x94" // U+F1514 +#define ICON_MDI_SHARK "\xf3\xb1\xa2\xba" // U+F18BA +#define ICON_MDI_SHARK_FIN "\xf3\xb1\x99\xb3" // U+F1673 +#define ICON_MDI_SHARK_FIN_OUTLINE "\xf3\xb1\x99\xb4" // U+F1674 +#define ICON_MDI_SHARK_OFF "\xf3\xb1\xa2\xbb" // U+F18BB +#define ICON_MDI_SHEEP "\xf3\xb0\xb3\x86" // U+F0CC6 +#define ICON_MDI_SHIELD "\xf3\xb0\x92\x98" // U+F0498 +#define ICON_MDI_SHIELD_ACCOUNT "\xf3\xb0\xa2\x8f" // U+F088F +#define ICON_MDI_SHIELD_ACCOUNT_OUTLINE "\xf3\xb0\xa8\x92" // U+F0A12 +#define ICON_MDI_SHIELD_ACCOUNT_VARIANT "\xf3\xb1\x96\xa7" // U+F15A7 +#define ICON_MDI_SHIELD_ACCOUNT_VARIANT_OUTLINE "\xf3\xb1\x96\xa8" // U+F15A8 +#define ICON_MDI_SHIELD_AIRPLANE "\xf3\xb0\x9a\xbb" // U+F06BB +#define ICON_MDI_SHIELD_AIRPLANE_OUTLINE "\xf3\xb0\xb3\x87" // U+F0CC7 +#define ICON_MDI_SHIELD_ALERT "\xf3\xb0\xbb\x8c" // U+F0ECC +#define ICON_MDI_SHIELD_ALERT_OUTLINE "\xf3\xb0\xbb\x8d" // U+F0ECD +#define ICON_MDI_SHIELD_BUG "\xf3\xb1\x8f\x9a" // U+F13DA +#define ICON_MDI_SHIELD_BUG_OUTLINE "\xf3\xb1\x8f\x9b" // U+F13DB +#define ICON_MDI_SHIELD_CAR "\xf3\xb0\xbe\x83" // U+F0F83 +#define ICON_MDI_SHIELD_CHECK "\xf3\xb0\x95\xa5" // U+F0565 +#define ICON_MDI_SHIELD_CHECK_OUTLINE "\xf3\xb0\xb3\x88" // U+F0CC8 +#define ICON_MDI_SHIELD_CROSS "\xf3\xb0\xb3\x89" // U+F0CC9 +#define ICON_MDI_SHIELD_CROSS_OUTLINE "\xf3\xb0\xb3\x8a" // U+F0CCA +#define ICON_MDI_SHIELD_CROWN "\xf3\xb1\xa2\xbc" // U+F18BC +#define ICON_MDI_SHIELD_CROWN_OUTLINE "\xf3\xb1\xa2\xbd" // U+F18BD +#define ICON_MDI_SHIELD_EDIT "\xf3\xb1\x86\xa0" // U+F11A0 +#define ICON_MDI_SHIELD_EDIT_OUTLINE "\xf3\xb1\x86\xa1" // U+F11A1 +#define ICON_MDI_SHIELD_HALF "\xf3\xb1\x8d\xa0" // U+F1360 +#define ICON_MDI_SHIELD_HALF_FULL "\xf3\xb0\x9e\x80" // U+F0780 +#define ICON_MDI_SHIELD_HOME "\xf3\xb0\x9a\x8a" // U+F068A +#define ICON_MDI_SHIELD_HOME_OUTLINE "\xf3\xb0\xb3\x8b" // U+F0CCB +#define ICON_MDI_SHIELD_KEY "\xf3\xb0\xaf\x84" // U+F0BC4 +#define ICON_MDI_SHIELD_KEY_OUTLINE "\xf3\xb0\xaf\x85" // U+F0BC5 +#define ICON_MDI_SHIELD_LINK_VARIANT "\xf3\xb0\xb4\xb3" // U+F0D33 +#define ICON_MDI_SHIELD_LINK_VARIANT_OUTLINE "\xf3\xb0\xb4\xb4" // U+F0D34 +#define ICON_MDI_SHIELD_LOCK "\xf3\xb0\xa6\x9d" // U+F099D +#define ICON_MDI_SHIELD_LOCK_OPEN "\xf3\xb1\xa6\x9a" // U+F199A +#define ICON_MDI_SHIELD_LOCK_OPEN_OUTLINE "\xf3\xb1\xa6\x9b" // U+F199B +#define ICON_MDI_SHIELD_LOCK_OUTLINE "\xf3\xb0\xb3\x8c" // U+F0CCC +#define ICON_MDI_SHIELD_MOON "\xf3\xb1\xa0\xa8" // U+F1828 +#define ICON_MDI_SHIELD_MOON_OUTLINE "\xf3\xb1\xa0\xa9" // U+F1829 +#define ICON_MDI_SHIELD_OFF "\xf3\xb0\xa6\x9e" // U+F099E +#define ICON_MDI_SHIELD_OFF_OUTLINE "\xf3\xb0\xa6\x9c" // U+F099C +#define ICON_MDI_SHIELD_OUTLINE "\xf3\xb0\x92\x99" // U+F0499 +#define ICON_MDI_SHIELD_PLUS "\xf3\xb0\xab\x9a" // U+F0ADA +#define ICON_MDI_SHIELD_PLUS_OUTLINE "\xf3\xb0\xab\x9b" // U+F0ADB +#define ICON_MDI_SHIELD_REFRESH "\xf3\xb0\x82\xaa" // U+F00AA +#define ICON_MDI_SHIELD_REFRESH_OUTLINE "\xf3\xb0\x87\xa0" // U+F01E0 +#define ICON_MDI_SHIELD_REMOVE "\xf3\xb0\xab\x9c" // U+F0ADC +#define ICON_MDI_SHIELD_REMOVE_OUTLINE "\xf3\xb0\xab\x9d" // U+F0ADD +#define ICON_MDI_SHIELD_SEARCH "\xf3\xb0\xb6\x9a" // U+F0D9A +#define ICON_MDI_SHIELD_STAR "\xf3\xb1\x84\xbb" // U+F113B +#define ICON_MDI_SHIELD_STAR_OUTLINE "\xf3\xb1\x84\xbc" // U+F113C +#define ICON_MDI_SHIELD_SUN "\xf3\xb1\x81\x9d" // U+F105D +#define ICON_MDI_SHIELD_SUN_OUTLINE "\xf3\xb1\x81\x9e" // U+F105E +#define ICON_MDI_SHIELD_SWORD "\xf3\xb1\xa2\xbe" // U+F18BE +#define ICON_MDI_SHIELD_SWORD_OUTLINE "\xf3\xb1\xa2\xbf" // U+F18BF +#define ICON_MDI_SHIELD_SYNC "\xf3\xb1\x86\xa2" // U+F11A2 +#define ICON_MDI_SHIELD_SYNC_OUTLINE "\xf3\xb1\x86\xa3" // U+F11A3 +#define ICON_MDI_SHIMMER "\xf3\xb1\x95\x85" // U+F1545 +#define ICON_MDI_SHIP_WHEEL "\xf3\xb0\xa0\xb3" // U+F0833 +#define ICON_MDI_SHIPPING_PALLET "\xf3\xb1\xa1\x8e" // U+F184E +#define ICON_MDI_SHOE_BALLET "\xf3\xb1\x97\x8a" // U+F15CA +#define ICON_MDI_SHOE_CLEAT "\xf3\xb1\x97\x87" // U+F15C7 +#define ICON_MDI_SHOE_FORMAL "\xf3\xb0\xad\x87" // U+F0B47 +#define ICON_MDI_SHOE_HEEL "\xf3\xb0\xad\x88" // U+F0B48 +#define ICON_MDI_SHOE_PRINT "\xf3\xb0\xb7\xba" // U+F0DFA +#define ICON_MDI_SHOE_SNEAKER "\xf3\xb1\x97\x88" // U+F15C8 +#define ICON_MDI_SHOPPING "\xf3\xb0\x92\x9a" // U+F049A +#define ICON_MDI_SHOPPING_MUSIC "\xf3\xb0\x92\x9b" // U+F049B +#define ICON_MDI_SHOPPING_OUTLINE "\xf3\xb1\x87\x95" // U+F11D5 +#define ICON_MDI_SHOPPING_SEARCH "\xf3\xb0\xbe\x84" // U+F0F84 +#define ICON_MDI_SHOPPING_SEARCH_OUTLINE "\xf3\xb1\xa9\xaf" // U+F1A6F +#define ICON_MDI_SHORE "\xf3\xb1\x93\xb9" // U+F14F9 +#define ICON_MDI_SHOVEL "\xf3\xb0\x9c\x90" // U+F0710 +#define ICON_MDI_SHOVEL_OFF "\xf3\xb0\x9c\x91" // U+F0711 +#define ICON_MDI_SHOWER "\xf3\xb0\xa6\xa0" // U+F09A0 +#define ICON_MDI_SHOWER_HEAD "\xf3\xb0\xa6\xa1" // U+F09A1 +#define ICON_MDI_SHREDDER "\xf3\xb0\x92\x9c" // U+F049C +#define ICON_MDI_SHUFFLE "\xf3\xb0\x92\x9d" // U+F049D +#define ICON_MDI_SHUFFLE_DISABLED "\xf3\xb0\x92\x9e" // U+F049E +#define ICON_MDI_SHUFFLE_VARIANT "\xf3\xb0\x92\x9f" // U+F049F +#define ICON_MDI_SHURIKEN "\xf3\xb1\x8d\xbf" // U+F137F +#define ICON_MDI_SICKLE "\xf3\xb1\xa3\x80" // U+F18C0 +#define ICON_MDI_SIGMA "\xf3\xb0\x92\xa0" // U+F04A0 +#define ICON_MDI_SIGMA_LOWER "\xf3\xb0\x98\xab" // U+F062B +#define ICON_MDI_SIGN_CAUTION "\xf3\xb0\x92\xa1" // U+F04A1 +#define ICON_MDI_SIGN_DIRECTION "\xf3\xb0\x9e\x81" // U+F0781 +#define ICON_MDI_SIGN_DIRECTION_MINUS "\xf3\xb1\x80\x80" // U+F1000 +#define ICON_MDI_SIGN_DIRECTION_PLUS "\xf3\xb0\xbf\x9c" // U+F0FDC +#define ICON_MDI_SIGN_DIRECTION_REMOVE "\xf3\xb0\xbf\x9d" // U+F0FDD +#define ICON_MDI_SIGN_LANGUAGE "\xf3\xb1\xad\x8d" // U+F1B4D +#define ICON_MDI_SIGN_LANGUAGE_OUTLINE "\xf3\xb1\xad\x8e" // U+F1B4E +#define ICON_MDI_SIGN_POLE "\xf3\xb1\x93\xb8" // U+F14F8 +#define ICON_MDI_SIGN_REAL_ESTATE "\xf3\xb1\x84\x98" // U+F1118 +#define ICON_MDI_SIGN_TEXT "\xf3\xb0\x9e\x82" // U+F0782 +#define ICON_MDI_SIGN_YIELD "\xf3\xb1\xae\xaf" // U+F1BAF +#define ICON_MDI_SIGNAL "\xf3\xb0\x92\xa2" // U+F04A2 +#define ICON_MDI_SIGNAL_2G "\xf3\xb0\x9c\x92" // U+F0712 +#define ICON_MDI_SIGNAL_3G "\xf3\xb0\x9c\x93" // U+F0713 +#define ICON_MDI_SIGNAL_4G "\xf3\xb0\x9c\x94" // U+F0714 +#define ICON_MDI_SIGNAL_5G "\xf3\xb0\xa9\xaf" // U+F0A6F +#define ICON_MDI_SIGNAL_CELLULAR_1 "\xf3\xb0\xa2\xbc" // U+F08BC +#define ICON_MDI_SIGNAL_CELLULAR_2 "\xf3\xb0\xa2\xbd" // U+F08BD +#define ICON_MDI_SIGNAL_CELLULAR_3 "\xf3\xb0\xa2\xbe" // U+F08BE +#define ICON_MDI_SIGNAL_CELLULAR_OUTLINE "\xf3\xb0\xa2\xbf" // U+F08BF +#define ICON_MDI_SIGNAL_DISTANCE_VARIANT "\xf3\xb0\xb9\xa4" // U+F0E64 +#define ICON_MDI_SIGNAL_HSPA "\xf3\xb0\x9c\x95" // U+F0715 +#define ICON_MDI_SIGNAL_HSPA_PLUS "\xf3\xb0\x9c\x96" // U+F0716 +#define ICON_MDI_SIGNAL_OFF "\xf3\xb0\x9e\x83" // U+F0783 +#define ICON_MDI_SIGNAL_VARIANT "\xf3\xb0\x98\x8a" // U+F060A +#define ICON_MDI_SIGNATURE "\xf3\xb0\xb7\xbb" // U+F0DFB +#define ICON_MDI_SIGNATURE_FREEHAND "\xf3\xb0\xb7\xbc" // U+F0DFC +#define ICON_MDI_SIGNATURE_IMAGE "\xf3\xb0\xb7\xbd" // U+F0DFD +#define ICON_MDI_SIGNATURE_TEXT "\xf3\xb0\xb7\xbe" // U+F0DFE +#define ICON_MDI_SILO "\xf3\xb1\xae\x9f" // U+F1B9F +#define ICON_MDI_SILO_OUTLINE "\xf3\xb0\xad\x89" // U+F0B49 +#define ICON_MDI_SILVERWARE "\xf3\xb0\x92\xa3" // U+F04A3 +#define ICON_MDI_SILVERWARE_CLEAN "\xf3\xb0\xbf\x9e" // U+F0FDE +#define ICON_MDI_SILVERWARE_FORK "\xf3\xb0\x92\xa4" // U+F04A4 +#define ICON_MDI_SILVERWARE_FORK_KNIFE "\xf3\xb0\xa9\xb0" // U+F0A70 +#define ICON_MDI_SILVERWARE_SPOON "\xf3\xb0\x92\xa5" // U+F04A5 +#define ICON_MDI_SILVERWARE_VARIANT "\xf3\xb0\x92\xa6" // U+F04A6 +#define ICON_MDI_SIM "\xf3\xb0\x92\xa7" // U+F04A7 +#define ICON_MDI_SIM_ALERT "\xf3\xb0\x92\xa8" // U+F04A8 +#define ICON_MDI_SIM_ALERT_OUTLINE "\xf3\xb1\x97\x93" // U+F15D3 +#define ICON_MDI_SIM_OFF "\xf3\xb0\x92\xa9" // U+F04A9 +#define ICON_MDI_SIM_OFF_OUTLINE "\xf3\xb1\x97\x94" // U+F15D4 +#define ICON_MDI_SIM_OUTLINE "\xf3\xb1\x97\x95" // U+F15D5 +#define ICON_MDI_SIMPLE_ICONS "\xf3\xb1\x8c\x9d" // U+F131D +#define ICON_MDI_SINA_WEIBO "\xf3\xb0\xab\x9f" // U+F0ADF +#define ICON_MDI_SINE_WAVE "\xf3\xb0\xa5\x9b" // U+F095B +#define ICON_MDI_SITEMAP "\xf3\xb0\x92\xaa" // U+F04AA +#define ICON_MDI_SITEMAP_OUTLINE "\xf3\xb1\xa6\x9c" // U+F199C +#define ICON_MDI_SIZE_L "\xf3\xb1\x8e\xa6" // U+F13A6 +#define ICON_MDI_SIZE_M "\xf3\xb1\x8e\xa5" // U+F13A5 +#define ICON_MDI_SIZE_S "\xf3\xb1\x8e\xa4" // U+F13A4 +#define ICON_MDI_SIZE_XL "\xf3\xb1\x8e\xa7" // U+F13A7 +#define ICON_MDI_SIZE_XS "\xf3\xb1\x8e\xa3" // U+F13A3 +#define ICON_MDI_SIZE_XXL "\xf3\xb1\x8e\xa8" // U+F13A8 +#define ICON_MDI_SIZE_XXS "\xf3\xb1\x8e\xa2" // U+F13A2 +#define ICON_MDI_SIZE_XXXL "\xf3\xb1\x8e\xa9" // U+F13A9 +#define ICON_MDI_SKATE "\xf3\xb0\xb4\xb5" // U+F0D35 +#define ICON_MDI_SKATE_OFF "\xf3\xb0\x9a\x99" // U+F0699 +#define ICON_MDI_SKATEBOARD "\xf3\xb1\x93\x82" // U+F14C2 +#define ICON_MDI_SKATEBOARDING "\xf3\xb0\x94\x81" // U+F0501 +#define ICON_MDI_SKEW_LESS "\xf3\xb0\xb4\xb6" // U+F0D36 +#define ICON_MDI_SKEW_MORE "\xf3\xb0\xb4\xb7" // U+F0D37 +#define ICON_MDI_SKI "\xf3\xb1\x8c\x84" // U+F1304 +#define ICON_MDI_SKI_CROSS_COUNTRY "\xf3\xb1\x8c\x85" // U+F1305 +#define ICON_MDI_SKI_WATER "\xf3\xb1\x8c\x86" // U+F1306 +#define ICON_MDI_SKIP_BACKWARD "\xf3\xb0\x92\xab" // U+F04AB +#define ICON_MDI_SKIP_BACKWARD_OUTLINE "\xf3\xb0\xbc\xa5" // U+F0F25 +#define ICON_MDI_SKIP_FORWARD "\xf3\xb0\x92\xac" // U+F04AC +#define ICON_MDI_SKIP_FORWARD_OUTLINE "\xf3\xb0\xbc\xa6" // U+F0F26 +#define ICON_MDI_SKIP_NEXT "\xf3\xb0\x92\xad" // U+F04AD +#define ICON_MDI_SKIP_NEXT_CIRCLE "\xf3\xb0\x99\xa1" // U+F0661 +#define ICON_MDI_SKIP_NEXT_CIRCLE_OUTLINE "\xf3\xb0\x99\xa2" // U+F0662 +#define ICON_MDI_SKIP_NEXT_OUTLINE "\xf3\xb0\xbc\xa7" // U+F0F27 +#define ICON_MDI_SKIP_PREVIOUS "\xf3\xb0\x92\xae" // U+F04AE +#define ICON_MDI_SKIP_PREVIOUS_CIRCLE "\xf3\xb0\x99\xa3" // U+F0663 +#define ICON_MDI_SKIP_PREVIOUS_CIRCLE_OUTLINE "\xf3\xb0\x99\xa4" // U+F0664 +#define ICON_MDI_SKIP_PREVIOUS_OUTLINE "\xf3\xb0\xbc\xa8" // U+F0F28 +#define ICON_MDI_SKULL "\xf3\xb0\x9a\x8c" // U+F068C +#define ICON_MDI_SKULL_CROSSBONES "\xf3\xb0\xaf\x86" // U+F0BC6 +#define ICON_MDI_SKULL_CROSSBONES_OUTLINE "\xf3\xb0\xaf\x87" // U+F0BC7 +#define ICON_MDI_SKULL_OUTLINE "\xf3\xb0\xaf\x88" // U+F0BC8 +#define ICON_MDI_SKULL_SCAN "\xf3\xb1\x93\x87" // U+F14C7 +#define ICON_MDI_SKULL_SCAN_OUTLINE "\xf3\xb1\x93\x88" // U+F14C8 +#define ICON_MDI_SKYPE "\xf3\xb0\x92\xaf" // U+F04AF +#define ICON_MDI_SKYPE_BUSINESS "\xf3\xb0\x92\xb0" // U+F04B0 +#define ICON_MDI_SLACK "\xf3\xb0\x92\xb1" // U+F04B1 +#define ICON_MDI_SLASH_FORWARD "\xf3\xb0\xbf\x9f" // U+F0FDF +#define ICON_MDI_SLASH_FORWARD_BOX "\xf3\xb0\xbf\xa0" // U+F0FE0 +#define ICON_MDI_SLEDDING "\xf3\xb0\x90\x9b" // U+F041B +#define ICON_MDI_SLEEP "\xf3\xb0\x92\xb2" // U+F04B2 +#define ICON_MDI_SLEEP_OFF "\xf3\xb0\x92\xb3" // U+F04B3 +#define ICON_MDI_SLIDE "\xf3\xb1\x96\xa5" // U+F15A5 +#define ICON_MDI_SLOPE_DOWNHILL "\xf3\xb0\xb7\xbf" // U+F0DFF +#define ICON_MDI_SLOPE_UPHILL "\xf3\xb0\xb8\x80" // U+F0E00 +#define ICON_MDI_SLOT_MACHINE "\xf3\xb1\x84\x94" // U+F1114 +#define ICON_MDI_SLOT_MACHINE_OUTLINE "\xf3\xb1\x84\x95" // U+F1115 +#define ICON_MDI_SMART_CARD "\xf3\xb1\x82\xbd" // U+F10BD +#define ICON_MDI_SMART_CARD_OFF "\xf3\xb1\xa3\xb7" // U+F18F7 +#define ICON_MDI_SMART_CARD_OFF_OUTLINE "\xf3\xb1\xa3\xb8" // U+F18F8 +#define ICON_MDI_SMART_CARD_OUTLINE "\xf3\xb1\x82\xbe" // U+F10BE +#define ICON_MDI_SMART_CARD_READER "\xf3\xb1\x82\xbf" // U+F10BF +#define ICON_MDI_SMART_CARD_READER_OUTLINE "\xf3\xb1\x83\x80" // U+F10C0 +#define ICON_MDI_SMOG "\xf3\xb0\xa9\xb1" // U+F0A71 +#define ICON_MDI_SMOKE "\xf3\xb1\x9e\x99" // U+F1799 +#define ICON_MDI_SMOKE_DETECTOR "\xf3\xb0\x8e\x92" // U+F0392 +#define ICON_MDI_SMOKE_DETECTOR_ALERT "\xf3\xb1\xa4\xae" // U+F192E +#define ICON_MDI_SMOKE_DETECTOR_ALERT_OUTLINE "\xf3\xb1\xa4\xaf" // U+F192F +#define ICON_MDI_SMOKE_DETECTOR_OFF "\xf3\xb1\xa0\x89" // U+F1809 +#define ICON_MDI_SMOKE_DETECTOR_OFF_OUTLINE "\xf3\xb1\xa0\x8a" // U+F180A +#define ICON_MDI_SMOKE_DETECTOR_OUTLINE "\xf3\xb1\xa0\x88" // U+F1808 +#define ICON_MDI_SMOKE_DETECTOR_VARIANT "\xf3\xb1\xa0\x8b" // U+F180B +#define ICON_MDI_SMOKE_DETECTOR_VARIANT_ALERT "\xf3\xb1\xa4\xb0" // U+F1930 +#define ICON_MDI_SMOKE_DETECTOR_VARIANT_OFF "\xf3\xb1\xa0\x8c" // U+F180C +#define ICON_MDI_SMOKING "\xf3\xb0\x92\xb4" // U+F04B4 +#define ICON_MDI_SMOKING_OFF "\xf3\xb0\x92\xb5" // U+F04B5 +#define ICON_MDI_SMOKING_PIPE "\xf3\xb1\x90\x8d" // U+F140D +#define ICON_MDI_SMOKING_PIPE_OFF "\xf3\xb1\x90\xa8" // U+F1428 +#define ICON_MDI_SNAIL "\xf3\xb1\x99\xb7" // U+F1677 +#define ICON_MDI_SNAKE "\xf3\xb1\x94\x8e" // U+F150E +#define ICON_MDI_SNAPCHAT "\xf3\xb0\x92\xb6" // U+F04B6 +#define ICON_MDI_SNOWBOARD "\xf3\xb1\x8c\x87" // U+F1307 +#define ICON_MDI_SNOWFLAKE "\xf3\xb0\x9c\x97" // U+F0717 +#define ICON_MDI_SNOWFLAKE_ALERT "\xf3\xb0\xbc\xa9" // U+F0F29 +#define ICON_MDI_SNOWFLAKE_CHECK "\xf3\xb1\xa9\xb0" // U+F1A70 +#define ICON_MDI_SNOWFLAKE_MELT "\xf3\xb1\x8b\x8b" // U+F12CB +#define ICON_MDI_SNOWFLAKE_OFF "\xf3\xb1\x93\xa3" // U+F14E3 +#define ICON_MDI_SNOWFLAKE_THERMOMETER "\xf3\xb1\xa9\xb1" // U+F1A71 +#define ICON_MDI_SNOWFLAKE_VARIANT "\xf3\xb0\xbc\xaa" // U+F0F2A +#define ICON_MDI_SNOWMAN "\xf3\xb0\x92\xb7" // U+F04B7 +#define ICON_MDI_SNOWMOBILE "\xf3\xb0\x9b\x9d" // U+F06DD +#define ICON_MDI_SNOWSHOEING "\xf3\xb1\xa9\xb2" // U+F1A72 +#define ICON_MDI_SOCCER "\xf3\xb0\x92\xb8" // U+F04B8 +#define ICON_MDI_SOCCER_FIELD "\xf3\xb0\xa0\xb4" // U+F0834 +#define ICON_MDI_SOCIAL_DISTANCE_2_METERS "\xf3\xb1\x95\xb9" // U+F1579 +#define ICON_MDI_SOCIAL_DISTANCE_6_FEET "\xf3\xb1\x95\xba" // U+F157A +#define ICON_MDI_SOFA "\xf3\xb0\x92\xb9" // U+F04B9 +#define ICON_MDI_SOFA_OUTLINE "\xf3\xb1\x95\xad" // U+F156D +#define ICON_MDI_SOFA_SINGLE "\xf3\xb1\x95\xae" // U+F156E +#define ICON_MDI_SOFA_SINGLE_OUTLINE "\xf3\xb1\x95\xaf" // U+F156F +#define ICON_MDI_SOLAR_PANEL "\xf3\xb0\xb6\x9b" // U+F0D9B +#define ICON_MDI_SOLAR_PANEL_LARGE "\xf3\xb0\xb6\x9c" // U+F0D9C +#define ICON_MDI_SOLAR_POWER "\xf3\xb0\xa9\xb2" // U+F0A72 +#define ICON_MDI_SOLAR_POWER_VARIANT "\xf3\xb1\xa9\xb3" // U+F1A73 +#define ICON_MDI_SOLAR_POWER_VARIANT_OUTLINE "\xf3\xb1\xa9\xb4" // U+F1A74 +#define ICON_MDI_SOLDERING_IRON "\xf3\xb1\x82\x92" // U+F1092 +#define ICON_MDI_SOLID "\xf3\xb0\x9a\x8d" // U+F068D +#define ICON_MDI_SONY_PLAYSTATION "\xf3\xb0\x90\x94" // U+F0414 +#define ICON_MDI_SORT "\xf3\xb0\x92\xba" // U+F04BA +#define ICON_MDI_SORT_ALPHABETICAL_ASCENDING "\xf3\xb0\x96\xbd" // U+F05BD +#define ICON_MDI_SORT_ALPHABETICAL_ASCENDING_VARIANT "\xf3\xb1\x85\x88" // U+F1148 +#define ICON_MDI_SORT_ALPHABETICAL_DESCENDING "\xf3\xb0\x96\xbf" // U+F05BF +#define ICON_MDI_SORT_ALPHABETICAL_DESCENDING_VARIANT "\xf3\xb1\x85\x89" // U+F1149 +#define ICON_MDI_SORT_ALPHABETICAL_VARIANT "\xf3\xb0\x92\xbb" // U+F04BB +#define ICON_MDI_SORT_ASCENDING "\xf3\xb0\x92\xbc" // U+F04BC +#define ICON_MDI_SORT_BOOL_ASCENDING "\xf3\xb1\x8e\x85" // U+F1385 +#define ICON_MDI_SORT_BOOL_ASCENDING_VARIANT "\xf3\xb1\x8e\x86" // U+F1386 +#define ICON_MDI_SORT_BOOL_DESCENDING "\xf3\xb1\x8e\x87" // U+F1387 +#define ICON_MDI_SORT_BOOL_DESCENDING_VARIANT "\xf3\xb1\x8e\x88" // U+F1388 +#define ICON_MDI_SORT_CALENDAR_ASCENDING "\xf3\xb1\x95\x87" // U+F1547 +#define ICON_MDI_SORT_CALENDAR_DESCENDING "\xf3\xb1\x95\x88" // U+F1548 +#define ICON_MDI_SORT_CLOCK_ASCENDING "\xf3\xb1\x95\x89" // U+F1549 +#define ICON_MDI_SORT_CLOCK_ASCENDING_OUTLINE "\xf3\xb1\x95\x8a" // U+F154A +#define ICON_MDI_SORT_CLOCK_DESCENDING "\xf3\xb1\x95\x8b" // U+F154B +#define ICON_MDI_SORT_CLOCK_DESCENDING_OUTLINE "\xf3\xb1\x95\x8c" // U+F154C +#define ICON_MDI_SORT_DESCENDING "\xf3\xb0\x92\xbd" // U+F04BD +#define ICON_MDI_SORT_NUMERIC_ASCENDING "\xf3\xb1\x8e\x89" // U+F1389 +#define ICON_MDI_SORT_NUMERIC_ASCENDING_VARIANT "\xf3\xb0\xa4\x8d" // U+F090D +#define ICON_MDI_SORT_NUMERIC_DESCENDING "\xf3\xb1\x8e\x8a" // U+F138A +#define ICON_MDI_SORT_NUMERIC_DESCENDING_VARIANT "\xf3\xb0\xab\x92" // U+F0AD2 +#define ICON_MDI_SORT_NUMERIC_VARIANT "\xf3\xb0\x92\xbe" // U+F04BE +#define ICON_MDI_SORT_REVERSE_VARIANT "\xf3\xb0\x8c\xbc" // U+F033C +#define ICON_MDI_SORT_VARIANT "\xf3\xb0\x92\xbf" // U+F04BF +#define ICON_MDI_SORT_VARIANT_LOCK "\xf3\xb0\xb3\x8d" // U+F0CCD +#define ICON_MDI_SORT_VARIANT_LOCK_OPEN "\xf3\xb0\xb3\x8e" // U+F0CCE +#define ICON_MDI_SORT_VARIANT_OFF "\xf3\xb1\xaa\xbb" // U+F1ABB +#define ICON_MDI_SORT_VARIANT_REMOVE "\xf3\xb1\x85\x87" // U+F1147 +#define ICON_MDI_SOUNDBAR "\xf3\xb1\x9f\x9b" // U+F17DB +#define ICON_MDI_SOUNDCLOUD "\xf3\xb0\x93\x80" // U+F04C0 +#define ICON_MDI_SOURCE_BRANCH "\xf3\xb0\x98\xac" // U+F062C +#define ICON_MDI_SOURCE_BRANCH_CHECK "\xf3\xb1\x93\x8f" // U+F14CF +#define ICON_MDI_SOURCE_BRANCH_MINUS "\xf3\xb1\x93\x8b" // U+F14CB +#define ICON_MDI_SOURCE_BRANCH_PLUS "\xf3\xb1\x93\x8a" // U+F14CA +#define ICON_MDI_SOURCE_BRANCH_REFRESH "\xf3\xb1\x93\x8d" // U+F14CD +#define ICON_MDI_SOURCE_BRANCH_REMOVE "\xf3\xb1\x93\x8c" // U+F14CC +#define ICON_MDI_SOURCE_BRANCH_SYNC "\xf3\xb1\x93\x8e" // U+F14CE +#define ICON_MDI_SOURCE_COMMIT "\xf3\xb0\x9c\x98" // U+F0718 +#define ICON_MDI_SOURCE_COMMIT_END "\xf3\xb0\x9c\x99" // U+F0719 +#define ICON_MDI_SOURCE_COMMIT_END_LOCAL "\xf3\xb0\x9c\x9a" // U+F071A +#define ICON_MDI_SOURCE_COMMIT_LOCAL "\xf3\xb0\x9c\x9b" // U+F071B +#define ICON_MDI_SOURCE_COMMIT_NEXT_LOCAL "\xf3\xb0\x9c\x9c" // U+F071C +#define ICON_MDI_SOURCE_COMMIT_START "\xf3\xb0\x9c\x9d" // U+F071D +#define ICON_MDI_SOURCE_COMMIT_START_NEXT_LOCAL "\xf3\xb0\x9c\x9e" // U+F071E +#define ICON_MDI_SOURCE_FORK "\xf3\xb0\x93\x81" // U+F04C1 +#define ICON_MDI_SOURCE_MERGE "\xf3\xb0\x98\xad" // U+F062D +#define ICON_MDI_SOURCE_PULL "\xf3\xb0\x93\x82" // U+F04C2 +#define ICON_MDI_SOURCE_REPOSITORY "\xf3\xb0\xb3\x8f" // U+F0CCF +#define ICON_MDI_SOURCE_REPOSITORY_MULTIPLE "\xf3\xb0\xb3\x90" // U+F0CD0 +#define ICON_MDI_SOY_SAUCE "\xf3\xb0\x9f\xae" // U+F07EE +#define ICON_MDI_SOY_SAUCE_OFF "\xf3\xb1\x8f\xbc" // U+F13FC +#define ICON_MDI_SPA "\xf3\xb0\xb3\x91" // U+F0CD1 +#define ICON_MDI_SPA_OUTLINE "\xf3\xb0\xb3\x92" // U+F0CD2 +#define ICON_MDI_SPACE_INVADERS "\xf3\xb0\xaf\x89" // U+F0BC9 +#define ICON_MDI_SPACE_STATION "\xf3\xb1\x8e\x83" // U+F1383 +#define ICON_MDI_SPADE "\xf3\xb0\xb9\xa5" // U+F0E65 +#define ICON_MDI_SPEAKER "\xf3\xb0\x93\x83" // U+F04C3 +#define ICON_MDI_SPEAKER_BLUETOOTH "\xf3\xb0\xa6\xa2" // U+F09A2 +#define ICON_MDI_SPEAKER_MESSAGE "\xf3\xb1\xac\x91" // U+F1B11 +#define ICON_MDI_SPEAKER_MULTIPLE "\xf3\xb0\xb4\xb8" // U+F0D38 +#define ICON_MDI_SPEAKER_OFF "\xf3\xb0\x93\x84" // U+F04C4 +#define ICON_MDI_SPEAKER_PAUSE "\xf3\xb1\xad\xb3" // U+F1B73 +#define ICON_MDI_SPEAKER_PLAY "\xf3\xb1\xad\xb2" // U+F1B72 +#define ICON_MDI_SPEAKER_STOP "\xf3\xb1\xad\xb4" // U+F1B74 +#define ICON_MDI_SPEAKER_WIRELESS "\xf3\xb0\x9c\x9f" // U+F071F +#define ICON_MDI_SPEAR "\xf3\xb1\xa1\x85" // U+F1845 +#define ICON_MDI_SPEEDOMETER "\xf3\xb0\x93\x85" // U+F04C5 +#define ICON_MDI_SPEEDOMETER_MEDIUM "\xf3\xb0\xbe\x85" // U+F0F85 +#define ICON_MDI_SPEEDOMETER_SLOW "\xf3\xb0\xbe\x86" // U+F0F86 +#define ICON_MDI_SPELLCHECK "\xf3\xb0\x93\x86" // U+F04C6 +#define ICON_MDI_SPHERE "\xf3\xb1\xa5\x94" // U+F1954 +#define ICON_MDI_SPHERE_OFF "\xf3\xb1\xa5\x95" // U+F1955 +#define ICON_MDI_SPIDER "\xf3\xb1\x87\xaa" // U+F11EA +#define ICON_MDI_SPIDER_OUTLINE "\xf3\xb1\xb1\xb5" // U+F1C75 +#define ICON_MDI_SPIDER_THREAD "\xf3\xb1\x87\xab" // U+F11EB +#define ICON_MDI_SPIDER_WEB "\xf3\xb0\xaf\x8a" // U+F0BCA +#define ICON_MDI_SPIRIT_LEVEL "\xf3\xb1\x93\xb1" // U+F14F1 +#define ICON_MDI_SPOON_SUGAR "\xf3\xb1\x90\xa9" // U+F1429 +#define ICON_MDI_SPOTIFY "\xf3\xb0\x93\x87" // U+F04C7 +#define ICON_MDI_SPOTLIGHT "\xf3\xb0\x93\x88" // U+F04C8 +#define ICON_MDI_SPOTLIGHT_BEAM "\xf3\xb0\x93\x89" // U+F04C9 +#define ICON_MDI_SPRAY "\xf3\xb0\x99\xa5" // U+F0665 +#define ICON_MDI_SPRAY_BOTTLE "\xf3\xb0\xab\xa0" // U+F0AE0 +#define ICON_MDI_SPRINKLER "\xf3\xb1\x81\x9f" // U+F105F +#define ICON_MDI_SPRINKLER_FIRE "\xf3\xb1\xa6\x9d" // U+F199D +#define ICON_MDI_SPRINKLER_VARIANT "\xf3\xb1\x81\xa0" // U+F1060 +#define ICON_MDI_SPROUT "\xf3\xb0\xb9\xa6" // U+F0E66 +#define ICON_MDI_SPROUT_OUTLINE "\xf3\xb0\xb9\xa7" // U+F0E67 +#define ICON_MDI_SQUARE "\xf3\xb0\x9d\xa4" // U+F0764 +#define ICON_MDI_SQUARE_CIRCLE "\xf3\xb1\x94\x80" // U+F1500 +#define ICON_MDI_SQUARE_CIRCLE_OUTLINE "\xf3\xb1\xb1\x90" // U+F1C50 +#define ICON_MDI_SQUARE_EDIT_OUTLINE "\xf3\xb0\xa4\x8c" // U+F090C +#define ICON_MDI_SQUARE_MEDIUM "\xf3\xb0\xa8\x93" // U+F0A13 +#define ICON_MDI_SQUARE_MEDIUM_OUTLINE "\xf3\xb0\xa8\x94" // U+F0A14 +#define ICON_MDI_SQUARE_OFF "\xf3\xb1\x8b\xae" // U+F12EE +#define ICON_MDI_SQUARE_OFF_OUTLINE "\xf3\xb1\x8b\xaf" // U+F12EF +#define ICON_MDI_SQUARE_OPACITY "\xf3\xb1\xa1\x94" // U+F1854 +#define ICON_MDI_SQUARE_OUTLINE "\xf3\xb0\x9d\xa3" // U+F0763 +#define ICON_MDI_SQUARE_ROOT "\xf3\xb0\x9e\x84" // U+F0784 +#define ICON_MDI_SQUARE_ROOT_BOX "\xf3\xb0\xa6\xa3" // U+F09A3 +#define ICON_MDI_SQUARE_ROUNDED "\xf3\xb1\x93\xbb" // U+F14FB +#define ICON_MDI_SQUARE_ROUNDED_BADGE "\xf3\xb1\xa8\x87" // U+F1A07 +#define ICON_MDI_SQUARE_ROUNDED_BADGE_OUTLINE "\xf3\xb1\xa8\x88" // U+F1A08 +#define ICON_MDI_SQUARE_ROUNDED_OUTLINE "\xf3\xb1\x93\xbc" // U+F14FC +#define ICON_MDI_SQUARE_SMALL "\xf3\xb0\xa8\x95" // U+F0A15 +#define ICON_MDI_SQUARE_WAVE "\xf3\xb1\x91\xbb" // U+F147B +#define ICON_MDI_SQUEEGEE "\xf3\xb0\xab\xa1" // U+F0AE1 +#define ICON_MDI_SSH "\xf3\xb0\xa3\x80" // U+F08C0 +#define ICON_MDI_STACK_EXCHANGE "\xf3\xb0\x98\x8b" // U+F060B +#define ICON_MDI_STACK_OVERFLOW "\xf3\xb0\x93\x8c" // U+F04CC +#define ICON_MDI_STACKPATH "\xf3\xb0\x8d\x99" // U+F0359 +#define ICON_MDI_STADIUM "\xf3\xb0\xbf\xb9" // U+F0FF9 +#define ICON_MDI_STADIUM_OUTLINE "\xf3\xb1\xac\x83" // U+F1B03 +#define ICON_MDI_STADIUM_VARIANT "\xf3\xb0\x9c\xa0" // U+F0720 +#define ICON_MDI_STAIRS "\xf3\xb0\x93\x8d" // U+F04CD +#define ICON_MDI_STAIRS_BOX "\xf3\xb1\x8e\x9e" // U+F139E +#define ICON_MDI_STAIRS_DOWN "\xf3\xb1\x8a\xbe" // U+F12BE +#define ICON_MDI_STAIRS_UP "\xf3\xb1\x8a\xbd" // U+F12BD +#define ICON_MDI_STAMPER "\xf3\xb0\xb4\xb9" // U+F0D39 +#define ICON_MDI_STANDARD_DEFINITION "\xf3\xb0\x9f\xaf" // U+F07EF +#define ICON_MDI_STAR "\xf3\xb0\x93\x8e" // U+F04CE +#define ICON_MDI_STAR_BOX "\xf3\xb0\xa9\xb3" // U+F0A73 +#define ICON_MDI_STAR_BOX_MULTIPLE "\xf3\xb1\x8a\x86" // U+F1286 +#define ICON_MDI_STAR_BOX_MULTIPLE_OUTLINE "\xf3\xb1\x8a\x87" // U+F1287 +#define ICON_MDI_STAR_BOX_OUTLINE "\xf3\xb0\xa9\xb4" // U+F0A74 +#define ICON_MDI_STAR_CHECK "\xf3\xb1\x95\xa6" // U+F1566 +#define ICON_MDI_STAR_CHECK_OUTLINE "\xf3\xb1\x95\xaa" // U+F156A +#define ICON_MDI_STAR_CIRCLE "\xf3\xb0\x93\x8f" // U+F04CF +#define ICON_MDI_STAR_CIRCLE_OUTLINE "\xf3\xb0\xa6\xa4" // U+F09A4 +#define ICON_MDI_STAR_COG "\xf3\xb1\x99\xa8" // U+F1668 +#define ICON_MDI_STAR_COG_OUTLINE "\xf3\xb1\x99\xa9" // U+F1669 +#define ICON_MDI_STAR_CRESCENT "\xf3\xb0\xa5\xb9" // U+F0979 +#define ICON_MDI_STAR_DAVID "\xf3\xb0\xa5\xba" // U+F097A +#define ICON_MDI_STAR_FACE "\xf3\xb0\xa6\xa5" // U+F09A5 +#define ICON_MDI_STAR_FOUR_POINTS "\xf3\xb0\xab\xa2" // U+F0AE2 +#define ICON_MDI_STAR_FOUR_POINTS_BOX "\xf3\xb1\xb1\x91" // U+F1C51 +#define ICON_MDI_STAR_FOUR_POINTS_BOX_OUTLINE "\xf3\xb1\xb1\x92" // U+F1C52 +#define ICON_MDI_STAR_FOUR_POINTS_CIRCLE "\xf3\xb1\xb1\x93" // U+F1C53 +#define ICON_MDI_STAR_FOUR_POINTS_CIRCLE_OUTLINE "\xf3\xb1\xb1\x94" // U+F1C54 +#define ICON_MDI_STAR_FOUR_POINTS_OUTLINE "\xf3\xb0\xab\xa3" // U+F0AE3 +#define ICON_MDI_STAR_FOUR_POINTS_SMALL "\xf3\xb1\xb1\x95" // U+F1C55 +#define ICON_MDI_STAR_HALF "\xf3\xb0\x89\x86" // U+F0246 +#define ICON_MDI_STAR_HALF_FULL "\xf3\xb0\x93\x90" // U+F04D0 +#define ICON_MDI_STAR_MINUS "\xf3\xb1\x95\xa4" // U+F1564 +#define ICON_MDI_STAR_MINUS_OUTLINE "\xf3\xb1\x95\xa8" // U+F1568 +#define ICON_MDI_STAR_OFF "\xf3\xb0\x93\x91" // U+F04D1 +#define ICON_MDI_STAR_OFF_OUTLINE "\xf3\xb1\x95\x9b" // U+F155B +#define ICON_MDI_STAR_OUTLINE "\xf3\xb0\x93\x92" // U+F04D2 +#define ICON_MDI_STAR_PLUS "\xf3\xb1\x95\xa3" // U+F1563 +#define ICON_MDI_STAR_PLUS_OUTLINE "\xf3\xb1\x95\xa7" // U+F1567 +#define ICON_MDI_STAR_REMOVE "\xf3\xb1\x95\xa5" // U+F1565 +#define ICON_MDI_STAR_REMOVE_OUTLINE "\xf3\xb1\x95\xa9" // U+F1569 +#define ICON_MDI_STAR_SETTINGS "\xf3\xb1\x99\xaa" // U+F166A +#define ICON_MDI_STAR_SETTINGS_OUTLINE "\xf3\xb1\x99\xab" // U+F166B +#define ICON_MDI_STAR_SHOOTING "\xf3\xb1\x9d\x81" // U+F1741 +#define ICON_MDI_STAR_SHOOTING_OUTLINE "\xf3\xb1\x9d\x82" // U+F1742 +#define ICON_MDI_STAR_THREE_POINTS "\xf3\xb0\xab\xa4" // U+F0AE4 +#define ICON_MDI_STAR_THREE_POINTS_OUTLINE "\xf3\xb0\xab\xa5" // U+F0AE5 +#define ICON_MDI_STATE_MACHINE "\xf3\xb1\x87\xaf" // U+F11EF +#define ICON_MDI_STEAM "\xf3\xb0\x93\x93" // U+F04D3 +#define ICON_MDI_STEERING "\xf3\xb0\x93\x94" // U+F04D4 +#define ICON_MDI_STEERING_OFF "\xf3\xb0\xa4\x8e" // U+F090E +#define ICON_MDI_STEP_BACKWARD "\xf3\xb0\x93\x95" // U+F04D5 +#define ICON_MDI_STEP_BACKWARD_2 "\xf3\xb0\x93\x96" // U+F04D6 +#define ICON_MDI_STEP_FORWARD "\xf3\xb0\x93\x97" // U+F04D7 +#define ICON_MDI_STEP_FORWARD_2 "\xf3\xb0\x93\x98" // U+F04D8 +#define ICON_MDI_STETHOSCOPE "\xf3\xb0\x93\x99" // U+F04D9 +#define ICON_MDI_STICKER "\xf3\xb1\x8d\xa4" // U+F1364 +#define ICON_MDI_STICKER_ALERT "\xf3\xb1\x8d\xa5" // U+F1365 +#define ICON_MDI_STICKER_ALERT_OUTLINE "\xf3\xb1\x8d\xa6" // U+F1366 +#define ICON_MDI_STICKER_CHECK "\xf3\xb1\x8d\xa7" // U+F1367 +#define ICON_MDI_STICKER_CHECK_OUTLINE "\xf3\xb1\x8d\xa8" // U+F1368 +#define ICON_MDI_STICKER_CIRCLE_OUTLINE "\xf3\xb0\x97\x90" // U+F05D0 +#define ICON_MDI_STICKER_EMOJI "\xf3\xb0\x9e\x85" // U+F0785 +#define ICON_MDI_STICKER_MINUS "\xf3\xb1\x8d\xa9" // U+F1369 +#define ICON_MDI_STICKER_MINUS_OUTLINE "\xf3\xb1\x8d\xaa" // U+F136A +#define ICON_MDI_STICKER_OUTLINE "\xf3\xb1\x8d\xab" // U+F136B +#define ICON_MDI_STICKER_PLUS "\xf3\xb1\x8d\xac" // U+F136C +#define ICON_MDI_STICKER_PLUS_OUTLINE "\xf3\xb1\x8d\xad" // U+F136D +#define ICON_MDI_STICKER_REMOVE "\xf3\xb1\x8d\xae" // U+F136E +#define ICON_MDI_STICKER_REMOVE_OUTLINE "\xf3\xb1\x8d\xaf" // U+F136F +#define ICON_MDI_STICKER_TEXT "\xf3\xb1\x9e\x8e" // U+F178E +#define ICON_MDI_STICKER_TEXT_OUTLINE "\xf3\xb1\x9e\x8f" // U+F178F +#define ICON_MDI_STOCKING "\xf3\xb0\x93\x9a" // U+F04DA +#define ICON_MDI_STOMACH "\xf3\xb1\x82\x93" // U+F1093 +#define ICON_MDI_STOOL "\xf3\xb1\xa5\x9d" // U+F195D +#define ICON_MDI_STOOL_OUTLINE "\xf3\xb1\xa5\x9e" // U+F195E +#define ICON_MDI_STOP "\xf3\xb0\x93\x9b" // U+F04DB +#define ICON_MDI_STOP_CIRCLE "\xf3\xb0\x99\xa6" // U+F0666 +#define ICON_MDI_STOP_CIRCLE_OUTLINE "\xf3\xb0\x99\xa7" // U+F0667 +#define ICON_MDI_STORAGE_TANK "\xf3\xb1\xa9\xb5" // U+F1A75 +#define ICON_MDI_STORAGE_TANK_OUTLINE "\xf3\xb1\xa9\xb6" // U+F1A76 +#define ICON_MDI_STORE "\xf3\xb0\x93\x9c" // U+F04DC +#define ICON_MDI_STORE_24_HOUR "\xf3\xb0\x93\x9d" // U+F04DD +#define ICON_MDI_STORE_ALERT "\xf3\xb1\xa3\x81" // U+F18C1 +#define ICON_MDI_STORE_ALERT_OUTLINE "\xf3\xb1\xa3\x82" // U+F18C2 +#define ICON_MDI_STORE_CHECK "\xf3\xb1\xa3\x83" // U+F18C3 +#define ICON_MDI_STORE_CHECK_OUTLINE "\xf3\xb1\xa3\x84" // U+F18C4 +#define ICON_MDI_STORE_CLOCK "\xf3\xb1\xa3\x85" // U+F18C5 +#define ICON_MDI_STORE_CLOCK_OUTLINE "\xf3\xb1\xa3\x86" // U+F18C6 +#define ICON_MDI_STORE_COG "\xf3\xb1\xa3\x87" // U+F18C7 +#define ICON_MDI_STORE_COG_OUTLINE "\xf3\xb1\xa3\x88" // U+F18C8 +#define ICON_MDI_STORE_EDIT "\xf3\xb1\xa3\x89" // U+F18C9 +#define ICON_MDI_STORE_EDIT_OUTLINE "\xf3\xb1\xa3\x8a" // U+F18CA +#define ICON_MDI_STORE_MARKER "\xf3\xb1\xa3\x8b" // U+F18CB +#define ICON_MDI_STORE_MARKER_OUTLINE "\xf3\xb1\xa3\x8c" // U+F18CC +#define ICON_MDI_STORE_MINUS "\xf3\xb1\x99\x9e" // U+F165E +#define ICON_MDI_STORE_MINUS_OUTLINE "\xf3\xb1\xa3\x8d" // U+F18CD +#define ICON_MDI_STORE_OFF "\xf3\xb1\xa3\x8e" // U+F18CE +#define ICON_MDI_STORE_OFF_OUTLINE "\xf3\xb1\xa3\x8f" // U+F18CF +#define ICON_MDI_STORE_OUTLINE "\xf3\xb1\x8d\xa1" // U+F1361 +#define ICON_MDI_STORE_PLUS "\xf3\xb1\x99\x9f" // U+F165F +#define ICON_MDI_STORE_PLUS_OUTLINE "\xf3\xb1\xa3\x90" // U+F18D0 +#define ICON_MDI_STORE_REMOVE "\xf3\xb1\x99\xa0" // U+F1660 +#define ICON_MDI_STORE_REMOVE_OUTLINE "\xf3\xb1\xa3\x91" // U+F18D1 +#define ICON_MDI_STORE_SEARCH "\xf3\xb1\xa3\x92" // U+F18D2 +#define ICON_MDI_STORE_SEARCH_OUTLINE "\xf3\xb1\xa3\x93" // U+F18D3 +#define ICON_MDI_STORE_SETTINGS "\xf3\xb1\xa3\x94" // U+F18D4 +#define ICON_MDI_STORE_SETTINGS_OUTLINE "\xf3\xb1\xa3\x95" // U+F18D5 +#define ICON_MDI_STOREFRONT "\xf3\xb0\x9f\x87" // U+F07C7 +#define ICON_MDI_STOREFRONT_CHECK "\xf3\xb1\xad\xbd" // U+F1B7D +#define ICON_MDI_STOREFRONT_CHECK_OUTLINE "\xf3\xb1\xad\xbe" // U+F1B7E +#define ICON_MDI_STOREFRONT_EDIT "\xf3\xb1\xad\xbf" // U+F1B7F +#define ICON_MDI_STOREFRONT_EDIT_OUTLINE "\xf3\xb1\xae\x80" // U+F1B80 +#define ICON_MDI_STOREFRONT_MINUS "\xf3\xb1\xae\x83" // U+F1B83 +#define ICON_MDI_STOREFRONT_MINUS_OUTLINE "\xf3\xb1\xae\x84" // U+F1B84 +#define ICON_MDI_STOREFRONT_OUTLINE "\xf3\xb1\x83\x81" // U+F10C1 +#define ICON_MDI_STOREFRONT_PLUS "\xf3\xb1\xae\x81" // U+F1B81 +#define ICON_MDI_STOREFRONT_PLUS_OUTLINE "\xf3\xb1\xae\x82" // U+F1B82 +#define ICON_MDI_STOREFRONT_REMOVE "\xf3\xb1\xae\x85" // U+F1B85 +#define ICON_MDI_STOREFRONT_REMOVE_OUTLINE "\xf3\xb1\xae\x86" // U+F1B86 +#define ICON_MDI_STOVE "\xf3\xb0\x93\x9e" // U+F04DE +#define ICON_MDI_STRATEGY "\xf3\xb1\x87\x96" // U+F11D6 +#define ICON_MDI_STRETCH_TO_PAGE "\xf3\xb0\xbc\xab" // U+F0F2B +#define ICON_MDI_STRETCH_TO_PAGE_OUTLINE "\xf3\xb0\xbc\xac" // U+F0F2C +#define ICON_MDI_STRING_LIGHTS "\xf3\xb1\x8a\xba" // U+F12BA +#define ICON_MDI_STRING_LIGHTS_OFF "\xf3\xb1\x8a\xbb" // U+F12BB +#define ICON_MDI_SUBDIRECTORY_ARROW_LEFT "\xf3\xb0\x98\x8c" // U+F060C +#define ICON_MDI_SUBDIRECTORY_ARROW_RIGHT "\xf3\xb0\x98\x8d" // U+F060D +#define ICON_MDI_SUBMARINE "\xf3\xb1\x95\xac" // U+F156C +#define ICON_MDI_SUBTITLES "\xf3\xb0\xa8\x96" // U+F0A16 +#define ICON_MDI_SUBTITLES_OUTLINE "\xf3\xb0\xa8\x97" // U+F0A17 +#define ICON_MDI_SUBWAY "\xf3\xb0\x9a\xac" // U+F06AC +#define ICON_MDI_SUBWAY_ALERT_VARIANT "\xf3\xb0\xb6\x9d" // U+F0D9D +#define ICON_MDI_SUBWAY_VARIANT "\xf3\xb0\x93\x9f" // U+F04DF +#define ICON_MDI_SUMMIT "\xf3\xb0\x9e\x86" // U+F0786 +#define ICON_MDI_SUN_ANGLE "\xf3\xb1\xac\xa7" // U+F1B27 +#define ICON_MDI_SUN_ANGLE_OUTLINE "\xf3\xb1\xac\xa8" // U+F1B28 +#define ICON_MDI_SUN_CLOCK "\xf3\xb1\xa9\xb7" // U+F1A77 +#define ICON_MDI_SUN_CLOCK_OUTLINE "\xf3\xb1\xa9\xb8" // U+F1A78 +#define ICON_MDI_SUN_COMPASS "\xf3\xb1\xa6\xa5" // U+F19A5 +#define ICON_MDI_SUN_SNOWFLAKE "\xf3\xb1\x9e\x96" // U+F1796 +#define ICON_MDI_SUN_SNOWFLAKE_VARIANT "\xf3\xb1\xa9\xb9" // U+F1A79 +#define ICON_MDI_SUN_THERMOMETER "\xf3\xb1\xa3\x96" // U+F18D6 +#define ICON_MDI_SUN_THERMOMETER_OUTLINE "\xf3\xb1\xa3\x97" // U+F18D7 +#define ICON_MDI_SUN_WIRELESS "\xf3\xb1\x9f\xbe" // U+F17FE +#define ICON_MDI_SUN_WIRELESS_OUTLINE "\xf3\xb1\x9f\xbf" // U+F17FF +#define ICON_MDI_SUNGLASSES "\xf3\xb0\x93\xa0" // U+F04E0 +#define ICON_MDI_SURFING "\xf3\xb1\x9d\x86" // U+F1746 +#define ICON_MDI_SURROUND_SOUND "\xf3\xb0\x97\x85" // U+F05C5 +#define ICON_MDI_SURROUND_SOUND_2_0 "\xf3\xb0\x9f\xb0" // U+F07F0 +#define ICON_MDI_SURROUND_SOUND_2_1 "\xf3\xb1\x9c\xa9" // U+F1729 +#define ICON_MDI_SURROUND_SOUND_3_1 "\xf3\xb0\x9f\xb1" // U+F07F1 +#define ICON_MDI_SURROUND_SOUND_5_1 "\xf3\xb0\x9f\xb2" // U+F07F2 +#define ICON_MDI_SURROUND_SOUND_5_1_2 "\xf3\xb1\x9c\xaa" // U+F172A +#define ICON_MDI_SURROUND_SOUND_7_1 "\xf3\xb0\x9f\xb3" // U+F07F3 +#define ICON_MDI_SVG "\xf3\xb0\x9c\xa1" // U+F0721 +#define ICON_MDI_SWAP_HORIZONTAL "\xf3\xb0\x93\xa1" // U+F04E1 +#define ICON_MDI_SWAP_HORIZONTAL_BOLD "\xf3\xb0\xaf\x8d" // U+F0BCD +#define ICON_MDI_SWAP_HORIZONTAL_CIRCLE "\xf3\xb0\xbf\xa1" // U+F0FE1 +#define ICON_MDI_SWAP_HORIZONTAL_CIRCLE_OUTLINE "\xf3\xb0\xbf\xa2" // U+F0FE2 +#define ICON_MDI_SWAP_HORIZONTAL_VARIANT "\xf3\xb0\xa3\x81" // U+F08C1 +#define ICON_MDI_SWAP_VERTICAL "\xf3\xb0\x93\xa2" // U+F04E2 +#define ICON_MDI_SWAP_VERTICAL_BOLD "\xf3\xb0\xaf\x8e" // U+F0BCE +#define ICON_MDI_SWAP_VERTICAL_CIRCLE "\xf3\xb0\xbf\xa3" // U+F0FE3 +#define ICON_MDI_SWAP_VERTICAL_CIRCLE_OUTLINE "\xf3\xb0\xbf\xa4" // U+F0FE4 +#define ICON_MDI_SWAP_VERTICAL_VARIANT "\xf3\xb0\xa3\x82" // U+F08C2 +#define ICON_MDI_SWIM "\xf3\xb0\x93\xa3" // U+F04E3 +#define ICON_MDI_SWITCH "\xf3\xb0\x93\xa4" // U+F04E4 +#define ICON_MDI_SWORD "\xf3\xb0\x93\xa5" // U+F04E5 +#define ICON_MDI_SWORD_CROSS "\xf3\xb0\x9e\x87" // U+F0787 +#define ICON_MDI_SYLLABARY_HANGUL "\xf3\xb1\x8c\xb3" // U+F1333 +#define ICON_MDI_SYLLABARY_HIRAGANA "\xf3\xb1\x8c\xb4" // U+F1334 +#define ICON_MDI_SYLLABARY_KATAKANA "\xf3\xb1\x8c\xb5" // U+F1335 +#define ICON_MDI_SYLLABARY_KATAKANA_HALFWIDTH "\xf3\xb1\x8c\xb6" // U+F1336 +#define ICON_MDI_SYMBOL "\xf3\xb1\x94\x81" // U+F1501 +#define ICON_MDI_SYMFONY "\xf3\xb0\xab\xa6" // U+F0AE6 +#define ICON_MDI_SYNAGOGUE "\xf3\xb1\xac\x84" // U+F1B04 +#define ICON_MDI_SYNAGOGUE_OUTLINE "\xf3\xb1\xac\x85" // U+F1B05 +#define ICON_MDI_SYNC "\xf3\xb0\x93\xa6" // U+F04E6 +#define ICON_MDI_SYNC_ALERT "\xf3\xb0\x93\xa7" // U+F04E7 +#define ICON_MDI_SYNC_CIRCLE "\xf3\xb1\x8d\xb8" // U+F1378 +#define ICON_MDI_SYNC_OFF "\xf3\xb0\x93\xa8" // U+F04E8 +#define ICON_MDI_TAB "\xf3\xb0\x93\xa9" // U+F04E9 +#define ICON_MDI_TAB_MINUS "\xf3\xb0\xad\x8b" // U+F0B4B +#define ICON_MDI_TAB_PLUS "\xf3\xb0\x9d\x9c" // U+F075C +#define ICON_MDI_TAB_REMOVE "\xf3\xb0\xad\x8c" // U+F0B4C +#define ICON_MDI_TAB_SEARCH "\xf3\xb1\xa6\x9e" // U+F199E +#define ICON_MDI_TAB_UNSELECTED "\xf3\xb0\x93\xaa" // U+F04EA +#define ICON_MDI_TABLE "\xf3\xb0\x93\xab" // U+F04EB +#define ICON_MDI_TABLE_ACCOUNT "\xf3\xb1\x8e\xb9" // U+F13B9 +#define ICON_MDI_TABLE_ALERT "\xf3\xb1\x8e\xba" // U+F13BA +#define ICON_MDI_TABLE_ARROW_DOWN "\xf3\xb1\x8e\xbb" // U+F13BB +#define ICON_MDI_TABLE_ARROW_LEFT "\xf3\xb1\x8e\xbc" // U+F13BC +#define ICON_MDI_TABLE_ARROW_RIGHT "\xf3\xb1\x8e\xbd" // U+F13BD +#define ICON_MDI_TABLE_ARROW_UP "\xf3\xb1\x8e\xbe" // U+F13BE +#define ICON_MDI_TABLE_BORDER "\xf3\xb0\xa8\x98" // U+F0A18 +#define ICON_MDI_TABLE_CANCEL "\xf3\xb1\x8e\xbf" // U+F13BF +#define ICON_MDI_TABLE_CHAIR "\xf3\xb1\x81\xa1" // U+F1061 +#define ICON_MDI_TABLE_CHECK "\xf3\xb1\x8f\x80" // U+F13C0 +#define ICON_MDI_TABLE_CLOCK "\xf3\xb1\x8f\x81" // U+F13C1 +#define ICON_MDI_TABLE_COG "\xf3\xb1\x8f\x82" // U+F13C2 +#define ICON_MDI_TABLE_COLUMN "\xf3\xb0\xa0\xb5" // U+F0835 +#define ICON_MDI_TABLE_COLUMN_PLUS_AFTER "\xf3\xb0\x93\xac" // U+F04EC +#define ICON_MDI_TABLE_COLUMN_PLUS_BEFORE "\xf3\xb0\x93\xad" // U+F04ED +#define ICON_MDI_TABLE_COLUMN_REMOVE "\xf3\xb0\x93\xae" // U+F04EE +#define ICON_MDI_TABLE_COLUMN_WIDTH "\xf3\xb0\x93\xaf" // U+F04EF +#define ICON_MDI_TABLE_EDIT "\xf3\xb0\x93\xb0" // U+F04F0 +#define ICON_MDI_TABLE_EYE "\xf3\xb1\x82\x94" // U+F1094 +#define ICON_MDI_TABLE_EYE_OFF "\xf3\xb1\x8f\x83" // U+F13C3 +#define ICON_MDI_TABLE_FILTER "\xf3\xb1\xae\x8c" // U+F1B8C +#define ICON_MDI_TABLE_FURNITURE "\xf3\xb0\x96\xbc" // U+F05BC +#define ICON_MDI_TABLE_HEADERS_EYE "\xf3\xb1\x88\x9d" // U+F121D +#define ICON_MDI_TABLE_HEADERS_EYE_OFF "\xf3\xb1\x88\x9e" // U+F121E +#define ICON_MDI_TABLE_HEART "\xf3\xb1\x8f\x84" // U+F13C4 +#define ICON_MDI_TABLE_KEY "\xf3\xb1\x8f\x85" // U+F13C5 +#define ICON_MDI_TABLE_LARGE "\xf3\xb0\x93\xb1" // U+F04F1 +#define ICON_MDI_TABLE_LARGE_PLUS "\xf3\xb0\xbe\x87" // U+F0F87 +#define ICON_MDI_TABLE_LARGE_REMOVE "\xf3\xb0\xbe\x88" // U+F0F88 +#define ICON_MDI_TABLE_LOCK "\xf3\xb1\x8f\x86" // U+F13C6 +#define ICON_MDI_TABLE_MERGE_CELLS "\xf3\xb0\xa6\xa6" // U+F09A6 +#define ICON_MDI_TABLE_MINUS "\xf3\xb1\x8f\x87" // U+F13C7 +#define ICON_MDI_TABLE_MULTIPLE "\xf3\xb1\x8f\x88" // U+F13C8 +#define ICON_MDI_TABLE_NETWORK "\xf3\xb1\x8f\x89" // U+F13C9 +#define ICON_MDI_TABLE_OF_CONTENTS "\xf3\xb0\xa0\xb6" // U+F0836 +#define ICON_MDI_TABLE_OFF "\xf3\xb1\x8f\x8a" // U+F13CA +#define ICON_MDI_TABLE_PICNIC "\xf3\xb1\x9d\x83" // U+F1743 +#define ICON_MDI_TABLE_PIVOT "\xf3\xb1\xa0\xbc" // U+F183C +#define ICON_MDI_TABLE_PLUS "\xf3\xb0\xa9\xb5" // U+F0A75 +#define ICON_MDI_TABLE_QUESTION "\xf3\xb1\xac\xa1" // U+F1B21 +#define ICON_MDI_TABLE_REFRESH "\xf3\xb1\x8e\xa0" // U+F13A0 +#define ICON_MDI_TABLE_REMOVE "\xf3\xb0\xa9\xb6" // U+F0A76 +#define ICON_MDI_TABLE_ROW "\xf3\xb0\xa0\xb7" // U+F0837 +#define ICON_MDI_TABLE_ROW_HEIGHT "\xf3\xb0\x93\xb2" // U+F04F2 +#define ICON_MDI_TABLE_ROW_PLUS_AFTER "\xf3\xb0\x93\xb3" // U+F04F3 +#define ICON_MDI_TABLE_ROW_PLUS_BEFORE "\xf3\xb0\x93\xb4" // U+F04F4 +#define ICON_MDI_TABLE_ROW_REMOVE "\xf3\xb0\x93\xb5" // U+F04F5 +#define ICON_MDI_TABLE_SEARCH "\xf3\xb0\xa4\x8f" // U+F090F +#define ICON_MDI_TABLE_SETTINGS "\xf3\xb0\xa0\xb8" // U+F0838 +#define ICON_MDI_TABLE_SPLIT_CELL "\xf3\xb1\x90\xaa" // U+F142A +#define ICON_MDI_TABLE_STAR "\xf3\xb1\x8f\x8b" // U+F13CB +#define ICON_MDI_TABLE_SYNC "\xf3\xb1\x8e\xa1" // U+F13A1 +#define ICON_MDI_TABLE_TENNIS "\xf3\xb0\xb9\xa8" // U+F0E68 +#define ICON_MDI_TABLET "\xf3\xb0\x93\xb6" // U+F04F6 +#define ICON_MDI_TABLET_CELLPHONE "\xf3\xb0\xa6\xa7" // U+F09A7 +#define ICON_MDI_TABLET_DASHBOARD "\xf3\xb0\xbb\x8e" // U+F0ECE +#define ICON_MDI_TACO "\xf3\xb0\x9d\xa2" // U+F0762 +#define ICON_MDI_TAG "\xf3\xb0\x93\xb9" // U+F04F9 +#define ICON_MDI_TAG_ARROW_DOWN "\xf3\xb1\x9c\xab" // U+F172B +#define ICON_MDI_TAG_ARROW_DOWN_OUTLINE "\xf3\xb1\x9c\xac" // U+F172C +#define ICON_MDI_TAG_ARROW_LEFT "\xf3\xb1\x9c\xad" // U+F172D +#define ICON_MDI_TAG_ARROW_LEFT_OUTLINE "\xf3\xb1\x9c\xae" // U+F172E +#define ICON_MDI_TAG_ARROW_RIGHT "\xf3\xb1\x9c\xaf" // U+F172F +#define ICON_MDI_TAG_ARROW_RIGHT_OUTLINE "\xf3\xb1\x9c\xb0" // U+F1730 +#define ICON_MDI_TAG_ARROW_UP "\xf3\xb1\x9c\xb1" // U+F1731 +#define ICON_MDI_TAG_ARROW_UP_OUTLINE "\xf3\xb1\x9c\xb2" // U+F1732 +#define ICON_MDI_TAG_CHECK "\xf3\xb1\xa9\xba" // U+F1A7A +#define ICON_MDI_TAG_CHECK_OUTLINE "\xf3\xb1\xa9\xbb" // U+F1A7B +#define ICON_MDI_TAG_EDIT "\xf3\xb1\xb2\x9c" // U+F1C9C +#define ICON_MDI_TAG_EDIT_OUTLINE "\xf3\xb1\xb2\x9d" // U+F1C9D +#define ICON_MDI_TAG_FACES "\xf3\xb0\x93\xba" // U+F04FA +#define ICON_MDI_TAG_HEART "\xf3\xb0\x9a\x8b" // U+F068B +#define ICON_MDI_TAG_HEART_OUTLINE "\xf3\xb0\xaf\x8f" // U+F0BCF +#define ICON_MDI_TAG_HIDDEN "\xf3\xb1\xb1\xb6" // U+F1C76 +#define ICON_MDI_TAG_MINUS "\xf3\xb0\xa4\x90" // U+F0910 +#define ICON_MDI_TAG_MINUS_OUTLINE "\xf3\xb1\x88\x9f" // U+F121F +#define ICON_MDI_TAG_MULTIPLE "\xf3\xb0\x93\xbb" // U+F04FB +#define ICON_MDI_TAG_MULTIPLE_OUTLINE "\xf3\xb1\x8b\xb7" // U+F12F7 +#define ICON_MDI_TAG_OFF "\xf3\xb1\x88\xa0" // U+F1220 +#define ICON_MDI_TAG_OFF_OUTLINE "\xf3\xb1\x88\xa1" // U+F1221 +#define ICON_MDI_TAG_OUTLINE "\xf3\xb0\x93\xbc" // U+F04FC +#define ICON_MDI_TAG_PLUS "\xf3\xb0\x9c\xa2" // U+F0722 +#define ICON_MDI_TAG_PLUS_OUTLINE "\xf3\xb1\x88\xa2" // U+F1222 +#define ICON_MDI_TAG_REMOVE "\xf3\xb0\x9c\xa3" // U+F0723 +#define ICON_MDI_TAG_REMOVE_OUTLINE "\xf3\xb1\x88\xa3" // U+F1223 +#define ICON_MDI_TAG_SEARCH "\xf3\xb1\xa4\x87" // U+F1907 +#define ICON_MDI_TAG_SEARCH_OUTLINE "\xf3\xb1\xa4\x88" // U+F1908 +#define ICON_MDI_TAG_TEXT "\xf3\xb1\x88\xa4" // U+F1224 +#define ICON_MDI_TAG_TEXT_OUTLINE "\xf3\xb0\x93\xbd" // U+F04FD +#define ICON_MDI_TAILWIND "\xf3\xb1\x8f\xbf" // U+F13FF +#define ICON_MDI_TALLY_MARK_1 "\xf3\xb1\xaa\xbc" // U+F1ABC +#define ICON_MDI_TALLY_MARK_2 "\xf3\xb1\xaa\xbd" // U+F1ABD +#define ICON_MDI_TALLY_MARK_3 "\xf3\xb1\xaa\xbe" // U+F1ABE +#define ICON_MDI_TALLY_MARK_4 "\xf3\xb1\xaa\xbf" // U+F1ABF +#define ICON_MDI_TALLY_MARK_5 "\xf3\xb1\xab\x80" // U+F1AC0 +#define ICON_MDI_TANGRAM "\xf3\xb0\x93\xb8" // U+F04F8 +#define ICON_MDI_TANK "\xf3\xb0\xb4\xba" // U+F0D3A +#define ICON_MDI_TANKER_TRUCK "\xf3\xb0\xbf\xa5" // U+F0FE5 +#define ICON_MDI_TAPE_DRIVE "\xf3\xb1\x9b\x9f" // U+F16DF +#define ICON_MDI_TAPE_MEASURE "\xf3\xb0\xad\x8d" // U+F0B4D +#define ICON_MDI_TARGET "\xf3\xb0\x93\xbe" // U+F04FE +#define ICON_MDI_TARGET_ACCOUNT "\xf3\xb0\xaf\x90" // U+F0BD0 +#define ICON_MDI_TARGET_VARIANT "\xf3\xb0\xa9\xb7" // U+F0A77 +#define ICON_MDI_TAXI "\xf3\xb0\x93\xbf" // U+F04FF +#define ICON_MDI_TEA "\xf3\xb0\xb6\x9e" // U+F0D9E +#define ICON_MDI_TEA_OUTLINE "\xf3\xb0\xb6\x9f" // U+F0D9F +#define ICON_MDI_TEAMVIEWER "\xf3\xb0\x94\x80" // U+F0500 +#define ICON_MDI_TEDDY_BEAR "\xf3\xb1\xa3\xbb" // U+F18FB +#define ICON_MDI_TELESCOPE "\xf3\xb0\xad\x8e" // U+F0B4E +#define ICON_MDI_TELEVISION "\xf3\xb0\x94\x82" // U+F0502 +#define ICON_MDI_TELEVISION_AMBIENT_LIGHT "\xf3\xb1\x8d\x96" // U+F1356 +#define ICON_MDI_TELEVISION_BOX "\xf3\xb0\xa0\xb9" // U+F0839 +#define ICON_MDI_TELEVISION_CLASSIC "\xf3\xb0\x9f\xb4" // U+F07F4 +#define ICON_MDI_TELEVISION_CLASSIC_OFF "\xf3\xb0\xa0\xba" // U+F083A +#define ICON_MDI_TELEVISION_GUIDE "\xf3\xb0\x94\x83" // U+F0503 +#define ICON_MDI_TELEVISION_OFF "\xf3\xb0\xa0\xbb" // U+F083B +#define ICON_MDI_TELEVISION_PAUSE "\xf3\xb0\xbe\x89" // U+F0F89 +#define ICON_MDI_TELEVISION_PLAY "\xf3\xb0\xbb\x8f" // U+F0ECF +#define ICON_MDI_TELEVISION_SHIMMER "\xf3\xb1\x84\x90" // U+F1110 +#define ICON_MDI_TELEVISION_SPEAKER "\xf3\xb1\xac\x9b" // U+F1B1B +#define ICON_MDI_TELEVISION_SPEAKER_OFF "\xf3\xb1\xac\x9c" // U+F1B1C +#define ICON_MDI_TELEVISION_STOP "\xf3\xb0\xbe\x8a" // U+F0F8A +#define ICON_MDI_TEMPERATURE_CELSIUS "\xf3\xb0\x94\x84" // U+F0504 +#define ICON_MDI_TEMPERATURE_FAHRENHEIT "\xf3\xb0\x94\x85" // U+F0505 +#define ICON_MDI_TEMPERATURE_KELVIN "\xf3\xb0\x94\x86" // U+F0506 +#define ICON_MDI_TEMPLE_BUDDHIST "\xf3\xb1\xac\x86" // U+F1B06 +#define ICON_MDI_TEMPLE_BUDDHIST_OUTLINE "\xf3\xb1\xac\x87" // U+F1B07 +#define ICON_MDI_TEMPLE_HINDU "\xf3\xb1\xac\x88" // U+F1B08 +#define ICON_MDI_TEMPLE_HINDU_OUTLINE "\xf3\xb1\xac\x89" // U+F1B09 +#define ICON_MDI_TENNIS "\xf3\xb0\xb6\xa0" // U+F0DA0 +#define ICON_MDI_TENNIS_BALL "\xf3\xb0\x94\x87" // U+F0507 +#define ICON_MDI_TENNIS_BALL_OUTLINE "\xf3\xb1\xb1\x9f" // U+F1C5F +#define ICON_MDI_TENT "\xf3\xb0\x94\x88" // U+F0508 +#define ICON_MDI_TERRAFORM "\xf3\xb1\x81\xa2" // U+F1062 +#define ICON_MDI_TERRAIN "\xf3\xb0\x94\x89" // U+F0509 +#define ICON_MDI_TEST_TUBE "\xf3\xb0\x99\xa8" // U+F0668 +#define ICON_MDI_TEST_TUBE_EMPTY "\xf3\xb0\xa4\x91" // U+F0911 +#define ICON_MDI_TEST_TUBE_OFF "\xf3\xb0\xa4\x92" // U+F0912 +#define ICON_MDI_TEXT "\xf3\xb0\xa6\xa8" // U+F09A8 +#define ICON_MDI_TEXT_ACCOUNT "\xf3\xb1\x95\xb0" // U+F1570 +#define ICON_MDI_TEXT_BOX "\xf3\xb0\x88\x9a" // U+F021A +#define ICON_MDI_TEXT_BOX_CHECK "\xf3\xb0\xba\xa6" // U+F0EA6 +#define ICON_MDI_TEXT_BOX_CHECK_OUTLINE "\xf3\xb0\xba\xa7" // U+F0EA7 +#define ICON_MDI_TEXT_BOX_EDIT "\xf3\xb1\xa9\xbc" // U+F1A7C +#define ICON_MDI_TEXT_BOX_EDIT_OUTLINE "\xf3\xb1\xa9\xbd" // U+F1A7D +#define ICON_MDI_TEXT_BOX_MINUS "\xf3\xb0\xba\xa8" // U+F0EA8 +#define ICON_MDI_TEXT_BOX_MINUS_OUTLINE "\xf3\xb0\xba\xa9" // U+F0EA9 +#define ICON_MDI_TEXT_BOX_MULTIPLE "\xf3\xb0\xaa\xb7" // U+F0AB7 +#define ICON_MDI_TEXT_BOX_MULTIPLE_OUTLINE "\xf3\xb0\xaa\xb8" // U+F0AB8 +#define ICON_MDI_TEXT_BOX_OUTLINE "\xf3\xb0\xa7\xad" // U+F09ED +#define ICON_MDI_TEXT_BOX_PLUS "\xf3\xb0\xba\xaa" // U+F0EAA +#define ICON_MDI_TEXT_BOX_PLUS_OUTLINE "\xf3\xb0\xba\xab" // U+F0EAB +#define ICON_MDI_TEXT_BOX_REMOVE "\xf3\xb0\xba\xac" // U+F0EAC +#define ICON_MDI_TEXT_BOX_REMOVE_OUTLINE "\xf3\xb0\xba\xad" // U+F0EAD +#define ICON_MDI_TEXT_BOX_SEARCH "\xf3\xb0\xba\xae" // U+F0EAE +#define ICON_MDI_TEXT_BOX_SEARCH_OUTLINE "\xf3\xb0\xba\xaf" // U+F0EAF +#define ICON_MDI_TEXT_LONG "\xf3\xb0\xa6\xaa" // U+F09AA +#define ICON_MDI_TEXT_RECOGNITION "\xf3\xb1\x84\xbd" // U+F113D +#define ICON_MDI_TEXT_SEARCH "\xf3\xb1\x8e\xb8" // U+F13B8 +#define ICON_MDI_TEXT_SEARCH_VARIANT "\xf3\xb1\xa9\xbe" // U+F1A7E +#define ICON_MDI_TEXT_SHADOW "\xf3\xb0\x99\xa9" // U+F0669 +#define ICON_MDI_TEXT_SHORT "\xf3\xb0\xa6\xa9" // U+F09A9 +#define ICON_MDI_TEXTURE "\xf3\xb0\x94\x8c" // U+F050C +#define ICON_MDI_TEXTURE_BOX "\xf3\xb0\xbf\xa6" // U+F0FE6 +#define ICON_MDI_THEATER "\xf3\xb0\x94\x8d" // U+F050D +#define ICON_MDI_THEME_LIGHT_DARK "\xf3\xb0\x94\x8e" // U+F050E +#define ICON_MDI_THERMOMETER "\xf3\xb0\x94\x8f" // U+F050F +#define ICON_MDI_THERMOMETER_ALERT "\xf3\xb0\xb8\x81" // U+F0E01 +#define ICON_MDI_THERMOMETER_AUTO "\xf3\xb1\xac\x8f" // U+F1B0F +#define ICON_MDI_THERMOMETER_BLUETOOTH "\xf3\xb1\xa2\x95" // U+F1895 +#define ICON_MDI_THERMOMETER_CHECK "\xf3\xb1\xa9\xbf" // U+F1A7F +#define ICON_MDI_THERMOMETER_CHEVRON_DOWN "\xf3\xb0\xb8\x82" // U+F0E02 +#define ICON_MDI_THERMOMETER_CHEVRON_UP "\xf3\xb0\xb8\x83" // U+F0E03 +#define ICON_MDI_THERMOMETER_HIGH "\xf3\xb1\x83\x82" // U+F10C2 +#define ICON_MDI_THERMOMETER_LINES "\xf3\xb0\x94\x90" // U+F0510 +#define ICON_MDI_THERMOMETER_LOW "\xf3\xb1\x83\x83" // U+F10C3 +#define ICON_MDI_THERMOMETER_MINUS "\xf3\xb0\xb8\x84" // U+F0E04 +#define ICON_MDI_THERMOMETER_OFF "\xf3\xb1\x94\xb1" // U+F1531 +#define ICON_MDI_THERMOMETER_PLUS "\xf3\xb0\xb8\x85" // U+F0E05 +#define ICON_MDI_THERMOMETER_PROBE "\xf3\xb1\xac\xab" // U+F1B2B +#define ICON_MDI_THERMOMETER_PROBE_OFF "\xf3\xb1\xac\xac" // U+F1B2C +#define ICON_MDI_THERMOMETER_WATER "\xf3\xb1\xaa\x80" // U+F1A80 +#define ICON_MDI_THERMOSTAT "\xf3\xb0\x8e\x93" // U+F0393 +#define ICON_MDI_THERMOSTAT_AUTO "\xf3\xb1\xac\x97" // U+F1B17 +#define ICON_MDI_THERMOSTAT_BOX "\xf3\xb0\xa2\x91" // U+F0891 +#define ICON_MDI_THERMOSTAT_BOX_AUTO "\xf3\xb1\xac\x98" // U+F1B18 +#define ICON_MDI_THERMOSTAT_COG "\xf3\xb1\xb2\x80" // U+F1C80 +#define ICON_MDI_THOUGHT_BUBBLE "\xf3\xb0\x9f\xb6" // U+F07F6 +#define ICON_MDI_THOUGHT_BUBBLE_OUTLINE "\xf3\xb0\x9f\xb7" // U+F07F7 +#define ICON_MDI_THUMB_DOWN "\xf3\xb0\x94\x91" // U+F0511 +#define ICON_MDI_THUMB_DOWN_OUTLINE "\xf3\xb0\x94\x92" // U+F0512 +#define ICON_MDI_THUMB_UP "\xf3\xb0\x94\x93" // U+F0513 +#define ICON_MDI_THUMB_UP_OUTLINE "\xf3\xb0\x94\x94" // U+F0514 +#define ICON_MDI_THUMBS_UP_DOWN "\xf3\xb0\x94\x95" // U+F0515 +#define ICON_MDI_THUMBS_UP_DOWN_OUTLINE "\xf3\xb1\xa4\x94" // U+F1914 +#define ICON_MDI_TICKET "\xf3\xb0\x94\x96" // U+F0516 +#define ICON_MDI_TICKET_ACCOUNT "\xf3\xb0\x94\x97" // U+F0517 +#define ICON_MDI_TICKET_CONFIRMATION "\xf3\xb0\x94\x98" // U+F0518 +#define ICON_MDI_TICKET_CONFIRMATION_OUTLINE "\xf3\xb1\x8e\xaa" // U+F13AA +#define ICON_MDI_TICKET_OUTLINE "\xf3\xb0\xa4\x93" // U+F0913 +#define ICON_MDI_TICKET_PERCENT "\xf3\xb0\x9c\xa4" // U+F0724 +#define ICON_MDI_TICKET_PERCENT_OUTLINE "\xf3\xb1\x90\xab" // U+F142B +#define ICON_MDI_TIE "\xf3\xb0\x94\x99" // U+F0519 +#define ICON_MDI_TILDE "\xf3\xb0\x9c\xa5" // U+F0725 +#define ICON_MDI_TILDE_OFF "\xf3\xb1\xa3\xb3" // U+F18F3 +#define ICON_MDI_TIMELAPSE "\xf3\xb0\x94\x9a" // U+F051A +#define ICON_MDI_TIMELINE "\xf3\xb0\xaf\x91" // U+F0BD1 +#define ICON_MDI_TIMELINE_ALERT "\xf3\xb0\xbe\x95" // U+F0F95 +#define ICON_MDI_TIMELINE_ALERT_OUTLINE "\xf3\xb0\xbe\x98" // U+F0F98 +#define ICON_MDI_TIMELINE_CHECK "\xf3\xb1\x94\xb2" // U+F1532 +#define ICON_MDI_TIMELINE_CHECK_OUTLINE "\xf3\xb1\x94\xb3" // U+F1533 +#define ICON_MDI_TIMELINE_CLOCK "\xf3\xb1\x87\xbb" // U+F11FB +#define ICON_MDI_TIMELINE_CLOCK_OUTLINE "\xf3\xb1\x87\xbc" // U+F11FC +#define ICON_MDI_TIMELINE_MINUS "\xf3\xb1\x94\xb4" // U+F1534 +#define ICON_MDI_TIMELINE_MINUS_OUTLINE "\xf3\xb1\x94\xb5" // U+F1535 +#define ICON_MDI_TIMELINE_OUTLINE "\xf3\xb0\xaf\x92" // U+F0BD2 +#define ICON_MDI_TIMELINE_PLUS "\xf3\xb0\xbe\x96" // U+F0F96 +#define ICON_MDI_TIMELINE_PLUS_OUTLINE "\xf3\xb0\xbe\x97" // U+F0F97 +#define ICON_MDI_TIMELINE_QUESTION "\xf3\xb0\xbe\x99" // U+F0F99 +#define ICON_MDI_TIMELINE_QUESTION_OUTLINE "\xf3\xb0\xbe\x9a" // U+F0F9A +#define ICON_MDI_TIMELINE_REMOVE "\xf3\xb1\x94\xb6" // U+F1536 +#define ICON_MDI_TIMELINE_REMOVE_OUTLINE "\xf3\xb1\x94\xb7" // U+F1537 +#define ICON_MDI_TIMELINE_TEXT "\xf3\xb0\xaf\x93" // U+F0BD3 +#define ICON_MDI_TIMELINE_TEXT_OUTLINE "\xf3\xb0\xaf\x94" // U+F0BD4 +#define ICON_MDI_TIMER "\xf3\xb1\x8e\xab" // U+F13AB +#define ICON_MDI_TIMER_10 "\xf3\xb0\x94\x9c" // U+F051C +#define ICON_MDI_TIMER_3 "\xf3\xb0\x94\x9d" // U+F051D +#define ICON_MDI_TIMER_ALERT "\xf3\xb1\xab\x8c" // U+F1ACC +#define ICON_MDI_TIMER_ALERT_OUTLINE "\xf3\xb1\xab\x8d" // U+F1ACD +#define ICON_MDI_TIMER_CANCEL "\xf3\xb1\xab\x8e" // U+F1ACE +#define ICON_MDI_TIMER_CANCEL_OUTLINE "\xf3\xb1\xab\x8f" // U+F1ACF +#define ICON_MDI_TIMER_CHECK "\xf3\xb1\xab\x90" // U+F1AD0 +#define ICON_MDI_TIMER_CHECK_OUTLINE "\xf3\xb1\xab\x91" // U+F1AD1 +#define ICON_MDI_TIMER_COG "\xf3\xb1\xa4\xa5" // U+F1925 +#define ICON_MDI_TIMER_COG_OUTLINE "\xf3\xb1\xa4\xa6" // U+F1926 +#define ICON_MDI_TIMER_EDIT "\xf3\xb1\xab\x92" // U+F1AD2 +#define ICON_MDI_TIMER_EDIT_OUTLINE "\xf3\xb1\xab\x93" // U+F1AD3 +#define ICON_MDI_TIMER_LOCK "\xf3\xb1\xab\x94" // U+F1AD4 +#define ICON_MDI_TIMER_LOCK_OPEN "\xf3\xb1\xab\x95" // U+F1AD5 +#define ICON_MDI_TIMER_LOCK_OPEN_OUTLINE "\xf3\xb1\xab\x96" // U+F1AD6 +#define ICON_MDI_TIMER_LOCK_OUTLINE "\xf3\xb1\xab\x97" // U+F1AD7 +#define ICON_MDI_TIMER_MARKER "\xf3\xb1\xab\x98" // U+F1AD8 +#define ICON_MDI_TIMER_MARKER_OUTLINE "\xf3\xb1\xab\x99" // U+F1AD9 +#define ICON_MDI_TIMER_MINUS "\xf3\xb1\xab\x9a" // U+F1ADA +#define ICON_MDI_TIMER_MINUS_OUTLINE "\xf3\xb1\xab\x9b" // U+F1ADB +#define ICON_MDI_TIMER_MUSIC "\xf3\xb1\xab\x9c" // U+F1ADC +#define ICON_MDI_TIMER_MUSIC_OUTLINE "\xf3\xb1\xab\x9d" // U+F1ADD +#define ICON_MDI_TIMER_OFF "\xf3\xb1\x8e\xac" // U+F13AC +#define ICON_MDI_TIMER_OFF_OUTLINE "\xf3\xb0\x94\x9e" // U+F051E +#define ICON_MDI_TIMER_OUTLINE "\xf3\xb0\x94\x9b" // U+F051B +#define ICON_MDI_TIMER_PAUSE "\xf3\xb1\xab\x9e" // U+F1ADE +#define ICON_MDI_TIMER_PAUSE_OUTLINE "\xf3\xb1\xab\x9f" // U+F1ADF +#define ICON_MDI_TIMER_PLAY "\xf3\xb1\xab\xa0" // U+F1AE0 +#define ICON_MDI_TIMER_PLAY_OUTLINE "\xf3\xb1\xab\xa1" // U+F1AE1 +#define ICON_MDI_TIMER_PLUS "\xf3\xb1\xab\xa2" // U+F1AE2 +#define ICON_MDI_TIMER_PLUS_OUTLINE "\xf3\xb1\xab\xa3" // U+F1AE3 +#define ICON_MDI_TIMER_REFRESH "\xf3\xb1\xab\xa4" // U+F1AE4 +#define ICON_MDI_TIMER_REFRESH_OUTLINE "\xf3\xb1\xab\xa5" // U+F1AE5 +#define ICON_MDI_TIMER_REMOVE "\xf3\xb1\xab\xa6" // U+F1AE6 +#define ICON_MDI_TIMER_REMOVE_OUTLINE "\xf3\xb1\xab\xa7" // U+F1AE7 +#define ICON_MDI_TIMER_SAND "\xf3\xb0\x94\x9f" // U+F051F +#define ICON_MDI_TIMER_SAND_COMPLETE "\xf3\xb1\xa6\x9f" // U+F199F +#define ICON_MDI_TIMER_SAND_EMPTY "\xf3\xb0\x9a\xad" // U+F06AD +#define ICON_MDI_TIMER_SAND_FULL "\xf3\xb0\x9e\x8c" // U+F078C +#define ICON_MDI_TIMER_SAND_PAUSED "\xf3\xb1\xa6\xa0" // U+F19A0 +#define ICON_MDI_TIMER_SETTINGS "\xf3\xb1\xa4\xa3" // U+F1923 +#define ICON_MDI_TIMER_SETTINGS_OUTLINE "\xf3\xb1\xa4\xa4" // U+F1924 +#define ICON_MDI_TIMER_STAR "\xf3\xb1\xab\xa8" // U+F1AE8 +#define ICON_MDI_TIMER_STAR_OUTLINE "\xf3\xb1\xab\xa9" // U+F1AE9 +#define ICON_MDI_TIMER_STOP "\xf3\xb1\xab\xaa" // U+F1AEA +#define ICON_MDI_TIMER_STOP_OUTLINE "\xf3\xb1\xab\xab" // U+F1AEB +#define ICON_MDI_TIMER_SYNC "\xf3\xb1\xab\xac" // U+F1AEC +#define ICON_MDI_TIMER_SYNC_OUTLINE "\xf3\xb1\xab\xad" // U+F1AED +#define ICON_MDI_TIMETABLE "\xf3\xb0\x94\xa0" // U+F0520 +#define ICON_MDI_TIRE "\xf3\xb1\xa2\x96" // U+F1896 +#define ICON_MDI_TOASTER "\xf3\xb1\x81\xa3" // U+F1063 +#define ICON_MDI_TOASTER_OFF "\xf3\xb1\x86\xb7" // U+F11B7 +#define ICON_MDI_TOASTER_OVEN "\xf3\xb0\xb3\x93" // U+F0CD3 +#define ICON_MDI_TOGGLE_SWITCH "\xf3\xb0\x94\xa1" // U+F0521 +#define ICON_MDI_TOGGLE_SWITCH_OFF "\xf3\xb0\x94\xa2" // U+F0522 +#define ICON_MDI_TOGGLE_SWITCH_OFF_OUTLINE "\xf3\xb0\xa8\x99" // U+F0A19 +#define ICON_MDI_TOGGLE_SWITCH_OUTLINE "\xf3\xb0\xa8\x9a" // U+F0A1A +#define ICON_MDI_TOGGLE_SWITCH_VARIANT "\xf3\xb1\xa8\xa5" // U+F1A25 +#define ICON_MDI_TOGGLE_SWITCH_VARIANT_OFF "\xf3\xb1\xa8\xa6" // U+F1A26 +#define ICON_MDI_TOILET "\xf3\xb0\xa6\xab" // U+F09AB +#define ICON_MDI_TOOLBOX "\xf3\xb0\xa6\xac" // U+F09AC +#define ICON_MDI_TOOLBOX_OUTLINE "\xf3\xb0\xa6\xad" // U+F09AD +#define ICON_MDI_TOOLS "\xf3\xb1\x81\xa4" // U+F1064 +#define ICON_MDI_TOOLTIP "\xf3\xb0\x94\xa3" // U+F0523 +#define ICON_MDI_TOOLTIP_ACCOUNT "\xf3\xb0\x80\x8c" // U+F000C +#define ICON_MDI_TOOLTIP_CELLPHONE "\xf3\xb1\xa0\xbb" // U+F183B +#define ICON_MDI_TOOLTIP_CHECK "\xf3\xb1\x95\x9c" // U+F155C +#define ICON_MDI_TOOLTIP_CHECK_OUTLINE "\xf3\xb1\x95\x9d" // U+F155D +#define ICON_MDI_TOOLTIP_EDIT "\xf3\xb0\x94\xa4" // U+F0524 +#define ICON_MDI_TOOLTIP_EDIT_OUTLINE "\xf3\xb1\x8b\x85" // U+F12C5 +#define ICON_MDI_TOOLTIP_IMAGE "\xf3\xb0\x94\xa5" // U+F0525 +#define ICON_MDI_TOOLTIP_IMAGE_OUTLINE "\xf3\xb0\xaf\x95" // U+F0BD5 +#define ICON_MDI_TOOLTIP_MINUS "\xf3\xb1\x95\x9e" // U+F155E +#define ICON_MDI_TOOLTIP_MINUS_OUTLINE "\xf3\xb1\x95\x9f" // U+F155F +#define ICON_MDI_TOOLTIP_OUTLINE "\xf3\xb0\x94\xa6" // U+F0526 +#define ICON_MDI_TOOLTIP_PLUS "\xf3\xb0\xaf\x96" // U+F0BD6 +#define ICON_MDI_TOOLTIP_PLUS_OUTLINE "\xf3\xb0\x94\xa7" // U+F0527 +#define ICON_MDI_TOOLTIP_QUESTION "\xf3\xb1\xae\xba" // U+F1BBA +#define ICON_MDI_TOOLTIP_QUESTION_OUTLINE "\xf3\xb1\xae\xbb" // U+F1BBB +#define ICON_MDI_TOOLTIP_REMOVE "\xf3\xb1\x95\xa0" // U+F1560 +#define ICON_MDI_TOOLTIP_REMOVE_OUTLINE "\xf3\xb1\x95\xa1" // U+F1561 +#define ICON_MDI_TOOLTIP_TEXT "\xf3\xb0\x94\xa8" // U+F0528 +#define ICON_MDI_TOOLTIP_TEXT_OUTLINE "\xf3\xb0\xaf\x97" // U+F0BD7 +#define ICON_MDI_TOOTH "\xf3\xb0\xa3\x83" // U+F08C3 +#define ICON_MDI_TOOTH_OUTLINE "\xf3\xb0\x94\xa9" // U+F0529 +#define ICON_MDI_TOOTHBRUSH "\xf3\xb1\x84\xa9" // U+F1129 +#define ICON_MDI_TOOTHBRUSH_ELECTRIC "\xf3\xb1\x84\xac" // U+F112C +#define ICON_MDI_TOOTHBRUSH_PASTE "\xf3\xb1\x84\xaa" // U+F112A +#define ICON_MDI_TORCH "\xf3\xb1\x98\x86" // U+F1606 +#define ICON_MDI_TORTOISE "\xf3\xb0\xb4\xbb" // U+F0D3B +#define ICON_MDI_TOSLINK "\xf3\xb1\x8a\xb8" // U+F12B8 +#define ICON_MDI_TOUCH_TEXT_OUTLINE "\xf3\xb1\xb1\xa0" // U+F1C60 +#define ICON_MDI_TOURNAMENT "\xf3\xb0\xa6\xae" // U+F09AE +#define ICON_MDI_TOW_TRUCK "\xf3\xb0\xa0\xbc" // U+F083C +#define ICON_MDI_TOWER_BEACH "\xf3\xb0\x9a\x81" // U+F0681 +#define ICON_MDI_TOWER_FIRE "\xf3\xb0\x9a\x82" // U+F0682 +#define ICON_MDI_TOWN_HALL "\xf3\xb1\xa1\xb5" // U+F1875 +#define ICON_MDI_TOY_BRICK "\xf3\xb1\x8a\x88" // U+F1288 +#define ICON_MDI_TOY_BRICK_MARKER "\xf3\xb1\x8a\x89" // U+F1289 +#define ICON_MDI_TOY_BRICK_MARKER_OUTLINE "\xf3\xb1\x8a\x8a" // U+F128A +#define ICON_MDI_TOY_BRICK_MINUS "\xf3\xb1\x8a\x8b" // U+F128B +#define ICON_MDI_TOY_BRICK_MINUS_OUTLINE "\xf3\xb1\x8a\x8c" // U+F128C +#define ICON_MDI_TOY_BRICK_OUTLINE "\xf3\xb1\x8a\x8d" // U+F128D +#define ICON_MDI_TOY_BRICK_PLUS "\xf3\xb1\x8a\x8e" // U+F128E +#define ICON_MDI_TOY_BRICK_PLUS_OUTLINE "\xf3\xb1\x8a\x8f" // U+F128F +#define ICON_MDI_TOY_BRICK_REMOVE "\xf3\xb1\x8a\x90" // U+F1290 +#define ICON_MDI_TOY_BRICK_REMOVE_OUTLINE "\xf3\xb1\x8a\x91" // U+F1291 +#define ICON_MDI_TOY_BRICK_SEARCH "\xf3\xb1\x8a\x92" // U+F1292 +#define ICON_MDI_TOY_BRICK_SEARCH_OUTLINE "\xf3\xb1\x8a\x93" // U+F1293 +#define ICON_MDI_TRACK_LIGHT "\xf3\xb0\xa4\x94" // U+F0914 +#define ICON_MDI_TRACK_LIGHT_OFF "\xf3\xb1\xac\x81" // U+F1B01 +#define ICON_MDI_TRACKPAD "\xf3\xb0\x9f\xb8" // U+F07F8 +#define ICON_MDI_TRACKPAD_LOCK "\xf3\xb0\xa4\xb3" // U+F0933 +#define ICON_MDI_TRACTOR "\xf3\xb0\xa2\x92" // U+F0892 +#define ICON_MDI_TRACTOR_VARIANT "\xf3\xb1\x93\x84" // U+F14C4 +#define ICON_MDI_TRADEMARK "\xf3\xb0\xa9\xb8" // U+F0A78 +#define ICON_MDI_TRAFFIC_CONE "\xf3\xb1\x8d\xbc" // U+F137C +#define ICON_MDI_TRAFFIC_LIGHT "\xf3\xb0\x94\xab" // U+F052B +#define ICON_MDI_TRAFFIC_LIGHT_OUTLINE "\xf3\xb1\xa0\xaa" // U+F182A +#define ICON_MDI_TRAIN "\xf3\xb0\x94\xac" // U+F052C +#define ICON_MDI_TRAIN_BUS "\xf3\xb1\xb3\x87" // U+F1CC7 +#define ICON_MDI_TRAIN_CAR "\xf3\xb0\xaf\x98" // U+F0BD8 +#define ICON_MDI_TRAIN_CAR_AUTORACK "\xf3\xb1\xac\xad" // U+F1B2D +#define ICON_MDI_TRAIN_CAR_BOX "\xf3\xb1\xac\xae" // U+F1B2E +#define ICON_MDI_TRAIN_CAR_BOX_FULL "\xf3\xb1\xac\xaf" // U+F1B2F +#define ICON_MDI_TRAIN_CAR_BOX_OPEN "\xf3\xb1\xac\xb0" // U+F1B30 +#define ICON_MDI_TRAIN_CAR_CABOOSE "\xf3\xb1\xac\xb1" // U+F1B31 +#define ICON_MDI_TRAIN_CAR_CENTERBEAM "\xf3\xb1\xac\xb2" // U+F1B32 +#define ICON_MDI_TRAIN_CAR_CENTERBEAM_FULL "\xf3\xb1\xac\xb3" // U+F1B33 +#define ICON_MDI_TRAIN_CAR_CONTAINER "\xf3\xb1\xac\xb4" // U+F1B34 +#define ICON_MDI_TRAIN_CAR_FLATBED "\xf3\xb1\xac\xb5" // U+F1B35 +#define ICON_MDI_TRAIN_CAR_FLATBED_CAR "\xf3\xb1\xac\xb6" // U+F1B36 +#define ICON_MDI_TRAIN_CAR_FLATBED_TANK "\xf3\xb1\xac\xb7" // U+F1B37 +#define ICON_MDI_TRAIN_CAR_GONDOLA "\xf3\xb1\xac\xb8" // U+F1B38 +#define ICON_MDI_TRAIN_CAR_GONDOLA_FULL "\xf3\xb1\xac\xb9" // U+F1B39 +#define ICON_MDI_TRAIN_CAR_HOPPER "\xf3\xb1\xac\xba" // U+F1B3A +#define ICON_MDI_TRAIN_CAR_HOPPER_COVERED "\xf3\xb1\xac\xbb" // U+F1B3B +#define ICON_MDI_TRAIN_CAR_HOPPER_FULL "\xf3\xb1\xac\xbc" // U+F1B3C +#define ICON_MDI_TRAIN_CAR_INTERMODAL "\xf3\xb1\xac\xbd" // U+F1B3D +#define ICON_MDI_TRAIN_CAR_PASSENGER "\xf3\xb1\x9c\xb3" // U+F1733 +#define ICON_MDI_TRAIN_CAR_PASSENGER_DOOR "\xf3\xb1\x9c\xb4" // U+F1734 +#define ICON_MDI_TRAIN_CAR_PASSENGER_DOOR_OPEN "\xf3\xb1\x9c\xb5" // U+F1735 +#define ICON_MDI_TRAIN_CAR_PASSENGER_VARIANT "\xf3\xb1\x9c\xb6" // U+F1736 +#define ICON_MDI_TRAIN_CAR_TANK "\xf3\xb1\xac\xbe" // U+F1B3E +#define ICON_MDI_TRAIN_VARIANT "\xf3\xb0\xa3\x84" // U+F08C4 +#define ICON_MDI_TRAM "\xf3\xb0\x94\xad" // U+F052D +#define ICON_MDI_TRAM_SIDE "\xf3\xb0\xbf\xa7" // U+F0FE7 +#define ICON_MDI_TRANSCRIBE "\xf3\xb0\x94\xae" // U+F052E +#define ICON_MDI_TRANSCRIBE_CLOSE "\xf3\xb0\x94\xaf" // U+F052F +#define ICON_MDI_TRANSFER "\xf3\xb1\x81\xa5" // U+F1065 +#define ICON_MDI_TRANSFER_DOWN "\xf3\xb0\xb6\xa1" // U+F0DA1 +#define ICON_MDI_TRANSFER_LEFT "\xf3\xb0\xb6\xa2" // U+F0DA2 +#define ICON_MDI_TRANSFER_RIGHT "\xf3\xb0\x94\xb0" // U+F0530 +#define ICON_MDI_TRANSFER_UP "\xf3\xb0\xb6\xa3" // U+F0DA3 +#define ICON_MDI_TRANSIT_CONNECTION "\xf3\xb0\xb4\xbc" // U+F0D3C +#define ICON_MDI_TRANSIT_CONNECTION_HORIZONTAL "\xf3\xb1\x95\x86" // U+F1546 +#define ICON_MDI_TRANSIT_CONNECTION_VARIANT "\xf3\xb0\xb4\xbd" // U+F0D3D +#define ICON_MDI_TRANSIT_DETOUR "\xf3\xb0\xbe\x8b" // U+F0F8B +#define ICON_MDI_TRANSIT_SKIP "\xf3\xb1\x94\x95" // U+F1515 +#define ICON_MDI_TRANSIT_TRANSFER "\xf3\xb0\x9a\xae" // U+F06AE +#define ICON_MDI_TRANSITION "\xf3\xb0\xa4\x95" // U+F0915 +#define ICON_MDI_TRANSITION_MASKED "\xf3\xb0\xa4\x96" // U+F0916 +#define ICON_MDI_TRANSLATE "\xf3\xb0\x97\x8a" // U+F05CA +#define ICON_MDI_TRANSLATE_OFF "\xf3\xb0\xb8\x86" // U+F0E06 +#define ICON_MDI_TRANSLATE_VARIANT "\xf3\xb1\xae\x99" // U+F1B99 +#define ICON_MDI_TRANSMISSION_TOWER "\xf3\xb0\xb4\xbe" // U+F0D3E +#define ICON_MDI_TRANSMISSION_TOWER_EXPORT "\xf3\xb1\xa4\xac" // U+F192C +#define ICON_MDI_TRANSMISSION_TOWER_IMPORT "\xf3\xb1\xa4\xad" // U+F192D +#define ICON_MDI_TRANSMISSION_TOWER_OFF "\xf3\xb1\xa7\x9d" // U+F19DD +#define ICON_MDI_TRASH_CAN "\xf3\xb0\xa9\xb9" // U+F0A79 +#define ICON_MDI_TRASH_CAN_OUTLINE "\xf3\xb0\xa9\xba" // U+F0A7A +#define ICON_MDI_TRAY "\xf3\xb1\x8a\x94" // U+F1294 +#define ICON_MDI_TRAY_ALERT "\xf3\xb1\x8a\x95" // U+F1295 +#define ICON_MDI_TRAY_ARROW_DOWN "\xf3\xb0\x84\xa0" // U+F0120 +#define ICON_MDI_TRAY_ARROW_UP "\xf3\xb0\x84\x9d" // U+F011D +#define ICON_MDI_TRAY_FULL "\xf3\xb1\x8a\x96" // U+F1296 +#define ICON_MDI_TRAY_MINUS "\xf3\xb1\x8a\x97" // U+F1297 +#define ICON_MDI_TRAY_PLUS "\xf3\xb1\x8a\x98" // U+F1298 +#define ICON_MDI_TRAY_REMOVE "\xf3\xb1\x8a\x99" // U+F1299 +#define ICON_MDI_TREASURE_CHEST "\xf3\xb0\x9c\xa6" // U+F0726 +#define ICON_MDI_TREASURE_CHEST_OUTLINE "\xf3\xb1\xb1\xb7" // U+F1C77 +#define ICON_MDI_TREE "\xf3\xb0\x94\xb1" // U+F0531 +#define ICON_MDI_TREE_OUTLINE "\xf3\xb0\xb9\xa9" // U+F0E69 +#define ICON_MDI_TRELLO "\xf3\xb0\x94\xb2" // U+F0532 +#define ICON_MDI_TRENDING_DOWN "\xf3\xb0\x94\xb3" // U+F0533 +#define ICON_MDI_TRENDING_NEUTRAL "\xf3\xb0\x94\xb4" // U+F0534 +#define ICON_MDI_TRENDING_UP "\xf3\xb0\x94\xb5" // U+F0535 +#define ICON_MDI_TRIANGLE "\xf3\xb0\x94\xb6" // U+F0536 +#define ICON_MDI_TRIANGLE_DOWN "\xf3\xb1\xb1\x96" // U+F1C56 +#define ICON_MDI_TRIANGLE_DOWN_OUTLINE "\xf3\xb1\xb1\x97" // U+F1C57 +#define ICON_MDI_TRIANGLE_OUTLINE "\xf3\xb0\x94\xb7" // U+F0537 +#define ICON_MDI_TRIANGLE_SMALL_DOWN "\xf3\xb1\xa8\x89" // U+F1A09 +#define ICON_MDI_TRIANGLE_SMALL_UP "\xf3\xb1\xa8\x8a" // U+F1A0A +#define ICON_MDI_TRIANGLE_WAVE "\xf3\xb1\x91\xbc" // U+F147C +#define ICON_MDI_TRIFORCE "\xf3\xb0\xaf\x99" // U+F0BD9 +#define ICON_MDI_TROPHY "\xf3\xb0\x94\xb8" // U+F0538 +#define ICON_MDI_TROPHY_AWARD "\xf3\xb0\x94\xb9" // U+F0539 +#define ICON_MDI_TROPHY_BROKEN "\xf3\xb0\xb6\xa4" // U+F0DA4 +#define ICON_MDI_TROPHY_OUTLINE "\xf3\xb0\x94\xba" // U+F053A +#define ICON_MDI_TROPHY_VARIANT "\xf3\xb0\x94\xbb" // U+F053B +#define ICON_MDI_TROPHY_VARIANT_OUTLINE "\xf3\xb0\x94\xbc" // U+F053C +#define ICON_MDI_TRUCK "\xf3\xb0\x94\xbd" // U+F053D +#define ICON_MDI_TRUCK_ALERT "\xf3\xb1\xa7\x9e" // U+F19DE +#define ICON_MDI_TRUCK_ALERT_OUTLINE "\xf3\xb1\xa7\x9f" // U+F19DF +#define ICON_MDI_TRUCK_CARGO_CONTAINER "\xf3\xb1\xa3\x98" // U+F18D8 +#define ICON_MDI_TRUCK_CHECK "\xf3\xb0\xb3\x94" // U+F0CD4 +#define ICON_MDI_TRUCK_CHECK_OUTLINE "\xf3\xb1\x8a\x9a" // U+F129A +#define ICON_MDI_TRUCK_DELIVERY "\xf3\xb0\x94\xbe" // U+F053E +#define ICON_MDI_TRUCK_DELIVERY_OUTLINE "\xf3\xb1\x8a\x9b" // U+F129B +#define ICON_MDI_TRUCK_FAST "\xf3\xb0\x9e\x88" // U+F0788 +#define ICON_MDI_TRUCK_FAST_OUTLINE "\xf3\xb1\x8a\x9c" // U+F129C +#define ICON_MDI_TRUCK_FLATBED "\xf3\xb1\xa2\x91" // U+F1891 +#define ICON_MDI_TRUCK_MINUS "\xf3\xb1\xa6\xae" // U+F19AE +#define ICON_MDI_TRUCK_MINUS_OUTLINE "\xf3\xb1\xa6\xbd" // U+F19BD +#define ICON_MDI_TRUCK_OFF_ROAD "\xf3\xb1\xb2\x9e" // U+F1C9E +#define ICON_MDI_TRUCK_OFF_ROAD_OFF "\xf3\xb1\xb2\x9f" // U+F1C9F +#define ICON_MDI_TRUCK_OUTLINE "\xf3\xb1\x8a\x9d" // U+F129D +#define ICON_MDI_TRUCK_PLUS "\xf3\xb1\xa6\xad" // U+F19AD +#define ICON_MDI_TRUCK_PLUS_OUTLINE "\xf3\xb1\xa6\xbc" // U+F19BC +#define ICON_MDI_TRUCK_REMOVE "\xf3\xb1\xa6\xaf" // U+F19AF +#define ICON_MDI_TRUCK_REMOVE_OUTLINE "\xf3\xb1\xa6\xbe" // U+F19BE +#define ICON_MDI_TRUCK_SNOWFLAKE "\xf3\xb1\xa6\xa6" // U+F19A6 +#define ICON_MDI_TRUCK_TRAILER "\xf3\xb0\x9c\xa7" // U+F0727 +#define ICON_MDI_TRUMPET "\xf3\xb1\x82\x96" // U+F1096 +#define ICON_MDI_TSHIRT_CREW "\xf3\xb0\xa9\xbb" // U+F0A7B +#define ICON_MDI_TSHIRT_CREW_OUTLINE "\xf3\xb0\x94\xbf" // U+F053F +#define ICON_MDI_TSHIRT_V "\xf3\xb0\xa9\xbc" // U+F0A7C +#define ICON_MDI_TSHIRT_V_OUTLINE "\xf3\xb0\x95\x80" // U+F0540 +#define ICON_MDI_TSUNAMI "\xf3\xb1\xaa\x81" // U+F1A81 +#define ICON_MDI_TUMBLE_DRYER "\xf3\xb0\xa4\x97" // U+F0917 +#define ICON_MDI_TUMBLE_DRYER_ALERT "\xf3\xb1\x86\xba" // U+F11BA +#define ICON_MDI_TUMBLE_DRYER_OFF "\xf3\xb1\x86\xbb" // U+F11BB +#define ICON_MDI_TUNE "\xf3\xb0\x98\xae" // U+F062E +#define ICON_MDI_TUNE_VARIANT "\xf3\xb1\x95\x82" // U+F1542 +#define ICON_MDI_TUNE_VERTICAL "\xf3\xb0\x99\xaa" // U+F066A +#define ICON_MDI_TUNE_VERTICAL_VARIANT "\xf3\xb1\x95\x83" // U+F1543 +#define ICON_MDI_TUNNEL "\xf3\xb1\xa0\xbd" // U+F183D +#define ICON_MDI_TUNNEL_OUTLINE "\xf3\xb1\xa0\xbe" // U+F183E +#define ICON_MDI_TURBINE "\xf3\xb1\xaa\x82" // U+F1A82 +#define ICON_MDI_TURKEY "\xf3\xb1\x9c\x9b" // U+F171B +#define ICON_MDI_TURNSTILE "\xf3\xb0\xb3\x95" // U+F0CD5 +#define ICON_MDI_TURNSTILE_OUTLINE "\xf3\xb0\xb3\x96" // U+F0CD6 +#define ICON_MDI_TURTLE "\xf3\xb0\xb3\x97" // U+F0CD7 +#define ICON_MDI_TWITCH "\xf3\xb0\x95\x83" // U+F0543 +#define ICON_MDI_TWITTER "\xf3\xb0\x95\x84" // U+F0544 +#define ICON_MDI_TWO_FACTOR_AUTHENTICATION "\xf3\xb0\xa6\xaf" // U+F09AF +#define ICON_MDI_TYPEWRITER "\xf3\xb0\xbc\xad" // U+F0F2D +#define ICON_MDI_UBISOFT "\xf3\xb0\xaf\x9a" // U+F0BDA +#define ICON_MDI_UBUNTU "\xf3\xb0\x95\x88" // U+F0548 +#define ICON_MDI_UFO "\xf3\xb1\x83\x84" // U+F10C4 +#define ICON_MDI_UFO_OUTLINE "\xf3\xb1\x83\x85" // U+F10C5 +#define ICON_MDI_ULTRA_HIGH_DEFINITION "\xf3\xb0\x9f\xb9" // U+F07F9 +#define ICON_MDI_UMBRACO "\xf3\xb0\x95\x89" // U+F0549 +#define ICON_MDI_UMBRELLA "\xf3\xb0\x95\x8a" // U+F054A +#define ICON_MDI_UMBRELLA_BEACH "\xf3\xb1\xa2\x8a" // U+F188A +#define ICON_MDI_UMBRELLA_BEACH_OUTLINE "\xf3\xb1\xa2\x8b" // U+F188B +#define ICON_MDI_UMBRELLA_CLOSED "\xf3\xb0\xa6\xb0" // U+F09B0 +#define ICON_MDI_UMBRELLA_CLOSED_OUTLINE "\xf3\xb1\x8f\xa2" // U+F13E2 +#define ICON_MDI_UMBRELLA_CLOSED_VARIANT "\xf3\xb1\x8f\xa1" // U+F13E1 +#define ICON_MDI_UMBRELLA_OUTLINE "\xf3\xb0\x95\x8b" // U+F054B +#define ICON_MDI_UNDO "\xf3\xb0\x95\x8c" // U+F054C +#define ICON_MDI_UNDO_VARIANT "\xf3\xb0\x95\x8d" // U+F054D +#define ICON_MDI_UNFOLD_LESS_HORIZONTAL "\xf3\xb0\x95\x8e" // U+F054E +#define ICON_MDI_UNFOLD_LESS_VERTICAL "\xf3\xb0\x9d\xa0" // U+F0760 +#define ICON_MDI_UNFOLD_MORE_HORIZONTAL "\xf3\xb0\x95\x8f" // U+F054F +#define ICON_MDI_UNFOLD_MORE_VERTICAL "\xf3\xb0\x9d\xa1" // U+F0761 +#define ICON_MDI_UNGROUP "\xf3\xb0\x95\x90" // U+F0550 +#define ICON_MDI_UNICODE "\xf3\xb0\xbb\x90" // U+F0ED0 +#define ICON_MDI_UNICORN "\xf3\xb1\x97\x82" // U+F15C2 +#define ICON_MDI_UNICORN_VARIANT "\xf3\xb1\x97\x83" // U+F15C3 +#define ICON_MDI_UNICYCLE "\xf3\xb1\x97\xa5" // U+F15E5 +#define ICON_MDI_UNITY "\xf3\xb0\x9a\xaf" // U+F06AF +#define ICON_MDI_UNREAL "\xf3\xb0\xa6\xb1" // U+F09B1 +#define ICON_MDI_UPDATE "\xf3\xb0\x9a\xb0" // U+F06B0 +#define ICON_MDI_UPLOAD "\xf3\xb0\x95\x92" // U+F0552 +#define ICON_MDI_UPLOAD_LOCK "\xf3\xb1\x8d\xb3" // U+F1373 +#define ICON_MDI_UPLOAD_LOCK_OUTLINE "\xf3\xb1\x8d\xb4" // U+F1374 +#define ICON_MDI_UPLOAD_MULTIPLE "\xf3\xb0\xa0\xbd" // U+F083D +#define ICON_MDI_UPLOAD_NETWORK "\xf3\xb0\x9b\xb6" // U+F06F6 +#define ICON_MDI_UPLOAD_NETWORK_OUTLINE "\xf3\xb0\xb3\x98" // U+F0CD8 +#define ICON_MDI_UPLOAD_OFF "\xf3\xb1\x83\x86" // U+F10C6 +#define ICON_MDI_UPLOAD_OFF_OUTLINE "\xf3\xb1\x83\x87" // U+F10C7 +#define ICON_MDI_UPLOAD_OUTLINE "\xf3\xb0\xb8\x87" // U+F0E07 +#define ICON_MDI_USB "\xf3\xb0\x95\x93" // U+F0553 +#define ICON_MDI_USB_C_PORT "\xf3\xb1\xb2\xbf" // U+F1CBF +#define ICON_MDI_USB_FLASH_DRIVE "\xf3\xb1\x8a\x9e" // U+F129E +#define ICON_MDI_USB_FLASH_DRIVE_OUTLINE "\xf3\xb1\x8a\x9f" // U+F129F +#define ICON_MDI_USB_PORT "\xf3\xb1\x87\xb0" // U+F11F0 +#define ICON_MDI_VACUUM "\xf3\xb1\xa6\xa1" // U+F19A1 +#define ICON_MDI_VACUUM_OUTLINE "\xf3\xb1\xa6\xa2" // U+F19A2 +#define ICON_MDI_VALVE "\xf3\xb1\x81\xa6" // U+F1066 +#define ICON_MDI_VALVE_CLOSED "\xf3\xb1\x81\xa7" // U+F1067 +#define ICON_MDI_VALVE_OPEN "\xf3\xb1\x81\xa8" // U+F1068 +#define ICON_MDI_VAN_PASSENGER "\xf3\xb0\x9f\xba" // U+F07FA +#define ICON_MDI_VAN_UTILITY "\xf3\xb0\x9f\xbb" // U+F07FB +#define ICON_MDI_VANISH "\xf3\xb0\x9f\xbc" // U+F07FC +#define ICON_MDI_VANISH_QUARTER "\xf3\xb1\x95\x94" // U+F1554 +#define ICON_MDI_VANITY_LIGHT "\xf3\xb1\x87\xa1" // U+F11E1 +#define ICON_MDI_VARIABLE "\xf3\xb0\xab\xa7" // U+F0AE7 +#define ICON_MDI_VARIABLE_BOX "\xf3\xb1\x84\x91" // U+F1111 +#define ICON_MDI_VECTOR_ARRANGE_ABOVE "\xf3\xb0\x95\x94" // U+F0554 +#define ICON_MDI_VECTOR_ARRANGE_BELOW "\xf3\xb0\x95\x95" // U+F0555 +#define ICON_MDI_VECTOR_BEZIER "\xf3\xb0\xab\xa8" // U+F0AE8 +#define ICON_MDI_VECTOR_CIRCLE "\xf3\xb0\x95\x96" // U+F0556 +#define ICON_MDI_VECTOR_CIRCLE_VARIANT "\xf3\xb0\x95\x97" // U+F0557 +#define ICON_MDI_VECTOR_COMBINE "\xf3\xb0\x95\x98" // U+F0558 +#define ICON_MDI_VECTOR_CURVE "\xf3\xb0\x95\x99" // U+F0559 +#define ICON_MDI_VECTOR_DIFFERENCE "\xf3\xb0\x95\x9a" // U+F055A +#define ICON_MDI_VECTOR_DIFFERENCE_AB "\xf3\xb0\x95\x9b" // U+F055B +#define ICON_MDI_VECTOR_DIFFERENCE_BA "\xf3\xb0\x95\x9c" // U+F055C +#define ICON_MDI_VECTOR_ELLIPSE "\xf3\xb0\xa2\x93" // U+F0893 +#define ICON_MDI_VECTOR_INTERSECTION "\xf3\xb0\x95\x9d" // U+F055D +#define ICON_MDI_VECTOR_LINE "\xf3\xb0\x95\x9e" // U+F055E +#define ICON_MDI_VECTOR_LINK "\xf3\xb0\xbf\xa8" // U+F0FE8 +#define ICON_MDI_VECTOR_POINT "\xf3\xb0\x87\x84" // U+F01C4 +#define ICON_MDI_VECTOR_POINT_EDIT "\xf3\xb0\xa7\xa8" // U+F09E8 +#define ICON_MDI_VECTOR_POINT_MINUS "\xf3\xb1\xad\xb8" // U+F1B78 +#define ICON_MDI_VECTOR_POINT_PLUS "\xf3\xb1\xad\xb9" // U+F1B79 +#define ICON_MDI_VECTOR_POINT_SELECT "\xf3\xb0\x95\x9f" // U+F055F +#define ICON_MDI_VECTOR_POLYGON "\xf3\xb0\x95\xa0" // U+F0560 +#define ICON_MDI_VECTOR_POLYGON_VARIANT "\xf3\xb1\xa1\x96" // U+F1856 +#define ICON_MDI_VECTOR_POLYLINE "\xf3\xb0\x95\xa1" // U+F0561 +#define ICON_MDI_VECTOR_POLYLINE_EDIT "\xf3\xb1\x88\xa5" // U+F1225 +#define ICON_MDI_VECTOR_POLYLINE_MINUS "\xf3\xb1\x88\xa6" // U+F1226 +#define ICON_MDI_VECTOR_POLYLINE_PLUS "\xf3\xb1\x88\xa7" // U+F1227 +#define ICON_MDI_VECTOR_POLYLINE_REMOVE "\xf3\xb1\x88\xa8" // U+F1228 +#define ICON_MDI_VECTOR_RADIUS "\xf3\xb0\x9d\x8a" // U+F074A +#define ICON_MDI_VECTOR_RECTANGLE "\xf3\xb0\x97\x86" // U+F05C6 +#define ICON_MDI_VECTOR_SELECTION "\xf3\xb0\x95\xa2" // U+F0562 +#define ICON_MDI_VECTOR_SQUARE "\xf3\xb0\x80\x81" // U+F0001 +#define ICON_MDI_VECTOR_SQUARE_CLOSE "\xf3\xb1\xa1\x97" // U+F1857 +#define ICON_MDI_VECTOR_SQUARE_EDIT "\xf3\xb1\xa3\x99" // U+F18D9 +#define ICON_MDI_VECTOR_SQUARE_MINUS "\xf3\xb1\xa3\x9a" // U+F18DA +#define ICON_MDI_VECTOR_SQUARE_OPEN "\xf3\xb1\xa1\x98" // U+F1858 +#define ICON_MDI_VECTOR_SQUARE_PLUS "\xf3\xb1\xa3\x9b" // U+F18DB +#define ICON_MDI_VECTOR_SQUARE_REMOVE "\xf3\xb1\xa3\x9c" // U+F18DC +#define ICON_MDI_VECTOR_TRIANGLE "\xf3\xb0\x95\xa3" // U+F0563 +#define ICON_MDI_VECTOR_UNION "\xf3\xb0\x95\xa4" // U+F0564 +#define ICON_MDI_VHS "\xf3\xb0\xa8\x9b" // U+F0A1B +#define ICON_MDI_VIBRATE "\xf3\xb0\x95\xa6" // U+F0566 +#define ICON_MDI_VIBRATE_OFF "\xf3\xb0\xb3\x99" // U+F0CD9 +#define ICON_MDI_VIDEO "\xf3\xb0\x95\xa7" // U+F0567 +#define ICON_MDI_VIDEO_2D "\xf3\xb1\xa8\x9c" // U+F1A1C +#define ICON_MDI_VIDEO_3D "\xf3\xb0\x9f\xbd" // U+F07FD +#define ICON_MDI_VIDEO_3D_OFF "\xf3\xb1\x8f\x99" // U+F13D9 +#define ICON_MDI_VIDEO_3D_VARIANT "\xf3\xb0\xbb\x91" // U+F0ED1 +#define ICON_MDI_VIDEO_4K_BOX "\xf3\xb0\xa0\xbe" // U+F083E +#define ICON_MDI_VIDEO_ACCOUNT "\xf3\xb0\xa4\x99" // U+F0919 +#define ICON_MDI_VIDEO_BOX "\xf3\xb0\x83\xbd" // U+F00FD +#define ICON_MDI_VIDEO_BOX_OFF "\xf3\xb0\x83\xbe" // U+F00FE +#define ICON_MDI_VIDEO_CHECK "\xf3\xb1\x81\xa9" // U+F1069 +#define ICON_MDI_VIDEO_CHECK_OUTLINE "\xf3\xb1\x81\xaa" // U+F106A +#define ICON_MDI_VIDEO_HIGH_DEFINITION "\xf3\xb1\x94\xae" // U+F152E +#define ICON_MDI_VIDEO_IMAGE "\xf3\xb0\xa4\x9a" // U+F091A +#define ICON_MDI_VIDEO_INPUT_ANTENNA "\xf3\xb0\xa0\xbf" // U+F083F +#define ICON_MDI_VIDEO_INPUT_COMPONENT "\xf3\xb0\xa1\x80" // U+F0840 +#define ICON_MDI_VIDEO_INPUT_HDMI "\xf3\xb0\xa1\x81" // U+F0841 +#define ICON_MDI_VIDEO_INPUT_SCART "\xf3\xb0\xbe\x8c" // U+F0F8C +#define ICON_MDI_VIDEO_INPUT_SVIDEO "\xf3\xb0\xa1\x82" // U+F0842 +#define ICON_MDI_VIDEO_MARKER "\xf3\xb1\xa6\xa9" // U+F19A9 +#define ICON_MDI_VIDEO_MARKER_OUTLINE "\xf3\xb1\xa6\xaa" // U+F19AA +#define ICON_MDI_VIDEO_MINUS "\xf3\xb0\xa6\xb2" // U+F09B2 +#define ICON_MDI_VIDEO_MINUS_OUTLINE "\xf3\xb0\x8a\xba" // U+F02BA +#define ICON_MDI_VIDEO_OFF "\xf3\xb0\x95\xa8" // U+F0568 +#define ICON_MDI_VIDEO_OFF_OUTLINE "\xf3\xb0\xaf\x9b" // U+F0BDB +#define ICON_MDI_VIDEO_OUTLINE "\xf3\xb0\xaf\x9c" // U+F0BDC +#define ICON_MDI_VIDEO_PLUS "\xf3\xb0\xa6\xb3" // U+F09B3 +#define ICON_MDI_VIDEO_PLUS_OUTLINE "\xf3\xb0\x87\x93" // U+F01D3 +#define ICON_MDI_VIDEO_STABILIZATION "\xf3\xb0\xa4\x9b" // U+F091B +#define ICON_MDI_VIDEO_STANDARD_DEFINITION "\xf3\xb1\xb2\xa0" // U+F1CA0 +#define ICON_MDI_VIDEO_SWITCH "\xf3\xb0\x95\xa9" // U+F0569 +#define ICON_MDI_VIDEO_SWITCH_OUTLINE "\xf3\xb0\x9e\x90" // U+F0790 +#define ICON_MDI_VIDEO_VINTAGE "\xf3\xb0\xa8\x9c" // U+F0A1C +#define ICON_MDI_VIDEO_WIRELESS "\xf3\xb0\xbb\x92" // U+F0ED2 +#define ICON_MDI_VIDEO_WIRELESS_OUTLINE "\xf3\xb0\xbb\x93" // U+F0ED3 +#define ICON_MDI_VIEW_AGENDA "\xf3\xb0\x95\xaa" // U+F056A +#define ICON_MDI_VIEW_AGENDA_OUTLINE "\xf3\xb1\x87\x98" // U+F11D8 +#define ICON_MDI_VIEW_ARRAY "\xf3\xb0\x95\xab" // U+F056B +#define ICON_MDI_VIEW_ARRAY_OUTLINE "\xf3\xb1\x92\x85" // U+F1485 +#define ICON_MDI_VIEW_CAROUSEL "\xf3\xb0\x95\xac" // U+F056C +#define ICON_MDI_VIEW_CAROUSEL_OUTLINE "\xf3\xb1\x92\x86" // U+F1486 +#define ICON_MDI_VIEW_COLUMN "\xf3\xb0\x95\xad" // U+F056D +#define ICON_MDI_VIEW_COLUMN_OUTLINE "\xf3\xb1\x92\x87" // U+F1487 +#define ICON_MDI_VIEW_COMFY "\xf3\xb0\xb9\xaa" // U+F0E6A +#define ICON_MDI_VIEW_COMFY_OUTLINE "\xf3\xb1\x92\x88" // U+F1488 +#define ICON_MDI_VIEW_COMPACT "\xf3\xb0\xb9\xab" // U+F0E6B +#define ICON_MDI_VIEW_COMPACT_OUTLINE "\xf3\xb0\xb9\xac" // U+F0E6C +#define ICON_MDI_VIEW_DASHBOARD "\xf3\xb0\x95\xae" // U+F056E +#define ICON_MDI_VIEW_DASHBOARD_EDIT "\xf3\xb1\xa5\x87" // U+F1947 +#define ICON_MDI_VIEW_DASHBOARD_EDIT_OUTLINE "\xf3\xb1\xa5\x88" // U+F1948 +#define ICON_MDI_VIEW_DASHBOARD_OUTLINE "\xf3\xb0\xa8\x9d" // U+F0A1D +#define ICON_MDI_VIEW_DASHBOARD_VARIANT "\xf3\xb0\xa1\x83" // U+F0843 +#define ICON_MDI_VIEW_DASHBOARD_VARIANT_OUTLINE "\xf3\xb1\x92\x89" // U+F1489 +#define ICON_MDI_VIEW_DAY "\xf3\xb0\x95\xaf" // U+F056F +#define ICON_MDI_VIEW_DAY_OUTLINE "\xf3\xb1\x92\x8a" // U+F148A +#define ICON_MDI_VIEW_GALLERY "\xf3\xb1\xa2\x88" // U+F1888 +#define ICON_MDI_VIEW_GALLERY_OUTLINE "\xf3\xb1\xa2\x89" // U+F1889 +#define ICON_MDI_VIEW_GRID "\xf3\xb0\x95\xb0" // U+F0570 +#define ICON_MDI_VIEW_GRID_COMPACT "\xf3\xb1\xb1\xa1" // U+F1C61 +#define ICON_MDI_VIEW_GRID_OUTLINE "\xf3\xb1\x87\x99" // U+F11D9 +#define ICON_MDI_VIEW_GRID_PLUS "\xf3\xb0\xbe\x8d" // U+F0F8D +#define ICON_MDI_VIEW_GRID_PLUS_OUTLINE "\xf3\xb1\x87\x9a" // U+F11DA +#define ICON_MDI_VIEW_HEADLINE "\xf3\xb0\x95\xb1" // U+F0571 +#define ICON_MDI_VIEW_LIST "\xf3\xb0\x95\xb2" // U+F0572 +#define ICON_MDI_VIEW_LIST_OUTLINE "\xf3\xb1\x92\x8b" // U+F148B +#define ICON_MDI_VIEW_MODULE "\xf3\xb0\x95\xb3" // U+F0573 +#define ICON_MDI_VIEW_MODULE_OUTLINE "\xf3\xb1\x92\x8c" // U+F148C +#define ICON_MDI_VIEW_PARALLEL "\xf3\xb0\x9c\xa8" // U+F0728 +#define ICON_MDI_VIEW_PARALLEL_OUTLINE "\xf3\xb1\x92\x8d" // U+F148D +#define ICON_MDI_VIEW_QUILT "\xf3\xb0\x95\xb4" // U+F0574 +#define ICON_MDI_VIEW_QUILT_OUTLINE "\xf3\xb1\x92\x8e" // U+F148E +#define ICON_MDI_VIEW_SEQUENTIAL "\xf3\xb0\x9c\xa9" // U+F0729 +#define ICON_MDI_VIEW_SEQUENTIAL_OUTLINE "\xf3\xb1\x92\x8f" // U+F148F +#define ICON_MDI_VIEW_SPLIT_HORIZONTAL "\xf3\xb0\xaf\x8b" // U+F0BCB +#define ICON_MDI_VIEW_SPLIT_VERTICAL "\xf3\xb0\xaf\x8c" // U+F0BCC +#define ICON_MDI_VIEW_STREAM "\xf3\xb0\x95\xb5" // U+F0575 +#define ICON_MDI_VIEW_STREAM_OUTLINE "\xf3\xb1\x92\x90" // U+F1490 +#define ICON_MDI_VIEW_WEEK "\xf3\xb0\x95\xb6" // U+F0576 +#define ICON_MDI_VIEW_WEEK_OUTLINE "\xf3\xb1\x92\x91" // U+F1491 +#define ICON_MDI_VIMEO "\xf3\xb0\x95\xb7" // U+F0577 +#define ICON_MDI_VIOLIN "\xf3\xb0\x98\x8f" // U+F060F +#define ICON_MDI_VIRTUAL_REALITY "\xf3\xb0\xa2\x94" // U+F0894 +#define ICON_MDI_VIRUS "\xf3\xb1\x8e\xb6" // U+F13B6 +#define ICON_MDI_VIRUS_OFF "\xf3\xb1\xa3\xa1" // U+F18E1 +#define ICON_MDI_VIRUS_OFF_OUTLINE "\xf3\xb1\xa3\xa2" // U+F18E2 +#define ICON_MDI_VIRUS_OUTLINE "\xf3\xb1\x8e\xb7" // U+F13B7 +#define ICON_MDI_VLC "\xf3\xb0\x95\xbc" // U+F057C +#define ICON_MDI_VOICEMAIL "\xf3\xb0\x95\xbd" // U+F057D +#define ICON_MDI_VOLCANO "\xf3\xb1\xaa\x83" // U+F1A83 +#define ICON_MDI_VOLCANO_OUTLINE "\xf3\xb1\xaa\x84" // U+F1A84 +#define ICON_MDI_VOLLEYBALL "\xf3\xb0\xa6\xb4" // U+F09B4 +#define ICON_MDI_VOLUME_EQUAL "\xf3\xb1\xac\x90" // U+F1B10 +#define ICON_MDI_VOLUME_HIGH "\xf3\xb0\x95\xbe" // U+F057E +#define ICON_MDI_VOLUME_LOW "\xf3\xb0\x95\xbf" // U+F057F +#define ICON_MDI_VOLUME_MEDIUM "\xf3\xb0\x96\x80" // U+F0580 +#define ICON_MDI_VOLUME_MINUS "\xf3\xb0\x9d\x9e" // U+F075E +#define ICON_MDI_VOLUME_MUTE "\xf3\xb0\x9d\x9f" // U+F075F +#define ICON_MDI_VOLUME_OFF "\xf3\xb0\x96\x81" // U+F0581 +#define ICON_MDI_VOLUME_PLUS "\xf3\xb0\x9d\x9d" // U+F075D +#define ICON_MDI_VOLUME_SOURCE "\xf3\xb1\x84\xa0" // U+F1120 +#define ICON_MDI_VOLUME_VARIANT_OFF "\xf3\xb0\xb8\x88" // U+F0E08 +#define ICON_MDI_VOLUME_VIBRATE "\xf3\xb1\x84\xa1" // U+F1121 +#define ICON_MDI_VOTE "\xf3\xb0\xa8\x9f" // U+F0A1F +#define ICON_MDI_VOTE_OUTLINE "\xf3\xb0\xa8\xa0" // U+F0A20 +#define ICON_MDI_VPN "\xf3\xb0\x96\x82" // U+F0582 +#define ICON_MDI_VUEJS "\xf3\xb0\xa1\x84" // U+F0844 +#define ICON_MDI_VUETIFY "\xf3\xb0\xb9\xad" // U+F0E6D +#define ICON_MDI_WALK "\xf3\xb0\x96\x83" // U+F0583 +#define ICON_MDI_WALL "\xf3\xb0\x9f\xbe" // U+F07FE +#define ICON_MDI_WALL_FIRE "\xf3\xb1\xa8\x91" // U+F1A11 +#define ICON_MDI_WALL_SCONCE "\xf3\xb0\xa4\x9c" // U+F091C +#define ICON_MDI_WALL_SCONCE_FLAT "\xf3\xb0\xa4\x9d" // U+F091D +#define ICON_MDI_WALL_SCONCE_FLAT_OUTLINE "\xf3\xb1\x9f\x89" // U+F17C9 +#define ICON_MDI_WALL_SCONCE_FLAT_VARIANT "\xf3\xb0\x90\x9c" // U+F041C +#define ICON_MDI_WALL_SCONCE_FLAT_VARIANT_OUTLINE "\xf3\xb1\x9f\x8a" // U+F17CA +#define ICON_MDI_WALL_SCONCE_OUTLINE "\xf3\xb1\x9f\x8b" // U+F17CB +#define ICON_MDI_WALL_SCONCE_ROUND "\xf3\xb0\x9d\x88" // U+F0748 +#define ICON_MDI_WALL_SCONCE_ROUND_OUTLINE "\xf3\xb1\x9f\x8c" // U+F17CC +#define ICON_MDI_WALL_SCONCE_ROUND_VARIANT "\xf3\xb0\xa4\x9e" // U+F091E +#define ICON_MDI_WALL_SCONCE_ROUND_VARIANT_OUTLINE "\xf3\xb1\x9f\x8d" // U+F17CD +#define ICON_MDI_WALLET "\xf3\xb0\x96\x84" // U+F0584 +#define ICON_MDI_WALLET_BIFOLD "\xf3\xb1\xb1\x98" // U+F1C58 +#define ICON_MDI_WALLET_BIFOLD_OUTLINE "\xf3\xb1\xb1\x99" // U+F1C59 +#define ICON_MDI_WALLET_GIFTCARD "\xf3\xb0\x96\x85" // U+F0585 +#define ICON_MDI_WALLET_MEMBERSHIP "\xf3\xb0\x96\x86" // U+F0586 +#define ICON_MDI_WALLET_OUTLINE "\xf3\xb0\xaf\x9d" // U+F0BDD +#define ICON_MDI_WALLET_PLUS "\xf3\xb0\xbe\x8e" // U+F0F8E +#define ICON_MDI_WALLET_PLUS_OUTLINE "\xf3\xb0\xbe\x8f" // U+F0F8F +#define ICON_MDI_WALLET_TRAVEL "\xf3\xb0\x96\x87" // U+F0587 +#define ICON_MDI_WALLPAPER "\xf3\xb0\xb8\x89" // U+F0E09 +#define ICON_MDI_WAN "\xf3\xb0\x96\x88" // U+F0588 +#define ICON_MDI_WARDROBE "\xf3\xb0\xbe\x90" // U+F0F90 +#define ICON_MDI_WARDROBE_OUTLINE "\xf3\xb0\xbe\x91" // U+F0F91 +#define ICON_MDI_WAREHOUSE "\xf3\xb0\xbe\x81" // U+F0F81 +#define ICON_MDI_WASHING_MACHINE "\xf3\xb0\x9c\xaa" // U+F072A +#define ICON_MDI_WASHING_MACHINE_ALERT "\xf3\xb1\x86\xbc" // U+F11BC +#define ICON_MDI_WASHING_MACHINE_OFF "\xf3\xb1\x86\xbd" // U+F11BD +#define ICON_MDI_WATCH "\xf3\xb0\x96\x89" // U+F0589 +#define ICON_MDI_WATCH_EXPORT "\xf3\xb0\x96\x8a" // U+F058A +#define ICON_MDI_WATCH_EXPORT_VARIANT "\xf3\xb0\xa2\x95" // U+F0895 +#define ICON_MDI_WATCH_IMPORT "\xf3\xb0\x96\x8b" // U+F058B +#define ICON_MDI_WATCH_IMPORT_VARIANT "\xf3\xb0\xa2\x96" // U+F0896 +#define ICON_MDI_WATCH_VARIANT "\xf3\xb0\xa2\x97" // U+F0897 +#define ICON_MDI_WATCH_VIBRATE "\xf3\xb0\x9a\xb1" // U+F06B1 +#define ICON_MDI_WATCH_VIBRATE_OFF "\xf3\xb0\xb3\x9a" // U+F0CDA +#define ICON_MDI_WATER "\xf3\xb0\x96\x8c" // U+F058C +#define ICON_MDI_WATER_ALERT "\xf3\xb1\x94\x82" // U+F1502 +#define ICON_MDI_WATER_ALERT_OUTLINE "\xf3\xb1\x94\x83" // U+F1503 +#define ICON_MDI_WATER_BOILER "\xf3\xb0\xbe\x92" // U+F0F92 +#define ICON_MDI_WATER_BOILER_ALERT "\xf3\xb1\x86\xb3" // U+F11B3 +#define ICON_MDI_WATER_BOILER_AUTO "\xf3\xb1\xae\x98" // U+F1B98 +#define ICON_MDI_WATER_BOILER_OFF "\xf3\xb1\x86\xb4" // U+F11B4 +#define ICON_MDI_WATER_CHECK "\xf3\xb1\x94\x84" // U+F1504 +#define ICON_MDI_WATER_CHECK_OUTLINE "\xf3\xb1\x94\x85" // U+F1505 +#define ICON_MDI_WATER_CIRCLE "\xf3\xb1\xa0\x86" // U+F1806 +#define ICON_MDI_WATER_MINUS "\xf3\xb1\x94\x86" // U+F1506 +#define ICON_MDI_WATER_MINUS_OUTLINE "\xf3\xb1\x94\x87" // U+F1507 +#define ICON_MDI_WATER_OFF "\xf3\xb0\x96\x8d" // U+F058D +#define ICON_MDI_WATER_OFF_OUTLINE "\xf3\xb1\x94\x88" // U+F1508 +#define ICON_MDI_WATER_OPACITY "\xf3\xb1\xa1\x95" // U+F1855 +#define ICON_MDI_WATER_OUTLINE "\xf3\xb0\xb8\x8a" // U+F0E0A +#define ICON_MDI_WATER_PERCENT "\xf3\xb0\x96\x8e" // U+F058E +#define ICON_MDI_WATER_PERCENT_ALERT "\xf3\xb1\x94\x89" // U+F1509 +#define ICON_MDI_WATER_PLUS "\xf3\xb1\x94\x8a" // U+F150A +#define ICON_MDI_WATER_PLUS_OUTLINE "\xf3\xb1\x94\x8b" // U+F150B +#define ICON_MDI_WATER_POLO "\xf3\xb1\x8a\xa0" // U+F12A0 +#define ICON_MDI_WATER_PUMP "\xf3\xb0\x96\x8f" // U+F058F +#define ICON_MDI_WATER_PUMP_OFF "\xf3\xb0\xbe\x93" // U+F0F93 +#define ICON_MDI_WATER_REMOVE "\xf3\xb1\x94\x8c" // U+F150C +#define ICON_MDI_WATER_REMOVE_OUTLINE "\xf3\xb1\x94\x8d" // U+F150D +#define ICON_MDI_WATER_SYNC "\xf3\xb1\x9f\x86" // U+F17C6 +#define ICON_MDI_WATER_THERMOMETER "\xf3\xb1\xaa\x85" // U+F1A85 +#define ICON_MDI_WATER_THERMOMETER_OUTLINE "\xf3\xb1\xaa\x86" // U+F1A86 +#define ICON_MDI_WATER_WELL "\xf3\xb1\x81\xab" // U+F106B +#define ICON_MDI_WATER_WELL_OUTLINE "\xf3\xb1\x81\xac" // U+F106C +#define ICON_MDI_WATERFALL "\xf3\xb1\xa1\x89" // U+F1849 +#define ICON_MDI_WATERING_CAN "\xf3\xb1\x92\x81" // U+F1481 +#define ICON_MDI_WATERING_CAN_OUTLINE "\xf3\xb1\x92\x82" // U+F1482 +#define ICON_MDI_WATERMARK "\xf3\xb0\x98\x92" // U+F0612 +#define ICON_MDI_WAVE "\xf3\xb0\xbc\xae" // U+F0F2E +#define ICON_MDI_WAVE_ARROW_DOWN "\xf3\xb1\xb2\xb0" // U+F1CB0 +#define ICON_MDI_WAVE_ARROW_UP "\xf3\xb1\xb2\xb1" // U+F1CB1 +#define ICON_MDI_WAVE_UNDERCURRENT "\xf3\xb1\xb3\x80" // U+F1CC0 +#define ICON_MDI_WAVEFORM "\xf3\xb1\x91\xbd" // U+F147D +#define ICON_MDI_WAVES "\xf3\xb0\x9e\x8d" // U+F078D +#define ICON_MDI_WAVES_ARROW_LEFT "\xf3\xb1\xa1\x99" // U+F1859 +#define ICON_MDI_WAVES_ARROW_RIGHT "\xf3\xb1\xa1\x9a" // U+F185A +#define ICON_MDI_WAVES_ARROW_UP "\xf3\xb1\xa1\x9b" // U+F185B +#define ICON_MDI_WAZE "\xf3\xb0\xaf\x9e" // U+F0BDE +#define ICON_MDI_WEATHER_CLOUDY "\xf3\xb0\x96\x90" // U+F0590 +#define ICON_MDI_WEATHER_CLOUDY_ALERT "\xf3\xb0\xbc\xaf" // U+F0F2F +#define ICON_MDI_WEATHER_CLOUDY_ARROW_RIGHT "\xf3\xb0\xb9\xae" // U+F0E6E +#define ICON_MDI_WEATHER_CLOUDY_CLOCK "\xf3\xb1\xa3\xb6" // U+F18F6 +#define ICON_MDI_WEATHER_DUST "\xf3\xb1\xad\x9a" // U+F1B5A +#define ICON_MDI_WEATHER_FOG "\xf3\xb0\x96\x91" // U+F0591 +#define ICON_MDI_WEATHER_HAIL "\xf3\xb0\x96\x92" // U+F0592 +#define ICON_MDI_WEATHER_HAZY "\xf3\xb0\xbc\xb0" // U+F0F30 +#define ICON_MDI_WEATHER_HURRICANE "\xf3\xb0\xa2\x98" // U+F0898 +#define ICON_MDI_WEATHER_HURRICANE_OUTLINE "\xf3\xb1\xb1\xb8" // U+F1C78 +#define ICON_MDI_WEATHER_LIGHTNING "\xf3\xb0\x96\x93" // U+F0593 +#define ICON_MDI_WEATHER_LIGHTNING_RAINY "\xf3\xb0\x99\xbe" // U+F067E +#define ICON_MDI_WEATHER_NIGHT "\xf3\xb0\x96\x94" // U+F0594 +#define ICON_MDI_WEATHER_NIGHT_PARTLY_CLOUDY "\xf3\xb0\xbc\xb1" // U+F0F31 +#define ICON_MDI_WEATHER_PARTLY_CLOUDY "\xf3\xb0\x96\x95" // U+F0595 +#define ICON_MDI_WEATHER_PARTLY_LIGHTNING "\xf3\xb0\xbc\xb2" // U+F0F32 +#define ICON_MDI_WEATHER_PARTLY_RAINY "\xf3\xb0\xbc\xb3" // U+F0F33 +#define ICON_MDI_WEATHER_PARTLY_SNOWY "\xf3\xb0\xbc\xb4" // U+F0F34 +#define ICON_MDI_WEATHER_PARTLY_SNOWY_RAINY "\xf3\xb0\xbc\xb5" // U+F0F35 +#define ICON_MDI_WEATHER_POURING "\xf3\xb0\x96\x96" // U+F0596 +#define ICON_MDI_WEATHER_RAINY "\xf3\xb0\x96\x97" // U+F0597 +#define ICON_MDI_WEATHER_SNOWY "\xf3\xb0\x96\x98" // U+F0598 +#define ICON_MDI_WEATHER_SNOWY_HEAVY "\xf3\xb0\xbc\xb6" // U+F0F36 +#define ICON_MDI_WEATHER_SNOWY_RAINY "\xf3\xb0\x99\xbf" // U+F067F +#define ICON_MDI_WEATHER_SUNNY "\xf3\xb0\x96\x99" // U+F0599 +#define ICON_MDI_WEATHER_SUNNY_ALERT "\xf3\xb0\xbc\xb7" // U+F0F37 +#define ICON_MDI_WEATHER_SUNNY_OFF "\xf3\xb1\x93\xa4" // U+F14E4 +#define ICON_MDI_WEATHER_SUNSET "\xf3\xb0\x96\x9a" // U+F059A +#define ICON_MDI_WEATHER_SUNSET_DOWN "\xf3\xb0\x96\x9b" // U+F059B +#define ICON_MDI_WEATHER_SUNSET_UP "\xf3\xb0\x96\x9c" // U+F059C +#define ICON_MDI_WEATHER_TORNADO "\xf3\xb0\xbc\xb8" // U+F0F38 +#define ICON_MDI_WEATHER_WINDY "\xf3\xb0\x96\x9d" // U+F059D +#define ICON_MDI_WEATHER_WINDY_VARIANT "\xf3\xb0\x96\x9e" // U+F059E +#define ICON_MDI_WEB "\xf3\xb0\x96\x9f" // U+F059F +#define ICON_MDI_WEB_BOX "\xf3\xb0\xbe\x94" // U+F0F94 +#define ICON_MDI_WEB_CANCEL "\xf3\xb1\x9e\x90" // U+F1790 +#define ICON_MDI_WEB_CHECK "\xf3\xb0\x9e\x89" // U+F0789 +#define ICON_MDI_WEB_CLOCK "\xf3\xb1\x89\x8a" // U+F124A +#define ICON_MDI_WEB_MINUS "\xf3\xb1\x82\xa0" // U+F10A0 +#define ICON_MDI_WEB_OFF "\xf3\xb0\xaa\x8e" // U+F0A8E +#define ICON_MDI_WEB_PLUS "\xf3\xb0\x80\xb3" // U+F0033 +#define ICON_MDI_WEB_REFRESH "\xf3\xb1\x9e\x91" // U+F1791 +#define ICON_MDI_WEB_REMOVE "\xf3\xb0\x95\x91" // U+F0551 +#define ICON_MDI_WEB_SYNC "\xf3\xb1\x9e\x92" // U+F1792 +#define ICON_MDI_WEBCAM "\xf3\xb0\x96\xa0" // U+F05A0 +#define ICON_MDI_WEBCAM_OFF "\xf3\xb1\x9c\xb7" // U+F1737 +#define ICON_MDI_WEBHOOK "\xf3\xb0\x98\xaf" // U+F062F +#define ICON_MDI_WEBPACK "\xf3\xb0\x9c\xab" // U+F072B +#define ICON_MDI_WEBRTC "\xf3\xb1\x89\x88" // U+F1248 +#define ICON_MDI_WECHAT "\xf3\xb0\x98\x91" // U+F0611 +#define ICON_MDI_WEIGHT "\xf3\xb0\x96\xa1" // U+F05A1 +#define ICON_MDI_WEIGHT_GRAM "\xf3\xb0\xb4\xbf" // U+F0D3F +#define ICON_MDI_WEIGHT_KILOGRAM "\xf3\xb0\x96\xa2" // U+F05A2 +#define ICON_MDI_WEIGHT_LIFTER "\xf3\xb1\x85\x9d" // U+F115D +#define ICON_MDI_WEIGHT_POUND "\xf3\xb0\xa6\xb5" // U+F09B5 +#define ICON_MDI_WHATSAPP "\xf3\xb0\x96\xa3" // U+F05A3 +#define ICON_MDI_WHEEL_BARROW "\xf3\xb1\x93\xb2" // U+F14F2 +#define ICON_MDI_WHEELCHAIR "\xf3\xb1\xaa\x87" // U+F1A87 +#define ICON_MDI_WHEELCHAIR_ACCESSIBILITY "\xf3\xb0\x96\xa4" // U+F05A4 +#define ICON_MDI_WHISTLE "\xf3\xb0\xa6\xb6" // U+F09B6 +#define ICON_MDI_WHISTLE_OUTLINE "\xf3\xb1\x8a\xbc" // U+F12BC +#define ICON_MDI_WHITE_BALANCE_AUTO "\xf3\xb0\x96\xa5" // U+F05A5 +#define ICON_MDI_WHITE_BALANCE_INCANDESCENT "\xf3\xb0\x96\xa6" // U+F05A6 +#define ICON_MDI_WHITE_BALANCE_IRIDESCENT "\xf3\xb0\x96\xa7" // U+F05A7 +#define ICON_MDI_WHITE_BALANCE_SUNNY "\xf3\xb0\x96\xa8" // U+F05A8 +#define ICON_MDI_WIDGETS "\xf3\xb0\x9c\xac" // U+F072C +#define ICON_MDI_WIDGETS_OUTLINE "\xf3\xb1\x8d\x95" // U+F1355 +#define ICON_MDI_WIFI "\xf3\xb0\x96\xa9" // U+F05A9 +#define ICON_MDI_WIFI_ALERT "\xf3\xb1\x9a\xb5" // U+F16B5 +#define ICON_MDI_WIFI_ARROW_DOWN "\xf3\xb1\x9a\xb6" // U+F16B6 +#define ICON_MDI_WIFI_ARROW_LEFT "\xf3\xb1\x9a\xb7" // U+F16B7 +#define ICON_MDI_WIFI_ARROW_LEFT_RIGHT "\xf3\xb1\x9a\xb8" // U+F16B8 +#define ICON_MDI_WIFI_ARROW_RIGHT "\xf3\xb1\x9a\xb9" // U+F16B9 +#define ICON_MDI_WIFI_ARROW_UP "\xf3\xb1\x9a\xba" // U+F16BA +#define ICON_MDI_WIFI_ARROW_UP_DOWN "\xf3\xb1\x9a\xbb" // U+F16BB +#define ICON_MDI_WIFI_CANCEL "\xf3\xb1\x9a\xbc" // U+F16BC +#define ICON_MDI_WIFI_CHECK "\xf3\xb1\x9a\xbd" // U+F16BD +#define ICON_MDI_WIFI_COG "\xf3\xb1\x9a\xbe" // U+F16BE +#define ICON_MDI_WIFI_LOCK "\xf3\xb1\x9a\xbf" // U+F16BF +#define ICON_MDI_WIFI_LOCK_OPEN "\xf3\xb1\x9b\x80" // U+F16C0 +#define ICON_MDI_WIFI_MARKER "\xf3\xb1\x9b\x81" // U+F16C1 +#define ICON_MDI_WIFI_MINUS "\xf3\xb1\x9b\x82" // U+F16C2 +#define ICON_MDI_WIFI_OFF "\xf3\xb0\x96\xaa" // U+F05AA +#define ICON_MDI_WIFI_PLUS "\xf3\xb1\x9b\x83" // U+F16C3 +#define ICON_MDI_WIFI_REFRESH "\xf3\xb1\x9b\x84" // U+F16C4 +#define ICON_MDI_WIFI_REMOVE "\xf3\xb1\x9b\x85" // U+F16C5 +#define ICON_MDI_WIFI_SETTINGS "\xf3\xb1\x9b\x86" // U+F16C6 +#define ICON_MDI_WIFI_STAR "\xf3\xb0\xb8\x8b" // U+F0E0B +#define ICON_MDI_WIFI_STRENGTH_1 "\xf3\xb0\xa4\x9f" // U+F091F +#define ICON_MDI_WIFI_STRENGTH_1_ALERT "\xf3\xb0\xa4\xa0" // U+F0920 +#define ICON_MDI_WIFI_STRENGTH_1_LOCK "\xf3\xb0\xa4\xa1" // U+F0921 +#define ICON_MDI_WIFI_STRENGTH_1_LOCK_OPEN "\xf3\xb1\x9b\x8b" // U+F16CB +#define ICON_MDI_WIFI_STRENGTH_2 "\xf3\xb0\xa4\xa2" // U+F0922 +#define ICON_MDI_WIFI_STRENGTH_2_ALERT "\xf3\xb0\xa4\xa3" // U+F0923 +#define ICON_MDI_WIFI_STRENGTH_2_LOCK "\xf3\xb0\xa4\xa4" // U+F0924 +#define ICON_MDI_WIFI_STRENGTH_2_LOCK_OPEN "\xf3\xb1\x9b\x8c" // U+F16CC +#define ICON_MDI_WIFI_STRENGTH_3 "\xf3\xb0\xa4\xa5" // U+F0925 +#define ICON_MDI_WIFI_STRENGTH_3_ALERT "\xf3\xb0\xa4\xa6" // U+F0926 +#define ICON_MDI_WIFI_STRENGTH_3_LOCK "\xf3\xb0\xa4\xa7" // U+F0927 +#define ICON_MDI_WIFI_STRENGTH_3_LOCK_OPEN "\xf3\xb1\x9b\x8d" // U+F16CD +#define ICON_MDI_WIFI_STRENGTH_4 "\xf3\xb0\xa4\xa8" // U+F0928 +#define ICON_MDI_WIFI_STRENGTH_4_ALERT "\xf3\xb0\xa4\xa9" // U+F0929 +#define ICON_MDI_WIFI_STRENGTH_4_LOCK "\xf3\xb0\xa4\xaa" // U+F092A +#define ICON_MDI_WIFI_STRENGTH_4_LOCK_OPEN "\xf3\xb1\x9b\x8e" // U+F16CE +#define ICON_MDI_WIFI_STRENGTH_ALERT_OUTLINE "\xf3\xb0\xa4\xab" // U+F092B +#define ICON_MDI_WIFI_STRENGTH_LOCK_OPEN_OUTLINE "\xf3\xb1\x9b\x8f" // U+F16CF +#define ICON_MDI_WIFI_STRENGTH_LOCK_OUTLINE "\xf3\xb0\xa4\xac" // U+F092C +#define ICON_MDI_WIFI_STRENGTH_OFF "\xf3\xb0\xa4\xad" // U+F092D +#define ICON_MDI_WIFI_STRENGTH_OFF_OUTLINE "\xf3\xb0\xa4\xae" // U+F092E +#define ICON_MDI_WIFI_STRENGTH_OUTLINE "\xf3\xb0\xa4\xaf" // U+F092F +#define ICON_MDI_WIFI_SYNC "\xf3\xb1\x9b\x87" // U+F16C7 +#define ICON_MDI_WIKIPEDIA "\xf3\xb0\x96\xac" // U+F05AC +#define ICON_MDI_WIND_POWER "\xf3\xb1\xaa\x88" // U+F1A88 +#define ICON_MDI_WIND_POWER_OUTLINE "\xf3\xb1\xaa\x89" // U+F1A89 +#define ICON_MDI_WIND_TURBINE "\xf3\xb0\xb6\xa5" // U+F0DA5 +#define ICON_MDI_WIND_TURBINE_ALERT "\xf3\xb1\xa6\xab" // U+F19AB +#define ICON_MDI_WIND_TURBINE_CHECK "\xf3\xb1\xa6\xac" // U+F19AC +#define ICON_MDI_WINDOW_CLOSE "\xf3\xb0\x96\xad" // U+F05AD +#define ICON_MDI_WINDOW_CLOSED "\xf3\xb0\x96\xae" // U+F05AE +#define ICON_MDI_WINDOW_CLOSED_VARIANT "\xf3\xb1\x87\x9b" // U+F11DB +#define ICON_MDI_WINDOW_MAXIMIZE "\xf3\xb0\x96\xaf" // U+F05AF +#define ICON_MDI_WINDOW_MINIMIZE "\xf3\xb0\x96\xb0" // U+F05B0 +#define ICON_MDI_WINDOW_OPEN "\xf3\xb0\x96\xb1" // U+F05B1 +#define ICON_MDI_WINDOW_OPEN_VARIANT "\xf3\xb1\x87\x9c" // U+F11DC +#define ICON_MDI_WINDOW_RESTORE "\xf3\xb0\x96\xb2" // U+F05B2 +#define ICON_MDI_WINDOW_SHUTTER "\xf3\xb1\x84\x9c" // U+F111C +#define ICON_MDI_WINDOW_SHUTTER_ALERT "\xf3\xb1\x84\x9d" // U+F111D +#define ICON_MDI_WINDOW_SHUTTER_AUTO "\xf3\xb1\xae\xa3" // U+F1BA3 +#define ICON_MDI_WINDOW_SHUTTER_COG "\xf3\xb1\xaa\x8a" // U+F1A8A +#define ICON_MDI_WINDOW_SHUTTER_OPEN "\xf3\xb1\x84\x9e" // U+F111E +#define ICON_MDI_WINDOW_SHUTTER_SETTINGS "\xf3\xb1\xaa\x8b" // U+F1A8B +#define ICON_MDI_WINDSOCK "\xf3\xb1\x97\xba" // U+F15FA +#define ICON_MDI_WIPER "\xf3\xb0\xab\xa9" // U+F0AE9 +#define ICON_MDI_WIPER_WASH "\xf3\xb0\xb6\xa6" // U+F0DA6 +#define ICON_MDI_WIPER_WASH_ALERT "\xf3\xb1\xa3\x9f" // U+F18DF +#define ICON_MDI_WIZARD_HAT "\xf3\xb1\x91\xb7" // U+F1477 +#define ICON_MDI_WORDPRESS "\xf3\xb0\x96\xb4" // U+F05B4 +#define ICON_MDI_WRAP "\xf3\xb0\x96\xb6" // U+F05B6 +#define ICON_MDI_WRAP_DISABLED "\xf3\xb0\xaf\x9f" // U+F0BDF +#define ICON_MDI_WRENCH "\xf3\xb0\x96\xb7" // U+F05B7 +#define ICON_MDI_WRENCH_CHECK "\xf3\xb1\xae\x8f" // U+F1B8F +#define ICON_MDI_WRENCH_CHECK_OUTLINE "\xf3\xb1\xae\x90" // U+F1B90 +#define ICON_MDI_WRENCH_CLOCK "\xf3\xb1\xa6\xa3" // U+F19A3 +#define ICON_MDI_WRENCH_CLOCK_OUTLINE "\xf3\xb1\xae\x93" // U+F1B93 +#define ICON_MDI_WRENCH_COG "\xf3\xb1\xae\x91" // U+F1B91 +#define ICON_MDI_WRENCH_COG_OUTLINE "\xf3\xb1\xae\x92" // U+F1B92 +#define ICON_MDI_WRENCH_OUTLINE "\xf3\xb0\xaf\xa0" // U+F0BE0 +#define ICON_MDI_XAMARIN "\xf3\xb0\xa1\x85" // U+F0845 +#define ICON_MDI_XML "\xf3\xb0\x97\x80" // U+F05C0 +#define ICON_MDI_XMPP "\xf3\xb0\x9f\xbf" // U+F07FF +#define ICON_MDI_YAHOO "\xf3\xb0\xad\x8f" // U+F0B4F +#define ICON_MDI_YEAST "\xf3\xb0\x97\x81" // U+F05C1 +#define ICON_MDI_YIN_YANG "\xf3\xb0\x9a\x80" // U+F0680 +#define ICON_MDI_YOGA "\xf3\xb1\x85\xbc" // U+F117C +#define ICON_MDI_YOUTUBE "\xf3\xb0\x97\x83" // U+F05C3 +#define ICON_MDI_YOUTUBE_GAMING "\xf3\xb0\xa1\x88" // U+F0848 +#define ICON_MDI_YOUTUBE_STUDIO "\xf3\xb0\xa1\x87" // U+F0847 +#define ICON_MDI_YOUTUBE_SUBSCRIPTION "\xf3\xb0\xb5\x80" // U+F0D40 +#define ICON_MDI_YOUTUBE_TV "\xf3\xb0\x91\x88" // U+F0448 +#define ICON_MDI_YURT "\xf3\xb1\x94\x96" // U+F1516 +#define ICON_MDI_Z_WAVE "\xf3\xb0\xab\xaa" // U+F0AEA +#define ICON_MDI_ZEND "\xf3\xb0\xab\xab" // U+F0AEB +#define ICON_MDI_ZIGBEE "\xf3\xb0\xb5\x81" // U+F0D41 +#define ICON_MDI_ZIP_BOX "\xf3\xb0\x97\x84" // U+F05C4 +#define ICON_MDI_ZIP_BOX_OUTLINE "\xf3\xb0\xbf\xba" // U+F0FFA +#define ICON_MDI_ZIP_DISK "\xf3\xb0\xa8\xa3" // U+F0A23 +#define ICON_MDI_ZODIAC_AQUARIUS "\xf3\xb0\xa9\xbd" // U+F0A7D +#define ICON_MDI_ZODIAC_ARIES "\xf3\xb0\xa9\xbe" // U+F0A7E +#define ICON_MDI_ZODIAC_CANCER "\xf3\xb0\xa9\xbf" // U+F0A7F +#define ICON_MDI_ZODIAC_CAPRICORN "\xf3\xb0\xaa\x80" // U+F0A80 +#define ICON_MDI_ZODIAC_GEMINI "\xf3\xb0\xaa\x81" // U+F0A81 +#define ICON_MDI_ZODIAC_LEO "\xf3\xb0\xaa\x82" // U+F0A82 +#define ICON_MDI_ZODIAC_LIBRA "\xf3\xb0\xaa\x83" // U+F0A83 +#define ICON_MDI_ZODIAC_PISCES "\xf3\xb0\xaa\x84" // U+F0A84 +#define ICON_MDI_ZODIAC_SAGITTARIUS "\xf3\xb0\xaa\x85" // U+F0A85 +#define ICON_MDI_ZODIAC_SCORPIO "\xf3\xb0\xaa\x86" // U+F0A86 +#define ICON_MDI_ZODIAC_TAURUS "\xf3\xb0\xaa\x87" // U+F0A87 +#define ICON_MDI_ZODIAC_VIRGO "\xf3\xb0\xaa\x88" // U+F0A88 +#define ICON_MDI_BLANK "\xef\x9a\x8c" // U+F68C +#line 0 +// editor_script +#define GLEQ_IMPLEMENTATION +#line 1 "3rd_lite_sys_gleq.h" +/* + * GLEQ - A basic event queue for GLFW 3 + * Copyright © Camilla Löwy + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would + * be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ + +#ifndef GLEQ_HEADER_FILE +#define GLEQ_HEADER_FILE + +// #include + +#ifdef GLEQ_STATIC + #define GLEQDEF static +#else + #define GLEQDEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + GLEQ_NONE = 0, + GLEQ_WINDOW_MOVED = 1<<1, + GLEQ_WINDOW_RESIZED = 1<<2, + GLEQ_WINDOW_CLOSED = 1<<3, + GLEQ_WINDOW_REFRESH = 1<<4, + GLEQ_WINDOW_FOCUSED = 1<<5, + GLEQ_WINDOW_DEFOCUSED = 1<<6, + GLEQ_WINDOW_ICONIFIED = 1<<7, + GLEQ_WINDOW_UNICONIFIED = 1<<8, + GLEQ_FRAMEBUFFER_RESIZED = 1<<9, + GLEQ_BUTTON_PRESSED = 1<<10, + GLEQ_BUTTON_RELEASED = 1<<11, + GLEQ_CURSOR_MOVED = 1<<12, + GLEQ_CURSOR_ENTERED = 1<<13, + GLEQ_CURSOR_LEFT = 1<<14, + GLEQ_SCROLLED = 1<<15, + GLEQ_KEY_PRESSED = 1<<16, + GLEQ_KEY_REPEATED = 1<<17, + GLEQ_KEY_RELEASED = 1<<18, + GLEQ_CODEPOINT_INPUT = 1<<19, + GLEQ_MONITOR_CONNECTED = 1<<20, + GLEQ_MONITOR_DISCONNECTED = 1<<21, +#if GLFW_VERSION_MINOR >= 1 + GLEQ_FILE_DROPPED = 1<<22, +#endif +#if GLFW_VERSION_MINOR >= 2 + GLEQ_JOYSTICK_CONNECTED = 1<<23, + GLEQ_JOYSTICK_DISCONNECTED = 1<<24, +#endif +#if GLFW_VERSION_MINOR >= 3 + GLEQ_WINDOW_MAXIMIZED = 1<<25, + GLEQ_WINDOW_UNMAXIMIZED = 1<<26, + GLEQ_WINDOW_SCALE_CHANGED = 1<<27, +#endif +} GLEQtype; + +typedef struct GLEQevent +{ + unsigned/*GLEQtype*/ type; + union { + GLFWwindow* window; + GLFWmonitor* monitor; + int joystick; + }; + union { + struct { + int x; + int y; + } pos; + struct { + int width; + int height; + } size; + struct { + double x; + double y; + } scroll; + struct { + int key; + int scancode; + int mods; + } keyboard; + struct { + int button; + int mods; + } mouse; + unsigned int codepoint; +#if GLFW_VERSION_MINOR >= 1 + struct { + char** paths; + int count; + } file; +#endif +#if GLFW_VERSION_MINOR >= 3 + struct { + float x; + float y; + } scale; +#endif + }; +} GLEQevent; + +GLEQDEF void gleqInit(void); +GLEQDEF void gleqTrackWindow(GLFWwindow* window); + +GLEQDEF int gleqNextEvent(GLEQevent* event); +GLEQDEF void gleqFreeEvent(GLEQevent* event); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEQ_IMPLEMENTATION + +#include +#include +#include + +#ifndef GLEQ_CAPACITY + #define GLEQ_CAPACITY 1024 +#endif + +static struct +{ + GLEQevent events[GLEQ_CAPACITY]; + size_t head; + size_t tail; +} gleq_queue = { {0}, 0, 0 }; + +static char* gleq_strdup(const char* string) +{ + const size_t size = strlen(string) + 1; + char* result = (char*) malloc(size); + memcpy(result, string, size); + return result; +} + +static GLEQevent* gleq_new_event(void) +{ + GLEQevent* event = gleq_queue.events + gleq_queue.head; + gleq_queue.head = (gleq_queue.head + 1) % GLEQ_CAPACITY; + assert(gleq_queue.head != gleq_queue.tail); + memset(event, 0, sizeof(GLEQevent)); + return event; +} + +static void gleq_window_pos_callback(GLFWwindow* window, int x, int y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_MOVED; + event->window = window; + event->pos.x = x; + event->pos.y = y; +} + +static void gleq_window_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_window_close_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_CLOSED; + event->window = window; +} + +static void gleq_window_refresh_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_REFRESH; + event->window = window; +} + +static void gleq_window_focus_callback(GLFWwindow* window, int focused) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (focused) + event->type = GLEQ_WINDOW_FOCUSED; + else + event->type = GLEQ_WINDOW_DEFOCUSED; +} + +static void gleq_window_iconify_callback(GLFWwindow* window, int iconified) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (iconified) + event->type = GLEQ_WINDOW_ICONIFIED; + else + event->type = GLEQ_WINDOW_UNICONIFIED; +} + +static void gleq_framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FRAMEBUFFER_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->mouse.button = button; + event->mouse.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_BUTTON_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_BUTTON_RELEASED; +} + +static void gleq_cursor_pos_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CURSOR_MOVED; + event->window = window; + event->pos.x = (int) x; + event->pos.y = (int) y; +} + +static void gleq_cursor_enter_callback(GLFWwindow* window, int entered) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (entered) + event->type = GLEQ_CURSOR_ENTERED; + else + event->type = GLEQ_CURSOR_LEFT; +} + +static void gleq_scroll_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_SCROLLED; + event->window = window; + event->scroll.x = x; + event->scroll.y = y; +} + +static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->keyboard.key = key; + event->keyboard.scancode = scancode; + event->keyboard.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_KEY_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_KEY_RELEASED; + else if (action == GLFW_REPEAT) + event->type = GLEQ_KEY_REPEATED; +} + +static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CODEPOINT_INPUT; + event->window = window; + event->codepoint = codepoint; +} + +static void gleq_monitor_callback(GLFWmonitor* monitor, int action) +{ + GLEQevent* event = gleq_new_event(); + event->monitor = monitor; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_MONITOR_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_MONITOR_DISCONNECTED; +} + +#if GLFW_VERSION_MINOR >= 1 +static void gleq_file_drop_callback(GLFWwindow* window, int count, const char** paths) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FILE_DROPPED; + event->window = window; + event->file.paths = (char**) malloc(count * sizeof(char*)); + event->file.count = count; + + while (count--) + event->file.paths[count] = gleq_strdup(paths[count]); +} +#endif + +#if GLFW_VERSION_MINOR >= 2 +static void gleq_joystick_callback(int jid, int action) +{ + GLEQevent* event = gleq_new_event(); + event->joystick = jid; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_JOYSTICK_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_JOYSTICK_DISCONNECTED; +} +#endif + +#if GLFW_VERSION_MINOR >= 3 +static void gleq_window_maximize_callback(GLFWwindow* window, int maximized) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (maximized) + event->type = GLEQ_WINDOW_MAXIMIZED; + else + event->type = GLEQ_WINDOW_UNMAXIMIZED; +} + +static void gleq_window_content_scale_callback(GLFWwindow* window, float xscale, float yscale) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->type = GLEQ_WINDOW_SCALE_CHANGED; + event->scale.x = xscale; + event->scale.y = yscale; +} +#endif + +GLEQDEF void gleqInit(void) +{ + glfwSetMonitorCallback(gleq_monitor_callback); +#if GLFW_VERSION_MINOR >= 2 + glfwSetJoystickCallback(gleq_joystick_callback); +#endif +} + +GLEQDEF void gleqTrackWindow(GLFWwindow* window) +{ + glfwSetWindowPosCallback(window, gleq_window_pos_callback); + glfwSetWindowSizeCallback(window, gleq_window_size_callback); + glfwSetWindowCloseCallback(window, gleq_window_close_callback); + glfwSetWindowRefreshCallback(window, gleq_window_refresh_callback); + glfwSetWindowFocusCallback(window, gleq_window_focus_callback); + glfwSetWindowIconifyCallback(window, gleq_window_iconify_callback); + glfwSetFramebufferSizeCallback(window, gleq_framebuffer_size_callback); + glfwSetMouseButtonCallback(window, gleq_mouse_button_callback); + glfwSetCursorPosCallback(window, gleq_cursor_pos_callback); + glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback); + glfwSetScrollCallback(window, gleq_scroll_callback); + glfwSetKeyCallback(window, gleq_key_callback); + glfwSetCharCallback(window, gleq_char_callback); +#if GLFW_VERSION_MINOR >= 1 + glfwSetDropCallback(window, gleq_file_drop_callback); +#endif +#if GLFW_VERSION_MINOR >= 3 + glfwSetWindowMaximizeCallback(window, gleq_window_maximize_callback); + glfwSetWindowContentScaleCallback(window, gleq_window_content_scale_callback); +#endif +} + +GLEQDEF int gleqNextEvent(GLEQevent* event) +{ + memset(event, 0, sizeof(GLEQevent)); + + if (gleq_queue.head != gleq_queue.tail) + { + *event = gleq_queue.events[gleq_queue.tail]; + gleq_queue.tail = (gleq_queue.tail + 1) % GLEQ_CAPACITY; + } + + return event->type != GLEQ_NONE; +} + +GLEQDEF void gleqFreeEvent(GLEQevent* event) +{ +#if GLFW_VERSION_MINOR >= 1 + if (event->type == GLEQ_FILE_DROPPED) + { + while (event->file.count--) + free(event->file.paths[event->file.count]); + + free(event->file.paths); + } +#endif + + memset(event, 0, sizeof(GLEQevent)); +} + +#endif /* GLEQ_IMPLEMENTATION */ + +#endif /* GLEQ_HEADER_FILE */ +#line 0 +#line 1 "3rd_lite_sys.h" +// lite editor, platform details +// - rlyeh, public domain + +#define LT_DATAPATH "/lite" + +#define lt_assert(x) ASSERT(x) + +#define lt_realpath(p, q) file_pathabs(p) +#define lt_realpath_free(p) + +#define lt_malloc(n) MALLOC(n) +#define lt_calloc(n,m) CALLOC(n,m) +#define lt_free(p) FREE(p) +#define lt_memcpy(d,s,c) memcpy(d,s,c) +#define lt_memset(p,ch,c) memset(p,ch,c) + +#define lt_time_ms() time_ms() +#define lt_sleep_ms(ms) sleep_ms(ms) + +#define lt_getclipboard(w) window_clipboard() +#define lt_setclipboard(w,s) window_setclipboard(s) + +#define lt_window() window_handle() +#define lt_setwindowmode(m) window_fullscreen(m == 2), (m < 2 && (window_maximize(m),1)) // 0:normal,1:maximized,2:fullscreen +#define lt_setwindowtitle(t) //window_title(t) +#define lt_haswindowfocus() window_has_focus() +#define lt_setcursor(shape) window_cursor_shape(lt_events & (1<<31) ? CURSOR_SW_AUTO : shape+1) // 0:arrow,1:ibeam,2:sizeh,3:sizev,4:hand + +#define lt_prompt(msg,title) ifndef(win32, 0, (MessageBoxA(0, msg, title, MB_YESNO | MB_ICONWARNING) == IDYES)) + +unsigned lt_events = ~0u; +int lt_mx = 0, lt_my = 0, lt_wx = 0, lt_wy = 0, lt_ww = 0, lt_wh = 0; + +typedef struct lt_surface { + unsigned w, h; + void *pixels; + texture_t t; +} lt_surface; + +typedef struct lt_rect { + int x, y, width, height; +} lt_rect; + +lt_surface *lt_getsurface(void *window) { + static lt_surface s = {0}; + return &s; +} +void lt_updatesurfacerects(lt_surface *s, lt_rect* rects, unsigned count) { + if(0) + for( int i = 0; i < count; ++i ) { + memset( (unsigned*)s->pixels + (rects[i].x + rects[i].y * s->w), 0xFF, rects[i].width*4 ); + memset( (unsigned*)s->pixels + (rects[i].x + (rects[i].y + (rects[i].height-1)) * s->w), 0xFF, rects[i].width*4 ); + for( int y = 1; y < (rects[i].height-1); ++y ) { + ((unsigned*)s->pixels)[ rects[i].x + y * s->w ] = + ((unsigned*)s->pixels)[ rects[i].x + (rects[i].width-1) + y * s->w ] = 0xFFFFFFFF; + } + } + + // update contents + texture_update(&s->t, s->w, s->h, 4, s->pixels, TEXTURE_LINEAR|TEXTURE_BGRA); +} + +void ren_set_clip_rect(struct lt_rect rect); +void rencache_invalidate(void); +int lt_resizesurface(lt_surface *s, int ww, int wh) { + s->w = ww, s->h = wh; + if( s->t.id == 0 || s->w != s->t.w || s->h != s->t.h ) { + // invalidate tiles + ren_set_clip_rect( (lt_rect) { 0, 0, s->w, s->h } ); + rencache_invalidate(); + + // texture clear + if( !s->t.id ) s->t = texture_create(1, 1, 4, " ", TEXTURE_LINEAR|TEXTURE_RGBA|TEXTURE_BYTE ); + s->pixels = REALLOC(s->pixels, s->w * s->h * 4); + memset(s->pixels, 0, s->w * s->h * 4); + + // texture update + lt_updatesurfacerects(s,0,0); + return 1; // resized + } + return 0; // unchanged +} + +void *lt_load_file(const char *filename, int *size) { + int datalen; char *data = file_load(filename, &datalen); + if( !data || !datalen ) { + filename = (const char *)file_normalize(filename); + if( strbegi(filename, app_path()) ) filename += strlen(app_path()); + data = vfs_load(filename, &datalen); + } + if (size) *size = 0; + if (!data) { return NULL; } + if (size) *size = datalen; + // return permanent buffers here, as file_load() and vfs_load() do return temporaries + data = memcpy(MALLOC(datalen+1), data, datalen); + data[datalen] = 0; + return data; +} + +const char* lt_button_name(int button) { + if(button == GLFW_MOUSE_BUTTON_LEFT) return "left"; + if(button == GLFW_MOUSE_BUTTON_RIGHT) return "right"; + if(button == GLFW_MOUSE_BUTTON_MIDDLE) return "middle"; + return "?"; +} + +char* lt_key_name(char *dst, int key, int vk, int mods) { + // @todo: "altgr" -> left ctrl + right alt + + if( key == GLFW_KEY_UP ) return "up"; + if( key == GLFW_KEY_DOWN ) return "down"; + if( key == GLFW_KEY_LEFT ) return "left"; + if( key == GLFW_KEY_RIGHT ) return "right"; + if( key == GLFW_KEY_LEFT_ALT ) return "left alt"; + if( key == GLFW_KEY_RIGHT_ALT ) return "right alt"; + if( key == GLFW_KEY_LEFT_SHIFT ) return "left shift"; + if( key == GLFW_KEY_RIGHT_SHIFT ) return "right shift"; + if( key == GLFW_KEY_LEFT_CONTROL ) return "left ctrl"; + if( key == GLFW_KEY_RIGHT_CONTROL ) return "right ctrl"; + if( key == GLFW_KEY_LEFT_SUPER ) return "left windows"; + if( key == GLFW_KEY_RIGHT_SUPER ) return "left windows"; + if( key == GLFW_KEY_MENU ) return "menu"; + + if( key == GLFW_KEY_ESCAPE ) return "escape"; + if( key == GLFW_KEY_BACKSPACE ) return "backspace"; + if( key == GLFW_KEY_ENTER ) return "return"; + if( key == GLFW_KEY_KP_ENTER ) return "keypad enter"; + if( key == GLFW_KEY_TAB ) return "tab"; + if( key == GLFW_KEY_CAPS_LOCK ) return "capslock"; + + if( key == GLFW_KEY_HOME ) return "home"; + if( key == GLFW_KEY_END ) return "end"; + if( key == GLFW_KEY_INSERT ) return "insert"; + if( key == GLFW_KEY_DELETE ) return "delete"; + if( key == GLFW_KEY_PAGE_UP ) return "pageup"; + if( key == GLFW_KEY_PAGE_DOWN ) return "pagedown"; + + if( key == GLFW_KEY_F1 ) return "f1"; + if( key == GLFW_KEY_F2 ) return "f2"; + if( key == GLFW_KEY_F3 ) return "f3"; + if( key == GLFW_KEY_F4 ) return "f4"; + if( key == GLFW_KEY_F5 ) return "f5"; + if( key == GLFW_KEY_F6 ) return "f6"; + if( key == GLFW_KEY_F7 ) return "f7"; + if( key == GLFW_KEY_F8 ) return "f8"; + if( key == GLFW_KEY_F9 ) return "f9"; + if( key == GLFW_KEY_F10 ) return "f10"; + if( key == GLFW_KEY_F11 ) return "f11"; + if( key == GLFW_KEY_F12 ) return "f12"; + + const char *name = glfwGetKeyName(key, vk); + strcpy(dst, name ? name : ""); + char *p = dst; + while (*p) { + *p = tolower(*p); + p++; + } + return dst; +} + +void lt_globpath(struct lua_State*L, const char *path) { + unsigned j = 0; + + if(!strend(path, "/")) path = (const char *)va("%s/", path); + for( dir *d = dir_open(path, ""); d; dir_close(d), d = 0 ) { + for( unsigned i = 0, end = dir_count(d); i < end; ++i ) { + char *name = dir_name(d,i); + char *last = name + strlen(name) - 1; + if( *last == '/' ) *last = '\0'; + name = file_name(name); + lua_pushstring(L, name); + lua_rawseti(L, -2, ++j); + } + } + + for( const char *section = strstri(path, LT_DATAPATH); section && section[sizeof(LT_DATAPATH)-1] == '/'; section = 0) { + array(char*) list = vfs_list("**"); + for( unsigned i = 0, end = array_count(list); i < end; ++i ) { + char *name = list[i]; + if( !strstri(name, section+1) ) continue; + lua_pushstring(L, file_name(name)); + lua_rawseti(L, -2, ++j); + } + if( array_count(list) ) return; + } +} + +int lt_emit_event(lua_State *L, const char *event_name, const char *event_fmt, ...) { + int count = 0; + lua_pushstring(L, event_name); + if( event_fmt ) { + va_list va; + va_start(va, event_fmt); + for( ; event_fmt[count]; ++count ) { + /**/ if( event_fmt[count] == 'd' ) { int d = va_arg(va, int); lua_pushnumber(L, d); } + else if( event_fmt[count] == 'f' ) { double f = va_arg(va, double); lua_pushnumber(L, f); } + else if( event_fmt[count] == 's' ) { const char *s = va_arg(va, const char *); lua_pushstring(L, s); } + } + va_end(va); + } + return 1+count; +} + +int printi(int i) { + // printf("clicks: %d\n", i); + return i; +} + +static const char* codepoint_to_utf8(unsigned c); +int lt_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = 0; + char buf[16]; + static int prevx = 0, prevy = 0; + + static unsigned clicks_time = 0, clicks = 0; + if( (lt_time_ms() - clicks_time) > 400 ) clicks = 0; + + // + + for( GLEQevent e; gleqNextEvent(&e); gleqFreeEvent(&e) ) + if( lt_events & e.type ) + switch (e.type) { + default: + break; case GLEQ_WINDOW_CLOSED: // it used to be ok. depends on window_swap() flow + rc += lt_emit_event(L, "quit", NULL); + return rc; + + break; case GLEQ_WINDOW_MOVED: + lt_wx = e.pos.x; + lt_wy = e.pos.y; + + break; case GLEQ_WINDOW_RESIZED: + rc += lt_emit_event(L, "resized", "dd", lt_ww = e.size.width, lt_wh = e.size.height); + lt_resizesurface(lt_getsurface(lt_window()), lt_ww, lt_wh); + + break; case GLEQ_WINDOW_REFRESH: + rc += lt_emit_event(L, "exposed", NULL); + rencache_invalidate(); + + break; case GLEQ_FILE_DROPPED: + rc += lt_emit_event(L, "filedropped", "sdd", e.file.paths[0], lt_mx, lt_my); + + break; case GLEQ_KEY_PRESSED: + case GLEQ_KEY_REPEATED: + rc += lt_emit_event(L, "keypressed", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_KEY_RELEASED: + rc += lt_emit_event(L, "keyreleased", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_CODEPOINT_INPUT: + rc += lt_emit_event(L, "textinput", "s", codepoint_to_utf8(e.codepoint)); + + break; case GLEQ_BUTTON_PRESSED: + rc += lt_emit_event(L, "mousepressed", "sddd", lt_button_name(e.mouse.button), lt_mx, lt_my, printi(1 + clicks)); + + break; case GLEQ_BUTTON_RELEASED: + clicks += e.mouse.button == GLFW_MOUSE_BUTTON_1; + clicks_time = lt_time_ms(); + rc += lt_emit_event(L, "mousereleased", "sdd", lt_button_name(e.mouse.button), lt_mx, lt_my); + + break; case GLEQ_CURSOR_MOVED: + lt_mx = e.pos.x - lt_wx, lt_my = e.pos.y - lt_wy; + rc += lt_emit_event(L, "mousemoved", "dddd", lt_mx, lt_my, lt_mx - prevx, lt_my - prevy); + prevx = lt_mx, prevy = lt_my; + + break; case GLEQ_SCROLLED: + rc += lt_emit_event(L, "mousewheel", "f", e.scroll.y); + } + +bottom:; + + return rc; +} +#line 0 +#line 1 "3rd_lite.h" +// Copyright (c) 2020 rxi +// +// 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. + +// [doc] https://rxi.github.io/lite_an_implementation_overview.html +// [chg] differences from https://github.com/rxi/lite listed below: +// +// a) amalgamated as single-file source. +// b) platform agnostic now (no more specific SDL calls; tested with GLFW backend). +// c) specific `lt_` platform bits have been moved out to an external file (lite_sys.h) +// d) lua, stb-truetype and lite_sys headers *must be included* beforehand. +// e) embeddable: reverted loop handler from framework to library mode. see: lt_init/lt_tick +// f) data folders reorganized as data/themes, data/languages/ and data/plugins/. +// g) DATADIR path can be specified now and no longer forced to be EXEDIR/data/. +// h) packaged with a bunch of handy plugins from https://github.com/rxi/lite-plugins +// i) packaged with all color themes from https://github.com/rxi/lite-colors +// j) merged a few pending PRs and pending fixes from original repo. +// k) Lua sources fixed for Lua >= 5.2 +// +// All contributions released under same MIT licensing terms than original code. +// - rlyeh. + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +// ---------------------------------------------------------------------------- +// lite/api.h + +#define API_TYPE_FONT "Font" + +// ---------------------------------------------------------------------------- +// lite/renderer.h + +typedef struct RenImage RenImage; +typedef struct RenFont RenFont; + +typedef struct { uint8_t b, g, r, a; } RenColor; +//typedef struct { int x, y, width, height; } RenRect; +typedef lt_rect RenRect; + + +void ren_init(void *win); +void ren_update_rects(RenRect *rects, int count); +void ren_set_clip_rect(RenRect rect); +void ren_get_size(int *x, int *y); + +RenImage* ren_new_image(int width, int height); +void ren_free_image(RenImage *image); + +RenFont* ren_load_font(const char *filename, float size); +void ren_free_font(RenFont *font); +void ren_set_font_tab_width(RenFont *font, int n); +int ren_get_font_tab_width(RenFont *font); +int ren_get_font_width(RenFont *font, const char *text); +int ren_get_font_height(RenFont *font); + +void ren_draw_rect(RenRect rect, RenColor color); +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color); +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); + +// ---------------------------------------------------------------------------- +// lite/rencache.h + +void rencache_show_debug(bool enable); +void rencache_free_font(RenFont *font); +void rencache_set_clip_rect(RenRect rect); +void rencache_draw_rect(RenRect rect, RenColor color); +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); +void rencache_invalidate(void); +void rencache_begin_frame(void); +void rencache_end_frame(void); + +// ---------------------------------------------------------------------------- +// lite/renderer.c + +#define MAX_GLYPHSET 256 + +struct RenImage { + RenColor *pixels; + int width, height; +}; + +typedef struct { + RenImage *image; + stbtt_bakedchar glyphs[256]; +} GlyphSet; + +struct RenFont { + void *data; + stbtt_fontinfo stbfont; + GlyphSet *sets[MAX_GLYPHSET]; + float size; + int height; +}; + +static struct { int left, top, right, bottom; } lt_clip; + +static const char* codepoint_to_utf8(unsigned c) { //< @r-lyeh + static char s[4+1]; + lt_memset(s, 0, 5); + /**/ if (c < 0x80) s[0] = c, s[1] = 0; + else if (c < 0x800) s[0] = 0xC0 | ((c >> 6) & 0x1F), s[1] = 0x80 | ( c & 0x3F), s[2] = 0; + else if (c < 0x10000) s[0] = 0xE0 | ((c >> 12) & 0x0F), s[1] = 0x80 | ((c >> 6) & 0x3F), s[2] = 0x80 | ( c & 0x3F), s[3] = 0; + else if (c < 0x110000) s[0] = 0xF0 | ((c >> 18) & 0x07), s[1] = 0x80 | ((c >> 12) & 0x3F), s[2] = 0x80 | ((c >> 6) & 0x3F), s[3] = 0x80 | (c & 0x3F), s[4] = 0; + return s; +} +static const char* utf8_to_codepoint(const char *p, unsigned *dst) { + unsigned res, n; + switch (*p & 0xf0) { + case 0xf0 : res = *p & 0x07; n = 3; break; + case 0xe0 : res = *p & 0x0f; n = 2; break; + case 0xd0 : + case 0xc0 : res = *p & 0x1f; n = 1; break; + default : res = *p; n = 0; break; + } + while (n-- && *p++) { //< https://github.com/rxi/lite/issues/262 + res = (res << 6) | (*p & 0x3f); //< https://github.com/rxi/lite/issues/262 + } + *dst = res; + return p + 1; +} + +void ren_init(void *win) { + lt_surface *surf = lt_getsurface(lt_window()); + ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } ); +} + + +void ren_update_rects(RenRect *rects, int count) { + lt_updatesurfacerects(lt_getsurface(lt_window()), (lt_rect*) rects, count); +} + + +void ren_set_clip_rect(RenRect rect) { + lt_clip.left = rect.x; + lt_clip.top = rect.y; + lt_clip.right = rect.x + rect.width; + lt_clip.bottom = rect.y + rect.height; +} + + +void ren_get_size(int *x, int *y) { + lt_surface *surf = lt_getsurface(lt_window()); + *x = surf->w; + *y = surf->h; +} + + +RenImage* ren_new_image(int width, int height) { + lt_assert(width > 0 && height > 0); + RenImage *image = lt_malloc(sizeof(RenImage) + width * height * sizeof(RenColor)); + image->pixels = (void*) (image + 1); + image->width = width; + image->height = height; + return image; +} + + +void ren_free_image(RenImage *image) { + lt_free(image); +} + + +static GlyphSet* load_glyphset(RenFont *font, int idx) { + GlyphSet *set = lt_calloc(1, sizeof(GlyphSet)); + + /* init image */ + int width = 128; + int height = 128; +retry: + set->image = ren_new_image(width, height); + + /* load glyphs */ + float s = + stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) / + stbtt_ScaleForPixelHeight(&font->stbfont, 1); + int res = stbtt_BakeFontBitmap( + font->data, 0, font->size * s, (void*) set->image->pixels, + width, height, idx * 256, 256, set->glyphs); + + /* retry with a larger image buffer if the buffer wasn't large enough */ + if (res < 0) { + width *= 2; + height *= 2; + ren_free_image(set->image); + goto retry; + } + + /* adjust glyph yoffsets and xadvance */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size); + int scaled_ascent = ascent * scale + 0.5; + for (int i = 0; i < 256; i++) { + set->glyphs[i].yoff += scaled_ascent; + set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance); + } + + /* convert 8bit data to 32bit */ + for (int i = width * height - 1; i >= 0; i--) { + uint8_t n = *((uint8_t*) set->image->pixels + i); + set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n }; + } + + return set; +} + + +static GlyphSet* get_glyphset(RenFont *font, int codepoint) { + int idx = (codepoint >> 8) % MAX_GLYPHSET; + if (!font->sets[idx]) { + font->sets[idx] = load_glyphset(font, idx); + } + return font->sets[idx]; +} + + +RenFont* ren_load_font(const char *filename, float size) { + /* load font into buffer */ //< @r-lyeh: load font file before allocating `font` + char *fontdata = lt_load_file(filename, NULL); + if( !fontdata ) return NULL; + + RenFont *font = NULL; + + /* init font */ + font = lt_calloc(1, sizeof(RenFont)); + font->size = size; + font->data = fontdata; + + /* init stbfont */ + int ok = stbtt_InitFont(&font->stbfont, font->data, 0); + if (!ok) { + if (font) { lt_free(font->data); } + lt_free(font); + return NULL; + } + + /* get height and scale */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size); + font->height = (ascent - descent + linegap) * scale + 0.5; + + /* make tab and newline glyphs invisible */ + stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs; + g['\t'].x1 = g['\t'].x0; + g['\n'].x1 = g['\n'].x0; + + return font; +} + + +void ren_free_font(RenFont *font) { + for (int i = 0; i < MAX_GLYPHSET; i++) { + GlyphSet *set = font->sets[i]; + if (set) { + ren_free_image(set->image); + lt_free(set); + } + } + lt_free(font->data); + lt_free(font); +} + + +void ren_set_font_tab_width(RenFont *font, int n) { + GlyphSet *set = get_glyphset(font, '\t'); + set->glyphs['\t'].xadvance = n; +} + + +int ren_get_font_tab_width(RenFont *font) { + GlyphSet *set = get_glyphset(font, '\t'); + return set->glyphs['\t'].xadvance; +} + + +int ren_get_font_width(RenFont *font, const char *text) { + int x = 0; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + x += g->xadvance; + } + return x; +} + + +int ren_get_font_height(RenFont *font) { + return font->height; +} + + +static inline RenColor blend_pixel(RenColor dst, RenColor src) { + int ia = 0xff - src.a; + dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8; + dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8; + dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8; + return dst; +} + + +static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) { + src.a = (src.a * color.a) >> 8; + int ia = 0xff - src.a; + dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8); + dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8); + dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8); + return dst; +} + + +#define rect_draw_loop(expr) \ + for (int j = y1; j < y2; j++) { \ + for (int i = x1; i < x2; i++) { \ + *d = expr; \ + d++; \ + } \ + d += dr; \ + } + +void ren_draw_rect(RenRect rect, RenColor color) { + if (color.a == 0) { return; } + + int x1 = rect.x < lt_clip.left ? lt_clip.left : rect.x; + int y1 = rect.y < lt_clip.top ? lt_clip.top : rect.y; + int x2 = rect.x + rect.width; + int y2 = rect.y + rect.height; + x2 = x2 > lt_clip.right ? lt_clip.right : x2; + y2 = y2 > lt_clip.bottom ? lt_clip.bottom : y2; + + lt_surface *surf = lt_getsurface(lt_window()); + RenColor *d = (RenColor*) surf->pixels; + d += x1 + y1 * surf->w; + int dr = surf->w - (x2 - x1); + + if (color.a == 0xff) { + rect_draw_loop(color); + } else { + rect_draw_loop(blend_pixel(*d, color)); + } +} + + +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) { + if (color.a == 0) { return; } + + /* clip */ + int n; + if ((n = lt_clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; } + if ((n = lt_clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; } + if ((n = x + sub->width - lt_clip.right ) > 0) { sub->width -= n; } + if ((n = y + sub->height - lt_clip.bottom) > 0) { sub->height -= n; } + + if (sub->width <= 0 || sub->height <= 0) { + return; + } + + /* draw */ + lt_surface *surf = lt_getsurface(lt_window()); + RenColor *s = image->pixels; + RenColor *d = (RenColor*) surf->pixels; + s += sub->x + sub->y * image->width; + d += x + y * surf->w; + int sr = image->width - sub->width; + int dr = surf->w - sub->width; + + for (int j = 0; j < sub->height; j++) { + for (int i = 0; i < sub->width; i++) { + *d = blend_pixel2(*d, *s, color); + d++; + s++; + } + d += dr; + s += sr; + } +} + + +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + rect.x = g->x0; + rect.y = g->y0; + rect.width = g->x1 - g->x0; + rect.height = g->y1 - g->y0; + ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color); + x += g->xadvance; + } + return x; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_font.c + +static int f_load(lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + float size = luaL_checknumber(L, 2); + RenFont **self = lua_newuserdata(L, sizeof(*self)); + luaL_setmetatable(L, API_TYPE_FONT); + *self = ren_load_font(filename, size); + if (!*self) { luaL_error(L, "failed to load font"); } + return 1; +} + + +static int f_set_tab_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + int n = luaL_checknumber(L, 2); + ren_set_font_tab_width(*self, n); + return 0; +} + + +static int f_GC(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + if (*self) { rencache_free_font(*self); } + return 0; +} + + +static int f_get_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + lua_pushnumber(L, ren_get_font_width(*self, text) ); + return 1; +} + + +static int f_get_height(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + lua_pushnumber(L, ren_get_font_height(*self) ); + return 1; +} + + +int luaopen_renderer_font(lua_State *L) { + static const luaL_Reg lib[] = { + { "__gc", f_GC }, + { "load", f_load }, + { "set_tab_width", f_set_tab_width }, + { "get_width", f_get_width }, + { "get_height", f_get_height }, + { NULL, NULL } + }; + luaL_newmetatable(L, API_TYPE_FONT); + luaL_setfuncs(L, lib, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_api.c + +static RenColor checkcolor(lua_State *L, int idx, int def) { + RenColor color; + if (lua_isnoneornil(L, idx)) { + return (RenColor) { def, def, def, 255 }; + } + lua_rawgeti(L, idx, 1); + lua_rawgeti(L, idx, 2); + lua_rawgeti(L, idx, 3); + lua_rawgeti(L, idx, 4); + color.r = luaL_checknumber(L, -4); + color.g = luaL_checknumber(L, -3); + color.b = luaL_checknumber(L, -2); + color.a = luaL_optnumber(L, -1, 255); + lua_pop(L, 4); + return color; +} + + +static int f_show_debug(lua_State *L) { + luaL_checkany(L, 1); + rencache_show_debug(lua_toboolean(L, 1)); + return 0; +} + + +static int f_get_size(lua_State *L) { + int w, h; + ren_get_size(&w, &h); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + return 2; +} + + +static int f_begin_frame(lua_State *L) { + rencache_begin_frame(); + return 0; +} + + +static int f_end_frame(lua_State *L) { + rencache_end_frame(); + return 0; +} + + +static int f_set_clip_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + rencache_set_clip_rect(rect); + return 0; +} + + +static int f_draw_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + rencache_draw_rect(rect, color); + return 0; +} + + +static int f_draw_text(lua_State *L) { + RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + int x = luaL_checknumber(L, 3); + int y = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + x = rencache_draw_text(*font, text, x, y, color); + lua_pushnumber(L, x); + return 1; +} + +int luaopen_renderer(lua_State *L) { + static const luaL_Reg lib[] = { + { "show_debug", f_show_debug }, + { "get_size", f_get_size }, + { "begin_frame", f_begin_frame }, + { "end_frame", f_end_frame }, + { "set_clip_rect", f_set_clip_rect }, + { "draw_rect", f_draw_rect }, + { "draw_text", f_draw_text }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + luaopen_renderer_font(L); + lua_setfield(L, -2, "font"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/rencache.c + +/* a cache over the software renderer -- all drawing operations are stored as +** commands when issued. At the end of the frame we write the commands to a grid +** of hash values, take the cells that have changed since the previous frame, +** merge them into dirty rectangles and redraw only those regions */ + +#define CELLS_X 80 +#define CELLS_Y 50 +#define CELL_SIZE 96 +#define COMMAND_BUF_SIZE (1024 * 512) + +enum { FREE_FONT, SET_CLIP, DRAW_TEXT, DRAW_RECT }; + +typedef struct { + int type, size; + RenRect rect; + RenColor color; + RenFont *font; + int tab_width; + char text[0]; +} Command; + + +static unsigned cells_buf1[CELLS_X * CELLS_Y]; +static unsigned cells_buf2[CELLS_X * CELLS_Y]; +static unsigned *cells_prev = cells_buf1; +static unsigned *cells = cells_buf2; +static RenRect rect_buf[CELLS_X * CELLS_Y / 2]; +static char command_buf[COMMAND_BUF_SIZE]; +static int command_buf_idx; +static RenRect screen_rect; +static bool show_debug; + + +/* 32bit fnv-1a hash */ +#define HASH_INITIAL 2166136261 + +static void hash(unsigned *h, const void *data, int size) { + const unsigned char *p = data; + while (size--) { + *h = (*h ^ *p++) * 16777619; + } +} + + +static inline int cell_idx(int x, int y) { + return x + y * CELLS_X; +} + + +static inline bool rects_overlap(RenRect a, RenRect b) { + return b.x + b.width >= a.x && b.x <= a.x + a.width + && b.y + b.height >= a.y && b.y <= a.y + a.height; +} + + +static RenRect intersect_rects(RenRect a, RenRect b) { + int x1 = maxi(a.x, b.x); + int y1 = maxi(a.y, b.y); + int x2 = mini(a.x + a.width, b.x + b.width); + int y2 = mini(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, max(0, x2 - x1), max(0, y2 - y1) }; +} + + +static RenRect merge_rects(RenRect a, RenRect b) { + int x1 = mini(a.x, b.x); + int y1 = mini(a.y, b.y); + int x2 = maxi(a.x + a.width, b.x + b.width); + int y2 = maxi(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, x2 - x1, y2 - y1 }; +} + + +static Command* push_command(int type, int size) { + size_t alignment = 7; // alignof(max_align_t) - 1; //< C11 https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + size = (size + alignment) & ~alignment; //< https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + Command *cmd = (Command*) (command_buf + command_buf_idx); + int n = command_buf_idx + size; + if (n > COMMAND_BUF_SIZE) { + fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n"); + return NULL; + } + command_buf_idx = n; + lt_memset(cmd, 0, sizeof(Command)); + cmd->type = type; + cmd->size = size; + return cmd; +} + + +static bool next_command(Command **prev) { + if (*prev == NULL) { + *prev = (Command*) command_buf; + } else { + *prev = (Command*) (((char*) *prev) + (*prev)->size); + } + return *prev != ((Command*) (command_buf + command_buf_idx)); +} + + +void rencache_show_debug(bool enable) { + show_debug = enable; +} + + +void rencache_free_font(RenFont *font) { + Command *cmd = push_command(FREE_FONT, sizeof(Command)); + if (cmd) { cmd->font = font; } +} + + +void rencache_set_clip_rect(RenRect rect) { + Command *cmd = push_command(SET_CLIP, sizeof(Command)); + if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); } +} + + +void rencache_draw_rect(RenRect rect, RenColor color) { + if (!rects_overlap(screen_rect, rect)) { return; } + Command *cmd = push_command(DRAW_RECT, sizeof(Command)); + if (cmd) { + cmd->rect = rect; + cmd->color = color; + } +} + + +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + rect.x = x; + rect.y = y; + rect.width = ren_get_font_width(font, text); + rect.height = ren_get_font_height(font); + + if (rects_overlap(screen_rect, rect)) { + int sz = strlen(text) + 1; + Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz); + if (cmd) { + memcpy(cmd->text, text, sz); + cmd->color = color; + cmd->font = font; + cmd->rect = rect; + cmd->tab_width = ren_get_font_tab_width(font); + } + } + + return x + rect.width; +} + + +void rencache_invalidate(void) { + lt_memset(cells_prev, 0xff, sizeof(cells_buf1)); +} + + +void rencache_begin_frame(void) { + /* reset all cells if the screen width/height has changed */ + int w, h; + ren_get_size(&w, &h); + if (screen_rect.width != w || h != screen_rect.height) { + screen_rect.width = w; + screen_rect.height = h; + rencache_invalidate(); + } +} + + +static void update_overlapping_cells(RenRect r, unsigned h) { + int x1 = r.x / CELL_SIZE; + int y1 = r.y / CELL_SIZE; + int x2 = (r.x + r.width) / CELL_SIZE; + int y2 = (r.y + r.height) / CELL_SIZE; + + for (int y = y1; y <= y2; y++) { + for (int x = x1; x <= x2; x++) { + int idx = cell_idx(x, y); + hash(&cells[idx], &h, sizeof(h)); + } + } +} + + +static void push_rect(RenRect r, int *count) { + /* try to merge with existing rectangle */ + for (int i = *count - 1; i >= 0; i--) { + RenRect *rp = &rect_buf[i]; + if (rects_overlap(*rp, r)) { + *rp = merge_rects(*rp, r); + return; + } + } + /* couldn't merge with previous rectangle: push */ + rect_buf[(*count)++] = r; +} + + +void rencache_end_frame(void) { + /* update cells from commands */ + Command *cmd = NULL; + RenRect cr = screen_rect; + while (next_command(&cmd)) { + if (cmd->type == SET_CLIP) { cr = cmd->rect; } + RenRect r = intersect_rects(cmd->rect, cr); + if (r.width == 0 || r.height == 0) { continue; } + unsigned h = HASH_INITIAL; + hash(&h, cmd, cmd->size); + update_overlapping_cells(r, h); + } + + /* push rects for all cells changed from last frame, reset cells */ + int rect_count = 0; + int max_x = screen_rect.width / CELL_SIZE + 1; + int max_y = screen_rect.height / CELL_SIZE + 1; + for (int y = 0; y < max_y; y++) { + for (int x = 0; x < max_x; x++) { + /* compare previous and current cell for change */ + int idx = cell_idx(x, y); + if (cells[idx] != cells_prev[idx]) { + push_rect((RenRect) { x, y, 1, 1 }, &rect_count); + } + cells_prev[idx] = HASH_INITIAL; + } + } + + /* expand rects from cells to pixels */ + for (int i = 0; i < rect_count; i++) { + RenRect *r = &rect_buf[i]; + r->x *= CELL_SIZE; + r->y *= CELL_SIZE; + r->width *= CELL_SIZE; + r->height *= CELL_SIZE; + *r = intersect_rects(*r, screen_rect); + } + + /* redraw updated regions */ + bool has_free_commands = false; + for (int i = 0; i < rect_count; i++) { + /* draw */ + RenRect r = rect_buf[i]; + ren_set_clip_rect(r); + + cmd = NULL; + while (next_command(&cmd)) { + switch (cmd->type) { + case FREE_FONT: + has_free_commands = true; + break; + case SET_CLIP: + ren_set_clip_rect(intersect_rects(cmd->rect, r)); + break; + case DRAW_RECT: + ren_draw_rect(cmd->rect, cmd->color); + break; + case DRAW_TEXT: + ren_set_font_tab_width(cmd->font, cmd->tab_width); + ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color); + break; + } + } + + if (show_debug) { + RenColor color = { rand(), rand(), rand(), 50 }; + ren_draw_rect(r, color); + } + } + + /* update dirty rects */ + if (rect_count > 0) { + ren_update_rects(rect_buf, rect_count); + } + + /* free fonts */ + if (has_free_commands) { + cmd = NULL; + while (next_command(&cmd)) { + if (cmd->type == FREE_FONT) { + ren_free_font(cmd->font); + } + } + } + + /* swap cell buffer and reset */ + unsigned *tmp = cells; + cells = cells_prev; + cells_prev = tmp; + command_buf_idx = 0; +} + +// ---------------------------------------------------------------------------- +// lite/system.c + +static int f_set_cursor(lua_State *L) { + static const char *cursor_opts[] = { + "arrow", + "ibeam", + "sizeh", + "sizev", + "hand", + NULL + }; + int n = luaL_checkoption(L, 1, "arrow", cursor_opts); + lt_setcursor(n); + return 0; +} + +static int f_set_window_title(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + lt_setwindowtitle(title); + return 0; +} +static int f_set_window_mode(lua_State *L) { + static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 }; + enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN }; + int n = luaL_checkoption(L, 1, "normal", window_opts); + lt_setwindowmode(n); + return 0; +} +static int f_window_has_focus(lua_State *L) { + unsigned flags = lt_haswindowfocus(); + lua_pushboolean(L, flags); + return 1; +} + +static int f_show_confirm_dialog(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + const char *msg = luaL_checkstring(L, 2); + int id = lt_prompt(msg, title); // 0:no, 1:yes + lua_pushboolean(L, !!id); + return 1; +} + +static int f_chdir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + int err = chdir(path); + if (err) { luaL_error(L, "chdir() failed"); } + return 0; +} +static int f_list_dir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + lua_newtable(L); + lt_globpath(L, path); + return 1; +} +static int f_absolute_path(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + char *res = lt_realpath(path, NULL); + if (!res) { return 0; } + lua_pushstring(L, res); + lt_realpath_free(res); + return 1; +} +static int f_get_file_info(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + struct stat s; + int err = stat(path, &s); + if (err < 0) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; + } + + lua_newtable(L); + lua_pushnumber(L, s.st_mtime); + lua_setfield(L, -2, "modified"); + + lua_pushnumber(L, s.st_size); + lua_setfield(L, -2, "size"); + + if (S_ISREG(s.st_mode)) { + lua_pushstring(L, "file"); + } else if (S_ISDIR(s.st_mode)) { + lua_pushstring(L, "dir"); + } else { + lua_pushnil(L); + } + lua_setfield(L, -2, "type"); + + return 1; +} + + +static int f_get_clipboard(lua_State *L) { + const char *text = lt_getclipboard(lt_window()); + if (!text) { return 0; } + lua_pushstring(L, text); + return 1; +} +static int f_set_clipboard(lua_State *L) { + const char *text = luaL_checkstring(L, 1); + lt_setclipboard(lt_window(), text); + return 0; +} + + +static int f_get_time(lua_State *L) { + double ss = lt_time_ms() / 1000.0; + lua_pushnumber(L, ss); + return 1; +} +static int f_sleep(lua_State *L) { + double ss = luaL_checknumber(L, 1); + lt_sleep_ms(ss * 1000); + return 0; +} + + +static int f_exec(lua_State *L) { + size_t len; + const char *cmd = luaL_checklstring(L, 1, &len); + char *buf = lt_malloc(len + 32); + if (!buf) { luaL_error(L, "buffer allocation failed"); } +#if _WIN32 + sprintf(buf, "cmd /c \"%s\"", cmd); + WinExec(buf, SW_HIDE); +#else + sprintf(buf, "%s &", cmd); + int res = system(buf); +#endif + lt_free(buf); + return 0; +} + + +static int f_fuzzy_match(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + const char *ptn = luaL_checkstring(L, 2); + int score = 0; + int run = 0; + + while (*str && *ptn) { + while (*str == ' ') { str++; } + while (*ptn == ' ') { ptn++; } + if (tolower(*str) == tolower(*ptn)) { + score += run * 10 - (*str != *ptn); + run++; + ptn++; + } else { + score -= 10; + run = 0; + } + str++; + } + if (*ptn) { return 0; } + + lua_pushnumber(L, score - (int) strlen(str)); + return 1; +} + +static int f_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = lt_poll_event(L); + return rc; +} + +int luaopen_system(lua_State *L) { + static const luaL_Reg lib[] = { + { "poll_event", f_poll_event }, + { "set_cursor", f_set_cursor }, + { "set_window_title", f_set_window_title }, + { "set_window_mode", f_set_window_mode }, + { "window_has_focus", f_window_has_focus }, + { "show_confirm_dialog", f_show_confirm_dialog }, + { "chdir", f_chdir }, + { "list_dir", f_list_dir }, + { "absolute_path", f_absolute_path }, + { "get_file_info", f_get_file_info }, + { "get_clipboard", f_get_clipboard }, + { "set_clipboard", f_set_clipboard }, + { "get_time", f_get_time }, + { "sleep", f_sleep }, + { "exec", f_exec }, + { "fuzzy_match", f_fuzzy_match }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/api/api.c + +void api_load_libs(lua_State *L) { + static const luaL_Reg libs[] = { + { "system", luaopen_system }, + { "renderer", luaopen_renderer }, + { NULL, NULL } + }; + for (int i = 0; libs[i].name; i++) { + luaL_requiref(L, libs[i].name, libs[i].func, 1); + } +} + +// ---------------------------------------------------------------------------- +// lite/main.c + +void lt_init(lua_State *L, void *handle, const char *pathdata, int argc, char **argv, float scale, const char *platform, const char *pathexe) { + // setup renderer + ren_init(handle); + + // setup lua context + api_load_libs(L); + + lua_newtable(L); + for (int i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setglobal(L, "ARGS"); + + lua_pushstring(L, "1.11"); + lua_setglobal(L, "VERSION"); + + lua_pushstring(L, platform); + lua_setglobal(L, "PLATFORM"); + + lua_pushnumber(L, scale); + lua_setglobal(L, "SCALE"); + + lua_pushstring(L, pathdata); + lua_setglobal(L, "DATADIR"); + + lua_pushstring(L, pathexe); + lua_setglobal(L, "EXEFILE"); + + // init lite + luaL_dostring(L, "core = {}"); + luaL_dostring(L, + "xpcall(function()\n" + " SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n" + " PATHSEP = package.config:sub(1, 1)\n" + " EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n" + " USERDIR = EXEDIR .. 'data/user/'\n" + " package.path = EXEDIR .. '/data/?.lua;' .. package.path\n" + " package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n" + " core = require('core')\n" + " core.init()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} +void lt_tick(struct lua_State *L) { + luaL_dostring(L, + "xpcall(function()\n" + " core.run1()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} +#line 0 + #endif // V4K_3RD diff --git a/engine/v4k.c b/engine/v4k.c index b10c17f..b748f28 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -101,7 +101,7 @@ //----------------------------------------------------------------------------- // C files -#line 1 "engine/split/v4k_begin.c" +#line 1 "v4k_begin.c" #define do_threadlock(mutexptr) \ for( int init_ = !!(mutexptr) || (thread_mutex_init( (mutexptr) = CALLOC(1, sizeof(thread_mutex_t)) ), 1); init_; init_ = 0) \ for( int lock_ = (thread_mutex_lock( mutexptr ), 1); lock_; lock_ = (thread_mutex_unlock( mutexptr ), 0) ) @@ -110,7 +110,7 @@ ((struct nk_color){ ((color>>0))&255,((color>>8))&255,((color>>16))&255,((color>>24))&255 }) #line 0 -#line 1 "engine/split/v4k_ds.c" +#line 1 "v4k_ds.c" // ----------------------------------------------------------------------------- // sort/less @@ -500,7 +500,7 @@ void (set_free)(set* m) { } #line 0 -#line 1 "engine/split/v4k_string.c" +#line 1 "v4k_string.c" #include char* tempvl(const char *fmt, va_list vl) { @@ -921,9 +921,158 @@ AUTORUN { test( !strcmp("Hello happy world.", buf) ); } #endif + +// ---------------------------------------------------------------------------- +// localization kit + +static const char *kit_lang = "enUS", *kit_langs = + "enUS,enGB," + "frFR," + "esES,esAR,esMX," + "deDE,deCH,deAT," + "itIT,itCH," + "ptBR,ptPT," + "zhCN,zhSG,zhTW,zhHK,zhMO," + "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," + "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" +; + +static map(char*,char*) kit_ids; +static map(char*,char*) kit_vars; + +#ifndef KIT_FMT_ID2 +#define KIT_FMT_ID2 "%s.%s" +#endif + +void kit_init() { + do_once map_init(kit_ids, less_str, hash_str); + do_once map_init(kit_vars, less_str, hash_str); +} + +void kit_insert( const char *id, const char *translation) { + char *id2 = va(KIT_FMT_ID2, kit_lang, id); + + char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); + if(*found) FREE(*found); + *found = STRDUP(translation); +} + +bool kit_merge( const char *filename ) { + // @todo: xlsx2ini + return false; +} + +void kit_clear() { + map_clear(kit_ids); +} + +bool kit_load( const char *filename ) { + return kit_clear(), kit_merge( filename ); +} + +void kit_set( const char *key, const char *value ) { + value = value && value[0] ? value : ""; + + char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); + if(*found) FREE(*found); + *found = STRDUP(value); +} + +void kit_reset() { + map_clear(kit_vars); +} + +char *kit_translate2( const char *id, const char *lang ) { + char *id2 = va(KIT_FMT_ID2, lang, id); + + char **found = map_find(kit_ids, id2); + + // return original [[ID]] if no translation is found + if( !found ) return va("[[%s]]", id); + + // return translation if no {{moustaches}} are found + if( !strstr(*found, "{{") ) return *found; + + // else replace all found {{moustaches}} with context vars + { + // make room + static __thread char *results[16] = {0}; + static __thread unsigned counter = 0; counter = (counter+1) % 16; + + char *buffer = results[ counter ]; + if( buffer ) FREE(buffer), buffer = 0; + + // iterate moustaches + const char *begin, *end, *text = *found; + while( NULL != (begin = strstr(text, "{{")) ) { + end = strstr(begin+2, "}}"); + if( end ) { + char *var = va("%.*s", (int)(end - (begin+2)), begin+2); + char **found_var = map_find(kit_vars, var); + + if( found_var && 0[*found_var] ) { + strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); + } else { + strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); + } + + text = end+2; + } else { + strcatf(&buffer, "%.*s", (int)(begin - text), text); + + text = begin+2; + } + } + + strcatf(&buffer, "%s", text); + return buffer; + } +} + +char *kit_translate( const char *id ) { + return kit_translate2( id, kit_lang ); +} + +void kit_locale( const char *lang ) { + kit_lang = STRDUP(lang); // @leak +} + +void kit_dump_state( FILE *fp ) { + for each_map(kit_ids, char *, k, char *, v) { + fprintf(fp, "[ID ] %s=%s\n", k, v); + } + for each_map(kit_vars, char *, k, char *, v) { + fprintf(fp, "[VAR] %s=%s\n", k, v); + } +} + +/* +int main() { + kit_init(); + + kit_locale("enUS"); + kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Nice to meet you."); + + kit_locale("esES"); + kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); + kit_insert("GREET_PLAYERS", "Un placer conoceros."); + + kit_locale("enUS"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. + + kit_locale("esES"); + kit_set("PLAYER1", "John"); + kit_set("PLAYER2", "Karl"); + printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. + + assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] + assert(~puts("Ok")); +} +*/ #line 0 -#line 1 "engine/split/v4k_compat.c" +#line 1 "v4k_compat.c" //----------------------------------------------------------------------------- // compat (unix & stdio.h) @@ -1042,7 +1191,7 @@ static void v4k_pre_init(); static void v4k_post_init(float); #line 0 -#line 1 "engine/split/v4k_ui.c" +#line 1 "v4k_ui.c" // ---------------------------------------------------------------------------------------- // ui extensions first @@ -2946,8 +3095,8 @@ int ui_color4f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3] }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), clampf(color[3],0,1) }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), clampf(after.a,0,1) }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -3034,8 +3183,8 @@ int ui_color3f(const char *label, float *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, ui_alpha }, before = after; - struct nk_colorf clamped = { clampf(color[0],0,1), clampf(color[1],0,1), clampf(color[2],0,1), 1 }; + struct nk_colorf after = { color[0]*ui_alpha, color[1]*ui_alpha, color[2]*ui_alpha, color[3]*ui_alpha }, before = after; + struct nk_colorf clamped = { clampf(after.r,0,1), clampf(after.g,0,1), clampf(after.b,0,1), ui_alpha }; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(clamped), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -3078,7 +3227,7 @@ int ui_color3(const char *label, unsigned *color) { nk_layout_row_dynamic(ui_ctx, 0, 2); ui_label_(label, NK_TEXT_LEFT); - struct nk_colorf after = { r*ui_alpha, g*ui_alpha, b*ui_alpha, 1 }, before = after; + struct nk_colorf after = { r*ui_alpha/255, g*ui_alpha/255, b*ui_alpha/255, ui_alpha }, before = after; if (nk_combo_begin_color(ui_ctx, nk_rgb_cf(after), nk_vec2(200,400))) { nk_layout_row_dynamic(ui_ctx, 120, 1); after = nk_color_picker(ui_ctx, after, NK_RGB); @@ -3740,8 +3889,10 @@ int ui_demo(int do_windows) { static float float2[2] = {1,2}; static float float3[3] = {1,2,3}; static float float4[4] = {1,2,3,4}; - static float rgb[3] = {0.84,0.67,0.17}; - static float rgba[4] = {0.67,0.90,0.12,1}; + static float rgbf[3] = {0.84,0.67,0.17}; + static float rgbaf[4] = {0.67,0.90,0.12,1}; + static unsigned rgb = CYAN; + static unsigned rgba = PINK; static float slider = 0.5f; static float slider2 = 0.5f; static char string[64] = "hello world 123"; @@ -3785,8 +3936,10 @@ int ui_demo(int do_windows) { if( ui_list("my list", list, 3, &item ) ) puts("list changed"); if( ui_section("Colors")) {} - if( ui_color3f("my color3", rgb) ) puts("color3 changed"); - if( ui_color4f("my color4@this is a tooltip", rgba) ) puts("color4 changed"); + if( ui_color3("my color3", &rgb) ) puts("color3 changed"); + if( ui_color4("my color4@this is a tooltip", &rgba) ) puts("color4 changed"); + if( ui_color3f("my color3f", rgbf) ) puts("color3f changed"); + if( ui_color4f("my color4f@this is a tooltip", rgbaf) ) puts("color4f changed"); if( ui_section("Sliders")) {} if( ui_slider("my slider", &slider)) puts("slider changed"); @@ -3899,7 +4052,7 @@ int ui_demo(int do_windows) { #line 0 -#line 1 "engine/split/v4k_audio.c" +#line 1 "v4k_audio.c" // @fixme: really shutdown audio & related threads before quitting. ma_dr_wav crashes. @@ -4492,7 +4645,7 @@ int ui_audio() { } #line 0 -#line 1 "engine/split/v4k_collide.c" +#line 1 "v4k_collide.c" /* poly */ poly poly_alloc(int cnt) { poly p = {0}; @@ -5920,7 +6073,7 @@ void collide_demo() { // debug draw collisions // @fixme: fix leaks: poly_free() } #line 0 -#line 1 "engine/split/v4k_cook.c" +#line 1 "v4k_cook.c" // data pipeline // - rlyeh, public domain. // ---------------------------------------------------------------------------- @@ -5934,7 +6087,7 @@ void collide_demo() { // debug draw collisions // @fixme: fix leaks: poly_free() const char *ART = "art/"; const char *TOOLS = "tools/bin/"; -const char *EDITOR = "tools/editor/"; +const char *EDITOR = "tools/"; const char *COOK_INI = "tools/cook.ini"; static unsigned ART_SKIP_ROOT; // number of chars to skip the base root in ART folder @@ -6431,11 +6584,14 @@ int cook(void *userdata) { fclose(in); } +// if(array_count(uncooked)) +// PRINTF("cook_jobs[%d]=%d\n", job->threadid, array_count(uncooked)); + // generate cook metrics. you usually do `game.exe --cook-stats && (type *.csv | sort /R > cook.csv)` static __thread FILE *statsfile = 0; if(flag("--cook-stats")) fseek(statsfile = fopen(va("cook%d.csv",job->threadid), "a+t"), 0L, SEEK_END); - if(statsfile && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); + if(statsfile && !job->threadid && ftell(statsfile) == 0) fprintf(statsfile,"%10s,%10s,%10s,%10s,%10s, %s\n","+total_ms","gen_ms","exe_ms","zip_ms","pass","file"); // added or changed files for( int i = 0, end = array_count(uncooked); i < end && !cook_cancelling; ++i ) { @@ -6748,10 +6904,8 @@ void cook_stop() { int cook_progress() { int count = 0, sum = 0; for( int i = 0, end = cook_jobs(); i < end; ++i ) { -// if( jobs[i].progress >= 0 ) { sum += jobs[i].progress; ++count; -// } } return cook_jobs() ? sum / (count+!count) : 100; } @@ -6779,7 +6933,7 @@ bool have_tools() { } #line 0 -#line 1 "engine/split/v4k_data.c" +#line 1 "v4k_data.c" static array(json5) roots; static array(char*) sources; @@ -7009,7 +7163,7 @@ bool data_tests() { } #line 0 -#line 1 "engine/split/v4k_extend.c" +#line 1 "v4k_extend.c" // dll ------------------------------------------------------------------------ /* deprecated @@ -7300,7 +7454,7 @@ void *script_init_env(unsigned flags) { } #line 0 -#line 1 "engine/split/v4k_file.c" +#line 1 "v4k_file.c" // ----------------------------------------------------------------------------- // file @@ -8187,7 +8341,7 @@ if( found && *found == 0 ) { char *cmd = va("%scook" ifdef(osx,".osx",ifdef(linux,".linux",".exe"))" %s %s --cook-ini=%s --cook-additive --cook-jobs=1 --quiet", TOOLS, group1, group2, COOK_INI); // cook groups - int rc = atoi(app_exec(cmd)); + int rc = system(cmd); // atoi(app_exec(cmd)); if(rc < 0) PANIC("cannot invoke `%scook` (return code %d)", TOOLS, rc); vfs_reload(); // @todo: optimize me. it is waaay inefficent to reload the whole VFS layout after cooking a single asset @@ -8453,7 +8607,7 @@ bool ini_write(const char *filename, const char *section, const char *key, const #line 0 -#line 1 "engine/split/v4k_font.c" +#line 1 "v4k_font.c" // font framework. original code by Vassvik (UNLICENSED) // - rlyeh, public domain. // @@ -10807,7 +10961,7 @@ vec2 font_rect(const char *str) { } #line 0 -#line 1 "engine/split/v4k_input.c" +#line 1 "v4k_input.c" // input framework // - rlyeh, public domain // @@ -11572,7 +11726,7 @@ int ui_gamepads() { } #line 0 -#line 1 "engine/split/v4k_math.c" +#line 1 "v4k_math.c" // ----------------------------------------------------------------------------- // math framework: rand, ease, vec2, vec3, vec4, quat, mat2, mat33, mat34, mat4 // - rlyeh, public domain @@ -12452,7 +12606,7 @@ AUTORUN { } #line 0 -#line 1 "engine/split/v4k_memory.c" +#line 1 "v4k_memory.c" size_t dlmalloc_usable_size(void*); // __ANDROID_API__ #if is(bsd) || is(osx) // bsd or osx @@ -12461,9 +12615,10 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ # include #endif -#ifndef SYS_REALLOC -#define SYS_REALLOC realloc -#define SYS_MSIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ +#ifndef SYS_MEM_INIT +#define SYS_MEM_INIT() +#define SYS_MEM_REALLOC realloc +#define SYS_MEM_SIZE /* bsd/osx, then win32, then ems/__GLIBC__, then __ANDROID_API__ */ \ ifdef(osx, malloc_size, ifdef(bsd, malloc_size, \ ifdef(win32, _msize, malloc_usable_size))) #endif @@ -12473,10 +12628,12 @@ size_t dlmalloc_usable_size(void*); // __ANDROID_API__ static __thread uint64_t xstats_current = 0, xstats_total = 0, xstats_allocs = 0; void* xrealloc(void* oldptr, size_t size) { + static __thread int once = 0; for(;!once;once = 1) SYS_MEM_INIT(); + // for stats size_t oldsize = xsize(oldptr); - void *ptr = SYS_REALLOC(oldptr, size); + void *ptr = SYS_MEM_REALLOC(oldptr, size); if( !ptr && size ) { PANIC("Not memory enough (trying to allocate %u bytes)", (unsigned)size); } @@ -12501,7 +12658,7 @@ void* xrealloc(void* oldptr, size_t size) { return ptr; } size_t xsize(void* p) { - if( p ) return SYS_MSIZE(p); + if( p ) return SYS_MEM_SIZE(p); return 0; } char *xstats(void) { @@ -12553,7 +12710,7 @@ void* forget( void *ptr ) { } #line 0 -#line 1 "engine/split/v4k_network.c" +#line 1 "v4k_network.c" #if is(tcc) && is(win32) // @fixme: https lib is broken with tcc. replaced with InternetReadFile() api for now @@ -12850,7 +13007,7 @@ static void network_init() { } #line 0 -#line 1 "engine/split/v4k_track.c" +#line 1 "v4k_track.c" static __thread int track__sock = -1; //~ Lifecycle methods @@ -12987,7 +13144,7 @@ int track_event_props(char const *event_id, char const *user_id, const track_pro #undef TRACK__APPEND_SAFE_EX #line 0 -#line 1 "engine/split/v4k_netsync.c" +#line 1 "v4k_netsync.c" typedef void* (*rpc_function)(); typedef struct rpc_call { @@ -13673,7 +13830,7 @@ void network_rpc_send(unsigned id, const char *cmdline) { } #line 0 -#line 1 "engine/split/v4k_pack.c" +#line 1 "v4k_pack.c" // ----------------------------------------------------------------------------- // semantic versioning in a single byte (octal) // - rlyeh, public domain. @@ -16046,7 +16203,7 @@ AUTORUN { #endif #line 0 -#line 1 "engine/split/v4k_reflect.c" +#line 1 "v4k_reflect.c" // C reflection: enums, functions, structs, members and anotations. // - rlyeh, public domain // @@ -16240,7 +16397,7 @@ AUTOTEST { } #line 0 -#line 1 "engine/split/v4k_render.c" +#line 1 "v4k_render.c" // ----------------------------------------------------------------------------- // opengl @@ -17672,1110 +17829,6 @@ void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } -// ---------------------------------------------------------------------------- -// sprites - -typedef struct sprite_t { - float px, py, pz; // origin x, y, depth - float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree - float sx, sy; // scale x,y - uint32_t rgba; // vertex color - float cellw, cellh; // dimensions of any cell in spritesheet - - union { - struct { - int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet - }; - struct { - float x, y, w, h; // normalized[0..1] within texture bounds - }; - }; -} sprite_t; - -// sprite batching -typedef struct batch_t { array(sprite_t) sprites; mesh_t mesh; int dirty; } batch_t; -typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon - -// sprite stream -typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; -typedef struct sprite_index { GLuint triangle[3]; } sprite_index; - -#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) -#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) - -// sprite impl -static int sprite_count = 0; -static int sprite_program = -1; -static array(sprite_index) sprite_indices = 0; -static array(sprite_vertex) sprite_vertices = 0; -static batch_group_t sprite_additive_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_translucent_group = {0}; // (w/2,h/2) centered -static batch_group_t sprite_00_translucent_group = {0}; // (0,0) centered - -void sprite( texture_t texture, float position[3], float rotation, uint32_t color ) { - float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; - sprite_sheet( texture, spritesheet, position, rotation, offset, scale, 0, color, false ); -} - -// rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scalex,scaley), rotation (degrees), color (rgba) -void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba) { - // do not queue if either alpha or scale is zero - if( 0 == (pos.z * pos.w * ((tint_rgba>>24) & 255)) ) return; - - sprite_t s = {0}; - - s.px = pos.x, s.py = pos.y, s.pz = zindex; - s.sx = pos.z, s.sy = pos.w; - - s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; - s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; - - s.rgba = tint_rgba; - s.ox = 0/*ox*/ * s.sx; - s.oy = 0/*oy*/ * s.sy; - if( tilt_deg ) { - tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); - s.cos = cosf(tilt_deg); - s.sin = sinf(tilt_deg); - } else { - s.cos = 1; - s.sin = 0; - } - - batch_group_t *batches = &sprite_00_translucent_group; - batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); - - array_push(found->sprites, s); -} - -void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant) { - const float px = position[0], py = position[1], pz = position[2]; - const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; - const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; - - if (frame < 0) return; - if (frame > 0 && frame >= (xcells * ycells)) return; - - // no need to queue if alpha or scale are zero - if( sx && sy && alpha(rgba) ) { - vec3 bak = camera_get_active()->position; - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - } - - sprite_t s; - s.px = px; - s.py = py; - s.pz = pz; - s.frame = frame; - s.ncx = xcells ? xcells : 1; - s.ncy = ycells ? ycells : 1; - s.sx = sx; - s.sy = sy; - s.ox = ox * sx; - s.oy = oy * sy; - s.cellw = (texture.x * sx / s.ncx); - s.cellh = (texture.y * sy / s.ncy); - s.rgba = rgba; - s.cos = 1; - s.sin = 0; - if(rotation) { - rotation = (rotation + 0) * ((float)C_PI / 180); - s.cos = cosf(rotation); - s.sin = sinf(rotation); - } - - batch_group_t *batches = is_additive ? &sprite_additive_group : &sprite_translucent_group; -#if 0 - batch_t *found = map_find(*batches, texture.id); - if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); -#else - batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); -#endif - - array_push(found->sprites, s); - - if( resolution_independant ) { // @todo: optimize me - sprite_flush(); - camera_get_active()->position = bak; - } - } -} - -static void sprite_rebuild_meshes() { - sprite_count = 0; - - batch_group_t* list[] = { &sprite_additive_group, &sprite_translucent_group }; - for( int l = 0; l < countof(list); ++l) { - for each_map_ptr(*list[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float cx = (1.0f / it->ncx) - 1e-9f; - float cy = (1.0f / it->ncy) - 1e-9f; - int idx = (int)it->frame; - int px = idx % it->ncx; - int py = idx / it->ncx; - - float ux = px * cx, uy = py * cy; - float vx = ux + cx, vy = uy + cy; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } - - batch_group_t* list2[] = { &sprite_00_translucent_group }; - for( int l = 0; l < countof(list2); ++l) { - for each_map_ptr(*list2[l], int,_, batch_t,bt) { - - bt->dirty = array_count(bt->sprites) ? 1 : 0; - if( !bt->dirty ) continue; - - int index = 0; - array_clear(sprite_indices); - array_clear(sprite_vertices); - - array_foreach_ptr(bt->sprites, sprite_t,it ) { - float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; - float y0 = it->oy - it->cellh/2, y3 = y0; - float x1 = x0, x2 = x3; - float y1 = y0 + it->cellh, y2 = y1; - - // @todo: move this affine transform into glsl shader - vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; - vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; - vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; - vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; - - float ux = it->x, vx = ux + it->w; - float uy = it->y, vy = uy + it->h; - - vec2 uv0 = vec2(ux, uy); - vec2 uv1 = vec2(ux, vy); - vec2 uv2 = vec2(vx, vy); - vec2 uv3 = vec2(vx, uy); - - array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) - array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) - array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) - array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) - - // A--B A A-B - // quad | | becomes triangle |\ and triangle \| - // D--C D-C C - GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; - - array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 - array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 - } - - mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); - - // clear elements from queue - sprite_count += array_count(bt->sprites); - array_clear(bt->sprites); - } - } -} - -static void sprite_render_meshes() { - if( map_count(sprite_additive_group) <= 0 ) - if( map_count(sprite_translucent_group) <= 0 ) - if( map_count(sprite_00_translucent_group) <= 0 ) - return; - - if( sprite_program < 0 ) { - sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), - "att_Position,att_TexCoord,att_Color", - "fragColor", NULL - ); - } - - // use the shader and bind the texture @ unit 0 - shader_bind(sprite_program); - glActiveTexture(GL_TEXTURE0); - - // setup rendering state - glEnable(GL_DEPTH_TEST); - glEnable(GL_BLEND); - glDepthFunc(GL_LEQUAL); // try to help with zfighting - - // update camera - // camera_fps(camera_get_active(), 0,0); - vec3 pos = camera_get_active()->position; - float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); - float width = window_width(); - float height = window_height(); - - // set mvp in the uniform. (0,0) is center of screen. - mat44 mvp2d; - float zdepth_max = window_height(); // 1; - float l = pos.x - width * zoom / 2; - float r = pos.x + width * zoom / 2; - float b = pos.y + height * zoom / 2; - float t = pos.y - height * zoom / 2; - ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); - - shader_mat44("u_mvp", mvp2d); - - // set (unit 0) in the uniform texture sampler, and render batch - // for all additive then translucent groups - - if( map_count(sprite_additive_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); - for each_map_ptr(sprite_additive_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_additive_group); - } - - if( map_count(sprite_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_translucent_group); - } - - if( map_count(sprite_00_translucent_group) > 0 ) { - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - for each_map_ptr(sprite_00_translucent_group, int,texture_id, batch_t,bt) { - if( bt->dirty ) { - shader_texture_unit("u_texture", *texture_id, 0); - mesh_render(&bt->mesh); - } - } -// map_clear(sprite_00_translucent_group); - } - - glDisable(GL_DEPTH_TEST); - glDisable(GL_BLEND); - glDepthFunc(GL_LESS); - glUseProgram(0); -} - -static void sprite_init() { - do_once { - map_init(sprite_00_translucent_group, less_int, hash_int); - map_init(sprite_translucent_group, less_int, hash_int); - map_init(sprite_additive_group, less_int, hash_int); - } -} - -void sprite_flush() { - profile("Sprite.rebuild_time") { - sprite_rebuild_meshes(); - } - profile("Sprite.render_time") { - sprite_render_meshes(); - } -} - -// ----------------------------------------------------------------------------- -// tilemaps - -tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { - tilemap_t t = {0}; - t.tint = ~0u; // WHITE - t.blank_chr = blank_chr; - for( ; *map ; ++map ) { - if( map[0] == linefeed_chr ) ++t.rows; - else { - array_push(t.map, map[0]); - ++t.cols; - } - } - return t; -} - -void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { - vec3 old_pos = camera_get_active()->position; - sprite_flush(); - camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); - - float scale[2] = {xy_zoom[2], xy_zoom[2]}; - xy_zoom[2] = zindex; - - float offset[2] = {0,0}; - float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) - - for( unsigned y = 0, c = 0; y < m.rows; ++y ) { - for( unsigned x = 0; x < m.cols; ++x, ++c ) { - if( m.map[c] != m.blank_chr ) { - spritesheet[0] = m.map[c]; - sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, is_additive, tint, false); - } - offset[0] += t.tile_w; - } - offset[0] = 0, offset[1] += t.tile_h; - } - - sprite_flush(); - camera_get_active()->position = old_pos; -} - -void tilemap_render( tilemap_t map, tileset_t set ) { - map.position.x += set.tile_w; - map.position.y += set.tile_h; - tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); -} - -tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { - tileset_t t = {0}; - t.tex = tex; - t.cols = cols, t.rows = rows; - t.tile_w = tile_w, t.tile_h = tile_h; - return t; -} - -int ui_tileset( tileset_t t ) { - ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); - int choice; - if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { - int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; - int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; - t.selected = px + py * t.cols; - } - // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} - return t.selected; -} - -// ----------------------------------------------------------------------------- -// tiled - -tiled_t tiled(const char *file_tmx) { - tiled_t zero = {0}, ti = zero; - - // read file and parse json - if( !xml_push(file_tmx) ) return zero; - - // sanity checks - bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); - if( !supported ) return xml_pop(), zero; - - // tileset - const char *file_tsx = xml_string("/map/tileset/@source"); - if( !xml_push(vfs_read(file_tsx)) ) return zero; - const char *set_src = xml_string("/tileset/image/@source"); - int set_w = xml_int("/tileset/@tilewidth"); - int set_h = xml_int("/tileset/@tileheight"); - int set_c = xml_int("/tileset/@columns"); - int set_r = xml_int("/tileset/@tilecount") / set_c; - tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); - xml_pop(); - - // actual parsing - ti.w = xml_int("/map/@width"); - ti.h = xml_int("/map/@height"); - ti.tilew = xml_int("/map/@tilewidth"); - ti.tileh = xml_int("/map/@tileheight"); - ti.first_gid = xml_int("/map/tileset/@firstgid"); - ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak - - for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { - if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { - PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); - continue; - } - - int cols = xml_int("/map/layer[%d]/@width",l); - int rows = xml_int("/map/layer[%d]/@height",l); - - tilemap_t tm = tilemap("", ' ', '\n'); - tm.blank_chr = ~0u; //ti.first_gid - 1; - tm.cols = cols; - tm.rows = rows; - array_resize(tm.map, tm.cols * tm.rows); - memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); - - for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { - int cw, ch; - int cx, cy; - array(char) b64 = 0; - - if( !chunks ) { // non-infinite mode - b64 = xml_blob("/map/layer[%d]/data/$",l); - cw = tm.cols, ch = tm.rows; - cx = 0, cy = 0; - } else { // infinite mode - b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); - cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 - cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) - cx = abs(cx), cy = abs(cy); - } - - int outlen = cw * ch * 4; - static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak - if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { - for( int y = 0, p = 0; y < ch; ++y ) { - for( int x = 0; x < cw; ++x, ++p ) { - if( out[p] >= ti.first_gid ) { - int offset = (x + cx) + (y + cy) * tm.cols; - if( offset >= 0 && offset < (cw * ch) ) - tm.map[ offset ] = out[ p ] - ti.first_gid; - } - } - } - } - else { - PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); - } - - array_free(b64); - } - - array_push(ti.layers, tm); - array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); - array_push(ti.visible, true); - array_push(ti.sets, set); - } - - xml_pop(); - return ti; -} - -void tiled_render(tiled_t tmx, vec3 pos) { - for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { - tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); - if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); - if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); - } -} - -void ui_tiled(tiled_t *t) { - ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); - ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); - ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); - ui_separator(); - ui_bool("Parallax", &t->parallax); - ui_separator(); - ui_label2("Layers", va("%d", array_count(t->layers))); - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF - t->visible[i] ^= true; - } - } - ui_separator(); - if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { - for( int i = 0; i < array_count(t->layers); ++i ) { - if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { - t->sets[i].selected = ui_tileset( t->sets[i] ); - ui_collapse_end(); - } - } - ui_collapse_end(); - } -} - -// ----------------------------------------------------------------------------- -// spine json loader (wip) -// - rlyeh, public domain -// -// [ref] http://es.esotericsoftware.com/spine-json-format -// -// notable misses: -// - mesh deforms -// - cubic beziers -// - shears -// - bounding boxes - -enum { SPINE_MAX_BONES = 64 }; // max bones - -typedef struct spine_bone_t { - char *name, *parent; - struct spine_bone_t *parent_bone; - - float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) - - float len; - float x, y, deg; // base - float x2, y2, deg2; // accum / temporaries during bone transform time - float x3, y3, deg3; // values from timeline - - unsigned rect_id; - unsigned atlas_id; -} spine_bone_t; - -typedef struct spine_slot_t { - char *name, *bone, *attach; -} spine_slot_t; - -typedef struct spine_rect_t { - char *name; - float x,y,w,h,sx,sy,deg; -} spine_rect_t; - -typedef struct spine_skin_t { - char *name; - array(spine_rect_t) rects; -} spine_skin_t; - -typedef struct spine_animkey_t { // offline; only during loading - float time, curve[4]; // time is mandatory, curve is optional - union { - char *name; // type: attachment (mode-1) - struct { float deg; }; // type: rotate (mode-2) - struct { float x,y; }; // type: translate (mode-3) - }; -} spine_animkey_t; - -#if 0 -typedef struct spine_pose_t { // runtime; only during playing - unsigned frame; - array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) -} spine_pose_t; -#endif - -typedef struct spine_anim_t { - char *name; - union { -#if 0 - struct { - unsigned frames; - array(spine_pose_t) poses; - }; -#endif - struct { - array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; - array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; - }; - }; -} spine_anim_t; - -typedef struct spine_atlas_t { - char *name; - float x,y,w,h,deg; -} spine_atlas_t; - -typedef struct spine_t { - char *name; - texture_t texture; - unsigned skin; - array(spine_bone_t) bones; - array(spine_slot_t) slots; - array(spine_skin_t) skins; - array(spine_anim_t) anims; - array(spine_atlas_t) atlas; - // anim controller - unsigned inuse; - float time, maxtime; - unsigned debug_atlas_id; -} spine_t; - -// --- - -static -void spine_convert_animkeys_to_animpose(spine_anim_t *input) { - spine_anim_t copy = *input; // @todo - // @leak: attach/rot/tra keys -} - -static -int find_bone_id(spine_t *s, const char *bone_name) { - for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) - if( !strcmp(s->bones[i].name, bone_name)) return i; - return -1; -} -static -spine_bone_t *find_bone(spine_t *s, const char *bone_name) { - int bone_id = find_bone_id(s, bone_name); - return bone_id >= 0 ? &s->bones[bone_id] : NULL; -} - -void spine_skin(spine_t *p, unsigned skin) { - if( !p->texture.id ) return; - if( skin >= array_count(p->skins) ) return; - - p->skin = skin; - - char *skin_name = va("%s/", p->skins[skin].name); - int header = strlen(skin_name); - - for( int i = 0; i < array_count(p->atlas); ++i) { - if(!strbeg(p->atlas[i].name, skin_name)) continue; - - int bone_id = find_bone_id(p, p->atlas[i].name+header ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].atlas_id = i; - } - - for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { - int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); - if( bone_id < 0 ) continue; - - p->bones[bone_id].rect_id = i; - } -} - -static -bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { - char *atlas = vfs_read(file_atlas); - if(!atlas || !atlas[0]) return false; - - memset(t, 0, sizeof(spine_t)); - - // goblins.png - // size: 1024, 128 - // filter: Linear, Linear - // pma: true - // dagger - // bounds: 2, 18, 26, 108 - // goblin/eyes-closed - // bounds: 2, 4, 34, 12 - spine_atlas_t *sa = 0; - const char *last_id = 0; - const char *texture_name = 0; - const char *texture_filter = 0; - const char *texture_format = 0; - const char *texture_repeat = 0; - float texture_width = 0, texture_height = 0, temp; - for each_substring(atlas, "\r\n", it) { - it += strspn(it, " \t\f\v"); - /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored - else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); - else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) - else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string - else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string - else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string - else if( strbeg(it, "bounds:" ) ) { - sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); - } - else if( !texture_name ) texture_name = va("%s", it); - else { - array_push(t->atlas, ((spine_atlas_t){0}) ); - sa = &t->atlas[array_count(t->atlas) - 1]; - sa->name = STRDUP(it); - } - } - for( int i = 0; i < array_count(t->atlas); ++i ) { - sa = &t->atlas[i]; - sa->x /= texture_width, sa->y /= texture_height; - sa->w /= texture_width, sa->h /= texture_height; - } - - if(!texture_name) return false; - - t->texture = texture(texture_name, TEXTURE_LINEAR); - - json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? - - array_resize(t->bones, json_count("/bones")); - array_reserve(t->slots, json_count("/slots")); - array_resize(t->skins, json_count("/skins")); - array_resize(t->anims, json_count("/animations")); - - for( int i = 0, end = json_count("/bones"); i < end; ++i ) { - spine_bone_t v = {0}; - v.name = STRDUP(json_string("/bones[%d]/name", i)); - v.parent = STRDUP(json_string("/bones[%d]/parent", i)); - v.x = json_float("/bones[%d]/x", i); - v.y = json_float("/bones[%d]/y", i); - v.z = i; - v.len = json_float("/bones[%d]/length", i); - v.deg = json_float("/bones[%d]/rotation", i); - t->bones[i] = v; - - for( int j = i-1; j > 0; --j ) { - if( strcmp(t->bones[j].name,v.parent) ) continue; - t->bones[i].parent_bone = &t->bones[j]; - break; - } - } - - for( int i = 0, end = json_count("/slots"); i < end; ++i ) { - spine_slot_t v = {0}; - v.name = STRDUP(json_string("/slots[%d]/name", i)); - v.bone = STRDUP(json_string("/slots[%d]/bone", i)); - v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); - - array_push(t->slots, v); - - // slots define draw-order. so, update draw-order/zindex in bone - spine_bone_t *b = find_bone(t, v.name); - if( b ) b->z = i; - } - - for( int i = 0, end = json_count("/skins"); i < end; ++i ) { - spine_skin_t v = {0}; - v.name = STRDUP(json_string("/skins[%d]/name", i)); - - for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ - for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ - spine_rect_t r = {0}; - r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); - r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); - r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); - r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; - r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; - r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); - r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); - r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); - array_push(v.rects, r); - } - - t->skins[i] = v; - } - -#if 1 - // simplify: - // merge /skins/default into existing /skins/*, then delete /skins/default - if( array_count(t->skins) > 1 ) { - for( int i = 1; i < array_count(t->skins); ++i ) { - for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { - array_push(t->skins[i].rects, t->skins[0].rects[j]); - } - } - // @leak @fixme: FREE(t->skins[0]) - for( int i = 0; i < array_count(t->skins)-1; ++i ) { - t->skins[i] = t->skins[i+1]; - } - array_pop(t->skins); - } -#endif - - for( int i = 0, end = json_count("/animations"); i < end; ++i ) { - int id; - const char *name; - - spine_anim_t v = {0}; - v.name = STRDUP(json_key("/animations[%d]", i)); - - // slots / attachments - - for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) - for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids - { - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - spine_animkey_t key = {0}; - - key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); - key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); - } - - // @todo: convert name to id - // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) - // printf("%s vs %s\n", key.name, t->bones[id].name); - - array_push(v.attach_keys[bone_id], key); - } - } - - // bones - - for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones - for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids - int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); - if( bone_id < 0 ) continue; - - // parse bones - for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) - const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); - int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; - if( !track ) continue; - - spine_animkey_t key = {0}; - - key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); - if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { - key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); - key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); - key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); - key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); - } - - if( track == 1 ) - key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" - array_push(v.rotate_keys[bone_id], key); - else - key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), - key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), - array_push(v.translate_keys[bone_id], key); - } - } - - t->anims[i] = v; - } - - json_pop(); - - spine_skin(t, 0); - - return true; -} - -spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { - spine_t *t = MALLOC(sizeof(spine_t)); - if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; - return t; -} - -void spine_render(spine_t *p, vec3 offset, unsigned flags) { - if( !p->texture.id ) return; - if( !flags ) return; - - ddraw_push_2d(); - // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); - // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); - - // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches - - for( int i = 1; i < array_count(p->bones); ++i ) { - spine_bone_t *self = &p->bones[i]; - if( !self->rect_id ) continue; - - int num_bones = 0; - static array(spine_bone_t*) chain = 0; array_resize(chain, 0); - for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { - array_push(chain, next); - } - - vec3 target = {0}, prev = {0}; - for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction - int j_opposite = end - 1 - j; - - spine_bone_t *b = chain[j_opposite]; // bone - spine_bone_t *pb = b->parent_bone; // parent bone - - float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; - if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; - - const float deg2rad = C_PI / 180; - b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); - b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); - b->deg2 = -b->deg3 + pb_deg2 - b->deg; - - prev = target; - target = vec3(b->x2,b->y2,b->deg2); - } - - target.z = 0; - target = add3(target, offset); - prev.z = 0; - prev = add3(prev, offset); - - if( flags & 2 ) { - ddraw_point( target ); - ddraw_text( target, -0.25f, self->name ); - ddraw_bone( prev, target ); // from parent to bone - } - if( flags & 1 ) { - spine_atlas_t *a = &p->atlas[self->atlas_id]; - spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; - - vec4 rect = ptr4(&a->x); - float zindex = self->z; - float offsx = 0; - float offsy = 0; - float tilt = self->deg2 + (a->deg - r->deg); - unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; - - if( 1 ) { - vec3 dir = vec3(r->x,r->y,0); - dir = rotatez3(dir, self->deg2); - offsx = dir.x * r->sx; - offsy = dir.y * r->sy; - } - - sprite_rect(p->texture, rect, zindex, add4(vec4(target.x,target.y,1,1),vec4(offsx,offsy,0,0)), tilt, tint); - } - } - - ddraw_pop_2d(); - ddraw_flush(); -} - -static -void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { - if( !p->texture.id ) return; - - if( delta > 1/120.f ) delta = 1/120.f; - if( *time >= *maxtime ) *time = 0; else *time += delta; - - // reset root // needed? - p->bones[0].x2 = 0; - p->bones[0].y2 = 0; - p->bones[0].deg2 = 0; - p->bones[0].x3 = 0; - p->bones[0].y3 = 0; - p->bones[0].deg3 = 0; - - for( int i = 0, end = array_count(p->bones); i < end; ++i) { - // @todo: attach channel - // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} - for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].deg3 = r->deg; - } - } - for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { - double r0 = r->time; - *maxtime = maxf( *maxtime, r0 ); - if( absf(*time - r0) < delta ) { - p->bones[i].x3 = r->x; - p->bones[i].y3 = r->y; - } - } - } -} - -void spine_animate(spine_t *p, float delta) { - spine_animate_(p, &p->time, &p->maxtime, delta); -} - -void ui_spine(spine_t *p) { - if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { - for each_array_ptr(p->anims, spine_anim_t, q) { - if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { - spine_animate(p, 0); - } - - int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); - if( choice == 1 ) window_pause( 0 ); // play - if( choice == 2 ) window_pause( 1 ); // pause - - for( int i = 0; i < SPINE_MAX_BONES; ++i ) { - ui_separator(); - ui_label(va("Bone %d: Attachment keys", i)); - for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); - } - ui_label(va("Bone %d: Rotate keys", i)); - for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); - } - ui_label(va("Bone %d: Translate keys", i)); - for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { - ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); - } - } - } - ui_collapse_end(); - } - if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { - for each_array_ptr(p->bones, spine_bone_t, q) - if( ui_collapse(q->name, va("%p-b2", q)) ) { - ui_label2("Parent:", q->parent); - ui_label2("X:", va("%.2f", q->x)); - ui_label2("Y:", va("%.2f", q->y)); - ui_label2("Length:", va("%.2f", q->len)); - ui_label2("Rotation:", va("%.2f", q->deg)); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { - for each_array_ptr(p->slots, spine_slot_t, q) - if( ui_collapse(q->name, va("%p-s2", q)) ) { - ui_label2("Bone:", q->bone); - ui_label2("Attachment:", q->attach); - ui_collapse_end(); - } - ui_collapse_end(); - } - if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { - for each_array_ptr(p->skins, spine_skin_t, q) - if( ui_collapse(q->name, va("%p-k2", q)) ) { - for each_array_ptr(q->rects, spine_rect_t, r) - if( ui_collapse(r->name, va("%p-k3", r)) ) { - ui_label2("X:", va("%.2f", r->x)); - ui_label2("Y:", va("%.2f", r->y)); - ui_label2("Scale X:", va("%.2f", r->sx)); - ui_label2("Scale Y:", va("%.2f", r->sy)); - ui_label2("Width:", va("%.2f", r->w)); - ui_label2("Height:", va("%.2f", r->h)); - ui_label2("Rotation:", va("%.2f", r->deg)); - ui_collapse_end(); - - spine_bone_t *b = find_bone(p, r->name); - if( b ) { - p->debug_atlas_id = b->atlas_id; - - static float tilt = 0; - if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; - spine_atlas_t *r = p->atlas + b->atlas_id; - sprite_flush(); - camera_get_active()->position = vec3(0,0,2); - vec4 rect = ptr4(&r->x); float zindex = 0; vec3 xy_zoom = vec3(0,0,0); unsigned tint = ~0u; - sprite_rect(p->texture, - // rect: vec4(r->x*1.0/p->texture.w,r->y*1.0/p->texture.h,(r->x+r->w)*1.0/p->texture.w,(r->y+r->h)*1.0/p->texture.h), - ptr4(&r->x), // atlas - 0, vec4(0,0,1,1), r->deg + tilt, tint); - sprite_flush(); - camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); - } - } - ui_collapse_end(); - } - ui_collapse_end(); - } - - if( ui_int("Use skin", &p->skin) ) { - p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); - spine_skin(p, p->skin); - } - - if( p->texture.id ) ui_texture(0, p->texture); -} - // ----------------------------------------------------------------------------- // cubemaps @@ -21054,7 +20107,7 @@ anims_t animations(const char *pathfile, int flags) { } #line 0 -#line 1 "engine/split/v4k_renderdd.c" +#line 1 "v4k_renderdd.c" static const char *dd_vs = "//" FILELINE "\n" "in vec3 att_position;\n" "uniform mat4 u_MVP;\n" @@ -21902,7 +20955,7 @@ void ddraw_demo() { } #line 0 -#line 1 "engine/split/v4k_scene.c" +#line 1 "v4k_scene.c" // // @todo: remove explicit GL code from here @@ -22474,7 +21527,1476 @@ void scene_render(int flags) { } #line 0 -#line 1 "engine/split/v4k_system.c" +#line 1 "v4k_sprite.c" +// ---------------------------------------------------------------------------- +// sprites + +typedef struct sprite_static_t { + float px, py, pz; // origin x, y, depth + float ox, oy, cos, sin; // offset x, offset y, cos/sin of rotation degree + float sx, sy; // scale x,y + float cellw, cellh; // dimensions of any cell in spritesheet + + union { + struct { + int frame, ncx, ncy; // frame in a (num cellx, num celly) spritesheet + }; + struct { + float x, y, w, h; // normalized[0..1] within texture bounds + }; + }; + + uint32_t rgba, flags; // vertex color and flags +} sprite_static_t; + +// sprite batching +typedef struct batch_t { array(sprite_static_t) sprites; mesh_t mesh; int dirty; } batch_t; +typedef map(int, batch_t) batch_group_t; // mapkey is anything that forces a flush. texture_id for now, might be texture_id+program_id soon + +// sprite stream +typedef struct sprite_vertex { vec3 pos; vec2 uv; uint32_t rgba; } sprite_vertex; +typedef struct sprite_index { GLuint triangle[3]; } sprite_index; + +#define sprite_vertex(...) C_CAST(sprite_vertex, __VA_ARGS__) +#define sprite_index(...) C_CAST(sprite_index, __VA_ARGS__) + +// sprite impl +static int sprite_count = 0; +static int sprite_program = -1; +static array(sprite_index) sprite_indices = 0; +static array(sprite_vertex) sprite_vertices = 0; + +// center_wh << 2 | additive << 1 | projected << 0 +static batch_group_t sprite_group[8] = {0}; + +// rect(x,y,w,h) is [0..1] normalized, pos(xyz,z-index), scale_offset(sx,sy,offx,offy), rotation (degrees), color (rgba) +void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scale_offset, float tilt_deg, unsigned tint_rgba, unsigned flags) { + float zindex = pos.w; + float scalex = scale_offset.x; + float scaley = scale_offset.y; + float offsetx = scale_offset.z; + float offsety = scale_offset.w; + + // do not queue if either scales or alpha are zero + if( 0 == (scalex * scaley * ((tint_rgba>>24) & 255)) ) return; + + ASSERT( (flags & SPRITE_CENTERED) == 0 ); + if( flags & SPRITE_PROJECTED ) { + tilt_deg += 180, scalex = -scalex; // flip texture Y on mvp3d (same than turn 180º then flip X) + } + + sprite_static_t s = {0}; + + s.px = pos.x, s.py = pos.y, s.pz = pos.z - zindex; + s.sx = scalex, s.sy = scaley; + + s.x = rect.x, s.y = rect.y, s.w = rect.z, s.h = rect.w; + s.cellw = s.w * s.sx * t.w, s.cellh = s.h * s.sy * t.h; + + s.rgba = tint_rgba; + s.flags = flags; + +#if 0 + s.ox = 0/*ox*/ * s.sx; + s.oy = 0/*oy*/ * s.sy; +#else + s.ox += offsetx * scalex; + s.oy += offsety * scaley; +#endif + + if( tilt_deg ) { + tilt_deg = (tilt_deg + 0) * ((float)C_PI / 180); + s.cos = cosf(tilt_deg); + s.sin = sinf(tilt_deg); + } else { + s.cos = 1; + s.sin = 0; + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; + batch_t *found = map_find_or_add(*batches, t.id, (batch_t){0}); + + array_push(found->sprites, s); +} + +void sprite_sheet( texture_t texture, float spritesheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags) { + flags |= SPRITE_CENTERED; + ASSERT( flags & SPRITE_CENTERED ); + + const float px = position[0], py = position[1], pz = position[2]; + const float ox = offset[0], oy = offset[1], sx = scale[0], sy = scale[1]; + const float frame = spritesheet[0], xcells = spritesheet[1], ycells = spritesheet[2]; + + if (frame < 0) return; + if (frame > 0 && frame >= (xcells * ycells)) return; + + // no need to queue if alpha or scale are zero + if( sx && sy && alpha(rgba) ) { + vec3 bak = camera_get_active()->position; + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + } + + sprite_static_t s; + s.px = px; + s.py = py; + s.pz = pz; + s.frame = frame; + s.ncx = xcells ? xcells : 1; + s.ncy = ycells ? ycells : 1; + s.sx = sx; + s.sy = sy; + s.ox = ox * sx; + s.oy = oy * sy; + s.cellw = (texture.x * sx / s.ncx); + s.cellh = (texture.y * sy / s.ncy); + s.rgba = rgba; + s.flags = flags; + s.cos = 1; + s.sin = 0; + if(rotation) { + rotation = (rotation + 0) * ((float)C_PI / 180); + s.cos = cosf(rotation); + s.sin = sinf(rotation); + } + + batch_group_t *batches = &sprite_group[ flags & 7 ]; +#if 0 + batch_t *found = map_find(*batches, texture.id); + if( !found ) found = map_insert(*batches, texture.id, (batch_t){0}); +#else + batch_t *found = map_find_or_add(*batches, texture.id, (batch_t){0}); +#endif + + array_push(found->sprites, s); + + if( flags & SPRITE_RESOLUTION_INDEPENDANT ) { // @todo: optimize me + sprite_flush(); + camera_get_active()->position = bak; + } + } +} + +void sprite( texture_t texture, float position[3], float rotation, unsigned color, unsigned flags) { + float offset[2] = {0,0}, scale[2] = {1,1}, spritesheet[3] = {0,0,0}; + sprite_sheet( texture, spritesheet, position, rotation, offset, scale, color, flags ); +} + +static void sprite_rebuild_meshes() { + sprite_count = 0; + + // w/2,h/2 centered + for( int l = countof(sprite_group) / 2; l < countof(sprite_group); ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float cx = (1.0f / it->ncx) - 1e-9f; + float cy = (1.0f / it->ncy) - 1e-9f; + int idx = (int)it->frame; + int px = idx % it->ncx; + int py = idx / it->ncx; + + float ux = px * cx, uy = py * cy; + float vx = ux + cx, vy = uy + cy; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } + + // (0,0) centered + for( int l = 0; l < countof(sprite_group) / 2; ++l) { + for each_map_ptr(sprite_group[l], int,_, batch_t,bt) { + + bt->dirty = array_count(bt->sprites) ? 1 : 0; + if( !bt->dirty ) continue; + + int index = 0; + array_clear(sprite_indices); + array_clear(sprite_vertices); + + array_foreach_ptr(bt->sprites, sprite_static_t,it ) { + float x0 = it->ox - it->cellw/2, x3 = x0 + it->cellw; + float y0 = it->oy - it->cellh/2, y3 = y0; + float x1 = x0, x2 = x3; + float y1 = y0 + it->cellh, y2 = y1; + + // @todo: move this affine transform into glsl shader + vec3 v0 = { it->px + ( x0 * it->cos - y0 * it->sin ), it->py + ( x0 * it->sin + y0 * it->cos ), it->pz }; + vec3 v1 = { it->px + ( x1 * it->cos - y1 * it->sin ), it->py + ( x1 * it->sin + y1 * it->cos ), it->pz }; + vec3 v2 = { it->px + ( x2 * it->cos - y2 * it->sin ), it->py + ( x2 * it->sin + y2 * it->cos ), it->pz }; + vec3 v3 = { it->px + ( x3 * it->cos - y3 * it->sin ), it->py + ( x3 * it->sin + y3 * it->cos ), it->pz }; + + float ux = it->x, vx = ux + it->w; + float uy = it->y, vy = uy + it->h; + + vec2 uv0 = vec2(ux, uy); + vec2 uv1 = vec2(ux, vy); + vec2 uv2 = vec2(vx, vy); + vec2 uv3 = vec2(vx, uy); + + array_push( sprite_vertices, sprite_vertex(v0, uv0, it->rgba) ); // Vertex 0 (A) + array_push( sprite_vertices, sprite_vertex(v1, uv1, it->rgba) ); // Vertex 1 (B) + array_push( sprite_vertices, sprite_vertex(v2, uv2, it->rgba) ); // Vertex 2 (C) + array_push( sprite_vertices, sprite_vertex(v3, uv3, it->rgba) ); // Vertex 3 (D) + + // A--B A A-B + // quad | | becomes triangle |\ and triangle \| + // D--C D-C C + GLuint A = (index+0), B = (index+1), C = (index+2), D = (index+3); index += 4; + + array_push( sprite_indices, sprite_index(C, D, A) ); // Triangle 1 + array_push( sprite_indices, sprite_index(C, A, B) ); // Triangle 2 + } + + mesh_update(&bt->mesh, "p3 t2 c4B", 0,array_count(sprite_vertices),sprite_vertices, 3*array_count(sprite_indices),sprite_indices, MESH_STATIC); + + // clear elements from queue + sprite_count += array_count(bt->sprites); + array_clear(bt->sprites); + } + } +} + +static void sprite_render_meshes_group(batch_group_t* sprites, int alpha_key, int alpha_value, float mvp[16]) { + if( map_count(*sprites) > 0 ) { + // setup shader + if( sprite_program < 0 ) { + sprite_program = shader( vfs_read("shaders/vs_324_24_sprite.glsl"), vfs_read("shaders/fs_24_4_sprite.glsl"), + "att_Position,att_TexCoord,att_Color", + "fragColor", NULL + ); + } + shader_bind(sprite_program); + shader_mat44("u_mvp", mvp); + + // set (unit 0) in the uniform texture sampler, and render batch + glActiveTexture(GL_TEXTURE0); + glBlendFunc( alpha_key, alpha_value ); + + for each_map_ptr(*sprites, int,texture_id, batch_t,bt) { + if( bt->dirty ) { + shader_texture_unit("u_texture", *texture_id, 0); + mesh_render(&bt->mesh); + } + } +// map_clear(*sprites); + } +} + +static void sprite_init() { + do_once for(int i = 0; i < countof(sprite_group); ++i) { + map_init(sprite_group[i], less_int, hash_int); + } +} + +void sprite_flush() { + profile("Sprite.rebuild_time") { + sprite_rebuild_meshes(); + } + profile("Sprite.render_time") { + // setup rendering state + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glDepthFunc(GL_LEQUAL); // try to help with zfighting + + // 3d + mat44 mvp3d; multiply44x2(mvp3d, camera_get_active()->proj, camera_get_active()->view); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + sprite_render_meshes_group(&sprite_group[SPRITE_PROJECTED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp3d ); + + // 2d: (0,0) is center of screen + mat44 mvp2d; + vec3 pos = camera_get_active()->position; + float zoom = absf(pos.z); if(zoom < 0.1f) zoom = 0.1f; zoom = 1.f / (zoom + !zoom); + float zdepth_max = window_height(); // 1; + float l = pos.x - window_width() * zoom / 2; + float r = pos.x + window_width() * zoom / 2; + float b = pos.y + window_height() * zoom / 2; + float t = pos.y - window_height() * zoom / 2; + ortho44(mvp2d, l,r,b,t, -zdepth_max, +zdepth_max); + // render all additive then translucent groups + sprite_render_meshes_group(&sprite_group[0], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED], GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_CENTERED|SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + sprite_render_meshes_group(&sprite_group[SPRITE_ADDITIVE], GL_SRC_ALPHA, GL_ONE, mvp2d ); + + // restore rendering state + glDisable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glDepthFunc(GL_LESS); + glUseProgram(0); + } +} + +// ----------------------------------------------------------------------------- +// tilemaps + +tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr) { + tilemap_t t = {0}; + t.tint = ~0u; // WHITE + t.blank_chr = blank_chr; + for( ; *map ; ++map ) { + if( map[0] == linefeed_chr ) ++t.rows; + else { + array_push(t.map, map[0]); + ++t.cols; + } + } + return t; +} + +void tilemap_render_ext( tilemap_t m, tileset_t t, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ) { + vec3 old_pos = camera_get_active()->position; + sprite_flush(); + camera_get_active()->position = vec3(window_width()/2,window_height()/2,1); + + float scale[2] = {xy_zoom[2], xy_zoom[2]}; + xy_zoom[2] = zindex; + + float offset[2] = {0,0}; + float spritesheet[3] = {0,t.cols,t.rows}; // selected tile index and spritesheet dimensions (cols,rows) + + for( unsigned y = 0, c = 0; y < m.rows; ++y ) { + for( unsigned x = 0; x < m.cols; ++x, ++c ) { + if( m.map[c] != m.blank_chr ) { + spritesheet[0] = m.map[c]; + sprite_sheet(t.tex, spritesheet, xy_zoom, tilt, offset, scale, tint, is_additive ? SPRITE_ADDITIVE : 0); + } + offset[0] += t.tile_w; + } + offset[0] = 0, offset[1] += t.tile_h; + } + + sprite_flush(); + camera_get_active()->position = old_pos; +} + +void tilemap_render( tilemap_t map, tileset_t set ) { + map.position.x += set.tile_w; + map.position.y += set.tile_h; + tilemap_render_ext( map, set, map.zindex, &map.position.x, map.tilt, map.tint, map.is_additive ); +} + +tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows) { + tileset_t t = {0}; + t.tex = tex; + t.cols = cols, t.rows = rows; + t.tile_w = tile_w, t.tile_h = tile_h; + return t; +} + +int ui_tileset( tileset_t t ) { + ui_subimage(va("Selection #%d (%d,%d)", t.selected, t.selected % t.cols, t.selected / t.cols), t.tex.id, t.tex.w, t.tex.h, (t.selected % t.cols) * t.tile_w, (t.selected / t.cols) * t.tile_h, t.tile_w, t.tile_h); + int choice; + if( (choice = ui_image(0, t.tex.id, t.tex.w,t.tex.h)) ) { + int px = ((choice / 100) / 100.f) * t.tex.w / t.tile_w; + int py = ((choice % 100) / 100.f) * t.tex.h / t.tile_h; + t.selected = px + py * t.cols; + } + // if( (choice = ui_buttons(3, "load", "save", "clear")) ) {} + return t.selected; +} + +// ----------------------------------------------------------------------------- +// tiled + +tiled_t tiled(const char *file_tmx) { + tiled_t zero = {0}, ti = zero; + + // read file and parse json + if( !xml_push(file_tmx) ) return zero; + + // sanity checks + bool supported = !strcmp(xml_string("/map/@orientation"), "orthogonal") && !strcmp(xml_string("/map/@renderorder"), "right-down"); + if( !supported ) return xml_pop(), zero; + + // tileset + const char *file_tsx = xml_string("/map/tileset/@source"); + if( !xml_push(vfs_read(file_tsx)) ) return zero; + const char *set_src = xml_string("/tileset/image/@source"); + int set_w = xml_int("/tileset/@tilewidth"); + int set_h = xml_int("/tileset/@tileheight"); + int set_c = xml_int("/tileset/@columns"); + int set_r = xml_int("/tileset/@tilecount") / set_c; + tileset_t set = tileset(texture(set_src,0), set_w, set_h, set_c, set_r ); + xml_pop(); + + // actual parsing + ti.w = xml_int("/map/@width"); + ti.h = xml_int("/map/@height"); + ti.tilew = xml_int("/map/@tilewidth"); + ti.tileh = xml_int("/map/@tileheight"); + ti.first_gid = xml_int("/map/tileset/@firstgid"); + ti.map_name = STRDUP( xml_string("/map/tileset/@source") ); // @leak + + for(int l = 0, layers = xml_count("/map/layer"); l < layers; ++l ) { + if( strcmp(xml_string("/map/layer[%d]/data/@encoding",l), "base64") || strcmp(xml_string("/map/layer[%d]/data/@compression",l), "zlib") ) { + PRINTF("Warning: layer encoding not supported: '%s' -> layer '%s'\n", file_tmx, *array_back(ti.names)); + continue; + } + + int cols = xml_int("/map/layer[%d]/@width",l); + int rows = xml_int("/map/layer[%d]/@height",l); + + tilemap_t tm = tilemap("", ' ', '\n'); + tm.blank_chr = ~0u; //ti.first_gid - 1; + tm.cols = cols; + tm.rows = rows; + array_resize(tm.map, tm.cols * tm.rows); + memset(tm.map, 0xFF, tm.cols * tm.rows * sizeof(int)); + + for( int c = 0, chunks = xml_count("/map/layer[%d]/data/chunk", l); c <= chunks; ++c ) { + int cw, ch; + int cx, cy; + array(char) b64 = 0; + + if( !chunks ) { // non-infinite mode + b64 = xml_blob("/map/layer[%d]/data/$",l); + cw = tm.cols, ch = tm.rows; + cx = 0, cy = 0; + } else { // infinite mode + b64 = xml_blob("/map/layer[%d]/data/chunk[%d]/$",l,c); + cw = xml_int("/map/layer[%d]/data/chunk[%d]/@width",l,c), ch = xml_int("/map/layer[%d]/data/chunk[%d]/@height",l,c); // 20x20 + cx = xml_int("/map/layer[%d]/data/chunk[%d]/@x",l,c), cy = xml_int("/map/layer[%d]/data/chunk[%d]/@y",l,c); // (-16,-32) + cx = abs(cx), cy = abs(cy); + } + + int outlen = cw * ch * 4; + static __thread int *out = 0; out = (int *)REALLOC( 0, outlen + zexcess(COMPRESS_ZLIB) ); // @leak + if( zdecode( out, outlen, b64, array_count(b64), COMPRESS_ZLIB ) > 0 ) { + for( int y = 0, p = 0; y < ch; ++y ) { + for( int x = 0; x < cw; ++x, ++p ) { + if( out[p] >= ti.first_gid ) { + int offset = (x + cx) + (y + cy) * tm.cols; + if( offset >= 0 && offset < (cw * ch) ) + tm.map[ offset ] = out[ p ] - ti.first_gid; + } + } + } + } + else { + PRINTF("Warning: bad zlib stream: '%s' -> layer #%d -> chunk #%d\n", file_tmx, l, c); + } + + array_free(b64); + } + + array_push(ti.layers, tm); + array_push(ti.names, STRDUP(xml_string("/map/layer[%d]/@name",l))); + array_push(ti.visible, true); + array_push(ti.sets, set); + } + + xml_pop(); + return ti; +} + +void tiled_render(tiled_t tmx, vec3 pos) { + for( unsigned i = 0, end = array_count(tmx.layers); i < end; ++i ) { + tmx.layers[i].position = pos; // add3(camera_get_active()->position, pos); + if( tmx.parallax ) tmx.layers[i].position.x /= (3+i), tmx.layers[i].position.y /= (5+i); + if( tmx.visible[i] ) tilemap_render(tmx.layers[i], tmx.sets[i]); + } +} + +void ui_tiled(tiled_t *t) { + ui_label2("Loaded map", t->map_name ? t->map_name : "(none)"); + ui_label2("Map dimensions", va("%dx%d", t->w, t->h)); + ui_label2("Tile dimensions", va("%dx%d", t->tilew, t->tileh)); + ui_separator(); + ui_bool("Parallax", &t->parallax); + ui_separator(); + ui_label2("Layers", va("%d", array_count(t->layers))); + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_label2_toolbar(va("- %s (%dx%d)", t->names[i], t->layers[i].cols, t->layers[i].rows ), t->visible[i] ? "\xee\xa3\xb4" : "\xee\xa3\xb5") > 0 ) { // ICON_MD_VISIBILITY / ICON_MD_VISIBILITY_OFF + t->visible[i] ^= true; + } + } + ui_separator(); + if( ui_collapse(va("Sets: %d", array_count(t->layers)), va("%p",t))) { + for( int i = 0; i < array_count(t->layers); ++i ) { + if( ui_collapse(va("%d", i+1), va("%p%d",t,i)) ) { + t->sets[i].selected = ui_tileset( t->sets[i] ); + ui_collapse_end(); + } + } + ui_collapse_end(); + } +} + +// ----------------------------------------------------------------------------- +// spine json loader (wip) +// - rlyeh, public domain +// +// [ref] http://es.esotericsoftware.com/spine-json-format +// +// notable misses: +// - mesh deforms +// - cubic beziers +// - shears +// - bounding boxes + +enum { SPINE_MAX_BONES = 64 }; // max bones + +typedef struct spine_bone_t { + char *name, *parent; + struct spine_bone_t *parent_bone; + + float z; // draw order usually matches bone-id. ie, zindex == bone_id .. root(0) < chest (mid) < finger(top) + + float len; + float x, y, deg; // base + float x2, y2, deg2; // accum / temporaries during bone transform time + float x3, y3, deg3; // values from timeline + + unsigned rect_id; + unsigned atlas_id; +} spine_bone_t; + +typedef struct spine_slot_t { + char *name, *bone, *attach; +} spine_slot_t; + +typedef struct spine_rect_t { + char *name; + float x,y,w,h,sx,sy,deg; +} spine_rect_t; + +typedef struct spine_skin_t { + char *name; + array(spine_rect_t) rects; +} spine_skin_t; + +typedef struct spine_animkey_t { // offline; only during loading + float time, curve[4]; // time is mandatory, curve is optional + union { + char *name; // type: attachment (mode-1) + struct { float deg; }; // type: rotate (mode-2) + struct { float x,y; }; // type: translate (mode-3) + }; +} spine_animkey_t; + +#if 0 +typedef struct spine_pose_t { // runtime; only during playing + unsigned frame; + array(vec4) xform; // entry per bone. translation(x,y),rotation(z),attachment-id(w) +} spine_pose_t; +#endif + +typedef struct spine_anim_t { + char *name; + union { +#if 0 + struct { + unsigned frames; + array(spine_pose_t) poses; + }; +#endif + struct { + array(spine_animkey_t) attach_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) rotate_keys[SPINE_MAX_BONES]; + array(spine_animkey_t) translate_keys[SPINE_MAX_BONES]; + }; + }; +} spine_anim_t; + +typedef struct spine_atlas_t { + char *name; + float x,y,w,h,deg; +} spine_atlas_t; + +typedef struct spine_t { + char *name; + texture_t texture; + unsigned skin; + array(spine_bone_t) bones; + array(spine_slot_t) slots; + array(spine_skin_t) skins; + array(spine_anim_t) anims; + array(spine_atlas_t) atlas; + // anim controller + unsigned inuse; + float time, maxtime; + unsigned debug_atlas_id; +} spine_t; + +// --- + +static +void spine_convert_animkeys_to_animpose(spine_anim_t *input) { + spine_anim_t copy = *input; // @todo + // @leak: attach/rot/tra keys +} + +static +int find_bone_id(spine_t *s, const char *bone_name) { + for( unsigned i = 0, end = array_count(s->bones); i < end; ++i ) + if( !strcmp(s->bones[i].name, bone_name)) return i; + return -1; +} +static +spine_bone_t *find_bone(spine_t *s, const char *bone_name) { + int bone_id = find_bone_id(s, bone_name); + return bone_id >= 0 ? &s->bones[bone_id] : NULL; +} + +void spine_skin(spine_t *p, unsigned skin) { + if( !p->texture.id ) return; + if( skin >= array_count(p->skins) ) return; + + p->skin = skin; + + char *skin_name = va("%s/", p->skins[skin].name); + int header = strlen(skin_name); + + for( int i = 0; i < array_count(p->atlas); ++i) { + if(!strbeg(p->atlas[i].name, skin_name)) continue; + + int bone_id = find_bone_id(p, p->atlas[i].name+header ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].atlas_id = i; + } + + for( int i = 0; i < array_count(p->skins[p->skin].rects); ++i) { + int bone_id = find_bone_id(p, p->skins[p->skin].rects[i].name ); + if( bone_id < 0 ) continue; + + p->bones[bone_id].rect_id = i; + } +} + +static +bool spine_(spine_t *t, const char *file_json, const char *file_atlas, unsigned flags) { + char *atlas = vfs_read(file_atlas); + if(!atlas || !atlas[0]) return false; + + memset(t, 0, sizeof(spine_t)); + + // goblins.png + // size: 1024, 128 + // filter: Linear, Linear + // pma: true + // dagger + // bounds: 2, 18, 26, 108 + // goblin/eyes-closed + // bounds: 2, 4, 34, 12 + spine_atlas_t *sa = 0; + const char *last_id = 0; + const char *texture_name = 0; + const char *texture_filter = 0; + const char *texture_format = 0; + const char *texture_repeat = 0; + float texture_width = 0, texture_height = 0, temp; + for each_substring(atlas, "\r\n", it) { + it += strspn(it, " \t\f\v"); + /**/ if( strbeg(it, "pma:" ) || strbeg(it, "index:") ) {} // ignored + else if( strbeg(it, "size:" ) ) sscanf(it+5, "%f,%f", &texture_width, &texture_height); + else if( strbeg(it, "rotate:" ) ) { float tmp; tmp=sa->w,sa->w=sa->h,sa->h=tmp; sa->deg = 90; } // assert(val==90) + else if( strbeg(it, "repeat:" ) ) texture_repeat = it+7; // temp string + else if( strbeg(it, "filter:" ) ) texture_filter = it+7; // temp string + else if( strbeg(it, "format:" ) ) texture_format = it+7; // temp string + else if( strbeg(it, "bounds:" ) ) { + sscanf(it+7, "%f,%f,%f,%f", &sa->x, &sa->y, &sa->w, &sa->h); + } + else if( !texture_name ) texture_name = va("%s", it); + else { + array_push(t->atlas, ((spine_atlas_t){0}) ); + sa = &t->atlas[array_count(t->atlas) - 1]; + sa->name = STRDUP(it); + } + } + for( int i = 0; i < array_count(t->atlas); ++i ) { + sa = &t->atlas[i]; + sa->x /= texture_width, sa->y /= texture_height; + sa->w /= texture_width, sa->h /= texture_height; + } + + if(!texture_name) return false; + + t->texture = texture(texture_name, TEXTURE_LINEAR); + + json_push(vfs_read(file_json)); // @fixme: json_push_from_file() ? + + array_resize(t->bones, json_count("/bones")); + array_reserve(t->slots, json_count("/slots")); + array_resize(t->skins, json_count("/skins")); + array_resize(t->anims, json_count("/animations")); + + for( int i = 0, end = json_count("/bones"); i < end; ++i ) { + spine_bone_t v = {0}; + v.name = STRDUP(json_string("/bones[%d]/name", i)); + v.parent = STRDUP(json_string("/bones[%d]/parent", i)); + v.x = json_float("/bones[%d]/x", i); + v.y = json_float("/bones[%d]/y", i); + v.z = i; + v.len = json_float("/bones[%d]/length", i); + v.deg = json_float("/bones[%d]/rotation", i); + t->bones[i] = v; + + for( int j = i-1; j > 0; --j ) { + if( strcmp(t->bones[j].name,v.parent) ) continue; + t->bones[i].parent_bone = &t->bones[j]; + break; + } + } + + for( int i = 0, end = json_count("/slots"); i < end; ++i ) { + spine_slot_t v = {0}; + v.name = STRDUP(json_string("/slots[%d]/name", i)); + v.bone = STRDUP(json_string("/slots[%d]/bone", i)); + v.attach = STRDUP(json_string("/slots[%d]/attachment", i)); + + array_push(t->slots, v); + + // slots define draw-order. so, update draw-order/zindex in bone + spine_bone_t *b = find_bone(t, v.name); + if( b ) b->z = i; + } + + for( int i = 0, end = json_count("/skins"); i < end; ++i ) { + spine_skin_t v = {0}; + v.name = STRDUP(json_string("/skins[%d]/name", i)); + + for( int j = 0, jend = json_count("/skins[%d]/attachments",i); j < jend; ++j ) // /skins/default/ + for( int k = 0, kend = json_count("/skins[%d]/attachments[%d]",i,j); k < kend; ++k ) { // /skins/default/left hand item/ + spine_rect_t r = {0}; + r.name = STRDUP(json_key("/skins[%d]/attachments[%d][%d]",i,j,k)); // stringf("%s-%s-%s", json_key("/skins[%d]",i), json_key("/skins[%d][%d]",i,j), json_key("/skins[%d][%d][%d]",i,j,k)); + r.x = json_float("/skins[%d]/attachments[%d][%d]/x",i,j,k); + r.y = json_float("/skins[%d]/attachments[%d][%d]/y",i,j,k); + r.sx= json_float("/skins[%d]/attachments[%d][%d]/scaleX",i,j,k); r.sx += !r.sx; + r.sy= json_float("/skins[%d]/attachments[%d][%d]/scaleY",i,j,k); r.sy += !r.sy; + r.w = json_float("/skins[%d]/attachments[%d][%d]/width",i,j,k); + r.h = json_float("/skins[%d]/attachments[%d][%d]/height",i,j,k); + r.deg = json_float("/skins[%d]/attachments[%d][%d]/rotation",i,j,k); + array_push(v.rects, r); + } + + t->skins[i] = v; + } + +#if 1 + // simplify: + // merge /skins/default into existing /skins/*, then delete /skins/default + if( array_count(t->skins) > 1 ) { + for( int i = 1; i < array_count(t->skins); ++i ) { + for( int j = 0; j < array_count(t->skins[0].rects); ++j ) { + array_push(t->skins[i].rects, t->skins[0].rects[j]); + } + } + // @leak @fixme: FREE(t->skins[0]) + for( int i = 0; i < array_count(t->skins)-1; ++i ) { + t->skins[i] = t->skins[i+1]; + } + array_pop(t->skins); + } +#endif + + for( int i = 0, end = json_count("/animations"); i < end; ++i ) { + int id; + const char *name; + + spine_anim_t v = {0}; + v.name = STRDUP(json_key("/animations[%d]", i)); + + // slots / attachments + + for( int j = 0, jend = json_count("/animations[%d]/slots",i); j < jend; ++j ) + for( int k = 0, kend = json_count("/animations[%d]/slots[%d]",i,j); k < kend; ++k ) // ids + { + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + for( int l = 0, lend = json_count("/animations[%d]/slots[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + spine_animkey_t key = {0}; + + key.name = STRDUP(json_string("/animations[%d]/slots[%d][%d][%d]/name",i,j,k,l)); + key.time = json_float("/animations[%d]/slots[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/slots[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/slots[%d][%d][%d]/curve[3]",i,j,k,l); + } + + // @todo: convert name to id + // for(id = 0; t->bones[id].name && strcmp(t->bones[id].name,key.name); ++id) + // printf("%s vs %s\n", key.name, t->bones[id].name); + + array_push(v.attach_keys[bone_id], key); + } + } + + // bones + + for( int j = 0, jend = json_count("/animations[%d]/bones",i); j < jend; ++j ) // slots or bones + for( int k = 0, kend = json_count("/animations[%d]/bones[%d]",i,j); k < kend; ++k ) { // bone ids + int bone_id = find_bone_id(t, json_key("/animations[%d]/bones[%d]",i,j)); + if( bone_id < 0 ) continue; + + // parse bones + for( int l = 0, lend = json_count("/animations[%d]/bones[%d][%d]",i,j,k); l < lend; ++l ) { // channels (rot,tra,attach) + const char *channel = json_key("/animations[%d]/bones[%d][%d]",i,j,k); + int track = !strcmp(channel, "rotate") ? 1 : !strcmp(channel, "translate") ? 2 : 0; + if( !track ) continue; + + spine_animkey_t key = {0}; + + key.time = json_float("/animations[%d]/bones[%d][%d][%d]/time",i,j,k,l); + if( json_count("/animations[%d]/bones[%d][%d][%d]/curve",i,j,k,l) == 4 ) { + key.curve[0] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[0]",i,j,k,l); + key.curve[1] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[1]",i,j,k,l); + key.curve[2] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[2]",i,j,k,l); + key.curve[3] = json_float("/animations[%d]/bones[%d][%d][%d]/curve[3]",i,j,k,l); + } + + if( track == 1 ) + key.deg = json_float("/animations[%d]/bones[%d][%d][%d]/value",i,j,k,l), // "/angle" + array_push(v.rotate_keys[bone_id], key); + else + key.x = json_float("/animations[%d]/bones[%d][%d][%d]/x",i,j,k,l), + key.y = json_float("/animations[%d]/bones[%d][%d][%d]/y",i,j,k,l), + array_push(v.translate_keys[bone_id], key); + } + } + + t->anims[i] = v; + } + + json_pop(); + + spine_skin(t, 0); + + return true; +} + +spine_t* spine(const char *file_json, const char *file_atlas, unsigned flags) { + spine_t *t = MALLOC(sizeof(spine_t)); + if( !spine_(t, file_json, file_atlas, flags) ) return FREE(t), NULL; + return t; +} + +void spine_render(spine_t *p, vec3 offset, unsigned flags) { + if( !p->texture.id ) return; + if( !flags ) return; + + ddraw_push_2d(); + // if( flags & 2 ) ddraw_line(vec3(0,0,0), vec3(window_width(),window_height(),0)); + // if( flags & 2 ) ddraw_line(vec3(window_width(),0,0), vec3(0,window_height(),0)); + + // int already_computed[SPINE_MAX_BONES] = {0}; // @fixme: optimize: update longest chains first, then remnant branches + + for( int i = 1; i < array_count(p->bones); ++i ) { + spine_bone_t *self = &p->bones[i]; + if( !self->rect_id ) continue; + + int num_bones = 0; + static array(spine_bone_t*) chain = 0; array_resize(chain, 0); + for( spine_bone_t *next = self; next ; next = next->parent_bone, ++num_bones ) { + array_push(chain, next); + } + + vec3 target = {0}, prev = {0}; + for( int j = 0, end = array_count(chain); j < end; ++j ) { // traverse from root(skipped) -> `i` bone direction + int j_opposite = end - 1 - j; + + spine_bone_t *b = chain[j_opposite]; // bone + spine_bone_t *pb = b->parent_bone; // parent bone + + float pb_x2 = 0, pb_y2 = 0, pb_deg2 = 0; + if( pb ) pb_x2 = pb->x2, pb_y2 = pb->y2, pb_deg2 = pb->deg2; + + const float deg2rad = C_PI / 180; + b->x2 = b->x3 + pb_x2 + b->x * cos( -pb_deg2 * deg2rad ) - b->y * sin( -pb_deg2 * deg2rad ); + b->y2 = -b->y3 + pb_y2 - b->y * cos( pb_deg2 * deg2rad ) + b->x * sin( pb_deg2 * deg2rad ); + b->deg2 = -b->deg3 + pb_deg2 - b->deg; + + prev = target; + target = vec3(b->x2,b->y2,b->deg2); + } + + target.z = 0; + target = add3(target, offset); + prev.z = 0; + prev = add3(prev, offset); + + if( flags & 2 ) { + ddraw_point( target ); + ddraw_text( target, -0.25f, self->name ); + ddraw_bone( prev, target ); // from parent to bone + } + if( flags & 1 ) { + spine_atlas_t *a = &p->atlas[self->atlas_id]; + spine_rect_t *r = &p->skins[p->skin].rects[self->rect_id]; + + vec4 rect = ptr4(&a->x); + float zindex = self->z; + float offsx = 0; + float offsy = 0; + float tilt = self->deg2 + (a->deg - r->deg); + unsigned tint = self->atlas_id == p->debug_atlas_id ? 0xFF<<24 | 0xFF : ~0u; + + if( 1 ) { + vec3 dir = vec3(r->x,r->y,0); + dir = rotatez3(dir, self->deg2); + offsx = dir.x * r->sx; + offsy = dir.y * r->sy; + } + + sprite_rect(p->texture, rect, vec4(target.x,target.y,0,zindex), vec4(1,1,offsx,offsy), tilt, tint, 0); + } + } + + ddraw_pop_2d(); + ddraw_flush(); +} + +static +void spine_animate_(spine_t *p, float *time, float *maxtime, float delta) { + if( !p->texture.id ) return; + + if( delta > 1/120.f ) delta = 1/120.f; + if( *time >= *maxtime ) *time = 0; else *time += delta; + + // reset root // needed? + p->bones[0].x2 = 0; + p->bones[0].y2 = 0; + p->bones[0].deg2 = 0; + p->bones[0].x3 = 0; + p->bones[0].y3 = 0; + p->bones[0].deg3 = 0; + + for( int i = 0, end = array_count(p->bones); i < end; ++i) { + // @todo: attach channel + // @todo: per channel: if curve == linear || curve == stepped || array_count(curve) == 4 {...} + for each_array_ptr(p->anims[p->inuse].rotate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].deg3 = r->deg; + } + } + for each_array_ptr(p->anims[p->inuse].translate_keys[i], spine_animkey_t, r) { + double r0 = r->time; + *maxtime = maxf( *maxtime, r0 ); + if( absf(*time - r0) < delta ) { + p->bones[i].x3 = r->x; + p->bones[i].y3 = r->y; + } + } + } +} + +void spine_animate(spine_t *p, float delta) { + spine_animate_(p, &p->time, &p->maxtime, delta); +} + +void ui_spine(spine_t *p) { + if( ui_collapse(va("Anims: %d", array_count(p->anims)), va("%p-a", p))) { + for each_array_ptr(p->anims, spine_anim_t, q) { + if(ui_slider2("", &p->time, va("%.2f/%.0f %.2f%%", p->time, p->maxtime, p->time * 100.f))) { + spine_animate(p, 0); + } + + int choice = ui_label2_toolbar(q->name, ICON_MD_PAUSE_CIRCLE " " ICON_MD_PLAY_CIRCLE); + if( choice == 1 ) window_pause( 0 ); // play + if( choice == 2 ) window_pause( 1 ); // pause + + for( int i = 0; i < SPINE_MAX_BONES; ++i ) { + ui_separator(); + ui_label(va("Bone %d: Attachment keys", i)); + for each_array_ptr(q->attach_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %s", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->name)); + } + ui_label(va("Bone %d: Rotate keys", i)); + for each_array_ptr(q->rotate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] %.2f deg", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->deg)); + } + ui_label(va("Bone %d: Translate keys", i)); + for each_array_ptr(q->translate_keys[i], spine_animkey_t, r) { + ui_label(va("%.2f [%.2f %.2f %.2f %.2f] (%.2f,%.2f)", r->time, r->curve[0], r->curve[1], r->curve[2], r->curve[3], r->x, r->y)); + } + } + } + ui_collapse_end(); + } + if( ui_collapse(va("Bones: %d", array_count(p->bones)), va("%p-b", p))) { + for each_array_ptr(p->bones, spine_bone_t, q) + if( ui_collapse(q->name, va("%p-b2", q)) ) { + ui_label2("Parent:", q->parent); + ui_label2("X:", va("%.2f", q->x)); + ui_label2("Y:", va("%.2f", q->y)); + ui_label2("Length:", va("%.2f", q->len)); + ui_label2("Rotation:", va("%.2f", q->deg)); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Slots: %d", array_count(p->slots)), va("%p-s", p))) { + for each_array_ptr(p->slots, spine_slot_t, q) + if( ui_collapse(q->name, va("%p-s2", q)) ) { + ui_label2("Bone:", q->bone); + ui_label2("Attachment:", q->attach); + ui_collapse_end(); + } + ui_collapse_end(); + } + if( ui_collapse(va("Skins: %d", array_count(p->skins)), va("%p-k", p))) { + for each_array_ptr(p->skins, spine_skin_t, q) + if( ui_collapse(q->name, va("%p-k2", q)) ) { + for each_array_ptr(q->rects, spine_rect_t, r) + if( ui_collapse(r->name, va("%p-k3", r)) ) { + ui_label2("X:", va("%.2f", r->x)); + ui_label2("Y:", va("%.2f", r->y)); + ui_label2("Scale X:", va("%.2f", r->sx)); + ui_label2("Scale Y:", va("%.2f", r->sy)); + ui_label2("Width:", va("%.2f", r->w)); + ui_label2("Height:", va("%.2f", r->h)); + ui_label2("Rotation:", va("%.2f", r->deg)); + ui_collapse_end(); + + spine_bone_t *b = find_bone(p, r->name); + if( b ) { + p->debug_atlas_id = b->atlas_id; + + static float tilt = 0; + if( input(KEY_LCTRL) ) tilt += 60*1/60.f; else tilt = 0; + spine_atlas_t *r = p->atlas + b->atlas_id; + sprite_flush(); + camera_get_active()->position = vec3(0,0,2); + vec4 rect = ptr4(&r->x); float zindex = 0; vec4 scale_offset = vec4(1,1,0,0); + sprite_rect(p->texture, ptr4(&r->x), vec4(0,0,0,zindex), scale_offset, r->deg + tilt, ~0u, 0); + sprite_flush(); + camera_get_active()->position = vec3(+window_width()/3,window_height()/2.25,2); + } + } + ui_collapse_end(); + } + ui_collapse_end(); + } + + if( ui_int("Use skin", &p->skin) ) { + p->skin = clampf(p->skin, 0, array_count(p->skins) - 1); + spine_skin(p, p->skin); + } + + if( p->texture.id ) ui_texture(0, p->texture); +} + +// ---------------------------------------------------------------------------- + +// texture_t texture_createclip(unsigned cx,unsigned cy,unsigned cw,unsigned ch, unsigned tw,unsigned th,unsigned tn,void *pixels, unsigned flags) { +// return texture_create(tw,th,tn,pixels,flags); +// static array(unsigned) clip = 0; +// array_resize(clip, cw*ch*4); +// for( unsigned y = 0; y < ch; ++y ) +// memcpy((char *)clip + (0+(0+y)*cw)*tn, (char*)pixels + (cx+(cy+y)*tw)*tn, cw*tn); +// return texture_create(cw,ch,tn,clip,flags); +// } + +typedef unsigned quark_t; + +#define array_reserve_(arr,x) (array_count(arr) > (x) ? (arr) : array_resize(arr, 1+(x))) + +#define ui_array(label,type,ptr) do { \ + int changed = 0; \ + if( ui_collapse(label, va(#type "%p",ptr)) ) { \ + char label_ex[8]; \ + for( int idx = 0, iend = array_count(*(ptr)); idx < iend; ++idx ) { \ + type* it = *(ptr) + idx; \ + snprintf(label_ex, sizeof(label_ex), "[%d]", idx); \ + changed |= ui_##type(label_ex, it); \ + } \ + ui_collapse_end(); \ + } \ +} while(0) + +int ui_vec2i(const char *label, vec2i *v) { return ui_unsigned2(label, (unsigned*)v); } +int ui_vec3i(const char *label, vec3i *v) { return ui_unsigned3(label, (unsigned*)v); } +int ui_vec2(const char *label, vec2 *v) { return ui_float2(label, (float*)v); } +int ui_vec3(const char *label, vec3 *v) { return ui_float3(label, (float*)v); } +int ui_vec4(const char *label, vec4 *v) { return ui_float4(label, (float*)v); } + +char *trimspace(char *str) { + for( char *s = str; *s; ++s ) + if(*s <= 32) memmove(s, s+1, strlen(s)); + return str; +} + +char *file_parent(const char *f) { // folder/folder/abc + char *p = file_path(f); // folder/folder/ + char *last = strrchr(p, '/'); // ^ + if( !last ) return p; // return parent if no sep + *last = '\0'; // folder/folder + last = strrchr(p, '/'); // ^ + return last ? last + 1 : p; // return parent if no sep +} + +int ui_obj(const char *fmt, obj *o) { + int changed = 0, item = 1; + for each_objmember(o, TYPE,NAME,PTR) { + char *label = va(fmt, NAME); + /**/ if(!strcmp(TYPE,"float")) { if(ui_float(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"int")) { if(ui_int(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"unsigned")) { if(ui_unsigned(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec2")) { if(ui_float2(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec3")) { if(ui_float3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"vec4")) { if(ui_float4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgb")) { if(ui_color3(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"rgba")) { if(ui_color4(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color3f")) { if(ui_color3f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"color4f")) { if(ui_color4f(label, PTR)) changed = item; } + else if(!strcmp(TYPE,"char*")) { if(ui_string(label, PTR)) changed = item; } + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + ++item; + } + return changed; +} + +#define OBJTYPEDEF2(...) OBJTYPEDEF(__VA_ARGS__); AUTORUN + +// ---------------------------------------------------------------------------- +// atlas + +typedef struct atlas_frame_t { + unsigned delay; + vec4 sheet; + vec2 anchor; // @todo + array(vec3i) indices; + array(vec2) coords; + array(vec2) uvs; +} atlas_frame_t; + +typedef struct atlas_anim_t { + quark_t name; + array(unsigned) frames; +} atlas_anim_t; + +typedef struct atlas_t { + texture_t tex; + + array(atlas_frame_t) frames; + array(atlas_anim_t) anims; + + quarks_db db; +} atlas_t; + +int ui_atlas_frame(atlas_frame_t *f) { + ui_unsigned("delay", &f->delay); + ui_vec4("sheet", &f->sheet); + ui_array("indices", vec3i, &f->indices); + ui_array("coords", vec2, &f->coords); + ui_array("uvs", vec2, &f->uvs); + return 0; +} + +int ui_atlas(atlas_t *a) { + int changed = 0; + ui_texture(NULL, a->tex); + for( int i = 0; i < array_count(a->anims); ++i ) { + if( ui_collapse(quark_string(&a->db, a->anims[i].name), va("%p%d", a, a->anims[i].name) ) ) { + changed = i+1; + for( int j = 0; j < array_count(a->anims[i].frames); ++j ) { + if( ui_collapse(va("[%d]",j), va("%p%d.%d", a, a->anims[i].name,j) ) ) { + ui_unsigned("Frame", &a->anims[i].frames[j]); + ui_atlas_frame(a->frames + a->anims[i].frames[j]); + ui_collapse_end(); + } + } + ui_collapse_end(); + } + } + return changed; +} + +void atlas_destroy(atlas_t *a) { + if( a ) { + texture_destroy(&a->tex); + memset(a, 0, sizeof(atlas_t)); + } +} +atlas_t atlas_create(const char *inifile, unsigned flags) { + atlas_t a = {0}; + int padding = 0, border = 0; + + ini_t kv = ini(inifile); + for each_map(kv, char*,k, char*,v ) { + unsigned index = atoi(k); + /**/ if( strend(k, ".name") ) { + array_reserve_(a.anims, index); + + a.anims[index].name = quark_intern(&a.db, v); + } + else if( strend(k, ".frames") ) { + array_reserve_(a.anims, index); + + array(char*) pairs = strsplit(v, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned frame = atoi(pairs[i]); + unsigned delay = atoi(pairs[i+1]); + + array_reserve_(a.frames, frame); + a.frames[frame].delay = delay; + + array_push(a.anims[index].frames, frame); + } + } + else if( strend(k, ".sheet") ) { + array_reserve_(a.frames, index); + + vec4 sheet = atof4(v); //x,y,x2+2,y2+2 -> x,y,w,h (for 2,2 padding) + a.frames[index].sheet = vec4(sheet.x,sheet.y,sheet.z-sheet.x,sheet.w-sheet.y); + } + else if( strend(k, ".indices") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) tuples = strsplit(text, ","); + for( int i = 0, end = array_count(tuples); i < end; i += 3 ) { + unsigned p1 = atoi(tuples[i]); + unsigned p2 = atoi(tuples[i+1]); + unsigned p3 = atoi(tuples[i+2]); + array_push(a.frames[index].indices, vec3i(p1,p2,p3)); + } + } + else if( strend(k, ".coords") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned x = atoi(pairs[i]); + unsigned y = atoi(pairs[i+1]); + array_push(a.frames[index].coords, vec2(x,y)); + } + } + else if( strend(k, ".uvs") ) { + array_reserve_(a.frames, index); + + const char *text = v; + array(char*) pairs = strsplit(text, ","); + for( int i = 0, end = array_count(pairs); i < end; i += 2 ) { + unsigned u = atoi(pairs[i]); + unsigned v = atoi(pairs[i+1]); + array_push(a.frames[index].uvs, vec2(u,v)); + } + } + else if( strend(k, "padding") ) { + padding = atoi(v); + } + else if( strend(k, "border") ) { + border = atoi(v); + } + else if( strend(k, "file") ) { + a.tex = texture(v, 0); + } + else if( strend(k, "bitmap") ) { + const char *text = v; + array(char) bin = base64_decode(text, strlen(text)); + a.tex = texture_from_mem(bin, array_count(bin), 0); + array_free(bin); + } +#if 0 + else if( strend(k, ".frame") ) { + array_reserve_(a.frames, index); + puts(k), puts(v); + } +#endif + } + + // post-process: normalize uvs and coords into [0..1] ranges + for each_array_ptr(a.frames, atlas_frame_t, f) { + for each_array_ptr(f->uvs, vec2, uv) { + uv->x /= a.tex.w; + uv->y /= a.tex.h; + } + for each_array_ptr(f->coords, vec2, xy) { + xy->x /= a.tex.w; + xy->y /= a.tex.h; + } + // @todo: adjust padding/border + } +#if 0 + // post-process: specify an anchor for each anim based on 1st frame dims + for each_array_ptr(a.anims, atlas_anim_t, anim) { + atlas_frame_t *first = a.frames + *anim->frames; + for( int i = 0; i < array_count(anim->frames); i += 2) { + atlas_frame_t *ff = a.frames + anim->frames[ i ]; + ff->anchor.x = (ff->sheet.z - first->sheet.z) / 2; + ff->anchor.y = (ff->sheet.w - first->sheet.w) / 2; + } + } +#endif + + return a; +} + +// ---------------------------------------------------------------------------- +// sprite v2 + +void sprite_ctor(sprite_t *s) { + s->tint = WHITE; + s->timer_ms = 100; + s->flipped = 1; + s->sca.x += !s->sca.x; + s->sca.y += !s->sca.y; +} +void sprite_dtor(sprite_t *s) { + memset(s, 0, sizeof(*s)); +} +void sprite_tick(sprite_t *s) { + int right = input(s->gamepad.array[3]) - input(s->gamepad.array[2]); // RIGHT - LEFT + int forward = input(s->gamepad.array[1]) - input(s->gamepad.array[0]); // DOWN - UP + int move = right || forward; + int dt = 16; // window_delta() * 1000; + + unsigned over = (s->timer - dt) > s->timer; + if(!s->paused) s->timer -= dt; + if( over ) { + int len = array_count(s->a->anims[s->play].frames); + unsigned next = (s->frame + 1) % (len + !len); + unsigned eoa = next < s->frame; + s->frame = next; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + s->timer_ms = f->delay; + s->timer += s->timer_ms; + } + + if( s->play == 0 && move ) sprite_setanim(s, 1); + if( s->play == 1 ) { //< + if(right) s->flip_ = right < 0, sprite_setanim(s, 1); + if(!right && !forward) sprite_setanim(s, 0); + + float speed = s->sca.x*2; + s->pos = add4(s->pos, scale4(norm4(vec4(right,0,forward,0)),speed)); + } +} +void sprite_draw(sprite_t *s) { + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + +#if 1 + // @todo { + unsigned sample = s->a->anims[s->play].frames[s->frame]; + sample = 0; + f->anchor.x = (-s->a->frames[sample].sheet.z + f->sheet.z) / 2; + f->anchor.y = (+s->a->frames[sample].sheet.w - f->sheet.w) / 2; + // } +#endif + + // rect(x,y,w,h) is [0..1] normalized, z-index, pos(x,y,scale), rotation (degrees), color (rgba) + vec4 rect = { f->sheet.x / s->a->tex.w, f->sheet.y / s->a->tex.h, f->sheet.z / s->a->tex.w, f->sheet.w / s->a->tex.h }; + sprite_rect(s->a->tex, rect, s->pos, vec4(s->flip_ ^ s->flipped?s->sca.x:-s->sca.x,s->sca.y,f->anchor.x,f->anchor.y), s->tilt, s->tint, 0|SPRITE_PROJECTED); +} +void sprite_edit(sprite_t *s) { + const char *name = obj_name(s); + const char *id = vac("%p", s); + if( s && ui_collapse(name ? name : id, id) ) { + ui_obj("%s", (obj*)s); + + ui_bool("paused", &s->paused); + ui_label(va("frame anim [%d]", s->a->anims[s->play].frames[s->frame])); + + int k = s->play; + if( ui_int("anim", &k) ) { + sprite_setanim(s, k); + } + + int selected = ui_atlas(s->a); + if( selected ) sprite_setanim(s, selected - 1); + + ui_collapse_end(); + } +} + +sprite_t* sprite_new(const char *ase, int bindings[6]) { + sprite_t *s = obj_new(sprite_t, {bindings[0],bindings[1],bindings[2],bindings[3]}, {bindings[4],bindings[5]}); + atlas_t own = atlas_create(ase, 0); + memcpy(s->a = MALLOC(sizeof(atlas_t)), &own, sizeof(atlas_t)); // s->a = &s->own; + return s; +} +void sprite_del(sprite_t *s) { + if( s ) { + if( s->a ) atlas_destroy(s->a), FREE(s->a); // if( s->a == &s->own ) + obj_free(s); + memset(s, 0, sizeof(sprite_t)); + } +} +void sprite_setanim(sprite_t *s, unsigned name) { + if( s->play != name ) { + s->play = name; + s->frame = 0; + + atlas_frame_t *f = &s->a->frames[ s->a->anims[s->play].frames[s->frame] ]; + + s->timer_ms = f->delay; + s->timer = s->timer_ms; + } +} + +AUTORUN { + STRUCT(sprite_t, vec4, pos); + STRUCT(sprite_t, vec2, sca); + STRUCT(sprite_t, float, tilt); + STRUCT(sprite_t, vec4, gamepad); + STRUCT(sprite_t, vec2, fire); + STRUCT(sprite_t, rgba, tint); + STRUCT(sprite_t, unsigned, frame); + STRUCT(sprite_t, unsigned, timer); + STRUCT(sprite_t, unsigned, timer_ms); + STRUCT(sprite_t, unsigned, flipped); + STRUCT(sprite_t, unsigned, play); + EXTEND_T(sprite, ctor,edit,draw,tick); +} +#line 0 + +#line 1 "v4k_system.c" #if (is(tcc) && is(linux)) || (is(gcc) && !is(mingw)) // || is(clang) int __argc; char **__argv; #if !is(ems) @@ -22677,8 +23199,8 @@ static char **backtrace_symbols(void *const *list,int size) { static __thread char **symbols = 0; //[32][64] = {0}; if( !symbols ) { - symbols = SYS_REALLOC(0, 128 * sizeof(char*)); - for( int i = 0; i < 128; ++i) symbols[i] = SYS_REALLOC(0, 128 * sizeof(char)); + symbols = SYS_MEM_REALLOC(0, 128 * sizeof(char*)); + for( int i = 0; i < 128; ++i) symbols[i] = SYS_MEM_REALLOC(0, 128 * sizeof(char)); } if(size > 128) size = 128; @@ -22711,7 +23233,7 @@ static char **backtrace_symbols(void *const *sym,int num) { return 0; } char *callstack( int traces ) { static __thread char *output = 0; - if(!output ) output = SYS_REALLOC( 0, 128 * (64+2) ); + if(!output ) output = SYS_MEM_REALLOC( 0, 128 * (64+2) ); if( output ) output[0] = '\0'; char *ptr = output; @@ -23270,7 +23792,7 @@ int (PRINTF)(const char *text, const char *stack, const char *file, int line, co static void *panic_oom_reserve; // for out-of-memory recovery int (PANIC)(const char *error, const char *file, int line) { - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 0); + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 0); tty_color(RED); @@ -23446,7 +23968,7 @@ int (test)(const char *file, int line, const char *expr, bool result) { } #line 0 -#line 1 "engine/split/v4k_time.c" +#line 1 "v4k_time.c" // ---------------------------------------------------------------------------- // time @@ -24086,7 +24608,7 @@ void curve_destroy(curve_t *c) { } #line 0 -#line 1 "engine/split/v4k_profile.c" +#line 1 "v4k_profile.c" #if ENABLE_PROFILER profiler_t profiler; int profiler_enabled = 1; @@ -24144,7 +24666,7 @@ void (ui_profiler)() { #endif #line 0 -#line 1 "engine/split/v4k_video.c" +#line 1 "v4k_video.c" // tip: convert video to x265/mp4. note: higher crf to increase compression (default crf is 28) // ffmpeg -i {{infile}} -c:v libx265 -crf 24 -c:a copy {{outfile}} @@ -24376,7 +24898,7 @@ void record_frame() { } #line 0 -#line 1 "engine/split/v4k_window.c" +#line 1 "v4k_window.c" //----------------------------------------------------------------------------- // fps locking @@ -24803,7 +25325,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) { #define ddraw_progress_bar(JOB_ID, JOB_MAX, PERCENT) do { \ /* NDC coordinates (2d): bottom-left(-1,-1), center(0,0), top-right(+1,+1) */ \ float progress = (PERCENT+1) / 100.f; if(progress > 1) progress = 1; \ - float speed = progress < 1 ? 0.2f : 0.5f; \ + float speed = progress < 1 ? 0.05f : 0.75f; \ float smooth = previous[JOB_ID] = progress * speed + previous[JOB_ID] * (1-speed); \ \ float pixel = 2.f / window_height(), dist = smooth*2-1, y = pixel*3*JOB_ID; \ @@ -25465,7 +25987,7 @@ double window_scale() { // ok? @testme } #line 0 -#line 1 "engine/split/v4k_obj.c" +#line 1 "v4k_obj.c" // ----------------------------------------------------------------------------- // factory of handle ids, based on code by randy gaul (PD/Zlib licensed) // - rlyeh, public domain @@ -26477,7 +26999,7 @@ void *obj_make(const char *str) { } #line 0 -#line 1 "engine/split/v4k_ai.c" +#line 1 "v4k_ai.c" // AI framework // - rlyeh, public domain. // @@ -27315,7 +27837,7 @@ int ui_bt(bt_t *b) { } #line 0 -#line 1 "engine/split/v4k_editor.c" +#line 1 "v4k_editor0.c" // editing: // nope > functions: add/rem property @@ -27848,158 +28370,9 @@ int gizmo(vec3 *pos, vec3 *rot, vec3 *sca) { return modified; } -// -- localization kit - -static const char *kit_lang = "enUS", *kit_langs = - "enUS,enGB," - "frFR," - "esES,esAR,esMX," - "deDE,deCH,deAT," - "itIT,itCH," - "ptBR,ptPT," - "zhCN,zhSG,zhTW,zhHK,zhMO," - "ruRU,elGR,trTR,daDK,noNB,svSE,nlNL,plPL,fiFI,jaJP," - "koKR,csCZ,huHU,roRO,thTH,bgBG,heIL" -; - -static map(char*,char*) kit_ids; -static map(char*,char*) kit_vars; - -#ifndef KIT_FMT_ID2 -#define KIT_FMT_ID2 "%s.%s" -#endif - -void kit_init() { - do_once map_init(kit_ids, less_str, hash_str); - do_once map_init(kit_vars, less_str, hash_str); -} - -void kit_insert( const char *id, const char *translation) { - char *id2 = va(KIT_FMT_ID2, kit_lang, id); - - char **found = map_find_or_add_allocated_key(kit_ids, STRDUP(id2), NULL); - if(*found) FREE(*found); - *found = STRDUP(translation); -} - -bool kit_merge( const char *filename ) { - // @todo: xlsx2ini - return false; -} - -void kit_clear() { - map_clear(kit_ids); -} - -bool kit_load( const char *filename ) { - return kit_clear(), kit_merge( filename ); -} - -void kit_set( const char *key, const char *value ) { - value = value && value[0] ? value : ""; - - char **found = map_find_or_add_allocated_key(kit_vars, STRDUP(key), NULL ); - if(*found) FREE(*found); - *found = STRDUP(value); -} - -void kit_reset() { - map_clear(kit_vars); -} - -char *kit_translate2( const char *id, const char *lang ) { - char *id2 = va(KIT_FMT_ID2, lang, id); - - char **found = map_find(kit_ids, id2); - - // return original [[ID]] if no translation is found - if( !found ) return va("[[%s]]", id); - - // return translation if no {{moustaches}} are found - if( !strstr(*found, "{{") ) return *found; - - // else replace all found {{moustaches}} with context vars - { - // make room - static __thread char *results[16] = {0}; - static __thread unsigned counter = 0; counter = (counter+1) % 16; - - char *buffer = results[ counter ]; - if( buffer ) FREE(buffer), buffer = 0; - - // iterate moustaches - const char *begin, *end, *text = *found; - while( NULL != (begin = strstr(text, "{{")) ) { - end = strstr(begin+2, "}}"); - if( end ) { - char *var = va("%.*s", (int)(end - (begin+2)), begin+2); - char **found_var = map_find(kit_vars, var); - - if( found_var && 0[*found_var] ) { - strcatf(&buffer, "%.*s%s", (int)(begin - text), text, *found_var); - } else { - strcatf(&buffer, "%.*s{{%s}}", (int)(begin - text), text, var); - } - - text = end+2; - } else { - strcatf(&buffer, "%.*s", (int)(begin - text), text); - - text = begin+2; - } - } - - strcatf(&buffer, "%s", text); - return buffer; - } -} - -char *kit_translate( const char *id ) { - return kit_translate2( id, kit_lang ); -} - -void kit_locale( const char *lang ) { - kit_lang = STRDUP(lang); // @leak -} - -void kit_dump_state( FILE *fp ) { - for each_map(kit_ids, char *, k, char *, v) { - fprintf(fp, "[ID ] %s=%s\n", k, v); - } - for each_map(kit_vars, char *, k, char *, v) { - fprintf(fp, "[VAR] %s=%s\n", k, v); - } -} - -/* -int main() { - kit_init(); - - kit_locale("enUS"); - kit_insert("HELLO_PLAYERS", "Hi {{PLAYER1}} and {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Nice to meet you."); - - kit_locale("esES"); - kit_insert("HELLO_PLAYERS", "Hola {{PLAYER1}} y {{PLAYER2}}!"); - kit_insert("GREET_PLAYERS", "Un placer conoceros."); - - kit_locale("enUS"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hi {{PLAYER1}} and {{PLAYER2}}! Nice to meet you. - - kit_locale("esES"); - kit_set("PLAYER1", "John"); - kit_set("PLAYER2", "Karl"); - printf("%s %s\n", kit_translate("HELLO_PLAYERS"), kit_translate("GREET_PLAYERS")); // Hola John y Karl! Un placer conoceros. - - assert( 0 == strcmp(kit_translate("NON_EXISTING"), "[[NON_EXISTING]]")); // [[NON_EXISTING]] - assert(~puts("Ok")); -} -*/ #line 0 -// editor is last in place, so it can use all internals from above headers - -#line 1 "engine/split/v4k_main.c" +#line 1 "v4k_main.c" // ---------------------------------------------------------------------------- static void v4k_pre_init() { @@ -28066,7 +28439,7 @@ void v4k_init() { ifdef(debug, trap_install()); // init panic handler - panic_oom_reserve = SYS_REALLOC(panic_oom_reserve, 1<<20); // 1MiB + panic_oom_reserve = SYS_MEM_REALLOC(panic_oom_reserve, 1<<20); // 1MiB // init glfw glfw_init(); @@ -28092,7 +28465,2155 @@ void v4k_init() { } #line 0 -#line 1 "engine/split/v4k_end.c" +// editor is last in place, so it can use all internals from above headers +#line 1 "v4k_editor.c" +// ## Editor long-term plan +// - editor = tree of nodes. levels and objects are nodes, and their widgets are also nodes +// - you can perform actions on nodes, with or without descendants, top-bottom or bottom-top +// - these operations include load/save, undo/redo, reset, play/render, ddraw, etc +// - nodes are saved to disk as a filesystem layout: parents are folders, and leafs are files +// - network replication can be done by external tools by comparing the filesystems and by sending the resulting diff zipped +// +// ## Editor roadmap +// - Gizmos?, scene tree, property editor?, load/save?, undo/redo?, copy/paste, on/off (vis,tick,ddraw,log), vcs. +// - Scenenode pass: node singleton display, node console, node labels, node outlines?. +// - Render pass: billboards?, materials, un/lit, cast shadows, wireframe, skybox?/mie?, fog/atmosphere +// - Level pass: volumes, triggers, platforms, level streaming, collide?, physics +// - Edit pass: Procedural content, brushes, noise and CSG. +// - GUI pass: timeline and data tracks, node graphs. + +// ## Alt plan +// editor is a database + window/tile manager + ui toolkit; all network driven. +// to be precise, editor is a dumb app and ... +// - does not know a thing about what it stores. +// - does not know how to render the game graphics. +// - does not know how to run the game logic. +// +// the editor will create a canvas for your game to render. +// your game will be responsible to tick the logic and render the window inside the editor. +// +// that being said, editor... +// - can store datas hierarchically. +// - can perform diffs and merges, and version the datas into repositories. +// - can be instructed to render UI on top of game and window views. +// - can download new .natvis and plugins quickly. +// - can dump whole project in a filesystem form (zip). + +// - editor reflects database contents up-to-date. +// - database can be queried and modified via OSC(UDP) commands. + +// editor database uses one table, and stores two kind of payload types: +// - classes: defines typename and dna. class names are prefixed by '@' +// - instances: defines typename and datas. instance names are as-is, not prefixed. +// +// every save contains 5Ws: what, who, when, where, how, +// every save can be diffed/merged. + +// ---------------------------------------------------------------------------- + +#define EDITOR_VERSION "2023.10" + +// ---------------------------------------------------------------------------- + +typedef struct editor_bind_t { + const char *command; + const char *bindings; + void (*fn)(); +} editor_bind_t; + +array(editor_bind_t) editor_binds; + +#define EDITOR_BIND(CMD,KEYS,...) void macro(editor_bind_##CMD##_fn_)() { __VA_ARGS__ }; AUTORUN { array_push(editor_binds, ((editor_bind_t){#CMD,KEYS,macro(editor_bind_##CMD##_fn_)}) ); } + +// ---------------------------------------------------------------------------- + +typedef void (*editor_no_property)(void *); +array(void*) editor_persist_kv; +array(editor_no_property) editor_no_properties; + +#define EDITOR_PROPERTY(property_name,T,defaults) \ +typedef map(void*,T) editor_##property_name##_map_t; \ +editor_##property_name##_map_t *editor_##property_name##_map() { \ + static editor_##property_name##_map_t map = 0; do_once map_init_ptr(map); \ + return ↦ \ +} \ +T editor_##property_name(const void *obj) { \ + return *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ +} \ +void editor_set##property_name(const void *obj, T value) { \ + *map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) value)) = ((T) value); \ +} \ +void editor_alt##property_name(const void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + *found = (T)(uintptr_t)!(*found); \ +} \ +void editor_no##property_name(void *obj) { \ + T* found = map_find_or_add(*editor_##property_name##_map(), (void*)obj, ((T) defaults)); \ + map_erase(*editor_##property_name##_map(), (void*)obj); \ +} \ +AUTORUN { array_push(editor_persist_kv, #T); array_push(editor_persist_kv, editor_##property_name##_map()); array_push(editor_no_properties, editor_no##property_name); } + +EDITOR_PROPERTY(open, int, 0); // whether object is tree opened in tree editor +EDITOR_PROPERTY(selected, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(changed, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(popup, int, 0); // whether object is displaying a contextual popup or not +EDITOR_PROPERTY(visible, int, 0); +EDITOR_PROPERTY(script, int, 0); +EDITOR_PROPERTY(event, int, 0); +EDITOR_PROPERTY(iconinstance, char*, 0); +EDITOR_PROPERTY(iconclass, char*, 0); +EDITOR_PROPERTY(treeoffsety, int, 0); +// new prop: breakpoint: request to break on any given node +// new prop: persist: objects with this property will be saved on disk + +void editor_destroy_properties(void *o) { + for each_array(editor_no_properties,editor_no_property,fn) { + fn(o); + } +} + +void editor_load_on_boot(void) { +} +void editor_save_on_quit(void) { +} +AUTORUN { + editor_load_on_boot(); + (atexit)(editor_save_on_quit); +} + +// ---------------------------------------------------------------------------- + +typedef int(*subeditor)(int mode); + +struct editor_t { + // time + unsigned frame; + double t, dt, slomo; + // controls + int transparent; + int attached; + int active; // focus? does_grabinput instead? + int key; + vec2 mouse; // 2d coord for ray/picking + bool gamepad; // mask instead? |1|2|4|8 + int hz_high, hz_medium, hz_low; + int filter; + bool battery; // battery mode: low fps + bool unlit; + bool ddraw; + // event root nodes + obj* root; + obj* on_init; + obj* on_tick; + obj* on_draw; + obj* on_edit; + obj* on_quit; + // all of them (hierarchical) + array(obj*) objs; // @todo:set() world? + // all of them (flat) + set(obj*) world; + // + array(char*) cmds; + // subeditors + array(subeditor) subeditors; +} editor = { + .active = 1, + .gamepad = 1, + .hz_high = 60, .hz_medium = 18, .hz_low = 5, +}; + +enum { + EDITOR_PANEL, + EDITOR_WINDOW, + EDITOR_WINDOW_NK, + EDITOR_WINDOW_NK_SMALL, +}; + +int editor_begin(const char *title, int mode) { + if( mode == 0 ) return ui_panel(title, PANEL_OPEN); + if( mode == 1 ) return ui_window(title, 0); + + int ww = window_width(), w = ww * 0.66; + int hh = window_height(), h = hh * 0.66; + + struct nk_rect position = { (ww-w)/2,(hh-h)/2, w,h }; + nk_flags win_flags = NK_WINDOW_TITLE | NK_WINDOW_BORDER | + NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE | + NK_WINDOW_CLOSABLE | NK_WINDOW_MINIMIZABLE | + // NK_WINDOW_SCALE_LEFT|NK_WINDOW_SCALE_TOP| //< @fixme: move this logic into nuklear + // NK_WINDOW_MAXIMIZABLE | NK_WINDOW_PINNABLE | + 0; // NK_WINDOW_SCROLL_AUTO_HIDE; + + if( mode == 3 ) { + mode = 2, position.x = input(MOUSE_X), position.w = w/3, win_flags = + NK_WINDOW_TITLE|NK_WINDOW_CLOSABLE| + NK_WINDOW_SCALABLE|NK_WINDOW_MOVABLE| //< nuklear requires these two to `remember` popup rects + 0; + } + + if( mode == 2 || mode == 3 ) + if (nk_begin(ui_ctx, title, position, win_flags)) + return 1; + else + return nk_end(ui_ctx), 0; + + return 0; +} +int editor_end(int mode) { + if( mode == 0 ) return ui_panel_end(); + if( mode == 1 ) return ui_window_end(); + if( mode == 2 ) nk_end(ui_ctx); + if( mode == 3 ) nk_end(ui_ctx); + return 0; +} + +#if 0 // deprecate +bool editor_active() { + return ui_hover() || ui_active() || gizmo_active() ? editor.active : 0; +} +#endif + +int editor_filter() { + if( editor.filter ) { + if (nk_begin(ui_ctx, "Filter", nk_rect(window_width()-window_width()*0.33,32, window_width()*0.33, 40), + NK_WINDOW_NO_SCROLLBAR)) { + + char *bak = ui_filter; ui_filter = 0; + ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &bak); + ui_filter = bak; + + if( input(KEY_ESC) || ( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 )) { + if( ui_filter ) ui_filter[0] = '\0'; + editor.filter = 0; + } + } + nk_end(ui_ctx); + } + + return editor.filter; + } + +static +int editor_select_(void *o, const char *mask) { + int matches = 0; + int off = mask[0] == '!', inv = mask[0] == '~'; + int match = strmatchi(obj_type(o), mask+off+inv) || strmatchi(obj_name(o), mask+off+inv); + if( match ) { + editor_setselected(o, inv ? editor_selected(o) ^ 1 : !off); + ++matches; + } + for each_objchild(o, obj*, oo) { + matches += editor_select_(oo, mask); + } + return matches; +} +void editor_select(const char *mask) { + for each_array( editor.objs, obj*, o ) + editor_select_(o, mask); +} +void editor_unselect() { // same than editor_select("!**"); + for each_map_ptr(*editor_selected_map(), void*,o, int, k) { + if( *k ) *k = 0; + } + } + +void editor_select_aabb(aabb box) { + int is_inv = input_held(KEY_CTRL); + int is_add = input_held(KEY_SHIFT); + if( !is_inv && !is_add ) editor_unselect(); + + aabb item = {0}; + for each_set_ptr( editor.world, obj*, o ) { + if( obj_hasmethod(*o,aabb) && obj_aabb(*o, &item) ) { + if( aabb_test_aabb(item, box) ) { + if( is_inv ) + editor_altselected(*o); + else + editor_setselected(*o, 1); + } + } + } +} + +static obj* active_ = 0; +static void editor_selectgroup_(obj *o, obj *first, obj *last) { + // printf("%s (looking for %s in [%s..%s])\n", obj_name(o), active_ ? obj_name(active_) : "", obj_name(first), obj_name(last)); + if( !active_ ) if( o == first || o == last ) active_ = o == first ? last : first; + if( active_ ) editor_setselected(o, 1); + if( o == active_ ) active_ = 0; + for each_objchild(o, obj*, oo) { + editor_selectgroup_(oo, first, last); + } +} +void editor_selectgroup(obj *first, obj *last) { + if( last ) { + if( !first ) first = array_count(editor.objs) ? editor.objs[0] : NULL; + if( !first ) editor_setselected(last, 1); + else { + active_ = 0; + for each_array(editor.objs,obj*,o) { + editor_selectgroup_(o, first, last); + } + } + } + } + +static obj *find_any_selected_(obj *o) { + if( editor_selected(o) ) return o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_any_selected_(oo); + if( ooo ) + return ooo; + } + return 0; +} +void* editor_first_selected() { + for each_array(editor.objs,obj*,o) { + obj *oo = find_any_selected_(o); + // if( oo ) printf("1st found: %s\n", obj_name(oo)); + if( oo ) return oo; +} + return 0; +} + +static obj *find_last_selected_(obj *o) { + void *last = 0; + if( editor_selected(o) ) last = o; + for each_objchild(o,obj*,oo) { + obj *ooo = find_last_selected_(oo); + if( ooo ) + last = ooo; +} + return last; +} +void* editor_last_selected() { + void *last = 0; + for each_array(editor.objs,obj*,o) { + obj *oo = find_last_selected_(o); + // if( oo ) printf("last found: %s\n", obj_name(oo)); + if( oo ) last = oo; +} + return last; +} + +// ---------------------------------------------------------------------------------------- + +void editor_addtoworld(obj *o) { + set_find_or_add(editor.world, o); + for each_objchild(o, obj*, oo) { + editor_addtoworld(oo); +} +} + +void editor_watch(const void *o) { + array_push(editor.objs, (obj*)o); + obj_push(o); // save state + + editor_addtoworld((obj*)o); +} +void* editor_spawn(const char *ini) { // deprecate? + obj *o = obj_make(ini); + editor_watch(o); + return o; +} +void editor_spawn1() { + obj *selected = editor_first_selected(); + obj *o = selected ? obj_make(obj_saveini(selected)) : obj_new(obj); + if( selected ) obj_attach(selected, o), editor_setopen(selected, 1); + else + editor_watch(o); + + editor_unselect(); + editor_setselected(o, 1); +} + +typedef set(obj*) set_objp_t; +static +void editor_glob_recurse(set_objp_t*list, obj *o) { + set_find_or_add(*list, o); + for each_objchild(o,obj*,oo) { + editor_glob_recurse(list, oo); + } +} +void editor_destroy_selected() { + set_objp_t list = 0; + set_init_ptr(list); + for each_map_ptr(*editor_selected_map(), obj*,o, int,selected) { + if( *selected ) { editor_glob_recurse(&list, *o); } + } + for each_set(list, obj*, o) { + obj_detach(o); + } + for each_set(list, obj*, o) { + // printf("deleting %p %s\n", o, obj_name(o)); + // remove from watched items + for (int i = 0, end = array_count(editor.objs); i < end; ++i) { + if (editor.objs[i] == o) { + editor.objs[i] = 0; + array_erase_slow(editor.objs, i); + --end; + --i; + } + } + // delete from world + set_erase(editor.world, o); + // delete properties + obj + editor_destroy_properties(o); + obj_free(o); + } + set_free(list); +} +void editor_inspect(obj *o) { + ui_section(va("%s (%s)", obj_type(o), obj_name(o))); + + if( obj_hasmethod(o, menu) ) { + obj_menu(o); + } + + for each_objmember(o,TYPE,NAME,PTR) { + if( !editor_changed(PTR) ) { + obj_push(o); + } + ui_label_icon_highlight = editor_changed(PTR); // @hack: remove ui_label_icon_highlight hack + char *label = va(ICON_MD_UNDO "%s", NAME); + int changed = 0; + /**/ if( !strcmp(TYPE,"float") ) changed = ui_float(label, PTR); + else if( !strcmp(TYPE,"int") ) changed = ui_int(label, PTR); + else if( !strcmp(TYPE,"vec2") ) changed = ui_float2(label, PTR); + else if( !strcmp(TYPE,"vec3") ) changed = ui_float3(label, PTR); + else if( !strcmp(TYPE,"vec4") ) changed = ui_float4(label, PTR); + else if( !strcmp(TYPE,"rgb") ) changed = ui_color3(label, PTR); + else if( !strcmp(TYPE,"rgba") ) changed = ui_color4(label, PTR); + else if( !strcmp(TYPE,"color") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"color3f") ) changed = ui_color3f(label, PTR); + else if( !strcmp(TYPE,"color4f") ) changed = ui_color4f(label, PTR); + else if( !strcmp(TYPE,"char*") ) changed = ui_string(label, PTR); + else ui_label2(label, va("(%s)", TYPE)); // INFO instead of (TYPE)? + if( changed ) { + editor_setchanged(PTR, 1); + } + if( ui_label_icon_highlight ) + if( ui_label_icon_clicked_L.x >= 6 && ui_label_icon_clicked_L.x <= 26 ) { // @hack: if clicked on UNDO icon (1st icon) + editor_setchanged(PTR, 0); + } + if( !editor_changed(PTR) ) { + obj_pop(o); + } + } +} + +// ---------------------------------------------------------------------------------------- +// tty + +static thread_mutex_t *console_lock; +static array(char*) editor_jobs; +int editor_send(const char *cmd) { // return job-id + int skip = strspn(cmd, " \t\r\n"); + char *buf = STRDUP(cmd + skip); + strswap(buf, "\r\n", ""); + int jobid; + do_threadlock(console_lock) { + array_push(editor_jobs, buf); + jobid = array_count(editor_jobs) - 1; + } + return jobid; +} +const char* editor_recv(int jobid, double timeout_ss) { + char *answer = 0; + + while(!answer && timeout_ss >= 0 ) { + do_threadlock(console_lock) { + if( editor_jobs[jobid][0] == '\0' ) + answer = editor_jobs[jobid]; + } + timeout_ss -= 0.1; + if( timeout_ss > 0 ) sleep_ms(100); // thread_yield() + } + + return answer + 1; +} + +// plain and ctrl keys +EDITOR_BIND(play, "down(F5)", { window_pause(0); /* if(!editor.slomo) editor.active = 0; */ editor.slomo = 1; } ); +EDITOR_BIND(stop, "down(ESC)", { if(editor.t > 0) { window_pause(1), editor.frame = 0, editor.t = 0, editor.dt = 0, editor.slomo = 0, editor.active = 1; editor_select("**"); editor_destroy_selected(); }} ); +EDITOR_BIND(eject, "down(F1)", { /*window_pause(!editor.active); editor.slomo = !!editor.active;*/ editor.active ^= 1; } ); +EDITOR_BIND(pause, "(held(CTRL) & down(P)) | down(PAUSE)", { window_pause( window_has_pause() ^ 1 ); } ); +EDITOR_BIND(frame, "held(CTRL) & down(LEFT)", { window_pause(1); editor.frame++, editor.t += (editor.dt = 1/60.f); } ); +EDITOR_BIND(slomo, "held(CTRL) & down(RIGHT)", { window_pause(0); editor.slomo = maxf(fmod(editor.slomo * 2, 16), 0.125); } ); +EDITOR_BIND(reload, "held(CTRL) & down(F5)", { window_reload(); } ); +EDITOR_BIND(filter, "held(CTRL) & down(F)", { editor.filter ^= 1; } ); + +// alt keys +EDITOR_BIND(quit, "held(ALT) & down(F4)", { record_stop(), exit(0); } ); +EDITOR_BIND(mute, "held(ALT) & down(M)", { audio_volume_master( 1 ^ !!audio_volume_master(-1) ); } ); +EDITOR_BIND(gamepad, "held(ALT) & down(G)", { editor.gamepad ^= 1; } ); +EDITOR_BIND(transparent, "held(ALT) & down(T)", { editor.transparent ^= 1; } ); +EDITOR_BIND(record, "held(ALT) & down(Z)", { if(record_active()) record_stop(), ui_notify(va("Video recorded"), date_string()); else { char *name = file_counter(va("%s.mp4",app_name())); app_beep(), window_record(name); } } ); +EDITOR_BIND(screenshot, "held(ALT) & down(S)", { char *name = file_counter(va("%s.png",app_name())); window_screenshot(name), ui_notify(va("Screenshot: %s", name), date_string()); } ); +EDITOR_BIND(battery, "held(ALT) & down(B)", { editor.battery ^= 1; } ); +EDITOR_BIND(outliner, "held(ALT) & down(O)", { ui_show("Outliner", ui_visible("Outliner") ^ true); } ); +EDITOR_BIND(profiler, "held(ALT) & down(P)", { ui_show("Profiler", profiler_enable(ui_visible("Profiler") ^ true)); } ); +EDITOR_BIND(fullscreen, "(held(ALT)&down(ENTER))|down(F11)",{ record_stop(), window_fullscreen( window_has_fullscreen() ^ 1 ); } ); // close any recording before framebuffer resizing, which would corrupt video stream +EDITOR_BIND(unlit, "held(ALT) & down(U)", { editor.unlit ^= 1; } ); +EDITOR_BIND(ddraw, "held(ALT) & down(D)", { editor.ddraw ^= 1; } ); + +void editor_pump() { + for each_array(editor_binds,editor_bind_t,b) { + if( input_eval(b.bindings) ) { + editor_send(b.command); + } + } + + do_threadlock(console_lock) { + for each_array_ptr(editor_jobs,char*,cmd) { + if( (*cmd)[0] ) { + int found = 0; + for each_array(editor_binds,editor_bind_t,b) { + if( !strcmpi(b.command, *cmd)) { + b.fn(); + found = 1; + break; + } + } + + if( !found ) { + // alert(va("Editor: could not handle `%s` command.", *cmd)); + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Err\n"); (*cmd)[0] = '\0'; + } + + if( (*cmd)[0] ) { + (*cmd)[0] = '\0'; strcatf(&(*cmd), "\1%s\n", "Ok\n"); (*cmd)[0] = '\0'; + } + } + } + } +} + +// ---------------------------------------------------------------------------------------- + +void editor_symbol(int x, int y, const char *sym) { + #define FONT_SYMBOLS FONT_FACE2 + #define FONT_WHITE FONT_COLOR1 + #define FONT_YELLOW FONT_COLOR2 + #define FONT_ORANGE FONT_COLOR3 + #define FONT_CYAN FONT_COLOR4 + // style: atlas size, unicode ranges and 6 font faces max + do_once font_face(FONT_SYMBOLS, "MaterialIconsSharp-Regular.otf", 24.f, FONT_EM|FONT_2048); + // style: 10 colors max + do_once font_color(FONT_WHITE, WHITE); + do_once font_color(FONT_YELLOW, YELLOW); + do_once font_color(FONT_CYAN, CYAN); + do_once font_color(FONT_ORANGE, ORANGE); + font_goto(x,y); + font_print(va(FONT_SYMBOLS FONT_WHITE FONT_H1 "%s", sym)); +} + +void editor_frame( void (*game)(unsigned, float, double) ) { + do_once { + set_init_ptr(editor.world); + //set_init_ptr(editor.selection); + profiler_enable( false ); + + window_pause( true ); + window_cursor_shape(CURSOR_SW_AUTO); + editor.hz_high = window_fps_target(); + + fx_load("editorOutline.fs"); + fx_enable(0, 1); + + obj_setname(editor.root = obj_new(obj), "Signals"); + obj_setname(editor.on_init = obj_new(obj), "onInit"); + obj_setname(editor.on_tick = obj_new(obj), "onTick"); + obj_setname(editor.on_draw = obj_new(obj), "onDraw"); + obj_setname(editor.on_edit = obj_new(obj), "onEdit"); + obj_setname(editor.on_quit = obj_new(obj), "onQuit"); + + obj_attach(editor.root, editor.on_init); + obj_attach(editor.root, editor.on_tick); + obj_attach(editor.root, editor.on_draw); + obj_attach(editor.root, editor.on_edit); + obj_attach(editor.root, editor.on_quit); + + editor_seticoninstance(editor.root, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_init, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_tick, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_draw, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_edit, ICON_MDI_SIGNAL_VARIANT); + editor_seticoninstance(editor.on_quit, ICON_MDI_SIGNAL_VARIANT); + + editor_seticonclass(obj_type(editor.root), ICON_MDI_CUBE_OUTLINE); + } + + // game tick + game(editor.frame, editor.dt, editor.t); + + // timing + editor.dt = clampf(window_delta(), 0, 1/60.f) * !window_has_pause() * editor.slomo; + editor.t += editor.dt; + editor.frame += !window_has_pause(); + editor.frame += !editor.frame; + + // process inputs & messages + editor_pump(); + + // adaptive framerate + int app_on_background = !window_has_focus(); + int hz = app_on_background ? editor.hz_low : editor.battery ? editor.hz_medium : editor.hz_high; + window_fps_lock( hz < 5 ? 5 : hz ); + + // draw menubar + static int stats_mode = 1; + static double last_fps = 0; if(!window_has_pause()) last_fps = window_fps(); + const char *STATS = va("x%4.3f %03d.%03dss %02dF %s", + editor.slomo, (int)editor.t, (int)(1000 * (editor.t - (int)editor.t)), + (editor.frame-1) % ((int)window_fps_target() + !(int)window_fps_target()), + stats_mode == 1 ? va("%5.2f/%dfps", last_fps, (int)window_fps_target()) : stats_mode == 0 ? "0/0 KiB" : xstats()); + const char *ICON_PL4Y = window_has_pause() ? ICON_MDI_PLAY : ICON_MDI_PAUSE; + const char *ICON_SKIP = window_has_pause() ? ICON_MDI_STEP_FORWARD/*ICON_MDI_SKIP_NEXT*/ : ICON_MDI_FAST_FORWARD; + + int is_borderless = !glfwGetWindowAttrib(window, GLFW_DECORATED); + int ingame = !editor.active; + static double clicked_titlebar = 0; + UI_MENU(14+is_borderless, \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MDI_FILE_TREE, editor_send("scene")) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_PL4Y, if(editor.t == 0) editor_send("eject"); editor_send(window_has_pause() ? "play" : "pause")) \ + UI_MENU_ITEM(ICON_SKIP, editor_send(window_has_pause() ? "frame" : "slomo")) \ + UI_MENU_ITEM(ICON_MDI_STOP, editor_send("stop")) \ + UI_MENU_ITEM(ICON_MDI_EJECT, editor_send("eject")) \ + UI_MENU_ITEM(STATS, stats_mode = (++stats_mode) % 3) \ + UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34 + 32*is_borderless, clicked_titlebar = time_ms()) \ + if(ingame) ui_disable(); \ + UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \ + UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \ + UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \ + UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \ + UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \ + UI_MENU_ITEM(ICON_MD_SEARCH, editor_send("filter")) \ + UI_MENU_POPUP(ICON_MD_SETTINGS, vec2(0.33,1.00), ui_debug()) \ + if(ingame) ui_enable(); \ + UI_MENU_ITEM(ICON_MD_CLOSE, editor_send("quit")) \ + ); + + if( is_borderless ) { + static vec3 drag = {0}; + if( clicked_titlebar ) { + static double clicks = 0; + if( input_up(MOUSE_L) ) ++clicks; + if( input_up(MOUSE_L) && clicks == 2 ) window_visible(false), window_maximize( window_has_maximize() ^ 1 ), window_visible(true); + if( (time_ms() - clicked_titlebar) > 400 ) clicks = 0, clicked_titlebar = 0; + + if( input_down(MOUSE_L) ) drag = vec3(input(MOUSE_X), input(MOUSE_Y), 1); + } + if( drag.z *= !input_up(MOUSE_L) ) { + int wx = 0, wy = 0; + glfwGetWindowPos(window_handle(), &wx, &wy); + glfwSetWindowPos(window_handle(), wx + input(MOUSE_X) - drag.x, wy + input(MOUSE_Y) - drag.y); + } + } + + if( !editor.active ) return; + + // draw edit view (gizmos, position markers, etc). + for each_set_ptr(editor.world,obj*,o) { + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); + } +} + + // draw silhouettes + sprite_flush(); + fx_begin(); + for each_map_ptr(*editor_selected_map(),void*,o,int,selected) { + if( !*selected ) continue; + if( obj_hasmethod(*o,draw) ) { + obj_draw(*o); + } + if( obj_hasmethod(*o,edit) ) { + obj_edit(*o); +} +} + sprite_flush(); + fx_end(); + + // draw box selection + if( !ui_active() ) { //< check that we're not moving a window + static vec2 from = {0}, to = {0}; + if( input_down(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)), from = to; + if( input(MOUSE_L) ) to = vec2(input(MOUSE_X), input(MOUSE_Y)); + if( len2sq(sub2(from,to)) > 0 ) { + vec2 a = min2(from, to), b = max2(from, to); + ddraw_push_2d(); + ddraw_color_push(YELLOW); + ddraw_line( vec3(a.x,a.y,0),vec3(b.x-1,a.y,0) ); + ddraw_line( vec3(b.x,a.y,0),vec3(b.x,b.y-1,0) ); + ddraw_line( vec3(b.x,b.y,0),vec3(a.x-1,b.y,0) ); + ddraw_line( vec3(a.x,b.y,0),vec3(a.x,a.y-1,0) ); + ddraw_color_pop(); + ddraw_pop_2d(); + } + if( input_up(MOUSE_L) ) { + vec2 a = min2(from, to), b = max2(from, to); + from = to = vec2(0,0); + + editor_select_aabb(aabb(vec3(a.x,a.y,0),vec3(b.x,b.y,0))); + } + } + + // draw mouse aabb + aabb mouse = { vec3(input(MOUSE_X),input(MOUSE_Y),0), vec3(input(MOUSE_X),input(MOUSE_Y),1)}; + if( 1 ) { + ddraw_color_push(YELLOW); + ddraw_push_2d(); + ddraw_aabb(mouse.min, mouse.max); + ddraw_pop_2d(); + ddraw_color_pop(); + } + + // tick mouse aabb selection and contextual tab (RMB) + aabb box = {0}; + for each_set(editor.world,obj*,o) { + if( !obj_hasmethod(o, aabb) ) continue; + if( !obj_aabb(o, &box) ) continue; + + // trigger contextual inspector + if( input_down(MOUSE_R) ) { + int is_selected = editor_selected(o); + editor_setpopup(o, is_selected); + } + + // draw contextual inspector + if( editor_popup(o) ) { + if( editor_begin(va("%s (%s)", obj_name(o), obj_type(o)),EDITOR_WINDOW_NK_SMALL) ) { + ui_label2(obj_name(o), obj_type(o)); + editor_inspect(o); + editor_end(EDITOR_WINDOW_NK_SMALL); + } else { + editor_setpopup(o, 0); + } + } +} + + + // draw subeditors + static int preferred_window_mode = EDITOR_WINDOW; + static struct nk_color bak, *on = 0; do_once bak = ui_ctx->style.window.fixed_background.data.color; // ui_ctx->style.window.fixed_background.data.color = !!(on = (on ? NULL : &bak)) ? AS_NKCOLOR(0) : bak; }; + if( editor.transparent ) ui_ctx->style.window.fixed_background.data.color = AS_NKCOLOR(0); + for each_array(editor.subeditors, subeditor, fn) { + fn(preferred_window_mode); + } + ui_ctx->style.window.fixed_background.data.color = bak; + + // draw ui filter (note: render at end-of-frame, so it's hopefully on-top) + editor_filter(); +} +#line 0 +#line 1 "v4k_editor_scene.h" +#define SCENE_ICON ICON_MDI_FILE_TREE +#define SCENE_TITLE "Scene " SCENE_ICON + +EDITOR_BIND(scene, "held(CTRL)&down(1)", { ui_show(SCENE_TITLE, ui_visible(SCENE_TITLE) ^ true); }); + +EDITOR_PROPERTY(bookmarked, int, 0); + +EDITOR_BIND(node_new, "down(INS)", { editor_spawn1(); } ); +EDITOR_BIND(node_del, "down(DEL)", { editor_destroy_selected(); } ); +EDITOR_BIND(node_save, "held(CTRL)&down(S)", { puts("@todo"); } ); +EDITOR_BIND(scene_save, "held(CTRL)&down(S)&held(SHIFT)",{ puts("@todo"); } ); +EDITOR_BIND(select_all, "held(CTRL) & down(A)", { editor_select("**"); } ); +EDITOR_BIND(select_none, "held(CTRL) & down(D)", { editor_select("!**"); } ); +EDITOR_BIND(select_invert, "held(CTRL) & down(I)", { editor_select("~**"); } ); +EDITOR_BIND(bookmark, "held(CTRL) & down(B)", { editor_selected_map_t *map = editor_selected_map(); \ + int on = 0; \ + for each_map_ptr(*map,void*,o,int,selected) if(*selected) on |= !editor_bookmarked(*o); \ + for each_map_ptr(*map,void*,o,int,selected) if(*selected) editor_setbookmarked(*o, on); \ +} ); + +enum { + SCENE_RECURSE = 1, + SCENE_SELECTION = 2, + SCENE_CHECKBOX = 4, + SCENE_INDENT = 8, + SCENE_ALL = ~0u +}; + +static +void editor_scene_(obj *o, unsigned flags) { + static unsigned tabs = ~0u; + ++tabs; + + if( o ) { + unsigned do_tags = 1; + unsigned do_indent = !!(flags & SCENE_INDENT); + unsigned do_checkbox = !!(flags & SCENE_CHECKBOX); + unsigned do_recurse = !!(flags & SCENE_RECURSE); + unsigned do_selection = !!(flags & SCENE_SELECTION); + + nk_layout_row_dynamic(ui_ctx, 25, 1); + + const char *objicon = editor_iconinstance(o); + if(!objicon) objicon = editor_iconclass(obj_type(o)); + if(!objicon) objicon = ICON_MDI_CUBE_OUTLINE; + + const char *objname = va("%s (%s)", obj_type(o), obj_name(o)); + + const char *objchevron = + !do_recurse || array_count(*obj_children(o)) <= 1 ? ICON_MDI_CIRCLE_SMALL : + editor_open(o) ? ICON_MDI_CHEVRON_DOWN : ICON_MDI_CHEVRON_RIGHT; + + char *label = va("%*s%s%s %s", do_indent*(4+2*tabs), "", objchevron, objicon, objname); + + const char *iconsL = + //editor_selected(o) ? ICON_MD_CHECK_BOX : ICON_MD_CHECK_BOX_OUTLINE_BLANK; + editor_selected(o) ? ICON_MDI_CHECKBOX_MARKED : ICON_MDI_CHECKBOX_BLANK_OUTLINE; + + const char *iconsR = va("%s%s%s", + editor_script(o) ? ICON_MDI_SCRIPT : ICON_MDI_CIRCLE_SMALL, + editor_event(o) ? ICON_MDI_CALENDAR : ICON_MDI_CIRCLE_SMALL, + editor_visible(o) ? ICON_MDI_EYE_OUTLINE : ICON_MDI_EYE_CLOSED ); + + UI_TOOLBAR_OVERLAY_DECLARE(int choiceL, choiceR); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); + + int clicked = nk_hovered_text(ui_ctx, label, strlen(label), NK_TEXT_LEFT, editor_selected(o)); + if( clicked && nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,bounds.w*0.66,bounds.h })) ) + editor_altselected( o ); + + vec2i offset_in_tree = {0}; + + if( do_indent ) { + float thickness = 2.f; + struct nk_color color = {255,255,255,64}; + + int offsx = 30; + int spacx = 10; + int lenx = (tabs+1)*spacx; + int halfy = bounds.h / 2; + int offsy = halfy + 2; + + offset_in_tree = vec2i(bounds.x+offsx+lenx-spacx,bounds.y+offsy); + + editor_settreeoffsety(o, offset_in_tree.y); + + for( obj *p = obj_parent(o); p ; p = 0 ) + nk_stroke_line(canvas, offset_in_tree.x-6,offset_in_tree.y, offset_in_tree.x-spacx,offset_in_tree.y, thickness, color), + nk_stroke_line(canvas, offset_in_tree.x-spacx,offset_in_tree.y,offset_in_tree.x-spacx,editor_treeoffsety(p)+4, thickness, color); + } + + if( ui_contextual() ) { + int choice = ui_label(ICON_MD_BOOKMARK_ADDED "Toggle bookmarks (CTRL+B)"); + if( choice & 1 ) editor_send("bookmark"); + + ui_contextual_end(!!choice); + } + + UI_TOOLBAR_OVERLAY(choiceL,iconsL,nk_rgba_f(1,1,1,do_checkbox*ui_alpha*0.65),NK_TEXT_LEFT); + + if( do_tags ) + UI_TOOLBAR_OVERLAY(choiceR,iconsR,nk_rgba_f(1,1,1,ui_alpha*0.65),NK_TEXT_RIGHT); + + if( choiceR == 3 ) editor_altscript( o ); + if( choiceR == 2 ) editor_altevent( o); + if( choiceR == 1 ) editor_altvisible( o ); + + if( do_recurse && editor_open(o) ) { + for each_objchild(o,obj*,oo) { + editor_scene_(oo,flags); + } + } + + if( clicked && !choiceL && !choiceR ) { + int is_picking = input(KEY_CTRL); + if( !is_picking ) { + if( input(KEY_SHIFT) ) { + editor_selectgroup( editor_first_selected(), editor_last_selected() ); + } else { + editor_unselect(); + editor_setselected(o, 1); + } + } + for( obj *p = obj_parent(o); p; p = obj_parent(p) ) { + editor_setopen(p, 1); + } + if( nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect) { bounds.x,bounds.y,offset_in_tree.x-bounds.x+UI_ICON_FONTSIZE/2,bounds.h })) ) { + editor_altopen( o ); + } + } + } + + --tabs; +} + +int editor_scene(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + + if( editor_begin(SCENE_TITLE, window_mode)) { + // #define HELP ICON_MDI_INFORMATION_OUTLINE "@-A\n-B\n-C\n" ";" + int choice = ui_toolbar(ICON_MDI_PLUS "@New node (CTRL+N);" ICON_MDI_DOWNLOAD "@Save node (CTRL+S);" ICON_MDI_DOWNLOAD "@Save scene (SHIFT+CTRL+S);" ICON_MD_BOOKMARK_ADDED "@Toggle Bookmark (CTRL+B);"); + if( choice == 1 ) editor_send("node_new"); + if( choice == 2 ) editor_send("node_save"); + if( choice == 3 ) editor_send("scene_save"); + if( choice == 4 ) editor_send("bookmark"); + + array(obj*) bookmarks = 0; + for each_map_ptr(*editor_bookmarked_map(), void*,o,int,bookmarked) { + if( *bookmarked ) { + array_push(bookmarks, *o); + } + } + if( ui_collapse("!" ICON_MD_BOOKMARK "Bookmarks", "DEBUG:BOOKMARK")) { + for each_array( bookmarks, obj*, o ) + editor_scene_( o, SCENE_ALL & ~(SCENE_RECURSE|SCENE_INDENT|SCENE_CHECKBOX) ); + ui_collapse_end(); + } + array_free(bookmarks); + + editor_scene_( editor.root, SCENE_ALL ); + + for each_array( editor.objs, obj*, o ) + editor_scene_( o, SCENE_ALL ); + + ui_separator(); + + // edit selection + for each_map(*editor_selected_map(), void*,o, int, k) { + if( k ) editor_inspect(o); + } + + editor_end(window_mode); + } + + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_scene); +} +#line 0 +#line 1 "v4k_editor_browser.h" +#define BROWSER_ICON ICON_MD_FOLDER_SPECIAL +#define BROWSER_TITLE "Browser " BROWSER_ICON + +EDITOR_BIND(browser, "held(CTRL)&down(2)", { ui_show(BROWSER_TITLE, ui_visible(BROWSER_TITLE) ^ true); }); + +int editor_browser(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + if( editor_begin(BROWSER_TITLE, window_mode) ) { + const char *file = 0; + if( ui_browse(&file, NULL) ) { + const char *sep = ifdef(win32, "\"", "'"); + app_exec(va("%s %s%s%s", ifdef(win32, "start \"\"", ifdef(osx, "open", "xdg-open")), sep, file, sep)); + } + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_browser); +} +#line 0 +#line 1 "v4k_editor_timeline.h" +#define TIMELINE_ICON ICON_MDI_CHART_TIMELINE +#define TIMELINE_TITLE "Timeline " TIMELINE_ICON + +EDITOR_BIND(timeline, "held(CTRL)&down(3)", { ui_show(TIMELINE_TITLE, ui_visible(TIMELINE_TITLE) ^ true); }); + +int ui_tween(const char *label, tween_t *t) { + if( ui_filter && ui_filter[0] ) if( !strstr(label, ui_filter) ) return 0; + + int expand_keys = label[0] == '!'; label += expand_keys; + const char *id = label; + if( strchr(id, '@') ) *strchr((char*)(id = (const char*)va("%s", label)), '@') = '\0'; + + enum { LABEL_SPACING = 250 }; + enum { ROUNDING = 0 }; + enum { THICKNESS = 1 }; + enum { PIXELS_PER_SECOND = 60 }; + enum { KEY_WIDTH = 5, KEY_HEIGHT = 5 }; + enum { TIMELINE_HEIGHT = 25 }; + enum { MARKER1_HEIGHT = 5, MARKER10_HEIGHT = 20, MARKER5_HEIGHT = (MARKER1_HEIGHT + MARKER10_HEIGHT) / 2 }; + unsigned base_color = WHITE; + unsigned time_color = YELLOW; + unsigned duration_color = ORANGE; + unsigned key_color = GREEN; + + int changed = 0; + +#if 0 + // two rows with height:30 composed of three widgets + nk_layout_row_template_begin(ui_ctx, 30); + nk_layout_row_template_push_variable(ui_ctx, t->duration * PIXELS_PER_SECOND); // min 80px. can grow + nk_layout_row_template_end(ui_ctx); +#endif + + char *sid = va("%s.%d", id, 0); + uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; + for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; + ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; + + ui_label(label); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_rect bounds; nk_layout_peek(&bounds, ui_ctx); + bounds.y -= 30; + + struct nk_rect baseline = bounds; baseline.y += 30/2; + baseline.x += LABEL_SPACING; + baseline.w -= LABEL_SPACING; + + // tween duration + { + struct nk_rect pos = baseline; + pos.w = pos.x + t->duration * PIXELS_PER_SECOND; + pos.y -= TIMELINE_HEIGHT/2; + pos.h = TIMELINE_HEIGHT; + nk_stroke_rect(canvas, pos, ROUNDING, THICKNESS*2, AS_NKCOLOR(duration_color)); + } + + // tween ranges + for(int i = 0, end = array_count(t->keyframes) - 1; i < end; ++i) { + tween_keyframe_t *k = t->keyframes + i; + tween_keyframe_t *next = k + 1; + + struct nk_rect pos = baseline; + pos.x += k->t * PIXELS_PER_SECOND; + pos.w = (next->t - k->t) * PIXELS_PER_SECOND; + pos.y -= TIMELINE_HEIGHT/2; + pos.h = TIMELINE_HEIGHT; + + char *sid = va("%s.%d", id, i); + uint64_t hash = 14695981039346656037ULL, mult = 0x100000001b3ULL; + for(int i = 0; sid[i]; ++i) hash = (hash ^ sid[i]) * mult; + ui_hue = (hash & 0x3F) / (float)0x3F; ui_hue += !ui_hue; + + struct nk_color c = nk_hsva_f(ui_hue, 0.75f, 0.8f, ui_alpha); + nk_fill_rect(canvas, pos, ROUNDING, k->ease == EASE_NOP ? AS_NKCOLOR(0) : c); // AS_NKCOLOR(track_color)); + } + + // horizontal line + nk_stroke_line(canvas, baseline.x, baseline.y, baseline.x+baseline.w,baseline.y, THICKNESS, AS_NKCOLOR(base_color)); + + // unit, 5-unit and 10-unit markers + for( float i = 0, j = 0; i < baseline.w; i += PIXELS_PER_SECOND/10, ++j ) { + int len = !((int)j%10) ? MARKER10_HEIGHT : !((int)j%5) ? MARKER5_HEIGHT : MARKER1_HEIGHT; + nk_stroke_line(canvas, baseline.x+i, baseline.y-len, baseline.x+i, baseline.y+len, THICKNESS, AS_NKCOLOR(base_color)); + } + + // time marker + float px = t->time * PIXELS_PER_SECOND; + nk_stroke_line(canvas, baseline.x+px, bounds.y, baseline.x+px, bounds.y+bounds.h, THICKNESS*2, AS_NKCOLOR(time_color)); + nk_draw_symbol(canvas, NK_SYMBOL_TRIANGLE_DOWN, ((struct nk_rect){ baseline.x+px-4,bounds.y-4-8,8,8}), /*bg*/AS_NKCOLOR(0), /*fg*/AS_NKCOLOR(time_color), 0.f/*border_width*/, ui_ctx->style.font); + + // key markers + for each_array_ptr(t->keyframes, tween_keyframe_t, k) { + struct nk_rect pos = baseline; + pos.x += k->t * PIXELS_PER_SECOND; + + vec2 romboid[] = { + {pos.x-KEY_WIDTH,pos.y}, {pos.x,pos.y-KEY_HEIGHT}, + {pos.x+KEY_WIDTH,pos.y}, {pos.x,pos.y+KEY_HEIGHT} + }; + + nk_fill_polygon(canvas, (float*)romboid, countof(romboid), AS_NKCOLOR(key_color)); + } + + // keys ui + if( expand_keys ) + for(int i = 0, end = array_count(t->keyframes); i < end; ++i) { + tween_keyframe_t *k = t->keyframes + i; + if( ui_collapse(va("Key %d", i), va("%s.%d", id, i))) { + changed |= ui_float("Time", &k->t); + changed |= ui_float3("Value", &k->v.x); + changed |= ui_list("Ease", ease_enums(), EASE_NUM, &k->ease ); + ui_collapse_end(); + } + } + + return changed; +} + +tween_t* rand_tween() { + tween_t demo = tween(); + int num_keys = randi(2,8); + double t = 0; + for( int i = 0; i < num_keys; ++i) { + tween_setkey(&demo, t, scale3(vec3(randf(),randf(),randf()),randi(-5,5)), randi(0,EASE_NUM) ); + t += randi(1,5) / ((float)(1 << randi(0,2))); + } + tween_t *p = CALLOC(1, sizeof(tween_t)); + memcpy(p, &demo, sizeof(tween_t)); + return p; +} + +int editor_timeline(int window_mode) { + static array(tween_t*) tweens = 0; + + do_once { + array_push(tweens, rand_tween()); + } + + if( editor.t == 0 ) + for each_array(tweens, tween_t*,t) { + tween_reset(t); + } + else + for each_array(tweens, tween_t*,t) { + tween_update(t, editor.dt); + } + + static void *selected = NULL; + if( editor_begin(TIMELINE_TITLE, window_mode) ) { + + int choice = ui_toolbar(ICON_MDI_PLUS ";" ICON_MDI_MINUS ); + if( choice == 1 ) array_push(tweens, rand_tween()); + if( choice == 2 && selected ) { + int target = -1; + for( int i = 0, end = array_count(tweens); i < end; ++i ) if( tweens[i] == selected ) { target = i; break; } + if( target >= 0 ) { array_erase_slow(tweens, target); selected = NULL; } + } + + for each_array(tweens, tween_t*,t) { + ui_tween(va("%s%p@%05.2fs Value: %s", t == selected ? "!":"", t, t->time, ftoa3(t->result)), t); + if(ui_label_icon_clicked_L.x) selected = (t != selected) ? t : NULL; + } + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_timeline); +} +#line 0 +#line 1 "v4k_editor_console.h" +#define CONSOLE_ICON ICON_MDI_CONSOLE +#define CONSOLE_TITLE "Console " CONSOLE_ICON + +EDITOR_BIND(console, "held(CTRL)&down(4)", { ui_show(CONSOLE_TITLE, ui_visible(CONSOLE_TITLE) ^ true); }); + +int editor_console(int window_mode) { + if( editor_begin(CONSOLE_TITLE, window_mode) ) { + + // peek complete window space + struct nk_rect bounds = nk_window_get_content_region(ui_ctx); + + enum { CONSOLE_LINE_HEIGHT = 20 }; + static array(char*) lines = 0; + do_once { + array_push(lines, stringf("> Editor v%s. Type `%s` for help.", EDITOR_VERSION, "")); + } + int max_lines = (bounds.h - UI_ROW_HEIGHT) / (CONSOLE_LINE_HEIGHT * 2); + if( max_lines >= 1 ) { + nk_layout_row_static(ui_ctx, bounds.h - UI_ROW_HEIGHT, bounds.w, 1); + if(nk_group_begin(ui_ctx, "console.group", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { + nk_layout_row_static(ui_ctx, CONSOLE_LINE_HEIGHT, bounds.w, 1); + for( int i = array_count(lines); i < max_lines; ++i ) + array_push_front(lines, 0); + for( int i = array_count(lines) - max_lines; i < array_count(lines); ++i ) { + if( !lines[i] ) { + #if 0 // debug + nk_label_wrap(ui_ctx, va("%d.A/%d",i+1,max_lines)); + nk_label_wrap(ui_ctx, va("%d.B/%d",i+1,max_lines)); + #else + nk_label_wrap(ui_ctx, ""); + nk_label_wrap(ui_ctx, ""); + #endif + } else { + nk_label_wrap(ui_ctx, lines[i]); + const char *answer = isdigit(*lines[i]) ? editor_recv( atoi(lines[i]), 0 ) : NULL; + nk_label_wrap(ui_ctx, answer ? answer : ""); + } + } + nk_group_end(ui_ctx); + } + } + static char *cmd = 0; + if( ui_string(NULL, &cmd) ) { + int jobid = editor_send(cmd); + array_push(lines, stringf("%d> %s", jobid, cmd)); + cmd[0] = 0; + } + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_console); +} +#line 0 +#line 1 "v4k_editor_nodes.h" +#define NODES_ICON ICON_MDI_GRAPH +#define NODES_TITLE "Nodes " NODES_ICON + +EDITOR_BIND(nodes, "held(CTRL)&down(5)", { ui_show(NODES_TITLE, ui_visible(NODES_TITLE) ^ true); }); + +/* +A basic node-based UI built with Nuklear. +Builds on the node editor example included in Nuklear v1.00, with the aim of +being used as a prototype for implementing a functioning node editor. + +Features: +- Nodes of different types. Currently their implementations are #included in + the main file, but they could easily be turned into eg. a plugin system. +- Pins/pins of different types -- currently float values and colors. +- Adding and removing nodes. +- Linking nodes, with validation (one link per input, only link similar pins). +- Detaching and moving links. +- Evaluation of output values of connected nodes. +- Memory management based on fixed size arrays for links and node pointers +- Multiple node types +- Multiple pin types +- Linking between pins of the same type +- Detaching and reattaching links +- Getting value from linked node if pin is connected + +Todo: +- Complete pin types. +- Allow dragging from output to input pin. +- Cut link by CTRL+clicking input pin. +- Cut link by drawing intersect line on a link. +- Group elemnts together with mouse, or LSHIFT+clicking. +- Drag groups. +- DEL elements. +- DEL groups. +- CTRL-C/CTRL-V/CTRL-X elements. +- CTRL-C/CTRL-V/CTRL-X groups. +- CTRL-Z,CTRL-Y. +- CTRL-N. +- CTRL-L,CTRL-S. +- CTRL-F. +- CTRL-Wheel Zooming. +- Allow to extend node types from Lua. + +Extra todo: +- Execution Flow (see: nk_stroke_triangle, nk_fill_triangle) +- Complete missing nodes (see: nk_draw_image, nk_draw_text) +- Right-click could visualize node/board diagram as Lua script. +- Once that done, copy/pasting scripts should work within editor. + +Sources: +- https://github.com/Immediate-Mode-UI/Nuklear/pull/561 +- https://github.com/vurtun/nuklear/blob/master/demo/node_editor.c +*/ + +typedef enum pin_type_t { + type_flow, + type_int,type_float, + type_block,type_texture,type_image, + type_color, + /* + type_bool, + type_char, type_string, + type_int2, type_int3, type_int4, + type_float2, type_float3, type_float4, + type_array, type_map, + */ + + type_total +} pin_type_t; + +struct node_pin { + pin_type_t pin_type; + nk_bool is_connected; + struct node* connected_node; + int connected_pin; +}; + +struct node { + int ID; + char name[32]; + struct nk_rect bounds; + int input_count; + int output_count; + struct node_pin *inputs; + struct node_pin *outputs; + struct { + float in_padding_x; + float in_padding_y; + float in_spacing_y; + float out_padding_x; + float out_padding_y; + float out_spacing_y; + } pin_spacing; /* Maybe this should be called "node_layout" and include the bounds? */ + struct node *next; /* Z ordering only */ + struct node *prev; /* Z ordering only */ + + void* (*eval_func)(struct node*, int oIndex); + void (*display_func)(struct nk_context*, struct node*); +}; + +struct node_link { + struct node* input_node; + int input_pin; + struct node* output_node; + int output_pin; + nk_bool is_active; +}; + +struct node_linking { + int active; + struct node *node; + int input_id; + int input_pin; +}; + +struct node_editor { + int initialized; + struct node *node_buf[32]; + struct node_link links[64]; + struct node *output_node; + struct node *begin; + struct node *end; + int node_count; + int link_count; + struct nk_rect bounds; + struct node *selected; + int show_grid; + struct nk_vec2 scrolling; + struct node_linking linking; +}; + +/* === PROTOTYPES === */ +/* The node implementations need these two functions. */ +/* These could/should go in a header file along with the node and node_pin structs and be #included in the node implementations */ + +struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count); +void* node_editor_eval_connected(struct node *node, int input_pin_number); +/* ================== */ + +/* === NODE TYPE IMPLEMENTATIONS === */ + +#define NODE_DEFAULT_ROW_HEIGHT 25 + + +// ---------------------------------------------------------------------------------------------------- +// #include "node_output.h" + +struct node_type_output { + struct node node; + struct nk_colorf input_val; +}; + +struct nk_colorf *node_output_get(struct node* node) { + struct node_type_output *output_node = (struct node_type_output*)node; + if (!node->inputs[0].is_connected) { + struct nk_colorf black = {0.0f, 0.0f, 0.0f, 0.0f}; + output_node->input_val = black; + } + return &output_node->input_val; +} + +static void node_output_display(struct nk_context *ctx, struct node *node) { + if (node->inputs[0].is_connected) { + struct node_type_output *output_node = (struct node_type_output*)node; + output_node->input_val = *(struct nk_colorf*)node_editor_eval_connected(node, 0); + nk_layout_row_dynamic(ctx, 60, 1); + nk_button_color(ctx, nk_rgba_cf(output_node->input_val)); + } +} + +struct node* node_output_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_output *output_node = (struct node_type_output*)node_editor_add(editor, sizeof(struct node_type_output), "Output", nk_rect(position.x, position.y, 100, 100), 1, 0); + if (output_node){ + output_node->node.inputs[0].pin_type = type_color; + output_node->node.display_func = node_output_display; + } + return (struct node*)output_node; +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_float.h" + +struct node_type_float { + struct node node; + float output_val; +}; + +static float *node_float_eval(struct node* node, int oIndex) { + struct node_type_float *float_node = (struct node_type_float*)node; + NK_ASSERT(oIndex == 0); + return &float_node->output_val; +} + +static void node_float_draw(struct nk_context *ctx, struct node *node) { + struct node_type_float *float_node = (struct node_type_float*)node; + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + float_node->output_val = nk_propertyf(ctx, "#Value:", 0.0f, float_node->output_val, 1.0f, 0.01f, 0.01f); +} + +void node_float_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_float *float_node = (struct node_type_float*)node_editor_add(editor, sizeof(struct node_type_float), "Float", nk_rect(position.x, position.y, 180, 75), 0, 1); + if (float_node) + { + float_node->output_val = 1.0f; + float_node->node.display_func = node_float_draw; + float_node->node.eval_func = (void*(*)(struct node*, int)) node_float_eval; + } +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_color.h" + +struct node_type_color { + struct node node; + float input_val[4]; + struct nk_colorf output_val; +}; + +static struct nk_colorf *node_color_eval(struct node* node, int oIndex) +{ + struct node_type_color *color_node = (struct node_type_color*)node; + NK_ASSERT(oIndex == 0); /* only one output connector */ + + return &color_node->output_val; +} + + +static void node_color_draw(struct nk_context *ctx, struct node *node) +{ + struct node_type_color *color_node = (struct node_type_color*)node; + float eval_result; /* Get the values from connected nodes into this so the inputs revert on disconnect */ + const char* labels[4] = {"#R:","#G:","#B:","#A:"}; + float color_val[4]; /* Because we can't just loop through the struct... */ + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + nk_button_color(ctx, nk_rgba_cf(color_node->output_val)); + + for (int i = 0; i < 4; i++) + { + if (color_node->node.inputs[i].is_connected) { + eval_result = *(float*)node_editor_eval_connected(node, i); + eval_result = nk_propertyf(ctx, labels[i], eval_result, eval_result, eval_result, 0.01f, 0.01f); + color_val[i] = eval_result; + } + else { + color_node->input_val[i] = nk_propertyf(ctx, labels[i], 0.0f, color_node->input_val[i], 1.0f, 0.01f, 0.01f); + color_val[i] = color_node->input_val[i]; + } + } + + color_node->output_val.r = color_val[0]; + color_node->output_val.g = color_val[1]; + color_node->output_val.b = color_val[2]; + color_node->output_val.a = color_val[3]; +} + +void node_color_create(struct node_editor *editor, struct nk_vec2 position) +{ + struct node_type_color *color_node = (struct node_type_color*)node_editor_add(editor, sizeof(struct node_type_color), "Color", nk_rect(position.x, position.y, 180, 190), 4, 1); + if (color_node) + { + const struct nk_colorf black = {0.0f, 0.0f, 0.0f, 1.0f}; + + for (int i = 0; i < color_node->node.input_count; i++) + color_node->node.inputs[i].pin_type = type_float; + color_node->node.outputs[0].pin_type = type_color; + + color_node->node.pin_spacing.in_padding_y += NODE_DEFAULT_ROW_HEIGHT; + + color_node->input_val[0] = 0.0f; + color_node->input_val[1] = 0.0f; + color_node->input_val[2] = 0.0f; + color_node->input_val[3] = 1.0f; + + color_node->output_val = black; + + color_node->node.display_func = node_color_draw; + color_node->node.eval_func = (void*(*)(struct node*, int)) node_color_eval; + } +} + +// ---------------------------------------------------------------------------------------------------- +// #include "node_blend.h" + +struct node_type_blend { + struct node node; + struct nk_colorf input_val[2]; + struct nk_colorf output_val; + float blend_val; +}; + +static struct nk_colorf *node_blend_eval(struct node *node, int oIndex) { + struct node_type_blend* blend_node = (struct node_type_blend*)node; + return &blend_node->output_val; +} + +static void node_blend_display(struct nk_context *ctx, struct node *node) { + struct node_type_blend *blend_node = (struct node_type_blend*)node; + const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; + float blend_amnt; + + nk_layout_row_dynamic(ctx, NODE_DEFAULT_ROW_HEIGHT, 1); + for (int i = 0; i < 2; i++){ + if(node->inputs[i].is_connected) { + blend_node->input_val[i] = *(struct nk_colorf*)node_editor_eval_connected(node, i); + } + else { + blend_node->input_val[i] = blank; + } + nk_button_color(ctx, nk_rgba_cf(blend_node->input_val[i])); + } + + if (node->inputs[2].is_connected) { + blend_amnt = *(float*)node_editor_eval_connected(node, 2); + blend_amnt = nk_propertyf(ctx, "#Blend", blend_amnt, blend_amnt, blend_amnt, 0.01f, 0.01f); + } + else { + blend_node->blend_val = nk_propertyf(ctx, "#Blend", 0.0f, blend_node->blend_val, 1.0f, 0.01f, 0.01f); + blend_amnt = blend_node->blend_val; + } + + + if(node->inputs[0].is_connected && node->inputs[1].is_connected) { + blend_node->output_val.r = blend_node->input_val[0].r * (1.0f-blend_amnt) + blend_node->input_val[1].r * blend_amnt; + blend_node->output_val.g = blend_node->input_val[0].g * (1.0f-blend_amnt) + blend_node->input_val[1].g * blend_amnt; + blend_node->output_val.b = blend_node->input_val[0].b * (1.0f-blend_amnt) + blend_node->input_val[1].b * blend_amnt; + blend_node->output_val.a = blend_node->input_val[0].a * (1.0f-blend_amnt) + blend_node->input_val[1].a * blend_amnt; + } + else { + blend_node->output_val = blank; + } +} + +void node_blend_create(struct node_editor *editor, struct nk_vec2 position) { + struct node_type_blend* blend_node = (struct node_type_blend*)node_editor_add(editor, sizeof(struct node_type_blend), "Blend", nk_rect(position.x, position.y, 180, 130), 3, 1); + if (blend_node) { + const struct nk_colorf blank = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) + blend_node->node.inputs[i].pin_type = type_color; + blend_node->node.outputs[0].pin_type = type_color; + + // blend_node->node.pin_spacing.in_padding_y = 42.0f; + // blend_node->node.pin_spacing.in_spacing_y = 29.0f; + + for (int i = 0; i < (int)NK_LEN(blend_node->input_val); i++) + blend_node->input_val[i] = blank; + blend_node->output_val = blank; + + blend_node->blend_val = 0.5f; + + blend_node->node.display_func = node_blend_display; + blend_node->node.eval_func = (void*(*)(struct node*, int)) node_blend_eval; + + } +} + +/* ================================= */ + +#define NK_RGB3(r,g,b) {r,g,b,255} +#define BG_COLOR ((struct nk_color){60,60,60,192}) // nk_rgba(0,0,0,192) + +static +struct editor_node_style { + int pin_type; + const char *shape; + struct nk_color color_idle; + struct nk_color color_hover; +} styles[] = { + // order matters: + { type_flow, "triangle_right", NK_RGB3(200,200,200), NK_RGB3(255,255,255) }, // if .num_links == 0 + { type_int, "circle", NK_RGB3(33,227,175), NK_RGB3(135,239,195) }, + { type_float, "circle", NK_RGB3(156,253,65), NK_RGB3(144,225,137) }, + { type_block, "circle", NK_RGB3(6,165,239), NK_RGB3(137,196,247) }, + { type_texture, "circle", NK_RGB3(148,0,0), NK_RGB3(183,137,137) }, + { type_image, "circle", NK_RGB3(200,130,255), NK_RGB3(220,170,255) }, + { type_color, "circle", NK_RGB3(252,200,35), NK_RGB3(255,217,140) }, +}; + +#define COLOR_FLOW_HI styles[type_flow].color_hover +#define COLOR_FLOW_LO styles[type_flow].color_idle + +#define GRID_SIZE 64.0f +#define GRID_COLOR ((struct nk_color)NK_RGB3(80,80,120)) +#define GRID_THICKNESS 1.0f + +// 4 colors: top-left, top-right, bottom-right, bottom-left +#define GRID_BG_COLORS ((struct nk_color){30,30,30,255}), ((struct nk_color){40,20,0,255}), ((struct nk_color){30,30,30,255}), ((struct nk_color){20,30,40,255}) + +#define LINK_THICKNESS 1.0f +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + nk_stroke_line(canvas, a.x, a.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) +#undef LINK_DRAW +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + nk_stroke_curve(canvas, a.x, a.y, a.x+50, a.y, b.x-50, b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) +#undef LINK_DRAW +#define LINK_DRAW(POINT_A,POINT_B,COLOR) do { \ + vec2 a = (POINT_A); \ + vec2 b = (POINT_B); \ + float dist2 = len2( sub2( ptr2(&b.x), ptr2(&a.x) ) ); \ + vec2 mid_a = mix2( ptr2(&a.x), ptr2(&b.x), 0.25 ); mid_a.y += dist2/2; \ + vec2 mid_b = mix2( ptr2(&a.x), ptr2(&b.x), 0.75 ); mid_b.y += dist2/3; \ + nk_stroke_curve(canvas, a.x, a.y, mid_a.x, mid_a.y, mid_b.x, mid_b.y, b.x, b.y, LINK_THICKNESS, COLOR); \ +} while(0) + + +#define PIN_RADIUS 12 +#define PIN_THICKNESS 1.0f +#define PIN_DRAW(PIN_ADDR,POINT,RADIUS) do { \ + circle.x = (POINT).x - (RADIUS) / 2; \ + circle.y = (POINT).y - (RADIUS) / 2; \ + circle.w = circle.h = (RADIUS); \ + struct nk_color color = node_get_type_color((PIN_ADDR).pin_type); \ + if((PIN_ADDR).is_connected) \ + nk_fill_circle(canvas, circle, color); \ + else \ + nk_stroke_circle(canvas, circle, PIN_THICKNESS, color); \ +} while(0) + + +static struct nk_color node_get_type_color(unsigned pin_type) { + for( int i = 0; i < type_total; ++i ) + if( styles[i].pin_type == pin_type ) + return styles[i].color_idle; + return ((struct nk_color)NK_RGB3(255,0,255)); +} + +static void node_editor_push(struct node_editor *editor, struct node *node) { + if (!editor->begin) { + node->next = NULL; + node->prev = NULL; + editor->begin = node; + editor->end = node; + } else { + node->prev = editor->end; + if (editor->end) + editor->end->next = node; + node->next = NULL; + editor->end = node; + } +} + +static void node_editor_pop(struct node_editor *editor, struct node *node) { + if (node->next) + node->next->prev = node->prev; + if (node->prev) + node->prev->next = node->next; + if (editor->end == node) + editor->end = node->prev; + if (editor->begin == node) + editor->begin = node->next; + node->next = NULL; + node->prev = NULL; +} + +static struct node* node_editor_find_by_id(struct node_editor *editor, int ID) { + struct node *iter = editor->begin; + while (iter) { + if (iter->ID == ID) + return iter; + iter = iter->next; + } + return NULL; +} + +static struct node_link* node_editor_find_link_by_output(struct node_editor *editor, struct node *output_node, int node_input_connector) { + for( int i = 0; i < editor->link_count; i++ ) { + if (editor->links[i].output_node == output_node && + editor->links[i].output_pin == node_input_connector && + editor->links[i].is_active == nk_true) { + return &editor->links[i]; + } + } + return NULL; +} + +static struct node_link* node_editor_find_link_by_input(struct node_editor *editor, struct node *input_node, int node_output_connector) { + for( int i = 0; i < editor->link_count; i++ ) { + if (editor->links[i].input_node == input_node && + editor->links[i].input_pin == node_output_connector && + editor->links[i].is_active == nk_true) { + return &editor->links[i]; + } + } + return NULL; +} + +static void node_editor_delete_link(struct node_link *link) { + link->is_active = nk_false; + link->input_node->outputs[link->input_pin].is_connected = nk_false; + link->output_node->inputs[link->output_pin].is_connected = nk_false; +} + +struct node* node_editor_add(struct node_editor *editor, size_t nodeSize, const char *name, struct nk_rect bounds, int in_count, int out_count) { + static int IDs = 0; + struct node *node = NULL; + + if ((nk_size)editor->node_count < NK_LEN(editor->node_buf)) { + /* node_buf has unused pins */ + node = MALLOC(nodeSize); + editor->node_buf[editor->node_count++] = node; + node->ID = IDs++; + } else { + /* check for freed up pins in node_buf */ + for (int i = 0; i < editor->node_count; i++) { + if (editor->node_buf[i] == NULL) { + node = MALLOC(nodeSize); + editor->node_buf[i] = node; + node->ID = i; + break; + } + } + } + if (node == NULL) { + puts("Node creation failed"); + return NULL; + } + + node->bounds = bounds; + + node->input_count = in_count; + node->output_count = out_count; + + node->inputs = MALLOC(node->input_count * sizeof(struct node_pin)); + node->outputs = MALLOC(node->output_count * sizeof(struct node_pin)); + + for (int i = 0; i < node->input_count; i++) { + node->inputs[i].is_connected = nk_false; + node->inputs[i].pin_type = type_float; /* default pin type */ + } + for (int i = 0; i < node->output_count; i++) { + node->outputs[i].is_connected = nk_false; + node->outputs[i].pin_type = type_float; /* default pin type */ + } + + /* default pin spacing */ + node->pin_spacing.in_padding_x = 2; + node->pin_spacing.in_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust + node->pin_spacing.in_spacing_y = 25; // row height+border + node->pin_spacing.out_padding_x = 3; + node->pin_spacing.out_padding_y = 32 + 25/2 + 6; // titlebar height + next half row + adjust + node->pin_spacing.out_spacing_y = 25; // row height+border + + strcpy(node->name, name); + node_editor_push(editor, node); + + return node; +} + +void *node_editor_eval_connected(struct node* node, int input_pin_number) { + NK_ASSERT(node->inputs[input_pin_number].is_connected); + return node->inputs[input_pin_number].connected_node->eval_func(node->inputs[input_pin_number].connected_node, node->inputs[input_pin_number].connected_pin); +} + +static void node_editor_link(struct node_editor *editor, struct node *in_node, int in_pin, struct node *out_node, int out_pin) { + /* Confusingly, in and out nodes/pins here refer to the inputs and outputs OF THE LINK ITSELF, not the nodes */ + struct node_link *link = NULL; + + if ((nk_size)editor->link_count < NK_LEN(editor->links)) { + link = &editor->links[editor->link_count++]; + } else { + for (int i = 0; i < (int)NK_LEN(editor->links); i++) + { + if (editor->links[i].is_active == nk_false) { + link = &editor->links[i]; + break; + } + } + } + if (link) { + out_node->inputs[out_pin].is_connected = nk_true; + in_node->outputs[in_pin].is_connected = nk_true; + out_node->inputs[out_pin].connected_node = in_node; + out_node->inputs[out_pin].connected_pin = in_pin; + + link->input_node = in_node; + link->input_pin = in_pin; + link->output_node = out_node; + link->output_pin = out_pin; + link->is_active = nk_true; + } else { + puts("Too many links"); + } +} + +static void node_editor_init(struct node_editor *editor) { + if (editor->initialized) return; + + struct nk_rect total_space = nk_window_get_content_region(ui_ctx); + struct nk_vec2 output_node_position = { total_space.w*2/3, total_space.h/3 }; + struct nk_vec2 color_node_position = { total_space.w*1/4, total_space.h/3 }; + + memset(editor, 0, sizeof(*editor)); + + editor->output_node = node_output_create(editor, output_node_position); + node_color_create(editor, color_node_position); + editor->show_grid = nk_true; + + editor->initialized = 1; +} + +static int node_editor(struct node_editor *editor) { + int n = 0; + struct nk_rect total_space; + const struct nk_input *in = &ui_ctx->input; + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct node *updated = 0; + + node_editor_init(editor); + + { + /* allocate complete window space */ + total_space = nk_window_get_content_region(ui_ctx); + nk_layout_space_begin(ui_ctx, NK_STATIC, total_space.h, editor->node_count); + { + struct node *it = editor->begin; + struct nk_rect size = nk_layout_space_bounds(ui_ctx); + struct nk_panel *nodePanel = 0; + + //nk_fill_rect(canvas, size, 0/*rounding*/, ((struct nk_color){30,30,30,255})); // 20,30,40,255 + nk_fill_rect_multi_color(canvas, size, GRID_BG_COLORS); + + if (editor->show_grid) { + /* display grid */ + for (float x = (float)fmod(size.x - editor->scrolling.x, GRID_SIZE); x < size.w; x += GRID_SIZE) + nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, GRID_THICKNESS, GRID_COLOR); + for (float y = (float)fmod(size.y - editor->scrolling.y, GRID_SIZE); y < size.h; y += GRID_SIZE) + nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, GRID_THICKNESS, GRID_COLOR); + } + + /* execute each node as a movable group */ + /* loop through nodes */ + while (it) { + /* Output node window should not have a close button */ + nk_flags nodePanel_flags = NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE; + if (it != editor->output_node) + nodePanel_flags |= NK_WINDOW_CLOSABLE; + + /* calculate scrolled node window position and size */ + nk_layout_space_push(ui_ctx, nk_rect(it->bounds.x - editor->scrolling.x, + it->bounds.y - editor->scrolling.y, it->bounds.w, it->bounds.h)); + + /* execute node window */ + char *name = va(" " ICON_MD_MENU " %s",it->name); //< @r-lyeh added some spacing+icon because of our UI customizations + +struct nk_color bak = ui_ctx->style.window.fixed_background.data.color; +ui_ctx->style.window.fixed_background.data.color = BG_COLOR; + + if (nk_group_begin(ui_ctx, name, nodePanel_flags)) + { + /* always have last selected node on top */ + + nodePanel = nk_window_get_panel(ui_ctx); + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nodePanel->bounds) && + (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT, + nk_layout_space_rect_to_screen(ui_ctx, nodePanel->bounds)))) && + editor->end != it) + { + updated = it; + } + + if ((nodePanel->flags & NK_WINDOW_HIDDEN)) /* Node close button has been clicked */ + { + /* Delete node */ + struct node_link *link_remove; + node_editor_pop(editor, it); + for (int n = 0; n < it->input_count; n++) { + if ((link_remove = node_editor_find_link_by_output(editor, it, n))) + { + node_editor_delete_link(link_remove); + } + } + for (int n = 0; n < it -> output_count; n++) { + while((link_remove = node_editor_find_link_by_input(editor, it, n))) + { + node_editor_delete_link(link_remove); + } + } + NK_ASSERT(editor->node_buf[it->ID] == it); + editor->node_buf[it->ID] = NULL; + FREE(it->inputs); + FREE(it->outputs); + FREE(it); + } + else { + + /* ================= NODE CONTENT ===================== */ + + it->display_func(ui_ctx, it); + + /* ==================================================== */ + + } + nk_group_end(ui_ctx); + + } + +ui_ctx->style.window.fixed_background.data.color = bak; + + if (!(nodePanel->flags & NK_WINDOW_HIDDEN)) + { + /* node pin and linking */ + struct nk_rect bounds; + bounds = nk_layout_space_rect_to_local(ui_ctx, nodePanel->bounds); + bounds.x += editor->scrolling.x; + bounds.y += editor->scrolling.y; + it->bounds = bounds; + + /* output pins */ + for (int n = 0; n < it->output_count; ++n) { + struct nk_rect circle; + struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; + pt.x += nodePanel->bounds.w - PIN_RADIUS / 2 + it->pin_spacing.out_padding_x; + pt.y += it->pin_spacing.out_padding_y + it->pin_spacing.out_spacing_y * (n); + PIN_DRAW(it->outputs[n],pt,PIN_RADIUS); + + /* start linking process */ + /* set linking active */ + if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) { + editor->linking.active = nk_true; + editor->linking.node = it; + editor->linking.input_id = it->ID; + editor->linking.input_pin = n; + } + + /* draw link being dragged (from linked pin to mouse position) */ + if (editor->linking.active && editor->linking.node == it && + editor->linking.input_pin == n) { + LINK_DRAW(vec2(circle.x+3,circle.y+3),ptr2(&in->mouse.pos.x),COLOR_FLOW_HI); + } + } + + /* input pins */ + for (int n = 0; n < it->input_count; ++n) { + struct nk_rect circle; + struct nk_vec2 pt = {nodePanel->bounds.x, nodePanel->bounds.y}; + pt.x += it->pin_spacing.in_padding_x; + pt.y += it->pin_spacing.in_padding_y + it->pin_spacing.in_spacing_y * (n); + PIN_DRAW(it->inputs[n],pt,PIN_RADIUS); + + /* Detach link */ + if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true) && + editor->linking.active == nk_false && + it->inputs[n].is_connected == nk_true) { + struct node_link *node_relink = node_editor_find_link_by_output(editor, it, n); + editor->linking.active = nk_true; + editor->linking.node = node_relink->input_node; + editor->linking.input_id = node_relink->input_node->ID; + editor->linking.input_pin = node_relink->input_pin; + node_editor_delete_link(node_relink); + } + + /* Create link */ + if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) && + nk_input_is_mouse_hovering_rect(in, circle) && + editor->linking.active && + editor->linking.node != it && + it->inputs[n].pin_type == editor->linking.node->outputs[editor->linking.input_pin].pin_type && + it->inputs[n].is_connected != nk_true) { + editor->linking.active = nk_false; + + node_editor_link(editor, editor->linking.node, + editor->linking.input_pin, it, n); + } + } + } + it = it->next; + } + + /* reset (output) linking connection */ + if (editor->linking.active && (!!input(KEY_LCTRL) || !!input(KEY_RCTRL) || nk_input_is_mouse_released(in, NK_BUTTON_LEFT))) { + editor->linking.active = nk_false; + editor->linking.node = NULL; + } + + /* draw each static link */ + for (int n = 0; n < editor->link_count; ++n) { + struct node_link *link = &editor->links[n]; + if (link->is_active == nk_true){ + struct node *ni = link->input_node; + struct node *no = link->output_node; + struct nk_vec2 l0 = nk_layout_space_to_screen(ui_ctx, nk_vec2(ni->bounds.x + ni->bounds.w + ni->pin_spacing.out_padding_x, 3.0f + ni->bounds.y + ni->pin_spacing.out_padding_y + ni->pin_spacing.out_spacing_y * (link->input_pin))); + struct nk_vec2 l1 = nk_layout_space_to_screen(ui_ctx, nk_vec2(no->bounds.x + no->pin_spacing.in_padding_x, 3.0f + no->bounds.y + no->pin_spacing.in_padding_y + no->pin_spacing.in_spacing_y * (link->output_pin))); + + l0.x -= editor->scrolling.x; + l0.y -= editor->scrolling.y; + l1.x -= editor->scrolling.x; + l1.y -= editor->scrolling.y; + + struct nk_color color = node_get_type_color(no->inputs[link->output_pin].pin_type); + LINK_DRAW(ptr2(&l0.x), ptr2(&l1.x), color); + } + } + + if (updated) { + /* reshuffle nodes to have least recently selected node on top */ + node_editor_pop(editor, updated); + node_editor_push(editor, updated); + } + + /* node selection */ + if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ui_ctx))) { + it = editor->begin; + editor->selected = NULL; + editor->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200); + while (it) { + struct nk_rect b = nk_layout_space_rect_to_screen(ui_ctx, it->bounds); + b.x -= editor->scrolling.x; + b.y -= editor->scrolling.y; + if (nk_input_is_mouse_hovering_rect(in, b)) + editor->selected = it; + it = it->next; + } + } + + /* contextual menu */ + if (nk_contextual_begin(ui_ctx, 0, nk_vec2(150, 220), nk_window_get_bounds(ui_ctx))) { + struct nk_vec2 wincoords = { in->mouse.pos.x-total_space.x-50, in->mouse.pos.y-total_space.y-32 }; + +#if 1 + static char *filter = 0; + static int do_filter = 0; + if( input_down(KEY_F) ) if( input(KEY_LCTRL) || input(KEY_RCTRL) ) do_filter ^= 1; + int choice = ui_toolbar(ICON_MD_SEARCH ";"); + if( choice == 1 ) do_filter = 1; + if( do_filter ) { + ui_string(ICON_MD_CLOSE " Filter " ICON_MD_SEARCH, &filter); + if( ui_label_icon_clicked_L.x > 0 && ui_label_icon_clicked_L.x <= 24 ) { // if clicked on CANCEL icon (1st icon) + do_filter = 0; + } + } else { + if( filter ) filter[0] = '\0'; + } + char *filter_mask = filter && filter[0] ? va("*%s*", filter) : "*"; +#endif + + #define ui_label_filtered(lbl) (strmatchi(lbl,filter_mask) && ui_label(lbl)) + + int close = 0; + if (ui_label_filtered("=Add Color node")) close=1,node_color_create(editor, wincoords); + if (ui_label_filtered("=Add Float node")) close=1,node_float_create(editor, wincoords); + if (ui_label_filtered("=Add Blend Node")) close=1,node_blend_create(editor, wincoords); + if (ui_label_filtered(editor->show_grid ? "=Hide Grid" : "=Show Grid")) + close=1,editor->show_grid = !editor->show_grid; + if(close) do_filter = 0, (filter ? filter[0] = '\0' : '\0'), nk_contextual_close(ui_ctx); + nk_contextual_end(ui_ctx); + } + } + nk_layout_space_end(ui_ctx); + + /* window content scrolling */ + if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ui_ctx)) && + nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) { + editor->scrolling.x += in->mouse.delta.x; + editor->scrolling.y += in->mouse.delta.y; + } + } + + return !nk_window_is_closed(ui_ctx, "NodeEdit"); +} + +int editor_nodes(int window_mode) { + window_mode = EDITOR_WINDOW; // force window + + if( editor_begin(NODES_TITLE, window_mode) ) { + + static struct node_editor nodeEditor = {0}; + node_editor(&nodeEditor); + + editor_end(window_mode); + } + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_nodes); +} +#line 0 +#line 1 "v4k_editor_script.h" + +int ui_texture_fit(texture_t t, struct nk_rect bounds) { + // allocate complete window space + struct nk_rect total_space = nk_window_get_content_region(ui_ctx); + nk_layout_space_begin(ui_ctx, NK_DYNAMIC, total_space.h - 4, 1); // -4 to hide scrollbar Y + nk_layout_space_push(ui_ctx, nk_rect(0,0,1,1)); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_image image = nk_image_id((int)t.id); + nk_draw_image(canvas, bounds, &image, nk_white); + + nk_layout_space_end(ui_ctx); + return 0; +} + +#define LITE_ICON ICON_MDI_SCRIPT_TEXT +#define LITE_TITLE "Script " LITE_ICON + +EDITOR_BIND(script, "held(CTRL)&down(6)", { ui_show(LITE_TITLE, ui_visible(LITE_TITLE) ^ true); }); + +int editor_scripted(int window_mode) { + window_mode = EDITOR_WINDOW; // force mode + + static lua_State *L = 0; + do_once { + L = script_init_env(SCRIPT_LUA|SCRIPT_DEBUGGER); + + const char *platform = "" // "Android" "FreeBSD" "OpenBSD" "NetBSD" + ifdef(ems, "Emscripten") + ifdef(linux, "Linux") + ifdef(osx, "macOS") + ifdef(win32, "Windows") + ; + const char *pathexe = vac("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")); + + gleqInit(); + gleqTrackWindow(window_handle()); + lt_init(L, window_handle(), LT_DATAPATH, __argc, __argv, window_scale(), platform, pathexe); + } + + unsigned lt_none = 0u; + unsigned lt_all = ~0u & ~(GLEQ_WINDOW_MOVED/*|GLEQ_WINDOW_RESIZED|GLEQ_WINDOW_REFRESH*/); + lt_events = lt_none; + + int mouse_in_rect = 0; + if( editor_begin(LITE_TITLE, window_mode) ) { + + lt_events = lt_all; + if( !nk_window_has_focus(ui_ctx) ) lt_events = lt_none; + + struct nk_rect bounds = nk_window_get_content_region(ui_ctx); + + lt_mx = input(MOUSE_X) - bounds.x; + lt_my = input(MOUSE_Y) - bounds.y; + lt_wx = bounds.x; + lt_wy = bounds.y; + lt_ww = bounds.w; + lt_wh = bounds.h; + + if( lt_resizesurface(lt_getsurface(0), lt_ww, lt_wh) ) { + gleq_window_refresh_callback(window_handle()); + } + // fullscreen_quad_rgb( lt_getsurface(0)->t, 1.2f ); + ui_texture_fit(lt_getsurface(0)->t, bounds); + + if( !!nk_input_is_mouse_hovering_rect(&ui_ctx->input, ((struct nk_rect){lt_wx+5,lt_wy+5,lt_ww-10,lt_wh-10})) ) { + lt_events &= ~(1<<31); // dont cursor shape + } + + editor_end(window_mode); + } + + lt_tick(L); + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_scripted); +} +#line 0 + +#line 1 "v4k_end.c" // Enable more performant GPUs on laptops. Does this work into a dll? // int NvOptimusEnablement = 1; // int AmdPowerXpressRequestHighPerformance = 1; diff --git a/engine/v4k.h b/engine/v4k.h index 6bb49ba..94e3bd1 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -95,7 +95,7 @@ extern "C" { //----------------------------------------------------------------------------- // Headers -#line 1 "engine/split/v4k_config.h" +#line 1 "v4k_config.h" // ----------------------------------------------------------------------------- // config directives @@ -510,7 +510,7 @@ typedef char bool; #endif #line 0 -#line 1 "engine/split/v4k_ds.h" +#line 1 "v4k_ds.h" // data structures and utils: array, set, map, hash, sort. // - rlyeh, public domain @@ -949,7 +949,7 @@ API bool (map_sort)(map* m); API void (map_clear)(map* m); #line 0 -#line 1 "engine/split/v4k_math.h" +#line 1 "v4k_math.h" // ----------------------------------------------------------------------------- // math framework: rand, ease, vec2, vec3, vec4, quat, mat2, mat33, mat34, mat4 // - rlyeh, public domain @@ -1230,7 +1230,7 @@ API void print34( float *m ); API void print44( float *m ); #line 0 -#line 1 "engine/split/v4k_obj.h" +#line 1 "v4k_obj.h" // ----------------------------------------------------------------------------- // factory of handle ids @@ -1394,6 +1394,7 @@ void* obj_free(void *o); // --- syntax sugars #define obj_extend(T,method) (obj_##method[OBJTYPE(T)] = (void*)T##_##method) +#define obj_extend_t(T,method) (obj_##method[OBJTYPE(T##_t)] = (void*)T##_##method) #define obj_method(method,o,...) (obj_##method[((struct obj*)(o))->objtype](o,##__VA_ARGS__)) // (obj_##method[((struct obj*)(o))->objtype]((o), ##__VA_ARGS__)) #define obj_hasmethod(o,method) (obj_typeid(o)[obj_##method]) @@ -1416,6 +1417,17 @@ void* obj_free(void *o); #define EXTEND9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8) #define EXTEND10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend(o,F1), obj_extend(o,F2), obj_extend(o,F3), obj_extend(o,F4), obj_extend(o,F5), obj_extend(o,F6), obj_extend(o,F7), obj_extend(o,F8), obj_extend(o,F9) +#define EXTEND_T(...) EXPAND(EXTEND_T, __VA_ARGS__) +#define EXTEND_T2(o,F1) obj_extend_t(o,F1) +#define EXTEND_T3(o,F1,F2) obj_extend_t(o,F1), obj_extend_t(o,F2) +#define EXTEND_T4(o,F1,F2,F3) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3) +#define EXTEND_T5(o,F1,F2,F3,F4) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4) +#define EXTEND_T6(o,F1,F2,F3,F4,F5) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5) +#define EXTEND_T7(o,F1,F2,F3,F4,F5,F6) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6) +#define EXTEND_T8(o,F1,F2,F3,F4,F5,F6,F7) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7) +#define EXTEND_T9(o,F1,F2,F3,F4,F5,F6,F7,F8) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8) +#define EXTEND_T10(o,F1,F2,F3,F4,F5,F6,F7,F8,F9) obj_extend_t(o,F1), obj_extend_t(o,F2), obj_extend_t(o,F3), obj_extend_t(o,F4), obj_extend_t(o,F5), obj_extend_t(o,F6), obj_extend_t(o,F7), obj_extend_t(o,F8), obj_extend_t(o,F9) + // --- declare vtables API extern void (*obj_ctor[256])(); ///- @@ -1434,6 +1446,8 @@ API extern int (*obj_lerp[256])(); ///- API extern int (*obj_edit[256])(); ///- API extern int (*obj_aabb[256])(); ///- +API extern const char*OBJTYPES[256]; /// - + // ---------------------------------------------------------------------------- // core @@ -1578,7 +1592,7 @@ typedef enum OBJTYPE_BUILTINS { #line 0 -#line 1 "engine/split/v4k_ai.h" +#line 1 "v4k_ai.h" // AI framework // - rlyeh, public domain. // @@ -1663,7 +1677,7 @@ API void swarm_update_acceleration_and_velocity_only(swarm_t *self, float del API int ui_swarm(swarm_t *self); #line 0 -#line 1 "engine/split/v4k_audio.h" +#line 1 "v4k_audio.h" // ----------------------------------------------------------------------------- // audio framework // - rlyeh, public domain @@ -1724,7 +1738,7 @@ enum AUDIO_FLAGS { API int audio_queue( const void *samples, int num_samples, int flags ); #line 0 -#line 1 "engine/split/v4k_collide.h" +#line 1 "v4k_collide.h" // ----------------------------------------------------------------------------- // original code by @vurtun (PD) and @barerose (CC0). // [src] https://gist.github.com/vurtun/95f088e4889da2474ad1ce82d7911fee @@ -1885,7 +1899,7 @@ API poly diamond(vec3 from, vec3 to, float size); // poly_free() required API void collide_demo(); // debug draw collisions #line 0 -#line 1 "engine/split/v4k_cook.h" +#line 1 "v4k_cook.h" // ----------------------------------------------------------------------------- // asset pipeline framework // - rlyeh, public domain. @@ -1921,7 +1935,7 @@ API int cook_progress(); // [0..100] API bool have_tools(); #line 0 -#line 1 "engine/split/v4k_data.h" +#line 1 "v4k_data.h" // ----------------------------------------------------------------------------- // data framework (json5, xml, compression) @todo:kvdb // - rlyeh, public domain @@ -1960,7 +1974,7 @@ API void xml_pop(); API bool data_tests(); #line 0 -#line 1 "engine/split/v4k_extend.h" +#line 1 "v4k_extend.h" // dll ------------------------------------------------------------------------ /// !!! `filename` must contain extension @@ -1997,54 +2011,7 @@ enum { API void *script_init_env(unsigned flags); #line 0 -#line 1 "engine/split/v4k_editor.h" -// ----------------------------------------------------------------------------- -// in-game editor -// - rlyeh, public domain. -// -// @todo: merge editor1.c and editor3.c internals into this api - -//API void editor(); -//API bool editor_active(); -API vec3 editor_pick(float mouse_x, float mouse_y); -API char* editor_path(const char *path); - -API float* engine_getf(const char *key); -API int* engine_geti(const char *key); -API char** engine_gets(const char *key); -API int engine_send(const char *cmd, const char *optional_value); - -API int ui_debug(); - -// open file dialog - -API char* dialog_load(); -API char* dialog_save(); - -// transform gizmos - -API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); -API bool gizmo_active(); -API bool gizmo_hover(); - -// localization kit (I18N, L10N) - -API bool kit_load( const char *filename ); // load translations file (xlsx) -API bool kit_merge( const char *filename ); // merge translations file into existing context -API void kit_insert( const char *id, const char *translation ); // insert single translation unit -API void kit_clear(); // delete all translations - -API void kit_set( const char *variable, const char *value ); // set context variable -API void kit_reset(); // reset all variables in context -API void kit_dump_state( FILE *fp ); // debug - -API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale - -API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... -API char* kit_translate( const char *id ); // perform a translation, given current locale -#line 0 - -#line 1 "engine/split/v4k_file.h" +#line 1 "v4k_file.h" // ----------------------------------------------------------------------------- // files, cache and virtual filesystem (registered directories and/or compressed zip archives). // - rlyeh, public domain. @@ -2144,7 +2111,7 @@ API void ini_destroy(ini_t); API bool ini_write(const char *filename, const char *section, const char *key, const char *value); #line 0 -#line 1 "engine/split/v4k_font.h" +#line 1 "v4k_font.h" // ----------------------------------------------------------------------------- // font framework // - rlyeh, public domain @@ -2236,7 +2203,7 @@ API void* font_colorize(const char *text, const char *comma_types, const char *c API vec2 font_highlight(const char *text, const void *colors); #line 0 -#line 1 "engine/split/v4k_input.h" +#line 1 "v4k_input.h" // ----------------------------------------------------------------------------- // input framework // - rlyeh, public domain @@ -2363,7 +2330,7 @@ enum INPUT_ALIASES { }; #line 0 -#line 1 "engine/split/v4k_memory.h" +#line 1 "v4k_memory.h" // ----------------------------------------------------------------------------- // memory framework // - rlyeh, public domain @@ -2403,7 +2370,7 @@ static FORCE_INLINE void *(CALLOC_)(size_t m, size_t n) { return n *= m, memset( static FORCE_INLINE char *(STRDUP_)(const char *s) { size_t n = strlen(s)+1; return ((char*)memcpy(REALLOC(0,n), s, n)); } ///- #line 0 -#line 1 "engine/split/v4k_network.h" +#line 1 "v4k_network.h" // ----------------------------------------------------------------------------- // network framework // - rlyeh, public domain @@ -2455,7 +2422,7 @@ API int tcp_debug(int); // toggle traffic monitoring on/off for given socket //API int tcp_crypt(int,uint64_t); // set shared secret #line 0 -#line 1 "engine/split/v4k_track.h" +#line 1 "v4k_track.h" #ifndef TRACK_SEND_BUFSIZE #define TRACK_SEND_BUFSIZE 576 #endif @@ -2516,7 +2483,7 @@ typedef struct track_prop { API int track_event_props(char const *event_id, char const *user_id, const track_prop *props); #line 0 -#line 1 "engine/split/v4k_netsync.h" +#line 1 "v4k_netsync.h" // high-level, socket-less networking api. inspired by Quake, MPI and RenderBuckets theories. // - rlyeh, public domain // @@ -2602,7 +2569,7 @@ API int64_t client_join(const char *ip, int port); #define LOCALHOST_IPV6 "::1" #line 0 -#line 1 "engine/split/v4k_pack.h" +#line 1 "v4k_pack.h" // ---------------------------------------------------------------------------- // compression api @@ -2731,25 +2698,25 @@ typedef struct double2 { double x,y; } double2; typedef struct double3 { double x,y,z; } double3; typedef struct double4 { double x,y,z,w; } double4; -#define byte2(x,y) M_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) -#define byte3(x,y,z) M_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) -#define byte4(x,y,z,w) M_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) +#define byte2(x,y) C_CAST(byte2, (uint8_t)(x), (uint8_t)(y) ) +#define byte3(x,y,z) C_CAST(byte3, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z) ) +#define byte4(x,y,z,w) C_CAST(byte4, (uint8_t)(x), (uint8_t)(y), (uint8_t)(z), (uint8_t)(w) ) -#define int2(x,y) M_CAST(int2, (int)(x), (int)(y) ) -#define int3(x,y,z) M_CAST(int3, (int)(x), (int)(y), (int)(z) ) -#define int4(x,y,z,w) M_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) +#define int2(x,y) C_CAST(int2, (int)(x), (int)(y) ) +#define int3(x,y,z) C_CAST(int3, (int)(x), (int)(y), (int)(z) ) +#define int4(x,y,z,w) C_CAST(int4, (int)(x), (int)(y), (int)(z), (int)(w) ) -#define uint2(x,y) M_CAST(uint2, (unsigned)(x), (unsigned)(y) ) -#define uint3(x,y,z) M_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) -#define uint4(x,y,z,w) M_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) +#define uint2(x,y) C_CAST(uint2, (unsigned)(x), (unsigned)(y) ) +#define uint3(x,y,z) C_CAST(uint3, (unsigned)(x), (unsigned)(y), (unsigned)(z) ) +#define uint4(x,y,z,w) C_CAST(uint4, (unsigned)(x), (unsigned)(y), (unsigned)(z), (unsigned)(w) ) -#define float2(x,y) M_CAST(float2, (float)(x), (float)(y) ) -#define float3(x,y,z) M_CAST(float3, (float)(x), (float)(y), (float)(z) ) -#define float4(x,y,z,w) M_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) +#define float2(x,y) C_CAST(float2, (float)(x), (float)(y) ) +#define float3(x,y,z) C_CAST(float3, (float)(x), (float)(y), (float)(z) ) +#define float4(x,y,z,w) C_CAST(float4, (float)(x), (float)(y), (float)(z), (float)(w) ) -#define double2(x,y) M_CAST(double2, (double)(x), (double)(y) ) -#define double3(x,y,z) M_CAST(double3, (double)(x), (double)(y), (double)(z) ) -#define double4(x,y,z,w) M_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) +#define double2(x,y) C_CAST(double2, (double)(x), (double)(y) ) +#define double3(x,y,z) C_CAST(double3, (double)(x), (double)(y), (double)(z) ) +#define double4(x,y,z,w) C_CAST(double4, (double)(x), (double)(y), (double)(z), (double)(w) ) // ----------------------------------------------------------------------------- // compile-time fourcc, eightcc @@ -2994,7 +2961,7 @@ API int loadb(const unsigned char *buf, const char *format, ...); #line 0 -#line 1 "engine/split/v4k_profile.h" +#line 1 "v4k_profile.h" // ----------------------------------------------------------------------------- // profiler & stats (@fixme: threadsafe) @@ -3026,7 +2993,7 @@ extern API int profiler_enabled; ///- #endif #line 0 -#line 1 "engine/split/v4k_reflect.h" +#line 1 "v4k_reflect.h" // C reflection: enums, functions, structs, members and anotations. // - rlyeh, public domain // @@ -3093,7 +3060,7 @@ API const char* symbol_naked(const char *s); API int ui_reflect(const char *mask); // *, model* or NULL #line 0 -#line 1 "engine/split/v4k_render.h" +#line 1 "v4k_render.h" // ----------------------------------------------------------------------------- // naive rendering framework // - rlyeh, public domain @@ -3279,82 +3246,6 @@ API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); -// ----------------------------------------------------------------------------- -// sprites - -// texture id, position(x,y,depth sort), tint color, rotation angle -API void sprite( texture_t texture, float position[3], float rotation /*0*/, uint32_t color /*~0u*/); - -// texture id, rect(x,y,w,h) is [0..1] normalized, z-index, pos(xy,scale.xy), rotation (degrees), color (rgba) -API void sprite_rect( texture_t t, vec4 rect, float zindex, vec4 pos, float tilt_deg, unsigned tint_rgba); - -// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color -API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant); - -API void sprite_flush(); - -// ----------------------------------------------------------------------------- -// tilemaps - -typedef struct tileset_t { - texture_t tex; // spritesheet - unsigned tile_w, tile_h; // dimensions per tile in pixels - unsigned cols, rows; // tileset num_cols, num_rows - unsigned selected; // active tile (while editing) -} tileset_t; - -API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); - -API int ui_tileset( tileset_t t ); - -typedef struct tilemap_t { - int blank_chr; // transparent tile - unsigned cols, rows; // map dimensions (in tiles) - array(int) map; - - vec3 position; // x,y,scale - float zindex; - float tilt; - unsigned tint; - bool is_additive; -} tilemap_t; - -API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); -API void tilemap_render( tilemap_t m, tileset_t style ); -API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); - -// ----------------------------------------------------------------------------- -// tiled maps - -typedef struct tiled_t { - char *map_name; - unsigned first_gid, tilew, tileh, w, h; - - bool parallax; - vec3 position; - array(bool) visible; - array(tilemap_t) layers; - array(tileset_t) sets; - array(char*) names; -} tiled_t; - -API tiled_t tiled(const char *file_tmx); -API void tiled_render(tiled_t tmx, vec3 pos); - -API void ui_tiled(tiled_t *t); - -// ----------------------------------------------------------------------------- -// spines - -typedef struct spine_t spine_t; - -API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); -API void spine_skin(spine_t *p, unsigned skin); -API void spine_render(spine_t *p, vec3 offset, unsigned flags); -API void spine_animate(spine_t *p, float delta); - -API void ui_spine(spine_t *p); - // ----------------------------------------------------------------------------- // cubemaps @@ -3801,7 +3692,7 @@ API void* screenshot(int components); // 3 RGB, 4 RGBA, -3 BGR, -4 BGRA API void* screenshot_async(int components); // 3 RGB, 4 RGBA, -3 BGR, -4 BGRA #line 0 -#line 1 "engine/split/v4k_renderdd.h" +#line 1 "v4k_renderdd.h" // ----------------------------------------------------------------------------- // debugdraw framework // - rlyeh, public domain. @@ -3868,7 +3759,7 @@ API void ddraw_flush(); API void ddraw_flush_projview(mat44 proj, mat44 view); #line 0 -#line 1 "engine/split/v4k_scene.h" +#line 1 "v4k_scene.h" // ----------------------------------------------------------------------------- // scene framework // - rlyeh, public domain @@ -4005,7 +3896,124 @@ API unsigned scene_count_light(); API light_t* scene_index_light(unsigned index); #line 0 -#line 1 "engine/split/v4k_string.h" +#line 1 "v4k_sprite.h" +// ----------------------------------------------------------------------------- +// sprites + +typedef enum SPRITE_FLAGS { + SPRITE_PROJECTED = 1, + SPRITE_ADDITIVE = 2, + SPRITE_CENTERED = 4, + SPRITE_RESOLUTION_INDEPENDANT = 128, +} SPRITE_FLAGS; + +// texture id, position(x,y,depth sort), tint color, rotation angle +API void sprite( texture_t texture, float position[3], float rotation /*0*/, unsigned color /*~0u*/, unsigned flags); + +// texture id, rect(x,y,w,h) is [0..1] normalized, then: pos(xyz,z-index), (scale.xy,offset.xy), rotation (degrees), color (rgba) +API void sprite_rect( texture_t t, vec4 rect, vec4 pos, vec4 scaleoff, float tilt_deg, unsigned tint_rgba, unsigned flags); + +// texture id, sheet(frameNumber,X,Y) (frame in a X*Y spritesheet), position(x,y,depth sort), rotation angle, offset(x,y), scale(x,y), is_additive, tint color +API void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], unsigned rgba, unsigned flags); + +API void sprite_flush(); + +// ----------------------------------------------------------------------------- +// tilemaps + +typedef struct tileset_t { + texture_t tex; // spritesheet + unsigned tile_w, tile_h; // dimensions per tile in pixels + unsigned cols, rows; // tileset num_cols, num_rows + unsigned selected; // active tile (while editing) +} tileset_t; + +API tileset_t tileset(texture_t tex, unsigned tile_w, unsigned tile_h, unsigned cols, unsigned rows); + +API int ui_tileset( tileset_t t ); + +typedef struct tilemap_t { + int blank_chr; // transparent tile + unsigned cols, rows; // map dimensions (in tiles) + array(int) map; + + vec3 position; // x,y,scale + float zindex; + float tilt; + unsigned tint; + bool is_additive; +} tilemap_t; + +API tilemap_t tilemap(const char *map, int blank_chr, int linefeed_chr); +API void tilemap_render( tilemap_t m, tileset_t style ); +API void tilemap_render_ext( tilemap_t m, tileset_t style, float zindex, float xy_zoom[3], float tilt, unsigned tint, bool is_additive ); + +// ----------------------------------------------------------------------------- +// tiled maps + +typedef struct tiled_t { + char *map_name; + unsigned first_gid, tilew, tileh, w, h; + + bool parallax; + vec3 position; + array(bool) visible; + array(tilemap_t) layers; + array(tileset_t) sets; + array(char*) names; +} tiled_t; + +API tiled_t tiled(const char *file_tmx); +API void tiled_render(tiled_t tmx, vec3 pos); + +API void ui_tiled(tiled_t *t); + +// ----------------------------------------------------------------------------- +// spines + +typedef struct spine_t spine_t; + +API spine_t*spine(const char *file_json, const char *file_atlas, unsigned flags); +API void spine_skin(spine_t *p, unsigned skin); +API void spine_render(spine_t *p, vec3 offset, unsigned flags); +API void spine_animate(spine_t *p, float delta); + +API void ui_spine(spine_t *p); + +// ---------------------------------------------------------------------------- +// sprite v2 api + +typedef struct sprite_t { OBJ + vec4 gamepad; // up,down,left,right + vec2 fire; // a,b + + vec4 pos; + vec2 sca; + float tilt; + unsigned tint; + unsigned frame; + unsigned timer, timer_ms; + unsigned flip_, flipped; + unsigned play; + bool paused; + // array(unsigned) play_queue; or unsigned play_next; + struct atlas_t *a; // shared + //atlas_t own; // owned +} sprite_t; + +OBJTYPEDEF(sprite_t,10); +API void sprite_ctor(sprite_t *s); +API void sprite_dtor(sprite_t *s); +API void sprite_tick(sprite_t *s); +API void sprite_draw(sprite_t *s); +API void sprite_edit(sprite_t *s); + +API sprite_t*sprite_new(const char *ase, int bindings[6]); +API void sprite_del(sprite_t *s); +API void sprite_setanim(sprite_t *s, unsigned name); +#line 0 + +#line 1 "v4k_string.h" // string framework // - rlyeh, public domain @@ -4098,9 +4106,26 @@ typedef struct quarks_db { API unsigned quark_intern( quarks_db*, const char *string ); API const char *quark_string( quarks_db*, unsigned key ); + +// ----------------------------------------------------------------------------- +// ## localization kit (I18N, L10N) + +API bool kit_load( const char *filename ); // load translations file (xlsx) +API bool kit_merge( const char *filename ); // merge translations file into existing context +API void kit_insert( const char *id, const char *translation ); // insert single translation unit +API void kit_clear(); // delete all translations + +API void kit_set( const char *variable, const char *value ); // set context variable +API void kit_reset(); // reset all variables in context +API void kit_dump_state( FILE *fp ); // debug + +API char* kit_translate2( const char *id, const char *langcode_iso639_1 ); // perform a translation given explicit locale + +API void kit_locale( const char *langcode_iso639_1 ); // set current locale: enUS, ptBR, esES, ... +API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 -#line 1 "engine/split/v4k_system.h" +#line 1 "v4k_system.h" // ----------------------------------------------------------------------------- // system framework utils // - rlyeh, public domain. @@ -4187,7 +4212,7 @@ API int (test)(const char *file, int line, const char *expr, bool result); #endif #line 0 -#line 1 "engine/split/v4k_time.h" +#line 1 "v4k_time.h" // ----------------------------------------------------------------------------- // time framework utils @@ -4346,7 +4371,7 @@ API vec3 curve_eval(curve_t *c, float dt, unsigned *color); API void curve_destroy(curve_t *c); #line 0 -#line 1 "engine/split/v4k_ui.h" +#line 1 "v4k_ui.h" // ----------------------------------------------------------------------------- // immediate ui framework // - rlyeh, public domain @@ -4440,7 +4465,7 @@ API int ui_demo(int do_windows); API void *ui_handle(); #line 0 -#line 1 "engine/split/v4k_video.h" +#line 1 "v4k_video.h" // ----------------------------------------------------------------------------- // video decoder (mpeg) // - rlyeh, public domain @@ -4483,7 +4508,7 @@ API bool record_active(); API void record_stop(void); #line 0 -#line 1 "engine/split/v4k_window.h" +#line 1 "v4k_window.h" // ----------------------------------------------------------------------------- // window framework // - rlyeh, public domain @@ -4587,6 +4612,39 @@ API void window_setclipboard(const char *text); // ---- +#line 1 "v4k_editor.h" +// ----------------------------------------------------------------------------- +// in-game editor +// - rlyeh, public domain. + +API int editor_send(const char *command); + +//API void editor(); +//API bool editor_active(); +API vec3 editor_pick(float mouse_x, float mouse_y); +API char* editor_path(const char *path); + +API float* engine_getf(const char *key); +API int* engine_geti(const char *key); +API char** engine_gets(const char *key); +API int engine_send(const char *cmd, const char *optional_value); + +API int ui_debug(); + +// open file dialog + +API char* dialog_load(); +API char* dialog_save(); + +// transform gizmos + +API int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); +API bool gizmo_active(); +API bool gizmo_hover(); +#line 0 + +// ---- + #if is(cpp) } // extern "C" #endif diff --git a/hello.c b/hello.c index 31fad86..eb4b40a 100644 --- a/hello.c +++ b/hello.c @@ -16,17 +16,18 @@ int main() { // options + unsigned no_flags = 0; bool do_debugdraw = 0; // window (80% sized, MSAA x4 flag) window_create(80, WINDOW_MSAA4); window_title(__FILE__); - // load skybox: launch with --mie for rayleigh/mie scattering (no flags) - skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0); + // load skybox: launch with --mie for rayleigh/mie scattering + skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", no_flags); - // animated models loading (no flags) - model_t girl = model("kgirl/kgirls01.fbx", 0); + // animated models loading + model_t girl = model("kgirl/kgirls01.fbx", no_flags); compose44( girl.pivot, vec3(0,0,0), eulerq(vec3(-90,0,0)), vec3(2,2,2)); // position, rotation, scale // camera @@ -38,8 +39,8 @@ int main() { // audio (both clips & streams) audio_t SFX1 = audio_clip( "coin.wav" ), SFX2 = audio_clip( "pew.sfxr" ); audio_t BGM1 = audio_stream( "waterworld-map.fur" ), BGM2 = audio_stream( "larry.mid" ), BGM = BGM1; - audio_play(SFX1, 0); - audio_play(BGM, 0); + audio_play(SFX1, no_flags); + audio_play(BGM, no_flags); // demo loop while (window_swap()) @@ -76,7 +77,7 @@ int main() { girl.curframe = model_animate(girl, girl.curframe + delta); // draw girl - model_render(girl, cam.proj, cam.view, girl.pivot, 0); + model_render(girl, cam.proj, cam.view, girl.pivot, no_flags); // post-fxs end here fx_end(); @@ -97,10 +98,10 @@ int main() { if( ui_button("Test Lua") ) script_run("ui_notify(nil, \"Hello from Lua! Version: \" .. _VERSION)"); ui_section("Audio"); - if( ui_label2_toolbar("BGM: Waterworld Map", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM1, 0); - if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM2, 0); - if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(SFX1, 0); - if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(SFX2, 0); + if( ui_label2_toolbar("BGM: Waterworld Map", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM1, no_flags); + if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM2, no_flags); + if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(SFX1, no_flags); + if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(SFX2, no_flags); ui_panel_end(); } diff --git a/tools/3rd_delaunay.h b/tools/3rd_delaunay.h new file mode 100644 index 0000000..0ca03dc --- /dev/null +++ b/tools/3rd_delaunay.h @@ -0,0 +1,1059 @@ +#ifndef DELAUNAY_H +#define DELAUNAY_H + +/* +** delaunay.c : compute 2D delaunay triangulation in the plane. +** Copyright (C) 2005 Wael El Oraiby +** +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU Affero General Public License as +** published by the Free Software Foundation, either version 3 of the +** License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Affero General Public License for more details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +*/ + + + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef double real; + +typedef struct { + real x, y; +} del_point2d_t; + +typedef struct { + /** input points count */ + unsigned int num_points; + + /** the input points */ + del_point2d_t* points; + + /** number of returned faces */ + unsigned int num_faces; + + /** the faces are given as a sequence: num verts, verts indices, num verts, verts indices... + * the first face is the external face */ + unsigned int* faces; +} delaunay2d_t; + +/* + * build the 2D Delaunay triangulation given a set of points of at least 3 points + * + * @points: point set given as a sequence of tuple x0, y0, x1, y1, .... + * @num_points: number of given point + * @preds: the incircle predicate + * @faces: the triangles given as a sequence: num verts, verts indices, num verts, verts indices. + * Note that the first face is the external face + * @return: the created topology + */ +delaunay2d_t* delaunay2d_from(del_point2d_t *points, unsigned int num_points); + +/* + * release a delaunay2d object + */ +void delaunay2d_release(delaunay2d_t* del); + + +typedef struct { + /** input points count */ + unsigned int num_points; + + /** input points */ + del_point2d_t* points; + + /** number of triangles */ + unsigned int num_triangles; + + /** the triangles indices v0,v1,v2, v0,v1,v2 .... */ + unsigned int* tris; +} tri_delaunay2d_t; + +/** + * build a tri_delaunay2d_t out of a delaunay2d_t object + */ +tri_delaunay2d_t* tri_delaunay2d_from(delaunay2d_t* del); + +/** + * release a tri_delaunay2d_t object + */ +void tri_delaunay2d_release(tri_delaunay2d_t* tdel); + +#ifdef __cplusplus +} +#endif + +#endif // DELAUNAY_H + +#ifdef DELAUNAY_C + +/* +** delaunay.c : compute 2D delaunay triangulation in the plane. +** Copyright (C) 2005 Wael El Oraiby +** +** +** This program is free software: you can redistribute it and/or modify +** it under the terms of the GNU Affero General Public License as +** published by the Free Software Foundation, either version 3 of the +** License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Affero General Public License for more details. +** +** You should have received a copy of the GNU Affero General Public License +** along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include + +#define ON_RIGHT 1 +#define ON_SEG 0 +#define ON_LEFT -1 + +#define OUTSIDE -1 +#define ON_CIRCLE 0 +#define INSIDE 1 + +struct point2d_s; +struct face_s; +struct halfedge_s; +struct delaunay_s; + + +#define REAL_ZERO 0.0l +#define REAL_ONE 1.0l +#define REAL_TWO 2.0l +#define REAL_FOUR 4.0l + + +typedef struct point2d_s point2d_t; +typedef struct face_s face_t; +typedef struct halfedge_s halfedge_t; +typedef struct delaunay_s delaunay_t; +typedef struct working_set_s working_set_t; + +typedef long double lreal; +typedef lreal mat3_t[3][3]; + +struct point2d_s { + real x, y; /* point coordinates */ + halfedge_t* he; /* point halfedge */ + unsigned int idx; /* point index in input buffer */ +}; + +struct face_s { + halfedge_t* he; /* a pointing half edge */ + unsigned int num_verts; /* number of vertices on this face */ +}; + +struct halfedge_s { + point2d_t* vertex; /* vertex */ + halfedge_t* pair; /* pair */ + halfedge_t* next; /* next */ + halfedge_t* prev; /* next^-1 */ + face_t* face; /* halfedge face */ +}; + +struct delaunay_s { + halfedge_t* rightmost_he; /* right most halfedge */ + halfedge_t* leftmost_he; /* left most halfedge */ + point2d_t* points; /* pointer to points */ + face_t* faces; /* faces of delaunay */ + unsigned int num_faces; /* face count */ + unsigned int start_point; /* start point index */ + unsigned int end_point; /* end point index */ +}; + +struct working_set_s { + halfedge_t* edges; /* all the edges (allocated in one shot) */ + face_t* faces; /* all the faces (allocated in one shot) */ + + unsigned int max_edge; /* maximum edge count: 2 * 3 * n where n is point count */ + unsigned int max_face; /* maximum face count: 2 * n where n is point count */ + + unsigned int num_edges; /* number of allocated edges */ + unsigned int num_faces; /* number of allocated faces */ + + halfedge_t* free_edge; /* pointer to the first free edge */ + face_t* free_face; /* pointer to the first free face */ +}; + +/* +* 3x3 matrix determinant +*/ +static lreal det3(mat3_t m) +{ + lreal res = m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + + return res; +} + +/* +* allocate a halfedge +*/ +static halfedge_t* halfedge_alloc() +{ + halfedge_t* d; + + d = (halfedge_t*)malloc(sizeof(halfedge_t)); + assert( NULL != d ); + memset(d, 0, sizeof(halfedge_t)); + + return d; +} + +/* +* free a halfedge +*/ +static void halfedge_free( halfedge_t* d ) +{ + assert( d != NULL ); + memset(d, 0, sizeof(halfedge_t)); + free(d); +} + +/* +* free all delaunay halfedges +*/ +void del_free_halfedges( delaunay_t *del ) +{ + unsigned int i; + halfedge_t *d, *sig; + + /* if there is nothing to do */ + if( del->points == NULL ) + return; + + for( i = 0; i <= (del->end_point - del->start_point); i++ ) + { + /* free all the halfedges around the point */ + d = del->points[i].he; + if( d != NULL ) + { + do { + sig = d->next; + halfedge_free( d ); + d = sig; + } while( d != del->points[i].he ); + del->points[i].he = NULL; + } + } +} + +/* +* compare 2 points when sorting +*/ +static int cmp_points( const void *_pt0, const void *_pt1 ) +{ + point2d_t *pt0, *pt1; + + pt0 = (point2d_t*)(_pt0); + pt1 = (point2d_t*)(_pt1); + + if( pt0->x < pt1->x ) + return -1; + else if( pt0->x > pt1->x ) + return 1; + else if( pt0->y < pt1->y ) + return -1; + else if( pt0->y > pt1->y ) + return 1; + printf("2 or more points share the same exact coordinate: (%f,%f)(%f,%f)\n", pt0->x,pt0->y,pt1->x,pt1->y); + assert(0 && "2 or more points share the same exact coordinate"); + return 0; /* Should not be given! */ +} + +/* +* classify a point relative to a segment +*/ +static int classify_point_seg( point2d_t *s, point2d_t *e, point2d_t *pt ) +{ + lreal se_x, se_y, spt_x, spt_y; + lreal res; + + se_x = e->x - s->x; + se_y = e->y - s->y; + + spt_x = pt->x - s->x; + spt_y = pt->y - s->y; + + res = (( se_x * spt_y ) - ( se_y * spt_x )); + if( res < REAL_ZERO ) + return ON_RIGHT; + else if( res > REAL_ZERO ) + return ON_LEFT; + + return ON_SEG; +} + +/* +* classify a point relative to a halfedge, -1 is left, 0 is on, 1 is right +*/ +static int del_classify_point( halfedge_t *d, point2d_t *pt ) +{ + point2d_t *s, *e; + + s = d->vertex; + e = d->pair->vertex; + + return classify_point_seg(s, e, pt); +} + +/* +* test if a point is inside a circle given by 3 points, 1 if inside, 0 if outside +*/ +static int in_circle( point2d_t *pt0, point2d_t *pt1, point2d_t *pt2, point2d_t *p ) +{ + // reduce the computational complexity by substracting the last row of the matrix + // ref: https://www.cs.cmu.edu/~quake/robust.html + lreal p0p_x, p0p_y, p1p_x, p1p_y, p2p_x, p2p_y, p0p, p1p, p2p, res; + mat3_t m; + + p0p_x = pt0->x - p->x; + p0p_y = pt0->y - p->y; + + p1p_x = pt1->x - p->x; + p1p_y = pt1->y - p->y; + + p2p_x = pt2->x - p->x; + p2p_y = pt2->y - p->y; + + p0p = p0p_x * p0p_x + p0p_y * p0p_y; + p1p = p1p_x * p1p_x + p1p_y * p1p_y; + p2p = p2p_x * p2p_x + p2p_y * p2p_y; + + m[0][0] = p0p_x; + m[0][1] = p0p_y; + m[0][2] = p0p; + + m[1][0] = p1p_x; + m[1][1] = p1p_y; + m[1][2] = p1p; + + m[2][0] = p2p_x; + m[2][1] = p2p_y; + m[2][2] = p2p; + + res = -det3(m); + + if( res < REAL_ZERO ) + return INSIDE; + else if( res > REAL_ZERO ) + return OUTSIDE; + + return ON_CIRCLE; +} + +/* +* initialize delaunay segment +*/ +static int del_init_seg( delaunay_t *del, int start ) +{ + halfedge_t *d0, *d1; + point2d_t *pt0, *pt1; + + /* init delaunay */ + del->start_point = start; + del->end_point = start + 1; + + /* setup pt0 and pt1 */ + pt0 = &(del->points[start]); + pt1 = &(del->points[start + 1]); + + /* allocate the halfedges and setup them */ + d0 = halfedge_alloc(); + d1 = halfedge_alloc(); + + d0->vertex = pt0; + d1->vertex = pt1; + + d0->next = d0->prev = d0; + d1->next = d1->prev = d1; + + d0->pair = d1; + d1->pair = d0; + + pt0->he = d0; + pt1->he = d1; + + del->rightmost_he = d1; + del->leftmost_he = d0; + + + return 0; +} + +/* +* initialize delaunay triangle +*/ +static int del_init_tri( delaunay_t *del, int start ) +{ + halfedge_t *d0, *d1, *d2, *d3, *d4, *d5; + point2d_t *pt0, *pt1, *pt2; + + /* initiate delaunay */ + del->start_point = start; + del->end_point = start + 2; + + /* setup the points */ + pt0 = &(del->points[start]); + pt1 = &(del->points[start + 1]); + pt2 = &(del->points[start + 2]); + + /* allocate the 6 halfedges */ + d0 = halfedge_alloc(); + d1 = halfedge_alloc(); + d2 = halfedge_alloc(); + d3 = halfedge_alloc(); + d4 = halfedge_alloc(); + d5 = halfedge_alloc(); + + if( classify_point_seg(pt0, pt2, pt1) == ON_LEFT ) /* first case */ + { + /* set halfedges points */ + d0->vertex = pt0; + d1->vertex = pt2; + d2->vertex = pt1; + + d3->vertex = pt2; + d4->vertex = pt1; + d5->vertex = pt0; + + /* set points halfedges */ + pt0->he = d0; + pt1->he = d2; + pt2->he = d1; + + /* next and next -1 setup */ + d0->next = d5; + d0->prev = d5; + + d1->next = d3; + d1->prev = d3; + + d2->next = d4; + d2->prev = d4; + + d3->next = d1; + d3->prev = d1; + + d4->next = d2; + d4->prev = d2; + + d5->next = d0; + d5->prev = d0; + + /* set halfedges pair */ + d0->pair = d3; + d3->pair = d0; + + d1->pair = d4; + d4->pair = d1; + + d2->pair = d5; + d5->pair = d2; + + del->rightmost_he = d1; + del->leftmost_he = d0; + + } else /* 2nd case */ + { + /* set halfedges points */ + d0->vertex = pt0; + d1->vertex = pt1; + d2->vertex = pt2; + + d3->vertex = pt1; + d4->vertex = pt2; + d5->vertex = pt0; + + /* set points halfedges */ + pt0->he = d0; + pt1->he = d1; + pt2->he = d2; + + /* next and next -1 setup */ + d0->next = d5; + d0->prev = d5; + + d1->next = d3; + d1->prev = d3; + + d2->next = d4; + d2->prev = d4; + + d3->next = d1; + d3->prev = d1; + + d4->next = d2; + d4->prev = d2; + + d5->next = d0; + d5->prev = d0; + + /* set halfedges pair */ + d0->pair = d3; + d3->pair = d0; + + d1->pair = d4; + d4->pair = d1; + + d2->pair = d5; + d5->pair = d2; + + del->rightmost_he = d2; + del->leftmost_he = d0; + } + + return 0; +} + +/* +* remove an edge given a halfedge +*/ +static void del_remove_edge( halfedge_t *d ) +{ + halfedge_t *next, *prev, *pair, *orig_pair; + + orig_pair = d->pair; + + next = d->next; + prev = d->prev; + pair = d->pair; + + assert(next != NULL); + assert(prev != NULL); + + next->prev = prev; + prev->next = next; + + + /* check to see if we have already removed pair */ + if( pair ) + pair->pair = NULL; + + /* check to see if the vertex points to this halfedge */ + if( d->vertex->he == d ) + d->vertex->he = next; + + d->vertex = NULL; + d->next = NULL; + d->prev = NULL; + d->pair = NULL; + + next = orig_pair->next; + prev = orig_pair->prev; + pair = orig_pair->pair; + + assert(next != NULL); + assert(prev != NULL); + + next->prev = prev; + prev->next = next; + + + /* check to see if we have already removed pair */ + if( pair ) + pair->pair = NULL; + + /* check to see if the vertex points to this halfedge */ + if( orig_pair->vertex->he == orig_pair ) + orig_pair->vertex->he = next; + + orig_pair->vertex = NULL; + orig_pair->next = NULL; + orig_pair->prev = NULL; + orig_pair->pair = NULL; + + + /* finally free the halfedges */ + halfedge_free(d); + halfedge_free(orig_pair); +} + +/* +* pass through all the halfedges on the left side and validate them +*/ +static halfedge_t* del_valid_left( halfedge_t* b ) +{ + point2d_t *g, *d, *u, *v; + halfedge_t *c, *du, *dg; + + g = b->vertex; /* base halfedge point */ + dg = b; + + d = b->pair->vertex; /* pair(halfedge) point */ + b = b->next; + + u = b->pair->vertex; /* next(pair(halfedge)) point */ + du = b->pair; + + v = b->next->pair->vertex; /* pair(next(next(halfedge)) point */ + + if( classify_point_seg(g, d, u) == ON_LEFT ) + { + /* 3 points aren't colinear */ + /* as long as the 4 points belong to the same circle, do the cleaning */ + assert( v != u && "1: floating point precision error"); + while( v != d && v != g && in_circle(g, d, u, v) == INSIDE ) + { + c = b->next; + du = b->next->pair; + del_remove_edge(b); + b = c; + u = du->vertex; + v = b->next->pair->vertex; + } + + assert( v != u && "2: floating point precision error"); + if( v != d && v != g && in_circle(g, d, u, v) == ON_CIRCLE ) + { + du = du->prev; + del_remove_edge(b); + } + } else /* treat the case where the 3 points are colinear */ + du = dg; + + assert(du->pair); + return du; +} + +/* +* pass through all the halfedges on the right side and validate them +*/ +static halfedge_t* del_valid_right( halfedge_t *b ) +{ + point2d_t *rv, *lv, *u, *v; + halfedge_t *c, *dd, *du; + + b = b->pair; + rv = b->vertex; + dd = b; + lv = b->pair->vertex; + b = b->prev; + u = b->pair->vertex; + du = b->pair; + + v = b->prev->pair->vertex; + + if( classify_point_seg(lv, rv, u) == ON_LEFT ) + { + assert( v != u && "1: floating point precision error"); + while( v != lv && v != rv && in_circle(lv, rv, u, v) == INSIDE ) + { + c = b->prev; + du = c->pair; + del_remove_edge(b); + b = c; + u = du->vertex; + v = b->prev->pair->vertex; + } + + assert( v != u && "1: floating point precision error"); + if( v != lv && v != rv && in_circle(lv, rv, u, v) == ON_CIRCLE ) + { + du = du->next; + del_remove_edge(b); + } + } else + du = dd; + + assert(du->pair); + return du; +} + + +/* +* validate a link +*/ +static halfedge_t* del_valid_link( halfedge_t *b ) +{ + point2d_t *g, *g_p, *d, *d_p; + halfedge_t *gd, *dd, *new_gd, *new_dd; + int a; + + g = b->vertex; + gd = del_valid_left(b); + g_p = gd->vertex; + + assert(b->pair); + d = b->pair->vertex; + dd = del_valid_right(b); + d_p = dd->vertex; + assert(b->pair); + + if( g != g_p && d != d_p ) { + a = in_circle(g, d, g_p, d_p); + + if( a != ON_CIRCLE ) { + if( a == INSIDE ) { + g_p = g; + gd = b; + } else { + d_p = d; + dd = b->pair; + } + } + } + + /* create the 2 halfedges */ + new_gd = halfedge_alloc(); + new_dd = halfedge_alloc(); + + /* setup new_gd and new_dd */ + + new_gd->vertex = gd->vertex; + new_gd->pair = new_dd; + new_gd->prev = gd; + new_gd->next = gd->next; + gd->next->prev = new_gd; + gd->next = new_gd; + + new_dd->vertex = dd->vertex; + new_dd->pair = new_gd; + new_dd->prev = dd->prev; + dd->prev->next = new_dd; + new_dd->next = dd; + dd->prev = new_dd; + + return new_gd; +} + +/* +* find the lower tangent between the two delaunay, going from left to right (returns the left half edge) +*/ +static halfedge_t* del_get_lower_tangent( delaunay_t *left, delaunay_t *right ) +{ + point2d_t *pl, *pr; + halfedge_t *right_d, *left_d, *new_ld, *new_rd; + int sl, sr; + + left_d = left->rightmost_he; + right_d = right->leftmost_he; + + do { + pl = left_d->prev->pair->vertex; + pr = right_d->pair->vertex; + + if( (sl = classify_point_seg(left_d->vertex, right_d->vertex, pl)) == ON_RIGHT ) { + left_d = left_d->prev->pair; + } + + if( (sr = classify_point_seg(left_d->vertex, right_d->vertex, pr)) == ON_RIGHT ) { + right_d = right_d->pair->next; + } + + } while( sl == ON_RIGHT || sr == ON_RIGHT ); + + /* create the 2 halfedges */ + new_ld = halfedge_alloc(); + new_rd = halfedge_alloc(); + + /* setup new_gd and new_dd */ + new_ld->vertex = left_d->vertex; + new_ld->pair = new_rd; + new_ld->prev = left_d->prev; + left_d->prev->next = new_ld; + new_ld->next = left_d; + left_d->prev = new_ld; + + new_rd->vertex = right_d->vertex; + new_rd->pair = new_ld; + new_rd->prev = right_d->prev; + right_d->prev->next = new_rd; + new_rd->next = right_d; + right_d->prev = new_rd; + + return new_ld; +} + +/* +* link the 2 delaunay together +*/ +static void del_link( delaunay_t *result, delaunay_t *left, delaunay_t *right ) +{ + point2d_t *u, *v, *ml, *mr; + halfedge_t *base; + + assert( left->points == right->points ); + + /* save the most right point and the most left point */ + ml = left->leftmost_he->vertex; + mr = right->rightmost_he->vertex; + + base = del_get_lower_tangent(left, right); + + u = base->next->pair->vertex; + v = base->pair->prev->pair->vertex; + + while( del_classify_point(base, u) == ON_LEFT || + del_classify_point(base, v) == ON_LEFT ) + { + base = del_valid_link(base); + u = base->next->pair->vertex; + v = base->pair->prev->pair->vertex; + } + + right->rightmost_he = mr->he; + left->leftmost_he = ml->he; + + /* TODO: this part is not needed, and can be optimized */ + while( del_classify_point( right->rightmost_he, right->rightmost_he->prev->pair->vertex ) == ON_RIGHT ) + right->rightmost_he = right->rightmost_he->prev; + + while( del_classify_point( left->leftmost_he, left->leftmost_he->prev->pair->vertex ) == ON_RIGHT ) + left->leftmost_he = left->leftmost_he->prev; + + result->leftmost_he = left->leftmost_he; + result->rightmost_he = right->rightmost_he; + result->points = left->points; + result->start_point = left->start_point; + result->end_point = right->end_point; +} + +/* +* divide and conquer delaunay +*/ +void del_divide_and_conquer( delaunay_t *del, int start, int end ) +{ + delaunay_t left, right; + int i, n; + + n = (end - start + 1); + + if( n > 3 ) { + i = (n / 2) + (n & 1); + left.points = del->points; + right.points = del->points; + del_divide_and_conquer( &left, start, start + i - 1 ); + del_divide_and_conquer( &right, start + i, end ); + del_link( del, &left, &right ); + } else { + if( n == 3 ) { + del_init_tri( del, start ); + } else { + if( n == 2 ) { + del_init_seg( del, start ); + } + } + } +} + +static void build_halfedge_face( delaunay_t *del, halfedge_t *d ) +{ + halfedge_t *curr; + + /* test if the halfedge has already a pointing face */ + if( d->face != NULL ) + return; + + /* TODO: optimize this */ + del->faces = (face_t*)realloc(del->faces, (del->num_faces + 1) * sizeof(face_t)); + assert( NULL != del->faces ); + + face_t *f = &(del->faces[del->num_faces]); + curr = d; + f->he = d; + f->num_verts = 0; + do { + curr->face = f; + (f->num_verts)++; + curr = curr->pair->prev; + } while( curr != d ); + + (del->num_faces)++; +} + +/* +* build the faces for all the halfedge +*/ +void del_build_faces( delaunay_t *del ) +{ + unsigned int i; + halfedge_t *curr; + + del->num_faces = 0; + del->faces = NULL; + + /* build external face first */ + build_halfedge_face(del, del->rightmost_he->pair); + + for( i = del->start_point; i <= del->end_point; i++ ) + { + curr = del->points[i].he; + + do { + build_halfedge_face( del, curr ); + curr = curr->next; + } while( curr != del->points[i].he ); + } +} + +/* +*/ +delaunay2d_t* delaunay2d_from(del_point2d_t *points, unsigned int num_points) { + delaunay2d_t* res = NULL; + delaunay_t del; + unsigned int i, j, fbuff_size = 0; + unsigned int* faces = NULL; + + /* allocate the points */ + del.points = (point2d_t*)malloc(num_points * sizeof(point2d_t)); + assert( NULL != del.points ); + memset(del.points, 0, num_points * sizeof(point2d_t)); + + /* copy the points */ + for( i = 0; i < num_points; i++ ) + { + del.points[i].idx = i; + del.points[i].x = points[i].x; + del.points[i].y = points[i].y; + } + + qsort(del.points, num_points, sizeof(point2d_t), cmp_points); + + if( num_points >= 3 ) { + del_divide_and_conquer( &del, 0, num_points - 1 ); + + del_build_faces( &del ); + + fbuff_size = 0; + for( i = 0; i < del.num_faces; i++ ) + fbuff_size += del.faces[i].num_verts + 1; + + faces = (unsigned int*)malloc(sizeof(unsigned int) * fbuff_size); + assert( NULL != faces ); + + j = 0; + for( i = 0; i < del.num_faces; i++ ) + { + halfedge_t *curr; + + faces[j] = del.faces[i].num_verts; + j++; + + curr = del.faces[i].he; + do { + faces[j] = curr->vertex->idx; + j++; + curr = curr->pair->prev; + } while( curr != del.faces[i].he ); + } + + del_free_halfedges( &del ); + + free(del.faces); + free(del.points); + } + + res = (delaunay2d_t*)malloc(sizeof(delaunay2d_t)); + assert( NULL != res ); + res->num_points = num_points; + res->points = (del_point2d_t*)malloc(sizeof(del_point2d_t) * num_points); + assert( NULL != res->points ); + memcpy(res->points, points, sizeof(del_point2d_t) * num_points); + res->num_faces = del.num_faces; + res->faces = faces; + + return res; +} + +void delaunay2d_release(delaunay2d_t *del) { + free(del->faces); + free(del->points); + free(del); +} + + +tri_delaunay2d_t* tri_delaunay2d_from(delaunay2d_t* del) { + unsigned int v_offset = del->faces[0] + 1; /* ignore external face */ + unsigned int dst_offset = 0; + unsigned int i; + + tri_delaunay2d_t* tdel = (tri_delaunay2d_t*)malloc(sizeof(tri_delaunay2d_t)); + assert( NULL != tdel ); + tdel->num_triangles = 0; + + /* count the number of triangles */ + if( 1 == del->num_faces ) { /* degenerate case: only external face exists */ + unsigned int nv = del->faces[0]; + tdel->num_triangles += nv - 2; + } else { + for( i = 1; i < del->num_faces; ++i ) { + unsigned int nv = del->faces[v_offset]; + tdel->num_triangles += nv - 2; + v_offset += nv + 1; + } + } + + /* copy points */ + tdel->num_points = del->num_points; + tdel->points = (del_point2d_t*)malloc(sizeof(del_point2d_t) * del->num_points); + assert( NULL != tdel->points ); + memcpy(tdel->points, del->points, sizeof(del_point2d_t) * del->num_points); + + /* build the triangles */ + tdel->tris = (unsigned int*)malloc(sizeof(unsigned int) * 3 * tdel->num_triangles); + assert( NULL != tdel->tris ); + + v_offset = del->faces[0] + 1; /* ignore external face */ + + if( 1 == del->num_faces ) { + /* handle the degenerated case where only the external face exists */ + unsigned int nv = del->faces[0]; + unsigned int j = 0; + v_offset = 1; + for( ; j < nv - 2; ++j ) { + tdel->tris[dst_offset] = del->faces[v_offset + j]; + tdel->tris[dst_offset + 1] = del->faces[(v_offset + j + 1) % nv]; + tdel->tris[dst_offset + 2] = del->faces[v_offset + j]; + dst_offset += 3; + } + } else { + for( i = 1; i < del->num_faces; ++i ) { + unsigned int nv = del->faces[v_offset]; + unsigned int j = 0; + unsigned int first = del->faces[v_offset + 1]; + + + for( ; j < nv - 2; ++j ) { + tdel->tris[dst_offset] = first; + tdel->tris[dst_offset + 1] = del->faces[v_offset + j + 2]; + tdel->tris[dst_offset + 2] = del->faces[v_offset + j + 3]; + dst_offset += 3; + } + + v_offset += nv + 1; + } + } + + return tdel; +} + + +void tri_delaunay2d_release(tri_delaunay2d_t* tdel) { + free(tdel->tris); + free(tdel->points); + free(tdel); +} + +#endif diff --git a/tools/3rd_sproutline.h b/tools/3rd_sproutline.h new file mode 100644 index 0000000..462cbe8 --- /dev/null +++ b/tools/3rd_sproutline.h @@ -0,0 +1,441 @@ +/* sproutline - v0.10 - public domain sprite outline detector - http://github.org/ands/sproutline + no warranty implied; use at your own risk + + Do this: + #define S2O_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define S2O_IMPLEMENTATION + #include "sproutline.h" + + You can #define S2O_MALLOC to avoid using malloc + + + QUICK NOTES: + Primarily of interest to game developers. + - Recommended to be used with stb_image. + - Detects outlines in sprite images with alpha channels. + - Extracts outlines as clockwise paths. + - Simplifies outlines based on a distance metric. + + Full documentation under "DOCUMENTATION" below. + + + Revision 0.10 release notes: + + - Initial release of sproutline.h. + + - Added S2O_MALLOC macro for replacing the memory allocator. + Unlike most STB libraries, this macro doesn't support a context parameter, + so if you need to pass a context in to the allocator, you'll have to + store it in a global or a thread-local variable. + + + Revision history: + 0.10 (2015-10-22) initial version + + ============================ Contributors ========================= + + Andreas Mantler (ands) + +License: + This software is in the public domain. Where that dedication is not + recognized, you are granted a perpetual, irrevocable license to copy + and modify this file however you want. + +*/ + +#ifndef S2O_INCLUDE_SPROUTLINE_H +#define S2O_INCLUDE_SPROUTLINE_H + +// DOCUMENTATION +// +// Limitations: +// - currently only works with images that have alpha channels +// +// Basic usage (with stb_image): +// int w, h, n, l; +// unsigned char *rgba = stbi_load(filename, &w, &h, &n, 4); +// unsigned char *alpha = s2o_rgba_to_alpha(rgba, w, h); +// unsigned char *thresholded = s2o_alpha_to_thresholded(alpha, w, h, ALPHA_THRESHOLD); +// unsigned char *outlined = s2o_thresholded_to_outlined(thresholded, w, h); +// s2o_point *outline = s2o_extract_outline_path(outlined, w, h, &l, 0); +// while(l) +// { +// s2o_distance_based_path_simplification(outline, &l, DISTANCE_THRESHOLD); +// // ... process outline here ... +// // ... l = number of points in outline +// // ... ALPHA_THRESHOLD = 1..255 (the min value to be considered solid) +// // ... DISTANCE_THRESHOLD = 0.0f..Inf (~0.5f is a suitable value) +// // ... a greater value results in fewer points in the output +// +// outline = s2o_extract_outline_path(outlined, w, h, &l, outline); +// }; +// free(outline); +// free(outlined); +// free(thresholded); +// free(alpha); +// free(rgba); +// +// s2o_rgba_to_alpha: +// Expects an 'unsigned char *' to memory of w * h 4-byte pixels in 'RGBA' order. +// The return value is an 'unsigned char *' to memory of w * h 1-byte pixel alpha components. +// +// s2o_alpha_to_thresholded: +// Expects an 'unsigned char *' to memory of w * h 1-byte pixel alpha components. +// The return value is an 'unsigned char *' to memory of w * h 1-byte values +// that are 255 if the corresponding input is >= the specified threshold, otherwise 0. +// +// s2o_thresholded_to_outlined: +// Expects an 'unsigned char *' to memory of w * h 1-byte pixels indicating their solidity {0, nonzero}. +// The return value is an 'unsigned char *' to memory of w * h 1-byte pixels that indicate if the +// corresponding input value is part of an outline (= is solid and has a non-solid neighbour). +// +// s2o_extract_outline_path: +// Expects an 'unsigned char *' to memory of w * h 1-byte pixels indicating their outline membership. +// The return value is an 's2o_point *' to memory of l s2o_point values consisting of a short x and y value. +// The procedure scans the input data from top to bottom and starts extracting the first outline it finds. +// The pixels corresponding to the extracted outline are set to 0 in the input, so that a subsequent call to +// s2o_extract_outline_path extracts a different outline. +// The length is set to 0 if no outline was found. +// +// s2o_distance_based_path_simplification: +// Expects an 's2o_point *' to memory of l outline points. +// The procedure throws out points in place that lie on or close to linear sections of the outline. +// The distanceThreshold parameter specifies the min distance value for points to remain in the outline. +// +// =========================================================================== +// +// Philosophy +// +// This library is designed with the stb philosophy in mind. +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small footprint ("easy to maintain") +// - No dependencies ("ease of use") +// + +typedef unsigned char s2o_uc; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef S2O_STATIC +#define S2ODEF static +#else +#define S2ODEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API +// + +S2ODEF s2o_uc * s2o_rgba_to_alpha (const s2o_uc *data, int w, int h); +S2ODEF s2o_uc * s2o_alpha_to_thresholded (const s2o_uc *data, int w, int h, s2o_uc threshold); +S2ODEF s2o_uc * s2o_thresholded_to_outlined(const s2o_uc *data, int w, int h); + +typedef struct { short x, y; } s2o_point; +S2ODEF s2o_point * s2o_extract_outline_path(s2o_uc *data, int w, int h, int *point_count, s2o_point *reusable_outline); +S2ODEF void s2o_distance_based_path_simplification(s2o_point *outline, int *outline_length, float distance_threshold); + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // S2O_INCLUDE_SPROUTLINE_H + +#ifdef S2O_IMPLEMENTATION + +#include // sqrtf, abs + +#ifndef S2O_MALLOC +#include // malloc +#define S2O_MALLOC(sz) malloc(sz) +#endif + +/////////////////////////////////////////////// +// +// locally used types + +typedef int s2o_bool; + +// 2d point type helpers +#define S2O_POINT_ADD(result, a, b) { (result).x = (a).x + (b).x; (result).y = (a).y + (b).y; } +#define S2O_POINT_SUB(result, a, b) { (result).x = (a).x - (b).x; (result).y = (a).y - (b).y; } +#define S2O_POINT_IS_INSIDE(a, w, h) ((a).x >= 0 && (a).y >= 0 && (a).x < (w) && (a).y < (h)) +#define S2O_POINT_IS_NEXT_TO(a, b) ((a).x - (b).x <= 1 && (a).x - (b).x >= -1 && (a).y - (b).y <= 1 && (a).y - (b).y >= -1) + +// direction type +typedef int s2o_direction; // 8 cw directions: >, _|, v, |_, <, |", ^, "| +#define S2O_DIRECTION_OPPOSITE(dir) ((dir + 4) & 7) +static const s2o_point s2o_direction_to_pixel_offset[] = { {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1} }; + +// image manipulation functions +S2ODEF s2o_uc * s2o_rgba_to_alpha(const s2o_uc *data, int w, int h) +{ + s2o_uc *result = (s2o_uc*)S2O_MALLOC(w * h); + int x, y; + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + result[y * w + x] = data[(y * w + x) * 4 + 3]; + return result; +} + +S2ODEF s2o_uc * s2o_alpha_to_thresholded(const s2o_uc *data, int w, int h, s2o_uc threshold) +{ + s2o_uc *result = (s2o_uc*)S2O_MALLOC(w * h); + int x, y; + for (y = 0; y < h; y++) + for (x = 0; x < w; x++) + result[y * w + x] = data[y * w + x] >= threshold ? 255 : 0; + return result; +} + +S2ODEF s2o_uc * s2o_dilate_thresholded(const s2o_uc *data, int w, int h) +{ + int x, y, dx, dy, cx, cy; + s2o_uc *result = (s2o_uc*)S2O_MALLOC(w * h); + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + result[y * w + x] = 0; + for (dy = -1; dy <= 1; dy++) + { + for (dx = -1; dx <= 1; dx++) + { + cx = x + dx; + cy = y + dy; + if (cx >= 0 && cx < w && cy >= 0 && cy < h) + { + if (data[cy * w + cx]) + { + result[y * w + x] = 255; + dy = 1; + break; + } + } + } + } + } + } + return result; +} + +S2ODEF s2o_uc * s2o_thresholded_to_outlined(const s2o_uc *data, int w, int h) +{ + s2o_uc *result = (s2o_uc*)S2O_MALLOC(w * h); + int x, y; + for (x = 0; x < w; x++) + { + result[x] = data[x]; + result[(h - 1) * w + x] = data[(h - 1) * w + x]; + } + for (y = 1; y < h - 1; y++) + { + result[y * w] = data[y * w]; + for (x = 1; x < w - 1; x++) + { + if (data[y * w + x] && + ( + !data[y * w + x - 1] || + !data[y * w + x + 1] || + !data[y * w + x - w] || + !data[y * w + x + w] + )) + { + result[y * w + x] = 255; + } + else + { + result[y * w + x] = 0; + } + } + result[y * w + w - 1] = data[y * w + w - 1]; + } + return result; +} + +// outline path procedures +static s2o_bool s2o_find_first_filled_pixel(const s2o_uc *data, int w, int h, s2o_point *first) +{ + int x, y; + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + { + if (data[y * w + x]) + { + first->x = (short)x; + first->y = (short)y; + return 1; + } + } + } + return 0; +} + +static s2o_bool s2o_find_next_filled_pixel(const s2o_uc *data, int w, int h, s2o_point current, s2o_direction *dir, s2o_point *next) +{ + // turn around 180°, then make a clockwise scan for a filled pixel + *dir = S2O_DIRECTION_OPPOSITE(*dir); + int i; + for (i = 0; i < 8; i++) + { + S2O_POINT_ADD(*next, current, s2o_direction_to_pixel_offset[*dir]); + + if (S2O_POINT_IS_INSIDE(*next, w, h) && data[next->y * w + next->x]) + return 1; + + // move to next angle (clockwise) + *dir = *dir - 1; + if (*dir < 0) + *dir = 7; + } + return 0; +} + +S2ODEF s2o_point * s2o_extract_outline_path(s2o_uc *data, int w, int h, int *point_count, s2o_point *reusable_outline) +{ + s2o_point *outline = reusable_outline; + if (!outline) + outline = (s2o_point*)S2O_MALLOC(w * h * sizeof(s2o_point)); + + s2o_point current, next; + +restart: + if (!s2o_find_first_filled_pixel(data, w, h, ¤t)) + { + *point_count = 0; + return outline; + } + + int count = 0; + s2o_direction dir = 0; + + while(S2O_POINT_IS_INSIDE(current, w, h) && count < (w*h)) //< @r-lyeh: buffer overflow: add count= 0 && count < (w * h); prev--) //< @r-lyeh: buffer overflow: add count 1; l--) + { + int a, b = l; + for (a = 0; a < length; a++) + { + s2o_point ab; + S2O_POINT_SUB(ab, outline[b], outline[a]); + float lab = sqrtf((float)(ab.x * ab.x + ab.y * ab.y)); + float ilab = 1.0f / lab; + float abnx = ab.x * ilab, abny = ab.y * ilab; + + if (lab != 0.0f) + { + s2o_bool found = 1; + int i = (a + 1) % length; + while (i != b) + { + s2o_point ai; + S2O_POINT_SUB(ai, outline[i], outline[a]); + float t = (abnx * ai.x + abny * ai.y) * ilab; + float distance = -abny * ai.x + abnx * ai.y; + if (t < 0.0f || t > 1.0f || distance > distance_threshold || -distance > distance_threshold) + { + found = 0; + break; + } + + if (++i == length) + i = 0; + } + + if (found) + { + int i; + if (a < b) + { + for (i = 0; i < length - b; i++) + outline[a + i + 1] = outline[b + i]; + length -= b - a - 1; + } + else + { + length = a - b + 1; + for (i = 0; i < length; i++) + outline[i] = outline[b + i]; + } + if (l >= length) + l = length - 1; + } + } + + if (++b >= length) + b = 0; + } + } + *outline_length = length; +} + +#endif // S2O_IMPLEMENTATION diff --git a/tools/3rd_stb_image_resize.h b/tools/3rd_stb_image_resize.h new file mode 100644 index 0000000..4ed5b16 --- /dev/null +++ b/tools/3rd_stb_image_resize.h @@ -0,0 +1,2634 @@ +/* stb_image_resize - v0.97 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.97 (2020-02-02) fixed warning + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/tools/3rd_stb_rect_pack.h b/tools/3rd_stb_rect_pack.h new file mode 100644 index 0000000..6a633ce --- /dev/null +++ b/tools/3rd_stb_rect_pack.h @@ -0,0 +1,623 @@ +// stb_rect_pack.h - v1.01 - public domain - rectangle packing +// Sean Barrett 2014 +// +// Useful for e.g. packing rectangular textures into an atlas. +// Does not do rotation. +// +// Before #including, +// +// #define STB_RECT_PACK_IMPLEMENTATION +// +// in the file that you want to have the implementation. +// +// Not necessarily the awesomest packing method, but better than +// the totally naive one in stb_truetype (which is primarily what +// this is meant to replace). +// +// Has only had a few tests run, may have issues. +// +// More docs to come. +// +// No memory allocations; uses qsort() and assert() from stdlib. +// Can override those by defining STBRP_SORT and STBRP_ASSERT. +// +// This library currently uses the Skyline Bottom-Left algorithm. +// +// Please note: better rectangle packers are welcome! Please +// implement them to the same API, but with a different init +// function. +// +// Credits +// +// Library +// Sean Barrett +// Minor features +// Martins Mozeiko +// github:IntellectualKitty +// +// Bugfixes / warning fixes +// Jeremy Jaussaud +// Fabian Giesen +// +// Version history: +// +// 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section +// 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles +// 0.99 (2019-02-07) warning fixes +// 0.11 (2017-03-03) return packing success/fail result +// 0.10 (2016-10-25) remove cast-away-const to avoid warnings +// 0.09 (2016-08-27) fix compiler warnings +// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) +// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) +// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort +// 0.05: added STBRP_ASSERT to allow replacing assert +// 0.04: fixed minor bug in STBRP_LARGE_RECTS support +// 0.01: initial release +// +// LICENSE +// +// See end of file for license information. + +////////////////////////////////////////////////////////////////////////////// +// +// INCLUDE SECTION +// + +#ifndef STB_INCLUDE_STB_RECT_PACK_H +#define STB_INCLUDE_STB_RECT_PACK_H + +#define STB_RECT_PACK_VERSION 1 + +#ifdef STBRP_STATIC +#define STBRP_DEF static +#else +#define STBRP_DEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct stbrp_context stbrp_context; +typedef struct stbrp_node stbrp_node; +typedef struct stbrp_rect stbrp_rect; + +typedef int stbrp_coord; + +#define STBRP__MAXVAL 0x7fffffff +// Mostly for internal use, but this is the maximum supported coordinate value. + +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +// Assign packed locations to rectangles. The rectangles are of type +// 'stbrp_rect' defined below, stored in the array 'rects', and there +// are 'num_rects' many of them. +// +// Rectangles which are successfully packed have the 'was_packed' flag +// set to a non-zero value and 'x' and 'y' store the minimum location +// on each axis (i.e. bottom-left in cartesian coordinates, top-left +// if you imagine y increasing downwards). Rectangles which do not fit +// have the 'was_packed' flag set to 0. +// +// You should not try to access the 'rects' array from another thread +// while this function is running, as the function temporarily reorders +// the array while it executes. +// +// To pack into another rectangle, you need to call stbrp_init_target +// again. To continue packing into the same rectangle, you can call +// this function again. Calling this multiple times with multiple rect +// arrays will probably produce worse packing results than calling it +// a single time with the full rectangle array, but the option is +// available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. + +struct stbrp_rect +{ + // reserved for your use: + int id; + + // input: + stbrp_coord w, h; + + // output: + stbrp_coord x, y; + int was_packed; // non-zero if valid packing + +}; // 16 bytes, nominally + + +STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); +// Initialize a rectangle packer to: +// pack a rectangle that is 'width' by 'height' in dimensions +// using temporary storage provided by the array 'nodes', which is 'num_nodes' long +// +// You must call this function every time you start packing into a new target. +// +// There is no "shutdown" function. The 'nodes' memory must stay valid for +// the following stbrp_pack_rects() call (or calls), but can be freed after +// the call (or calls) finish. +// +// Note: to guarantee best results, either: +// 1. make sure 'num_nodes' >= 'width' +// or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' +// +// If you don't do either of the above things, widths will be quantized to multiples +// of small integers to guarantee the algorithm doesn't run out of temporary storage. +// +// If you do #2, then the non-quantized algorithm will be used, but the algorithm +// may run out of temporary storage and be unable to pack some rectangles. + +STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); +// Optionally call this function after init but before doing any packing to +// change the handling of the out-of-temp-memory scenario, described above. +// If you call init again, this will be reset to the default (false). + + +STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); +// Optionally select which packing heuristic the library should use. Different +// heuristics will produce better/worse results for different data sets. +// If you call init again, this will be reset to the default. + +enum +{ + STBRP_HEURISTIC_Skyline_default=0, + STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, + STBRP_HEURISTIC_Skyline_BF_sortHeight +}; + + +////////////////////////////////////////////////////////////////////////////// +// +// the details of the following structures don't matter to you, but they must +// be visible so you can handle the memory allocations for them + +struct stbrp_node +{ + stbrp_coord x,y; + stbrp_node *next; +}; + +struct stbrp_context +{ + int width; + int height; + int align; + int init_mode; + int heuristic; + int num_nodes; + stbrp_node *active_head; + stbrp_node *free_head; + stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' +}; + +#ifdef __cplusplus +} +#endif + +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// IMPLEMENTATION SECTION +// + +#ifdef STB_RECT_PACK_IMPLEMENTATION +#ifndef STBRP_SORT +#include +#define STBRP_SORT qsort +#endif + +#ifndef STBRP_ASSERT +#include +#define STBRP_ASSERT assert +#endif + +#ifdef _MSC_VER +#define STBRP__NOTUSED(v) (void)(v) +#define STBRP__CDECL __cdecl +#else +#define STBRP__NOTUSED(v) (void)sizeof(v) +#define STBRP__CDECL +#endif + +enum +{ + STBRP__INIT_skyline = 1 +}; + +STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) +{ + switch (context->init_mode) { + case STBRP__INIT_skyline: + STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); + context->heuristic = heuristic; + break; + default: + STBRP_ASSERT(0); + } +} + +STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) +{ + if (allow_out_of_mem) + // if it's ok to run out of memory, then don't bother aligning them; + // this gives better packing, but may fail due to OOM (even though + // the rectangles easily fit). @TODO a smarter approach would be to only + // quantize once we've hit OOM, then we could get rid of this parameter. + context->align = 1; + else { + // if it's not ok to run out of memory, then quantize the widths + // so that num_nodes is always enough nodes. + // + // I.e. num_nodes * align >= width + // align >= width / num_nodes + // align = ceil(width/num_nodes) + + context->align = (context->width + context->num_nodes-1) / context->num_nodes; + } +} + +STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) +{ + int i; + + for (i=0; i < num_nodes-1; ++i) + nodes[i].next = &nodes[i+1]; + nodes[i].next = NULL; + context->init_mode = STBRP__INIT_skyline; + context->heuristic = STBRP_HEURISTIC_Skyline_default; + context->free_head = &nodes[0]; + context->active_head = &context->extra[0]; + context->width = width; + context->height = height; + context->num_nodes = num_nodes; + stbrp_setup_allow_out_of_mem(context, 0); + + // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) + context->extra[0].x = 0; + context->extra[0].y = 0; + context->extra[0].next = &context->extra[1]; + context->extra[1].x = (stbrp_coord) width; + context->extra[1].y = (1<<30); + context->extra[1].next = NULL; +} + +// find minimum y position if it starts at x1 +static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) +{ + stbrp_node *node = first; + int x1 = x0 + width; + int min_y, visited_width, waste_area; + + STBRP__NOTUSED(c); + + STBRP_ASSERT(first->x <= x0); + + #if 0 + // skip in case we're past the node + while (node->next->x <= x0) + ++node; + #else + STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency + #endif + + STBRP_ASSERT(node->x <= x0); + + min_y = 0; + waste_area = 0; + visited_width = 0; + while (node->x < x1) { + if (node->y > min_y) { + // raise min_y higher. + // we've accounted for all waste up to min_y, + // but we'll now add more waste for everything we've visted + waste_area += visited_width * (node->y - min_y); + min_y = node->y; + // the first time through, visited_width might be reduced + if (node->x < x0) + visited_width += node->next->x - x0; + else + visited_width += node->next->x - node->x; + } else { + // add waste area + int under_width = node->next->x - node->x; + if (under_width + visited_width > width) + under_width = width - visited_width; + waste_area += under_width * (min_y - node->y); + visited_width += under_width; + } + node = node->next; + } + + *pwaste = waste_area; + return min_y; +} + +typedef struct +{ + int x,y; + stbrp_node **prev_link; +} stbrp__findresult; + +static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) +{ + int best_waste = (1<<30), best_x, best_y = (1 << 30); + stbrp__findresult fr; + stbrp_node **prev, *node, *tail, **best = NULL; + + // align to multiple of c->align + width = (width + c->align - 1); + width -= width % c->align; + STBRP_ASSERT(width % c->align == 0); + + // if it can't possibly fit, bail immediately + if (width > c->width || height > c->height) { + fr.prev_link = NULL; + fr.x = fr.y = 0; + return fr; + } + + node = c->active_head; + prev = &c->active_head; + while (node->x + width <= c->width) { + int y,waste; + y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); + if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL + // bottom left + if (y < best_y) { + best_y = y; + best = prev; + } + } else { + // best-fit + if (y + height <= c->height) { + // can only use it if it first vertically + if (y < best_y || (y == best_y && waste < best_waste)) { + best_y = y; + best_waste = waste; + best = prev; + } + } + } + prev = &node->next; + node = node->next; + } + + best_x = (best == NULL) ? 0 : (*best)->x; + + // if doing best-fit (BF), we also have to try aligning right edge to each node position + // + // e.g, if fitting + // + // ____________________ + // |____________________| + // + // into + // + // | | + // | ____________| + // |____________| + // + // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned + // + // This makes BF take about 2x the time + + if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { + tail = c->active_head; + node = c->active_head; + prev = &c->active_head; + // find first node that's admissible + while (tail->x < width) + tail = tail->next; + while (tail) { + int xpos = tail->x - width; + int y,waste; + STBRP_ASSERT(xpos >= 0); + // find the left position that matches this + while (node->next->x <= xpos) { + prev = &node->next; + node = node->next; + } + STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); + y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); + if (y + height <= c->height) { + if (y <= best_y) { + if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { + best_x = xpos; + STBRP_ASSERT(y <= best_y); + best_y = y; + best_waste = waste; + best = prev; + } + } + } + tail = tail->next; + } + } + + fr.prev_link = best; + fr.x = best_x; + fr.y = best_y; + return fr; +} + +static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) +{ + // find best position according to heuristic + stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); + stbrp_node *node, *cur; + + // bail if: + // 1. it failed + // 2. the best node doesn't fit (we don't always check this) + // 3. we're out of memory + if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { + res.prev_link = NULL; + return res; + } + + // on success, create new node + node = context->free_head; + node->x = (stbrp_coord) res.x; + node->y = (stbrp_coord) (res.y + height); + + context->free_head = node->next; + + // insert the new node into the right starting point, and + // let 'cur' point to the remaining nodes needing to be + // stiched back in + + cur = *res.prev_link; + if (cur->x < res.x) { + // preserve the existing one, so start testing with the next one + stbrp_node *next = cur->next; + cur->next = node; + cur = next; + } else { + *res.prev_link = node; + } + + // from here, traverse cur and free the nodes, until we get to one + // that shouldn't be freed + while (cur->next && cur->next->x <= res.x + width) { + stbrp_node *next = cur->next; + // move the current node to the free list + cur->next = context->free_head; + context->free_head = cur; + cur = next; + } + + // stitch the list back in + node->next = cur; + + if (cur->x < res.x + width) + cur->x = (stbrp_coord) (res.x + width); + +#ifdef _DEBUG + cur = context->active_head; + while (cur->x < context->width) { + STBRP_ASSERT(cur->x < cur->next->x); + cur = cur->next; + } + STBRP_ASSERT(cur->next == NULL); + + { + int count=0; + cur = context->active_head; + while (cur) { + cur = cur->next; + ++count; + } + cur = context->free_head; + while (cur) { + cur = cur->next; + ++count; + } + STBRP_ASSERT(count == context->num_nodes+2); + } +#endif + + return res; +} + +static int STBRP__CDECL rect_height_compare(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + if (p->h > q->h) + return -1; + if (p->h < q->h) + return 1; + return (p->w > q->w) ? -1 : (p->w < q->w); +} + +static int STBRP__CDECL rect_original_order(const void *a, const void *b) +{ + const stbrp_rect *p = (const stbrp_rect *) a; + const stbrp_rect *q = (const stbrp_rect *) b; + return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); +} + +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +{ + int i, all_rects_packed = 1; + + // we use the 'was_packed' field internally to allow sorting/unsorting + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = i; + } + + // sort according to heuristic + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); + + for (i=0; i < num_rects; ++i) { + if (rects[i].w == 0 || rects[i].h == 0) { + rects[i].x = rects[i].y = 0; // empty rect needs no space + } else { + stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); + if (fr.prev_link) { + rects[i].x = (stbrp_coord) fr.x; + rects[i].y = (stbrp_coord) fr.y; + } else { + rects[i].x = rects[i].y = STBRP__MAXVAL; + } + } + } + + // unsort + STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); + + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { + rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/tools/ark.linux b/tools/ark.linux new file mode 100644 index 0000000000000000000000000000000000000000..bed073c3251e1d8951179f54407845242a408cc4 GIT binary patch literal 13424 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

jbR=>JQ0%3y<842Vv2uWQP_Nn=xOgB;Z{= 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 #include @@ -870,7 +870,6 @@ void export_animlist(FILE *out, const struct aiScene *scene) fprintf(out, "frame: %s\n", "0-0 Idle"); } - /* * For multi-mesh models, sometimes each mesh has its own inv_bind_matrix set * for each bone. To export to IQE we must have only one inv_bind_matrix per @@ -1540,49 +1539,3 @@ flags |= (doflipUV ? aiProcess_FlipUVs : 0); return 0; } -// base64 de/encoder. Based on code by Jon Mayo - November 13, 2003 (PUBLIC DOMAIN). -// - rlyeh, public domain - -#include -#include -#include -#include -#include - -unsigned base64_bounds(unsigned size) { - return 4 * ((size + 2) / 3); -} - -char* base64_encode(const void *in_, unsigned inlen) { - unsigned outlen = base64_bounds(inlen); - char *out_ = calloc(1, outlen); - - uint_least32_t v; - unsigned ii, io, rem; - char *out = (char *)out_; - const unsigned char *in = (const unsigned char *)in_; - const uint8_t base64enc_tab[]= "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - - for(io = 0, ii = 0, v = 0, rem = 0; ii < inlen; ii ++) { - unsigned char ch; - ch = in[ii]; - v = (v << 8) | ch; - rem += 8; - while (rem >= 6) { - rem -= 6; - if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ - out[io ++] = base64enc_tab[(v >> rem) & 63]; - } - } - if (rem) { - v <<= (6 - rem); - if (io >= outlen) - return (free(out_), 0); /* truncation is failure */ - out[io ++] = base64enc_tab[v & 63]; - } - if (io < outlen) - out[io] = 0; - - return out_; -} diff --git a/tools/cook.c b/tools/cook.c index c6449e7..ade20fe 100644 --- a/tools/cook.c +++ b/tools/cook.c @@ -28,9 +28,11 @@ int main(int argc, const char **argv) { return 0; } -// compiled with: -// tcc cook.c -I..\engine -// cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG -// cc -ObjC cook.c -I../engine -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -O3 -// cc cook.c -I../engine -o cook.linux -lm -lpthread -ldl -lX11 -O3 -// del cook.o & del cook.obj & del cook.lib & del cook.exp +/* + compiled with: + cc -ObjC cook.c -I../engine -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -O3 + cc cook.c -I../engine -o cook.linux -lm -lpthread -ldl -lX11 -O3 + tcc cook.c -I..\engine + cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG + del cook.o & del cook.obj & del cook.lib & del cook.exp +*/ \ No newline at end of file diff --git a/tools/cook.exe b/tools/cook.exe index 32777aaea5e49a5d425e0aab0df2d3216b6910ac..dda9c7e11045c17d51802015ce71a8b726017306 100644 GIT binary patch delta 160359 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 UGH7kJg4vf09U*66aWAK delta 179329 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%0DD-h5XEekStm_OFs7? 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%0AG7e8Va|xOOP=UH1uH(G_P)QF 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 JZSBu5{C|BtAp!sZ diff --git a/tools/cook.ini b/tools/cook.ini index 0208f36..589747c 100644 --- a/tools/cook.ini +++ b/tools/cook.ini @@ -25,9 +25,9 @@ ART=../demos/art/,../engine/art/,../tools/editor/art/ ; comma-separated folder( ; also, once a symbol is found, it is replaced by its value always. ; some predefined symbols: INPUT (input filename), OUTPUT (output filename), PRETTY (clean input filename), PROGRESS (cook progress). -;@windows `echo Cooking PROGRESS% PRETTY...` -;@linux `echo "Cooking PROGRESS% PRETTY..."` -;@osx `echo "Cooking PROGRESS% PRETTY..."` +@windows `echo Cooking PROGRESS% PRETTY...` +@linux `echo "Cooking PROGRESS% PRETTY..."` +@osx `echo "Cooking PROGRESS% PRETTY..."` ; ------------------------------------------------------------------------------ ; groups below are collection of files that we want to cook, and then package. diff --git a/tools/cook.linux b/tools/cook.linux index 14fa12e0fd83100d71a42b52009d24edf7bd2b22..b313a9c31870728a8aa9a7c535ed61a0ffac2fe0 100644 GIT binary patch delta 1840035 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

-ZCFo6PNBFuGx87wf3 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 twJn^Pe7CA>daf|v6? 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

M!gb^1ELQG8Zc2n5%3*S;l`wNqlkESW7S#*(< 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

xnZPaKF3~(HLQ_Arln%P}Vw=DJ~ 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

xW8VE=@z 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⩔)=Kg;{~`o;t`nBk3m@I`K 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%0DgVA1Hsn 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

EuF&))kK14<9Wc9Qa0%m%{rxT_e4UhmekY;py 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 delta 1587307 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

{t0)ra}9~bI=7oH<7JEOt!|b3^0kNX zezFQWib4nWXVah$)iN(sJA_c}6uv>>Rj2UODfkA1U~vjMeBa8WYJfr{2<+RnQe#i) zCgtjrE9{rG(%gtY0pKuWv1u@K1MkJHb9?L3ujChDj>4VMWMDMo&a?TSO8zR>S~#_F zsC7CIx#dE0r*H>z8{`!HokCL#Avpyr;>z99w;;^ zW3fFFU9#%o@Ue`4qmZC4RpFWd}b%VBx@yz!;d-9poGGy&|K5jT^2AE(`fJ;4qH)EhcVxEQpZjz zl!(urfXlGv3?yGv)2r?eS}|Fdk56e9+x7b!(^q2XO_*;M`b%IC>s=n$m??__-P!l+ zBwzJAP!es|VFb6>%CvqL!OnIGvy{fO^p}zy3O%abFKNm!-Ci6hVcH?)4|V7cLSsH z^v2)_tgKZ;72>rU&VlHBmM%Q8xR0*lI%HTptHMG`97JKU*Z|>HR2;d;+`f>E-8*67 z@u}C+TC>=0!6X(hZHcz_YPG{u>ed8`ahX5QikJ#V^UAxeJ-NWfe<5}CEupK^-jWM% zaG^TCz0AJ;LTVRb6+%Watmi{M6R+6w8>Qxw;KE1C-3T^vBh2vpaGhmtl!9ds0BbkG zLYB z>EWR1dv_vO%S}>eHJ*pTj|{|0)lr5t3@|_h;EPvBc_(rsT*L}t4fW9AF|;sr%o1}*BrvYh)ud;tONik6y z@WjTAeR%q#y~px+YSJIX&qjF_4 zrA|`zRQA(mDQt2!yvHk2plM~nwbLzt_UQ-A{)wbRn)G+55s1(vVw121|1&WmecYCC`H#Wk$$At_G%yaTMivKf|k zO3}e|_5Pig*XZ)M!au;Qz%14qkKnLPS2%3_ctLRiOpL;EOfa<@7R03BlFn=|oE5dl zwP~9Ii=qqADNh7{zqi)<8@Q?LaSecr`?e5AF09{h?Y-}zdF-C+<)Q3O_AbntIfdOm zB&qscZ0ccYgnlP0JuI2vkH-<1W5T?ek4UXLT!9ksXC#~!yQKB`8u}Kqu@lTwcf)6m z9+24J)+xHyFhh3-UZ7|n?Ps4Ik)mWM4?A&03g9tSLQM62=E5+O1Ua49*Y@#CkU(CG zqtabT3g4RNe+$4^M*l62wQyf05lll9G}Nqu#;VMaGJ z@`0C$`Mm)QwdAh21F;S*STC`NU!(y^cgDii7=8n;8(-2jYZ_b)-A1_lTo~pQnl=OB z#=mQXWT#LEg<~LS`7n7pF;DwV^3bz82fbRf_y|&hRW24=b%O1Ir3_Yytha}+J2fiZu5(G@JcQV4e1;>d5TiKu- zM@GUPm{o?$H_vEsF4j;Lr^x>8+>&+%dPe>mu%TH?cMY@rcUXo+u!@ZXNEGvP|)#z za625YlV;G`9C5&utdg@F*j`wZ2#;y-jAyc)&F=))tN>rS!Q246OXcBVxKD-qfgfvk z4r9=a(bh`6^@$_nN4ud)9;UPV{fHxNd4^ls{R7KjAngV5L>GxSEw60Afpi-miqriI zFiVBWpx5{kaa`X8(WF%t<3nGWVFR4#A${?gT;&%$f6uGTZkP`S&j)sAi96`_C-D-e zf{y=#65lpJiDP-T|67SC)G9F)7=uHBCqs)>`H80cA0?I`a=YKJ+--1{cxtT@zw-r_ zcrO|hL5VTWLTjxO4-&dmtHfL31e$;C0)xl@+%2y)seO41c0m0+teT-mv)SIzrX0qD ztLIH&6Rt?t<<0L+VS}zpFE_jRX*JB(k1{;l9Rbfl5r$*%S6PVfk8!$w_3ntg{Z}Qs zUb?r5CH^jLk(h-&{9XElowy;*4Q{qCLI?d&d~~_(6g;DJ#`EH9ZgAMX<-Ul#H#I3= zmQpw58UK_9)t5X!%9~j&ZLTZ5x+t%yhdf-bpTlOpBV<~R3-VlY4x3-Xb z9B9mk{$Js|W?aT(e}AqUP^(Gy=YHVS>jj??-3>^A zFR4QJuYegQ*4Q;)k4*C%I*x>Mcu~tF*H00>iNo)y4;%`!yLc#KzwVR5UWE|# zc0q{!@C6yfvIp4GV7aZFd3z+=7c93>hkM2@aOQfqV8X%vKbe9wPgzI8-|PUIiq+;qsfPK-%~e;_yquL-14JFbNNZElkCW znO+Kz3q{~FzZB{{=eY>_4i*uEawCV|D{zhv7|{-RUh#!Rj*hU7kbQV!xGx-awzRpt zK>E*HtU(Le(qP6LFb?7(%>(I2@cE?tb@p}(xmC=Y6%Y+{hi;C`@HB5XyeiH!?pSQk z!23C`jnq|io`O#zFcjgeB+PalNYakXVn4Q!8>=TW!5ewsRO5}5LvO0B7>DNEIMq@n zt$)@B)(G_R2zB(qg$-qWe6qgjizMKiZ~5QQ6RQ&OJUr z4AfmCZx-hJu!-%eD@XBOO}( zIJ3qo3a!SBWl>@BTR|sgf>w8GjW!6i-^PF!X31c?!{j#pmuG;%cTR(GXs~(=YHfp2 z`t(I91;SFE+3l8cq~EJxQ+1;ze!i5*a}4X)N*)}H(w{F%n_q#XS4_eyZqqSgEYrRH|{TpbXh4#H(w14YGd$EYd_KyM^9cDmWS#9Jrza+5yJgjEL*CEW^vr+6$ z8#!5OJ(U=6r%@dM6)&Dc?FXr}PJx&1HxS@1eeTP!qPB8Vb^kQ5kHUy-@DZTMKo?A871)bO5uA~L zD>V^T=Xj+DS*)suE*<7W;0&MTblRuj3iJ7b{349!V`n_PO%BEkabcxX;0bib42|X8 zj7Y!&33$AafCpbGuk~;y&>Iuj=!}OaaBCzaz=cgtfhX__2<%B)Ioi zOBl&=+Q|vh{7LLYJGo)x3ACBvwCRl(;pY($H5aBk1s-_s2f-t7Mk2Kw$rt$H{+ z*T9b;=MmET}-!`Vj>@*ru->+Es_B>D~7eBrcNjEVj*3=-wSdZ)kxZyUy1 zM9O86%iJJPd|POk{IeJpuhy|-2*ia%r?3Qt?~_^MC^<|DeVg@;l5hCrPvH(tYD4g7 z{N9)n!MaAvW&S!DqMQvwu88sqhAeoQHS8d_SGl&(sTE-!XTJ=|abcoUID&!3IE9%` z;Ta0?PT^grP=P`_r;yR%Z-AQgGX`A62CAhzR@>$!?^5zH|G(?NdItQGfiX?b?+;blqbmj8= zWtgMQ&KyNzj(!@%^j+jro*Fd0n(p4wMGkA%4GN2IN)0eWf=`B;JM`!XWCDx(N~LC_ zL8sjs&62vxjSRm)=ed{-9-#!pr96)fJ!`+W-#|aNWQNSA^!bFNcQ!EL=K2^c{1|5) zwe}-eaaTFAkrzj!y*-4PH=bAA7|z_g$t~qmlOkADH#wkd`Xr3_?Cf6Xsdf~m;L!RQ z)`CzokD22A8JuZzphS?M!RL(#rgoG4n%&_x=m`55MhpAVIPW>ydkosg3}@eWlV|Ez zv(_7WRhYl=!4A1rGlCZnADdnOoR67TH7g?~!#6uIwhinzj~?S9V2z-T^OA=jnUP z_{%i*JhA4~@9uu^$?S0@@TX!>GF#9?4sQM#o`l0)?etS>%;OfK)N~jt?ja{iw-cEX zCohzq#IqG~vQhdap5@2MP5kj?yVeJigt>k2!eC&ot0fO*m2q-dK-MU@r^4&h^i0>$ zi8~Yzo#mqhxn;ZbX?#lP6u5Hec%{DzYqqqP`d~~~ZKZs+K+7CljnfY;+28?k6EzB! zX08X*v;*2&5bQpDEg8-0oT!=CDTC36&z)56(;5!Jf}tzr5KCj9DA^bTPx)awOu78X z-Cm3B9DHk~{W7T9fiq6<#f_WM5_2%UKe(_NUU-XFB~`1Km40}#J)zpc*SF15coz7~ zKKEp8MQOC&jW2O?KG3H{7txxxY)BrS`)}i|S(ZNyU8oh8;R5nmw+nayrK46?Dt-BXka(IFt{|Mxh3~IV-(!a zV)fd%zAU)6Y##Uds0etlm^B?=x#W~Wmr;RZp!Q`VZ$e^ug6+xvJJ=T=gDwv}dYE@E z(@sLfcEjy+$uQ-S;hqN1gy6>8&KLTerHLLWaK*entfaTxv0f`^*`?M!&@Jh;y%r{$ zW8F-0f2sXYw!kDe92ELDH0N@7-V$ABa2O!Cbk^^VjG-$_=JiU*Z!3{;O9_8W*ZYVGde)UtEWjrd+h_@Sh!I2L{>YH<6zQQA{2f6y9zZ}%P2tq;v zccGllxVgm*AX*Y8xh&W83_dZmK59P8yR?pOk3aNJa6|WIQ;*bb8*?(c{NY`5ZfcY{ zx6epx)k|jh_DksxU(A&07moxV=!nI76Fx~>c_60<{w<2nK9F$)pIn!*Q%CArQXWgC z?(LQAIPO}P=_|h$-+WXI2LNyR|MbYu!q-bHd)9P;{Cn=?*qWQ(BYzs||9VmH7|Xg_ z$@=xH?^76?w5%S0P>oL%$asgglQ)l}P^i|qVG3*PA z+*R+x&ROIpLDMj7+>6iS;~^}JDeOd)=WDD%f_%lRJ~&!6wVAhLfILwzvEHmvqMWTx zLr?p&*J{Q*?ofMo!44gT&z(Xw_HBQ6#+ZAH_1G}{!RNkEBhZd3e@upVVR6`e;x6HF zD)hJTNo-4ty)U%Y)mbnDWGTy<1AltAhRF`NM{wDM64G3>9*ANK1mlxb+EU0r#IqXX z@$FyD^brPMV^J~8fjEOf=Z#;H*zP#*sr{FOny{IJ%sDy{Gjm= zxf>jOnm25SJYC-&H2A>wvAxr0c(mXOycz|^s0TkY760LGD!vY%7oD+n%7rlOUXpwb z1GBR)%P;d-+6|Qp4N^&`ygx_E1u%nbj$m6}lb`BC*v9d47x?qrc)6+HnDFz1!QS*FK$r!C*+$6NrMG3jt|>q&f3(SUt`Ga->&M!@sKaqb{s@dFWax-~-^J=zkn%qua|6mn6HcejA;4+jDGs|BTduSi| zRUGC=hW(XKqe~5xlQr^JlY#*&_{c3i0y4=A>s*j$Q0gKm8hRb}nU}Z~MU5Yb+RrRXb$_&|(I%z(P=5s;P z{#~!yVYWRo$7nOd&AD^*=9nk5{{tU=dAXVPOs=saM+`n1(lWr_wCBIY4q^(#-*uMU zE@&Kt>=B}Ni!Lg#*3LkEFql6}Ze|$|21?HT+Y zvv)PSF-vY5h_U742S+caHXZcf*>ZFBgPJ^m=hK@#EfZk(V5&S?-R?(`w^_lWp zdO2=ka$dc8@+mjztqgW8OKz|KkkwxxTjlTPB{Q}_PL;oe7W4N4`H2jH*u8~vU-@$& z-K_AmI&=yfZI$6?5g@uBt#XXsb5f%S{>lmdGM^kd!kHZFmm{}(ewLXdpOFSKmb^&* zmppWKGOJo7?|m-sdtV+SMZ<4OE|x!eP74>q^KSQdn6FKakkUS8$_m+!rP$UOGRaa*7VLSyV8TL8X z!|lNP{_o%WJ>>(OePp=3-X0xz_Qf|nTOU$(oGjK1`a`yn;kG*V{^95y=w{Wu@4Qjr z*ClNI!z&K1!MEXNoi1-#P@UiPKH;!5*LDk@Kj0_Mv?oQ?dD%_t!0#jdq%rtW&bcF% z9sl6+bZe=HHvF%r;i;pvTv4*`KzbN#@j3_wIgyp@csNp) zOoGD0xto&nHJqbK4*qtFvU@oEmm!;TQ`qZU0Omeawr8b%cM+zCKD$14w1!G92-7kvn|a*95+^h6N(&@PYlu#z&Aj zhcCDvMz|jBpz@;h^Niv8Lowix0Bw?9&!(D<#tQgQRkT^YQodq6EKVtd01zYe?+~nA z#n13*AzTxvOkTP0&mj0lfA?^S*X=$qtf^aA5eAut^72X^CPPknp3NP76#S(lhwVhg zpqlh@r>Qj+{S0cL6ymXrKViE=Rqay|$1Qv7Y$X-&;fB+Jg^cKV%70=A=k=^O&a(+^ z0%{@@s)(us+!zms_zWPr910!^SqH6RFU;#K_zE6WMXd?5Lbwd#Rc!$@8LWUrV>bve z%-9M3eIB^lnYI6aiTT2%LdUu0BEk0}BEho0Y7!)*!z)q&zqtceS$J+M`EL=6C0dxN zno?;0$Bg{9;?#tk0T+5AtcCG~gu0nw!Br=?SX6N=?rS;9vq?pFs8TKJ%2Nlsvt7<& z>rcpc6nHT7ig`H8qhiGjd>CMk4)udr<_>wTTx6Y+_h^S4=PT>7r{r}zAX~iM3edaD zw!5{Ei(%y0YIkeNzPS|a#=^gB>%-hm$uXh-9DVB0Zti>P$RCF&xY)@a=wKx!hq@ zY*-z(@su3Yye$Nx70j1#6ll8_&Lbgcf~^#1z=HO&Yp3KP(g!81)6ekQMJ-_J&$3Z% zT=LY>x6~X41KgTrXxMExq@LSOt~`pr!uE)-2CVTDv%2Zh;TMyN;Fk?<>ND=vJP|`@ zQ!o2)dNZMva&@uAk)f5k>-IE-JiAqn= z-R?mQ(MA_#AI_*>*_9#y*SHR(6u#KY9TQ88DVp(TR*yQmbhsK-j&vVOOi8+@Gu7y# zQa5*=Vod>9(rLL*@Bp}23HBMV+U!BPZ$fT9t~jEZWi7(NzBwZ&Nq^=u>5SZ=NzpX8 zoNcGoJR5(D@A$skAx3YC4Q`G9HMVE$o6{KE9v+*&ZaTy^&?UC*Y`|H0tj{Iz3@8_{ znocva{Ihb*OMe5!)2r;sS-HP@8DF#eC)8x8484hsUqkESf}d015BIqsXmg-p)D)jT zMdM()6>1l%Ji&H2y{=utuKgn*)@SgrdOZD2%YrhjlJxpDKQ(}v&_duwW_!-b391+p zYpgccSYZLQ-A`ctb|v;fdsag=S02j`eHXGE{bJ6(`3f2tznKmz*}ho)c9U4ixDoOZ z6P*zYSJGlTlVB^tx#sfpHp*@t_!ikegRFLw(%mclmc_bf_#{9pfCnac`YO|B7iIj} z%^iMh5Q^%4toeja6} zP%%F7h)T0CsIF42pw?(vQ038TGTdP&(*K2-d|%luWf!IQ=rLhG^7KX(Q=kf-H}_a~ zC1*6Yy%#gBRrCjlPe=R@4_na*j`OoJpz1D8thw5}@y*`mffqCja>9n3l~e2cKvK2Z z&F_y{!CARm-EhFza5g+D0lU4|Ls$FCQi?X&ZEyJ_Vz`&h4fn<`{<$^ zDb3r)N-oL~UWwbDIx762NZRt9c~39O5A(J)I_ltJGlBo~UkF`j6BU{VPBp+edk zV@32xofbiicE^~FERY!OkCBF~4zU}*^IaBtA-e~2Nf;mPlF$ct0~o+n5fYOF=WQew2H zhKg(_G1^vRJhIP;(aswEk$pgnHrHs2Y!)%vUqeCm8ZZ^BpZ3_e9|3SM8PYBrXOP7b zqm4H9B5O&E_S#s7tN}6FZo`V~Sw~S~+HqqNvYW(Uw++6pQHqpgRoA)CmVda01MA1XsQlniMH zq85FC^&~d*K5xzL$l4I2ZHOvO!2F5PPDIC%NyKO~qFu;tbr3be_alORofyLN1ZhvA zxyVY1(Y8cmk?kZ#I}^Rt8`$T>Xm6q+$UY!O+Y>#B0XB;m?ND?Hnfe+*+NG#%H-LkQ z(MClIvRGoYSJC~hz*-Wc?TXGIYe4Ll*sy3XvS-nv#I$G8I%GEmQwwR|A}hkvWJp^V zO+r>ejCL;y!nU%V7;RwWXb)@+G1|lE8nQ*iXd9z4WHX3~jf_;oHiTmc(q=|Wkqsb5 z`x(td)`b{tX*3d9b7HisQ4q3v#Ast9M>}9uQKA-TZ=-9-uB!xTd!sUh<-{61;0Ek7m~U$HL|abbXs0dlW-qzWAY!A&=K zb+1Fip~Pq-NGr0Q#As{bNyyp|qun5R59&{hHiYCos6>qRgycQwtq7&rI&ugwRl7-$wvX(H zhNp?q4w8+Kl@Oy%B%k12v7H$0BY6qg8e+7S6WJEvSXG73FM%R|PDj-6+$L9V12? zQuabtK#aDeY=LYeG1`^V9oceXv@vC6Yhd$W~3eJf8P z+f9tNuFONWp(d=@(|0YhCB$g|N)=fqF_reP9FK4!LE6T$KeD03XeZ0I$a)f^%`6pU zZHUo+miJo$^Cw1ITAo2B5u;6#)x8LBwHCEN8(XeJcAgmRZD~bTO6;Jh>Pg6U5~Ce1 z2O|5N7;SPHiR=SnxL-1KdS8YCo7Gws!|D<^b9FlV4S8{R{my~o13VekWP+a??hk^9 zB8buO+R6efkQj}wY5jrKAx5KXum0%&-wPL|r{OiIAFzwW&WS`EILaL%c2ls9H~{S? z=Aq-IdWgQ?24ZvI2l1h#7mzI>wpy?q$TETP@xP@AyaM4wGVCE(S7bwp(a`LRtS2!V zn%BhvYeS5NW-Bs(Vl*^QLM9P|p;`F<2ye9#wLoKYB(n3wXlV9DR!WS9=7&9i?Ibo> zWcmWK&xySvm?IY02gK$G=Gh6y|5*e-7VvgQFno>J4#7?#8%*q|V0p-5iD`nZMb?s7 z9X+pp6{&}FFpmEw0sAAoi4Yh$89~TS6C)>MT}xmk#K_68BHK=koQz4x z)(|5fV<56c#L&mU@jnvb41(lj_#zuajGT;zc*_hRMoz{BWL=1nld&IJb7Hg`HNV~J z5hEYteXvutsxVPvax&h+z}Jb9lQ9HYIWclFIwC71MovZ}WLt@mlkvm|Y!xx`F)krn z$Qg|Pk1-ROI-ejp86y!+ zCPq$1cVr`ok&_XEtPe4AGGt^C#K_6G(HvMHG4e5vBC8{qT1ZaD4utnwh*}^gV+FE{ z#K_5*jqC_9ax&78?IuP}MlWO=h>?%c0@)H`!pBez?g%ppl9N%{4A?|sDdH#K_4Qk8Ch8+9JC@vRGo|WVA)r zk{J0I3bF>o$j4CchX8!mOq7_Mj5Ek?5+f&LFS66b$jMlTtb`aj8CGQ5iII~r3E3KA zSO~J6#H2>N7SeDO z{hXMOV7-ui5Tc4inh3ZSC!lAMVOzmeWUmp65o{*E3xMHu9RnvdQ!*X!n%26cdS7u# zn^X9mV&CDpSljiG;rM?`z_AFca5)t)UmnoVwl}cr#GVN|1z9<Rsm( z84TH0V!ec28nRWyMgmiz0KE_{B>1KmclQAY0BEjQ{l;@*$^Y-AgVslqM|nYx6aMHu!%m`QA@Fl>QrBC%n@?jiPyLy3JZ>@FbdN$gc& zw;x#>V%vq?Ol1CosfF(d!;uIjGTbK&yCb_5Bx)g3*o7cFPwXdQCnGB*wn*5W2?n;4 z*ssEFFS5^xt>AX5VI9H`2>vMylab9LwoXLY71?XVo(Q`jWP^!)CF~s7=f@KB6kYQ* zWG#v95q5dV8mI&Vh2dI+&jLk>4+=vS*-c_?gk48ur-_{uc8!pg5Q`CZPnrPRPVAzv zyM$~FF*QLL9zeK=;7wu3kj)^LBJAcO8$;}&up5hP0I@fOos6stvAQtP2>r~BAYjdj z%@=m+mk8?-Y$^=jM^@EX)WXNYurIRf#G-^q6|YU?Iqw6RW3) z`TzU);82fXGlkc}8Dv$BL@jg{Y%j9w#4LiXLsm{~v|v_bg~X-`HVN5QVphT6!3LiH zR}o|a@+X^x#J&>jK0YH%A+}$zGssejof2#>vVO#_3$_kf2Vzx%S&;=J!|~tShnIK~ z!n$PGOt9|A9{5u&2o{3uDzO2A-N)yFW5iw&>Z?$--_tvYy0(gnH5WkZo1K|3eR`NEmKIxQYx%3B#qx77{xx>}DdHLhLPJHxgMY zu}Wdr9a%qM*zLB26IUPem>9pF z=|?PGurg#FkfHy#M8ItbgUN7>V2zN~CHAdgPtc!#;3aC|kYJaPT_yILV4gTo9V1pD z81JwOh}{E*{+}nd(v1XVF|c$+hhaIf`ho=^n-2_I^J(AbvtEJl#8SHv&zG>)o@hfU z{BnM7@a1Cxu}y-hH?X^GL-0QW9>C7XpIEtI44FjireJaauv?y@CS;jksvC`fohQ~r zu)WAiiFFZd9kQLCbpH<)Fd5sQkT~M z-V-ncVRJH+MQ3xs3s^m3eu8a6R`rsog;s*Sh3q=9Siy!MDd9P*~vVv*tf z|EYkx+ChRX$#9oot&lY!_LE?q$ewwK(%%s5c3WUKiRmBlq4gB9)5L-V%R^Q|tP3!_ z|JNeiPH>nooP-Ne))1Q^*g#~9h%FN=64?x5TLjyMUF{fR#S|a10mRNxe85z#3&Fb- zAsRL(rhm*!;)|>vF@M1xVpm(`PIrP}N0D78)=RJ*$jXTg7imQ zwqV_nts=Huun=SmiER>0MmB|5iC}ryC8rYmRWLht$^D2`Ap`%Pznkqqut60saWZz5 z!Nej2>xDgKU1EuXT|*D(K^;*GZwOX~>?*MZf^9=~j9BPN-sqPiQws>9G3D#7)ls>=|zA$CZxCpgOa6B{4` zUqU7kOB3t@ju*GwL@i7gY(KK|#H@n71tYgsN=#iXU@wF_34SeD3uK=YJ0h4nvJZ%9 zf>kyEHj9{{n%BZ{WUmpsBMPz$*V*b~8aAR9oep8AYe*9wGP2sRUJHnQf#dI^?>tRAtUg7rdHC5c*?CRht( z*NJ5d=8mkK*lNKl)j9wR34SHuab#PGrHHEDhHMqFBf@SevW3Kc6U-_Dn?mf7V6!D) zsl*zH#cOHE`bjkYw->M%!VY9;5v&EWU}6&lb4ON}m?~JM9@qoDsD)1iJC5usFdV`Q z;G|~O3qIc-!FMAzF-s%2mh#4ck!*S+w?MU5D{O!jw)60#_h#D-t-cR@*}W&_MQSsg z$5HPe1+|&3S^;Y3xVFSqTZ7s@u5EJFGC@cQFBHvYs0s%ynrlr-Q>olgLKOYD*xof@0cwxyVd*Wd+8We;Yf9x0jtoB`iKWS>#ChcErV;fT(tt!MsY3NHNiEg#c|E@ zf~G?0Gf`~D#c3~yprxW_;M!_eEf%#3Pb__%Hm)T^?I*77aSd06KH;}q3szkNo=0&d z7tgu|EI{pDuIVngB)A5(SGd;MHO@@bOk5k{qN#>d6vMbU$wf58qV^Kk{zpawQTwYd zmi`mha8)?@e3EOsUA6P5eb2ShHheb7+4;h4h~g()Jm(s44QlUk?T)LKiQ21N^Jwc* zGpVS>b1l?Wi&ar<&BYj3F%UIxu322Qs^*~GeF;lH-c>t~+Amz2>#7x?md`bYn)-a` zf!h$p&$#%VYrss@7I5vDtCot|>s-6(s>Py~z%{9zOU(o}$Jwyxv4Ql(i_O{T}nt>N?LlnQ@qSZBEDrz}g3wLe#v8cVt zHH)hjh}s~ot#ysF3g?&9XfEz{70;vS$F*awS^;X0-LdpnU9~l+{l>Ltu39E)#ax?K zlTlT;9njIB_-`&YZtrrPVo|ekE!tHJMC~1}Evt#NCeA8+WP6!wiLT+!qt@A7#ZruM z6$?;o%mZe+YHLudu7ly0yK0%JUE$hhS1lE_gIwGHTvO5Mf|ZgeZsFn{*HQ$cmdmxv zu38mNWKQRr?pK#uJCE9MuAP0Jph&L(wHVM;_?0zRaSe)1c|gwymq;^F({rt*tCot| zAFw}?X-}-H7K_?puBFu0R4jcUieGav+_e-{xW?xru1&8U5W}5EErV+xxM~HcjpEvR zS8WYyaa>dPxQdx5HshkjH8ZKG8MyX~Yq(g{D%`O2(_F&^qV^NlZoL=|W<#p*ar|2@ zu67N09<`NR^N4i06a}cg%e5lcaBEO|g=?2xwM^7ZT+{u=X9H^uK&dE(anb0SU@U4c zajk=^7KqwkGM3)rs#W3qz)7yX;;O0VQT(2ZGhM|3)IQ&0)ZXLTMprEpwO6@T z=&Gfn7SFXapuucltZUxHi}|U?yq{xHj2UOGWKb+GnoXdDQ;VW9j$0Y6YmB<660^wgxm++sDPfT*XWb_yyNqigu})RMc{~w)lUP z5VbeC*330rAZmlS)|0g7&wo`o!4%EKWY>V_QS;;4H?9d5p!QgYrT_m}I}fm^j<)Y_ zIR{t898|Cu)K$TVg4nRKy6B?V8}^nEV~m;vV>HG^0d=1hOA?*L6ix5ZBt|R|!Ga}; zVo7XKv1V878XL%d|9fWkP~PV)&vkuXm+Z{%zNgnS=giEB^0GA~JHutqm-lln$#R@r z_^`agQ6&6~%hJj_>_jpbm#r%=t3$FExok^$*<*TzGlNPUeq<%(%8$#*<6wtx$L7-p7J4m z6v-|ZQ_gHDFY83I{Umd4{l7w+wxUamh6Uo9MbKtx~HLUswTuh`i)+$db@+HJv zoP}dQZ+eO+;x-{AI;55|0%tYbtqSe*Ne;#RV&elwFiT4%%G7fl>)cXl*!o8^PHU%= zLUTP|Or)dU5^=BcIZx$rFw=cyIXL!~RXK?%o-Kw1;qD%o_w-l_!lxn%PMyBPrXrewlU-{?D#Q zU}q&8eAmgd^$UUrB$NjLxruF(OdbF@M0`dDBu!6Op-Pbeam1xD{#R>R`o4%Z32P3ey620ym}ClpEd6|V8DJxbqc z%$F=wu(iadN){!Ub27o<6803ZH?ba)jS{Rbu~w2z6YN1{usV`C1=~g}K(dvB%^-H? zipYsi1lvU&+Sw~k0e=y2Ji!A}alc@liEWbXq+ky!f_*HRSFqE>mPz(VupPwaN>=GQ z&zVn%B}rD(Dd5ctfP*D$DcI}Om3EV?hhPnfwUBItV5c!Md1^>DNwD6;Op;9#tS)uK zH!h0=rwaDKN!{it3D*d?jaaT^KM7Wo*pHI^F4!kVun#4>B-m_X|B|dwu+hX`m8{wg zo(tWHO}Z@m|CRz)C)i&qb`$K70j!f`g9LLEYbM!b!A20PCRwszorx7+5-Cm-jQLQp zuS({~bJB!J{e%XJKP6lv6c-cQDcRS8RVVhnWP1hk6@smi?3iF~Vv8j63RaWY%aZv7 zD|}4-|2PTj-{e{2d<@n{vIxNnXz*w+Sr5T7i8YoiQLy)jJtf(*f~}>oHA<=l6@iAj(@g0r>ca0| z5V>FzY{q5k|1U^5K){})cu=x2g6*a5b*p4k1$&R!=aS76Ov?v*Q?liP-8~03U$Tz{ zJ5FpWG3x&}3Al~maH+UYu(iZ`NOoGVRAQ|pyCK+f#Og?9;&Vr}FR=j0f(2_$><*5D zreVK181?_v37(a(lTdtc7VLmz{RKNsY?EXY1=~UFW653->=RV%;P=CRj~kEhO^@R(J-i1{e)mXJIM-eczktdrJ>qKZ?Ub z3q2R|MV5&3_S9&a*&dYaPq9b)Z|ZutN+$PrU!-pKbIIgh?&H*ny(yX8xBUurMDr!9 zFSc2?CN|Y6VT6FM_>h9(lF2>V&58ApOrA!>JFHfcB?-4PilJ9WGI<(N;S;a`$>h0y zt%=<^Clc(Go4(D|JDrvAC*k2<>WB_VCJ+02o!BPH{t|lQiG3{DEy0dbU$RUxpI{@1 z&6P~aN9ZZshRn~Yd!Fm(xB$?bW-h@~)$>iqno9Dr*NhbG!|4OX* zj7Xf^^ZkXB;8h9b2Jcsh{VAE;%iWOJPRZoH?LzA9zL(6uN1NCh$;5ta^%G)?B$HdO z2M~Mtj2!>vKI^9mj+2UVPjv-ieI%3Hr;k#H)m}2WRoY3cv1D>v^k`yFNhWtdcOdro zFOdrmJmUG!Oz?_?a%=Ni>R^sYCU-FpA(kbX+_7AN*w>QD-N~O&N3>cpdG6C}Vhbgc zXFT=&%LzDLLV2K5^S{7GNhZ&3G85}1nLMZI+-a~jlF2ifwh?O}nLK`p5vwGbJZk9` zV)swW@!x-VBf$%RG&sm3l%6JbP%?R3QUzjLC6h-ZT|5Q$xn%OF#T~@nluVv@^d7PK zlHqhC{`@za;8Y3aQAR_E4VO%wTGX0Y56R>SMU{!Ql1!dP^!G`yI+DqQhjtMQkW3yj zwDu&8|94J_6w4EZUMIz~lF7q^Mi4t7nLH>cn%E}EL(09z)RJnLsK zvAM)({Fev&d_piuD#|l_oWur8CeP~`O{|+_@@$?C#9Bxu&*7;~tcGOr$eo+V!Az3T z@j5jA|4Q)2Ns$ZkES)ciosvu*o0Cc`S2B4-&Uj)!g3*wBxZO z)I#Y8c0%#;-$oB(?{#>#Fg6$yoreqTZ zdym+BVpRUg0y+s!m5Pf68%@36aLL{itUIwDl6@~&6Jo6-+bJ0DIqOLFhhPQN(FI86 z1*7smMDWgWkqbpa@h4(uB?}UVzB6J6Bx@qr>%=xm)PdYOkyo06Q|y*Zeleglc(H2cLdDD88!>Z zBkg+{SlPA>|9tO*mOrA=AoY;?&H4^j1pNM@ZnLKQMIkA69#t)Xq z>+u%|zAB+SMZPz&Ns`F}pXA-L>nLOY9En?2% zKSYY~$Hzo27{vDI$;7TmR#UKs^iX+3GPwo5keY0kWOBFra$;XgCU>^;soZMG zjj%DvhHh)tDD?#q6f*l@|@9_$LldPpX>TVK2Y)=DzDwR#7!I+Dq4)b9}s zI4bA=a?A8=f_ILHT#(zNhY&j}ncNE9n%Du!hXIx6PO^>jS##ZOKQt=w#EslnLhiwePdqZlwh`^l~em`8A-&aMzQ$a@(ow ziCeLjkZK_PmMRhL?;Ia&u;BvNEj8OtHEex|w`=@D&8Te8iS9+d9RUc8Zocz&iZ3d4 zRSU~stxPv(4J=}V7(%=qkE=5o-lA=fXNTWWLc;1%Bn#fo`teoV#u~&U>;ImT7{o16 zP$<~UPv2*sFIASBa9eHL3?k0chL;0;C*BXSYcf8%@MO|506tftLMNA=EwM@w{ zE@VxXE3@$P?sDblFz#f|BRCo1cQT1W=T0UPcYr6YV4L1krc~hC-iNH|`^ra^xyAMn zD$lczS~L!3=_{0Z=GO;3VaiJ76|*|%N#@*@iq$BhRq;L)|K^vb#Tv3IzUB|(_CIX< zo5~la%`dW~w-lEt;>FC{Zz-!x!d0U?a5Vr|4$)OYS-;KkyQ+AHeYRQ|#M-~Bj5Pn= zqlmrvt`cGT;CYtwuF~H0?DOo=yZ&tb?H0VKLnX35DZ!2OytU-yK z_m}K9!woN#3&f`MMeetO~jqw%t$EQA4v@`}zw;wrTij$MHO%-qfrD5hwLzm)N*|yX@ z#)69__Yc`p3Vq3S6I^h))98R-@fCk1Px`q|YH7=bKThsZ19*gs=-wfp;Hr4m9`0AZ zY@PimHG3&SsgI3XdS4`mSI*59xF@@7iCf8c;kre$qjQ`=TbuwD1dOZS>X?vHM~*jW zNnjn2xTyWGSitcbdY3mEUxJouhTMY~c(5>#dvMaeWQ^_soN_--miC}C-1p1~91NF6 zm`fYtv{c}ZB}3)rd;mH28DanGZx2us{g7nRL6q*e@O%39@3(MQ;>vJciOH`*Bb z%rx|fRz5TIM-6gav*lb1vPIkSa7pVWj(ZT^?QnUtP1oGYcZOaw+4glxv)JsWGf}H{ zD)Ff~p}5#!4=h|s^+k$MaT?wvzaPL;Q`=cKzUHq}n5V5~)Lv@Aw{p8*R z_Zj5gwa4MQRpQR}vC{s3a;N+^?!Nk8+*$q`cU3=8+DD6Y2A7ZLf;)(4P>*N`D58Hj zTz9lhf4YNLQ3lQZ1X1~)9ESck4sU*<#J47g(ZSm(V_Xk%ZU)6_n|wUDSfVAN6}w?Y zXwQAB^l2d+{mdQZBFoSY;qLx|orq>ibnwsQP8Q$kPnBg(LmOUs(hbe1mYl#nz9{W; zD1mHbM!KODw3QDGEf9qO_bA160$tTER1Ye_|Fg?pihGph-#Z=ozlGY%;vNHVovzDZ8bLAn&YVoW>5W-6JSL7b$wP1aa}H;<4njKfh8!gNC9TEukmQv4F3Y^-e<) ziu!D?=->|wgJ&90%=YM-D7CZHRP5ABM)Bh2#^I!jHi3%aZu>L2>=E6TyR*5D+Hwkl zqGu~`dzw?Y14S)^pjLF-bOT%`xNh}w*ZY86_KL3e9YX8}rQdBi*AeV^3mPe$U(fN@ z;!^nF4$L5BdvrbS-tM{;9k_}|)DsjvAdq_Fz;udYbl?XFfGzk&sl}5-wHfK*H9fjF zdQ4u~d0LK>jFN&@P|IC!6%W95s)vXW?!*p?9)Ayw`v%3`m7Czoi-r<+`Uhf27Pz*% zPEk_f1@-gP%kk_8{?5=3;mSlsk9dg0P?}^ydQdzeM`!mPkM@8fNRLoA1V7QWLqUdh zFFNpNO4766Dvc`fzN#&CfNaILN^li4Jv74NXrMkb*$>|;EyGJx46ftoBW=;iRt2T# zBPFi>M5+gTr?iSKt$qlRlrAh3Q8ZTW5K%!>MuF>I;L7n^(wF4#l*mBx82N*K5z*N2 zof6S{A`RA$Ps@39)+;HPc}ydAg_s?4>#SsAR2w}cX1FULl$zAgRUIT zP+RP7t8jXb_7z* zgDRCM#uJD!6^i|0aAN`=ztVB}je&-KL>)K?`xoL@A@=}WrwSCTd-spwD1 z?U3Wl{iD*@oc3rs+wh|@-#ooZ5sUgs2{8|cA^s-?xA8un&Khr2V$GvMi`cUpmFFwW zrUp>)5BA4KWst@n?|wMuf8b_KH{nw0-5JAK-%U!_@U(Y_8|dzMoTC2$EjP}u4qFhv z(tI1;d-FNQcY+~MFz{4c1u&Tlo~SrnfRCsM3Dq1GZcV6)QJ9K(jQMVpnL4GLDnS3Im`AoXx%hb!CW zQ0NZyJZxCR{@$!SJ$UCk$de-!Sjbwa(?f6iY93g-5!`-184piYMsxH2S>s9~k>@HK z2{oO>LPKFe*)mxOd)drL817xswFdlY17wZ(UzqVk^If`VZ z-Y_~cMg-c1qW3^oJ`4}LiX$h#!VpLJK3vxu@4B6kF{Z*i{>&YfUGjKlb35)m$T1X~ z4O;p@Z8!v5kBkhv1!xAgRjj!#qLliK{1`ZvQ=sF zd^c!2QgIcw>k%%h4vcr*a^zg85TBE;B!uTCWGEd9Cdg;$1;vI?_#CD!C+D!?+wJ5! z+OkiD%>r8>Xb>K;)04p5FIiBYA@+=MNTNNGRo$jkcka{Db|A;xQ4ew{^0Pj`RnD_6 zrOpX7%{ps$j|_@SKb`!C-F22+SPFK?pb@iBZ%6*5m;%=Zq`p?1dqO=&#*~)nxR`ka zg3EXwpNLO;(EyhodmPp*(w`z47@raNyA^J{H_;EN+(Y*LHl?=H0&(hf#7#P~dbdFX z_o^Z^&AXACd1!I8h(N0vv>=glo-Xtbq;iT6-`^)=o;I(buefJ=!6Q=F(*DBV1&`CxK0y>gBhTfz!G?^NLbNn08izB(ZmFMo#fS`Wq@KVf(>rH6VvZ+wcK5lL`Y2W` zmpH#exgvWynP;7Iq|OaAxL?LX$|^W_-G);n)nX~g(q9pNi6xGe5YnOseXAqt!Zr{T z$p$>Fdw;+mS&4A2E%Gre^@&NuIQ5BHOIr$g>Jxag4F=Q|1>4;aN|?p_5x@%Q7hq|{ z;BJHU&a^%#kW_DM>iHd7`ls*>F;tNJJuo7Axhh4k3ZluEw)kQNa;~1Yx+q5qpK4JG zW!XmfKEDlY$TcnPbJ)mif_V+hTh`H4_3K&~4O!>wO*QOTOWokaD)`bLTCwCl8CnG= zlE{uy)zY3J`@WDRRuMrUcyLf{#OR_}Ib;8EZEJ={lS?-BuD z*8>jAN5I}d+(pe}RN-lVj3$sEPZtE~f^{Uw)CKi*!D6fgK)){$>`1==ggv`ed<|whwEYxhsR+Mxm-ffkTm!<6PT4n90DX&Y*%ju6U zr~ge^eOfek`R+Kh7JKh#6Gp0CLn92ZwaiY<4niDb4P_KYs`dXD`ICm_+&j{J$!4T! zpyw1uu8f@+GtUJVvAmti<)`~vBMf)7krBPcZ_}RQw|;l=8`4?)R_S1kVEMb0CiO!& zNc`)rmUtBZ4`^YBwXl76wIJ2kB!Y$R##H)RlL*5rHGryI0kZ8@sy}}WDCdfjwhimYb@wJArJXb*x$5Z$&9>zQ`rAyL0=2I zx(LB-->tMVkA&gIZl!j^+R%8V8R=GsX|o{(U0ADquLL9JYQ@G8tl1u=f!Wh2g7w~` zIL%4s;>`Vfl-g$Vy6_p9m-i{N%+-3poi^r}7WRxaRvTZXCw!jv8*=a#T(AF48Eak# zgZ4Y7C=()PWUlyKscvNELrN4oc2H@}J~;?e+e6CRChJG+z#*k+joAKZtRc<)O(Tz5 zz{o{MnQYo$N?kh)^cF1EkmCz-O!m2z?Lx z%A60us|C!lx?V~e&VKz%X%W8ISBPn*YuBvNE4Ct1KK_Qwfn%gv{X+t08=8M!_N;io z8k|ug`bp1JCb($i?(SjERqpH&uBtuTIM1sa$!${5@s|BM^SUOuO^wH|@C!}Y*3 z{}7JJa)*2|Ze)c7*8@j5Mqj+Rptbdl*Vut`c!4wTFf-*V_69YeV#}?7Szm0&)QIY^ z8L>MpxdL7u7LFasp2=5MnmQb05Av1wDjgUzvO>S`E1nBi+56{}W~NS$*zWVn=cZ~` z*|ZBvSJTmh?3)Y9$vP)SjjWIwaRz^l4)@@Wn4OY;AvvQ)vJWpRznHJ$mEqV+irsX6 zD*NP;5*=!6H`P$EZ!7AfA?szB@utSp;|}F$a-GcvXx+brUf>X%)x4}6&{NrSKTqYf z#Q&1YIaio^MQLdM5l)(4QDQ1hmA>x2#im|S{xo&D%zFH-Gp`QvZ(J$#dF~;Bo{W3!n|n$F zQ}nUSU+*b10!%&5u`Y#5!zxjKw=}%m{0_z--<6hZg{x{?Gp=i9YYUYe^ZV_K+2kT+ znmGc7BSp#~^XPWP?9(TB7v2Vj-=8SSHQqZ@NRza?G6GrDD7`hIffYsm^6^V!)*RH3S#>>E_91nsjZZsVm^L8c`fIN*O<7LpY@UZd4lVAMXPZ!+ z^@rzhUZKw&w3)iC1&`Aa!t7ivYhlXO=?31FjYcNhckbFUFkvEfK=~+dK3RPaK6!fW zE%a>}NP>7>u#f~1x}dKv_=*I<5YWufX;u?WmzT4XW;M>qANl8`qf4KKSWu6gwO)Ts zJ&|}4xTgbRDtlmlh9BPZ{v+P=T0E8eP`$@q+;cY99#6(?s^{kbJf?smpS$Zb^YLKp zOSWfaQ3kkf`i^ED5hiqK&KVB52d7@(K-|YieryrIqifuHj%$dU_()?h0q4;ydF5UV21b8QM+_q~ z&t4Pe-R>$Y<{^9cCnsf@+xxS&mN3Di<_(}(LL}DEnG*G~ZXGM|L zozOu2Ba$a-T)ysRtpL|_@T#bS#*ThZ&WOa;(Lu6EY)c(<7FDo|4jKzEKnL$mb@I55 z)=7%Uj%ReR;~B28PzSG0;^1u^yfK=Ck9F`1@(ek$RR^yO=imqj>M+>+75!vzf?m^G z)hP1Wah^c00qjIYwXyT%Ih4`K!?Ml@kKkp2?&UwCMm^GjU1V5rj6Z))i}u!%1NGTb z<>(zj<*0G*we(+WVY;Y3L6t?Rre|>5McAAOJ34EoC^Urqj$VADL{VgOpenHWljA{| z$aWi78*N8@OL|)Y-rC(wQ()!mSjTIUz5XV9I=V}_9P^e<(0L!M$ zxq=$W?TF`t8i;k*`mm<^wDc`xYiB0geJ%ZUvQ@b~8#cJ?N4AjTWP`^I$)@fh8+^GP zLbmn7mbQc%cycG6fxe^8EVnSCdR`DI{!9n^1=yy84FVj~0TaNhgZTm&JNpahSpjNr zplZ*TWMd&JA-?w=egg-h1K5dqS5utk7( zb+Ar=?{(muEl93T#tCqg1JwbWzueox>{k2mXknn0O&?JzY4b+WI;qWzCcjTKM$yvL zHL&@8D;`I_IUk}Qp+dSdN0Mh}$-W4|&ensCL#Y8Q*FmrVVh=O*Y*d!e z_(s>bAb_~Lk2LlRuusHvh`*uI$lM(kw1SNo_Tw=8MQ5E8-oV2E< z!?}e!S6|}Jk&}*UsP0|I!Agy$5^OTDGeY(0%z6V{DO(QE( zm=MJDu{`iZ9Sjp7g#)!YZ2n@c4zs&T4mvJsmSd|@vs_O$G|SdxQ$HXZ;%OwCQ+0DI z2K~id{Q-X{ObGZ-F-&dN!FB=ibnvMF1v+?L07EzOO??(Nf7AxS>{hGG;D=znAN9{D zf*+Pui#wn(zl|`#b^cVI?mjxGAksZf2RFuWjh8u4Pr&96Z8ywr^+U87bg@ZUi-Z$+ z|BmkX(G2W6p=zU(e9^z}(7_i19Mr*d0nTusI$-k$SPy2m+JXnDrT5Z!d#VX5?~4Oq zm-XOR6u30bbcXY`aUO#=-e6#{9qWE*4|}-%2&#kFM(9czBscog|`UckRCu2G5UISaCIUN@k_k|9u^=V z)*q+M0yN}6{TMcX6qdp4?wXI;2(^b5RrGxL8EJRA+xMTsN`~gv<{^=zC3DN~MeIwami3Wia3W`cplf_B0PVPuGxL>#BNYOQV z2_UxPkVb?6ALtsv0*K8yq){lcbE~d#A<4;eOYGGlmHk5HI9E}hM(+9xv?k2%cHx*{ z@L@{M_mR~lbM$XT-j~eLtM?b)^ZB#-d!G{Det_9sW!nn~pAWfrM4aHAv8O*H`$GpH zhy%4_DcAMLb;w*)K5EySuz>AWpCKEyYi=9NZRk|Qd013J;uI`O5eV7aK2-|C>7=stJr;JRqkr*yDUbl7)$I(ah> z7+jJwmHJT(mQJPAp#QI8=h=Z6G!iC?u!uo-9b}2lcMu0^WU0>g7}_(I^tf+YdN(Ze zx>c*N@t)0@CH7=d20g3$=S1TL5L>e-$C3na>Kgq75c{-9qpbk%>KcVZxgTQJ7HM1% z;3pBu-(W-4a`L9R85VR8E~JYF%QRYY{I`n$&xu*wF8y)6zW^l<^i4$_EP0?06rkjR z{;rrqhzEKn#q5+IB~SDtMFlB&qJNmk6C)qjFTmz+7Mtw6SJ{hr&?gA?EOGu3<)=6+ zhyrLNTB0~Mhd`nzuthhWe0SafM8NOi>S5$z$Sd4KEQs*D_+4ZxJiVZ2@E@WM-P1u} zcOJ4uX3Ocgv}rIwlJdu{TZpH ziF8s{hH!*vuhX4tqKDZe0JXnnBHq91Do;cR=XGEg-~k8fpIu9WoC>qut#;=@V!edt z)>FOwZKk0xA&?j-A|7pYkllrVGb>gnUvQGuUkA$s7^8z(0!-Dx7y(|>K~Dh|>!5`I zt2t1EVe{vffz0yxGXoP9IVEh|N;h_BN5*pyc&2s645e!ip*!Q|d5KC`=wRwaG8u(g62YCWC)4_w@T%&^y&I%B(gFOO_ z(m`@(?&L)d)N!!!e4z60!!3Lw)}bps3k}0GkCqso$1<|3kO*x%LE5R z0!mf|z7n8h5nzb`AM3GcE>iSUZ{Gh>i~L@+rs`*@K@vz8V6X0mrq#%nKXl;6suI8z z9lR{SeGb&6eM`!EgM$XFsaWNr0c$Q&;#P;k7Uy(b!=RP62peP&Y*q!wRCr0IP?!*l zFy8SHh!mjV5DJt)tN`~hc5ndgBQR&BRS|xu2`B^F_-A+J%iT)iJx$g~F|Q|APIc{o z;Rf$ato|ph$XXzhf<&zlX&8)=3}KO`N~4;0CcXjD-xX!uy5w(YwJ!7M_Q7!D*KY;0 z_dRU0E72b!20-pzrVZjrPVBKOd5MzM(65jc!%b=*Oxko0VfHp52mV*rS&jVD2E?y5 zdSdSkyj3gZpImT7f~s*%wGNd0{sqA7^tK`wx`)P69ImMQg@)5d$-;$Bk$~&%W9`~DivNcCj}TzF7yZph3RGY!#okuS89H{B{Fsp@d@HJ|VKZ2{N z79B!=QKEnAg1;G>g#OE7a>Zl(>OknPETi93U*8(-6zgG)F?;g|kc%G1n}+RkB>`L% ztCL8 z_mLO!l1e7u`f&M8lK)y(-m{c@C;9(DS$R#rJS&`=)JZZzPU_iuk&AKULN5Yw5GAFc zf^aZ*Oi2zU!R!q!qyI>}5#SMYQpb1KQzij_`sGseo9PkiwN&n?C`fvO7k)8*Xo}OhRkXB0mH#x7);-i~;u?{-Tggc%fkk z8`eavZax-J%wA}s9x!h(y~H|N)kda^Kd{kOwdqq`Ob*xlDao}Qdjlpsj%CZNYVGiK zTkL%B^>$hN#J9yT2JzXC&lAL}{q;@Z`zN2_(};1qSe{jF7Miq?e>Tx^Z%+$-b?d1C zAtefpa`ag5=AT)OrmDkKyn#(yw3!VZ!6pp-|LP`(J8-Q6qD9+Q(?&9>kny@lP3p&ko% z;SgaLhpnnD@#+Tt$c{ep+EjD)Q`0wo3t@+nmw37*dnoKdqc*?r)bJ!+x! z#AhA&LS{RXh`G*gU12+-Y4C0=v7-nK-cL*HR13Xt>vr2Vu22tQ@&Ihx$VYEriJf~` zgzvYcoO^H$_APnCQ2CE&#wN1%XEs9Zw|~e#Q!zMV9wb-KId5`k>koU^f6vCZRF{~V zrqCxkwJo#WqR&9m@>rz^wf(3uZ3i2+Vx3of54B?u=D(g=-=dwkyV@Y~{PI1S+qHuk z&Bn9+Q!Z*oqK|~A4$M2S>}T*8KH|cPBux8$bt^S^aCVMpv7^WOze2=Dj+4>zU+SZ%UD;aJ z3i_Cc`af45`jb{_jjFH0kAm;0YHdXk`3knP2d&gp)5q_yd9BrkHCBv6ku19B?~h)c ziLCs64f~8q9Oawqi} z)5R}Y-_B}S=M{JH4b)jIN@e-#JLs#q^olMWPvw0aQn3}In_FE| z>(&&c58mT&to4IKO5kszQ~acyq=cKF=!u) z>j5tTZ|EwvtSi#7a5}Gt>~dGNg=u>htJ+QNQR8{Dc#1oW8t%xLXAO$F@A<>cp6{l1 z?eO`>EyV}w4%$M66Ig~JGOk^oac>u*MMt{Te@t+URm$rqOuyraZg!@d+SI($G@Pm3 z)p@4(-eRfU)h4EZmF!FUJ->wg-d$~J{?#~~6?Ip;n_gPNy2h%_Oe5c7&&H}BnR2%= zi%tE^G{L~u+tkM9Z^DY%F&i>|oq<*8p*Ap&00`@$c4?dP5;E-341b0hX7&+d3 zC32igAM4U7l;iCevv+!^Kbd0Jvwl6{Rn_LjYbi{)T zrs)D6%ikdIWG>e~P^*`7fjW&p(R^kp_yTZ6)O~MEsvH+tpk005bUcmCwySGebxxx% zTD4W#G@@c_Lt>op+c zMqN1uhzO`W0$h}xT(CElO!SZ9zMsdv3&JazK<)DE`2gAAL<-V z5|zC;bqdt!+s7?=bC88!$NP(~Hr1tCh@XE-$=%nJUuqZPrWt%sONl7)!ZQm&>2qGL z{~UtKLM37!^ieB1gAiFXFXtkj7nHM}SLSgu6@uqEkw-lLMhnifWk5;Zd3p*?8Sd!- z&ZEA9qTau3)JHiH7yXfgW>pT>w6FT~vszkxVWz90kbg~WUYVw-#M zK!CWY`zxq@e~E;OJcCgrfwai;3mEmt_Rh)HAZ_sjvZhtR-+1@>MD}}MwN`*5 zW{TMzTRJ2owdIS{lXBiS0d z0|LVxtt#ylt@{RY>Uq00)No);XNTEt4U2zzaV#{oC0{~|_Ri4On(RB;ICc4|mIU?_ z`1OvKXt$2B+|fqnBx$YGqPJV(c$!{lv3ImF>J8ZV9-M?I4@GxzX9#R=7K)BK-pCT+ zKTn_oXEeAN<%za%CyL&YI?r0mkc^#`c55wmEDe|H&v5KwgpN0wD~g#xg3IUGhM5zuY_`RU z)f)k+D7jMQhIj-~QC-Fy#TyZW@KJc)aQu3*P~Wx$%|#tKr`M5vG&uc?%7k%)eb`Tp zGJl=FCi6%?bd4tFVv7f=v7_28M2@46DOquoU(#5A%!Yg0gx+i%hOw?8rb+@YGY;dwS=jx;!w4@8H|k{ zrZ!>2hpM6GMUJU#&QLXs<4=dGO@db;YFkjv3|s%0GSzVR^Ub7kdZ;?F;ZjHnK6Idl zI`$gYz(OKJ!BXrer;y0kUezf`2R?761BDze)8^j}PGuX1sckxwfMQ|rUPIyV_-ft| zWWIpM0X=u-qeZT;4ILKmx;Ml@hrG~{Q=zQ?z^XN!4m?l}3(-rzo?J=GOw9*(#i3iDSk(@@*qfzEtBu;LG$yj}U zmeO9&!sn^h?hZwdA!b`C&_LHmY&2u9sEuNFzl37Nb10rr60AW9s8Sa1SV{!yl&@f$ z-nIRINkc_<>byFolaN9-o`hCNg8MC!CO1I}8p;&BJ*7+v^yrjML)fvI|F<--nTcu_ zK8;9T*K%pymq2TYR|vZ4{{i2C{Tx%#Nn{&C?JHJn+RD-L@ABOK&Jd zS!#R@33F=9-W;MnB+o=1OuN6+I7EE6U)$mO)$_wNBon3GLVmi>r+=vzO#F*|{_Q?} zwojUig=X7Xe|kPh#<*JM)BU~w=F@$Q_WS`2lMt3aQC-QZj#FD0y{yYPwNB+ts542a z#Z_@i8k;yy4Ib1TbvC2d<0RgZe+>%`K}()z$A^gSblQKwCpGBl7J4zPBxvieIKp=( z#9Yu)mq9l^{1}c^vt^-rIcGI5NJ5d?S=KmpuIZ7HbsDc)tMWaeQ_kPc^$E$5CQ^+Eki-gPoyc;Npf5UMRAQo)msS=d+Ed;)8;lbS01z}fE%Zic; zeU*~*4X13`MD=NNbdisJ+u^CE?4?QSR`a6^gECu9R(BXHXwwm=nRD5_XVfvKq=lJ- zpH&|jrw*A5zyIAf+6j6~fZ09Ca#u>j zpg>Epw14O(7=Cl`zsld-JO<{VD(B|4WUml&8lSI3r~-{CC6>)uqs+kb^Dcz(1L#HMV%y zecq854T*RC!EV2z)~s+n*<#xpXJAhytF@hPBM14RhhK2R{p89voMu6*nl@KJKeX~d zvM=R!F%DHCKuynu&41UEdtv;FlPbwEv_#f6YJY(Wn*4NBwk>AgtCd^_?YOnBPhp`i zHOIIFzN8l57=S%S2-z3OYFOwf(VJVm1Ccl}4jn=VrO&O{_!(-wx>2aj3G^f~#prn! zeQIv%X3RQ_o=1}k+1R%OYP0n-)S9N%)7ZWlc+Olljoq4|##Gx?xmarANQ0Xm>$F1F zd8XQ+;alKQ*#&3hY=)W*chT zz62)LH^^9z<-ewmHMbs9$YSTHt;`3XD`YRtQCk~lu#e`bPuI$;Pd&~rR+>g{4Mq0j zB5%((NcyEYSoE90!sn_@%o8RQW)7IEMg%mvh}wYU;ds(moJ)d98kWv|Ck6b(Q*Bfs z`yfSKV_u~evrY@tJ~bUGt}>kL9(dGbaHn=mH}i9EzM9G2TcGwfUsa0PGYRgNO_4VS+YXxld2)snvi^(IwZ?bYjYVn;vvpKqX5Gc=I3vK^C29(O z3YVxe%tuBPvKL)yvZ+N8yNDO-P2RzjwjUl|;@!Q262h}%_ROD{FgZWLwbwEEIu^Y= z?%{=Ofu&C>pL>3lw*P8+sz_S7}2Ii$auBa`} zgZqr3-x)Hd4a{@6Q?p@pbWYuepO^c)heYDc()6)MW{rzm(#nzgdXOQxhQs}Om~TiZ z8tE2y&q#VoTSjimIDKV4f~b+vCoknu#n~@sB#`%g@*Eihu?+AQ1%b1P!V13Oy$t(n zRfTW`;Dy!pfZ7AbppKQqbhOKZIjC){Z5+~OM=%*ZWA^sM7-TTy_UwqkVQ0aPl7SC7 z!@H~BOXi)-Hd}2KnxNV9X=kHm_h9M-o5yqDGrpe{hmU!7e8!f~R>O@O*`O-HHCf(l z^l5Ph&jixI!=)JuJ4@_Vv*%D2H6H;ycQDoE7CzO+a_tYLrN{hIns`I_c4=WIgsz?Z zF-^Qp(3a7M?1$@o44Fs6<-Eyn#LjFdjwdJN+c}E(b@nWK9R_{XAX{p-DY#CI@ zW-nEL48C~tiLQfA$LHxWu#k1lQ0q1Q2@>=%=Sp>wp zF1}1xV8Cuu%`bgeR-Re`K6asHRZDED%87-iL5MC@Rd=bJQwSeJfyRj&Q$;`qrUoA@fuVh%=vS=VOu8 z0~(mKU>Hh45H#z~|%Mj7EHRd5`10`4*nOUv$O# zl)i|7%t))>z{+M%oQ z5HdpjA$(j`kgN+nDk~TrTF7?S47lv%-hEb9IKH9ZyRXX%dg+3%$_gSN;3vYOZfk$Y$0K z7$H)#v8>Rh`~O2(L6|PsP*$Mnf=*=x_v`zk8dX+sMhKj!+%3yWcI!@_E-Uy(7xdKy zJg45&1*3HVFXcH9B)A@X$KjhC&zR=^sQgi)6-w1@i0=Nk5(x=9)h}e1>jX^f!^?b4 zS>eule*aim!B@Iqby>j*2w48RflZBvS-_gW$UXsE(4X)j(AF_$*6D&AOpv#5d(1)G z(0EtjFq`W(=I2L}Tl1H|H88~!uY+lDz*#D$b^(RK2Y&`1XxxaSygS^yi6|Y2`=-urZNjTs-K6SUTpbCG+ z!AA}8F@GgDx5b>)7SRmEb=K}W1m9cM@pO+X_QiJGlYGiczVd{R<|8OAQTZcughvrO zS)k(m2Vsgi1NP@1&6tj`=z*c2D$Sbcp%2dxyKp9YL2@P!$8*Mx`@~~TzSr4@83-GFfHv(5aa{07Fpn}hG3)aBg&pP;gz;2&r6T;QAY}X z;sHcm_sj+Nwg)sLW~|#X%Oz8%C(OFs;x(`BQOtr?SbCX$#x0 zF5n*6An>%*{L-+p(k5ylYuPHGC}=3Y#gcDP&Uv0|Sj;-M4me{zZYX56A_E$m?^MPV zA~K-8d4J@S%vU1=uB)cno7l7M0|uHG2Nbf+?E|)%YkyqGUhNPt-TdW8h3xMR0drX7 zGQ4gGa=6gzvHr`{+BN#3R;M4?OZ5Q-+8;K&(iqC#SfR+pNRd;R9hc*+&8 zKjOD@b%P-#-n@PS+rCVV9=;Tb^1rrt7vlfuwFS<}`R(E3fAiLYjZ08#m}9H9WaF3P z`=9TF=#_*66^LF*tb?u0D~YZU;FSc$6t5&E&?||UWSnZxUr7w5R}zbVLye_Z5}3*J zR}w*XS0omsu#D@#(UXDv=t;b$WeYy963p%{S0n3}c_9Jczr_m*_ZTal>6dS)#9~*d z9h?boN5<^ZdY^Ee!q*IV?Nc@Ugw1#sZz?EE?*mMCvG8_~zX3s&%;;kAnD0MEOu4+^ z2qqfzq9~o_#r*08dLcp0*VDy>N^*-{S~ctAZwLH^L^N^>Pxt&ApslP%P0O(QdxEik zW5=0czf~88`k9i1{1}|Mq^704(VU+)ljYR1Oil=^jf@<#$F3#b!T&v4SVV3uki=a$ z!%Pc1Y176$v}l-Tl0q=d7Nmup(89Ll5gd~PPgkzs+9$QJ-(cZyws3eFv(~X3 zHq{Kud{D>oozc?89)3_ud&|tet!J^CR-4(8dY0a83{_{)EE;DGCb;hK70+Gt;yui> zHSvirA;WH+;1`{x$@Zs-PgvjjmIiUvQJ>wB*vE7o$FYX;121{UI~nKYKa)0-Z`e$S zP7I{3KTsz^->B|g0U$cq7_YXpwuxocw}d)#5niM#Pg@oSu{|n3Jn!&BAgk+E&O^oS zddAw8A3gKW~K3Nr-i4%mh&Wt9>oUOmrSz`u=#4*Ql9u`<&lG2 zyR|>wGfG8L>Q8<^1pzp>^6|lj3^S+ZSHPnn51qcP8)L2K3gZ!vbKOG|(K7m@Z6QY@ zkyF;TZYPqHdS1h!mac=ywmFI|^_mf4D~}M;U`;|6PoiadD*r9WBtt3Kr@CJsTj443TQ}Z@S)w4Q4)At!w=x4N;1%aK*Fek423>h zk=ra->7u0{VcSD3&7G0j@&LGWB;KuGc z@A@O^e$JzYu6KY?&Bm{D;yiVYhjJg=#6ChV`bZ{*K8-2@u^0;hduFm zafz_c#)n)UxOXw^rJ_M!gn2$jkARnESQ(3V`DpDU%7^<}7F>JCn_sxYoo4NbQgFE1 zTD7o2XpLv^p=CYZ-#J|GTRl+2=aymdp;)Wda!*;8I9zGgb%-aLsx4B>y?Tb9YdA61 zrsd`>(K6xFP*%0ErJgezN?K-5lNL5-rj~mJdbhOPy=NTmjn+tnsO3Ibk_5kYl3G}y z17GUpo;sstez_B~CoT6e{CY1NMw=Fvw;3H20?f@lqvig&L<{>z%k{!|8^+(X+{{?{xW>;Zn-+WtnmBr%oo-@j=>)q5 zm4{l$F&Iz4vrBd@1b&CWqu@f=5h4;9g6=u|8S4ZHc4^_s)|rqzfaDQEg`byUe0Lo( z7M`HP4nCrVFXijX6dSlqv!-xiI0if|%taP0Y{3cx%dlGN#Q%^Ddz_YgZ3+JTg>qY& z4}cJI;Vti}@q0nbU3m-m42tC=GAuy_*h?-RoS_uJu!o(uT6(iqO)ZTTgfuX-e^bjK z6Eb?tUx>p3;c4P;Fu$7u547-#I3E*3%pT>h=h-mDk(u@P27CAcTrq?S?>cPb-3a=L zB)e;=^$2P0i^>b%x8O01DXB+%haYNbyUpy67M5mC67yb?I!Fr^X|0WRQuh&Wyp`m7 z+e!l~`Z9Ea39hRc6XWScpeTROpM9y9Op`jKkl@0%h(6DD2pkang%oe?4j&5ihar!W zdKI6%wm}QFyD{Z=;wvI8a}Rp;fxM4L?-Z(K?!r%`97Ek{Y5DL1$2HnB! zd>|b-|0(Zh04rjC*OpVSfF}{hq%Efi!|6ur4uoZ2@+tqd`J5P4i+r>8^HDX;ngwC$ zfpsG%+(S9IVs$!&lu|ENppPYx;FxLnnnet&7FR7TW3U)fXSzjN{Nt&6o;4P`{g%+p zQg$u#8EY)kGr@^bVgk>3Ds8F^G`PM89Wl5D>Jx?kGQ5haReFS-X0=e4Om&6^hIRCd zan{||>TrvOMpY?8S&|^9SZ6)X)$ye(5k_0D9Bto#0HZCHwYKab=CBxT2X;?xMB^F; zw_qz(y=)%TMr#UwspdK0h{B?A2NQ2G5FskmLbUW__>1G;Y3%ZU-p`(Hjj;x+rDcZX zG@cV>M`bgO%6h)h#KijzMo3qV9F(K>$q{*i_YMDuJOKe3ymL#9$UNpa-5inSGfdu; zB5_Ng0|WBras%?nvIFu$8jx2OJoc?%p^=tEV@)Fd(n+IVln>oa{Q*y&rnj~sql@s1NqvG7X zzfB|X3*Q6it1kGkIJV{tJm~Mm3x=>eIJez`-^Y&BoX{THrZi<>F!DKdXXst6#l9XI zI~!%WVSL0Iwy}g%E<$Kk=hATYm|bsUY3t`tIHzIpF}oUNX~Le3wp8^Ci@ER?7qV!} z)3qM)Xpm3$^Z>c^RJ5fRTs3NI2{Fxm$hx$(*vz3dXJn?dwe&Lv8xd(tQhAdMM9E}% zYRq8g+gVx!AFfd%`Isc3kTh%$iLsPKxCxoT#zNBca7cMK0&K<88E?Z`2B?199$o1f zcE7!)tNF7BPqX$NEH4^svrju%T8wz=!P7Xt)v~)K zs;+;yz1?MDk2sHCyL%~bZFDYDkHpNT9W7XQ{nknkPItAc8?7|J!Z6P|lX4Qxo_-Rn z1L5#zQV?%tC28i2ctO)dRObI(`^?~_p7(t}|DPX+ zbI!i5z4lsbuf6u(Yi~Qi?!H^R`4*Ij;*C^19%^MqwQ3^)A{hxP$ru6BxRforTf8^! zcPs(Ga%l5BFXqsl1p5LL(=W`oh<9t>U>1wGpx68a)C&=iiitB7ZTRD;iov*JN0ZrU zi`cuD2IeG+8e9{Ox~-aC5U>_W(qyr_{fL^U-y%fNz!ty=N?Cfnp=Rm2)O21A>N?jH zrIy!qwTU~z2G&-XVkk^P5FI-~&aR71vEjFcrg$D{ysscl6#!e>UUKSU;+8I#Webw5lm|C;i!geGxnG<9Veqzfjos zER-o0>3Zy9#Y4oKIs|vZFoF8^uxUfY8#=5Ce>U<@9rhgEGA}5BaDmeG2kBu4 zpp}{TO8x~E2!sMxfn{9CKJ}Z_;|e1WFtZW zU$7i`Dc>PzS5Wzv(>H-zPDVk=zp{?LNnag@{D8TnSxt~Mf@`^(kgfir2J2ry(dAOo zSkpD*q@)$5JgPNmwaLPBCxN{1QZ*|}ERC`Qge^#l0TasKcl1RSFE*8c15hk#1zkhO zM9hw#30{J8v8e(jpb1By*ZO}_gJ|-K)=n^`BHwYmjWt;)3F*J*QO?}++kKbOmtvkfHKE{<`A@tE5t~?y7*Z?7;8)6>2*F5_;j~)o~d7?^6i~SZMMh zz%Kb`8qqkk`=Jt4KeL(VH-9^hx7hzGMN-{$Xni8yCI3SeAoR&4NSjJ=XzV7$zeTC)KpYVB#h!L2uJ8y+{Tc1O+8Z?CJZ&UUp(2 zw4+9XH7*qeV9wJ1NsV8vb_Uf1xYEtSKidl{-k@PYOO>GT@mp+K1R?;O{!;|~QcjNeI!^#yK*;Zsc|~LZXj7qR z=Gh_Hk(HWqf#4=6+lUdV1!giOtPW>Gp>@cCMBfAZ3prT;FOZ3ZS1Joa0Am1+L!fiX ztd0~Y?;HsE009z2S`ZnE%;R+8&6Dpp?$qt36 zXe1O-8DLeae-_v90RARw1D8d!xUNU(Q+YZVn<*aT0VAtq4u4W>XK^Z^@I(p+?eJtO zJnbO_)K)6a2pXbHYUd&8(;O-z2cFBiO~8UG0Cc0p{Ut&t9~pwURTkTV07RH0_BZ*L_< zmT zT|$Y_FnE`OkiG{{`%&Uvl(>Z;TpFg4dPHs`m{K{Q{tHAUb`sc}_tY6VKCo5-B0vd2 zLdpcLZa^6$8!0j;A~S(+d#*r{r zrC5}fhg`rd_3>88Z09N_?`aIspcA4~$-kMJt}+dECr1iKrp-VBnfnn%cmU``&zm9J zDMlS4DUy(bNSGIQfsA$$qPG%EDIuDJ@z6Y_? z5${Djq9J_&%p(5b_w$h@k%Cc=U(Hd1IG_p2A4UwG&I}v0syiG)vh@V6?RQUwujZf?&RVW|RhcPgrn}5RZv=zG3Qqv@!lPl1VnGk~nV@=|<7G_(_VXzUMVq-AP8IM#*z%8u^E9EsKahMO_5q`il8PvT;RvD{DJnow z5L!A7dv>(gLBHvjWcJc%@!p|eU8Jd_Zf>MBhNpfZLkoIu647No)Tn$KDLOyE!^aS1 zBJF0%@MAezFF`(7SeJY;9$E>_IG_hW(AV?&Do_SmN1|;#<$wgFi=^sMXe|;zPNI|0 zR7g;N1EdQkD?p8!IJ`vrb23N~?2T}=*{8DE87gcW!Moa2LOD=sz8&1P!nB-!)^as? zeL42$ms1JqC_{55Xu+iFg11Q6_Iiq9DFCarpc3>nr9q4;^>~yzrQzc<)rT~k1;=3F z7t1ZH`FsJn>|C1;D{5*TC^8T5@FF>|sT?}Bx_-xhLfxE^G3TIC^J)2I8xqb{ryd0C zm`0*nBL|2wn>T<9)HVR*exLC&w*HK~#95SCosOxkP=|cpiZklW@C=DL^aIKz=+S20 z&j1OcdNrTwTm;t}iNl=Iyqhwr{Kq8#EoJ2c(KQIKMuGOui3Ci3HInk8RAg?aEMb|F zk2MPOZhQ|uy_ed)3vgpaXiQ6_6hy1c)d-dh*9pSlWuh9IZt(o*27m^#YES{n!@WCgmd3;-qg=e6ww8(c!4Ay6^;ap zXw@$6cPSQ=YP%{x5$dIxM^a&(6uVoB!x|E)y~9g@zjF|#qd-tYo4Gb_{u5#AIk7K7 znN$`S5>gzKVblbH8;8}tr0L6nHmu*FW2b=S& zUJ{jx7z%RV&rYWc$@cXXj#fQiA1V4gZIf%eG}qU(SfY*e{A_E}f>oNy*j%$?Qe<<@ zm(OA2)+b+4gPo{@wnqIwwAFq$PGJ0RjqRzX`G06@LQP35T223IN}}*a_*W{7I@Tpa zxGM91M}n6eGAz3s2@Afwhy*t7PT^nLe=`4_Lh`7+>#$KvspiKivom%SeMZNA{NJ?F zmVWBw@Lfl9!v`jt-0J2T>g*+S*y%%@{lNAd)#u4lhL`pNx1!nV@ovd^ zH^Tq^h_|iAi@4CG$Gn66VaI4+u?sX&1^k$J@#^4itZ}J03pDU>_NYZL>w0cribbfq zx$zNn*0wVdian74ik-NmHMELHeAgbahx{^(TEfa@;lXo~W zN2@WIZyE_KVt@PFDCVS;(zz1?a66ZQo}9_uZ_wzBGXfp18_BNE6cRHkzb2Fn-q(jx zY)B0J4xX9u@-!`UJ;|9tof5f*Iqm?ZaSvXBN8s*nm_1WSw-?ig2H3-S49<`3$p=3~ zQKub*$UXts%)_;ZCM_xsSR8Ie)^W! zQ}*PTFy<~hh26o}BlNf_rqC))ys@>mdW*Z1uIU9!gWkQNDSz602I1@Bx7s~u;%WGg?icMlrkQz=L(GUcd66`9i4 zlHf!kXK34J;xG@ci>Cm5SY*%h$Jv2{hTHAWfsSDCL%>xZQ4f?* z!B_;((jL$!nBUwZ(mOt^JjX~D35zvO#C(RBEGK-KWp<|K zp2=3~aWD2C(!|~}Zk8{UrHS=e8MPqbiMnhoi5B)oP_R(ii)&mb-qTnpJ=Y-O>j++U zhzPomJ$}eAYuL6;1myVL=)G|@)P+0nb*NB!Vh@GvE|ew?UPwt~Y3Dh7P?CeaUJZvF zM#yOji7Vff%ru9KgqC<+-CPScF9iN8~jVYC|bWOJd^cAQGSodU9?#{k{V^M%sE ze*I9)I|0x|48=%Ko<^!bq4by^@5k_d+m6~~_DcWzEr))X6y8n(e4IQm+8?I{fw&N=!a% zxb_~Y>uCC}2d--irEzsq*NI+)HA-FYYqk!=_T9;gsZDv*Cd;L5`mjT|P3N%7vVtu? zjHArBqc23HWxSlUu53m&u1fiP(xNL>IBEHTF=#)$5!c5- z!V0T9)5!tc!PDUQWyv<$N3#429B^O)__4qZUK$sKXBa|C#Kr6a_Z{DO?1| z67$J+P^(3HN0kM!hziqPS8NYYgVPsmkC+$*^!T*s0bqYTyxxqf$I|*sMyYG;OXxqN zH3Nk8!tQp$x{O(lpd8LD)tp&Wp~Z&)wIl51MzlayHec+C!_*V_RqF}S__g78L3Xr; ziuXkjwS^=6V9VtQhugA91()G*Fz#*OniwUVAp9g&XooDKMPwHzrIq99v)He2h<$=FJA_zEd)6}L&w^`J{+ zdhBoH@~4R6%;N>(xLn?@_C_@C4Difu&ODHU_dqaL8%b1yzV>1#-ozIg@wK-Wf1ax& zp=@Uzk3+aEuTEy^#|;bgad>GsZm@RU>WfH9lwLu<81r!@_SWu~a?@igCnj zX36<2B*wI>W$+o!^5^JNtHmsVdQKzOUK2TlCF#E3x*2=ECKd}ww%0Zykj zqa8WZshN8>(x2}!nE0fw_NY5K5kk6+pS**JaME9Z9)+?%gcE|daUw*IUCNm&PyIJh zpu1EQT$BXo2FE=TPpY;$SYxo=Zr-+`=oqlJa%`7s`)oFWaul zns(AxPk3823XC_EU0fl5ralBZ*WstNmUo0Zb<(_~%Hdi^NbApxrbq!l1AbAGb9^{f z=LqTinVl%MBYqw56D8-caID@D()%+dinVvapU(KjNY0dSbd)0$<=KSOI6?-0W_OCc8oxOF;3upZnh${`I6{IyvnRz~gI^E);w2|-<)heWM=08#*_&do z#jlsO+&(Npa;^wRi;j@!&+JRl*WuR(zeLG7KOEb^5$fR2yn$k`$FCoLCODTtu^k<3BMchODVEZOpGHGU20y$LUJNiNu*qr!l^{@rgqLWvnSH57kdPB8q8na1;O=tPtVU3W z^UAy9rIX~mhTZ%puY;%|hH~`8OJ~XX6MI&TAYi&sL~p!ElJi~mxf&tj8-~});eGJ} zXFlWD5jBFy<|>M~0WaMo=XEUk46lP|DwZOW@e(IFe`8On5!9}$DdJ|lbeEhTu}=|k z6>yF3c#60cFFlGTutR6yB-0Th(z}Mj@4!pXqFd-SJ?rWETzbinpFB&wpXG_U6Jz+D zoN2eILpU4W0?GdxoQq%4Lu*xk;c?dcH@lJ$iyR?Qu*w@M+eywv;ZT()I#XJ3*{k7Dl@~Y@b}5=lxmEJ- zO6iP6P>m~xt0b>-V$lc+QAs_H(!>^JCR30~<0?ZIrBaAW+dU{ze9^TOLL~k6Swlbj z5S*000%10I(T|MaNZSRN*2>rzjbS{B6e?1r&<9U%%9XWeNwd1N8!%{MV6Rn0r#k78 zoWI~y-xZa-42g#!I4RO604*ZZ2tMK%Fv_;Dj6qkhX|0C%PD?L}B(?|v_w$J-G61K< zGwsrg3LydqT^EM)0G-4=?IMhl5JiKK>5^so1U6aBIn+ZIcM1UJSSkYUzYy-FE|6Hr z6P8xP5-1VzXm82+V>pQsQVSvN5{r_M%U-6F6{PXy@gFdc7R3g6Y@xXin#;QB<%fK&Ps+`ixQa*X$<*46?^W#^bemgNl z#b0$O8mS2HA<|(3mlrer%3|#4!M$o1{#EU!f}&^`#qR=s=K(4yeyWzeJNPg({Qn(* z;LAt`61k#$8UR6wcG4&>tAvl)dxJC1L@Y`F0}bo`M;dOs2rp>a8*GFE4?r%%nEg0L zTP;CCfDq}n5!!wW>M(H(EBOBd0RJZ@3ihN)C`^I+xvdvHg~Y+gkmfZ7L-5R_+8!3S z+aA0PuzyXN!%aC5c&zbt!=xTo`>c$o;=1n z7qK~S7}Brr1hbCS9o`t|`VGu`Clpq9lu4=-ZJw!G$Jr=p&SrM>4LDT1b6GO$KG!fq zS9lX!FxN0apYDE^Mb9%7=_k3Lt(rd1;MD1deU@BhSYXJD*1hls8~vW)DZLdZh&Q}v zc+#Nn{cdtq>W7BU1^t8BPqD_&44>;iLB@)u2Ctw$KPS2B!LJR!_t4)z<*BMc-y4$j z`a_eG+4ws6*H|zmnU&QUw(A@Jm{c{k-f)9f|6);cRq1v^vtB=cQZjpSm%*u*CMD0` zZ5W|nIWf6v^lpPQS`Xy0Uw$zh)&C1XY~5#=8D&pRg!!fzQ*_mQNPfmGkZsrBo+uUVz z+`WlOLxlVEZv&jih6n+z{sUklCrgOeeWGE7S;E8Oy_!&H-M0wclqKAz8=g6TsF18* zi|?C;3d6hC$v9N22;`WH76^hZu(1Z3hOjq=3eP2s!9|>&sCQrk&^Q`flKi#;|G=^e zd`YvWv&4IZXS4=3`ySz4ed?Ixs+(=XT&=c%ZO9gG(EU5ej%Eu9I!BOo8V2L^mmW5F zn2@NO<6(~u6Rzp;yyrs5J#x7_cV(^;$Whv?$|3kH4UF|vy*^C%)W9rx!nIiPGFr~t z903cKc=ljpbACGhSQ2OlbDjl%$L_(Oe5^;2>$JRh{FyWWN%!N$mWZ9hSV}rZDe5VQ z%}6aMAhH}(MB6> z_a2M4F^90g^vH79F!C`o9&?;ZGa;_)Gb;el5?cl!Fh2!<@=PdT2NivglHgpQ`6r|xEazk2&G#s%7OxvA*EsY~*Zf3mk3lG! zlaG~tYzjwS+SxsJE5#bAOcCJ?R7&z5q^iT-7CZpQ*bP)nK02>!UIPBuqVUHOV=j7{aE460fQHfz;qv{TCp0?2k)V{mzN=gRuLnM1%o?K8ko%!Y)Y@w zpN-J4u1tM`Mg5j_z61F{L@ z=tan$q9_A^4elYab?#=I9=a$vS*l&Q>#n<++CuC0qGMLUm;hAz|M;jVZr$$`Kyr-- zNUj&7ppm8>mH7%=Q#`jmts_yo)GqYQKX@3P-p~o-OVTyP4dhqH*%2A&z*`B*ptD)k zNJ3JUch-2m*cvYS6IuoGOx4pt^6}ro;(#R6OydJ}DXpw`i7;R|WU(fkVb>oYNv>?3 z;U#_ApO>UAO2JyuG?N+G;SUYFVDL+n<~+lfnD9B6BBVKw=-IzZuvXNUhaA(|YA$J?}9a0;+uxMzSiS2^93$Z1J-kA_>kKe3wbx}T;7<+s9-OjLHp&qXQO z?lLb_trIhaK6V5Y@4yNEM632-QWG3B&mk8AHV2^8a#(GSmMF<}4FUl<`P0jyjx*W{ zpqJ5VYkH1*0$J#aOmHFnvkeD3^Kv|<8LE&{-Rwi1gHM~NTQcMZ2pxaTqC(bnd1cU3!TJkP*NUP9QEoXygPU zE*NUhcN%mKw{8BgcH15f^^C&52nQHKp`&0tk3)Ds`#5WK2shXRu@3aSRQVm8{LFbD z==TiZoshQOR`4g;_(b|+EUYMxnopCEjC%WN?f1diFk7Z=CqpG~gf#mnv`kiZr5&X- z6HKYo50Gbu)Ev(Q(wcHB-7QesSj;kYRT%a!ne zsni15CTW>Z*=$>ot=+&Y80HzYDDYJG^C9KOrhgL#(*uKu1voBm!CQNi&*V~*gXA|D zk%?*B`Eq06A0Km{jl?iU$@L|)cV3D;@MqskGOG%Fuq!eHE^9e<`B};*n4T-QnkMt6 za4#Bx{WEYs^0+g;gXXs4SM(G1igsHJF^@Z$h zhx`*LsDOMPP#ZX5hP);33AlEOyeHrSs*!LfbsqOpv2Cjo69#WDDzGWLY|5d?CY3jz zf!f#WiM=BYHsxTpJIdsFS(~Gr<&G(iDT9Y2BHR6nCRBmFVeI}pdUb<7>D$sV){Z)n z1HxabtVjg?Iky+xRzAW2uJ&qegK6_d@j-u-N#pKy{6`e-DHd0er2Up`F*sef3*I2O zH`EG0j=44c5HJ9A&X~~HdhN-;-mRNR+we+dZzBikOBmh;-AU)^#&$lRF_04YUU-;7 zZ$&8g5i~)R6j^kT7u2#RNQ2>LrQH{5`*}DZDcPg%}cem@zIM z1yGYr1_T5XKry7_5Eymo?NtKkF>xEx(U`}CIBA6%fmRyhmLia{>)*sn>tn(-J)IY` z#ZBYyDx^i}$sgbRPeH34Qk7aD>=m?wSjqs_N*ayQLU2%9Div`&VpK zS$FcEP#oXUx3bKah2PZ3Q|*yfFhk&dT`LFnKycf~?Pf@Mv{Y+CjlPVHQ zQfItfT)~PkL_GW4ZK1LhxF_wR9r0;w1jr%$v zMzk+)_qG+BTU%TKEpSFn z0;LGGou!sX`yKdX9m|Cqr0ot|f~aM2wH*`ew^ED9r9Zlg4AM5`0xs7hOu-~b-|l&|-_*8X z?Tg6FJ=$iSRAr`$4e6e0>Zws~7dg8jXImpc4Rl+R%WIM5`qMV0c|-GPA3ew9ERH8V zX#h9_Ok4ijeGy15FGbGSU`Ar@QPzr2evwag(FB-+otujOg^W~olN8niq{hafR~)2tma2WzO?{W@)G_$WY$u*FhuwB zP3(kQFm<>AqKNl8>oQlcbom8si#SuCe1VOfE8M2<6y3_^&J_mePYJDT%UogTRXsmC zf2kw&X$bE-Pq@DGfe+7zns!#uPD=4i)u?%32>m|{t?aS+!tkE2fbUlQ-Q^lZr`YEC z!qfUia3qn=glnVuEoUdbs(OS8({;M%K4w3^DHP~pK4zJ336JPL|A_sYp2I(y|F-ZC z-LVhZIC{?hkb>jb&bP7i@#YU%?}Z55wwT!$3L|tcE@nFy3iEZpe!!l22jMe5VBf!k zGOqi8rMxTT=ytqc_0qe-&EyMw$$P@>J$?eo<&YLnccR1(^F+mGD;6;@?-V=xp75z| z$yT;_kzkG8(Mrk4cZ(;=%u~Gn2Rpw=xKF2DRF(U0!KBsobg}2(7uNI{>!kTA_9^k1 zBJvE%fD->oIx$6RpzZ7hcK-+19r?#+RWE-aEYYR>-GHS(2u3(|>}<%lKR(Udp*lDn z>S(}@tRD%F=-(dp6#Mccp|^b+HmZHQ2rOmgmp8y)OyEfh`mjAn84?eDHYV@@1uwZI zI03;?fq@jf?2_O_aI;D_wV zkA-2KYui%?W`9`a{TPmj_3Hurj!%Gqyv3~T6X7{sui5OmPqDZ4j#l>Or$V;{&MMbKzRu)@NDC=R&$}?z8OM z&xK!gUp~X$`9kpPf)m)kmI-+}Hi1WYu+F3yY(4 zrH@zDRtdwS{(1X2I3-QOBmh^*Q5DzY+x>hzsRYZg{HF$XrNDdRX?ni}H;1c%=O0DR z(b!8C7XNDK?-cqXLc!1bFge-vD4V)knA^)j;Z0<@yL!)A+F*(S1uoi@3;+2ZotU&n zXuf*twGi*m15s=LiBVJCJ}G_AZeA;_v0LELR37b-+th1cWo7Hg2OW(Ulm^UFu$tjG zk`E8FP;9^}7G*PNDaG-lM)?8zH?fCaE4}OW1$)C7;KhI0;qB<~>YTVl^eA@6DJKv` zAC35cXA)sJ^ubLqo6PlP(Zx#nFf(}UQQxEYG2z;@7T`iA9?J7Xb;NkO-Pfqk1Iy<< z2FoAFAyD~D|br)}D;fw#~RP%J(7z{PJHq6xkXzckwhGYnSaZ?d^lOfvVIi#@stIoRl% zsQi%&_ey%~Ah)7Lka$OOm19O;8~pTlhX7UbXItT)Jn5%LQ2Oui&UAbL1xK$Q&c!7{BPyS zJR6YdY6Fd;Wcc*SxiRF)M?!(BSRkXxlq||9J8HB!+M`(+HR^r=6puyh66BjcAMddI z&>g$HXP(B3R5=pAEWOq9upU%8Qaj@?&Hkiibyj7Uw5-`?DcEd#a?^~Gk`kLQn5eCX zmoVSi=%jjE!LFPqw^KOwIp!$aZN9^aR!{8JC_^XvTBF;`VMlyIyd9X5seNUSV8-Nm zUh8=f=Dl-P1-K!|0km9h9RwqkUj;s^d_)w!s(G6v7wNiTW~WWj2}CUM(wt8~>AA{r zgbV@`Sc#%+HZ8ha+kylZ91cJq0{Mf+1pk4go&lVfw42HJj4Oe&loO*K_?EZ=CFGAr zPo~RC3s`KF%1QJ$%vj@z`JU3;ubdc(A!1kH?!&Nr%-8^zeqZLq#@f|sgJ+1II*{WL ze;&c*foSnA;4{+Vy<}`E*bek_n#d|23wkIYF~Ep+#$rPg4&ad6`5t)CbY@Qw#{G+X z;;jlSomR9bk?Tk0F{W$)F8+rUXz1uLU&*0ZQ<|5E%WMTk5}_EIg3znNVh_xtg(Oi8 z<(Cj@DQ>HR6(~}=@*^*omzcJf%H)=HG$~SUup^aOq5Mc7rCaSNYk;*JZbPl*P)gJG z0yLhRmqP{co%q}`&YgD?gxJ(cxui!4#eZ!_|(qc zoT+8ySgt+HkPr7o z?F;nVPO_z_-m07?Ugq4*Iop$Em$k>yeGcq=FY8LoR&b7ZN`^qmQ%=f6wUXUgOuRJb zJzis*c3Ps%9c6NyyIZQnA_>VdPVaxp7$m@^)&WLhe`4ra$VX{$vHzMg>Nd}U?4 zp6y|-o)Bvc>VR)mu>Ktl*m3#o-gW{|JL_^9zy-e%8h{Y+yc`8WRDGsXFQnk^Bgy#< zpeL_=Ql%DWyYx4zf}lF5z?=J|mpDD!7f6(~USCUZ+1C;+CwXyCIoLX&wM)yYVZ($Q zT{WQ%39Z^%^lG+_QqBlcS&;P*8;5OA9#zH3(M0V|5+@g;lXg0eVgnQ~+<=yQ{-O6w z*Lp_jBJCdlNpOav4H6-%+!|#Jp1L^tqcL^@8~IToK$r0wgB!~q2W~yMWWqCC>zS@2 zjHA&Q5Nrjo;PQ?bJHR-k+!_NGL@&}{RYd&P5M+d{_OXg60)%lnQ7F5^L{SRgcy@R? zF(q(fSAJ~o2dNT)oK~<_kOyEiXamMaXBHH6OCqg$X9RS3UG_Uyt*5%VR>6{ z4ayT6&hl%xbV41g-6GtqyKNIYyG2Ou9zWxf33e>Npb7SY&1~Rzf>rlvclDz7acXj@Aih6-)huoo?1=uA zEPt0UPZ#pBzniC=^?<8NE3NI2h1r6PxZ%Rc!A2UCBOa6xMf|QAKBkjlDX2*Pl)KRp{S62LYgD(n@lI zRkTxW^li0U`m?HEg~BxP$q0)llKd$+OOFM`+=i3rm&s|1XpzY z#{QbXnJ?JK2ZZaRn>OHM^A~K#0ijRydiprIf}N+2w|UG8X8KLo(Ctg=Mk`2-?rh@= zE9aRJwmx&ox<_!^mtvclVEZBtdSrW?F!<>;xipVQD19%k)xk`p-ny41Rem%U@mWsn z>ADI)WVz=Lg2bm8iu1+JRAA{sUhWqQ@IbC3^wrs2x(H89v!qgM=lQRT@tvbg2+&AF zn=ujE%Wilb&Tn1^J;1>xw!)o_D*nNm@pG={i^ZFDxVPYbn%bykDaSBcIgV)oxl3d9 zOocl9HfGn33tCy4y8(ymF!}PzeKuqll=AE37Me;>kKFg&rC7F>8xBtf4cXeYgdJJoiIO%ChLF)H zJnaiN&_bET*C>W#15Z7C9ux7k1Vy-1nrgufeMnD9MXBs6NGw#kme=F9&tJYDjr~7V zhh%@P?)*c4TU{1rqplvnAFtCF==7}yXwLS;taX3c$m{bbo%9_xXiwUCYr@bguTkU+ ziB~p?@me@)IWoy)C8li$`lWfevltl2#@WhyJld>4XgkjDBhJr6^FYe%2o2o zBtm2uJs={xM!S@ER#E_yM5UDIN^(7p!9*@uOGKwB##p>I4{vs<>^)E`zUHEvB&lpU zx>I%!1t|{&B|ncikPCHuvP$%WLr}1#((WiMTPvVDh;?$6Q#3l=4CyVqXIrxnL<-$V z{#{A}l%fmp8H~Xn_=tCx(pFnJqqG7K$$1hDQmWmTkr*2~Pc+&88#!{E1s@|Y&;ya) zaDS=xe55BX?+A+fYe$^Sr|!Pk5uBL8o~4ATiB`|Q+H$ZqPjJ!*3PxT#^#~~X2dlE* z9p%z|3gkPQvCs{hhS~{%*Omhho_o$aTI>o8)Mbk>&qMrbVKLTW9TyB-?O%oI7^X)< z8kGq&C2y4Jj&==ujENTQr|f+u7W68O0*a){wKf2f?VfMO1C#X>Rl#As7l_4q>IH}Q zi@9#un445*#h#JbN6^8!1>PKGw+#w%e2!9`gJ)t6Sk@Sr2w}+0p0rIRFKM5(kK%$22FuqrK>Qpoj39gW&7PgclLtFtP;hQ_4z zV8qT++3jrln_~9u#JE&ne3<^NyxIV0fgfWc72BAl{Y{3kp}tA(a3m`uAkDsxU3gP0 z(2eZK{`r=8lVtJj2lLM-`4LDOd7i!ZmT1=P?Z7s@C8i?sS47U{k=_yKnfSKYU-xJS zHsEcsPd*Rk8)`H!^i)~yV(JG+VB3S6CxM0HZe_FYaHkG?pvJf~ZUNJLx&Dac3=%2s zPO1+}D44MzyA15Jx5Zwl`l3)e{@{7G`)%9~5(QgosRb++90&DNs+_8o)6*r_V`t!n znyx5T`hvnMr{XH7sbJlg@s$?h8fVir?Q=Vpw@~c$=qSWx{3w-5$f`70l|iOp6kfqB zgMf+P9Iy_#$X0f9{MxWr0(dqC%0E{-4+d}QZcmiR`&9lY99#psf|lop>$d9Y4bEw{^iL#FS~Q*X>dD6#?InVo;>t?$ag$ic8{2+$=E%` z>ImpShBtX^l+L5^yr|8%P;Bx{g;lHG>an!Rz914$TLbn!J0-@dc$M#!R+Rt3_ZY?O zd>B)9J7}xXVo)lG$1at=g*V4JK=mhx&GURn)>e|#%Jxi8#QqB9XE`(~-s%QI5@Gp_ zFlU4>JtNy9thpf_Jn}*}QR;5+(Ww{s6r#{3mMdOHj zzADlG*8%JAW&6|jUoKM6Ms>dtZVaCQzQ1gIG#>cBkB^l0uM+G+-sRPC3C4+E_Ka@J z_N*wiAYb762SEOGUWOUp6Z>_|Qa+*<10Pl*-rN6VL*IkIeF4G>6vveguqs|j4MEQZ z@W9t1Jh=Mt9l9*rJ<2?|D+HJPANp&RhVDu8!l;)8!;4h;6x7RyK)$m$d%#t@37#T-y_))7oZ2FG#GN`j zjyr0tcaFGAS1bZZYsL@7hX6A{n37oY@QWdcgs=E1U{V(A0-=uE*xBgx+FV}8e}&YbF%M9RFedG&;fcX-x2vZ zYg;7VV!u=rE+0Gf|MzT3rMa+CoJLOgwN+Cxbk3vLvhUhW^lRL|pw*dyJ>|P$G zkA%_iU3Le;NC?cYCJ{B?D^^3b0o2)^O6qL_wc(Xk2!-KV&pMu5wL z$sMd2t7%V)w+KgJsxe2dQSv~$@9}z0-1}-n^f`P*qh^BqTRV?a#vF}~ju2F)L z(A_w}l+lLsX}utd1loIarp~6Vv!;v12c*h;ZTdCEdu2!tsT4~e=+S&#`a@b)_&#ng zc^;Ppk{)qU>+Xv}F5>!7wr43CmhI2ja?UMiJy zsv;G9NJIzcYGb>)ILzbhc?74LNWcVS?05tFa5?IpZkAVKWCI7!UWmNzxuz0koGD#@L3MFgen1COLV4A?o$&fY;9B7D$=NvXuQ?d2Cu=; zrv}i3LAyD)7^0u++)34>X4fg3gQmX*Ex`#;B7*>3Fi3>_%1humNV1^9jVGj7Ln4wS z4QyYAeQZ4t45g0dM>eI+hEW&Fw=ttdDkD1;Mo1ETm@2uWN|iQ9A9bqqB81W9`YL36 zWa6Y;psCZXeIj!wRVr1WJ1-g6Xh;j*k1(3~L8GM0iYi#v{(op@mEvC` ze}kO3L2~Vm=gliY9)Lizx-fCrWp^bf{65uk-_lPgLaF=&$*f8Pd4);DEnziMWo8>4 zSJxzMR_ZYhhz%{;7EctZNN^f66RQ`z)ifovX`y5#lv>?xVmhl*i_23SZ332R+|E*( z6r+2vfMf-e+>Fd@wLLXyIt0=o=>#^379tGxO128z!F!tRas3cDF&F#0AWWtDwQ@~ z%`tNdg`xaLDir^+l+x9BKp=YY0Jf<%d~Hy_&Z}Rwcqjp-+7V!neIj1lIWfnx&_u%r z{JyMVuYDq3({UA&@Oi$>zWGGFOM94|`b6xb$2NJ^`&02B_9Qe03`&{!8lGpE*3qhy zhWKD!FiJBQ@WL?6ZjuL<64~ZJFP{=?gL;HTH(lnys5!Yx?F)b4MpB408~GDRk+DDq z%Lb9Mycz>HAEmTF)dZ7K#S+b^v-ER;sh&iOSc0%AJ8e+JZN7u(!JSPHlMRJ+Un1sd zpJC&dh?C7ke*O^l@S>0_c;SLJ_;C{vszu{|gPmL=-e^CFxtf)dW_wBrSFrQh@Bq^} zP33q3p(S{L7V>hG<}Bq{wz81~Cx!)UMl+EJZUu9`gacp~rTpENw+gn>=Kd*7$_ZzBPfO;fn9DG1v!LG!90Ux)sHJ^zIg`JH6 z1co4JitboG3XuB^T(akS6{#a7THW^qXqmuu0f9(PGjP-{f`f?zQ7@4Wx{xRY?V{$= z_AU-h4z|eOy;SUPCn($x!+W2}2rI7DKvvpB+3g}uRB8aG6A6^MJ}u;*4#npywe*<8 zS<2%~Cqd7RHwaAOoRZ~U?IKFgc4xs)7{8EkDhlKrtlfta7otQ2&rfR77` z4{%a+(pjAFRA!l0u+E>0eY<=HQxq*o;ff;?Pj`JT4!q8&)M5cDnmQ+KJH(-mF7TnY zSqF;GUjykG&))uA>|swKhaQQyg>W#0gD2}3a_~q$orFblmquA=T8Vr_0(E%0OK6Ht z&G~C4OF9G^(tm<d|n{=QT$OKQGjttVCSjNY-J0}Mm-YDfxpq!>+V3!<( zliW?s*eA_A5QR$6oxD5HJM8V{VvpE(Z42=rgs)VpLFrr+)GQZGIjM5S8eXmAD;x+) z+e9@|S*ZPl=YCyA0>gfv$$vO}daS{u*nGe0+$qv3QcY#`u1D_wB%V*@So)V@iZv1J zLy+0D%|z~)fw(w#_#=@6_AWhN})}WUm0A>BOZ;Xz!2JB8|>Se@_2&(F(u=5&Rj!3x$`{F7&D$O^tdRpY?`BZwRb9M-8) zOzWHo`ErtYtpFmOWmk%0V@c>BVT!g^R@Qs&X+ws1wyIJb-8+#V!UD$A2?693HAR-J z)hIa?B~D;BSBZn{DRNRPun(n?O zdSdT_UZ0){mbCWSPG#&tuSz5ywuO2~LBN2-j9YG|QP8Vni^ksWaAC92#EI+|30sK9;yqC+fd z1y(>wU=RvP^CUpu+TG4SS?AS`tbYqIF>~fcpZ3VJ`lJK}NWvW9Qp-kJNcbYb^yI0|w!`1A$RbuS* zmD?Z>nyfLkg4d-`-xyK&4;|AR(YN~Pv{5(#flfJ<0f40J!i#M_)rw5-QG^ta-U>i0Udh%()HJ)?WSks80pHIBPS{^uO z;8f$3Xm`@oSRA1I7w0k($oaB+u8aCSqTkTE2iLgR^#4F=P?rphej!#N#UsAvo>+Wq z{P&nO%00$QRDpSm5Da6((CT(o;7!qUe>AW2T+x107s z!96rhJ%HSlfbk!#Q2g;mV-lt#{CF%583se}C>^mNsL-kNvG5ur2Zc`}gZVpXzbkg5 z1^!5aVWfOJoz=tSov-B z6d!>qxETaaaWx@QIgY_hxC_Bo&e5w8R#Dabn~<$zn+^$gXcseWK(Gv^lOh9W55Nc{ z&Af-dr}Ot@{yvDm9|v{^&bILP2L5j4?}ym*fRL#Dg}oOLt{=URdgR+g{8e_#WcjbR zCixnUXBX7=9potik?L2^&OtszV8ae3^|S8MV1TkFZIThf z7t3#NFjG)SvCAu=CToJvaNPyMPF{&gizfKU#cv~h=U)7VBBu$`(ishwlmfo@1*l`4w{IYZ#&4Ine zlO5}58Ytxy{F;sVrg9oCIi%SqP=nhs2oYG5pXhc_63n+|X9KnFHxls${Yv4%d{2re z<|@~A#Z3_}c5%Bccq-Km`wO)rHL2=BEP1T_2u=x>pkN%Zsfp?b!VUe5jf@l>*{Q;h z=P~Vum^gdZR7#0mAvVXM7F*I;N3g^f)c;|FtLc4#Sg=1lI~IM62H-r^y`I>|)k-ne z8Eo1g^)puv1qA$WLt`Nha8WHBQuQQn_#9xs4RH}^r{odTxe_JxC9_J~8Q^uz=zYUcXd+2pzVH=!=97RRavl7}R;6yLQ160pv}Q`EE!;UXFG@ zN1i>5y+UbOmZnhAH$5HhI~n>1p@BRvcUR!0e_iZobbY;gh)${VwTcd03f~gd@O#oW zN24TT(4+J+#yG0fs%^H?2{c%8ODsSZDi}dE#16sctGlH+UjR%;NV3}*HRL$$feP0c z0sG3Di`|sI7bW-px8yK&(F|WR7*;Gz(FA(T5Yp@ zrlBxXT4v4CWcAsS1zP}hY@wnHrg1th0W9FyL!_w0({U1`l7ro#0Wu^_e zxoG#P7<`_y2QPp!ihHGO zA|m_LWf#=RdgnYliEZBdb9sj+)yoZs-7&ni);{$L+!y1*NRrwankOu!Lp2$K6y?1)}TJ26(#d6=+-R~v!wyAcjE8A*C1(QpS}JVS3pbmI|Rqz_Sr z0#}|^kvb)>1H8 zWkG96Bs$J1*s7d>#Nwk=(wRuZFlTP?D)o?4)qQ+2W+l{{Xg%&CKU1ICH^xJB;EC!Q z+y-faZpBmO>{|eDS9gDfFbd5$5&-B{ zH%mpWHDx3kG_20m<7&IRY&;JlaOhu6SxWoco_iu;Q`_I-!*4EcO&N)O`sXh*BTonu zLD+d~%BUEhO3c8ZxEg^ zre%BVBE6VVEaWtW!w&;-uA5PL*`Bg|JP>E0IMSX{v7>DE3?w0QQYu{hbM}CxK3l2I zhRDs;w#x1$pHTfrrP;Eb7xva-e8Yna6_B2*?7|tG+1(HWJqfpc;iQJUasz=_u$RtZ z;n2bct+eczt>A)9yDwY6whnP}h)n`0vin^si@bi!_LAsue?fIY?_0_rvsd6jhY+$0 z<}b&q9UBd$Wn)dT(y|F;An-nEQ?_DC5REBqM@(I!#axf`j`G`)>B&tM0zJ0#2adLw zt=a?Ro;Eelsy)hg{`(H-eFwR(m~nv~7~EXmG5?TUcY_v!w9~k~69z-fs-0k`UU(OA zY9~anjD`~)FYp#zf$GEvs*RN7BP1bIW23ev$1}hJH%GZjbGEM$m~N5Xo%5>)WW>YcJvK&(kwvuC=iQ^8a z3uD7Gphu=B#*Dbi79`B}jOZ?UqPk?eXE);$OQ7UoWq_;%16h!CP-EVt1IVi}rH918 z0pvm9y^k}&_&D1UKnpMNK|;+-N1tHzdTBHPLcqxxN2OVNAe+LZ2umdvqVP903dt>) zG|ZyYShAZl0rWT8o2D|v?0wi)hmI3!~bSHRVMakGA&H568=^`|+n^GABO(H?_5RbhQ8ao)O8Q>rvF(Fa5 zHDkXtr=yxW3`q<@5<`$20wlr7s${ekaPEUumwKI;E1Q^W=4t}T8|`b+6Yn9w+a3Tl z3E)VxQ&9o{ix~;%su3k?UDT@*&sr1Wr6Ob)!Mb z=2$P<29BkT^|W|tD{v8$*$O-nCbJdHBPPRXAEK4NV=nvOa#x+RqWSJ`HlR#G2p0x8BY!+;th>rYs_@@fs1< zk`+f6!+4YZ<5bZdCQT%Z2ye-?9B^t=E4!tP;e@60Cm|(VgShIG?1&bp&QK< zf(|Czl7$!shw0gxS8)GYs%LbxuT>A#b%ZHLn%$Ss2v&)7J>qi zC@Z!c<#)_|ak_-09vE8?15;ptf!K21h+!8i{xryh`HR0xvmXI5Tnc%rU2^`3FjQ&I zE_inUGC)+6aZ%xB&8SHa285V!?X@j{$D>Ti`7$t{U9gM@2|Gb(YG!+KBZ1)Bj=jwS zQ6dc%@scZpk07OlHvr`-CsV5LV8}HkObShuJT_>0j;m!^lEC z%C+olPt;Ip-3YTt8h+78rH)klR*`G>a?)%Xw4vf#l_1uqDHC=WH0;NM)FtY@ti)Qg zGS<>`bK1Sw>p*!V`&$@g&IC@v4{lQhOzia057r!jTYi`n?rNAlP_pEr`MaaFi!?hA z!7vmU!)3kl4Xv6OgRi0gBQq1VaM18)7{WoqrKAIdNq8u981zg#3A5vh_<)^v36`z7 zvVfIj>bNj%rDEavBIS|rL1MF(I*gWkB$tci&Ig#w5#L+2tysdRwpl$dX|d)lRlZKM z8*4@#7Rg6QbMyqhdo9PTFQ=eZPO8pQ>^z6k>I?O5s6Mkh6UGM8xs>{dvIbj3pUu#^ z;XXp{gWF_+4UJjKyHrS_A_Q^b0hOy%kDUV+1fz)rw9HL6a>GHF*NXLY=Q3cCHeMnM zbcu#iqKqv#dKQgVsDz;$ZyL%Ki}_T(nv5Fc8GxyMxPM>lAyr|rCcA2ir9zi?`U6&N zfM(aor%L=e34qB~us%G^$o8aI3mvau%GC(Ss5J1^JJj2s!-1}BSHr@PHM#gy*qX$P zY+8n?PWav+fRAdM zcBylJYFv4c(=DMc3|eq11OW$(I3PV}17)k}X*JbFtEug{jwm@1sA>7%g68RV&uj-@ zfdkY&%Tjndf}>C~*FBVaE(97Hi9k6`7d;%VCu7$u912V@14B6!Dr1D9Krpz`PMxXL zC+!N?-hkuZo5R*TS*h)FRz6dQ6{kKe*m-iX->EghozP`3oos7@%@~v;?cNE)YPb`q z!NFHJu0nw|2oL7MNP&d7UdfJA;gHyYj}aUeA4JuO5Hj(>-6XNvhh?&LUNI`CLUDvL z*Dlg9R1ym5A6^OG@aumam1%NHEQ#cQKP=1PdDJDNaClq}I%p!;4&M7H=L+y%=QG9s z5j?6NMgLd$2)h5D;7vyDfnT4*UV9vy%7(Y+pf}tHgXrUa&O_IhPz5wO%~sCP)HGMw zF!Dj{oy}I-WMwBi>l3fTnRoGVn>&i@<2Ec4nK2nm^9CLo(gqVGrjHdEUTKS@v!1`; zfcrZbl;s&0+EBJsmO!Bw{y*N{JT9uT|NoyEmNN=^P*HKmn#?^hO;Icc1|4)?8ELrba`{ae>K&cVS--S zn3jfVEOqt9IIa9UF`9peQFU-kGH#{#6%A!V0fiH`UoAM!c+2Z!v2YnX9HSEv1hoe1 z!OAhSprbZso)v$lM&r+8P;eVFBo>F_9{QVqw($?o$USs{f2ee~j0P&rEyw?VaPcL6 zPEpCO&;i^ac0T&RW>+G*DWZRaR>X;!-oY3=_@FouJ!ChQ)36e_gc*etf(F>1x$=b* z2&HNMAi73Aq>KqRIIUwz$MyzfpED;~P$aU;FZ4gf56VeumyyITO(;Ohwcnl5S{M8H zgzzw^cMHdQbpf`+Qa$g^%plJ3)#v_LOkbbR!Y0|wo!r+q*u2+;-KL3K)BOdrKj7jY zivz}MTKSNDZ$j7eGxcJzi<$Ax*ymU6IS(Lj2Unr@X<=rIA$<(?U%GOJn+f&&7M(Xl zUX%=uF()h$IsXSs3$tf9N)mHkV$PoiMb0Pe((@ilhW|10AG+(3n0d+{+pTSfJ`SfI zY_VGKiRjKUi^DNcs9j!!d!96eQfCy7>CEG?%wrT5lpc}CDr_FAQl8jh?fp!E$J-L2 z5qWf(ypS!@l~lPwj|D8WgE4OO{e#+O$2K1q6j{bmZ)c1X-6n2|k{A96yWj-;VRrcU zLgCS866}b85U(r9y&fQ;zkuHWj#2}Kfm$Mul%zcpFl;^ z4;8@h2mV8Q_h`bxD=Bh=@KiD>fir(*%=fx{T*7LUVlv|oIegWoph~gF!bpxgL1Z`*qzHA?-2-d6hC;m;*>iUW+Y?Q^A=VTF728X zZO=*yH)TX16{9_rEr~m3|8+%vY$vKM^Eg@*Q5VZ1lp$#E&BXO<`nYo`|ZZt%=c@!m;;9@!Q!Q<$guOA~epi6r7#mC+}m0K(rit0Cei znKGhKIKl(S`v&0)7)v{%d1kQrm^d_==*E<|?A?#C1tdUb5k6NhwUb}IS%tXizVSKX zdW|d0{L}Ca&zZ%+*WmlV@+k8z(G?cgize*S!bK^LMX*WcW{4rTdhWKJy;q;$ScIf}lNhHQt4v6%|#=jMa5pDi>D7H)-08dFZ@p`##+1T4E&Id z=ltoGRFgm2hJkwchGdw_V(3PKwk??_?Zjbm+Vy!OvH5DPl4rG2mtdEW@uecJTeR0Fw&k6 z4nPIe+l}wvgt_$N4e?{K=K9<@#8YUuoHZS5uEQRLx;9}k!?0-878bo=q24w&9JAv~ zl=y#e*8I+UsJrrsu)DKwDJ`!?J{Nyg+-=l6trbq33rlUv-_4o+o@mrDcZQ^~?(fq6`@#3fJky&UnABpgX9F;w!ymu=y zr9s;zbo6yRejszyJu{X6+=^^u`F^GnSsA${Dt-a2mo;p=V7juuGP18_{-a90s>r)7 zbDvXEsv^_twuS@e{H<`OEU$tN`EMRk{;Y}|Vj1_y@-C9yGGxZ`=@Rbxow3|6^|Qh+=eq6{9;?}MVVbHx$;V9Q4=$=kGFL?`Rpv-OK3TI*KoHzTe=YZ=-C z(SL%X&!I}aFv;y$VS?TO|M6_kDfApw%K}Io|8X2&QOkY0afkYsW>imWzkbgjc%6Dk zr;nNP_J>IiNS0pxl{=%P4wgTh%J3-ZJIk3QrB1Z;N{ctkZ&W2co%u5YR&z8n&NUoY z=a=75zKllpD-NYNTDscc{nTq>OTbDr$78mszdWSutta(w>_z3YAa?oNsCqVh5bEF^ z{ge*%r7`9?im$$uYQ9t1RbRTZD^?Et51~e5-|lICW_}z}Lv06=lc{p`Yn$2(4}~Rh z<|Dz8N_|-x9d&jh^jl-)zDQlI%#fu`4a<;5+ETi{o_}1qH%1yNV$lVmE#Si{pNbg*Nvp9!o^v`g^ezv zdga|6E4^e6n{x3+-rB~}A+tpqrUaTwuL{==j2X07kLIiE-K`|VA?d;s^9IIAlDYMd z*pQR-v^bTFl8>o;*~f!yE`PE5_4ymhv}RIV*m4+NX(runeq8yonRLGh_g@LyF+quK zE_Kcudq&!ayDK_f%j>R6w_7ZESMo-km*!i-mZWu5j{YTe3wsoX`WIm62!s8C^tfe8 zS>A^iq)*KjM_Jy$OVUGTOYmaeCuPzybJ&NDYf92(X=R+saXju%Y+=GJ;%~6)T&k!e zx?EFkUY70-Tb(MLjaQamL3&<3r~Gk6nib|xxu!huw*>8#XY(%nEloCCPM=gBzAD9A zywjAqSEW|14!UksEO{tru>R8^sn^Jdk=e`F*sfqdN4d@Us9oyA}AM3Ee z0i{c&6lXcNPZ>}t4GBBk>YDOKrF5sI-k(ZgrF1H6XWX^C&#I(IOZVJ83{>`UwTR{4 ztv~nFpQrJ81eBBM&qIGwj+?FdVM7~S%UfZwjxvXt8qH9yhgor}01QjQt$k_8+Z%3O zWR7WgsIto5_p$J~$NAYA2l6IGT3<2u{U4R*f%@37RTdnHt&eJA99p^Qbo4luvul*? zZuPGzcUi4Fo6@edcDWy3?^=~oc2kN~ZmVOxqZwW7uI<7C7ib-mn@j0oCErcYThv_I zBMH+Zw@J5$w*tdZ@KGGH{u8@>t-N;rI`lXQF7SdiRKQfooJ?j(I8LL1##8Y;q7zUU$y z5q7?=QsyYeMnvON9=BP4C=k1x$g|ZN+>C6lO}bwp`5CK?;fQ^prEr?=-!1}pN)I5M zRJs2ysc~-+I0llzKEm#2Y||hLc7|v-KH0he94suQNIjOdT9){0n zYFo5`MU8t}?4#1Lw3qXu(mO$Nhc&)Zk+(5HdM_;O?_VpGF+HW%!^ZqtnfG^3X_nct z)s#1-m((s&6sP6=Q20u|nVz?)pVTz0IZUR5*w1ecRzemRR>T+?uKblOtqOZ;&8@t* z>{1VNV^Q7;tidhp@{d0n2!9uTl~XBFj}D@=;DBP48g&sj!f)&FBi1_~QJ`w(H58%X z4*b#Pj+Nai>5GpG3ZDhof{4G7)t7$mH`Tu~KR8VBb4IkSc4OS^$XZG~-G z0gtdM$S5rqCefFGw-Z-r*Be_NFp-ZHWGj=)1HyS%JP6x+tR8g#z#F|x<@pvNMXTD=MnclK%r03kna9iCmDt{dgUhn-J=8dD@-8?Z&Xy$2%q-5D zXMR@pPC|F`>Q)SwKLSr04;@PQh40MFqO6xJPh}Qly%ZLoxe=qc7#!FNv(5U!5f}k& zu+T$0l6xyWYPfUbsxP#Ep49d@0)J8|94<9=Clplg;p5hfI82t-*qJdG8?!Lm(H^wM zSW+JxA_7xo?<_0hhF-uLOv5B$%`hJ=9jwx2Ula5t5kIup(ZUoqQubM3^6$6%4(0N#IzWB!9@rTXJ94<#eH2l z$W3Ps&a<1aD-BV>?N%?NUo39+*^5|W-<+^Z8i!M!NUfxF**g`#|MtJc@V_4?_?>PM zz+wd82&@+8U!VXAJMgi43!Pu?XSb$db27xD9y}8K5OS1P;KcK4qxxB!#e1j7-VR82 zZhp5R-wlpvj6fQRZAwsrT9ZEj?&d4H@fD$f;Nd}7VAZV$4o=jd50T;olJ9Cw`Ut7Z zmQ*|F$4Q}{xpqXJ0L2uN1M8Aqut5+;r`wbfr+-0uCSS&aKT`JoiH(2g1P?W3%7|cR z40e5sQ7j-Vac}{16%b{^IHnwy&Kbj<5iCGwu}%Sn2FS8GF=7Tt3{t8_SUFVg0^giG z!I`-NaTnLHU~{;2Pgs)lgzOuHAq|S`Q?l z3!r!fXAK4kb;~|4w(;-=AKcmWu{hkMXZZ$}<02e>#Sf+iPGYV{Epc-!1;ty8$o%Uj z>QR(^0R)H3eem^P!>K8wfmR69p-DA0E2)Pm^Pf;D5}}B_p9pwA9jl9L2I;wudYB}F zt1^O%N{6x$1e8=A5aJ?2ak>2`jgZn9lBXgbN7u2hlkF0t8N7(Df-~?yjJRwFZ6Q16 z1J7Zm_*Yuwtg~ey8c^&CU8Jz-1{-{#kd2{?awVP@d4+^Sl5bct4AM3Nw@pBVyD?t< zUWHV>cDRC#v=?C^=e2V1r0m%XzrXC8RqcPM?3;)uHv>SPno9F2d9&tOrb9(6x)NFQ!tjch+1c>Si@9B1z^-Q? zHI5}QU%W6>$Xen_FJyc0dH=I0P+)Ld*f3}n#W?$PETsGIrsxi+VZ_$O)oryZIvbA=^b_q&9U8O#~ch(T*MFMpL&_C zc;HR~nxkRMAm2l zojLYDkh(}#H`4Wx?7Ihz64nA|ZA8n0e$jC#7jorj@)#RJ!_=}DZ{Q|fNJ=VMv9Sy+ zgu~!R_+u2>bcn%jc>fYWD5K#r54CLjd*D%6Yyz_ zb$d#|K`0ykA|V`ES)0GeD(}NeFm_tvmOX6qhO#ZD*31}`0TvBt810F$f(_vl)hY|& zqh3sB_O4$hq;=Nyakz?6fJLIBW?h3sohZOM8|!LvRwevkQn>2-DR{(@0-PGWkM(Je zoBIrXJs={}bJA{#vWjAg)hFC!R<$I(!>@)gcla;rwQMTnjtkYpXaj<{sYt8$FIi^F zzAWs-*97-0n4F%MVkFu3ImX0}z<7x4)0r`R52o^4l~=j-QW}^X?+T1h-iSFQ$dWmz zjO#>|sA|Mw@AMbSzWwO(qU1}N6I}k1^up76nchAqXXG8GVhbxGTWMCL>=Y}F-w0zJ z8hKG+c1m3u*9v14jqBL|$xex;`8$E@(YRh1>x9Zw#W~45Y?0_t;-S{jRRsj2^$xsMD;najN?f+~1(pY@7Cd;j%Xw5|x`> z$Fgztr66%drAE05=3-k1n#X5k-w^CQKq^BkC z;MYY;6L3~l7YvN5j z7HE%j`F2u$%gwL#R6xM>MwtmdOL5Z%&6@U+uE0zbJG5Zz z3ObfHEsX3PCczZ!$vH2!tNs$9;j)H&fb5NNnNRr5C_7AQXu`x@92k+wK2G!$ z+mTg>Lb07i+!TBf^}JfNPLq8JV&*R-TJgeo0yj#&E?d!Stq&Ajfs8g(Gx$3ODR&ZQ! zbq7-VV}ypmNDQ`xMB6Yr&$i0G+u$^%D7-zgAFIhu_#$WDk+zAmfky&q zBaX3Iy|LI@gyFazx9AD71!^%WAC_!x^@Ha`JTRW;zJ4tVTBJO^jCeFb1A}ubPn76pr7Pw!Qd_rb4n@NHUy-PXtkM$0^*MYZXE-VVAh)n6(B~r#w9;GhPjME16S;y$Ll8ac6;!LB9@V8g0S*D1EvJ72N`t{{*{r&G9+GJ?txKqpcCLw;f&@ z>ME|nPIcWTRl6ApiQ5eV^NVVWA<*3nFRV?Atwns$#>8T%iB8wx$)~4_goQ9q^Z#9Jrj)3b z=`gKB`a`^n?i}06Y@|Lq5^N!}?G0#TwhZ;7zj+Qjo0 z8gP`4ACnT2{zR$roUFk1pnaY~=y{I5HxX*^qVIj~QgAD*oTyQh*|-wj$|A?p>V9nR zJC8w6tn&EdQVUDUbrF(#En1=fBcwNAm7bIL875ndA;<-6PtxSCD6URSnWIFp1IS*u zzo@E_D<_Lpg7pRhdKjkavig`Z>T(_@E6HNYyeho=?ZbjgP?+6%3x?7DPt~LSkr=e& zX(Q(odD@D2t-&Y z9eP-PJ*;OgR=Go-?6S{Y?P;*=n;|?wF6y2h&^`4;1n^Cv$)6~(Q;Pe$GXHUf&2)0= zg{^CP&ax&!#3|i;INel0 z*XeM0fW(9#J)w{ARv{CDkFkjl)c0F41Z;BC?~1t@JdfV~hOwNk*?LE4);x=g>tF1s z;9jU{=qcgH#zBFWRKqc$@ev9P9z94*r2BF_ZR9kq{@G)9Y3ZJf$cH@1z7MMXIG|HP z_(?YWbk_YuSNlPNj;!{B_wek?MpHbhp#GwYo!X0zAUFT@UF#5GdjOlQ_^q+pw?2Zx zgKw$C4^B(Fnp93e5>y6*c-~OJ^?~EYGC=zhB*Ev~v2c*Z6@||X3#5(Pq%NUNJX5Vf zO&gOsTXe-4cx&u#;X68_8FDlkj+dTz~xVk6Iznw)1 z(LD{9eMj)L(S%y2XVGZgQ*ZcDdmXJ1DIcq+{9cSDwZeDO_>k}UiQN&cT3H0)yrG0? zaa%icy1ph|tG0wS#6uEY^ano5wCSEU zLg@PG*%k)h1?}z~-2H%Uk!sQEn@WcX(rrD04iUK*;nV(oJl>|QaCGE1<9%_XAI2MH z@1q=PjldtZY*&Tio*><8k$WjyCPebEm@t0ggsleG@GIu z%BbhToBap;sVd#JA^ACER>kztBA&Rz_gX%d)lTo^vRbl9tf}Sm(q*iy**EX3m}=r- z`fkcM7b2S|`A_4`-L@%}Ph)e<-n|t{!bGX7rB#G7ZlcsFZa>rpJ99Q`x7tGPFdphE zMEK*0QmSQnxDuR*CFrrm6?yVA(sZ+Vnvyk1YTUjf#JO?SrOzPV?nsqG*$4pZVbNk& zC3d=4m8?Bcv36(RKD8Gn0JwbP-GTnJ;dP+!TKe7m%I)xq8EiCXbj=Hrpwk{J)3~f* z@x4mJ$x=s4K`Z6n$gd$N?G9G)!Q(IQ8*e&|W@bZoNI zT&&)BTih?~J*G6BBDL+udr4e4*M*Mw6AqeF=u2a6Y`)*~qw7K^|w;ygGAcCKji5gEv!AYHwuYWySKW zG}>&<8}qCbZjL#F7A?T*@379etRUE5nKo65Z@z?@TDs|R#m(H8)X8r$x*5Zjl~bkG z?hG_yPJe0eOS~s%K|D%?r$Uw&NJyvomEt&w_Xa-5NYFP#f(F+^zB3)0uzw-a5lxu9 zSRDHMA?u&%7?~XpO>5kzmNdIT4Mqh#C5MBY@_O`xaE>K+Kp2)blAvg91YYMFzuUeU zr__|O)1-OOl5~8Uq3=kBD(KBW>F7lBfmy<;I6RPPVre8SLF3&!Sg8nTw<#gb~h$p z#;PFKk+iZr7z>NNp$FgALwq;dDtv*l9Oh+WY7S|VhPeeS)8cl(oRKzc za#z!Fo=c>P{tcyX;l)Nyem$lTfyVfrQ%%&*+a_be;$`>05T;T*xNo2Q~Kj=;Jb7~k@x_?FU5bnsb2#L${i zZMjjie2j(v_{f%-Rvy(Q6&NY!KmuS3>Q>v&D=NuOFvo-P@oJ5wWu8IC@t3 zm%jlc6jJ+t$YzB7-z~yV`PGDWs$%OsG$D#ZF$wEWdRySuzR;pd#BJt96HYWd)L zUbuhLb{Nqor6L9XgR!LA7%FnONE!iIp?Kl4z5FT`GdId`>tDMQPW_$&{8g9qfW}o0 zzdc9r2!*7GCq|*N(^FCg=w?9x;QSIj0^R2Y%p(I|9r3oxucD z2gsl%IMn5P6`AZ2CDI(EE&=-{E8d>ZKSCk6m?zW}v)RSowIH|bIRbC<+Z=(VjHP=6 zW4sZ?38|MVVQmS=(j3@>FQ;#VvJ;dczlS;{p!-$=+e!r}o|^z_o%$?l83}3fR|ivb z<~Ed}E<}x8gI=xpTBcS;ry5_%loTol)5q_?qOGP&quA|@2&Jn%CliZ-mkfc^xE01D zPgaNmy}SVRE4TpN6Rlmvg&@_h!Sb3ZQcq*2z{FQOaMl&!Y=Hk@i<(0E9?juK zI)no!93ZZ^>l8PlBmRsuwD=3Vxsh1+4o;}~8i(dvtg4CRs>29kGH5K`p(S8BaxV$< zN<$2ChNL&Ab+Me#D}*)OZo6RTQF{r?mA7PHT*x{BcWYJNt`=h8$Q}?hjbbih8l+^e zgk9onjsHBpQLP)HgwK_3YjWsI?!P=I_A;gW2jFn&4t497O43}Zx#iO@mCy=WpK$TBEnZZK|q;*_FA9=09lepZPw``}^~ucji()Y=;?nvhr4@myh4k3Y!-) zkTphRoH;l!mT-0Bbi5-J6ZP$Pl?HBn3-ohg$z_T@JVJ*NTQ=@f4NTWPI?nxi{V+f*By*xPK4-9* ze%d3!!~Jm}4!=eIY8%cX=Ct&|A*B3!`0L+`q9uQI1=lpI_3;%V(CxC9+ZA{&TU^&< ze3a9zeb7^1=^uoxf=D{?JvBZiXxEFnQ*H5)R*FWe4Rq5mRf4J9YcnCfkcN22JiLsN z?(Ih@DG6RgGoer6`}fIT-Jr}~`hEpZiMrGMh}={?c&qvnu$J&aAF2_%*;ouvKm9QD z)^~K%F!eQg1J66NLp4Rjgz?((t+easbk#oF&}_dc#r!0KNO_fsoXTCN<9iq z>ebue^K$1)`Ihia!!Y`L(2D}1N1XZ?rr)|=)hA5$sr)=1`JaDdH2Pzir_ysC@2xd? z2^Y|>meIGWQcpsj;url{^)QV697EEu6SFgVShJq!mp0PH#SR42Z^V${8M2o>vVOxI zPB?*v7wB2Q)#7!)p8gze;$`nAh&&GQX2i+aJkNl=GknKgh*8Z5;ytBaEdlzar#zjS z@l(H%c1L>VHzGVXxY&Xzn=-684(#Q@eBL1qtuq6x%Kg8DH5uZlA-ZQ%ycGP`FhYbh z79l}Zgb5Lp7ru`8e9x`O_VP0a&gX;=_x~!ou=A8nKAaAM(q|=lfz&bTL%72#YCY`X zQ|t?*wsBv=yM6wB_&~F~@B=*XlQM5yS6*BoHMhPe-XAQ7+&FAdG9A(ENDaD0jF51jY1Mvium<>&EkGNC*s8IHFWw#r# z2wX$LVzQwkk}7#}*Ku1Xr*pjH5s8&%Oo`){4#&fxw?Oul>(3+f=Y#rlYA7H~RjdND z2kzt8mUq_M1GB@~hGoGlvIUFUh!<2WcuFkdTywz%3vPBTskD2}C>OG&=!WPvrXjQJ zn9Qc-RK`O*!&2S}xMjw^k^KGc5h&#J| z>ib8~XYV`BI`?95HE?=h;Z8VA_b)8KPw-73T$2D}43iDPnaa!g>bWpsf+F}l9Qe1o zvm@qQ8&aJ)C0k!N6`qgFZu|r&lwzHa$!80u&dEkA5TG#oZYL14S+M%5ox6Mn0eoz$8v1|O)Wc;kkH&IqvVNN1IW<`q zu;4Qw#-=f|DX-uaDI%-`bwhe8qOp<;)hoi>9=Al(P;$vrF(sp}-E*@y1ejU5n1dY- z&0)i?!-r?kWAWUKrb;X?cM}ojK$xKL=OklPjte#q>2A5>mey1C-wFEfWBTud_{BYN z;)U&TSr|eSFZHfL0D&}9&ag7i$xE37A?QqH0j}94Q)WIQRteO%s#{Ix;K5BP7qnSeB?O}o% ztjsI;-nrQ2!$u7lLu~PjPP+It>%R~T`nZD4pDx8)88LcT%Xv=Db6yI&xHHBoe=U(( zq;%4e;dFxLw2{vF(rg6I-z@$2dHr`feuG^V>#I`dupcU`lmlDqG;09;+&Jg5CELl2 z|0mu5i_)MVE_R4I1$zS#h|?ceoaKZi{}pGsV8WZKin2JzhlaFB{iy7^nB8O7&xqAb z#40@yiLDacUJ|b)f7iHGla$xQ*&}fqocf8Fvq6bd7EiPe9(M#%8O_b;TK&K(btQIh zK`a#@Y;A5$p;4c<>lcY`P2gVLKE1DyUe6u22Zmy{4y&VxXX(aJJy9Nf#@fN%c(M4Z zbewLTbP4gski~+w$A~vOtd#6sUS*%d!*4<&VBRc=Q)3uC^YySeqCM@zkJ^?2rDVRu zByUXf;LI6R;e*FRO!>f45e&zujhAZvmumi((tpOd*C%1V>~)KZo_6S zKG7ydEyEIQzY)VydN+{0Z{d|r;orVxDyqb%ldL_Tcn)FnORinOm1%vj^ELslcmiQC z)C-->A1%@WiXDsu7&)Z4($l zCBxnm%7Mw&Mvw2IgyFP_73*M)MWZ7;y;**(Z=}5FOIV9(1_X@VkLnsk2f1R!o-Yx- z!FYxhrjyhZ&6pi-Q+sJf^{xxbSCg%6&4b0e+=&P*D~W?VUcH*;MKin&1`j4c%$a@{ zG&K27>L(-C^uNVno$qsqpjsB*A(gPO<4QvxWhKA;gTJ&icoV-^tia?|rCDB_jgV{S zm>cEtw$$VQ_aB^1M)k1Di@WHpONn6e z;#S%-EL*DYAbdm?Jw@EX*Fsb$KM?!K>s_`Mh+NBzXFWk{)(LzWr$?+07SLsGQ)>+rkkF)SA7XFSnXI;bO zbg?kV-!soLUJX6~U--Vx=%EgTQ4D#QnsHi0)q)_3O+1UHys!ftI5(K)o6-A4_KE&4 zi-7QSCw-lQ>)=*=Z_*LjSBj;qeAIjh$8xpVFH9iWdrApRvnHi$sjt=xpg=Xme1tY% zwi`aPuEk~4$+{K~#iPhaW+T3c)oBeZgWN%bwL3AYe_rvZ~jB;h~?=k3Lq(W5k7Oh7LE85r-pse(;y+bkX zG=^id!#@X8;5(62jzA|4U&O$JNr%z;B0OR1bQXS`<8cX^(!GaE=W5N{hvhAMAIN28tnC3k# zdvD<2VsWaKg-_SR@&nDm6UbMiZ4%2si3PzJ{b?7JpAx-cqE8E%TCvQlFOF?-Ld|&tJpl_ygzfcmV(ApX6WvTxItgQexjSs5o%Q zxxa}m$2YBV?mn2%BzJ~!JB^hvY=R*Wg{H@axUaB<1 zREnJu8T^6@w425T)MVQi7%31uIGnM>IIB$Vwm=&8gJ*u|XF z!BQoa;$!*fmb@7E145~Id7A%h@HBiWyWW->ncFLWzAZi2DxEbW3Oi%XxZ}dh%Md-A zZCP*yu@|8Xdq)}=(@}HcDYDoT_sTiFl`r0r`X|cSFR`HGGfo~eJ|mb63G3h2X|t%m z8y`fjdoIP{it(y8<>xzG_s80TtChRnmD-rkDns9un$(A!yW|}IC!2-aj$KzW-<3L> zJ1HN&D>PikuZLQ&t7+NNDW-E#Q<2|kMk zn(NKuFW^=e3)XYHn5vjum|teAdg71k%8>V^VNDk! zD6K}? z^%YR8bCJ^U_5Z;&R zWIUew9hnvtT&ksj1KsPpe^QQqAdQHfhfj9-OR@SWHiE;^y%kEzhf+t|^xuqXglUa% zb!_Nat487K(BG~rOFqQuf;HFx;qX^7k6wbK;4|oop@y?ceuzTO`NmJ1`+#_FQ_$)4)=K}IC-VdvpQ7pcKBxEs%qrptw(54OeFNqP1?>3;Vfu@6LyBbaWnihknWx!(nSNDjtFeZEF~R%-G2 z2nng~S){4KD6Z*Xh34SpnklW%DNhC4kd4y4v2kOJK*SAYCER7%E(8198idco^l@JD zt5OGZ*hUPQro1NEUjGDQq^T1Bi4<=>sn|b}n#Ha|qd`3d=fmxulX9Voo8zjKsh>!9 z+>UL+keCToIJNyPMW_EjX?LUM%j=b~Ra2GqpGZHspM_9EB2MH2SngOp;BG=s6*dY}!=k}!2DYoZ5x02=D_QLKF+g$tn8(Az1xlIK5*v2RO z{F_?;!z|!x(O9#mgc8tI&ixC`8Cr#Gxa?;NM^w30YwvwL;zJh+a~80DhZ!S zjmNFheDIKLKU2K$5i92|*XSF9CJTyt+}#>|N6;)mTgti5fI<&y!d0{^HdvV^_>oY2 z`A#VHUZ;HWnbhtHGgdG&>ac;zJpn6>0nG*G|JV!9)<+aO)5m&XbA=C8f1QmJ4HIy2 zP;&%LUr51K43M6#6`rjJKi%kuJt!2<(ttp|<_NH%;G7M_iQuio^v8Pu%$F2K)e-A}yk2l*7O`!NS`eGR-M(Tkg1 zbBFl|7R=#G)qUMYUs3&#Vn}zYM&^g$_R_+$b>K0X9t(uO5*(FUHu%F~b;HAn z!n0O*aL~h6;Q^PGGkRsZhjxRtH?cIxxl`Z~B`}(AD?BUN&3oY4NzdEi9^U@O50f0( zwA$8Q_X;NGCcrDMP7QVy?{dWQW5gS1}dRu@eDhW7JM!B9C`tJ zsnHSak+2IpNOu*da@2tFK`eiG`&67WXHy)qmF9SP@jp$G@Jsx~=t><>J?G3G+<2QB z3%h9lpco9imHOXEP28pIcXR2bDP)r9jJ|`i3W1Oa@_MTs3-wi)F-yl5N>`54Y|pm(u~+3k_y&2s)9k6Vz{Ua_i#;2* zID1$rdk-oftd-&-UA9}Y_d6vYW~d>)iEAA-U*Vq02>6PCuL$@Gr>`5b_XW*1!c!Ru z+ep|(!Zw1o*JbY*%{J0gDZy5PtpwXh+9E!jb4Gk53Ut`p;4cdPqTsJC{Xy684$U^oQyC50XxK)>7X5jb z?QfjK(`=(XmGxj-54QDSi``}}+ZAjSP)gQ`@4hViCTlM1!x^@F707T_pU(bc@9?*s z%h8w9@Kk2+P;M^_qBBy6J$OIb3s1pVRe#ofF5Y~5VX%3ttHV`XgVHVGDkcFPJ&}Ps z%vAf_9m?f#nN4uE>cHl|4!=3gm!0OaG~CkWRWiPlerdZztBGd-tH@)1|9p2yMI{r=rff8XFPjL$e2QRaOwjhHkSby!}MhQEE+W(o5{!t531 ze!`qB%ngKjkud**!q<205@9aHD~(<=?v)hNBigm#HPm7K9;=kCw#2%z(EtTHv0(Pp zz)YNX6G^5~@S??Dpw6_ZATx45_UAxKT=UFO0;H1p7B|*8XmG zL2%ip?+R@F*E(F6^H$G1f*d}mLRdj$1-o(gPvCCX`2P&d3BSjgm}-?@ZVOdRl!O!# zgK}^c05scsPGg%q)MY?36e=li{?k7U*D2!qi1Pi=Na2|THxupugQ5&wU3r{9F%^_POh3ZpM_9@wu6JH$5 zx!$%#aGe@!H~$^{31buSHHn8Y?+54pB8GbKA`|bLIAP}>KQmTbvD0?H-Mk~%O@yDU zi82XoF2~bVaz2U#F8jhZNoZn;AHzK=1?grrct(uD9h?*08T=3hI5ea|GQEeF>jGAp zw^6#Mc_kxItH{g9Xi?<5!ruK|Eqj+gDoAx@TC#6I!kM-}tA;7~8)CI&14^c83sS}u z#7R0lLnfKFprtegH;8AH8`Bn~rYXpEizORSW=vbqZemRz&qnUX48dA5_X9Zm?h`KD zi%St4r0y4C!XDU4RCx1*B{*dtW6zGpf$ptlXX53|OF=K^Q+5Y=69Il4_^A;|r5#@z^td1e?LE8|~%821Jc=jLmoWoMnWB5dF26#@nZ!;RvxyqCLaVq}JQfqUp zvU0Q3?Jk})G(PAu26Dk!h#Gf&O;0G;fTqQi-}dk6Cf>n}3B))>`T>WGcu1tr4^l@o z78w{>OouDTxN8sA7%D~XF;EPpI9|e>H8Ne!{gG&$ z&?q#&(u7n)&z4A2Dm4F^Hs1O~1n0G_U@YcW@OY*JomIpypxb<`+r(=&7>3P&joX2k zuGFoPHLLb=?kL^UYTYJFv*|47_Ja+Mnk8I7s`Y>^yUw0_5Un%}$o#9`g2`T3B7+9r zff<&g@iQPNybj~jo34A)wYdWQ{fxS92v(%>AN9iO{Rh!E+QnE8lLBI=IiF z%%%AY@g;V1F+IEJIR&26%t!2nC+Z@Dkf8jmO`nR_1*YJKp<#E=~LP0b09q5qXIWALYyo~iJP-R%V!i<%F^4~9CP{&0Z%Lvg0OAIlT{ zd;x@DsHsn4%Zyp z^BwVg2d@o6U2Km_T4R;x3Na69Q$8q^5-sN=l|Krl+sB3kE>0`Oqmr{X`4f^hSzce{ z8h;2k>ZJA$xR!O3^XB(JxDNlG4m)6egD+J*m35qNBxkP+`(C_xb1GX_IoAXKXjdF4 zRQ_Yin61#lfo(A1Il!hms=x3K8N1i#pC~Ki5&m#o+*YU1zo+noRn99cyZ|*NCp!G6 zj(V`d{~rv%?FY}+sZ8^iX;R!dekbM$`myUj!Jjdx$GnT|fA#kxf=;ZbJLgx$QwsQE z*#W2_zuM%RH37CE3vnn$ny~rC7z#3N3qD)9bDMO>e@n8L@i{dl*-Y_hNU|rzV@*lM z4S|k8O-YsvQd5#~i0cUaOOmw^@ZXXwl3r^|vMWgDe@U_uqS}&d4-kdY3VdX3Nk;7r zwE0-KiN_;~DkRyPu=zhEnOpbt-;(Sp*!-6yYmPQklVtN?LS+z=EDL7Tf+YOZl4O_< zN1bNpFnr!qsHvz+m1vp&wb{)&I{e!Gns`!NMN+3;kB3NY$Be=%qJ3eQELAdH1L=>~WHP3)1Peo*)ET0BLzf3Ue~6+ucngW5xeT*f6ulz?-ki!_ubjI8{{MdvMe7D} zR%TvlZE57Giq}L@a3yXq(0f>psw&JanS!rE$A!`9!ZegA=mx>0bF`Rmdk^221b4N|@65E2(|wBe*^=)F0*ma3`LPAZ_fJ)8J6&_9lVICT6FDaLL@B40*QZrf~J?Gv@YjpO}sLl12tb1W{zBeFjruZ zbub1#FEg8+jJgYclx&TSGE+}Jvl-eeiJ_7yd%x&}CF7r$(QT5_@lD_d{9rpJa zIa$RX`3evuWw2|dQt_iSYG@yvi^VeTTI|O(9G;}Zb~U|jBZ&pU03#ittIHm!v8Z#9 zwpXFt0kYS0#q2F!8D9kgdX(dAeNY( z8;B*QaTApfev+QFG##ekMu~A2uO)BN9?4nPGAT`2cUZc^lA5L*JuG=GKRA?eMI|A5g}ZZhr5AsT?aCq%?}L-mYnq@t8EWZhuH@ zo+<9!OZoYj^mp{1{z)dGQBLiAkMi?zsgE@36%^^xo=T$yzAX{aTM%3~*`gys(lUplRJs4h>;`~0Ld z-W(Ql=(-}GmU<0(wx&x}?ZpEdoS(zSEf;F1H6zXC-v`xLHg!rzqy#6Q1JO1oHE%Cm z!WzvEg3G^GZFP_G>S?J_-1EO;-@vDsW5{=lpbrbrFZWV5pO%_696;Ml*y6~2aephm zQ#p59>g&G#3wV3*4P{qw#mLL(#phSy*wU6R2t@tM1{okM<{K8fkb>$#SYXC05V8K~ zaI{^Sk=w+K)` zt{w!bI!JF5G|&$~jnjjAL1S&n!gZFdu?VuVwc0BcjRkjt{h_l@HMWOrr_R=cxetPYr4P14~& z4PGdQ!}dCRRAalyVs$oMWABogbmrCA46?tz)l%U#J-kg|N5ID5OON0|%c#&olp9@N zai_!$_4KE>o6x^K5HUt%DNf^JfhqsVz0V;3j;pUDi2Nzq146p<2!ef??0JJ-ISe+H zEX!bdWDk@14YukKSbwtRd)*>*1UP`OJK+k$;kIAFT9d6d*k@#Q$<`TcGTGH{zzPjE zlt9VSb06LvA+Cc>^{y$tp~S#z=!gL%jz$y^3|n(Q*pfaZ@f*dVfFWaA8W z7ujyIDf^yrGjoyrjR@Bh&NdvD{|xpana5y9$rh6>HrN)j7s=i-*hgd&$UZUHLbBmx z-x$n2nebl1O$HoF){(5pV0V)>A=_`TreqefqXxTi0PG?Tj^>{+*m1Jo$;u42jjZS^ zH{f*xen$8$9Y*XA<#B-QJu=x~)5u;SYi_U+WV6WbFjz0LC&&^E)`DyZSrQoJ50k%Y zKVTn1r{VAvSv#^31}i3ONcOnFR*_ZWP;LHXgXNN)C!1ri$z(j`ou6$m*}V^NE8$WD z_T3BiCD{iC+ei8R7TFqurIIZm+hDLe$(|!CGFTMZV`TdcmiH6bz%MJ@Rr!A!@NU9; z=CSy!?q1}i3O zPS)07OUWY1?lPEC1a^59*u4fzB|Ape^nSL|e8-j@!=XlTH{l?|;YT~*a6Q>5gSp8* zBzwwWrQ5+4lRam!Eo3i}xefLa*#xpz47QMLxNx`JfRhRDC0t>!p=2G&zBbt1WKGBl z4Azv)Lbl&vGq-_VguaCQ69yYa_B+{Sjk%EweF=*QBM*kEQ&X~U$r>7LRUz1WWbp=@ zM)nF>SA&fpn?;snuwG5c8cZUykX|M2Afb zrjUJ0*4AKi$lfFCVz9@_ULosguoh&q$Wjef^)1*FWW&H9f7ufKNH~P>F~i|kWPQk{ z7;Gt7JF*uIHk+&=S+>E(kX3#R_NKw^BRfy_g~4uj6CNU5Z$OD`E7?|qZTbf6OS1h2 zd!OtrvJ(cINw$FOg26_SJx6xUV4cVw`XY4Lu;XjMu0st>ewx9yk)0(QL8kTpJ|p~@@Cn0VfGnSEy1}NAeL?0n*a))M z$#M+Vi|l2xcMR5oY%19o2CG`l{@=rd8w_}AHCTVLVuKZvbtgMyuvKKO$xa(Am#i+? z6@$$ry9%{5`Q{^`lpaNP63m?+W5B+Id+D&X!P<~*Bg7EUy)5Bds;Bj|65A&$zbSv8!E(vYll|c~;7r0p zgy#)5ifk)cxxxC9eMuJadnilVkiA9L&|qO?3&`RPcJ33f=g7L~4E?_!2_GZuYdHLh zY#^D_U`xsFA$!nZv&n8F8*i{NWcA5r80>+gZhGuZ89?z4o83@8!)O!lV1NYae3nh-ri;3A=}2#0avzWc>`*i)1zL@cwz2G)VtXT;_hSbbve5L;|u{CcmEg;sB*jENNg;)z>rw!~GVl{|eFtAR<9;^U%-M|{V z2>wp+F9QrAc8XY~p95|8+X`U&fnmImm-WTQ&xixu_`yf-*xC0+XoTu2#(K<%C2^uX zk63#HySf+HG-7GM^zsK097V97LAYlZuuNj33~V+hVM)aD4Qw>AXks1%OD9%~*h&M7 zA!Z`>iGl5Naqe>EO@IdsFqznCVn+?k$GOWvVrLC(DX~q&ZW>q+vA2nte+ksx$*sWV z602!oUvQd|_a^P%CIu6y8i6s#0W?+fL?8F8dn2lICvC#$= zN8|1Oa$xzyH2Zfo$10UzkwJKjBf$w`ih->pRzhrpfn^cfKy0spt)|*pPVAV0HF*b^ zo7k@g7PFG}?<9gZ4KRYee+V#$TFerPS~wH?XS(4nP>G7Tj* zfLMPcau$Uqjo2WA?j$E`vBV}Dbc={JAojk2t)y&Oh<#&VFMmq=_s%kaQw@gwNqCOf zDgztK$<nk#YyH(myMxw5WZmw=({5Z{nIBThF z-X=EN;8{#;F0rKs=K7Oznn!TG0p@erU^uY@23D6?2C=gS)_fDN1Y&<0m_*D@EWAUY zy02~o7EWx%wSZDOM(q9)j(;r-!d`4YbqTO!1M{){P7up7u&;@g5F2Y?18FU6AeL`n z#T-eN14E6xj8P*^4y%FABQ8r3Jxq3Kv}ztBzHLNoxD6496I*LwEkz9wbDj^B%tlF1 zAhzG2`+)*%Cw9)jRuc;+cE!M6W=*;7F9sNt5McN-t3@SN&%j<}t(+j%#=zpKT1$u} z8CYFn8;JEWuwts)<-`UX*o&+^H?dI(c$ZvT0s5FKcoM-^4Z;z$Ylje9Vql}G!<@wa zWnk~In%fcEX<+@A1B)Vd+`!_9RRf0R_QCvqjORT4XWl~FhN$fcT zyU#i6He#i1k=(ZCJaS^Om9?%LW-T-)gAuzjvZ6|hySdxLc zi-DB_LoH2$TQ)bs>NC%hR0SN$^6d z+^bB`+j$*D<+#)kmQ2=sD9r?l%Jl`nRvTC*u`|SW8CW}FrNmAcSR}E{#C!&JpUUH1 zVnLk(&2f&HOsuxc0Nv~wQvtF{;pT{=7QrToe*wyn@?WnJN)a}MK73IvO3_7&u67}_ z0S2$(RF$oX=Oe!M?HIn*kJ=ZNUW6DcLuhG z*k)iT#1gn=+d9}W_?k8|pvcvwjA3YSmw6a95aLeW+ z&~BXSh#_l>U(*%eg2H=9^Psc^Ecq^CKN#2+CixMu-wiCB&AgbH#e}SB_V)=Y1{c9; z#{>D@PHa4}m_#gCU@mVn13X7? zItd*Hc97U}z);1j;Fis8VFa_)Kf|pKvbllgb1$SCAEeu29mr#XVT+kK5H%yV$iNPA zl(5d@{Of%KJjed~w+zBMR|6Vx2C?6WwK1@8O2~J_HXGO$4(fY}eQjWyI0mdIcG1Ax z#1vwG6Vuv%48cNzH4FnSgV;o3Z468dDuao2Hn5*)IP@TvV_?gPJxR=Ij1@zOH72&s zpgZ~j+rKKo(boed9>U36`Rl;)4Xl8Zw+qBRGB7)_Z;4GZ5}C9Z*e+mbt|4&C=9kbf z*mvep>FUOp`X*ydWslR!{|fU~L~w!84Z9P2kyu5Yv?4Z?*m{GmIlWod zp4btC?j_itY7=0{+DN$NnA4C87p@&m@}AYG)DT9wWkktfO@Qwb}jsX`H*651}{Hkj?alUl4i2{GUu>H6J22ptkbQ z0XD$EOvK8F6&To8R7~FkL!9kYOv$<6O{4V)S|AJa1D-ZULw4(?<2K1s{b`Gc*0;XiJh#BSWg36B5HuxFaw)L>;SRJ z1~!D)Mqo(X$(k}Z)l!@0eXX-z{zZ(k+=%iD73@r6>kVuev9ZMV8dy_e{fT{JV3*ec za}fL4z;+Ug0fsEhhg&wk{jpwtCvK&X&9Cd;D)3QkM!pEc%RE6t-C~XqSPc5D2&}6c z%NtS5!gs{91)Z}n&O&osL6RTL`S@HqbUlf8F2H`>~okC(2i#&P6CK7wj zpgYP{_rb&})^4^C>p|@G3OcS!KS``&J!cEC#>8A(48ny3s}ihOSa&cKF)7$ETW>giE#ndhV zx!t-5EM6v-q!EDC3Sy&)%`@m`5zEq&8V5I&uma{{Zty$4@x;1=OZdM)r`x7QQ=5>7 z>sy0KPnIE!pwGan6Z^9e*czkf-(m;5M66OuAfu;<9V6D*z;+Vb0}Pq|5N@a+ZbC!- zKo1~Ol(R;zZ}E9z@>jrd?Ld;Zy%t-YLsmzPBu#ABDa7s>*bt5v&uZ+~pv-dotKZcdm@zBHewA8OcgdEFqgO70DoEv!UZG@yAz0f?sZ_(iP;V8 zAhG9&B^cNmV*QBqGO&5Xx)2*-V3UZo28PlPf!oDacpD!y$+os@QDK-&_QriCve`l( zS}Ghq(rh0|jqnR*|3rVpcd)YgE6t}(#kT29_w8&X=)4$^jH8sGUBo6CnCN~V5j*BG z#AP`N7Zbc>V8ZNn5nE_P9>Z=mp4eXoT?Vmdh}Cig5>CLXrJ4#1B^~uDbzUWrUG#u9 z8j;$3HtpZ;MwISUGZADn)WBL%^!_OT_M(Bk!`AZ=n`2b<%T7_xAF zKC_SqqZY$&l6SpEq`KZ`lubtIvZ*E)5IbsMkqdxL*Vu%@Et^{jHt0t9ELo1R(1$g9 zVPeYK`kwj}c~mSY-eJ)?5UW@eG@%E%)Mf-L7WU?`8LY%A7V*ZgY=3j9v|n$70|Vw&4(Q+lsBf@I%Vl2!EI>SpYB%u86x$%*}-#BDNcT zIk^VBT(c0p__4EEFMg59KG8MM(yz0Lh7#+n5g_>&h@}(DFzEUcizn9KpmVh+*o0uN zL0FGi7_kWk;RC9hKW70eFzC(`yF~0YgYGb~W5iY(bnA%iA-2k(n@?=*EGDwkAe>Ba zDG7HPgijNjP3(Jv?la2!^T1HjcQ~}fb9lu^w3&hBShWvhR4kjuvNv=hRS5|1dh2`YW+;16xPzYhcLWe7Nz_ zI+o?AUAE(scG-N2J~Z;{F5x{Wyhvh!rb*SsWcPugR_)Y`E@G;oE$^{&jn|UMn8RN2 zipEsy2P3q+sOgOLvXQZ!RPOP_mIzGjKV9QU)r8;%gK!14b{MgP2G*U`{^tx}KN?t- zg}^QmyKP`kQ^_6!hSCozV%B~__Y-D!SemFdbu(i$NgEgV{^%#>>s^9fGzvtuFbguV zECb79SDdP`jzkT}=2?QZwWtO@P?XJMG@quDk847t_8^bZ29FY`BK1jPzO$~tK=T2? z#spmk;ap->iJ8s?=q3;=pAPIzgD#d+vJ1rO7<9FWeM@Y!L3fYSuU)`UxQlShFWWvoYxWb3XZ;cLb+!#B*BM`OMMl?vN#s$h=Qdr@m&YxS#+X1w!8 zWuM}xkwxr|fmN9bESXs4Zd&)n{P)^R09z8QtAif%equIaZ4B%~VnM_@8`$f_uD%Q` z%fMbB_5-mT1M5rd5V4mGtUWQ;rvOoH_27Y(`W9*hE7%yLi#0lR5hJZKBHiNl&rD)l z4XhGNHI~?y2KFPF_b2wNfi)uLAXaW*u66kUV*nx(o#9TC%{4_Pux2Bww|aN2$4ZRY zSo46k3gi7T4cHR~Ha`#8uf$ReY%;O0iS;(Hr-|(#HpFFs9SN=`IL^Qt5nDuTnt=rq zn@MbrfnA;gY%H;52KH}a{edB~Tj8b=*B;NY@%NYB+V5*U@IEVn7t&zeC5OVw|#LgSo1Y+M4`_sTOi5(zj>7kDvF7pODPqqX*!{`CI=BF$f>d}| z4@Xi^5Ak?is#k@$(VqHmk1{+Gb4Vuxgmr~zUXyCG?!28dPcd_;*F zAoedUBQ7Mqo9bgD!OceQQrLUnB35x`rWUa|#7Ygib5zGuh@CXBT5e#^61!|*_X>eM zMeMGDRRiWyI{-u`Vhf;;ZNFnAyU-}vZtBrzwK!|w_9f!l27IpXy>U_N%&DZ0 zyd=JVKZ}I7ynzUhYY~>i?c1l_XzA^z4eDx5EzJHh!iI|bD+^FXCU0Xs{B|A~CK?vN z7SO3@fr0mO#;Gsj;L1bYhB}~yz3qaT>}!oHodYG(4-}~HlVJ_R;&X#eU7$sp#5lj< z=4X~DNM|@j3#-P&c8M@8gFopLjeg{J-I$u3m<@hi@-Y8F4ol$iP1PA5(jzp}7`7wB zPjUT6AcJq|^Slr}oS6y3{W^j0X?pmDDM(N@rf46~cKQ|=(sRNl@*Tk4A=bt&jQV<; zY}Nu#K%#wbia@OdeRPJ4$#A5>@D8QirNuc1x348$1YnKm=LggrEi7*)!aluTk->lI zGL_13jDKw)`M!T}r%|8;opgd`Oi-6Vggbdy0~58yP&G#j+aQD2r?`4z|U?L*gWXTBi!54*iQe7ZN5N@vx#xyMI4iNw{B)mA$?_o z{^DZLKdaFnh1>VXS*-wn>gP|?R4wodwceK^P%FVHjX-TihL?>KETmJdTAb62&`7emcK?q#vheaG=M0pZ&Cp7C~h{J^PbZMV<5r z&9ty3)DxeJFi}H%gWb{Jk)7`Oqklg<&&m6(W?xBw&45P~)|eF6w{>k;-o&meW&3wDdIJURDW3vnhMcJg^E>uW19 z+T*DM)O-UzTZ{-!+-4aKX1GhKTJvZywHB?8P#hsGYr6{I!@b-S>`_kSKk{yxJrd9K zm12ordl5becM-uFag$7xpRk3MBhLk5b>G8(k@t}H+jCoy+ddv_3vn!=7%UN#giHkY1#5`te7%5 z=n(xskRk}x*bV6;*@37d(I$BvnV+K1&_3eMfA7(1FAAR93je}M59Ak3Kn^`{TQqJx zce-%LHXmu{aX0TdJpXOI) zb_xD`ix~XXgOBOVamkec4!o)}uZLh@>SqAxB!7){1FO6Hf3xlgP8m#JTn<%8(Mm5o zI0%1&Hz>uiae*wCSzA=&n*vS!MHQ#7rYq$4CEj@Bj|=!@bu!TcJ<0^$O!Hm*Gm42@Lkq@N8!W$d0J3E z#D`O~dFOvzl%@i37u^U=CwhxdK@N0W6U`gCXkNyf$dn+;J5w*7G)A2a_JRs*z2|ho zJtTw-ek(XZZZtk6dhk08hOoGFdBi>Gk!mY2qMkEkvKb;9ow`Djn?EF(e`zF0z=1qv zdjHg_%{&Ob3{R{=ktL~35dp83F~5-0Z1~cJoI*(31zj!Z4DIkPmgwrl1n*u+){7oQ0iW*yI7A|M+gtD+_T^%c0KGx zgpmO*po{A`z3>_TTWoih9iYRqpGrfzaXrMZP%usIwcBW{|5LXQWD3l7d1%W35z(^fv z5&%Z&KzIPi)dBxZ@^C>_jnR>7K*TlD;J5>i#_$CU6l2oPEpX%NX#FB-2!xw)@qk#S z&>HQByua&R{K=*eXsiqCpBWuea{#c; zESk`0rD{Yz03~SF08X7+Nyn=^4Bnif5mz-p>NoXA9j+FDSzU*8Fl?ubN=PsNCLOH~ zk^r^(7C=!-7OZ*`P9Ra^^0E7WIk+EII;Cq9KJ6+Lk#e2X7M6*f0XXG=zhEIzZa$DBHHO` zAtI;%y0Ijpq}&L1{|ohkH|KCEA=)`snfHUGp6g?fL7$|9G8U}5%6YM&>T-h6D-VGd zweY{eYU&IB4Th@&{~N5OrU_6*>AQ8pBZSshb1)h^T&!E>jn6|+*b;EzCtBsVSA@9v zT*6Q&K*oh;w0N)U%@UeY9D0ajRiIH;H-5NLzK8FTM!BjU6wnO21zDg~X$R|WmE-)P zHWc{>yuMxx61_6mQd(t91Bi#*)A@`TDuwl3c-W#gA+1(N0orP6#(#t1YKQ*@YpG2I z7^n`s*fPTJclmuY#6XjR!e-m6(M~UV9g8`Xz;Mx(kb0oN?=^b3z~8~gNa3u+NMW_r-UjF3_GNbmF=8p&yp(9m@Wt3DcbA54S{ z&%N}0zg2b?kG0VJNN-u%yLd+8v~xWurbeuelBrlw`!AF`A4DSK(2^GKX&Y@f4Z0QQ)ozFfDy(UECE`}$ z`5=g`qwp6P#3hrQxLMo%lQR2fO9NM4ZA;k^O*rImNAXM57%@zXShi7UUhzCd{y^^@ z=Cp$_8<}`^1E`JFV`h zjN)nG8O2+oSuCgL>t3FJeD%;a3$>>k-T6XX*^otdLE(LXw6e*wnVyWZW z06#?J9z_I$!%EG2U-!;u$^jEZO<|yQTYjh>T7Zjb>93^wC+U76Z(ufD_gB%wGwGN6 zS3^QLN7;g+=n}6-cSA1%jd~+b>kFPzb#z@;L}^CQKcYJ{*A2Ifv7=3#$L zM-~<{3+O$_2D%G!!YuY?7BR>_2kF;D10}kT;<%aCl){n%yr#ek-;WAMI%oiQ1LhWS zgUQfSij1*-(~5_i(_DDhs|{ei3A7Tc^#s!YK2i_Nn!leSs)lWp5hr9Tf|h}9(Y_hF#g#A1{p$B8%l$hF z7`o-5P#1!~L9mw1t421X&mrJ*BOttWfZ-|zyln(DGy>+Z0~Q(qm5qSmj4=)YxorbA z#5J&Vyky%=^b1U4bVFI(b{g8IpJMIbPzC0=rP%JWa8 zCE^uOt2+V>#1T3JuhtjOR^Gd4NoeroH{}p?tZuERqA|)_kled(Z{?4RmZ;eBuXT!M zkRD$I{-w*aV%2j2_%%e-wR%CaKdZOW?UE%Sc){0->ypJ5Y&oPXyJQ(quQR5r+mXJ> zR|5j0UO!r{u~~Ldv0S#y4}SWNvi!28ca6K4S0s(H77aj+u?Jk9rQEx0X%c*3mQw#W zOa0WXxBnDhFXjz*7Voyl!V24oIi|_`=l*3lL3*qlf!3ljWRj76ArDB*XM&6P8UeA< zvy_*Avvh3prWS^WJp*^E&jCUTm;O6d|MkyQ&i-cUJ8T!KisA2Ly08Y*5VOv4GoF>l z&DfRWt_t-}l9X5YG-#f%g1)`XOy&Jb-16E3)OJW|;XP&=fBDPf1kv>(Wr1pGog#`6 zhRR_vvb8$EbMU>+Z|$hcmR-ur_ikSv{Teq&ih-wgP0B4mqe3s_nnU|0+T*Z&|5zYc-rPOC>UF(%;+C!_&5V2tT z5OlA%f|W|YTbi|_kc%hbvKuEV)auK7 zK?ju@%L04a*r7LL69o(F{MQjDW9$t3=va~lQp^Yui_Ypo7G=>z0%7WOf~i>L zd>G6n__VcX<-=eWz(6!uk6qo$^JSL0O&)s)#=YNaornA&v$&Oy$}G)X7YZrHAh5ds zM8+M3T}+O{J?fkCt2zqtijlP_2x&RwsT|AIUyti`aVXu>121Vv=-MzOaXO2RxT}zq zZiy2^t@HVmj-$X;AMqzZV!W{YIkE|3_eG?LdQOV!IyWuGg&JLji9JT-pt6JF!GRiH zO2hP6XU-oOIbiMvm6ZE^6VX&6_%eg8^#bbMR}Y~*<4FWWITQ0ANVnr2QhY9;x+61*Fe=e zt>rc7<%L)NWOlJk`LsyURPpX#vgoYB$lQ+V1W8b}CyxQxU+G$Go ztPsx>PA%0k=pvL%YvtM~T6)eikN`{s8kMSPuwI>oy9$s4jCMUj@vtpYD=Y~qJa=E| zblp-v^4|!tZp|>83Vl@z{=8Fo+yv7+sO+LL?YiX|Ys-h3XFpJaZdhtrza&$UVlsr`ZJfA&W-GC>&I)QNLPH;ijo?T;lxEFP%TD517REs+ zY4tEPZYOQLDgOCSCFPE#Zu3nD45&4{sidxgKkhip5^F#)sl_vtS$8Z^O_#y&75xu_ zX>}if?m{bx+N+k9s9NWL8KjheE_h^+a{i7bx`ltb$P5ZH{zj~)@Ei)P*4B7ns8mIj zIsQ~)|A5Mxvb7xDa6M_P^VgvndX2vn8)*EDkoQTgz5|9-QYSGx7(XR6gjMwUzl}^` zv^kGMOM%j;6LoS2*g3Fs5FTU%W$Qr`AhfxT(omNj4X+EZnxF?xL^5c?xDrPJ_Jo40 zuQdZjTH+K8UJA0)r#R`QK=vPjog*H%LvSu~2WmH_)vW^?{{P4bK-w z$+4}6`tvK1eoOP<@3$yj{FcT+_mpS-mZ*++F$S;IgsT>kQ%yKMB1_>t3zJmnoYshl zXJs;w%P2f}@65T0MVGmppD3ICmRMIQdasuIG|!E+mgf@p&&myCR2_!rh73kd7T8qbFCduj&vdFG7<2~Qg0y`As`wc~8pl^;o;QL&O&^?K% zsPlYiYA05{wMxcdaky)+sqCVW{CCrYxIqhq+O6A4Iw8)22RIRh#bvB4gxb>*?^);b z3Ew`&?ObwdDE6ELtKw-GSJ7k#&Iblq4>*a&3zkz||3&w(Q=uqs zrNkqi{nlbPl7{c4pv0Tj`BULZ$4ilI9I-IBQ27t6q>-l3XejR&4hFBj5RiM+5*?qO-Aw=lM2kOU!s31g5v7O!m zlItj(VSgYr2A zA|W{7?-8mSH9!1gX&bySSdkuBS~Ut!OU%Pw`}}suMla8;ULns|90eV#WOzRzn4^ zzGKp@6q9(1P(89sc_Bz@>`F&Vc9Y*FK^z{P9b%6J>$FbXrRSodwRix{E$h}E^)b|= zsjTi`#7LDxKfxn`c*NCFa332Qr6`4whZAY{{0KzbJ7ke^-0@!W0+t^QX^-sYIhWz_ z6+Q@>HP}<`ItEkNUZ+>imDEn5Yo{c79+X|~=DwKMAzdpc3bjdfgJH5CRb!olxeMN9 z%kAdLdnVSpwHHp?{Qlkfprd8yT0Th6IZ?Jw%S7m=vTre>E=t47N;u2Ia^<(9f=4#z zuwwHXI^=fqJ+5}xgXv*On;RO=D)VurM*Z_JR=cnh>uI;J%(r78xLvd5$byZ3dQhUu*L`ZpR8K?TUtvfuO$ypkP0iN!~$a zq|1tEeoT70LAk%mRubctkXfZGPR&tOV93fjC?nCgwOYn z;s`|zPs2p?mUU1`uJ!sCx2>(dzHJ@0?>7AE*>zaf+_?pzY1TF>f{)*}hMQ;pI~rR` z*U#Ltw)z?E-RfknHTuh2)`%hY@Y~h_`*C^)DpACL9M--%2-DtM);1-#tl@$p9HEZH zgEPX&kJ{QLn2@s_oXLU=H8ugZ$jk-ggE_o~B)`hFwmo7k^yAnnpc2Fd(?9})M0|BK z=+$2^=VanY&^qrZ$oY=>+)_F`6C3yjLyR+epoPlOKYag2r8=w|X^QJl*{ZK|ZA47& zqO9&ZtX5fQFzi$?FBCt_*b@J+&c9JfS!tHyg3EA{!z^XH-hufKW`Czc%B|5y%9h|A z^~Pf8NyFHKC)S5x|CR#?#~qGL)&=b$!=-8N6gDT$`y|lzfkNn#Ry-z1ozUf;u2!L_ zx}c3g#4)9-C$wo`u;SUJyuL||t#dwWi(qZ2;z&h3mS7B3j>LV|;@Kc@=G-fsu{*_- zKTO$s-%{80T^csDqR`jFgV^K6p{P)yR(|fEQ2uKMan`@I&)Al>9Q-@6S{!fZf-3LM_qK}`97*G zEoO!h)6R%J5z(-^8e-9IZnyA?nZ>-0=pH^d{sjzb%o^3Z&udx;oSRve;6GRJd-4>5uhzulI%?H2SRF8Wi zpV)O2&LK%q8FpE9_E!*AIF?UJj z?leY_UYSq%^)E}qnlZ94k2)2yZg9&R{wraBTk15OivC}?OGPnJU)unerVht{(;k%6 z7hBI* zDMp3oMYc}mq1tK?+-icaCv~{*?Q>`ZzD@e`2j%|OsR<+~``ICPKy^S_Obx~IklJR4 zu5-Hfh_bqOAWPlkiCDwh=UauzZP(&hl<0#PRcC+9JHe3 z-bD3ts|gm+y&cz39C3L2I*wjBa}Jlf?NK0ws6yS~++Rje34aGbb&g3-EMZ*_KkT;u z!5%kdkfR`>PkM0**2F=YHyDvA_>D}8ud;+p%>NVTka_l)sXuh~IF~t?eUO>dubDI< zD#eeIQMLvr2sl!khVgaW{5R>oGgP>X=~n6Pmp_~CuZD0{Ag{o>)os6xOsxsdYp^CX zKXOe_zA}Afl`4*U6}wk@_L?FMpA!XS{3AbWn+OT?%WvD+ytAQ`Cn0anqBB;vqFl2` zQ4tTI4?Rols}L;UYf58Dvb#o%7dtw&p#3c{Rd~1xswPxj+u@$S7fw*r!t#P0aZsMq zzOCTFBgS;E6K*$yOnaG_T6;AW&jFtcIng$R@iH}*!u{%3A7e;fSW%At{qS%!j@x@H z*}mg90N0&`S1fopm1~LSF+KY#dnKtsaMsVt&yrNPKS%;$&3g7V<<;FA+!zgfl)Wbm z`5o*_E70;4S2Fm(!|6EXKJ$BAJA`el4=n6-X~ToSE@-5nmmE-isyC> zb5$L|QOfh9SXeGqFKpaawYv0JQ2#;imE(+(o1rS55TBQ!F}N;l zncHWal3Yvb5CTM*S_`wZ_LLdX>>o5m)BfoFl(d*6G=zdd8_WmlJt8pk>u{@P4S$LF z1r2|N_*F8JlZO$%r{Uv>pVaW~#H(bIw|NlpJpz9&xh(@4YXLnOuv&{yn|M17??}9u zII0G2GGRQcJAsl?m~0}L*A}h^P3Xca$I17Fs~%i`HR-F&ut^R2ZRZHEmnu+BUWMSe zGeVuc#V(Qn!wKS7#8~+AVM7&NP3vA>1qIq$3A!b&M8yZ^{FF$o(gG% z6cTGo7dj9Bw-Ys8n2B}@&rUOmrGEH%#l7iz3WJ8zi6A(~zerRpG-}ugU%{5-WfdkLt_lIqA0{X7hr{XlMIHA> zxzfa1v!*hwuGBJe6_d9xbD!cEN7?7Ua1mHo-U_gwY+bR)=Gq~d%Gd_dq-y8uQuxrL(lf^?ml~iW z(b2e})Xeod64pA>BoO7D+JW9~+Ix02CH|M&A9{ZiqFicSvfsM(xX0ESM0lq|^qDSj zd;iizy%X`y8vYn@i+F6(Ea+QkxRrQq4X;o7>MP4#l!! zj%g7F6TgN=g(~<3I2y#v3}6$GRzzX)F@jh@qffSd1)n%1P*V#%poQ{#Ezs`KeC3q* z!sKn54^uoBy`O5{Gg{z!&G)tDTdn!_YQA?h-=~`IP0jbd=3A`!mTJCY%{NE$&7m)E zCekVrt|=UYUqBQ0_M7qY`EgAG57cJqn8%$%)DQ$uS0)(`ri`aRq1a*{|@2zbF8fmzsGzJ zPN6(~ZIF`7Zwm+Q|H`iu+}XX z*n1k$gziCk;xOY`=#)1vhl)jQ_C@l8{mm~hL-r5LmGmZ36IWCCoSs{L+gdnK?ad35 zSA>Y+dp;Y-^NXCk0RF+gL>zB6j==eC9YOv-vOd@weWfB3i}1Db!Z^$cuhr6Wx=p3Hkgm1*D!rOY^}CNkbgV82+w%yEne(@p zg{x;!X|OzTfC?eW5bZ1imZw$aA1Z>&aM8I+YP8M*roy`UOTmY^s;P9O-1e_Xx z|A-*(T07$e+!*j0yOdS!yLr@yI7Y92F;6i!my(8FfbIy4_*Nf=rae4kc-S`sVulJD zVnPL=zVNl^?_w^j{t7YZ8YXF}J$PRsEgud=jsy@C@dAFrhH!b`-rzsuNGFn_E z$DJmJn8FjG%@q!ti*6cS3;#(IZdzU8%~FM%X4j?&<$g_j~x7pzbmC^xOV|we!ECpGNec*3yZ`L@g9!t<_qTkG9;- z%5uUV>&t~#*k9fP5Z`YtH4kZxy0f>D+Vyu=`QNPXQ47%4gPr;lmJYDr=bH>(ep~PV zPpqh`ZyzjqodhGt#d8Febr&(ujCXc^nBl8U$Z#MH zVx`F;M}aJgl^TXjK&($=rL>Sp1l@~8EDw+-aZ;1UCvRtA46qh)15S(sUjR@)n1<|x zHM-VE84)MF*!Ac&WVnhbhHutS=s=E7ADsr%lx)-a!oj#Si3CjCc@Dl=VD!rVk0`4Py;0Z4DWjf{TE)Q*eaMPE z`U)~;{_%=Pt8HQO_*=}r=kNTUa`Gs+)h<(&y-!F_MvS?REC(aYzTsz(;jv4UkSC@1 zR%wXYjbFcZg29p|#~;0!1=afilgwgTFrI(p%~&%}}kixBWo*y6bxk;^o~G$P5JU9X+5r z0~qz2c2e!A*I=FRFwy27-!5Rbe*`t4PDD$ngI-la>!gaUbV5E+$#jP1vE?%O}_!{v~$y`n`Ca zTzM~E%6x*!ltme1G&N0z+^H9utWAc;uU4CZI^oCIzvH{z46N}Co~ATwFU3~bfeh1s z>?LJrd#Qei>E<|PdV6W+WBXYWo>->_v7(~)zD?ukA7p{Z6HI->H)EB?9i%5hGEpbl z9i%SLjJb*G)Vu4RQ|KnU(Rm!RI|t!-pLf-bai;uty_4{xTPfIcw>>J-#eg7WW$3}CXU?q7cgZ(y)w-43+6$^VyU)lWW#Xib6U=_QQd~J{nsGd*Y z7M<+#=@6mebHP*U9uOfh^GlknJkd#NT4xL>VMIb>bxMuQYsi&BuZsE@-$|ufM zlKVwEsmOKp~J{`w}ujp<4BGdWRwo{%Wur3uCsBu~mbgh9o<*$mHlWa@Vx zlWKsZ21DSGkiYpyNI-8Jp6YjsQ~kKy;(q^rJCA-}2`2dLD;DMK$BpasPfWgbmul5q z6>-3A9=K8L$6#FzeH1IC+mC#Y2-a@<@s)A&O%^7s6%j(rg)JFDrLRI9$qPt@XTF;Gsv zs^SMG&7_^ogxYzcaxO`#9h9h)CrQm+O(4NoaJArv)#@1P80L8PfH&$Enw;uiZG4PF zRso_Sca?=CgX!1+Q)lrOY)oUi5q={DuUkUNIr<|!9pQ0bIK-)s^zBd>{Bt?6^*ub( z@pMM6>qKVIZ7*P2ECgm_G0a=uEEWv;#>X2@Pq?oh z@+>R>wPwNJe%~;qyfaqo=A&DZ1ag^&-5neahpa>$P7C+r&DDG@OzeM0`f7rKTKx;Q zuvSXnCr}T(o&Y(0&g13)DYA7uf-k$L0JER0xAK{hmK$)c3?d&l2oy-V$AkjF4Iy~JF z|2LQh6%^W+_oT3D6rq0Gp+_k2^}f#I>IK0A6Q%bbp{PcRb|RTCHIiz6+w4b3!VD&B zHHvV*?b+K|%J8m|%{51ZYGG3ONF?04p{G1rqlom|>OVpeZcwCZ6b<~gKVgehln;k; zbskMLiYUMB`$s4$4>d^q=S2bSe%t3diTKn;)TLI9KWh}xe%oSFWZUhqp)8KlZhSEh zMrmDSkK^he4sErWC!JlduDM)tqul3i}EUR0eZ@Yj-aDN0MF5c|lp9 zDz$Fa0*Ux-(MUiT{jmTDq&2}=JZH5IrhKeu zWSPI=BQ@%v;RRbUN$4ik9Lbx@FoP)oY3>LHy2TEYjf}x&0N8vi*tqSh@LOLb=(cZy zJ6d;_z};S_9|L;sRFcn8{HF99r@YinnppoSo%ja8Ox=yXYZ}mR+_LUcvL1z_DWd$KN0|ig8_3S=?$U~&+1ncQ zkU9m`GLPdILZ$rt5C>$r)zdFm8Sj*S3d&QQ>C(JdSbQ|qAc~RPl8F?TTMWiX zq*g_!q~erPkgqqIW$&9{AKFv87&Jlg^~AjP^AmlPDo;sKL6eo%Pf4xn?t$T_4`O0x zU7e}E12)M&bG z*>Gd1o(b*Au|3%ie}<>|^CX#zDni%@gdwB~q5kC1$=nF;ya?~AfR2T6F7M-5co4(h zb&lh{vQgzdQDoEJAT%})E34!FgW}(#9v%6BN6aU%WUM5~k=|-i(l#l=LKm051_EHY@l9D=|Mt%?c_Ym}q zYF3VIVWIBeMNONHA=zX88K7*gd`k}+{s)3uYC%5& zl+B^o4aCSBv3Hv7O|1QELEi(E%|TD-K?~y%bQ_if7@h!#XYw9o>0xX7BkZ&mcC0U> z{r#dIRFaRNJzCH=lM&SL-Xa8@L1L$uBIsXQ(3fvyVrtp&&Zn7}YBKP~=Ljs)0uO)2 zK-=|W3_OlN%P9o9#%Q7Yjx#ju_nQp;0-;fN5&D!Cxce3Z&6grz!io|m)W()*TP<)~ z4U7cIzs5m1`w=g*J%VT(p@dtWKv4WISqQp|pfOJ)=$=aiecBg6VP{^^0M(77l|Qo!i&YnEQ9I!q7A9(|s2hB!t>dbKC?b5{9*5fY4uZd zN%+lcW9Ww+@)!Ja@@KtJU-;tL3LPWI?|vRW+<|PTFYItJe0ZcGkv`kekKqH~-e!~X z+%q_kkgF_sM#>Bh%T|7UMyeZptDkcJ87#IP@24~vAk`24yq}Ud0O2|P6nOyFX~*0i zr#v=L$_W~w$OEM>QkQ43%6N=0blSY`o>9B)4jdCJo6WN#syqavO@caV5Rcv6=4ib? zu%HmW1^OE^0`;*hMHwW;yRz@10qPGGvzrpwS&}B4yReP{%WUt2+UTtJ!4JLSJ=A|h zOI8r1b)8P&ZV!Sp8bJY8pDgJlfcUvGIyy?GEV_XrcQE`#;xtuHA3>-pXnqYYy(M*MpCp=IWk1* z9W+#_GgNvbxM-rXeyFr4WK*wlrOPm>M@Yx<(TZo7)V@l5DVE!2UxOY{z8EH@R^E;Q zU+pwlsrjsw(KZ$$wzCPe0c?o~)EB3@zPdmgCfxf*q9hp3VL zlnM=@feAn+EG!UON!pd4}7A410hRU#IM{s8i6ra2haD9j7^>)e&@f&I%rJcL)1s_bgYu!=*ZvA3KC$ z-*aAx_;=NsP1OwaIUe(4c5&+2d?zOwHrnD$&SK@{YX`HGh!Ik9ji<>zdCfsYEj$>d zZtSlekqDD`#0@nGGo{hfO2G)J!Q)Y0Xv;Hs4T@j$Y=^yy~@#awRTD8WLg} z`=YWi2M0Tje!oK5og>ADq#RqWT+fkOR4rpExj3!PRH8;ny+eXQ`{F36WpMC1G7!GwOVazmE*aEYCH2#tP9G{(NdGzTm)T{^vHsxw@0~hbF@?^WXldr z6mr38(p<2K7^FJ}0@- zs(gfn*EMQLCKg%u52qxjJR}%sljg^ z+L$f)T7CHNu_O?`OyabzSali))%~CJ>R+p|aMuYTQ9|%;AJ`d)cYN1OG#k=or95OFe=YQechG&hb> z4jxK*_a3>8n&w)S+GMpdbF9=NdJPe65`#^wvJX(N8w}|-%EcZwR%%!&LpC4#ypM8i ztQ4K_8fZ0%Q2+j0RLqH8qGwxtXEM+(X~RT6d8j)j%H|gld)7FqO}nOujqY@I$I%6l zn@P!!$c-(PP5Nle2*mt_G55c($K1r2uRI#_bJX;I#{6_kAEonn#2gujxsWm4kH+l( zf5gl}%y$?wI1qCZV=j0!<{ys#PV?sGKFR~e{MWzq+-5T7ibrEE{Xb$ZLd;*sJI&*4ym0j{#sv(0pBx$@rgI9*d6%y)#7 z@z~CR=1xY}SIuCo1&lEQS}@>B7i#YcjnB@2gvT@CUb5}yPesCU|3|_$Cw3xXWeaVm z$+MFDf@FK)l~tl{PVcx;jEuZ&q$e`+JkrwwrWpYuBiRU`j*-oSm}W^{ZFIpo+c*X$ z7vKk-tAKif8LSvos;^Q?UXZ$kT;0@137#m)uIILh$ofS1y&N%h>-c#e+W0vqxS`1@ zpO^}}wZQn342&OkN9=YYP)vrO(*k4vU|`I^TEebGpqLK#)B;=EILU0D-AvDpj#)Np478-GqQOzCiFpv{bF(EG00;~Oj z{3N%pg>luG5RcJA9`0=*)7D37jv#u71%C zfaiBETVs_Hi+9eR0OaHmNLOt@YT4GDd646K@69r$iPgJ5u&#jByUwH;2$hb&ClH8e zXAq*cAd61s>u~Fvm=CSs`39^|UdofA65FqUN!_DAvW<1F^?}Zp{H+(Yw+`#zk7|dC z&i6q1HV>9ZrS*LjU!GLI!x1sd&mYArCw@~qCL-;zq4t!nR+BRX+vv{L=666b?K#-7 zCAXZ`RwbzPw>O~y^QF#pQafnmrhl*K6d><_z=ioZuhABcwfRz)^oz?mB3>^M7pthJ zprW<$5n3Tywq0J^=ix6+u#n5E=ko^1<_#MuKKZd))*2<0EALH}Vp9gU|Bpn=zN8Kc z7`+)t4I}6_HC2oSkmx~30lDr(cE|H7D{=d=vAJA{o+fn<`KD{R^5QhC1rJRvSKgQ= zJ)T_#d2q_Rj!=ruYHqHStKVtvb99$#ZtlgZyEHc!&ee^YdpX_j)6K6VR&*>^Y%fbO z_P>xJer(|h5g$pZzX$xO77h5pQLf~^EH$ld7ks8$)cTquT&)3z5^*N7v9jl7Y0JQ} z4@HaDktpg%M)8iqp&PLe8SwvFDr)1hx(HJz!+?=(>&W1EUL%}SLp&&#|Hs&y zz{hxf|KrI_hCGijLB<|}kk}Ih!H^IPLT2o1QAO=b6I(GM3C1IuQoX3QT1)rRR!M>+ zD6wy~)7teJp|(mwG5`0ucjigr)9>%~53hOdJ?GwY_jAuZ_uPB2VPZ)AHjW*cE7d47 zfXCw0*y9HJip=MIshX_=;t(IIs+290iMl)-FDr(6?4rk9yeoiekqlbhpM+WS)Tz`2OiC*%5Zgv~1%b{fK7LsFjV9H=qT!z?`$}VTD}xab_HOq0O%+`iD(B;zko7Y$LZ$~{nsVw7dEGPOvwH; zSGgBCk2j%89fcq*i<)JV=1JwkeqP1v^mfJuBIOrdqF9?bDU#9nLdmdsQylwto)pyb zZN%!6kw{TYC8G@b&(sYz#C$zZsxhE~NKefeNs()ojBN0v2YoWKi>9DCxY@US4i3e~ zQx7HQ;H;Hw+I*=-)0~Zn1C`%()D-NqXzEV=d=osRpGv|PO!W3Q#GDN0zOk{)`O@qP zl@N;5UQ;2BgY&7EpRkw(Qiqz~en|C#)#dS?#7!0RPtZ0{HTXGewJu;A7Dyfa-z}Vg zJ&A>`ZVku$mY!ZPfjwLxHEJIA4AApQu2<<7|G^EmDQA)J)BQ=VLSym;IPGJST>0tK z@)78#Bv(PYfBpm(YnQ6qs~~i|Bgv&t9|5^Y+;_=4ViN4>mJ+Gtcag~ySNcHU6DDe% zBFXhUJqL*zlj$5+lIunKQuq>jJas>umE}ahgxH6V`~$kHFNmAa3dpc#3)zw^L)~Vb1fF)K z{%Gexegb4x8ZTLY%uS8(X?i3JkhKc}m&`1`d24C>}Zur{%TW8rJAfY7;yi<<;pZj(+5 z&#y?~7V!#T(r(Tt`bp*o5O+|kTwcgEYzLB;BiHZ~oRksgG(@9XKy^QdIxwrvbD@uQ zpDh}LEbyn+fVW?w0Mkka=t6nKiu;E!ES%}eOi%YxOj9T?SlX8Z6bG4F7p2}3PO2(l zQ2#gS0n0{FXd3qL<(*O=L=gWgt|~Azy|6o?uc1E*Jf?OZ+Vh`iFHpu;Ihk{Z1w zFBgm>V}k+)_hBawLmf!-#H)sH1l8Pg~Wo3$)(qqSZQ3)qunSjdj~ zVP}IBs9WqW))A`}%BsxkXV-vI2F_q20~azkoW?GR;rq|xyucP*bSl&;jGY4_Z z5Mao}FW1nITu@cy8hUdWf4+d*wIE8a!TS>mh*Qsof03MUJ>xDr0Uv5Wr{>DjTz53r zEw_uFMlcM3$CuNzYOWrdD@Jp5fQ!tta}8}YSRc437yHvpnlSD>vy>)!#c*$J92>Jl znxa1d$N44FC{ya%IO2brWQG~|<`NdWRO+N(v_6h~xD=+mpRI{w=a%9i)%{Q6n9(6c z=%WDX=8)R!*8;NGA({1musC+m0rRJw3KQ!og{pe>?H`i$f}MJ?b+x4A;q&w z@noPIC!}RSBiQ3Fh$G_W8~#=$(hJYAyQ}s+LC_Jg?u`f)-iY81AM!>9>U!dzSY5KjnI-&Mf&S&- zwD1O=s{LI691(L%L?DhZS21*14W-|5DagJ7ywlS@`49+1&nfD;Hwl)ONxJCltG`3L zxUd<-7PlWG)j7SG{|x-2;D>y=3=HBk2zbJ3yA^tY`c)lbCyAg$Gh*NP#!BEO-A8fk zyX8`?0dFH6u5|w#t7c6Er2-PDrf2CqR# zj`^ozY&={Q$E>MRKv3v9us7_;;e(Bn@WWOzq71;pC%6tlZ4_L<{yir(U_Ycvrn*BG zf#;vkh$6z?T|DLBgyU*sE!?(I0lSkb^$wI)@x1l2C_CL-7OmG3kG-i*ZCb#rE2K_! zmq8H9JC)%@v}%;3We);l`>u>*_g6^g?L!g~xfQ?Iog6iY6IQC7NWV6>nq`Xtb ziB)+4Vr2-Np*5)}%r`}a>G`p!uB1l1D1Imkl+M@GTRL8p#z3pBLok)kp!{s0{ERJ` zpNv4{XA^}H=y4i4hWgznKnujX8X}Gmi+~uL#vY|goddgn@Mbg4S}pRm6|LjHQtD(p zGM~z)4s3(evg#MGQ7fg!L$%7CPP( z0+L=T*&ndHt?IpC)MOB4cYDd~-lztqz`_G-1+Xk@h{Ps;Bvosj(JIu-*z}Zf5pAR> zWw$IxO&yMJYixRGmciI`-%JZ#tCXeC1VP=Bi%{yw_gU6QQgG|G?<2*Fo)JJHwE98uisu75k4L^6Y+&kGifp z8cZ>-A`s*(=Q=Q{qKH{h7%*y5 z{vYG0&)#L&JNZ~@F5h3zb8{dK>(q~>MiVL{`yd-8OrUW=VGwTNTm%UwMro#A4uI8m z(ktB4PMV(X%JyJ42O0${7}(>fYwO`EhTXx-fz`#2K*=mXsC~g9^D3kjFOGV0HY60O zUGU1;Xjr_A5n-c@U^ZF}GyLJ)eK_8MJ)*(uZR|%TRUiAi9!A|G(DTHcR4nziA0Ux; zYSC?2{)S^ssZ*mvhy72u=?G^@T^^i+>}8S(ubOS*b_XfGAdB2uKd`Z8Yoy?z4T$1D z;2=VG2uWO+)lD!P?rIfkwZ;#sbrHZtW>~$ zTqA{48@H76i55_G`g}qKhb9J<5cG+SJzOI-(&=Wg8f&E>W7G6jA@jRt7JmUQLs06J81T7pcob|K}TFG)#%r0CKuoDsNPt$X$;vt z$97r5GbmXcvx43bNM*$9qu#}Giu!qx>c>zXl$)-TY6PE2a8o{jKt+_@N+N9Con8#{ z&~?~eS|mbV%b2zVg*a03j7kE!n_xXfF{dNu35r?A6VpmD&y|d6`j4395wqzhh`BGG z=k8iY7{$C^GUl%p|2NH_QsUSOiutxDra#5ZD;cx@f5fyQ=HC=k=ZX1fF=FPIjQOm> z|EBpkIga&SkCDKo#P&V`v#iw!0~9utPN8AiIziPYbXd5jQju+26D0Gdo{3- z64(qcvb!i}_H?n$G|~B#qgsseN`J$|STUW!rW4vLKr!5hj1l*RRK0VZ#k`)%;Nvox zAdgwIfNTM+sZF0$CGL3Evf+-NqK-wh!+i@ zitdXD-IXbWx`bcp;<(D+enouNag#Ko@OQ`mbGB5$&RyS2R}K1< zQUz??&o~V~Zb}@x__H*wGR2~^3H=Qu0`21ABfSdPfM2BGiC+#Q2IK_ObY(=50>5dr zr&IEMkd^=DyVUuJDX`5nEZ2U;14~_2G4)x37CG3xc#A}HObcM}9-zg6t8GNXAX0sf3QDxG z5x+{GR~ld^QtfeUr#)OaQsXl9wA)y~4r#G|AFAZj9a3fa)HI+J)81(|mbF9Lrth!- zJ#?qExJo^5Hv>~l73TATVDG5$d>b>SOO5s4z|kRHYG(Xu9yh6s_s6z(_BeSK&EGR=V>3;;#HW^aAh@I~v7tnx)pj{Nxaq?luqbdncSbp;Ry?j-9CoR<8w>Z5? zLRs!&D>I}P`dQ=R*r5!mZnqC%JJ_me-e?v zzUo@QVjN>|N%UU${d+kc;Vx%9cBVx9HIb)s5g(W79&+cjp)oKSvK_l5}=$c-@Lc(CAx*C1oUXGv4KE5LNR>u4xbZe z(egKS>vg~^N;ZAe)A`7tvP&iR0k~y&_!e_UK0CKt>L2{1PtlCGKjRT;t>q9uLUez=U{N`^ndPn=%7*7iwx9)t`OruVHe{CJH!B-D$dsp? zxn-fI2;5vIl%2?t`r0Qx!Bml7fJ*bFi6l-dPcy2U2M;`m-WsAVAkuaiA_u8Gv^-d;7;KU2%Iw4$2Q~NNhRGDF8u6ieaZ@({wpMj!tB z`=!IWkiXc@-=t=`{JTv3O{&>&@!K3f6(8^!1m@=zKQ0n_`g2S-5Dq&a&GuVA)h(2K zH`T_rACOw>!k@AS_=Z#&$}7juxs}^IC1UIs=|`NGyYr>0zJT>Sh%1)*jRF}Qkhij* zPWV=2%MVIrE$uMv#TvUrGy<+y$^#rEwbEgJoIJv>MVZ*f(ymDXW}R5Y9EPB<1EvaT z*CY=xWAbJS)UHV>%(gcUO3n0>M%q}#T&am}_hZ&6SL&jlKiS5XdPEREu6p?(99_~rN zoEM~C`-hD}6h20T zpY9Isj3F5$`)``mu^mt}P%M#V@9{P^^N7?`cjy7zazu)>e>w~V4&9;zlPoxHKz~D# zkrcq4X&Cmf0D=>c_bB9)hg3k14t^woc2VjYs270_shl3^$>=Xnp<2#0)WgXX`g1nm z^Kvqr?5(3xK*$MP(8cDwq1MrI++!_kne?wStK7ztYn?+!B z-XBK@j!Hf2T^IsF2@@6b?{KI;UPCr;hg%<#(QSx=#*_!gv3kd(+ReKD<>?Pa8!7ub z(?$<$$irZLi`NBQYT8(=syC}UU$TT_=n>aJb^`uc9GB?lvbvQ@%9m_-1R4}^_lM99 zmTiK<@}6wEGM49l6XJ@#Z0)NKM3(t69ml*7LByRL564j))7OZq#i{!!loBux zLnx#fiivg<#!Z?>8P$VWQ)9*OvTq#gd|avob(d|xNk-&G@W{m z%8oJwqM8Q{LB@O#1{oXax%k7Wzs;1h(zrTD_&_oz^+BVY_!I3n1ue}ll?#U=@wO`8 zWdY})CMXq)Tb|BI^?GHsMb1Z3&I`4iPotdwdI?h(M-*s?F@#vJA@Vf@7jBa-vG2~| zj>5e*8#{4Ms#Lig|{Yj$1=FI@uxJV$eetI=p7XoQF9;+v>< zcx!oj|6f)LcY~}_ASh;Bph2F{pH2=nIY$lU373sNztl_6nNUeh~QK}|&0|;F7(Vwit zMJ&%Q>~gO$j^$o5j$L*g4q7)?Ahv45@w^eU-KV z-8fRUf1VdYLxS&}hM(a|cYpQgoEK;hB;vsNVX}ALfEovr$jreMpl(N(hg6X=i&HX> zK^S)Rs!x@OJee4yVvYtx^}EA6(AT5^#Ny#EwULGE-mhgHDiWvE9WB|rSENpc8GnF% zv4;nwh{1!pxTS%Iu)O&nTgGZFX@6}btp`_?T=x0@P94i_9yzh+8w#JddcwTvs?;zt z5E$gK96qWf`mc^aki?wQRnA0{QCg@fitXGu?JZm^v3tF$EaNH;u5B4W(#}henb!lO z5B0~gu_L29afXHcAyw|M`b55akA*A=i|umMKyc!-{lH^9do0FeG7$$YS9fGdzLL+Z zObTFY|G++zmIZZGb8zkhVw)mL*1;Vu zRAD#OS?C{}ZQ;cTlHHU&?#{iqpN);WCe@VZgA6jV0Di|cDOGpyD64W^sv&P9E{;Cg z4VsqgQl+6P+L*KVTHR2rh8Hm;K1X)AY~d!0{4S&UfnU#rt*iu2B4PkOT$Qc*?1JR7 zn{OBq>vz&fP^VsGTdzx1^a)XdtJQDbOmH=HW0*702G7lsJ+?L)G410UI2=B(D>6yD z|Llu78@)-l9+$XJ{@k_n`!6$P7MT zY{=kb>qXv|P3tf{nQua{-3Z69n^FhknV6zou=6ou7p#7H#Lio&HY6gNwt$~MU3h;a zZ)a005b(Yw)vaRz0qP2g=-lqEz$JIZ+!Po!@?1WfE|smw2H%p}8ZUJ&O6`x%HumK$ zsp-%fs5j@^Xe*D&iZ-V$LU1+pXz^)oDnJl=xfZSSSwti$Pkj!TCaIwV^o60H$;TYW z8r{Y@#l4MKuiH|!&eYZqOSbiwM-UMwEx7T^=JuS$Nlv`MfXqY{TkT9}L~~$;yX@QB zk|I~8c?ye`PBzx@j#OPfgIO5^Wkzosd*_Z6s!RKkt+*pq_REc?_9p9*SLfMJfOOsj zhxyc>z*!`K10fVE3cL(fV0 zJa082ClM(vr=LYZY;)X*cBnCq$JiuMQ%|rPccqGb+GN6pxydC=pb)q5<|B#QSK(92 zo}pjUA^MHT!Y?YZC#a|c(0QCz%Ec^S%#tf&97kgCD#5ky3#lI-I?cNNg|oFgBIEF= zxzxqpJCqCN5W!*`c+72IRw{%ux5W+b{!I{ovku_CdIMJ;xQtV@%gD67Lax&EMLi3| z#~OmGG#?)HAXalk8Q6h}OWw~PWEK@?(T{hqv6ZS6)*}=B3G9j%YU+=|eTv-F&j7zp z?vI6ACHFGn<|>&5!cAh7I^ziQbD}3%j<8lvm?8eu4!eL(sk(7vJAUY4L0d4@4**=_ zlv+1SHKQtN?$1FLI``w}e}>Xr3WBZ}q;5OIUOS~0LqBh2dD2JxyfH7-5cHfV?w z6B_UPxb?FwtY#JSQGDon9lVg^FdQV<8jJgxb@eMu?j&5n4togaz>*d8O+`o)GLCi(Bpe+V zHtXSXnG66c5nBlfJ#Z-9z~xU7Fp;OU^&xwadh6Q6vDNpbCZ=!OlHR5L1H$9Vbk${A zW3jOd_oYFS87SPD4R4zVQXk!-<81i@*gqIfu#5*%vi)HzUfk>W(2F=#c$qH~u&B(t zP<1HtZxn_rP8^19BK#@3b?9mvWD#v3!?@oERB~OX_(sh4m=3w-c@-R~UHBtbk)4B# zALx14M6s@65Ay?>T`^_&lW+k=4Y=fPcKUC;v=G<|CovyNb&aKw7#ev&2h`Hjh&a~r zq14X)ptUDe9a5!j%u^UzIj8{j$$sijV))$^Za(}j3-@&jb3(ZJ@Y^TceE97UZa)0J zB{!B>U*d}wTzz{*-ZiGsu?pOl$o_taS{%KfReuDPsj&;H_mKpKb0q{Pf8H|u%fF3J z(FwDsbU=;ts5jlnKd*$a)JIa~A@B0B9xU-c^F59c+Q+mnpm2EF2w zR@9IQG`FLn{GD{Y2^Z--bH-c*purubZad0eKayJ5KT-MMwqkJOQg96J+k9}J;IexZ z0{hX`Xt;`3^|pAQh;bN>wD_OFIuLBnN%r|;)1s9Dpf}AIjv|{)afswBj_!M=W zr37?$oo1-#@iewan`RJL8!yAS&ploW4p3_uEG^>Lwa2($#+b`okEK@j0*s@?Hk}hH zB+mBsO7P1%lQaRRKGf>~t5?9J)g6ckK&>3a=jTTZ5u`C3QI^Jk8nv>+^r9u|Wbe(= z7JV8uwMFTK<&NP#pz2?IoSIL;?J!U{wf}BT33tBW;zK(fKk0{bIBi@+JPp8D*sliB zoq$y`b1|W0ox~5q@f$ip9@kr;MTrIH;c`W2$;(c?6yjwJ#qQBH*Z^W5javfxs`vMh zW*xSEzWC+fxAtZy-dcw^hiK2pHD z5Cb*}w@(5S2nks?Mhw1gM)i7}-+{G#=DA`$hY-#p!|0%*p^WaaXt zbJh1nvM-77Ws#jixK;aTfw)bGzXd`iL{EY{3>=OwtVObCY=4igz40sn#E9Rxgs;P*i&GxqK}UjA)_wTQ9wTQe%|$AD1r%9SRLXWj~6 zbjEd5NObyD{AOIlPv%+tWSzoKuHi1ELds>X;W}LOM;AEsJcV=pgKj7 zstZg@fw?aty+s&rfvF}i&jcoxFn{gkne!5uR|3<6FvkVvZWCS-ok+(XM5tc`>X<7s^Ewik!vb?tVCLBc z>OP^i3e+KiS|%`;3A0*YeiRrcFoy{9zQBAWFq;Kt2Vq7D%v^y<8OobA8G^3bO<+b6 z#(pO2XAx-zp_&L(R}pEyz>FkJMS*E7FlPj&K4G3`^IE7NFnIzKK$vR+Q`m^tLZQGk zB+LPU`LmIoqYNT-aP@@DYpCUB?3b$$Y0LGHKn_mnZojx4_GJ=S+I1IiZz*Tiw1i(&a zYtcvid5rBmM)(=^Mi$jfgbbSKCVGyH4ff~PxPi(_z$3Lqk-Gf=S5_EPhGHWS%fDj{ zd9*$F!0-`kr+0C$uvcF^n4?6bH?*zoeC?;RAA?`Bg{= zbFtLQ_VV?`K7pGZ9zq{oP&v~F31!i3Z(!ihkXMJ{7a+i9wnLucm&2*AGX#zE2&#TK zTHHc17+NbRYGG^2Ccly--QsO*Y6scGQeR2Fe)a}nwYWLlFr|Tweep`_U17xt)EpQ& zZWSkia>9ua=KUH6$;yCC=m-3#8Sd= zyUs|~M5?`i&mhnxr;CHn_f$+?DTPskJSl9nyAB~3_S_(5w=5Em zgEs0W$dXxU{}PMPF0r)Y1P?uQqw=LzGS!|}b~eOkbpRq^9>i6TJRAG6+90O;3<_eX zl@QZOmwuv1FIE@?iQC=)0-FKzF4Lp|j6^H~a z^K%Wpr~_X4sdmT-NOc=xWD$t=PxfO}Vf&#Bp1j6uq=rH)U=Sn~L88-1gONc$TzAW( zsK4(*`lV3cqQj`8ck*g&j{%sKQ?gpsa;ThDLVb`G^>Tuj?721cWI5K+Tdr)M`7MZb z#riZY*RT&O3(6*6zNTdr7FD$R0TJrsUa2;B0xhpG{iJQH2(JkciEBA zae&Z1R5CW3UFwam&@+E>bGsySy>J_QrI))lauEDuG`DIeR}O{!6+?(?uK9LL(tR3Z z-gRwkijQ1Fcjjld+(&Mt>%X04_{jD2KQ@JJl#g7ewLApA;FN4@c*{p#{9tdl_wt@-6Id@p3-eNusGX8_H4wW%wKJ4E%W z|4#OqL2gi~3j&LL;@Midb6$yf(Zt67FvwNQK7(LKI=v+GQ-JiP`W=S zN1!-#vN*`i9;3mAxp@liA48DH(sEGq_h^Dw%zg-ik_Uz7L(Loa6K9QuU@uALaA5F; zF%I$|oZ+8ZHl~!8&AOPM*pbq56MaP0IQF8noUR*Enr-)$*OUvY2}-n=gZmfz{etU> z%6Fl-I^jNr*Q|${?qVpd# zyl0}!rfpLoj*MexWqE8h+NlcCHX*o$$;pjSd}aQ?`jwIEmfOrHKJ(wz(eWa;vy?J& zSm~Ycc-kpIy}C_k<~_y}?UxpEJCM*~x44!8$0}xTi7JG)(G&sNu)txD_XJmD;eK*- z*%#HQKu}p()veo@-A}Hjd+&SpiJ#m^KQqp^h0UvgQT3vhP;_rK@FVUYf z{Hcm;J#myTiD({1zkt@LuSLtY5na;dFUllL8d#puS8Y>Y$AvoIfMU@ge z4p7-cT#Y~n!VFH5)@Qpz*y?g}TlrH26nkRgEO1CYaTZv2eFH0JlpE+)uV;})xqjI$ zJ88FXNKRg^`sFull2Hx`C=U>7d~UGE{^?L<8~e&A*DOVo$)F+ZbWEd4EgFHdmu#j` z#k2*JYOx&=OwjyqU+^))M3Uaq3=S_$uvl$YD+ zCVtCCmzTSgeg_N<)Yyl;<;pB^L@k4q52k`E_>6JvYP(kh$xC^rJ6XURy zHnFfFgk^K*?IB(>+hcdMZ1naJwxELCs_MHuNO>NFziFuM#(-C&x3J?C1JXKr&4H_iAZgpxZoD;U1ONy4{( zRwcj=&&9rd)6=tL{2rYdLv@n%J9xb?vc}x*rOtcFR#uclL;JjZ?aDiAp~K?lEfuNO za6tf7T@WmGAe-aYCs>`gk=?8)cd14vz#f#mdH3cz6y*3O79AkB(m$waV{-%KYSp}m zlwv+z0i%1EDAECPpW4WN43H!3Ddh17BJXDp12InrjFJ~jNA2?^)daml6q!W4C1EM; z0_>jt(&c;~qsb#beDV+nf9b|s4;|0V3Uw%nJxIbC3#|GJm=DI4I51%6ytz7RLMgke z3~Cl4^hQ+6!q?tmda$5>9p~bEFMO?o$C&&jN9eh`CPcD@uYI`tJ?=JecNW4po@CLz z&}cSa_azxHJT$*}jbtI3rY>@2zjS3iMl&Q8+I6!owHr7O?*dS~zVj@pJ5>@uQ`sYY zR0;ACks*oU8i+(fXhiXZB<^NQgy+W#u0E#}q9E}>^k2QVUEH+zsW{t}x@0M6gW?@f zjIWqC$P?d!T{62R@>G1c#5VebCkJ76`he$9G1S3?LP8wf_ZXg^awf{S`e3`Ag+w6G z!M~I$GSvNfu?#tSP7`4FO)@l!abrxoZt?Md;lx91Vs;|v;aK=ed=hsp#IIc+KR_P*sc`rh)CSEm^lquU%hxE`<>xcrm5P|LV$h-ECsdJxf{Je4rX4ZGl!u8G10m5!BDuPD zE&H{KjQfdjkv1;fuEN5q%F_SdyzN(X^L7(l(O6aP&#&HoUR9n_nQqqRN3J=?cN93z zJC3MfDQrPCc}#=uWzpw9`Va$$Y%M$c@@o=sd_3U{-PS=DF!L*!_dR2N)#Y)eGyJd| zO#YC~tuBY#7s8|ZVfI0G6X2#cbj$~bB0B|(1P?*t38OZiD z+bZTez^GwFqMhM6-0_vkcDDFKJkGaqMcmjl0`D(A)hOoYnBJUcYm1e-5-}IiVayk% zl$}kk!wHQQ!-O)n?&$gPHSiXWxM8fDFJ173TYnT&ZwhuM!Jn?Fi=v4+3c`d}{9RAj zBy%$kIAY1|=8H?o*pnJ^@UWVQg)$oHv-djo@D{1)5O^jrO8pmggCkQgPmpQ6#SZ|@ z6DX%wJZ*GlrK1PBOg{q0RnFMGBMyX0*bk7)^g~q}n-M67RI$FIMFqB@-xfjR>mj`b zvW@)|C-1Xf(b_V~$b&P|G)^Tm7+N_gHIP6MC!r<s0?m zPb@M%PBE;NkSkn6mJ?qMnO-N^SU&{t-oj?pliMGO2tH#tQ=2PAb%JsvHclQ zbapAH6V`|A$r2@GIHo=y^jm?*))0P#$V+2SYs#&o?)g%6;fw`UN0Rw6gaWYV^`dg_ z0O>NFBzb|}Pd;c&?hL+_6$Jvkl0Nmdu?e;0!L1x4Fv<&&rD7V7XRwoZT+ADtmNmc= zz8dI(QhWj`wH4ydttAJuz#uu+UR1M#5iK38(3SVw*fdN|hu;F}(AOnMM+njzaa~lg zI2MnL``)?Ymv#+BKK0!R2*?xLvRuQw1&8(A$S|61K}yDV#;*&Mu#@&pBilR zY;mZkMM1Icrj||gyz5Qh1ItP@Q}%zIbKtL zrEl?jhi?;4a=7muR>yMgV~Rr*Frh?<68r>uE%G}IBMnd-s!1Pn4)qR+EsEJd)U6b) zouMk+@s){zW~Eb|(=g-b_7Wek-gV^~t=@h>yh<_5ea(x8`$f&ALB@Hx8s=3^#;1H2 z-KW>|0ozbl4mDMTXo#lw3HH43?K^+?1olT=xwRe;RykO%WiLgA;rmtVA&A9a&U*3| zb;?}z0q4Bt#ein%pqxcv7QwBa6YwbnuPop*2);+a2N1lWfWJ-f%>v$m;Ozyx55ZG8 z+-|NM2G|tp&Y^A67c2(A1>heD1Fvs0k1>wE&~21!RHBh1%fvb@Ph{*Lxl=_GwehNs|8qU`Y-iV~$N5{Pfo~;K0Ay; zIuKGY2_p}<2$)<$WlzBOC}3#{I8qCE9%8I9xf>677j9}BXB!H5jT*PLJK$Rm!>>G~ z9}l_L6Y>?Nnk-APychf>Y5=*%EMHPbpqQQIXbN`4S0P5I4#f-tJ@lz^HddyAT#r55 z)36fj+CZ+aJ5_~EX&{HRbs;=GR#nRfl6T)4{Pcaq-vq?QNeV`ydsE`O*H+{k>#VUK zL4{NH5GbB(Aa~WTf}=`9IYw`RV?;xFe^dFD6(b@RQZ*{7J09hn4JyXurzkgu+WnVS z+OCLL!F6(fu4L9ma$P9{P*`pF;i`p3ay7gEV~baJybVfk)NjC3&3mZM2rvkMk##$B z_ei+CUdM3vyKslS?!?{G;Lbs$yy=j&l_oz!Fs1@l01dp3@D;rL;Vm8an?C1$+*r#W z{ORmZBafLHBNJmNBDRz!Qv+P|n&^2X9a}bwZbLd$mItRJ2e>51uU;q|4%L|QoC>+{ zw?puXb82)16zg0>ruV7Qf4d=S9-uL(?k2K3Z)1?e!WZ8Ddel=Zkihw$h3v=1vY+=N zwyUw+wOklca0{5(x0tbsT-R?4B-o^!vXO@Hf32)T6WP*z%L}T-4S;*9-MImjDGS~s zJwxb$TI&`%{~GkNqFFO5v8a5i>n1zdM7Gt+x-|lk_{;DQR2Q_f{Ivru5*yc44y^bV z=%^Ew;@yya&{VEp^{a}s`x)QYqVUJRmp-SwErTe`7Bs;n8vEz7yryz!qvCaQ{08dg z5M?*a8|5Vl0Lsyw1pQgvwv2UXCQp*TEwoZU`lQgxwl|Yo2Tq4S{BW$}iMn$UIy7SkSi z|0?`7Hwj}667pp|6z5@bjn41uNgCo-ohS!lbwaER>fZFGZ5Z__#jt<^!P^F2^+pO5 zNV_RxYd~ly2(=H#-e6%q;*~-?ag;I^XT`oI-vITq<&;TNGY}axnC?b{=HAeNNK%Ji ziY%+2Q1!u=tmE197@2MYO{&#gu{Rt=+l~N0!PWKyqUjfGahz2DoQv}LJMQ8<09Foa z(C9*!T75pd6)s0LY5)p&uUW)R{8?n$)Y6i zODfN;BSpQr6mSch%T?_Y(UCJ|;V07<+006YD?BIKs!o`b?-~(32yFvR0hKDg0pGJj zg+faI0Kw?7;SI<;{i&ZUaTj(7sL=6mUR-+YO)-tYlO{;gf)7ZbS2X4qn1-oi?fH%H zq#N{WK_!~27D76b5~UR7NSWjh8Xy zBH$LKi*IIk-~h20yPWFo2ndEVa|o5(7_+ZCOo)A*7r+jL&QFQx1oFtpzfY~rpz``C z*oubDfMqpIR1!fQ=amSOSrY{KgtS_pSGNw(_gz-#a6OO|IuqJYt%|^u7CL0%0{-5E9+J-VRKr^)xE!F zt6RynnpD9;oT42=O3oa?T9q!LXo&F`PA@R=QKJk86Ul#NWj9*Moppn5u==g#$OaGa zLaLgM5$nWLxh{194K`eJBckB;N1oM)I7D08TApaHdapO8DNIY-P-~clRy;zV0(V)V zQtws_<$;e){hn8GFPdggWYLA+{DNBhYMku5d(ha3Y!x-m`A+QsF)B_NEDMsRx2Ou@;@%T?Ovf_XRu%?iX%% zDBSsOcUUoal!KRvJ#HiSFW09J<{$C;nY!)*>lZ0^)%Cf+)=sk09R${R*x6d=|+C-KcNig>%y`P?EwzhJ$;Dy9U=^%z-NglF_eu6Dj zZ284J4z*Y%4G5_&qLcB1OBe*w0IIpR2_=ee4aOZ|V$bv$dp*7 zAWMzM^`9G;i!-mZXTs~9TX?#-T?7kZI~t1 zWIi2blYReGbd~Ww!P-+pd56_(%x7GnE25+rj@;x$YlYpUoVfwu>xbbw#CMkr1D0a5 zt8vzPa8}-ET;uGVjhjzB+8%8i)%iA{U~x(JtI%n1JFbU`r=DXhxNQv{sL=Neh;z3sK&8dUz5C_;rF$vfxC z0G_-cx|Y+ET^Mf)%W*_`7W#4&cSYUl&knAO(tK2gLy~E z^>q2uIr*mFQ+;vm>rPAvq$%R$GtyGfNmEvNI_Wm#Lft%t&54q0>bfjoYop|7d-M53 zaSA4%;tihE(K|u1B<1=#7cC(CyKmrW4JAwg-=0Y(PB_E>zydTs)^0$QFa`AD zF%tYJpUz6FYH{uaQ6$QmYGK8=YBrX5<~@*VQd|paD-k=%mA{~jx^5OBHo;4) z8|M|!1)aT5mkH<7hZV?;M|R*S3Pq-ESd8z`MLIN5M^h&aRM8_)d-zF$ab4FAn+y($ zMs5YSCGt^xZNO!Mrx2UWHB|FNFW|CL49S1V#JwVXfXO?J6K4JThd=0R$!%rGzUeM+ zu3@*^DH04Ee;t!Dy_LNgIl&u-VIUH>kVnQvS@}Q@|8g!b2D~ zr^AhlWWpcdX+--R=MCgS<7O6RR}TD12fVwZg4I93xB#N{zj|7@Pm%k8a9<~PhH$Io z{(;%-AQsS%{CBAFk{xWpL6@c3`>Fe8q{ zmO_(~1yvFTn-b9mEk#3*R**&a>_G{Ui}%Hyop^yU)7ZU*sQoiRd+~-wOQ8}n{_Kt2 zO`a>W`8w~FUjjsbxrPmHmzp<;%4}XP0+h!`1TeZ?)U6Hb9n`V90irL0c1P4)!-&g* zl*Nt!^@`?B3r!G)`jqyEf^;>wsWI*-WshD%kq*a~QOpP6Qcodsis?r<(c8YmhyGA4 zz<)~kZG<;`Dey@iJWN`%AA#SgAA+9^9d3^vmg!qXht+*Hv0`WJ7|;H#k^^$Fib8D| zt0YmgDiP0!nqt0-kIUqR3U~fXBTdosi=EJD7Kcu~2II-(nCTiv3=_N1hQB$IYlw8s0ZEDnS>^aAxMPu%Qegd z3=NHEXt?Tc9OC2}M!A7B&b4R9@M@CtA`-X~UzVS$ z@U=^=gFZ{|rU=!`pMqC|cr?T5t5$ZtC$_loZawpll}({vAw%d^`{{vtTyAL;3{tLGz~nd65g-%c7rV%IJp(T_b?2J zNUR24KLFt0-QbQIc>7F%cMGsRxw!^E_A%g_-NEZ=;M+R@Uf~8;(ZDay13b$OE~9}1 z3IHDI2ERseMR^)mMwjaD20zxoG2>bT-rNnpt-*&41h~2zOwR%eD)F-b_Hl!cXyD}x z;0Iu1RQ%nXAH)ayXK&iM&T9{UFX8kgcD$EdRadGEQ+vrD>VBWd-tR3p)#)d)?|Q@b zclF!saBmo<&b?=4&wI-wbtzNX&^S3&xBV@4FHW{p?=UX}cN%rWx#IFZY5aa?VkU~Y zAyzrPtnvpG;ZLg^udk_ES$~_nOFwdM2&>pft{c~C7;GvOyRSMQ9R`jnYP@iSsuSU$ z9_11}YWYx7-4$B0Jp!tw33X7*-a@^_xU~>$qRx3MO99b{P2=3$6Vf1FgPuvRK@U<) zKb!=^ITIhrUxUu&Qf+EF(NGfc%l_yiH)+=?OIyihoT8Vg51KtfJ%0eY`EU$0jyRwp z_yf>YhqEqy<>ob?o#2Vscp}B#y2h=xl*sD7au?f-J(Nh^nT&0e!XFwTe$Vw7)QCV_ z)et=CSPgMSL-3?q3}cP@$zhS@De1%UlZz$Icop%aspy^f0d3Mg;Wbk9hxl+PUXJ%> zAN7;F_Mfqv=PD;7jdJxuOGD%ewJ#9QHH65OhA7k!B3D2dYq7Y#u7~VWuvu5l&5xXFtWiBtuzErZ8s3bS9O%^0_t`n71Oq( zJlUB4OqM@_UYjqJREFay%sD`AFsZF46JeAItCkkeL=(ycN5p9eo{0b;Xy8%elaaXb zgZW?rN}wNQ;7YvZzcauV43yj3S7wkU4T`;u9;iK9l5ol(q{tD+G=!*qApWmnk391K zv)J8mY>Pz>k{h(Sm+r3nG|I%Cl4<=h5SieJ+Zuuw`?rB?-5_X8HyrNGP7abI|jKc>4eZ@DpPz}zCt zd=KVtXgw)T7%-iO0TbxKeC)=Yni|435@yddH?^*A%rs#1!+{y@!Q?~sCu;svLw1fH zE_d_RADkS*es~K$wFdYuv2smQkXhx38a14WEz`aRy{>~ZDR+CkD zz!aRn+X#V+Jf+Dq0IZ%oFDAot7$O9D9+2m%JJ@yd7~P)VLHp_mInhFO@7>YE^>`IO zh(p~^BZOWriePf zTfH))Xs*KZxd#ww-6+`EUSJel7n-Q1{Q8L&eB2!kGd;mYr~mp^N!qSOfH4i zz$$AiM;?y%i!^M5)0lh^k&+7Q#*e~fw#MYIktXi9H70)!FxG&SHtyNG4j)(SBR};H z8fhJXt8)PKQU_Y|*_yZI+Qa= z01J_du&_d?$Yf3$CwXwM2WW3Sz{{%c#6WO@L15%j5#N1>RT?cfYjPAd>6|OTN}vs7 zv0#n2Yr9!;1pMly z{_M_ZxoPxcqKG`vqS2WAQsn6@h4{dV(7A@+;HE$45_CNGRuMAjGJSpqf#jt-`@JKN z@UB3XwovW+;yDR_lvmBT!VZj)7wWsB@w<-x>X0W42yLdP=gxwN^RfF@`<*{;Y z{oY>r?Dbf=olf7EwHqf7&=18G*B_0O!z!vragE@=nAJRVzq-UOjFUU-`$*4O;Jfly zEef-#080j8OvX=hn-uuxh&-!Dd5P)DBgJ%*0xIV8Y%42x7e`+9b%zW+xfN~}Gam#j zbi6#VR^(CYABVBg3A?d)@}$(nAu66_b=aru=kd_^UE=VgVCxp;qu@uV8w+xGoxV`; zhpBT014HIsKEZhD8MlH^^f0kl{i72d70N$GYK0X`iA3t|V3L6GzG@XtDdHxOv8mV@ z0hAtBRSYAMAhs9@P#YF^Nwegz3Kqo&+oKo&03wL~C^oGp$YJHE9n@9lu{bR&9ka40 z6Xcn?fb(p^M0u3{3&V4E0**ne4^c6DieipDOrD>G=RNK*Ql{G(dXp#RT^wypG9Nx- z^)eVg7zz*VPK3r{@bN3am57eJdBukAwz4IYy(Os|6U7>C`e;ujmmWq5bX6q)3%G$pX%~h-ggb~ss3;~E7D3! zG5?cE;r~{bBhmenW>j2X6XvDo={KQtLCsMPT^*Z7!CW zSP3ph2#}0JV1C<#y4gl-DSmo%7Bm`^T1%klo>XcIb!X3fwsfjI(Jv$26TyfJ*{90E zy2u->-ZY4f2L_V5{9%skl=JP!?wYeG>0~&mj@Pqv#1*A}*8n%q*q$m=R3UJXJa*c)0kn8BaxyJg>kc0Ib`-iZ3Gvpfn?e|eH ztBiu9V-4JAWna&b1LcBWQJ;9L=~pW|IYX|hkLi}r@@B{l>IA#F4%!Dx0lY$CE(b_- z(jD)lLW9Hbe7}{odQT40F9xN-@5zm7ER95;X!keQg-55_-KOuOUFud#KHKn~Tt|N- zI-ebQPwwP9a2ck!G^AvVmn-QXkDS0l<~ZO zN<8aIk9?LKk5x}_=X~~Wylk^i>zMEA75O^hA+^+Kc%1vtHxVF zM{YN|Bb6OZkSjEs8iR#ayFF=WMq|oJNDoTcejwaEH-$j-N2h9jz!zo+IacO3Q?AzV z6m!f#gtyK_U3LB0%Er%>>)34wOH)d$5)d5gxZpBf z1arlj4)0OJfkbHzpueOh!x0q9lLGK?5LAD%(sVf(K&5OP{hGSaZ$vx%s+W7vAV&e6 z$0@j@YVjD2KT8g>(BoxW$9V*syClC`NPmNlL&*VPZ-W@TGT8%=E7Y&pDD0Qe?)SR33z zi(=wZx{7=l0Ti_h&F(eU5gQz%W?8sslyVm}s@{moXD4RM)%3SpW1!5IJ4XK8n+^dE z-bWj4m~!~BJ#~0nAs-ohwo-LZ=G={RjHI3kf|1-LL?1l|-8{8qJhenb|~ zH}6B#AiYCSHnpH?j>u=axpD)2c{rNR#R1KKf3UJ)bLF0T1EPKlRINGa@|xOOQ%5D; zw?g)s|5b1HWUky^|7UCn3x8j3Sia=mqN1S!-h!9yEI?((j0>8`E`J^!P+Os(D3wfnoG>dGlr zUBQU{-8?y1PC)=n?Z&0Qvk&LM>hbkF96_xC;D1!zv+#V@V?Lyt({N0gkE+}Ct(C2x zFZZ+`_!ix|I%--SdJ8JTc+%F|+CvzRqRt%I&C{9vMxirXntKp!G{kf2<;^riTMbd2 zVpIY`C>2TQ2q2?-wRv?+8A-bmQ7SJsc7bfvcWagZ)$9ebx4vbqLiWBLvi!^7LiURt z2Mc3fzv3O6G>hFG$NKlp_?v12w)?C?qFe{>2HnAA9^ag`Pn2sJa`Z{pU$Wteay!Wz z)sEef8U5H7iE^MlzJD|<+j*+|C%fGlMhdhtS z-8W%7xzFBZJr>H5jc{>mQP0I<<8Vvj8?emm2ZR%+F;EL&YY)|JNVe+I@3Mo76G+to>rSXSruLQDj_uLAb$hvDJ&^psKlmMNSH~8k267Lsk&gO6Z(=?8IWZ zf%kA$xL8iC=z~yB8Ep`)%o<7fr#G0g1aj3M&)H8)qPrV1Qql*0h zvG*oWQ61agC_Ny}IR{S@0Z~Cw8w3Xw#YEx|S{iM%Q4>)?af)7JqKTS-8e`I$22H2a z2}YChW;F9)@{ismwnJh-kiijWoZ=Ym76%+aG%DY3*Xc&g&HaDtec$)idvC4hl0J26 z+_h`hu3fu!?em1@vCefY>J4E{hwNiSEpomVt0y&Tq4$w;{tc`}^xpL-yY_~#TyrQE za-S3PV)TRFZy!;ro8x^ya+sOk6eg&L9Aclp zDZHY-r)Gw?1lC~=zLQ2^ob@(4nce}$e($@niXDGT=&u;;0c)st2Az>bTi5}n;uAa}pv@L{82X9|RF)(9kH=HwBq zdLEYZbG)$n(K}$6>U}?XP(k=ayc_G5o&jB{a#|T3%#DyyUiaHsJUw%WuO&fpF_tZ* z2^)n!&jfUX!#6X6tA=}|ITN)I@Po&=% zMS@j^VMNjeeC!Cd8Iww6TOk4v8Zw{}u)`e%5m`2yu-xC#5TVzbhW8&ZIx`tLj9HWF|NQ%*ZA`XgyscT?AU9|g*UBNksFHp;I~hKQ ziS90efatx4_x-r{J&N8z13SI%e)|>JUcq$n(SV#c{dNPJ^S01I9*JnK8^-Iu9`cP>Jgsl7 z+IYunO?Vx9>>YS{7#+?zRBD%}`gpQ{OQjfVEEcPV<<2s6UP*YiF~N@#<|6^^(!}uC zuqVfO2AO&)BW=J_UP?x9o^SE9VG_aP*TM%+UxKGkRAbGP8f&g1W1)6Pa0?*i-tP*V zbuXU0i+<)tvL0UuAxvhF3_t(Q)tL!vRlO&-2XH;8@|ecTM^NRNEqw`{?k5n`kF~60 z`hN;_x@pIGwXKzEJG=)Lx8fVuqwfj3u(r3YW8w!;MD}De0|I?(bd> zh!Rht-{!us-F!Za9S8{QtajXCH6I8q$4yq&=au)@XPORX=LoFMAZmG?U%%nGpOUt! zemmzK?^5`p5`LY+Cn*e?S%5L2_rh(;NawPDd?-AU(4V3)b(7ueFo1mJeGyR}89(>! z#jdzl4pq!@B*#- zrumFkt+HX{WU zDHX*y&SWldjmXJ@KIS_h zpe@Jkr5pjW7QN#Wl4M}t=@$Q%GSpoJ4=$+m^NMoMDx^YSbEBws#xoeAa6G%Msm zp61Pt4-B;9U5uR&iD8^T7`vk5<~-9@KCQ5$rcjeLS%DigWQ{*uqcA|0SrC+ z_G4kRI=dfJuYxvj!HK)dH&a)+f53EK^H}RpHfojdlo}sA+Pn(xQO-Ta>Q@Ovqg(Z@ zZ^*P)jrH^;96+qnWAmtWKLNKim=4e%#8gblhsVKodcG>h0pCpO|!p|^U> z0Jii~p}l(lN3L%_6@FJ~rnabKj?aY;)i-vt&R+naJMX(*{X#gcQr9Q4X2&y%mudgE1~V!@d11;;O3o{P{rrN1`VD3^7(}+MPDiX%3qleA5+R+ zE{K+zp!bi1K97o-h*hjd3 z*vA@H3(-QKW(r7t)hzxyp?&)xyi=JOVE)MKcJ6LyzYF)_vo%BJfWT)`a$T~QWM0h z&w0h<7^g)eo@;;;_Gl~7JJmaE^J<~J)xWC`75GlvzoFt0SQ44g=j!hYXy;O;QZTaW z+4hkq0ns?=lNaEAC=VhC{mUp_ z^at1^a!HM8QyW9my&<#HR!Ny`JE#o);iH7>l@J9Xi8Vj<&MRHyi$nC%Wi zmAn)}FYT3sk+vQ|tO%#gn&p(1o`2SC=OHWcRcIZC&Pn6q@ii{ zD@2A^{w}bh;Xxfo?l;Om>^7^mxKl~>J*6^DwcnIf|MJhCUc8x8W(^0yGXSs3ET4>O zH_V;{x$IO8guYX>Y51DNua4Jh8{EzB)UrJW{}wD~L{NOcZHKt^MO(9dH36&KHyAgb ztm7bcc#d+3*pE+)>a)E1`@T_J!(2i~mF7=BXav>^{nR@yv45=>Qgkg{oLi?5w+>@1 zHo&7?gw6HD2BBJ|{`jWru}wlBRR?_alTN_rPRC~$-o|-wkQNa*NH*>6L8rqpx=!q$ zzX&5WQMyj9E5G3ET=S1+o!Cd4v5TA>(24!N8MZqe{X4ln_)Yjytx;<`vD7WXQ-U0v zZHU0_v0!|PdW+DbO?avtTW)mB4o9U64F>$;^Dp>CE~YBR$xk~?C)TxCctP`px)b}f z7%DF-0+q#rO>;}tiH$B1qFV1&;dHtds3@@ABcnPDGQsFVdO?X$qN(xg#KvqDdc*Sa2Fh_Z2fZbA-HNJ?ARK_G{1$~LU-)|MVYGxsDY^z`j9%P|zM_#hJ>0y_a zl8YvDQfclVWqiJ`C)va6EYQLP0 zX-Va*vP?*3`U+u~DvnL85DY=p+W-@I6cs68t15)g+T{3?o1kXvd99wIpV!|v(qzqd z2v4$A2L!G4S(v|bXmaN8a|I$gv+c4<&SMCfI z7O=~dU0$ck{i8I1`s7vG;YFzdSbm*WUlL^rPVThm23Jz*&eS&06o)5}oLOn$9XgVy zQ`6|8FaIhF4kf_H5+N(Vr!cQW6*;l5Nl?CT!H6Bmy;#}|T(^ej zDHxYfNZyF<_b}gf9;Wysrm!o7{MNWZdn;WE#aNCd56N?Lg}W5Tx>P5{>6}(?e#g+ zfn$6$3HNg8Uk<<2n}P8;2szH}K28|IRcK9u726RQL~{eyJf7EG{RddSo^!axw`mT| zJ0)*^bU~}!b=6R7$?+J&!bATyhWZD`FxfkZHSUM6){?KF^3_8pD9EA1IXfT!$?g*q&yuWANS$a=a-btdA^Q-{K?3@KblEwgXZ%?#}4#fB8 zbllQjC~sawQ1U6;9W=bvcD%Ov1Ch)q5uL|f}l@d|sCX=rQi{%S8?k##t- z(g+fi#qMP*vEo3^rh8YIR&&hG=XCY~X8U!;{%XsCzei0Y2`u6epgN8nP8ApuLQR)C z_W>HtVi3*IoZZxPZ**w!pBx!G<;^yZigoS}uhg>Su;!ty!)QDR758@eP;mo&a4)^W z9;*_f`_-RRI-c9c;+)ds0h~MwW~JbSK1*f4V%NAIMPojcBwt~xs)U#x@1h2qMn&+s zhwM@CagET_h>y-!8mUUobFsQAA;sEjKSx4$g+9U?=>s&A=%W!3#D5}?gG~v9(B*}S zFtQQ={SAG5L4@t&nQZ!TL1LdD7Fr0Sb}BHZpJYXc1xI4#Vu-5=WVy%1)e3S(esOm# zESxDJ?!kn8NN{gH%oZIHrnJhUg#l>r5{G~^g6Cf+*qtLnx5PD6e)NOoWvZAb40RmH|16$Zzxq>&(^Z9xkyC)m&MSG$$4DK`R?h0ZeIH-N zjK_r#b*JNO%yFT6>m^*Ec&QJ-;Is1K9SY)qKgL!a7s}P2A7Ib?F5DS2s2spJ(*3GS zc=Ode+$%tZUVbO%k>?rAS2^z%Ix}kIuUH`9u!Cx(nd}%7l5o_%$6jeW)vn0xZ@ZS*O0sj>&-18Gs_K!`ofe7m3ftM`UUL_V97eRTN- zskdFgn5|d^*gT1l5R%5U*1sTLFR)$0-hfU;_y(~0X9e4<<_CtdODBc)L(+_NMAKk# zj?t$Tom3n56;-$OPJM?w&=I17BhE@w`&~5y<+X`02F=kM9cpO3PI3QwwCdLwZJkw+ z@tD4o9Ku$d5(?YLf*=}~FRT;oWmmv7TfH=otnIe?Jv4{qo)-4$62T$}<@j1|P)Bhh zkZf^2k2CSRY{XKjWh;EJ&}`plwwXpiT>c{b6U+Z*-*knN_u1tZTV?6;SY#RmOh7$?-EL~0Zdw|Vi|BQAPwsY-@F8E{9W;+7BcYTM$;SAyMq}l$cHv=Y% z>VgF@z}OMZV{<6ylOcx1K4pHo>f+Zb)U*gSne3b1z#}&j3>(%cWhvo!BmHui+W`V6 z6+$(Sz)}qT({1+HS)r?pPZvThlIT@9m$0?3vz&Q^)wYO~un|ZLUK09|Xr!~(ckQcxCn2*^@8eJ-X*gm+n@sqBfKcQOpVw|!m&JCoFnxG7RURm5Y;H!q&o!j=7t8y zdH83PU3)C{-Jr53%tcRLiK01gE;^-2bIcTV=?=A}eJKtiFc+gNfm_T;2XnVfv)ygT z&4D_Q=(gxW6z$14cfjVsU6UrS%@B3wq^-GjWO0u1rCGpkkoFM!?HoSA@ieBIEhU_m zX0tm2<3I#af@uo%P$Zz@Jk>c^CA%)ctt&XsR&V*vp0-GK$AOP-ShE0ZXXZd3+gT4; z)Ez~2(fm71^iC|Z5&@rf@h&7C;+S$>fGRi1;(RKKhWB_STYFvzYe~zkBbB~iav5R; zQtYYW?x?-&_wzVKw>VS54`0@E$SjTz38MvR4tOF7kX;AU>{o%fC(?>MguvI+oYHoS zV>0juk02F5Cwj2WyupWaOZz?Mq;0uH)1Z9lI?ZUiL-3+L?7vcF*V!gWO$*##W0BW( zs@6KuF#E_2C+QpA!W63!cs&`F7FdGaXHB}iHVTRiIiI}FmF1HLk^TYP`R;1il}@wu z^~>qzW8B7UYO=^MDIw^0Wc%nA7C5YkaN?#xQxK3$w{g}q=oR-Xj#~IAKq!z!hq0lA`HIR zx9|x$?^N)GzRN@~gz7KciQo_$7L5Zyr|$Ux`T;I?-6wtpK-s-u>zzapfI0Wbk}PseK!vdENW_J7I} zdzES_p;{oO{e3OS5+GBS*_BLtO(<@i%7LYQ6p-Hn6BCYR$&1GE8|>6IAx*uvj&;2* zJl%XA=C7Be*3Z_m&#nvE>Yy^Fx&fi;sdCoxhVZU>Vk!IK2F}=LTiLc7!VLA`GWJNV z@KKvb05&|Qne4Q@K)2j5DjYg(97nxb%4%wb;p&~gF=L(3xjkVN`xKHE?t_oR*;ud& zI(6;9X8jZz&OWab+DCT4M1qYw=mZ90xuV5h2&Fw`EOvMOjh(I&zKo!Aba+3(?DdfC zO(V&rITrb`&uucfr8Z6oY!(%858V{OG_8K{#UvOPqV$~x>nf1mAO*~1H{xi}c(U<>I5}@50=x!R6yD|$CNF8-%t|iFJhT)N^#dAmC}*~xa^C`50yG}D zA80V*3MlG1jbAJtu&2ib>R+1DC0`CQ0T`)cEZA<4UcfP!{5Ix2if9CF^=diq7&>He z&g+9c2t+-1YEiAV!I6SANUTxFx1P4&#-$LsxCTVdBLhgYZGN(!oVON9kiDi8?t_Xz zhR#g|h$>5&ggk!kjcbWAub7>y=~Tu&&b#29DFk1!6(S1kr>({L8A%O|`>0XBT9Le* zC-2RvM)@+H7kOYRgDM=WUqkH}_m%{20AlR!#^EH4@f`v|On%2{%gQyS#_H z7zh(#-Zr1^gd|bWk=)}~&@tRhfZ~23rdvsNNV#j*1N{mH!0Ok-2C90g;@0|gWzpDh z@;Pw8-#+$nKsT+(di34>4me;Fd5I6n7ywTTGnQe!qLT0q$|FeNgJJ=hoko)wG-Xt- zxPQbl!3RYx=SL#ndMyWuD4o<&a$b8xdI!aYB*#d-?KTEiR>VQ?MAF_GP7MSCXFu3{B zr7HjjXOW;AcJhvp(RX%f49=b=1ch&>=hzDOQ$N@8&kNGUHEhzZ9F^m%=7mm^UnyK_ zQ;LrRoh?Ft*sQxkzgAbVIK!mf|JK$RRIPlNFw1}Wwis8*UBRSMC;rNW1|dRNvJTMj zq2UWt05(lI^Xz-svXMdE*@6Z^mSU7@Gv$0^&XI zd_$N(XYAW>|NJ0nxPSXg*5;cDR-XGQ4#NhZ&J%YvJUle_DwP~ayI6skjO8+d}yn7|7i z|Au|iOkB{t=2;X9ZA{}WrBflE5Z0K$3nhNTh6IRXyH`>nLt`2*RPr?u3ME80Ch$V5 zzh?UaM1yz$V}mof&}AhtOsx|Kw=oiFt)UVL50+^CHJhpvdugKHdXBxP6F(N0mncPt z7soJDpm@G}0hQ|4Sc(JC|4UTI6Z$tMZ~zQny2c7(fm-u+NsQ}~Bz_yHx%G35>%A~B z(qFUn=NOheSS)lch!9J4nh{^cxKg6UyBbZuuX$#-+SR42_)l#cMY4d%E&s5`GjtG4 zzS}A13?@HU_XKgXN^||6F|L}P;u^JP1OWf6xA>TJf^NmxZa*Y1IS|M$_ZDG&Bd~-{ zVmtLFf!z`CED%_vi03~9Hh`Xw3Tz@hWq~cC=h;B^2|YIiGWij)o$5{2{Sh%rHHD3! zM;|r^4|Px=`ydvXPV3mO^mOUi@3G>Ons)#ZI($~m+V&MC)u*gWU$K|C9E=S>3Gxy< zd%CZftS;8F)qPP7)3Q%;#Blaqu&7hd(6T~$*@YL?V@%&qY_A@!Wsk=rBV@sdhs15J zcKyW|Rp)VV-&Hx@6O{x*P1+w7V?pQpqm2lp+6yTelS0n>mhB!O)@pyk63ZGw#Wv04 zCCe!sfssIXHiZ}W6hkzgF@Lg-$zr^^)1Pc)ve;c!$85=B7wa~h0dvoto^VvXfmTiK ze4D$c^=K(hMRB)L6L&r9si6>L0zc0=gw{8w5Pe*8Jt6ylAjC`9Xq=O#8sd|CHgq7W@_o--8U z03K%ZjN(R}gscvS9@sn_)RWB^C(Jphmzf>Q{Sd$3$1_zn<2ppKF_-)43`Cu$(fwLraiC0wA<0WHStr z{e)ZJ9;V=M+}Pk=GS{`zBz~dRTzNglg_*x5P%~m-jO+Rc@kNztk?Ywf#DAzYLtczw z2QtJA%Oqknk9_(7PrWh@jD{!lX-wdZ<{%Q3)kQf4X~>yK+mRQ@f9|*QV_5DeF{67F z)i|iJAZJ~}sYaeKxG{m(`0zMZKT2$?X@=6RMvG5(KRFYnM>S^RrQaQk(mY{wV*)Sz z@>sTZwAfxVWFC4m8q3NmD*aSrCSLkt7E1Gk>5U1z^u8=MZj2Zq`p@IcH?k-OB}EHIwywB%Mx=nJrKB(CC*GVev9cJMer_e1dGGFel%g65?*ag;P8Gtn!Pnv zY~6CoQ;I|}0`M3TI6>UnxXUgpo4K6zY5-1}@(A zrWLuhY1rGyv7rt${P{HTBl&IQw7~KfrGk1s9pifZDY3s=95kJeP|$^GG0ZqY--VSt zEiP7nHI@y2Mx3L$v2Unr(=%dARm*1pHgvzk$Ro1qR>IL~@~qG$sKqlwJfv>9kRbX? z>Ppmz)JIwHEYap4zI&+Oc(&(NG19eemIzbv=_6}hOXrAZ)SBnU$GD!&5j&_fzfO%| zZ|90rHK)hLxNhZ&dbQ@W(xEPCzGzTs7H%ENdc7!K(Y#(V)D^uzY^~BfTRfBvd`Y~n zahYpbpM~Nm&G1n%u7ZW)S1L_z;ZXMIE8+^xo8w~Go>#;cn%73hu=f^=pSv7Zu}-Bq zn(2){FcJ&;VzH-6b8^#A*X~!vRw_-&#-Xlin>bjjS+H)XtM_XJ%2$up;${zsX1_6p zEq`5HuW3I#h7EIw<20L+W7vr)`Y_iPhZv&jdvNVg>{{ruL_!4((m@juf<~p6Ot31^E>|(*QZY z9&6IHRQbwY7-4P0-)W;9do9hr2f9Qx6ajKx5m-6hMxn~O9ZW{6RO^O*G4OhJ{lA8i z#sX^1A*+TQ!iXEZt7WP6nfi5|Aw;X#&jy)mA zmR*-K+ZcaUEh1~I%#m9B425r~%oItEub!tj%JIjIzcyG=X30BX-E#Z|<1dt%Cmk~W zq9pa?Ngm@Sp40+2ExH0!<0d7wD^jg;yxX|Zm+ar1k~b>JF-V@4YLCU=BsHd!4uQ-& z_!)7}Y%A8MCAslA805iJRQ9M(7ryli#|oy$mAyu8hk;OqWlAL;h3WQvX+>w+rmKz^ z?Zw8TKij1h-R|EeHSS2NeV?)DOuN*$eWti7)6-Q{%Qd-k6bL!#QfPS3(cVK6z1WXQe#FCVLg7Z%5)@3KSzyaos3q z9j2c>^i#n(6#_*-^6&UNh`(L)RRX)1^N_x*X!Ed*#4l{Lm~NsZfY ze7c0n0GI!%t-ou^$`L{xJVO1FV+nu>G#p0>l4FDsO5J-OB}A5ACUhE5am7~ta1BcT<+`14yu)is+{HnRmq2=5b1@4j4g8PNlHPEbCgw4Pr3lbDL3h_aS{jEyEVb7MP3H}k@0+pWf zrty(lZ+x{Ut1&*U=oCyDafLA-f`%n&o4jNp7#AkJ$>G2L8*qC5i9YZ!8aO#`6!;kN zyYImYugjhEK~MLkfIjjYMDTA5PaA004o`ytBPz>DygpFYYu{vv?~4YjFE)2a6OEY( z^?|pBj-v_@2ztgFi2es}Lf?Bbo}Q~X%me3-EPt3c*G;b^2JLv1zlTbAuZ9C}(l$H* z!93&BF%Dkb3yV&+GsP9g6|E<33I0@M zw3lB~mLangCqFcw>`!(%|xc606HOm_cqUqdb+jTCAB z2Dby-(?{yOJs6=NE?QE0(BFdhzwLo5wUILw60NcsuZkU0Q=hJ+ZUJz>TF!w^n}YjG zG?aG#+H6NO|V zs=BK(L~{HVZp64A2xK!q6_;sF^on`+Gwg7C^n%R#nbMW@xC!Ch)u=I7#J&6>BKb0vNurm8f(2E@1) zektxyw^-3lY2!v$rHztqF>Ks7;%0dU8igu>%cEjK42%6%oEO>+7=Zk0F7jx}!WZ%@ z(8PZFR{U5_NFW*Wd7ghy_ZZict3{^PycHkgy7N5=kH7bhVeNl_@Tln)<9h7}v71Ug z?;vxn5&xm7kB(vO)Ti1|D$+Zv$jW! ztNBmjAhkO4ch~53VkfnF_b<%4UVK>HvXZ&zY5kpDq365`)@g&-O+9@(8@)k%PQ89V zE8PIiL+nXbw?X_(+})nfyr37NAp36=>oplcwXRK@#6eoC-xO>g#9h9P2Ib}b*lpO-!V&4`T#+0LXrE0nj3WO+h5L`j8%)E3zTBm zfbHTVngB6|&EGDzkGL-Iu3*KDEpbo7IO869A=(W3mk`5#-YyQ-OhVR%?PAx&_M%cb zF-AfT>|5MBHD2UI@d$j^LGPcWR9WO+0|J@2L+mlRHjsA`@{T^T0%7!{ion^*b7nz2 zL!Tz`8s<|CU+_HWeJ0{E4ATkMh!1u0_)NkWV#XXwG zbulb{m)Ju+pq5SAC3aP>y6t*%mzbdrtDJ$E75BYw0&z3NL6=#5rPwJfDg$XVLsZ_Q z|5cHgHi4H}?>%DYut_74b|&{nbQ0yZPkNmX_r_nr4>Gb zw0jSx1zuvk_lnar9!(7UXfN2vBskyMD@JPOAmZ{~v7<0lOXveq!kJMgB{0iAF;w0T z3U9K^D04J#A9|co%Z}_5JE|M}Si?RsRay_EIRf>0_^3VvjvSdN!UU&XRgC_$^W&w#z{LrNm_lHL6s(*CfzJBBW zwDx|n-JH)}J0L!;R>iQR2gFGE55NM4c~Jz)B2|nl;Gk$!Y0O%zeTT$X!wP7m)Bo#% zk$(R?J99{Mwz-3Ov0*l4c&af&WP1$v^>fToCC*Uai)QszV!O7zZ{GOp)c^EuGd$747cjB?3Ijo z5JQLEc~{tl!_df}&bT9DpL&)0{CJpK(nAG21U^`@~t2+BKd+4Y*RrMvCcU1gdZN9`}j)}e0pWR~Pj$utZ zdy&0bilk17we|P z(rG~cK|p1(pEPUum+o>5vFXmlM11o+3a4z)^1cvmJE?-50qzU}+o_K6TF7$xR2XHZ z>x}SEMf`XYQg~oG1^AZ~d!Qj`o8`Pt2w=;c?#xJxP4nJ`afakuq4I#Yu|eE+7f(Hv z#50PXR41>B3={dvmSLEbZXX>E|L~{|tQar)oIu-MoDtKvn~jcUNn3MZ{v+p~Lf+#IWUTaa!d-vs>glNKyjlhTULHM8I%s~*Z3j}72YE5KoTj$sl?Oob^W z*e>|Y?4}Es#Q>v0bkgkW?Fb6UdFkj2v<(^}bl8<$Gi&IcbJ6K$X3fYb95$4~+QqD@ zA-^m5T$y5U*cN5dY^5sOR<$V!fXPeR0Y+OtgUSRTbaEaUD8RTf97rexSqII&8SSUC z^3Ma|oz`fI@4OY=rqv;GGSX>f0m&D;_hXKGm$K+6Bp~x8kf)A_U=)ZT6?U7s7&sbE zl$vldt!%J&Ob2_%bTGFOg=daGXmMQ7oM6})iMnu!8gdpQ%RRezfVNYd*x8;9om!~Y zGV4yT%SOS(&)9dAR-yd7KXJ%Z{fp0z2&EewAqFDnKIko&s1E1hAJQ}7lF9j013tu| zN-H|sjP{Jl;2B$!afMdSqXT%daRhep37sK*Ajq6CI~H({pGQFS?jdJxz(fQWs&{g! zuPGY!bwCrzIY#FoRTDe{msv#~_?&~191ivpAj9C6CGPZNQO8=3Vax9;;FM%<-o+d*_5x;VS`_T-Fxs{oo6W0Ibh0KuE8taFo|>Tld5&avlCi$c6ayP;+qPK)iM>y>xg3Owa_TG1Rg5TrAT?igXb z!=i^3ekDh;h%;jAA**=ggnigWZo^-Z9Dfql@t{e(_y=J!Ux$~ya#FU!xWaEEkz_)h zksnhU*VFg&+$(@fhwYA^c)VY|bM z&WOEQC}1uns26m{Cpf5{fV1MD-jhf=>D$UD)#&}P)tGSv>t+-soNwt%m`|n!Pat7h zfk$+`dRBzB#1fCI{15RxRanh4$ou3P-y*Df5_v}-V)M_7162>PP3Of&R14Vk^WuoM zA6|>*+z%WUJp^Be&E^##Yo;OGed(NQvRiyf)m=|Z_K3#n&d|o@*nYs&gAzVzOyFW& z@qQ*=5Dj6KB!ZPcDAw8cv(yXX2hERyd)}9u*vFz2slE`c2wIz}iJLqiXoWR@AU{4t zPxgzDvqq_o{qKuez0fijvr=|76|;_e6o&r4C}zd%{?B68GnjVwnUwGD6^U6RG!{=Z z$ypKlQ9GLmS~c!ySEtKjxJq-XI+_i&={|Sm06RUKV5b!g4P>V7@PviP}!J) z3tF~a%uypgqv>?cD`{>0{of>=o_}z5UgZAfch>u=*s;%@v(X@JeCz{krzA} z!dd>?k<)BHf{QL-XM3=Eg>a75hZy!(XQNrcRk4q%gjHM>yQ{T_*zK!gKg~JBlZ<6u zf-yzLrrW#gXS^*xqon;+#scTBLXqfVQR>&6$Uh>&!HH z%<*e7`}nFDr)tX@u8DE#{Rdo~uVee%(U0($t6v!=q;K_Wfh>kvv5V$70#DS6FKQN_gzvjr@xRnHJJ>6A zVpQv0JHQi72B~_Pd*ohH6mYXF(Nl-HdQ|*Qy>br;hCMYIZ+a!e#6ACyONP^(|G#9| zC>j2I{NE(Q?L~i)44*`v|94A7`YzVMF{n5E zp4ipsuH-9GHZ5upxOG@!{4)-5$}M(pR}vv~8?j+P5@c>8$;ViXXgTp0P)+_lv47;Z zCyA!VY)1kVhFMrbpvL5D;nxSF*@=5%nEHGvyLnGcP#Y>(=LRf>%??GgryIoBcJD)4 zK-~|35OB~7!YjMkng+3rrU=#SY7ifdoOP}pHjK1Yg#Bg2*D;s~TmGccHDpT#!}`4DlD$4zPk-Ja?+`(XV;_|hVB z8STfgF{aHItZS`msio%JzG(JOwe(>#ZqPfOMbrtc`{UEHUcFY6UEVruE~;JLU7m7* z{W(~rd#Y&DQBtB{!!xd!6>Fre>bz~P*R|3tm8uuJ?Jq4*uPkSCn@QK()I1HU`R!*P z)o`&^c0t{LyO8AtNL|7TNVcV3DrCh~mKE#R)&Oac=98V#thr8#)8y`oW{>Km#{x8% zOIX?!sg={_8^3`zE2))hjjbs1+0RT2lpvp>lKFvByS7`ma>8gTCH36F=>qcER`xUU zXxuxZ*`YuwR{isK_WlgHlltr?w(TmEn1;=4tRVFZXoeCPTGoDs-0IOUfd!CS(;8cB z_tyBjk~UQTSKU^Y|L*P4tVWQc)gNzD8kw-+-RokkKIGS?B(`n~n=eW!nyVGjY_lkJ z*Zj5(#YD**VETpUW6Or&zS^RR?fls|Novt*!Zsr1_#k>dA4D_nMn$xr8-9D2O48&u zD>ea9YY0)Ftn&>AN0ehN(*#Mg#W>`K<_q&}C_B|$3T<0~<@Yb$d$`=&z3+?I+90W2 zmpeRSLM1h~l81vs4DNR^!iZ7M6iC($`lT$I{TU>6R<0E; zb0D^~OhN3j=j2vxr(u}?((=AiZ_7gpdCQ&ui2@KUdCR?dm|E_&?yoIpm9pSja;*B1 zGNs|YKXJvOoCjjQKcQn-fL{7az01Yc=%oSSOSbaLgAU^9Ui=fUGiYr|G;0><+@48n2lnn)h@O0djXu>re-!aWYgz%F4 z2;UPTg_%Rg_NLq2QdR%NN=^R-a`4oN=M*VIjxv!NJbc^6z;a{N((7fy>cUaI7I5&;hBxR zI;bm2NrYCWa$O0Ix41`8_w659UWha>;9ybXxV0Rjch6OdS(+{YrwhGZ$WjuUc3~Zg zQx`_#>CRfCbioeC*1QX^6h*Vip;Awc5i#$EN{+Vg^Sb^+7bdXB!q5ftdbT7?>iTeN zj4{TUsAEj z?WNu=*3qKty^sDa!qChzV`X>?*7l2zI)BpR<*|zPQv2X1keCMb-wG9P1wObEBu2d};JVuC65qj-a8B9=Yr{J{HWcb?R)pEhYK~2hXdyV<#VO-;$pihI~ zb4p`MDl*E0%M&gc<96G(qfrRt!|#{?0wj_K6oOR*Vk=>jgooScG&jT@MrgnNu-O^m zq=7IyhwIG%>!eu)w>Q#uCzU75%S$auN38PlqGa7Je4`0D zpvEsusDSNx3Ur%l+`8lnN2nwNpp(OeZNv`L+U{xi#R)_YhG}MSvNkt_5_J4x1;x^L zJd<^{g@*m=xfAGY;3VO(97ZxGd)Y9jVZcylVho-2L*Z{-1zj)%+EqsM4oZ4$4|-b< zgD`CmD2=s=W?QM=)EC`;z6v$Djj%0+p1fRj6^94Maz-2N6*yjK#Vx7cB0DneI#M>9 ze)eLJy-&`DQQE4PUSQsjIl|{8TU3CcN ziRr3+W=*!?YcswlurlX~RGihEAUD=)6daxa3IneiZS?`kGAm8ayDI0u4{}SW@DUnm zicvqBejS+6zDDLPfMK4ydZpL39WGffG*m%d-507|#fpJD-}K3tK*>cuaZH9ngsX_2 z%H_NRATxeywF3ccX!n{?4L-e#?>E)ZF$vm@O#O)~lRHjxE_L`jI?qEu+Nq6>ZCYRRv!L?rosI914ZG>-_fzAjz5cfllN=zwu zM#(m;LZF#NRY>8l6OPhpOCd2WCt% zHhM?^lelPyH#4t=Aw1b~_V4)|=S@CN2sZEfsiX9=KYQqewgp=eCv{h+{gZ8tld{>V z1gVea(6`YnqNfxdRKFUtNS;^@`=IJS*qo#A;WDbHG*KPClCA40J!ADbr=}(2Ph8_M zV+rBjf^n~nCWiy(q4r(eM;SRhBoBwMiqwyk;Fv?O#O*~m1zfqvA`iZX^CLPpibFZG zBPBeItnhHJRJILA42&Pv<4Zp9pW7X8eDX)C@%eM0icU;n|D9uqB3I5jtQiTH;3qWQ zzCX=gM>D?)`zpALr`lp+kHx1sRw2*hnBBGpT;*;el|hH`Rq=1NVGd&+2M1bnx}pbWEfO@`?Y1`|O`F?-5_B7tdCGIA>FoE0IWwGC zA@NNrQ`{~&wh~bHuwB+-i72|PmP_~g;e^=ajKKDkcvH3^akw)g%%Xwz!-6+GQ3lSh zj}DY$B|uYbRe_m+rAq>AYxTyY>(8IVVv$JM`lzm9rRb3}#D35My3kov_b|cq(mDU3EMFbKn2|FeoM}`_}l?V zV2|1PxSkdkb5bQ{TC(n-oc|;(CqyGsffupTGIH3NbZFiM&n!@bm7l80@uBHoMdQ3b zMeBfHh-(WHb9=f2e!qv0@Qs9R-L-^5i+yAiL?v^RS%Hb!Sb$bmoqKBnoD88v^$zbm zNr#IEpfjp^lOjR=dVl`pMAB6?E$iG%deT7tAX>srS2#d_J`CUv)>r%T(wkKMLjf!7 zB_+hrk?Q>uIDYIf10E%!sD>xJHN23-4ktucf^g4gJMXZ?ChuV_wx6U~0@ zEuB|SU&+3F7#bxtM8E2bG##hO2Qfe>GL`>k8w_&nelS9yb3gv@%!C2@9t821i9s1# zcujsBcLn12E|@|~DNeEX(!^BfB%>Dpg`W{Wm_Va<5`R_rqlqxp&;!39SNvKGPxZMj zzXCHA6o4v@@U9r-B9X`9mokDzt6^@B0up|w8ff9lhD-fab^}y`q7t@~I8p}eNP_UL z_0SE;`*JQ@^@ue4-6ZMl=G)$CD#|J7=*pWgh!>@NiF)~n^A@R)RJA)e^LkQv9PRHO3-<7$4bDUzkm`Pq!=n^iQ)TVhD z>o7o?$m|28l&)#^1{qG7- z@)n+cAFmox36_|oN309MnrRa29D_q3qveuIwVWW(0Y*dZ7(Bv0P=~FJoR>lQfOWH7 zJJG(xk&}uYI%}-o$c8S0JK~tfZ-@@Al@0upNMfj&~ZCqq2JZ zRpFx99{iP=;wUU%S*P#^Mv#3D z0waR70$fF6Ho(pa|qd zw!-Un>H-#O1!CN6LGG+dlrKmBv&cRs>y*+2F1cjYH8yeefhMj38P}<%{UndaqA_?$ zx4o=aQGQ%E%({uc9r(LLa8ucBltTTiq8Mb!K7sF9p)}H{_{r;5U}by{IJ`jy{mY3! zQr2}Ube^ND5Asw~9Q|b8z}s1RJ3>FFd{G>k=cy0%6m=1~&fzWdPbC*B+sWf84)Sa8 zLRfuy9f!x>wsI&iu;a~WR-bO6Lf(=9XatqK!`t-&l}V6gpF`Aj%F2HTo?wFkaRd~H z4Ez`+DO(){wo{)7J$HGu0t)K+1NhGdK!^qF)gm6?f#8qkOd)W_XKelTwO zm$NCvuW(hM91`$@1fpZ$jT%$hxAI0CF_@mD0qs!ij_Vcuaw2gfyxFquT zpZy*VC&!$Z$CSxq4tXSq5olIfXV6Q8vkg|Qdz1Yy3k^@>3(Z1E%cvary3%8+Ar^&Z z!XrQV>c>)w2fm!bD+mEg|08Ugj4e*y!81;c`>6Hrg zN`+89qC#Xtg?e5gmOxa9cvPt86{4Wl^A(rm(Nhw>Azdqc=!PPKFTVISaA|Q^br#2S zIyUF2hgu9LN0G2+gQV;jqldShXH1S^84zmayq&NIG&y7_c8u8Bb${woN17ne|LO{A&VtMFWeX7Pi}P`Vf!$a62bAPL4nGf&teOugmbZ9eWHLpeoFkV?=N?r{zrWnhB@C z1R;4kSAf)(Oo0mwR2+HbZ8})Fa+Zr&7{%ENm$qW~a^(2^C{Db(27e~QeBK?RMtt58 zzmSLICGUe*I!5-uBu8(sW`H;#rX~WTc=W-0|6pn`9@Xf-~NI*>Ur!Ytehp*M>m6FC4KegT6VTZ=%q;qOv|NSq{(fxR3^i>47l z4aVfg7+ogr2#$XND~4xYR}63=?y+6B()`Jo8;Kll)DEQuL}08&9z<*fJQ$G7T0{UA zOk^lD;_KxlEr2N_l{EDuvm!J{GV2;2a$w(v0nqQF_0!+ za0m+W-lGX%lyJ#ODC;6%yMZ^}Y}P^rl_=E(aU3j;WjXUQ-T@DKeFcbe&x`XSN?vkX z#|90PMqA0(mSbcDh>&Wx7<6!JC+9r@(UP7AL0@KvV--E@+ia(y|GEJE*Ad%k4L%$> z_yE~xFU>_2_6z*FTX3M97Xy1^%sKQw4a;C3{-&Wf*gm)BZ~pWq$@v!pu(7AGelv8> zen|&%o-x|pCTBWa&Ed;%l}6|MJI1&@MOW1LDh9URYNz&B6 z^G$G^yR3e=WU!L+JpMUydFf%`$l|cA0`wqB$fi*0ay_ZVz9k8qhARl+?1uy&eD!l- zkYDnmhFMv0+5xikulk*T zm-CrdwG@!`Z|ly#%WjU4dRp6H=EF_NS#(xj+6aM(iPvV;EsVP76 z#*Th90AHq2G0UG_lV43j2RxJUL+7>tEOZU}iuJq%|2_Macq=Bw@>SG9T=R3jG+WNI zW2jAzp|kmF+mcRFhR!!RM&_8E&+x?vV^6%A;DxWCMF^6bWKWuXC$8$IJ7??ZwaDxo zrne;3K?4cxb2%Qxseylzve5`-V`}?9;lq~F%+{pK(8-$uZyEEjQcb|x7O4e&CE*sp z@?!Gcu)N5q+b-t?P^`U(4rrk6!f6aYg{gqvx&q225)9rTNMwC;D7@fEf?mMv5R*-E zU~AAN)<)>1<=|#W2oBGgi0EP3{!oJ%H=)Zsd$QJ>e=Gux1)#@9iA-%SovIAe88>ka z8EQ{v#*tE}b&!sy>!6vJV=u&&!)LFW7Wh8S>36WyB}0R)lS?o86+;!G6GD$K_m$g)tNLK#>G?NOW&YBk7<+V1FptdHm{XKe-eazaA{9VV**4h+$nQB{nSj$}D+HF{&RABQvH?-3%TL_lNJwYfz_s8Hb##|s=Uja^Lj zGdgD=CAgI-Y3B>iK2Q`&J2(^P#Z!|G|9cHq1+A&5Gq}~)vh#E zISMszG8|cz7z*swg2VVw;09y^xgiC+FzvOEgg}H9jCTH5Nx;i=X8Sew`+NC311CdW zh?C=Q$V*c2!LI8@tdvmWD61%zksj#UOJ-^fnjC~*;7j$$NeB)l*+QQ(m41g#=RQnm z4+mE!=vEd5@ysOPu-}Cb4*7Aod5ABRUrz;rfZ#7-7P{s5iwgt*;U8&__RD!0=OW;r ziHP8eBEAqgAwLON2V<2MF}$&GyD;GZ{&wRJ%lvp? ziK-lrBoG&Yh!j#qW?w}Pya%U*&h(hzPZRL%g$Ec<4(A8S%sN_XV}1Kvy|U~Y&=82r zvkokz02)ItvosMVi{z!VQ0RUv)=tlOUJc1-kj~(UO+{$v(0HoS33qj!wmu0%uH#t=Ap&W zY-^^}UG)O1&6IknOFFa8S^RZumef&w!jDvOs-nj?uxbP`6WkQW);3KVoEdg0D*v*_1)Upq9H+Iskax?cZP?6k}OI6 z4Dyo2C`iJ$7C5KHDhH^lp~Fm=QOG8KmZS6h#3Hk$VJ(M2P)kqRNyl)Oq%FR~**@&m zZ0WU@i7F%3I67q?=X@b=5k+0A!z7$Z<2qBOOga&Jul@Y#R%}D^~uRu0B!Z7m#vqKs- zXrg2ofeACANY0~aoQA|6=@2i{utM}vPBlv*EfiXkcJY(WLgn<6; z0*yI?@q)4v>L@vL8&04l9ZCJENn4)ZgCw)cZA_|G=geT`lcWfLIxAbks-BU$Brcg7 z0i;Pw@Ds8a43QQGl4{C{4N6OlAoXNSg9tD)+7noC2sn>rPL^Va<8yg)B>FG`zG6tc zkxqFR5!SKNlRTuyFV{Yjc;Mx)s8id_Y%A2_BpKtR%H0PjW7CuNeD$iKi^AC;_){K-715+&N4w(Ezr*7Y;tgkDY;wVU zE3p9BE~&;QZOuf9T#huk(*bjk1(RxD($+~*cw9CFbFyQCKp*GOY)aZXNdjjl?hsmd z99C&Rcok+|@>$o`-z-_dv6mserv4L4P00;*Ny#;zPXi`#?#E{BsIE%85QUP zS!+dWWgy%V8)Hk3`D@UL6*D;#1gy(iSl&&{3}t_qVBzM#SNi8b{!l_)PyAOABWD z&f-^zF!G5oYETLhMj@4od*ivm@vuy|qwS2QQ%Psw<{u_gJ8nNp|L@}G6!T>NKIqot zM*l(oZ#?Cml@}P@kP{e=a$xVJwoZ}4xVAD5_Bg>I=+akc=1#aEggky5YsLl@vyEcJq}oX2?U!!&68JLjs=S^`{a{g2tN4qA=7}| z^wYG!Yt{kZh`xI;)%apN838^W4vRM&#tYVXllI!F!p(XAu=v6`qhayw(tPn%2)5bk z`!gID0tLP)SJ>xM1-oU$6?S5((CymJpe0z)m4gDn>uK4A3<9Ay3h}A?LKlG!T6gpL zx?9GE-Y4|GQCV-X%qr_GCPCBMT9bpdbtNo|u-=lT8DDR6(oZ8!TW?PT*?hf~&1}=1 z5C#5E3vT93RtW}A2eXpDP}kd(tYG#(uD5Z9^%f!$-%Rs$m_1P_bn0UL_q8>Jt-D`H zGArw;=l`;vHe0~b)CCOUqLZY{Irvc*uryl09B`BYxjQr(cvJ|7uUs&aqSVUDwU1kd zL}LgD{n0G+1-dd302A#6B07LyQ~3n|T~>C8o+Zf!VfmG|O>5Oc3e#GJO}A(sTq#iTTW7`yLRo6K3O6U61n8cW`sq-5_)e8~C6wxbt_QXK|y; z;*D6QNjF*WI8`13E;udSz!p3xbnN`JlAwh*5{(29`!?paKmr`n&SLK&f%!)E8Gh`& zm2?6U36ux{mr#XO88Yg=K$k=oGfPM|=d*#cgsfKiqHiA{(r#8WOX$c}%n~+@ayjv6 zElE9AGcZ6%vu1->zUQu2MW=u9NI@A zECr^}P6~lIOrgyb0^>A=KBUk;d1!d+CWw_ZFBoQ-CQ}L&#ys@^pM`&!s4mfWl%&cr z`aI1?1$>@z-a#896}^G*NXCwJk--Ci<>N34werWs*x@SHJ}W@;i_S|FEt+3UMuU7OWpoyxC=}P|-0EZQ^9t)x| zKr^tfzG0hGi#KJlFw=W3n9JEDZcdZT;>M_HPAMCr_}jn>0boN9ZsD|u8#65g!Zcc< zf=CJlC>o$>0^uy^E)~?m+X!CbYynUU0%3Z2MyfC?90CAl1=B;UwzU{9qo6{~Q=*Dnvynb3gDFb+n&YUK-fP-aN zgPXx_L5Gilp{!SBK5HO97u@v$)@H8I$97#_V1fXa#knsVHCGrk@EuO-0Y^Sfh40ZF zzJP)K5a)p_o92usi530Ux=TuQqUd{qx*h=Yc|>JC*k)}bAzj>ZOCClFI(1%A1kCRlH%VHm&HWfv6VlKx_ESvcT~+O{>vJ&8Jmrgiox|G^rL~ zQgv4Wm^P!Mk;#L(1xm-9x{Qud7Ocsm@lq_!EC4X0zEuHM0N}}vrWF8~P8(D}EC8_t zXh{G}re{297xcq zI`n%36nv;VK^+h$JINf1MJ(6Uq}E`7 zFwX!&V8|FC7GJ8`<(JSwB1KHK0uU%<9?|y;a2as*56q3miobK~QK24({PsP9&&g~7y*6XqIP*}$*-a9&_XG1#E_Iz2~igh1X2hqoGEk*hUq(omutJmIyQ69i_134?HkXuCe$+++TZW4yHmJO%3>V#dO5X*O^*8Yf z3t`Ly=|T|zICp`t(8OJ^))RO6HywPfdJII(26t2%aIqL z5bxX~3h~aBoQZf;>F7a<Z*^NoPHg=YTDVCP^IJq@5ixj|7Ky=rOZ020?+7@c$ zOHT^hEsk^So}loFWk>_-yA-!#MxA4mmkMu14Zpe9##T?EF;P$5QO`~#N5x;&5?2{v zOcxEqV;sbUJ{@?D%~>Y&uwJ-ZB9N1tQ6mI>GP8BKL&LEWf6+)6gbXQf@Cw|h4j z(aVnPZ{5u@&df$VEhKa<?p^oQ)ZrczSs)O>R!>GBXfUT9@fie$d0xQQ^1MGpP*&aQU3iTl3YC!8RhR*}6X=P|eyF(*E~vmkYD}*N)Ebt`owd=4t(~=5iDoP|p*bi+;avE* z4xRXRnK2X0M(Dz$AU9V}$qDTIHpz=jQ!G$DcItq`(XIi%TH1aYWCL2a$eEKq*#01~&< zWfm%5_b5Lzlpk(;35f+?+MrFL5sSi+ob;s&cfREN!Gl#Fp>{ORC3)8%HJXdf2z-S8 zM)GTtD>$JDPn$|`4p?38!L$cor+2?Ilv@G!;e64-&lk(_a;pnhkL)gq8?}V1)h)Gh z>^QX_hWG{0iaxZ|th&rwP$kHMdW0Y9(I}3;@ff`D+fB!mOXSCfof~N!O5z~6VC+u9 z;D8yqu^RmW-gp4g6@;n;IfxYzgz3ejK?+H*Q(wcaMN5WRm-Q#>%Y@FBmOa@RCiETn zZzX}?^X>8>EHwX6QVB{jFK5p(p^Ifw54MpB3+-fXq$WkP0_B8J_tl`=ws?$IuClXR zR|&H$t#+~!C4vqGxHQOA}(E3CDwtYvA>2~SyKYT2jH2{&5OTl4wN20Sk$ zcAnWraniC1MH0E$F(K19u2Na?^TIXhzhaG3hd4=sn2146kjt?20MiL@>`H0*Wmq*) z3a10Rd@tMkywHANW9y3%Zv(lM6nz5L103t}$EPvibPYrqaMAxE6bV3T0UMChslxyV zZrWu9CP$O=QgTy{gFdu^JBw|D)dg0lFwHpv(V@W^oX=`r6t0eKt5X0gS}oi;d~!5N zfa!mhY~KJE9oucqCY zvK|Ijri6 zG3fPj#TM>vkyDBzJbG|(Xr@3gXbNMB}2-^kPQ*v>UVFWV7$ zWL|wl+8QcE5@vr{=#l*uCN`Dt`-}%*s=AE=sX!Z%-34cD6qKkhW1zCruZWA?KtLu2 z^7=fQNox>|C8#Sae_7~d`8kGdd|4QtHX8(nhi*eXP!Lc~XCT>St#g2RDq;!w^bQ}% zk{YwHfQ-tm2WIz4TSb2%Oa8Ag%yD^aeI#wCdsXShDEHSTpO#*<6#szd(4#Y27k`Cf z!n>PjcR4tXLc2e3Dw$x-_U~hB{ws9ve)Xtcrtl=Hod#kE4Fu7xPQQo$De12LjF zU6~qRiQZWt;yh9sPe33${VSIAiqP|p?`bZ&H*7UI}DZ)$?(ZDHU z$6qMof}9WEHK1E*C(#5P^Rh0l3Y}voM}x*6c^TG2%=xO&F8YYv;zm5c0b7=D>~;&u^+z+;-1UOddTXe$kec&#&fUf<#*{95Pr zEVkoUnAfQ|0l#tcuA-ad(HOeu9UMUx_bM=$@H4rATa!5XT}PutRxo?O;jvu?x3bO4 zz<^7q7Y5y zV)?H@mHLURO0#N(N$Xbe@q@rv=s5nR?t>x&J)YB1IskM*%PYuXIN-sW1jbZK)uq8; zo;YK z_B=vlV7?5$uE1=&E0~+uMIFX(uXWy-V%%dJ zEs$k3e&gm1D;|n5Jl~ASw~F4Qu*f4qcfrHOoZl7J2SP7d1-`d!_S4~SI5YOl2A>03 zySM_;wQlH%;>!aT7=%?TmvCVz*?*g4p?-zmAZAx5*WOSc30LAwu`~D&nf!>?n&t(H zCCHH0u(#^yz1R;OsMYpEuh1U!?k==ZBEZ)=po{=Fb^!!Ml|hh_ukB4c)zA|p-|P$7 zu)Sr4YavO^j3QID_UzfULQ>cHhZP@{=*-#*VEOvW3&2jzDn%>4m4V zwEqbO$>*`nMW6oTou6WMx2*N{MGiB6PHH zyAZKKQNouw5{e2Ssl;>96la2F7W*a)G1nmt*{JzmrvSYwzMcnSoFCJSSK?7&R^ZnD zxq&>pD}XuZ4=IVs&t44Q`-}b~Abx2N_fywQwtcY!7VX;s)ae^C1zw40h$)8j;ZaI; zN;|0F&+88ilHMt>xt9;)DC5g_U!Ky4{MKEZHQzpcL}SJvRZ$94l22>T@N+%*{xf?p<8)Ta_`m8ses@q#e(a z!E2U9q{x3)NVcH@QwcU6(O)Cy#>MXn>E@Qj9=gpvkA1mL=sz{v6=(z3L@p72W4?Du zEdt{b7X1iZdR$R(p%h!{>1uMvz(lDyS~@rx=epa-!_#iL-Bsrz6rqxCV2l-Sm4!bb zpYW0J*E;ELEUgg27WVwRnAF_g2l)XMH=(^*fiaH2xUAgZxOjTgJ;gF6p2e*fI>uT{ z?sDh1I^bNA$|kN82C;kB3nH_B-#ey1Dsz}{!33n3dLjI}LPCmrggx>DotkgWUs^A8 zi|>OmM?KhW*F`5HpD9q1#lBfDIAZtH$DQ$kF$t{41|hNc3i@6EFACqnsOj59#}o`K zz!(lMU7(=g`{K#Wy+Ig%Be@l@^KB~O;yd|(faR(8XS zm9o&WStC^^UjKlT1QjO<{}-GL_&?&L3n}ZwHzOxf(qI*SI80_Q&G;c~NMR@PDau!!5BqVH5iANd2b#gp79}ThMLxHf;<`Zhj zI7eU-5ei4jK(@L{Xcf&z?tfK6ck@UptOKvoF^pH)BuW0QZI9G7Yf6<;b(MTgd#YNg zxi!s>>49<7eKxLI=wY=6fT?j=$*dfN%HFLOy2UQO8mQ%cYiez5fVWo9*VCGOipzG$ z>#tEM5GvSc&TL)VP%3+GQjDES?9i@F6S}Yw_(|R!e~umfNa!PqzGtZ1G1fo{FB;Q>xn(@{vJ|BmdOAtz94CW8 zC}lZnqL&L$mQf2=9LvjsuonJJUed04L02g#8xsd#A_a!>sAnyP{=KaBO?^de;a7lq zl>41r53XWtU_6!k5N-}jr=azi8YrP*;4NjxKNh-lO;F3>T>>43UrI|JN*08mRDyE{ z7~2OHP%sYW_R>6i-Doa+i0c-Zq|pgmk6Gk&OfYWCo|)v%4~(^A``LQ0=G%+?ooQ{M)*7-Ewk=0TEf@31Ckw?hA z%@R6lhu%r_;pryRt?Zf_!DVUtGJCK_xV~2pFnTo44ZH2ReSnmsP!PMMG0+*0C{C!w zVvF(Iz>e0ydS!7Gmb4#Sb+q7`DtX0E($rzywhHT`3ZZj9uoZ5droY67Z4?8N4{Rpr*Qp08wGP|kB#H+BxNjbwZIFNy!H1&eK zxbbWx9Dkr0j+gNaY}{S8p4YcVTXK{R< zZL4$a;kRQuPL|F?Rh&eJnlq@Kh4(<%;(G=<-Xz;|+E!md=G@=}Lbp@;0+>>V3Mg_= z!B95*9q~VMPUp!Aba^sMTz81?&uNKqitF~HOHJ5+6xt=Xo62Y^m=mpz|Gy#sXSits z^6em3ARpKf+?mIW`9bMpS_NUpf< z3{EI=g1~tl?WlqCYc-ssy&AJoBE}iB44o(xn2Ia|(Z1xUeSPaB5aPV~xn%lD-JA}ljYs}}^A3KCT*XCdv@WU6- zJT3!~*o>XSU>=K0P%xY!fsy-=!!20mtQ9i;Gs;9fwE>3%J4D~p$iSWWNhj#c28=C| zBh_)L;L0vC8X>g-_Aqn{RQer{aVZxxWhr>s*S!%M z6ktFCJ=M$m*`=Mr@PTEB4c97#awx&PSPv?(?P_*B^Rk>9b&lQrsqjUc$1Fw>mc96X ztL`I@X#;iz+}RyVN(|Be93o-3f<2e$qg}mgQJo1t?zXPFZ74pnIjIkpgXl4A)n`K2 zuEl?nM$RdH;=bM$SWr~GAL0PNT9{fRKg)LS657Y#N`-hoiQ{ZrrEhj&m(VZHjn|M| zF#Cz@0a3%X4@><_xaFE0RHDi*f2%u=>OPUp>lW_3q}DC^e`8xe6Z%f+j;#6&s$7My zPz|lGRL2T30pM*cz$R2{<1nDCazE0982-sKK%`ZrC0PD`EY_AkGcA92UO3BYrdvCi zFSE&?3*9`wh(0pZ$E?qVlTP1%5r+8+oe{!A(~4U1rz?G#E$vVj3o;l;0Igw`T%=|M zA4s%U+3`(JM!8-q#U_2Y`*u9$oP`5vj6D{!1ZQM#!I+O@KK^2A21j~RXSqC4ds3BzTf17lJz!d z8=PhFElEM_8cE|^{9~<;XF}6X&HrfzX z;bF^2XsXguG&Bb@z9_Y(Ivcq;Mes&^2_+php%UpL_1`YKNL)gE>P}QCeJXBVM7$z2 z-q-*fThR#Ht$pq{!&vzau`?8_Mq^7e~HR^;K1;=Mv)SndPK{6aeYH?Pyg>r&nX;FBBfk(NT zqI#-P`AtzI*mEpZml|fxvkc%d zfiNDOMjZ`x1iq0@8T7x9nCOoNG_)CP?qA^bs3r8G3in_hHK$S0|2rjE`0oWAA~>0g z{YwRV2!8#)!%2r1>ZZUwG?D+>0D590)JP^_L=8l;6iDf$2GV*E5>5kq@_ek@Ri}!< zht}WQj1N6>S_5p*0jI%pWw?85nh?&3Y}+1TV5=lpv||a{WM`N52wkHpBBNQSy+RjT z9L3X3^LlyyGM2elxGB@rLS>5b!|fX*l1vXiVuobiku++Fq zT!Fbo)%jW`aQojcu&?$C*9_UC(TUs|1@So)%E!=ErMS_ZpJ!{`xf`98<&$S4^8Smg z-#%eh`+Q2!*{vn$$ocL`wr-y=wN0s^rdQ6h&iiS{6Q0HP?-%mhB(-c}=)rTat$}}* zLPOkSh!?KF{G#f$O_9zmXj4RX5J);1d4^Vp@OwPf&ZfGYTgWSj43$_Uyqp71{SAm! zyQv87-Lk5%XaKqbD<@U$xt#ji`#6TKum}L?L{-2%0@#i-^VdSx(Qr_hA8_DRS&RER zxRG|Jf~`QjCTE7gcqTAzuRhq+19=uIhFFY!Dt4}=n0as*`8CdnKCY^{1GP+z(jHlP zh8{ee{l{6FTob4kzTAF{41s*B_Yy89Z$KE6-h~qh-{U+!fzIHdq&BH78b&P|L@gSi zwaERq7HuI5G@H6X1>z!jE=D{c^v_Mg6X=s8N5Qc{Q(V-YyuG}Vxbb8%1M#6AEE|#V zliWY>3A2&|!Yh{1r&yP7g#Mma&r!D=^y0E~mfM;@ z({UI1aSV81B6GU>eV~|oKLCxkM1^$k62yN*{_X;VULclqJ8-qES$08+f%IQpN7-oi zg={7=`9q@A8m=TLMJ!4Xr7jPz-rUbfJdTQ;pOIq@Hog0}Q6tkSBq1m$VlxqH?tE zc4{i@q}rSh(VS{!7$!ht1c%STeB59)i;IaIyhpE)1&04^>L8!!qVG+j{< z_%#G$(L+$*Q3OF05xFIhsxC_g2lFrnBpo-dg`m4wak%~Fy{zbvkeo&WbHF=yOC4 zwrY$x7e$DOI7&-eXG;;MxOoXzE$}7Ac?ap(;LV?7mvl`y5`sgCPpp{6#N|~m@V;BA z%srMjy&M&VS5_6x!Fm{dza~6PLWksseuh-R0Z}@DOHLC3z*wA9W-1wOVszHia5f(f zJ{q=v9gY-bIP82l2zwX~MSSGL@glfH^WlhN%Z~iN8IF~P;kd-jAqn?!e;*EIf%*SB z99LWae+}jD=DK?|8 zX^4?uBXys56HNt>|F7=3flV0*b54Xe0_Cqyk=kw(jg86OF0d)B33x)T1Q6P!TQsVr zi%FcA?5&#?Me-L$YGF2gXb+obGDtCjB%vm^>T2o5&#OWVUx?iKyr61oDB4Yu$Tc|V zl{bg}%1~a^7|IIS`8zOELnxcq95ZQ02{Yk})OL{&?csnWvZYYg6K4NONFSQ7HCet5 zlDPl)+zH+*W^~N`AYbok@!%~wsHb}`rjafENw_0zjUMHSfievXM9MW#pM4}Jqp_&= zFsd8PCr5Qt?ykt)^JihKhkRGMf{W&Y@YQpS97vYZXWUyjR64l)Z*|oznn4qT8lgN; z0YOn!LND4{1Q0*r+J`d$(RYDL3O+*{OHDFUH&w-OGfiA&4RZKrjtK+<-PoUfS=I>ytP!*_TMJ zDk;NYWPmw&oC-@ISR7!kI>`1WQ_4LK3YyS{Q};S}4o_PpO9HY0WCbYYE}jY=mrSQ- z@n8aib|q*>u>2t&n}lGgQeq0Foy=p?5UjYL2OS6=oyvnQ1Wga{U_OGSN)-js=>Hle zx)9NYck&d3>!S}kOw@WiS}*#7XgvBFO>2A>aqVDcQR;CxbD@KSIEYX1d+`pAZCaof zAQb1Zh<4REPSH0heVfM1%kOAlq=K0j@g@?^?nqXRBKtjJmEy{&2ed@BKn(mpEyoK=9EwM8 zmM5-J!gdO;Rl-RWu28}$6s}alX%wze!VU`Wq_9Vt=%No2R8T=ag%2v>0tz2h!iBi3 zi;3%$zP&LZd_i~!b;p$AqC;JalxK5IAyTob-;TxjR_vV|G%AIg@%@1Y_g-&uJG_6k z5f`s%jCg>-Z>lOM+z*}yENiQG&B?!_*4=~9%2S43Ls7hd2hj#4>S;vbji=NLP7p<~ z(m~`bZI>Gk5sP&9;gVlTYpJHRk``-R4d7e-IKhKDF%rb!7QmLr72GrfSyL~h9+y8> z@(xg?#y1cz)rgzdQUU(sY6){`gw+Bvr~pzz?9=!=O07SkL{^QQf`p=__@a$B8c!Ly@ zE1mUdr)!uo2_HWTeE#FK`7;<$*&JpLnGX0+AUG1{q=?_#;M<%Bh3IMv?Ph}fn#9qn zt^k4o;uttb`U+WH&{q?8;sB_{U977tw3|duuUx^IxaRl`_aR1hZiBB}!O-!G!Z^T} zW)|g0zlU~H!n({NsyswC;~!((BcaRq|1koQ&>aZL@=qj~`b_LGS?I*d9*=E{ckJl$ z5DZHafilv`SqD=<`W0u6xq*AZWA29ZPotMB{n$*S&>A`nKEkwPKl}^dv5UT6aUxdj z;6>oR#}P2ywdj_76Ca)rC|sS#p#-WhlSDq)0Gq7CNC1`-3?R1-sv*!7R1blSm-vJZ z+DV|F44_g>9;F?72vlbPtp&)Vzz!1ZZ3AqNp6w`smKi{&bdXG-IR;Qd8?CZa1e$CB zIdo71fgCD`boSM6=*_3~O73OIHbc*5B~YvZRHlPyC6iD7(S(l*9h5+zuMD7VdR?@F z$et<#?1&CaBG`)t&_TUKT8Cw?0o0&_Xc3lY7(jMW!-s=Fc?QsBr7qy#OOsL_WPrK! zZ21K0U;xd~K{RFM%i*R@m+7EF0{v(Jb(lsZO%ykSK($REPxVk8Rz$G3nqbv8>!7&= zDmQ>C^vX&JRBQkh>AA`Xbh`ocqz)=4(5Nujyhg(>>abM=OEhHLsDsuJsFeYjMja{;X# zjXLNcfpQI?4%0o_z#Ju5ssWZfT?5GkYHt7y(?O>Q^k=B4vN1ZSfj~zMpj&kiZK&iO z9OO|L$Xz;&w0ZKIhHOPTD2_l+89)nlPy&J62GBD)$WEZ!44}7lP*N1cJo$P9Y>N&{ zp={R}K;P=1Gy+)-pg(kwgFwgSCVZG?XjpU+XrBQTM<5TM75N0)Xn=LovlS3%wE;9h z2Ne=%kpVP92hAYRGy^DK2Ne-$tOf%Aub!gA<`OJLg8?*42bB`&Y6ED#4k{ziCG5g9 zihD{2l@sWQ0rZ*?KtR18@&mS{iey8LrU&VMY&s@@HH%eFMB8)HPhhJ=D>AmZ*q-<+$WV#|zqP=h zD#CJEO0N9{GRajaxI7i&X>-BiO~7=)V!;oJVBvoWWnt6mQ^c8VB+i`v_H3k_RixXx zvui$RlW?tKwE<1IbcMDYr2dk&LI*2t^ZwX<>+dnRe&Q#C9e9O@@{JunEwt}0`bc{w z-(QE8(ryB3)xLyqvbcH&$4cfCeUmJK?56jQJrJAk#cfs`AbQbESK57u)<3OfFqgd}8s$Jo6t?W_+&HkFK!SWzrrKf_Au@vhhdV z#ba^hlkcBS${+8A5|yMmMGKnc8aza~>P$Kd)s9M0tI@^glX9ESp^C^hg`aO4Gv!zc z@*zYyver1x+Mei}&<1Bt5KG~FSx&;$BsTX9ym#$o?2PbiTn4U4z_u&jiM=)LlUUpt zTnp~EgUvoG^bqzymrrW!O1bd>TXR;pz5Q-gy!E)`>7Qc6g7fY2)E`*fIU%7XU}T=l zb|;HHhC=_@fb#eg3OItPqWwE0T)fYW+yB3jNK7&)S`~p*tSEn_lkCf0;_Ela_Lk5N zKSSFySU$zN0wZ8t*MA=wJt5;snO-+=VV6kTG|ZrA1xo_N`=f~AM@jO4uUXrRLOV9( z91cq3u|&XJ1$J7Z&q`tGic`9tg~Rv+cXnjYE~ScZP@Gc5$85oQVdxzt zC;@lZ@Q&u!3vku$0Wu*&n~+UjjWRHtb4i_V2d?Net!Tj*NCjvNPlbXzd;zskjsJM@ zOdKb{^Ow$r;Q5R#I^Vj3ho|J+O1^kNVQ}xE6=b*OUxk3iB*>Jwsg9|rL)t+lyH_r{ zLR#WE-T27zaXZ30dE@7tq^zNbG4kc&W^^CYqW_dNaYfm$757`!`Ja4j|YX8(-G)I<#BT5iP+rW zIoazV-7s^;%IX5C6-w)+%oI6k8qnhFgxBE zmSRNm!$=(No;oQJTu1|io|lR&NTB~mj& z|5K1ahRF$=8&R^nY!fxwofw}TXc7KQJsd$3tx(!w7Qg=)hEc-($K#@}A8<@9YlD$+ zD)b^QaUv2Y3Y;uLF?Rmb70RdM$+iGdD_wuCW2El-dvBdpA zt2F`%#}H^{W}Ad3cWLf{`{o7u!+RG=q_lYDN}*=^-h}V;<>{mx-V1V}#bzE-SD)ju zfN|eD`Fnm)sz{kJ_i4gd1+XML0MkU44mzlkK)np00Xm59dt(itF*=CvdrzWeT7mcK zpgpw5l)o~-=IF441gbKC0y>EAdtWqw*61L<@5PFzSGG>~z!AxtMkNS!%B|~jG%-nCs#we5=75QGd-%1k zc_9~TH{B(u`GDUkNT`^`A@;b@aPn4{om8`$f2Wi#zLCDuYW)1yfig|(;-5l1lec#i zJan##6aA@PD~n)tqpL zLqt>Ms*|#9w?er7p2!2aYIP!xpa=`D;0JaZs26q+UN;f$WHXlZ@Eh{|pR-pl!((n7 z`{FXZaB&l>UObW5fcGA&w;vMxmd}KRA1Q27F`hrSQdW5Dz4xeo^R@CEt|Z(Dvm5# z=a*>3@WjKZ7!G($2ke1_D)#_@SoH+=Y{(|Az!uJ;VO7%?Ed}QTE|ha9x#bq1kGI~4 zh11(P&f;vj=+R%YrJrWx%KGzz~;gL%>)?b~%E_ zG~Qh?%+@cq@T!M#Oaf8)1dB7%m8(}Y z+8*dP2!{z+a$`kbA&!W|r8nYK0^e;!p99|r*`3^aNc20{3bQTMypq+KZ7%cGEY4y} z?eaVlVYP(&|63B{G1IUp2wVjCsZArBVzDK8>W~6WBTuU^o;pGE&K@aW1=<9oEz7|! zi#PnFMl&T_u=NNGjI3D0$#*>wB#xux-J6?rzcu-Z(TiKF78i@&K-j@!!bfpqjle8A z%9hjNJQ_jL5?XK)rWk7K@$8-`TQBGJkn@|jVHxV8m_R9MEBK0VClV=b-^0Jh;X6RW znYiRLwkyguFrhR&%j76?+c537nqBD^iw{w=AKb#)M%&t3rkGiBw5{`io$sR?B!KP! z#u7x|=kOv6J$wYBUV=RTV-inbgwA1Q+t|a=wtk89gfh_zZkBgNtxjnP%{;U(M_NaO zmo2@K#%iK%@mF8XmAhH+V_mz%0SL}Imc+48w5^Z%TGlqk*4J|SBTf{lAE8W66oqY7 zqHxw9mft&a1&ef}A2~gaYzc3CZC*^GTj-igJlnKN1-5 zip9zK6CBL{Nxnp`z&hqjpwr1k&d^(kL_QEpbaUkQ{fI?kZC&!;;+>gW1mP^YdTzW{ z->-+SkWoprW>g|RH4`jSHy8=!qX}GyYhLQ+O}q!5@oK5n_I7&556KHrs4AWCj)+gy zH^A+MbX=EGj^Ufz9MDOsDYWB~T8oo!ghT7K@8-2$w@D==PW0e7?9LXpR{i#HVuImC zC9ofIK)zB0+rJ~@3~P+FbuHKmy5_?*S8Fw4MSkayf(zc}`fr`mZq;x@e5xzjs~K&C z;&|gB=r(WN!fK9_ej~KztO17zm0=0_x8@Az&B?!{HD_nD=A8ebS#wl-^QAD+iG=RK zhF{;pHgCq4RlFIlY^~G;eXy6I#4PDYwSQWHYth1xSt;;uotmYTmN7;vP1f07DoU$d zO;YCj+#g9PM)DsBuu~N$z;+jiX@GHZ0yJF>)P&i7!IpH}bQMrtfJkKn_2T!up*m46 zttO*1^0`U3$#6>o4yS)7wzJRO4_86XOhqoNUqnV?lld?luO>-f*+sonSsw`<(hJoJls70- zs#-0u+TKA!$6McCiO3f|GFYRf(gabh(QpY}sgK?!Bj+8{@vBt{uFY%Zm*wQEP&L0T z!k@kZ>m#cw^bM?!mTIuR49@yGaWw?+K&;QHvOZexLx)+4U~BLBo)|f;f_9DJ$?`#v z1F1|x_rU-e3<`>XOjtsYcW|$WL2zE!5iR=1AScJp+i0b@Ar`Tgvaw*@gyzxW##{O} zP8%)VlGGRqPy)q(nPU%K(t5*c1Y3))y*H}83B-j?p=K46r0$rxo~5+0bsV5Ivz+KH zfHYa~jz@ESSjAa&P&NGbTF(b`q;95Krs1DwIQosoD4o*h&PA7rtBX(Fg*JjO_!2o^ zA9IF1X0r{w`B6-!syLEY_D|R3l?IZb9(a$0D+27(0bR+> z&DN!7jXslYXpMsGrLZS}tx5*?GzOCBd8n+fCVLNP$!+DkS`D`jZGLGxTWu98kozW+cDiyrD`KuiJI{>1jxnD&FDIQR)Rk9^S1Ie z09e8oU17k_J4*KBO2ZWqJG70Gcp{-Fr8K9KCQ~Vt-r_^XmfEV&q~ayj!7aB=fH^XT z1KI(DqJXd16boTB$c0tuAkLHVrmc&vlpbqHZU~mSK+|}yi{Hczv|wL~wxMIc#ks1^ zTe+)wNMbUbu4B(%OWMQrO%34N>~KX@3Jq%UecEXAv5Q;BZi>TX>7rg&U7a`=%O$*k zkOM*}2prHv>u(>C;X^`yj z_lzAWU?#L(EE7>WdEbW(1{`aUHDxB1bb5`N~CTD~tp&FFiu(>y?&XH;jQ7$PuadSUJt8t1z2A@*I z*hhBu03!P6@g#ABiC!0@WAKb|qW?+!;tpq3XCw&QH1(4sEfwCh;7Ur|FoYhq$Un9VP!>?Mp9tX5i@y^xucY zqV&>m(KiS}c~0;KbNDJQ+0Z379^V!5;s$X2I^VwHkb19?8yp{#J6yg1SA;+q_dxe2 zp)>tw_d<%v5;v^o^}#PQ;`wI!a8B}fSwU9>542c4Ip%MbieT9}NZinZaIhWC%StjJo8?rs&vT~*U?OR-2j7B}EcjBRFLP4V$Gi@S4fI^OOeL(E+B0rlpi%X~N|{c`cU zFd?FWlrMps(QQWgGzGx_LY%!VXdo&W=+D5~#z!4(%L#7eo6@=KNR!k+LU=)>oQ};X z=#ncwV&zxaI(QD#f{$mtKvSAN3l^%h+5Ras5p?G)U1%;5{bW^xpk+92h$0A2k2ggD zw^7+X_)ITD42)|^FZRbZ5gAMQvrC~kN-nh@hXk%IS&k%;`VyV7?T|0Zs5nSGzS2Ov9!(Sj1@bP8PsC`Y&w zYv$#`Fa*nu)%R&}2&W0k$b&xOThM*Sxu8_s4n!r|ea9KaKWkJJf)<2S`U!AMo)cJ- zf|0<)jl-K+@Lz$Uybsmo1emh3I>Ill(j(Gv%sCDa+I!>#1l&4?9)3F>gtEHK+u-=e z6`TiCttS&%TsvE5kF=Nbpx3gn)+B^oWDTQGyhiJl<3KQ?PXfftXj~ z2E-7JK8yK~aZfeBj0gMsLbo-1^|bPTq*Bp$o=86cOMM&x-NYxldr$`LgHZ^N59VX! z>%z9ui|BhkRQ~&s0|Efdd~njb$CccOvH95*7y@MrO z_kNSR51C1~aN_=>8~)aEaf1E7sG+q!qunesXX zFjHQ{Z^%P;HUM@7$Cy(;MK2AEp}**((*(Hf*$@|e7>8q9!5x0VlMpRjc&ppjo@P$) zqr@U&X3AA)`LlZ96(bi%4+v>MFvk?6rEU7-kPzv>Dy1qGC0AcDv3J_px_a{9*AHNS zF2I}bUVcA~qijW46giCNA)%CLj_y~wq*_XF?1GY@JrZD}PV{3!l*X5Y@lE4LQ;8~)-$1#1NH?c|(aUN4Q|kzBadF0DcS)XFxvQRZ%^Du z{|x{&(I4Nv{DlDBAV5scu1FY~j#jI*rO~*0vx==waI;2lm?rC-!C89f| zgh*HY_wv^p&PEpfNkV8P#w8*?)gI+b-;0~QToScXv(z=y_dH~)j2zMb0g({4BE&z! zqAFSs$7>%i5y0y)t~{Z?Fqlw)(lqBuc+-`nwwlmnz%)A1={`j7#^J6nUx|6oWi#Bd z6D_xcJZC@}t>r+P$1rU}JAneVg{Xjwnl+pgg-WR*U^F;#@dImBCb|xrI!%+jxDxZW z*B~`#t%I=5p@Vd2U2l-p2tZT64^^V^Tn8~pIelUc9l(jNCVmB(EGb9&ns|yGyxuOI z-(31W6xhJISPN-c{;eh$OC{ zmsTK1W;E-di?6{KgctB!9Nf#-tOnM&qD=IiKyrFD%s-3rDO$gT$TM_I;=cy^vK?aC zA%t-h9&Q8iB09%=C0_L1j>OJ@AG%T2vZL)kmSTz7JKBb_FFM)=-i7rLnl9Soic78r zJpvQ)go#!NXA}ARP~b?u2d00-8xdg=$JC**@f@HivWh!~=opjpUwYX+YXr{4#3fsy z{_JEcXwSVMU<#nQWoQos@-p10W}kJkb@cq0jaP&f#2m*>^iTonCN7I3i<8d!Lvqq< z^v&~9ykGB?yG*zlICK13;)riOgL0D49T(Ik*J89;C7pgjayqk+gct6GO0B$!`= z0kmHS9VO8H2GDUGBok2ur3Um-Z zEBx62dPE12U?uM~fR^eYepdL70aO7M0X5MhdF_<#X#?y{JzEliN(`VqYBuFGQNF_f zs?&4vV@0O{^s5eXP=UP-AkR4+<|0^Y11#nN4UPE(It2}fhK~dtR6wAw4WMgvP$7Y; z4WL{dG=o4d0p!t2{ErSRBACyR?Udf>xdgh;0E$b{tV~M@bdv#;ri01|G}r+0=yjEQ z2$o=gJ*~r55$Fn?jHnale>!LlfqpW8KG8vI2~=kQeXD~i2=ulAboK%L;JT7v%M38{ zgBtQ{2sFn4YO8~G5@@mk)L#efA&|oW%GN;#3Dipgd5Aky->$=s5-iq`ZI%v_33T$k zCVZ6Xpi>0;$^iPW4r(A!l>zjT4l-c{_sB0AUigJ`oa|7ZX`sDm5?sx^QX z=pYw?-qJxHQ}r?(mQS#99cHRtqk{?vRBQmfuY(E+bh`nxQwPl;&?p1wpbjb`P-2Cr zsb|M@*j$3OGGx1;gGvc>0!j~UQnYzULw*^7_7h0*mLr@KSm?s7ak+34%pXW*@~%ZJ z_Mf0Q!14)}<wi-gtmx-1f4rI(^0Ha%QgJFulfzN%1d7)^T4B_(`bo&`eg_$D|^}U3bs6_Wx-&akSo+r z$`Owo5aJX+9#!S!ie<9yZieqC9$^rQIN%N)P=*;Q-^SQ$y=>R^2)&LXlxtw}AqodJ zt)Vei?L|60$IkV#C0bs6optJMn`8Oo1@?4ro8#K0XcITAE&dhWO;Y!h8eR00%P4FXxLNRRIFu!`U{4@Bnr{V> z7WAoVnn}*1)Gz|(rNB%WE@pp%niA#(u+9|y$B-NAOTfxeb(};QN)F#7bkM&xmnDV%p<&*%_DEcjp=Lw(Phw;?%8j zzw)yY?*dbd@=6HeW46A9L}GtD7ztBjJL{2VOJJ>r*;;!RG+7&MmuCjFaT5LH4N4iS zFEouc_piq-UX?++W2HK1Zz+3y#q_uqm2+a$s2>N5(h-gid4eGlCJPq2pW0KLmG z7gxh?6O)r{T`l!1Sj%MFps2xbHL}lBY+cQ7vD@i8|A`12=MlRKE7a;flzXpcmC3f$ zsJm}&U>V7_E|zoeve>@1L6$WVTbgX^YI}LPo_5ajY(`((8OxdF?2djmm!;qt_If|t zb(W&#>~KHZc#J+>4aexiR|k#T3;4oAF?`(U1O*Ov`RKofcy09I^pKDK&HVA=e;R*y zi29eYFJ3@{t~$AS7gzMKxf_Q;0lApMEy`C8v&G+ayKz*$U)(e*c|h7Fo z&zJqvs9g6XM#W7ie{vNtUe10?vURsCS*D_Vi;D6s9Oagyeg%y`mg{KTz!a3vzJ;T_ ztGQOec#5CRO0jhlno_o43c?>RR}d~QRS<3}XI~Dqjg4xztC9VIK{D@BDm(Q!dv^#* z2p;5q0LgZU(Q^qw#O}&rR?)mo5ND{Bx^IsHqA13 zKbteiHrVn(DSK;>Ev5I%pls~bh46o?_S^@)cV@k|=i|qckCZ`=GUaJz9&F3%IDJhb zZhv2Equ)ntm}4pkrJMcwHNgUH5sNgKcG_i%a=G7p4U?k(4NNkR zf==CjTw!;wmtta(G=R4tGEfBGi*qPHS@;+gnt(Z{ut#*79u2hfhwLXKn&b!q)8m0B z_fv(TH~g$*nC&^+ zh?`03DxO5DvW|y(R2;0;agHZr3ot#Xw^^N-A z?gl0d1v9yY4bPzYTdeT7Wux5+rL^@9QfH;|`hmvmP1GIju{f|oJ8enAdO$)vQoBunlV zfMUCL6xrk*F5r#F;a%XZ1ZH;FhCI~YN0z6Gi7os%|KX$spkCfNTc=sy=QN1N-8SwD z8R}7a?4u;Gk+rSSUUmIKI&pZ5qOzn{>^KgEBKkTIUSRRtIJOCFuE2lASNV1GUgrL+{*XRJh083 zKIN)9IzsfyEg)E$)0Un06zbPimGkW+={`nH!aB+m*JUR0UnqU0BZSP*6o9Kt3sBRm z&^szt!<8i34w=VxIc?VsUVsSe=vU7X8e zGHuyyGAzYc;{iffaKQ|Dl$gaz>4KZi1nOPwAY42WPBj>lNU^&?~(Ok}M z%eHlk?**Tx>Xz;i;5D@d1+V}h$%8*6NO4bb{n)i}W^0_Pc5s!+*e~t4h zwl5oIy#qntRrF@UND9sA2Cshh>Z2G2exd}A5X&CJ9!k2R&hLP*0}m>g!UvW44+r^l zC}EYKpH00&C^&?UhOkcUmXE#2yB4ZLX6Hwst4PR+pzQGw5rG+l_SmP>ts+Zs*^-AI zL^hmZj{dTe z{bxj*p#}0c#b^y}Z$1%y0c4`NHuw>oy z;>2_CH}`ce{K9+xh|42cmfVo%1RTow{UH94!m~8>oUCB}spri*-ILvNqpiKx=j*yH zaiL!70=UjG`TNiRR22wo5bd7B;zqXVd=Dwzrw}*euCKX!{qoB5=mkHmp(|g4yt-In zq0LfZRZ;r2l!jT_9{Q0u2OmRa34V(sBfJq}Z0UGgmuLq{p-|UU1ZZJvQR?YpDvn95 zp<4&^04uDrgC%xY@-@hpAq6YblP*lM!}+!zQO9pT&n)9@PP4?a#@p-(l^D@5sRBSY z8UuM1aqRMVTc(E$1S2a7F}7f(%16HPL1tO1r)_PYP3u(YrVoK-lY6@>;9bS>{Xr%D zP;+X)vBPhwRVnu%A}dJAhqB2`JF7+gx^tyrxE zZ*oz}I&T@fa)V7|xg*-N5@5j1#Y>Gahk33LUP-Vz$MHOWMy@m;O0Jm&xe}h0mL}xW zQn3bav*0~Vcr54gD;iAqvgt9EoJFB`JKn%sb|F%BN_1XDZUT!SW|Bd4oQNJ zsW3PBckN5@ZF#kMV@utjT3jI%}G9=Yldk1yZqgp zvmRWqYv~M3ipC>%6}+rXYw&}m0ZV)(kNBVlKTrVTKaD3aN^%{VXp)|Jk|OCLcNpmD zr+-i~iTQSgUTZeUG*o)#Y!YcHYbf5V!JG`jqxBW)cu z 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%0DJKQ?+;J7$jE@C9%0b%PHbuDZu*hXL+Sg7}bY; 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

0Qd$fy>5Wnm;eG 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�fct?9Q)I`rj9i!Be39go)n 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