Add support for cmap type 13.

* devel/ftoption.h, include/freetype/config/ftoption.h
(TT_CONFIG_CMAP_FORMAT_13): New macro.

* src/sfnt/ttcmap.c (TT_CMap13Rec, tt_cmap13_init,
tt_cmap13_validate, tt_cmap13_char_index, tt_cmap13_char_next,
tt_cmap13_get_info, tt_cmap13_char_map_def_binary,
tt_cmap14_class_rec): New functions and structures for cmap 13
support.
(tt_cmap_classes): Register tt_cmap13_class_rec.

* docs/CHANGES: Mention cmap 13 support.
This commit is contained in:
Werner Lemberg 2009-04-04 07:42:38 +02:00
parent 8566d4a096
commit ca98f8cc2b
5 changed files with 361 additions and 10 deletions

View File

@ -1,3 +1,19 @@
2009-04-04 Werner Lemberg <wl@gnu.org>
Add support for cmap type 13.
* devel/ftoption.h, include/freetype/config/ftoption.h
(TT_CONFIG_CMAP_FORMAT_13): New macro.
* src/sfnt/ttcmap.c (TT_CMap13Rec, tt_cmap13_init,
tt_cmap13_validate, tt_cmap13_char_index, tt_cmap13_char_next,
tt_cmap13_get_info, tt_cmap13_char_map_def_binary,
tt_cmap14_class_rec): New functions and structures for cmap 13
support.
(tt_cmap_classes): Register tt_cmap13_class_rec.
* docs/CHANGES: Mention cmap 13 support.
2009-04-01 Werner Lemberg <wl@gnu.org>
Ignore empty contours in CFF glyphs.

View File

@ -4,7 +4,7 @@
/* */
/* User-selectable configuration macros (specification only). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
/* Copyright 1996-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, */
@ -457,6 +457,7 @@ FT_BEGIN_HEADER
#define TT_CONFIG_CMAP_FORMAT_8
#define TT_CONFIG_CMAP_FORMAT_10
#define TT_CONFIG_CMAP_FORMAT_12
#define TT_CONFIG_CMAP_FORMAT_13
#define TT_CONFIG_CMAP_FORMAT_14

View File

@ -1,3 +1,13 @@
CHANGES BETWEEN 2.3.10 and 2.3.9
I. IMPORTANT CHANGES
- Support for the SFNT cmap 13 table format (as defined by the new
OpenType 1.6 specification) has been added.
======================================================================
CHANGES BETWEEN 2.3.9 and 2.3.8
I. IMPORTANT BUG FIXES

View File

@ -4,7 +4,7 @@
/* */
/* User-selectable configuration macros (specification only). */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
/* Copyright 1996-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, */
@ -457,6 +457,7 @@ FT_BEGIN_HEADER
#define TT_CONFIG_CMAP_FORMAT_8
#define TT_CONFIG_CMAP_FORMAT_10
#define TT_CONFIG_CMAP_FORMAT_12
#define TT_CONFIG_CMAP_FORMAT_13
#define TT_CONFIG_CMAP_FORMAT_14

View File

@ -157,7 +157,7 @@
FT_Byte* p = cmap->data + 4;
cmap_info->format = 0;
cmap_info->format = 0;
cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
return SFNT_Err_Ok;
@ -536,7 +536,7 @@
FT_Byte* p = cmap->data + 4;
cmap_info->format = 2;
cmap_info->format = 2;
cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
return SFNT_Err_Ok;
@ -1375,7 +1375,7 @@
FT_Byte* p = cmap->data + 4;
cmap_info->format = 4;
cmap_info->format = 4;
cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
return SFNT_Err_Ok;
@ -1537,7 +1537,7 @@
FT_Byte* p = cmap->data + 4;
cmap_info->format = 6;
cmap_info->format = 6;
cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
return SFNT_Err_Ok;
@ -1793,7 +1793,7 @@
FT_Byte* p = cmap->data + 8;
cmap_info->format = 8;
cmap_info->format = 8;
cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
return SFNT_Err_Ok;
@ -1945,7 +1945,7 @@
FT_Byte* p = cmap->data + 8;
cmap_info->format = 10;
cmap_info->format = 10;
cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
return SFNT_Err_Ok;
@ -2265,7 +2265,7 @@
FT_Byte* p = cmap->data + 8;
cmap_info->format = 12;
cmap_info->format = 12;
cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
return SFNT_Err_Ok;
@ -2293,6 +2293,325 @@
#endif /* TT_CONFIG_CMAP_FORMAT_12 */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FORMAT 13 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* TABLE OVERVIEW */
/* -------------- */
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
/* format 0 USHORT must be 13 */
/* reserved 2 USHORT reserved */
/* length 4 ULONG length in bytes */
/* language 8 ULONG Mac language code */
/* count 12 ULONG number of groups */
/* 16 */
/* */
/* This header is followed by `count' groups of the following format: */
/* */
/* start 0 ULONG first charcode */
/* end 4 ULONG last charcode */
/* glyphId 8 ULONG glyph ID for the whole group */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_13
typedef struct TT_CMap13Rec_
{
TT_CMapRec cmap;
FT_Bool valid;
FT_ULong cur_charcode;
FT_UInt cur_gindex;
FT_ULong cur_group;
FT_ULong num_groups;
} TT_CMap13Rec, *TT_CMap13;
FT_CALLBACK_DEF( FT_Error )
tt_cmap13_init( TT_CMap13 cmap,
FT_Byte* table )
{
cmap->cmap.data = table;
table += 12;
cmap->num_groups = FT_PEEK_ULONG( table );
cmap->valid = 0;
return SFNT_Err_Ok;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap13_validate( FT_Byte* table,
FT_Validator valid )
{
FT_Byte* p;
FT_ULong length;
FT_ULong num_groups;
if ( table + 16 > valid->limit )
FT_INVALID_TOO_SHORT;
p = table + 4;
length = TT_NEXT_ULONG( p );
p = table + 12;
num_groups = TT_NEXT_ULONG( p );
if ( length > (FT_ULong)( valid->limit - table ) ||
length < 16 + 12 * num_groups )
FT_INVALID_TOO_SHORT;
/* check groups, they must be in increasing order */
{
FT_ULong n, start, end, glyph_id, last = 0;
for ( n = 0; n < num_groups; n++ )
{
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
glyph_id = TT_NEXT_ULONG( p );
if ( start > end )
FT_INVALID_DATA;
if ( n > 0 && start <= last )
FT_INVALID_DATA;
if ( valid->level >= FT_VALIDATE_TIGHT )
{
if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
FT_INVALID_GLYPH_ID;
}
last = end;
}
}
return SFNT_Err_Ok;
}
/* search the index of the charcode next to cmap->cur_charcode */
/* cmap->cur_group should be set up properly by caller */
/* */
static void
tt_cmap13_next( TT_CMap13 cmap )
{
FT_Byte* p;
FT_ULong start, end, glyph_id, char_code;
FT_ULong n;
FT_UInt gindex;
if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
goto Fail;
char_code = cmap->cur_charcode + 1;
n = cmap->cur_group;
for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
{
p = cmap->cmap.data + 16 + 12 * n;
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
glyph_id = TT_PEEK_ULONG( p );
if ( char_code < start )
char_code = start;
if ( char_code <= end )
{
gindex = (FT_UInt)glyph_id;
if ( gindex )
{
cmap->cur_charcode = char_code;;
cmap->cur_gindex = gindex;
cmap->cur_group = n;
return;
}
}
}
Fail:
cmap->valid = 0;
}
static FT_UInt
tt_cmap13_char_map_binary( TT_CMap cmap,
FT_UInt32* pchar_code,
FT_Bool next )
{
FT_UInt gindex = 0;
FT_Byte* p = cmap->data + 12;
FT_UInt32 num_groups = TT_PEEK_ULONG( p );
FT_UInt32 char_code = *pchar_code;
FT_UInt32 start, end;
FT_UInt32 max, min, mid;
if ( !num_groups )
return 0;
/* make compiler happy */
mid = num_groups;
end = 0xFFFFFFFFUL;
if ( next )
char_code++;
min = 0;
max = num_groups;
/* binary search */
while ( min < max )
{
mid = ( min + max ) >> 1;
p = cmap->data + 16 + 12 * mid;
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
if ( char_code < start )
max = mid;
else if ( char_code > end )
min = mid + 1;
else
{
gindex = (FT_UInt)TT_PEEK_ULONG( p );
break;
}
}
if ( next )
{
TT_CMap13 cmap13 = (TT_CMap13)cmap;
/* if `char_code' is not in any group, then `mid' is */
/* the group nearest to `char_code' */
/* */
if ( char_code > end )
{
mid++;
if ( mid == num_groups )
return 0;
}
cmap13->valid = 1;
cmap13->cur_charcode = char_code;
cmap13->cur_group = mid;
if ( !gindex )
{
tt_cmap13_next( cmap13 );
if ( cmap13->valid )
gindex = cmap13->cur_gindex;
}
else
cmap13->cur_gindex = gindex;
if ( gindex )
*pchar_code = cmap13->cur_charcode;
}
return gindex;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap13_char_index( TT_CMap cmap,
FT_UInt32 char_code )
{
return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap13_char_next( TT_CMap cmap,
FT_UInt32 *pchar_code )
{
TT_CMap13 cmap13 = (TT_CMap13)cmap;
FT_ULong gindex;
if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
return 0;
/* no need to search */
if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
{
tt_cmap13_next( cmap13 );
if ( cmap13->valid )
{
gindex = cmap13->cur_gindex;
if ( gindex )
*pchar_code = cmap13->cur_charcode;
}
else
gindex = 0;
}
else
gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
return gindex;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap13_get_info( TT_CMap cmap,
TT_CMapInfo *cmap_info )
{
FT_Byte* p = cmap->data + 8;
cmap_info->format = 13;
cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
return SFNT_Err_Ok;
}
FT_CALLBACK_TABLE_DEF
const TT_CMap_ClassRec tt_cmap13_class_rec =
{
{
sizeof ( TT_CMap13Rec ),
(FT_CMap_InitFunc) tt_cmap13_init,
(FT_CMap_DoneFunc) NULL,
(FT_CMap_CharIndexFunc)tt_cmap13_char_index,
(FT_CMap_CharNextFunc) tt_cmap13_char_next,
NULL, NULL, NULL, NULL, NULL
},
13,
(TT_CMap_ValidateFunc) tt_cmap13_validate,
(TT_CMap_Info_GetFunc) tt_cmap13_get_info
};
#endif /* TT_CONFIG_CMAP_FORMAT_13 */
/*************************************************************************/
/*************************************************************************/
/***** *****/
@ -2553,7 +2872,7 @@
{
FT_UNUSED( cmap );
cmap_info->format = 14;
cmap_info->format = 14;
/* subtable 14 does not define a language field */
cmap_info->language = 0xFFFFFFFFUL;
@ -3062,6 +3381,10 @@
&tt_cmap12_class_rec,
#endif
#ifdef TT_CONFIG_CMAP_FORMAT_13
&tt_cmap13_class_rec,
#endif
#ifdef TT_CONFIG_CMAP_FORMAT_14
&tt_cmap14_class_rec,
#endif