diff --git a/lib/libimhex/include/hex/api/event_manager.hpp b/lib/libimhex/include/hex/api/event_manager.hpp index 876644b9395d6..43da0a12be902 100644 --- a/lib/libimhex/include/hex/api/event_manager.hpp +++ b/lib/libimhex/include/hex/api/event_manager.hpp @@ -226,6 +226,7 @@ namespace hex { EVENT_DEF(EventAbnormalTermination, int); EVENT_DEF(EventThemeChanged); EVENT_DEF(EventOSThemeChanged); + EVENT_DEF(EventDPIChanged, float, float); EVENT_DEF(EventWindowFocused, bool); /** diff --git a/lib/libimhex/include/hex/api/theme_manager.hpp b/lib/libimhex/include/hex/api/theme_manager.hpp index 9d88e6c851e6b..2c0681cf017db 100644 --- a/lib/libimhex/include/hex/api/theme_manager.hpp +++ b/lib/libimhex/include/hex/api/theme_manager.hpp @@ -56,6 +56,7 @@ namespace hex { */ static void addStyleHandler(const std::string &name, const StyleMap &styleMap); + static void reapplyCurrentTheme(); static std::vector getThemeNames(); static const std::string &getImageTheme(); diff --git a/lib/libimhex/source/api/theme_manager.cpp b/lib/libimhex/source/api/theme_manager.cpp index e13ad589d04d9..c3a8be59f14b3 100644 --- a/lib/libimhex/source/api/theme_manager.cpp +++ b/lib/libimhex/source/api/theme_manager.cpp @@ -21,6 +21,11 @@ namespace hex { } + void ThemeManager::reapplyCurrentTheme() { + ThemeManager::changeTheme(s_currTheme); + } + + void ThemeManager::addThemeHandler(const std::string &name, const ColorMap &colorMap, const std::function &getFunction, const std::function &setFunction) { std::unique_lock lock(s_themeMutex); diff --git a/main/gui/source/window/win_window.cpp b/main/gui/source/window/win_window.cpp index 3a25ba7d5ef02..4ff534fd3e682 100644 --- a/main/gui/source/window/win_window.cpp +++ b/main/gui/source/window/win_window.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "window.hpp" @@ -45,6 +48,22 @@ namespace hex { // Custom Window procedure for receiving OS events static LRESULT commonWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { + case WM_DPICHANGED: { + int interfaceScaleSetting = int(hex::ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 0.0F) * 10.0F); + if (interfaceScaleSetting != 0) + break; + + const auto newScale = LOWORD(wParam) / 96.0F; + const auto oldScale = ImHexApi::System::getNativeScale(); + + EventDPIChanged::post(oldScale, newScale); + ImHexApi::System::impl::setNativeScale(newScale); + + ThemeManager::reapplyCurrentTheme(); + ImGui::GetStyle().ScaleAllSizes(newScale); + + return TRUE; + } case WM_COPYDATA: { // Handle opening files in existing instance @@ -371,6 +390,18 @@ namespace hex { void Window::initNative() { + // Setup DPI Awareness + { + using SetProcessDpiAwarenessContextFunc = HRESULT(WINAPI *)(DPI_AWARENESS_CONTEXT); + + SetProcessDpiAwarenessContextFunc SetProcessDpiAwarenessContext = + (SetProcessDpiAwarenessContextFunc)(void*)GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetProcessDpiAwarenessContext"); + + if (SetProcessDpiAwarenessContext != nullptr) { + SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); + } + } + if (ImHexApi::System::isDebugBuild()) { // If the application is running in debug mode, ImHex runs under the CONSOLE subsystem, // so we don't need to do anything besides enabling ANSI colors diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 187db405ec73e..27e7e652a074b 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -115,6 +115,21 @@ namespace hex { m_popupsToOpen.push_back(name); }); + EventDPIChanged::subscribe([this](float oldScaling, float newScaling) { + if (oldScaling == newScaling || oldScaling == 0 || newScaling == 0) + return; + + int width, height; + glfwGetWindowSize(m_window, &width, &height); + + width = float(width) * newScaling / oldScaling; + height = float(height) * newScaling / oldScaling; + + ImHexApi::System::impl::setMainWindowSize(width, height); + glfwSetWindowSize(m_window, width, height); + }); + + LayoutManager::registerLoadCallback([this](std::string_view line) { int width = 0, height = 0; sscanf(line.data(), "MainWindowSize=%d,%d", &width, &height); @@ -827,6 +842,7 @@ namespace hex { auto win = static_cast(glfwGetWindowUserPointer(window)); win->m_unlockFrameRate = true; + win->fullFrame(); }); // Register window resize callback diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index 80b468363653e..5ea00c763627d 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -455,6 +455,7 @@ "hex.builtin.setting.font.font_italic": "Italic", "hex.builtin.setting.font.font_antialias": "Antialiasing", "hex.builtin.setting.font.font_path": "Custom Font Path", + "hex.builtin.setting.font.pixel_perfect_default_font": "Use a Pixel-Perfect default font", "hex.builtin.setting.font.font_size": "Font Size", "hex.builtin.setting.font.font_size.tooltip": "The font size can only be adjusted when a custom font has been selected above.\n\nThis is because ImHex uses a pixel-perfect bitmap font by default. Scaling it by any non-integer factor will only cause it to become blurry.", "hex.builtin.setting.general": "General", diff --git a/plugins/builtin/source/content/init_tasks.cpp b/plugins/builtin/source/content/init_tasks.cpp index c7fc5318b2312..ff79305e31f1c 100644 --- a/plugins/builtin/source/content/init_tasks.cpp +++ b/plugins/builtin/source/content/init_tasks.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -98,15 +99,20 @@ namespace hex::plugin::builtin { } bool configureUIScale() { - int interfaceScaleSetting = int(ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 1.0F) * 10.0F); + EventDPIChanged::subscribe([](float, float newScaling) { + int interfaceScaleSetting = int(ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.scaling_factor", 0.0F) * 10.0F); - float interfaceScaling; - if (interfaceScaleSetting == 0) - interfaceScaling = ImHexApi::System::getNativeScale(); - else - interfaceScaling = interfaceScaleSetting / 10.0F; + float interfaceScaling; + if (interfaceScaleSetting == 0) + interfaceScaling = newScaling; + else + interfaceScaling = interfaceScaleSetting / 10.0F; - ImHexApi::System::impl::setGlobalScale(interfaceScaling); + ImHexApi::System::impl::setGlobalScale(interfaceScaling); + }); + + const auto nativeScale = ImHexApi::System::getNativeScale(); + EventDPIChanged::post(nativeScale, nativeScale); return true; } diff --git a/plugins/builtin/source/content/settings_entries.cpp b/plugins/builtin/source/content/settings_entries.cpp index 5d47589794d38..1c791cd3a22b0 100644 --- a/plugins/builtin/source/content/settings_entries.cpp +++ b/plugins/builtin/source/content/settings_entries.cpp @@ -201,6 +201,10 @@ namespace hex::plugin::builtin { return m_value; } + float getValue() const { + return m_value; + } + private: float m_value = 1.0F; }; @@ -834,6 +838,14 @@ namespace hex::plugin::builtin { .requiresRestart() .setEnabledCallback(customFontsEnabled); + ContentRegistry::Settings::add("hex.builtin.setting.font", "hex.builtin.setting.font.custom_font", "hex.builtin.setting.font.pixel_perfect_default_font", true) + .setEnabledCallback([customFontPathSetting] { + auto &fontPath = static_cast(customFontPathSetting.getWidget()); + + return fontPath.getPath().empty(); + }) + .requiresRestart(); + const auto customFontSettingsEnabled = [customFontEnabledSetting, customFontPathSetting] { auto &customFontsEnabled = static_cast(customFontEnabledSetting.getWidget()); auto &fontPath = static_cast(customFontPathSetting.getWidget()); diff --git a/plugins/fonts/romfs/BLENDERICONS_LICENSE.txt b/plugins/fonts/romfs/BLENDERICONS_LICENSE.txt new file mode 100644 index 0000000000000..33bec29d5181d --- /dev/null +++ b/plugins/fonts/romfs/BLENDERICONS_LICENSE.txt @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/plugins/fonts/romfs/FIRACODE_LICENSE.txt b/plugins/fonts/romfs/FIRACODE_LICENSE.txt new file mode 100644 index 0000000000000..6bd9f9f2f8bd3 --- /dev/null +++ b/plugins/fonts/romfs/FIRACODE_LICENSE.txt @@ -0,0 +1,93 @@ +Copyright (c) 2014, The Fira Code Project Authors (https://github.com/tonsky/FiraCode) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +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, +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 +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/plugins/fonts/romfs/fonts/firacode.ttf b/plugins/fonts/romfs/fonts/firacode.ttf new file mode 100644 index 0000000000000..660742d61d11f Binary files /dev/null and b/plugins/fonts/romfs/fonts/firacode.ttf differ diff --git a/plugins/fonts/source/font_loader.cpp b/plugins/fonts/source/font_loader.cpp index ef2a2f429b2a8..46be93a455f30 100644 --- a/plugins/fonts/source/font_loader.cpp +++ b/plugins/fonts/source/font_loader.cpp @@ -1,12 +1,16 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include #include @@ -64,13 +68,14 @@ namespace hex::fonts { config.SizePixels = std::floor(ImHexApi::System::getGlobalScale()) * 13.0F; auto font = m_fontAtlas->AddFontDefault(&config); + m_fontSizes.emplace_back(false, config.SizePixels); m_config.MergeMode = true; return Font(font); } - Font addFontFromMemory(const std::vector &fontData, float fontSize, ImVec2 offset, bool ownedByImGui = false, const ImVector &glyphRange = {}) { + Font addFontFromMemory(const std::vector &fontData, float fontSize, bool scalable, ImVec2 offset, bool ownedByImGui = false, const ImVector &glyphRange = {}) { auto &storedFontData = m_fontData.emplace_back(fontData); ImFontConfig config = m_config; @@ -78,22 +83,23 @@ namespace hex::fonts { config.GlyphOffset = { offset.x, offset.y }; auto font = m_fontAtlas->AddFontFromMemoryTTF(storedFontData.data(), int(storedFontData.size()), fontSize, &config, !glyphRange.empty() ? glyphRange.Data : m_glyphRange.Data); + m_fontSizes.emplace_back(scalable, fontSize); m_config.MergeMode = true; return Font(font); } - Font addFontFromRomFs(const std::fs::path &path, float fontSize, ImVec2 offset, const ImVector &glyphRange = {}) { + Font addFontFromRomFs(const std::fs::path &path, float fontSize, bool scalable, ImVec2 offset, const ImVector &glyphRange = {}) { auto data = romfs::get(path).span(); - return addFontFromMemory({ data.begin(), data.end() }, fontSize, offset, false, glyphRange); + return addFontFromMemory({ data.begin(), data.end() }, fontSize, scalable, offset, false, glyphRange); } - Font addFontFromFile(const std::fs::path &path, float fontSize, ImVec2 offset, const ImVector &glyphRange = {}) { + Font addFontFromFile(const std::fs::path &path, float fontSize, bool scalable, ImVec2 offset, const ImVector &glyphRange = {}) { wolv::io::File file(path, wolv::io::File::Mode::Read); auto data = file.readVector(); - return addFontFromMemory(data, fontSize, offset, true, glyphRange); + return addFontFromMemory(data, fontSize, scalable, offset, true, glyphRange); } void setBold(bool enabled) { @@ -154,7 +160,6 @@ namespace hex::fonts { [[nodiscard]] ImFontAtlas* takeAtlas() { auto result = m_fontAtlas; - m_fontAtlas = nullptr; return result; } @@ -198,8 +203,22 @@ namespace hex::fonts { m_config.MergeMode = false; } + void updateFontScaling(float newScaling) { + for (int i = 0; i < m_fontAtlas->ConfigData.size(); i += 1) { + const auto &[scalable, fontSize] = m_fontSizes[i]; + auto &configData = m_fontAtlas->ConfigData[i]; + + if (!scalable) { + configData.SizePixels = fontSize * std::floor(newScaling); + } else { + configData.SizePixels = fontSize * newScaling; + } + } + } + private: ImFontAtlas* m_fontAtlas; + std::vector> m_fontSizes; ImFontConfig m_config; ImVector m_glyphRange; @@ -288,7 +307,7 @@ namespace hex::fonts { // Try to load the custom font if one was set std::optional defaultFont; if (!customFontPath.empty()) { - defaultFont = fontAtlas.addFontFromFile(customFontPath, fontSize, ImVec2()); + defaultFont = fontAtlas.addFontFromFile(customFontPath, fontSize, true, ImVec2()); if (!fontAtlas.build()) { log::error("Failed to load custom font '{}'! Falling back to default font", wolv::util::toUTF8String(customFontPath)); defaultFont.reset(); @@ -297,7 +316,13 @@ namespace hex::fonts { // If there's no custom font set, or it failed to load, fall back to the default font if (!defaultFont.has_value()) { - defaultFont = fontAtlas.addDefaultFont(); + auto pixelPerfectFont = ContentRegistry::Settings::read("hex.builtin.setting.font", "hex.builtin.setting.font.pixel_perfect_default_font", true); + + if (pixelPerfectFont) + defaultFont = fontAtlas.addDefaultFont(); + else + defaultFont = fontAtlas.addFontFromRomFs("fonts/firacode.ttf", fontSize * 1.1, true, ImVec2()); + if (!fontAtlas.build()) { log::fatal("Failed to load default font!"); return false; @@ -326,10 +351,20 @@ namespace hex::fonts { ImVec2 offset = { font.offset.x, font.offset.y - (defaultFont->getDescent() - fontAtlas.calculateFontDescend(font, fontSize)) }; // Load the font - fontAtlas.addFontFromMemory(font.fontData, font.defaultSize.value_or(fontSize), offset, false, glyphRanges.back()); + fontAtlas.addFontFromMemory(font.fontData, font.defaultSize.value_or(fontSize), !font.defaultSize.has_value(), offset, false, glyphRanges.back()); } } + EventDPIChanged::subscribe([](float, float newScaling) { + fontAtlas.updateFontScaling(newScaling); + + if (fontAtlas.build()) { + ImGui_ImplOpenGL3_DestroyFontsTexture(); + ImGui_ImplOpenGL3_CreateFontsTexture(); + ImHexApi::Fonts::impl::setFontAtlas(fontAtlas.takeAtlas()); + } + }); + // Build the font atlas const bool result = fontAtlas.build(); if (result) {