summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/psnames/psmodule.c
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/3rdparty/freetype/src/psnames/psmodule.c
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/3rdparty/freetype/src/psnames/psmodule.c')
-rw-r--r--src/3rdparty/freetype/src/psnames/psmodule.c590
1 files changed, 590 insertions, 0 deletions
diff --git a/src/3rdparty/freetype/src/psnames/psmodule.c b/src/3rdparty/freetype/src/psnames/psmodule.c
new file mode 100644
index 0000000000..41942a9b46
--- /dev/null
+++ b/src/3rdparty/freetype/src/psnames/psmodule.c
@@ -0,0 +1,590 @@
+/***************************************************************************/
+/* */
+/* psmodule.c */
+/* */
+/* PSNames module implementation (body). */
+/* */
+/* Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 by */
+/* David Turner, Robert Wilhelm, and Werner Lemberg. */
+/* */
+/* 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_INTERNAL_OBJECTS_H
+#include FT_SERVICE_POSTSCRIPT_CMAPS_H
+
+#include "psmodule.h"
+#include "pstables.h"
+
+#include "psnamerr.h"
+
+
+#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+
+
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+
+#define VARIANT_BIT 0x80000000UL
+#define BASE_GLYPH( code ) ( (code) & ~VARIANT_BIT )
+
+
+ /* Return the Unicode value corresponding to a given glyph. Note that */
+ /* we do deal with glyph variants by detecting a non-initial dot in */
+ /* the name, as in `A.swash' or `e.final'; in this case, the */
+ /* VARIANT_BIT is set in the return value. */
+ /* */
+ static FT_UInt32
+ ps_unicode_value( const char* glyph_name )
+ {
+ /* If the name begins with `uni', then the glyph name may be a */
+ /* hard-coded unicode character code. */
+ if ( glyph_name[0] == 'u' &&
+ glyph_name[1] == 'n' &&
+ glyph_name[2] == 'i' )
+ {
+ /* determine whether the next four characters following are */
+ /* hexadecimal. */
+
+ /* XXX: Add code to deal with ligatures, i.e. glyph names like */
+ /* `uniXXXXYYYYZZZZ'... */
+
+ FT_Int count;
+ FT_ULong value = 0;
+ const char* p = glyph_name + 3;
+
+
+ for ( count = 4; count > 0; count--, p++ )
+ {
+ char c = *p;
+ unsigned int d;
+
+
+ d = (unsigned char)c - '0';
+ if ( d >= 10 )
+ {
+ d = (unsigned char)c - 'A';
+ if ( d >= 6 )
+ d = 16;
+ else
+ d += 10;
+ }
+
+ /* Exit if a non-uppercase hexadecimal character was found */
+ /* -- this also catches character codes below `0' since such */
+ /* negative numbers cast to `unsigned int' are far too big. */
+ if ( d >= 16 )
+ break;
+
+ value = ( value << 4 ) + d;
+ }
+
+ /* there must be exactly four hex digits */
+ if ( count == 0 )
+ {
+ if ( *p == '\0' )
+ return value;
+ if ( *p == '.' )
+ return value | VARIANT_BIT;
+ }
+ }
+
+ /* If the name begins with `u', followed by four to six uppercase */
+ /* hexadecimal digits, it is a hard-coded unicode character code. */
+ if ( glyph_name[0] == 'u' )
+ {
+ FT_Int count;
+ FT_ULong value = 0;
+ const char* p = glyph_name + 1;
+
+
+ for ( count = 6; count > 0; count--, p++ )
+ {
+ char c = *p;
+ unsigned int d;
+
+
+ d = (unsigned char)c - '0';
+ if ( d >= 10 )
+ {
+ d = (unsigned char)c - 'A';
+ if ( d >= 6 )
+ d = 16;
+ else
+ d += 10;
+ }
+
+ if ( d >= 16 )
+ break;
+
+ value = ( value << 4 ) + d;
+ }
+
+ if ( count <= 2 )
+ {
+ if ( *p == '\0' )
+ return value;
+ if ( *p == '.' )
+ return value | VARIANT_BIT;
+ }
+ }
+
+ /* Look for a non-initial dot in the glyph name in order to */
+ /* find variants like `A.swash', `e.final', etc. */
+ {
+ const char* p = glyph_name;
+ const char* dot = NULL;
+
+
+ for ( ; *p; p++ )
+ {
+ if ( *p == '.' && p > glyph_name )
+ {
+ dot = p;
+ break;
+ }
+ }
+
+ /* now look up the glyph in the Adobe Glyph List */
+ if ( !dot )
+ return ft_get_adobe_glyph_index( glyph_name, p );
+ else
+ return ft_get_adobe_glyph_index( glyph_name, dot ) | VARIANT_BIT;
+ }
+ }
+
+
+ /* ft_qsort callback to sort the unicode map */
+ FT_CALLBACK_DEF( int )
+ compare_uni_maps( const void* a,
+ const void* b )
+ {
+ PS_UniMap* map1 = (PS_UniMap*)a;
+ PS_UniMap* map2 = (PS_UniMap*)b;
+ FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode );
+ FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode );
+
+
+ /* sort base glyphs before glyph variants */
+ if ( unicode1 == unicode2 )
+ {
+ if ( map1->unicode > map2->unicode )
+ return 1;
+ else if ( map1->unicode < map2->unicode )
+ return -1;
+ else
+ return 0;
+ }
+ else
+ {
+ if ( unicode1 > unicode2 )
+ return 1;
+ else if ( unicode1 < unicode2 )
+ return -1;
+ else
+ return 0;
+ }
+ }
+
+
+ /* support for extra glyphs not handled (well) in AGL; */
+ /* we add extra mappings for them if necessary */
+
+#define EXTRA_GLYPH_LIST_SIZE 10
+
+ static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
+ {
+ /* WGL 4 */
+ 0x0394,
+ 0x03A9,
+ 0x2215,
+ 0x00AD,
+ 0x02C9,
+ 0x03BC,
+ 0x2219,
+ 0x00A0,
+ /* Romanian */
+ 0x021A,
+ 0x021B
+ };
+
+ static const char ft_extra_glyph_names[] =
+ {
+ 'D','e','l','t','a',0,
+ 'O','m','e','g','a',0,
+ 'f','r','a','c','t','i','o','n',0,
+ 'h','y','p','h','e','n',0,
+ 'm','a','c','r','o','n',0,
+ 'm','u',0,
+ 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
+ 's','p','a','c','e',0,
+ 'T','c','o','m','m','a','a','c','c','e','n','t',0,
+ 't','c','o','m','m','a','a','c','c','e','n','t',0
+ };
+
+ static const FT_Int
+ ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
+ {
+ 0,
+ 6,
+ 12,
+ 21,
+ 28,
+ 35,
+ 38,
+ 53,
+ 59,
+ 72
+ };
+
+
+ static void
+ ps_check_extra_glyph_name( const char* gname,
+ FT_UInt glyph,
+ FT_UInt* extra_glyphs,
+ FT_UInt *states )
+ {
+ FT_UInt n;
+
+
+ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
+ {
+ if ( ft_strcmp( ft_extra_glyph_names +
+ ft_extra_glyph_name_offsets[n], gname ) == 0 )
+ {
+ if ( states[n] == 0 )
+ {
+ /* mark this extra glyph as a candidate for the cmap */
+ states[n] = 1;
+ extra_glyphs[n] = glyph;
+ }
+
+ return;
+ }
+ }
+ }
+
+
+ static void
+ ps_check_extra_glyph_unicode( FT_UInt32 uni_char,
+ FT_UInt *states )
+ {
+ FT_UInt n;
+
+
+ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
+ {
+ if ( uni_char == ft_extra_glyph_unicodes[n] )
+ {
+ /* disable this extra glyph from being added to the cmap */
+ states[n] = 2;
+
+ return;
+ }
+ }
+ }
+
+
+ /* Build a table that maps Unicode values to glyph indices. */
+ static FT_Error
+ ps_unicodes_init( FT_Memory memory,
+ PS_Unicodes table,
+ FT_UInt num_glyphs,
+ PS_GetGlyphNameFunc get_glyph_name,
+ PS_FreeGlyphNameFunc free_glyph_name,
+ FT_Pointer glyph_data )
+ {
+ FT_Error error;
+
+ FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
+
+
+ /* we first allocate the table */
+ table->num_maps = 0;
+ table->maps = 0;
+
+ if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
+ {
+ FT_UInt n;
+ FT_UInt count;
+ PS_UniMap* map;
+ FT_UInt32 uni_char;
+
+
+ map = table->maps;
+
+ for ( n = 0; n < num_glyphs; n++ )
+ {
+ const char* gname = get_glyph_name( glyph_data, n );
+
+
+ if ( gname )
+ {
+ ps_check_extra_glyph_name( gname, n,
+ extra_glyphs, extra_glyph_list_states );
+ uni_char = ps_unicode_value( gname );
+
+ if ( BASE_GLYPH( uni_char ) != 0 )
+ {
+ ps_check_extra_glyph_unicode( uni_char,
+ extra_glyph_list_states );
+ map->unicode = uni_char;
+ map->glyph_index = n;
+ map++;
+ }
+
+ if ( free_glyph_name )
+ free_glyph_name( glyph_data, gname );
+ }
+ }
+
+ for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
+ {
+ if ( extra_glyph_list_states[n] == 1 )
+ {
+ /* This glyph name has an additional representation. */
+ /* Add it to the cmap. */
+
+ map->unicode = ft_extra_glyph_unicodes[n];
+ map->glyph_index = extra_glyphs[n];
+ map++;
+ }
+ }
+
+ /* now compress the table a bit */
+ count = (FT_UInt)( map - table->maps );
+
+ if ( count == 0 )
+ {
+ FT_FREE( table->maps );
+ if ( !error )
+ error = PSnames_Err_Invalid_Argument; /* No unicode chars here! */
+ }
+ else {
+ /* Reallocate if the number of used entries is much smaller. */
+ if ( count < num_glyphs / 2 )
+ {
+ (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
+ error = PSnames_Err_Ok;
+ }
+
+ /* Sort the table in increasing order of unicode values, */
+ /* taking care of glyph variants. */
+ ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
+ compare_uni_maps );
+ }
+
+ table->num_maps = count;
+ }
+
+ return error;
+ }
+
+
+ static FT_UInt
+ ps_unicodes_char_index( PS_Unicodes table,
+ FT_UInt32 unicode )
+ {
+ PS_UniMap *min, *max, *mid, *result = NULL;
+
+
+ /* Perform a binary search on the table. */
+
+ min = table->maps;
+ max = min + table->num_maps - 1;
+
+ while ( min <= max )
+ {
+ FT_UInt32 base_glyph;
+
+
+ mid = min + ( ( max - min ) >> 1 );
+
+ if ( mid->unicode == unicode )
+ {
+ result = mid;
+ break;
+ }
+
+ base_glyph = BASE_GLYPH( mid->unicode );
+
+ if ( base_glyph == unicode )
+ result = mid; /* remember match but continue search for base glyph */
+
+ if ( min == max )
+ break;
+
+ if ( base_glyph < unicode )
+ min = mid + 1;
+ else
+ max = mid - 1;
+ }
+
+ if ( result )
+ return result->glyph_index;
+ else
+ return 0;
+ }
+
+
+ static FT_ULong
+ ps_unicodes_char_next( PS_Unicodes table,
+ FT_UInt32 *unicode )
+ {
+ FT_UInt result = 0;
+ FT_UInt32 char_code = *unicode + 1;
+
+
+ {
+ FT_UInt min = 0;
+ FT_UInt max = table->num_maps;
+ FT_UInt mid;
+ PS_UniMap* map;
+ FT_UInt32 base_glyph;
+
+
+ while ( min < max )
+ {
+ mid = min + ( ( max - min ) >> 1 );
+ map = table->maps + mid;
+
+ if ( map->unicode == char_code )
+ {
+ result = map->glyph_index;
+ goto Exit;
+ }
+
+ base_glyph = BASE_GLYPH( map->unicode );
+
+ if ( base_glyph == char_code )
+ result = map->glyph_index;
+
+ if ( base_glyph < char_code )
+ min = mid + 1;
+ else
+ max = mid;
+ }
+
+ if ( result )
+ goto Exit; /* we have a variant glyph */
+
+ /* we didn't find it; check whether we have a map just above it */
+ char_code = 0;
+
+ if ( min < table->num_maps )
+ {
+ map = table->maps + min;
+ result = map->glyph_index;
+ char_code = BASE_GLYPH( map->unicode );
+ }
+ }
+
+ Exit:
+ *unicode = char_code;
+ return result;
+ }
+
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+
+ static const char*
+ ps_get_macintosh_name( FT_UInt name_index )
+ {
+ if ( name_index >= FT_NUM_MAC_NAMES )
+ name_index = 0;
+
+ return ft_standard_glyph_names + ft_mac_names[name_index];
+ }
+
+
+ static const char*
+ ps_get_standard_strings( FT_UInt sid )
+ {
+ if ( sid >= FT_NUM_SID_NAMES )
+ return 0;
+
+ return ft_standard_glyph_names + ft_sid_names[sid];
+ }
+
+
+ static
+ const FT_Service_PsCMapsRec pscmaps_interface =
+ {
+#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
+
+ (PS_Unicode_ValueFunc) ps_unicode_value,
+ (PS_Unicodes_InitFunc) ps_unicodes_init,
+ (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
+ (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
+
+#else
+
+ 0,
+ 0,
+ 0,
+ 0,
+
+#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
+
+ (PS_Macintosh_NameFunc) ps_get_macintosh_name,
+ (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
+
+ t1_standard_encoding,
+ t1_expert_encoding
+ };
+
+
+ static const FT_ServiceDescRec pscmaps_services[] =
+ {
+ { FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface },
+ { NULL, NULL }
+ };
+
+
+ static FT_Pointer
+ psnames_get_service( FT_Module module,
+ const char* service_id )
+ {
+ FT_UNUSED( module );
+
+ return ft_service_list_lookup( pscmaps_services, service_id );
+ }
+
+#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
+
+
+
+ FT_CALLBACK_TABLE_DEF
+ const FT_Module_Class psnames_module_class =
+ {
+ 0, /* this is not a font driver, nor a renderer */
+ sizeof ( FT_ModuleRec ),
+
+ "psnames", /* driver name */
+ 0x10000L, /* driver version */
+ 0x20000L, /* driver requires FreeType 2 or above */
+
+#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
+ 0,
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) 0
+#else
+ (void*)&pscmaps_interface, /* module specific interface */
+ (FT_Module_Constructor)0,
+ (FT_Module_Destructor) 0,
+ (FT_Module_Requester) psnames_get_service
+#endif
+ };
+
+
+/* END */