2002-08-01 20:12:25 +00:00
/***************************************************************************
*
2013-04-15 23:54:51 +00:00
* Copyright ( C ) 1998 - 2013 , International Business Machines
2002-08-01 20:12:25 +00:00
* Corporation and others . All Rights Reserved .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-10-03 21:48:10 +00:00
2013-06-25 00:51:57 +00:00
# include "layout/LETypes.h"
# include "layout/LESwaps.h"
2001-10-03 21:48:10 +00:00
# include "sfnt.h"
# include "cmaps.h"
2013-04-15 23:54:51 +00:00
# include <stdio.h>
2001-10-03 21:48:10 +00:00
2002-12-24 17:15:36 +00:00
# define SWAPU16(code) ((LEUnicode16) SWAPW(code))
# define SWAPU32(code) ((LEUnicode32) SWAPL(code))
2001-10-03 21:48:10 +00:00
//
// Finds the high bit by binary searching
// through the bits in value.
//
le_int8 highBit ( le_uint32 value )
{
le_uint8 bit = 0 ;
if ( value > = 1 < < 16 ) {
value > > = 16 ;
bit + = 16 ;
}
if ( value > = 1 < < 8 ) {
value > > = 8 ;
bit + = 8 ;
}
if ( value > = 1 < < 4 ) {
value > > = 4 ;
bit + = 4 ;
}
if ( value > = 1 < < 2 ) {
value > > = 2 ;
bit + = 2 ;
}
if ( value > = 1 < < 1 ) {
value > > = 1 ;
bit + = 1 ;
}
return bit ;
}
CMAPMapper * CMAPMapper : : createUnicodeMapper ( const CMAPTable * cmap )
{
2002-04-02 02:55:31 +00:00
le_uint16 i ;
le_uint16 nSubtables = SWAPW ( cmap - > numberSubtables ) ;
const CMAPEncodingSubtable * subtable = NULL ;
2013-04-15 23:54:51 +00:00
le_bool found = FALSE ;
le_uint16 foundPlatformID = 0xFFFF ;
le_uint16 foundPlatformSpecificID = 0xFFFF ;
le_uint32 foundOffset = 0 ;
le_uint16 foundTable = 0xFFFF ;
// first pass, look for MS table. (preferred?)
for ( i = 0 ; i < nSubtables & & ! found ; i + = 1 ) {
2002-04-02 02:55:31 +00:00
const CMAPEncodingSubtableHeader * esh = & cmap - > encodingSubtableHeaders [ i ] ;
2013-04-15 23:54:51 +00:00
le_uint16 platformID = SWAPW ( esh - > platformID ) ;
le_uint16 platformSpecificID = SWAPW ( esh - > platformSpecificID ) ;
if ( platformID = = 3 ) { // microsoft
switch ( platformSpecificID ) {
case 1 : // Unicode BMP (UCS-2)
case 10 : // Unicode UCS-4
foundOffset = SWAPL ( esh - > encodingOffset ) ;
foundPlatformID = platformID ;
foundPlatformSpecificID = platformSpecificID ;
found = TRUE ;
foundTable = i ;
2002-04-02 02:55:31 +00:00
break ;
2013-04-15 23:54:51 +00:00
//default:
// printf("%s:%d: microsoft (3) platform specific ID %d (wanted 1 or 10) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformSpecificID)), i, nSubtables);
2002-04-02 02:55:31 +00:00
}
2013-04-15 23:54:51 +00:00
} else {
//printf("%s:%d: platform ID %d (wanted 3, microsoft) for subtable %d/%d\n", __FILE__, __LINE__, (SWAPW(esh->platformID)), i, nSubtables);
}
}
// second pass, allow non MS table
// first pass, look for MS table. (preferred?)
for ( i = 0 ; i < nSubtables & & ! found ; i + = 1 ) {
const CMAPEncodingSubtableHeader * esh = & cmap - > encodingSubtableHeaders [ i ] ;
le_uint16 platformID = SWAPW ( esh - > platformID ) ;
le_uint16 platformSpecificID = SWAPW ( esh - > platformSpecificID ) ;
//printf("%s:%d: table %d/%d has platform:specific %d:%d\n", __FILE__, __LINE__, i, nSubtables, platformID, platformSpecificID);
switch ( platformID ) {
case 0 : // Unicode platform
switch ( platformSpecificID ) {
case 0 :
case 1 :
case 2 :
case 3 :
foundOffset = SWAPL ( esh - > encodingOffset ) ;
foundPlatformID = platformID ;
foundPlatformSpecificID = platformSpecificID ;
foundTable = i ;
found = TRUE ;
break ;
default : printf ( " Error: table %d (psid %d) is unknown. Skipping. \n " , i , platformSpecificID ) ; break ;
}
break ;
//default:
//printf("Skipping platform id %d\n", platformID);
2002-04-02 02:55:31 +00:00
}
}
2013-04-15 23:54:51 +00:00
if ( found )
2002-04-02 02:55:31 +00:00
{
2013-04-15 23:54:51 +00:00
subtable = ( const CMAPEncodingSubtable * ) ( ( const char * ) cmap + foundOffset ) ;
//printf("%s:%d: using subtable #%d/%d type %d:%d\n", __FILE__, __LINE__, foundTable, nSubtables, foundPlatformID, foundPlatformSpecificID);
2002-04-02 02:55:31 +00:00
} else {
2013-04-15 23:54:51 +00:00
printf ( " %s:%d: could not find subtable. \n " , __FILE__ , __LINE__ ) ;
return NULL ;
2002-04-02 02:55:31 +00:00
}
2013-04-15 23:54:51 +00:00
le_uint16 tableFormat = SWAPW ( subtable - > format ) ;
//printf("%s:%d: table format %d\n", __FILE__, __LINE__, tableFormat);
switch ( tableFormat ) {
2002-04-02 02:55:31 +00:00
case 4 :
return new CMAPFormat4Mapper ( cmap , ( const CMAPFormat4Encoding * ) subtable ) ;
case 12 :
{
const CMAPFormat12Encoding * encoding = ( const CMAPFormat12Encoding * ) subtable ;
return new CMAPGroupMapper ( cmap , encoding - > groups , SWAPL ( encoding - > nGroups ) ) ;
}
default :
break ;
}
2013-04-15 23:54:51 +00:00
printf ( " %s:%d: Unknown format %x. \n " , __FILE__ , __LINE__ , ( SWAPW ( subtable - > format ) ) ) ;
2002-04-02 02:55:31 +00:00
return NULL ;
2001-10-03 21:48:10 +00:00
}
CMAPFormat4Mapper : : CMAPFormat4Mapper ( const CMAPTable * cmap , const CMAPFormat4Encoding * header )
2002-04-02 02:55:31 +00:00
: CMAPMapper ( cmap )
2001-10-03 21:48:10 +00:00
{
2002-04-02 02:55:31 +00:00
le_uint16 segCount = SWAPW ( header - > segCountX2 ) / 2 ;
fEntrySelector = SWAPW ( header - > entrySelector ) ;
fRangeShift = SWAPW ( header - > rangeShift ) / 2 ;
fEndCodes = & header - > endCodes [ 0 ] ;
fStartCodes = & header - > endCodes [ segCount + 1 ] ; // + 1 for reservedPad...
fIdDelta = & fStartCodes [ segCount ] ;
fIdRangeOffset = & fIdDelta [ segCount ] ;
2001-10-03 21:48:10 +00:00
}
LEGlyphID CMAPFormat4Mapper : : unicodeToGlyph ( LEUnicode32 unicode32 ) const
{
2002-04-02 02:55:31 +00:00
if ( unicode32 > = 0x10000 ) {
return 0 ;
}
LEUnicode16 unicode = ( LEUnicode16 ) unicode32 ;
le_uint16 index = 0 ;
le_uint16 probe = 1 < < fEntrySelector ;
2003-02-05 00:12:26 +00:00
TTGlyphID result = 0 ;
2002-04-02 02:55:31 +00:00
2002-12-24 17:15:36 +00:00
if ( SWAPU16 ( fStartCodes [ fRangeShift ] ) < = unicode ) {
2002-04-02 02:55:31 +00:00
index = fRangeShift ;
}
while ( probe > ( 1 < < 0 ) ) {
probe > > = 1 ;
2002-12-24 17:15:36 +00:00
if ( SWAPU16 ( fStartCodes [ index + probe ] ) < = unicode ) {
2002-04-02 02:55:31 +00:00
index + = probe ;
}
}
2002-12-24 17:15:36 +00:00
if ( unicode > = SWAPU16 ( fStartCodes [ index ] ) & & unicode < = SWAPU16 ( fEndCodes [ index ] ) ) {
2002-04-02 02:55:31 +00:00
if ( fIdRangeOffset [ index ] = = 0 ) {
2003-02-05 00:12:26 +00:00
result = ( TTGlyphID ) unicode ;
2002-04-02 02:55:31 +00:00
} else {
2002-12-24 17:15:36 +00:00
le_uint16 offset = unicode - SWAPU16 ( fStartCodes [ index ] ) ;
2002-04-02 02:55:31 +00:00
le_uint16 rangeOffset = SWAPW ( fIdRangeOffset [ index ] ) ;
le_uint16 * glyphIndexTable = ( le_uint16 * ) ( ( char * ) & fIdRangeOffset [ index ] + rangeOffset ) ;
result = SWAPW ( glyphIndexTable [ offset ] ) ;
}
result + = SWAPW ( fIdDelta [ index ] ) ;
} else {
result = 0 ;
}
2003-02-05 00:12:26 +00:00
return LE_SET_GLYPH ( 0 , result ) ;
2001-10-03 21:48:10 +00:00
}
CMAPFormat4Mapper : : ~ CMAPFormat4Mapper ( )
{
2002-04-02 02:55:31 +00:00
// parent destructor does it all
2001-10-03 21:48:10 +00:00
}
CMAPGroupMapper : : CMAPGroupMapper ( const CMAPTable * cmap , const CMAPGroup * groups , le_uint32 nGroups )
2002-04-02 02:55:31 +00:00
: CMAPMapper ( cmap ) , fGroups ( groups )
2001-10-03 21:48:10 +00:00
{
le_uint8 bit = highBit ( nGroups ) ;
fPower = 1 < < bit ;
fRangeOffset = nGroups - fPower ;
}
LEGlyphID CMAPGroupMapper : : unicodeToGlyph ( LEUnicode32 unicode32 ) const
{
le_int32 probe = fPower ;
le_int32 range = 0 ;
2002-12-24 17:15:36 +00:00
if ( SWAPU32 ( fGroups [ fRangeOffset ] . startCharCode ) < = unicode32 ) {
2001-10-03 21:48:10 +00:00
range = fRangeOffset ;
}
while ( probe > ( 1 < < 0 ) ) {
probe > > = 1 ;
2002-12-24 17:15:36 +00:00
if ( SWAPU32 ( fGroups [ range + probe ] . startCharCode ) < = unicode32 ) {
2001-10-03 21:48:10 +00:00
range + = probe ;
}
}
2002-12-24 17:15:36 +00:00
if ( SWAPU32 ( fGroups [ range ] . startCharCode ) < = unicode32 & & SWAPU32 ( fGroups [ range ] . endCharCode ) > = unicode32 ) {
return ( LEGlyphID ) ( SWAPU32 ( fGroups [ range ] . startGlyphCode ) + unicode32 - SWAPU32 ( fGroups [ range ] . startCharCode ) ) ;
2001-10-03 21:48:10 +00:00
}
return 0 ;
}
CMAPGroupMapper : : ~ CMAPGroupMapper ( )
{
2002-04-02 02:55:31 +00:00
// parent destructor does it all
2001-10-03 21:48:10 +00:00
}