This commit is contained in:
Vincent Wei
2019-03-11 18:45:46 +08:00
parent c66f1a5fa3
commit ce7b9eccca
5 changed files with 112 additions and 93 deletions
+85 -57
View File
@@ -7314,17 +7314,13 @@ MG_EXPORT int GUIAPI GetFirstWord (PLOGFONT log_font,
* @{
*/
typedef Uint8 BidiLevel;
typedef Sint8 BidiLevel;
typedef Uint16 BidiType;
typedef Uint32 BidiBracketType;
typedef Uint8 BidiJoiningType;
typedef Uint8 BidiArabicProp;
#define BIDI_PGDIR_LTR 0
#define BIDI_PGDIR_RTL 1
#define BIDI_PGDIR_ON 2
#define BIDI_FLAG_SHAPE_MIRRORING 0x00000001
#define BIDI_FLAG_REORDER_NSM 0x00000002
#define BIDI_FLAG_SHAPE_ARAB_PRES 0x00000100
@@ -7356,20 +7352,15 @@ typedef Uint8 BidiArabicProp;
#define BIDI_MASK_RTL 0x0001 /* Is right to left */
#define BIDI_MASK_ARABIC 0x0002 /* Is arabic */
#define BIDI_MASK_FIRST 0x0004 /* Is direction is determined by first strong */
#define BIDI_MASK_SEPARATOR 0x0008 /* Is separator: BS, SS */
#define BIDI_MASK_FIRST 0x0004 /* Whether direction is determined by first strong */
#define BIDI_MASK_BN 0x0008 /* flag for BN */
#define BIDI_SWN_MASK 0x0030
#define BIDI_MASK_STRONG 0x0000 /* Is strong */
#define BIDI_MASK_WEAK 0x0010 /* Is weak */
#define BIDI_MASK_NEUTRAL 0x0020 /* Is neutral */
#define BIDI_MASK_WS 0x0040
#define BIDI_MASK_STRONG 0x0010 /* Is strong */
#define BIDI_MASK_WEAK 0x0020 /* Is weak */
#define BIDI_MASK_NEUTRAL 0x0040 /* Is neutral */
#define BIDI_MASK_SENTINEL 0x0080 /* Is sentinel: SOT, EOT */
/* Each char can be only one of the seven following. */
#define BIDI_TYPE_MASK 0x0F00
/* Each char can be only one of the seven following: */
#define BIDI_MASK_LETTER 0x0100 /* Is letter: L, R, AL */
#define BIDI_MASK_NUMBER 0x0200 /* Is number: EN, AN */
#define BIDI_MASK_NUMSEPTER 0x0300 /* Is number separator or terminator: ES, ET, CS */
@@ -7377,176 +7368,206 @@ typedef Uint8 BidiArabicProp;
#define BIDI_MASK_EXPLICIT 0x0500 /* Is expilict mark: LRE, RLE, LRO, RLO, PDF */
#define BIDI_MASK_ISOLATE 0x0600 /* Is isolate mark: LRI, RLI, FSI, PDI */
#define BIDI_MASK_NSM 0x0700 /* Is non spacing mark: NSM */
# define BIDI_TYPE_MASK 0x0700
/* Can be on only if BIDI_MASK_SPACE is also on. */
#define BIDI_MASK_SEPARATOR 0x0800 /* Is separator: BS, SS */
/* Can be on only if BIDI_MASK_EXPLICIT is also on. */
#define BIDI_MASK_OVERRIDE 0x8000 /* Is explicit override: LRO, RLO */
#define BIDI_MISC_MASK 0x7000
/* Each char can be only one of the seven following: */
#define BIDI_MASK_ES 0x1000
#define BIDI_MASK_CS 0x2000
#define BIDI_MASK_ET 0x3000
#define BIDI_MASK_BS 0x4000
#define BIDI_MASK_SS 0x5000
#define BIDI_MASK_BN 0x6000
#define BIDI_MASK_WS 0x7000
# define BIDI_MISC_MASK 0x7000
/* Reserved for private use */
#define BIDI_MASK_PRIVATE 0x8000
/**
* \def BIDI_TYPE_LTR
* \brief Strong left to right
*/
#define BIDI_TYPE_LTR (BIDI_MASK_STRONG | BIDI_MASK_LETTER)
#define BIDI_TYPE_LTR \
(BIDI_MASK_STRONG | BIDI_MASK_LETTER)
/**
* \def BIDI_TYPE_RTL
* \brief Right to left characters
*/
#define BIDI_TYPE_RTL (BIDI_MASK_STRONG | BIDI_MASK_LETTER | BIDI_MASK_RTL)
#define BIDI_TYPE_RTL \
(BIDI_MASK_STRONG | BIDI_MASK_LETTER | BIDI_MASK_RTL)
/**
* \def BIDI_TYPE_AL
* \brief Arabic characters
*/
#define BIDI_TYPE_AL (BIDI_MASK_STRONG | BIDI_MASK_LETTER | BIDI_MASK_RTL | BIDI_MASK_ARABIC)
#define BIDI_TYPE_AL \
(BIDI_MASK_STRONG | BIDI_MASK_LETTER | BIDI_MASK_RTL | BIDI_MASK_ARABIC)
/**
* \def BIDI_TYPE_LRE
* \brief Left-To-Right embedding
*/
#define BIDI_TYPE_LRE (BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT)
#define BIDI_TYPE_LRE \
(BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT)
/**
* \def BIDI_TYPE_RLE
* \brief Right-To-Left embedding
*/
#define BIDI_TYPE_RLE (BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_RTL)
#define BIDI_TYPE_RLE \
(BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_RTL)
/**
* \def BIDI_TYPE_LRO
* \brief Left-To-Right override
*/
#define BIDI_TYPE_LRO (BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_OVERRIDE)
#define BIDI_TYPE_LRO \
(BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_OVERRIDE)
/**
* \def BIDI_TYPE_RLO
* \brief Right-To-Left override
*/
#define BIDI_TYPE_RLO (BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_RTL | BIDI_MASK_OVERRIDE)
#define BIDI_TYPE_RLO \
(BIDI_MASK_STRONG | BIDI_MASK_EXPLICIT | BIDI_MASK_RTL | BIDI_MASK_OVERRIDE)
/**
* \def BIDI_TYPE_PDF
* \brief Pop directional override
*/
#define BIDI_TYPE_PDF (BIDI_MASK_WEAK | BIDI_MASK_EXPLICIT)
#define BIDI_TYPE_PDF \
(BIDI_MASK_WEAK | BIDI_MASK_EXPLICIT)
/**
* \def BIDI_TYPE_EN
* \brief European digit
*/
#define BIDI_TYPE_EN (BIDI_MASK_WEAK | BIDI_MASK_NUMBER)
#define BIDI_TYPE_EN \
(BIDI_MASK_WEAK | BIDI_MASK_NUMBER)
/**
* \def BIDI_TYPE_AN
* \brief Arabic digit
*/
#define BIDI_TYPE_AN (BIDI_MASK_WEAK | BIDI_MASK_NUMBER | BIDI_MASK_ARABIC)
#define BIDI_TYPE_AN \
(BIDI_MASK_WEAK | BIDI_MASK_NUMBER | BIDI_MASK_ARABIC)
/**
* \def BIDI_TYPE_ES
* \brief European number separator
*/
#define BIDI_TYPE_ES (BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_ES)
#define BIDI_TYPE_ES \
(BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_ES)
/**
* \def BIDI_TYPE_ET
* \brief European number terminator
*/
#define BIDI_TYPE_ET (BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_ET)
#define BIDI_TYPE_ET \
(BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_ET)
/**
* \def BIDI_TYPE_CS
* \brief Common Separator
*/
#define BIDI_TYPE_CS (BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_CS)
#define BIDI_TYPE_CS \
(BIDI_MASK_WEAK | BIDI_MASK_NUMSEPTER | BIDI_MASK_CS)
/**
* \def BIDI_TYPE_NSM
* \brief Non spacing mark
*/
#define BIDI_TYPE_NSM (BIDI_MASK_WEAK | BIDI_MASK_NSM)
#define BIDI_TYPE_NSM \
(BIDI_MASK_WEAK | BIDI_MASK_NSM)
/**
* \def BIDI_TYPE_BN
* \brief Boundary neutral
*/
#define BIDI_TYPE_BN (BIDI_MASK_WEAK | BIDI_MASK_SPACE | BIDI_MASK_BN)
#define BIDI_TYPE_BN \
(BIDI_MASK_WEAK | BIDI_MASK_SPACE | BIDI_MASK_BN)
/**
* \def BIDI_TYPE_BS
* \brief Block separator (Paragraph separator)
*/
#define BIDI_TYPE_BS (BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_SEPARATOR | BIDI_MASK_BS)
#define BIDI_TYPE_BS \
(BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_SEPARATOR | BIDI_MASK_BS)
/**
* \def BIDI_TYPE_SS
* \brief Segment separator
*/
#define BIDI_TYPE_SS (BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_SEPARATOR | BIDI_MASK_SS)
#define BIDI_TYPE_SS \
(BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_SEPARATOR | BIDI_MASK_SS)
/**
* \def BIDI_TYPE_WS
* \brief Whitespace
*/
#define BIDI_TYPE_WS (BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_WS)
#define BIDI_TYPE_WS \
(BIDI_MASK_NEUTRAL | BIDI_MASK_SPACE | BIDI_MASK_WS)
/**
* \def BIDI_TYPE_ON
* \brief Other Neutral
*/
#define BIDI_TYPE_ON (BIDI_MASK_NEUTRAL)
#define BIDI_TYPE_ON \
(BIDI_MASK_NEUTRAL)
/**
* \def BIDI_TYPE_LRI
* \brief Left-to-Right Isolate
*/
#define BIDI_TYPE_LRI (BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE)
#define BIDI_TYPE_LRI \
(BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE)
/**
* \def BIDI_TYPE_RLI
* \brief Right-to-Left Isolate
*/
#define BIDI_TYPE_RLI (BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE | BIDI_MASK_RTL)
#define BIDI_TYPE_RLI \
(BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE | BIDI_MASK_RTL)
/**
* \def BIDI_TYPE_FSI
* \brief First Strong Isolate
*/
#define BIDI_TYPE_FSI (BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE | BIDI_MASK_FIRST)
#define BIDI_TYPE_FSI \
(BIDI_MASK_NEUTRAL | BIDI_MASK_ISOLATE | BIDI_MASK_FIRST)
/**
* \def BIDI_TYPE_PDI
* \brief Pop Directional Isolate
*/
#define BIDI_TYPE_PDI (BIDI_MASK_NEUTRAL | BIDI_MASK_WEAK | BIDI_MASK_ISOLATE)
#define BIDI_TYPE_PDI \
(BIDI_MASK_NEUTRAL | BIDI_MASK_WEAK | BIDI_MASK_ISOLATE)
#define BIDI_TYPE_SENTINEL (BIDI_MASK_SENTINEL)
/* Weak Left-To-Right */
#define BIDI_TYPE_WLTR (BIDI_MASK_WEAK)
/* Weak Right-To-Left */
#define BIDI_TYPE_WRTL (BIDI_MASK_WEAK | BIDI_MASK_RTL)
/* The following are only used internally */
/* Weak Left-To-Right */
#define BIDI_TYPE_WLTR (BIDI_MASK_WEAK)
/* Weak Right-To-Left */
#define BIDI_TYPE_WRTL (BIDI_MASK_WEAK | BIDI_MASK_RTL)
/* Start of text */
#define BIDI_TYPE_SOT (BIDI_MASK_SENTINEL)
#define BIDI_TYPE_SOT (BIDI_MASK_SENTINEL)
/* End of text */
#define BIDI_TYPE_EOT (BIDI_MASK_SENTINEL + BIDI_MASK_RTL)
#define BIDI_TYPE_EOT (BIDI_MASK_SENTINEL | BIDI_MASK_RTL)
#define BIDI_TYPE_PRIVATE (BIDI_MASK_PRIVATE)
/* Is private-use value? */
//#define BIDI_TYPE_PRIVATE(p) ((p) < 0)
#define BIDI_IS_PRIVATE(p) ((p) & BIDI_MASK_PRIVATE)
/* Is right to left? */
#define BIDI_IS_RTL(p) ((p) & BIDI_MASK_RTL)
/* Is arabic? */
#define BIDI_IS_ARABIC(p) ((p) & BIDI_MASK_ARABIC)
@@ -7564,7 +7585,7 @@ typedef Uint8 BidiArabicProp;
((BidiLevel) (BIDI_IS_RTL(dir) ? 1 : 0))
/* Is strong? */
#define BIDI_IS_STRONG(p) (!((p) & BIDI_SWN_MASK))
#define BIDI_IS_STRONG(p) ((p) & BIDI_MASK_STRONG)
/* Is weak? */
#define BIDI_IS_WEAK(p) ((p) & BIDI_MASK_WEAK)
/* Is neutral? */
@@ -7615,23 +7636,26 @@ typedef Uint8 BidiArabicProp;
/* Is explicit or BN: LRE, RLE, LRO, RLO, PDF, BN? */
#define BIDI_IS_EXPLICIT_OR_BN(p) \
((((p) & BIDI_TYPE_MASK) == BIDI_MASK_EXPLICIT) || \
((p) & (BIDI_MASK_BN)))
(((p) & BIDI_MISC_MASK) == BIDI_MASK_BN))
/* Is explicit or BN or WS: LRE, RLE, LRO, RLO, PDF, BN, WS? */
#define BIDI_IS_EXPLICIT_OR_BN_OR_WS(p) \
((((p) & BIDI_TYPE_MASK) == BIDI_MASK_EXPLICIT) || \
((p) & (BIDI_MASK_BN | BIDI_MASK_WS)))
(((p) & BIDI_MISC_MASK) == BIDI_MASK_BN) || \
(((p) & BIDI_MISC_MASK) == BIDI_MASK_WS))
/* Is explicit or separator or BN or WS: LRE, RLE, LRO, RLO, PDF, BS, SS, BN, WS? */
#define BIDI_IS_EXPLICIT_OR_SEPARATOR_OR_BN_OR_WS(p) \
((((p) & BIDI_TYPE_MASK) == BIDI_MASK_EXPLICIT) || \
((p) & (BIDI_MASK_SEPARATOR | BIDI_MASK_BN | BIDI_MASK_WS)))
((p) & BIDI_MASK_SEPARATOR) || \
(((p) & BIDI_MISC_MASK) == BIDI_MASK_BN) || \
(((p) & BIDI_MISC_MASK) == BIDI_MASK_WS))
/* Is explicit or BN or NSM: LRE, RLE, LRO, RLO, PDF, BN, NSM? */
#define BIDI_IS_EXPLICIT_OR_BN_OR_NSM(p) \
((((p) & BIDI_TYPE_MASK) == BIDI_MASK_EXPLICIT) || \
(((p) & BIDI_TYPE_MASK) == BIDI_MASK_NSM) || \
((p) & BIDI_MASK_BN))
(((p) & BIDI_MISC_MASK) == BIDI_MASK_BN))
/* Override status of an explicit mark:
* LRO,LRE->LTR, RLO,RLE->RTL, otherwise->ON. */
@@ -7643,6 +7667,10 @@ typedef Uint8 BidiArabicProp;
#define BIDI_CHANGE_NUMBER_TO_RTL(p) \
(BIDI_IS_NUMBER(p) ? BIDI_TYPE_RTL : (p))
#define BIDI_PGDIR_LTR BIDI_TYPE_LTR
#define BIDI_PGDIR_RTL BIDI_TYPE_RTL
#define BIDI_PGDIR_ON BIDI_TYPE_ON
/** @} end of bidi_types */
#ifdef _MGCHARSET_UNICODE
+1 -9
View File
@@ -33,7 +33,7 @@
*/
/*
** mgbidi-bidi-types-list.h:
** mgbidi-bidi-types-list.inc:
**
** The list of BIDI types
**
@@ -42,14 +42,6 @@
** This implementation is based on LGPL'd FriBidi:
**
** https://github.com/fribidi/fribidi
**
** Authors:
** Behdad Esfahbod, 2001, 2002, 2004
** Dov Grobgeld, 1999, 2000, 2017
**
** Copyright (C) 2004 Sharif FarsiWeb, Inc
** Copyright (C) 2001,2002 Behdad Esfahbod
** Copyright (C) 1999,2000,2017 Dov Grobgeld
*/
#ifndef _UNIBIDI_ADD_TYPE
+22 -23
View File
@@ -88,6 +88,7 @@ static void validate_run_list(BidiRun *run_list)
static inline void validate_run_list(BidiRun *run_list)
{
// do nothing.
}
#endif /* !DEBUG */
@@ -481,11 +482,11 @@ static const char char_from_level_array[] = {
static const char *unibidi_get_bidi_type_name(BidiType t)
{
switch ((int)t) {
# define _BIDI_ADD_TYPE(TYPE,SYMBOL) case BIDI_TYPE_##TYPE: return #TYPE;
# define _BIDI_ALL_TYPES
# include "unicode-bidi-types-list.inc"
# undef _BIDI_ALL_TYPES
# undef _BIDI_ADD_TYPE
#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) case BIDI_TYPE_##TYPE: return #TYPE;
#define _UNIBIDI_ALL_TYPES
#include "unicode-bidi-types-list.inc"
#undef _UNIBIDI_ALL_TYPES
#undef _UNIBIDI_ADD_TYPE
default:
return "?";
}
@@ -504,8 +505,7 @@ static void print_types_re(const BidiRun *pp)
static void print_resolved_levels(const BidiRun *pp)
{
_DBG_PRINTF (" Res. levels: ");
for_run_list (pp, pp)
{
for_run_list (pp, pp) {
register int i;
for (i = RL_LEN (pp); i; i--)
_DBG_PRINTF ("%c", unibidi_char_from_level (RL_LEVEL (pp)));
@@ -754,8 +754,6 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
goto out;
}
_DBG_PRINTF ("in UBidiGetParagraphEmbeddingLevels");
/* Determinate character types */
{
/* Get run-length encoded character types */
@@ -791,8 +789,8 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
}
}
base_dir = BIDI_LEVEL_TO_DIR (base_level);
_DBG_PRINTF (" base level : %c", unibidi_char_from_level (base_level));
_DBG_PRINTF (" base dir : %s", unibidi_get_bidi_type_name (base_dir));
_DBG_PRINTF (" base level : %c\n", unibidi_char_from_level (base_level));
_DBG_PRINTF (" base dir : %s\n", unibidi_get_bidi_type_name (base_dir));
base_level_per_iso_level[0] = base_level;
@@ -801,7 +799,8 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
#endif /* DEBUG */
/* Explicit Levels and Directions */
_DBG_PRINTF ("explicit levels and directions");
_DBG_PRINTF ("explicit levels and directions\n");
{
BidiLevel level, new_level = 0;
int isolate_level = 0;
@@ -1046,7 +1045,7 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
/* 4. Resolving weak types. Also calculate the maximum isolate level */
max_iso_level = 0;
_DBG_PRINTF ("resolving weak types");
_DBG_PRINTF ("resolving weak types\n");
{
int last_strong_stack[BIDI_MAX_RESOLVED_LEVELS];
BidiType prev_type_orig;
@@ -1224,7 +1223,8 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
/* 5. Resolving Neutral Types */
_DBG_PRINTF ("resolving neutral types - N0");
_DBG_PRINTF ("resolving neutral types - N0\n");
{
/* BD16 - Build list of all pairs*/
int num_iso_levels = max_iso_level + 1;
@@ -1396,7 +1396,7 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
#endif /* DEBUG */
}
_DBG_PRINTF ("resolving neutral types - N1+N2");
_DBG_PRINTF ("resolving neutral types - N1+N2\n");
{
for_run_list (pp, main_run_list)
{
@@ -1435,7 +1435,7 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
#endif /* DEBUG */
/* 6. Resolving implicit levels */
_DBG_PRINTF ("resolving implicit levels");
_DBG_PRINTF ("resolving implicit levels\n");
{
max_level = base_level;
@@ -1471,7 +1471,7 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
/* Reinsert the explicit codes & BN's that are already removed, from the
explicits_list to main_run_list. */
_DBG_PRINTF ("reinserting explicit codes");
_DBG_PRINTF ("reinserting explicit codes\n");
if (explicits_list->next != explicits_list) {
register BidiRun *p;
register BOOL stat =
@@ -1494,7 +1494,7 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
print_resolved_types (main_run_list);
#endif /* DEBUG */
_DBG_PRINTF ("reset the embedding levels, 1, 2, 3.");
_DBG_PRINTF ("reset the embedding levels, 1, 2, 3.\n");
{
register int j, state, pos;
register BidiType char_type;
@@ -1566,8 +1566,6 @@ BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types,
status = TRUE;
out:
_DBG_PRINTF ("leaving UBidiGetParagraphEmbeddingLevels");
if (main_run_list)
free_run_list (main_run_list);
if (explicits_list) free_run_list (explicits_list);
@@ -1613,9 +1611,9 @@ BidiLevel UBidiReorderLine(Uint32 flags,
goto out;
}
_DBG_PRINTF ("in UBidiReorderLine");
_DBG_PRINTF ("%s: reset the embedding levels, 4. whitespace at the end of line\n",
__FUNCTION__);
_DBG_PRINTF ("reset the embedding levels, 4. whitespace at the end of line");
{
register int i;
@@ -1649,7 +1647,8 @@ BidiLevel UBidiReorderLine(Uint32 flags,
if (i < off || embedding_levels[i] != level) {
i++;
_DBG_PRINTF ("warning: NSM(s) at the beginning of level run");
_DBG_PRINTF ("%s, warning: NSM(s) at the beginning of level run\n",
__FUNCTION__);
}
if (visual_str) {
+1 -1
View File
@@ -284,10 +284,10 @@ struct _BidiRun {
BidiRun *next_isolate;
int pos, len;
BidiBracketType bracket_type;
BidiType type;
BidiLevel level;
BidiLevel isolate_level;
Uint8 bracket_type;
};
#define swap(a,b) \
+3 -3
View File
@@ -71,10 +71,10 @@ static char get_char_from_joining_type(BidiJoiningType j, BOOL visual)
(!BIDI_JOINS_RIGHT (j) && BIDI_JOINS_LEFT (j))))
j ^= BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT;
# define _BIDI_ADD_TYPE(TYPE,SYMBOL) \
#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) \
if (BIDI_IS_JOINING_TYPE_##TYPE(j)) return SYMBOL;
# include "unicode-joining-types-list.inc"
# undef _BIDI_ADD_TYPE
#include "unicode-joining-types-list.inc"
#undef _UNIBIDI_ADD_TYPE
return '?';
}