Refactor: Store BLF Glyphs in blender::Map #118528

Merged
Harley Acheson merged 9 commits from Harley/blender:GlyphMap into main 2024-02-21 18:17:30 +01:00
5 changed files with 30 additions and 74 deletions

View File

@ -23,8 +23,6 @@ set(SRC
intern/blf_font_default.cc
intern/blf_glyph.cc
intern/blf_thumbs.cc
intern/blf_util.cc
BLF_api.hh
intern/blf_internal.hh
intern/blf_internal_types.hh

View File

@ -91,7 +91,7 @@ static GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font)
static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{
std::unique_ptr<GlyphCacheBLF> gc = std::make_unique<GlyphCacheBLF>(GlyphCacheBLF{});
std::unique_ptr<GlyphCacheBLF> gc = std::make_unique<GlyphCacheBLF>();
gc->size = font->size;
gc->bold = ((font->flags & BLF_BOLD) != 0);
@ -101,8 +101,6 @@ static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
gc->char_width = font->char_width;
gc->char_spacing = font->char_spacing;
memset(gc->bucket, 0, sizeof(gc->bucket));
blf_ensure_size(font);
/* Determine ideal fixed-width size for monospaced output. */
@ -146,11 +144,7 @@ void blf_glyph_cache_release(FontBLF *font)
GlyphCacheBLF::~GlyphCacheBLF()
{
for (uint i = 0; i < ARRAY_SIZE(this->bucket); i++) {
while (GlyphBLF *g = static_cast<GlyphBLF *>(BLI_pophead(&this->bucket[i]))) {
blf_glyph_free(g);
}
}
this->glyphs.clear_and_shrink();
if (this->texture) {
GPU_texture_free(this->texture);
}
@ -174,12 +168,10 @@ static GlyphBLF *blf_glyph_cache_find_glyph(const GlyphCacheBLF *gc,
uint charcode,
uint8_t subpixel)
{
GlyphBLF *g = static_cast<GlyphBLF *>(gc->bucket[blf_hash(charcode << 6 | subpixel)].first);
while (g) {
if (g->c == charcode && g->subpixel == subpixel) {
return g;
}
g = g->next;
const std::unique_ptr<GlyphBLF> *ptr = gc->glyphs.lookup_ptr_as(
GlyphCacheKey{charcode, subpixel});
if (ptr != nullptr) {
return ptr->get();
}
return nullptr;
}
@ -231,7 +223,7 @@ static GlyphBLF *blf_glyph_cache_add_glyph(FontBLF *font,
FT_UInt glyph_index,
uint8_t subpixel)
{
GlyphBLF *g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get");
std::unique_ptr<GlyphBLF> g = std::make_unique<GlyphBLF>();
g->c = charcode;
g->idx = glyph_index;
g->advance_x = (ft_pix)glyph->advance.x;
@ -344,9 +336,9 @@ static GlyphBLF *blf_glyph_cache_add_glyph(FontBLF *font,
}
}
BLI_addhead(&(gc->bucket[blf_hash(g->c << 6 | subpixel)]), g);
return g;
GlyphCacheKey key = {charcode, subpixel};
gc->glyphs.add(key, std::move(g));
return gc->glyphs.lookup(key).get();
}
/** \} */
@ -1326,12 +1318,11 @@ GlyphBLF *blf_glyph_ensure_subpixel(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *
}
#endif
void blf_glyph_free(GlyphBLF *g)
GlyphBLF::~GlyphBLF()
{
if (g->bitmap) {
MEM_freeN(g->bitmap);
if (this->bitmap) {
MEM_freeN(this->bitmap);
}
MEM_freeN(g);
}
/** \} */

View File

@ -54,8 +54,6 @@ extern struct FontBLF *global_font[BLF_MAX_FONT];
void blf_batch_draw_begin(struct FontBLF *font);
void blf_batch_draw(void);
unsigned int blf_next_p2(unsigned int x);
unsigned int blf_hash(unsigned int val);
/**
* Some font have additional file with metrics information,
* in general, the extension of the file is: `.afm` or `.pfm`
@ -200,7 +198,6 @@ float blf_character_to_curves(FontBLF *font,
struct ListBase *nurbsbase,
const float scale);
void blf_glyph_free(struct GlyphBLF *g);
void blf_glyph_draw(
struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, int x, int y);

View File

@ -10,6 +10,7 @@
#include <mutex>
#include "BLI_map.hh"
#include "BLI_vector.hh"
#include "GPU_texture.h"
@ -116,6 +117,19 @@ struct KerningCacheBLF {
int ascii_table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE];
};
struct GlyphCacheKey {
uint charcode;
uint8_t subpixel;
friend bool operator==(const GlyphCacheKey &a, const GlyphCacheKey &b)
{
return a.charcode == b.charcode && a.subpixel == b.subpixel;
}
uint64_t hash() const
{
return blender::get_default_hash(charcode, subpixel);
Harley marked this conversation as resolved Outdated

get_default_hash(charcode, subpixel) might be more straightforward, unless there's still a reason to use this hash

`get_default_hash(charcode, subpixel)` might be more straightforward, unless there's still a reason to use this hash

My hesitancy is mostly about my own unknowns with get_default_hash

Unicode codepoints max out at U+10FFFF, so with a byte for subpixel I am well within 32-bit integer. But then I see that DefaultHash drops the lower four bits of each before multiplying them?

My hesitancy is mostly about my own unknowns with `get_default_hash` Unicode codepoints max out at U+10FFFF, so with a byte for subpixel I am well within 32-bit integer. But then I see that `DefaultHash` drops the lower four bits of each before multiplying them?

DefaultHash for all integer types is just the value unchanged. Then the two hashes are combined like this: h1 ^ (h2 * 19349669);

My reasoning was more like "just use the default unless we know some reason to do it differently"

`DefaultHash` for all integer types is just the value unchanged. Then the two hashes are combined like this: `h1 ^ (h2 * 19349669);` My reasoning was more like "just use the default unless we know some reason to do it differently"

I can see the multiples being combined like that. The only part that gives me pause is that each part first goes through a change that looks like it drops 4 bits.

I can see the multiples being combined like that. The only part that gives me pause is that each part first goes through a change that looks like it drops 4 bits.

Seems like you're looking at the DefaultHash specialization for pointers. For integers it's this:

#define TRIVIAL_DEFAULT_INT_HASH(TYPE) \
  template<> struct DefaultHash<TYPE> { \
    uint64_t operator()(TYPE value) const \
    { \
      return uint64_t(value); \
    } \
  }

...


TRIVIAL_DEFAULT_INT_HASH(uint32_t);
Seems like you're looking at the `DefaultHash` specialization for pointers. For integers it's this: ```cpp #define TRIVIAL_DEFAULT_INT_HASH(TYPE) \ template<> struct DefaultHash<TYPE> { \ uint64_t operator()(TYPE value) const \ { \ return uint64_t(value); \ } \ } ... TRIVIAL_DEFAULT_INT_HASH(uint32_t); ```

Yup, I sure was. LOL

Yup, I sure was. LOL
}
};
struct GlyphCacheBLF {
/** Font size. */
float size;
@ -132,7 +146,7 @@ struct GlyphCacheBLF {
int fixed_width;
/** The glyphs. */
ListBase bucket[257];
blender::Map<GlyphCacheKey, std::unique_ptr<GlyphBLF>> glyphs;
/** Texture array, to draw the glyphs. */
GPUTexture *texture;
@ -145,9 +159,6 @@ struct GlyphCacheBLF {
};
struct GlyphBLF {
GlyphBLF *next;
GlyphBLF *prev;
/** The character, as UTF-32. */
unsigned int c;
@ -192,6 +203,8 @@ struct GlyphBLF {
int pos[2];
GlyphCacheBLF *glyph_cache;
~GlyphBLF();
};
struct FontBufInfoBLF {

View File

@ -1,43 +0,0 @@
/* SPDX-FileCopyrightText: 2009 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup blf
*
* Internal utility API for BLF.
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "BLI_utildefines.h"
#include "blf_internal.hh"
uint blf_next_p2(uint x)
{
x -= 1;
x |= (x >> 16);
x |= (x >> 8);
x |= (x >> 4);
x |= (x >> 2);
x |= (x >> 1);
x += 1;
return x;
}
uint blf_hash(uint val)
{
uint key;
key = val;
key += ~(key << 16);
key ^= (key >> 5);
key += (key << 3);
key ^= (key >> 13);
key += ~(key << 9);
key ^= (key >> 17);
return key % 257;
}