mirror of
https://github.com/VincentWei/MiniGUI.git
synced 2026-09-25 11:07:54 +08:00
Split GetUCharsAndBreaks into two APIs: GetUCharsUntilParagraphBoundary and UStrGetBreaks
This commit is contained in:
+93
-55
@@ -8490,6 +8490,78 @@ MG_EXPORT void GUIAPI UBidiShape(Uint32 shaping_flags,
|
||||
const BidiLevel *embedding_levels, int len,
|
||||
BidiArabicProp *ar_props, Uchar32* ucs);
|
||||
|
||||
/**
|
||||
* \fn int GUIAPI UStrGetBreaks(Uchar32* ucs, int nr_ucs,
|
||||
* UCharScriptType writing_system, Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
* Uint16** break_oppos);
|
||||
* \brief Convert a multi-byte character string to a Unicode character string
|
||||
* and calculate the breaking opportunities under the specified rules and
|
||||
* line breaking policy.
|
||||
*
|
||||
* This function calculates and allocates the Uchar32 string and the breaking
|
||||
* opportunities of the characters from a multi-byte string under the specified
|
||||
* content language \a content_language, the writing system \a writing_system,
|
||||
* the white space rule \a wsr, the text transformation rule
|
||||
* \a ctr, the word breaking rule \a wbr, and the line breaking policy \a lbp.
|
||||
*
|
||||
* The implementation of this function conforms to UNICODE LINE BREAKING
|
||||
* ALGORITHM:
|
||||
*
|
||||
* https://www.unicode.org/reports/tr14/tr14-39.html
|
||||
*
|
||||
* and UNICODE TEXT SEGMENTATION:
|
||||
*
|
||||
* https://www.unicode.org/reports/tr29/tr29-33.html
|
||||
*
|
||||
* and the CSS Text Module Level 3:
|
||||
*
|
||||
* https://www.w3.org/TR/css-text-3/
|
||||
*
|
||||
* The function will return if it encounters any hard line break or the null
|
||||
* character. The hard line break will be included in the returned Uchar32 if
|
||||
* there was one.
|
||||
*
|
||||
* Note that you are responsible for freeing the Uchar32 string and the
|
||||
* break opportunities array allocated by this function.
|
||||
*
|
||||
* \param logfont The logfont used to parse the string.
|
||||
* \param mstr The pointer to the multi-byte string.
|
||||
* \param mstr_len The length of \a mstr in bytes.
|
||||
* \param content_language The content lanuage identifier.
|
||||
* \param writing_system The writing system (script) identifier.
|
||||
* \param wsr The white space rule; see \a white_space_rules.
|
||||
* \param ctr The character transformation rule;
|
||||
* see \a char_transform_rule.
|
||||
* \param wbr The word breaking rule; see \a word_break_rules.
|
||||
* \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.
|
||||
* \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
|
||||
* the glyphs array. The first unit of the array stores the
|
||||
* break opportunity before the first glyph, and the others store
|
||||
* the break opportunities after other gyphs.
|
||||
* The break opportunity can be one of the following values:
|
||||
* - BOV_LB_MANDATORY\n
|
||||
* The mandatory breaking.
|
||||
* - BOV_LB_NOTALLOWED\n
|
||||
* No breaking allowed after the glyph definitely.
|
||||
* - BOV_LB_ALLOWED\n
|
||||
* Breaking allowed after the glyph.
|
||||
* \param nr_glyphs The buffer to store the number of the allocated glyphs.
|
||||
*
|
||||
* \return The number of the bytes consumed in \a mstr; zero on error.
|
||||
*
|
||||
* \note Only available when support for UNICODE is enabled.
|
||||
*
|
||||
* \sa DrawGlyphStringEx, white_space_rules, char_transform_rule
|
||||
*/
|
||||
MG_EXPORT int GUIAPI UStrGetBreaks(Uchar32* ucs, int nr_ucs,
|
||||
UCharScriptType writing_system, Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
Uint16** break_oppos);
|
||||
|
||||
/** The function determines whether a character is alphanumeric. */
|
||||
MG_EXPORT BOOL GUIAPI IsUCharAlnum(Uchar32 uc);
|
||||
|
||||
@@ -11812,70 +11884,38 @@ static inline int GUIAPI LanguageCodeFromISO639s1Code (const char* iso639_1)
|
||||
*/
|
||||
#define BOV_LB_NOTALLOWED 0x0003
|
||||
|
||||
/** @} end of breaking_opportunities */
|
||||
|
||||
/**
|
||||
* \fn int GUIAPI GetUCharsAndBreaks(LOGFONT* logfont,
|
||||
* const char* mstr, unsigned int mstr_len,
|
||||
* LanguageCode content_language, UCharScriptType writing_system,
|
||||
* Uint8 wsr, Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
* Uchar32** uchars, Uint16** break_oppos,
|
||||
* int* nr_uchars);
|
||||
* \brief Convert a multi-byte character string to a Unicode character string
|
||||
* and calculate the breaking opportunities under the specified rules and
|
||||
* line breaking policy.
|
||||
* \fn int GUIAPI GetUCharsUntilParagraphBoundary(LOGFONT* logfont,
|
||||
* const char* mstr, int mstr_len, Uint8 wsr,
|
||||
* Uchar32** uchars, int* nr_uchars);
|
||||
* \brief Convert a multi-byte character string to a Unicode character
|
||||
* (Uchar32) string until the end of text (null character) or an
|
||||
* explicit paragraph boundary encountered.
|
||||
*
|
||||
* This function calculates and allocates the Uchar32 string and the breaking
|
||||
* opportunities of the characters from a multi-byte string under the specified
|
||||
* content language \a content_language, the writing system \a writing_system,
|
||||
* the white space rule \a wsr, the text transformation rule
|
||||
* \a ctr, the word breaking rule \a wbr, and the line breaking policy \a lbp.
|
||||
* This function calculates and allocates the Uchar32 string from a multi-byte
|
||||
* string until it encounters the end of text (null character) or an explicit
|
||||
* paragraph boundary. It also processes the text according to the specified
|
||||
* white space rule \a wsr and the text transformation rule \a ctr.
|
||||
*
|
||||
* The implementation of this function conforms to UNICODE LINE BREAKING
|
||||
* ALGORITHM:
|
||||
*
|
||||
* https://www.unicode.org/reports/tr14/tr14-39.html
|
||||
*
|
||||
* and UNICODE TEXT SEGMENTATION:
|
||||
*
|
||||
* https://www.unicode.org/reports/tr29/tr29-33.html
|
||||
*
|
||||
* and the CSS Text Module Level 3:
|
||||
* The implementation of this function conforms to the CSS Text Module Level 3:
|
||||
*
|
||||
* https://www.w3.org/TR/css-text-3/
|
||||
*
|
||||
* The function will return if it encounters any hard line break or the null
|
||||
* character. The hard line break will be included in the returned Uchar32 if
|
||||
* there was one.
|
||||
*
|
||||
* Note that you are responsible for freeing the Uchar32 string and the
|
||||
* break opportunities array allocated by this function.
|
||||
* Note that you are responsible for freeing the Uchar32 string allocated
|
||||
* by this function.
|
||||
*
|
||||
* \param logfont The logfont used to parse the string.
|
||||
* \param mstr The pointer to the multi-byte string.
|
||||
* \param mstr_len The length of \a mstr in bytes.
|
||||
* \param content_language The content lanuage identifier.
|
||||
* \param writing_system The writing system (script) identifier.
|
||||
* \param wsr The white space rule; see \a white_space_rules.
|
||||
* \param ctr The character transformation rule;
|
||||
* see \a char_transform_rule.
|
||||
* \param wbr The word breaking rule; see \a word_break_rules.
|
||||
* \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.
|
||||
* \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
|
||||
* the glyphs array. The first unit of the array stores the
|
||||
* break opportunity before the first glyph, and the others store
|
||||
* the break opportunities after other gyphs.
|
||||
* The break opportunity can be one of the following values:
|
||||
* - BOV_LB_MANDATORY\n
|
||||
* The mandatory breaking.
|
||||
* - BOV_LB_NOTALLOWED\n
|
||||
* No breaking allowed after the glyph definitely.
|
||||
* - BOV_LB_ALLOWED\n
|
||||
* Breaking allowed after the glyph.
|
||||
* \param nr_glyphs The buffer to store the number of the allocated glyphs.
|
||||
* \param nr_uchars The buffer to store the number of the allocated
|
||||
* Uchar32 array.
|
||||
*
|
||||
* \return The number of the bytes consumed in \a mstr; zero on error.
|
||||
*
|
||||
@@ -11883,11 +11923,9 @@ static inline int GUIAPI LanguageCodeFromISO639s1Code (const char* iso639_1)
|
||||
*
|
||||
* \sa DrawGlyphStringEx, white_space_rules, char_transform_rule
|
||||
*/
|
||||
MG_EXPORT int GUIAPI GetUCharsAndBreaks(LOGFONT* logfont,
|
||||
const char* mstr, int mstr_len,
|
||||
LanguageCode content_language, UCharScriptType writing_system,
|
||||
Uint8 wsr, Uint8 ctr, Uint8 wbr, Uint8 lbp,
|
||||
Uchar32** uchars, Uint16** break_oppos, int* nr_ucs);
|
||||
MG_EXPORT int GUIAPI GetUCharsUntilParagraphBoundary(LOGFONT* logfont,
|
||||
const char* mstr, int mstr_len, Uint8 wsr,
|
||||
Uchar32** uchars, int* nr_uchars);
|
||||
|
||||
/**
|
||||
* \fn AChar2UChar(LOGFONT* logfont, Achar32 chv)
|
||||
@@ -12208,7 +12246,7 @@ typedef struct _SHAPEDGLYPH {
|
||||
* \a content_language, and the writing system \a writing_system.
|
||||
*
|
||||
* This function also performs the basic shaping process according to the
|
||||
* Unicode character properties if the content language is Arabic.
|
||||
* Unicode character properties if the content language is Arabic.
|
||||
* The shaping process includes:
|
||||
*
|
||||
* - Shaping (substituting) glyphs.
|
||||
|
||||
@@ -14,6 +14,7 @@ SRC_FILES = charset.c charset-arabic.c legacy-bidi.c charset-unicode.c \
|
||||
bitmapfont.c scripteasy.c \
|
||||
unicode-emoji.c \
|
||||
unicode-bidi.c \
|
||||
unicode-break.c \
|
||||
unicode-joining-types.c unicode-joining.c unicode-shape.c \
|
||||
unicode-shape-arabic.c
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,10 +43,33 @@
|
||||
#ifndef GUI_UNICODE_OPS_H
|
||||
#define GUI_UNICODE_OPS_H
|
||||
|
||||
#define UCHAR_SPACE 0x0020
|
||||
#define UCHAR_SHY 0x00AD
|
||||
#define UCHAR_IDSPACE 0x3000
|
||||
#define UCHAR_TAB 0x0009
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
static inline BOOL is_uchar_letter(Uchar32 uc,
|
||||
UCharGeneralCategory gc, UCharBreakType bt)
|
||||
{
|
||||
if ((gc >= UCHAR_CATEGORY_LOWERCASE_LETTER
|
||||
&& gc <= UCHAR_CATEGORY_UPPERCASE_LETTER)
|
||||
|| (gc >= UCHAR_CATEGORY_DECIMAL_NUMBER
|
||||
&& gc <= UCHAR_CATEGORY_OTHER_NUMBER))
|
||||
return TRUE;
|
||||
|
||||
if (bt == UCHAR_BREAK_NUMERIC
|
||||
|| bt == UCHAR_BREAK_ALPHABETIC
|
||||
|| bt == UCHAR_BREAK_IDEOGRAPHIC
|
||||
|| bt == UCHAR_BREAK_AMBIGUOUS)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL _unicode_is_emoji(Uchar32 ch);
|
||||
BOOL _unicode_is_emoji_presentation(Uchar32 ch);
|
||||
BOOL _unicode_is_emoji_modifier(Uchar32 ch);
|
||||
|
||||
@@ -13,7 +13,7 @@ SRC_FILES = gdi.c attr.c clip.c map.c coor.c rect.c \
|
||||
region.c generators.c polygon.c flood.c \
|
||||
advapi.c midash.c mispans.c miwideline.c \
|
||||
mifillarc.c mifpolycon.c miarc.c rotatebmp.c \
|
||||
text.c achar.c glyph.c legacy-bidi.c \
|
||||
text.c achar-uchar.c glyph.c legacy-bidi.c \
|
||||
textout.c tabbedtextout.c drawtext.c \
|
||||
glyph-unicode.c shaped-glyph.c
|
||||
endif
|
||||
|
||||
@@ -31,8 +31,10 @@
|
||||
* For more information about the commercial license, please refer to
|
||||
* <http://www.minigui.com/en/about/licensing-policy/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
** achar.c: API implementation for abstract character.
|
||||
** achar-uchar.c: API implementation for conversion between
|
||||
** abstract characters and Unicode characters.
|
||||
**
|
||||
** Create date: 2019/03/05
|
||||
*/
|
||||
@@ -184,6 +186,8 @@ Uint16 GUIAPI GetACharBidiType (LOGFONT* log_font, Achar32 chv)
|
||||
|
||||
#ifdef _MGCHARSET_UNICODE
|
||||
|
||||
#include "unicode-ops.h"
|
||||
|
||||
Uchar32 GUIAPI Achar2UChar(LOGFONT* logfont, Achar32 chv)
|
||||
{
|
||||
Uchar32 uc;
|
||||
@@ -331,4 +335,248 @@ int GUIAPI UChars2AChars(LOGFONT* logfont, const Uchar32* ucs,
|
||||
return i;
|
||||
}
|
||||
|
||||
#define MIN_LEN_UCHARS 4
|
||||
#define INC_LEN_UCHARS 8
|
||||
|
||||
struct ustr_ctxt {
|
||||
Uchar32* ucs;
|
||||
int len_buff;
|
||||
int n;
|
||||
Uint8 wsr;
|
||||
};
|
||||
|
||||
static int usctxt_init_spaces(struct ustr_ctxt* ctxt, int size)
|
||||
{
|
||||
// pre-allocate buffers
|
||||
ctxt->len_buff = size;
|
||||
if (ctxt->len_buff < MIN_LEN_UCHARS)
|
||||
ctxt->len_buff = MIN_LEN_UCHARS;
|
||||
|
||||
ctxt->ucs = (Uchar32*)malloc(sizeof(Uchar32) * ctxt->len_buff);
|
||||
if (ctxt->ucs == NULL)
|
||||
return 0;
|
||||
|
||||
ctxt->n = 0;
|
||||
return ctxt->len_buff;
|
||||
}
|
||||
|
||||
static int usctxt_push_back(struct ustr_ctxt* ctxt, Uchar32 uc)
|
||||
{
|
||||
/* realloc buffers if it needs */
|
||||
if ((ctxt->n + 2) >= ctxt->len_buff) {
|
||||
ctxt->len_buff += INC_LEN_UCHARS;
|
||||
ctxt->ucs = (Uchar32*)realloc(ctxt->ucs,
|
||||
sizeof(Uchar32) * ctxt->len_buff);
|
||||
|
||||
if (ctxt->ucs == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctxt->ucs[ctxt->n] = uc;
|
||||
ctxt->n++;
|
||||
return ctxt->n;
|
||||
}
|
||||
|
||||
static int get_next_uchar(LOGFONT* lf, const char* mstr, int mstr_len,
|
||||
Uchar32* uc)
|
||||
{
|
||||
int mclen = 0;
|
||||
|
||||
if (mstr_len <= 0 || *mstr == '\0')
|
||||
return 0;
|
||||
|
||||
if (lf->devfonts[1]) {
|
||||
mclen = lf->devfonts[1]->charset_ops->len_first_char
|
||||
((const unsigned char*)mstr, mstr_len);
|
||||
|
||||
if (mclen > 0) {
|
||||
Achar32 chv = lf->devfonts[1]->charset_ops->get_char_value
|
||||
(NULL, 0, (Uint8*)mstr, mclen);
|
||||
|
||||
if (lf->devfonts[1]->charset_ops->conv_to_uc32)
|
||||
*uc = lf->devfonts[1]->charset_ops->conv_to_uc32(chv);
|
||||
else
|
||||
*uc = chv;
|
||||
|
||||
chv = SET_MBCHV(chv);
|
||||
}
|
||||
}
|
||||
|
||||
if (mclen == 0) {
|
||||
mclen = lf->devfonts[0]->charset_ops->len_first_char
|
||||
((const unsigned char*)mstr, mstr_len);
|
||||
|
||||
if (mclen > 0) {
|
||||
Achar32 chv = lf->devfonts[0]->charset_ops->get_char_value
|
||||
(NULL, 0, (Uint8*)mstr, mclen);
|
||||
|
||||
if (lf->devfonts[0]->charset_ops->conv_to_uc32)
|
||||
*uc = lf->devfonts[0]->charset_ops->conv_to_uc32(chv);
|
||||
else
|
||||
*uc = chv;
|
||||
}
|
||||
}
|
||||
|
||||
return mclen;
|
||||
}
|
||||
|
||||
static int is_next_mchar_bt(LOGFONT* lf,
|
||||
const char* mstr, int mstr_len, Uchar32* uc,
|
||||
UCharBreakType bt)
|
||||
{
|
||||
int mclen;
|
||||
|
||||
mclen = get_next_uchar(lf, mstr, mstr_len, uc);
|
||||
if (mclen > 0 && UCharGetBreakType(*uc) == bt)
|
||||
return mclen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int is_next_mchar_lf(LOGFONT* lf,
|
||||
const char* mstr, int mstr_len, Uchar32* uc)
|
||||
{
|
||||
return is_next_mchar_bt(lf, mstr, mstr_len, uc,
|
||||
UCHAR_BREAK_LINE_FEED);
|
||||
}
|
||||
|
||||
static int collapse_space(LOGFONT* lf, const char* mstr, int mstr_len)
|
||||
{
|
||||
Uchar32 uc;
|
||||
UCharBreakType bt;
|
||||
int cosumed = 0;
|
||||
|
||||
do {
|
||||
int mclen;
|
||||
|
||||
mclen = get_next_uchar(lf, mstr, mstr_len, &uc);
|
||||
if (mclen == 0)
|
||||
break;
|
||||
|
||||
bt = UCharGetBreakType(uc);
|
||||
if (bt != UCHAR_BREAK_SPACE && uc != UCHAR_TAB)
|
||||
break;
|
||||
|
||||
mstr += mclen;
|
||||
mstr_len -= mclen;
|
||||
cosumed += mclen;
|
||||
} while (1);
|
||||
|
||||
return cosumed;
|
||||
}
|
||||
|
||||
/*
|
||||
Reference:
|
||||
[CSS Text Module Level 3](https://www.w3.org/TR/css-text-3/)
|
||||
*/
|
||||
int GUIAPI GetUCharsUntilParagraphBoundary(LOGFONT* logfont,
|
||||
const char* mstr, int mstr_len, Uint8 wsr,
|
||||
Uchar32** uchars, int* nr_uchars)
|
||||
{
|
||||
struct ustr_ctxt ctxt;
|
||||
int cosumed = 0;
|
||||
BOOL col_sp = FALSE;
|
||||
BOOL col_nl = FALSE;
|
||||
|
||||
// CSS: collapses space according to space rule
|
||||
if (wsr == WSR_NORMAL || wsr == WSR_NOWRAP || wsr == WSR_PRE_LINE)
|
||||
col_sp = TRUE;
|
||||
// CSS: collapses new lines acoording to space rule
|
||||
if (wsr == WSR_NORMAL || wsr == WSR_NOWRAP)
|
||||
col_nl = TRUE;
|
||||
|
||||
*uchars = NULL;
|
||||
*nr_uchars = 0;
|
||||
|
||||
if (mstr_len == 0)
|
||||
return 0;
|
||||
|
||||
ctxt.wsr = wsr;
|
||||
if (usctxt_init_spaces(&ctxt, mstr_len >> 1) <= 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
Uchar32 uc, next_uc;
|
||||
UCharBreakType bt;
|
||||
|
||||
int mclen = 0;
|
||||
int next_mclen;
|
||||
int cosumed_one_loop = 0;
|
||||
|
||||
mclen = get_next_uchar(logfont, mstr, mstr_len, &uc);
|
||||
if (mclen == 0) {
|
||||
// badly encoded or end of text
|
||||
break;
|
||||
}
|
||||
|
||||
mstr += mclen;
|
||||
mstr_len -= mclen;
|
||||
cosumed += mclen;
|
||||
|
||||
if ((wsr == WSR_NORMAL || wsr == WSR_NOWRAP
|
||||
|| wsr == WSR_PRE_LINE) && uc == UCHAR_TAB) {
|
||||
_DBG_PRINTF ("CSS: Every tab is converted to a space (U+0020)\n");
|
||||
uc = UCHAR_SPACE;
|
||||
}
|
||||
|
||||
bt = UCharGetBreakType(uc);
|
||||
if (usctxt_push_back(&ctxt, uc) == 0)
|
||||
goto error;
|
||||
|
||||
/* Check mandatory breaks */
|
||||
if (bt == UCHAR_BREAK_MANDATORY) {
|
||||
break;
|
||||
}
|
||||
else if (bt == UCHAR_BREAK_CARRIAGE_RETURN
|
||||
&& (next_mclen = is_next_mchar_lf(logfont,
|
||||
mstr, mstr_len, &next_uc)) > 0) {
|
||||
cosumed_one_loop += next_mclen;
|
||||
|
||||
if (col_nl) {
|
||||
ctxt.n--;
|
||||
}
|
||||
else {
|
||||
if (usctxt_push_back(&ctxt, next_uc) == 0)
|
||||
goto error;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (bt == UCHAR_BREAK_CARRIAGE_RETURN
|
||||
|| bt == UCHAR_BREAK_LINE_FEED
|
||||
|| bt == UCHAR_BREAK_NEXT_LINE) {
|
||||
|
||||
if (col_nl) {
|
||||
ctxt.n--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* collapse spaces */
|
||||
else if (col_sp && (bt == UCHAR_BREAK_SPACE
|
||||
|| bt == UCHAR_BREAK_ZERO_WIDTH_SPACE)) {
|
||||
cosumed_one_loop += collapse_space(logfont, mstr, mstr_len);
|
||||
}
|
||||
|
||||
mstr_len -= cosumed_one_loop;
|
||||
mstr += cosumed_one_loop;
|
||||
cosumed += cosumed_one_loop;
|
||||
}
|
||||
|
||||
if (ctxt.n > 0) {
|
||||
*uchars = ctxt.ucs;
|
||||
*nr_uchars = ctxt.n;
|
||||
}
|
||||
else
|
||||
goto error;
|
||||
|
||||
return cosumed;
|
||||
|
||||
error:
|
||||
if (ctxt.ucs) free(ctxt.ucs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* _MGCHARSET_UNICODE */
|
||||
|
||||
+1
-3104
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user