348 lines
7.8 KiB
C
348 lines
7.8 KiB
C
/*******************************************************************
|
|
*
|
|
* ftxcmap.h 1.0
|
|
*
|
|
* API extension for iterating over Cmaps
|
|
*
|
|
* Copyright 1996-1999 by Juliusz Chroboczek,
|
|
* 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 "ftxcmap.h"
|
|
|
|
#include "tttypes.h"
|
|
#include "ttobjs.h"
|
|
#include "tttables.h"
|
|
|
|
static Long charmap_first4 ( PCMap4, UShort* );
|
|
static Long charmap_next4 ( PCMap4, UShort, UShort* );
|
|
static Long charmap_last4 ( PCMap4, UShort* );
|
|
static UShort charmap_find_id4( PCMap4, UShort, TCMap4Segment*, UShort );
|
|
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Function : TT_CharMap_First
|
|
*
|
|
* Description : Returns the first valid character code in a
|
|
* given character map. Also returns the corresponding
|
|
* glyph index.
|
|
*
|
|
* Input : charMap handle to the target character map
|
|
* id address where the glyph index will be
|
|
* be returned in case of success
|
|
*
|
|
* Output : First valid character code. -1 in case of failure.
|
|
*
|
|
* Notes :
|
|
*
|
|
******************************************************************/
|
|
|
|
EXPORT_FUNC
|
|
TT_Long TT_CharMap_First( TT_CharMap charMap,
|
|
TT_UShort* id )
|
|
{
|
|
PCMapTable cmap;
|
|
UShort i, c;
|
|
|
|
|
|
if ( !( cmap = HANDLE_CharMap( charMap ) ) )
|
|
return -1;
|
|
|
|
switch ( cmap->format )
|
|
{
|
|
case 0:
|
|
if ( id )
|
|
*id = cmap->c.cmap0.glyphIdArray[0];
|
|
return 0;
|
|
|
|
case 4:
|
|
return charmap_first4( &cmap->c.cmap4, id );
|
|
|
|
case 6:
|
|
if ( cmap->c.cmap6.entryCount < 1 )
|
|
return -1;
|
|
|
|
if ( id )
|
|
*id = cmap->c.cmap6.glyphIdArray[0];
|
|
return cmap->c.cmap6.firstCode;
|
|
|
|
default:
|
|
/* Now loop from 0 to 65535. We can't use a simple "for' on */
|
|
/* 16-bits systems, hence the "strange" loop here.. */
|
|
i = 0;
|
|
do
|
|
{
|
|
c = TT_Char_Index( charMap, i );
|
|
if ( c > 0 )
|
|
{
|
|
if ( id )
|
|
*id = c;
|
|
return i;
|
|
}
|
|
i++;
|
|
} while ( i != 0 ); /* because i is UShort! */
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
static Long charmap_first4( PCMap4 cmap4,
|
|
UShort* id )
|
|
{
|
|
UShort firstCode;
|
|
|
|
|
|
if ( cmap4->segCountX2 / 2 < 1 )
|
|
return -1;
|
|
|
|
firstCode = cmap4->segments[0].startCount;
|
|
|
|
if ( id )
|
|
*id = charmap_find_id4( cmap4, firstCode, &(cmap4->segments[0]), 0 );
|
|
|
|
return firstCode;
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Function : TT_CharMap_Next
|
|
*
|
|
* Description : Returns the next valid character code in a given
|
|
* charMap.
|
|
*
|
|
* Input : charMap handle to the target char. map
|
|
* index starting character code
|
|
* id address where the glyph index of the next
|
|
* character will be returned
|
|
*
|
|
* Output : Next valid character code after 'index'. -1 in case
|
|
* of failure.
|
|
*
|
|
* Notes :
|
|
*
|
|
******************************************************************/
|
|
|
|
EXPORT_FUNC
|
|
TT_Long TT_CharMap_Next( TT_CharMap charMap,
|
|
TT_UShort index,
|
|
TT_UShort* id )
|
|
{
|
|
PCMapTable cmap;
|
|
UShort i, c;
|
|
|
|
|
|
cmap = HANDLE_CharMap( charMap );
|
|
if ( !cmap )
|
|
return -1;
|
|
|
|
switch ( cmap->format )
|
|
{
|
|
case 0:
|
|
if ( index < 255 )
|
|
{
|
|
if ( id )
|
|
*id = cmap->c.cmap0.glyphIdArray[index + 1];
|
|
return index + 1;
|
|
}
|
|
else
|
|
return -1;
|
|
|
|
case 4:
|
|
return charmap_next4( &cmap->c.cmap4, index, id );
|
|
|
|
case 6:
|
|
{
|
|
UShort firstCode = cmap->c.cmap6.firstCode;
|
|
|
|
|
|
if ( index + 1 < firstCode + cmap->c.cmap6.entryCount )
|
|
{
|
|
if ( id )
|
|
*id = cmap->c.cmap6.glyphIdArray[index + 1 - firstCode];
|
|
return index + 1;
|
|
}
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
default:
|
|
/* Now loop from 0 to 65535. We can't use a simple "for" on */
|
|
/* 16-bits systems, hence the "strange" loop here.. */
|
|
i = 0;
|
|
do
|
|
{
|
|
c = TT_Char_Index( charMap, i );
|
|
if ( c > 0 )
|
|
{
|
|
if ( id )
|
|
*id = c;
|
|
return i;
|
|
}
|
|
i++;
|
|
} while ( i != 0 ); /* because i is UShort! */
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
static Long charmap_next4( PCMap4 cmap4,
|
|
UShort charCode,
|
|
UShort* id)
|
|
{
|
|
UShort segCount, nextCode;
|
|
UShort i;
|
|
TCMap4Segment seg4;
|
|
|
|
|
|
if ( charCode == 0xFFFF )
|
|
return -1; /* get it out of the way now */
|
|
|
|
segCount = cmap4->segCountX2 / 2;
|
|
|
|
for ( i = 0; i < segCount; i++ )
|
|
if ( charCode < cmap4->segments[i].endCount )
|
|
break;
|
|
|
|
/* Safety check - even though the last endCount should be 0xFFFF */
|
|
if ( i >= segCount )
|
|
return -1;
|
|
|
|
seg4 = cmap4->segments[i];
|
|
|
|
if ( charCode < seg4.startCount )
|
|
nextCode = seg4.startCount;
|
|
else
|
|
nextCode = charCode + 1;
|
|
|
|
if ( id )
|
|
*id = charmap_find_id4( cmap4, nextCode, &seg4, i );
|
|
|
|
return nextCode;
|
|
}
|
|
|
|
|
|
static UShort
|
|
charmap_find_id4( PCMap4 cmap4,
|
|
UShort charCode,
|
|
TCMap4Segment* seg4,
|
|
UShort i )
|
|
{
|
|
UShort index1;
|
|
|
|
|
|
if ( seg4->idRangeOffset == 0 )
|
|
return (charCode + seg4->idDelta) & 0xFFFF;
|
|
else
|
|
{
|
|
index1 = seg4->idRangeOffset / 2 + charCode-seg4->startCount -
|
|
( cmap4->segCountX2 / 2 - i );
|
|
|
|
if ( index1 >= cmap4->numGlyphId || cmap4->glyphIdArray[index1] == 0 )
|
|
return 0;
|
|
else
|
|
return (cmap4->glyphIdArray[index1] + seg4->idDelta) & 0xFFFF;
|
|
}
|
|
}
|
|
|
|
|
|
/*******************************************************************
|
|
*
|
|
* Function : TT_CharMap_Last
|
|
*
|
|
* Description : Returns the last valid character code in a
|
|
* given character map. Also returns the corresponding
|
|
* glyph index.
|
|
*
|
|
* Input : charMap handle to the target character map
|
|
* id address where the glyph index will be
|
|
* be returned in case of success
|
|
*
|
|
* Output : Last valid character code. -1 in case of failure.
|
|
*
|
|
* Notes :
|
|
*
|
|
******************************************************************/
|
|
|
|
EXPORT_FUNC
|
|
TT_Long TT_CharMap_Last( TT_CharMap charMap,
|
|
TT_UShort* id )
|
|
{
|
|
PCMapTable cmap;
|
|
UShort i, c;
|
|
|
|
|
|
if ( !( cmap = HANDLE_CharMap( charMap ) ) )
|
|
return -1;
|
|
|
|
switch ( cmap->format )
|
|
{
|
|
case 0:
|
|
if ( id )
|
|
*id = cmap->c.cmap0.glyphIdArray[255];
|
|
return 255;
|
|
|
|
case 4:
|
|
return charmap_last4( &cmap->c.cmap4, id );
|
|
|
|
case 6:
|
|
if ( cmap->c.cmap6.entryCount < 1 )
|
|
return -1;
|
|
|
|
if ( id )
|
|
*id = cmap->c.cmap6.glyphIdArray[cmap->c.cmap6.entryCount - 1];
|
|
return cmap->c.cmap6.firstCode + cmap->c.cmap6.entryCount - 1;
|
|
|
|
default:
|
|
i = 65535;
|
|
do
|
|
{
|
|
c = TT_Char_Index( charMap, i );
|
|
if ( c > 0 )
|
|
{
|
|
if ( id )
|
|
*id = c;
|
|
return i;
|
|
}
|
|
i--;
|
|
} while ( i != 0 );
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
static Long charmap_last4( PCMap4 cmap4,
|
|
UShort* id )
|
|
{
|
|
UShort lastCode;
|
|
|
|
|
|
if ( cmap4->segCountX2 / 2 < 1 )
|
|
return -1;
|
|
|
|
lastCode = cmap4->segments[cmap4->segCountX2 / 2 - 1].endCount;
|
|
|
|
if ( id )
|
|
*id = charmap_find_id4( cmap4,
|
|
lastCode,
|
|
&(cmap4->segments[cmap4->segCountX2 / 2 - 1]),
|
|
0 );
|
|
|
|
return lastCode;
|
|
}
|
|
|
|
|
|
/* END */
|