[fonts] Initial fonts support commit

This commit is contained in:
SpaiR committed 2020-02-10 22:02:44 +03:00
1 parent 1a5365d14a
commit f16672b80a
10 files changed
+491 -69

No files matched your search

@@ -0,0 +1,9 @@
package imgui;
/**
* While implementing this interface, class could be manually destroyed (free allocated memory on the JNI side).
* Read javadoc and "BINDING NOTICE" for specific cases.
*/
interface ImDestroyable {
void destroy();
}
@@ -6,6 +6,7 @@ import java.nio.ByteOrder;
/**
* All draw data to render a Dear ImGui frame.
* <p>
* BINDING NOTICE: DO NOT TRY TO MODIFY FIELDS OF THIS CLASS MANUALLY! You should only access their values after {@link ImGui#render()} call.
*/
public final class ImDrawData {
@@ -0,0 +1,142 @@
package imgui;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Load and rasterize multiple TTF/OTF fonts into a same texture. The font atlas will build a single texture holding:
* - One or more fonts.
* - Custom graphics data needed to render the shapes needed by Dear ImGui.
* - Mouse cursor shapes for software cursor rendering (unless setting 'Flags |= ImFontAtlasFlags_NoMouseCursors' in the font atlas).
* It is the user-code responsibility to setup/build the atlas, then upload the pixel data into a texture accessible by your graphics api.
* - Optionally, call any of the AddFont*** functions. If you don't call any, the default font embedded in the code will be loaded for you.
* - Call GetTexDataAsAlpha8() or GetTexDataAsRGBA32() to build and retrieve pixels data.
* - Upload the pixels data into a texture within your graphics system (see imgui_impl_xxxx.cpp examples)
* - Call SetTexID(my_tex_id); and pass the pointer/identifier to your texture in a format natural to your graphics API.
* This value will be passed back to you during rendering to identify the texture. Read FAQ entry about ImTextureID for more details.
* Common pitfalls:
* - If you pass a 'glyph_ranges' array to AddFont*** functions, you need to make sure that your array persist up until the
* atlas is build (when calling GetTexData*** or Build()). We only copy the pointer, not the data.
* - Important: By default, AddFontFromMemoryTTF() takes ownership of the data. Even though we are not writing to it, we will free the pointer on destruction.
* You can set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed,
* - Even though many functions are suffixed with "TTF", OTF data is supported just as well.
* - This is an old API and it is currently awkward for those and and various other reasons! We will address them in the future!
*/
public final class ImFontAtlas implements ImDestroyable {
final long ptr;
/**
* This class will create a native structure.
* Call {@link #destroy()} method to manually free used memory.
*/
public ImFontAtlas() {
ImGui.touch();
ptr = nCreate();
}
ImFontAtlas(final long ptr) {
this.ptr = ptr;
}
@Override
public void destroy() {
nDestroy(ptr);
}
/*JNI
#include <imgui.h>
jfieldID imFontAtlasPtrID;
#define IM_FONT_ATLAS ((ImFontAtlas*)env->GetLongField(object, imFontAtlasPtrID))
*/
static native void nInit(); /*
jclass jImFontAtlasClass = env->FindClass("imgui/ImFontAtlas");
imFontAtlasPtrID = env->GetFieldID(jImFontAtlasClass, "ptr", "J");
*/
private native long nCreate(); /*
ImFontAtlas* imFontAtlas = new ImFontAtlas();
return (long)imFontAtlas;
*/
private native void nDestroy(long ptr); /*
delete (ImFontAtlas*)ptr;
*/
// Build atlas, retrieve pixel data.
// User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID().
// The pitch is always = Width * BytesPerPixels (1 or 4)
// 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.
/**
* Build pixels data. This is called automatically for you by the GetTexData*** functions.
*/
public native boolean build(); /*
return IM_FONT_ATLAS->Build();
*/
/**
* 1 byte-per-pixel
*/
public ByteBuffer getTexDataAsAlpha8(final ImInt outWidth, final ImInt outHeight) {
return getTexDataAsAlpha8(outWidth, outHeight, new ImInt());
}
/**
* 1 byte-per-pixel
*/
public ByteBuffer getTexDataAsAlpha8(final ImInt outWidth, final ImInt outHeight, final ImInt outBytesPerPixel) {
final byte[] tmpBuff = getTexDataAsAlpha8(outWidth.data, outHeight.data, outBytesPerPixel.data);
final ByteBuffer buffer = ByteBuffer.allocateDirect(tmpBuff.length).order(ByteOrder.nativeOrder());
buffer.put(tmpBuff);
buffer.flip();
return buffer;
}
private native byte[] getTexDataAsAlpha8(int[] outWidth, int[] outHeight, int[] outBytesPerPixel); /*
unsigned char* pixels;
IM_FONT_ATLAS->GetTexDataAsAlpha8(&pixels, &outWidth[0], &outHeight[0], &outBytesPerPixel[0]);
int size = outWidth[0] * outHeight[0] * outBytesPerPixel[0];
jbyteArray jBytes = env->NewByteArray(size);
env->SetByteArrayRegion(jBytes, 0, size, (jbyte*)pixels);
return jBytes;
*/
/**
* 4 bytes-per-pixel
*/
public ByteBuffer getTexDataAsRGBA32(final ImInt outWidth, final ImInt outHeight) {
return getTexDataAsRGBA32(outWidth, outHeight, new ImInt());
}
/**
* 4 bytes-per-pixel
*/
public ByteBuffer getTexDataAsRGBA32(final ImInt outWidth, final ImInt outHeight, final ImInt outBytesPerPixel) {
final byte[] tmpBuff = nGetTexDataAsRGBA32(outWidth.data, outHeight.data, outBytesPerPixel.data);
final ByteBuffer buffer = ByteBuffer.allocateDirect(tmpBuff.length).order(ByteOrder.nativeOrder());
buffer.put(tmpBuff);
buffer.flip();
return buffer;
}
private native byte[] nGetTexDataAsRGBA32(int[] outWidth, int[] outHeight, int[] outBytesPerPixel); /*
unsigned char* pixels;
IM_FONT_ATLAS->GetTexDataAsRGBA32(&pixels, &outWidth[0], &outHeight[0], &outBytesPerPixel[0]);
int size = outWidth[0] * outHeight[0] * outBytesPerPixel[0];
jbyteArray jBytes = env->NewByteArray(size);
env->SetByteArrayRegion(jBytes, 0, size, (jbyte*)pixels);
return jBytes;
*/
public native boolean isBuilt(); /*
return IM_FONT_ATLAS->IsBuilt();
*/
public native void setTexID(int imTextureId); /*
IM_FONT_ATLAS->SetTexID((ImTextureID)imTextureId);
*/
}
@@ -0,0 +1,273 @@
package imgui;
public final class ImFontConfig implements ImDestroyable {
final long ptr;
private short[] glyphRanges;
/**
* This class will create a native structure.
* Call {@link #destroy()} method to manually free used memory.
*/
public ImFontConfig() {
ImGui.touch();
ptr = nCreate();
}
ImFontConfig(final long ptr) {
this.ptr = ptr;
}
@Override
public void destroy() {
nDestroy(ptr);
}
/*JNI
#include <imgui.h>
#include "jni_common.h"
jfieldID imFontConfigPtrID;
#define IM_FONT_CONFIG ((ImFontConfig*)env->GetLongField(object, imFontConfigPtrID))
*/
static native void nInit(); /*
jclass jImFontConfigClass = env->FindClass("imgui/ImFontConfig");
imFontConfigPtrID = env->GetFieldID(jImFontConfigClass, "ptr", "J");
*/
private native long nCreate(); /*
ImFontConfig* imFontConfig = new ImFontConfig();
return (long)imFontConfig;
*/
private native void nDestroy(long ptr); /*
delete (ImFontConfig*)ptr;
*/
/**
* TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
*/
public native boolean getFontDataOwnedByAtlas(); /*
return IM_FONT_CONFIG->FontDataOwnedByAtlas;
*/
/**
* TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself).
*/
public native void setFontDataOwnedByAtlas(boolean isFontDataOwnedByAtlas); /*
IM_FONT_CONFIG->FontDataOwnedByAtlas = isFontDataOwnedByAtlas;
*/
/**
* Index of font within TTF/OTF file
*/
public native int getFontNo(); /*
return IM_FONT_CONFIG->FontNo;
*/
/**
* Index of font within TTF/OTF file
*/
public native void setFontNo(int fontNo); /*
IM_FONT_CONFIG->FontNo = fontNo;
*/
/**
* Size in pixels for rasterizer (more or less maps to the resulting font height).
*/
public native float getSizePixels(); /*
return IM_FONT_CONFIG->SizePixels;
*/
/**
* Size in pixels for rasterizer (more or less maps to the resulting font height).
*/
public native void setSizePixels(float sizePixels); /*
IM_FONT_CONFIG->SizePixels = sizePixels;
*/
/**
* Rasterize at higher quality for sub-pixel positioning.
* Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
*/
public native int getOversampleH(); /*
return IM_FONT_CONFIG->OversampleH;
*/
/**
* Rasterize at higher quality for sub-pixel positioning.
* Read https://github.com/nothings/stb/blob/master/tests/oversample/README.md for details.
*/
public native void setOversampleH(int oversampleH); /*
IM_FONT_CONFIG->OversampleH = oversampleH;
*/
/**
* Rasterize at higher quality for sub-pixel positioning.
* We don't use sub-pixel positions on the Y axis.
*/
public native int getOversampleV(); /*
return IM_FONT_CONFIG->OversampleV;
*/
/**
* Rasterize at higher quality for sub-pixel positioning.
* We don't use sub-pixel positions on the Y axis.
*/
public native void setOversampleV(int oversampleV); /*
IM_FONT_CONFIG->OversampleV = oversampleV;
*/
/**
* Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font.
* If enabled, you can set OversampleH/V to 1.
*/
public native boolean getPixelSnapH(); /*
return IM_FONT_CONFIG->PixelSnapH;
*/
/**
* Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font.
* If enabled, you can set OversampleH/V to 1.
*/
public native void setPixelSnapH(boolean isPixelSnapH); /*
IM_FONT_CONFIG->PixelSnapH = isPixelSnapH;
*/
/**
* Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
*/
public native void getGlyphExtraSpacing(ImVec2 dstImVec2); /*
Jni::ImVec2Cpy(env, &IM_FONT_CONFIG->GlyphExtraSpacing, dstImVec2);
*/
/**
* Extra spacing (in pixels) between glyphs. Only X axis is supported for now.
*/
public native void setGlyphExtraSpacing(float x, float y); /*
IM_FONT_CONFIG->GlyphExtraSpacing.x = x;
IM_FONT_CONFIG->GlyphExtraSpacing.y = y;
*/
/**
* Offset all glyphs from this font input.
*/
public native void getGlyphOffset(ImVec2 dstImVec2); /*
Jni::ImVec2Cpy(env, &IM_FONT_CONFIG->GlyphOffset, dstImVec2);
*/
/**
* Offset all glyphs from this font input.
*/
public native void setGlyphOffset(float x, float y); /*
IM_FONT_CONFIG->GlyphOffset.x = x;
IM_FONT_CONFIG->GlyphOffset.y = y;
*/
/**
* Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
* THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
*/
public short[] getGlyphRanges() {
return glyphRanges;
}
/**
* Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list).
* THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE.
*/
public void setGlyphRanges(final short[] glyphRanges) {
this.glyphRanges = glyphRanges;
nSetGlyphRanges(glyphRanges);
}
private native void nSetGlyphRanges(short[] glyphRanges); /*
IM_FONT_CONFIG->GlyphRanges = glyphRanges != NULL ? (ImWchar*)&glyphRanges[0] : NULL;
*/
/**
* Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
*/
public native float getGlyphMinAdvanceX(); /*
return IM_FONT_CONFIG->GlyphMinAdvanceX;
*/
/**
* Minimum AdvanceX for glyphs, set Min to align font icons, set both Min/Max to enforce mono-space font
*/
public native void setGlyphMinAdvanceX(float glyphMinAdvanceX); /*
IM_FONT_CONFIG->GlyphMinAdvanceX = glyphMinAdvanceX;
*/
/**
* Maximum AdvanceX for glyphs
*/
public native float getGlyphMaxAdvanceX(); /*
return IM_FONT_CONFIG->GlyphMaxAdvanceX;
*/
/**
* Maximum AdvanceX for glyphs
*/
public native void setGlyphMaxAdvanceX(float glyphMaxAdvanceX); /*
IM_FONT_CONFIG->GlyphMaxAdvanceX = glyphMaxAdvanceX;
*/
/**
* Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
*/
public native boolean getMergeMode(); /*
return IM_FONT_CONFIG->MergeMode;
*/
/**
* Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights.
*/
public native void setMergeMode(boolean mergeMode); /*
IM_FONT_CONFIG->MergeMode = mergeMode;
*/
/**
* Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.
*/
public native int getRasterizerFlags(); /*
return IM_FONT_CONFIG->RasterizerFlags;
*/
/**
* Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one.
*/
public native void setRasterizerFlags(int rasterizerFlags); /*
IM_FONT_CONFIG->RasterizerFlags = (unsigned int)rasterizerFlags;
*/
/**
* Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
*/
public native float getRasterizerMultiply(); /*
return IM_FONT_CONFIG->RasterizerMultiply;
*/
/**
* Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
*/
public native void setRasterizerMultiply(float rasterizerMultiply); /*
IM_FONT_CONFIG->RasterizerMultiply = rasterizerMultiply;
*/
/**
* Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
*/
public native short getEllipsisChar(); /*
return (short)IM_FONT_CONFIG->EllipsisChar;
*/
/**
* Explicitly specify unicode codepoint of ellipsis character. When fonts are being merged first specified ellipsis will be used.
*/
public native void setEllipsisChar(short ellipsisChar); /*
IM_FONT_CONFIG->EllipsisChar = (ImWchar)ellipsisChar;
*/
}
+19 -3
View File
@@ -17,9 +17,9 @@ public final class ImGui {
private static final String LIB_NAME_DEFAULT = System.getProperty("os.arch").contains("64") ? "imgui-java64" : "imgui-java";
private static final String LIB_TMP_DIR_PREFIX = "imgui-java-bin_" + System.getProperty("user.name", "user");
private static final ImDrawData DRAW_DATA = new ImDrawData(100_000, 100_000, 1000);
private static final ImGuiIO IMGUI_IO = new ImGuiIO();
private static final ImGuiStyle IMGUI_STYLE = new ImGuiStyle();
private static final ImDrawData DRAW_DATA;
private static final ImGuiIO IMGUI_IO;
private static final ImGuiStyle IMGUI_STYLE;
private static final ImDrawList IM_DRAW_LIST_WINDOW = new ImDrawList(ImDrawList.TYPE_WINDOW);
private static final ImDrawList IM_DRAW_LIST_BACKGROUND = new ImDrawList(ImDrawList.TYPE_BACKGROUND);
@@ -40,9 +40,15 @@ public final class ImGui {
System.loadLibrary(libName);
}
DRAW_DATA = new ImDrawData(100_000, 100_000, 1000);
IMGUI_IO = new ImGuiIO();
IMGUI_STYLE = new ImGuiStyle();
nInitJni();
ImDrawList.nInit();
ImDrawData.nInit();
ImFontAtlas.nInit();
ImFontConfig.nInit();
nInitInputTextData();
}
@@ -81,6 +87,14 @@ public final class ImGui {
}
}
/**
* For internal usage.
* Method is used to initiate static instantiation (loading of the native libraries etc.).
* Otherwise native libraries will be loaded on demand and natively mapped objects won't work.
*/
static void touch() {
}
private ImGui() {
}
@@ -854,6 +868,7 @@ public final class ImGui {
/**
* Retrieve given color with style alpha applied
* <p>
* BINDING NOTICE: Since {@link #getColorU32(int)} has the same signature, this specific method has an 'i' suffix.
*/
public static native int getColorU32i(int col); /*
@@ -1196,6 +1211,7 @@ public final class ImGui {
/**
* Formatted text
* <p>
* BINDING NOTICE: Since all text formatting could be done on Java side, this call is equal to {@link ImGui#textUnformatted(String)}.
*/
public static native void text(String text); /*
+32 -7
View File
@@ -8,6 +8,8 @@ import imgui.callbacks.ImStrSupplier;
* Access via ImGui::GetIO(). Read 'Programmer guide' section in .cpp file for general usage.
*/
public final class ImGuiIO {
private ImFontAtlas imFontAtlas;
ImGuiIO() {
}
@@ -17,6 +19,10 @@ public final class ImGuiIO {
#include "jni_callbacks.h"
*/
private native long nGetFontsPtr(); /*
return (long)ImGui::GetIO().Fonts;
*/
//------------------------------------------------------------------
// Configuration (fill once)
//------------------------------------------------------------------
@@ -152,12 +158,32 @@ public final class ImGuiIO {
ImGui::GetIO().KeyRepeatRate = keyRepeatRate;
*/
// TODO fonts configuration
/**
* Font atlas: load, rasterize and pack one or more fonts into a single texture.
*/
public ImFontAtlas getFonts() {
// on demand instantiation
// will throw native exception if Dear ImGui context isn't created (like in the original library)
if (imFontAtlas == null) {
imFontAtlas = new ImFontAtlas(nGetFontsPtr());
}
return imFontAtlas;
}
// BINDING NOTICE: this is a stub to pass important for ImGui info
public native void setFontsTexID(int id); /*
ImGui::GetIO().Fonts->TexID = (ImTextureID)id;
*/
/**
* Font atlas: load, rasterize and pack one or more fonts into a single texture.
* <p>
* BINDING NOTICE: You should manually destroy previously used ImFontAtlas:
* <pre>
* io.getFonts().destroy();
* io.setFonts(newImFontAtlas);
* </pre>
*/
public void setFonts(final ImFontAtlas imFontAtlas) {
this.imFontAtlas = imFontAtlas;
}
// TODO fonts configuration
// Miscellaneous options
@@ -626,8 +652,7 @@ public final class ImGuiIO {
* Queue new character input.
*/
public native void addInputCharacter(int c); /*
if (c > 0 && c < 0x10000)
ImGui::GetIO().AddInputCharacter((unsigned short)c);
ImGui::GetIO().AddInputCharacter((unsigned int)c);
*/
/**
@@ -1,48 +0,0 @@
package imgui;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public final class TexDataRGBA32 {
public int width;
public int height;
public ByteBuffer pixelBuffer;
private TexDataRGBA32() {
final int pixelMax = 131072;
pixelBuffer = ByteBuffer.allocateDirect(pixelMax).order(ByteOrder.nativeOrder());
}
public static TexDataRGBA32 create() {
final TexDataRGBA32 data = new TexDataRGBA32();
data.nFillData(data.pixelBuffer);
return data;
}
/*JNI
#include <imgui.h>
*/
private native void nFillData(Buffer pixelBuf); /*
jclass jTexDataClass = env->GetObjectClass(object);
if(jTexDataClass == NULL)
return;
jfieldID widthID = env->GetFieldID(jTexDataClass, "width", "I");
jfieldID heightID = env->GetFieldID(jTexDataClass, "height", "I");
unsigned char* pixels;
int width, height;
ImGuiIO& io = ImGui::GetIO();
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
env->SetIntField(object, widthID, width);
env->SetIntField(object, heightID, height);
memcpy(pixelBuf, pixels, width * height * 4);
*/
}