BLF: Correct the Showing of VFont Not Found Character
When VFont objects use a custom (non-default) font and reference a character that is not contained in that font, our intention is to show placeholder curves that represents "not found". Instead we are currently showing the ".notdef" glyph if there is one defined inside the font or blank space if not. This PR fixes that by altering BLF_character_to_curves so that it returns a boolean success instead of character advance. This way we can properly distinguish "not found" from the return of other empty, non-advancing characters. Pull Request: https://projects.blender.org/blender/blender/pulls/143484
This commit is contained in:
committed by
Harley Acheson
parent
4afe62ee29
commit
276eee8f53
@@ -126,9 +126,14 @@ bool BLF_get_vfont_metrics(int fontid, float *ascend_ratio, float *em_ratio, flo
|
||||
|
||||
/**
|
||||
* Convert a character's outlines into curves.
|
||||
* \return success if the character was found and converted.
|
||||
*/
|
||||
float BLF_character_to_curves(
|
||||
int fontid, unsigned int unicode, ListBase *nurbsbase, const float scale, bool use_fallback);
|
||||
bool BLF_character_to_curves(int fontid,
|
||||
unsigned int unicode,
|
||||
ListBase *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance);
|
||||
|
||||
/**
|
||||
* Check if font supports a particular glyph.
|
||||
|
||||
@@ -1127,14 +1127,18 @@ bool BLF_get_vfont_metrics(int fontid, float *ascend_ratio, float *em_ratio, flo
|
||||
return true;
|
||||
}
|
||||
|
||||
float BLF_character_to_curves(
|
||||
int fontid, uint unicode, ListBase *nurbsbase, const float scale, bool use_fallback)
|
||||
bool BLF_character_to_curves(int fontid,
|
||||
uint unicode,
|
||||
ListBase *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
if (!font) {
|
||||
return 0.0f;
|
||||
return false;
|
||||
}
|
||||
return blf_character_to_curves(font, unicode, nurbsbase, scale, use_fallback);
|
||||
return blf_character_to_curves(font, unicode, nurbsbase, scale, use_fallback, r_advance);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
@@ -1863,6 +1863,11 @@ static FT_GlyphSlot blf_glyphslot_ensure_outline(FontBLF *font, uint charcode, b
|
||||
FontBLF *font_with_glyph = font;
|
||||
FT_UInt glyph_index = use_fallback ? blf_glyph_index_from_charcode(&font_with_glyph, charcode) :
|
||||
blf_get_char_index(font_with_glyph, charcode);
|
||||
|
||||
if (!glyph_index) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!blf_ensure_face(font_with_glyph)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1883,16 +1888,22 @@ static FT_GlyphSlot blf_glyphslot_ensure_outline(FontBLF *font, uint charcode, b
|
||||
return glyph;
|
||||
}
|
||||
|
||||
float blf_character_to_curves(
|
||||
FontBLF *font, uint unicode, ListBase *nurbsbase, const float scale, bool use_fallback)
|
||||
bool blf_character_to_curves(FontBLF *font,
|
||||
uint unicode,
|
||||
ListBase *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance)
|
||||
{
|
||||
FT_GlyphSlot glyph = blf_glyphslot_ensure_outline(font, unicode, use_fallback);
|
||||
if (!glyph) {
|
||||
return 0.0f;
|
||||
*r_advance = 0.0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
blf_glyph_to_curves(glyph->outline, nurbsbase, scale);
|
||||
return float(glyph->advance.x) * scale;
|
||||
*r_advance = float(glyph->advance.x) * scale;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -203,11 +203,12 @@ GlyphBLF *blf_glyph_ensure_icon(
|
||||
/**
|
||||
* Convert a character's outlines into curves.
|
||||
*/
|
||||
float blf_character_to_curves(FontBLF *font,
|
||||
unsigned int unicode,
|
||||
ListBase *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback);
|
||||
bool blf_character_to_curves(FontBLF *font,
|
||||
unsigned int unicode,
|
||||
ListBase *nurbsbase,
|
||||
const float scale,
|
||||
bool use_fallback,
|
||||
float *r_advance);
|
||||
|
||||
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, int x, int y);
|
||||
|
||||
|
||||
@@ -38,6 +38,13 @@ struct VFontData_Metrics {
|
||||
};
|
||||
|
||||
struct VFontData {
|
||||
/**
|
||||
* A hash that maps `uint -> VChar` (code-points to character outlines).
|
||||
*
|
||||
* \note values may be null when the character does not exist in the font.
|
||||
* This is done to differentiate characters known not to exist from
|
||||
* characters that have not yet been loaded.
|
||||
*/
|
||||
GHash *characters;
|
||||
char name[128];
|
||||
|
||||
|
||||
@@ -245,6 +245,9 @@ void BKE_vfont_data_free(VFont *vfont)
|
||||
GHashIterator gh_iter;
|
||||
GHASH_ITER (gh_iter, vfont->data->characters) {
|
||||
VChar *che = static_cast<VChar *>(BLI_ghashIterator_getValue(&gh_iter));
|
||||
if (che == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (che->nurbsbase.first) {
|
||||
Nurb *nu = static_cast<Nurb *>(che->nurbsbase.first);
|
||||
|
||||
@@ -107,9 +107,14 @@ static VFontData *vfont_data_ensure_with_lock(VFont *vfont)
|
||||
return vfont->data;
|
||||
}
|
||||
|
||||
static VChar *vfont_char_find(const VFontData *vfd, char32_t charcode)
|
||||
static bool vfont_char_find(const VFontData *vfd, char32_t charcode, VChar **r_che)
|
||||
{
|
||||
return static_cast<VChar *>(BLI_ghash_lookup(vfd->characters, POINTER_FROM_UINT(charcode)));
|
||||
if (void **che_p = BLI_ghash_lookup_p(vfd->characters, POINTER_FROM_UINT(charcode))) {
|
||||
*r_che = static_cast<VChar *>(*che_p);
|
||||
return true;
|
||||
}
|
||||
*r_che = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,19 +129,19 @@ static VChar *vfont_char_ensure_with_lock(VFont *vfont, char32_t charcode)
|
||||
if (vfont && vfont->data) {
|
||||
VFontData *vfd = vfont->data;
|
||||
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_READ);
|
||||
che = vfont_char_find(vfd, charcode);
|
||||
bool che_found = vfont_char_find(vfd, charcode, &che);
|
||||
BLI_rw_mutex_unlock(&vfont_rwlock);
|
||||
|
||||
/* The character wasn't in the current curve base so load it. */
|
||||
if (che == nullptr) {
|
||||
if (che_found == false) {
|
||||
BLI_rw_mutex_lock(&vfont_rwlock, THREAD_LOCK_WRITE);
|
||||
/* Check it once again, char might have been already load
|
||||
* between previous #BLI_rw_mutex_unlock() and this #BLI_rw_mutex_lock().
|
||||
*
|
||||
* Such a check should not be a bottleneck since it wouldn't
|
||||
* happen often once all the chars are load. */
|
||||
che = vfont_char_find(vfd, charcode);
|
||||
if (che == nullptr) {
|
||||
che_found = vfont_char_find(vfd, charcode, &che);
|
||||
if (che_found == false) {
|
||||
che = BKE_vfontdata_char_from_freetypefont(vfont, charcode);
|
||||
}
|
||||
BLI_rw_mutex_unlock(&vfont_rwlock);
|
||||
@@ -268,7 +273,10 @@ static VChar *vfont_char_find_or_placeholder(const VFontData *vfd,
|
||||
char32_t charcode,
|
||||
VCharPlaceHolder &che_placeholder)
|
||||
{
|
||||
VChar *che = vfd ? vfont_char_find(vfd, charcode) : nullptr;
|
||||
VChar *che = nullptr;
|
||||
if (vfd) {
|
||||
vfont_char_find(vfd, charcode, &che);
|
||||
}
|
||||
if (UNLIKELY(che == nullptr)) {
|
||||
che = vfont_placeholder_ensure(che_placeholder, charcode);
|
||||
}
|
||||
@@ -491,7 +499,8 @@ void BKE_vfont_char_build(Curve *cu,
|
||||
if (!vfd) {
|
||||
return;
|
||||
}
|
||||
VChar *che = vfont_char_find(vfd, charcode);
|
||||
VChar *che;
|
||||
vfont_char_find(vfd, charcode, &che);
|
||||
vfont_char_build_impl(cu, nubase, che, info, ofsx, ofsy, rot, charidx, fsize);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ VFontData *BKE_vfontdata_from_freetypefont(PackedFile *pf)
|
||||
|
||||
static void *vfontdata_copy_characters_value_cb(const void *src)
|
||||
{
|
||||
return BKE_vfontdata_char_copy(static_cast<const VChar *>(src));
|
||||
return src ? BKE_vfontdata_char_copy(static_cast<const VChar *>(src)) : nullptr;
|
||||
}
|
||||
|
||||
VFontData *BKE_vfontdata_copy(const VFontData *vfont_src, const int /*flag*/)
|
||||
@@ -122,8 +122,18 @@ VChar *BKE_vfontdata_char_from_freetypefont(VFont *vfont, uint character)
|
||||
/* need to set a size for embolden, etc. */
|
||||
BLF_size(font_id, 16);
|
||||
|
||||
che->width = BLF_character_to_curves(
|
||||
font_id, character, &che->nurbsbase, vfont->data->metrics.scale, use_fallback);
|
||||
if (!BLF_character_to_curves(font_id,
|
||||
character,
|
||||
&che->nurbsbase,
|
||||
vfont->data->metrics.scale,
|
||||
use_fallback,
|
||||
&che->width))
|
||||
{
|
||||
/* Free but add to the character cache to prevent future lookups
|
||||
* from attempting to load the font again. */
|
||||
MEM_freeN(che);
|
||||
che = nullptr;
|
||||
}
|
||||
|
||||
BLI_ghash_insert(vfont->data->characters, POINTER_FROM_UINT(character), che);
|
||||
BLF_unload_id(font_id);
|
||||
|
||||
Reference in New Issue
Block a user