Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • engelerp/framebuffer-testing
1 result
Show changes
Showing
with 16733 additions and 2 deletions
File added
File added
File added
File added
File added
// dear imgui
// (binary_to_compressed_c.cpp)
// Helper tool to turn a file into a C array, if you want to embed font data in your source code.
// The data is first compressed with stb_compress() to reduce source code size,
// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex)
// (If we used 32-bit constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent)
// Note that even with compression, the output array is likely to be bigger than the binary file..
// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF()
// Build with, e.g:
// # cl.exe binary_to_compressed_c.cpp
// # gcc binary_to_compressed_c.cpp
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
// Usage:
// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname>
// Usage example:
// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
// stb_compress* from stb.h - declaration
typedef unsigned int stb_uint;
typedef unsigned char stb_uchar;
stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len);
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression);
int main(int argc, char** argv)
{
if (argc < 3)
{
printf("Syntax: %s [-base85] [-nocompress] <inputfile> <symbolname>\n", argv[0]);
return 0;
}
int argn = 1;
bool use_base85_encoding = false;
bool use_compression = true;
if (argv[argn][0] == '-')
{
if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
else
{
fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
return 1;
}
}
bool ret = binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression);
if (!ret)
fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
return ret ? 0 : 1;
}
char Encode85Byte(unsigned int x)
{
x = (x % 85) + 35;
return (x>='\\') ? x+1 : x;
}
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression)
{
// Read file
FILE* f = fopen(filename, "rb");
if (!f) return false;
int data_sz;
if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; }
char* data = new char[data_sz+4];
if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; }
memset((void*)(((char*)data) + data_sz), 0, 4);
fclose(f);
// Compress
int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess
char* compressed = use_compression ? new char[maxlen] : data;
int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz;
if (use_compression)
memset(compressed + compressed_sz, 0, maxlen - compressed_sz);
// Output as Base85 encoded
FILE* out = stdout;
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
const char* compressed_str = use_compression ? "compressed_" : "";
if (use_base85_encoding)
{
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz+3)/4)*5);
char prev_c = 0;
for (int src_i = 0; src_i < compressed_sz; src_i += 4)
{
// This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??.
unsigned int d = *(unsigned int*)(compressed + src_i);
for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85)
{
char c = Encode85Byte(d);
fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c);
prev_c = c;
}
if ((src_i % 112) == 112-4)
fprintf(out, "\"\n \"");
}
fprintf(out, "\";\n\n");
}
else
{
fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz);
fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz+3)/4)*4);
int column = 0;
for (int i = 0; i < compressed_sz; i += 4)
{
unsigned int d = *(unsigned int*)(compressed + i);
if ((column++ % 12) == 0)
fprintf(out, "\n 0x%08x, ", d);
else
fprintf(out, "0x%08x, ", d);
}
fprintf(out, "\n};\n\n");
}
// Cleanup
delete[] data;
if (use_compression)
delete[] compressed;
return true;
}
// stb_compress* from stb.h - definition
//////////////////// compressor ///////////////////////
static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen)
{
const unsigned long ADLER_MOD = 65521;
unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
unsigned long blocklen, i;
blocklen = buflen % 5552;
while (buflen) {
for (i=0; i + 7 < blocklen; i += 8) {
s1 += buffer[0], s2 += s1;
s1 += buffer[1], s2 += s1;
s1 += buffer[2], s2 += s1;
s1 += buffer[3], s2 += s1;
s1 += buffer[4], s2 += s1;
s1 += buffer[5], s2 += s1;
s1 += buffer[6], s2 += s1;
s1 += buffer[7], s2 += s1;
buffer += 8;
}
for (; i < blocklen; ++i)
s1 += *buffer++, s2 += s1;
s1 %= ADLER_MOD, s2 %= ADLER_MOD;
buflen -= blocklen;
blocklen = 5552;
}
return (s2 << 16) + s1;
}
static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen)
{
stb_uint i;
for (i=0; i < maxlen; ++i)
if (m1[i] != m2[i]) return i;
return i;
}
// simple implementation that just takes the source data in a big block
static stb_uchar *stb__out;
static FILE *stb__outfile;
static stb_uint stb__outbytes;
static void stb__write(unsigned char v)
{
fputc(v, stb__outfile);
++stb__outbytes;
}
//#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v)))
#define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0)
static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); }
static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); }
static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); }
static void outliterals(stb_uchar *in, int numlit)
{
while (numlit > 65536) {
outliterals(in,65536);
in += 65536;
numlit -= 65536;
}
if (numlit == 0) ;
else if (numlit <= 32) stb_out (0x000020 + numlit-1);
else if (numlit <= 2048) stb_out2(0x000800 + numlit-1);
else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1);
if (stb__out) {
memcpy(stb__out,in,numlit);
stb__out += numlit;
} else
fwrite(in, 1, numlit, stb__outfile);
}
static int stb__window = 0x40000; // 256K
static int stb_not_crap(int best, int dist)
{
return ((best > 2 && dist <= 0x00100)
|| (best > 5 && dist <= 0x04000)
|| (best > 7 && dist <= 0x80000));
}
static stb_uint stb__hashsize = 32768;
// note that you can play with the hashing functions all you
// want without needing to change the decompressor
#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c])
#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d])
#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e])
static unsigned int stb__running_adler;
static int stb_compress_chunk(stb_uchar *history,
stb_uchar *start,
stb_uchar *end,
int length,
int *pending_literals,
stb_uchar **chash,
stb_uint mask)
{
(void)history;
int window = stb__window;
stb_uint match_max;
stb_uchar *lit_start = start - *pending_literals;
stb_uchar *q = start;
#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask)
// stop short of the end so we don't scan off the end doing
// the hashing; this means we won't compress the last few bytes
// unless they were part of something longer
while (q < start+length && q+12 < end) {
int m;
stb_uint h1,h2,h3,h4, h;
stb_uchar *t;
int best = 2, dist=0;
if (q+65536 > end)
match_max = end-q;
else
match_max = 65536;
#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
if (p ? dist != q-t : 1) \
if ((m = stb_matchlen(t, q, match_max)) > best) \
if (stb__nc(m,q-(t))) \
best = m, dist = q - (t)
// rather than search for all matches, only try 4 candidate locations,
// chosen based on 4 different hash functions of different lengths.
// this strategy is inspired by LZO; hashing is unrolled here using the
// 'hc' macro
h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h);
t = chash[h1]; if (t) STB__TRY(t,0);
h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h);
h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1);
h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h);
h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1);
h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h);
t = chash[h4]; if (t) STB__TRY(t,1);
// because we use a shared hash table, can only update it
// _after_ we've probed all of them
chash[h1] = chash[h2] = chash[h3] = chash[h4] = q;
if (best > 2)
assert(dist > 0);
// see if our best match qualifies
if (best < 3) { // fast path literals
++q;
} else if (best > 2 && best <= 0x80 && dist <= 0x100) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
stb_out(0x80 + best-1);
stb_out(dist-1);
} else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
stb_out2(0x4000 + dist-1);
stb_out(best-1);
} else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
stb_out3(0x180000 + dist-1);
stb_out(best-1);
} else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
stb_out3(0x100000 + dist-1);
stb_out2(best-1);
} else if (best > 9 && dist <= 0x1000000) {
if (best > 65536) best = 65536;
outliterals(lit_start, q-lit_start); lit_start = (q += best);
if (best <= 0x100) {
stb_out(0x06);
stb_out3(dist-1);
stb_out(best-1);
} else {
stb_out(0x04);
stb_out3(dist-1);
stb_out2(best-1);
}
} else { // fallback literals if no match was a balanced tradeoff
++q;
}
}
// if we didn't get all the way, add the rest to literals
if (q-start < length)
q = start+length;
// the literals are everything from lit_start to q
*pending_literals = (q - lit_start);
stb__running_adler = stb_adler32(stb__running_adler, start, q - start);
return q - start;
}
static int stb_compress_inner(stb_uchar *input, stb_uint length)
{
int literals = 0;
stb_uint len,i;
stb_uchar **chash;
chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
if (chash == NULL) return 0; // failure
for (i=0; i < stb__hashsize; ++i)
chash[i] = NULL;
// stream signature
stb_out(0x57); stb_out(0xbc);
stb_out2(0);
stb_out4(0); // 64-bit length requires 32-bit leading 0
stb_out4(length);
stb_out4(stb__window);
stb__running_adler = 1;
len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1);
assert(len == length);
outliterals(input+length - literals, literals);
free(chash);
stb_out2(0x05fa); // end opcode
stb_out4(stb__running_adler);
return 1; // success
}
stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
{
stb__out = out;
stb__outfile = NULL;
stb_compress_inner(input, length);
return stb__out - out;
}
# imgui_freetype
Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer in Dear ImGui).
<br>by @vuhdo, @mikesart, @ocornut.
### Usage
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`, `vcpkg integrate install`).
2. Add imgui_freetype.h/cpp alongside your imgui sources.
3. Include imgui_freetype.h after imgui.h.
4. Call `ImGuiFreeType::BuildFontAtlas()` *BEFORE* calling `ImFontAtlas::GetTexDataAsRGBA32()` or `ImFontAtlas::Build()` (so normal Build() won't be called):
```cpp
// See ImGuiFreeType::RasterizationFlags
unsigned int flags = ImGuiFreeType::NoHinting;
ImGuiFreeType::BuildFontAtlas(io.Fonts, flags);
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
```
### Gamma Correct Blending
FreeType assumes blending in linear space rather than gamma space.
See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking).
### Test code Usage
```cpp
#include "misc/freetype/imgui_freetype.h"
#include "misc/freetype/imgui_freetype.cpp"
// Load various small fonts
ImGuiIO& io = ImGui::GetIO();
io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f);
io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f);
io.Fonts->AddFontDefault();
FreeTypeTest freetype_test;
// Main Loop
while (true)
{
if (freetype_test.UpdateRebuild())
{
// REUPLOAD FONT TEXTURE TO GPU
ImGui_ImplXXX_DestroyDeviceObjects();
ImGui_ImplXXX_CreateDeviceObjects();
}
ImGui::NewFrame();
freetype_test.ShowFreetypeOptionsWindow();
...
}
```
### Test code
```cpp
#include "misc/freetype/imgui_freetype.h"
#include "misc/freetype/imgui_freetype.cpp"
struct FreeTypeTest
{
enum FontBuildMode
{
FontBuildMode_FreeType,
FontBuildMode_Stb
};
FontBuildMode BuildMode;
bool WantRebuild;
float FontsMultiply;
int FontsPadding;
unsigned int FontsFlags;
FreeTypeTest()
{
BuildMode = FontBuildMode_FreeType;
WantRebuild = true;
FontsMultiply = 1.0f;
FontsPadding = 1;
FontsFlags = 0;
}
// Call _BEFORE_ NewFrame()
bool UpdateRebuild()
{
if (!WantRebuild)
return false;
ImGuiIO& io = ImGui::GetIO();
io.Fonts->TexGlyphPadding = FontsPadding;
for (int n = 0; n < io.Fonts->ConfigData.Size; n++)
{
ImFontConfig* font_config = (ImFontConfig*)&io.Fonts->ConfigData[n];
font_config->RasterizerMultiply = FontsMultiply;
font_config->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00;
}
if (BuildMode == FontBuildMode_FreeType)
ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags);
else if (BuildMode == FontBuildMode_Stb)
io.Fonts->Build();
WantRebuild = false;
return true;
}
// Call to draw interface
void ShowFreetypeOptionsWindow()
{
ImGui::Begin("FreeType Options");
ImGui::ShowFontSelector("Fonts");
WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType);
ImGui::SameLine();
WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb);
WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f);
WantRebuild |= ImGui::DragInt("Padding", &FontsPadding, 0.1f, 0, 16);
if (BuildMode == FontBuildMode_FreeType)
{
WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting);
WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint);
WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint);
WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting);
WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting);
WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold);
WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique);
WantRebuild |= ImGui::CheckboxFlags("Monochrome", &FontsFlags, ImGuiFreeType::Monochrome);
}
ImGui::End();
}
};
```
### Known issues
- `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer).
This diff is collapsed.
// dear imgui: wrapper to use FreeType (instead of stb_truetype)
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
// Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut
#pragma once
#include "imgui.h" // IMGUI_API, ImFontAtlas
namespace ImGuiFreeType
{
// Hinting greatly impacts visuals (and glyph sizes).
// When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output.
// The Default hinting mode usually looks good, but may distort glyphs in an unusual way.
// The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer.
// You can set those flags on a per font basis in ImFontConfig::RasterizerFlags.
// Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts.
enum RasterizerFlags
{
// By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter.
NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes.
NoAutoHint = 1 << 1, // Disable auto-hinter.
ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter.
LightHinting = 1 << 3, // 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.
MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output.
Bold = 1 << 5, // Styling: Should we artificially embolden the font?
Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style?
Monochrome = 1 << 7 // Disable anti-aliasing. Combine this with MonoHinting for best results!
};
IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);
// By default ImGuiFreeType will use IM_ALLOC()/IM_FREE().
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired:
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
}
Natvis file to describe dear imgui types in the Visual Studio debugger.
With this, types like ImVector<> will be displayed nicely in the debugger.
You can include this file a Visual Studio project file, or install it in Visual Studio folder.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#version 410 core
layout (location = 0) in vec3 verCoords;
uniform float new_value;
void main()
{
gl_Position = vec4(verCoords.x, verCoords.y, 0.0, 1.0);
}
This diff is collapsed.
This diff is collapsed.
File added
This diff is collapsed.
This diff is collapsed.