diff --git a/include/gdi.h b/include/gdi.h index 483b6a7c..fd2c9842 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -2009,20 +2009,26 @@ MG_EXPORT void GUIAPI DeleteSecondaryDC (HWND hwnd); #define DC_ATTR_TEXT_ALIGN 10 +#define DC_ATTR_BIDI_ENABLED 11 +#define DC_ATTR_BIDI_FIRSTCH_TYPE 12 + #define BIDI_CHAR_TYPE_INIT 0 + #define BIDI_CHAR_TYPE_LTR 1 + #define BIDI_CHAR_TYPE_RTL 2 + #ifdef _MGHAVE_ADV_2DAPI -#define DC_ATTR_PEN_TYPE 11 -#define DC_ATTR_PEN_CAP_STYLE 12 -#define DC_ATTR_PEN_JOIN_STYLE 13 -#define DC_ATTR_PEN_WIDTH 14 +#define DC_ATTR_PEN_TYPE 13 +#define DC_ATTR_PEN_CAP_STYLE 14 +#define DC_ATTR_PEN_JOIN_STYLE 15 +#define DC_ATTR_PEN_WIDTH 16 -#define DC_ATTR_BRUSH_TYPE 15 +#define DC_ATTR_BRUSH_TYPE 17 -#define NR_DC_ATTRS 16 +#define NR_DC_ATTRS 18 #else -#define NR_DC_ATTRS 11 +#define NR_DC_ATTRS 13 #endif @@ -2064,9 +2070,12 @@ MG_EXPORT void GUIAPI DeleteSecondaryDC (HWND hwnd); * Spacing bellow line for the DC. * - DC_ATTR_MAP_MODE\n * mode of a DC. - * - DC_ATTR_TEXT_ALIGN\n + * - DC_ATTR_TEXT_ALIGN\n * Text-alignment flags of a DC. - * + * - DC_ATTR_BIDI_ENABLED\n + * Is BIDI enabled. + * - DC_ATTR_BIDI_FIRSTCH_TYPE\n + * The first character type, on of BIDI_CHAR_TYPE_INIT, BIDI_CHAR_TYPE_LTR, or BIDI_CHAR_TYPE_RTL. * \return The attribute value. * * \sa SetDCAttr @@ -7008,7 +7017,15 @@ MG_EXPORT int GUIAPI GetTabbedTextExtent (HDC hdc, * \sa GetTextAlign */ #define SetTextAlign(hdc, ta_flags) \ - SetDCAttr (hdc, DC_ATTR_TEXT_ALIGN, (DWORD)ta_flags) + SetDCAttr (hdc, DC_ATTR_TEXT_ALIGN, (DWORD)ta_flags) + +#define GetBIDIFlag(hdc) GetDCAttr (hdc, DC_ATTR_BIDI_ENABLED) +#define SetBIDIFlag(hdc, bidi) \ + SetDCAttr (hdc, DC_ATTR_BIDI_ENABLED, (DWORD)bidi) + +#define GetBIDIFirstChType(hdc) GetDCAttr (hdc, DC_ATTR_BIDI_FIRSTCH_TYPE) +#define SetBIDIFirstChType(hdc, type) \ + SetDCAttr (hdc, DC_ATTR_BIDI_FIRSTCH_TYPE, (DWORD)type) /** * \fn int GUIAPI TextOutLen (HDC hdc, int x, int y, \ @@ -8534,24 +8551,6 @@ MG_EXPORT BOOL GUIAPI AddGlyphsToBMPFont (DEVFONT* dev_font, BITMAP* glyph_bmp, */ MG_EXPORT void GUIAPI DestroyBMPFont (DEVFONT* dev_font); -#ifdef _DEBUG -/* - * Dump avl tree info - */ -void dump_tree (DEVFONT *dev_font); - -/* - * look up a node in bitmap font avl tree. - */ -int avl_look_up (DEVFONT *dev_font, char *start_mchar, int n); - -/* - * destroy bitmap font avl tree. - */ -void destroy_avl_tree (DEVFONT *dev_font); - -#endif /* end of _DEBUG */ - #endif /* end of _MGFONT_BMPF */ /** @@ -8810,6 +8809,200 @@ MG_EXPORT int GUIAPI GetGlyphsExtent(HDC hdc, Glyph32* glyphs, int nr_glyphs, MG_EXPORT int GUIAPI GetGlyphsExtentPoint(HDC hdc, Glyph32* glyphs, int nr_glyphs, int max_extent, SIZE* size); +/* + * Define some bit masks, that character types are based on, each one has + * only one bit on. + */ + +#define BIDI_MASK_RTL 0x00000001L /* Is right to left */ +#define BIDI_MASK_ARABIC 0x00000002L /* Is arabic */ + +/* Each char can be only one of the three following. */ +#define BIDI_MASK_STRONG 0x00000010L /* Is strong */ +#define BIDI_MASK_WEAK 0x00000020L /* Is weak */ +#define BIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */ +#define BIDI_MASK_SENTINEL 0x00000080L /* Is sentinel: SOT, EOT */ + +/* Each char can be only one of the five following. */ +#define BIDI_MASK_LETTER 0x00000100L /* Is letter: L, R, AL */ +#define BIDI_MASK_NUMBER 0x00000200L /* Is number: EN, AN */ +#define BIDI_MASK_NUMSEPTER 0x00000400L /* Is number separator or terminator: ES, ET, CS */ +#define BIDI_MASK_SPACE 0x00000800L /* Is space: BN, BS, SS, WS */ +#define BIDI_MASK_EXPLICIT 0x00001000L /* Is expilict mark: LRE, RLE, LRO, RLO, PDF */ + +/* Can be on only if BIDI_MASK_SPACE is also on. */ +#define BIDI_MASK_SEPARATOR 0x00002000L /* Is test separator: BS, SS */ +/* Can be on only if BIDI_MASK_EXPLICIT is also on. */ +#define BIDI_MASK_OVERRIDE 0x00004000L /* Is explicit override: LRO, RLO */ + +#define BIDI_MASK_ES 0x00010000L +#define BIDI_MASK_ET 0x00020000L +#define BIDI_MASK_CS 0x00040000L + +#define BIDI_MASK_NSM 0x00080000L +#define BIDI_MASK_BN 0x00100000L + +#define BIDI_MASK_BS 0x00200000L +#define BIDI_MASK_SS 0x00400000L +#define BIDI_MASK_WS 0x00800000L + +/* + * Define values for Bidi char type + */ + +/* Strong left to right */ +#define BIDI_TYPE_LTR (BIDI_MASK_STRONG + BIDI_MASK_LETTER) + +/* Right to left characters */ +#define BIDI_TYPE_RTL (BIDI_MASK_STRONG + BIDI_MASK_LETTER \ + + BIDI_MASK_RTL) + +/* Arabic characters */ +#define BIDI_TYPE_AL (BIDI_MASK_STRONG + BIDI_MASK_LETTER \ + + BIDI_MASK_RTL + BIDI_MASK_ARABIC) + +/* Left-To-Right embedding */ +#define BIDI_TYPE_LRE (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT) + +/* Right-To-Left embedding */ +#define BIDI_TYPE_RLE (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ + + BIDI_MASK_RTL) + +/* Left-To-Right override */ +#define BIDI_TYPE_LRO (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ + + BIDI_MASK_OVERRIDE) + +/* Right-To-Left override */ +#define BIDI_TYPE_RLO (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ + + BIDI_MASK_RTL + BIDI_MASK_OVERRIDE) + +/* Pop directional override */ +#define BIDI_TYPE_PDF (BIDI_MASK_WEAK + BIDI_MASK_EXPLICIT) + +/* European digit */ +#define BIDI_TYPE_EN (BIDI_MASK_WEAK + BIDI_MASK_NUMBER) + +/* Arabic digit */ +#define BIDI_TYPE_AN (BIDI_MASK_WEAK + BIDI_MASK_NUMBER \ + + BIDI_MASK_ARABIC) + +/* European number separator */ +#define BIDI_TYPE_ES (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ + + BIDI_MASK_ES) + +/* European number terminator */ +#define BIDI_TYPE_ET (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ + + BIDI_MASK_ET) + +/* Common Separator */ +#define BIDI_TYPE_CS (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ + + BIDI_MASK_CS) + +/* Non spacing mark */ +#define BIDI_TYPE_NSM (BIDI_MASK_WEAK + BIDI_MASK_NSM) + +/* Boundary neutral */ +#define BIDI_TYPE_BN (BIDI_MASK_WEAK + BIDI_MASK_SPACE \ + + BIDI_MASK_BN) + +/* Block separator */ +#define BIDI_TYPE_BS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ + + BIDI_MASK_SEPARATOR + BIDI_MASK_BS) + +/* Segment separator */ +#define BIDI_TYPE_SS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ + + BIDI_MASK_SEPARATOR + BIDI_MASK_SS) +/* Whitespace */ +#define BIDI_TYPE_WS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ + + BIDI_MASK_WS) + +/* Other Neutral */ +#define BIDI_TYPE_ON (BIDI_MASK_NEUTRAL) + +/* The following are used to identify the paragraph direction, + types L, R, N are not used internally anymore, and recommended to use + LTR, RTL and ON instead, didn't removed because of compatability. */ + +#define BIDI_TYPE_L (BIDI_TYPE_LTR) +#define BIDI_TYPE_R (BIDI_TYPE_RTL) +#define BIDI_TYPE_N (BIDI_TYPE_ON) +/* Weak left to right */ +#define BIDI_TYPE_WL (BIDI_MASK_WEAK) +/* Weak right to left */ +#define BIDI_TYPE_WR (BIDI_MASK_WEAK + BIDI_MASK_RTL) + +/* The following are only used internally */ + +/* Start of text */ +#define BIDI_TYPE_SOT (BIDI_MASK_SENTINEL) +/* End of text */ +#define BIDI_TYPE_EOT (BIDI_MASK_SENTINEL + BIDI_MASK_RTL) + +/* Is private-use value? */ +#define BIDI_TYPE_PRIVATE(p) ((p) < 0) + +/* Return the direction of the level number, BIDI_TYPE_LTR for even and + BIDI_TYPE_RTL for odds. */ +#define BIDI_LEVEL_TO_DIR(lev) (BIDI_TYPE_LTR | (lev & 1)) + +/* Return the minimum level of the direction, 0 for BIDI_TYPE_LTR and + 1 for BIDI_TYPE_RTL and BIDI_TYPE_AL. */ +#define BIDI_DIR_TO_LEVEL(dir) ((BYTE)(dir & 1)) + +/* Is right to left? */ +#define BIDI_IS_RTL(p) ((p) & BIDI_MASK_RTL) +/* Is arabic? */ +#define BIDI_IS_ARABIC(p) ((p) & BIDI_MASK_ARABIC) + +/* Is strong? */ +#define BIDI_IS_STRONG(p) ((p) & BIDI_MASK_STRONG) +/* Is weak? */ +#define BIDI_IS_WEAK(p) ((p) & BIDI_MASK_WEAK) +/* Is neutral? */ +#define BIDI_IS_NEUTRAL(p) ((p) & BIDI_MASK_NEUTRAL) +/* Is sentinel? */ +#define BIDI_IS_SENTINEL(p) ((p) & BIDI_MASK_SENTINEL) + +/* Is letter: L, R, AL? */ +#define BIDI_IS_LETTER(p) ((p) & BIDI_MASK_LETTER) +/* Is number: EN, AN? */ +#define BIDI_IS_NUMBER(p) ((p) & BIDI_MASK_NUMBER) +/* Is number separator or terminator: ES, ET, CS? */ +#define BIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR(p) \ + ((p) & BIDI_MASK_NUMSEPTER) + +/* Is space: BN, BS, SS, WS? */ +#define BIDI_IS_SPACE(p) ((p) & BIDI_MASK_SPACE) +/* Is explicit mark: LRE, RLE, LRO, RLO, PDF? */ +#define BIDI_IS_EXPLICIT(p) ((p) & BIDI_MASK_EXPLICIT) + +/* Is test separator: BS, SS? */ +#define BIDI_IS_SEPARATOR(p) ((p) & BIDI_MASK_SEPARATOR) + +/* Is explicit override: LRO, RLO? */ +#define BIDI_IS_OVERRIDE(p) ((p) & BIDI_MASK_OVERRIDE) + +/* Some more: */ + +/* Is left to right letter: LTR? */ +#define BIDI_IS_LTR_LETTER(p) \ + ((p) & (BIDI_MASK_LETTER | BIDI_MASK_RTL) == BIDI_MASK_LETTER) + +/* Is right to left letter: RTL, AL? */ +#define BIDI_IS_RTL_LETTER(p) \ + ((p) & (BIDI_MASK_LETTER | BIDI_MASK_RTL) \ + == (BIDI_MASK_LETTER | BIDI_MASK_RTL)) + +/* Is ES or CS: ES, CS? */ +#define BIDI_IS_ES_OR_CS(p) \ + ((p) & (BIDI_MASK_ES | BIDI_MASK_CS)) + +/* Change numbers: EN, AN to RTL. */ +#define BIDI_NUMBER_TO_RTL(p) \ + (BIDI_IS_NUMBER(p) ? BIDI_TYPE_RTL : (p)) + +MG_EXPORT GUIAPI BOOL GetGlyphBIDIType (LOGFONT* log_font, Glyph32 glyph_value, Uint32 *bidi_type); + /** \fn int GUIAPI BIDIGetTextLogicalGlyphs(LOGFONT* log_font, \ const char* text, int text_len, Glyph32** glyphs, \ GLYPHMAPINFO** glyphs_map) diff --git a/src/font/bitmapfont.c b/src/font/bitmapfont.c index a2e26862..2a7ca0c9 100644 --- a/src/font/bitmapfont.c +++ b/src/font/bitmapfont.c @@ -66,7 +66,7 @@ static int def_glyph_width = 8; /* default bitmap glyph */ static unsigned char def_glyph [] = {0}; -#define DEFGLYPHWIDTH 8; +#define DEFGLYPHWIDTH 8 /*** tree ops ***/ @@ -595,10 +595,9 @@ void DestroyBMPFont (DEVFONT* dev_font) return; } -#ifdef _DEBUG +#if 0 -static int -print_tree_struct ( GLYPHTREENODE *node) +static int print_tree_struct ( GLYPHTREENODE *node) { if (node == NULL) @@ -621,8 +620,7 @@ print_tree_struct ( GLYPHTREENODE *node) return 0; } - -void dump_tree (DEVFONT *dev_font) +static void dump_tree (DEVFONT *dev_font) { if (dev_font == NULL || dev_font->data == NULL || @@ -636,7 +634,7 @@ void dump_tree (DEVFONT *dev_font) _MG_PRINTF ("\n"); } -int avl_look_up (DEVFONT *dev_font, char *start_mchar, int n) +static int avl_look_up (DEVFONT *dev_font, char *start_mchar, int n) { GLYPHTREENODE *p; int offset; @@ -659,7 +657,7 @@ int avl_look_up (DEVFONT *dev_font, char *start_mchar, int n) return 0; } -void destroy_avl_tree (DEVFONT *dev_font) +static void destroy_avl_tree (DEVFONT *dev_font) { if (dev_font && ((BMPFONTINFO *)dev_font->data)->tree != NULL) { @@ -670,7 +668,7 @@ void destroy_avl_tree (DEVFONT *dev_font) } } -void draw_root_bmp (HDC hdc, DEVFONT *dev_font) +static void draw_root_bmp (HDC hdc, DEVFONT *dev_font) { GLYPHTREENODE *root = ((BMPFONTINFO *)dev_font->data)->tree; @@ -681,7 +679,7 @@ void draw_root_bmp (HDC hdc, DEVFONT *dev_font) FillBoxWithBitmap (hdc, 0, 400, 0, 0, root->data); } -#endif /* End of _DEBUG */ +#endif #endif /* End of _MGFONT_BMPF */ diff --git a/src/font/charset-arabic.c b/src/font/charset-arabic.c index 5f30b7b6..909400e1 100644 --- a/src/font/charset-arabic.c +++ b/src/font/charset-arabic.c @@ -468,7 +468,7 @@ static unsigned int iso8859_6_glyph_type (Glyph32 glyph_value) return ch_type; } -static BidiCharType __mg_iso8859_68x_type[] = { +static Uint32 __mg_iso8859_68x_type[] = { /*0x00~0x0f*/ BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, diff --git a/src/font/charset-bidi.c b/src/font/charset-bidi.c index 43e4a18e..17b0f615 100644 --- a/src/font/charset-bidi.c +++ b/src/font/charset-bidi.c @@ -63,14 +63,14 @@ struct _TYPERUN struct _TYPERUN *prev; struct _TYPERUN *next; - BidiCharType type; /* char type. */ + Uint32 type; /* char type. */ int pos, len; /* run start position、run len.*/ BYTE level; /* Embedding level. */ }; #ifdef BIDI_DEBUG -static char bidi_type_name(BidiCharType c) +static char bidi_type_name(Uint32 c) { switch (c){ case BIDI_TYPE_LTR: return 'L'; @@ -251,7 +251,7 @@ static TYPERUN* get_runtype_link (const CHARSETOPS* charset_ops, Glyph32* glyphs /* 1.Find base level */ -static void bidi_resolveParagraphs(TYPERUN **ptype_rl_list, BidiCharType* pbase_dir, BYTE* pbase_level) +static void bidi_resolveParagraphs(TYPERUN **ptype_rl_list, Uint32* pbase_dir, BYTE* pbase_level) { TYPERUN *type_rl_list = *ptype_rl_list, *pp = NULL; DBGLOG("\n1:Finding the base level\n"); @@ -273,7 +273,7 @@ static void bidi_resolveParagraphs(TYPERUN **ptype_rl_list, BidiCharType* pbase_ /* 2.Resolving Explicit levels. * now nothing need to do.*/ -static void bidi_resolveExplicit (TYPERUN **ptype_rl_list, BidiCharType base_dir) +static void bidi_resolveExplicit (TYPERUN **ptype_rl_list, Uint32 base_dir) { TYPERUN *type_rl_list = *ptype_rl_list, *pp = NULL; DBGLOG("\n2:Resolving weak types\n"); @@ -286,10 +286,10 @@ static void bidi_resolveExplicit (TYPERUN **ptype_rl_list, BidiCharType base_dir } /* 3.Resolving weak types */ -static void bidi_resolveWeak(TYPERUN **ptype_rl_list, BidiCharType base_dir) +static void bidi_resolveWeak(TYPERUN **ptype_rl_list, Uint32 base_dir) { TYPERUN *type_rl_list = *ptype_rl_list, *pp = NULL; - BidiCharType last_strong, prev_type_org; + Uint32 last_strong, prev_type_org; BOOL w4; DBGLOG("\n3:Resolving weak types\n"); @@ -297,7 +297,7 @@ static void bidi_resolveWeak(TYPERUN **ptype_rl_list, BidiCharType base_dir) for (pp = type_rl_list->next; pp->next; pp = pp->next) { - BidiCharType prev_type, this_type, next_type; + Uint32 prev_type, this_type, next_type; prev_type = TYPE(pp->prev); this_type = TYPE(pp); @@ -338,7 +338,7 @@ static void bidi_resolveWeak(TYPERUN **ptype_rl_list, BidiCharType base_dir) for (pp = type_rl_list->next; pp->next; pp = pp->next) { - BidiCharType prev_type, this_type, next_type; + Uint32 prev_type, this_type, next_type; prev_type = TYPE(pp->prev); this_type = TYPE(pp); @@ -409,13 +409,13 @@ static void bidi_resolveWeak(TYPERUN **ptype_rl_list, BidiCharType base_dir) #define BIDI_EMBEDDING_DIR(list) BIDI_LEVEL_TO_DIR(LEVEL(list)) /* 4.Resolving Neutral Types */ -static void bidi_resolveNeutrals(TYPERUN **ptype_rl_list, BidiCharType base_bir) +static void bidi_resolveNeutrals(TYPERUN **ptype_rl_list, Uint32 base_bir) { TYPERUN *type_rl_list = *ptype_rl_list, *pp = NULL; DBGLOG ("\n4:Resolving neutral types\n"); for (pp = type_rl_list->next; pp->next; pp = pp->next) { - BidiCharType prev_type, this_type, next_type; + Uint32 prev_type, this_type, next_type; prev_type = TYPE(pp->prev); this_type = TYPE(pp); @@ -446,7 +446,7 @@ static int bidi_resolveImplicit(TYPERUN **ptype_rl_list, int base_level) DBGLOG ("\n5:Resolving implicit levels\n"); for (pp = type_rl_list->next; pp->next; pp = pp->next){ - BidiCharType this_type; + Uint32 this_type; int level; this_type = TYPE(pp); @@ -536,7 +536,7 @@ static void bidi_resolve_string (const CHARSETOPS* charset_ops, Glyph32* glyphs, TYPERUN **ptype_rl_list, BYTE *pmax_level) { BYTE base_level = 0; - BidiCharType base_dir = BIDI_TYPE_L; + Uint32 base_dir = BIDI_TYPE_L; TYPERUN *type_rl_list = NULL; /* split the text to some runs. */ @@ -699,10 +699,10 @@ Glyph32* __mg_charset_bidi_glyphs_reorder (const CHARSETOPS* charset_ops, Glyph3 return glyphs; } -BidiCharType __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len) +Uint32 __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len) { BYTE base_level = 0; - BidiCharType base_dir = BIDI_TYPE_L; + Uint32 base_dir = BIDI_TYPE_L; TYPERUN *type_rl_list = NULL; /* split the text to some runs. */ @@ -717,3 +717,14 @@ BidiCharType __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyp return base_dir; } +BOOL GetGlyphBIDIType (LOGFONT* log_font, Glyph32 glyph_value, Uint32 *bidi_type) +{ + DEVFONT* mbc_devfont = log_font->mbc_devfont; + + if (mbc_devfont == NULL || mbc_devfont->charset_ops->bidi_glyph_type == NULL) + return FALSE; + + *bidi_type = mbc_devfont->charset_ops->bidi_glyph_type (glyph_value); + return TRUE; +} + diff --git a/src/font/charset.c b/src/font/charset.c index 5d27cb66..647b4f36 100644 --- a/src/font/charset.c +++ b/src/font/charset.c @@ -950,7 +950,7 @@ static const unsigned char* iso8859_8_get_next_word (const unsigned char* mstr, //return sb_get_next_word(mstr, mstrlen, word_info); } -static BidiCharType __mg_iso8859_8_type[] = { +static Uint32 __mg_iso8859_8_type[] = { /*0x00~0x0f*/ BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, BIDI_TYPE_BN, diff --git a/src/font/unicode-bidi-tables.h b/src/font/unicode-bidi-tables.h index d0da7a3d..89781be4 100644 --- a/src/font/unicode-bidi-tables.h +++ b/src/font/unicode-bidi-tables.h @@ -42,9 +42,9 @@ typedef struct _bidichar_type_map { - BidiCharType type; // Type of Unicode characters - Glyph32 glyph; // Starting index of Unicode character - Uint8 count; // Total number of Unicode characters of same type starting from glyphn + Uint32 type; // Type of Unicode characters + Glyph32 glyph; // Starting index of Unicode character + Uint8 count; // Total number of Unicode characters of same type starting from glyphn } BIDICHAR_TYPE_MAP; static const BIDICHAR_TYPE_MAP __mg_unicode_bidi_char_type_map []= diff --git a/src/include/bidi.h b/src/include/bidi.h index 03faee4f..86db14ac 100644 --- a/src/include/bidi.h +++ b/src/include/bidi.h @@ -59,199 +59,6 @@ extern "C" { #define DBGLOG4(s, t1, t2, t3) #endif -/* - * Define some bit masks, that character types are based on, each one has - * only one bit on. - */ - -#define BIDI_MASK_RTL 0x00000001L /* Is right to left */ -#define BIDI_MASK_ARABIC 0x00000002L /* Is arabic */ - -/* Each char can be only one of the three following. */ -#define BIDI_MASK_STRONG 0x00000010L /* Is strong */ -#define BIDI_MASK_WEAK 0x00000020L /* Is weak */ -#define BIDI_MASK_NEUTRAL 0x00000040L /* Is neutral */ -#define BIDI_MASK_SENTINEL 0x00000080L /* Is sentinel: SOT, EOT */ - -/* Each char can be only one of the five following. */ -#define BIDI_MASK_LETTER 0x00000100L /* Is letter: L, R, AL */ -#define BIDI_MASK_NUMBER 0x00000200L /* Is number: EN, AN */ -#define BIDI_MASK_NUMSEPTER 0x00000400L /* Is number separator or terminator: ES, ET, CS */ -#define BIDI_MASK_SPACE 0x00000800L /* Is space: BN, BS, SS, WS */ -#define BIDI_MASK_EXPLICIT 0x00001000L /* Is expilict mark: LRE, RLE, LRO, RLO, PDF */ - -/* Can be on only if BIDI_MASK_SPACE is also on. */ -#define BIDI_MASK_SEPARATOR 0x00002000L /* Is test separator: BS, SS */ -/* Can be on only if BIDI_MASK_EXPLICIT is also on. */ -#define BIDI_MASK_OVERRIDE 0x00004000L /* Is explicit override: LRO, RLO */ - -#define BIDI_MASK_ES 0x00010000L -#define BIDI_MASK_ET 0x00020000L -#define BIDI_MASK_CS 0x00040000L - -#define BIDI_MASK_NSM 0x00080000L -#define BIDI_MASK_BN 0x00100000L - -#define BIDI_MASK_BS 0x00200000L -#define BIDI_MASK_SS 0x00400000L -#define BIDI_MASK_WS 0x00800000L - -/* - * Define values for BidiCharType - */ - -/* Strong left to right */ -#define BIDI_TYPE_LTR (BIDI_MASK_STRONG + BIDI_MASK_LETTER) - -/* Right to left characters */ -#define BIDI_TYPE_RTL (BIDI_MASK_STRONG + BIDI_MASK_LETTER \ - + BIDI_MASK_RTL) - -/* Arabic characters */ -#define BIDI_TYPE_AL (BIDI_MASK_STRONG + BIDI_MASK_LETTER \ - + BIDI_MASK_RTL + BIDI_MASK_ARABIC) - -/* Left-To-Right embedding */ -#define BIDI_TYPE_LRE (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT) - -/* Right-To-Left embedding */ -#define BIDI_TYPE_RLE (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ - + BIDI_MASK_RTL) - -/* Left-To-Right override */ -#define BIDI_TYPE_LRO (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ - + BIDI_MASK_OVERRIDE) - -/* Right-To-Left override */ -#define BIDI_TYPE_RLO (BIDI_MASK_STRONG + BIDI_MASK_EXPLICIT \ - + BIDI_MASK_RTL + BIDI_MASK_OVERRIDE) - -/* Pop directional override */ -#define BIDI_TYPE_PDF (BIDI_MASK_WEAK + BIDI_MASK_EXPLICIT) - -/* European digit */ -#define BIDI_TYPE_EN (BIDI_MASK_WEAK + BIDI_MASK_NUMBER) - -/* Arabic digit */ -#define BIDI_TYPE_AN (BIDI_MASK_WEAK + BIDI_MASK_NUMBER \ - + BIDI_MASK_ARABIC) - -/* European number separator */ -#define BIDI_TYPE_ES (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ - + BIDI_MASK_ES) - -/* European number terminator */ -#define BIDI_TYPE_ET (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ - + BIDI_MASK_ET) - -/* Common Separator */ -#define BIDI_TYPE_CS (BIDI_MASK_WEAK + BIDI_MASK_NUMSEPTER \ - + BIDI_MASK_CS) - -/* Non spacing mark */ -#define BIDI_TYPE_NSM (BIDI_MASK_WEAK + BIDI_MASK_NSM) - -/* Boundary neutral */ -#define BIDI_TYPE_BN (BIDI_MASK_WEAK + BIDI_MASK_SPACE \ - + BIDI_MASK_BN) - -/* Block separator */ -#define BIDI_TYPE_BS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ - + BIDI_MASK_SEPARATOR + BIDI_MASK_BS) - -/* Segment separator */ -#define BIDI_TYPE_SS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ - + BIDI_MASK_SEPARATOR + BIDI_MASK_SS) -/* Whitespace */ -#define BIDI_TYPE_WS (BIDI_MASK_NEUTRAL + BIDI_MASK_SPACE \ - + BIDI_MASK_WS) - -/* Other Neutral */ -#define BIDI_TYPE_ON (BIDI_MASK_NEUTRAL) - -/* The following are used to identify the paragraph direction, - types L, R, N are not used internally anymore, and recommended to use - LTR, RTL and ON instead, didn't removed because of compatability. */ - -#define BIDI_TYPE_L (BIDI_TYPE_LTR) -#define BIDI_TYPE_R (BIDI_TYPE_RTL) -#define BIDI_TYPE_N (BIDI_TYPE_ON) -/* Weak left to right */ -#define BIDI_TYPE_WL (BIDI_MASK_WEAK) -/* Weak right to left */ -#define BIDI_TYPE_WR (BIDI_MASK_WEAK + BIDI_MASK_RTL) - -/* The following are only used internally */ - -/* Start of text */ -#define BIDI_TYPE_SOT (BIDI_MASK_SENTINEL) -/* End of text */ -#define BIDI_TYPE_EOT (BIDI_MASK_SENTINEL + BIDI_MASK_RTL) - -/* Is private-use value? */ -#define BIDI_TYPE_PRIVATE(p) ((p) < 0) - -/* Return the direction of the level number, BIDI_TYPE_LTR for even and - BIDI_TYPE_RTL for odds. */ -#define BIDI_LEVEL_TO_DIR(lev) (BIDI_TYPE_LTR | (lev & 1)) - -/* Return the minimum level of the direction, 0 for BIDI_TYPE_LTR and - 1 for BIDI_TYPE_RTL and BIDI_TYPE_AL. */ -#define BIDI_DIR_TO_LEVEL(dir) ((BYTE)(dir & 1)) - -/* Is right to left? */ -#define BIDI_IS_RTL(p) ((p) & BIDI_MASK_RTL) -/* Is arabic? */ -#define BIDI_IS_ARABIC(p) ((p) & BIDI_MASK_ARABIC) - -/* Is strong? */ -#define BIDI_IS_STRONG(p) ((p) & BIDI_MASK_STRONG) -/* Is weak? */ -#define BIDI_IS_WEAK(p) ((p) & BIDI_MASK_WEAK) -/* Is neutral? */ -#define BIDI_IS_NEUTRAL(p) ((p) & BIDI_MASK_NEUTRAL) -/* Is sentinel? */ -#define BIDI_IS_SENTINEL(p) ((p) & BIDI_MASK_SENTINEL) - -/* Is letter: L, R, AL? */ -#define BIDI_IS_LETTER(p) ((p) & BIDI_MASK_LETTER) -/* Is number: EN, AN? */ -#define BIDI_IS_NUMBER(p) ((p) & BIDI_MASK_NUMBER) -/* Is number separator or terminator: ES, ET, CS? */ -#define BIDI_IS_NUMBER_SEPARATOR_OR_TERMINATOR(p) \ - ((p) & BIDI_MASK_NUMSEPTER) - -/* Is space: BN, BS, SS, WS? */ -#define BIDI_IS_SPACE(p) ((p) & BIDI_MASK_SPACE) -/* Is explicit mark: LRE, RLE, LRO, RLO, PDF? */ -#define BIDI_IS_EXPLICIT(p) ((p) & BIDI_MASK_EXPLICIT) - -/* Is test separator: BS, SS? */ -#define BIDI_IS_SEPARATOR(p) ((p) & BIDI_MASK_SEPARATOR) - -/* Is explicit override: LRO, RLO? */ -#define BIDI_IS_OVERRIDE(p) ((p) & BIDI_MASK_OVERRIDE) - -/* Some more: */ - -/* Is left to right letter: LTR? */ -#define BIDI_IS_LTR_LETTER(p) \ - ((p) & (BIDI_MASK_LETTER | BIDI_MASK_RTL) == BIDI_MASK_LETTER) - -/* Is right to left letter: RTL, AL? */ -#define BIDI_IS_RTL_LETTER(p) \ - ((p) & (BIDI_MASK_LETTER | BIDI_MASK_RTL) \ - == (BIDI_MASK_LETTER | BIDI_MASK_RTL)) - -/* Is ES or CS: ES, CS? */ -#define BIDI_IS_ES_OR_CS(p) \ - ((p) & (BIDI_MASK_ES | BIDI_MASK_CS)) - -/* Change numbers: EN, AN to RTL. */ -#define BIDI_NUMBER_TO_RTL(p) \ - (BIDI_IS_NUMBER(p) ? BIDI_TYPE_RTL : (p)) - -typedef Uint32 BidiCharType; typedef struct _TYPERUN TYPERUN; typedef struct _BIDICHAR_MIRROR_MAP { @@ -272,7 +79,7 @@ void __mg_charset_bidi_get_embeddlevels (const CHARSETOPS* charset_ops, Glyph32* Glyph32* __mg_charset_bidi_index_reorder (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len, int* index_map); -BidiCharType __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len); +Uint32 __mg_charset_bidi_str_base_dir (const CHARSETOPS* charset_ops, Glyph32* glyphs, int len); #ifdef __cplusplus } diff --git a/src/include/dc.h b/src/include/dc.h index f00769f3..fa8b36ae 100644 --- a/src/include/dc.h +++ b/src/include/dc.h @@ -166,6 +166,9 @@ struct tagDC int ta_flags; /* Text alignment flags */ + int bidi_flag; /* BIDI enable flag */ + int bidi_firstch_type; /* BIDI first char type */ + #ifdef _MGHAVE_ADV_2DAPI /* pen attributes */ int pen_type; diff --git a/src/include/readbmp.h b/src/include/readbmp.h index da2a1144..b9acceed 100644 --- a/src/include/readbmp.h +++ b/src/include/readbmp.h @@ -114,6 +114,7 @@ BOOL __mg_check_gif (MG_RWops* fp); void* __mg_init_jpg (MG_RWops* fp, MYBITMAP *jpg, RGB *pal); int __mg_load_jpg (MG_RWops* fp, void* init_info, MYBITMAP *jpg, CB_ONE_SCANLINE cb, void* context); void __mg_cleanup_jpg (void* init_info); +int __mg_save_jpg (MG_RWops* fp, MYBITMAP* bmp, RGB* pal); BOOL __mg_check_jpg (MG_RWops* fp); #endif diff --git a/src/mybmp/jpeg.c b/src/mybmp/jpeg.c index e62d94df..4f41b274 100644 --- a/src/mybmp/jpeg.c +++ b/src/mybmp/jpeg.c @@ -36,6 +36,9 @@ ** ** Current maintainer: Wei Yongming ** +** 2018-09-4 +** Merge pull request from 10km (https://github.com/10km): __mg_save_jpg. +** ** Create date: 2000/08/29 */ @@ -254,11 +257,37 @@ static void my_error_exit (j_common_ptr cinfo) longjmp (myerr->setjmp_buffer, 1); } +/* + * Common JPEG markers + * see also https://en.wikipedia.org/wiki/JPEG + * */ +#define JMK_SOI 0xFFD8 /* Start Of Image */ +#define JMK_SOF0 0xFFC0 /* Start Of Frame (baseline DCT) */ +#define JMK_SOF2 0xFFC2 /* Start Of Frame (progressive DCT) */ +#define JMK_DHT 0xFFC4 /* Define Huffman Table(s) */ +#define JMK_DQT 0xFFDB /* Define Quantization Table(s) */ +#define JMK_DRI 0xFFDD /* Define Restart Interval */ +#define JMK_SOS 0xFFDA /* Start Of Scan */ +#define JMK_RST_mask 0xFFD0 /* mask of Restart */ +#define JMK_APP_mask 0xFFE0 /* mask of Application-specific */ +#define JMK_COM 0xFFFE /* Comment */ +#define JMK_EOI 0xFFD9 /* End Of Image */ +/** + * Reads a 16-bit big endian integer from a MG_RWops object. + * return TRUE if sucess,or FALSE if the read failed. + */ +static BOOL read_be16 (MG_RWops *fp, Uint16 *value) +{ + if(-1 == MGUI_RWread (fp, value, (sizeof *value), 1)) + return FALSE; + *value = (ArchSwapBE16 (*value)); + return TRUE; +} + void* __mg_init_jpg (MG_RWops *fp, MYBITMAP* mybmp, RGB* pal) { int i; - unsigned char magic[5]; - Uint16 magic_db; + Uint16 soi_marker; /* This struct contains the JPEG decompression parameters * and pointers to working space @@ -268,22 +297,10 @@ void* __mg_init_jpg (MG_RWops *fp, MYBITMAP* mybmp, RGB* pal) struct my_error_mgr *jerr; jpeg_init_info_t* init_info; - if (!MGUI_RWread (fp, magic, 2, 1)) - goto err; /* not JPEG image*/ - if (magic[0] != 0xFF || magic[1] != 0xD8) - goto err; /* not JPEG image*/ + if (!read_be16(fp,&soi_marker) || JMK_SOI != soi_marker) + goto err; /* not JPEG image*/ - magic_db = MGUI_ReadLE16 (fp); - MGUI_RWread (fp, magic, 2, 1); - - MGUI_RWread (fp, magic, 4, 1); - magic [4] = '\0'; - if (magic_db != 0xDBFF - && strncmp((char*)magic, "JFIF", 4) != 0 - && strncmp((char*)magic, "Exif", 4) != 0) - goto err; /* not JPEG image*/ - - MGUI_RWseek (fp, -10, SEEK_CUR); + MGUI_RWseek (fp, 0, SEEK_SET); /* Step 1: allocate and initialize JPEG decompression object */ cinfo = calloc (1, sizeof(struct jpeg_decompress_struct)); @@ -318,7 +335,10 @@ void* __mg_init_jpg (MG_RWops *fp, MYBITMAP* mybmp, RGB* pal) my_jpeg_data_src (cinfo, fp); /* Step 3: read file parameters with jpeg_read_header() */ - jpeg_read_header (cinfo, TRUE); + if(JPEG_HEADER_OK != jpeg_read_header (cinfo, TRUE)) + { + longjmp (jerr->setjmp_buffer, 1); + } /* Step 4: set parameters for decompression */ cinfo->out_color_space = (mybmp->flags & MYBMP_LOAD_GRAYSCALE) ? JCS_GRAYSCALE: JCS_RGB; @@ -453,27 +473,324 @@ int __mg_load_jpg (MG_RWops* fp, void* init_info, MYBITMAP *my_bmp, return ERR_BMP_OK; } + +/** + * loop read JPEG marker from MG_RWops object,until reach SOF0 or SOF2. + * return TRUE if match JPEG image format,or FALSE if the read failed or not JPEG image + */ BOOL __mg_check_jpg (MG_RWops* fp) { - unsigned char magic [5]; - Uint16 magic_db; + Uint16 jpeg_marker; + for (; read_be16 (fp, &jpeg_marker) /* read JPEG marker */;) { + /* payload length of current marker */ + Uint16 payload = 1; /* set 1 for default, mean that current marker followed by payload bytes*/ + switch (jpeg_marker) { + case JMK_SOI: + payload = 0; /* no payload */ + break; - if (!MGUI_RWread (fp, magic, 2, 1)) - return FALSE; /* not JPEG image*/ - if (magic[0] != 0xFF || magic[1] != 0xD8) - return FALSE; /* not JPEG image*/ + case JMK_SOF0: + case JMK_SOF2: + return TRUE; /* JPEG image*/ - magic_db = MGUI_ReadLE16 (fp); - MGUI_RWread (fp, magic, 2, 1); + case JMK_DHT: + case JMK_DQT: + case JMK_DRI: + case JMK_SOS: + case JMK_COM: + break; - MGUI_RWread (fp, magic, 4, 1); - magic [4] = '\0'; - if (magic_db != 0xDBFF - && strncmp((char*)magic, "JFIF", 4) != 0 - && strncmp((char*)magic, "Exif", 4) != 0) - return FALSE; /* not JPEG image*/ + case JMK_EOI: + return FALSE; /* not JPEG image*/ - return TRUE; + default: + if ((0XFFF8 & jpeg_marker) == JMK_RST_mask) { + payload = 0; /* RST0~7(FFD0~FFD7),no payload */ + } + else if ((0XFFF0 & jpeg_marker) == JMK_APP_mask) { + /* APP0~APP15,do nothing */ + } + else + return FALSE; /* not JPEG image*/ + + break; + } + + if (payload) { + /*read payload length and skip next marker */ + if (!read_be16 (fp, &payload)) + return FALSE; /* not JPEG image*/ + MGUI_RWseek (fp, payload - sizeof(payload), SEEK_CUR); + } + } + + return FALSE; /* not JPEG image*/ +} + +// color space conversion function type for one-row pixel of MYBITMAP +typedef BYTE* (*MYBITMAP_get_pixel_row)(unsigned int cinfo,MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer); + +// convert index(16) color pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_pal16(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + int i, j, end_i; + + BYTE* bits = mybmp->bits + mybmp->pitch * next_scanline; + RGB rgb0, rgb1; + for (i = 0, j = 0, end_i = (mybmp->w + 1) >> 1; i < end_i; ++i) { + + rgb0 = pal[ (bits[ i ] & 0XF0) >> 4 ]; + rgb1 = pal[ bits[ i ] & 0X0F ]; + + linebuffer[ j ++ ] = rgb0.r; + linebuffer[ j ++ ] = rgb0.g; + linebuffer[ j ++ ] = rgb0.b; + linebuffer[ j ++ ] = rgb1.r; + linebuffer[ j ++ ] = rgb1.g; + linebuffer[ j ++ ] = rgb1.b; + } + return linebuffer; + +} + +// convert index(256) color pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_pal256(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + int i, j; + BYTE* bits = mybmp->bits + mybmp->pitch * next_scanline; + RGB rgb; + + for (i = 0, j = 0; i < mybmp->w; i++) { + + rgb = pal [bits[i] ]; + + linebuffer[ j++ ] = rgb.r; + linebuffer[ j++ ] = rgb.g; + linebuffer[ j++ ] = rgb.b; + + } + return linebuffer; + +} + +#define RGB_FROM_RGB565(pixel, r, g, b) \ +{ \ + r = (((pixel&0xF800)>>11)<<3); \ + g = (((pixel&0x07E0)>>5)<<2); \ + b = ((pixel&0x001F)<<3); \ +} + +// convert RGB565 pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_RGB565(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + int i, j; + Uint16* bits = (Uint16*)(mybmp->bits + mybmp->pitch * next_scanline); + + for (i = 0, j = 0; i < mybmp->w; i++) { + RGB_FROM_RGB565(bits[i], linebuffer[ j ++ ], linebuffer[ j ++ ], linebuffer[ j ++ ]) + } + return linebuffer; + +} + +// convert RGB pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_RGB(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + return (JSAMPROW)(mybmp->bits + mybmp->pitch * next_scanline); +} + +// convert BGR pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_BGR(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + int i, end_i; + BYTE* bits = mybmp->bits + mybmp->pitch * next_scanline; + + for (i = 0, end_i = mybmp->w * 3; i < end_i; i += 3) { + linebuffer[ i ] = bits[ i + 2 ]; + linebuffer[ i + 1 ] = bits[ i + 1 ]; + linebuffer[ i + 2 ] = bits[ i ]; + } + return linebuffer; +} + +#ifndef _MGIMAGE_JPG_RGBA_BGCOLOR +/* background color for RGBA color space conversion,for example: 0xFF0000 is red */ +#define _MGIMAGE_JPG_RGBA_BGCOLOR 0xFFFFFF +#endif + +// convert RGBA pixel line to RGB +static BYTE* MYBITMAP_get_pixel_row_RGBA(unsigned int next_scanline, + MYBITMAP* mybmp,RGB* pal,BYTE* linebuffer) +{ + int i, j; + RGB* bits = (RGB*)(mybmp->bits + mybmp->pitch * next_scanline); + RGB pixel; + RGB bgcolor = { + (_MGIMAGE_JPG_RGBA_BGCOLOR >> 16) & 0xFF,/* red */ + (_MGIMAGE_JPG_RGBA_BGCOLOR >> 8) & 0xFF,/* green */ + _MGIMAGE_JPG_RGBA_BGCOLOR & 0xFF,/* blue */ + 0x00 /* alpha,no used */ + }; + + for (i = 0, j = 0; i < mybmp->w; i++, j += 3) { + pixel = bits[i]; + /* alpha composite, + * C = Cx * ALPHAx + (1 - ALPHAx) * Cbg + * see also : https://en.wikipedia.org/wiki/Alpha_compositing#Analytical_derivation_of_the_over_operator */ + linebuffer[ j ] = (JSAMPLE)((Uint32)pixel.r * pixel.a >> 8); /* red */ + linebuffer[ j + 1 ] = (JSAMPLE)((Uint32)pixel.g * pixel.a >> 8); /* green */ + linebuffer[ j + 2 ] = (JSAMPLE)((Uint32)pixel.b * pixel.a >> 8); /* blue */ + + linebuffer[ j ] += (JSAMPLE)((Uint32)bgcolor.r * (255 - pixel.a) >> 8); /* red + background color*/ + linebuffer[ j + 1 ] += (JSAMPLE)((Uint32)bgcolor.g * (255 - pixel.a) >> 8); /* green + background color */ + linebuffer[ j + 2 ] += (JSAMPLE)((Uint32)bgcolor.b * (255 - pixel.a) >> 8); /* blue + background color */ + } + return linebuffer; +} + +#ifndef _MGIMAGE_JPG_SAVE_QUALITY +#define _MGIMAGE_JPG_SAVE_QUALITY 90 +#endif + +int __mg_save_jpg (MG_RWops* fp, MYBITMAP* mybmp, RGB* pal) +{ + j_compress_ptr cinfo; + struct my_error_mgr *jerr; + JSAMPROW linebuffer = NULL; + JSAMPROW row_pointer[1]; + MYBITMAP_get_pixel_row get_row; + int mybmp_type; + int retcode = ERR_BMP_CANT_SAVE; + + /* Step 1: Allocate and initialize JPEG compression object */ + cinfo = calloc (1, sizeof(struct jpeg_compress_struct)); + if (NULL == cinfo) { + fprintf(stderr, "__fl_save_jpg allocation error!\n"); + return ERR_BMP_MEM; + } + jpeg_create_compress(cinfo); + + /* Step 2: Allocate and initialize my_error_mgr object by jpeg_memory_mgr,and init */ + jerr = cinfo->mem->alloc_small ((j_common_ptr) cinfo, JPOOL_IMAGE, sizeof(struct my_error_mgr)); + if (NULL == jerr) { + retcode = ERR_BMP_MEM; + goto do_finally; + } + memset (jerr, 0, sizeof(struct my_error_mgr)); + + /* We set up the normal JPEG error routines first. */ + cinfo->err = jpeg_std_error (&jerr->pub); + jerr->pub.error_exit = my_error_exit; + + /* Establish the setjmp return context for my_error_exit to use. */ + if (setjmp (jerr->setjmp_buffer)) { + fprintf(stderr, "__fl_save_jpg error!\n"); + goto do_finally; + } + /* not supported RWAREA_TYPE_MEM type, + * because the MEM type object can not dynamic allocate memory,so it's not safe */ + if(RWAREA_TYPE_STDIO != fp->type) { + fprintf(stderr, "unsupported type of MG_RWops,only support RWAREA_TYPE_STDIO so far\n"); + longjmp (jerr->setjmp_buffer, 1); + } + + /* Step 3: specify data source */ + jpeg_stdio_dest(cinfo, fp->hidden.stdio.fp); + + /* Step 4: initialize JPEG compression object */ + /* for JPEG compression, supported color space : JCS_GRAYSCALE,JCS_RGB,JCS_YCbCr,JCS_CMYK,JCS_YCCK + * in this case,MYBITMAP is base on RGB , + * we can select JCS_RGB only,so we must convert all color space (eg.RGBA,BGR,RGB565,...) to RGB + * */ + cinfo->in_color_space = JCS_RGB; + cinfo->image_width = mybmp->w; + cinfo->image_height = mybmp->h; + /* all of MYBMP_TYPE(eg.BRG,RGBA,RGB565...) will be converted to RGB,so input_components is constant 3 */ + cinfo->input_components = 3; + /* set jpeg compression parameters to default */ + jpeg_set_defaults(cinfo); + +#if _MGIMAGE_JPG_SAVE_QUALITY > 0 && _MGIMAGE_JPG_SAVE_QUALITY <= 100 + /* if _MGIMAGE_JPG_SAVE_QUALITY is valid value,use it + * otherwise use default value(75) of libjpeg, + * see also: libjpeg/jcparam.c jpeg_set_defaults function. + * */ + jpeg_set_quality(cinfo, _MGIMAGE_JPG_SAVE_QUALITY, TRUE); +#endif + + mybmp_type = mybmp->flags & MYBMP_TYPE_MASK; + + switch(mybmp->depth) { + case 4: + get_row = MYBITMAP_get_pixel_row_pal16; + break; + case 8: + get_row = MYBITMAP_get_pixel_row_pal256; + break; + case 16: + get_row = MYBITMAP_get_pixel_row_RGB565; + break; + case 24: + if(MYBMP_TYPE_RGB == mybmp_type) + get_row = MYBITMAP_get_pixel_row_RGB; + else + get_row = MYBITMAP_get_pixel_row_BGR; + break; + case 32: + get_row = MYBITMAP_get_pixel_row_RGBA; + break; + default: + fprintf(stderr, "invalid MYBITMAP.depth = %d\n",mybmp->depth); + longjmp (jerr->setjmp_buffer, 1); + break; + } + + if (mybmp->depth <= 8 && NULL == pal) { + fprintf(stderr, "the 'pal' argument must not be NULL for index color space\n"); + longjmp (jerr->setjmp_buffer, 1); + } + + if (24 == mybmp->depth && MYBMP_TYPE_RGB == mybmp_type) { + /* + * do nothing while RGB type, + * the MYBITMAP_get_pixel_row function will return address in MYBITMAP.bits data directly, + * without using line buffer + * */ + } + else { + /* Allocate one-row buffer for color space conversion(4 byte alignment) */ + linebuffer = (JSAMPROW)cinfo->mem->alloc_large + ((j_common_ptr) cinfo, JPOOL_IMAGE, + (((cinfo->image_width + 3) & ~3) * cinfo->input_components)); + if(NULL == linebuffer) + { + retcode = ERR_BMP_MEM; + fprintf(stderr, "libjpeg allocation error!\n"); + longjmp (jerr->setjmp_buffer, 1); + } + } + + /* Step 5: scan and compress line data */ + jpeg_start_compress(cinfo, TRUE); + while (cinfo->next_scanline < cinfo->image_height) { + /* get one line pixel data with RGB format from MYBITMAP object */ + row_pointer[0] = get_row(cinfo->next_scanline, mybmp, pal, linebuffer); + jpeg_write_scanlines(cinfo, row_pointer, 1); + } + + jpeg_finish_compress(cinfo); + retcode = ERR_BMP_OK; + +do_finally: + /* clean up the JPEG object, free the objects and return. */ + jpeg_destroy_compress (cinfo); + free (cinfo); + return retcode; } #endif /* _MGIMAGE_JPG */ diff --git a/src/mybmp/mybmp.c b/src/mybmp/mybmp.c index f4292ae8..82799214 100644 --- a/src/mybmp/mybmp.c +++ b/src/mybmp/mybmp.c @@ -80,8 +80,8 @@ static BITMAP_TYPE_INFO bitmap_types [MAX_BITMAP_TYPES] = { "gif", __mg_init_gif, __mg_load_gif, __mg_cleanup_gif, NULL, __mg_check_gif }, #endif #ifdef _MGIMAGE_JPG - { "jpg", __mg_init_jpg, __mg_load_jpg, __mg_cleanup_jpg, NULL, __mg_check_jpg }, - { "jpeg", __mg_init_jpg, __mg_load_jpg, __mg_cleanup_jpg, NULL, __mg_check_jpg }, + { "jpg", __mg_init_jpg, __mg_load_jpg, __mg_cleanup_jpg, __mg_save_jpg, __mg_check_jpg }, + { "jpeg", __mg_init_jpg, __mg_load_jpg, __mg_cleanup_jpg, __mg_save_jpg, __mg_check_jpg }, #endif #ifdef _MGIMAGE_PNG { "png", __mg_init_png, __mg_load_png, __mg_cleanup_png, NULL, __mg_check_png }, diff --git a/src/newgdi/bidi.c b/src/newgdi/bidi.c index 0294ebbd..48c282ac 100644 --- a/src/newgdi/bidi.c +++ b/src/newgdi/bidi.c @@ -940,24 +940,30 @@ int GUIAPI BIDIGetTextLogicalGlyphs( { int i = 0; int left_bytes = text_len; + int nr_chars; int prev_len = 0, len_cur_char = 0; const char* prev_mchar = NULL; Glyph32 glyph_value = INV_GLYPH_VALUE; Glyph32* glyph_string = NULL; GLYPHMAPINFO* map = NULL; - if(glyphs && *glyphs == NULL){ - *glyphs = malloc(text_len * sizeof (Glyph32)); - memset(*glyphs, 0, text_len * sizeof(Glyph32)); + /* use the actual characters count for optimized memory usage. */ + nr_chars = GetTextMCharInfo (log_font, text, text_len, NULL); + + if (glyphs && *glyphs == NULL){ + *glyphs = malloc (nr_chars * sizeof (Glyph32)); + memset (*glyphs, 0, nr_chars * sizeof(Glyph32)); } if(glyphs_map && *glyphs_map == NULL){ - *glyphs_map = malloc(text_len * sizeof (GLYPHMAPINFO)); - memset(*glyphs_map, 0, text_len * sizeof(GLYPHMAPINFO)); + *glyphs_map = malloc (nr_chars * sizeof (GLYPHMAPINFO)); + memset (*glyphs_map, 0, nr_chars * sizeof(GLYPHMAPINFO)); } - if(glyphs) glyph_string = *glyphs; - if(glyphs_map) map = *glyphs_map; - if(!map && !glyph_string) return 0; + + if (glyphs) glyph_string = *glyphs; + if (glyphs_map) map = *glyphs_map; + if (!map && !glyph_string) + return 0; while (left_bytes > 0){ len_cur_char = GetFirstMCharLen(log_font, text, left_bytes); @@ -979,6 +985,7 @@ int GUIAPI BIDIGetTextLogicalGlyphs( i ++; } + return i; } diff --git a/src/newgdi/tabbedtextout.c b/src/newgdi/tabbedtextout.c index cf086a99..edbb51b6 100644 --- a/src/newgdi/tabbedtextout.c +++ b/src/newgdi/tabbedtextout.c @@ -529,10 +529,9 @@ int GUIAPI GetTabbedTextExtentPoint (HDC hdc, const char* text, /* set size to zero first */ size->cx = size->cy = 0; - /* FIXME: use HDC property for BIDI enable or not - if (mbc_devfont && mbc_devfont->charset_ops->bidi_reorder) + /* This function does not support BIDI */ + if (mbc_devfont && pdc->bidi_flag && mbc_devfont->charset_ops->bidi_glyph_type) return -1; - */ _gdi_start_new_line (pdc); diff --git a/src/newgdi/textout.c b/src/newgdi/textout.c index 4aa51f7a..116d0b1d 100644 --- a/src/newgdi/textout.c +++ b/src/newgdi/textout.c @@ -462,10 +462,9 @@ int GUIAPI GetTextExtentPoint (HDC hdc, const char* text, int len, /* set size to zero first */ size->cx = size->cy = 0; - /* FIXME: use HDC property for BIDI enable or not - if (mbc_devfont && mbc_devfont->charset_ops->bidi_reorder) + /* This function does not support BIDI */ + if (mbc_devfont && pdc->bidi_flag && mbc_devfont->charset_ops->bidi_glyph_type) return -1; - */ _gdi_start_new_line(pdc); diff --git a/src/sysres/font/makefile.ng b/src/sysres/font/makefile.ng old mode 100755 new mode 100644