[autofit] Rewrite HarfBuzz interface to support character clusters.
Scripts like Khmer have blue zones that can't be directly represented by Unicode characters. Instead, it is necessary to let HarfBuzz convert character clusters into proper glyph representation forms, then deriving the blue zone information from the resulting glyphs. * src/autofit/hbshim.c, src/autofit/hbshim.h: Replaced by... * src/autofit/afshaper.c, src/autofit/afshaper.h: ... these two new files, providing a new API to access HarfBuzz. The new API manages a HarfBuzz buffer with `af_shaper_buf_create' and `af_shaper_buf_destroy'. The buffer receives a UTF8 encoded string with function `af_shaper_get_cluster', and the resulting glyph data (indices, advance widths, vertical offsets) can be iteratively accessed with function `af_shaper_get_elem'. * src/autofit/afcjk.c (af_cjk_metrics_init_widths, af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated. * src/autofit/aflatin.c (af_latin_metrics_init_widths, af_latin_metrics_init_blues, af_latin_metrics_check_digits): Updated. * include/freetype/internal/fttrace.h: s/afharfbuzz/afshaper/. * src/autofit/afglobal.c: s/hbshim.h/afshaper.h/. (af_face_globals_compute_style_coverage): Updated. * src/autofit/afglocal.h: s/hbshim.h/afshaper.h/. * src/autofit/autofit.c: s/hbshim.c/afshaper.c/. * src/autofit/Jamfile, src/autofit/rules.mk (AUTOF_DRV_SRC): Updated.
This commit is contained in:
parent
de5999411a
commit
24aa9c665e
39
ChangeLog
39
ChangeLog
|
@ -1,3 +1,42 @@
|
||||||
|
2015-12-06 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
|
[autofit] Rewrite HarfBuzz interface to support character clusters.
|
||||||
|
|
||||||
|
Scripts like Khmer have blue zones that can't be directly
|
||||||
|
represented by Unicode characters. Instead, it is necessary to let
|
||||||
|
HarfBuzz convert character clusters into proper glyph representation
|
||||||
|
forms, then deriving the blue zone information from the resulting
|
||||||
|
glyphs.
|
||||||
|
|
||||||
|
* src/autofit/hbshim.c, src/autofit/hbshim.h: Replaced by...
|
||||||
|
* src/autofit/afshaper.c, src/autofit/afshaper.h: ... these two new
|
||||||
|
files, providing a new API to access HarfBuzz.
|
||||||
|
|
||||||
|
The new API manages a HarfBuzz buffer with `af_shaper_buf_create'
|
||||||
|
and `af_shaper_buf_destroy'. The buffer receives a UTF8 encoded
|
||||||
|
string with function `af_shaper_get_cluster', and the resulting
|
||||||
|
glyph data (indices, advance widths, vertical offsets) can be
|
||||||
|
iteratively accessed with function `af_shaper_get_elem'.
|
||||||
|
|
||||||
|
* src/autofit/afcjk.c (af_cjk_metrics_init_widths,
|
||||||
|
af_cjk_metrics_init_blues, af_cjk_metrics_check_digits): Updated.
|
||||||
|
|
||||||
|
* src/autofit/aflatin.c (af_latin_metrics_init_widths,
|
||||||
|
af_latin_metrics_init_blues, af_latin_metrics_check_digits):
|
||||||
|
Updated.
|
||||||
|
|
||||||
|
* include/freetype/internal/fttrace.h: s/afharfbuzz/afshaper/.
|
||||||
|
|
||||||
|
* src/autofit/afglobal.c: s/hbshim.h/afshaper.h/.
|
||||||
|
(af_face_globals_compute_style_coverage): Updated.
|
||||||
|
|
||||||
|
* src/autofit/afglocal.h: s/hbshim.h/afshaper.h/.
|
||||||
|
|
||||||
|
* src/autofit/autofit.c: s/hbshim.c/afshaper.c/.
|
||||||
|
|
||||||
|
* src/autofit/Jamfile, src/autofit/rules.mk (AUTOF_DRV_SRC):
|
||||||
|
Updated.
|
||||||
|
|
||||||
2015-12-06 Werner Lemberg <wl@gnu.org>
|
2015-12-06 Werner Lemberg <wl@gnu.org>
|
||||||
|
|
||||||
[autofit] Prepare forthcoming changes.
|
[autofit] Prepare forthcoming changes.
|
||||||
|
|
|
@ -148,7 +148,7 @@ FT_TRACE_DEF( afcjk )
|
||||||
FT_TRACE_DEF( aflatin )
|
FT_TRACE_DEF( aflatin )
|
||||||
FT_TRACE_DEF( aflatin2 )
|
FT_TRACE_DEF( aflatin2 )
|
||||||
FT_TRACE_DEF( afwarp )
|
FT_TRACE_DEF( afwarp )
|
||||||
FT_TRACE_DEF( afharfbuzz )
|
FT_TRACE_DEF( afshaper )
|
||||||
FT_TRACE_DEF( afglobal )
|
FT_TRACE_DEF( afglobal )
|
||||||
|
|
||||||
/* END */
|
/* END */
|
||||||
|
|
|
@ -33,8 +33,8 @@ SubDir FT2_TOP src autofit ;
|
||||||
afmodule
|
afmodule
|
||||||
afpic
|
afpic
|
||||||
afranges
|
afranges
|
||||||
|
afshaper
|
||||||
afwarp
|
afwarp
|
||||||
hbshim
|
|
||||||
;
|
;
|
||||||
|
|
||||||
if $(FT2_AUTOFIT2)
|
if $(FT2_AUTOFIT2)
|
||||||
|
|
|
@ -88,7 +88,6 @@
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
|
||||||
int dim;
|
int dim;
|
||||||
AF_CJKMetricsRec dummy[1];
|
AF_CJKMetricsRec dummy[1];
|
||||||
AF_Scaler scaler = &dummy->root.scaler;
|
AF_Scaler scaler = &dummy->root.scaler;
|
||||||
|
@ -101,31 +100,56 @@
|
||||||
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
|
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
|
||||||
[style_class->script];
|
[style_class->script];
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
const char* p;
|
const char* p;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
FT_ULong ch;
|
FT_ULong ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = script_class->standard_charstring;
|
||||||
p = script_class->standard_charstring;
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
/* We check a list of standard characters. The first match wins. */
|
/* We check a list of standard characters. The first match wins. */
|
||||||
|
|
||||||
glyph_index = 0;
|
glyph_index = 0;
|
||||||
while ( *p )
|
while ( *p )
|
||||||
{
|
{
|
||||||
|
unsigned int num_idx;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
const char* p_old;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
while ( *p == ' ' )
|
while ( *p == ' ' )
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
GET_UTF8_CHAR( ch, p );
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
p_old = p;
|
||||||
|
GET_UTF8_CHAR( ch, p_old );
|
||||||
|
#endif
|
||||||
|
|
||||||
af_get_char_index( &metrics->root,
|
/* reject input that maps to more than a single glyph */
|
||||||
ch,
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
&glyph_index,
|
if ( num_idx > 1 )
|
||||||
&y_offset );
|
continue;
|
||||||
|
|
||||||
|
/* otherwise exit loop if we have a result */
|
||||||
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
|
shaper_buf,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL );
|
||||||
if ( glyph_index )
|
if ( glyph_index )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
|
if ( !glyph_index )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
if ( !glyph_index )
|
if ( !glyph_index )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -168,6 +192,12 @@
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We assume that the glyphs selected for the stem width
|
||||||
|
* computation are `featureless' enough so that the linking
|
||||||
|
* algorithm works fine without adjustments of its scoring
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
af_latin_hints_link_segments( hints,
|
af_latin_hints_link_segments( hints,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
|
@ -266,6 +296,8 @@
|
||||||
AF_Blue_Stringset bss = sc->blue_stringset;
|
AF_Blue_Stringset bss = sc->blue_stringset;
|
||||||
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
|
const AF_Blue_StringRec* bs = &af_blue_stringsets[bss];
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
|
|
||||||
|
|
||||||
/* we walk over the blue character strings as specified in the */
|
/* we walk over the blue character strings as specified in the */
|
||||||
/* style's entry in the `af_blue_stringset' array, computing its */
|
/* style's entry in the `af_blue_stringset' array, computing its */
|
||||||
|
@ -275,6 +307,8 @@
|
||||||
"==========================\n"
|
"==========================\n"
|
||||||
"\n" ));
|
"\n" ));
|
||||||
|
|
||||||
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
|
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
|
||||||
{
|
{
|
||||||
const char* p = &af_blue_strings[bs->string];
|
const char* p = &af_blue_strings[bs->string];
|
||||||
|
@ -313,26 +347,47 @@
|
||||||
|
|
||||||
while ( *p )
|
while ( *p )
|
||||||
{
|
{
|
||||||
FT_ULong ch;
|
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
|
||||||
FT_Pos best_pos; /* same as points.y or points.x, resp. */
|
FT_Pos best_pos; /* same as points.y or points.x, resp. */
|
||||||
FT_Int best_point;
|
FT_Int best_point;
|
||||||
FT_Vector* points;
|
FT_Vector* points;
|
||||||
|
|
||||||
|
unsigned int num_idx;
|
||||||
|
|
||||||
GET_UTF8_CHAR( ch, p );
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
const char* p_old;
|
||||||
|
FT_ULong ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
while ( *p == ' ' )
|
||||||
|
p++;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
p_old = p;
|
||||||
|
GET_UTF8_CHAR( ch, p_old );
|
||||||
|
#endif
|
||||||
|
|
||||||
/* switch to characters that define flat values */
|
/* switch to characters that define flat values */
|
||||||
if ( ch == '|' )
|
if ( *p == '|' )
|
||||||
{
|
{
|
||||||
fill = 0;
|
fill = 0;
|
||||||
FT_TRACE5(( " [reference values]\n" ));
|
FT_TRACE5(( " [reference values]\n" ));
|
||||||
|
p++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* reject input that maps to more than a single glyph */
|
||||||
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
|
if ( num_idx > 1 )
|
||||||
|
continue;
|
||||||
|
|
||||||
/* load the character in the face -- skip unknown or empty ones */
|
/* load the character in the face -- skip unknown or empty ones */
|
||||||
af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
|
shaper_buf,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL );
|
||||||
if ( glyph_index == 0 )
|
if ( glyph_index == 0 )
|
||||||
{
|
{
|
||||||
FT_TRACE5(( " U+%04lX unavailable\n", ch ));
|
FT_TRACE5(( " U+%04lX unavailable\n", ch ));
|
||||||
|
@ -341,9 +396,9 @@
|
||||||
|
|
||||||
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
|
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
|
||||||
outline = face->glyph->outline;
|
outline = face->glyph->outline;
|
||||||
if ( error || outline.n_points <= 0 )
|
if ( error || outline.n_points <= 2 )
|
||||||
{
|
{
|
||||||
FT_TRACE5(( " U+%04lX contains no outlines\n", ch ));
|
FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,7 +477,8 @@
|
||||||
fills[num_fills++] = best_pos;
|
fills[num_fills++] = best_pos;
|
||||||
else
|
else
|
||||||
flats[num_flats++] = best_pos;
|
flats[num_flats++] = best_pos;
|
||||||
}
|
|
||||||
|
} /* end while loop */
|
||||||
|
|
||||||
if ( num_flats == 0 && num_fills == 0 )
|
if ( num_flats == 0 && num_fills == 0 )
|
||||||
{
|
{
|
||||||
|
@ -489,7 +545,10 @@
|
||||||
FT_TRACE5(( " -> reference = %ld\n"
|
FT_TRACE5(( " -> reference = %ld\n"
|
||||||
" overshoot = %ld\n",
|
" overshoot = %ld\n",
|
||||||
*blue_ref, *blue_shoot ));
|
*blue_ref, *blue_shoot ));
|
||||||
}
|
|
||||||
|
} /* end for loop */
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
FT_TRACE5(( "\n" ));
|
FT_TRACE5(( "\n" ));
|
||||||
|
|
||||||
|
@ -503,27 +562,36 @@
|
||||||
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
|
af_cjk_metrics_check_digits( AF_CJKMetrics metrics,
|
||||||
FT_Face face )
|
FT_Face face )
|
||||||
{
|
{
|
||||||
FT_UInt i;
|
|
||||||
FT_Bool started = 0, same_width = 1;
|
FT_Bool started = 0, same_width = 1;
|
||||||
FT_Fixed advance, old_advance = 0;
|
FT_Fixed advance, old_advance = 0;
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
|
|
||||||
/* digit `0' is 0x30 in all supported charmaps */
|
/* in all supported charmaps, digits have character codes 0x30-0x39 */
|
||||||
for ( i = 0x30; i <= 0x39; i++ )
|
const char digits[] = "0 1 2 3 4 5 6 7 8 9";
|
||||||
|
const char* p;
|
||||||
|
|
||||||
|
|
||||||
|
p = digits;
|
||||||
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
|
while ( *p )
|
||||||
{
|
{
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
unsigned int num_idx;
|
||||||
|
|
||||||
|
|
||||||
af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
|
/* reject input that maps to more than a single glyph */
|
||||||
if ( glyph_index == 0 )
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
|
if ( num_idx > 1 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( FT_Get_Advance( face, glyph_index,
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
FT_LOAD_NO_SCALE |
|
shaper_buf,
|
||||||
FT_LOAD_NO_HINTING |
|
0,
|
||||||
FT_LOAD_IGNORE_TRANSFORM,
|
&advance,
|
||||||
&advance ) )
|
NULL );
|
||||||
|
if ( !glyph_index )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( started )
|
if ( started )
|
||||||
|
@ -541,6 +609,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
metrics->root.digits_have_same_width = same_width;
|
metrics->root.digits_have_same_width = same_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
#include "afglobal.h"
|
#include "afglobal.h"
|
||||||
#include "afranges.h"
|
#include "afranges.h"
|
||||||
#include "hbshim.h"
|
#include "afshaper.h"
|
||||||
#include FT_INTERNAL_DEBUG_H
|
#include FT_INTERNAL_DEBUG_H
|
||||||
|
|
||||||
|
|
||||||
|
@ -240,12 +240,12 @@
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* get glyphs not directly addressable by cmap */
|
/* get glyphs not directly addressable by cmap */
|
||||||
af_get_coverage( globals, style_class, gstyles );
|
af_shaper_get_coverage( globals, style_class, gstyles );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle the default OpenType features of the default script ... */
|
/* handle the default OpenType features of the default script ... */
|
||||||
af_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
|
af_shaper_get_coverage( globals, AF_STYLE_CLASSES_GET[dflt], gstyles );
|
||||||
|
|
||||||
/* ... and the remaining default OpenType features */
|
/* ... and the remaining default OpenType features */
|
||||||
for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
|
for ( ss = 0; AF_STYLE_CLASSES_GET[ss]; ss++ )
|
||||||
|
@ -254,7 +254,7 @@
|
||||||
|
|
||||||
|
|
||||||
if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
|
if ( ss != dflt && style_class->coverage == AF_COVERAGE_DEFAULT )
|
||||||
af_get_coverage( globals, style_class, gstyles );
|
af_shaper_get_coverage( globals, style_class, gstyles );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* mark ASCII digits */
|
/* mark ASCII digits */
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
#include "aftypes.h"
|
#include "aftypes.h"
|
||||||
#include "afmodule.h"
|
#include "afmodule.h"
|
||||||
#include "hbshim.h"
|
#include "afshaper.h"
|
||||||
|
|
||||||
|
|
||||||
FT_BEGIN_HEADER
|
FT_BEGIN_HEADER
|
||||||
|
|
|
@ -79,7 +79,6 @@
|
||||||
{
|
{
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
|
||||||
int dim;
|
int dim;
|
||||||
AF_LatinMetricsRec dummy[1];
|
AF_LatinMetricsRec dummy[1];
|
||||||
AF_Scaler scaler = &dummy->root.scaler;
|
AF_Scaler scaler = &dummy->root.scaler;
|
||||||
|
@ -92,12 +91,15 @@
|
||||||
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
|
AF_ScriptClass script_class = AF_SCRIPT_CLASSES_GET
|
||||||
[style_class->script];
|
[style_class->script];
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
const char* p;
|
const char* p;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
FT_ULong ch;
|
FT_ULong ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = script_class->standard_charstring;
|
||||||
p = script_class->standard_charstring;
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We check a list of standard characters to catch features like
|
* We check a list of standard characters to catch features like
|
||||||
|
@ -109,19 +111,41 @@
|
||||||
glyph_index = 0;
|
glyph_index = 0;
|
||||||
while ( *p )
|
while ( *p )
|
||||||
{
|
{
|
||||||
|
unsigned int num_idx;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
const char* p_old;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
while ( *p == ' ' )
|
while ( *p == ' ' )
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
GET_UTF8_CHAR( ch, p );
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
p_old = p;
|
||||||
|
GET_UTF8_CHAR( ch, p_old );
|
||||||
|
#endif
|
||||||
|
|
||||||
af_get_char_index( &metrics->root,
|
/* reject input that maps to more than a single glyph */
|
||||||
ch,
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
&glyph_index,
|
if ( num_idx > 1 )
|
||||||
&y_offset );
|
continue;
|
||||||
|
|
||||||
|
/* otherwise exit loop if we have a result */
|
||||||
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
|
shaper_buf,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL );
|
||||||
if ( glyph_index )
|
if ( glyph_index )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
|
if ( !glyph_index )
|
||||||
|
goto Exit;
|
||||||
|
|
||||||
if ( !glyph_index )
|
if ( !glyph_index )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -269,6 +293,8 @@
|
||||||
|
|
||||||
FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
|
FT_Pos flat_threshold = FLAT_THRESHOLD( metrics->units_per_em );
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
|
|
||||||
|
|
||||||
/* we walk over the blue character strings as specified in the */
|
/* we walk over the blue character strings as specified in the */
|
||||||
/* style's entry in the `af_blue_stringset' array */
|
/* style's entry in the `af_blue_stringset' array */
|
||||||
|
@ -277,6 +303,8 @@
|
||||||
"============================\n"
|
"============================\n"
|
||||||
"\n" ));
|
"\n" ));
|
||||||
|
|
||||||
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
|
for ( ; bs->string != AF_BLUE_STRING_MAX; bs++ )
|
||||||
{
|
{
|
||||||
const char* p = &af_blue_strings[bs->string];
|
const char* p = &af_blue_strings[bs->string];
|
||||||
|
@ -340,24 +368,51 @@
|
||||||
|
|
||||||
while ( *p )
|
while ( *p )
|
||||||
{
|
{
|
||||||
FT_ULong ch;
|
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
FT_Long y_offset;
|
||||||
FT_Pos best_y; /* same as points.y */
|
|
||||||
FT_Int best_point, best_contour_first, best_contour_last;
|
FT_Int best_point, best_contour_first, best_contour_last;
|
||||||
FT_Vector* points;
|
FT_Vector* points;
|
||||||
FT_Bool round = 0;
|
|
||||||
|
FT_Pos best_y_extremum; /* same as points.y */
|
||||||
|
FT_Bool best_round = 0;
|
||||||
|
|
||||||
unsigned int i, num_idx;
|
unsigned int i, num_idx;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
const char* p_old;
|
||||||
|
FT_ULong ch;
|
||||||
|
#endif
|
||||||
|
|
||||||
GET_UTF8_CHAR( ch, p );
|
|
||||||
|
|
||||||
num_idx = 1;
|
while ( *p == ' ' )
|
||||||
|
p++;
|
||||||
|
|
||||||
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
p_old = p;
|
||||||
|
GET_UTF8_CHAR( ch, p_old );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
|
|
||||||
|
if ( AF_LATIN_IS_TOP_BLUE( bs ) )
|
||||||
|
best_y_extremum = FT_INT_MIN;
|
||||||
|
else
|
||||||
|
best_y_extremum = FT_INT_MAX;
|
||||||
|
|
||||||
|
/* iterate over all glyph elements of the character cluster */
|
||||||
|
/* and get the data of the `biggest' one */
|
||||||
for ( i = 0; i < num_idx; i++ )
|
for ( i = 0; i < num_idx; i++ )
|
||||||
{
|
{
|
||||||
|
FT_Pos best_y;
|
||||||
|
FT_Bool round = 0;
|
||||||
|
|
||||||
|
|
||||||
/* load the character in the face -- skip unknown or empty ones */
|
/* load the character in the face -- skip unknown or empty ones */
|
||||||
af_get_char_index( &metrics->root, ch, &glyph_index, &y_offset );
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
|
shaper_buf,
|
||||||
|
i,
|
||||||
|
NULL,
|
||||||
|
&y_offset );
|
||||||
if ( glyph_index == 0 )
|
if ( glyph_index == 0 )
|
||||||
{
|
{
|
||||||
FT_TRACE5(( " U+%04lX unavailable\n", ch ));
|
FT_TRACE5(( " U+%04lX unavailable\n", ch ));
|
||||||
|
@ -369,7 +424,13 @@
|
||||||
/* reject glyphs that don't produce any rendering */
|
/* reject glyphs that don't produce any rendering */
|
||||||
if ( error || outline.n_points <= 2 )
|
if ( error || outline.n_points <= 2 )
|
||||||
{
|
{
|
||||||
FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
|
if ( num_idx == 1 )
|
||||||
|
FT_TRACE5(( " U+%04lX contains no (usable) outlines\n", ch ));
|
||||||
|
else
|
||||||
|
FT_TRACE5(( " component %d of cluster starting with U+%04lX"
|
||||||
|
" contains no (usable) outlines\n", i, ch ));
|
||||||
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,9 +455,10 @@
|
||||||
|
|
||||||
last = outline.contours[nn];
|
last = outline.contours[nn];
|
||||||
|
|
||||||
/* Avoid single-point contours since they are never rasterized. */
|
/* Avoid single-point contours since they are never */
|
||||||
/* In some fonts, they correspond to mark attachment points */
|
/* rasterized. In some fonts, they correspond to mark */
|
||||||
/* that are way outside of the glyph's real outline. */
|
/* attachment points that are way outside of the glyph's */
|
||||||
|
/* real outline. */
|
||||||
if ( last <= first )
|
if ( last <= first )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -648,8 +710,8 @@
|
||||||
if ( l2r == left2right &&
|
if ( l2r == left2right &&
|
||||||
d >= length_threshold )
|
d >= length_threshold )
|
||||||
{
|
{
|
||||||
/* all constraints are met; update segment after finding */
|
/* all constraints are met; update segment after */
|
||||||
/* its end */
|
/* finding its end */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ( last < best_contour_last )
|
if ( last < best_contour_last )
|
||||||
|
@ -735,12 +797,31 @@
|
||||||
FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
|
FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( round )
|
if ( AF_LATIN_IS_TOP_BLUE( bs ) )
|
||||||
rounds[num_rounds++] = best_y;
|
{
|
||||||
|
if ( best_y > best_y_extremum )
|
||||||
|
{
|
||||||
|
best_y_extremum = best_y;
|
||||||
|
best_round = round;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
flats[num_flats++] = best_y;
|
{
|
||||||
}
|
if ( best_y < best_y_extremum )
|
||||||
}
|
{
|
||||||
|
best_y_extremum = best_y;
|
||||||
|
best_round = round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* end for loop */
|
||||||
|
|
||||||
|
if ( best_round )
|
||||||
|
rounds[num_rounds++] = best_y_extremum;
|
||||||
|
else
|
||||||
|
flats[num_flats++] = best_y_extremum;
|
||||||
|
|
||||||
|
} /* end while loop */
|
||||||
|
|
||||||
if ( num_flats == 0 && num_rounds == 0 )
|
if ( num_flats == 0 && num_rounds == 0 )
|
||||||
{
|
{
|
||||||
|
@ -820,7 +901,10 @@
|
||||||
FT_TRACE5(( " -> reference = %ld\n"
|
FT_TRACE5(( " -> reference = %ld\n"
|
||||||
" overshoot = %ld\n",
|
" overshoot = %ld\n",
|
||||||
*blue_ref, *blue_shoot ));
|
*blue_ref, *blue_shoot ));
|
||||||
}
|
|
||||||
|
} /* end for loop */
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
FT_TRACE5(( "\n" ));
|
FT_TRACE5(( "\n" ));
|
||||||
|
|
||||||
|
@ -834,27 +918,36 @@
|
||||||
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
|
af_latin_metrics_check_digits( AF_LatinMetrics metrics,
|
||||||
FT_Face face )
|
FT_Face face )
|
||||||
{
|
{
|
||||||
FT_UInt i;
|
|
||||||
FT_Bool started = 0, same_width = 1;
|
FT_Bool started = 0, same_width = 1;
|
||||||
FT_Fixed advance, old_advance = 0;
|
FT_Fixed advance, old_advance = 0;
|
||||||
|
|
||||||
|
void* shaper_buf;
|
||||||
|
|
||||||
/* digit `0' is 0x30 in all supported charmaps */
|
/* in all supported charmaps, digits have character codes 0x30-0x39 */
|
||||||
for ( i = 0x30; i <= 0x39; i++ )
|
const char digits[] = "0 1 2 3 4 5 6 7 8 9";
|
||||||
|
const char* p;
|
||||||
|
|
||||||
|
|
||||||
|
p = digits;
|
||||||
|
shaper_buf = af_shaper_buf_create( face );
|
||||||
|
|
||||||
|
while ( *p )
|
||||||
{
|
{
|
||||||
FT_ULong glyph_index;
|
FT_ULong glyph_index;
|
||||||
FT_Long y_offset;
|
unsigned int num_idx;
|
||||||
|
|
||||||
|
|
||||||
af_get_char_index( &metrics->root, i, &glyph_index, &y_offset );
|
/* reject input that maps to more than a single glyph */
|
||||||
if ( glyph_index == 0 )
|
p = af_shaper_get_cluster( p, &metrics->root, shaper_buf, &num_idx );
|
||||||
|
if ( num_idx > 1 )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( FT_Get_Advance( face, glyph_index,
|
glyph_index = af_shaper_get_elem( &metrics->root,
|
||||||
FT_LOAD_NO_SCALE |
|
shaper_buf,
|
||||||
FT_LOAD_NO_HINTING |
|
0,
|
||||||
FT_LOAD_IGNORE_TRANSFORM,
|
&advance,
|
||||||
&advance ) )
|
NULL );
|
||||||
|
if ( !glyph_index )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( started )
|
if ( started )
|
||||||
|
@ -872,6 +965,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
af_shaper_buf_destroy( face, shaper_buf );
|
||||||
|
|
||||||
metrics->root.digits_have_same_width = same_width;
|
metrics->root.digits_have_same_width = same_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* hbshim.c */
|
/* afshaper.c */
|
||||||
/* */
|
/* */
|
||||||
/* HarfBuzz interface for accessing OpenType features (body). */
|
/* HarfBuzz interface for accessing OpenType features (body). */
|
||||||
/* */
|
/* */
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include "afglobal.h"
|
#include "afglobal.h"
|
||||||
#include "aftypes.h"
|
#include "aftypes.h"
|
||||||
#include "hbshim.h"
|
#include "afshaper.h"
|
||||||
|
|
||||||
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
|
#ifdef FT_CONFIG_OPTION_USE_HARFBUZZ
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
/* messages during execution. */
|
/* messages during execution. */
|
||||||
/* */
|
/* */
|
||||||
#undef FT_COMPONENT
|
#undef FT_COMPONENT
|
||||||
#define FT_COMPONENT trace_afharfbuzz
|
#define FT_COMPONENT trace_afshaper
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -96,9 +96,9 @@
|
||||||
|
|
||||||
|
|
||||||
FT_Error
|
FT_Error
|
||||||
af_get_coverage( AF_FaceGlobals globals,
|
af_shaper_get_coverage( AF_FaceGlobals globals,
|
||||||
AF_StyleClass style_class,
|
AF_StyleClass style_class,
|
||||||
FT_UShort* gstyles )
|
FT_UShort* gstyles )
|
||||||
{
|
{
|
||||||
hb_face_t* face;
|
hb_face_t* face;
|
||||||
|
|
||||||
|
@ -418,88 +418,110 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
FT_Error
|
void*
|
||||||
af_get_char_index( AF_StyleMetrics metrics,
|
af_shaper_buf_create( FT_Face face )
|
||||||
FT_ULong charcode,
|
|
||||||
FT_ULong *codepoint,
|
|
||||||
FT_Long *y_offset )
|
|
||||||
{
|
{
|
||||||
AF_StyleClass style_class;
|
FT_UNUSED( face );
|
||||||
|
|
||||||
|
return (void*)hb_buffer_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
af_shaper_buf_destroy( FT_Face face,
|
||||||
|
void* buf )
|
||||||
|
{
|
||||||
|
FT_UNUSED( face );
|
||||||
|
|
||||||
|
hb_buffer_destroy( (hb_buffer_t*)buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
af_shaper_get_cluster( const char* p,
|
||||||
|
AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int* count )
|
||||||
|
{
|
||||||
|
AF_StyleClass style_class;
|
||||||
const hb_feature_t* feature;
|
const hb_feature_t* feature;
|
||||||
|
FT_Int upem;
|
||||||
|
const char* q;
|
||||||
|
int len;
|
||||||
|
|
||||||
FT_ULong in_idx, out_idx;
|
hb_buffer_t* buf = (hb_buffer_t*)buf_;
|
||||||
|
hb_font_t* font;
|
||||||
|
hb_codepoint_t dummy;
|
||||||
|
|
||||||
|
|
||||||
if ( !metrics )
|
upem = (FT_Int)metrics->globals->face->units_per_EM;
|
||||||
return FT_THROW( Invalid_Argument );
|
|
||||||
|
|
||||||
in_idx = FT_Get_Char_Index( metrics->globals->face, charcode );
|
|
||||||
|
|
||||||
style_class = metrics->style_class;
|
style_class = metrics->style_class;
|
||||||
|
feature = features[style_class->coverage];
|
||||||
|
|
||||||
feature = features[style_class->coverage];
|
font = metrics->globals->hb_font;
|
||||||
|
|
||||||
if ( feature )
|
/* we shape at a size of units per EM; this means font units */
|
||||||
{
|
hb_font_set_scale( font, upem, upem );
|
||||||
FT_Int upem = (FT_Int)metrics->globals->face->units_per_EM;
|
|
||||||
|
|
||||||
hb_font_t* font = metrics->globals->hb_font;
|
while ( *p == ' ' )
|
||||||
hb_buffer_t* buf = hb_buffer_create();
|
p++;
|
||||||
|
|
||||||
uint32_t c = (uint32_t)charcode;
|
/* count characters up to next space (or end of buffer) */
|
||||||
|
q = p;
|
||||||
|
while ( !( *q == ' ' || *q == '\0' ) )
|
||||||
|
GET_UTF8_CHAR( dummy, q );
|
||||||
|
len = (int)( q - p );
|
||||||
|
|
||||||
hb_glyph_info_t* ginfo;
|
/* feed character(s) to the HarfBuzz buffer */
|
||||||
hb_glyph_position_t* gpos;
|
hb_buffer_clear_contents( buf );
|
||||||
unsigned int gcount;
|
hb_buffer_add_utf8( buf, p, len, 0, len );
|
||||||
|
|
||||||
|
/* we let HarfBuzz guess the script and writing direction */
|
||||||
|
hb_buffer_guess_segment_properties( buf );
|
||||||
|
|
||||||
/* we shape at a size of units per EM; this means font units */
|
/* shape buffer, which means conversion from character codes to */
|
||||||
hb_font_set_scale( font, upem, upem );
|
/* glyph indices, possibly applying a feature */
|
||||||
|
hb_shape( font, buf, feature, feature ? 1 : 0 );
|
||||||
|
|
||||||
/* XXX: is this sufficient for a single character of any script? */
|
*count = hb_buffer_get_length( buf );
|
||||||
hb_buffer_set_direction( buf, HB_DIRECTION_LTR );
|
|
||||||
hb_buffer_set_script( buf, scripts[style_class->script] );
|
|
||||||
|
|
||||||
/* we add one character to `buf' ... */
|
|
||||||
hb_buffer_add_utf32( buf, &c, 1, 0, 1 );
|
|
||||||
|
|
||||||
/* ... and apply one feature */
|
|
||||||
hb_shape( font, buf, feature, 1 );
|
|
||||||
|
|
||||||
ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
|
|
||||||
gpos = hb_buffer_get_glyph_positions( buf, &gcount );
|
|
||||||
|
|
||||||
out_idx = ginfo[0].codepoint;
|
|
||||||
|
|
||||||
/* getting the same index indicates no substitution, */
|
|
||||||
/* which means that the glyph isn't available in the feature */
|
|
||||||
if ( in_idx == out_idx )
|
|
||||||
{
|
|
||||||
*codepoint = 0;
|
|
||||||
*y_offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*codepoint = out_idx;
|
|
||||||
*y_offset = gpos[0].y_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
hb_buffer_destroy( buf );
|
|
||||||
|
|
||||||
#ifdef FT_DEBUG_LEVEL_TRACE
|
#ifdef FT_DEBUG_LEVEL_TRACE
|
||||||
if ( gcount > 1 )
|
if ( feature && *count > 1 )
|
||||||
FT_TRACE1(( "af_get_char_index:"
|
FT_TRACE1(( "af_get_char_index:"
|
||||||
" input character mapped to multiple glyphs\n" ));
|
" input character mapped to multiple glyphs\n" ));
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*codepoint = in_idx;
|
|
||||||
*y_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FT_Err_Ok;
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_ULong
|
||||||
|
af_shaper_get_elem( AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int idx,
|
||||||
|
FT_Long* advance,
|
||||||
|
FT_Long* y_offset )
|
||||||
|
{
|
||||||
|
hb_buffer_t* buf = (hb_buffer_t*)buf_;
|
||||||
|
hb_glyph_info_t* ginfo;
|
||||||
|
hb_glyph_position_t* gpos;
|
||||||
|
unsigned int gcount;
|
||||||
|
|
||||||
|
FT_UNUSED( metrics );
|
||||||
|
|
||||||
|
|
||||||
|
ginfo = hb_buffer_get_glyph_infos( buf, &gcount );
|
||||||
|
gpos = hb_buffer_get_glyph_positions( buf, &gcount );
|
||||||
|
|
||||||
|
if ( idx >= gcount )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ( advance )
|
||||||
|
*advance = gpos[idx].x_advance;
|
||||||
|
if ( y_offset )
|
||||||
|
*y_offset = gpos[idx].y_offset;
|
||||||
|
|
||||||
|
return ginfo[idx].codepoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -507,9 +529,9 @@
|
||||||
|
|
||||||
|
|
||||||
FT_Error
|
FT_Error
|
||||||
af_get_coverage( AF_FaceGlobals globals,
|
af_shaper_get_coverage( AF_FaceGlobals globals,
|
||||||
AF_StyleClass style_class,
|
AF_StyleClass style_class,
|
||||||
FT_UShort* gstyles )
|
FT_UShort* gstyles )
|
||||||
{
|
{
|
||||||
FT_UNUSED( globals );
|
FT_UNUSED( globals );
|
||||||
FT_UNUSED( style_class );
|
FT_UNUSED( style_class );
|
||||||
|
@ -519,24 +541,91 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_Error
|
void*
|
||||||
af_get_char_index( AF_StyleMetrics metrics,
|
af_shaper_buf_create( FT_Face face )
|
||||||
FT_ULong charcode,
|
|
||||||
FT_ULong *codepoint,
|
|
||||||
FT_Long *y_offset )
|
|
||||||
{
|
{
|
||||||
FT_Face face;
|
FT_Memory memory = face->memory;
|
||||||
|
FT_ULong* buf;
|
||||||
|
|
||||||
|
|
||||||
if ( !metrics )
|
FT_ALLOC( buf, sizeof ( FT_ULong ) );
|
||||||
return FT_THROW( Invalid_Argument );
|
|
||||||
|
|
||||||
face = metrics->globals->face;
|
return (void*)buf;
|
||||||
|
}
|
||||||
|
|
||||||
*codepoint = FT_Get_Char_Index( face, charcode );
|
|
||||||
*y_offset = 0;
|
|
||||||
|
|
||||||
return FT_Err_Ok;
|
void
|
||||||
|
af_shaper_buf_destroy( FT_Face face,
|
||||||
|
void* buf )
|
||||||
|
{
|
||||||
|
FT_Memory memory = face->memory;
|
||||||
|
|
||||||
|
|
||||||
|
FT_FREE( buf );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char*
|
||||||
|
af_shaper_get_cluster( const char* p,
|
||||||
|
AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int* count )
|
||||||
|
{
|
||||||
|
FT_Face face = metrics->globals->face;
|
||||||
|
FT_ULong ch, dummy = 0;
|
||||||
|
FT_ULong* buf = (FT_ULong*)buf_;
|
||||||
|
|
||||||
|
|
||||||
|
while ( *p == ' ' )
|
||||||
|
p++;
|
||||||
|
|
||||||
|
GET_UTF8_CHAR( ch, p );
|
||||||
|
|
||||||
|
/* since we don't have an engine to handle clusters, */
|
||||||
|
/* we scan the characters but return zero */
|
||||||
|
while ( !( *p == ' ' || *p == '\0' ) )
|
||||||
|
GET_UTF8_CHAR( dummy, p );
|
||||||
|
|
||||||
|
if ( dummy )
|
||||||
|
{
|
||||||
|
*buf = 0;
|
||||||
|
*count = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*buf = FT_Get_Char_Index( face, ch );
|
||||||
|
*count = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FT_ULong
|
||||||
|
af_shaper_get_elem( AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int idx,
|
||||||
|
FT_Long* advance,
|
||||||
|
FT_Long* y_offset )
|
||||||
|
{
|
||||||
|
FT_Face face = metrics->globals->face;
|
||||||
|
FT_ULong glyph_index = *(FT_ULong*)buf_;
|
||||||
|
|
||||||
|
FT_UNUSED( idx );
|
||||||
|
|
||||||
|
|
||||||
|
if ( advance )
|
||||||
|
FT_Get_Advance( face,
|
||||||
|
glyph_index,
|
||||||
|
FT_LOAD_NO_SCALE |
|
||||||
|
FT_LOAD_NO_HINTING |
|
||||||
|
FT_LOAD_IGNORE_TRANSFORM,
|
||||||
|
advance ) )
|
||||||
|
|
||||||
|
if ( y_offset )
|
||||||
|
*y_offset = 0;
|
||||||
|
|
||||||
|
return glyph_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/* hbshim.h */
|
/* afshaper.h */
|
||||||
/* */
|
/* */
|
||||||
/* HarfBuzz interface for accessing OpenType features (specification). */
|
/* HarfBuzz interface for accessing OpenType features (specification). */
|
||||||
/* */
|
/* */
|
||||||
|
@ -16,8 +16,8 @@
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#ifndef __HBSHIM_H__
|
#ifndef __AFSHAPER_H__
|
||||||
#define __HBSHIM_H__
|
#define __AFSHAPER_H__
|
||||||
|
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
|
@ -36,21 +36,36 @@
|
||||||
FT_BEGIN_HEADER
|
FT_BEGIN_HEADER
|
||||||
|
|
||||||
FT_Error
|
FT_Error
|
||||||
af_get_coverage( AF_FaceGlobals globals,
|
af_shaper_get_coverage( AF_FaceGlobals globals,
|
||||||
AF_StyleClass style_class,
|
AF_StyleClass style_class,
|
||||||
FT_UShort* gstyles );
|
FT_UShort* gstyles );
|
||||||
|
|
||||||
FT_Error
|
|
||||||
af_get_char_index( AF_StyleMetrics metrics,
|
void*
|
||||||
FT_ULong charcode,
|
af_shaper_buf_create( FT_Face face );
|
||||||
FT_ULong *codepoint,
|
|
||||||
FT_Long *y_offset );
|
void
|
||||||
|
af_shaper_buf_destroy( FT_Face face,
|
||||||
|
void* buf );
|
||||||
|
|
||||||
|
const char*
|
||||||
|
af_shaper_get_cluster( const char* p,
|
||||||
|
AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int* count );
|
||||||
|
|
||||||
|
FT_ULong
|
||||||
|
af_shaper_get_elem( AF_StyleMetrics metrics,
|
||||||
|
void* buf_,
|
||||||
|
unsigned int idx,
|
||||||
|
FT_Long* x_advance,
|
||||||
|
FT_Long* y_offset );
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
||||||
FT_END_HEADER
|
FT_END_HEADER
|
||||||
|
|
||||||
#endif /* __HBSHIM_H__ */
|
#endif /* __AFSHAPER_H__ */
|
||||||
|
|
||||||
|
|
||||||
/* END */
|
/* END */
|
|
@ -34,7 +34,7 @@
|
||||||
#include "afcjk.c"
|
#include "afcjk.c"
|
||||||
#include "afindic.c"
|
#include "afindic.c"
|
||||||
|
|
||||||
#include "hbshim.c"
|
#include "afshaper.c"
|
||||||
|
|
||||||
#include "afloader.c"
|
#include "afloader.c"
|
||||||
#include "afmodule.c"
|
#include "afmodule.c"
|
||||||
|
|
|
@ -40,8 +40,8 @@ AUTOF_DRV_SRC := $(AUTOF_DIR)/afangles.c \
|
||||||
$(AUTOF_DIR)/afmodule.c \
|
$(AUTOF_DIR)/afmodule.c \
|
||||||
$(AUTOF_DIR)/afpic.c \
|
$(AUTOF_DIR)/afpic.c \
|
||||||
$(AUTOF_DIR)/afranges.c \
|
$(AUTOF_DIR)/afranges.c \
|
||||||
$(AUTOF_DIR)/afwarp.c \
|
$(AUTOF_DIR)/afshaper.c \
|
||||||
$(AUTOF_DIR)/hbshim.c
|
$(AUTOF_DIR)/afwarp.c
|
||||||
|
|
||||||
# AUTOF driver headers
|
# AUTOF driver headers
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue