forked from external/yambar
commit
85ce6dc8ef
1 changed files with 61 additions and 20 deletions
|
@ -10,21 +10,26 @@
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
#include "../plugin.h"
|
#include "../plugin.h"
|
||||||
|
|
||||||
|
struct text_run_cache {
|
||||||
|
uint64_t hash;
|
||||||
|
struct fcft_text_run *run;
|
||||||
|
int width;
|
||||||
|
bool in_use;
|
||||||
|
};
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
char *text;
|
char *text;
|
||||||
size_t max_len;
|
size_t max_len;
|
||||||
|
|
||||||
struct {
|
size_t cache_size;
|
||||||
uint64_t hash;
|
struct text_run_cache *cache;
|
||||||
struct fcft_text_run *run;
|
|
||||||
int width;
|
|
||||||
} cached;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct eprivate {
|
struct eprivate {
|
||||||
/* Set when instantiating */
|
/* Set when instantiating */
|
||||||
char *text;
|
char *text;
|
||||||
|
|
||||||
|
ssize_t cache_idx;
|
||||||
const struct fcft_glyph **glyphs;
|
const struct fcft_glyph **glyphs;
|
||||||
const struct fcft_glyph **allocated_glyphs;
|
const struct fcft_glyph **allocated_glyphs;
|
||||||
long *kern_x;
|
long *kern_x;
|
||||||
|
@ -66,20 +71,27 @@ begin_expose(struct exposable *exposable)
|
||||||
e->glyphs = e->allocated_glyphs = NULL;
|
e->glyphs = e->allocated_glyphs = NULL;
|
||||||
e->num_glyphs = 0;
|
e->num_glyphs = 0;
|
||||||
e->kern_x = NULL;
|
e->kern_x = NULL;
|
||||||
|
e->cache_idx = -1;
|
||||||
|
|
||||||
uint64_t hash = sdbm_hash(e->text);
|
uint64_t hash = sdbm_hash(e->text);
|
||||||
|
|
||||||
if (p->cached.hash == hash) {
|
for (size_t i = 0; i < p->cache_size; i++) {
|
||||||
e->glyphs = p->cached.run->glyphs;
|
if (p->cache[i].hash == hash) {
|
||||||
e->num_glyphs = p->cached.run->count;
|
assert(p->cache[i].run != NULL);
|
||||||
e->kern_x = calloc(p->cached.run->count, sizeof(e->kern_x[0]));
|
|
||||||
|
|
||||||
exposable->width =
|
p->cache[i].in_use = true;
|
||||||
exposable->particle->left_margin +
|
e->cache_idx = i;
|
||||||
p->cached.width +
|
e->glyphs = p->cache[i].run->glyphs;
|
||||||
exposable->particle->right_margin;
|
e->num_glyphs = p->cache[i].run->count;
|
||||||
|
e->kern_x = calloc(p->cache[i].run->count, sizeof(e->kern_x[0]));
|
||||||
|
|
||||||
return exposable->width;
|
exposable->width =
|
||||||
|
exposable->particle->left_margin +
|
||||||
|
p->cache[i].width +
|
||||||
|
exposable->particle->right_margin;
|
||||||
|
|
||||||
|
return exposable->width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t chars = mbstowcs(NULL, e->text, 0);
|
size_t chars = mbstowcs(NULL, e->text, 0);
|
||||||
|
@ -96,11 +108,32 @@ begin_expose(struct exposable *exposable)
|
||||||
for (size_t i = 0; i < run->count; i++)
|
for (size_t i = 0; i < run->count; i++)
|
||||||
w += run->glyphs[i]->advance.x;
|
w += run->glyphs[i]->advance.x;
|
||||||
|
|
||||||
fcft_text_run_destroy(p->cached.run);
|
ssize_t cache_idx = -1;
|
||||||
p->cached.hash = hash;
|
for (size_t i = 0; i < p->cache_size; i++) {
|
||||||
p->cached.run = run;
|
if (p->cache[i].run == NULL || !p->cache[i].in_use) {
|
||||||
p->cached.width = w;
|
fcft_text_run_destroy(p->cache[i].run);
|
||||||
|
cache_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache_idx < 0) {
|
||||||
|
size_t new_size = p->cache_size + 1;
|
||||||
|
struct text_run_cache *new_cache = realloc(
|
||||||
|
p->cache, new_size * sizeof(new_cache[0]));
|
||||||
|
|
||||||
|
p->cache_size = new_size;
|
||||||
|
p->cache = new_cache;
|
||||||
|
cache_idx = new_size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(cache_idx >= 0 && cache_idx < p->cache_size);
|
||||||
|
p->cache[cache_idx].hash = hash;
|
||||||
|
p->cache[cache_idx].run = run;
|
||||||
|
p->cache[cache_idx].width = w;
|
||||||
|
p->cache[cache_idx].in_use = true;
|
||||||
|
|
||||||
|
e->cache_idx = cache_idx;
|
||||||
e->num_glyphs = run->count;
|
e->num_glyphs = run->count;
|
||||||
e->glyphs = run->glyphs;
|
e->glyphs = run->glyphs;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +180,11 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
|
||||||
const struct eprivate *e = exposable->private;
|
const struct eprivate *e = exposable->private;
|
||||||
const struct fcft_font *font = exposable->particle->font;
|
const struct fcft_font *font = exposable->particle->font;
|
||||||
|
|
||||||
|
if (e->cache_idx >= 0) {
|
||||||
|
struct private *priv = exposable->particle->private;
|
||||||
|
priv->cache[e->cache_idx].in_use = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (e->num_glyphs == 0)
|
if (e->num_glyphs == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -247,7 +285,9 @@ static void
|
||||||
particle_destroy(struct particle *particle)
|
particle_destroy(struct particle *particle)
|
||||||
{
|
{
|
||||||
struct private *p = particle->private;
|
struct private *p = particle->private;
|
||||||
fcft_text_run_destroy(p->cached.run);
|
for (size_t i = 0; i < p->cache_size; i++)
|
||||||
|
fcft_text_run_destroy(p->cache[i].run);
|
||||||
|
free(p->cache);
|
||||||
free(p->text);
|
free(p->text);
|
||||||
free(p);
|
free(p);
|
||||||
particle_default_destroy(particle);
|
particle_default_destroy(particle);
|
||||||
|
@ -259,7 +299,8 @@ string_new(struct particle *common, const char *text, size_t max_len)
|
||||||
struct private *p = calloc(1, sizeof(*p));
|
struct private *p = calloc(1, sizeof(*p));
|
||||||
p->text = strdup(text);
|
p->text = strdup(text);
|
||||||
p->max_len = max_len;
|
p->max_len = max_len;
|
||||||
p->cached.hash = -1;
|
p->cache_size = 0;
|
||||||
|
p->cache = NULL;
|
||||||
|
|
||||||
common->private = p;
|
common->private = p;
|
||||||
common->destroy = &particle_destroy;
|
common->destroy = &particle_destroy;
|
||||||
|
|
Loading…
Add table
Reference in a new issue