forked from old/legacy-imlib2
add speculative fotn cache ability - just like we have for images and pixmaps
and ximages. SVN revision: 452
This commit is contained in:
parent
b37dfafbb9
commit
d426a29288
73
api.c
73
api.c
|
@ -1055,3 +1055,76 @@ imlib_list_font_path(int *number_return)
|
|||
{
|
||||
return __imlib_list_font_path(number_return);
|
||||
}
|
||||
|
||||
int
|
||||
imlib_text_get_index_and_location(Imlib_Font *font,
|
||||
Imlib_Text_Direction direction,
|
||||
char *text, int x, int y,
|
||||
int *char_x_return, int *char_y_return,
|
||||
int *char_width_return,
|
||||
int *char_height_return)
|
||||
{
|
||||
ImlibFont *fn;
|
||||
int w, h, cx, cy, cw, ch, cp, xx, yy;
|
||||
|
||||
fn = (ImlibFont *)font;
|
||||
switch(direction)
|
||||
{
|
||||
case IMLIB_TEXT_TO_RIGHT:
|
||||
return __imlib_char_pos(fn, text, x, y, char_x_return, char_y_return,
|
||||
char_width_return, char_height_return);
|
||||
break;
|
||||
case IMLIB_TEXT_TO_LEFT:
|
||||
__imlib_calc_size(fn, &w, &h, text);
|
||||
xx = w - x;
|
||||
yy = h - y;
|
||||
cp = __imlib_char_pos(fn, text, xx, yy, &cx, &cy, &cw, &ch);
|
||||
cx = 1 + w - cx - cw;
|
||||
if (char_x_return)
|
||||
*char_x_return = cx;
|
||||
if (char_y_return)
|
||||
*char_y_return = cy;
|
||||
if (char_width_return)
|
||||
*char_width_return = cw;
|
||||
if (char_height_return)
|
||||
*char_height_return = ch;
|
||||
return cp;
|
||||
break;
|
||||
case IMLIB_TEXT_TO_DOWN:
|
||||
__imlib_calc_size(fn, &w, &h, text);
|
||||
xx = h - y;
|
||||
yy = x;
|
||||
cp = __imlib_char_pos(fn, text, xx, yy, &cx, &cy, &cw, &ch);
|
||||
if (char_x_return)
|
||||
*char_x_return = cy;
|
||||
if (char_y_return)
|
||||
*char_y_return = cx;
|
||||
if (char_width_return)
|
||||
*char_width_return = ch;
|
||||
if (char_height_return)
|
||||
*char_height_return = cw;
|
||||
return cp;
|
||||
break;
|
||||
case IMLIB_TEXT_TO_UP:
|
||||
__imlib_calc_size(fn, &w, &h, text);
|
||||
xx = w - y;
|
||||
yy = x;
|
||||
cp = __imlib_char_pos(fn, text, xx, yy, &cx, &cy, &cw, &ch);
|
||||
cy = 1 + h - cy - ch;
|
||||
if (char_x_return)
|
||||
*char_x_return = cy;
|
||||
if (char_y_return)
|
||||
*char_y_return = cx;
|
||||
if (char_width_return)
|
||||
*char_width_return = ch;
|
||||
if (char_height_return)
|
||||
*char_height_return = cw;
|
||||
return cp;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
8
api.h
8
api.h
|
@ -277,7 +277,13 @@ void imlib_get_text_size(Imlib_Font font, Imlib_Text_Direction direction,
|
|||
void imlib_add_path_to_font_path(char *path);
|
||||
void imlib_remove_path_from_font_path(char *path);
|
||||
char **imlib_list_font_path(int *number_return);
|
||||
|
||||
int imlib_text_get_index_and_location(Imlib_Font *font,
|
||||
Imlib_Text_Direction direction,
|
||||
char *text, int x, int y,
|
||||
int *char_x_return, int *char_y_return,
|
||||
int *char_width_return,
|
||||
int *char_height_return);
|
||||
|
||||
#if 0
|
||||
void imlib_image_copy_alpha_to_image(Imlib_Image image_source,
|
||||
Imlib_Image image_destination,
|
||||
|
|
313
font.c
313
font.c
|
@ -11,9 +11,12 @@
|
|||
#define TT_VALID( handle ) ( ( handle ).z != NULL )
|
||||
|
||||
/* cached font list and font path */
|
||||
static ImlibFont *fonts = NULL;
|
||||
static int fpath_num = 0;
|
||||
static char **fpath = NULL;
|
||||
static ImlibFont *fonts = NULL;
|
||||
static int fpath_num = 0;
|
||||
static char **fpath = NULL;
|
||||
static TT_Engine engine;
|
||||
static char have_engine = 0;
|
||||
static int font_cache_size = 0;
|
||||
|
||||
/* lookupt table of raster_map -> RGBA Alpha values */
|
||||
static int rend_lut[9] =
|
||||
|
@ -88,13 +91,24 @@ __imlib_list_font_path(int *num_ret)
|
|||
ImlibFont *
|
||||
__imlib_find_cached_font(char *fontname)
|
||||
{
|
||||
ImlibFont *f;
|
||||
ImlibFont *pf, *f;
|
||||
|
||||
pf = NULL;
|
||||
f = fonts;
|
||||
while(f)
|
||||
{
|
||||
if (!strcmp(f->name, fontname))
|
||||
return f;
|
||||
{
|
||||
/* if it's not the top of the list - move it there */
|
||||
if (pf)
|
||||
{
|
||||
pf->next = f->next;
|
||||
f->next = fonts;
|
||||
fonts = f;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
pf = f;
|
||||
f = f->next;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -108,8 +122,6 @@ __imlib_load_font(char *fontname)
|
|||
TT_CharMap char_map;
|
||||
TT_Glyph_Metrics metrics;
|
||||
TT_Instance_Metrics imetrics;
|
||||
static TT_Engine engine;
|
||||
static char have_engine = 0;
|
||||
int dpi = 96;
|
||||
unsigned short i, n, code, load_flags;
|
||||
unsigned short num_glyphs = 0, no_cmap = 0;
|
||||
|
@ -184,6 +196,7 @@ __imlib_load_font(char *fontname)
|
|||
f->references = 1;
|
||||
/* remember engine */
|
||||
f->engine = engine;
|
||||
f->mem_use = 0;
|
||||
error = TT_Open_Face(f->engine, file, &f->face);
|
||||
if (error)
|
||||
{
|
||||
|
@ -290,61 +303,11 @@ __imlib_load_font(char *fontname)
|
|||
/* all ent well in loading, so add to head of font list and return */
|
||||
f->next = fonts;
|
||||
fonts = f;
|
||||
/* we dont need the file handle hanging around so flush it out */
|
||||
TT_Flush_Face(f->face);
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_free_font(ImlibFont *font)
|
||||
{
|
||||
int i;
|
||||
ImlibFont *f, *pf;
|
||||
|
||||
/* defererence */
|
||||
font->references--;
|
||||
/* if still referenced exit here */
|
||||
if (font->references > 0)
|
||||
return;
|
||||
|
||||
/* remove form font cache list */
|
||||
pf = NULL;
|
||||
f = fonts;
|
||||
while (f)
|
||||
{
|
||||
if (f == font)
|
||||
{
|
||||
if (!pf)
|
||||
fonts = f->next;
|
||||
else
|
||||
pf->next = f->next;
|
||||
f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pf = f;
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
/* free freetype instance stuff */
|
||||
TT_Done_Instance(font->instance);
|
||||
TT_Close_Face(font->face);
|
||||
/* free all cached glyphs */
|
||||
for (i = 0; i < font->num_glyph; i++)
|
||||
{
|
||||
if ((font->glyphs_cached_right) && (font->glyphs_cached_right[i]))
|
||||
__imlib_destroy_font_raster(font->glyphs_cached_right[i]);
|
||||
if (!TT_VALID(font->glyphs[i]))
|
||||
TT_Done_Glyph(font->glyphs[i]);
|
||||
}
|
||||
/* free glyph info */
|
||||
free(font->glyphs);
|
||||
/* free glyph cache arrays */
|
||||
if (font->glyphs_cached_right)
|
||||
free(font->glyphs_cached_right);
|
||||
/* free font struct & name */
|
||||
free(font->name);
|
||||
free(font);
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_calc_size(ImlibFont *f, int *width, int *height, char *text)
|
||||
{
|
||||
|
@ -486,6 +449,9 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, char *text,
|
|||
((ymax - ymin) / 64) + 1);
|
||||
TT_Get_Glyph_Pixmap(fn->glyphs[j], rtmp, -xmin, -ymin);
|
||||
fn->glyphs_cached_right[j] = rtmp;
|
||||
fn->mem_use +=
|
||||
(((xmax - xmin) / 64) + 1) *
|
||||
(((ymax - ymin) / 64) + 1);
|
||||
}
|
||||
|
||||
/* Blit-or the resulting small pixmap into the biggest one */
|
||||
|
@ -608,3 +574,232 @@ __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx, int dry, char *text,
|
|||
__imlib_destroy_font_raster(rmap);
|
||||
}
|
||||
|
||||
int
|
||||
__imlib_char_pos(ImlibFont *fn, char *text, int x, int y,
|
||||
int *cx, int *cy, int *cw, int *ch)
|
||||
{
|
||||
int i, px, ppx;
|
||||
TT_Glyph_Metrics gmetrics;
|
||||
|
||||
if ((y < 0) || (y > (fn->ascent + fn->descent)))
|
||||
return -1;
|
||||
if (cy)
|
||||
*cy = 0;
|
||||
if (ch)
|
||||
*ch = fn->ascent + fn->descent;
|
||||
ppx = 0;
|
||||
px = 0;
|
||||
for (i = 0; text[i]; i++)
|
||||
{
|
||||
unsigned char j;
|
||||
|
||||
j = text[i];
|
||||
if (!TT_VALID(fn->glyphs[j]))
|
||||
continue;
|
||||
TT_Get_Glyph_Metrics(fn->glyphs[j], &gmetrics);
|
||||
ppx = px;
|
||||
if (i == 0)
|
||||
px += ((-gmetrics.bearingX) / 64);
|
||||
if (text[i + 1] == 0)
|
||||
px += (gmetrics.bbox.xMax / 64);
|
||||
else
|
||||
px += gmetrics.advance / 64;
|
||||
if ((x >= ppx) && (x < px))
|
||||
{
|
||||
if (cx)
|
||||
*cx = ppx;
|
||||
if (cw)
|
||||
*cw = px - ppx;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
char **
|
||||
__imlib_list_fonts(int *num_ret)
|
||||
{
|
||||
int i, j, d, l = 0;
|
||||
char **list = NULL, **dir, *path;
|
||||
TT_Error error;
|
||||
|
||||
/* if we dont have a truetype font engine yet - make one */
|
||||
if (!have_engine)
|
||||
{
|
||||
error = TT_Init_FreeType(&engine);
|
||||
if (error)
|
||||
return NULL;
|
||||
have_engine = 1;
|
||||
}
|
||||
for (i = 0; i < fpath_num; i++)
|
||||
{
|
||||
dir = __imlib_FileDir(fpath[i], &d);
|
||||
if (dir)
|
||||
{
|
||||
for (j = 0; j < d; j++)
|
||||
{
|
||||
if (__imlib_FileIsFile(dir[j]))
|
||||
{
|
||||
TT_Face f;
|
||||
|
||||
path = malloc(strlen(fpath[i]) + 1 + strlen(dir[j] + 1));
|
||||
strcpy(path, fpath[i]);
|
||||
strcat(path, "/");
|
||||
strcat(path, dir[j]);
|
||||
error = TT_Open_Face(engine, path, &f);
|
||||
free(path);
|
||||
if (!error)
|
||||
{
|
||||
TT_Close_Face(f);
|
||||
l++;
|
||||
if (list)
|
||||
list = realloc(list, sizeof(char *) * l);
|
||||
else
|
||||
list = malloc(sizeof(char *));
|
||||
list[l - 1] = strdup(dir[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(dir);
|
||||
}
|
||||
}
|
||||
*num_ret = l;
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
__imlib_get_cached_font_size(void)
|
||||
{
|
||||
ImlibFont *f;
|
||||
int num = 0;
|
||||
|
||||
f = fonts;
|
||||
while(f)
|
||||
{
|
||||
if (f->references == 0)
|
||||
num += f->mem_use;
|
||||
f = f->next;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_flush_font_cache(void)
|
||||
{
|
||||
int size;
|
||||
ImlibFont *flast, *f;
|
||||
|
||||
size = __imlib_get_cached_font_size();
|
||||
while (size > font_cache_size)
|
||||
{
|
||||
flast = NULL;
|
||||
f = fonts;
|
||||
while (f)
|
||||
{
|
||||
if (f->references == 0)
|
||||
flast = f;
|
||||
f = f->next;
|
||||
}
|
||||
if (flast)
|
||||
{
|
||||
size -= flast->mem_use;
|
||||
__imlib_nuke_font(flast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_purge_font_cache(void)
|
||||
{
|
||||
ImlibFont *pf, *f;
|
||||
|
||||
f = fonts;
|
||||
while(f)
|
||||
{
|
||||
pf = f;
|
||||
f = f->next;
|
||||
if (pf->references == 0)
|
||||
__imlib_nuke_font(pf);
|
||||
}
|
||||
if (!fonts)
|
||||
{
|
||||
if (have_engine)
|
||||
{
|
||||
TT_Done_FreeType(engine);
|
||||
have_engine = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
__imlib_get_font_cache_size(void)
|
||||
{
|
||||
return font_cache_size;
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_set_font_cache_size(int size)
|
||||
{
|
||||
if (size < 0)
|
||||
size = 0;
|
||||
font_cache_size = size;
|
||||
__imlib_flush_font_cache();
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_free_font(ImlibFont *font)
|
||||
{
|
||||
/* defererence */
|
||||
font->references--;
|
||||
/* if still referenced exit here */
|
||||
if (font->references > 0)
|
||||
return;
|
||||
__imlib_flush_font_cache();
|
||||
}
|
||||
|
||||
void
|
||||
__imlib_nuke_font(ImlibFont *font)
|
||||
{
|
||||
int i;
|
||||
ImlibFont *f, *pf;
|
||||
|
||||
/* remove form font cache list */
|
||||
pf = NULL;
|
||||
f = fonts;
|
||||
while (f)
|
||||
{
|
||||
if (f == font)
|
||||
{
|
||||
if (!pf)
|
||||
fonts = f->next;
|
||||
else
|
||||
pf->next = f->next;
|
||||
f = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
pf = f;
|
||||
f = f->next;
|
||||
}
|
||||
}
|
||||
/* free freetype instance stuff */
|
||||
TT_Done_Instance(font->instance);
|
||||
TT_Close_Face(font->face);
|
||||
/* free all cached glyphs */
|
||||
for (i = 0; i < font->num_glyph; i++)
|
||||
{
|
||||
if ((font->glyphs_cached_right) && (font->glyphs_cached_right[i]))
|
||||
__imlib_destroy_font_raster(font->glyphs_cached_right[i]);
|
||||
if (!TT_VALID(font->glyphs[i]))
|
||||
TT_Done_Glyph(font->glyphs[i]);
|
||||
}
|
||||
/* free glyph info */
|
||||
free(font->glyphs);
|
||||
/* free glyph cache arrays */
|
||||
if (font->glyphs_cached_right)
|
||||
free(font->glyphs_cached_right);
|
||||
/* free font struct & name */
|
||||
free(font->name);
|
||||
free(font);
|
||||
}
|
||||
|
||||
|
|
11
font.h
11
font.h
|
@ -20,6 +20,7 @@ struct _imlib_font
|
|||
int max_ascent;
|
||||
int descent;
|
||||
int ascent;
|
||||
int mem_use;
|
||||
};
|
||||
|
||||
TT_Raster_Map *__imlib_create_font_raster(int width, int height);
|
||||
|
@ -37,5 +38,13 @@ void __imlib_render_str(ImlibImage *im, ImlibFont *fn, int drx,
|
|||
DATA8 r, DATA8 g, DATA8 b, DATA8 a,
|
||||
char dir, int *retw, int *reth, int blur,
|
||||
int *nextx, int *nexty, ImlibOp op);
|
||||
|
||||
int __imlib_char_pos(ImlibFont *fn, char *text, int x, int y,
|
||||
int *cx, int *cy, int *cw, int *ch);
|
||||
char **__imlib_list_fonts(int *num_ret);
|
||||
int __imlib_get_cached_font_size(void);
|
||||
void __imlib_flush_font_cache(void);
|
||||
void __imlib_purge_font_cache(void);
|
||||
int __imlib_get_font_cache_size(void);
|
||||
void __imlib_set_font_cache_size(int size);
|
||||
void __imlib_nuke_font(ImlibFont *font);
|
||||
#endif
|
||||
|
|
31
main.c
31
main.c
|
@ -279,11 +279,11 @@ int main (int argc, char **argv)
|
|||
}
|
||||
if (fon)
|
||||
{
|
||||
int retw, reth, ty, nx, ny;
|
||||
int retw, reth, ty, nx, ny, cx, cy, cw, ch, cp;
|
||||
|
||||
if (!str)
|
||||
str = "This is a test string";
|
||||
ty = y;
|
||||
ty = 50;
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
Imlib_Color cl;
|
||||
|
@ -297,16 +297,33 @@ int main (int argc, char **argv)
|
|||
cl.blue = 255;
|
||||
cl.alpha = al;
|
||||
|
||||
imlib_text_draw_with_return_metrics(fn, im, x, ty,
|
||||
imlib_text_draw_with_return_metrics(fn, im, 50, ty,
|
||||
IMLIB_TEXT_TO_RIGHT,
|
||||
str, &cl,
|
||||
IMLIB_OP_COPY,
|
||||
&retw, &reth,
|
||||
&nx, &ny);
|
||||
up = imlib_update_append_rect(up, px, ty + (py - y), retw, reth);
|
||||
up = imlib_update_append_rect(up, x, ty, retw, reth);
|
||||
/* up = imlib_update_append_rect(up, px, ty + (py - y), retw, reth);*/
|
||||
up = imlib_update_append_rect(up, 50, ty, retw, reth);
|
||||
ty += ny;
|
||||
}
|
||||
cp = imlib_text_get_index_and_location(fn,
|
||||
IMLIB_TEXT_TO_RIGHT,
|
||||
str, x - 50, y - 50,
|
||||
&cx, &cy, &cw, &ch);
|
||||
if (cp >= 0)
|
||||
{
|
||||
#if 0
|
||||
GC gc;
|
||||
XGCValues gcv;
|
||||
|
||||
gc = XCreateGC(disp, win, 0, &gcv);
|
||||
XSetForeground(disp, gc, 0xffff);
|
||||
XDrawRectangle(disp, win, gc, 50 + cx, 50 + cy, cw, ch);
|
||||
XFreeGC(disp, gc);
|
||||
#endif
|
||||
printf("over char %c\n", str[cp]);
|
||||
}
|
||||
}
|
||||
if ((px != x) || (py != y))
|
||||
{
|
||||
|
@ -350,7 +367,7 @@ int main (int argc, char **argv)
|
|||
0, 0, 50, 50,
|
||||
0, 50, 50, h - 50, NULL, IMLIB_OP_COPY);
|
||||
up = imlib_update_append_rect(up, 0, 50, 50, h - 50);
|
||||
up = imlib_updates_merge(up, w, h);
|
||||
up = imlib_updates_merge_for_rendering(up, w, h);
|
||||
imlib_render_image_updates_on_drawable(im, up, disp, win, vis, cm,
|
||||
depth, dith, 0, 0, NULL);
|
||||
if ((px != x) || (py != y))
|
||||
|
@ -371,7 +388,7 @@ int main (int argc, char **argv)
|
|||
u = imlib_updates_get_next(u);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
#if 0
|
||||
{
|
||||
Imlib_Updates up2;
|
||||
GC gc;
|
||||
|
|
Loading…
Reference in New Issue