mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-02-07 19:37:00 +08:00
new API: UBidiGetParagraphEmbeddingLevelsAlt, an optimized call
This commit is contained in:
@@ -8277,6 +8277,10 @@ MG_EXPORT BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevels(
|
||||
const BidiBracketType* bracket_types, int len,
|
||||
ParagraphDir *paragraph_dir, BidiLevel *embedding_levels);
|
||||
|
||||
MG_EXPORT BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevelsAlt(
|
||||
const Uchar32* ucs, int nr_ucs,
|
||||
ParagraphDir *paragraph_dir, BidiLevel *embedding_levels);
|
||||
|
||||
/*
|
||||
* \var typedef void (*CB_REVERSE_ARRAY) (void* extra, int len, int pos)
|
||||
* \brief The prototype of the user defined function to reverse an array.
|
||||
@@ -12429,7 +12433,6 @@ MG_EXPORT GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
LanguageCode lang_code, ScriptType script_type,
|
||||
ParagraphDir base_dir, GlyphRunDir run_dir,
|
||||
GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy,
|
||||
Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
LOGFONT* logfont, RGBCOLOR color);
|
||||
|
||||
/**
|
||||
@@ -12700,7 +12703,8 @@ MG_EXPORT GLYPHEXTINFO* GUIAPI GetShapedGlyphsExtentInfo(
|
||||
* GetGlyphsExtentInfo, DrawShapedGlyphString, GLYPHEXTINFO, glyph_render_flags
|
||||
*/
|
||||
MG_EXPORT int GUIAPI GetShapedGlyphsFittingLine(const GLYPHRUNINFO* run_info,
|
||||
int uc_start_index, int x, int y,
|
||||
const BreakOppo* break_oppos,
|
||||
int uc_start_index, int x, int y, Uint32 render_flags,
|
||||
int letter_spacing, int word_spacing, int tab_size, int max_extent,
|
||||
SIZE* line_size, GLYPHPOS** glyph_pos, int* nr_glyphs);
|
||||
|
||||
|
||||
@@ -1711,4 +1711,130 @@ out:
|
||||
return status ? max_level + 1 : 0;
|
||||
}
|
||||
|
||||
/* Local array size, used for stack-based local arrays */
|
||||
#if SIZEOF_PTR == 8
|
||||
# define LOCAL_ARRAY_SIZE 256
|
||||
#else
|
||||
# define LOCAL_ARRAY_SIZE 128
|
||||
#endif
|
||||
|
||||
BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevelsAlt(
|
||||
const Uchar32* ucs, int nr_ucs,
|
||||
ParagraphDir *paragraph_dir, BidiLevel *els)
|
||||
{
|
||||
int i;
|
||||
ParagraphDir base_dir = *paragraph_dir;
|
||||
BidiLevel max_level = 0;
|
||||
|
||||
BidiType local_bidi_ts[LOCAL_ARRAY_SIZE];
|
||||
BidiType *bidi_ts = NULL;
|
||||
BidiType ored_types = 0;
|
||||
BidiType anded_strongs = BIDI_TYPE_RLE;
|
||||
|
||||
BidiBracketType local_brk_ts[LOCAL_ARRAY_SIZE];
|
||||
BidiBracketType *brk_ts = NULL;
|
||||
|
||||
if (!els) {
|
||||
_DBG_PRINTF("%s: Embedding levels is NULL.\n",
|
||||
__FUNCTION__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nr_ucs < LOCAL_ARRAY_SIZE)
|
||||
bidi_ts = local_bidi_ts;
|
||||
else
|
||||
bidi_ts = malloc(nr_ucs * sizeof(BidiType));
|
||||
|
||||
if (!bidi_ts) {
|
||||
_DBG_PRINTF("%s: failed to allocate space for bidi types.\n",
|
||||
__FUNCTION__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nr_ucs < LOCAL_ARRAY_SIZE)
|
||||
brk_ts = local_brk_ts;
|
||||
else
|
||||
brk_ts = (BidiBracketType*)malloc (nr_ucs * sizeof(BidiBracketType));
|
||||
|
||||
if (!brk_ts) {
|
||||
_DBG_PRINTF("%s: failed to allocate space for bracket types.\n",
|
||||
__FUNCTION__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_ucs; i++) {
|
||||
BidiType bidi_type;
|
||||
bidi_ts[i] = bidi_type = UCharGetBidiType(ucs[i]);
|
||||
ored_types |= bidi_type;
|
||||
if (BIDI_IS_STRONG (bidi_type))
|
||||
anded_strongs &= bidi_type;
|
||||
|
||||
if (bidi_ts[i] == BIDI_TYPE_ON)
|
||||
brk_ts[i] = UCharGetBracketType(ucs[i]);
|
||||
else
|
||||
brk_ts[i] = BIDI_BRACKET_NONE;
|
||||
}
|
||||
|
||||
/* Short-circuit (malloc-expensive) Bidi call for unidirectional text. */
|
||||
|
||||
/* The case that all resolved levels will be ltr.
|
||||
* No isolates, all strongs be LTR, there should be no Arabic numbers
|
||||
* (or letters for that matter), and one of the following:
|
||||
*
|
||||
* o base_dir doesn't have an RTL taste.
|
||||
* o there are letters, and base_dir is weak.
|
||||
*/
|
||||
if (!BIDI_IS_ISOLATE (ored_types) &&
|
||||
!BIDI_IS_RTL (ored_types) &&
|
||||
!BIDI_IS_ARABIC (ored_types) &&
|
||||
(!BIDI_IS_RTL (base_dir) ||
|
||||
(BIDI_IS_WEAK (base_dir) &&
|
||||
BIDI_IS_LETTER (ored_types))
|
||||
))
|
||||
{
|
||||
/* all LTR */
|
||||
base_dir = BIDI_PGDIR_LTR;
|
||||
memset (els, 0, nr_ucs);
|
||||
}
|
||||
/* The case that all resolved levels will be RTL is much more complex.
|
||||
* No isolates, no numbers, all strongs are RTL, and one of
|
||||
* the following:
|
||||
*
|
||||
* o base_dir has an RTL taste (may be weak).
|
||||
* o there are letters, and base_dir is weak.
|
||||
*/
|
||||
else if (!BIDI_IS_ISOLATE (ored_types) &&
|
||||
!BIDI_IS_NUMBER (ored_types) &&
|
||||
BIDI_IS_RTL (anded_strongs) &&
|
||||
(BIDI_IS_RTL (base_dir) ||
|
||||
(BIDI_IS_WEAK (base_dir) &&
|
||||
BIDI_IS_LETTER (ored_types))
|
||||
))
|
||||
{
|
||||
/* all RTL */
|
||||
base_dir = BIDI_PGDIR_RTL;
|
||||
memset (els, 1, nr_ucs);
|
||||
}
|
||||
else {
|
||||
max_level = UBidiGetParagraphEmbeddingLevels(bidi_ts, brk_ts, nr_ucs,
|
||||
&base_dir, els);
|
||||
if (max_level == 0) {
|
||||
_DBG_PRINTF("%s: failed to get paragraph embedding levels.\n");
|
||||
memset (els, 0, nr_ucs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
*paragraph_dir = (base_dir == BIDI_PGDIR_LTR) ? BIDI_PGDIR_LTR : BIDI_PGDIR_RTL;
|
||||
|
||||
out:
|
||||
if (bidi_ts && bidi_ts != local_bidi_ts)
|
||||
free (bidi_ts);
|
||||
|
||||
if (brk_ts && brk_ts != local_brk_ts)
|
||||
free (brk_ts);
|
||||
|
||||
return max_level;
|
||||
}
|
||||
|
||||
#endif /* _MGCHARSET_UNICODE */
|
||||
|
||||
@@ -210,18 +210,14 @@ typedef unsigned char *emoji_text_iter_t;
|
||||
#include "emoji_presentation_scanner.inc"
|
||||
|
||||
EmojiIterator * __mg_emoji_iter_init (EmojiIterator *iter,
|
||||
const Uchar32* ucs, int nr_ucs)
|
||||
const Uchar32* ucs, int nr_ucs, Uint8* types_buff)
|
||||
{
|
||||
int i;
|
||||
unsigned char *types;
|
||||
Uint8 *types = types_buff;
|
||||
const Uchar32 *p;
|
||||
|
||||
assert (nr_ucs > 0);
|
||||
|
||||
types = malloc (sizeof (unsigned char) * nr_ucs);
|
||||
if (types == NULL)
|
||||
return NULL;
|
||||
|
||||
p = ucs;
|
||||
for (i = 0; i < nr_ucs; i++) {
|
||||
types[i] = emojiSegmentationCategory (*p);
|
||||
@@ -272,9 +268,4 @@ BOOL __mg_emoji_iter_next (EmojiIterator *iter)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void __mg_emoji_iter_fini (EmojiIterator *iter)
|
||||
{
|
||||
free (iter->types);
|
||||
}
|
||||
|
||||
#endif /* _MGCHARSET_UNICODE */
|
||||
|
||||
@@ -128,7 +128,7 @@ WidthIterator* __mg_width_iter_init (WidthIterator* iter,
|
||||
void __mg_width_iter_next(WidthIterator* iter);
|
||||
|
||||
EmojiIterator* __mg_emoji_iter_init (EmojiIterator *iter,
|
||||
const Uchar32* ucs, int nr_ucs);
|
||||
const Uchar32* ucs, int nr_ucs, Uint8* types_buff);
|
||||
BOOL __mg_emoji_iter_next (EmojiIterator *iter);
|
||||
void __mg_emoji_iter_fini (EmojiIterator *iter);
|
||||
|
||||
|
||||
@@ -53,16 +53,24 @@
|
||||
#include "unicode-ops.h"
|
||||
#include "glyphruninfo.h"
|
||||
|
||||
typedef enum {
|
||||
EMBEDDING_CHANGED = 1 << 0,
|
||||
SCRIPT_CHANGED = 1 << 1,
|
||||
LANG_CHANGED = 1 << 2,
|
||||
DERIVED_LANG_CHANGED = 1 << 3,
|
||||
WIDTH_CHANGED = 1 << 3,
|
||||
EMOJI_CHANGED = 1 << 5,
|
||||
} ChangedFlags;
|
||||
/* Local array size, used for stack-based local arrays */
|
||||
#if SIZEOF_PTR == 8
|
||||
# define LOCAL_ARRAY_SIZE 256
|
||||
#else
|
||||
# define LOCAL_ARRAY_SIZE 128
|
||||
#endif
|
||||
|
||||
typedef struct _GlyphRunState {
|
||||
enum {
|
||||
EMBEDDING_CHANGED = 1 << 0,
|
||||
SCRIPT_CHANGED = 1 << 1,
|
||||
LANG_CHANGED = 1 << 2,
|
||||
DERIVED_LANG_CHANGED = 1 << 3,
|
||||
FONT_CHANGED = 1 << 4,
|
||||
WIDTH_CHANGED = 1 << 5,
|
||||
EMOJI_CHANGED = 1 << 6,
|
||||
};
|
||||
|
||||
typedef struct _GLYPHRUNSTATE {
|
||||
GLYPHRUNINFO* context;
|
||||
const Uchar32* text;
|
||||
const Uchar32* end;
|
||||
@@ -90,11 +98,13 @@ typedef struct _GlyphRunState {
|
||||
EmojiIterator emoji_iter;
|
||||
|
||||
LanguageCode derived_lang;
|
||||
} GlyphRunState;
|
||||
} GLYPHRUNSTATE;
|
||||
|
||||
static BOOL init_glyph_runs(GLYPHRUNINFO* runinfo)
|
||||
static BOOL init_glyph_runs(GLYPHRUNINFO* runinfo, BidiLevel* els)
|
||||
{
|
||||
#if 0
|
||||
GLYPHRUNSTATE state;
|
||||
|
||||
BidiLevel el = runinfo->els[0];
|
||||
ScriptType st = UCharGetScriptType(runinfo->ucs[0]);
|
||||
#endif
|
||||
@@ -102,36 +112,17 @@ static BOOL init_glyph_runs(GLYPHRUNINFO* runinfo)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Local array size, used for stack-based local arrays */
|
||||
#if SIZEOF_PTR == 8
|
||||
# define LOCAL_ARRAY_SIZE 256
|
||||
#else
|
||||
# define LOCAL_ARRAY_SIZE 128
|
||||
#endif
|
||||
|
||||
GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
LanguageCode lang_code, ScriptType script_type,
|
||||
ParagraphDir base_dir, GlyphRunDir run_dir,
|
||||
GlyphOrient glyph_orient, GlyphOrientPolicy orient_policy,
|
||||
Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
LOGFONT* logfont, RGBCOLOR color)
|
||||
{
|
||||
BOOL ok = FALSE;
|
||||
|
||||
GLYPHRUNINFO* runinfo;
|
||||
BidiLevel local_els[LOCAL_ARRAY_SIZE];
|
||||
BidiLevel* els = NULL;
|
||||
BreakOppo* bos = NULL;
|
||||
|
||||
BidiLevel max_level = 0;
|
||||
|
||||
BidiType local_bidi_ts[LOCAL_ARRAY_SIZE];
|
||||
BidiType *bidi_ts = NULL;
|
||||
|
||||
BidiBracketType local_brk_ts[LOCAL_ARRAY_SIZE];
|
||||
BidiBracketType *brk_ts = NULL;
|
||||
BidiLevel level_or, level_and;
|
||||
|
||||
int i, j;
|
||||
|
||||
runinfo = (GLYPHRUNINFO*)calloc(1, sizeof(GLYPHRUNINFO));
|
||||
if (ucs == NULL || nr_ucs <= 0 || runinfo == NULL) {
|
||||
@@ -139,53 +130,28 @@ GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
}
|
||||
|
||||
if (nr_ucs < LOCAL_ARRAY_SIZE)
|
||||
bidi_ts = local_bidi_ts;
|
||||
els = local_els;
|
||||
else
|
||||
bidi_ts = malloc(nr_ucs * sizeof(BidiType));
|
||||
els = (BidiLevel*)malloc (nr_ucs * sizeof(BidiLevel));
|
||||
|
||||
if (!bidi_ts) {
|
||||
_DBG_PRINTF("%s: failed to allocate space for bidi types.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
UStrGetBidiTypes(ucs, nr_ucs, bidi_ts);
|
||||
|
||||
if (nr_ucs < LOCAL_ARRAY_SIZE)
|
||||
brk_ts = local_brk_ts;
|
||||
else
|
||||
brk_ts = (BidiBracketType*)malloc (nr_ucs * sizeof(BidiBracketType));
|
||||
|
||||
if (!brk_ts) {
|
||||
_DBG_PRINTF("%s: failed to allocate space for bracket types.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
UStrGetBracketTypes (ucs, bidi_ts, nr_ucs, brk_ts);
|
||||
|
||||
els = (BidiLevel*)malloc (nr_ucs * sizeof(BidiLevel));
|
||||
if (!els) {
|
||||
_DBG_PRINTF("%s: failed to allocate space for embedding levels.\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
max_level = UBidiGetParagraphEmbeddingLevels(bidi_ts, brk_ts, nr_ucs,
|
||||
&base_dir, els) - 1;
|
||||
if (max_level < 0) {
|
||||
_DBG_PRINTF("%s: failed to get paragraph embedding levels.\n");
|
||||
goto out;
|
||||
}
|
||||
UBidiGetParagraphEmbeddingLevelsAlt(ucs, nr_ucs, &base_dir, els);
|
||||
|
||||
/* the breaking opportunities should be passed to the layout function.
|
||||
// Calculate the breaking opportunities
|
||||
if (UStrGetBreaks(script_type, ctr, wbr, lbp,
|
||||
ucs, nr_ucs, &bos) == 0) {
|
||||
_DBG_PRINTF("%s: failed to get breaking opportunities.\n");
|
||||
goto out;
|
||||
}
|
||||
*/
|
||||
|
||||
// Initialize other fields
|
||||
runinfo->ucs = ucs;
|
||||
runinfo->els = els;
|
||||
runinfo->bos = bos;
|
||||
|
||||
INIT_LIST_HEAD(&runinfo->cm_head.list);
|
||||
runinfo->cm_head.si = 0;
|
||||
@@ -206,6 +172,11 @@ GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
runinfo->run_head.dir = run_dir;
|
||||
runinfo->run_head.ort = glyph_orient;
|
||||
|
||||
#if 0
|
||||
int i, j;
|
||||
BidiLevel max_level = 0;
|
||||
BidiLevel level_or, level_and;
|
||||
|
||||
// make the embedding levels of the bidi marks to be -1.
|
||||
level_or = 0, level_and = 1;
|
||||
j = 0;
|
||||
@@ -222,11 +193,12 @@ GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
|
||||
// check for all even or odd
|
||||
/* If none of the levels had the LSB set, all chars were even. */
|
||||
runinfo->run_head.all_even = (level_or & 0x1) == 0;
|
||||
runinfo->all_even = (level_or & 0x1) == 0;
|
||||
/* If all of the levels had the LSB set, all chars were odd. */
|
||||
runinfo->run_head.all_odd = (level_and & 0x1) == 1;
|
||||
runinfo->all_odd = (level_and & 0x1) == 1;
|
||||
#endif
|
||||
|
||||
if (!init_glyph_runs(runinfo)) {
|
||||
if (!init_glyph_runs(runinfo, els)) {
|
||||
_DBG_PRINTF("%s: failed to call init_glyph_runs.\n");
|
||||
goto out;
|
||||
}
|
||||
@@ -234,18 +206,13 @@ GLYPHRUNINFO* GUIAPI CreateGlyphRunInfo(Uchar32* ucs, int nr_ucs,
|
||||
ok = TRUE;
|
||||
|
||||
out:
|
||||
if (bidi_ts && bidi_ts != local_bidi_ts)
|
||||
free (bidi_ts);
|
||||
|
||||
if (brk_ts && brk_ts != local_brk_ts)
|
||||
free (brk_ts);
|
||||
if (els && els != local_els)
|
||||
free(els);
|
||||
|
||||
if (ok)
|
||||
return runinfo;
|
||||
|
||||
if (runinfo->l2g) free(runinfo->l2g);
|
||||
if (els) free(els);
|
||||
if (bos) free(bos);
|
||||
free(runinfo);
|
||||
|
||||
return NULL;
|
||||
@@ -340,7 +307,7 @@ BOOL GUIAPI ResetFontInGlyphRuns(GLYPHRUNINFO* runinfo, LOGFONT* logfont)
|
||||
|
||||
runinfo->run_head.lf = logfont;
|
||||
|
||||
return init_glyph_runs(runinfo);
|
||||
return init_glyph_runs(runinfo, NULL);
|
||||
}
|
||||
|
||||
static void set_run_dir(GLYPHRUNINFO* runinfo, GLYPHRUN* run,
|
||||
@@ -401,17 +368,13 @@ BOOL GUIAPI ResetColorInGlyphRuns(GLYPHRUNINFO* runinfo, RGBCOLOR color)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
BOOL GUIAPI ResetBreaksInGlyphRuns(GLYPHRUNINFO* runinfo,
|
||||
Uint8 ctr, Uint8 wbr, Uint8 lbp)
|
||||
{
|
||||
if (runinfo == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (runinfo->bos) {
|
||||
free (runinfo->bos);
|
||||
runinfo->bos = NULL;
|
||||
}
|
||||
|
||||
// Re-calculate the breaking opportunities
|
||||
if (UStrGetBreaks(runinfo->run_head.st, ctr, wbr, lbp,
|
||||
runinfo->ucs, runinfo->run_head.nr_ucs, &runinfo->bos) == 0) {
|
||||
@@ -421,6 +384,7 @@ BOOL GUIAPI ResetBreaksInGlyphRuns(GLYPHRUNINFO* runinfo,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL GUIAPI DestroyGlyphRunInfo(GLYPHRUNINFO* runinfo)
|
||||
{
|
||||
@@ -446,8 +410,6 @@ BOOL GUIAPI DestroyGlyphRunInfo(GLYPHRUNINFO* runinfo)
|
||||
|
||||
if (runinfo->l2g) free(runinfo->l2g);
|
||||
if (runinfo->ges) free(runinfo->ges);
|
||||
if (runinfo->els) free(runinfo->els);
|
||||
if (runinfo->bos) free(runinfo->bos);
|
||||
|
||||
free(runinfo);
|
||||
return TRUE;
|
||||
|
||||
@@ -82,8 +82,6 @@ typedef struct _GLYPHRUN {
|
||||
Uint32 level:8; // the bidi level
|
||||
Uint32 dir:4; // the run direction
|
||||
Uint32 ort:2; // the glyph orientation
|
||||
Uint32 all_even:1; // flag indicating all level is even
|
||||
Uint8 all_odd:1; // flag indicating all level is odd
|
||||
} GLYPHRUN;
|
||||
|
||||
// NOTE: we arrange the fields carefully to avoid wasting space when
|
||||
@@ -102,9 +100,7 @@ typedef struct _UCHARCOLORMAP {
|
||||
|
||||
struct _GLYPHRUNINFO {
|
||||
/* The following fields will be initialized by CreateGlyphRunInfo. */
|
||||
Uchar32* ucs;
|
||||
BidiLevel* els;
|
||||
BreakOppo* bos;
|
||||
const Uchar32* ucs;
|
||||
|
||||
UCHARCOLORMAP cm_head; // the head of color map list of the characters.
|
||||
// change by calling SetPartColorInGlyphRunInfo.
|
||||
@@ -117,6 +113,8 @@ struct _GLYPHRUNINFO {
|
||||
GLYPHEXTINFO* ges; // the glyph extent information.
|
||||
|
||||
Uint32 rf; // the rendering flags.
|
||||
Uint8 all_even:1; // flag indicating all level is even
|
||||
Uint8 all_odd:1; // flag indicating all level is odd
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
Reference in New Issue
Block a user