mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-23 16:43:58 +08:00
optimize complex shaping engine
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user