From d09b5756e916a0adf8d2634e4d3103e7facad0ad Mon Sep 17 00:00:00 2001 From: iongion Date: Mon, 18 Mar 2024 21:04:47 +0100 Subject: [PATCH] Upgrade and cleanup --- .gitignore | 5 + CMakeLists.txt | 5 +- README.md | 61 +- assets/LICENSE.txt | 2 +- assets/alien_small.tga | Bin 0 -> 4140 bytes assets/demo.rml | 6 +- assets/invader.rcss | 243 +++--- assets/rml.rcss | 7 +- dependencies/RmlUi | 2 +- dependencies/raylib | 2 +- .../basic/bitmapfont/FontEngineBitmap.h | 120 +++ .../bitmapfont/FontEngineInterfaceBitmap.h | 91 +++ .../basic/bitmapfont/fontEngineBitmap.h | 119 --- .../bitmapfont/fontEngineInterfaceBitmap.h | 70 -- src/main.cpp | 5 +- src/raylibFileInterface.cpp | 2 +- src/samples/basic/animation.cpp | 29 +- src/samples/basic/animationEvent.cpp | 14 +- src/samples/basic/benchmark.cpp | 1 + src/samples/basic/bitmapfont.cpp | 7 +- .../basic/bitmapfont/FontEngineBitmap.cpp | 288 +++++++ .../bitmapfont/FontEngineInterfaceBitmap.cpp | 94 +++ .../bitmapfont/data/Comfortaa_Regular_22.fnt | 758 ++++++++++++++++++ .../bitmapfont/data/Comfortaa_Regular_22.tga | Bin 0 -> 131116 bytes .../basic/bitmapfont/data/bitmapfont.rml | 31 + .../basic/bitmapfont/fontEngineBitmap.cpp | 289 ------- .../bitmapfont/fontEngineInterfaceBitmap.cpp | 104 --- src/samples/basic/databinding.cpp | 1 + src/samples/raylib.cpp | 3 +- 29 files changed, 1583 insertions(+), 776 deletions(-) create mode 100644 assets/alien_small.tga create mode 100644 include/samples/basic/bitmapfont/FontEngineBitmap.h create mode 100644 include/samples/basic/bitmapfont/FontEngineInterfaceBitmap.h delete mode 100644 include/samples/basic/bitmapfont/fontEngineBitmap.h delete mode 100644 include/samples/basic/bitmapfont/fontEngineInterfaceBitmap.h create mode 100644 src/samples/basic/bitmapfont/FontEngineBitmap.cpp create mode 100644 src/samples/basic/bitmapfont/FontEngineInterfaceBitmap.cpp create mode 100644 src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.fnt create mode 100644 src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.tga create mode 100644 src/samples/basic/bitmapfont/data/bitmapfont.rml delete mode 100644 src/samples/basic/bitmapfont/fontEngineBitmap.cpp delete mode 100644 src/samples/basic/bitmapfont/fontEngineInterfaceBitmap.cpp diff --git a/.gitignore b/.gitignore index faa52c2..c3bbeab 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,9 @@ # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 +# VSCODE +.vscode/ + # User-specific stuff: .idea/workspace.xml .idea/tasks.xml @@ -58,6 +61,8 @@ **/*.cbp **/CMakeScripts **/compile_commands.json +builddir/ +build/ # Gradle: .idea/gradle.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index b134077..c7c8e4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project(RmlUI_Example) set(CMAKE_CXX_STANDARD 20) set(CMAKE_C_STANDARD 99) +set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) set(BUILD_SHARED_LIBS ON) @@ -55,8 +56,8 @@ set(benchmarkSource set (bitmapfontSource src/samples/basic/bitmapfont.cpp src/samples/exampleEvent.cpp - src/samples/basic/bitmapfont/fontEngineBitmap.cpp - src/samples/basic/bitmapfont/fontEngineInterfaceBitmap.cpp + src/samples/basic/bitmapfont/FontEngineBitmap.cpp + src/samples/basic/bitmapfont/FontEngineInterfaceBitmap.cpp ) set (databindingSource diff --git a/README.md b/README.md index 2b9b6f3..c9b834e 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,43 @@ # Raylib + RmlUi -[Raylib](https://github.com/raysan5/raylib) is a thin wrapper around OpenGL using the inbuilt rlgl. - -[RmlUi](https://github.com/mikke89/RmlUi) is a XHTML 1.0 / CSS 2 renderer with ease of interaction with the elements. - -# Examples -* [ ] Basic - * [x] Animation - * [x] Benchmark - * [x] Bitmapfont - * [x] Databinding - * [ ] Demo - * [ ] Drag - * [ ] LoadDocuments - * [ ] Lottie - * [ ] SVG - * [ ] Transform - * [ ] Treeview -* [ ] Invaders -* [ ] Tutorial - - -# Building Examples -```bash + +- [Raylib](https://github.com/raysan5/raylib) is a thin wrapper around OpenGL using the inbuilt rlgl. +- [RmlUi](https://github.com/mikke89/RmlUi) is a XHTML 1.0 / CSS 2 renderer with ease of interaction with the elements. + +## Examples + +- [ ] Basic + - [x] Animation + - [x] Benchmark + - [x] Bitmapfont + - [x] Databinding + - [ ] Demo + - [ ] Drag + - [ ] LoadDocuments + - [ ] Lottie + - [ ] SVG + - [ ] Transform + - [ ] Treeview +- [ ] Invaders +- [ ] Tutorial + +## Building Examples + +```shell git submodule update --init --recursive cmake -S . -B ./build -DCMAKE_BUILD_TYPE=Debug cmake --build ./build -- -j $(nproc) ``` + +### Running examples + +After building + +- `cd bin/Debug` +- `./RmlUI_Example` or `./RmlUI_Example.exe` if on Windows + +Other examples + +- `./RaylibAnimation_Example` +- `./RaylibBenchmark_Example` +- `./RaylibBitmapfont_Example` +- `./RaylibDatabinding_Example` diff --git a/assets/LICENSE.txt b/assets/LICENSE.txt index dd4a9e2..63ef813 100644 --- a/assets/LICENSE.txt +++ b/assets/LICENSE.txt @@ -34,7 +34,7 @@ with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, +fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The diff --git a/assets/alien_small.tga b/assets/alien_small.tga new file mode 100644 index 0000000000000000000000000000000000000000..6d7c53d72e29775123f1154f8fe6e2679304c8e3 GIT binary patch literal 4140 zcmeH}%}T>S6osRf6a*K7qDyh*M)4)81Vo`~(U<5GxCrh`-^A|S^wHw^!i?NbGHIJ; z*PL?5%-p}ZH=R34lEcK~D$(!8&-!OyfxZHj3LI!J!1b4SLZocP${V_Wb(ha&c0 zMN44oeBi6;+(^6v^m)hF|L3*sHn4R*Ha!Q8c@GAI0>+T0X#qpHJy6Sab!g0chxnV; z;aq$C4)@>H9N!`_V&FW@yNVb3!M8|^81_9reRSsQrZNAUWjOcideV2w-ecA(`o?}H zy{7xC?!H+V`*J@f7Jaeojb_cpFJ;Dl-F?LQv-d6in{!*+hkQ)$-#^{D?|t~lMPlQd z7%|j+Z_vN5#Y!L6+RFPe@rjKMw%k9vevjC?@D4dgoMm!@j9EjrNuE;M3bro%e>kV~ m5psi!Swq&vcbDAs=qs>46?hxJk0#k`_VRrD@sK@@?vg(Z8d{bB literal 0 HcmV?d00001 diff --git a/assets/demo.rml b/assets/demo.rml index f136db9..82f2e6f 100644 --- a/assets/demo.rml +++ b/assets/demo.rml @@ -7,15 +7,15 @@ { width: 300dp; height: 225dp; - + margin: auto; } - + div#title_bar div#icon { display: none; } - + div#content { text-align: left; diff --git a/assets/invader.rcss b/assets/invader.rcss index fe525be..a58c058 100644 --- a/assets/invader.rcss +++ b/assets/invader.rcss @@ -1,24 +1,24 @@ -@spritesheet theme +@spritesheet theme { src: invader.tga; - + /* For high dpi screens, designates the scaling it is intended to be shown at. */ - resolution: 1x; - + resolution: 1x; + /** - The following specifies a list of sprite names and associated rectangles into the image given above. - Any sprite given here can be specified in a decorator. Their names must be globally unique. - Rectangles are specified as: x y width height. With the origin assumed to be at the top left corner. + The following specifies a list of sprite names and associated rectangles into the image given above. + Any sprite given here can be specified in a decorator. Their names must be globally unique. + Rectangles are specified as: x y width height. With the origin assumed to be at the top left corner. */ title-bar-l: 147px 0px 82px 85px; title-bar-c: 229px 0px 1px 85px; title-bar-r: 231px 0px 15px 85px; - + /* huditems are vertically flipped titlebars */ huditem-l: 147px 55px 82px -55px; huditem-c: 229px 55px 1px -55px; huditem-r: 231px 55px 15px -55px; - + icon-help: 128px 152px 51px 39px; icon-invader: 179px 152px 51px 39px; icon-game: 230px 152px 51px 39px; @@ -27,7 +27,7 @@ icon-flag: 336px 191px 51px 39px; icon-lives: 383px 152px 51px 39px; icon-score: 434px 152px 51px 39px; - + window-tl: 0px 0px 133px 140px; window-t: 134px 0px 1px 140px; window-tr: 136px 0px 10px 140px; @@ -37,20 +37,24 @@ window-bl: 0px 140px 11px 11px; window-b: 11px 140px 1px 11px; window-br: 136px 140px 10px 11px; - + button: 247px 0px 159px 45px; button-hover: 247px 45px 159px 45px; button-active: 247px 90px 159px 45px; - + button-inner: 259px 19px 135px 1px; button-inner-hover: 259px 64px 135px 1px; button-inner-active: 259px 109px 135px 1px; - + text-l: 162px 192px 14px 31px; text-c: 176px 192px 1px 31px; + text-focus-l: 162px 230px 14px 31px; + text-focus-c: 176px 230px 1px 31px; textarea: 162px 193px 145px 31px; textarea-inner: 173px 206px 127px 10px; - + textarea-focus: 162px 231px 145px 31px; + textarea-focus-inner: 173px 244px 127px 10px; + selectbox-tl: 281px 275px 11px 9px; selectbox-t: 292px 275px 1px 9px; selectbox-tr: 294px 275px 11px 9px; @@ -59,42 +63,42 @@ selectbox-bl: 281px 285px 11px 11px; selectbox-b: 292px 285px 1px 11px; selectbox-br: 294px 285px 11px 11px; - + selectvalue: 162px 192px 145px 37px; selectvalue-hover: 162px 230px 145px 37px; selectarrow: 307px 192px 30px 37px; selectarrow-hover: 307px 230px 30px 37px; selectarrow-active: 307px 268px 30px 37px; - + radio: 407px 0px 30px 30px; radio-hover: 437px 0px 30px 30px; radio-active: 467px 0px 30px 30px; radio-checked: 407px 30px 30px 30px; radio-checked-hover: 437px 30px 30px 30px; radio-checked-active: 467px 30px 30px 30px; - + checkbox: 407px 60px 30px 30px; checkbox-hover: 437px 60px 30px 30px; checkbox-active: 467px 60px 30px 30px; checkbox-checked: 407px 90px 30px 30px; checkbox-checked-hover: 437px 90px 30px 30px; checkbox-checked-active: 467px 90px 30px 30px; - - datagridheader-l: 127px 192px 16px 31px; - datagridheader-c: 143px 192px 2px 31px; - datagridheader-r: 145px 192px 15px 31px; - - datagridexpand: 3px 232px 17px 17px; - datagridexpand-hover: 21px 232px 17px 17px; - datagridexpand-active: 39px 232px 17px 17px; - datagridexpand-collapsed: 3px 250px 17px 17px; - datagridexpand-collapsed-hover: 21px 250px 17px 17px; - datagridexpand-collapsed-active: 39px 250px 17px 17px; - + + tableheader-l: 127px 192px 16px 31px; + tableheader-c: 143px 192px 2px 31px; + tableheader-r: 145px 192px 15px 31px; + + expand: 3px 232px 17px 17px; + expand-hover: 21px 232px 17px 17px; + expand-active: 39px 232px 17px 17px; + expand-collapsed: 3px 250px 17px 17px; + expand-collapsed-hover: 21px 250px 17px 17px; + expand-collapsed-active: 39px 250px 17px 17px; + slidertrack-t: 70px 199px 27px 2px; slidertrack-c: 70px 201px 27px 1px; slidertrack-b: 70px 202px 27px 2px; - + sliderbar-t: 56px 152px 23px 23px; sliderbar-c: 56px 175px 23px 1px; sliderbar-b: 56px 176px 23px 22px; @@ -104,17 +108,20 @@ sliderbar-active-t: 104px 152px 23px 23px; sliderbar-active-c: 104px 175px 23px 1px; sliderbar-active-b: 104px 176px 23px 22px; - + sliderarrowdec: 0px 152px 27px 24px; sliderarrowdec-hover: 0px 177px 27px 24px; sliderarrowdec-active: 0px 202px 27px 24px; - + sliderarrowinc: 28px 152px 27px 24px; sliderarrowinc-hover: 28px 177px 27px 24px; sliderarrowinc-active: 28px 202px 27px 24px; - - range-track: 219px 194px 3px 32px; - range-track-inner: 220px 204px 1px 14px; + + range-track: 219px 194px 3px 32px; + range-track-inner: 220px 204px 1px 14px; + range-track-focus: 219px 232px 3px 32px; + range-track-focus-inner: 220px 242px 1px 14px; + range-bar: 127px 191px 34px 32px; range-dec: 3px 232px 17px 17px; range-dec-hover: 21px 232px 17px 17px; @@ -122,7 +129,7 @@ range-inc: 3px 250px 17px 17px; range-inc-hover: 21px 250px 17px 17px; range-inc-active: 39px 250px 17px 17px; - + progress-l: 103px 267px 13px 34px; progress-c: 116px 267px 54px 34px; progress-r: 170px 267px 13px 34px; @@ -140,16 +147,17 @@ body font-style: normal; font-size: 15dp; color: white; + nav: auto; } body.window { padding-top: 43dp; padding-bottom: 20dp; - + min-width: 250dp; max-width: 800dp; - + min-height: 135dp; max-height: 700dp; } @@ -161,7 +169,7 @@ div#title_bar position: absolute; top: 7dp; left: 0; - + text-align: left; vertical-align: bottom; } @@ -171,7 +179,7 @@ div#title_bar div#icon position: absolute; left: 15dp; top: -4dp; - + width: 51dp; height: 39dp; } @@ -183,13 +191,13 @@ div#title_bar span padding-right: 25dp; padding-top: 18dp; padding-bottom: 43dp; - + vertical-align: top; - + line-height: 24dp; font-size: 20dp; font-weight: bold; - + font-effect: glow(1dp black); decorator: tiled-horizontal( title-bar-l, title-bar-c, title-bar-r ); } @@ -197,10 +205,11 @@ div#title_bar span div#window { width: auto; + height: 100%; padding: 10dp 15dp; - + decorator: tiled-box( - window-tl, window-t, window-tr, + window-tl, window-t, window-tr, window-l, window-c, window-r, window-bl, window-b, window-br ); @@ -241,8 +250,7 @@ h1 input, -select, -dataselect +select { margin-left: 20dp; } @@ -252,7 +260,9 @@ input.submit margin-left: 0; } - +input, button, select { + nav: auto; +} button, input.submit @@ -261,9 +271,7 @@ input.submit width: 159dp; height: 33dp; - padding-top: 12dp; - vertical-align: -18dp; font-size: 16dp; text-align: center; @@ -278,8 +286,8 @@ input.submit:focus font-effect: blur(3dp #fff); } -button:hover, -input.submit:hover +button:hover, button:focus-visible, +input.submit:hover, input.submit:focus-visible { decorator: image(button-hover); } @@ -304,6 +312,11 @@ input.text, input.password padding: 11dp 10dp 0; decorator: tiled-horizontal( text-l, text-c, auto ); /* Right becomes mirrored left */ cursor: text; + text-align: left; +} +input.text:focus-visible, input.password:focus-visible +{ + decorator: tiled-horizontal( text-focus-l, text-focus-c, auto ); } textarea @@ -311,19 +324,23 @@ textarea padding: 14dp 12dp 10dp; decorator: ninepatch( textarea, textarea-inner, 1.0 ); cursor: text; + text-align: left; +} +textarea:focus-visible +{ + decorator: ninepatch( textarea-focus, textarea-focus-inner, 1.0 ); } input.text, input.password, select, -dataselect, textarea { color: #333; font-size: 13dp; } -datagrid input.text, table input.text +table input.text { box-sizing: border-box; width: 100%; @@ -337,56 +354,53 @@ datagrid input.text, table input.text background-color: white; font-size: 15dp; - +} +table input.text, table input.text:focus-visible +{ decorator: none; } - -select, -dataselect +select { width: 175dp; height: 37dp; } -select selectvalue, -dataselect selectvalue +select selectvalue { width: auto; margin-right: 30dp; - + height: 25dp; padding: 12dp 10dp 0dp 10dp; - decorator: image( selectvalue ); + decorator: image( selectvalue ); +} +select:focus-visible selectvalue { + decorator: image( selectvalue-hover ); } -select selectarrow, -dataselect selectarrow +select selectarrow { width: 30dp; height: 37dp; - + decorator: image( selectarrow ); } -select:hover selectarrow, -dataselect:hover selectarrow +select:hover selectarrow, select:focus-visible selectarrow { decorator: image( selectarrow-hover ); } select:active selectarrow, -select selectarrow:checked, -dataselect:active selectarrow, -dataselect selectarrow:checked +select selectarrow:checked { decorator: image( selectarrow-active ); } -select selectbox, -dataselect selectbox +select selectbox { margin-left: 1dp; margin-top: -7dp; @@ -396,19 +410,16 @@ dataselect selectbox } select selectbox, -dataselect selectbox, -datagrid datagridbody, tbody { decorator: tiled-box( - selectbox-tl, selectbox-t, selectbox-tr, + selectbox-tl, selectbox-t, selectbox-tr, selectbox-l, selectbox-c, auto, /* auto mirrors left */ selectbox-bl, selectbox-b, selectbox-br ); } -select selectbox option, -dataselect selectbox option +select selectbox option { width: auto; padding: 3dp 0 3dp 6dp; @@ -416,19 +427,15 @@ dataselect selectbox option } select selectbox option:nth-child(even), -dataselect selectbox option:nth-child(even), -datagrid datagridrow:nth-child(even), tr:nth-child(even) { background: #FFFFFFA0; } -select selectbox option:checked, -dataselect selectbox option:checked +select selectbox option:checked { font-weight: bold; } -select selectbox option:hover, -dataselect selectbox option:hover +select selectbox option:hover { background: #FF5D5D; } @@ -449,7 +456,7 @@ input.radio decorator: image(radio); } -input.radio:hover +input.radio:hover, input.radio:focus-visible { decorator: image(radio-hover); } @@ -464,7 +471,7 @@ input.radio:checked decorator: image(radio-checked); } -input.radio:checked:hover +input.radio:checked:hover, input.radio:checked:focus-visible { decorator: image(radio-checked-hover); } @@ -479,7 +486,7 @@ input.checkbox decorator: image(checkbox); } -input.checkbox:hover +input.checkbox:hover, input.checkbox:focus-visible { decorator: image(checkbox-hover); } @@ -494,7 +501,7 @@ input.checkbox:checked decorator: image(checkbox-checked); } -input.checkbox:checked:hover +input.checkbox:checked:hover, input.checkbox:checked:focus-visible { decorator: image(checkbox-checked-hover); } @@ -515,6 +522,9 @@ input.range slidertrack { image-color: #ecc; decorator: ninepatch( range-track, range-track-inner, 1.0 ); } +input.range:focus-visible slidertrack { + decorator: ninepatch( range-track-focus, range-track-focus-inner, 1.0 ); +} input.range sliderbar { margin-left: -8dp; margin-right: -7dp; @@ -523,10 +533,10 @@ input.range sliderbar { height: 23dp; decorator: image( range-bar ); } -input.range:hover sliderbar { +input.range sliderbar:hover, input.range slidertrack:hover + sliderbar { image-color: #cc0; } -input.range sliderbar:active { +input.range sliderbar:active, input.range slidertrack:active + sliderbar { image-color: #c80; } input.range sliderarrowdec, input.range sliderarrowinc { @@ -543,7 +553,7 @@ input.range sliderarrowinc:active { decorator: image( range-inc-active ); } thead tr { height: 35dp; - decorator: tiled-horizontal( datagridheader-l, datagridheader-c, datagridheader-r ); + decorator: tiled-horizontal( tableheader-l, tableheader-c, tableheader-r ); } thead td { padding-top: 11dp; @@ -563,60 +573,41 @@ tbody tr { color: black; } -datagrid datagridheader -{ - width: auto; - height: 25dp; - padding: 5dp 10dp 0 10dp; - - decorator: tiled-horizontal( datagridheader-l, datagridheader-c, datagridheader-r ); -} - -datagrid datagridbody -{ - color: black; - - margin-left: 4dp; - margin-right: 3dp; - padding: 0 4dp 4dp 4dp; -} - - -datagridexpand, expand +expand { display: block; - + margin: 1dp 0 1dp 5dp; height: 17dp; width: 17dp; - - decorator: image( datagridexpand ); + + decorator: image( expand ); } -datagridexpand:hover, expand:hover +expand:hover { - decorator: image( datagridexpand-hover ); + decorator: image( expand-hover ); } -datagridexpand:active, expand:active +expand:active { - decorator: image( datagridexpand-active ); + decorator: image( expand-active ); } -datagridexpand.collapsed, expand.collapsed +expand.collapsed { - decorator: image( datagridexpand-collapsed ); + decorator: image( expand-collapsed ); } -datagridexpand.collapsed:hover, expand.collapsed:hover +expand.collapsed:hover { - decorator: image( datagridexpand-collapsed-hover ); + decorator: image( expand-collapsed-hover ); } -datagridexpand.collapsed:active, expand.collapsed:active +expand.collapsed:active { - decorator: image( datagridexpand-collapsed-active ); + decorator: image( expand-collapsed-active ); } @@ -698,9 +689,9 @@ textarea scrollbarvertical margin: 10dp 0 4dp 0; width: 12dp; } -textarea scrollbarvertical slidertrack -{ - decorator: none; +textarea scrollbarvertical slidertrack +{ + decorator: none; } textarea scrollbarvertical sliderbar { diff --git a/assets/rml.rcss b/assets/rml.rcss index c429568..0905b24 100644 --- a/assets/rml.rcss +++ b/assets/rml.rcss @@ -27,12 +27,7 @@ strong font-weight: bold; } -datagrid -{ - display: block; -} - -select, dataselect, datacombo +select { text-align: left; } diff --git a/dependencies/RmlUi b/dependencies/RmlUi index 40edf1a..23b9348 160000 --- a/dependencies/RmlUi +++ b/dependencies/RmlUi @@ -1 +1 @@ -Subproject commit 40edf1acfa7f13f0c9b2af91d6f09ed47aa2c2c9 +Subproject commit 23b93483c576776c04f8eb7d221b0b0b4ad392bd diff --git a/dependencies/raylib b/dependencies/raylib index 17c443e..9cf408f 160000 --- a/dependencies/raylib +++ b/dependencies/raylib @@ -1 +1 @@ -Subproject commit 17c443ee6db0a111d111e766bb517657204c3574 +Subproject commit 9cf408f77c58828fd1019d5cd35c6b8c5139c8dc diff --git a/include/samples/basic/bitmapfont/FontEngineBitmap.h b/include/samples/basic/bitmapfont/FontEngineBitmap.h new file mode 100644 index 0000000..1259174 --- /dev/null +++ b/include/samples/basic/bitmapfont/FontEngineBitmap.h @@ -0,0 +1,120 @@ +/* + * This source file is part of RmlUi, the HTML/CSS Interface Middleware + * + * For the latest information, see http://github.com/mikke89/RmlUi + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * Copyright (c) 2019-2023 The RmlUi Team, and contributors + * + * 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. + * + */ + +#ifndef FONTENGINEBITMAP_H +#define FONTENGINEBITMAP_H + +#include "FontEngineInterfaceBitmap.h" +#include +#include +#include + +class FontFaceBitmap; + +namespace FontProviderBitmap { +void Initialise(); +void Shutdown(); +bool LoadFontFace(const String& file_name); +FontFaceBitmap* GetFontFaceHandle(const String& family, FontStyle style, FontWeight weight, int size); +} // namespace FontProviderBitmap + +struct BitmapGlyph { + int advance = 0; + Vector2f offset = {0, 0}; + Vector2f position = {0, 0}; + Vector2f dimension = {0, 0}; +}; + +// A mapping of characters to their glyphs. +using FontGlyphs = Rml::UnorderedMap; + +// Mapping of combined (left, right) character to kerning in pixels. +using FontKerning = Rml::UnorderedMap; + +class FontFaceBitmap { +public: + FontFaceBitmap(String family, FontStyle style, FontWeight weight, FontMetrics metrics, Texture texture, Vector2f texture_dimensions, + FontGlyphs&& glyphs, FontKerning&& kerning); + + // Get width of string. + int GetStringWidth(const String& string, Character prior_character); + + // Generate the string geometry, returning its width. + int GenerateString(const String& string, const Vector2f& position, const Colourb& colour, GeometryList& geometry); + + const FontMetrics& GetMetrics() const { return metrics; } + + const String& GetFamily() const { return family; } + FontStyle GetStyle() const { return style; } + FontWeight GetWeight() const { return weight; } + +private: + int GetKerning(Character left, Character right) const; + + String family; + FontStyle style; + FontWeight weight; + + FontMetrics metrics; + + Texture texture; + Vector2f texture_dimensions; + + FontGlyphs glyphs; + FontKerning kerning; +}; + +/* + Parses the font meta data from an xml file. +*/ + +class FontParserBitmap : public Rml::BaseXMLParser { +public: + FontParserBitmap() {} + virtual ~FontParserBitmap(); + + /// Called when the parser finds the beginning of an element tag. + void HandleElementStart(const String& name, const Rml::XMLAttributes& attributes) override; + /// Called when the parser finds the end of an element tag. + void HandleElementEnd(const String& name) override; + /// Called when the parser encounters data. + void HandleData(const String& data, Rml::XMLDataType type) override; + + String family; + FontStyle style = FontStyle::Normal; + FontWeight weight = FontWeight::Normal; + + String texture_name; + Vector2f texture_dimensions = {0, 0}; + + FontMetrics metrics = {}; + FontGlyphs glyphs; + FontKerning kerning; +}; + +#endif diff --git a/include/samples/basic/bitmapfont/FontEngineInterfaceBitmap.h b/include/samples/basic/bitmapfont/FontEngineInterfaceBitmap.h new file mode 100644 index 0000000..ef4b56b --- /dev/null +++ b/include/samples/basic/bitmapfont/FontEngineInterfaceBitmap.h @@ -0,0 +1,91 @@ +/* + * This source file is part of RmlUi, the HTML/CSS Interface Middleware + * + * For the latest information, see http://github.com/mikke89/RmlUi + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * Copyright (c) 2019-2023 The RmlUi Team, and contributors + * + * 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. + * + */ + +#ifndef FONTENGINEINTERFACEBITMAP_H +#define FONTENGINEINTERFACEBITMAP_H + +#include +#include +#include + +using Rml::FontEffectsHandle; +using Rml::FontFaceHandle; + +using Rml::byte; +using Rml::Character; +using Rml::Colourb; +using Rml::String; +using Rml::Texture; +using Rml::Vector2f; +using Rml::Vector2i; +using Rml::Style::FontStyle; +using Rml::Style::FontWeight; + +using Rml::FontEffectList; +using Rml::FontMetrics; +using Rml::GeometryList; +using Rml::TextShapingContext; + +class FontEngineInterfaceBitmap : public Rml::FontEngineInterface { +public: + /// Called when RmlUi is being initialized. + void Initialize() override; + + /// Called when RmlUi is being shut down. + void Shutdown() override; + + /// Called by RmlUi when it wants to load a font face from file. + bool LoadFontFace(const String& file_name, bool fallback_face, FontWeight weight) override; + + /// Called by RmlUi when it wants to load a font face from memory, registered using the provided family, style, and weight. + /// @param[in] data A pointer to the data. + bool LoadFontFace(const byte* data, int data_size, const String& family, FontStyle style, FontWeight weight, bool fallback_face) override; + + /// Called by RmlUi when a font configuration is resolved for an element. Should return a handle that + /// can later be used to resolve properties of the face, and generate string geometry to be rendered. + FontFaceHandle GetFontFaceHandle(const String& family, FontStyle style, FontWeight weight, int size) override; + + /// Called by RmlUi when a list of font effects is resolved for an element with a given font face. + FontEffectsHandle PrepareFontEffects(FontFaceHandle handle, const FontEffectList& font_effects) override; + + /// Should return the font metrics of the given font face. + const FontMetrics& GetFontMetrics(FontFaceHandle handle) override; + + /// Called by RmlUi when it wants to retrieve the width of a string when rendered with this handle. + int GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& text_shaping_context, + Character prior_character = Character::Null) override; + + /// Called by RmlUi when it wants to retrieve the geometry required to render a single line of text. + int GenerateString(FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, const String& string, const Vector2f& position, + const Colourb& colour, float opacity, const TextShapingContext& text_shaping_context, GeometryList& geometry) override; + + /// Called by RmlUi to determine if the text geometry is required to be re-generated.eometry. + int GetVersion(FontFaceHandle handle) override; +}; + +#endif diff --git a/include/samples/basic/bitmapfont/fontEngineBitmap.h b/include/samples/basic/bitmapfont/fontEngineBitmap.h deleted file mode 100644 index 6debbd2..0000000 --- a/include/samples/basic/bitmapfont/fontEngineBitmap.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef RMLUI_EXAMPLE_FONTENGINEBITMAP_H -#define RMLUI_EXAMPLE_FONTENGINEBITMAP_H - -#include -#include -#include "fontEngineInterfaceBitmap.h" - -class FontFaceBitmap; - -namespace FontProviderBitmap { - void Initialise(); - - void Shutdown(); - - bool LoadFontFace(const String &file_name); - - FontFaceBitmap* GetFontFaceHandle(const String &family, FontStyle style, FontWeight weight, int size); -} - - -struct BitmapGlyph { - int advance = 0; - Vector2f offset = { 0, 0 }; - Vector2f position = { 0, 0 }; - Vector2f dimension = { 0, 0 }; -}; - -struct FontMetrics { - int size = 0; - int x_height = 0; - int line_height = 0; - int baseline = 0; - float underline_position = 0, underline_thickness = 0; -}; - -// A mapping of characters to their glyphs. -using FontGlyphs = Rml::UnorderedMap; - -// Mapping of combined (left, right) character to kerning in pixels. -using FontKerning = Rml::UnorderedMap; - - -class FontFaceBitmap { -public: - FontFaceBitmap(String family, FontStyle style, FontWeight weight, FontMetrics metrics, Texture texture, Vector2f texture_dimensions, FontGlyphs &&glyphs, - FontKerning &&kerning); - - // Get width of string. - int GetStringWidth(const String &string, Character prior_character); - - // Generate the string geometry, returning its width. - int GenerateString(const String &string, const Vector2f &position, const Colourb &colour, GeometryList &geometry); - - - const FontMetrics &GetMetrics() const { - return metrics; - } - - const String &GetFamily() const { - return family; - } - - FontStyle GetStyle() const { - return style; - } - - FontWeight GetWeight() const { - return weight; - } - -private: - int GetKerning(Character left, Character right) const; - - String family; - FontStyle style; - FontWeight weight; - - FontMetrics metrics; - - Texture texture; - Vector2f texture_dimensions; - - FontGlyphs glyphs; - FontKerning kerning; -}; - - -/* - Parses the font meta data from an xml file. -*/ - -class FontParserBitmap : public Rml::BaseXMLParser { -public: - FontParserBitmap() { - } - - virtual ~FontParserBitmap(); - - /// Called when the parser finds the beginning of an element tag. - void HandleElementStart(const String &name, const Rml::XMLAttributes &attributes) override; - - /// Called when the parser finds the end of an element tag. - void HandleElementEnd(const String &name) override; - - /// Called when the parser encounters data. - void HandleData(const String &data, Rml::XMLDataType type) override; - - String family; - FontStyle style = FontStyle::Normal; - FontWeight weight = FontWeight::Normal; - - String texture_name; - Vector2f texture_dimensions = { 0, 0 }; - - FontMetrics metrics; - FontGlyphs glyphs; - FontKerning kerning; -}; -#endif //RMLUI_EXAMPLE_FONTENGINEBITMAP_H diff --git a/include/samples/basic/bitmapfont/fontEngineInterfaceBitmap.h b/include/samples/basic/bitmapfont/fontEngineInterfaceBitmap.h deleted file mode 100644 index a8f3853..0000000 --- a/include/samples/basic/bitmapfont/fontEngineInterfaceBitmap.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef RMLUI_EXAMPLE_FONTENGINEINTERFACEBITMAP_H -#define RMLUI_EXAMPLE_FONTENGINEINTERFACEBITMAP_H - -#include -#include -#include - -using Rml::FontFaceHandle; -using Rml::FontEffectsHandle; - -using Rml::Vector2i; -using Rml::Vector2f; -using Rml::Colourb; -using Rml::Texture; -using Rml::String; -using Rml::Character; -using Rml::Style::FontStyle; -using Rml::Style::FontWeight; -using Rml::byte; - -using Rml::FontEffectList; -using Rml::GeometryList; - - -class FontEngineInterfaceBitmap : public Rml::FontEngineInterface { -public: - FontEngineInterfaceBitmap(); - - virtual ~FontEngineInterfaceBitmap(); - - /// Called by RmlUi when it wants to load a font face from file. - bool LoadFontFace(const String &file_name, bool fallback_face, FontWeight weight) override; - - /// Called by RmlUi when it wants to load a font face from memory, registered using the provided family, style, and weight. - /// @param[in] data A pointer to the data. - bool LoadFontFace(const byte* data, int data_size, const String &family, FontStyle style, FontWeight weight, bool fallback_face) override; - - /// Called by RmlUi when a font configuration is resolved for an element. Should return a handle that - /// can later be used to resolve properties of the face, and generate string geometry to be rendered. - FontFaceHandle GetFontFaceHandle(const String &family, FontStyle style, FontWeight weight, int size) override; - - /// Called by RmlUi when a list of font effects is resolved for an element with a given font face. - FontEffectsHandle PrepareFontEffects(FontFaceHandle handle, const FontEffectList &font_effects) override; - - /// Should return the point size of this font face. - int GetSize(FontFaceHandle handle) override; - - /// Should return the pixel height of a lower-case x in this font face. - int GetXHeight(FontFaceHandle handle) override; - - /// Should return the default height between this font face's baselines. - int GetLineHeight(FontFaceHandle handle) override; - - /// Should return the font's baseline, as a pixel offset from the bottom of the font. - int GetBaseline(FontFaceHandle handle) override; - - /// Should return the font's underline, as a pixel offset from the bottom of the font. - float GetUnderline(FontFaceHandle handle, float &thickness) override; - - /// Called by RmlUi when it wants to retrieve the width of a string when rendered with this handle. - int GetStringWidth(FontFaceHandle handle, const String &string, Character prior_character = Character::Null) override; - - /// Called by RmlUi when it wants to retrieve the geometry required to render a single line of text. - int GenerateString(FontFaceHandle face_handle, FontEffectsHandle font_effects_handle, const String &string, const Vector2f &position, - const Colourb &colour, float opacity, GeometryList &geometry) override; - - /// Called by RmlUi to determine if the text geometry is required to be re-generated.eometry. - int GetVersion(FontFaceHandle handle) override; -}; -#endif //RMLUI_EXAMPLE_FONTENGINEINTERFACEBITMAP_H diff --git a/src/main.cpp b/src/main.cpp index eb9b9e2..f70bcbd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,11 +7,8 @@ int main() { auto size = Example::GetWindowSize(); InitWindow(size.x, size.y, TextFormat("Raylib RmlUi %s", Example::GetWindowTitle())); SetTargetFPS(500); - SetExitKey(0); - Example::Initialize(); - while (Example::RunProgram()) { if (WindowShouldClose()) { Example::StopProgram(); @@ -33,7 +30,7 @@ int main() { EndDrawing(); } - + Example::DeInitialize(); CloseWindow(); diff --git a/src/raylibFileInterface.cpp b/src/raylibFileInterface.cpp index c6c0a13..91d1be2 100644 --- a/src/raylibFileInterface.cpp +++ b/src/raylibFileInterface.cpp @@ -2,7 +2,7 @@ #include "raylibFileInterface.h" #include -const std::filesystem::path dir("../../assets/"); +const std::filesystem::path dir("./assets/"); inline bool StartsWith(const std::string &text, const std::string &ending) { if (ending.size() > text.size()) { diff --git a/src/samples/basic/animation.cpp b/src/samples/basic/animation.cpp index 687dc55..7496b3b 100644 --- a/src/samples/basic/animation.cpp +++ b/src/samples/basic/animation.cpp @@ -12,6 +12,7 @@ Rml::Vector2i Example::GetWindowSize() { } void Example::Initialize() { + Rml::Log::Message(Rml::Log::LT_INFO, "Initializing animation example\n"); Sample::runLoop = true; Sample::singleLoop = false; Sample::nudge = 0; @@ -46,16 +47,16 @@ void Example::Initialize() { } { auto el = document->GetElementById("high_scores"); - el->Animate("margin-left", Property(0.f, Property::PX), 0.3f, Tween{ Tween::Sine, Tween::In }, 10, true, 1.f); - el->AddAnimationKey("margin-left", Property(100.f, Property::PX), 3.0f, Tween{ Tween::Circular, Tween::Out }); + el->Animate("margin-left", Property(0.f, Unit::PX), 0.3f, Tween{ Tween::Sine, Tween::In }, 10, true, 1.f); + el->AddAnimationKey("margin-left", Property(100.f, Unit::PX), 3.0f, Tween{ Tween::Circular, Tween::Out }); } { auto el = document->GetElementById("options"); - el->Animate("image-color", Property(Colourb(128, 255, 255, 255), Property::COLOUR), 0.3f, Tween{}, -1, false); - el->AddAnimationKey("image-color", Property(Colourb(128, 128, 255, 255), Property::COLOUR), 0.3f); - el->AddAnimationKey("image-color", Property(Colourb(0, 128, 128, 255), Property::COLOUR), 0.3f); - el->AddAnimationKey("image-color", Property(Colourb(64, 128, 255, 0), Property::COLOUR), 0.9f); - el->AddAnimationKey("image-color", Property(Colourb(255, 255, 255, 255), Property::COLOUR), 0.3f); + el->Animate("image-color", Property(Colourb(128, 255, 255, 255), Unit::COLOUR), 0.3f, Tween{}, -1, false); + el->AddAnimationKey("image-color", Property(Colourb(128, 128, 255, 255), Unit::COLOUR), 0.3f); + el->AddAnimationKey("image-color", Property(Colourb(0, 128, 128, 255), Unit::COLOUR), 0.3f); + el->AddAnimationKey("image-color", Property(Colourb(64, 128, 255, 0), Unit::COLOUR), 0.9f); + el->AddAnimationKey("image-color", Property(Colourb(255, 255, 255, 255), Unit::COLOUR), 0.3f); } { auto el = document->GetElementById("exit"); @@ -67,34 +68,34 @@ void Example::Initialize() { // Transform tests { auto el = document->GetElementById("generic"); - auto p = Transform::MakeProperty({ Transforms::TranslateY{ 50, Property::PX }, Transforms::Rotate3D{ 0, 0, 1, -90, Property::DEG }, Transforms::ScaleY{ 0.8f }}); + auto p = Transform::MakeProperty({ Transforms::TranslateY{ 50, Unit::PX }, Transforms::Rotate3D{ 0, 0, 1, -90, Unit::DEG }, Transforms::ScaleY{ 0.8f }}); el->Animate("transform", p, 1.5f, Tween{ Tween::Sine, Tween::InOut }, -1, true); } { auto el = document->GetElementById("combine"); - auto p = Transform::MakeProperty({ Transforms::Translate2D{ 50, 50, Property::PX }, Transforms::Rotate2D(1215) }); + auto p = Transform::MakeProperty({ Transforms::Translate2D{ 50, 50, Unit::PX }, Transforms::Rotate2D(1215) }); el->Animate("transform", p, 8.0f, Tween{}, -1, true); } { auto el = document->GetElementById("decomposition"); - auto p = Transform::MakeProperty({ Transforms::TranslateY{ 50, Property::PX }, Transforms::Rotate3D{ 0.8f, 0, 1, 110, Property::DEG }}); + auto p = Transform::MakeProperty({ Transforms::TranslateY{ 50, Unit::PX }, Transforms::Rotate3D{ 0.8f, 0, 1, 110, Unit::DEG }}); el->Animate("transform", p, 1.3f, Tween{ Tween::Quadratic, Tween::InOut }, -1, true); } // Mixed units tests { auto el = document->GetElementById("abs_rel"); - el->Animate("margin-left", Property(50.f, Property::PERCENT), 1.5f, Tween{}, -1, true); + el->Animate("margin-left", Property(50.f, Unit::PERCENT), 1.5f, Tween{}, -1, true); } { auto el = document->GetElementById("abs_rel_transform"); - auto p = Transform::MakeProperty({ Transforms::TranslateX{ 0, Property::PX }}); + auto p = Transform::MakeProperty({ Transforms::TranslateX{ 0, Unit::PX }}); el->Animate("transform", p, 1.5f, Tween{}, -1, true); } { auto el = document->GetElementById("animation_event"); - el->Animate("top", Property(Math::RandomReal(250.f), Property::PX), 1.5f, Tween{ Tween::Cubic, Tween::InOut }); - el->Animate("left", Property(Math::RandomReal(250.f), Property::PX), 1.5f, Tween{ Tween::Cubic, Tween::InOut }); + el->Animate("top", Property(Math::RandomReal(250.f), Unit::PX), 1.5f, Tween{ Tween::Cubic, Tween::InOut }); + el->Animate("left", Property(Math::RandomReal(250.f), Unit::PX), 1.5f, Tween{ Tween::Cubic, Tween::InOut }); } } diff --git a/src/samples/basic/animationEvent.cpp b/src/samples/basic/animationEvent.cpp index 4a99875..e878c92 100644 --- a/src/samples/basic/animationEvent.cpp +++ b/src/samples/basic/animationEvent.cpp @@ -27,17 +27,17 @@ void ExampleEvent::ProcessEvent(Rml::Event &event) { Sample::nudge = -1; } else if (key_identifier == Rml::Input::KI_LEFT) { auto el = RaylibRmlUi::Context->GetRootElement()->GetElementById("keyevent_response"); - if (el) el->Animate("left", Property{ -200.f, Property::DP }, 0.5, Tween{ Tween::Cubic }); + if (el) el->Animate("left", Property{ -200.f, Unit::DP }, 0.5, Tween{ Tween::Cubic }); } else if (key_identifier == Rml::Input::KI_RIGHT) { auto el = RaylibRmlUi::Context->GetRootElement()->GetElementById("keyevent_response"); - if (el) el->Animate("left", Property{ 200.f, Property::DP }, 0.5, Tween{ Tween::Cubic }); + if (el) el->Animate("left", Property{ 200.f, Unit::DP }, 0.5, Tween{ Tween::Cubic }); } else if (key_identifier == Rml::Input::KI_UP) { auto el = RaylibRmlUi::Context->GetRootElement()->GetElementById("keyevent_response"); - auto offset_right = Property{ 200.f, Property::DP }; - if (el) el->Animate("left", Property{ 0.f, Property::PX }, 0.5, Tween{ Tween::Cubic }, 1, true, 0, &offset_right); + auto offset_right = Property{ 200.f, Unit::DP }; + if (el) el->Animate("left", Property{ 0.f, Unit::PX }, 0.5, Tween{ Tween::Cubic }, 1, true, 0, &offset_right); } else if (key_identifier == Rml::Input::KI_DOWN) { auto el = RaylibRmlUi::Context->GetRootElement()->GetElementById("keyevent_response"); - if (el) el->Animate("left", Property{ 0.f, Property::PX }, 0.5, Tween{ Tween::Cubic }); + if (el) el->Animate("left", Property{ 0.f, Unit::PX }, 0.5, Tween{ Tween::Cubic }); } } break; @@ -53,8 +53,8 @@ void ExampleEvent::ProcessEvent(Rml::Event &event) { case EventId::Animationend: { auto el = event.GetTargetElement(); if (el->GetId() == "animation_event") { - el->Animate("top", Property(Math::RandomReal(200.f), Property::PX), 1.2f, Tween{ Tween::Cubic, Tween::InOut }); - el->Animate("left", Property(Math::RandomReal(100.f), Property::PERCENT), 0.8f, Tween{ Tween::Cubic, Tween::InOut }); + el->Animate("top", Property(Math::RandomReal(200.f), Unit::PX), 1.2f, Tween{ Tween::Cubic, Tween::InOut }); + el->Animate("left", Property(Math::RandomReal(100.f), Unit::PERCENT), 0.8f, Tween{ Tween::Cubic, Tween::InOut }); } } break; diff --git a/src/samples/basic/benchmark.cpp b/src/samples/basic/benchmark.cpp index 77bcaf2..4cff5a9 100644 --- a/src/samples/basic/benchmark.cpp +++ b/src/samples/basic/benchmark.cpp @@ -10,6 +10,7 @@ Rml::Vector2i Example::GetWindowSize() { } void Example::Initialize() { + Rml::Log::Message(Rml::Log::LT_INFO, "Initializing benchmark example\n"); Sample::runGame = RaylibRmlUi::Initialize(1800, 1000); if (!Sample::runGame) { diff --git a/src/samples/basic/bitmapfont.cpp b/src/samples/basic/bitmapfont.cpp index 2022a80..6a19bcb 100644 --- a/src/samples/basic/bitmapfont.cpp +++ b/src/samples/basic/bitmapfont.cpp @@ -2,7 +2,7 @@ #include "raylibRmlUi.h" #include "samples/sample.h" #include "samples/event.h" -#include "samples/basic/bitmapfont/fontEngineInterfaceBitmap.h" +#include "samples/basic/bitmapfont/FontEngineInterfaceBitmap.h" Rml::ElementDocument* document; std::unique_ptr fontEngine; @@ -12,6 +12,7 @@ Rml::Vector2i Example::GetWindowSize() { } void Example::Initialize() { + Rml::Log::Message(Rml::Log::LT_INFO, "Initializing bitmapfont example\n"); fontEngine = Rml::MakeUnique(); Rml::SetFontEngineInterface(fontEngine.get()); @@ -21,7 +22,7 @@ void Example::Initialize() { return; } - if (!Rml::LoadFontFace("samples/basic/bitmapfont/Comfortaa_Regular_22.fnt")) { + if (!Rml::LoadFontFace("samples/basic/bitmapfont/data/Comfortaa_Regular_22.fnt")) { Sample::runGame = false; return; } @@ -29,7 +30,7 @@ void Example::Initialize() { ExampleEventInstancer eventListenerInstancer; Rml::Factory::RegisterEventListenerInstancer(&eventListenerInstancer); - RaylibRmlUi::LoadRml("samples/basic/bitmapfont.rml", "bitmapfont", true); + RaylibRmlUi::LoadRml("samples/basic/bitmapfont/data/bitmapfont.rml", "bitmapfont", true); document = RaylibRmlUi::GetPage("bitmapfont"); diff --git a/src/samples/basic/bitmapfont/FontEngineBitmap.cpp b/src/samples/basic/bitmapfont/FontEngineBitmap.cpp new file mode 100644 index 0000000..93abac7 --- /dev/null +++ b/src/samples/basic/bitmapfont/FontEngineBitmap.cpp @@ -0,0 +1,288 @@ +/* + * This source file is part of RmlUi, the HTML/CSS Interface Middleware + * + * For the latest information, see http://github.com/mikke89/RmlUi + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * Copyright (c) 2019-2023 The RmlUi Team, and contributors + * + * 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. + * + */ + +#include "samples/basic/bitmapfont/FontEngineBitmap.h" +#include +#include +#include +#include +#include + +namespace FontProviderBitmap { +static Rml::Vector> fonts; + +void Initialise() {} + +void Shutdown() +{ + fonts.clear(); +} + +bool LoadFontFace(const String& file_name) +{ + // Load the xml meta file into memory + Rml::UniquePtr data; + size_t length = 0; + + { + auto file_interface = Rml::GetFileInterface(); + auto handle = file_interface->Open(file_name); + if (!handle) + return false; + + length = file_interface->Length(handle); + + data.reset(new byte[length]); + + size_t read_length = file_interface->Read(data.get(), length, handle); + + file_interface->Close(handle); + + if (read_length != length || !data) + return false; + } + + // Parse the xml font description + FontParserBitmap parser; + + { + auto stream = Rml::MakeUnique(data.get(), length); + stream->SetSourceURL(file_name); + + parser.Parse(stream.get()); + + if (parser.family.empty() || parser.glyphs.empty() || parser.texture_name.empty() || parser.metrics.size == 0) + return false; + + // Fill the remaining metrics + parser.metrics.underline_position = 3.f; + parser.metrics.underline_thickness = 1.f; + } + + Texture texture; + texture.Set(parser.texture_name, file_name); + + // Construct and add the font face + fonts.push_back(Rml::MakeUnique(parser.family, parser.style, parser.weight, parser.metrics, texture, parser.texture_dimensions, + std::move(parser.glyphs), std::move(parser.kerning))); + + return true; +} + +FontFaceBitmap* GetFontFaceHandle(const String& family, FontStyle style, FontWeight weight, int size) +{ + FontFaceBitmap* best_match = nullptr; + int best_score = 0; + + // Normally, we'd want to only match the font family exactly, but for this demo we create a very lenient heuristic. + for (const auto& font : fonts) + { + int score = 1; + if (font->GetFamily() == family) + score += 100; + + score += 10 - std::min(10, std::abs(font->GetMetrics().size - size)); + + if (font->GetStyle() == style) + score += 2; + if (font->GetWeight() == weight) + score += 1; + + if (score > best_score) + { + best_match = font.get(); + best_score = score; + } + } + + return best_match; +} + +} // namespace FontProviderBitmap + +FontFaceBitmap::FontFaceBitmap(String family, FontStyle style, FontWeight weight, FontMetrics metrics, Texture texture, Vector2f texture_dimensions, + FontGlyphs&& glyphs, FontKerning&& kerning) : + family(family), + style(style), weight(weight), metrics(metrics), texture(texture), texture_dimensions(texture_dimensions), glyphs(std::move(glyphs)), + kerning(std::move(kerning)) +{} + +int FontFaceBitmap::GetStringWidth(const String& string, Character previous_character) +{ + int width = 0; + + for (auto it_char = Rml::StringIteratorU8(string); it_char; ++it_char) + { + Character character = *it_char; + + auto it_glyph = glyphs.find(character); + if (it_glyph == glyphs.end()) + continue; + + const BitmapGlyph& glyph = it_glyph->second; + + int kerning = GetKerning(previous_character, character); + + width += glyph.advance + kerning; + previous_character = character; + } + + return width; +} + +int FontFaceBitmap::GenerateString(const String& string, const Vector2f& string_position, const Colourb& colour, GeometryList& geometry_list) +{ + int width = 0; + + geometry_list.resize(1); + Rml::Geometry& geometry = geometry_list[0]; + + geometry.SetTexture(&texture); + + auto& vertices = geometry.GetVertices(); + auto& indices = geometry.GetIndices(); + + vertices.reserve(string.size() * 4); + indices.reserve(string.size() * 6); + + Vector2f position = string_position.Round(); + Character previous_character = Character::Null; + + for (auto it_char = Rml::StringIteratorU8(string); it_char; ++it_char) + { + Character character = *it_char; + + auto it_glyph = glyphs.find(character); + if (it_glyph == glyphs.end()) + continue; + + int kerning = GetKerning(previous_character, character); + + width += kerning; + position.x += kerning; + + const BitmapGlyph& glyph = it_glyph->second; + + // Generate the geometry for the character. + vertices.resize(vertices.size() + 4); + indices.resize(indices.size() + 6); + + Vector2f uv_top_left = glyph.position / texture_dimensions; + Vector2f uv_bottom_right = (glyph.position + glyph.dimension) / texture_dimensions; + + Rml::GeometryUtilities::GenerateQuad(&vertices[0] + (vertices.size() - 4), &indices[0] + (indices.size() - 6), + Vector2f(position + glyph.offset).Round(), glyph.dimension, colour, uv_top_left, uv_bottom_right, (int)vertices.size() - 4); + + width += glyph.advance; + position.x += glyph.advance; + + previous_character = character; + } + + return width; +} + +int FontFaceBitmap::GetKerning(Character left, Character right) const +{ + uint64_t key = (((uint64_t)left << 32) | (uint64_t)right); + + auto it = kerning.find(key); + if (it != kerning.end()) + return it->second; + + return 0; +} + +FontParserBitmap::~FontParserBitmap() {} + +void FontParserBitmap::HandleElementStart(const String& name, const Rml::XMLAttributes& attributes) +{ + if (name == "info") + { + family = Rml::StringUtilities::ToLower(Get(attributes, "face", String())); + metrics.size = Get(attributes, "size", 0); + + style = Get(attributes, "italic", 0) == 1 ? FontStyle::Italic : FontStyle::Normal; + weight = Get(attributes, "bold", 0) == 1 ? FontWeight::Bold : FontWeight::Normal; + } + else if (name == "common") + { + metrics.line_spacing = Get(attributes, "lineHeight", 0.f); + metrics.ascent = Get(attributes, "base", 0.f); + metrics.descent = metrics.line_spacing - metrics.ascent; + + texture_dimensions.x = Get(attributes, "scaleW", 0.f); + texture_dimensions.y = Get(attributes, "scaleH", 0.f); + } + else if (name == "page") + { + int id = Get(attributes, "id", -1); + if (id != 0) + { + Rml::Log::Message(Rml::Log::LT_WARNING, "Only single font textures are supported in Bitmap Font Engine"); + return; + } + texture_name = Get(attributes, "file", String()); + } + else if (name == "char") + { + Character character = (Character)Get(attributes, "id", 0); + if (character == Character::Null) + return; + + BitmapGlyph& glyph = glyphs[character]; + + glyph.offset.x = Get(attributes, "xoffset", 0.f); + glyph.offset.y = Get(attributes, "yoffset", 0.f) - metrics.ascent; // Shift y-origin from top to baseline + + glyph.advance = Get(attributes, "xadvance", 0); + glyph.position.x = Get(attributes, "x", 0.f); + glyph.position.y = Get(attributes, "y", 0.f); + glyph.dimension.x = Get(attributes, "width", 0.f); + glyph.dimension.y = Get(attributes, "height", 0.f); + + if (character == (Character)'x') + metrics.x_height = glyph.dimension.y; + } + else if (name == "kerning") + { + uint64_t first = (uint64_t)Get(attributes, "first", 0); + uint64_t second = (uint64_t)Get(attributes, "second", 0); + int amount = Get(attributes, "amount", 0); + + if (first != 0 && second != 0 && amount != 0) + { + uint64_t key = ((first << 32) | second); + kerning[key] = amount; + } + } +} + +void FontParserBitmap::HandleElementEnd(const String& /*name*/) {} + +void FontParserBitmap::HandleData(const String& /*data*/, Rml::XMLDataType /*type*/) {} diff --git a/src/samples/basic/bitmapfont/FontEngineInterfaceBitmap.cpp b/src/samples/basic/bitmapfont/FontEngineInterfaceBitmap.cpp new file mode 100644 index 0000000..a3accdf --- /dev/null +++ b/src/samples/basic/bitmapfont/FontEngineInterfaceBitmap.cpp @@ -0,0 +1,94 @@ +/* + * This source file is part of RmlUi, the HTML/CSS Interface Middleware + * + * For the latest information, see http://github.com/mikke89/RmlUi + * + * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd + * Copyright (c) 2019-2023 The RmlUi Team, and contributors + * + * 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. + * + */ + +#include "samples/basic/bitmapfont/FontEngineInterfaceBitmap.h" +#include "samples/basic/bitmapfont/FontEngineBitmap.h" +#include + +void FontEngineInterfaceBitmap::Initialize() +{ + FontProviderBitmap::Initialise(); +} + +void FontEngineInterfaceBitmap::Shutdown() +{ + FontProviderBitmap::Shutdown(); +} + +bool FontEngineInterfaceBitmap::LoadFontFace(const String& file_name, bool /*fallback_face*/, FontWeight /*weight*/) +{ + return FontProviderBitmap::LoadFontFace(file_name); +} + +bool FontEngineInterfaceBitmap::LoadFontFace(const byte* /*data*/, int /*data_size*/, const String& font_family, FontStyle /*style*/, + FontWeight /*weight*/, bool /*fallback_face*/) +{ + // We return 'true' here to allow the debugger to continue loading, but we will use our own fonts when it asks for a handle. + // The debugger might look a bit off with our own fonts, but hey it works. + if (font_family == "rmlui-debugger-font") + return true; + + return false; +} + +FontFaceHandle FontEngineInterfaceBitmap::GetFontFaceHandle(const String& family, FontStyle style, FontWeight weight, int size) +{ + auto handle = FontProviderBitmap::GetFontFaceHandle(family, style, weight, size); + return reinterpret_cast(handle); +} + +FontEffectsHandle FontEngineInterfaceBitmap::PrepareFontEffects(FontFaceHandle /*handle*/, const FontEffectList& /*font_effects*/) +{ + // Font effects are not rendered in this implementation. + return 0; +} + +const FontMetrics& FontEngineInterfaceBitmap::GetFontMetrics(FontFaceHandle handle) +{ + auto handle_bitmap = reinterpret_cast(handle); + return handle_bitmap->GetMetrics(); +} + +int FontEngineInterfaceBitmap::GetStringWidth(FontFaceHandle handle, const String& string, const TextShapingContext& /*text_shaping_context*/, + Character prior_character) +{ + auto handle_bitmap = reinterpret_cast(handle); + return handle_bitmap->GetStringWidth(string, prior_character); +} + +int FontEngineInterfaceBitmap::GenerateString(FontFaceHandle handle, FontEffectsHandle /*font_effects_handle*/, const String& string, + const Vector2f& position, const Colourb& colour, float /*opacity*/, const TextShapingContext& /*text_shaping_context*/, GeometryList& geometry) +{ + auto handle_bitmap = reinterpret_cast(handle); + return handle_bitmap->GenerateString(string, position, colour, geometry); +} + +int FontEngineInterfaceBitmap::GetVersion(FontFaceHandle /*handle*/) +{ + return 0; +} diff --git a/src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.fnt b/src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.fnt new file mode 100644 index 0000000..f569e15 --- /dev/null +++ b/src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.fnt @@ -0,0 +1,758 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.tga b/src/samples/basic/bitmapfont/data/Comfortaa_Regular_22.tga new file mode 100644 index 0000000000000000000000000000000000000000..4c081dce1dab7912ce6657b0bcb6df0faa42bd16 GIT binary patch literal 131116 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 + +Demo + + + + +

This is a bitmap font sample!

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Urna neque viverra justo nec ultrices dui sapien eget mi. Risus quis varius quam quisque id. Amet est placerat in egestas erat imperdiet. Velit egestas dui id ornare arcu odio ut sem. Aliquet porttitor lacus luctus accumsan tortor posuere. Et malesuada fames ac turpis egestas integer eget. Enim nunc faucibus a pellentesque sit amet porttitor eget. Nunc pulvinar sapien et ligula. Sit amet mattis vulputate enim nulla aliquet porttitor lacus luctus. Dolor sit amet consectetur adipiscing. Congue eu consequat ac felis donec et odio pellentesque. Nunc non blandit massa enim nec dui nunc mattis.

+

Posuere sollicitudin aliquam ultrices sagittis orci a scelerisque. Quam pellentesque nec nam aliquam sem et. Et tortor consequat id porta nibh venenatis. Facilisi cras fermentum odio eu feugiat pretium nibh ipsum consequat. Magna ac placerat vestibulum lectus mauris ultrices eros. Amet purus gravida quis blandit turpis cursus. Elit duis tristique sollicitudin nibh sit amet commodo nulla. Suscipit adipiscing bibendum est ultricies integer quis auctor elit sed. Iaculis at erat pellentesque adipiscing commodo elit at imperdiet. Pellentesque elit ullamcorper dignissim cras. Nunc eget lorem dolor sed viverra ipsum nunc. Ac felis donec et odio pellentesque diam volutpat commodo.

+ + diff --git a/src/samples/basic/bitmapfont/fontEngineBitmap.cpp b/src/samples/basic/bitmapfont/fontEngineBitmap.cpp deleted file mode 100644 index c007d08..0000000 --- a/src/samples/basic/bitmapfont/fontEngineBitmap.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * This source file is part of RmlUi, the HTML/CSS Interface Middleware - * - * For the latest information, see http://github.com/mikke89/RmlUi - * - * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd - * Copyright (c) 2019 The RmlUi Team, and contributors - * - * 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. - * - */ - -#include -#include -#include -#include "samples/basic/bitmapfont/fontEngineBitmap.h" - -namespace FontProviderBitmap { - static Rml::Vector> fonts; - - - void Initialise() { - } - - void Shutdown() { - fonts.clear(); - } - - bool LoadFontFace(const String &file_name) { - // Load the xml meta file into memory - Rml::UniquePtr data; - size_t length = 0; - - { - auto file_interface = Rml::GetFileInterface(); - auto handle = file_interface->Open(file_name); - if (!handle) - return false; - - length = file_interface->Length(handle); - - data.reset(new byte[length]); - - size_t read_length = file_interface->Read(data.get(), length, handle); - - file_interface->Close(handle); - - if (read_length != length || !data) - return false; - } - - // Parse the xml font description - FontParserBitmap parser; - - { - auto stream = Rml::MakeUnique(data.get(), length); - stream->SetSourceURL(file_name); - - parser.Parse(stream.get()); - - if (parser.family.empty() || parser.glyphs.empty() || parser.texture_name.empty() || parser.metrics.size == 0) - return false; - - // Fill the remaining metrics - parser.metrics.underline_position = -parser.metrics.baseline - 1.f; - parser.metrics.underline_thickness = 1.f; - } - - Texture texture; - texture.Set(parser.texture_name, file_name); - - // Construct and add the font face - fonts.push_back( - Rml::MakeUnique( - parser.family, parser.style, parser.weight, parser.metrics, texture, parser.texture_dimensions, std::move(parser.glyphs), std::move(parser.kerning) - )); - - return true; - } - - FontFaceBitmap* GetFontFaceHandle(const String &family, FontStyle style, FontWeight weight, int size) { - FontFaceBitmap* best_match = nullptr; - int best_score = 0; - - // Normally, we'd want to only match the font family exactly, but for this demo we create a very lenient heuristic. - for (const auto &font: fonts) { - int score = 1; - if (font->GetFamily() == family) - score += 100; - - score += 10 - std::min(10, std::abs(font->GetMetrics().size - size)); - - if (font->GetStyle() == style) - score += 2; - if (font->GetWeight() == weight) - score += 1; - - if (score > best_score) { - best_match = font.get(); - best_score = score; - } - } - - return best_match; - } - -} - - -FontFaceBitmap::FontFaceBitmap(String family, FontStyle style, FontWeight weight, FontMetrics metrics, Texture texture, Vector2f texture_dimensions, FontGlyphs &&glyphs, - FontKerning &&kerning) - : family(family), style(style), weight(weight), metrics(metrics), texture(texture), texture_dimensions(texture_dimensions), glyphs(std::move(glyphs)), - kerning(std::move(kerning)) { -} - -int FontFaceBitmap::GetStringWidth(const String &string, Character previous_character) { - int width = 0; - - for (auto it_char = Rml::StringIteratorU8(string) ; it_char ; ++it_char) { - Character character = *it_char; - - auto it_glyph = glyphs.find(character); - if (it_glyph == glyphs.end()) - continue; - - const BitmapGlyph &glyph = it_glyph->second; - - int kerning = GetKerning(previous_character, character); - - width += glyph.advance + kerning; - previous_character = character; - } - - return width; -} - -int FontFaceBitmap::GenerateString(const String &string, const Vector2f &string_position, const Colourb &colour, GeometryList &geometry_list) { - int width = 0; - - geometry_list.resize(1); - Rml::Geometry &geometry = geometry_list[0]; - - geometry.SetTexture(&texture); - - auto &vertices = geometry.GetVertices(); - auto &indices = geometry.GetIndices(); - - vertices.reserve(string.size() * 4); - indices.reserve(string.size() * 6); - - Vector2f position = string_position.Round(); - Character previous_character = Character::Null; - - for (auto it_char = Rml::StringIteratorU8(string) ; it_char ; ++it_char) { - Character character = *it_char; - - auto it_glyph = glyphs.find(character); - if (it_glyph == glyphs.end()) - continue; - - int kerning = GetKerning(previous_character, character); - - width += kerning; - position.x += kerning; - - const BitmapGlyph &glyph = it_glyph->second; - - // Generate the geometry for the character. - vertices.resize(vertices.size() + 4); - indices.resize(indices.size() + 6); - - Vector2f uv_top_left = glyph.position / texture_dimensions; - Vector2f uv_bottom_right = (glyph.position + glyph.dimension) / texture_dimensions; - - Rml::GeometryUtilities::GenerateQuad( - &vertices[0] + (vertices.size() - 4), - &indices[0] + (indices.size() - 6), - Vector2f(position + glyph.offset).Round(), - glyph.dimension, - colour, - uv_top_left, - uv_bottom_right, - (int)vertices.size() - 4 - ); - - width += glyph.advance; - position.x += glyph.advance; - - previous_character = character; - } - - return width; -} - -int FontFaceBitmap::GetKerning(Character left, Character right) const { - uint64_t key = (((uint64_t)left << 32) | (uint64_t)right); - - auto it = kerning.find(key); - if (it != kerning.end()) - return it->second; - - return 0; -} - - -FontParserBitmap::~FontParserBitmap() { -} - -// Called when the parser finds the beginning of an element tag. -void FontParserBitmap::HandleElementStart(const String &name, const Rml::XMLAttributes &attributes) { - if (name == "info") { - family = Rml::StringUtilities::ToLower(Get(attributes, "face", String())); - metrics.size = Get(attributes, "size", 0); - - style = Get(attributes, "italic", 0) == 1 ? FontStyle::Italic : FontStyle::Normal; - weight = Get(attributes, "bold", 0) == 1 ? FontWeight::Bold : FontWeight::Normal; - } else if (name == "common") { - metrics.line_height = Get(attributes, "lineHeight", 0); - metrics.baseline = metrics.line_height - Get(attributes, "base", 0); - - texture_dimensions.x = Get(attributes, "scaleW", 0.f); - texture_dimensions.y = Get(attributes, "scaleH", 0.f); - } else if (name == "page") { - int id = Get(attributes, "id", -1); - if (id != 0) { - Rml::Log::Message(Rml::Log::LT_WARNING, "Only single font textures are supported in Bitmap Font Engine"); - return; - } - texture_name = Get(attributes, "file", String()); - } else if (name == "char") { - Character character = (Character)Get(attributes, "id", 0); - if (character == Character::Null) - return; - - BitmapGlyph &glyph = glyphs[character]; - - glyph.advance = Get(attributes, "xadvance", 0); - - // Shift y-origin from top to baseline - float origin_shift_y = float(metrics.baseline - metrics.line_height); - - glyph.offset.x = Get(attributes, "xoffset", 0.f); - glyph.offset.y = Get(attributes, "yoffset", 0.f) + origin_shift_y; - - glyph.position.x = Get(attributes, "x", 0.f); - glyph.position.y = Get(attributes, "y", 0.f); - glyph.dimension.x = Get(attributes, "width", 0.f); - glyph.dimension.y = Get(attributes, "height", 0.f); - - if (character == (Character)'x') - metrics.x_height = (int)glyph.dimension.y; - } else if (name == "kerning") { - uint64_t first = (uint64_t)Get(attributes, "first", 0); - uint64_t second = (uint64_t)Get(attributes, "second", 0); - int amount = Get(attributes, "amount", 0); - - if (first != 0 && second != 0 && amount != 0) { - uint64_t key = ((first << 32) | second); - kerning[key] = amount; - } - } -} - -// Called when the parser finds the end of an element tag. -void FontParserBitmap::HandleElementEnd(const String &RMLUI_UNUSED_PARAMETER(name)) { - RMLUI_UNUSED(name); -} - -// Called when the parser encounters data. -void FontParserBitmap::HandleData(const String &RMLUI_UNUSED_PARAMETER(data), Rml::XMLDataType RMLUI_UNUSED_PARAMETER(type)) { - RMLUI_UNUSED(data); - RMLUI_UNUSED(type); -} diff --git a/src/samples/basic/bitmapfont/fontEngineInterfaceBitmap.cpp b/src/samples/basic/bitmapfont/fontEngineInterfaceBitmap.cpp deleted file mode 100644 index 52540c9..0000000 --- a/src/samples/basic/bitmapfont/fontEngineInterfaceBitmap.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This source file is part of RmlUi, the HTML/CSS Interface Middleware - * - * For the latest information, see http://github.com/mikke89/RmlUi - * - * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd - * Copyright (c) 2019 The RmlUi Team, and contributors - * - * 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. - * - */ - -#include -#include "samples/basic/bitmapfont/fontEngineInterfaceBitmap.h" -#include "samples/basic/bitmapfont/fontEngineBitmap.h" - -FontEngineInterfaceBitmap::FontEngineInterfaceBitmap() { - FontProviderBitmap::Initialise(); -} - -FontEngineInterfaceBitmap::~FontEngineInterfaceBitmap() { - FontProviderBitmap::Shutdown(); -} - -bool FontEngineInterfaceBitmap::LoadFontFace(const String &file_name, bool /*fallback_face*/, FontWeight /*weight*/) { - return FontProviderBitmap::LoadFontFace(file_name); -} - -bool -FontEngineInterfaceBitmap::LoadFontFace(const byte* /*data*/, int /*data_size*/, const String &font_family, FontStyle /*style*/, FontWeight /*weight*/, bool /*fallback_face*/) { - // We return 'true' here to allow the debugger to continue loading, but we will use our own fonts when it asks for a handle. - // The debugger might look a bit off with our own fonts, but hey it works. - if (font_family == "rmlui-debugger-font") - return true; - - return false; -} - -FontFaceHandle FontEngineInterfaceBitmap::GetFontFaceHandle(const String &family, FontStyle style, FontWeight weight, int size) { - auto handle = FontProviderBitmap::GetFontFaceHandle(family, style, weight, size); - return reinterpret_cast(handle); -} - -FontEffectsHandle FontEngineInterfaceBitmap::PrepareFontEffects(FontFaceHandle /*handle*/, const FontEffectList & /*font_effects*/) { - // Font effects are not rendered in this implementation. - return 0; -} - -int FontEngineInterfaceBitmap::GetSize(FontFaceHandle handle) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GetMetrics().size; -} - -int FontEngineInterfaceBitmap::GetXHeight(FontFaceHandle handle) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GetMetrics().x_height; -} - -int FontEngineInterfaceBitmap::GetLineHeight(FontFaceHandle handle) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GetMetrics().line_height; -} - -int FontEngineInterfaceBitmap::GetBaseline(FontFaceHandle handle) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GetMetrics().baseline; -} - -float FontEngineInterfaceBitmap::GetUnderline(FontFaceHandle handle, float &thickness) { - auto handle_bitmap = reinterpret_cast(handle); - thickness = handle_bitmap->GetMetrics().underline_thickness; - return handle_bitmap->GetMetrics().underline_position; -} - -int FontEngineInterfaceBitmap::GetStringWidth(FontFaceHandle handle, const String &string, Character prior_character) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GetStringWidth(string, prior_character); -} - -int FontEngineInterfaceBitmap::GenerateString(FontFaceHandle handle, FontEffectsHandle /*font_effects_handle*/, const String &string, - const Vector2f &position, const Colourb &colour, float /*opacity*/, GeometryList &geometry) { - auto handle_bitmap = reinterpret_cast(handle); - return handle_bitmap->GenerateString(string, position, colour, geometry); -} - -int FontEngineInterfaceBitmap::GetVersion(FontFaceHandle /*handle*/) { - return 0; -} \ No newline at end of file diff --git a/src/samples/basic/databinding.cpp b/src/samples/basic/databinding.cpp index 223ce43..7c0b05e 100644 --- a/src/samples/basic/databinding.cpp +++ b/src/samples/basic/databinding.cpp @@ -15,6 +15,7 @@ Rml::Vector2i Example::GetWindowSize() { } void Example::Initialize() { + Rml::Log::Message(Rml::Log::LT_INFO, "Initializing databinding example\n"); Sample::runGame = RaylibRmlUi::Initialize(1600, 900); if (!Sample::runGame) { diff --git a/src/samples/raylib.cpp b/src/samples/raylib.cpp index df8140e..cf35fd9 100644 --- a/src/samples/raylib.cpp +++ b/src/samples/raylib.cpp @@ -7,10 +7,9 @@ Rml::Vector2i Example::GetWindowSize() { } void Example::Initialize() { + Rml::Log::Message(Rml::Log::LT_INFO, "Initializing Raylib example\n"); RaylibRmlUi::Initialize(1280, 720); - RaylibRmlUi::LoadFont("UbuntuMono-Regular.ttf"); - RaylibRmlUi::LoadRml("raylib.rml", "index", true); }