diff --git a/include/gdi.h b/include/gdi.h index df5e97e3..53de3153 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -10357,13 +10357,15 @@ static inline int GUIAPI LanguageCodeFromISO639s1Code (const char* iso639_1) #define BOV_BEFORE_MASK 0xF0 #define BOV_AFTER_MASK 0x0F -#define BOV_BEFORE_NOTALLOWED 0x00 -#define BOV_BEFORE_MANDATORY 0x10 -#define BOV_BEFORE_ALLOWED 0x20 +#define BOV_BEFORE_UNKNOWN 0x00 +#define BOV_BEFORE_NOTALLOWED 0x80 +#define BOV_BEFORE_ALLOWED 0x90 +#define BOV_BEFORE_MANDATORY 0xB0 -#define BOV_AFTER_NOTALLOWED 0x00 -#define BOV_AFTER_MANDATORY 0x10 -#define BOV_AFTER_ALLOWED 0x20 +#define BOV_AFTER_UNKNOWN 0x00 +#define BOV_AFTER_NOTALLOWED 0x08 +#define BOV_AFTER_ALLOWED 0x09 +#define BOV_AFTER_MANDATORY 0x0B /** * \fn int GUIAPI GetGlyphsByRules(LOGFONT* logfont, diff --git a/src/newgdi/glyph-css.c b/src/newgdi/glyph-css.c index ec07358d..f05497d6 100644 --- a/src/newgdi/glyph-css.c +++ b/src/newgdi/glyph-css.c @@ -66,7 +66,79 @@ #ifdef _MGCHARSET_UNICODE -static int get_next_glyph(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +#define MIN_LEN_GLYPHS 4 +#define INC_LEN_GLYPHS 4 + +struct glyph_break_info { + DEVFONT* mbc_devfont; + DEVFONT* sbc_devfont; + int len_buff; + int n; + Glyph32* gs; + Uint8* bs; +}; + +static int gbinfo_init(struct glyph_break_info* gbinfo, int size) +{ + // pre-allocate buffers + gbinfo->len_buff = size; + if (gbinfo->len_buff < MIN_LEN_GLYPHS) + gbinfo->len_buff = MIN_LEN_GLYPHS; + + gbinfo->gs = (Glyph32*)malloc(sizeof(Glyph32) * gbinfo->len_buff); + gbinfo->bs = (Uint8*)malloc(sizeof(Uint8) * gbinfo->len_buff); + if (gbinfo->gs == NULL || gbinfo->bs == NULL) + return 0; + + return gbinfo->len_buff; +} + +static int gbinfo_push_back(struct glyph_break_info* gbinfo, + Glyph32 gv, Uint8 bt) +{ + /* realloc buffers if it needs */ + if ((gbinfo->n + 2) >= gbinfo->len_buff) { + gbinfo->len_buff += INC_LEN_GLYPHS; + gbinfo->gs = (Glyph32*)realloc(gbinfo->gs, + sizeof(Glyph32) * gbinfo->len_buff); + gbinfo->bs = (Uint8*)realloc(gbinfo->bs, + sizeof(Uint8) * gbinfo->len_buff); + if (gbinfo->gs == NULL || gbinfo->bs == NULL) + return 0; + } + + gbinfo->gs[gbinfo->n] = gv; + gbinfo->bs[gbinfo->n] = bt; + gbinfo->n++; + return gbinfo->n; +} + +static BOOL gbinfo_change_bt(struct glyph_break_info* gbinfo, int i, Uint8 bt) +{ + Uint8 bb, ba; + + if (i >= gbinfo->n) + return FALSE; + else if (i < 0) + i = gbinfo->n + i; + + if (i < 0) + return FALSE; + + bb = bt & BOV_BEFORE_MASK; + if (bb) { + gbinfo->bs[i] = (gbinfo->bs[i] & ~BOV_BEFORE_MASK) | bb; + } + + ba = bt & BOV_AFTER_MASK; + if (ba) { + gbinfo->bs[i] = (gbinfo->bs[i] & ~BOV_AFTER_MASK) | ba; + } + + return TRUE; +} + +static int get_next_glyph(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) { int mclen = 0; @@ -74,31 +146,31 @@ static int get_next_glyph(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, if (mstr_len <= 0) return 0; - if (mbc_devfont) { - mclen = mbc_devfont->charset_ops->len_first_char + if (gbinfo->mbc_devfont) { + mclen = gbinfo->mbc_devfont->charset_ops->len_first_char ((const unsigned char*)mstr, mstr_len); if (mclen > 0) { - *gv = mbc_devfont->charset_ops->char_glyph_value + *gv = gbinfo->mbc_devfont->charset_ops->char_glyph_value (NULL, 0, (Uint8*)mstr, mclen); *gv = SET_MBC_GLYPH(*gv); - if (mbc_devfont->charset_ops->conv_to_uc32) - *uc = mbc_devfont->charset_ops->conv_to_uc32(*gv); + if (gbinfo->mbc_devfont->charset_ops->conv_to_uc32) + *uc = gbinfo->mbc_devfont->charset_ops->conv_to_uc32(*gv); else *uc = GLYPH2UCHAR(*gv); } } if (*gv == INV_GLYPH_VALUE) { - mclen = sbc_devfont->charset_ops->len_first_char + mclen = gbinfo->sbc_devfont->charset_ops->len_first_char ((const unsigned char*)mstr, mstr_len); if (mclen > 0) { - *gv = sbc_devfont->charset_ops->char_glyph_value + *gv = gbinfo->sbc_devfont->charset_ops->char_glyph_value (NULL, 0, (Uint8*)mstr, mclen); - if (sbc_devfont->charset_ops->conv_to_uc32) - *uc = sbc_devfont->charset_ops->conv_to_uc32(*gv); + if (gbinfo->sbc_devfont->charset_ops->conv_to_uc32) + *uc = gbinfo->sbc_devfont->charset_ops->conv_to_uc32(*gv); else *uc = GLYPH2UCHAR(*gv); } @@ -145,7 +217,7 @@ static UCharBreakType resolve_line_breaking_class( return bt; } -static int collapse_space(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int collapse_space(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len) { UCharBreakType bt; @@ -156,7 +228,7 @@ static int collapse_space(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, Glyph32 gv; Uchar32 uc; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); if (mclen == 0) break; @@ -171,7 +243,7 @@ static int collapse_space(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return cosumed; } -static int collapse_line_feed(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int collapse_line_feed(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len) { int cosumed = 0; @@ -179,7 +251,7 @@ static int collapse_line_feed(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, Glyph32 gv; Uchar32 uc; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); if (mclen > 0 && UCharGetBreak(uc) == UCHAR_BREAK_LINE_FEED) cosumed = mclen; @@ -187,14 +259,14 @@ static int collapse_line_feed(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return cosumed; } -static BOOL is_next_glyph_zw(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static BOOL is_next_glyph_zw(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len) { int mclen; Glyph32 gv; Uchar32 uc; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); if (mclen > 0 && UCharGetBreak(uc) == UCHAR_BREAK_ZERO_WIDTH_SPACE) return TRUE; @@ -202,26 +274,96 @@ static BOOL is_next_glyph_zw(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return FALSE; } -static int is_next_glyph_sp(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) +static int is_next_glyph_bt(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc, + UCharBreakType bt) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_SPACE) + if (mclen > 0 && UCharGetBreak(*uc) == bt) return mclen; return 0; } -static int is_next_glyph_cm_zwj(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static inline int is_next_glyph_sp(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_SPACE); +} + +static inline int is_next_glyph_gl(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_NON_BREAKING_GLUE); +} + +static inline int is_next_glyph_hl(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_HEBREW_LETTER); +} + +static inline int is_next_glyph_in(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_INSEPARABLE); +} + +static inline int is_next_glyph_nu(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_NUMERIC); +} + +static inline int is_next_glyph_po(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_POSTFIX); +} + +static inline int is_next_glyph_pr(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_PREFIX); +} + +static inline int is_next_glyph_op(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_OPEN_PUNCTUATION); +} + +static inline int is_next_glyph_jt(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_HANGUL_T_JAMO); +} + +static int is_next_glyph_em(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) +{ + return is_next_glyph_bt(gbinfo, mstr, mstr_len, gv, uc, + UCHAR_BREAK_EMOJI_MODIFIER); +} + +static int is_next_glyph_cm_zwj(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); if (bt == UCHAR_BREAK_COMBINING_MARK @@ -232,28 +374,12 @@ static int is_next_glyph_cm_zwj(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_gl(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32* gv, Uchar32* uc) -{ - int mclen; - - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0) { - UCharBreakType bt = UCharGetBreak(*uc); - if (bt == UCHAR_BREAK_NON_BREAKING_GLUE) - return mclen; - } - - return 0; -} - -static int is_next_glyph_hy_or_ba(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_hy_or_ba(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -265,50 +391,11 @@ static int is_next_glyph_hy_or_ba(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_hl(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_al_hl(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_HEBREW_LETTER) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_in(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_INSEPARABLE) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_nu(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_NUMERIC) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_al_hl(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -319,11 +406,11 @@ static int is_next_glyph_al_hl(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_pr_po(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_pr_po(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -334,11 +421,11 @@ static int is_next_glyph_pr_po(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_id_eb_em(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_id_eb_em(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -351,50 +438,11 @@ static int is_next_glyph_id_eb_em(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_po(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_jl_jv_jt_h2_h3(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_POSTFIX) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_pr(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_PREFIX) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_op(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - gv, uc); - if (mclen > 0 && UCharGetBreak(*uc) == UCHAR_BREAK_OPEN_PUNCTUATION) { - return mclen; - } - - return 0; -} - -static int is_next_glyph_jl_jv_jt_h2_h3(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) -{ - int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -409,11 +457,11 @@ static int is_next_glyph_jl_jv_jt_h2_h3(DEVFONT* mbc_devfont, DEVFONT* sbc_devfo return 0; } -static int is_next_glyph_jl_jv_h2_h3(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_jl_jv_h2_h3(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -427,11 +475,11 @@ static int is_next_glyph_jl_jv_h2_h3(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_jv_jt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_jv_jt(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); @@ -443,72 +491,32 @@ static int is_next_glyph_jv_jt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return 0; } -static int is_next_glyph_jt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_next_glyph_al_hl_nu(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, Glyph32*gv, Uchar32 *uc) { int mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, gv, uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(*uc); - if (bt == UCHAR_BREAK_HANGUL_T_JAMO) + if (bt == UCHAR_BREAK_HEBREW_LETTER + || bt == UCHAR_BREAK_ALPHABETIC + || bt == UCHAR_BREAK_NUMERIC) return mclen; } return 0; } -#define MIN_LEN_GLYPHS 4 -#define INC_LEN_GLYPHS 4 - -struct glyph_break_info { - int len_buff; - int n; - Glyph32* gs; - Uint8* bs; -}; - -static int gbinfo_init(struct glyph_break_info* gbinfo, int size) -{ - // pre-allocate buffers - gbinfo->len_buff = size; - if (gbinfo->len_buff < MIN_LEN_GLYPHS) - gbinfo->len_buff = MIN_LEN_GLYPHS; - - gbinfo->gs = (Glyph32*)malloc(sizeof(Glyph32) * gbinfo->len_buff); - gbinfo->bs = (Uint8*)malloc(sizeof(Uint8) * gbinfo->len_buff); - if (gbinfo->gs == NULL || gbinfo->bs == NULL) - return 0; - - return gbinfo->len_buff; -} - -static int gbinfo_push_back(struct glyph_break_info* gbinfo, Glyph32 gv, Uint8 bt) -{ - /* realloc buffers if it needs */ - if ((gbinfo->n + 2) >= gbinfo->len_buff) { - gbinfo->len_buff += INC_LEN_GLYPHS; - gbinfo->gs = (Glyph32*)realloc(gbinfo->gs, sizeof(Glyph32) * gbinfo->len_buff); - gbinfo->bs = (Uint8*)realloc(gbinfo->bs, sizeof(Uint8) * gbinfo->len_buff); - if (gbinfo->gs == NULL || gbinfo->bs == NULL) - return 0; - } - - gbinfo->gs[gbinfo->n] = gv; - gbinfo->bs[gbinfo->n] = bt; - gbinfo->n++; - return gbinfo->n; -} - -static int check_subsequent_cm_or_zwj(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, struct glyph_break_info* gbinfo) +static int check_subsequent_cm_or_zwj(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len) { int cosumed = 0; int mclen; Glyph32 gv; Uchar32 uc; - while ((mclen = is_next_glyph_cm_zwj(mbc_devfont, sbc_devfont, + while ((mclen = is_next_glyph_cm_zwj(gbinfo, mstr, mstr_len, &gv, &uc)) > 0) { // FIXME: CM/ZWJ should have the same break class as @@ -521,15 +529,15 @@ static int check_subsequent_cm_or_zwj(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont return cosumed; } -static int check_subsequent_sp(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, struct glyph_break_info* gbinfo) +static int check_subsequent_sp(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len) { int cosumed = 0; int mclen; Glyph32 gv; Uchar32 uc; - while ((mclen = is_next_glyph_sp(mbc_devfont, sbc_devfont, + while ((mclen = is_next_glyph_sp(gbinfo, mstr, mstr_len, &gv, &uc)) > 0) { gbinfo_push_back(gbinfo, gv, BOV_AFTER_NOTALLOWED); @@ -539,7 +547,7 @@ static int check_subsequent_sp(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, return cosumed; } -static int is_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, +static int is_subsequent_sps_and_end_bt(struct glyph_break_info* gbinfo, const char* mstr, int mstr_len, UCharBreakType end_bt) { Glyph32 gv; @@ -547,7 +555,7 @@ static int is_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfo int mclen; while (mstr_len > 0 && *mstr != '\0') { - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(uc); @@ -567,9 +575,8 @@ static int is_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfo return FALSE; } -static int check_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_devfont, - const char* mstr, int mstr_len, UCharBreakType end_bt, - struct glyph_break_info* gbinfo) +static int check_subsequent_sps_and_end_bt(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len, UCharBreakType end_bt) { int cosumed = 0; int mclen; @@ -577,7 +584,7 @@ static int check_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_de Uchar32 uc; while (mstr_len > 0 && *mstr != '\0') { - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); if (mclen > 0) { UCharBreakType bt = UCharGetBreak(uc); @@ -603,19 +610,85 @@ static int check_subsequent_sps_and_end_bt(DEVFONT* mbc_devfont, DEVFONT* sbc_de return cosumed; } +static BOOL is_even_nubmer_of_subsequent_ri(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len) +{ + int nr = 0; + int mclen; + Glyph32 gv; + Uchar32 uc; + + while (mstr_len > 0 && *mstr != '\0') { + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); + mstr_len -= mclen; + + if (mclen > 0 && UCharGetBreak(uc) == UCHAR_BREAK_REGIONAL_INDICATOR) { + nr++; + continue; + } + else + break; + } + + if (nr > 0 && nr % 2 == 0) + return TRUE; + + return FALSE; +} + +static int check_even_nubmer_of_subsequent_ri(struct glyph_break_info* gbinfo, + const char* mstr, int mstr_len) +{ + int nr = 0; + int cosumed = 0; + int mclen; + Glyph32 gv; + Uchar32 uc; + + while (mstr_len > 0 && *mstr != '\0') { + mclen = get_next_glyph(gbinfo, mstr, mstr_len, &gv, &uc); + if (mclen > 0 && UCharGetBreak(uc) == UCHAR_BREAK_REGIONAL_INDICATOR) { + mstr += mclen; + mstr_len -= mclen; + cosumed += mclen; + nr++; + + gbinfo_push_back(gbinfo, gv, + BOV_BEFORE_UNKNOWN | BOV_BEFORE_UNKNOWN); + continue; + } + else + break; + } + + if (nr > 0 && nr % 2 == 0) { + gbinfo_change_bt(gbinfo, -2, BOV_AFTER_NOTALLOWED); + gbinfo_change_bt(gbinfo, -1, BOV_BEFORE_NOTALLOWED); + return cosumed; + } + + return 0; +} + int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, LanguageCode content_language, UCharScriptType writing_system, Uint32 space_rule, Uint32 trans_rule, Glyph32** glyphs, Uint8** break_oppos, int* nr_glyphs) { - struct glyph_break_info gbinfo = {0, 0, NULL, NULL}; + struct glyph_break_info gbinfo; int cosumed = 0; - DEVFONT* sbc_devfont = logfont->sbc_devfont; - DEVFONT* mbc_devfont = logfont->mbc_devfont; + + gbinfo.mbc_devfont = logfont->mbc_devfont; + gbinfo.sbc_devfont = logfont->sbc_devfont; + gbinfo.len_buff = 0; + gbinfo.n = 0; + gbinfo.gs = NULL; + gbinfo.bs = NULL; *glyphs = NULL; *break_oppos = NULL; *nr_glyphs = 0; + if (mstr_len == 0) return 0; @@ -635,8 +708,7 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, Uchar32 next_uc; int next_mclen; - mclen = get_next_glyph(mbc_devfont, sbc_devfont, mstr, mstr_len, - &gv, &uc); + mclen = get_next_glyph(&gbinfo, mstr, mstr_len, &gv, &uc); if (mclen == 0) { // badly encoded or end of text break; @@ -679,8 +751,7 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // and NL as hard line breaks. // LB6 Do not break before hard line breaks. else if (bt == UCHAR_BREAK_CARRIAGE_RETURN) { - mclen += collapse_line_feed(mbc_devfont, sbc_devfont, mstr, - mstr_len); + mclen += collapse_line_feed(&gbinfo, mstr, mstr_len); bo = BOV_AFTER_MANDATORY | BOV_BEFORE_NOTALLOWED; if (gbinfo_push_back(&gbinfo, gv, bo) == 0) goto error; @@ -705,8 +776,7 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, if (space_rule == WSR_NORMAL || space_rule == WSR_NOWRAP) { // CSS: collapses space according to space rule - mclen += collapse_space(mbc_devfont, sbc_devfont, mstr, - mstr_len); + mclen += collapse_space(&gbinfo, mstr, mstr_len); } } // LB7: Do not break before spaces or zero width space. @@ -717,7 +787,7 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } // LB8: Break before any character following a zero-width space, // even if one or more spaces intervene. - else if (is_next_glyph_zw(mbc_devfont, sbc_devfont, mstr, mstr_len)) { + else if (is_next_glyph_zw(&gbinfo, mstr, mstr_len)) { bo = BOV_BEFORE_MANDATORY; if (gbinfo_push_back(&gbinfo, gv, bo) == 0) goto error; @@ -725,8 +795,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // LB8a Do not break between a zero width joiner and an ideograph, // emoji base or emoji modifier. else if (bt == UCHAR_BREAK_ZERO_WIDTH_JOINER - && (next_mclen = is_next_glyph_id_eb_em(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_id_eb_em(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -751,8 +821,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, && bt != UCHAR_BREAK_NEXT_LINE && bt != UCHAR_BREAK_SPACE && bt != UCHAR_BREAK_ZERO_WIDTH_SPACE - && (next_mclen = is_next_glyph_cm_zwj(mbc_devfont, - sbc_devfont, mstr, mstr_len, &next_gv, &next_uc)) > 0) { + && (next_mclen = is_next_glyph_cm_zwj(&gbinfo, + mstr, mstr_len, &next_gv, &next_uc)) > 0) { mclen += next_mclen; bo = BOV_AFTER_NOTALLOWED; @@ -766,9 +836,9 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; // For any possible subsequent CM/ZWJ characters. - mclen += check_subsequent_cm_or_zwj(mbc_devfont, - sbc_devfont, mstr + mclen + next_mclen, - mstr_len - mclen - next_mclen, &gbinfo); + mclen += check_subsequent_cm_or_zwj(&gbinfo, + mstr + mclen + next_mclen, + mstr_len - mclen - next_mclen); } // LB10 Treat any remaining combining mark or ZWJ as AL. @@ -798,8 +868,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, if (bt != UCHAR_BREAK_SPACE && bt != UCHAR_BREAK_AFTER && bt != UCHAR_BREAK_HYPHEN - && (next_mclen = is_next_glyph_gl(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_gl(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -830,14 +900,13 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; // For any possible subsequent space. - mclen += check_subsequent_sp(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, - &gbinfo); + mclen += check_subsequent_sp(&gbinfo, + mstr + mclen, mstr_len - mclen); } // LB15 Do not break within ‘”[’, even with intervening spaces. else if (bt == UCHAR_BREAK_QUOTATION - && (is_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (is_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, UCHAR_BREAK_OPEN_PUNCTUATION))) { bo |= BOV_AFTER_NOTALLOWED; @@ -845,17 +914,16 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; // For subsequent spaces and OP. - mclen += check_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, - UCHAR_BREAK_OPEN_PUNCTUATION, - &gbinfo); + mclen += check_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, + UCHAR_BREAK_OPEN_PUNCTUATION); } // LB16 Do not break between closing punctuation and a nonstarter // (lb=NS), even with intervening spaces. else if ((bt == UCHAR_BREAK_CLOSE_PUNCTUATION || bt == UCHAR_BREAK_CLOSE_PARANTHESIS) - && (is_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (is_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, UCHAR_BREAK_NON_STARTER))) { bo |= BOV_AFTER_NOTALLOWED; @@ -863,15 +931,14 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; // For subsequent spaces and NS. - mclen += check_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, - UCHAR_BREAK_NON_STARTER, - &gbinfo); + mclen += check_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, + UCHAR_BREAK_NON_STARTER); } // LB17 Do not break within ‘——’, even with intervening spaces. else if (bt == UCHAR_BREAK_BEFORE_AND_AFTER - && (is_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (is_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, UCHAR_BREAK_BEFORE_AND_AFTER))) { bo |= BOV_AFTER_NOTALLOWED; @@ -879,10 +946,9 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; // For subsequent spaces and B2. - mclen += check_subsequent_sps_and_end_bt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, - UCHAR_BREAK_BEFORE_AND_AFTER, - &gbinfo); + mclen += check_subsequent_sps_and_end_bt(&gbinfo, + mstr + mclen, mstr_len - mclen, + UCHAR_BREAK_BEFORE_AND_AFTER); } /* Spaces */ @@ -922,8 +988,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } // LB21a Don't break after Hebrew + Hyphen. else if (bt == UCHAR_BREAK_HEBREW_LETTER - && (next_mclen = is_next_glyph_hy_or_ba(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_hy_or_ba(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -937,8 +1003,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } // LB21b Don’t break between Solidus and Hebrew letters. else if (bt == UCHAR_BREAK_SYMBOL - && (next_mclen = is_next_glyph_hl(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_hl(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -960,8 +1026,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, || bt == UCHAR_BREAK_EMOJI_MODIFIER || bt == UCHAR_BREAK_INSEPARABLE || bt == UCHAR_BREAK_NUMERIC) - && (next_mclen = is_next_glyph_in(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_in(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -978,8 +1044,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // LB23 Do not break between digits and letters. if ((bt == UCHAR_BREAK_HEBREW_LETTER || bt == UCHAR_BREAK_ALPHABETIC) - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -992,8 +1058,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_NUMERIC - && (next_mclen = is_next_glyph_al_hl(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_al_hl(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1008,8 +1074,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // LB23a Do not break between numeric prefixes and ideographs, // or between ideographs and numeric postfixes. else if (bt == UCHAR_BREAK_PREFIX - && (next_mclen = is_next_glyph_id_eb_em(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_id_eb_em(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1024,8 +1090,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, else if ((bt == UCHAR_BREAK_IDEOGRAPHIC || bt == UCHAR_BREAK_EMOJI_BASE || bt == UCHAR_BREAK_EMOJI_MODIFIER) - && (next_mclen = is_next_glyph_po(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_po(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1041,8 +1107,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // or between letters and prefix/postfix. else if ((bt == UCHAR_BREAK_PREFIX || bt == UCHAR_BREAK_POSTFIX) - && (next_mclen = is_next_glyph_al_hl(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_al_hl(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1056,8 +1122,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } else if ((bt == UCHAR_BREAK_ALPHABETIC || bt == UCHAR_BREAK_HEBREW_LETTER) - && (next_mclen = is_next_glyph_pr_po(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_pr_po(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1072,8 +1138,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, // LB25 Do not break between the following pairs of classes // relevant to numbers else if (bt == UCHAR_BREAK_CLOSE_PUNCTUATION - && (next_mclen = is_next_glyph_po(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_po(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1086,8 +1152,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_CLOSE_PUNCTUATION - && (next_mclen = is_next_glyph_po(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_po(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1100,8 +1166,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_CLOSE_PARANTHESIS - && (next_mclen = is_next_glyph_pr(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_pr(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1114,8 +1180,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_CLOSE_PARANTHESIS - && (next_mclen = is_next_glyph_pr(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_pr(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1128,8 +1194,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_NUMERIC - && (next_mclen = is_next_glyph_pr(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_pr(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1142,8 +1208,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_NUMERIC - && (next_mclen = is_next_glyph_pr(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_pr(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1156,8 +1222,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_POSTFIX - && (next_mclen = is_next_glyph_op(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_op(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1170,8 +1236,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_POSTFIX - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1184,8 +1250,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_PREFIX - && (next_mclen = is_next_glyph_op(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_op(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1198,8 +1264,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_PREFIX - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1212,8 +1278,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_HYPHEN - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1226,8 +1292,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_INFIX_SEPARATOR - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1240,8 +1306,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_NUMERIC - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1254,8 +1320,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_SYMBOL - && (next_mclen = is_next_glyph_nu(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1271,8 +1337,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, /* Korean syllable blocks */ // LB26 Do not break a Korean syllable. else if (bt == UCHAR_BREAK_HANGUL_L_JAMO - && (next_mclen = is_next_glyph_jl_jv_h2_h3(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_jl_jv_h2_h3(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1286,8 +1352,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } else if ((bt == UCHAR_BREAK_HANGUL_V_JAMO || bt == UCHAR_BREAK_HANGUL_LV_SYLLABLE) - && (next_mclen = is_next_glyph_jv_jt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_jv_jt(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1301,8 +1367,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, } else if ((bt == UCHAR_BREAK_HANGUL_T_JAMO || bt == UCHAR_BREAK_HANGUL_LV_SYLLABLE) - && (next_mclen = is_next_glyph_jt(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_jt(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1320,8 +1386,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, || bt == UCHAR_BREAK_HANGUL_T_JAMO || bt == UCHAR_BREAK_HANGUL_LV_SYLLABLE || bt == UCHAR_BREAK_HANGUL_LVT_SYLLABLE) - && (next_mclen = is_next_glyph_in(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_in(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1338,8 +1404,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, || bt == UCHAR_BREAK_HANGUL_T_JAMO || bt == UCHAR_BREAK_HANGUL_LV_SYLLABLE || bt == UCHAR_BREAK_HANGUL_LVT_SYLLABLE) - && (next_mclen = is_next_glyph_po(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_po(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1352,8 +1418,8 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, goto error; } else if (bt == UCHAR_BREAK_PREFIX - && (next_mclen = is_next_glyph_jl_jv_jt_h2_h3(mbc_devfont, - sbc_devfont, mstr + mclen, mstr_len - mclen, + && (next_mclen = is_next_glyph_jl_jv_jt_h2_h3(&gbinfo, + mstr + mclen, mstr_len - mclen, &next_gv, &next_uc)) > 0) { mclen += next_mclen; @@ -1370,18 +1436,108 @@ int GUIAPI GetGlyphsByRules(LOGFONT* logfont, const char* mstr, int mstr_len, and break everything else. */ // LB28 Do not break between alphabetics (“at”). + if ((bt == UCHAR_BREAK_HEBREW_LETTER + || bt == UCHAR_BREAK_ALPHABETIC) + && (next_mclen = is_next_glyph_al_hl(&gbinfo, + mstr + mclen, mstr_len - mclen, + &next_gv, &next_uc)) > 0) { + mclen += next_mclen; + + bo = BOV_AFTER_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + bo = BOV_BEFORE_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, next_gv, bo) == 0) + goto error; + } // LB29 Do not break between numeric punctuation // and alphabetics (“e.g.”). + else if (bt == UCHAR_BREAK_INFIX_SEPARATOR + && (next_mclen = is_next_glyph_al_hl(&gbinfo, + mstr + mclen, mstr_len - mclen, + &next_gv, &next_uc)) > 0) { + mclen += next_mclen; + + bo = BOV_AFTER_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + bo = BOV_BEFORE_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, next_gv, bo) == 0) + goto error; + } // LB30 Do not break between letters, numbers, or ordinary symbols and // opening or closing parentheses. + else if ((bt == UCHAR_BREAK_HEBREW_LETTER + || bt == UCHAR_BREAK_ALPHABETIC + || bt == UCHAR_BREAK_NUMERIC) + && (next_mclen = is_next_glyph_op(&gbinfo, + mstr + mclen, mstr_len - mclen, + &next_gv, &next_uc)) > 0) { + mclen += next_mclen; + + bo = BOV_AFTER_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + bo = BOV_BEFORE_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, next_gv, bo) == 0) + goto error; + } + else if (bt == UCHAR_BREAK_CLOSE_PARANTHESIS + && (next_mclen = is_next_glyph_al_hl_nu(&gbinfo, + mstr + mclen, mstr_len - mclen, + &next_gv, &next_uc)) > 0) { + mclen += next_mclen; + + bo = BOV_AFTER_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + bo = BOV_BEFORE_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, next_gv, bo) == 0) + goto error; + } // LB30a Break between two regional indicator symbols if and only if // there are an even number of regional indicators preceding the // position of the break. + if (gbinfo.n == 0 && bt == UCHAR_BREAK_REGIONAL_INDICATOR + && is_even_nubmer_of_subsequent_ri(&gbinfo, + mstr - mclen, mstr_len + mclen)) { + mclen = check_even_nubmer_of_subsequent_ri(&gbinfo, + mstr - mclen, mstr_len + mclen); + } + else if (bt != UCHAR_BREAK_REGIONAL_INDICATOR + && is_even_nubmer_of_subsequent_ri(&gbinfo, + mstr + mclen, mstr_len - mclen)) { + + bo = BOV_BEFORE_UNKNOWN | BOV_AFTER_ALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + mclen += check_even_nubmer_of_subsequent_ri(&gbinfo, + mstr + mclen, mstr_len - mclen); + } // LB30b Do not break between an emoji base and an emoji modifier. + if (bt == UCHAR_BREAK_EMOJI_BASE + && (next_mclen = is_next_glyph_em(&gbinfo, + mstr + mclen, mstr_len - mclen, + &next_gv, &next_uc)) > 0) { + mclen += next_mclen; + + bo = BOV_AFTER_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, gv, bo) == 0) + goto error; + + bo = BOV_BEFORE_NOTALLOWED; + if (gbinfo_push_back(&gbinfo, next_gv, bo) == 0) + goto error; + } // LB31 Break everywhere else.