diff options
Diffstat (limited to 'src/freetype2/pshinter')
-rw-r--r-- | src/freetype2/pshinter/pshalgo.c | 93 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshalgo.h | 4 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshinter.c | 1 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshmod.c | 17 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshmod.h | 2 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshpic.c | 67 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshpic.h | 53 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshrec.c | 101 | ||||
-rw-r--r-- | src/freetype2/pshinter/pshrec.h | 6 |
9 files changed, 241 insertions, 103 deletions
diff --git a/src/freetype2/pshinter/pshalgo.c b/src/freetype2/pshinter/pshalgo.c index 505d95c..417dcee 100644 --- a/src/freetype2/pshinter/pshalgo.c +++ b/src/freetype2/pshinter/pshalgo.c @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (body). */ /* */ -/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ +/* Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used */ @@ -103,7 +103,7 @@ if ( idx >= table->max_hints ) { - FT_ERROR(( "psh_hint_table_record: invalid hint index %d\n", idx )); + FT_TRACE0(( "psh_hint_table_record: invalid hint index %d\n", idx )); return; } @@ -137,7 +137,7 @@ if ( table->num_hints < table->max_hints ) table->sort_global[table->num_hints++] = hint; else - FT_ERROR(( "psh_hint_table_record: too many sorted hints! BUG!\n" )); + FT_TRACE0(( "psh_hint_table_record: too many sorted hints! BUG!\n" )); } @@ -230,7 +230,7 @@ FT_UInt idx; - FT_ERROR(( "psh_hint_table_init: missing/incorrect hint masks!\n" )); + FT_TRACE0(( "psh_hint_table_init: missing/incorrect hint masks\n" )); count = table->max_hints; for ( idx = 0; idx < count; idx++ ) @@ -282,8 +282,8 @@ { hint2 = sort[0]; if ( psh_hint_overlap( hint, hint2 ) ) - FT_ERROR(( "psh_hint_table_activate_mask:" - " found overlapping hints\n" )) + FT_TRACE0(( "psh_hint_table_activate_mask:" + " found overlapping hints\n" )) } #else count2 = 0; @@ -295,8 +295,8 @@ if ( count < table->max_hints ) table->sort[count++] = hint; else - FT_ERROR(( "psh_hint_tableactivate_mask:" - " too many active hints\n" )); + FT_TRACE0(( "psh_hint_tableactivate_mask:" + " too many active hints\n" )); } } } @@ -898,7 +898,7 @@ #ifdef DEBUG_ZONES -#include <stdio.h> +#include FT_CONFIG_STANDARD_LIBRARY_H static void psh_print_zone( PSH_Zone zone ) @@ -2223,15 +2223,22 @@ FT_Fixed x_scale = dim_x->scale_mult; FT_Fixed y_scale = dim_y->scale_mult; + FT_Fixed old_x_scale = x_scale; + FT_Fixed old_y_scale = y_scale; + FT_Fixed scaled; FT_Fixed fitted; + FT_Bool rescale = FALSE; + scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale ); fitted = FT_PIX_ROUND( scaled ); if ( fitted != 0 && scaled != fitted ) { + rescale = TRUE; + y_scale = FT_MulDiv( y_scale, fitted, scaled ); if ( fitted < scaled ) @@ -2239,43 +2246,47 @@ psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 ); } - } - - glyph->do_horz_hints = 1; - glyph->do_vert_hints = 1; - - glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || - hint_mode == FT_RENDER_MODE_LCD ); - glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || - hint_mode == FT_RENDER_MODE_LCD_V ); + glyph->do_horz_hints = 1; + glyph->do_vert_hints = 1; - glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); + glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD ); - for ( dimension = 0; dimension < 2; dimension++ ) - { - /* load outline coordinates into glyph */ - psh_glyph_load_points( glyph, dimension ); - - /* compute local extrema */ - psh_glyph_compute_extrema( glyph ); - - /* compute aligned stem/hints positions */ - psh_hint_table_align_hints( &glyph->hint_tables[dimension], - glyph->globals, - dimension, - glyph ); + glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO || + hint_mode == FT_RENDER_MODE_LCD_V ); - /* find strong points, align them, then interpolate others */ - psh_glyph_find_strong_points( glyph, dimension ); - if ( dimension == 1 ) - psh_glyph_find_blue_points( &globals->blues, glyph ); - psh_glyph_interpolate_strong_points( glyph, dimension ); - psh_glyph_interpolate_normal_points( glyph, dimension ); - psh_glyph_interpolate_other_points( glyph, dimension ); + glyph->do_stem_adjust = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT ); - /* save hinted coordinates back to outline */ - psh_glyph_save_points( glyph, dimension ); + for ( dimension = 0; dimension < 2; dimension++ ) + { + /* load outline coordinates into glyph */ + psh_glyph_load_points( glyph, dimension ); + + /* compute local extrema */ + psh_glyph_compute_extrema( glyph ); + + /* compute aligned stem/hints positions */ + psh_hint_table_align_hints( &glyph->hint_tables[dimension], + glyph->globals, + dimension, + glyph ); + + /* find strong points, align them, then interpolate others */ + psh_glyph_find_strong_points( glyph, dimension ); + if ( dimension == 1 ) + psh_glyph_find_blue_points( &globals->blues, glyph ); + psh_glyph_interpolate_strong_points( glyph, dimension ); + psh_glyph_interpolate_normal_points( glyph, dimension ); + psh_glyph_interpolate_other_points( glyph, dimension ); + + /* save hinted coordinates back to outline */ + psh_glyph_save_points( glyph, dimension ); + + if ( rescale ) + psh_globals_set_scale( glyph->globals, + old_x_scale, old_y_scale, 0, 0 ); + } } Exit: diff --git a/src/freetype2/pshinter/pshalgo.h b/src/freetype2/pshinter/pshalgo.h index f68de71..1a248a7 100644 --- a/src/freetype2/pshinter/pshalgo.h +++ b/src/freetype2/pshinter/pshalgo.h @@ -4,7 +4,7 @@ /* */ /* PostScript hinting algorithm (specification). */ /* */ -/* Copyright 2001, 2002, 2003 by */ +/* Copyright 2001, 2002, 2003, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -32,7 +32,7 @@ FT_BEGIN_HEADER typedef struct PSH_HintRec_* PSH_Hint; /* hint bit-flags */ - typedef enum + typedef enum PSH_Hint_Flags_ { PSH_HINT_GHOST = PS_HINT_FLAG_GHOST, PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM, diff --git a/src/freetype2/pshinter/pshinter.c b/src/freetype2/pshinter/pshinter.c index 8e3f193..b35a2a9 100644 --- a/src/freetype2/pshinter/pshinter.c +++ b/src/freetype2/pshinter/pshinter.c @@ -19,6 +19,7 @@ #define FT_MAKE_OPTION_SINGLE_OBJECT #include <ft2build.h> +#include "pshpic.c" #include "pshrec.c" #include "pshglob.c" #include "pshalgo.c" diff --git a/src/freetype2/pshinter/pshmod.c b/src/freetype2/pshinter/pshmod.c index 4eb3d91..91da5d7 100644 --- a/src/freetype2/pshinter/pshmod.c +++ b/src/freetype2/pshinter/pshmod.c @@ -20,6 +20,7 @@ #include FT_INTERNAL_OBJECTS_H #include "pshrec.h" #include "pshalgo.h" +#include "pshpic.h" /* the Postscript Hinter module structure */ @@ -92,30 +93,26 @@ } - static - const PSHinter_Interface pshinter_interface = - { + FT_DEFINE_PSHINTER_INTERFACE(pshinter_interface, pshinter_get_globals_funcs, pshinter_get_t1_funcs, pshinter_get_t2_funcs - }; + ) - FT_CALLBACK_TABLE_DEF - const FT_Module_Class pshinter_module_class = - { + FT_DEFINE_MODULE(pshinter_module_class, + 0, sizeof ( PS_Hinter_ModuleRec ), "pshinter", 0x10000L, 0x20000L, - &pshinter_interface, /* module-specific interface */ + &FTPSHINTER_INTERFACE_GET, /* module-specific interface */ (FT_Module_Constructor)ps_hinter_init, (FT_Module_Destructor) ps_hinter_done, (FT_Module_Requester) 0 /* no additional interface for now */ - }; - + ) /* END */ diff --git a/src/freetype2/pshinter/pshmod.h b/src/freetype2/pshinter/pshmod.h index 1a91025..0ae7e96 100644 --- a/src/freetype2/pshinter/pshmod.h +++ b/src/freetype2/pshinter/pshmod.h @@ -27,7 +27,7 @@ FT_BEGIN_HEADER - FT_EXPORT_VAR( const FT_Module_Class ) pshinter_module_class; + FT_DECLARE_MODULE( pshinter_module_class ) FT_END_HEADER diff --git a/src/freetype2/pshinter/pshpic.c b/src/freetype2/pshinter/pshpic.c new file mode 100644 index 0000000..51a0879 --- /dev/null +++ b/src/freetype2/pshinter/pshpic.c @@ -0,0 +1,67 @@ +/***************************************************************************/ +/* */ +/* pshpic.c */ +/* */ +/* The FreeType position independent code services for pshinter module. */ +/* */ +/* Copyright 2009 by */ +/* Oran Agra and Mickey Gabel. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_INTERNAL_OBJECTS_H +#include "pshpic.h" + +#ifdef FT_CONFIG_OPTION_PIC + + /* forward declaration of PIC init functions from pshmod.c */ + void FT_Init_Class_pshinter_interface( FT_Library, PSHinter_Interface*); + + void + pshinter_module_class_pic_free( FT_Library library ) + { + FT_PIC_Container* pic_container = &library->pic_container; + FT_Memory memory = library->memory; + if ( pic_container->pshinter ) + { + FT_FREE( pic_container->pshinter ); + pic_container->pshinter = NULL; + } + } + + FT_Error + pshinter_module_class_pic_init( FT_Library library ) + { + FT_PIC_Container* pic_container = &library->pic_container; + FT_Error error = FT_Err_Ok; + PSHinterPIC* container; + FT_Memory memory = library->memory; + + /* allocate pointer, clear and set global container pointer */ + if ( FT_ALLOC ( container, sizeof ( *container ) ) ) + return error; + FT_MEM_SET( container, 0, sizeof(*container) ); + pic_container->pshinter = container; + + /* add call to initialization function when you add new scripts */ + FT_Init_Class_pshinter_interface(library, &container->pshinter_interface); + +/*Exit:*/ + if(error) + pshinter_module_class_pic_free(library); + return error; + } + + +#endif /* FT_CONFIG_OPTION_PIC */ + +/* END */ diff --git a/src/freetype2/pshinter/pshpic.h b/src/freetype2/pshinter/pshpic.h new file mode 100644 index 0000000..3555d8e --- /dev/null +++ b/src/freetype2/pshinter/pshpic.h @@ -0,0 +1,53 @@ +/***************************************************************************/ +/* */ +/* pshpic.h */ +/* */ +/* The FreeType position independent code services for pshinter module. */ +/* */ +/* Copyright 2009 by */ +/* Oran Agra and Mickey Gabel. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + + +#ifndef __PSHPIC_H__ +#define __PSHPIC_H__ + + +FT_BEGIN_HEADER + +#include FT_INTERNAL_PIC_H + +#ifndef FT_CONFIG_OPTION_PIC + +#define FTPSHINTER_INTERFACE_GET pshinter_interface + +#else /* FT_CONFIG_OPTION_PIC */ + +#include FT_INTERNAL_POSTSCRIPT_HINTS_H + + typedef struct PSHinterPIC_ + { + PSHinter_Interface pshinter_interface; + } PSHinterPIC; + +#define GET_PIC(lib) ((PSHinterPIC*)((lib)->pic_container.autofit)) +#define FTPSHINTER_INTERFACE_GET (GET_PIC(library)->pshinter_interface) + + +#endif /* FT_CONFIG_OPTION_PIC */ + + /* */ + +FT_END_HEADER + +#endif /* __PSHPIC_H__ */ + + +/* END */ diff --git a/src/freetype2/pshinter/pshrec.c b/src/freetype2/pshinter/pshrec.c index 2a885ef..0910cc5 100644 --- a/src/freetype2/pshinter/pshrec.c +++ b/src/freetype2/pshinter/pshrec.c @@ -4,7 +4,7 @@ /* */ /* FreeType PostScript hints recorder (body). */ /* */ -/* Copyright 2001, 2002, 2003, 2004, 2007 by */ +/* Copyright 2001, 2002, 2003, 2004, 2007, 2009 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -20,6 +20,8 @@ #include FT_FREETYPE_H #include FT_INTERNAL_OBJECTS_H #include FT_INTERNAL_DEBUG_H +#include FT_INTERNAL_CALC_H + #include "pshrec.h" #include "pshalgo.h" @@ -62,7 +64,7 @@ { FT_UInt old_max = table->max_hints; FT_UInt new_max = count; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; if ( new_max > old_max ) @@ -81,7 +83,7 @@ FT_Memory memory, PS_Hint *ahint ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; FT_UInt count; PS_Hint hint = 0; @@ -137,7 +139,7 @@ { FT_UInt old_max = ( mask->max_bits + 7 ) >> 3; FT_UInt new_max = ( count + 7 ) >> 3; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; if ( new_max > old_max ) @@ -184,7 +186,7 @@ FT_Int idx, FT_Memory memory ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; FT_Byte* p; @@ -234,7 +236,7 @@ { FT_UInt old_max = table->max_masks; FT_UInt new_max = count; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; if ( new_max > old_max ) @@ -254,7 +256,7 @@ PS_Mask *amask ) { FT_UInt count; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; PS_Mask mask = 0; @@ -285,7 +287,7 @@ FT_Memory memory, PS_Mask *amask ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; FT_UInt count; PS_Mask mask; @@ -314,7 +316,7 @@ FT_UInt bit_count, FT_Memory memory ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; PS_Mask mask; @@ -407,7 +409,7 @@ FT_Memory memory ) { FT_UInt temp; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; /* swap index1 and index2 so that index1 < index2 */ @@ -481,8 +483,8 @@ table->num_masks--; } else - FT_ERROR(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", - index1, index2 )); + FT_TRACE0(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n", + index1, index2 )); Exit: return error; @@ -497,7 +499,7 @@ FT_Memory memory ) { FT_Int index1, index2; - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; for ( index1 = table->num_masks - 1; index1 > 0; index1-- ) @@ -558,8 +560,8 @@ FT_UInt idx, FT_Memory memory ) { - PS_Mask mask; - FT_Error error = 0; + PS_Mask mask; + FT_Error error = PSH_Err_Ok; /* get last hint mask */ @@ -619,7 +621,7 @@ FT_UInt end_point, FT_Memory memory ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; /* reset current mask, if any */ @@ -644,7 +646,7 @@ FT_Memory memory, FT_Int *aindex ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; FT_UInt flags = 0; @@ -715,7 +717,7 @@ FT_Int hint3, FT_Memory memory ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; FT_UInt count = dim->counters.num_masks; PS_Mask counter = dim->counters.masks; @@ -789,7 +791,7 @@ ps_dimension_done( &hints->dimension[0], memory ); ps_dimension_done( &hints->dimension[1], memory ); - hints->error = 0; + hints->error = PSH_Err_Ok; hints->memory = 0; } @@ -800,7 +802,7 @@ { FT_MEM_ZERO( hints, sizeof ( *hints ) ); hints->memory = memory; - return 0; + return PSH_Err_Ok; } @@ -813,7 +815,7 @@ { case PS_HINT_TYPE_1: case PS_HINT_TYPE_2: - hints->error = 0; + hints->error = PSH_Err_Ok; hints->hint_type = hint_type; ps_dimension_init( &hints->dimension[0] ); @@ -824,7 +826,7 @@ hints->error = PSH_Err_Invalid_Argument; hints->hint_type = hint_type; - FT_ERROR(( "ps_hints_open: invalid charstring type!\n" )); + FT_TRACE0(( "ps_hints_open: invalid charstring type\n" )); break; } } @@ -842,8 +844,8 @@ /* limit "dimension" to 0..1 */ if ( dimension < 0 || dimension > 1 ) { - FT_ERROR(( "ps_hints_stem: invalid dimension (%d) used\n", - dimension )); + FT_TRACE0(( "ps_hints_stem: invalid dimension (%d) used\n", + dimension )); dimension = ( dimension != 0 ); } @@ -878,8 +880,8 @@ } default: - FT_ERROR(( "ps_hints_stem: called with invalid hint type (%d)\n", - hints->hint_type )); + FT_TRACE0(( "ps_hints_stem: called with invalid hint type (%d)\n", + hints->hint_type )); break; } } @@ -888,11 +890,11 @@ /* add one Type1 counter stem to the current hints table */ static void - ps_hints_t1stem3( PS_Hints hints, - FT_Int dimension, - FT_Long* stems ) + ps_hints_t1stem3( PS_Hints hints, + FT_Int dimension, + FT_Fixed* stems ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; if ( !hints->error ) @@ -906,8 +908,8 @@ /* limit "dimension" to 0..1 */ if ( dimension < 0 || dimension > 1 ) { - FT_ERROR(( "ps_hints_t1stem3: invalid dimension (%d) used\n", - dimension )); + FT_TRACE0(( "ps_hints_t1stem3: invalid dimension (%d) used\n", + dimension )); dimension = ( dimension != 0 ); } @@ -919,9 +921,10 @@ /* add the three stems to our hints/masks table */ for ( count = 0; count < 3; count++, stems += 2 ) { - error = ps_dimension_add_t1stem( - dim, (FT_Int)stems[0], (FT_Int)stems[1], - memory, &idx[count] ); + error = ps_dimension_add_t1stem( dim, + (FT_Int)FIXED_TO_INT( stems[0] ), + (FT_Int)FIXED_TO_INT( stems[1] ), + memory, &idx[count] ); if ( error ) goto Fail; } @@ -934,7 +937,7 @@ } else { - FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type!\n" )); + FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" )); error = PSH_Err_Invalid_Argument; goto Fail; } @@ -953,7 +956,7 @@ ps_hints_t1reset( PS_Hints hints, FT_UInt end_point ) { - FT_Error error = 0; + FT_Error error = PSH_Err_Ok; if ( !hints->error ) @@ -1008,8 +1011,8 @@ /* check bit count; must be equal to current total hint count */ if ( bit_count != count1 + count2 ) { - FT_ERROR(( "ps_hints_t2mask: " - "called with invalid bitcount %d (instead of %d)\n", + FT_TRACE0(( "ps_hints_t2mask:" + " called with invalid bitcount %d (instead of %d)\n", bit_count, count1 + count2 )); /* simply ignore the operator */ @@ -1053,8 +1056,8 @@ /* check bit count, must be equal to current total hint count */ if ( bit_count != count1 + count2 ) { - FT_ERROR(( "ps_hints_t2counter: " - "called with invalid bitcount %d (instead of %d)\n", + FT_TRACE0(( "ps_hints_t2counter:" + " called with invalid bitcount %d (instead of %d)\n", bit_count, count1 + count2 )); /* simply ignore the operator */ @@ -1124,11 +1127,17 @@ } static void - t1_hints_stem( T1_Hints hints, - FT_Int dimension, - FT_Long* coords ) + t1_hints_stem( T1_Hints hints, + FT_Int dimension, + FT_Fixed* coords ) { - ps_hints_stem( (PS_Hints)hints, dimension, 1, coords ); + FT_Pos stems[2]; + + + stems[0] = FIXED_TO_INT( coords[0] ); + stems[1] = FIXED_TO_INT( coords[1] ); + + ps_hints_stem( (PS_Hints)hints, dimension, 1, stems ); } @@ -1183,7 +1192,7 @@ for ( n = 0; n < count * 2; n++ ) { y += coords[n]; - stems[n] = ( y + 0x8000L ) >> 16; + stems[n] = FIXED_TO_INT( y ); } /* compute lengths */ diff --git a/src/freetype2/pshinter/pshrec.h b/src/freetype2/pshinter/pshrec.h index f7ef900..dcb3197 100644 --- a/src/freetype2/pshinter/pshrec.h +++ b/src/freetype2/pshinter/pshrec.h @@ -4,7 +4,7 @@ /* */ /* Postscript (Type1/Type2) hints recorder (specification). */ /* */ -/* Copyright 2001, 2002, 2003, 2006 by */ +/* Copyright 2001, 2002, 2003, 2006, 2008 by */ /* David Turner, Robert Wilhelm, and Werner Lemberg. */ /* */ /* This file is part of the FreeType project, and may only be used, */ @@ -52,7 +52,7 @@ FT_BEGIN_HEADER typedef struct PS_HintRec_* PS_Hint; /* hint types */ - typedef enum + typedef enum PS_Hint_Type_ { PS_HINT_TYPE_1 = 1, PS_HINT_TYPE_2 = 2 @@ -61,7 +61,7 @@ FT_BEGIN_HEADER /* hint flags */ - typedef enum + typedef enum PS_Hint_Flags_ { PS_HINT_FLAG_GHOST = 1, PS_HINT_FLAG_BOTTOM = 2 |