#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 );
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:
i = 0;
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_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;
}
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:
i = 0;
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_next4( PCMap4 cmap4,
UShort charCode,
UShort* id)
{
UShort segCount, nextCode;
UShort i;
TCMap4Segment seg4;
if ( charCode == 0xFFFF )
return -1;
segCount = cmap4->segCountX2 / 2;
for ( i = 0; i < segCount; i++ )
if ( charCode < cmap4->segments[i].endCount )
break;
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;
}
}
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;
}