Merge harfbuzz-ng
This commit is contained in:
commit
ce48f03946
|
@ -0,0 +1 @@
|
||||||
|
main
|
|
@ -2,17 +2,20 @@
|
||||||
|
|
||||||
INCLUDES = \
|
INCLUDES = \
|
||||||
-I $(srcdir) \
|
-I $(srcdir) \
|
||||||
$(FREETYPE_CFLAGS)
|
$(FREETYPE_CFLAGS) \
|
||||||
|
$(GLIB_CFLAGS)
|
||||||
|
CXX = gcc $(GCCOPTS) -fno-rtti -fno-exceptions -Wabi -Wpadded -Wcast-align
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libharfbuzz-1.la
|
noinst_LTLIBRARIES = libharfbuzz-1.la
|
||||||
|
|
||||||
MAINSOURCES = \
|
MAINSOURCES = \
|
||||||
harfbuzz.c
|
$(INCLUDEDSOURCES) \
|
||||||
|
hb-ot-layout.cc
|
||||||
|
# harfbuzz.c
|
||||||
|
|
||||||
# included from harfbuzz.c
|
# included from harfbuzz.c
|
||||||
INCLUDEDSOURCES = \
|
INCLUDEDSOURCES = \
|
||||||
harfbuzz-buffer.c \
|
harfbuzz-buffer.c \
|
||||||
harfbuzz-gdef.c \
|
|
||||||
harfbuzz-gpos.c \
|
harfbuzz-gpos.c \
|
||||||
harfbuzz-gsub.c \
|
harfbuzz-gsub.c \
|
||||||
harfbuzz-impl.c \
|
harfbuzz-impl.c \
|
||||||
|
@ -23,7 +26,6 @@ PUBLICHEADERS = \
|
||||||
harfbuzz.h \
|
harfbuzz.h \
|
||||||
harfbuzz-global.h \
|
harfbuzz-global.h \
|
||||||
harfbuzz-buffer.h \
|
harfbuzz-buffer.h \
|
||||||
harfbuzz-gdef.h \
|
|
||||||
harfbuzz-gpos.h \
|
harfbuzz-gpos.h \
|
||||||
harfbuzz-gsub.h \
|
harfbuzz-gsub.h \
|
||||||
harfbuzz-open.h
|
harfbuzz-open.h
|
||||||
|
@ -31,7 +33,6 @@ PUBLICHEADERS = \
|
||||||
PRIVATEHEADERS = \
|
PRIVATEHEADERS = \
|
||||||
harfbuzz-impl.h \
|
harfbuzz-impl.h \
|
||||||
harfbuzz-buffer-private.h \
|
harfbuzz-buffer-private.h \
|
||||||
harfbuzz-gdef-private.h \
|
|
||||||
harfbuzz-gpos-private.h \
|
harfbuzz-gpos-private.h \
|
||||||
harfbuzz-gsub-private.h \
|
harfbuzz-gsub-private.h \
|
||||||
harfbuzz-open-private.h \
|
harfbuzz-open-private.h \
|
||||||
|
@ -45,7 +46,7 @@ libharfbuzz_1_la_SOURCES = \
|
||||||
libharfbuzz_1_la_LIBADD = \
|
libharfbuzz_1_la_LIBADD = \
|
||||||
$(FREETYPE_LIBS)
|
$(FREETYPE_LIBS)
|
||||||
|
|
||||||
noinst_PROGRAMS = harfbuzz-dump
|
noinst_PROGRAMS = harfbuzz-dump main
|
||||||
|
|
||||||
harfbuzz_dump_SOURCES = \
|
harfbuzz_dump_SOURCES = \
|
||||||
harfbuzz-dump.c \
|
harfbuzz-dump.c \
|
||||||
|
@ -56,6 +57,9 @@ harfbuzz_dump_LDADD = \
|
||||||
$(libharfbuzz_1_la_LIBADD) \
|
$(libharfbuzz_1_la_LIBADD) \
|
||||||
libharfbuzz-1.la
|
libharfbuzz-1.la
|
||||||
|
|
||||||
|
main_LDADD = \
|
||||||
|
$(GLIB_LIBS)
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
README \
|
README \
|
||||||
COPYING \
|
COPYING \
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
all: main
|
||||||
|
|
||||||
|
CPPFLAGS = -Wall -Wextra `pkg-config --cflags glib-2.0`
|
||||||
|
LDFLAGS = `pkg-config --libs glib-2.0`
|
||||||
|
CXX = gcc $(GCCOPTS) -fno-rtti -fno-exceptions -Wabi -Wpadded -Wcast-align
|
||||||
|
|
||||||
|
main: main.cc *.h
|
||||||
|
$(CXX) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f main main.o
|
|
@ -83,9 +83,9 @@ _hb_buffer_allocate_ligid( HB_Buffer buffer );
|
||||||
#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
|
#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
|
||||||
#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
|
#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
|
||||||
|
|
||||||
#define CHECK_Property( gdef, index, flags, property ) \
|
#define CHECK_Property( layout, index, flags, property ) \
|
||||||
( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \
|
(error = _hb_ot_layout_check_glyph_properties((layout), (index), (flags), (property)) \
|
||||||
(property) ) ) != HB_Err_Ok )
|
? HB_Err_Ok : HB_Err_Not_Covered)
|
||||||
|
|
||||||
#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
|
#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
|
||||||
( ( error = _hb_buffer_add_output_glyphs( (buffer), \
|
( ( error = _hb_buffer_add_output_glyphs( (buffer), \
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
#ifndef HARFBUZZ_GLOBAL_H
|
#ifndef HARFBUZZ_GLOBAL_H
|
||||||
#define HARFBUZZ_GLOBAL_H
|
#define HARFBUZZ_GLOBAL_H
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#include "hb-ot-layout.h"
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ static HB_Error default_mmfunc( HB_Font font,
|
||||||
|
|
||||||
HB_Error HB_Load_GPOS_Table( HB_Font font,
|
HB_Error HB_Load_GPOS_Table( HB_Font font,
|
||||||
HB_GPOSHeader** retptr,
|
HB_GPOSHeader** retptr,
|
||||||
HB_GDEFHeader* gdef )
|
hb_ot_layout_t *layout )
|
||||||
{
|
{
|
||||||
HB_UInt cur_offset, new_offset, base_offset;
|
HB_UInt cur_offset, new_offset, base_offset;
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ HB_Error HB_Load_GPOS_Table( HB_Font font,
|
||||||
HB_Error error;
|
HB_Error error;
|
||||||
|
|
||||||
|
|
||||||
if ( !retptr )
|
if ( !retptr || !layout )
|
||||||
return ERR(HB_Err_Invalid_Argument);
|
return ERR(HB_Err_Invalid_Argument);
|
||||||
|
|
||||||
if ( GOTO_Table( TTAG_GPOS ) )
|
if ( GOTO_Table( TTAG_GPOS ) )
|
||||||
|
@ -143,20 +143,12 @@ HB_Error HB_Load_GPOS_Table( HB_Font font,
|
||||||
stream, HB_Type_GPOS ) ) != HB_Err_Ok )
|
stream, HB_Type_GPOS ) ) != HB_Err_Ok )
|
||||||
goto Fail2;
|
goto Fail2;
|
||||||
|
|
||||||
gpos->gdef = gdef; /* can be NULL */
|
gpos->layout = layout; /* can be NULL */
|
||||||
|
|
||||||
if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, stream,
|
|
||||||
gpos->LookupList.Lookup,
|
|
||||||
gpos->LookupList.LookupCount ) ) )
|
|
||||||
goto Fail1;
|
|
||||||
|
|
||||||
*retptr = gpos;
|
*retptr = gpos;
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return HB_Err_Ok;
|
||||||
|
|
||||||
Fail1:
|
|
||||||
_HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
|
|
||||||
|
|
||||||
Fail2:
|
Fail2:
|
||||||
_HB_OPEN_Free_FeatureList( &gpos->FeatureList );
|
_HB_OPEN_Free_FeatureList( &gpos->FeatureList );
|
||||||
|
|
||||||
|
@ -1005,7 +997,7 @@ static HB_Error Lookup_SinglePos( GPOS_Instance* gpi,
|
||||||
if ( context_length != 0xFFFF && context_length < 1 )
|
if ( context_length != 0xFFFF && context_length < 1 )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &sp->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -1568,7 +1560,7 @@ static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
|
||||||
if ( context_length != 0xFFFF && context_length < 2 )
|
if ( context_length != 0xFFFF && context_length < 2 )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &pp->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -1580,7 +1572,7 @@ static HB_Error Lookup_PairPos( GPOS_Instance* gpi,
|
||||||
first_pos = buffer->in_pos;
|
first_pos = buffer->in_pos;
|
||||||
(buffer->in_pos)++;
|
(buffer->in_pos)++;
|
||||||
|
|
||||||
while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
while ( CHECK_Property( gpos->layout, IN_CURITEM(),
|
||||||
flags, &property ) )
|
flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
|
@ -1794,13 +1786,13 @@ static HB_Error Lookup_CursivePos( GPOS_Instance* gpi,
|
||||||
/* Glyphs not having the right GDEF properties will be ignored, i.e.,
|
/* Glyphs not having the right GDEF properties will be ignored, i.e.,
|
||||||
gpi->last won't be reset (contrary to user defined properties). */
|
gpi->last won't be reset (contrary to user defined properties). */
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* We don't handle mark glyphs here. According to Andrei, this isn't
|
/* We don't handle mark glyphs here. According to Andrei, this isn't
|
||||||
possible, but who knows... */
|
possible, but who knows... */
|
||||||
|
|
||||||
if ( property == HB_GDEF_MARK )
|
if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK )
|
||||||
{
|
{
|
||||||
gpi->last = 0xFFFF;
|
gpi->last = 0xFFFF;
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
@ -2216,7 +2208,7 @@ static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
|
||||||
if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
|
if ( flags & HB_LOOKUP_FLAG_IGNORE_BASE_GLYPHS )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(),
|
||||||
flags, &property ) )
|
flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
@ -2232,12 +2224,11 @@ static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
|
||||||
|
|
||||||
while ( i <= buffer->in_pos )
|
while ( i <= buffer->in_pos )
|
||||||
{
|
{
|
||||||
error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
|
||||||
&property );
|
if ( !property )
|
||||||
if ( error )
|
return HB_Err_Not_Covered;
|
||||||
return error;
|
|
||||||
|
|
||||||
if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
@ -2246,7 +2237,7 @@ static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
|
||||||
|
|
||||||
/* The following assertion is too strong -- at least for mangal.ttf. */
|
/* The following assertion is too strong -- at least for mangal.ttf. */
|
||||||
#if 0
|
#if 0
|
||||||
if ( property != HB_GDEF_BASE_GLYPH )
|
if ( property != HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2628,7 +2619,7 @@ static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
|
||||||
|
|
||||||
mark_glyph = IN_CURGLYPH();
|
mark_glyph = IN_CURGLYPH();
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
|
error = _HB_OPEN_Coverage_Index( &mlp->MarkCoverage, mark_glyph, &mark_index );
|
||||||
|
@ -2642,12 +2633,11 @@ static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
|
||||||
|
|
||||||
while ( i <= buffer->in_pos )
|
while ( i <= buffer->in_pos )
|
||||||
{
|
{
|
||||||
error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
|
||||||
&property );
|
if ( !property )
|
||||||
if ( error )
|
return HB_Err_Not_Covered;
|
||||||
return error;
|
|
||||||
|
|
||||||
if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
|
@ -2657,7 +2647,7 @@ static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
|
||||||
/* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
|
/* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
|
||||||
too strong, thus it is commented out. */
|
too strong, thus it is commented out. */
|
||||||
#if 0
|
#if 0
|
||||||
if ( property != HB_GDEF_LIGATURE )
|
if ( property != HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2951,7 +2941,7 @@ static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
|
||||||
if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
|
if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
|
if ( CHECK_Property( gpos->layout, IN_CURITEM(),
|
||||||
flags, &property ) )
|
flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
|
@ -2970,12 +2960,11 @@ static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
|
||||||
j = buffer->in_pos - 1;
|
j = buffer->in_pos - 1;
|
||||||
while ( i <= buffer->in_pos )
|
while ( i <= buffer->in_pos )
|
||||||
{
|
{
|
||||||
error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
|
property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
|
||||||
&property );
|
if ( !property )
|
||||||
if ( error )
|
return HB_Err_Not_Covered;
|
||||||
return error;
|
|
||||||
|
|
||||||
if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
|
if ( flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
|
||||||
|
@ -3780,12 +3769,12 @@ static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi,
|
||||||
HB_GPOSHeader* gpos = gpi->gpos;
|
HB_GPOSHeader* gpos = gpi->gpos;
|
||||||
|
|
||||||
HB_PosRule* pr;
|
HB_PosRule* pr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &cpf1->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -3805,7 +3794,7 @@ static HB_Error Lookup_ContextPos1( GPOS_Instance* gpi,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3849,12 +3838,12 @@ static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,
|
||||||
|
|
||||||
HB_PosClassSet* pcs;
|
HB_PosClassSet* pcs;
|
||||||
HB_PosClassRule* pr;
|
HB_PosClassRule* pr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* Note: The coverage table in format 2 doesn't give an index into
|
/* Note: The coverage table in format 2 doesn't give an index into
|
||||||
|
@ -3900,7 +3889,7 @@ static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End;
|
goto End;
|
||||||
|
@ -3954,12 +3943,12 @@ static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,
|
||||||
HB_GPOSHeader* gpos = gpi->gpos;
|
HB_GPOSHeader* gpos = gpi->gpos;
|
||||||
|
|
||||||
HB_Coverage* c;
|
HB_Coverage* c;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
|
if ( context_length != 0xFFFF && context_length < cpf3->GlyphCount )
|
||||||
|
@ -3972,7 +3961,7 @@ static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,
|
||||||
|
|
||||||
for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
|
for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -4990,12 +4979,12 @@ static HB_Error Lookup_ChainContextPos1(
|
||||||
|
|
||||||
HB_ChainPosRule* cpr;
|
HB_ChainPosRule* cpr;
|
||||||
HB_ChainPosRule curr_cpr;
|
HB_ChainPosRule curr_cpr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &ccpf1->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -5027,7 +5016,7 @@ static HB_Error Lookup_ChainContextPos1(
|
||||||
|
|
||||||
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -5056,7 +5045,7 @@ static HB_Error Lookup_ChainContextPos1(
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -5075,7 +5064,7 @@ static HB_Error Lookup_ChainContextPos1(
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -5130,12 +5119,12 @@ static HB_Error Lookup_ChainContextPos2(
|
||||||
|
|
||||||
HB_ChainPosClassSet* cpcs;
|
HB_ChainPosClassSet* cpcs;
|
||||||
HB_ChainPosClassRule cpcr;
|
HB_ChainPosClassRule cpcr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* Note: The coverage table in format 2 doesn't give an index into
|
/* Note: The coverage table in format 2 doesn't give an index into
|
||||||
|
@ -5198,7 +5187,7 @@ static HB_Error Lookup_ChainContextPos2(
|
||||||
|
|
||||||
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -5230,7 +5219,7 @@ static HB_Error Lookup_ChainContextPos2(
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -5260,7 +5249,7 @@ static HB_Error Lookup_ChainContextPos2(
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -5324,12 +5313,12 @@ static HB_Error Lookup_ChainContextPos3(
|
||||||
HB_Coverage* bc;
|
HB_Coverage* bc;
|
||||||
HB_Coverage* ic;
|
HB_Coverage* ic;
|
||||||
HB_Coverage* lc;
|
HB_Coverage* lc;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gpos->gdef;
|
layout = gpos->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
bgc = ccpf3->BacktrackGlyphCount;
|
bgc = ccpf3->BacktrackGlyphCount;
|
||||||
|
@ -5353,7 +5342,7 @@ static HB_Error Lookup_ChainContextPos3(
|
||||||
|
|
||||||
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -5374,7 +5363,7 @@ static HB_Error Lookup_ChainContextPos3(
|
||||||
for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
|
for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
/* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
|
/* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */
|
||||||
while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( j > buffer->in_pos && CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -5396,7 +5385,7 @@ static HB_Error Lookup_ChainContextPos3(
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
#ifndef HARFBUZZ_GPOS_H
|
#ifndef HARFBUZZ_GPOS_H
|
||||||
#define HARFBUZZ_GPOS_H
|
#define HARFBUZZ_GPOS_H
|
||||||
|
|
||||||
#include "harfbuzz-gdef.h"
|
#include "harfbuzz-open.h"
|
||||||
#include "harfbuzz-buffer.h"
|
#include "harfbuzz-buffer.h"
|
||||||
|
|
||||||
HB_BEGIN_HEADER
|
HB_BEGIN_HEADER
|
||||||
|
@ -86,7 +86,7 @@ struct HB_GPOSHeader_
|
||||||
HB_FeatureList FeatureList;
|
HB_FeatureList FeatureList;
|
||||||
HB_LookupList LookupList;
|
HB_LookupList LookupList;
|
||||||
|
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t *layout;
|
||||||
|
|
||||||
/* the next field is used for a callback function to get the
|
/* the next field is used for a callback function to get the
|
||||||
glyph outline. */
|
glyph outline. */
|
||||||
|
@ -107,7 +107,7 @@ typedef HB_GPOSHeader* HB_GPOS;
|
||||||
|
|
||||||
HB_Error HB_Load_GPOS_Table( HB_Font font,
|
HB_Error HB_Load_GPOS_Table( HB_Font font,
|
||||||
HB_GPOSHeader** gpos,
|
HB_GPOSHeader** gpos,
|
||||||
HB_GDEFHeader* gdef );
|
hb_ot_layout_t *layout );
|
||||||
|
|
||||||
|
|
||||||
HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
|
HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
|
||||||
|
|
|
@ -47,7 +47,7 @@ static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
HB_Error HB_Load_GSUB_Table( HB_Font font,
|
HB_Error HB_Load_GSUB_Table( HB_Font font,
|
||||||
HB_GSUBHeader** retptr,
|
HB_GSUBHeader** retptr,
|
||||||
HB_GDEFHeader* gdef )
|
hb_ot_layout_t *layout )
|
||||||
{
|
{
|
||||||
HB_Stream stream = font->stream;
|
HB_Stream stream = font->stream;
|
||||||
HB_Error error;
|
HB_Error error;
|
||||||
|
@ -55,7 +55,7 @@ HB_Error HB_Load_GSUB_Table( HB_Font font,
|
||||||
|
|
||||||
HB_GSUBHeader* gsub;
|
HB_GSUBHeader* gsub;
|
||||||
|
|
||||||
if ( !retptr )
|
if ( !retptr || !layout )
|
||||||
return ERR(HB_Err_Invalid_Argument);
|
return ERR(HB_Err_Invalid_Argument);
|
||||||
|
|
||||||
if ( GOTO_Table( TTAG_GSUB ) )
|
if ( GOTO_Table( TTAG_GSUB ) )
|
||||||
|
@ -111,20 +111,12 @@ HB_Error HB_Load_GSUB_Table( HB_Font font,
|
||||||
stream, HB_Type_GSUB ) ) != HB_Err_Ok )
|
stream, HB_Type_GSUB ) ) != HB_Err_Ok )
|
||||||
goto Fail2;
|
goto Fail2;
|
||||||
|
|
||||||
gsub->gdef = gdef; /* can be NULL */
|
gsub->layout = layout; /* can be NULL */
|
||||||
|
|
||||||
if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, stream,
|
|
||||||
gsub->LookupList.Lookup,
|
|
||||||
gsub->LookupList.LookupCount ) ) )
|
|
||||||
goto Fail1;
|
|
||||||
|
|
||||||
*retptr = gsub;
|
*retptr = gsub;
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return HB_Err_Ok;
|
||||||
|
|
||||||
Fail1:
|
|
||||||
_HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
|
|
||||||
|
|
||||||
Fail2:
|
Fail2:
|
||||||
_HB_OPEN_Free_FeatureList( &gsub->FeatureList );
|
_HB_OPEN_Free_FeatureList( &gsub->FeatureList );
|
||||||
|
|
||||||
|
@ -271,14 +263,14 @@ static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
|
||||||
HB_UShort index, value, property;
|
HB_UShort index, value, property;
|
||||||
HB_Error error;
|
HB_Error error;
|
||||||
HB_SingleSubst* ss = &st->single;
|
HB_SingleSubst* ss = &st->single;
|
||||||
HB_GDEFHeader* gdef = gsub->gdef;
|
hb_ot_layout_t* layout = gsub->layout;
|
||||||
|
|
||||||
HB_UNUSED(nesting_level);
|
HB_UNUSED(nesting_level);
|
||||||
|
|
||||||
if ( context_length != 0xFFFF && context_length < 1 )
|
if ( context_length != 0xFFFF && context_length < 1 )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &ss->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -305,13 +297,11 @@ static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
|
||||||
return ERR(HB_Err_Invalid_SubTable);
|
return ERR(HB_Err_Invalid_SubTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gdef && gdef->NewGlyphClasses )
|
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||||
{
|
{
|
||||||
/* we inherit the old glyph class to the substituted glyph */
|
/* we inherit the old glyph class to the substituted glyph */
|
||||||
|
|
||||||
error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
|
hb_ot_layout_set_glyph_class (layout, value, property);
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return HB_Err_Ok;
|
||||||
|
@ -477,14 +467,14 @@ static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
|
||||||
HB_UShort index, property, n, count;
|
HB_UShort index, property, n, count;
|
||||||
HB_UShort*s;
|
HB_UShort*s;
|
||||||
HB_MultipleSubst* ms = &st->multiple;
|
HB_MultipleSubst* ms = &st->multiple;
|
||||||
HB_GDEFHeader* gdef = gsub->gdef;
|
hb_ot_layout_t* layout = gsub->layout;
|
||||||
|
|
||||||
HB_UNUSED(nesting_level);
|
HB_UNUSED(nesting_level);
|
||||||
|
|
||||||
if ( context_length != 0xFFFF && context_length < 1 )
|
if ( context_length != 0xFFFF && context_length < 1 )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &ms->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -500,19 +490,15 @@ static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
|
||||||
if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
|
if ( ADD_String( buffer, 1, count, s, 0xFFFF, 0xFFFF ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( gdef && gdef->NewGlyphClasses )
|
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||||
{
|
{
|
||||||
/* this is a guess only ... */
|
/* this is a guess only ... */
|
||||||
|
|
||||||
if ( property == HB_GDEF_LIGATURE )
|
if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
|
||||||
property = HB_GDEF_BASE_GLYPH;
|
property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
|
||||||
|
|
||||||
for ( n = 0; n < count; n++ )
|
for ( n = 0; n < count; n++ )
|
||||||
{
|
hb_ot_layout_set_glyph_class (layout, s[n], property);
|
||||||
error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
|
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return HB_Err_Ok;
|
||||||
|
@ -674,7 +660,7 @@ static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
|
||||||
HB_Error error;
|
HB_Error error;
|
||||||
HB_UShort index, value, alt_index, property;
|
HB_UShort index, value, alt_index, property;
|
||||||
HB_AlternateSubst* as = &st->alternate;
|
HB_AlternateSubst* as = &st->alternate;
|
||||||
HB_GDEFHeader* gdef = gsub->gdef;
|
hb_ot_layout_t* layout = gsub->layout;
|
||||||
HB_AlternateSet aset;
|
HB_AlternateSet aset;
|
||||||
|
|
||||||
HB_UNUSED(nesting_level);
|
HB_UNUSED(nesting_level);
|
||||||
|
@ -682,7 +668,7 @@ static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
|
||||||
if ( context_length != 0xFFFF && context_length < 1 )
|
if ( context_length != 0xFFFF && context_length < 1 )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &as->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -704,14 +690,9 @@ static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
|
||||||
if ( REPLACE_Glyph( buffer, value, nesting_level ) )
|
if ( REPLACE_Glyph( buffer, value, nesting_level ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( gdef && gdef->NewGlyphClasses )
|
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||||
{
|
|
||||||
/* we inherit the old glyph class to the substituted glyph */
|
/* we inherit the old glyph class to the substituted glyph */
|
||||||
|
hb_ot_layout_set_glyph_class (layout, value, property);
|
||||||
error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
|
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return HB_Err_Ok;
|
||||||
}
|
}
|
||||||
|
@ -953,16 +934,16 @@ static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
|
||||||
HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
|
HB_UShort numlig, i, j, is_mark, first_is_mark = FALSE;
|
||||||
HB_UShort* c;
|
HB_UShort* c;
|
||||||
HB_LigatureSubst* ls = &st->ligature;
|
HB_LigatureSubst* ls = &st->ligature;
|
||||||
HB_GDEFHeader* gdef = gsub->gdef;
|
hb_ot_layout_t* layout = gsub->layout;
|
||||||
|
|
||||||
HB_Ligature* lig;
|
HB_Ligature* lig;
|
||||||
|
|
||||||
HB_UNUSED(nesting_level);
|
HB_UNUSED(nesting_level);
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
|
if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS )
|
||||||
first_is_mark = TRUE;
|
first_is_mark = TRUE;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &ls->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -990,7 +971,7 @@ static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -1000,22 +981,16 @@ static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !( property == HB_GDEF_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
if ( !( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK || property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) )
|
||||||
is_mark = FALSE;
|
is_mark = FALSE;
|
||||||
|
|
||||||
if ( IN_GLYPH( j ) != c[i - 1] )
|
if ( IN_GLYPH( j ) != c[i - 1] )
|
||||||
goto next_ligature;
|
goto next_ligature;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( gdef && gdef->NewGlyphClasses )
|
if ( _hb_ot_layout_has_new_glyph_classes (layout) )
|
||||||
{
|
|
||||||
/* this is just a guess ... */
|
/* this is just a guess ... */
|
||||||
|
hb_ot_layout_set_glyph_class (layout, lig->LigGlyph, is_mark ? HB_OT_LAYOUT_GLYPH_CLASS_MARK : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
|
||||||
error = _HB_GDEF_Add_Glyph_Property( gdef, lig->LigGlyph,
|
|
||||||
is_mark ? HB_GDEF_MARK : HB_GDEF_LIGATURE );
|
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
|
if ( j == buffer->in_pos + i ) /* No input glyphs skipped */
|
||||||
{
|
{
|
||||||
|
@ -1051,7 +1026,7 @@ static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0; i < lig->ComponentCount - 1; i++ )
|
for ( i = 0; i < lig->ComponentCount - 1; i++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_CURITEM(),
|
while ( CHECK_Property( layout, IN_CURITEM(),
|
||||||
flags, &property ) )
|
flags, &property ) )
|
||||||
if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
|
if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
|
||||||
return error;
|
return error;
|
||||||
|
@ -1813,12 +1788,12 @@ static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
|
||||||
HB_Error error;
|
HB_Error error;
|
||||||
|
|
||||||
HB_SubRule* sr;
|
HB_SubRule* sr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &csf1->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -1838,7 +1813,7 @@ static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -1880,12 +1855,12 @@ static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
HB_SubClassSet* scs;
|
HB_SubClassSet* scs;
|
||||||
HB_SubClassRule* sr;
|
HB_SubClassRule* sr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* Note: The coverage table in format 2 doesn't give an index into
|
/* Note: The coverage table in format 2 doesn't give an index into
|
||||||
|
@ -1931,7 +1906,7 @@ static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End;
|
goto End;
|
||||||
|
@ -1984,12 +1959,12 @@ static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
|
||||||
HB_UShort index, i, j, property;
|
HB_UShort index, i, j, property;
|
||||||
|
|
||||||
HB_Coverage* c;
|
HB_Coverage* c;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
|
if ( context_length != 0xFFFF && context_length < csf3->GlyphCount )
|
||||||
|
@ -2002,7 +1977,7 @@ static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3004,12 +2979,12 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
HB_ChainSubRule* csr;
|
HB_ChainSubRule* csr;
|
||||||
HB_ChainSubRule curr_csr;
|
HB_ChainSubRule curr_csr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
|
error = _HB_OPEN_Coverage_Index( &ccsf1->Coverage, IN_CURGLYPH(), &index );
|
||||||
|
@ -3041,7 +3016,7 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3070,7 +3045,7 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3089,7 +3064,7 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3142,12 +3117,12 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
HB_ChainSubClassSet* cscs;
|
HB_ChainSubClassSet* cscs;
|
||||||
HB_ChainSubClassRule ccsr;
|
HB_ChainSubClassRule ccsr;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
/* Note: The coverage table in format 2 doesn't give an index into
|
/* Note: The coverage table in format 2 doesn't give an index into
|
||||||
|
@ -3210,7 +3185,7 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -3242,7 +3217,7 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -3272,7 +3247,7 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
goto End1;
|
goto End1;
|
||||||
|
@ -3334,12 +3309,12 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
|
||||||
HB_Coverage* bc;
|
HB_Coverage* bc;
|
||||||
HB_Coverage* ic;
|
HB_Coverage* ic;
|
||||||
HB_Coverage* lc;
|
HB_Coverage* lc;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
bgc = ccsf3->BacktrackGlyphCount;
|
bgc = ccsf3->BacktrackGlyphCount;
|
||||||
|
@ -3363,7 +3338,7 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->out_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, OUT_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, OUT_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3384,7 +3359,7 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
|
||||||
for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
|
for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
|
||||||
{
|
{
|
||||||
/* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
|
/* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */
|
||||||
while ( j > buffer->in_pos && CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( j > buffer->in_pos && CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3406,7 +3381,7 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0; i < lgc; i++, j++ )
|
for ( i = 0; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3653,14 +3628,14 @@ static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
|
||||||
HB_ReverseChainContextSubst* rccs = &st->reverse;
|
HB_ReverseChainContextSubst* rccs = &st->reverse;
|
||||||
HB_Coverage* bc;
|
HB_Coverage* bc;
|
||||||
HB_Coverage* lc;
|
HB_Coverage* lc;
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t* layout;
|
||||||
|
|
||||||
if ( nesting_level != 1 || context_length != 0xFFFF )
|
if ( nesting_level != 1 || context_length != 0xFFFF )
|
||||||
return HB_Err_Not_Covered;
|
return HB_Err_Not_Covered;
|
||||||
|
|
||||||
gdef = gsub->gdef;
|
layout = gsub->layout;
|
||||||
|
|
||||||
if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
|
if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
bgc = rccs->BacktrackGlyphCount;
|
bgc = rccs->BacktrackGlyphCount;
|
||||||
|
@ -3680,7 +3655,7 @@ static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
@ -3706,7 +3681,7 @@ static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
|
||||||
|
|
||||||
for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
|
for ( i = 0, j = buffer->in_pos + 1; i < lgc; i++, j++ )
|
||||||
{
|
{
|
||||||
while ( CHECK_Property( gdef, IN_ITEM( j ), flags, &property ) )
|
while ( CHECK_Property( layout, IN_ITEM( j ), flags, &property ) )
|
||||||
{
|
{
|
||||||
if ( error && error != HB_Err_Not_Covered )
|
if ( error && error != HB_Err_Not_Covered )
|
||||||
return error;
|
return error;
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct HB_GSUBHeader_
|
||||||
HB_FeatureList FeatureList;
|
HB_FeatureList FeatureList;
|
||||||
HB_LookupList LookupList;
|
HB_LookupList LookupList;
|
||||||
|
|
||||||
HB_GDEFHeader* gdef;
|
hb_ot_layout_t *layout;
|
||||||
|
|
||||||
/* the next two fields are used for an alternate substitution callback
|
/* the next two fields are used for an alternate substitution callback
|
||||||
function to select the proper alternate glyph. */
|
function to select the proper alternate glyph. */
|
||||||
|
@ -83,7 +83,7 @@ typedef HB_GSUBHeader* HB_GSUB;
|
||||||
|
|
||||||
HB_Error HB_Load_GSUB_Table( HB_Font font,
|
HB_Error HB_Load_GSUB_Table( HB_Font font,
|
||||||
HB_GSUBHeader** gsub,
|
HB_GSUBHeader** gsub,
|
||||||
HB_GDEFHeader* gdef );
|
hb_ot_layout_t *layout );
|
||||||
|
|
||||||
|
|
||||||
HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
|
HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
|
||||||
|
|
|
@ -34,6 +34,9 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#include "hb-ot-layout-private.h"
|
||||||
|
|
||||||
HB_BEGIN_HEADER
|
HB_BEGIN_HEADER
|
||||||
|
|
||||||
#ifndef HB_INTERNAL
|
#ifndef HB_INTERNAL
|
||||||
|
@ -66,8 +69,12 @@ HB_BEGIN_HEADER
|
||||||
# define HB_UNUSED(arg) ((arg) = (arg))
|
# define HB_UNUSED(arg) ((arg) = (arg))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HB_LIKELY(cond) (cond)
|
#ifndef HB_LIKELY
|
||||||
#define HB_UNLIKELY(cond) (cond)
|
# define HB_LIKELY(cond) (cond)
|
||||||
|
#endif
|
||||||
|
#ifndef HB_UNLIKELY
|
||||||
|
# define HB_UNLIKELY(cond) (cond)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define ALLOC(_ptr,_size) \
|
#define ALLOC(_ptr,_size) \
|
||||||
|
|
|
@ -124,15 +124,6 @@ static HB_Error Load_Script( HB_ScriptTable* s,
|
||||||
|
|
||||||
count = s->LangSysCount = GET_UShort();
|
count = s->LangSysCount = GET_UShort();
|
||||||
|
|
||||||
/* safety check; otherwise the official handling of TrueType Open
|
|
||||||
fonts won't work */
|
|
||||||
|
|
||||||
if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 )
|
|
||||||
{
|
|
||||||
error = HB_Err_Not_Covered;
|
|
||||||
goto Fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
FORGET_Frame();
|
FORGET_Frame();
|
||||||
|
|
||||||
s->LangSysRecord = NULL;
|
s->LangSysRecord = NULL;
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
#include "harfbuzz-global.h"
|
#include "harfbuzz-global.h"
|
||||||
#include "harfbuzz-buffer.h"
|
#include "harfbuzz-buffer.h"
|
||||||
#include "harfbuzz-gdef.h"
|
|
||||||
#include "harfbuzz-gsub.h"
|
#include "harfbuzz-gsub.h"
|
||||||
#include "harfbuzz-gpos.h"
|
#include "harfbuzz-gpos.h"
|
||||||
#include "harfbuzz-open.h"
|
#include "harfbuzz-open.h"
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_COMMON_H
|
||||||
|
#define HB_COMMON_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
# ifdef __cplusplus
|
||||||
|
# define HB_BEGIN_DECLS() extern "C" { extern int hb_dummy_prototype (int)
|
||||||
|
# define HB_END_DECLS() } extern "C" int hb_dummy_prototype (int)
|
||||||
|
# else /* !__cplusplus */
|
||||||
|
# define HB_BEGIN_DECLS() extern int hb_dummy_prototype (int)
|
||||||
|
# define HB_END_DECLS() extern int hb_dummy_prototype (int)
|
||||||
|
# endif /* !__cplusplus */
|
||||||
|
|
||||||
|
typedef int hb_bool_t;
|
||||||
|
|
||||||
|
typedef uint32_t hb_tag_t;
|
||||||
|
#define HB_TAG(a,b,c,d) ((hb_tag_t)(((uint8_t)a<<24)|((uint8_t)b<<16)|((uint8_t)c<<8)|(uint8_t)d))
|
||||||
|
#define HB_TAG_STR(s) (HB_TAG(((const char *) s)[0], \
|
||||||
|
((const char *) s)[1], \
|
||||||
|
((const char *) s)[2], \
|
||||||
|
((const char *) s)[3]))
|
||||||
|
|
||||||
|
typedef uint32_t hb_codepoint_t;
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
typedef struct HB_BufferRec_ hb_buffer_t;
|
||||||
|
|
||||||
|
#endif /* HB_COMMON_H */
|
|
@ -0,0 +1,276 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_GDEF_PRIVATE_H
|
||||||
|
#define HB_OT_LAYOUT_GDEF_PRIVATE_H
|
||||||
|
|
||||||
|
#include "hb-ot-layout-private.h"
|
||||||
|
|
||||||
|
#include "hb-ot-layout-open-private.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP(Type, name) \
|
||||||
|
inline const Type& name (hb_codepoint_t glyph) { \
|
||||||
|
const Coverage &c = get_coverage (); \
|
||||||
|
hb_ot_layout_coverage_t c_index = c.get_coverage (glyph); \
|
||||||
|
return (*this)[c_index]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct GlyphClassDef : ClassDef {
|
||||||
|
static const unsigned int BaseGlyph = 0x0001u;
|
||||||
|
static const unsigned int LigatureGlyph = 0x0002u;
|
||||||
|
static const unsigned int MarkGlyph = 0x0003u;
|
||||||
|
static const unsigned int ComponentGlyph = 0x0004u;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attachment List Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct AttachPoint {
|
||||||
|
|
||||||
|
friend struct AttachList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* countour point indices, in increasing numerical order */
|
||||||
|
DEFINE_ARRAY_TYPE (USHORT, pointIndex, pointCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT pointCount; /* Number of attachment points on
|
||||||
|
* this glyph */
|
||||||
|
USHORT pointIndex[]; /* Array of contour point indices--in
|
||||||
|
* increasing numerical order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (AttachPoint, 2);
|
||||||
|
|
||||||
|
struct AttachList {
|
||||||
|
|
||||||
|
friend struct GDEF;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* const AttachPoint& get_attach_points (hb_codepoint_t glyph); */
|
||||||
|
DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (AttachPoint, get_attach_points);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* AttachPoint tables, in Coverage Index order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (AttachPoint, attachPoint, glyphCount);
|
||||||
|
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Offset coverage; /* Offset to Coverage table -- from
|
||||||
|
* beginning of AttachList table */
|
||||||
|
USHORT glyphCount; /* Number of glyphs with attachment
|
||||||
|
* points */
|
||||||
|
Offset attachPoint[]; /* Array of offsets to AttachPoint
|
||||||
|
* tables--from beginning of AttachList
|
||||||
|
* table--in Coverage Index order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (AttachList, 4);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ligature Caret Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct CaretValueFormat1 {
|
||||||
|
|
||||||
|
friend struct CaretValue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline int get_caret_value (int ppem) const {
|
||||||
|
return /* TODO garbage */ coordinate / ppem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT caretValueFormat; /* Format identifier--format = 1 */
|
||||||
|
SHORT coordinate; /* X or Y value, in design units */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (CaretValueFormat1, 4);
|
||||||
|
|
||||||
|
struct CaretValueFormat2 {
|
||||||
|
|
||||||
|
friend struct CaretValue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline int get_caret_value (int ppem) const {
|
||||||
|
return /* TODO garbage */ 0 / ppem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT caretValueFormat; /* Format identifier--format = 2 */
|
||||||
|
USHORT caretValuePoint; /* Contour point index on glyph */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (CaretValueFormat2, 4);
|
||||||
|
|
||||||
|
struct CaretValueFormat3 {
|
||||||
|
|
||||||
|
friend struct CaretValue;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const Device& get_device (void) const {
|
||||||
|
if (HB_UNLIKELY (!deviceTable)) return NullDevice;
|
||||||
|
return *(const Device*)((const char*)this + deviceTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int get_caret_value (int ppem) const {
|
||||||
|
return /* TODO garbage */ (coordinate + get_device().get_delta (ppem)) / ppem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT caretValueFormat; /* Format identifier--format = 3 */
|
||||||
|
SHORT coordinate; /* X or Y value, in design units */
|
||||||
|
Offset deviceTable; /* Offset to Device table for X or Y
|
||||||
|
* value--from beginning of CaretValue
|
||||||
|
* table */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (CaretValueFormat3, 6);
|
||||||
|
|
||||||
|
struct CaretValue {
|
||||||
|
DEFINE_NON_INSTANTIABLE(CaretValue);
|
||||||
|
|
||||||
|
unsigned int get_size (void) const {
|
||||||
|
switch (u.caretValueFormat) {
|
||||||
|
case 1: return sizeof (u.format1);
|
||||||
|
case 2: return sizeof (u.format2);
|
||||||
|
case 3: return sizeof (u.format3);
|
||||||
|
default:return sizeof (u.caretValueFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX we need access to a load-contour-point vfunc here */
|
||||||
|
int get_caret_value (int ppem) const {
|
||||||
|
switch (u.caretValueFormat) {
|
||||||
|
case 1: return u.format1.get_caret_value(ppem);
|
||||||
|
case 2: return u.format2.get_caret_value(ppem);
|
||||||
|
case 3: return u.format3.get_caret_value(ppem);
|
||||||
|
default:return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
USHORT caretValueFormat; /* Format identifier */
|
||||||
|
CaretValueFormat1 format1;
|
||||||
|
CaretValueFormat2 format2;
|
||||||
|
CaretValueFormat3 format3;
|
||||||
|
/* FIXME old HarfBuzz code has a format 4 here! */
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
DEFINE_NULL (CaretValue, 2);
|
||||||
|
|
||||||
|
struct LigGlyph {
|
||||||
|
|
||||||
|
friend struct LigCaretList;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Caret value tables, in increasing coordinate order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (CaretValue, caretValue, caretCount);
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT caretCount; /* Number of CaretValues for this
|
||||||
|
* ligature (components - 1) */
|
||||||
|
Offset caretValue[]; /* Array of offsets to CaretValue
|
||||||
|
* tables--from beginning of LigGlyph
|
||||||
|
* table--in increasing coordinate
|
||||||
|
* order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LigGlyph, 2);
|
||||||
|
|
||||||
|
struct LigCaretList {
|
||||||
|
|
||||||
|
friend struct GDEF;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* const LigGlyph& get_lig_glyph (hb_codepoint_t glyph); */
|
||||||
|
DEFINE_INDIRECT_GLYPH_ARRAY_LOOKUP (LigGlyph, get_lig_glyph);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* AttachPoint tables, in Coverage Index order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (LigGlyph, ligGlyph, ligGlyphCount);
|
||||||
|
DEFINE_GET_ACCESSOR (Coverage, coverage, coverage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of LigCaretList table */
|
||||||
|
USHORT ligGlyphCount; /* Number of ligature glyphs */
|
||||||
|
Offset ligGlyph[]; /* Array of offsets to LigGlyph
|
||||||
|
* tables--from beginning of
|
||||||
|
* LigCaretList table--in Coverage
|
||||||
|
* Index order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LigCaretList, 4);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDEF
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct GDEF {
|
||||||
|
static const hb_tag_t Tag = HB_TAG ('G','D','E','F');
|
||||||
|
|
||||||
|
static const hb_ot_layout_class_t UnclassifiedGlyph = 0;
|
||||||
|
static const hb_ot_layout_class_t BaseGlyph = 1;
|
||||||
|
static const hb_ot_layout_class_t LigatureGlyph = 2;
|
||||||
|
static const hb_ot_layout_class_t MarkGlyph = 3;
|
||||||
|
static const hb_ot_layout_class_t ComponentGlyph = 4;
|
||||||
|
|
||||||
|
STATIC_DEFINE_GET_FOR_DATA (GDEF);
|
||||||
|
/* XXX check version here? */
|
||||||
|
|
||||||
|
DEFINE_GET_HAS_ACCESSOR (ClassDef, glyph_classes, glyphClassDef);
|
||||||
|
DEFINE_GET_HAS_ACCESSOR (AttachList, attach_list, attachList);
|
||||||
|
DEFINE_GET_HAS_ACCESSOR (LigCaretList, lig_caret_list, ligCaretList);
|
||||||
|
DEFINE_GET_HAS_ACCESSOR (ClassDef, mark_attachment_types, markAttachClassDef);
|
||||||
|
|
||||||
|
inline hb_ot_layout_class_t get_glyph_class (hb_codepoint_t glyph) const {
|
||||||
|
return get_glyph_classes ().get_class (glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline hb_ot_layout_class_t get_mark_attachment_type (hb_codepoint_t glyph) const {
|
||||||
|
return get_mark_attachment_types ().get_class (glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO get_attach and get_lig_caret */
|
||||||
|
|
||||||
|
private:
|
||||||
|
Fixed version; /* Version of the GDEF table--initially
|
||||||
|
* 0x00010000 */
|
||||||
|
Offset glyphClassDef; /* Offset to class definition table
|
||||||
|
* for glyph type--from beginning of
|
||||||
|
* GDEF header (may be Null) */
|
||||||
|
Offset attachList; /* Offset to list of glyphs with
|
||||||
|
* attachment points--from beginning
|
||||||
|
* of GDEF header (may be Null) */
|
||||||
|
Offset ligCaretList; /* Offset to list of positioning points
|
||||||
|
* for ligature carets--from beginning
|
||||||
|
* of GDEF header (may be Null) */
|
||||||
|
Offset markAttachClassDef; /* Offset to class definition table for
|
||||||
|
* mark attachment type--from beginning
|
||||||
|
* of GDEF header (may be Null) */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (GDEF, 12);
|
||||||
|
|
||||||
|
#endif /* HB_OT_LAYOUT_GDEF_PRIVATE_H */
|
|
@ -0,0 +1,583 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_GSUB_PRIVATE_H
|
||||||
|
#define HB_OT_LAYOUT_GSUB_PRIVATE_H
|
||||||
|
|
||||||
|
#include "hb-ot-layout-private.h"
|
||||||
|
|
||||||
|
#include "hb-ot-layout-open-private.h"
|
||||||
|
#include "hb-ot-layout-gdef-private.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct SingleSubstFormat1 {
|
||||||
|
|
||||||
|
friend struct SingleSubst;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline bool substitute (hb_ot_layout_t *layout,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
unsigned int context_length,
|
||||||
|
unsigned int nesting_level_left) const {
|
||||||
|
// if (get_coverage (IN_CURGLYPH()))
|
||||||
|
// return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
SHORT deltaGlyphID; /* Add to original GlyphID to get
|
||||||
|
* substitute GlyphID */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (SingleSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct SingleSubstFormat2 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 2 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||||
|
* array */
|
||||||
|
GlyphID substitute[]; /* Array of substitute
|
||||||
|
* GlyphIDs--ordered by Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (SingleSubstFormat2, 6);
|
||||||
|
|
||||||
|
struct MultipleSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT sequenceCount; /* Number of Sequence table offsets in
|
||||||
|
* the Sequence array */
|
||||||
|
Offset sequence[]; /* Array of offsets to Sequence
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (MultipleSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct Sequence {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||||
|
* array. This should always be
|
||||||
|
* greater than 0. */
|
||||||
|
GlyphID substitute[]; /* String of GlyphIDs to substitute */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Sequence, 2);
|
||||||
|
|
||||||
|
struct AlternateSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT alternateSetCount; /* Number of AlternateSet tables */
|
||||||
|
Offset alternateSet[]; /* Array of offsets to AlternateSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (AlternateSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct AlternateSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT glyphCount; /* Number of GlyphIDs in the Alternate
|
||||||
|
* array */
|
||||||
|
GlyphID alternate[]; /* Array of alternate GlyphIDs--in
|
||||||
|
* arbitrary order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (AlternateSet, 2);
|
||||||
|
|
||||||
|
struct LigatureSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT ligSetCount; /* Number of LigatureSet tables */
|
||||||
|
Offset ligatureSet[]; /* Array of offsets to LigatureSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (LigatureSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct LigatureSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT ligatureCount; /* Number of Ligature tables */
|
||||||
|
Offset ligature[]; /* Array of offsets to Ligature
|
||||||
|
* tables--from beginning of
|
||||||
|
* LigatureSet table--ordered by
|
||||||
|
* preference */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LigatureSet, 2);
|
||||||
|
|
||||||
|
struct Ligature {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
GlyphID ligGlyph; /* GlyphID of ligature to substitute */
|
||||||
|
USHORT compCount; /* Number of components in the ligature */
|
||||||
|
GlyphID component[]; /* Array of component GlyphIDs--start
|
||||||
|
* with the second component--ordered
|
||||||
|
* in writing direction */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Ligature, 4);
|
||||||
|
|
||||||
|
struct SubstLookupRecord {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT sequenceIndex; /* Index into current glyph
|
||||||
|
* sequence--first glyph = 0 */
|
||||||
|
USHORT lookupListIndex; /* Lookup to apply to that
|
||||||
|
* position--zero--based */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SubstLookupRecord, 4);
|
||||||
|
|
||||||
|
struct ContextSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT subRuleSetCount; /* Number of SubRuleSet tables--must
|
||||||
|
* equal GlyphCount in Coverage table */
|
||||||
|
Offset subRuleSet[]; /* Array of offsets to SubRuleSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ContextSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct SubRuleSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT subRuleCount; /* Number of SubRule tables */
|
||||||
|
Offset subRule[]; /* Array of offsets to SubRule
|
||||||
|
* tables--from beginning of SubRuleSet
|
||||||
|
* table--ordered by preference */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SubRuleSet, 2);
|
||||||
|
|
||||||
|
struct SubRule {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT glyphCount; /* Total number of glyphs in input
|
||||||
|
* glyph sequence--includes the first
|
||||||
|
* glyph */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
GlyphID input[]; /* Array of input GlyphIDs--start with
|
||||||
|
* second glyph */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SubRule, 4);
|
||||||
|
|
||||||
|
struct ContextSubstFormat2 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 2 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
Offset classDef; /* Offset to glyph ClassDef table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT subClassSetCnt; /* Number of SubClassSet tables */
|
||||||
|
Offset subClassSet[]; /* Array of offsets to SubClassSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* class--may be NULL */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ContextSubstFormat2, 8);
|
||||||
|
|
||||||
|
struct SubClassSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT subClassRuleCnt; /* Number of SubClassRule tables */
|
||||||
|
Offset subClassRule[]; /* Array of offsets to SubClassRule
|
||||||
|
* tables--from beginning of
|
||||||
|
* SubClassSet--ordered by preference */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SubClassSet, 2);
|
||||||
|
|
||||||
|
struct SubClassRule {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT glyphCount; /* Total number of classes
|
||||||
|
* specified for the context in the
|
||||||
|
* rule--includes the first class */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
USHORT klass[]; /* Array of classes--beginning with the
|
||||||
|
* second class--to be matched to the
|
||||||
|
* input glyph class sequence */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SubClassRule, 4);
|
||||||
|
|
||||||
|
struct ContextSubstFormat3 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 3 */
|
||||||
|
USHORT glyphCount; /* Number of glyphs in the input glyph
|
||||||
|
* sequence */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
Offset coverage[]; /* Array of offsets to Coverage
|
||||||
|
* table--from beginning of
|
||||||
|
* Substitution table--in glyph
|
||||||
|
* sequence order */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ContextSubstFormat3, 6);
|
||||||
|
|
||||||
|
struct ChainContextSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT chainSubRuleSetCount; /* Number of ChainSubRuleSet
|
||||||
|
* tables--must equal GlyphCount in
|
||||||
|
* Coverage table */
|
||||||
|
Offset chainSubRuleSet[]; /* Array of offsets to ChainSubRuleSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by
|
||||||
|
* Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ChainContextSubstFormat1, 6);
|
||||||
|
|
||||||
|
struct ChainSubRuleSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT chainSubRuleCount; /* Number of ChainSubRule tables */
|
||||||
|
Offset chainSubRule[]; /* Array of offsets to ChainSubRule
|
||||||
|
* tables--from beginning of
|
||||||
|
* ChainSubRuleSet table--ordered
|
||||||
|
* by preference */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ChainSubRuleSet, 2);
|
||||||
|
|
||||||
|
struct ChainSubRule {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT backtrackGlyphCount; /* Total number of glyphs in the
|
||||||
|
* backtrack sequence (number of
|
||||||
|
* glyphs to be matched before the
|
||||||
|
* first glyph) */
|
||||||
|
GlyphID backtrack[]; /* Array of backtracking GlyphID's
|
||||||
|
* (to be matched before the input
|
||||||
|
* sequence) */
|
||||||
|
USHORT inputGlyphCount; /* Total number of glyphs in the input
|
||||||
|
* sequence (includes the first glyph) */
|
||||||
|
GlyphID input[]; /* Array of input GlyphIDs (start with
|
||||||
|
* second glyph) */
|
||||||
|
USHORT lookaheadGlyphCount; /* Total number of glyphs in the look
|
||||||
|
* ahead sequence (number of glyphs to
|
||||||
|
* be matched after the input sequence) */
|
||||||
|
GlyphID lookAhead[]; /* Array of lookahead GlyphID's (to be
|
||||||
|
* matched after the input sequence) */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order) */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ChainSubRule, 8);
|
||||||
|
|
||||||
|
struct ChainContextSubstFormat2 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 2 */
|
||||||
|
Offset coverage; /* Offset to Coverage table--from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
Offset backtrackClassDef; /* Offset to glyph ClassDef table
|
||||||
|
* containing backtrack sequence
|
||||||
|
* data--from beginning of Substitution
|
||||||
|
* table */
|
||||||
|
Offset inputClassDef; /* Offset to glyph ClassDef
|
||||||
|
* table containing input sequence
|
||||||
|
* data--from beginning of Substitution
|
||||||
|
* table */
|
||||||
|
Offset lookaheadClassDef; /* Offset to glyph ClassDef table
|
||||||
|
* containing lookahead sequence
|
||||||
|
* data--from beginning of Substitution
|
||||||
|
* table */
|
||||||
|
USHORT chainSubClassSetCnt; /* Number of ChainSubClassSet tables */
|
||||||
|
Offset chainSubClassSet[]; /* Array of offsets to ChainSubClassSet
|
||||||
|
* tables--from beginning of
|
||||||
|
* Substitution table--ordered by input
|
||||||
|
* class--may be NULL */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ChainContextSubstFormat2, 12);
|
||||||
|
|
||||||
|
struct ChainSubClassSet {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT chainSubClassRuleCnt; /* Number of ChainSubClassRule tables */
|
||||||
|
Offset chainSubClassRule[]; /* Array of offsets
|
||||||
|
* to ChainSubClassRule
|
||||||
|
* tables--from beginning of
|
||||||
|
* ChainSubClassSet--ordered by
|
||||||
|
* preference */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ChainSubClassSet, 2);
|
||||||
|
|
||||||
|
struct ChainSubClassRule {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT backtrackGlyphCount; /* Total number of glyphs in the
|
||||||
|
* backtrack sequence (number of
|
||||||
|
* glyphs to be matched before the
|
||||||
|
* first glyph) */
|
||||||
|
USHORT backtrack[]; /* Array of backtracking classes(to be
|
||||||
|
* matched before the input sequence) */
|
||||||
|
USHORT inputGlyphCount; /* Total number of classes in the input
|
||||||
|
* sequence (includes the first class) */
|
||||||
|
USHORT input[]; /* Array of input classes(start with
|
||||||
|
* second class; to be matched with
|
||||||
|
* the input glyph sequence) */
|
||||||
|
USHORT lookaheadGlyphCount; /* Total number of classes in the
|
||||||
|
* look ahead sequence (number of
|
||||||
|
* classes to be matched after the
|
||||||
|
* input sequence) */
|
||||||
|
USHORT lookAhead[]; /* Array of lookahead classes(to be
|
||||||
|
* matched after the input sequence) */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order) */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ChainSubClassRule, 8);
|
||||||
|
|
||||||
|
struct ChainContextSubstFormat3 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 3 */
|
||||||
|
USHORT backtrackGlyphCount; /* Number of glyphs in the backtracking
|
||||||
|
* sequence */
|
||||||
|
Offset backtrackCoverage[]; /* Array of offsets to coverage tables
|
||||||
|
* in backtracking sequence, in glyph
|
||||||
|
* sequence order */
|
||||||
|
USHORT inputGlyphCount; /* Number of glyphs in input sequence */
|
||||||
|
Offset inputCoverage[]; /* Array of offsets to coverage
|
||||||
|
* tables in input sequence, in glyph
|
||||||
|
* sequence order */
|
||||||
|
USHORT lookaheadGlyphCount; /* Number of glyphs in lookahead
|
||||||
|
* sequence */
|
||||||
|
Offset lookaheadCoverage[]; /* Array of offsets to coverage tables
|
||||||
|
* in lookahead sequence, in glyph
|
||||||
|
* sequence order */
|
||||||
|
USHORT substCount; /* Number of SubstLookupRecords */
|
||||||
|
SubstLookupRecord substLookupRecord[];/* Array of SubstLookupRecords--in
|
||||||
|
* design order */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ChainContextSubstFormat3, 10);
|
||||||
|
|
||||||
|
struct ExtensionSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier. Set to 1. */
|
||||||
|
USHORT extensionLookupType; /* Lookup type of subtable referenced
|
||||||
|
* by ExtensionOffset (i.e. the
|
||||||
|
* extension subtable). */
|
||||||
|
ULONG extensionOffset; /* Offset to the extension subtable,
|
||||||
|
* of lookup type subtable. */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ExtensionSubstFormat1, 8);
|
||||||
|
|
||||||
|
struct ReverseChainSingleSubstFormat1 {
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT substFormat; /* Format identifier--format = 1 */
|
||||||
|
Offset coverage; /* Offset to Coverage table -- from
|
||||||
|
* beginning of Substitution table */
|
||||||
|
USHORT backtrackGlyphCount; /* Number of glyphs in the backtracking
|
||||||
|
* sequence */
|
||||||
|
Offset backtrackCoverage[]; /* Array of offsets to coverage tables
|
||||||
|
* in backtracking sequence, in glyph
|
||||||
|
* sequence order */
|
||||||
|
USHORT lookaheadGlyphCount; /* Number of glyphs in lookahead
|
||||||
|
* sequence */
|
||||||
|
Offset lookaheadCoverage[]; /* Array of offsets to coverage tables
|
||||||
|
* in lookahead sequence, in glyph
|
||||||
|
* sequence order */
|
||||||
|
USHORT glyphCount; /* Number of GlyphIDs in the Substitute
|
||||||
|
* array */
|
||||||
|
GlyphID substitute[]; /* Array of substitute
|
||||||
|
* GlyphIDs--ordered by Coverage Index */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ReverseChainSingleSubstFormat1, 10);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SubstLookup
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct SubstLookupSubTable {
|
||||||
|
DEFINE_NON_INSTANTIABLE(SubstLookupSubTable);
|
||||||
|
|
||||||
|
friend struct SubstLookup;
|
||||||
|
|
||||||
|
unsigned int get_size (unsigned int lookup_type) const {
|
||||||
|
switch (lookup_type) {
|
||||||
|
// case 1: return u.format1.get_size ();
|
||||||
|
// case 2: return u.format2.get_size ();
|
||||||
|
/*
|
||||||
|
case Single:
|
||||||
|
case Multiple:
|
||||||
|
case Alternate:
|
||||||
|
case Ligature:
|
||||||
|
case Context:
|
||||||
|
case ChainingContext:
|
||||||
|
case Extension:
|
||||||
|
case ReverseChainingContextSingle:
|
||||||
|
*/
|
||||||
|
default:return sizeof (LookupSubTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool substitute (hb_ot_layout_t *layout,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
unsigned int context_length,
|
||||||
|
unsigned int nesting_level_left,
|
||||||
|
unsigned int lookup_type) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
USHORT substFormat;
|
||||||
|
CoverageFormat1 format1;
|
||||||
|
CoverageFormat2 format2;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SubstLookup : Lookup {
|
||||||
|
|
||||||
|
DEFINE_NON_INSTANTIABLE(SubstLookup);
|
||||||
|
|
||||||
|
static const unsigned int Single = 1;
|
||||||
|
static const unsigned int Multiple = 2;
|
||||||
|
static const unsigned int Alternate = 3;
|
||||||
|
static const unsigned int Ligature = 4;
|
||||||
|
static const unsigned int Context = 5;
|
||||||
|
static const unsigned int ChainingContext = 6;
|
||||||
|
static const unsigned int Extension = 7;
|
||||||
|
static const unsigned int ReverseChainingContextSingle = 8;
|
||||||
|
|
||||||
|
inline const SubstLookupSubTable& get_subtable (unsigned int i) const {
|
||||||
|
return *(SubstLookupSubTable*)&(((Lookup *)this)->get_subtable (i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Like get_type(), but looks through extension lookups.
|
||||||
|
* Never returns SubstLookup::Extension */
|
||||||
|
inline unsigned int get_effective_type (void) const {
|
||||||
|
unsigned int type = get_type ();
|
||||||
|
|
||||||
|
if (HB_UNLIKELY (type == Extension)) {
|
||||||
|
/* Return lookup type of first extension subtable.
|
||||||
|
* The spec says all of them should have the same type.
|
||||||
|
* XXX check for that somehow */
|
||||||
|
//XXX type = get_subtable(0).v.extension.get_type ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool is_reverse (void) const {
|
||||||
|
switch (get_effective_type ()) {
|
||||||
|
case ReverseChainingContextSingle: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool substitute (hb_ot_layout_t *layout,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
unsigned int context_length,
|
||||||
|
unsigned int nesting_level_left) const {
|
||||||
|
unsigned int lookup_type = get_type ();
|
||||||
|
|
||||||
|
if (HB_UNLIKELY (nesting_level_left == 0))
|
||||||
|
return false;
|
||||||
|
nesting_level_left--;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < get_subtable_count (); i++)
|
||||||
|
if (get_subtable (i).substitute (layout, buffer,
|
||||||
|
context_length, nesting_level_left,
|
||||||
|
lookup_type))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ALIAS (SubstLookup, Lookup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct GSUB : GSUBGPOS {
|
||||||
|
static const hb_tag_t Tag = HB_TAG ('G','S','U','B');
|
||||||
|
|
||||||
|
STATIC_DEFINE_GET_FOR_DATA (GSUB);
|
||||||
|
/* XXX check version here? */
|
||||||
|
|
||||||
|
inline const SubstLookup& get_lookup (unsigned int i) const {
|
||||||
|
return *(SubstLookup*)&(((GSUBGPOS *)this)->get_lookup (i));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ALIAS (GSUB, GSUBGPOS);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HB_OT_LAYOUT_GSUB_PRIVATE_H */
|
|
@ -0,0 +1,993 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_OPEN_PRIVATE_H
|
||||||
|
#define HB_OT_LAYOUT_OPEN_PRIVATE_H
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_CC
|
||||||
|
#error "This file should only be included from hb-ot-layout.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "hb-ot-layout-private.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define NO_INDEX ((unsigned int) 0xFFFF)
|
||||||
|
#define NO_CONTEXT ((unsigned int) -1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Int types
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX define these as structs of chars on machines that do not allow
|
||||||
|
* unaligned access */
|
||||||
|
#define DEFINE_INT_TYPE1(NAME, TYPE, BIG_ENDIAN) \
|
||||||
|
inline NAME& operator = (TYPE i) { v = BIG_ENDIAN(i); return *this; } \
|
||||||
|
inline operator TYPE(void) const { return BIG_ENDIAN(v); } \
|
||||||
|
inline bool operator== (NAME o) const { return v == o.v; } \
|
||||||
|
private: TYPE v; \
|
||||||
|
public:
|
||||||
|
#define DEFINE_INT_TYPE0(NAME, type) DEFINE_INT_TYPE1 (NAME, type, hb_be_##type)
|
||||||
|
#define DEFINE_INT_TYPE(NAME, u, w) DEFINE_INT_TYPE0 (NAME, u##int##w##_t)
|
||||||
|
#define DEFINE_INT_TYPE_STRUCT(NAME, u, w) \
|
||||||
|
struct NAME { \
|
||||||
|
DEFINE_INT_TYPE(NAME, u, w) \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Array types
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* get_len() is a method returning the number of items in an array-like object */
|
||||||
|
#define DEFINE_LEN(Type, array, num) \
|
||||||
|
inline unsigned int get_len(void) const { return num; } \
|
||||||
|
|
||||||
|
/* get_size() is a method returning the size in bytes of an array-like object */
|
||||||
|
#define DEFINE_SIZE(Type, array, num) \
|
||||||
|
inline unsigned int get_size(void) const { return sizeof (*this) + sizeof (Type) * num; }
|
||||||
|
|
||||||
|
#define DEFINE_LEN_AND_SIZE(Type, array, num) \
|
||||||
|
DEFINE_LEN(Type, array, num) \
|
||||||
|
DEFINE_SIZE(Type, array, num)
|
||||||
|
|
||||||
|
/* An array type is one that contains a variable number of objects
|
||||||
|
* as its last item. An array object is extended with len() and size()
|
||||||
|
* methods, as well as overloaded [] operator. */
|
||||||
|
#define DEFINE_ARRAY_TYPE(Type, array, num) \
|
||||||
|
DEFINE_INDEX_OPERATOR(Type, array, num) \
|
||||||
|
DEFINE_LEN_AND_SIZE(Type, array, num)
|
||||||
|
#define DEFINE_INDEX_OPERATOR(Type, array, num) \
|
||||||
|
inline const Type& operator[] (unsigned int i) const { \
|
||||||
|
if (HB_UNLIKELY (i >= num)) return Null##Type; \
|
||||||
|
return array[i]; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* An offset array type is like an array type, but it contains a table
|
||||||
|
* of offsets to the objects, relative to the beginning of the current
|
||||||
|
* object. */
|
||||||
|
#define DEFINE_OFFSET_ARRAY_TYPE(Type, array, num) \
|
||||||
|
DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
|
||||||
|
DEFINE_LEN_AND_SIZE(Offset, array, num)
|
||||||
|
#define DEFINE_OFFSET_INDEX_OPERATOR(Type, array, num) \
|
||||||
|
inline const Type& operator[] (unsigned int i) const { \
|
||||||
|
if (HB_UNLIKELY (i >= num)) return Null##Type; \
|
||||||
|
if (HB_UNLIKELY (!array[i])) return Null##Type; \
|
||||||
|
return *(const Type *)((const char*)this + array[i]); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A record array type is like an array type, but it contains a table
|
||||||
|
* of records to the objects. Each record has a tag, and an offset
|
||||||
|
* relative to the beginning of the current object. */
|
||||||
|
#define DEFINE_RECORD_ARRAY_TYPE(Type, array, num) \
|
||||||
|
DEFINE_RECORD_ACCESSOR(Type, array, num) \
|
||||||
|
DEFINE_LEN_AND_SIZE(Record, array, num)
|
||||||
|
#define DEFINE_RECORD_ACCESSOR(Type, array, num) \
|
||||||
|
inline const Type& operator[] (unsigned int i) const { \
|
||||||
|
if (HB_UNLIKELY (i >= num)) return Null##Type; \
|
||||||
|
if (HB_UNLIKELY (!array[i].offset)) return Null##Type; \
|
||||||
|
return *(const Type *)((const char*)this + array[i].offset); \
|
||||||
|
} \
|
||||||
|
inline const Tag& get_tag (unsigned int i) const { \
|
||||||
|
if (HB_UNLIKELY (i >= num)) return NullTag; \
|
||||||
|
return array[i].tag; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_ARRAY_INTERFACE(Type, name) \
|
||||||
|
inline const Type& get_##name (unsigned int i) const { \
|
||||||
|
return (*this)[i]; \
|
||||||
|
} \
|
||||||
|
inline unsigned int get_##name##_count (void) const { \
|
||||||
|
return this->get_len (); \
|
||||||
|
}
|
||||||
|
#define DEFINE_INDEX_ARRAY_INTERFACE(name) \
|
||||||
|
inline unsigned int get_##name##_index (unsigned int i) const { \
|
||||||
|
if (HB_UNLIKELY (i >= get_len ())) return NO_INDEX; \
|
||||||
|
return (*this)[i]; \
|
||||||
|
} \
|
||||||
|
inline unsigned int get_##name##_count (void) const { \
|
||||||
|
return get_len (); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEFINE_LIST_ARRAY(Type, name) \
|
||||||
|
inline const Type##List& get_##name##_list (void) const { \
|
||||||
|
if (HB_UNLIKELY (!name##List)) return Null##Type##List; \
|
||||||
|
return *(const Type##List *)((const char*)this + name##List); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_LIST_INTERFACE(Type, name) \
|
||||||
|
inline const Type& get_##name (unsigned int i) const { \
|
||||||
|
return get_##name##_list ()[i]; \
|
||||||
|
} \
|
||||||
|
inline unsigned int get_##name##_count (void) const { \
|
||||||
|
return get_##name##_list ().get_len (); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tag types
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEFINE_TAG_ARRAY_INTERFACE(Type, name) \
|
||||||
|
DEFINE_ARRAY_INTERFACE (Type, name); \
|
||||||
|
inline const Tag& get_##name##_tag (unsigned int i) const { \
|
||||||
|
return (*this)[i].tag; \
|
||||||
|
}
|
||||||
|
#define DEFINE_TAG_LIST_INTERFACE(Type, name) \
|
||||||
|
DEFINE_LIST_INTERFACE (Type, name); \
|
||||||
|
inline const Tag& get_##name##_tag (unsigned int i) const { \
|
||||||
|
return get_##name##_list ().get_tag (i); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_TAG_FIND_INTERFACE(Type, name) \
|
||||||
|
inline bool find_##name##_index (hb_tag_t tag, unsigned int *name##_index) const { \
|
||||||
|
const Tag t = tag; \
|
||||||
|
for (unsigned int i = 0; i < get_##name##_count (); i++) { \
|
||||||
|
if (t == get_##name##_tag (i)) { \
|
||||||
|
if (name##_index) *name##_index = i; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (name##_index) *name##_index = NO_INDEX; \
|
||||||
|
return false; \
|
||||||
|
} \
|
||||||
|
inline const Type& get_##name##_by_tag (hb_tag_t tag) const { \
|
||||||
|
unsigned int i; \
|
||||||
|
if (find_##name##_index (tag, &i)) \
|
||||||
|
return get_##name (i); \
|
||||||
|
else \
|
||||||
|
return Null##Type; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class features
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* makes class uninstantiable. should be used for union classes that don't
|
||||||
|
* contain any complete type */
|
||||||
|
#define DEFINE_NON_INSTANTIABLE(Type) \
|
||||||
|
protected: inline Type() {} /* cannot be instantiated */ \
|
||||||
|
public:
|
||||||
|
|
||||||
|
// TODO use a global nul-array for most Null's
|
||||||
|
/* defines Null##Type as a safe nil instance of Type */
|
||||||
|
#define DEFINE_NULL_DATA(Type, size, data) \
|
||||||
|
static const unsigned char Null##Type##Data[size] = data; \
|
||||||
|
DEFINE_NULL_ALIAS (Type, Type)
|
||||||
|
#define DEFINE_NULL(Type, size) \
|
||||||
|
DEFINE_NULL_DATA(Type, size, "")
|
||||||
|
#define DEFINE_NULL_ASSERT_SIZE(Type, size) \
|
||||||
|
DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, "")
|
||||||
|
#define DEFINE_NULL_ASSERT_SIZE_DATA(Type, size, data) \
|
||||||
|
ASSERT_SIZE (Type, size); \
|
||||||
|
DEFINE_NULL_DATA (Type, size, data)
|
||||||
|
#define DEFINE_NULL_ALIAS(NewType, OldType) \
|
||||||
|
/* XXX static */ const NewType &Null##NewType = *(NewType *)Null##OldType##Data
|
||||||
|
|
||||||
|
/* get_for_data() is a static class method returning a reference to an
|
||||||
|
* instance of Type located at the input data location. It's just a
|
||||||
|
* fancy, NULL-safe, cast! */
|
||||||
|
#define STATIC_DEFINE_GET_FOR_DATA(Type) \
|
||||||
|
static inline const Type& get_for_data (const char *data) { \
|
||||||
|
extern const Type &Null##Type; \
|
||||||
|
if (HB_UNLIKELY (data == NULL)) return Null##Type; \
|
||||||
|
return *(const Type*)data; \
|
||||||
|
} \
|
||||||
|
static inline Type& get_for_data (char *data) { \
|
||||||
|
return *(Type*)data; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFINE_GET_ACCESSOR(Type, name, Name) \
|
||||||
|
inline const Type& get_##name (void) const { \
|
||||||
|
if (HB_UNLIKELY (!Name)) return Null##Type; \
|
||||||
|
return *(const Type*)((const char*)this + Name); \
|
||||||
|
}
|
||||||
|
#define DEFINE_GET_HAS_ACCESSOR(Type, name, Name) \
|
||||||
|
DEFINE_GET_ACCESSOR (Type, name, Name); \
|
||||||
|
inline bool has_##name (void) const { \
|
||||||
|
return Name != 0; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* The OpenType Font File
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data Types
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* "The following data types are used in the OpenType font file.
|
||||||
|
* All OpenType fonts use Motorola-style byte ordering (Big Endian):" */
|
||||||
|
|
||||||
|
|
||||||
|
DEFINE_INT_TYPE_STRUCT (BYTE, u, 8); /* 8-bit unsigned integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (BYTE, 1);
|
||||||
|
DEFINE_INT_TYPE_STRUCT (CHAR, , 8); /* 8-bit signed integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (CHAR, 1);
|
||||||
|
DEFINE_INT_TYPE_STRUCT (USHORT, u, 16); /* 16-bit unsigned integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (USHORT, 2);
|
||||||
|
DEFINE_INT_TYPE_STRUCT (SHORT, , 16); /* 16-bit signed integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (SHORT, 2);
|
||||||
|
DEFINE_INT_TYPE_STRUCT (ULONG, u, 32); /* 32-bit unsigned integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ULONG, 4);
|
||||||
|
DEFINE_INT_TYPE_STRUCT (LONG, , 32); /* 32-bit signed integer. */
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LONG, 4);
|
||||||
|
|
||||||
|
/* Date represented in number of seconds since 12:00 midnight, January 1,
|
||||||
|
* 1904. The value is represented as a signed 64-bit integer. */
|
||||||
|
DEFINE_INT_TYPE_STRUCT (LONGDATETIME, , 64);
|
||||||
|
|
||||||
|
/* 32-bit signed fixed-point number (16.16) */
|
||||||
|
struct Fixed {
|
||||||
|
inline Fixed& operator = (int32_t v) { i = (int16_t) (v >> 16); f = (uint16_t) v; return *this; } \
|
||||||
|
inline operator int32_t(void) const { return (((int32_t) i) << 16) + (uint16_t) f; } \
|
||||||
|
inline bool operator== (Fixed o) const { return i == o.i && f == o.f; } \
|
||||||
|
|
||||||
|
inline operator double(void) const { return (uint32_t) this / 65536.; }
|
||||||
|
inline int16_t int_part (void) const { return i; }
|
||||||
|
inline uint16_t frac_part (void) const { return f; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
SHORT i;
|
||||||
|
USHORT f;
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Fixed, 4);
|
||||||
|
|
||||||
|
/* Smallest measurable distance in the em space. */
|
||||||
|
struct FUNIT;
|
||||||
|
|
||||||
|
/* 16-bit signed integer (SHORT) that describes a quantity in FUnits. */
|
||||||
|
struct FWORD : SHORT {
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (FWORD, 2);
|
||||||
|
|
||||||
|
/* 16-bit unsigned integer (USHORT) that describes a quantity in FUnits. */
|
||||||
|
struct UFWORD : USHORT {
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (UFWORD, 2);
|
||||||
|
|
||||||
|
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||||
|
struct F2DOT14 : SHORT {
|
||||||
|
inline operator double() const { return (uint32_t) this / 16384.; }
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (F2DOT14, 2);
|
||||||
|
|
||||||
|
/* Array of four uint8s (length = 32 bits) used to identify a script, language
|
||||||
|
* system, feature, or baseline */
|
||||||
|
struct Tag {
|
||||||
|
inline Tag (void) { v[0] = v[1] = v[2] = v[3] = 0; }
|
||||||
|
inline Tag (uint32_t v) { (ULONG&)(*this) = v; }
|
||||||
|
inline Tag (const char *c) { v[0] = c[0]; v[1] = c[1]; v[2] = c[2]; v[3] = c[3]; }
|
||||||
|
inline bool operator== (Tag o) const { return v[0]==o.v[0]&&v[1]==o.v[1]&&v[2]==o.v[2]&&v[3]==o.v[3]; }
|
||||||
|
inline bool operator== (const char *c) const { return v[0]==c[0]&&v[1]==c[1]&&v[2]==c[2]&&v[3]==c[3]; }
|
||||||
|
inline bool operator== (uint32_t i) const { return i == (uint32_t) *this; }
|
||||||
|
inline operator uint32_t(void) const { return (v[0]<<24)+(v[1]<<16) +(v[2]<<8)+v[3]; }
|
||||||
|
/* What the char* converters return is NOT nul-terminated. Print using "%.4s" */
|
||||||
|
inline operator const char* (void) const { return (const char *)this; }
|
||||||
|
inline operator char* (void) { return (char *)this; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char v[4];
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (Tag, 4);
|
||||||
|
DEFINE_NULL_DATA (Tag, 5, " ");
|
||||||
|
|
||||||
|
/* Glyph index number, same as uint16 (length = 16 bits) */
|
||||||
|
DEFINE_INT_TYPE_STRUCT (GlyphID, u, 16);
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (GlyphID, 2);
|
||||||
|
|
||||||
|
/* Offset to a table, same as uint16 (length = 16 bits), Null offset = 0x0000 */
|
||||||
|
DEFINE_INT_TYPE_STRUCT (Offset, u, 16);
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Offset, 2);
|
||||||
|
|
||||||
|
/* CheckSum */
|
||||||
|
struct CheckSum : ULONG {
|
||||||
|
static uint32_t CalcTableChecksum (ULONG *Table, uint32_t Length) {
|
||||||
|
uint32_t Sum = 0L;
|
||||||
|
ULONG *EndPtr = Table+((Length+3) & ~3) / sizeof(ULONG);
|
||||||
|
|
||||||
|
while (Table < EndPtr)
|
||||||
|
Sum += *Table++;
|
||||||
|
return Sum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (CheckSum, 4);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Version Numbers
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct USHORT_Version : USHORT {
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (USHORT_Version, 2);
|
||||||
|
|
||||||
|
struct Fixed_Version : Fixed {
|
||||||
|
inline int16_t major (void) const { return this->int_part(); }
|
||||||
|
inline int16_t minor (void) const { return this->frac_part(); }
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Fixed_Version, 4);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Organization of an OpenType Font
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OpenTypeFontFile;
|
||||||
|
struct OffsetTable;
|
||||||
|
struct TTCHeader;
|
||||||
|
|
||||||
|
typedef struct TableDirectory {
|
||||||
|
|
||||||
|
friend struct OpenTypeFontFile;
|
||||||
|
friend struct OffsetTable;
|
||||||
|
|
||||||
|
inline bool is_null (void) const { return length == 0; }
|
||||||
|
inline const Tag& get_tag (void) const { return tag; }
|
||||||
|
inline unsigned long get_checksum (void) const { return checkSum; }
|
||||||
|
inline unsigned long get_offset (void) const { return offset; }
|
||||||
|
inline unsigned long get_length (void) const { return length; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tag tag; /* 4-byte identifier. */
|
||||||
|
CheckSum checkSum; /* CheckSum for this table. */
|
||||||
|
ULONG offset; /* Offset from beginning of TrueType font
|
||||||
|
* file. */
|
||||||
|
ULONG length; /* Length of this table. */
|
||||||
|
} OpenTypeTable;
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (TableDirectory, 16);
|
||||||
|
DEFINE_NULL_ALIAS (OpenTypeTable, TableDirectory);
|
||||||
|
|
||||||
|
typedef struct OffsetTable {
|
||||||
|
|
||||||
|
friend struct OpenTypeFontFile;
|
||||||
|
friend struct TTCHeader;
|
||||||
|
|
||||||
|
DEFINE_TAG_ARRAY_INTERFACE (OpenTypeTable, table); /* get_table_count(), get_table(i), get_table_tag(i) */
|
||||||
|
DEFINE_TAG_FIND_INTERFACE (OpenTypeTable, table); /* find_table_index(tag), get_table_by_tag(tag) */
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* OpenTypeTables, in no particular order */
|
||||||
|
DEFINE_ARRAY_TYPE (TableDirectory, tableDir, numTables);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tag sfnt_version; /* '\0\001\0\00' if TrueType / 'OTTO' if CFF */
|
||||||
|
USHORT numTables; /* Number of tables. */
|
||||||
|
USHORT searchRange; /* (Maximum power of 2 <= numTables) x 16 */
|
||||||
|
USHORT entrySelector; /* Log2(maximum power of 2 <= numTables). */
|
||||||
|
USHORT rangeShift; /* NumTables x 16-searchRange. */
|
||||||
|
TableDirectory tableDir[]; /* TableDirectory entries. numTables items */
|
||||||
|
} OpenTypeFontFace;
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (OffsetTable, 12);
|
||||||
|
DEFINE_NULL_ALIAS (OpenTypeFontFace, OffsetTable);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TrueType Collections
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct TTCHeader {
|
||||||
|
|
||||||
|
friend struct OpenTypeFontFile;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* OpenTypeFontFaces, in no particular order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (OffsetTable, offsetTable, numFonts);
|
||||||
|
/* XXX check version here? */
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tag ttcTag; /* TrueType Collection ID string: 'ttcf' */
|
||||||
|
ULONG version; /* Version of the TTC Header (1.0 or 2.0),
|
||||||
|
* 0x00010000 or 0x00020000 */
|
||||||
|
ULONG numFonts; /* Number of fonts in TTC */
|
||||||
|
ULONG offsetTable[]; /* Array of offsets to the OffsetTable for each font
|
||||||
|
* from the beginning of the file */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (TTCHeader, 12);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OpenType Font File
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct OpenTypeFontFile {
|
||||||
|
DEFINE_NON_INSTANTIABLE(OpenTypeFontFile);
|
||||||
|
static const hb_tag_t TrueTypeTag = HB_TAG ( 0 , 1 , 0 , 0 );
|
||||||
|
static const hb_tag_t CFFTag = HB_TAG ('O','T','T','O');
|
||||||
|
static const hb_tag_t TTCTag = HB_TAG ('t','t','c','f');
|
||||||
|
|
||||||
|
STATIC_DEFINE_GET_FOR_DATA (OpenTypeFontFile);
|
||||||
|
|
||||||
|
DEFINE_ARRAY_INTERFACE (OpenTypeFontFace, face); /* get_face_count(), get_face(i) */
|
||||||
|
|
||||||
|
inline const Tag& get_tag (void) const { return tag; }
|
||||||
|
|
||||||
|
/* This is how you get a table */
|
||||||
|
inline const char* get_table_data (const OpenTypeTable& table) const {
|
||||||
|
return (*this)[table];
|
||||||
|
}
|
||||||
|
inline char* get_table_data (const OpenTypeTable& table) {
|
||||||
|
return (*this)[table];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline const char* operator[] (const OpenTypeTable& table) const {
|
||||||
|
if (G_UNLIKELY (table.offset == 0)) return NULL;
|
||||||
|
return ((const char*)this) + table.offset;
|
||||||
|
}
|
||||||
|
inline char* operator[] (const OpenTypeTable& table) {
|
||||||
|
if (G_UNLIKELY (table.offset == 0)) return NULL;
|
||||||
|
return ((char*)this) + table.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Array interface sans get_size() */
|
||||||
|
unsigned int get_len (void) const {
|
||||||
|
switch (tag) {
|
||||||
|
default: return 0;
|
||||||
|
case TrueTypeTag: case CFFTag: return 1;
|
||||||
|
case TTCTag: return ((const TTCHeader&)*this).get_len();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const OpenTypeFontFace& operator[] (unsigned int i) const {
|
||||||
|
if (HB_UNLIKELY (i >= get_len ())) return NullOpenTypeFontFace;
|
||||||
|
switch (tag) {
|
||||||
|
default: case TrueTypeTag: case CFFTag: return (const OffsetTable&)*this;
|
||||||
|
case TTCTag: return ((const TTCHeader&)*this)[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tag tag; /* 4-byte identifier. */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (OpenTypeFontFile, 4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* OpenType Layout Common Table Formats
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct Record {
|
||||||
|
Tag tag; /* 4-byte Tag identifier */
|
||||||
|
Offset offset; /* Offset from beginning of object holding
|
||||||
|
* the Record */
|
||||||
|
} ScriptRecord, LangSysRecord, FeatureRecord;
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Record, 6);
|
||||||
|
|
||||||
|
struct LangSys {
|
||||||
|
|
||||||
|
DEFINE_INDEX_ARRAY_INTERFACE (feature);
|
||||||
|
|
||||||
|
inline const bool has_required_feature (void) const {
|
||||||
|
return reqFeatureIndex != 0xffff;
|
||||||
|
}
|
||||||
|
/* Returns NO_INDEX if none */
|
||||||
|
inline int get_required_feature_index (void) const {
|
||||||
|
if (reqFeatureIndex == 0xffff)
|
||||||
|
return NO_INDEX;
|
||||||
|
return reqFeatureIndex;;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Feature indices, in no particular order */
|
||||||
|
DEFINE_ARRAY_TYPE (USHORT, featureIndex, featureCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Offset lookupOrder; /* = Null (reserved for an offset to a
|
||||||
|
* reordering table) */
|
||||||
|
USHORT reqFeatureIndex;/* Index of a feature required for this
|
||||||
|
* language system--if no required features
|
||||||
|
* = 0xFFFF */
|
||||||
|
USHORT featureCount; /* Number of FeatureIndex values for this
|
||||||
|
* language system--excludes the required
|
||||||
|
* feature */
|
||||||
|
USHORT featureIndex[]; /* Array of indices into the FeatureList--in
|
||||||
|
* arbitrary order. featureCount entires long */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE_DATA (LangSys, 6, "\0\0\xFF\xFF");
|
||||||
|
|
||||||
|
struct Script {
|
||||||
|
|
||||||
|
/* DEFINE_ARRAY_INTERFACE (LangSys, lang_sys) but handling defaultLangSys */
|
||||||
|
|
||||||
|
inline const LangSys& get_lang_sys (unsigned int i) const {
|
||||||
|
if (i == NO_INDEX) return get_default_lang_sys ();
|
||||||
|
return (*this)[i];
|
||||||
|
}
|
||||||
|
inline unsigned int get_lang_sys_count (void) const {
|
||||||
|
return this->get_len ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Tag& get_lang_sys_tag (unsigned int i) const {
|
||||||
|
return get_tag (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LONGTERMTODO bsearch
|
||||||
|
DEFINE_TAG_FIND_INTERFACE (LangSys, lang_sys); /* find_lang_sys_index (), get_lang_sys_by_tag (tag) */
|
||||||
|
|
||||||
|
inline const bool has_default_lang_sys (void) const {
|
||||||
|
return defaultLangSys != 0;
|
||||||
|
}
|
||||||
|
inline const LangSys& get_default_lang_sys (void) const {
|
||||||
|
if (HB_UNLIKELY (!defaultLangSys))
|
||||||
|
return NullLangSys;
|
||||||
|
return *(LangSys*)((const char*)this + defaultLangSys);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* LangSys', in sorted alphabetical tag order */
|
||||||
|
DEFINE_RECORD_ARRAY_TYPE (LangSys, langSysRecord, langSysCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Offset defaultLangSys; /* Offset to DefaultLangSys table--from
|
||||||
|
* beginning of Script table--may be Null */
|
||||||
|
USHORT langSysCount; /* Number of LangSysRecords for this script--
|
||||||
|
* excluding the DefaultLangSys */
|
||||||
|
LangSysRecord langSysRecord[];/* Array of LangSysRecords--listed
|
||||||
|
* alphabetically by LangSysTag */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Script, 4);
|
||||||
|
|
||||||
|
struct ScriptList {
|
||||||
|
|
||||||
|
friend struct GSUBGPOS;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Scripts, in sorted alphabetical tag order */
|
||||||
|
DEFINE_RECORD_ARRAY_TYPE (Script, scriptRecord, scriptCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT scriptCount; /* Number of ScriptRecords */
|
||||||
|
ScriptRecord scriptRecord[]; /* Array of ScriptRecords--listed alphabetically
|
||||||
|
* by ScriptTag */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (ScriptList, 2);
|
||||||
|
|
||||||
|
struct Feature {
|
||||||
|
|
||||||
|
DEFINE_INDEX_ARRAY_INTERFACE (lookup); /* get_lookup_count(), get_lookup_index(i) */
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* LookupList indices, in no particular order */
|
||||||
|
DEFINE_ARRAY_TYPE (USHORT, lookupIndex, lookupCount);
|
||||||
|
|
||||||
|
/* TODO: implement get_feature_parameters() */
|
||||||
|
/* TODO: implement FeatureSize and other special features? */
|
||||||
|
|
||||||
|
private:
|
||||||
|
Offset featureParams; /* Offset to Feature Parameters table (if one
|
||||||
|
* has been defined for the feature), relative
|
||||||
|
* to the beginning of the Feature Table; = Null
|
||||||
|
* if not required */
|
||||||
|
USHORT lookupCount; /* Number of LookupList indices for this
|
||||||
|
* feature */
|
||||||
|
USHORT lookupIndex[]; /* Array of LookupList indices for this
|
||||||
|
* feature--zero-based (first lookup is
|
||||||
|
* LookupListIndex = 0) */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Feature, 4);
|
||||||
|
|
||||||
|
struct FeatureList {
|
||||||
|
|
||||||
|
friend struct GSUBGPOS;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Feature indices, in sorted alphabetical tag order */
|
||||||
|
DEFINE_RECORD_ARRAY_TYPE (Feature, featureRecord, featureCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT featureCount; /* Number of FeatureRecords in this table */
|
||||||
|
FeatureRecord featureRecord[];/* Array of FeatureRecords--zero-based (first
|
||||||
|
* feature has FeatureIndex = 0)--listed
|
||||||
|
* alphabetically by FeatureTag */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (FeatureList, 2);
|
||||||
|
|
||||||
|
struct LookupFlag : USHORT {
|
||||||
|
static const unsigned int RightToLeft = 0x0001u;
|
||||||
|
static const unsigned int IgnoreBaseGlyphs = 0x0002u;
|
||||||
|
static const unsigned int IgnoreLigatures = 0x0004u;
|
||||||
|
static const unsigned int IgnoreMarks = 0x0008u;
|
||||||
|
static const unsigned int Reserved = 0x00F0u;
|
||||||
|
static const unsigned int MarkAttachmentType = 0xFF00u;
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LookupFlag, 2);
|
||||||
|
|
||||||
|
struct LookupSubTable {
|
||||||
|
DEFINE_NON_INSTANTIABLE(LookupSubTable);
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT format; /* Subtable format. Different for GSUB and GPOS */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LookupSubTable, 2);
|
||||||
|
|
||||||
|
|
||||||
|
struct Lookup {
|
||||||
|
DEFINE_NON_INSTANTIABLE(Lookup);
|
||||||
|
|
||||||
|
DEFINE_ARRAY_INTERFACE (LookupSubTable, subtable); /* get_subtable_count(), get_subtable(i) */
|
||||||
|
|
||||||
|
inline bool is_right_to_left (void) const { return lookupFlag & LookupFlag::RightToLeft; }
|
||||||
|
inline bool ignore_base_glyphs(void) const { return lookupFlag & LookupFlag::IgnoreBaseGlyphs; }
|
||||||
|
inline bool ignore_ligatures (void) const { return lookupFlag & LookupFlag::IgnoreLigatures; }
|
||||||
|
inline bool ignore_marks (void) const { return lookupFlag & LookupFlag::IgnoreMarks; }
|
||||||
|
inline bool get_mark_attachment_type (void) const { return lookupFlag & LookupFlag::MarkAttachmentType; }
|
||||||
|
|
||||||
|
inline unsigned int get_type (void) const { return lookupType; }
|
||||||
|
inline unsigned int get_flag (void) const { return lookupFlag; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* SubTables, in the desired order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (LookupSubTable, subTableOffset, subTableCount);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
USHORT lookupType; /* Different enumerations for GSUB and GPOS */
|
||||||
|
USHORT lookupFlag; /* Lookup qualifiers */
|
||||||
|
USHORT subTableCount; /* Number of SubTables for this lookup */
|
||||||
|
Offset subTableOffset[];/* Array of offsets to SubTables-from
|
||||||
|
* beginning of Lookup table */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Lookup, 6);
|
||||||
|
|
||||||
|
struct LookupList {
|
||||||
|
|
||||||
|
friend struct GSUBGPOS;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* Lookup indices, in sorted alphabetical tag order */
|
||||||
|
DEFINE_OFFSET_ARRAY_TYPE (Lookup, lookupOffset, lookupCount);
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT lookupCount; /* Number of lookups in this table */
|
||||||
|
Offset lookupOffset[]; /* Array of offsets to Lookup tables--from
|
||||||
|
* beginning of LookupList--zero based (first
|
||||||
|
* lookup is Lookup index = 0) */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (LookupList, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Coverage Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct CoverageFormat1 {
|
||||||
|
|
||||||
|
friend struct Coverage;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* GlyphIDs, in sorted numerical order */
|
||||||
|
DEFINE_ARRAY_TYPE (GlyphID, glyphArray, glyphCount);
|
||||||
|
|
||||||
|
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||||
|
GlyphID gid;
|
||||||
|
if (HB_UNLIKELY (glyph_id > 65535))
|
||||||
|
return -1;
|
||||||
|
gid = glyph_id;
|
||||||
|
// TODO: bsearch
|
||||||
|
for (unsigned int i = 0; i < glyphCount; i++)
|
||||||
|
if (gid == glyphArray[i])
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT coverageFormat; /* Format identifier--format = 1 */
|
||||||
|
USHORT glyphCount; /* Number of glyphs in the GlyphArray */
|
||||||
|
GlyphID glyphArray[]; /* Array of GlyphIDs--in numerical order */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (CoverageFormat1, 4);
|
||||||
|
|
||||||
|
struct CoverageRangeRecord {
|
||||||
|
|
||||||
|
friend struct CoverageFormat2;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||||
|
if (glyph_id >= start && glyph_id <= end)
|
||||||
|
return startCoverageIndex + (glyph_id - start);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GlyphID start; /* First GlyphID in the range */
|
||||||
|
GlyphID end; /* Last GlyphID in the range */
|
||||||
|
USHORT startCoverageIndex; /* Coverage Index of first GlyphID in
|
||||||
|
* range */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE_DATA (CoverageRangeRecord, 6, "\001");
|
||||||
|
|
||||||
|
struct CoverageFormat2 {
|
||||||
|
|
||||||
|
friend struct Coverage;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* CoverageRangeRecords, in sorted numerical start order */
|
||||||
|
DEFINE_ARRAY_TYPE (CoverageRangeRecord, rangeRecord, rangeCount);
|
||||||
|
|
||||||
|
inline hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||||
|
// TODO: bsearch
|
||||||
|
for (unsigned int i = 0; i < rangeCount; i++) {
|
||||||
|
int coverage = rangeRecord[i].get_coverage (glyph_id);
|
||||||
|
if (coverage >= 0)
|
||||||
|
return coverage;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT coverageFormat; /* Format identifier--format = 2 */
|
||||||
|
USHORT rangeCount; /* Number of CoverageRangeRecords */
|
||||||
|
CoverageRangeRecord rangeRecord[]; /* Array of glyph ranges--ordered by
|
||||||
|
* Start GlyphID. rangeCount entries
|
||||||
|
* long */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (CoverageFormat2, 4);
|
||||||
|
|
||||||
|
struct Coverage {
|
||||||
|
DEFINE_NON_INSTANTIABLE(Coverage);
|
||||||
|
|
||||||
|
unsigned int get_size (void) const {
|
||||||
|
switch (u.coverageFormat) {
|
||||||
|
case 1: return u.format1.get_size ();
|
||||||
|
case 2: return u.format2.get_size ();
|
||||||
|
default:return sizeof (u.coverageFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_ot_layout_coverage_t get_coverage (hb_codepoint_t glyph_id) const {
|
||||||
|
switch (u.coverageFormat) {
|
||||||
|
case 1: return u.format1.get_coverage(glyph_id);
|
||||||
|
case 2: return u.format2.get_coverage(glyph_id);
|
||||||
|
default:return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
USHORT coverageFormat; /* Format identifier */
|
||||||
|
CoverageFormat1 format1;
|
||||||
|
CoverageFormat2 format2;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
DEFINE_NULL (Coverage, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class Definition Table
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct ClassDefFormat1 {
|
||||||
|
|
||||||
|
friend struct ClassDef;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* GlyphIDs, in sorted numerical order */
|
||||||
|
DEFINE_ARRAY_TYPE (USHORT, classValueArray, glyphCount);
|
||||||
|
|
||||||
|
inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
|
||||||
|
if (glyph_id >= startGlyph && glyph_id - startGlyph < glyphCount)
|
||||||
|
return classValueArray[glyph_id - startGlyph];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT classFormat; /* Format identifier--format = 1 */
|
||||||
|
GlyphID startGlyph; /* First GlyphID of the classValueArray */
|
||||||
|
USHORT glyphCount; /* Size of the classValueArray */
|
||||||
|
USHORT classValueArray[]; /* Array of Class Values--one per GlyphID */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ClassDefFormat1, 6);
|
||||||
|
|
||||||
|
struct ClassRangeRecord {
|
||||||
|
|
||||||
|
friend struct ClassDefFormat2;
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
|
||||||
|
if (glyph_id >= start && glyph_id <= end)
|
||||||
|
return classValue;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
GlyphID start; /* First GlyphID in the range */
|
||||||
|
GlyphID end; /* Last GlyphID in the range */
|
||||||
|
USHORT classValue; /* Applied to all glyphs in the range */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE_DATA (ClassRangeRecord, 6, "\001");
|
||||||
|
|
||||||
|
struct ClassDefFormat2 {
|
||||||
|
|
||||||
|
friend struct ClassDef;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* ClassRangeRecords, in sorted numerical start order */
|
||||||
|
DEFINE_ARRAY_TYPE (ClassRangeRecord, rangeRecord, rangeCount);
|
||||||
|
|
||||||
|
inline hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
|
||||||
|
// TODO: bsearch
|
||||||
|
for (unsigned int i = 0; i < rangeCount; i++) {
|
||||||
|
int classValue = rangeRecord[i].get_class (glyph_id);
|
||||||
|
if (classValue > 0)
|
||||||
|
return classValue;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT classFormat; /* Format identifier--format = 2 */
|
||||||
|
USHORT rangeCount; /* Number of Number of ClassRangeRecords */
|
||||||
|
ClassRangeRecord rangeRecord[]; /* Array of glyph ranges--ordered by
|
||||||
|
* Start GlyphID */
|
||||||
|
};
|
||||||
|
ASSERT_SIZE (ClassDefFormat2, 4);
|
||||||
|
|
||||||
|
struct ClassDef {
|
||||||
|
DEFINE_NON_INSTANTIABLE(ClassDef);
|
||||||
|
|
||||||
|
unsigned int get_size (void) const {
|
||||||
|
switch (u.classFormat) {
|
||||||
|
case 1: return u.format1.get_size ();
|
||||||
|
case 2: return u.format2.get_size ();
|
||||||
|
default:return sizeof (u.classFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_ot_layout_class_t get_class (hb_codepoint_t glyph_id) const {
|
||||||
|
switch (u.classFormat) {
|
||||||
|
case 1: return u.format1.get_class(glyph_id);
|
||||||
|
case 2: return u.format2.get_class(glyph_id);
|
||||||
|
default:return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
union {
|
||||||
|
USHORT classFormat; /* Format identifier */
|
||||||
|
ClassDefFormat1 format1;
|
||||||
|
ClassDefFormat2 format2;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
DEFINE_NULL (ClassDef, 2);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Device Tables
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Device {
|
||||||
|
DEFINE_NON_INSTANTIABLE(Device);
|
||||||
|
|
||||||
|
unsigned int get_size (void) const {
|
||||||
|
int count = endSize - startSize + 1;
|
||||||
|
if (count < 0) count = 0;
|
||||||
|
switch (deltaFormat) {
|
||||||
|
case 1: return sizeof (Device) + sizeof (USHORT) * ((count+7)/8);
|
||||||
|
case 2: return sizeof (Device) + sizeof (USHORT) * ((count+3)/4);
|
||||||
|
case 3: return sizeof (Device) + sizeof (USHORT) * ((count+1)/2);
|
||||||
|
default:return sizeof (Device);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_delta (int ppem_size) const {
|
||||||
|
if (ppem_size >= startSize && ppem_size <= endSize &&
|
||||||
|
deltaFormat >= 1 && deltaFormat <= 3) {
|
||||||
|
int s = ppem_size - startSize;
|
||||||
|
int f = deltaFormat;
|
||||||
|
|
||||||
|
uint16_t byte = deltaValue[s >> (4 - f)];
|
||||||
|
uint16_t bits = byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f));
|
||||||
|
uint16_t mask = 0xFFFF >> (16 - (1 << f));
|
||||||
|
|
||||||
|
int delta = bits & mask;
|
||||||
|
|
||||||
|
if (delta >= ((mask + 1) >> 1))
|
||||||
|
delta -= mask + 1;
|
||||||
|
|
||||||
|
return delta;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
USHORT startSize; /* Smallest size to correct--in ppem */
|
||||||
|
USHORT endSize; /* Largest size to correct--in ppem */
|
||||||
|
USHORT deltaFormat; /* Format of DeltaValue array data: 1, 2, or 3 */
|
||||||
|
USHORT deltaValue[]; /* Array of compressed data */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (Device, 6);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB/GPOS Common
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct GSUBGPOS {
|
||||||
|
static const hb_tag_t GSUBTag = HB_TAG ('G','S','U','B');
|
||||||
|
static const hb_tag_t GPOSTag = HB_TAG ('G','P','O','S');
|
||||||
|
|
||||||
|
STATIC_DEFINE_GET_FOR_DATA (GSUBGPOS);
|
||||||
|
/* XXX check version here? */
|
||||||
|
|
||||||
|
DEFINE_TAG_LIST_INTERFACE (Script, script ); /* get_script_count (), get_script (i), get_script_tag (i) */
|
||||||
|
DEFINE_TAG_LIST_INTERFACE (Feature, feature); /* get_feature_count(), get_feature(i), get_feature_tag(i) */
|
||||||
|
DEFINE_LIST_INTERFACE (Lookup, lookup ); /* get_lookup_count (), get_lookup (i) */
|
||||||
|
|
||||||
|
// LONGTERMTODO bsearch
|
||||||
|
DEFINE_TAG_FIND_INTERFACE (Script, script ); /* find_script_index (), get_script_by_tag (tag) */
|
||||||
|
DEFINE_TAG_FIND_INTERFACE (Feature, feature); /* find_feature_index(), get_feature_by_tag(tag) */
|
||||||
|
|
||||||
|
private:
|
||||||
|
DEFINE_LIST_ARRAY(Script, script);
|
||||||
|
DEFINE_LIST_ARRAY(Feature, feature);
|
||||||
|
DEFINE_LIST_ARRAY(Lookup, lookup);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Fixed_Version version; /* Version of the GSUB/GPOS table--initially set
|
||||||
|
* to 0x00010000 */
|
||||||
|
Offset scriptList; /* Offset to ScriptList table--from beginning of
|
||||||
|
* GSUB/GPOS table */
|
||||||
|
Offset featureList; /* Offset to FeatureList table--from beginning of
|
||||||
|
* GSUB/GPOS table */
|
||||||
|
Offset lookupList; /* Offset to LookupList table--from beginning of
|
||||||
|
* GSUB/GPOS table */
|
||||||
|
};
|
||||||
|
DEFINE_NULL_ASSERT_SIZE (GSUBGPOS, 10);
|
||||||
|
|
||||||
|
#endif /* HB_OT_LAYOUT_OPEN_PRIVATE_H */
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_PRIVATE_H
|
||||||
|
#define HB_OT_LAYOUT_PRIVATE_H
|
||||||
|
|
||||||
|
#include "hb-private.h"
|
||||||
|
#include "hb-ot-layout.h"
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#include "harfbuzz-buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
typedef uint16_t hb_ot_layout_class_t;
|
||||||
|
typedef uint16_t hb_ot_layout_glyph_properties_t;
|
||||||
|
typedef uint16_t hb_ot_layout_lookup_flags_t;
|
||||||
|
typedef int hb_ot_layout_coverage_t; /* -1 is not covered, >= 0 otherwise */
|
||||||
|
|
||||||
|
/* XXX #define HB_OT_LAYOUT_INTERNAL static */
|
||||||
|
#define HB_OT_LAYOUT_INTERNAL
|
||||||
|
|
||||||
|
HB_BEGIN_DECLS();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDEF
|
||||||
|
*/
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_bool_t
|
||||||
|
_hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout);
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t
|
||||||
|
_hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph);
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_bool_t
|
||||||
|
_hb_ot_layout_check_glyph_properties (hb_ot_layout_t *layout,
|
||||||
|
HB_GlyphItem gitem,
|
||||||
|
hb_ot_layout_lookup_flags_t lookup_flags,
|
||||||
|
hb_ot_layout_glyph_properties_t *property);
|
||||||
|
|
||||||
|
HB_END_DECLS();
|
||||||
|
|
||||||
|
#endif /* HB_OT_LAYOUT_PRIVATE_H */
|
|
@ -0,0 +1,565 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1998-2004 David Turner and Werner Lemberg
|
||||||
|
* Copyright (C) 2006 Behdad Esfahbod
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HB_OT_LAYOUT_CC
|
||||||
|
|
||||||
|
#include "hb-ot-layout.h"
|
||||||
|
#include "hb-ot-layout-private.h"
|
||||||
|
|
||||||
|
#include "hb-ot-layout-open-private.h"
|
||||||
|
#include "hb-ot-layout-gdef-private.h"
|
||||||
|
#include "hb-ot-layout-gsub-private.h"
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#include "harfbuzz-buffer-private.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct _hb_ot_layout_t {
|
||||||
|
const GDEF *gdef;
|
||||||
|
const GSUB *gsub;
|
||||||
|
const /*XXX*/GSUBGPOS *gpos;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned char *klasses;
|
||||||
|
unsigned int len;
|
||||||
|
} new_gdef;
|
||||||
|
|
||||||
|
/* TODO add max-nesting-level here? */
|
||||||
|
};
|
||||||
|
|
||||||
|
hb_ot_layout_t *
|
||||||
|
hb_ot_layout_create (void)
|
||||||
|
{
|
||||||
|
hb_ot_layout_t *layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
|
||||||
|
|
||||||
|
layout->gdef = &NullGDEF;
|
||||||
|
layout->gsub = &NullGSUB;
|
||||||
|
layout->gpos = &/*XXX*/NullGSUBGPOS;
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_ot_layout_t *
|
||||||
|
hb_ot_layout_create_for_data (const char *font_data,
|
||||||
|
int face_index)
|
||||||
|
{
|
||||||
|
hb_ot_layout_t *layout;
|
||||||
|
|
||||||
|
if (HB_UNLIKELY (font_data == NULL))
|
||||||
|
return hb_ot_layout_create ();
|
||||||
|
|
||||||
|
layout = (hb_ot_layout_t *) calloc (1, sizeof (hb_ot_layout_t));
|
||||||
|
|
||||||
|
const OpenTypeFontFile &font = OpenTypeFontFile::get_for_data (font_data);
|
||||||
|
const OpenTypeFontFace &face = font.get_face (face_index);
|
||||||
|
|
||||||
|
layout->gdef = &GDEF::get_for_data (font.get_table_data (face.get_table_by_tag (GDEF::Tag)));
|
||||||
|
layout->gsub = &GSUB::get_for_data (font.get_table_data (face.get_table_by_tag (GSUB::Tag)));
|
||||||
|
layout->gpos = &/*XXX*/GSUBGPOS::get_for_data (font.get_table_data (face.get_table_by_tag (/*XXX*/GSUBGPOS::GPOSTag)));
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_destroy (hb_ot_layout_t *layout)
|
||||||
|
{
|
||||||
|
free (layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDEF
|
||||||
|
*/
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_has_font_glyph_classes (hb_ot_layout_t *layout)
|
||||||
|
{
|
||||||
|
return layout->gdef->has_glyph_classes ();
|
||||||
|
}
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_bool_t
|
||||||
|
_hb_ot_layout_has_new_glyph_classes (hb_ot_layout_t *layout)
|
||||||
|
{
|
||||||
|
return layout->new_gdef.len > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_ot_layout_glyph_properties_t
|
||||||
|
_hb_ot_layout_get_glyph_properties (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph)
|
||||||
|
{
|
||||||
|
hb_ot_layout_class_t klass;
|
||||||
|
|
||||||
|
/* TODO old harfbuzz doesn't always parse mark attachments as it says it was
|
||||||
|
* introduced without a version bump, so it may not be safe */
|
||||||
|
klass = layout->gdef->get_mark_attachment_type (glyph);
|
||||||
|
if (klass)
|
||||||
|
return klass << 8;
|
||||||
|
|
||||||
|
klass = layout->gdef->get_glyph_class (glyph);
|
||||||
|
|
||||||
|
if (!klass && glyph < layout->new_gdef.len)
|
||||||
|
klass = layout->new_gdef.klasses[glyph];
|
||||||
|
|
||||||
|
switch (klass) {
|
||||||
|
default:
|
||||||
|
case GDEF::UnclassifiedGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED;
|
||||||
|
case GDEF::BaseGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
|
||||||
|
case GDEF::LigatureGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE;
|
||||||
|
case GDEF::MarkGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_MARK;
|
||||||
|
case GDEF::ComponentGlyph: return HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HB_OT_LAYOUT_INTERNAL hb_bool_t
|
||||||
|
_hb_ot_layout_check_glyph_properties (hb_ot_layout_t *layout,
|
||||||
|
HB_GlyphItem gitem,
|
||||||
|
hb_ot_layout_lookup_flags_t lookup_flags,
|
||||||
|
hb_ot_layout_glyph_properties_t *property)
|
||||||
|
{
|
||||||
|
hb_ot_layout_glyph_class_t basic_glyph_class;
|
||||||
|
hb_ot_layout_glyph_properties_t desired_attachment_class;
|
||||||
|
|
||||||
|
if (gitem->gproperties == HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN)
|
||||||
|
{
|
||||||
|
gitem->gproperties = *property = _hb_ot_layout_get_glyph_properties (layout, gitem->gindex);
|
||||||
|
if (gitem->gproperties == HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*property = gitem->gproperties;
|
||||||
|
|
||||||
|
/* If the glyph was found in the MarkAttachmentClass table,
|
||||||
|
* then that class value is the high byte of the result,
|
||||||
|
* otherwise the low byte contains the basic type of the glyph
|
||||||
|
* as defined by the GlyphClassDef table.
|
||||||
|
*/
|
||||||
|
if (*property & LookupFlag::MarkAttachmentType)
|
||||||
|
basic_glyph_class = HB_OT_LAYOUT_GLYPH_CLASS_MARK;
|
||||||
|
else
|
||||||
|
basic_glyph_class = (hb_ot_layout_glyph_class_t) *property;
|
||||||
|
|
||||||
|
/* Not covered, if, for example, basic_glyph_class
|
||||||
|
* is HB_GDEF_LIGATURE and lookup_flags includes LookupFlags::IgnoreLigatures
|
||||||
|
*/
|
||||||
|
if (lookup_flags & basic_glyph_class)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* The high byte of lookup_flags has the meaning
|
||||||
|
* "ignore marks of attachment type different than
|
||||||
|
* the attachment type specified."
|
||||||
|
*/
|
||||||
|
desired_attachment_class = lookup_flags & LookupFlag::MarkAttachmentType;
|
||||||
|
if (desired_attachment_class)
|
||||||
|
{
|
||||||
|
if (basic_glyph_class == HB_OT_LAYOUT_GLYPH_CLASS_MARK &&
|
||||||
|
*property != desired_attachment_class )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hb_ot_layout_glyph_class_t
|
||||||
|
hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph)
|
||||||
|
{
|
||||||
|
hb_ot_layout_glyph_properties_t properties;
|
||||||
|
hb_ot_layout_class_t klass;
|
||||||
|
|
||||||
|
properties = _hb_ot_layout_get_glyph_properties (layout, glyph);
|
||||||
|
|
||||||
|
if (properties & 0xFF00)
|
||||||
|
return HB_OT_LAYOUT_GLYPH_CLASS_MARK;
|
||||||
|
|
||||||
|
return (hb_ot_layout_glyph_class_t) properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_ot_layout_glyph_class_t klass)
|
||||||
|
{
|
||||||
|
/* TODO optimize this, similar to old harfbuzz code for example */
|
||||||
|
|
||||||
|
hb_ot_layout_class_t gdef_klass;
|
||||||
|
int len = layout->new_gdef.len;
|
||||||
|
|
||||||
|
if (glyph >= len) {
|
||||||
|
int new_len;
|
||||||
|
unsigned char *new_klasses;
|
||||||
|
|
||||||
|
new_len = len == 0 ? 120 : 2 * len;
|
||||||
|
if (new_len > 65535)
|
||||||
|
new_len = 65535;
|
||||||
|
new_klasses = (unsigned char *) realloc (layout->new_gdef.klasses, new_len * sizeof (unsigned char));
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!new_klasses))
|
||||||
|
return;
|
||||||
|
|
||||||
|
memset (new_klasses + len, 0, new_len - len);
|
||||||
|
|
||||||
|
layout->new_gdef.klasses = new_klasses;
|
||||||
|
layout->new_gdef.len = new_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (klass) {
|
||||||
|
default:
|
||||||
|
case HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED: gdef_klass = GDEF::UnclassifiedGlyph; break;
|
||||||
|
case HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH: gdef_klass = GDEF::BaseGlyph; break;
|
||||||
|
case HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE: gdef_klass = GDEF::LigatureGlyph; break;
|
||||||
|
case HB_OT_LAYOUT_GLYPH_CLASS_MARK: gdef_klass = GDEF::MarkGlyph; break;
|
||||||
|
case HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT: gdef_klass = GDEF::ComponentGlyph; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->new_gdef.klasses[glyph] = gdef_klass;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout,
|
||||||
|
uint16_t num_total_glyphs,
|
||||||
|
hb_codepoint_t *glyphs,
|
||||||
|
unsigned char *klasses,
|
||||||
|
uint16_t count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!count || !glyphs || !klasses))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (layout->new_gdef.len == 0) {
|
||||||
|
layout->new_gdef.klasses = (unsigned char *) calloc (num_total_glyphs, sizeof (unsigned char));
|
||||||
|
layout->new_gdef.len = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
hb_ot_layout_set_glyph_class (layout, glyphs[i], (hb_ot_layout_glyph_class_t) klasses[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB/GPOS
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const GSUBGPOS&
|
||||||
|
get_gsubgpos_table (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type)
|
||||||
|
{
|
||||||
|
switch (table_type) {
|
||||||
|
case HB_OT_LAYOUT_TABLE_TYPE_GSUB: return *(layout->gsub);
|
||||||
|
case HB_OT_LAYOUT_TABLE_TYPE_GPOS: return *(layout->gpos);
|
||||||
|
default: return NullGSUBGPOS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_script_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
return g.get_script_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_table_get_script_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
return g.get_script_tag (script_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_table_find_script (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
hb_tag_t script_tag,
|
||||||
|
unsigned int *script_index)
|
||||||
|
{
|
||||||
|
ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_SCRIPT_INDEX);
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
if (g.find_script_index (script_tag, script_index))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* try finding 'DFLT' */
|
||||||
|
if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT, script_index))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* try with 'dflt'; MS site has had typos and many fonts use it now :( */
|
||||||
|
if (g.find_script_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, script_index))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (script_index) *script_index = HB_OT_LAYOUT_NO_SCRIPT_INDEX;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_feature_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
return g.get_feature_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_table_get_feature_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
return g.get_feature_tag (feature_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_table_find_feature (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
hb_tag_t feature_tag,
|
||||||
|
unsigned int *feature_index)
|
||||||
|
{
|
||||||
|
ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
if (g.find_feature_index (feature_tag, feature_index))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_lookup_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
|
||||||
|
return g.get_lookup_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_script_get_language_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index)
|
||||||
|
{
|
||||||
|
const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
|
||||||
|
|
||||||
|
return s.get_lang_sys_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_script_get_language_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index)
|
||||||
|
{
|
||||||
|
const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
|
||||||
|
|
||||||
|
return s.get_lang_sys_tag (language_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_script_find_language (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
hb_tag_t language_tag,
|
||||||
|
unsigned int *language_index)
|
||||||
|
{
|
||||||
|
ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX);
|
||||||
|
const Script &s = get_gsubgpos_table (layout, table_type).get_script (script_index);
|
||||||
|
|
||||||
|
if (s.find_lang_sys_index (language_tag, language_index))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* try with 'dflt'; MS site has had typos and many fonts use it now :( */
|
||||||
|
if (s.find_lang_sys_index (HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE, language_index))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (language_index) *language_index = HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_language_get_required_feature_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int *feature_index)
|
||||||
|
{
|
||||||
|
const LangSys &l = get_gsubgpos_table (layout, table_type).get_script (script_index).get_lang_sys (language_index);
|
||||||
|
|
||||||
|
if (feature_index) *feature_index = l.get_required_feature_index ();
|
||||||
|
|
||||||
|
return l.has_required_feature ();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_language_get_feature_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index)
|
||||||
|
{
|
||||||
|
const LangSys &l = get_gsubgpos_table (layout, table_type).get_script (script_index).get_lang_sys (language_index);
|
||||||
|
|
||||||
|
return l.get_feature_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_language_get_feature_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int num_feature)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
|
||||||
|
|
||||||
|
return l.get_feature_index (num_feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_language_get_feature_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int num_feature)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
|
||||||
|
unsigned int feature_index = l.get_feature_index (num_feature);
|
||||||
|
|
||||||
|
return g.get_feature_tag (feature_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_language_find_feature (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
hb_tag_t feature_tag,
|
||||||
|
unsigned int *feature_index)
|
||||||
|
{
|
||||||
|
ASSERT_STATIC (NO_INDEX == HB_OT_LAYOUT_NO_FEATURE_INDEX);
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
const LangSys &l = g.get_script (script_index).get_lang_sys (language_index);
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < l.get_feature_count (); i++) {
|
||||||
|
unsigned int f_index = l.get_feature_index (i);
|
||||||
|
|
||||||
|
if (feature_tag == g.get_feature_tag (f_index)) {
|
||||||
|
if (feature_index) *feature_index = f_index;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (feature_index) *feature_index = HB_OT_LAYOUT_NO_FEATURE_INDEX;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_feature_get_lookup_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
const Feature &f = g.get_feature (feature_index);
|
||||||
|
|
||||||
|
return f.get_lookup_count ();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index,
|
||||||
|
unsigned int num_lookup)
|
||||||
|
{
|
||||||
|
const GSUBGPOS &g = get_gsubgpos_table (layout, table_type);
|
||||||
|
const Feature &f = g.get_feature (feature_index);
|
||||||
|
|
||||||
|
return f.get_lookup_index (num_lookup);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB
|
||||||
|
*/
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
unsigned int lookup_index,
|
||||||
|
hb_ot_layout_feature_mask_t mask)
|
||||||
|
{
|
||||||
|
const GSUB &gsub = *(layout->gsub);
|
||||||
|
const SubstLookup &l = gsub.get_lookup (lookup_index);
|
||||||
|
unsigned int lookup_type = l.get_type ();
|
||||||
|
unsigned int nesting_level_left = HB_OT_LAYOUT_MAX_NESTING_LEVEL;
|
||||||
|
unsigned int context_length = NO_CONTEXT;
|
||||||
|
bool handled, ret = false;
|
||||||
|
|
||||||
|
if (!l.is_reverse ()) {
|
||||||
|
|
||||||
|
/* in/out forward substitution */
|
||||||
|
_hb_buffer_clear_output (buffer);
|
||||||
|
buffer->in_pos = 0;
|
||||||
|
while (buffer->in_pos < buffer->in_length) {
|
||||||
|
|
||||||
|
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||||
|
l.substitute (layout, buffer, context_length, nesting_level_left))
|
||||||
|
ret = true;
|
||||||
|
else
|
||||||
|
_hb_buffer_copy_output_glyph (buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
_hb_buffer_swap (buffer);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* in-place backward substitution */
|
||||||
|
buffer->in_pos = buffer->in_length - 1;
|
||||||
|
do {
|
||||||
|
|
||||||
|
if ((~IN_PROPERTIES (buffer->in_pos) & mask) &&
|
||||||
|
l.substitute (layout, buffer, context_length, nesting_level_left))
|
||||||
|
ret = true;
|
||||||
|
else
|
||||||
|
buffer->in_pos--;
|
||||||
|
|
||||||
|
} while (buffer->in_pos);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_OT_LAYOUT_H
|
||||||
|
#define HB_OT_LAYOUT_H
|
||||||
|
|
||||||
|
#include "hb-common.h"
|
||||||
|
|
||||||
|
HB_BEGIN_DECLS();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* hb_ot_layout_t
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct _hb_ot_layout_t hb_ot_layout_t;
|
||||||
|
|
||||||
|
hb_ot_layout_t *
|
||||||
|
hb_ot_layout_create (void);
|
||||||
|
|
||||||
|
hb_ot_layout_t *
|
||||||
|
hb_ot_layout_create_for_data (const char *font_data,
|
||||||
|
int face_index);
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_destroy (hb_ot_layout_t *layout);
|
||||||
|
|
||||||
|
/* TODO sanitizing API/constructor (make_wrieable_func_t) */
|
||||||
|
/* TODO get_table_func_t constructor */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GDEF
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED = 0x0000,
|
||||||
|
HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH = 0x0002,
|
||||||
|
HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE = 0x0004,
|
||||||
|
HB_OT_LAYOUT_GLYPH_CLASS_MARK = 0x0008,
|
||||||
|
HB_OT_LAYOUT_GLYPH_CLASS_COMPONENT = 0x0010
|
||||||
|
} hb_ot_layout_glyph_class_t;
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_has_font_glyph_classes (hb_ot_layout_t *layout);
|
||||||
|
|
||||||
|
hb_ot_layout_glyph_class_t
|
||||||
|
hb_ot_layout_get_glyph_class (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph);
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_set_glyph_class (hb_ot_layout_t *layout,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_ot_layout_glyph_class_t klass);
|
||||||
|
|
||||||
|
void
|
||||||
|
hb_ot_layout_build_glyph_classes (hb_ot_layout_t *layout,
|
||||||
|
uint16_t num_total_glyphs,
|
||||||
|
hb_codepoint_t *glyphs,
|
||||||
|
unsigned char *klasses,
|
||||||
|
uint16_t count);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB/GPOS
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HB_OT_LAYOUT_TABLE_TYPE_GSUB,
|
||||||
|
HB_OT_LAYOUT_TABLE_TYPE_GPOS,
|
||||||
|
HB_OT_LAYOUT_TABLE_TYPE_NONE
|
||||||
|
} hb_ot_layout_table_type_t;
|
||||||
|
|
||||||
|
typedef uint16_t hb_ot_layout_feature_mask_t;
|
||||||
|
|
||||||
|
#define HB_OT_LAYOUT_MAX_NESTING_LEVEL 100
|
||||||
|
|
||||||
|
#define HB_OT_LAYOUT_NO_SCRIPT_INDEX ((unsigned int) 0xFFFF)
|
||||||
|
#define HB_OT_LAYOUT_NO_FEATURE_INDEX ((unsigned int) 0xFFFF)
|
||||||
|
#define HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX ((unsigned int) 0xFFFF)
|
||||||
|
#define HB_OT_LAYOUT_TAG_DEFAULT_SCRIPT HB_TAG ('D', 'F', 'L', 'T')
|
||||||
|
#define HB_OT_LAYOUT_TAG_DEFAULT_LANGUAGE HB_TAG ('d', 'f', 'l', 't')
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_script_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type);
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_table_get_script_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index);
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_table_find_script (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
hb_tag_t script_tag,
|
||||||
|
unsigned int *script_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_feature_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type);
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_table_get_feature_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index);
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_table_find_script (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
hb_tag_t feature_tag,
|
||||||
|
unsigned int *feature_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_table_get_lookup_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_script_get_language_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index);
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_script_get_language_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index);
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_script_find_language (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
hb_tag_t language_tag,
|
||||||
|
unsigned int *language_index);
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_language_get_required_feature_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int *feature_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_language_get_feature_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_language_get_feature_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int num_feature);
|
||||||
|
|
||||||
|
hb_tag_t
|
||||||
|
hb_ot_layout_language_get_feature_tag (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
unsigned int num_feature);
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_language_find_feature (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int script_index,
|
||||||
|
unsigned int language_index,
|
||||||
|
hb_tag_t feature_tag,
|
||||||
|
unsigned int *feature_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_feature_get_lookup_count (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index);
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
hb_ot_layout_feature_get_lookup_index (hb_ot_layout_t *layout,
|
||||||
|
hb_ot_layout_table_type_t table_type,
|
||||||
|
unsigned int feature_index,
|
||||||
|
unsigned int num_lookup);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GSUB
|
||||||
|
*/
|
||||||
|
|
||||||
|
hb_bool_t
|
||||||
|
hb_ot_layout_substitute_lookup (hb_ot_layout_t *layout,
|
||||||
|
hb_buffer_t *buffer,
|
||||||
|
unsigned int lookup_index,
|
||||||
|
hb_ot_layout_feature_mask_t mask);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
#define PANGO_OT_ALL_GLYPHS ((guint) 0xFFFF)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
HB_END_DECLS();
|
||||||
|
|
||||||
|
#endif /* HB_OT_LAYOUT_H */
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HB_PRIVATE_H
|
||||||
|
#define HB_PRIVATE_H
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
/* Macros to convert to/from BigEndian */
|
||||||
|
#define hb_be_uint8_t
|
||||||
|
#define hb_be_int8_t
|
||||||
|
#define hb_be_uint16_t GUINT16_TO_BE
|
||||||
|
#define hb_be_int16_t GINT16_TO_BE
|
||||||
|
#define hb_be_uint32_t GUINT32_TO_BE
|
||||||
|
#define hb_be_int32_t GINT32_TO_BE
|
||||||
|
#define hb_be_uint64_t GUINT64_TO_BE
|
||||||
|
#define hb_be_int64_t GINT64_TO_BE
|
||||||
|
|
||||||
|
#define HB_LIKELY G_LIKEYLY
|
||||||
|
#define HB_UNLIKELY G_UNLIKELY
|
||||||
|
#define HB_UNUSED(arg) ((arg) = (arg))
|
||||||
|
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define _ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1]
|
||||||
|
#define _ASSERT_STATIC0(_line, _cond) _ASSERT_STATIC1 (_line, (_cond))
|
||||||
|
#define ASSERT_STATIC(_cond) _ASSERT_STATIC0 (__LINE__, (_cond))
|
||||||
|
|
||||||
|
#define ASSERT_SIZE(_type, _size) ASSERT_STATIC (sizeof (_type) == (_size))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* buffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
#define HB_BUFFER_GLYPH_PROPERTIES_UNKNOWN 0xFFFF
|
||||||
|
|
||||||
|
#endif /* HB_PRIVATE_H */
|
|
@ -0,0 +1,174 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2007,2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, an OpenType Layout engine library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Red Hat Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define HB_OT_LAYOUT_CC
|
||||||
|
#include "hb-ot-layout-open-private.h"
|
||||||
|
#include "hb-ot-layout-gdef-private.h"
|
||||||
|
#include "hb-ot-layout-gsub-private.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
GMappedFile *mf = g_mapped_file_new (argv[1], FALSE, NULL);
|
||||||
|
const char *font_data = g_mapped_file_get_contents (mf);
|
||||||
|
int len = g_mapped_file_get_length (mf);
|
||||||
|
|
||||||
|
printf ("Opened font file %s: %d bytes long\n", argv[1], len);
|
||||||
|
|
||||||
|
const OpenTypeFontFile &ot = OpenTypeFontFile::get_for_data (font_data);
|
||||||
|
|
||||||
|
switch (ot.get_tag()) {
|
||||||
|
case OpenTypeFontFile::TrueTypeTag:
|
||||||
|
printf ("OpenType font with TrueType outlines\n");
|
||||||
|
break;
|
||||||
|
case OpenTypeFontFile::CFFTag:
|
||||||
|
printf ("OpenType font with CFF (Type1) outlines\n");
|
||||||
|
break;
|
||||||
|
case OpenTypeFontFile::TTCTag:
|
||||||
|
printf ("TrueType Collection of OpenType fonts\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("Unknown font format\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_fonts = ot.get_face_count ();
|
||||||
|
printf ("%d font(s) found in file\n", num_fonts);
|
||||||
|
for (int n_font = 0; n_font < num_fonts; n_font++) {
|
||||||
|
const OpenTypeFontFace &font = ot.get_face (n_font);
|
||||||
|
printf ("Font %d of %d:\n", n_font, num_fonts);
|
||||||
|
|
||||||
|
int num_tables = font.get_table_count ();
|
||||||
|
printf (" %d table(s) found in font\n", num_tables);
|
||||||
|
for (int n_table = 0; n_table < num_tables; n_table++) {
|
||||||
|
const OpenTypeTable &table = font.get_table (n_table);
|
||||||
|
printf (" Table %2d of %2d: %.4s (0x%08lx+0x%08lx)\n", n_table, num_tables,
|
||||||
|
(const char *)table.get_tag(), table.get_offset(), table.get_length());
|
||||||
|
|
||||||
|
switch (table.get_tag ()) {
|
||||||
|
|
||||||
|
case GSUBGPOS::GSUBTag:
|
||||||
|
case GSUBGPOS::GPOSTag:
|
||||||
|
{
|
||||||
|
|
||||||
|
const GSUBGPOS &g = GSUBGPOS::get_for_data (ot.get_table_data (table));
|
||||||
|
|
||||||
|
int num_scripts = g.get_script_count ();
|
||||||
|
printf (" %d script(s) found in table\n", num_scripts);
|
||||||
|
for (int n_script = 0; n_script < num_scripts; n_script++) {
|
||||||
|
const Script &script = g.get_script (n_script);
|
||||||
|
printf (" Script %2d of %2d: %.4s\n", n_script, num_scripts,
|
||||||
|
(const char *)g.get_script_tag(n_script));
|
||||||
|
|
||||||
|
if (!script.has_default_lang_sys())
|
||||||
|
printf (" No default language system\n");
|
||||||
|
int num_langsys = script.get_lang_sys_count ();
|
||||||
|
printf (" %d language system(s) found in script\n", num_langsys);
|
||||||
|
for (int n_langsys = script.has_default_lang_sys() ? -1 : 0; n_langsys < num_langsys; n_langsys++) {
|
||||||
|
const LangSys &langsys = n_langsys == -1
|
||||||
|
? script.get_default_lang_sys ()
|
||||||
|
: script.get_lang_sys (n_langsys);
|
||||||
|
printf (n_langsys == -1
|
||||||
|
? " Default Language System\n"
|
||||||
|
: " Language System %2d of %2d: %.4s\n", n_langsys, num_langsys,
|
||||||
|
(const char *)script.get_lang_sys_tag (n_langsys));
|
||||||
|
if (langsys.get_required_feature_index () == NO_INDEX)
|
||||||
|
printf (" No required feature\n");
|
||||||
|
|
||||||
|
int num_features = langsys.get_feature_count ();
|
||||||
|
printf (" %d feature(s) found in language system\n", num_features);
|
||||||
|
for (int n_feature = 0; n_feature < num_features; n_feature++) {
|
||||||
|
unsigned int feature_index = langsys.get_feature_index (n_feature);
|
||||||
|
printf (" Feature index %2d of %2d: %d\n", n_feature, num_features,
|
||||||
|
langsys.get_feature_index (n_feature));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_features = g.get_feature_count ();
|
||||||
|
printf (" %d feature(s) found in table\n", num_features);
|
||||||
|
for (int n_feature = 0; n_feature < num_features; n_feature++) {
|
||||||
|
const Feature &feature = g.get_feature (n_feature);
|
||||||
|
printf (" Feature %2d of %2d: %.4s; %d lookup(s)\n", n_feature, num_features,
|
||||||
|
(const char *)g.get_feature_tag(n_feature),
|
||||||
|
feature.get_lookup_count());
|
||||||
|
|
||||||
|
int num_lookups = feature.get_lookup_count ();
|
||||||
|
printf (" %d lookup(s) found in feature\n", num_lookups);
|
||||||
|
for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
|
||||||
|
unsigned int lookup_index = feature.get_lookup_index (n_lookup);
|
||||||
|
printf (" Lookup index %2d of %2d: %d\n", n_lookup, num_lookups,
|
||||||
|
feature.get_lookup_index (n_lookup));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int num_lookups = g.get_lookup_count ();
|
||||||
|
printf (" %d lookup(s) found in table\n", num_lookups);
|
||||||
|
for (int n_lookup = 0; n_lookup < num_lookups; n_lookup++) {
|
||||||
|
const Lookup &lookup = g.get_lookup (n_lookup);
|
||||||
|
printf (" Lookup %2d of %2d: type %d, flags 0x%04X\n", n_lookup, num_lookups,
|
||||||
|
lookup.get_type(), lookup.get_flag());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GDEF::Tag:
|
||||||
|
{
|
||||||
|
|
||||||
|
const GDEF &gdef = GDEF::get_for_data (ot.get_table_data (table));
|
||||||
|
|
||||||
|
printf (" Has %sglyph classes\n",
|
||||||
|
gdef.has_glyph_classes () ? "" : "no ");
|
||||||
|
printf (" Has %smark attachment types\n",
|
||||||
|
gdef.has_mark_attachment_types () ? "" : "no ");
|
||||||
|
printf (" Has %sattach list\n",
|
||||||
|
gdef.has_attach_list () ? "" : "no ");
|
||||||
|
printf (" Has %slig caret list\n",
|
||||||
|
gdef.has_lig_caret_list () ? "" : "no ");
|
||||||
|
|
||||||
|
for (int glyph = 0; glyph < 1; glyph++)
|
||||||
|
printf (" glyph %d has class %d and mark attachment type %d\n",
|
||||||
|
glyph,
|
||||||
|
gdef.get_glyph_class (glyph),
|
||||||
|
gdef.get_mark_attachment_type (glyph));
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue