optimize complex shaping engine

This commit is contained in:
Vincent Wei
2019-04-08 17:52:46 +08:00
parent 4ea2e11c5a
commit 7e776f6b78
+113 -33
View File
@@ -58,10 +58,121 @@
#include "textruns.h"
#include "layout.h"
#include "glyph.h"
#include "list.h"
#include <hb.h>
#include <hb-ft.h>
typedef struct _FtFontInfo {
struct list_head list;
LOGFONT* lf;
ScriptType st;
FT_Face face;
hb_font_t* hb_font;
int dfi;
} FtFontInfo;
struct _SEInstance {
int signature;
int nr_fonts;
struct list_head cached_fonts;
};
static hb_font_t* get_hb_font_for_script(SEInstance* inst,
LOGFONT* lf, ScriptType st, Uchar32 uc, int* dfi)
{
struct list_head* f;
FT_Face face;
hb_font_t* hb_font;
FtFontInfo *new_fi;
FONT_RES* font_res;
list_for_each(f, &inst->cached_fonts) {
FtFontInfo *fi = (FtFontInfo*)f;
if (fi->lf == lf && fi->st == st) {
*dfi = fi->dfi;
return fi->hb_font;
}
}
face = (FT_Face)__mg_ft2_get_face(lf, uc, dfi);
if (face == NULL) {
_WRN_PRINTF("Cannot get FT2 face for logfont (%p) and uc (0x%x)\n",
lf, uc);
return NULL;
}
hb_font = hb_ft_font_create_referenced(face);
//hb_font = hb_ft_font_create(face, NULL);
if (hb_font == NULL)
return NULL;
new_fi = mg_slice_new(FtFontInfo);
new_fi->lf = lf;
new_fi->st = st;
new_fi->face = face;
new_fi->hb_font = hb_font;
new_fi->dfi = *dfi;
font_res = (FONT_RES*)lf;
AddResRef(font_res->key);
list_add_tail(&new_fi->list, &inst->cached_fonts);
inst->nr_fonts++;
return hb_font;
}
static SEInstance* create_instance(void)
{
SEInstance* inst;
inst = mg_slice_new(SEInstance);
inst->signature = 0x77520388;
inst->nr_fonts = 0;
INIT_LIST_HEAD(&inst->cached_fonts);
_DBG_PRINTF("%s: new complex shaping engine instance: %p\n",
__FUNCTION__, inst);
return inst;
}
static BOOL destroy_instance(SEInstance* inst)
{
_DBG_PRINTF("%s: destroy complex shaping engine instance: %p\n",
__FUNCTION__, inst);
if (inst->signature != 0x77520388) {
_WRN_PRINTF("you passed a non-complex shaping engine instance.");
return FALSE;
}
while (!list_empty(&inst->cached_fonts)) {
FONT_RES* font_res;
FtFontInfo *fi = (FtFontInfo*)inst->cached_fonts.prev;
list_del(inst->cached_fonts.prev);
hb_font_destroy(fi->hb_font);
font_res = (FONT_RES*)fi->lf;
if (font_res->key) {
int rc = ReleaseRes(font_res->key);
_DBG_PRINTF("%s: ref count of logfont (%p): %d\n",
__FUNCTION__, fi->lf, rc);
}
mg_slice_delete(FtFontInfo, fi);
inst->nr_fonts--;
}
assert(inst->nr_fonts == 0);
mg_slice_delete(SEInstance, inst);
return TRUE;
}
static BOOL shape_layout_run(SEInstance* inst,
const TEXTRUNS* info, const LayoutRun* run,
GlyphString* gs)
@@ -69,19 +180,12 @@ static BOOL shape_layout_run(SEInstance* inst,
BOOL ok = FALSE;
int dfi;
unsigned int i, nr_glyphs;
FT_Face face = NULL;
hb_buffer_t *hb_buf = NULL;
hb_font_t *hb_font = NULL;
hb_glyph_info_t *glyph_info;
hb_glyph_position_t *glyph_pos;
int last_cluster;
face = (FT_Face)__mg_ft2_get_face(run->lf, run->ucs[0], &dfi);
if (face == NULL) {
_WRN_PRINTF("Can not get FT2 face object for layout run: %p\n", run);
return FALSE;
}
hb_buf = hb_buffer_create();
if (hb_buf == NULL)
goto error;
@@ -96,7 +200,7 @@ static BOOL shape_layout_run(SEInstance* inst,
hb_buffer_set_language(hb_buf,
hb_language_from_string(LanguageCodeToISO639s1(run->lc), -1));
hb_font = hb_ft_font_create(face, NULL);
hb_font = get_hb_font_for_script(inst, run->lf, run->st, run->ucs[0], &dfi);
if (hb_font == NULL)
goto error;
@@ -153,39 +257,15 @@ static BOOL shape_layout_run(SEInstance* inst,
error:
if (hb_font)
hb_font_destroy(hb_font);
if (hb_buf)
hb_buffer_destroy(hb_buf);
return ok;
}
struct _SEInstance {
const char* name;
int ref_count;
};
static struct _SEInstance shaping_engine_complex = {
"Complex Shapping Engine", 0
};
static BOOL destroy_instance(SEInstance* instance)
{
if (instance == &shaping_engine_complex) {
shaping_engine_complex.ref_count--;
return TRUE;
}
_WRN_PRINTF("you are destroying a non-complex shaping engine instance.");
return FALSE;
}
BOOL GUIAPI InitComplexShapingEngine(TEXTRUNS* truns)
{
shaping_engine_complex.ref_count++;
truns->sei.inst = &shaping_engine_complex;
truns->sei.inst = create_instance();
truns->sei.shape = shape_layout_run;
truns->sei.free = destroy_instance;
return TRUE;