add speculative fotn cache ability - just like we have for images and pixmaps

and ximages.


SVN revision: 452
This commit is contained in:
Carsten Haitzler 1999-09-29 17:25:52 +00:00
parent b37dfafbb9
commit d426a29288
5 changed files with 368 additions and 68 deletions

73
api.c
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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
View File

@ -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;