From e3f2cc22ec703a860b693ebe756aa2a473ec484f Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Sun, 17 Feb 2019 12:56:35 +0800 Subject: [PATCH] tune BIDILogGlyphs2VisGlyphsEx and BIDILogGlyphs2VisGlyphs --- include/gdi.h | 98 +++++++++++++++--------------- src/font/charset-bidi.c | 128 +++++++++++++++++++++++++--------------- src/include/bidi.h | 7 ++- src/newgdi/bidi.c | 62 +++++++++---------- 4 files changed, 164 insertions(+), 131 deletions(-) diff --git a/include/gdi.h b/include/gdi.h index 09ab9d08..3831be49 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -11104,64 +11104,64 @@ MG_EXPORT int GUIAPI BIDIGetTextVisualGlyphs (LOGFONT* log_font, const char* text, int text_len, Glyph32** glyphs, GLYPHMAPINFO** glyphs_map); -/** \fn BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx (LOGFONT* log_font, - * Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyph_map, int pel) - * \brief Reorder the specified logical glyph string to the visual glyph string. +/* + * \var typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos) + * \brief The prototype of the user defined function to reverse an array. * - * This function reorders the logical glyph string in place to a visual - * glyphs string. If \a index_map is not NULL, it also returns - * the index of logical glyphs. + * The function reverse an array pointed by \a extra from the position + * specified by \a pos for the length specified by \a len. + * + * \sa BIDILogGlyphs2VisGlyphsEx + */ +typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos); + +/** \fn BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx (LOGFONT* log_font, + * Glyph32* glyphs, int nr_glyphs, int pel, + * void* extra, CB_REVERSE_EXTRA cb_reverse_extra) + * \brief Reorder the specified logical glyph string in visual order and + * reorder an extra array to reflect the visule order of the glyphs. + * + * This function reorders the logical glyph string in place to visual order. + * If \a extra and \a cb_reverse_extra are both not NULL, it also reorders + * the array pointed by \a extra by calling the callback function + * \a cb_reverse_extra. + * + * \param log_font The logical font. + * \param glyphs The pointer to the glyph string. + * \param nr_glyphs The length of the glyph string. + * \param pel The paragraph embedding level, can be one of the following values: + * - 0: Level 0 (left to right) + * - 1: Level 1 (right to left) + * - others: Determine according to the heuristic given in + * steps P2 and P3 of the Unicode bidirectional algorithm. + * \param extra The pointer to the extra array to reorder; can be NULL. + * \param cb_reverse_extra The callback function to reverse the extra array. + * + * \return TRUE on success, otherwise FALSE. + */ +MG_EXPORT BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx (LOGFONT* log_font, + Glyph32* glyphs, int nr_glyphs, int pel, + void* extra, CB_REVERSE_EXTRA cb_reverse_extra); + +/** \fn BOOL GUIAPI BIDILogGlyphs2VisGlyphs (LOGFONT* log_font, + * Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyphs_map) + * \brief Reorder the specified logical glyph string in visual order and + * reorder glyph map if specified. + * + * This function reorders the logical glyph string in place to visual order. + * If \a glyphs_map is not NULL, it also reorders + * the map to reflect the visual order. * * \param log_font The logical font. * \param glyphs The pointer to the glyph string. * \param nr_glyphs The length of the glyph string. * \param glyphs_map The position map returned by \a BIDIGetTextLogicalGlyphs; * can be NULL. - * \param pel The paragraph embedding level, can be one of the following values: - * - 0: Level 0 (left to right) - * - 1: Level 1 (right to left) - * - others: Determine according to the heuristic given in - * steps P2 and P3 of the Unicode bidirectional algorithm. * - * \return TRUE on success, otherwise FALSE. + * \return The pointer to the visual glyphs; NULL when error. */ -MG_EXPORT BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx (LOGFONT* log_font, - Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyph_map, int pel); - -/** obsolete; use BIDILogGlyphs2VisGlyphsEx instead */ -static inline Glyph32* BIDILogGlyphs2VisGlyphs (LOGFONT* log_font, - Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyph_map) -{ - if (BIDILogGlyphs2VisGlyphsEx (log_font, glyphs, nr_glyphs, glyph_map, -1)) - return glyphs; - - return NULL; -} - -/** \fn BOOL GUIAPI BIDIGetVisualGlyphIndexMap (LOGFONT* log_font, - * Glyph32* glyphs, int nr_glyphs, int** index_map, int pel) - * \brief Reorder the specified logical glyph string to the visual glyph string. - * - * This function reorders the logical glyph string in place to a visual - * glyphs string. If \a index_map is not NULL, it also returns - * the index of logical glyphs. - * - * \param log_font The logical font. - * \param glyphs The pointer to the glyph string. - * \param nr_glyphs The length of the glyph string. - * \param index_map The pointer to the position map from the logical glyph string to - * the visual glyph string. If *index_map is NULL, the function will - * try to allocate a new one. The caller should free it when it is not useful. - * \param pel The paragraph embedding level, can be one of the following values: - * - 0: Level 0 (left to right) - * - 1: Level 1 (right to left) - * - others: Determine according to the heuristic given in - * steps P2 and P3 of the Unicode bidirectional algorithm. - * - * \return TRUE on success, otherwise FALSE. - */ -MG_EXPORT BOOL GUIAPI BIDIGetVisualGlyphIndexMap (LOGFONT* log_font, - Glyph32* glyphs, int nr_glyphs, int** index_map, int pel); +MG_EXPORT Glyph32* GUIAPI BIDILogGlyphs2VisGlyphs (LOGFONT* log_font, + Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyphs_map); /** * \fn void GUIAPI BIDIGetLogicalEmbedLevelsEx (LOGFONT* log_font, \ diff --git a/src/font/charset-bidi.c b/src/font/charset-bidi.c index d3b06f39..3a9f28ce 100644 --- a/src/font/charset-bidi.c +++ b/src/font/charset-bidi.c @@ -491,47 +491,11 @@ bidi_resolveMirrorChar (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, glyphs[i] = mirrored_ch; } } - } + } DBGLOG (" Mirroring, Done\n"); } -static void bidi_map_reverse (void* context, int len, int pos) -{ - GLYPHMAPINFO* str = (GLYPHMAPINFO*)context + pos; - int i; - for (i = 0; i < len / 2; i++) - { - GLYPHMAPINFO tmp = str[i]; - str[i] = str[len - 1 - i]; - str[len - 1 - i] = tmp; - } -} - -static void bidi_index_reverse (void* context, int len, int pos) -{ - char* str = (char*)context + pos; - int i; - for (i = 0; i < len / 2; i++) - { - char tmp = str[i]; - str[i] = str[len - 1 - i]; - str[len - 1 - i] = tmp; - } -} - -static void bidi_string_reverse (void* context, int len, int pos) -{ - Glyph32* str = (Glyph32*)context + pos; - int i; - for (i = 0; i < len / 2; i++) - { - Glyph32 tmp = str[i]; - str[i] = str[len - 1 - i]; - str[len - 1 - i] = tmp; - } -} - static void bidi_resolve_string (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, int pel, TYPERUN **ptype_rl_list, BYTE *pmax_level) @@ -570,8 +534,26 @@ static void bidi_resolve_string (const CHARSETOPS* charset_ops, *ptype_rl_list = type_rl_list; } -static void bidi_reorder_cb (void* context, int len, - TYPERUN **ptype_rl_list, BYTE max_level, CB_DO_REORDER cb) +typedef struct _REORDER_CONTEXT { + Glyph32* glyphs; + void* extra; + CB_REVERSE_EXTRA cb; +} REORDER_CONTEXT; + +static void bidi_reverse_glyphs (Glyph32* glyphs, int len, int pos) +{ + int i; + Glyph32* gs = glyphs + pos; + + for (i = 0; i < len / 2; i++) { + Glyph32 tmp = gs[i]; + gs[i] = gs[len - 1 - i]; + gs[len - 1 - i] = tmp; + } +} + +static void bidi_reorder (REORDER_CONTEXT* context, int len, + TYPERUN **ptype_rl_list, BYTE max_level) { int i = 0; TYPERUN *type_rl_list = *ptype_rl_list, *pp = NULL; @@ -590,13 +572,32 @@ static void bidi_reorder_cb (void* context, int len, pp1 = pp1->next; } pp = pp1->prev; - cb(context, len, pos); + + if (context->glyphs) { + bidi_reverse_glyphs(context->glyphs, len, pos); + } + + if (context->extra && context->cb) { + context->cb(context->extra, len, pos); + } } } } DBGLOG("\nReordering, Done\n"); } +static void bidi_reverse_chars (void* context, int len, int pos) +{ + char* str = (char*)context + pos; + int i; + for (i = 0; i < len / 2; i++) + { + char tmp = str[i]; + str[i] = str[len - 1 - i]; + str[len - 1 - i] = tmp; + } +} + void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, int pel, Uint8* embedding_levels, Uint8 type) { @@ -607,7 +608,8 @@ void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, print_hexstr(glyphs, len, FALSE); /* W1~W7, N1~N2, I1~I2, Get the Embedding Level. */ - bidi_resolve_string (charset_ops, glyphs, len, pel, &type_rl_list, &max_level); + bidi_resolve_string (charset_ops, glyphs, len, pel, &type_rl_list, + &max_level); /* type = 0, get the logical embedding level; else visual level.*/ for (pp = type_rl_list->next; pp->next; pp = pp->next){ @@ -615,9 +617,14 @@ void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, for(i = 0; i < len; i++) embedding_levels[pos + i] = LEVEL(pp); } + if (type) { - bidi_reorder_cb(embedding_levels, len, &type_rl_list, max_level, - bidi_index_reverse); + REORDER_CONTEXT rc; + + rc.glyphs = NULL; + rc.extra = embedding_levels; + rc.cb = bidi_reverse_chars; + bidi_reorder(&rc, len, &type_rl_list, max_level); } /* free typerun list.*/ @@ -626,6 +633,19 @@ void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, print_hexstr(glyphs, len, TRUE); } +#if 0 +static void bidi_map_reverse (void* context, int len, int pos) +{ + GLYPHMAPINFO* str = (GLYPHMAPINFO*)context + pos; + int i; + for (i = 0; i < len / 2; i++) + { + GLYPHMAPINFO tmp = str[i]; + str[i] = str[len - 1 - i]; + str[len - 1 - i] = tmp; + } +} + Glyph32* __mg_charset_bidi_map_reorder (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, GLYPHMAPINFO* map, int pel) { @@ -683,19 +703,26 @@ Glyph32* __mg_charset_bidi_index_reorder (const CHARSETOPS* charset_ops, return glyphs; } +#endif Glyph32* __mg_charset_bidi_glyphs_reorder (const CHARSETOPS* charset_ops, - Glyph32* glyphs, int len, int pel) + Glyph32* glyphs, int len, int pel, + void* extra, CB_REVERSE_EXTRA cb_reverse_extra) { BYTE max_level = 1; TYPERUN *type_rl_list = NULL; + REORDER_CONTEXT rc; print_hexstr(glyphs, len, FALSE); /* W1~W7, N1~N2, I1~I2, Get the Embedding Level. */ - bidi_resolve_string (charset_ops, glyphs, len, pel, &type_rl_list, &max_level); + bidi_resolve_string (charset_ops, glyphs, len, pel, &type_rl_list, + &max_level); - bidi_reorder_cb (glyphs, len, &type_rl_list, max_level, bidi_string_reverse); + rc.glyphs = glyphs; + rc.extra = extra; + rc.cb = cb_reverse_extra; + bidi_reorder (&rc, len, &type_rl_list, max_level); /* free typerun list.*/ free_typerun_list (type_rl_list); @@ -705,7 +732,8 @@ Glyph32* __mg_charset_bidi_glyphs_reorder (const CHARSETOPS* charset_ops, return glyphs; } -Uint32 __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len) +Uint32 __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, + Glyph32* glyphs, int len) { BYTE base_level = 0; Uint32 base_dir = BIDI_TYPE_L; @@ -723,11 +751,13 @@ Uint32 __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* g return base_dir; } -BOOL GetGlyphBIDIType (LOGFONT* log_font, Glyph32 glyph_value, Uint32 *bidi_type) +BOOL GetGlyphBIDIType (LOGFONT* log_font, Glyph32 glyph_value, + Uint32 *bidi_type) { DEVFONT* mbc_devfont = log_font->mbc_devfont; - if (mbc_devfont == NULL || mbc_devfont->charset_ops->bidi_glyph_type == NULL) + if (mbc_devfont == NULL || + mbc_devfont->charset_ops->bidi_glyph_type == NULL) return FALSE; *bidi_type = mbc_devfont->charset_ops->bidi_glyph_type (glyph_value); diff --git a/src/include/bidi.h b/src/include/bidi.h index 812b63a4..a87de113 100644 --- a/src/include/bidi.h +++ b/src/include/bidi.h @@ -66,16 +66,17 @@ typedef struct _BIDICHAR_MIRROR_MAP { Glyph32 mirrored; } BIDICHAR_MIRROR_MAP; -typedef void (*CB_DO_REORDER) (void* context, int len, int pos); - Glyph32* __mg_charset_bidi_glyphs_reorder (const CHARSETOPS* charset_ops, - Glyph32* glyphs, int len, int pel); + Glyph32* glyphs, int len, int pel, + void* extra, CB_REVERSE_EXTRA cb_reverse_extra); +/* Glyph32* __mg_charset_bidi_map_reorder (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, GLYPHMAPINFO* map, int pel); Glyph32* __mg_charset_bidi_index_reorder (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, int* index_map, int pel); +*/ void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, int pel, Uint8* embedding_levels, Uint8 type); diff --git a/src/newgdi/bidi.c b/src/newgdi/bidi.c index c0606c15..303cde59 100644 --- a/src/newgdi/bidi.c +++ b/src/newgdi/bidi.c @@ -468,7 +468,7 @@ Glyph32* _gdi_bidi_reorder (PDC pdc, const unsigned char* text, int text_len, logical_glyphs = _gdi_get_glyphs_string (pdc, text, text_len, nr_glyphs); if (*nr_glyphs > 0) __mg_charset_bidi_glyphs_reorder (mbc_devfont->charset_ops, - logical_glyphs, *nr_glyphs, -1); + logical_glyphs, *nr_glyphs, -1, NULL, NULL); } return logical_glyphs; @@ -868,7 +868,7 @@ int _gdi_reorder_text_break (PDC pdc, const unsigned char* text, logical_glyphs = _gdi_get_glyphs_string_break(pdc, text, text_len, &nr_glyphs, context); __mg_charset_bidi_glyphs_reorder (mbc_devfont->charset_ops, - logical_glyphs, nr_glyphs, -1); + logical_glyphs, nr_glyphs, -1, NULL, NULL); if(!logical_glyphs) return 0; @@ -1425,6 +1425,18 @@ void GUIAPI BIDIGetTextRangesLog2Vis(LOGFONT* log_font, free(l_glyphs); } +static void bidi_reverse_map (void* context, int len, int pos) +{ + GLYPHMAPINFO* str = (GLYPHMAPINFO*)context + pos; + int i; + for (i = 0; i < len / 2; i++) + { + GLYPHMAPINFO tmp = str[i]; + str[i] = str[len - 1 - i]; + str[len - 1 - i] = tmp; + } +} + int GUIAPI BIDIGetTextVisualGlyphs(LOGFONT* log_font, const char* text, int text_len, Glyph32** glyphs, @@ -1439,56 +1451,46 @@ int GUIAPI BIDIGetTextVisualGlyphs(LOGFONT* log_font, nr_glyphs = BIDIGetTextLogicalGlyphs(log_font, text, text_len, glyphs, glyphs_map); - if (mbc_devfont && mbc_devfont->charset_ops->bidi_glyph_type){ - __mg_charset_bidi_map_reorder (mbc_devfont->charset_ops, *glyphs, - nr_glyphs, *glyphs_map, -1); + if (nr_glyphs > 0 && mbc_devfont + && mbc_devfont->charset_ops->bidi_glyph_type) { __mg_charset_bidi_glyphs_reorder (mbc_devfont->charset_ops, - *glyphs, nr_glyphs, -1); + *glyphs, nr_glyphs, -1, + *glyphs_map, bidi_reverse_map); } + return nr_glyphs; } -BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx (LOGFONT* log_font, - Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyph_map, int pel) +Glyph32* GUIAPI BIDILogGlyphs2VisGlyphs(LOGFONT* log_font, + Glyph32* glyphs, int nr_glyphs, GLYPHMAPINFO* glyphs_map) { DEVFONT* mbc_devfont = log_font->mbc_devfont; if (nr_glyphs > 0 && mbc_devfont && mbc_devfont->charset_ops->bidi_glyph_type) { - if (glyph_map) { - __mg_charset_bidi_map_reorder (mbc_devfont->charset_ops, - glyphs, nr_glyphs, glyph_map, pel); - } __mg_charset_bidi_glyphs_reorder (mbc_devfont->charset_ops, - glyphs, nr_glyphs, pel); + glyphs, nr_glyphs, -1, + glyphs_map, bidi_reverse_map); - return TRUE; + return glyphs; } - return FALSE; + return NULL; } -BOOL GUIAPI BIDIGetVisualGlyphIndexMap (LOGFONT* log_font, - Glyph32* glyphs, int nr_glyphs, int** index_map, int pel) +BOOL GUIAPI BIDILogGlyphs2VisGlyphsEx(LOGFONT* log_font, + Glyph32* glyphs, int nr_glyphs, int pel, + void* extra, CB_REVERSE_EXTRA cb_reorder_extra) { DEVFONT* mbc_devfont = log_font->mbc_devfont; if (nr_glyphs > 0 && mbc_devfont && mbc_devfont->charset_ops->bidi_glyph_type) { - if (*index_map == NULL) - *index_map = malloc (nr_glyphs * sizeof (int)); + __mg_charset_bidi_glyphs_reorder (mbc_devfont->charset_ops, + glyphs, nr_glyphs, pel, + extra, cb_reorder_extra); - if (*index_map) { - int i; - for (i = 0; i < nr_glyphs; i++) { - *index_map[i] = i; - } - - __mg_charset_bidi_index_reorder (mbc_devfont->charset_ops, - glyphs, nr_glyphs, *index_map, pel); - - return TRUE; - } + return TRUE; } return FALSE;