FreeType 1.31.1
This commit is contained in:
386
test/arabic.c
Normal file
386
test/arabic.c
Normal file
@@ -0,0 +1,386 @@
|
||||
/****************************************************************************/
|
||||
/* */
|
||||
/* The FreeType project -- a free and portable quality TrueType renderer. */
|
||||
/* */
|
||||
/* Copyright 1996-1999 by */
|
||||
/* D. Turner, R.Wilhelm, and W. Lemberg */
|
||||
/* */
|
||||
/* arabic -- An implementation of the contextual algorithm given in the */
|
||||
/* Unicode 2.0 book to assign the `isolated', `initial', `medial', and */
|
||||
/* `final' properties to an input string of character codes for the Arabic */
|
||||
/* script. */
|
||||
/* */
|
||||
/****************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "arabic.h"
|
||||
#include "freetype.h"
|
||||
#include "ftxopen.h"
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Here a table of the joining classes for characters in the range
|
||||
U+0620 - U+06FF.
|
||||
|
||||
The following character also has a joining class:
|
||||
|
||||
U+200C ZERO WIDTH NON-JOINER -> causing
|
||||
|
||||
All other characters are given the joining class `none'.
|
||||
|
||||
*/
|
||||
|
||||
joining_class arabic[] =
|
||||
{
|
||||
/* U+0620 */
|
||||
none, none, right, right,
|
||||
right, right, dual, right,
|
||||
dual, right, dual, dual,
|
||||
dual, dual, dual, right,
|
||||
|
||||
/* U+0630 */
|
||||
right, right, right, dual,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, none,
|
||||
none, none, none, none,
|
||||
|
||||
/* U+0640 */
|
||||
causing, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
right, right, dual, transparent,
|
||||
transparent, transparent, transparent, transparent,
|
||||
|
||||
/* U+0650 */
|
||||
transparent, transparent, transparent, none,
|
||||
none, none, none, none,
|
||||
none, none, none, none,
|
||||
none, none, none, none,
|
||||
|
||||
/* U+0660 */
|
||||
none, none, none, none,
|
||||
none, none, none, none,
|
||||
none, none, none, none,
|
||||
none, none, none, none,
|
||||
|
||||
/* U+0670 */
|
||||
transparent, none, right, right,
|
||||
none, right, right, right,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
|
||||
/* U+0680 */
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
right, right, right, right,
|
||||
right, right, right, right,
|
||||
|
||||
/* U+0690 */
|
||||
right, right, right, right,
|
||||
right, right, right, right,
|
||||
right, right, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
|
||||
/* U+06A0 */
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
|
||||
/* U+06B0 */
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
dual, dual, dual, dual,
|
||||
|
||||
/* U+06C0 */
|
||||
right, dual, right, right,
|
||||
right, right, right, right,
|
||||
right, right, right, right,
|
||||
dual, right, dual, right,
|
||||
|
||||
/* U+06D0 */
|
||||
dual, dual, right, right,
|
||||
none, none, none, transparent,
|
||||
transparent, transparent, transparent, transparent,
|
||||
transparent, transparent, transparent, transparent,
|
||||
|
||||
/* U+06E0 */
|
||||
transparent, transparent, transparent, transparent,
|
||||
transparent, none, none, transparent,
|
||||
transparent, none, transparent, transparent,
|
||||
transparent, transparent, none, none,
|
||||
|
||||
/* U+06F0 */
|
||||
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 )
|
||||
{
|
||||
/* no Arabic font */
|
||||
*gdef = NULL;
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
/* sort it */
|
||||
|
||||
qsort( Arabic, num_glyphs, sizeof ( cgc ), compare_cgc );
|
||||
|
||||
/* write it to the arrays, removing duplicates */
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* The joining rules as given in the Unicode 2.0 book (characters are
|
||||
here specified as appearing in the byte stream, i.e. *not* in
|
||||
visual order). Joining classes are given in angle brackets, glyph
|
||||
forms in square brackets. Glyphs affected by a specific rule are
|
||||
enclosed with vertical bars.
|
||||
|
||||
Note: The description of the joining algorithm in the book is
|
||||
severely broken. You can get a corrected version from
|
||||
www.unicode.org (as of 29-Jun-1999, this hasn't appeared).
|
||||
|
||||
R1: <anything1> <transparent> <anything2>
|
||||
|
||||
apply joining rules for
|
||||
<anything1> <anything2> -> [shape1] [shape2]
|
||||
|
||||
-> [shape1] [isolated] [shape2]
|
||||
|
||||
R2: <causing|left|dual> |<right>|
|
||||
|
||||
-> [final]
|
||||
|
||||
R3: |<left>| <causing|right|dual>
|
||||
|
||||
-> [initial]
|
||||
|
||||
R4: <causing|left|dual> |<dual>| <causing|right|dual>
|
||||
|
||||
-> [medial]
|
||||
|
||||
R5: <causing|left|dual> |<dual>| <!(causing|right|dual)>
|
||||
|
||||
-> [final]
|
||||
|
||||
R6: <!(causing|left|dual)> |<dual>| <causing|right|dual>
|
||||
|
||||
-> [initial]
|
||||
|
||||
R7: If R1-R6 fail:
|
||||
|
||||
<anything> -> [isolated] */
|
||||
|
||||
|
||||
/* `direction' can be -1, 0, or 1 to indicate the last non-transparent
|
||||
glyph, the current glyph, and the next non-transparent glyph,
|
||||
respectively. */
|
||||
|
||||
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 );
|
||||
|
||||
/* R1 */
|
||||
|
||||
if ( current == transparent )
|
||||
{
|
||||
properties[i] |= isolated_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R2 */
|
||||
|
||||
if ( previous == causing ||
|
||||
previous == left ||
|
||||
previous == dual )
|
||||
if ( current == right )
|
||||
{
|
||||
properties[i] |= final_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R3 */
|
||||
|
||||
if ( current == left )
|
||||
if ( next == causing ||
|
||||
next == right ||
|
||||
next == dual )
|
||||
{
|
||||
properties[i] |= initial_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R4 */
|
||||
|
||||
if ( previous == causing ||
|
||||
previous == left ||
|
||||
previous == dual )
|
||||
if ( current == dual )
|
||||
if ( next == causing ||
|
||||
next == right ||
|
||||
next == dual )
|
||||
{
|
||||
properties[i] |= medial_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R5 */
|
||||
|
||||
if ( previous == causing ||
|
||||
previous == left ||
|
||||
previous == dual )
|
||||
if ( current == dual )
|
||||
if ( !( next == causing ||
|
||||
next == right ||
|
||||
next == dual ) )
|
||||
{
|
||||
properties[i] |= final_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R6 */
|
||||
|
||||
if ( !( previous == causing ||
|
||||
previous == left ||
|
||||
previous == dual ) )
|
||||
if ( current == dual )
|
||||
if ( next == causing ||
|
||||
next == right ||
|
||||
next == dual )
|
||||
{
|
||||
properties[i] |= initial_p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* R7 */
|
||||
|
||||
if ( current != none )
|
||||
properties[i] |= isolated_p;
|
||||
}
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
/* End */
|
||||
Reference in New Issue
Block a user