Files
freetype/lib/extend/ftxcmap.c
2023-08-27 18:03:45 +02:00

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 */