diff --git a/.gitignore b/.gitignore index f333580..d69a77b 100644 --- a/.gitignore +++ b/.gitignore @@ -25,7 +25,7 @@ logs/ *.tar.gz *.rar *.gpg -!vendor/freetype-2.12.1.tar.gz +!vendor/* # Gradle .gradletasknamecache diff --git a/build.gradle b/build.gradle index 7b091cd..9d15dda 100644 --- a/build.gradle +++ b/build.gradle @@ -54,6 +54,7 @@ tasks.register('generateAst', GenerateAst) { headerFiles = [ file('include/imgui/imgui.h'), file('include/imgui/imgui_internal.h'), + file('include/imgui/misc/freetype/imgui_freetype.h'), file('include/ImGuiFileDialog/ImGuiFileDialog.h'), file('include/imgui-knobs/imgui-knobs.h'), file('include/imguizmo/ImGuizmo.h'), diff --git a/buildSrc/scripts/vendor_freetype.sh b/buildSrc/scripts/vendor_freetype.sh index eecb26b..5d973c7 100755 --- a/buildSrc/scripts/vendor_freetype.sh +++ b/buildSrc/scripts/vendor_freetype.sh @@ -17,7 +17,7 @@ echo "Vendor type set to '$VTYPE'" # Define library directory and version LIBDIR=build/vendor/freetype -VERSION=2.12.1 +VERSION=2.13.3 # Clean and create library directory, then extract FreeType source echo "Cleaning and creating library directory, then extracting FreeType source..." diff --git a/buildSrc/src/main/groovy/tool/generator/GenerateLibs.groovy b/buildSrc/src/main/groovy/tool/generator/GenerateLibs.groovy index 1a2a5c2..398baa7 100644 --- a/buildSrc/src/main/groovy/tool/generator/GenerateLibs.groovy +++ b/buildSrc/src/main/groovy/tool/generator/GenerateLibs.groovy @@ -85,7 +85,15 @@ class GenerateLibs extends DefaultTask { spec.from(project.rootProject.file('include/imgui/misc/freetype')) { CopySpec it -> it.include('*.h', '*.cpp') } spec.into("$jniDir/misc/freetype") } - enableDefine('IMGUI_ENABLE_FREETYPE') + + // Since we give a possibility to build library without enabled freetype - define should be set like that. + replaceSourceFileContent("imconfig.h", "//#define IMGUI_ENABLE_FREETYPE", "#define IMGUI_ENABLE_FREETYPE") + + // Binding specific behavior to handle FreeType. + // By defining IMGUI_ENABLE_FREETYPE, Dear ImGui will default to using the FreeType font renderer. + // However, we modify the source code to ensure that, even with this, the STB_TrueType renderer is used instead. + // To use the FreeType font renderer, it must be explicitly forced on the atlas manually. + replaceSourceFileContent("imgui_draw.cpp", "ImGuiFreeType::GetBuilderForFreeType()", "ImFontAtlasGetBuilderForStbTruetype()") } // Copy dirent for ImGuiFileDialog @@ -181,7 +189,13 @@ class GenerateLibs extends DefaultTask { target.libraries += ' -lfreetype' } - void enableDefine(String define) { - new File("$jniDir/imconfig.h").text += "#define $define" + void replaceSourceFileContent(String fileName, String replaceWhat, String replaceWith) { + def sourceFile = new File("$jniDir/$fileName") + def sourceTxt = sourceFile.text + def sourceTxtModified = sourceTxt.replace(replaceWhat, replaceWith) + if (sourceTxt == sourceTxtModified) { + throw new IllegalStateException("Unable to replace [$fileName] with content [$replaceWith]!") + } + sourceFile.text = sourceTxtModified } } diff --git a/buildSrc/src/main/kotlin/tool/generator/ast/task/GenerateAst.kt b/buildSrc/src/main/kotlin/tool/generator/ast/task/GenerateAst.kt index 6dcb0d9..e1f98ed 100644 --- a/buildSrc/src/main/kotlin/tool/generator/ast/task/GenerateAst.kt +++ b/buildSrc/src/main/kotlin/tool/generator/ast/task/GenerateAst.kt @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.SerializationFeature import com.lordcodes.turtle.shellRun import org.gradle.api.DefaultTask +import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction @@ -23,6 +24,8 @@ open class GenerateAst : DefaultTask() { @InputFiles lateinit var headerFiles: Collection + @Input + var defines: Set = emptySet() private val dstDir: File = File("${project.rootDir}/buildSrc/src/main/resources/${AstParser.RESOURCE_PATH}") private val objectMapper: ObjectMapper = ObjectMapper() @@ -403,9 +406,21 @@ open class GenerateAst : DefaultTask() { } private fun callClangAstBump(scriptPath: String, srcHeader: File, dstJson: File) { + fun buildCommand(): List { + val command = mutableListOf( + scriptPath, + srcHeader.absolutePath, + dstJson.absolutePath, + ) + if (defines.isNotEmpty()) { + command += defines.map { "-D$it" } + } + return command + } + dstJson.delete() val pb = ProcessBuilder() - pb.command(scriptPath, srcHeader.absolutePath, dstJson.absolutePath) + pb.command(buildCommand()) pb.start().waitFor() } diff --git a/buildSrc/src/main/resources/generator/api/ast/_gen_ast.sh b/buildSrc/src/main/resources/generator/api/ast/_gen_ast.sh index bca5dda..75eae06 100755 --- a/buildSrc/src/main/resources/generator/api/ast/_gen_ast.sh +++ b/buildSrc/src/main/resources/generator/api/ast/_gen_ast.sh @@ -4,4 +4,22 @@ # Java ProcessBuilder doesn't see command properly. # Also, running like that helps to ignore local clang++ warnings which can happen. -clang++ -Xclang -ast-dump=json -fsyntax-only -fparse-all-comments -fmerge-all-constants "$1" >> "$2" +# Assign the first argument to 'input_file' (the C++ file to analyze). +input_file="$1" + +# Assign the second argument to 'output_file' (where to save the AST JSON). +output_file="$2" + +# 'shift 2' shifts the positional parameters to the left by two positions. +# This means "$@" will now contain any additional arguments (like macro definitions). +shift 2 + +# Run clang++ with the specified options. +# -Xclang -ast-dump=json: Dumps the AST in JSON format. +# -fsyntax-only: Only checks the syntax, does not compile. +# -fparse-all-comments: Includes comments in the AST. +# -fmerge-all-constants: Merges identical constants. +# "$@" passes any additional arguments (like -D for macro definitions). +# "$input_file" is the C++ source file to process. +# The output is redirected and appended to the specified output file. +clang++ -Xclang -ast-dump=json -fsyntax-only -fparse-all-comments -fmerge-all-constants "$@" "$input_file" >> "$output_file" diff --git a/buildSrc/src/main/resources/generator/api/ast/ast-imgui_freetype.json b/buildSrc/src/main/resources/generator/api/ast/ast-imgui_freetype.json new file mode 100644 index 0000000..ec5d1e5 --- /dev/null +++ b/buildSrc/src/main/resources/generator/api/ast/ast-imgui_freetype.json @@ -0,0 +1,186 @@ +{ + "info" : { + "source" : "include/imgui/misc/freetype/imgui_freetype.h", + "hash" : "5976473c3ad2fbe2f0386eaa9019d4e0", + "url" : "https://github.com/ocornut/imgui", + "revision" : "1ee252772ae9c0a971d06257bb5c89f628fa696a" + }, + "decls" : [ { + "@type" : "AstRecordDecl", + "name" : "ImFontAtlas", + "decls" : [ { + "@type" : "AstFullComment", + "decls" : [ { + "@type" : "AstParagraphComment", + "decls" : [ { + "@type" : "AstTextComment", + "text" : " Forward declarations" + } ] + } ] + } ] + }, { + "@type" : "AstEnumDecl", + "name" : "ImGuiFreeTypeBuilderFlags", + "decls" : [ { + "@type" : "AstFullComment", + "decls" : [ { + "@type" : "AstParagraphComment", + "decls" : [ { + "@type" : "AstTextComment", + "text" : " Hinting greatly impacts visuals (and glyph sizes)." + }, { + "@type" : "AstTextComment", + "text" : " - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter." + }, { + "@type" : "AstTextComment", + "text" : " - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h" + }, { + "@type" : "AstTextComment", + "text" : " - The Default hinting mode usually looks good, but may distort glyphs in an unusual way." + }, { + "@type" : "AstTextComment", + "text" : " - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer." + }, { + "@type" : "AstTextComment", + "text" : " You can set those flags globaly in ImFontAtlas::FontBuilderFlags" + }, { + "@type" : "AstTextComment", + "text" : " You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags" + } ] + } ] + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_NoHinting", + "docComment" : "Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 0, + "value" : "1 << 0", + "evaluatedValue" : 1 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_NoAutoHint", + "docComment" : "Disable auto-hinter.", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 1, + "value" : "1 << 1", + "evaluatedValue" : 2 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_ForceAutoHint", + "docComment" : "Indicates that the auto-hinter is preferred over the font's native hinter.", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 2, + "value" : "1 << 2", + "evaluatedValue" : 4 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_LightHinting", + "docComment" : "A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text.", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 3, + "value" : "1 << 3", + "evaluatedValue" : 8 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_MonoHinting", + "docComment" : "Strong hinting algorithm that should only be used for monochrome output.", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 4, + "value" : "1 << 4", + "evaluatedValue" : 16 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_Bold", + "docComment" : "Styling: Should we artificially embolden the font?", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 5, + "value" : "1 << 5", + "evaluatedValue" : 32 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_Oblique", + "docComment" : "Styling: Should we slant the font, emulating italic style?", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 6, + "value" : "1 << 6", + "evaluatedValue" : 64 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_Monochrome", + "docComment" : "Disable anti-aliasing. Combine this with MonoHinting for best results!", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 7, + "value" : "1 << 7", + "evaluatedValue" : 128 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_LoadColor", + "docComment" : "Enable FreeType color-layered glyphs", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 8, + "value" : "1 << 8", + "evaluatedValue" : 256 + }, { + "@type" : "AstEnumConstantDecl", + "name" : "ImGuiFreeTypeBuilderFlags_Bitmap", + "docComment" : "Enable FreeType bitmap glyphs", + "qualType" : "ImGuiFreeTypeBuilderFlags", + "order" : 9, + "value" : "1 << 9", + "evaluatedValue" : 512 + } ] + }, { + "@type" : "AstNamespaceDecl", + "name" : "ImGuiFreeType", + "decls" : [ { + "@type" : "AstFunctionDecl", + "name" : "SetAllocatorFunctions", + "resultType" : "int", + "decls" : [ { + "@type" : "AstParmVarDecl", + "name" : "alloc_func", + "qualType" : "void *(*)(int, void *)", + "desugaredQualType" : "void *(*)(int, void *)" + }, { + "@type" : "AstParmVarDecl", + "name" : "free_func", + "qualType" : "void (*)(void *, void *)", + "desugaredQualType" : "void (*)(void *, void *)" + }, { + "@type" : "AstParmVarDecl", + "name" : "user_data", + "qualType" : "void *", + "desugaredQualType" : "void *", + "defaultValue" : "=" + }, { + "@type" : "AstFullComment", + "decls" : [ { + "@type" : "AstParagraphComment", + "decls" : [ { + "@type" : "AstTextComment", + "text" : " Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()" + }, { + "@type" : "AstTextComment", + "text" : " However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired." + } ] + } ] + } ] + }, { + "@type" : "AstFunctionDecl", + "name" : "BuildFontAtlas", + "resultType" : "bool", + "decls" : [ { + "@type" : "AstParmVarDecl", + "name" : "atlas", + "qualType" : "ImFontAtlas *", + "desugaredQualType" : "ImFontAtlas *" + }, { + "@type" : "AstParmVarDecl", + "name" : "flags", + "qualType" : "unsigned int", + "desugaredQualType" : "unsigned int", + "defaultValue" : "0" + } ] + } ] + } ] +} \ No newline at end of file diff --git a/example/src/main/java/Main.java b/example/src/main/java/Main.java index d70f5a8..fd82506 100644 --- a/example/src/main/java/Main.java +++ b/example/src/main/java/Main.java @@ -43,7 +43,11 @@ public class Main extends Application { * For more information read: https://github.com/ocornut/imgui/blob/33cdbe97b8fd233c6c12ca216e76398c2e89b0d8/docs/FONTS.md */ private void initFonts(final ImGuiIO io) { - io.getFonts().addFontDefault(); // Add default font for latin glyphs + // This enables FreeType font renderer, which is disabled by default. + io.getFonts().setFreeTypeRenderer(true); + + // Add default font for latin glyphs + io.getFonts().addFontDefault(); // You can use the ImFontGlyphRangesBuilder helper to create glyph ranges based on text input. // For example: for a game where your script is known, if you can feed your entire script to it (using addText) and only build the characters the game needs. diff --git a/imgui-binding/src/generated/java/imgui/ImFontAtlas.java b/imgui-binding/src/generated/java/imgui/ImFontAtlas.java index f42e63a..e7036fa 100644 --- a/imgui-binding/src/generated/java/imgui/ImFontAtlas.java +++ b/imgui-binding/src/generated/java/imgui/ImFontAtlas.java @@ -460,6 +460,32 @@ public final class ImFontAtlas extends ImGuiStructDestroyable { // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste. + /*JNI + #ifdef IMGUI_ENABLE_FREETYPE + #include "misc/freetype/imgui_freetype.h" + #endif + */ + + /** + * BINDING NOTICE: This method is specific to the imgui-java binding. + *

+ * Since FreeType is included in the final build, it's possible to use both font renderers (STB_TrueType and FreeType) simultaneously without needing to rebuild the library. + * By default, we use small hacks to set STB_TrueType as the default font renderer. However, this method allows you to enforce the use of the FreeType renderer. + *

+ * This method MUST be called before invoking the "#build" or "#getTexData*" methods. + * + * @param enabled true to enable the FreeType font renderer + */ + public native void setFreeTypeRenderer(boolean enabled); /* + #ifdef IMGUI_ENABLE_FREETYPE + if (enabled) { + THIS->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType(); + } else { + THIS->FontBuilderIO = NULL; + } + #endif + */ + /** * Build pixels data. This is called automatically for you by the GetTexData*** functions. */ diff --git a/imgui-binding/src/generated/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java b/imgui-binding/src/generated/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java index 8417d73..cd824e7 100644 --- a/imgui-binding/src/generated/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java +++ b/imgui-binding/src/generated/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java @@ -5,5 +5,73 @@ public final class ImGuiFreeTypeBuilderFlags { private ImGuiFreeTypeBuilderFlags() { } + /** + * Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. + * + *

Definition: {@code 1 << 0} + */ + public static final int NoHinting = 1; + /** + * Disable auto-hinter. + * + *

Definition: {@code 1 << 1} + */ + public static final int NoAutoHint = 2; + + /** + * Indicates that the auto-hinter is preferred over the font's native hinter. + * + *

Definition: {@code 1 << 2} + */ + public static final int ForceAutoHint = 4; + + /** + * A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. + * + *

Definition: {@code 1 << 3} + */ + public static final int LightHinting = 8; + + /** + * Strong hinting algorithm that should only be used for monochrome output. + * + *

Definition: {@code 1 << 4} + */ + public static final int MonoHinting = 16; + + /** + * Styling: Should we artificially embolden the font? + * + *

Definition: {@code 1 << 5} + */ + public static final int Bold = 32; + + /** + * Styling: Should we slant the font, emulating italic style? + * + *

Definition: {@code 1 << 6} + */ + public static final int Oblique = 64; + + /** + * Disable anti-aliasing. Combine this with MonoHinting for best results! + * + *

Definition: {@code 1 << 7} + */ + public static final int Monochrome = 128; + + /** + * Enable FreeType color-layered glyphs + * + *

Definition: {@code 1 << 8} + */ + public static final int LoadColor = 256; + + /** + * Enable FreeType bitmap glyphs + * + *

Definition: {@code 1 << 9} + */ + public static final int Bitmap = 512; } diff --git a/imgui-binding/src/main/java/imgui/ImFontAtlas.java b/imgui-binding/src/main/java/imgui/ImFontAtlas.java index 590e1a2..254f20d 100644 --- a/imgui-binding/src/main/java/imgui/ImFontAtlas.java +++ b/imgui-binding/src/main/java/imgui/ImFontAtlas.java @@ -137,6 +137,32 @@ public final class ImFontAtlas extends ImGuiStructDestroyable { // Building in RGBA32 format is provided for convenience and compatibility, but note that unless you manually manipulate or copy color data into // the texture (e.g. when using the AddCustomRect*** api), then the RGB pixels emitted will always be white (~75% of memory/bandwidth waste. + /*JNI + #ifdef IMGUI_ENABLE_FREETYPE + #include "misc/freetype/imgui_freetype.h" + #endif + */ + + /** + * BINDING NOTICE: This method is specific to the imgui-java binding. + *

+ * Since FreeType is included in the final build, it's possible to use both font renderers (STB_TrueType and FreeType) simultaneously without needing to rebuild the library. + * By default, we use small hacks to set STB_TrueType as the default font renderer. However, this method allows you to enforce the use of the FreeType renderer. + *

+ * This method MUST be called before invoking the "#build" or "#getTexData*" methods. + * + * @param enabled true to enable the FreeType font renderer + */ + public native void setFreeTypeRenderer(boolean enabled); /* + #ifdef IMGUI_ENABLE_FREETYPE + if (enabled) { + THIS->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType(); + } else { + THIS->FontBuilderIO = NULL; + } + #endif + */ + /** * Build pixels data. This is called automatically for you by the GetTexData*** functions. */ diff --git a/imgui-binding/src/main/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java b/imgui-binding/src/main/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java index b4f6c94..45e0748 100644 --- a/imgui-binding/src/main/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java +++ b/imgui-binding/src/main/java/imgui/flag/ImGuiFreeTypeBuilderFlags.java @@ -8,6 +8,6 @@ public final class ImGuiFreeTypeBuilderFlags { private ImGuiFreeTypeBuilderFlags() { } - @BindingAstEnum(file = "ast-imgui.json", qualType = "ImGuiFreeTypeBuilderFlags_") + @BindingAstEnum(file = "ast-imgui_freetype.json", qualType = "ImGuiFreeTypeBuilderFlags", sanitizeName = "ImGuiFreeTypeBuilderFlags_") public Void __; } diff --git a/imgui-binding/src/main/native/imconfig.h b/imgui-binding/src/main/native/imconfig.h index 35adb4a..c18c07d 100644 --- a/imgui-binding/src/main/native/imconfig.h +++ b/imgui-binding/src/main/native/imconfig.h @@ -13,6 +13,7 @@ //----------------------------------------------------------------------------- #pragma once + #include "jni_assertion.h" //---- Define assertion handler. Defaults to calling assert(). @@ -30,6 +31,7 @@ //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names. #define IMGUI_DISABLE_OBSOLETE_FUNCTIONS +//#define IMGUI_DISABLE_OBSOLETE_KEYIO // 1.87: disable legacy io.KeyMap[]+io.KeysDown[] in favor io.AddKeyEvent(). This will be folded into IMGUI_DISABLE_OBSOLETE_FUNCTIONS in a few versions. //---- Disable all of Dear ImGui or don't implement standard windows. // It is very strongly recommended to NOT disable the demo windows during development. Please read comments in imgui_demo.cpp. @@ -77,7 +79,7 @@ //---- Use stb_truetype to build and rasterize the font atlas (default) // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. -//#define IMGUI_ENABLE_STB_TRUETYPE +#define IMGUI_ENABLE_STB_TRUETYPE //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. diff --git a/vendor/freetype-2.12.1.tar.gz b/vendor/freetype-2.12.1.tar.gz deleted file mode 100644 index 0d1b56d..0000000 Binary files a/vendor/freetype-2.12.1.tar.gz and /dev/null differ diff --git a/vendor/freetype-2.13.3.tar.gz b/vendor/freetype-2.13.3.tar.gz new file mode 100644 index 0000000..93cb7fb Binary files /dev/null and b/vendor/freetype-2.13.3.tar.gz differ