diff options
| author | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-05 19:04:14 +0200 |
|---|---|---|
| committer | Jean-Philippe Bruyère <jp_bruyere@hotmail.com> | 2026-10-05 19:04:14 +0200 |
| commit | b5d0777c0f456ec7c830a3129d4618f947115c05 (patch) | |
| tree | 5c668e751311184599c352c7c6ec77a41165fc42 | |
| parent | 61fc5439991549bc8060a376dbf2c6d39c77bcb8 (diff) | |
font revemping wip; font cache upload img bounds reduced to current stagingX
| -rw-r--r-- | CMakeLists.txt | 30 | ||||
| -rw-r--r-- | gunit_tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | gunit_tests/textDraw.cpp | 47 | ||||
| -rw-r--r-- | src/cross_os.h | 17 | ||||
| -rw-r--r-- | src/vkvg_context.c | 2 | ||||
| -rw-r--r-- | src/vkvg_fonts.c | 147 | ||||
| -rw-r--r-- | src/vkvg_fonts.h | 22 | ||||
| -rw-r--r-- | src/vkvg_internal.h | 66 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 42 | ||||
| -rw-r--r-- | tests/font_tests/font_tests.c | 12 |
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; |