summaryrefslogtreecommitdiffstatsci
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-05 19:04:14 +0200
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2026-10-05 19:04:14 +0200
commitb5d0777c0f456ec7c830a3129d4618f947115c05 (patch)
tree5c668e751311184599c352c7c6ec77a41165fc42
parent61fc5439991549bc8060a376dbf2c6d39c77bcb8 (diff)
font revemping wip; font cache upload img bounds reduced to current stagingX
-rw-r--r--CMakeLists.txt30
-rw-r--r--gunit_tests/CMakeLists.txt1
-rw-r--r--gunit_tests/textDraw.cpp47
-rw-r--r--src/cross_os.h17
-rw-r--r--src/vkvg_context.c2
-rw-r--r--src/vkvg_fonts.c147
-rw-r--r--src/vkvg_fonts.h22
-rw-r--r--src/vkvg_internal.h66
-rw-r--r--tests/CMakeLists.txt42
-rw-r--r--tests/font_tests/font_tests.c12
10 files changed, 247 insertions, 139 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 32b430d..879e901 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -334,22 +334,22 @@ IF (VKVG_BUILD_TESTS)
#font tests
- ADD_EXECUTABLE(fonts_test "${CMAKE_CURRENT_SOURCE_DIR}/tests/font_tests/font_tests.c")
+ # ADD_EXECUTABLE(fonts_test "${CMAKE_CURRENT_SOURCE_DIR}/tests/font_tests/font_tests.c")
- TARGET_INCLUDE_DIRECTORIES(fonts_test PRIVATE
- ${FREETYPE_INCLUDE_DIRS}
- ${HarfBuzz_INCLUDE_DIRS}
- ${Vulkan_INCLUDE_DIRS}
- ${CMAKE_CURRENT_SOURCE_DIR}/include
- ${Fontconfig_INCLUDE_DIRS}
- )
- TARGET_LINK_LIBRARIES(fonts_test PUBLIC
- #vkvg
- ${HarfBuzz_LIBRARIES}
- ${FREETYPE_LIBRARY}
- ${Fontconfig_LIBRARIES}
- ${Vulkan_LIBRARIES}
- )
+ # TARGET_INCLUDE_DIRECTORIES(fonts_test PRIVATE
+ # ${FREETYPE_INCLUDE_DIRS}
+ # ${HarfBuzz_INCLUDE_DIRS}
+ # ${Vulkan_INCLUDE_DIRS}
+ # ${CMAKE_CURRENT_SOURCE_DIR}/include
+ # ${Fontconfig_INCLUDE_DIRS}
+ # )
+ # TARGET_LINK_LIBRARIES(fonts_test PUBLIC
+ # #vkvg
+ # ${HarfBuzz_LIBRARIES}
+ # ${FREETYPE_LIBRARY}
+ # ${Fontconfig_LIBRARIES}
+ # ${Vulkan_LIBRARIES}
+ # )
###################
diff --git a/gunit_tests/CMakeLists.txt b/gunit_tests/CMakeLists.txt
index bc95fb4..81683e7 100644
--- a/gunit_tests/CMakeLists.txt
+++ b/gunit_tests/CMakeLists.txt
@@ -32,6 +32,7 @@ add_executable("${PROJECT_NAME}"
imageDraw.cpp
matrices.cpp
patternDraw.cpp
+ textDraw.cpp
save_restore.cpp
unitTest.h
)
diff --git a/gunit_tests/textDraw.cpp b/gunit_tests/textDraw.cpp
new file mode 100644
index 0000000..8e40294
--- /dev/null
+++ b/gunit_tests/textDraw.cpp
@@ -0,0 +1,47 @@
+#include "drawTestBase.h"
+#include "unitTest.h"
+
+
+class TextDrawTest : public DrawTestBase {
+
+ protected:
+ void SetUp() override {
+ surf = vkvg_surface_create(dev, 512, 512);
+
+ }
+ void TearDown() override {
+ DrawTestBase::TearDown();
+ }
+};
+TEST_F(TextDrawTest, References) {
+ /*EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_font_status(NULL));
+ EXPECT_EQ(0, vkvg_pattern_get_reference_count(NULL));
+ EXPECT_NO_FATAL_FAILURE(vkvg_pattern_reference(NULL));
+
+ VkvgPattern pat = vkvg_pattern_create_for_surface(NULL);
+ EXPECT_EQ(VKVG_STATUS_NULL_POINTER, vkvg_pattern_status(pat));
+
+ pat = vkvg_pattern_create_linear(0, 0, 0, 0);
+ EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_pattern_status(pat));
+ EXPECT_EQ(1, vkvg_pattern_get_reference_count(pat));
+ vkvg_pattern_reference(pat);
+ EXPECT_EQ(2, vkvg_pattern_get_reference_count(pat));
+
+ EXPECT_NO_FATAL_FAILURE(vkvg_pattern_destroy(NULL));
+ vkvg_pattern_destroy(pat);
+ EXPECT_EQ(1, vkvg_pattern_get_reference_count(pat));
+ vkvg_pattern_destroy(pat);
+
+ pat = vkvg_pattern_create_radial(0, 0, 0, 0, 0, 0);
+ EXPECT_EQ(VKVG_STATUS_SUCCESS, vkvg_pattern_status(pat));
+ EXPECT_EQ(1, vkvg_pattern_get_reference_count(pat));
+ vkvg_pattern_destroy(pat);*/
+}
+
+TEST_F(TextDrawTest, PaintImgPattern) {
+
+ VkvgContext ctx = vkvg_create(surf);
+ vkvg_destroy(ctx);
+
+ compareWithRefImage();
+}
diff --git a/src/cross_os.h b/src/cross_os.h
index 4c7baa1..bdd3f7a 100644
--- a/src/cross_os.h
+++ b/src/cross_os.h
@@ -56,7 +56,22 @@ void _linux_register_error_handler();
#endif
#endif
-
+#if defined(__clang__)
+#define DIAGNOSTIC_DISABLE_UNUSED _Pragma("clang diagnostic push") \
+_Pragma("clang diagnostic ignored \"-Wunused-function\"")
+#define DIAGNOSTIC_RESTORE_UNUSED _Pragma("clang diagnostic pop")
+#elif defined(__GNUC__)
+#define DIAGNOSTIC_DISABLE_UNUSED _Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wunused-function\"")
+#define DIAGNOSTIC_RESTORE_UNUSED _Pragma("GCC diagnostic pop")
+#elif defined(_MSC_VER)
+#define DIAGNOSTIC_DISABLE_UNUSED __pragma(warning(push)) \
+__pragma(warning(disable : 4505))
+#define DIAGNOSTIC_RESTORE_UNUSED __pragma(warning(pop))
+#else
+#define DIAGNOSTIC_DISABLE_UNUSED
+#define DIAGNOSTIC_RESTORE_UNUSED
+#endif
// 1. Check if we are in a POSIX environment that supports strncasecmp
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)
diff --git a/src/vkvg_context.c b/src/vkvg_context.c
index fb3b86b..c8d332c 100644
--- a/src/vkvg_context.c
+++ b/src/vkvg_context.c
@@ -258,6 +258,8 @@ void vkvg_destroy(VkvgContext ctx) {
if (ctx->pattern)
vkvg_pattern_destroy(ctx->pattern);
+ if (ctx->currentFont)
+ vkvg_font_destroy(ctx->currentFont);
_clear_context(ctx);
diff --git a/src/vkvg_fonts.c b/src/vkvg_fonts.c
index f000827..05eff90 100644
--- a/src/vkvg_fonts.c
+++ b/src/vkvg_fonts.c
@@ -203,28 +203,29 @@ void _flush_chars_to_tex(VkvgDevice dev, vkvg_font_t* f) {
_font_cache_t* cache = dev->fontCache;
if (cache->stagingX == 0) // no char in stagging buff to flush
return;
+ tex_ref_t l = f->texLines.elements[f->texLines.count - 1];
- LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n", f->curLine.penX, f->curLine.penY);
+ LOG(VKVG_LOG_INFO, "_flush_chars_to_tex pen(%d, %d)\n", l.penX, l.penY);
vkWaitForFences(dev->vkDev, 1, &cache->uploadFence, VK_TRUE, UINT64_MAX);
ResetFences(dev->vkDev, 1, &cache->uploadFence);
vkResetCommandBuffer(cache->cmd, 0);
memcpy(vkh_buffer_get_mapped_pointer(&cache->buff), cache->hostBuff,
- (uint64_t)f->curLine.height * FONT_PAGE_SIZE * cache->texPixelSize);
+ (uint64_t)l.height * FONT_PAGE_SIZE * cache->texPixelSize);
vkh_cmd_begin(cache->cmd, VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
- VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, f->curLine.pageIdx, 1};
+ VkImageSubresourceRange subres = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, l.pageIdx, 1};
vkh_image_set_layout_subres(cache->cmd, cache->texture, subres, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT);
- VkBufferImageCopy bufferCopyRegion = {.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, f->curLine.pageIdx, 1},
+ VkBufferImageCopy bufferCopyRegion = {.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, l.pageIdx, 1},
.bufferRowLength = FONT_PAGE_SIZE,
- .bufferImageHeight = f->curLine.height,
- .imageOffset = {f->curLine.penX, f->curLine.penY, 0},
- .imageExtent = {FONT_PAGE_SIZE - f->curLine.penX, f->curLine.height, 1}};
+ .bufferImageHeight = l.height,
+ .imageOffset = {l.penX, l.penY, 0},
+ .imageExtent = {cache->stagingX, l.height, 1}};
vkCmdCopyBufferToImage(cache->cmd, cache->buff.buffer, vkh_image_get_vkimage(cache->texture),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &bufferCopyRegion);
@@ -237,27 +238,46 @@ void _flush_chars_to_tex(VkvgDevice dev, vkvg_font_t* f) {
_device_submit_cmd(dev, &cache->cmd, cache->uploadFence);
- f->curLine.penX += cache->stagingX;
+ l.penX += cache->stagingX;
+ f->texLines.elements[f->texLines.count - 1] = l;
+
cache->stagingX = 0;
memset(cache->hostBuff, 0, (uint64_t)FONT_PAGE_SIZE * FONT_PAGE_SIZE * cache->texPixelSize);
}
/// Start a new line in font cache, increase texture layer count if needed.
void _init_next_line_in_tex_cache(VkvgDevice dev, vkvg_font_t* f) {
_font_cache_t* cache = dev->fontCache;
+ tex_ref_t *l = &f->texLines.elements[f->texLines.count - 1];
int i;
for (i = 0; i < cache->texLength; ++i) {
- if (cache->pensY[i] + f->curLine.height >= FONT_PAGE_SIZE)
+ if (cache->pensY[i] + l->height >= FONT_PAGE_SIZE)
continue;
- f->curLine.pageIdx = (unsigned char)i;
- f->curLine.penX = 0;
- f->curLine.penY = cache->pensY[i];
- cache->pensY[i] += f->curLine.height;
+ l->pageIdx = (unsigned char)i;
+ l->penX = 0;
+ l->penY = cache->pensY[i];
+ cache->pensY[i] += l->height;
return;
}
_flush_chars_to_tex(dev, f);
_increase_font_tex_array(dev);
_init_next_line_in_tex_cache(dev, f);
}
+void _font_buffer_destroy (vkvg_font_face_t* face) {
+ array_destroy_VkvgFont(&face->sizes);
+ array_destroy_uint64_t(&face->queryHashes);
+ FT_Done_Face(face->face);
+ mtx_destroy(&face->mutex);
+}
+void _font_face_destroy (vkvg_font_face_t* face) {
+ array_destroy_VkvgFont(&face->sizes);
+ array_destroy_uint64_t(&face->queryHashes);
+ FT_Done_Face(face->face);
+ mtx_destroy(&face->mutex);
+
+ array_del_vkvg_font_face_t(&face->fontBuffer->faces, face->index);
+// if (face->fontBuffer->faces.count == 0)
+// _font_face_destroy(font->face);
+}
void _font_cache_destroy(VkvgDevice dev) {
_font_cache_t* cache = (_font_cache_t*)dev->fontCache;
@@ -271,11 +291,7 @@ void _font_cache_destroy(VkvgDevice dev) {
for (int k = 0; k < faces[j].sizes.count; ++k) {
vkvg_font_destroy(fonts[k]);
}
- vkvg_font_face_t* face = &faces[j];
- array_destroy_VkvgFont(&face->sizes);
- array_destroy_uint64_t(&face->queryHashes);
- FT_Done_Face(face->face);
- mtx_destroy(&face->mutex);
+ // _font_face_destroy(&faces[j]);
}
vkvg_font_buffer_t* buff = &buffs[i];
free(buff->buffer);
@@ -350,12 +366,12 @@ void _font_cache_update_context_descset(VkvgContext ctx) {
_char_ref _prepare_char(VkvgDevice dev, VkvgText tr, uint32_t gindex) {
VkvgFont f = tr->font;
#ifdef VKVG_USE_FREETYPE
-#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
+ #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
FT_CHECK_RESULT(FT_Load_Glyph(f->face, gindex, FT_LOAD_TARGET_NORMAL));
FT_CHECK_RESULT(FT_Render_Glyph(f->face->glyph, FT_RENDER_MODE_LCD));
-#else
+ #else
FT_CHECK_RESULT(FT_Load_Glyph(f->face->face, gindex, FT_LOAD_RENDER));
-#endif
+ #endif
FT_GlyphSlot slot = f->face->face->glyph;
FT_Bitmap bmp = slot->bitmap;
@@ -364,9 +380,9 @@ _char_ref _prepare_char(VkvgDevice dev, VkvgText tr, uint32_t gindex) {
uint32_t bmpRows = bmp.rows;
unsigned char* buffer = bmp.buffer;
-#if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
+ #if defined(VKVG_LCD_FONT_FILTER) && defined(FT_CONFIG_OPTION_SUBPIXEL_RENDERING)
bmpPixelWidth /= 3;
-#endif
+ #endif
#else
stbtt_fontinfo* pStbInfo = &tr->fontId->stbInfo;
int c_x1, c_y1, c_x2, c_y2;
@@ -376,8 +392,8 @@ _char_ref _prepare_char(VkvgDevice dev, VkvgText tr, uint32_t gindex) {
uint32_t bmpRows = c_y2 - c_y1;
#endif
uint8_t* data = dev->fontCache->hostBuff;
-
- if (dev->fontCache->stagingX + f->curLine.penX + bmpPixelWidth > FONT_PAGE_SIZE) {
+ tex_ref_t l = f->texLines.elements[f->texLines.count - 1];
+ if (dev->fontCache->stagingX + l.penX + bmpPixelWidth > FONT_PAGE_SIZE) {
_flush_chars_to_tex(dev, f);
_init_next_line_in_tex_cache(dev, f);
}
@@ -414,68 +430,19 @@ _char_ref _prepare_char(VkvgDevice dev, VkvgText tr, uint32_t gindex) {
cr.bmpDiff.y = (int16_t)-c_y1;
cr.advance = (vec2){(uint32_t)roundf(f->scale * advance) << 6, 0};
#endif
- vec4 uvBounds = {{(float)(penX + f->curLine.penX) / (float)FONT_PAGE_SIZE},
- {(float)f->curLine.penY / (float)FONT_PAGE_SIZE},
+ vec4 uvBounds = {{(float)(penX + l.penX) / (float)FONT_PAGE_SIZE},
+ {(float)l.penY / (float)FONT_PAGE_SIZE},
{(float)bmpPixelWidth},
{(float)bmpRows}};
cr.bounds = uvBounds;
- cr.pageIdx = f->curLine.pageIdx;
+ cr.pageIdx = l.pageIdx;
f->charLookup[gindex] = cr;
dev->fontCache->stagingX += bmpPixelWidth;
return cr;
}
-void _font_add_name(vkvg_font_face_t* font, const char* name) {
- /*if (++font->namesCount == 1)
- font->names = (char**)malloc(sizeof(char*));
- else
- font->names = (char**)realloc(font->names, font->namesCount * sizeof(char*));
- font->names[font->namesCount - 1] = (char*)calloc(strlen(name) + 1, sizeof(char));
- strcpy(font->names[font->namesCount - 1], name);*/
-}
-// select current font for context
-vkvg_font_t* _find_or_create_font_size(VkvgContext ctx) {
- /*vkvg_font_face_t* font;// = ctx->currentFont;
-
- for (uint32_t i = 0; i < font->sizeCount; ++i) {
- if (font->sizes[i].charSize == ctx->selectedCharSize)
- return &font->sizes[i];
- }
- // if not found, create a new font size structure
- if (++font->sizeCount == 1)
- font->sizes = (vkvg_font_t*)malloc(sizeof(vkvg_font_t));
- else
- font->sizes = (vkvg_font_t*)realloc(font->sizes, font->sizeCount * sizeof(vkvg_font_t));
- vkvg_font_t newSize = {.charSize = ctx->selectedCharSize};
-
- VkvgDevice dev = ctx->dev;
-
-#ifdef VKVG_USE_HARFBUZZ
- newSize.hb_font = hb_ft_font_create(newSize.face, NULL);
-#endif
-
- _init_next_line_in_tex_cache(dev, &newSize);
-
- font->sizes[font->sizeCount - 1] = newSize;
- return &font->sizes[font->sizeCount - 1];*/
-}
-
-// try find font already resolved with fontconfig by font name
-bool _tryFindFontByName(VkvgContext ctx, vkvg_font_face_t** font) {
- /*_font_cache_t* cache = ctx->dev->fontCache;
- for (int i = 0; i < cache->fontsCount; ++i) {
- for (uint32_t j = 0; j < cache->fonts[i].namesCount; j++) {
- if (cache->fonts[i].names[j] == ctx->selectedFontName) {
- *font = &cache->fonts[i];
- return true;
- }
- }
- }*/
- return false;
-}
-
/*void _fcpattern_append(FcPattern* dest, const FcPattern* src) {
FcPatternIter iter;
FcPatternIterStart(src, &iter);
@@ -606,7 +573,7 @@ bool _tryResolveFontNameWithFontConfig(VkvgDevice dev, const char* fontString, v
array_add_vkvg_font_buffer_t(&cache->fontBuffers, buff);
}
- vkvg_font_face_t newFace = {0};
+ vkvg_font_face_t newFace = { buffPtr->faces.count, buffPtr };
newFace.queryHashes = array_create_uint64_t(2);
array_add_uint64_t(&newFace.queryHashes, queryHash);
if (dev->threadAware)
@@ -927,6 +894,10 @@ bool _try_get_font_size (vkvg_font_face_t* face, uint32_t pt26_6, VkvgFont *font
return false;
}
+void _clear_cache() {
+
+}
+
VkvgFont vkvg_font_create (VkvgDevice dev, const char* query, float pointSize) {
uint32_t pt26_6 = (uint32_t)(pointSize * 64.f);
VkvgFont font = NULL;
@@ -949,22 +920,27 @@ VkvgFont vkvg_font_create (VkvgDevice dev, const char* query, float pointSize) {
_font_cache_t* cache = dev->fontCache;
#ifdef VKVG_USE_FREETYPE
- if (face->sizes.count) {
+ if (face->sizes.size) {
FT_CHECK_RESULT(FT_New_Size (face->face, &font->ftSize));
FT_Activate_Size(font->ftSize);
} else {
face->sizes = array_create_VkvgFont(5);
}
- array_add_VkvgFont(&face->sizes, font);
+ font->eltIndex = array_add_VkvgFont(&face->sizes, font);
FT_CHECK_RESULT(FT_Set_Char_Size(face->face, 0, font->charSize, dev->hdpi, dev->vdpi));
font->ftSize = face->face->size;
font->charLookup = (_char_ref*)calloc(face->face->num_glyphs, sizeof(_char_ref));
+ tex_ref_t l = {0};//pageIdx??
+
if (FT_IS_SCALABLE(face->face))
- font->curLine.height = face->face->size->metrics.height >> 6;
+ l.height = face->face->size->metrics.height >> 6;
else
- font->curLine.height = face->face->height >> 6;
+ l.height = face->face->height >> 6;
+
+ font->texLines = array_create_tex_ref_t(2);
+ array_add_tex_ref_t(&font->texLines, l);
#else
stbtt_GetFontVMetrics(&font->stbInfo, &font->ascent, &font->descent, &font->lineGap);
font->charLookup = (_char_ref**)calloc(font->stbInfo.numGlyphs, sizeof(_char_ref*));
@@ -978,6 +954,7 @@ VkvgFont vkvg_font_create (VkvgDevice dev, const char* query, float pointSize) {
#ifdef VKVG_USE_HARFBUZZ
font->hb_font = hb_ft_font_create(face->face, NULL);
#endif
+ _init_next_line_in_tex_cache(dev, font);
atomic_init(&font->references, 1);
return font;
}
@@ -1007,6 +984,12 @@ void vkvg_font_destroy(VkvgFont font) {
hb_font_destroy(font->hb_font);
#endif
+
+ array_destroy_tex_ref_t(&font->texLines);
+
+ array_del_VkvgFont(&font->face->sizes , font->eltIndex);
+ if (font->face->sizes.count == 0)
+ _font_face_destroy(font->face);
free(font->charLookup);
free(font);
font = NULL;
diff --git a/src/vkvg_fonts.h b/src/vkvg_fonts.h
index 6ccac88..4328648 100644
--- a/src/vkvg_fonts.h
+++ b/src/vkvg_fonts.h
@@ -60,7 +60,7 @@
#endif
#define FONT_PAGE_SIZE 1024
-#define FONT_CACHE_INIT_LAYERS 1
+#define FONT_CACHE_INIT_LAYERS 2
#define FONT_FILE_NAME_MAX_SIZE 1024
#define FONT_NAME_MAX_SIZE 128
@@ -176,19 +176,25 @@ typedef struct {
// Current location in font cache texture array for new character addition. Each font holds such structure to locate
// where to upload new chars.
-typedef struct {
+typedef struct _tex_ref_t{
uint8_t pageIdx; /* Current page number in font cache */
int penX; /* Current X in cache for next char addition */
int penY; /* Current Y in cache for next char addition */
int height; /* Height of current line pointed by this structure */
-} _tex_ref_t;
+} tex_ref_t;
+DIAGNOSTIC_DISABLE_UNUSED
+CTOR_ARRAY(tex_ref_t)
CTOR_ARRAY(uint64_t)
CTOR_ARRAY(VkvgFont)
+typedef struct _vkvg_font_buffer_t vkvg_font_buffer_t;
+
/* Font identification structure */
typedef struct {
+ uint32_t index; /* index in face list of containing font buffer */
+ vkvg_font_buffer_t* fontBuffer;
array_uint64_t queryHashes;
#ifdef VKVG_USE_FREETYPE
FT_Face face; /* FreeType face*/
@@ -206,8 +212,7 @@ typedef struct {
CTOR_ARRAY(vkvg_font_face_t)
-typedef struct
-{
+typedef struct _vkvg_font_buffer_t {
uint64_t fontPathHash;
size_t bufferSize;
unsigned char* buffer;
@@ -216,11 +221,14 @@ typedef struct
CTOR_ARRAY(vkvg_font_buffer_t)
+DIAGNOSTIC_RESTORE_UNUSED
+
typedef struct _vkvg_font_t {
vkvg_status_t status;
atomic_int references; // reference count
- vkvg_font_face_t* face;
+ vkvg_font_face_t *face;
+ uint32_t eltIndex; // index in face->sizes[] array
#ifdef VKVG_USE_FREETYPE
FT_F26Dot6 charSize; /* Font size in Point as fixed float 26.6 */
FT_Size ftSize; /* FT size rec */
@@ -236,7 +244,7 @@ typedef struct _vkvg_font_t {
hb_font_t* hb_font; /* HarfBuzz font instance*/
#endif
_char_ref* charLookup; /* Lookup table of characteres in cache, if not found, upload is queued*/
- _tex_ref_t curLine; /* texture reference where to add new glyph bmp's in cache*/
+ array_tex_ref_t texLines; /* texture reference where to add new glyph bmp's in cache */
} vkvg_font_t;
diff --git a/src/vkvg_internal.h b/src/vkvg_internal.h
index c1fb758..469b7fd 100644
--- a/src/vkvg_internal.h
+++ b/src/vkvg_internal.h
@@ -54,32 +54,6 @@
#define M_2_PIF 0.63661977236758134308f // 2/pi
#endif
-#define CTOR_ARRAY(type) \
-typedef struct { \
- uint32_t count; \
- uint32_t size; \
- type *elements; \
-} array_##type; \
-static array_##type array_create_##type (uint32_t reservedSize) { \
- type *elts = (type*)malloc(reservedSize * sizeof(type)); \
- return (array_##type) {0, reservedSize, elts}; \
-} \
-static int array_add_##type (array_##type* arr, type elt) { \
- if (arr->size <= arr->count) { \
- uint32_t newSize = arr->size * 2; \
- type *elts = (type*)realloc(arr->elements, newSize * sizeof(type)); \
- if (elts == NULL) \
- return 0; \
- arr->elements = elts; \
- arr->size = newSize; \
- } \
- arr->elements[arr->count++] = elt; \
- return 1; \
-} \
-static void array_destroy_##type (array_##type* arr) { \
- free(arr->elements); \
-}
-
/**
* @brief Computes the 64-bit FNV-1a hash of a ascii string lowering case.
*
@@ -160,6 +134,46 @@ static inline uint64_t fnv1a_64_str(const char *const restrict str) {
#define VKVG_FENCE_TIMEOUT 30000000000
// #define VKVG_FENCE_TIMEOUT 10000
+#define CTOR_ARRAY(type) \
+typedef struct { \
+ uint32_t count; \
+ uint32_t size; \
+ type *elements; \
+} array_##type; \
+static array_##type array_create_##type (uint32_t reservedSize) { \
+ type *elts = (type*)malloc(reservedSize * sizeof(type)); \
+ return (array_##type) {0, reservedSize, elts}; \
+} \
+static int array_add_##type (array_##type* arr, type elt) { \
+ if (arr->size <= arr->count) { \
+ uint32_t newSize = arr->size * 2; \
+ type *elts = (type*)realloc(arr->elements, newSize * sizeof(type)); \
+ if (elts == NULL) \
+ return -1; \
+ arr->elements = elts; \
+ arr->size = newSize; \
+ } \
+ arr->elements[arr->count++] = elt; \
+ return arr->count - 1; \
+} \
+static type* array_last_##type (array_##type* arr) { \
+ if (!arr->count) \
+ return NULL; \
+ return &arr->elements[arr->count - 1]; \
+} \
+static void array_destroy_##type (array_##type* arr) { \
+ free(arr->elements); \
+ arr->count = 0; \
+ arr->size = 0; \
+} \
+static void array_del_##type (array_##type* arr, uint32_t index) { \
+ if (index >= arr->count) \
+ return; \
+ if (index < arr->count - 1) \
+ memcpy (&arr->elements[index], &arr->elements[index + 1], arr->count - index - 1); \
+ arr->count--; \
+}
+
#include "vectors.h"
/*typedef struct {
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 16356dd..98b437a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -12,17 +12,15 @@ ENDIF ()
SET(TESTS_DATA_ROOT "${CMAKE_SOURCE_DIR}/tests/data/" CACHE STRING "Data path for tests")
-FUNCTION (buildtest TEST_FILE)
- GET_FILENAME_COMPONENT(TEST_NAME ${TEST_FILE} NAME_WE)
- ADD_EXECUTABLE(${TEST_NAME} ${TEST_FILE} $<TARGET_OBJECTS:tests_common>)
+FUNCTION (buildtest TEST_NAME)
SET_TARGET_PROPERTIES(${TEST_NAME} PROPERTIES
OUTPUT_NAME ${TEST_NAME}
C_STANDARD 11
LINKER_LANGUAGE C
)
- target_compile_definitions("${TEST_NAME}" PUBLIC
- TESTS_DATA_ROOT="${TESTS_DATA_ROOT}"
- )
+ target_compile_definitions("${TEST_NAME}" PUBLIC
+ TESTS_DATA_ROOT="${TESTS_DATA_ROOT}"
+ )
TARGET_INCLUDE_DIRECTORIES(${TEST_NAME}
PRIVATE
${Vulkan_INCLUDE_DIRS}
@@ -39,7 +37,7 @@ FUNCTION (buildtest TEST_FILE)
${GLFW3_LIBRARY}
Threads::Threads
)
- TARGET_LINK_LIBRARIES(${TEST_NAME} PRIVATE vkvg vkh)
+ TARGET_LINK_LIBRARIES(${TEST_NAME} PRIVATE vkvg vkh)
ENDFUNCTION (buildtest)
@@ -88,9 +86,37 @@ IF (VKVG_SVG)
ENDIF()
FOREACH(TEST ${TESTS})
- buildtest(${TEST})
+ GET_FILENAME_COMPONENT(TEST_NAME ${TEST} NAME_WE)
+ ADD_EXECUTABLE(${TEST_NAME} ${TEST} $<TARGET_OBJECTS:tests_common>)
+ buildtest(${TEST_NAME})
ENDFOREACH()
+#font and text tests
+file(GLOB FONT_TESTS
+ "fonts/*.c"
+)
+FOREACH(FONT_TEST ${FONT_TESTS})
+ GET_FILENAME_COMPONENT(FONT_TEST_NAME ${FONT_TEST} NAME_WE)
+ ADD_EXECUTABLE(${FONT_TEST_NAME} ${FONT_TEST} $<TARGET_OBJECTS:tests_common>)
+ TARGET_INCLUDE_DIRECTORIES(${FONT_TEST_NAME} PRIVATE
+ $<$<BOOL:${VKVG_USE_FREETYPE}>:${FREETYPE_INCLUDE_DIRS}>
+ $<$<BOOL:${VKVG_USE_HARFBUZZ}>:${HarfBuzz_INCLUDE_DIRS}>
+ $<$<BOOL:${VKVG_USE_FONTCONFIG}>:${Fontconfig_INCLUDE_DIRS}>
+ )
+ IF(VKVG_USE_FREETYPE)
+ TARGET_LINK_LIBRARIES("${FONT_TEST_NAME}" PUBLIC ${FREETYPE_LIBRARY})
+ ENDIF()
+ IF(VKVG_USE_FONTCONFIG)
+ TARGET_LINK_LIBRARIES("${FONT_TEST_NAME}" PRIVATE ${Fontconfig_LIBRARIES})
+ ENDIF()
+ IF(VKVG_USE_HARFBUZZ)
+ TARGET_LINK_LIBRARIES("${FONT_TEST_NAME}" PRIVATE ${HarfBuzz_LIBRARIES})
+ ENDIF()
+
+ buildtest(${FONT_TEST_NAME})
+ENDFOREACH()
+
+
diff --git a/tests/font_tests/font_tests.c b/tests/font_tests/font_tests.c
index ed2a279..024328e 100644
--- a/tests/font_tests/font_tests.c
+++ b/tests/font_tests/font_tests.c
@@ -332,6 +332,7 @@ void ft_face_flags_to_string(FT_Long face_flags, char* out_str, size_t max_len)
#define AXIS_TAG_ITAL FT_MAKE_TAG('i', 't', 'a', 'l')
typedef enum {
+ font_weight_unset = 0,
font_weight_thin = 100,
font_weight_extra_light = 200,
font_weight_light = 300,
@@ -344,6 +345,7 @@ typedef enum {
} font_weight;
typedef enum {
+ font_width_unset = 0,
font_width_ultra_condensed = 1,//50%
font_width_extra_condensed = 2,
font_width_condensed = 3,
@@ -356,6 +358,7 @@ typedef enum {
} font_width;
typedef enum {
+ font_slant_unset = 0,
font_slant_italic = 0b0000000000000001,
font_slant_regular = 0b0000000001000000,
font_slant_oblic = 0b0000001000000000
@@ -370,6 +373,15 @@ typedef struct {
uint32_t styleHash;
} font_id_t;
+typedef struct {
+ const char *txtFontPattern; // font config textual representation of pattern
+ const char *family;
+ const char *style;
+ font_weight weight;
+ font_width width;
+ font_slant slant;
+ uint32_t flags;
+} vkvg_font_create_info_t;
font_id_t font_id_cache[7000];
array_t* font_names;