#include <stdio.h>
#include <stdlib.h>
#include "arabic.h"
#include "freetype.h"
#include "ftxopen.h"
joining_class arabic[] =
{
none, none, right, right,
right, right, dual, right,
dual, right, dual, dual,
dual, dual, dual, right,
right, right, right, dual,
dual, dual, dual, dual,
dual, dual, dual, none,
none, none, none, none,
causing, dual, dual, dual,
dual, dual, dual, dual,
right, right, dual, transparent,
transparent, transparent, transparent, transparent,
transparent, transparent, transparent, none,
none, none, none, none,
none, none, none, none,
none, none, none, none,
none, none, none, none,
none, none, none, none,
none, none, none, none,
none, none, none, none,
transparent, none, right, right,
none, right, right, right,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
right, right, right, right,
right, right, right, right,
right, right, right, right,
right, right, right, right,
right, right, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
dual, dual, dual, dual,
right, dual, right, right,
right, right, right, right,
right, right, right, right,
dual, right, dual, right,
dual, dual, right, right,
none, none, none, transparent,
transparent, transparent, transparent, transparent,
transparent, transparent, transparent, transparent,
transparent, transparent, transparent, transparent,
transparent, none, none, transparent,
transparent, none, transparent, transparent,
transparent, transparent, none, none,
none, none, none, none,
none, none, none, none,
none, none, dual, dual,
dual, none, none, none
};
struct cgc_
{
TT_UShort char_code;
TT_UShort glyph_index;
TT_UShort class;
};
typedef struct cgc_ cgc;
int compare_cgc( const void* a,
const void* b )
{
return ( ((cgc*)a)->glyph_index > ((cgc*)b)->glyph_index ) ?
1 : ( ( ((cgc*)a)->glyph_index == ((cgc*)b)->glyph_index ) ?
0 : -1 );
}
TT_Error Build_Arabic_Glyph_Properties( TT_CharMap char_map,
TT_UShort max_glyphs,
TTO_GDEFHeader** gdef )
{
TT_UShort i, j, num_glyphs;
cgc Arabic[0x0700 - 0x0620];
TT_UShort glyph_indices[0x700 - 0x0620];
TT_UShort classes[0x700 - 0x0620];
if ( !gdef )
return TT_Err_Invalid_Argument;
j = 0;
for ( i = 0x0620; i < 0x0700; i++ )
{
Arabic[j].char_code = i;
Arabic[j].class = ( arabic[i - 0x0620] == transparent ) ?
MARK_GLYPH : SIMPLE_GLYPH;
Arabic[j].glyph_index = TT_Char_Index( char_map, i );
if ( Arabic[j].glyph_index )
j++;
}
num_glyphs = j;
if ( !num_glyphs )
{
*gdef = NULL;
return TT_Err_Ok;
}
qsort( Arabic, num_glyphs, sizeof ( cgc ), compare_cgc );
glyph_indices[0] = Arabic[0].glyph_index;
classes[0] = Arabic[0].class;
j = 1;
for ( i = 1; i < num_glyphs; i++ )
{
glyph_indices[j] = Arabic[i].glyph_index;
classes[j] = Arabic[i].class;
if ( glyph_indices[j - 1] != glyph_indices[j] )
j++;
}
num_glyphs = j;
TT_GDEF_Build_ClassDefinition( *gdef, max_glyphs, num_glyphs,
glyph_indices, classes );
return TT_Err_Ok;
}
static joining_class Get_Joining_Class( TT_UShort* string,
TT_UShort pos,
TT_UShort length,
int direction )
{
joining_class j;
while ( 1 )
{
if ( pos == 0 && direction < 0 )
return none;
pos += direction;
if ( pos >= length )
return none;
if ( string[pos] < 0x0620 ||
string[pos] >= 0x0700 )
{
if ( string[pos] == 0x200C )
return causing;
else
return none;
}
else
j = arabic[string[pos] - 0x0620];
if ( !direction || j != transparent )
return j;
}
}
TT_Error Assign_Arabic_Properties( TT_UShort* string,
TT_UShort* properties,
TT_UShort length )
{
joining_class previous, current, next;
TT_UShort i;
if ( !string || !properties || length == 0 )
return TT_Err_Invalid_Argument;
for ( i = 0; i < length; i++ )
{
previous = Get_Joining_Class( string, i, length, -1 );
current = Get_Joining_Class( string, i, length, 0 );
next = Get_Joining_Class( string, i, length, 1 );
if ( current == transparent )
{
properties[i] |= isolated_p;
continue;
}
if ( previous == causing ||
previous == left ||
previous == dual )
if ( current == right )
{
properties[i] |= final_p;
continue;
}
if ( current == left )
if ( next == causing ||
next == right ||
next == dual )
{
properties[i] |= initial_p;
continue;
}
if ( previous == causing ||
previous == left ||
previous == dual )
if ( current == dual )
if ( next == causing ||
next == right ||
next == dual )
{
properties[i] |= medial_p;
continue;
}
if ( previous == causing ||
previous == left ||
previous == dual )
if ( current == dual )
if ( !( next == causing ||
next == right ||
next == dual ) )
{
properties[i] |= final_p;
continue;
}
if ( !( previous == causing ||
previous == left ||
previous == dual ) )
if ( current == dual )
if ( next == causing ||
next == right ||
next == dual )
{
properties[i] |= initial_p;
continue;
}
if ( current != none )
properties[i] |= isolated_p;
}
return TT_Err_Ok;
}