From ca9d0200f36195149db357940d0fd2eab159ef6d Mon Sep 17 00:00:00 2001 From: Vincent Wei Date: Mon, 11 Mar 2019 15:47:48 +0800 Subject: [PATCH] Implementation of UBidiXXX functions --- include/gdi.h | 248 +++++++++++++++++++++++++------ src/font/Makefile.am | 4 +- src/font/charset.c | 6 +- src/font/unicode-bidi.c | 14 +- src/font/unicode-bidi.h | 185 ++++++++++++++++++++++- src/font/unicode-joining-types.c | 84 +++++++++++ src/font/unicode-joining.c | 199 +++++++++++++++++++++++++ src/font/unicode-shape-arabic.c | 168 +++++++++++++++++++++ src/font/unicode-shape.c | 97 ++++++++++++ 9 files changed, 944 insertions(+), 61 deletions(-) create mode 100644 src/font/unicode-joining-types.c create mode 100644 src/font/unicode-joining.c create mode 100644 src/font/unicode-shape-arabic.c create mode 100644 src/font/unicode-shape.c diff --git a/include/gdi.h b/include/gdi.h index bccb07ab..b0165b1f 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -5920,7 +5920,7 @@ typedef Uint32 Uchar32; * * These are the possible character classifications from the * Unicode specification. - * See [Unicode Character Database](http://www.unicode.org/reports/tr44/#General_Category_Values). + * See [Unicode Character Database](https://www.unicode.org/reports/tr44/#General_Category_Values). */ typedef enum { UCHAR_CATEGORY_CONTROL, @@ -6007,7 +6007,7 @@ typedef enum { * Since new unicode versions may add new types here, applications should be * ready to handle unknown values. They may be regarded as %UCHAR_BREAK_UNKNOWN. * - * See [Unicode Line Breaking Algorithm](http://www.unicode.org/unicode/reports/tr14/). + * See [Unicode Line Breaking Algorithm](https://www.unicode.org/unicode/reports/tr14/). */ typedef enum { UCHAR_BREAK_MANDATORY, @@ -6221,7 +6221,7 @@ typedef enum { * * Note that new types may be added in the future. Applications * should be ready to handle unknown values. - * See [Unicode Standard Annex #24: Script names](http://www.unicode.org/reports/tr24/). + * See [Unicode Standard Annex #24: Script names](https://www.unicode.org/reports/tr24/). */ typedef enum { UCHAR_SCRIPT_INVALID_CODE = -1, @@ -7310,6 +7310,9 @@ typedef Uint8 BidiLevel; typedef Uint16 BidiType; typedef Uint32 BidiBracketType; +typedef Uint8 BidiJoiningType; +typedef Uint8 BidiArabicProp; + #ifdef _MGCHARSET_UNICODE #include @@ -7487,12 +7490,12 @@ MG_EXPORT UCharBreakType GUIAPI UCharGetBreakType(Uchar32 uc); * * \return The bidi type. * - * \sa UCharGetBidiTypes, bidi_types + * \sa UStrGetBidiTypes, bidi_types */ MG_EXPORT BidiType GUIAPI UCharGetBidiType(Uchar32 uc); /** - * \fn void GUIAPI UCharGetBidiTypes(const Uchar32* ucs, int nr_ucs, + * \fn void GUIAPI UStrGetBidiTypes(const Uchar32* ucs, int nr_ucs, * BidiType* bds); * \brief Get bidi types for an string of Unicode characters. * @@ -7505,7 +7508,7 @@ MG_EXPORT BidiType GUIAPI UCharGetBidiType(Uchar32 uc); * * \sa UCharGetBidiType */ -MG_EXPORT void GUIAPI UCharGetBidiTypes(const Uchar32* ucs, int nr_ucs, +MG_EXPORT void GUIAPI UStrGetBidiTypes(const Uchar32* ucs, int nr_ucs, BidiType* bds); #define BIDI_BRACKET_NONE 0 @@ -7519,7 +7522,7 @@ MG_EXPORT void GUIAPI UCharGetBidiTypes(const Uchar32* ucs, int nr_ucs, * * This function finds the bracketed equivalent of a character as defined in * the file BidiBrackets.txt of the Unicode Character Database available at - * http://www.unicode.org/Public/UNIDATA/BidiBrackets.txt. + * https://www.unicode.org/Public/UNIDATA/BidiBrackets.txt. * * If the input character is a declared as a brackets character in the * Unicode standard and has a bracketed equivalent. The matching bracketed @@ -7533,11 +7536,11 @@ MG_EXPORT void GUIAPI UCharGetBidiTypes(const Uchar32* ucs, int nr_ucs, * property. Use BCHI_BRACKET_CHAR(BidiBracketType) to get * the bracketed character value. * - * \sa UCharGetBracketTypes + * \sa UStrGetBracketTypes */ MG_EXPORT BidiBracketType GUIAPI UCharGetBracketType(Uchar32 ch); -/* \fn void UCharGetBracketTypes(const Uchar32 *ucs, int nr_ucs, +/* \fn void UStrGetBracketTypes(const Uchar32 *ucs, int nr_ucs, * const BidiType *bidi_types, BidiBracketType *bracket_types) * \brief Get bracketed characters of a Uchar32 string. * @@ -7553,7 +7556,7 @@ MG_EXPORT BidiBracketType GUIAPI UCharGetBracketType(Uchar32 ch); * * \sa UCharGetBracketType */ -MG_EXPORT void GUIAPI UCharGetBracketTypes(const Uchar32 *ucs, int len_ucs, +MG_EXPORT void GUIAPI UStrGetBracketTypes(const Uchar32 *ucs, int len_ucs, const BidiType *bidi_types, BidiBracketType *bracket_types); /** @@ -7579,15 +7582,55 @@ MG_EXPORT void GUIAPI UCharGetBracketTypes(const Uchar32 *ucs, int len_ucs, MG_EXPORT BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored); /** - * \fn int GUIAPI UCharGetParagraphDir(const BidiType *bidi_types, int len) + * \fn BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 uc) + * \brief Get character joining type. + * + * This function returns the joining type of a character as defined in Table + * 8-2 Primary Arabic Joining Classes of the Unicode standard available at + * + * https://www.unicode.org/versions/Unicode12.0.0/ch08.pdf#G7462 + * + * using data provided in file ArabicShaping.txt and UnicodeData.txt of + * the Unicode Character Database available at + * + * https://www.unicode.org/Public/UNIDATA/ArabicShaping.txt + * + * and + * + * https://www.unicode.org/Public/UNIDATA/UnicodeData.txt. + * + */ +MG_EXPORT BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 uc); + +/** + * \fn void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, + * BidiJoiningType *joing_types, int len) + * \brief Get joining types for a string of Unicode characters + * + * This function finds the joining types of an string of characters. + * See \a UCharGetJoiningType for more information about the + * joining types returned by this function. + * + * \param ucs The input Uchar32 string. + * \param joining_types The output joining types. + * \param len The string length. + * + * \sa UCharGetJoiningType + */ +MG_EXPORT void GUIAPI UStrGetJoiningTypes(const Uchar32 *ucs, + BidiJoiningType *joing_types, int len); + +/** + * \fn int GUIAPI UBidiGetParagraphDir(const BidiType *bidi_types, int len) * \brief get base paragraph direction * * This function finds the base direction of a single paragraph, * as defined by rule P2 of the Unicode Bidirectional Algorithm available at - * http://www.unicode.org/reports/tr9/#P2. + * + * https://www.unicode.org/reports/tr9/#P2. * * You typically do not need this function as - * __mg_unicode_bidi_get_paragraph_els() knows how to compute base direction + * UBidiGetParagraphEmbeddingLevels() knows how to compute base direction * itself, but you may need this to implement a more sophisticated paragraph * direction handling. Note that you can pass more than a paragraph to this * function and the direction of the first non-neutral paragraph is returned, @@ -7596,17 +7639,17 @@ MG_EXPORT BOOL GUIAPI UCharGetMirror(Uchar32 uc, Uchar32* mirrored); * direction of the previous paragraph. * * \param bidi_types the pointer to the BidiType array as returned by - * __mg_unicode_bidi_get_bidi_types() + * UStrGetBidiTypes(). * \param len The length of bidi_types * * \return Base pargraph direction. No weak paragraph direction is returned, * only BIDI_PGDIR_LTR, BIDI_PGDIR_RTL, or BIDI_PGDIR_ON. * */ -MG_EXPORT int GUIAPI UCharGetParagraphDir(const BidiType *bidi_types, int len); +MG_EXPORT int GUIAPI UBidiGetParagraphDir(const BidiType *bidi_types, int len); /** - * \fn BidiLevel GUIAPI UCharGetParagraphEmbeddingLevels( + * \fn BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevels( * const BidiType *bidi_types, * const BidiBracketType* bracket_types, int len, * int *base_dir, BidiLevel *embedding_levels); @@ -7618,12 +7661,12 @@ MG_EXPORT int GUIAPI UCharGetParagraphDir(const BidiType *bidi_types, int len); * https://www.unicode.org/reports/tr9/. * * This function implements rules P2 to I1 inclusive, and parts 1 to 3 of L1. - * Part 4 of L1 is implemented in __mg_unicode_bidi_reorder_line(). + * Part 4 of L1 is implemented in UBidiReorderLine(). * * \param bidi_types the pointer to the BidiType array as returned by - * UCharGetBidiTypes(). + * UStrGetBidiTypes(). * \param bracket_types The pointer to a Uint8 which contains the - bracket types as returned by UCharGetBracketTypes() + bracket types as returned by UStrGetBracketTypes() * \param len The length of the list. * \param base_dir requested and resolved paragraph base direction * \param embedding_levels The pointer to a buffer which will restore @@ -7632,9 +7675,9 @@ MG_EXPORT int GUIAPI UCharGetParagraphDir(const BidiType *bidi_types, int len); * \return The Maximum level found plus one, or zero if any error occurred * (memory allocation failure most probably). * - * \sa UCharGetBidiTypes, UCharGetBracketTypes + * \sa UStrGetBidiTypes, UStrGetBracketTypes */ -MG_EXPORT BidiLevel GUIAPI UCharGetParagraphEmbeddingLevels( +MG_EXPORT BidiLevel GUIAPI UBidiGetParagraphEmbeddingLevels( const BidiType *bidi_types, const BidiBracketType* bracket_types, int len, int *base_dir, BidiLevel *embedding_levels); @@ -7646,12 +7689,12 @@ MG_EXPORT BidiLevel GUIAPI UCharGetParagraphEmbeddingLevels( * The function reverse an array pointed by \a extra from the position * specified by \a pos for the length specified by \a len. * - * \sa UCharReorderBidiLine, BIDILogAChars2VisACharsEx + * \sa UBidiReorderLine, BIDILogAChars2VisACharsEx */ typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos); /** - * \fn BidiLevel GUIAPI UCharReorderBidiLine(Uint32 reorder_flags, + * \fn BidiLevel GUIAPI UBidiReorderLine(Uint32 bidi_flags, * const BidiType *bidi_types, int len, int off, * int base_dir, BidiLevel *embedding_levels, * Uchar32 *visual_str, int *map, @@ -7669,7 +7712,7 @@ typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos); * As a side effect it also sets position maps if not NULL. * * You should provide the resolved paragraph direction and embedding levels as - * set by UCharGetParagraphEmbeddingLevels(). Also note that the embedding + * set by UBidiGetParagraphEmbeddingLevels(). Also note that the embedding * levels may change a bit. To be exact, the embedding level of any sequence * of white space at the end of line is reset to the paragraph embedding level * (That is part 4 of rule L1). @@ -7687,54 +7730,161 @@ typedef void (*CB_REVERSE_EXTRA) (void* extra, int len, int pos); * for example do not like it. This is controlled by the * BIDI_FLAG_REORDER_NSM flag. The flag is on in BIDI_FLAGS_DEFAULT. * - * \param reorder_flags The reorder flags. + * \param bidi_flags The reorder flags. * \param bidi_types the pointer to the BidiType array as returned by - * UCharGetBidiTypes() + * UStrGetBidiTypes() * \param bracket_types The pointer to a BidiBracketType array which - * contains the bracket types as returned by UCharGetBracketTypes() + * contains the bracket types as returned by UStrGetBracketTypes() * \param len The length of the list. * \param off The input offset of the beginning of the line in the paragraph. * \param base_dir The resolved paragraph base direction. * \param embedding_levels The embedding levels, as returned by - UCharGetParagraphEmbeddingLevels() + UBidiGetParagraphEmbeddingLevels() * \param visual_str The Uchar32 string will be reordered. - * \param map a map of string indices which is reordered to reflect - * where each glyph ends up. + * \param indices_map A map of string indices which is reordered to reflect + * where each character ends up. * \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 Maximum level found in this line plus one, or zero if any error * occurred (memory allocation failure most probably). * - * \sa UCharGetBidiTypes, UCharGetBracketTypes, - * UCharGetParagraphEmbeddingLevels + * \sa UStrGetBidiTypes, UStrGetBracketTypes, + * UBidiGetParagraphEmbeddingLevels */ -MG_EXPORT BidiLevel GUIAPI UCharReorderBidiLine(Uint32 reorder_flags, +MG_EXPORT BidiLevel GUIAPI UBidiReorderLine(Uint32 bidi_flags, const BidiType *bidi_types, int len, int off, int base_dir, BidiLevel *embedding_levels, - Uchar32 *visual_str, int *map, + Uchar32 *visual_str, int *indices_map, void* extra, CB_REVERSE_EXTRA cb_reverse_extra); /** - * \fn void GUIAPI UCharShapeMirroring(const BidiLevel *els, int len, - * Uchar32 *ucs) + * \fn void GUIAPI UBidiShapeMirroring(const BidiLevel *els, + * Uchar32 *ucs, int len) * \brief Do mirroring shaping * * This functions replaces mirroring characters on right-to-left embeddings in * string with their mirrored equivalent as returned by UCharGetMirror(). * * This function implements rule L4 of the Unicode Bidirectional Algorithm - * available at http://www.unicode.org/reports/tr9/#L4. + * available at + * + * https://www.unicode.org/reports/tr9/#L4. * * \param els input list of embedding levels, as returned by - * UCharGetParagraphEmbeddingLevels(). - * \param len The input string length. + * UBidiGetParagraphEmbeddingLevels(). * \param ucs The Uchar32 string to shape. + * \param len The input string length. * - * \sa UCharGetParagraphEmbeddingLevels + * \sa UBidiGetParagraphEmbeddingLevels */ -MG_EXPORT void GUIAPI UCharShapeMirroring(const BidiLevel *els, int len, - Uchar32 *ucs); +MG_EXPORT void GUIAPI UBidiShapeMirroring(const BidiLevel *els, + Uchar32* ucs, int len); + +/** + * \fn void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, + * const BidiLevel *embedding_levels, BidiArabicProp *ar_props, + * int len); + * \brief Do Arabic joining + * + * This function does the Arabic joining algorithm. Means, given Arabic + * joining types of the characters in ar_props (note that + * FriBidiJoiningType can be casted to BidiArabicProp automagically), this + * function modifies this properties to grasp the effect of neighboring + * characters. You probably need this information later to do Arabic shaping. + * + * This function implements rules R1 to R7 inclusive (all rules) of the Arabic + * Cursive Joining algorithm of the Unicode standard as available at + * + * https://www.unicode.org/versions/Unicode4.0.0/ch08.pdf#G7462. + * + * It also interacts correctly with the bidirection algorithm as defined in + * Section 3.5 Shaping of the Unicode Bidirectional Algorithm available at + * + * https://www.unicode.org/reports/tr9/#Shaping. + * + * There are a few macros defined in fribidi-joining-types.h for querying the + * Arabic properties computed by this function. + * + * \param bidi_types The list of bidi types as returned by UStrGetBidiTypes(). + * \param embedding_levels input list of embedding levels, as returned by + * UBidiGetParagraphEmbeddingLevels(). + * \param ar_props Arabic properties to analyze, initialized by joining types, + * as returned by fribidi_get_joining_types + */ +MG_EXPORT void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, + const BidiLevel *embedding_levels, BidiArabicProp *ar_props, + int len); + +/** + * \fn void GUIAPI UBidiShapeArabic(Uint32 bidi_flags, + * const BidiLevel *embedding_levels, + * BidiArabicProp *ar_props, FriBidiChar *ucs, int len) + * \brief Do Arabic shaping. + * + * The actual shaping that is done depends on the flags set. The following + * flags affect this function: + * + * - BIDI_FLAG_SHAPE_MIRRORING: Do mirroring.\n + * - BIDI_FLAG_SHAPE_ARAB_PRES: Shape Arabic characters to + * their presentation form glyphs.\n + * - BIDI_FLAG_SHAPE_ARAB_LIGA: Form mandatory Arabic ligatures.\n + * - BIDI_FLAG_SHAPE_ARAB_CONSOLE: Perform additional Arabic shaping + * suitable for text rendered on grid terminals with no mark + * rendering capabilities. + * + * Of the above, FRIBIDI_FLAG_SHAPE_ARAB_CONSOLE is only used in special + * cases, but the rest are recommended in any environment that doesn't have + * other means for doing Arabic shaping. The set of extra flags that enable + * this level of Arabic support has a shortcut named FRIBIDI_FLAGS_ARABIC. + * + * \param shaping_flags shaping flags. + * \param embedding_levels input list of embedding levels, as returned by + * UBidiGetParagraphEmbeddingLevels(). + * \param arb_props The Arabic character properties as computed by + * UBidiJoinArabic(). + * \param ucs The Uchar32 string to shape. + * \param len The length of the string. + * + * \sa UBidiGetParagraphEmbeddingLevels, UBidiJoinArabic + */ +MG_EXPORT void GUIAPI UBidiShapeArabic(Uint32 shaping_flags, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, Uchar32* ucs, int len); + +/** + * \fn void GUIAPI UBidiShape(Uint32 shaping_flags, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, Uchar32* ucs, int len) + * \brief Do bidi-aware shaping. + * + * This function does all shaping work that depends on the resolved embedding + * levels of the characters. Currently it does mirroring and Arabic shaping, + * but the list may grow in the future. This function is a wrapper around + * fribidi_shape_mirroring and fribidi_shape_arabic. + * + * The flags parameter specifies which shapings are applied. The only flags + * affecting the functionality of this function are those beginning with + * BIDI_FLAG_SHAPE_. Of these, only BIDI_FLAG_SHAPE_MIRRORING is on + * in BIDI_FLAGS_DEFAULT. For details of the Arabic-specific flags see + * UBidiShapeArabic. If ar_props is NULL, no Arabic shaping is performed. + * + * Feel free to do your own shaping before or after calling this function, + * but you should take care of embedding levels yourself then. + * + * \param shaping_flags shaping flags + * \param embedding_levels input list of embedding levels, as returned by + * UBidiGetParagraphEmbeddingLevels(). + * \param arb_props The Arabic character properties as computed by + * UBidiJoinArabic(). + * \param ucs The Uchar32 string to shape. + * \param len The length of the string. + * + * \sa UBidiShapeArabic, UBidiShapeMirroring + */ +MG_EXPORT void GUIAPI UBidiShape(Uint32 shaping_flags, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, Uchar32* ucs, int len); /** The function determines whether a character is alphanumeric. */ MG_EXPORT BOOL GUIAPI IsUCharAlnum(Uchar32 uc); @@ -7798,7 +7948,7 @@ MG_EXPORT BOOL GUIAPI IsUCharWide(Uchar32 uc); * cell under legacy East Asian locales. If a character is wide according to * g_unichar_iswide(), then it is also reported wide with this function, but * the converse is not necessarily true. See the - * [Unicode Standard Annex #11](http://www.unicode.org/reports/tr11/) + * [Unicode Standard Annex #11](https://www.unicode.org/reports/tr11/) * for details. */ MG_EXPORT BOOL GUIAPI IsUCharWideCJK(Uchar32 uc); @@ -7889,7 +8039,7 @@ MG_EXPORT int GUIAPI UCharGetScriptType (Uchar32 ch); * is not understood. * * See - * [Codes for the representation of names of scripts](http://unicode.org/iso15924/codelists.html) + * [Codes for the representation of names of scripts](https://www.unicode.org/iso15924/codelists.html) * for details. * * Since: 3.4.0 @@ -7912,7 +8062,7 @@ MG_EXPORT Uint32 GUIAPI UCharScriptTypeToISO15924 (int script); * \a UCHAR_SCRIPT_UNKNOWN if \a iso15924 is unknown. * * See - * [Codes for the representation of names of scripts](http://unicode.org/iso15924/codelists.html) + * [Codes for the representation of names of scripts](https://www.unicode.org/iso15924/codelists.html) * for details. * * Since: 3.4.0 @@ -7932,7 +8082,7 @@ MG_EXPORT int GUIAPI UCharScriptTypeFromISO15924 (Uint32 iso15924); * \a UCHAR_SCRIPT_UNKNOWN if \a iso15924 is unknown. * * See - * [Codes for the representation of names of scripts](http://unicode.org/iso15924/codelists.html) + * [Codes for the representation of names of scripts](https://www.unicode.org/iso15924/codelists.html) * for details. * * Since: 3.4.0 @@ -11386,7 +11536,7 @@ static inline int GUIAPI LanguageCodeFromISO639s1Code (const char* iso639_1) * \param lbp The line breaking policy; * see \a line_break_policies. * \param uchars The pointer to a buffer to store the address of the - * UChar32 array which contains the Unicode character values. + * Uchar32 array which contains the Unicode character values. * \param break_oppos The pointer to a buffer to store the address of the * Uint16 array which contains the break opportunities of the glyphs. * Note that the length of this array is always one longer than @@ -11750,7 +11900,7 @@ typedef struct _SHAPEDGLYPH { * such as UTF-8, UTF-16LE, and UTF-16BE. * \param content_language The content lanuage identifier. * \param writing_system The writing system (script) identifier. - * \param ucs The pointer to the UChar32 array which contains the Unicode + * \param ucs The pointer to the Uchar32 array which contains the Unicode * characters. * \param break_oppos The pointer to a Uint16 array which contains * the break opportunities of the Unicode characters. @@ -11806,7 +11956,7 @@ MG_EXPORT int GUIAPI GetShapedGlyphsBasic(LOGFONT* logfont, * of the logfont should be OpenType font files, and use FreeType2 engine. * \param content_language The content lanuage identifier. * \param writing_system The writing system (script) identifier. - * \param ucs The pointer to the UChar32 array which contains the Unicode + * \param ucs The pointer to the Uchar32 array which contains the Unicode * characters. * \param break_oppos The pointer to a Uint16 array which contains * the break opportunities of the Unicode characters. diff --git a/src/font/Makefile.am b/src/font/Makefile.am index 74dcba89..1778ae05 100644 --- a/src/font/Makefile.am +++ b/src/font/Makefile.am @@ -13,7 +13,9 @@ SRC_FILES = charset.c charset-arabic.c legacy-bidi.c \ mapunitogb.c mapunitogbk.c mapunitobig5.c mapunitogb18030.c \ bitmapfont.c scripteasy.c \ unicode-emoji.c \ - unicode-bidi.c + unicode-bidi.c \ + unicode-joining-types.c unicode-joining.c unicode-shape.c \ + unicode-shape-arabic.c HDR_FILES = charset.h rawbitmap.h varbitmap.h freetype2.h qpf.h se_minigui.h \ upf.h bitmapfont.h unicode-bidi-tables.h \ diff --git a/src/font/charset.c b/src/font/charset.c index 6d2590c0..5bb00177 100644 --- a/src/font/charset.c +++ b/src/font/charset.c @@ -3608,7 +3608,7 @@ BidiType GUIAPI UCharGetBidiType(Uchar32 uc) return linear_enum_to_bidi_type[UNIBIDI_GET_BIDI_TYPE(uc)]; } -void GUIAPI UCharGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) +void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) { register int i = len; for (; i; i--) { @@ -3650,7 +3650,7 @@ BidiBracketType UCharGetBracketType(Uchar32 ch) return bracket_type; } -void UCharGetBracketTypes(const Uchar32 *str, int len, +void UStrGetBracketTypes(const Uchar32 *str, int len, const BidiType *types, BidiBracketType *btypes) { int i; @@ -3773,7 +3773,7 @@ found: return bracket_type; } -void GUIAPI UCharGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) +void GUIAPI UStrGetBidiTypes(const Uchar32 *str, int len, BidiType *btypes) { register int i = len; for (; i; i--) { diff --git a/src/font/unicode-bidi.c b/src/font/unicode-bidi.c index b77f5946..f1306ef3 100644 --- a/src/font/unicode-bidi.c +++ b/src/font/unicode-bidi.c @@ -644,7 +644,7 @@ static void print_pairing_nodes(BidiPairingNode *nodes) #define BIDI_EMBEDDING_DIRECTION(link) \ BIDI_LEVEL_TO_DIR(RL_LEVEL(link)) -int UCharGetParagraphDir(const BidiType *bidi_types, const int len) +int UBidiGetParagraphDir(const BidiType *bidi_types, const int len) { register int i; @@ -738,7 +738,7 @@ static void free_pairing_nodes(BidiPairingNode *nodes) } } -BidiLevel UCharGetParagraphEmbeddingLevels(const BidiType *bidi_types, +BidiLevel UBidiGetParagraphEmbeddingLevels(const BidiType *bidi_types, const BidiBracketType *bracket_types, const int len, int *pbase_dir, BidiLevel *embedding_levels) { @@ -754,7 +754,7 @@ BidiLevel UCharGetParagraphEmbeddingLevels(const BidiType *bidi_types, goto out; } - _DBG_PRINTF ("in UCharGetParagraphEmbeddingLevels"); + _DBG_PRINTF ("in UBidiGetParagraphEmbeddingLevels"); /* Determinate character types */ { @@ -1507,7 +1507,7 @@ BidiLevel UCharGetParagraphEmbeddingLevels(const BidiType *bidi_types, separator or paragraph separator, and 4. any sequence of whitespace characters and/or isolate formatting characters at the end of the line. - ... (to be continued in UCharReorderBidiLine()). */ + ... (to be continued in UBidiReorderLine()). */ list = new_run_list (); if (!list) goto out; q = list; @@ -1566,7 +1566,7 @@ BidiLevel UCharGetParagraphEmbeddingLevels(const BidiType *bidi_types, status = TRUE; out: - _DBG_PRINTF ("leaving UCharGetParagraphEmbeddingLevels"); + _DBG_PRINTF ("leaving UBidiGetParagraphEmbeddingLevels"); if (main_run_list) free_run_list (main_run_list); @@ -1599,7 +1599,7 @@ static void index_array_reverse (int *arr, int len) } } -BidiLevel UCharReorderBidiLine(Uint32 flags, +BidiLevel UBidiReorderLine(Uint32 flags, const BidiType *bidi_types, int len, int off, int base_dir, BidiLevel *embedding_levels, Uchar32 *visual_str, int *map, @@ -1613,7 +1613,7 @@ BidiLevel UCharReorderBidiLine(Uint32 flags, goto out; } - _DBG_PRINTF ("in UCharReorderBidiLine"); + _DBG_PRINTF ("in UBidiReorderLine"); _DBG_PRINTF ("reset the embedding levels, 4. whitespace at the end of line"); { diff --git a/src/font/unicode-bidi.h b/src/font/unicode-bidi.h index bfe95c9c..7bb7dac9 100644 --- a/src/font/unicode-bidi.h +++ b/src/font/unicode-bidi.h @@ -55,6 +55,41 @@ #define UNIBIDI_UNICODE_CHARS 0xFFFE #endif +/* Some special Unicode characters */ + +/* Bidirectional marks */ +#define BIDI_CHAR_LRM 0x200E +#define BIDI_CHAR_RLM 0x200F +#define BIDI_CHAR_LRE 0x202A +#define BIDI_CHAR_RLE 0x202B +#define BIDI_CHAR_PDF 0x202C +#define BIDI_CHAR_LRO 0x202D +#define BIDI_CHAR_RLO 0x202E +#define BIDI_CHAR_LRI 0x2066 +#define BIDI_CHAR_RLI 0x2067 +#define BIDI_CHAR_FSI 0x2068 +#define BIDI_CHAR_PDI 0x2069 + +/* Line and Paragraph Separators */ +#define BIDI_CHAR_LS 0x2028 +#define BIDI_CHAR_PS 0x2029 + +/* Arabic Joining marks */ +#define BIDI_CHAR_ZWNJ 0x200C +#define BIDI_CHAR_ZWJ 0x200D + +/* Hebrew and Arabic */ +#define BIDI_CHAR_HEBREW_ALEF 0x05D0 +#define BIDI_CHAR_ARABIC_ALEF 0x0627 +#define BIDI_CHAR_ARABIC_ZERO 0x0660 +#define BIDI_CHAR_PERSIAN_ZERO 0x06F0 + +/* Misc */ +#define BIDI_CHAR_ZWNBSP 0xFEFF + +/* Char we place for a deleted slot, to delete later */ +#define BIDI_CHAR_FILL BIDI_CHAR_ZWNBSP + /* some general macros */ #define STRINGIZE(symbol) #symbol @@ -84,7 +119,155 @@ /* The maximum *number* of nested brackets: 0-63 */ #define BIDI_MAX_NESTED_BRACKET_PAIRS 63 -#define BIDI_SENTINEL -1 +#define BIDI_SENTINEL -1 + +/* + * Define bit masks that joining types are based on, each mask has + * only one bit set. + */ +#define BIDI_MASK_JOINS_RIGHT 0x01 /* May join to right */ +#define BIDI_MASK_JOINS_LEFT 0x02 /* May join to right */ +#define BIDI_MASK_ARAB_SHAPES 0x04 /* May Arabic shape */ +#define BIDI_MASK_TRANSPARENT 0x08 /* Is transparent */ +#define BIDI_MASK_IGNORED 0x10 /* Is ignored */ +#define BIDI_MASK_LIGATURED 0x20 /* Is ligatured */ + +/* + * Define values for FriBidiJoiningType + */ + +/* nUn-joining */ +#define BIDI_JOINING_TYPE_U_VAL ( 0 ) + +/* Right-joining */ +#define BIDI_JOINING_TYPE_R_VAL \ + ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_ARAB_SHAPES ) + +/* Dual-joining */ +#define BIDI_JOINING_TYPE_D_VAL \ + ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT \ + | BIDI_MASK_ARAB_SHAPES ) + +/* join-Causing */ +#define BIDI_JOINING_TYPE_C_VAL \ + ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT ) + +/* Left-joining */ +#define BIDI_JOINING_TYPE_L_VAL \ + ( BIDI_MASK_JOINS_LEFT | BIDI_MASK_ARAB_SHAPES ) + +/* Transparent */ +#define BIDI_JOINING_TYPE_T_VAL \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_ARAB_SHAPES ) + +/* iGnored */ +#define BIDI_JOINING_TYPE_G_VAL ( BIDI_MASK_IGNORED ) + +enum _BidiJoiningTypeEnum { +# define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) \ + BIDI_JOINING_TYPE_##TYPE = BIDI_JOINING_TYPE_##TYPE##_VAL, +# include "unicode-joining-types-list.inc" +# undef _UNIBIDI_ADD_TYPE + _UNIBIDI_JOINING_TYPE_JUNK /* Don't use this */ +}; + +/* + * The equivalent of JoiningType values for ArabicProp + */ + +/* Primary Arabic Joining Classes (Table 8-2) */ + +/* nUn-joining */ +#define BIDI_IS_JOINING_TYPE_U(p) \ + ( 0 == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT ) ) ) + +/* Right-joining */ +#define BIDI_IS_JOINING_TYPE_R(p) \ + ( BIDI_MASK_JOINS_RIGHT == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT ) ) ) + +/* Dual-joining */ +#define BIDI_IS_JOINING_TYPE_D(p) \ + ( ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT \ + | BIDI_MASK_ARAB_SHAPES ) == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT \ + | BIDI_MASK_ARAB_SHAPES ) ) ) + +/* join-Causing */ +#define BIDI_IS_JOINING_TYPE_C(p) \ + ( ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT ) == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT \ + | BIDI_MASK_ARAB_SHAPES ) ) ) + +/* Left-joining */ +#define BIDI_IS_JOINING_TYPE_L(p) \ + ( BIDI_MASK_JOINS_LEFT == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT ) ) ) + +/* Transparent */ +#define BIDI_IS_JOINING_TYPE_T(p) \ + ( BIDI_MASK_TRANSPARENT == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED ) ) ) + +/* iGnored */ +#define BIDI_IS_JOINING_TYPE_G(p) \ + ( BIDI_MASK_IGNORED == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED ) ) ) + +/* and for Derived Arabic Joining Classes (Table 8-3) */ + +/* Right join-Causing */ +#define BIDI_IS_JOINING_TYPE_RC(p) \ + ( BIDI_MASK_JOINS_RIGHT == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_RIGHT ) ) ) + +/* Left join-Causing */ +#define BIDI_IS_JOINING_TYPE_LC(p) \ + ( BIDI_MASK_JOINS_LEFT == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_JOINS_LEFT ) ) ) + +/* + * Defining macros for needed queries, It is fully dependent on the + * implementation of FriBidiJoiningType. + */ + +/* Joins to right: R, D, C? */ +#define BIDI_JOINS_RIGHT(p) ((p) & BIDI_MASK_JOINS_RIGHT) + +/* Joins to left: L, D, C? */ +#define BIDI_JOINS_LEFT(p) ((p) & BIDI_MASK_JOINS_LEFT) + +/* May shape: R, D, L, T? */ +#define BIDI_ARAB_SHAPES(p) ((p) & BIDI_MASK_ARAB_SHAPES) + +/* Is skipped in joining: T, G? */ +#define BIDI_IS_JOIN_SKIPPED(p) \ + ((p) & (BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED)) + +/* Is base that will be shaped: R, D, L? */ +#define BIDI_IS_JOIN_BASE_SHAPES(p) \ + ( BIDI_MASK_ARAB_SHAPES == ( (p) & \ + ( BIDI_MASK_TRANSPARENT | BIDI_MASK_IGNORED \ + | BIDI_MASK_ARAB_SHAPES ) ) ) + +#define BIDI_JOINS_PRECEDING_MASK(level) \ + (BIDI_LEVEL_IS_RTL (level) ? BIDI_MASK_JOINS_RIGHT \ + : BIDI_MASK_JOINS_LEFT) + +#define BIDI_JOINS_FOLLOWING_MASK(level) \ + (BIDI_LEVEL_IS_RTL (level) ? BIDI_MASK_JOINS_LEFT \ + : BIDI_MASK_JOINS_RIGHT) + +#define BIDI_JOIN_SHAPE(p) \ + ((p) & ( BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT )) #ifdef __cplusplus extern "C" { diff --git a/src/font/unicode-joining-types.c b/src/font/unicode-joining-types.c new file mode 100644 index 00000000..d269504a --- /dev/null +++ b/src/font/unicode-joining-types.c @@ -0,0 +1,84 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ + +/* +** unicode-joining-types.c: character joining types +** +** Created by WEI Yongming at 2019/03/11 +** +** This implementation is based on LGPL'd FriBidi: +** +** https://github.com/fribidi/fribidi +*/ + +#include +#include +#include +#include +#include + +#include "common.h" + +#ifdef _MGCHARSET_UNICODE + +#include "minigui.h" +#include "gdi.h" + +#include "unicode-bidi.h" + +enum _BidiJoiningTypeShortEnum { +#define _UNIBIDI_ADD_TYPE(TYPE,SYMBOL) TYPE = BIDI_JOINING_TYPE_##TYPE, +#include "unicode-joining-types-list.inc" +#undef _UNIBIDI_ADD_TYPE + _UNIBIDI_NUM_TYPES +}; + +#include "unicode-joining-type-table.inc" + +BidiJoiningType GUIAPI UCharGetJoiningType(Uchar32 ch) +{ + return UNIBIDI_GET_JOINING_TYPE (ch); +} + +void GUIAPI UStrGetJoiningTypes (const Uchar32 *ucs, + BidiJoiningType *joining_types, int len) +{ + register int i = len; + for (; i; i--) { + *joining_types++ = UNIBIDI_GET_JOINING_TYPE (*ucs); + ucs++; + } +} + +#endif /* _MGCHARSET_UNICODE */ diff --git a/src/font/unicode-joining.c b/src/font/unicode-joining.c new file mode 100644 index 00000000..603efbb0 --- /dev/null +++ b/src/font/unicode-joining.c @@ -0,0 +1,199 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ + +/* +** unicode-joining.c: +** The implementation of Arabic joining algorithm +** +** Created by WEI Yongming at 2019/03/11 +** +** This implementation is based on LGPL'd FriBidi: +** +** https://github.com/fribidi/fribidi +*/ + +#include +#include +#include +#include +#include + +#include "common.h" + +#ifdef _MGCHARSET_UNICODE + +#include "minigui.h" +#include "gdi.h" + +#include "unicode-bidi.h" + +#ifdef DEBUG +/*====================================================================== + * For debugging, define some functions for printing joining types and + * properties. + *----------------------------------------------------------------------*/ + +static char get_char_from_joining_type(BidiJoiningType j, BOOL visual) +{ + /* switch left and right if on visual run */ + if (visual & ((BIDI_JOINS_RIGHT (j) && !BIDI_JOINS_LEFT (j)) | + (!BIDI_JOINS_RIGHT (j) && BIDI_JOINS_LEFT (j)))) + j ^= BIDI_MASK_JOINS_RIGHT | BIDI_MASK_JOINS_LEFT; + +# define _BIDI_ADD_TYPE(TYPE,SYMBOL) \ + if (BIDI_IS_JOINING_TYPE_##TYPE(j)) return SYMBOL; +# include "fribidi-joining-types-list.h" +# undef _BIDI_ADD_TYPE + + return '?'; +} + +static void print_joining_types(const BidiLevel *embedding_levels, + int len, const BidiJoiningType *jtypes) +{ + register int i; + + _DBG_PRINTF (" Join. types: "); + for (i = 0; i < len; i++) + _DBG_PRINTF2 ("%c", get_char_from_joining_type (jtypes[i], + !BIDI_LEVEL_IS_RTL(embedding_levels[i]))); + _DBG_PRINTF ("\n"); +} + +#endif /* DEBUG */ + +#define UNIBIDI_CONSISTENT_LEVEL(i) \ + (BIDI_IS_EXPLICIT_OR_BN (bidi_types[(i)]) \ + ? BIDI_SENTINEL \ + : embedding_levels[(i)]) + +#define BIDI_LEVELS_MATCH(i, j) \ + ((i) == (j) || (i) == BIDI_SENTINEL || (j) == BIDI_SENTINEL) + +void GUIAPI UBidiJoinArabic(const BidiType *bidi_types, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, int len) +{ + if (len == 0) return; + + _DBG_PRINTF ("in fribidi_join_arabic"); + +#ifdef DEBUG + print_joining_types (embedding_levels, len, ar_props); +#endif /* DEBUG */ + + /* The joining algorithm turned out very very dirty :(. That's what happens + * when you follow the standard which has never been implemented closely + * before. + */ + + /* 8.2 Arabic - Cursive Joining */ + _DBG_PRINTF ("Arabic cursive joining"); + { + /* The following do not need to be initialized as long as joins is + * initialized to FALSE. We just do to turn off compiler warnings. */ + register int saved = 0; + register BidiLevel saved_level = BIDI_SENTINEL; + register BOOL saved_shapes = FALSE; + register BidiArabicProp saved_joins_following_mask = 0; + + register BOOL joins = FALSE; + register int i; + + for (i = 0; i < len; i++) + if (!BIDI_IS_JOINING_TYPE_G (ar_props[i])) + { + register BOOL disjoin = FALSE; + register BOOL shapes = BIDI_ARAB_SHAPES (ar_props[i]); + register BidiLevel level = UNIBIDI_CONSISTENT_LEVEL (i); + + if (joins && !BIDI_LEVELS_MATCH (saved_level, level)) + { + disjoin = TRUE; + joins = FALSE; + } + + if (!BIDI_IS_JOIN_SKIPPED (ar_props[i])) + { + register const BidiArabicProp joins_preceding_mask = + BIDI_JOINS_PRECEDING_MASK (level); + + if (!joins) + { + if (shapes) + BIDI_UNSET_BITS (ar_props[i], joins_preceding_mask); + } + else if (!BIDI_TEST_BITS (ar_props[i], joins_preceding_mask)) + { + disjoin = TRUE; + } + else + { + register int j; + /* This is a FriBidi extension: we set joining properties + * for skipped characters in between, so we can put NSMs on tatweel + * later if we want. Useful on console for example. + */ + for (j = saved + 1; j < i; j++) + BIDI_SET_BITS (ar_props[j], joins_preceding_mask | saved_joins_following_mask); + } + } + + if (disjoin && saved_shapes) + BIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask); + + if (!BIDI_IS_JOIN_SKIPPED (ar_props[i])) + { + saved = i; + saved_level = level; + saved_shapes = shapes; + saved_joins_following_mask = + BIDI_JOINS_FOLLOWING_MASK (level); + joins = + BIDI_TEST_BITS (ar_props[i], saved_joins_following_mask); + } + } + if ((joins) && saved_shapes) + BIDI_UNSET_BITS (ar_props[saved], saved_joins_following_mask); + + } + +#ifdef DEBUG + print_joining_types (embedding_levels, len, ar_props); +#endif /* DEBUG */ + + _DBG_PRINTF ("leaving fribidi_join_arabic"); +} + +#endif /* _MGCHARSET_UNICODE */ diff --git a/src/font/unicode-shape-arabic.c b/src/font/unicode-shape-arabic.c new file mode 100644 index 00000000..440e4b67 --- /dev/null +++ b/src/font/unicode-shape-arabic.c @@ -0,0 +1,168 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ + +/* +** unicode-shape-arabic.c: +** The implementation of Arabic joining algorithm +** +** Created by WEI Yongming at 2019/03/11 +** +** This implementation is based on LGPL'd FriBidi: +** +** https://github.com/fribidi/fribidi +*/ + +#include +#include +#include +#include +#include + +#include "common.h" + +#ifdef _MGCHARSET_UNICODE + +#include "minigui.h" +#include "gdi.h" + +#include "unicode-bidi.h" + +typedef struct _PairMap { + Uchar32 pair[2], to; +} PairMap; + +#define UNIBIDI_ACCESS_SHAPE_TABLE(table,min,max,x,shape) (table), (min), (max) +# define UNIBIDI_ACCESS_SHAPE_TABLE_REAL(table,min,max,x,shape) \ + (((x)<(min)||(x)>(max))?(x):(table)[(x)-(min)][(shape)]) + +#include "unicode-arabic-shaping-table.inc" +#include "unicode-arabic-misc-table.inc" + +static void unibidi_shape_arabic_joining (const Uchar32 table[][4], + Uchar32 min, Uchar32 max, + const int len, + const BidiArabicProp *ar_props, + Uchar32 *str) +{ + register int i; + + for (i = 0; i < len; i++) { + if (BIDI_ARAB_SHAPES(ar_props[i])) + str[i] = UNIBIDI_ACCESS_SHAPE_TABLE_REAL(table, min, max, str[i], + BIDI_JOIN_SHAPE (ar_props[i])); + } +} + +static int comp_PairMap (const void *pa, const void *pb) +{ + PairMap *a = (PairMap *)pa; + PairMap *b = (PairMap *)pb; + + if (a->pair[0] != b->pair[0]) + return a->pair[0] < b->pair[0] ? -1 : +1; + else + return a->pair[1] < b->pair[1] ? -1 : + a->pair[1] > b->pair[1] ? +1 : 0; +} + + +static Uchar32 find_pair_match (const PairMap *table, int size, + Uchar32 first, Uchar32 second) +{ + PairMap *match; + PairMap x; + x.pair[0] = first; + x.pair[1] = second; + x.to = 0; + match = bsearch (&x, table, size, sizeof (table[0]), comp_PairMap); + return match ? match->to : 0; +} + +#define PAIR_MATCH(table,len,first,second) \ + ((first)<(table[0].pair[0])||(first)>(table[len-1].pair[0])?0: \ + find_pair_match(table, len, first, second)) + +static void unibidi_shape_arabic_ligature(const PairMap *table, + int size, const BidiLevel *embedding_levels, + int len, + BidiArabicProp *ar_props, Uchar32 *str) +{ + /* TODO: This doesn't form ligatures for even-level Arabic text. + * no big problem though. */ + register int i; + + for (i = 0; i < len - 1; i++) { + register Uchar32 c; + if (BIDI_LEVEL_IS_RTL(embedding_levels[i]) && + embedding_levels[i] == embedding_levels[i+1] && + (c = PAIR_MATCH(table, size, str[i], str[i+1]))) + { + str[i] = BIDI_CHAR_FILL; + BIDI_SET_BITS(ar_props[i], BIDI_MASK_LIGATURED); + str[i+1] = c; + } + } +} + +#define DO_LIGATURING(table, levels, len, ar_props, str) \ + unibidi_shape_arabic_ligature ((table), \ + sizeof(table)/sizeof((table)[0]), levels, len, ar_props, str) + +#define DO_SHAPING(tablemacro, len, ar_props, str) \ + unibidi_shape_arabic_joining (tablemacro(,), len, ar_props, str) + +void UBidiShapeArabic(Uint32 flags, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, + Uchar32 *str, int len) +{ + _DBG_PRINTF ("in UBidiShapeArabic"); + + if (len == 0 || !str) return; + + if (BIDI_TEST_BITS (flags, BIDI_FLAG_SHAPE_ARAB_PRES)) { + DO_SHAPING (UNIBIDI_GET_ARABIC_SHAPE_PRES, len, ar_props, str); + } + + if (BIDI_TEST_BITS (flags, BIDI_FLAG_SHAPE_ARAB_LIGA)) { + DO_LIGATURING (mandatory_liga_table, embedding_levels, len, ar_props, str); + } + + if (BIDI_TEST_BITS (flags, BIDI_FLAG_SHAPE_ARAB_CONSOLE)) { + DO_LIGATURING (console_liga_table, embedding_levels, len, ar_props, str); + DO_SHAPING (UNIBIDI_GET_ARABIC_SHAPE_NSM, len, ar_props, str); + } +} + +#endif /* _MGCHARSET_UNICODE */ diff --git a/src/font/unicode-shape.c b/src/font/unicode-shape.c new file mode 100644 index 00000000..47a89d4c --- /dev/null +++ b/src/font/unicode-shape.c @@ -0,0 +1,97 @@ +/* + * This file is part of MiniGUI, a mature cross-platform windowing + * and Graphics User Interface (GUI) support system for embedded systems + * and smart IoT devices. + * + * Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd. + * Copyright (C) 1998~2002, WEI Yongming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Or, + * + * As this program is a library, any link to this program must follow + * GNU General Public License version 3 (GPLv3). If you cannot accept + * GPLv3, you need to be licensed from FMSoft. + * + * If you have got a commercial license of this program, please use it + * under the terms and conditions of the commercial license. + * + * For more information about the commercial license, please refer to + * . + */ + +/* +** unicode-shape.c: +** The implementation of Arabic joining algorithm +** +** Created by WEI Yongming at 2019/03/11 +** +** This implementation is based on LGPL'd FriBidi: +** +** https://github.com/fribidi/fribidi +*/ + +#include +#include +#include +#include +#include + +#include "common.h" + +#ifdef _MGCHARSET_UNICODE + +#include "minigui.h" +#include "gdi.h" + +#include "unicode-bidi.h" + +void GUIAPI UBidiShapeMirroring(const BidiLevel *embedding_levels, + Uchar32* str, int len) +{ + register int i; + + _DBG_PRINTF("in fribidi_shape_mirroring"); + + if (len == 0 || !str) return; + + /* L4. Mirror all characters that are in odd levels and have mirrors. */ + for (i = len - 1; i >= 0; i--) { + if (BIDI_LEVEL_IS_RTL(embedding_levels[i])) { + Uchar32 mirrored_ch; + + if (UCharGetMirror(str[i], &mirrored_ch)) + str[i] = mirrored_ch; + } + } +} + +void GUIAPI UBidiShape(Uint32 flags, + const BidiLevel *embedding_levels, + BidiArabicProp *ar_props, Uchar32 *str, int len) +{ + if (len == 0 || !str) + return; + + _DBG_PRINTF ("in fribidi_shape"); + + if (ar_props) + UBidiShapeArabic(flags, embedding_levels, ar_props, str, len); + + if (BIDI_TEST_BITS (flags, BIDI_FLAG_SHAPE_MIRRORING)) + UBidiShapeMirroring (embedding_levels, str, len); +} + +#endif /* _MGCHARSET_UNICODE */