summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2009-11-02 14:35:51 -0500
committerBehdad Esfahbod <behdad@behdad.org>2009-11-02 14:38:33 -0500
commitce48f03946bef895912019046bdbe62bb1301d0b (patch)
treedb45789df9e20f4b119eeb8f6cf9e2d257558799
parent0e13beeb93077750183a8242780158b88df81e26 (diff)
parent2d15e72c75931398db5e027e660f1320bb979117 (diff)
downloadharfbuzz-ce48f03946bef895912019046bdbe62bb1301d0b.tar.gz
Merge harfbuzz-ngng-mergepoint
-rw-r--r--src/.gitignore1
-rw-r--r--src/Makefile.am16
-rw-r--r--src/Makefile.ng11
-rw-r--r--src/harfbuzz-buffer-private.h6
-rw-r--r--src/harfbuzz-global.h3
-rw-r--r--src/harfbuzz-gpos.c121
-rw-r--r--src/harfbuzz-gpos.h6
-rw-r--r--src/harfbuzz-gsub.c145
-rw-r--r--src/harfbuzz-gsub.h4
-rw-r--r--src/harfbuzz-impl.h11
-rw-r--r--src/harfbuzz-open.c9
-rw-r--r--src/harfbuzz.h1
-rw-r--r--src/hb-common.h54
-rw-r--r--src/hb-ot-layout-gdef-private.h276
-rw-r--r--src/hb-ot-layout-gsub-private.h583
-rw-r--r--src/hb-ot-layout-open-private.h993
-rw-r--r--src/hb-ot-layout-private.h66
-rw-r--r--src/hb-ot-layout.cc565
-rw-r--r--src/hb-ot-layout.h229
-rw-r--r--src/hb-private.h62
-rw-r--r--src/main.cc174
21 files changed, 3159 insertions, 177 deletions
diff --git a/src/.gitignore b/src/.gitignore
new file mode 100644
index 00000000..ba2906d0
--- /dev/null
+++ b/src/.gitignore
@@ -0,0 +1 @@
+main
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c0b18ef..40644c1a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,17 +2,20 @@
INCLUDES = \
-I $(srcdir) \
- $(FREETYPE_CFLAGS)
+ $(FREETYPE_CFLAGS) \
+ $(GLIB_CFLAGS)
+CXX = gcc $(GCCOPTS) -fno-rtti -fno-exceptions -Wabi -Wpadded -Wcast-align
noinst_LTLIBRARIES = libharfbuzz-1.la
MAINSOURCES = \
- harfbuzz.c
+ $(INCLUDEDSOURCES) \
+ hb-ot-layout.cc
+# harfbuzz.c
# included from harfbuzz.c
INCLUDEDSOURCES = \
harfbuzz-buffer.c \
- harfbuzz-gdef.c \
harfbuzz-gpos.c \
harfbuzz-gsub.c \
harfbuzz-impl.c \
@@ -23,7 +26,6 @@ PUBLICHEADERS = \
harfbuzz.h \
harfbuzz-global.h \
harfbuzz-buffer.h \
- harfbuzz-gdef.h \
harfbuzz-gpos.h \
harfbuzz-gsub.h \
harfbuzz-open.h
@@ -31,7 +33,6 @@ PUBLICHEADERS = \
PRIVATEHEADERS = \
harfbuzz-impl.h \
harfbuzz-buffer-private.h \
- harfbuzz-gdef-private.h \
harfbuzz-gpos-private.h \
harfbuzz-gsub-private.h \
harfbuzz-open-private.h \
@@ -45,7 +46,7 @@ libharfbuzz_1_la_SOURCES = \
libharfbuzz_1_la_LIBADD = \
$(FREETYPE_LIBS)
-noinst_PROGRAMS = harfbuzz-dump
+noinst_PROGRAMS = harfbuzz-dump main
harfbuzz_dump_SOURCES = \
harfbuzz-dump.c \
@@ -56,6 +57,9 @@ harfbuzz_dump_LDADD = \
$(libharfbuzz_1_la_LIBADD) \
libharfbuzz-1.la
+main_LDADD = \
+ $(GLIB_LIBS)
+
EXTRA_DIST = \
README \
COPYING \
diff --git a/src/Makefile.ng b/src/Makefile.ng
new file mode 100644
index 00000000..816269b4
--- /dev/null
+++ b/src/Makefile.ng
@@ -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
diff --git a/src/harfbuzz-buffer-private.h b/src/harfbuzz-buffer-private.h
index 5065f2e0..02ae3363 100644
--- a/src/harfbuzz-buffer-private.h
+++ b/src/harfbuzz-buffer-private.h
@@ -83,9 +83,9 @@ _hb_buffer_allocate_ligid( HB_Buffer buffer );
#define OUT_GLYPH( pos ) (buffer->out_string[(pos)].gindex)
#define OUT_ITEM( pos ) (&buffer->out_string[(pos)])
-#define CHECK_Property( gdef, index, flags, property ) \
- ( ( error = _HB_GDEF_Check_Property( (gdef), (index), (flags), \
- (property) ) ) != HB_Err_Ok )
+#define CHECK_Property( layout, index, flags, property ) \
+ (error = _hb_ot_layout_check_glyph_properties((layout), (index), (flags), (property)) \
+ ? HB_Err_Ok : HB_Err_Not_Covered)
#define ADD_String( buffer, num_in, num_out, glyph_data, component, ligID ) \
( ( error = _hb_buffer_add_output_glyphs( (buffer), \
diff --git a/src/harfbuzz-global.h b/src/harfbuzz-global.h
index dab20b54..7b8a0f27 100644
--- a/src/harfbuzz-global.h
+++ b/src/harfbuzz-global.h
@@ -28,6 +28,9 @@
#ifndef HARFBUZZ_GLOBAL_H
#define HARFBUZZ_GLOBAL_H
+/* XXX */
+#include "hb-ot-layout.h"
+
#include <ft2build.h>
#include FT_FREETYPE_H
diff --git a/src/harfbuzz-gpos.c b/src/harfbuzz-gpos.c
index c78dcba4..560a2911 100644
--- a/src/harfbuzz-gpos.c
+++ b/src/harfbuzz-gpos.c
@@ -75,7 +75,7 @@ static HB_Error default_mmfunc( HB_Font font,
HB_Error HB_Load_GPOS_Table( HB_Font font,
HB_GPOSHeader** retptr,
- HB_GDEFHeader* gdef )
+ hb_ot_layout_t *layout )
{
HB_UInt cur_offset, new_offset, base_offset;
@@ -85,7 +85,7 @@ HB_Error HB_Load_GPOS_Table( HB_Font font,
HB_Error error;
- if ( !retptr )
+ if ( !retptr || !layout )
return ERR(HB_Err_Invalid_Argument);
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 )
goto Fail2;
- gpos->gdef = gdef; /* can be NULL */
-
- if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, stream,
- gpos->LookupList.Lookup,
- gpos->LookupList.LookupCount ) ) )
- goto Fail1;
+ gpos->layout = layout; /* can be NULL */
*retptr = gpos;
return HB_Err_Ok;
-Fail1:
- _HB_OPEN_Free_LookupList( &gpos->LookupList, HB_Type_GPOS );
-
Fail2:
_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 )
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;
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 )
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;
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;
(buffer->in_pos)++;
- while ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ while ( CHECK_Property( gpos->layout, IN_CURITEM(),
flags, &property ) )
{
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.,
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;
/* We don't handle mark glyphs here. According to Andrei, this isn't
possible, but who knows... */
- if ( property == HB_GDEF_MARK )
+ if ( property == HB_OT_LAYOUT_GLYPH_CLASS_MARK )
{
gpi->last = 0xFFFF;
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 )
return HB_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ if ( CHECK_Property( gpos->layout, IN_CURITEM(),
flags, &property ) )
return error;
@@ -2232,12 +2224,11 @@ static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
while ( i <= buffer->in_pos )
{
- error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
+ property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
+ if ( !property )
+ return HB_Err_Not_Covered;
- 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;
i++;
@@ -2246,7 +2237,7 @@ static HB_Error Lookup_MarkBasePos( GPOS_Instance* gpi,
/* The following assertion is too strong -- at least for mangal.ttf. */
#if 0
- if ( property != HB_GDEF_BASE_GLYPH )
+ if ( property != HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH )
return HB_Err_Not_Covered;
#endif
@@ -2628,7 +2619,7 @@ static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
mark_glyph = IN_CURGLYPH();
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(), flags, &property ) )
+ if ( CHECK_Property( gpos->layout, IN_CURITEM(), flags, &property ) )
return error;
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 )
{
- error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
+ property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
+ if ( !property )
+ return HB_Err_Not_Covered;
- 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;
i++;
@@ -2657,7 +2647,7 @@ static HB_Error Lookup_MarkLigPos( GPOS_Instance* gpi,
/* Similar to Lookup_MarkBasePos(), I suspect that this assertion is
too strong, thus it is commented out. */
#if 0
- if ( property != HB_GDEF_LIGATURE )
+ if ( property != HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
return HB_Err_Not_Covered;
#endif
@@ -2951,7 +2941,7 @@ static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
if ( flags & HB_LOOKUP_FLAG_IGNORE_MARKS )
return HB_Err_Not_Covered;
- if ( CHECK_Property( gpos->gdef, IN_CURITEM(),
+ if ( CHECK_Property( gpos->layout, IN_CURITEM(),
flags, &property ) )
return error;
@@ -2970,12 +2960,11 @@ static HB_Error Lookup_MarkMarkPos( GPOS_Instance* gpi,
j = buffer->in_pos - 1;
while ( i <= buffer->in_pos )
{
- error = HB_GDEF_Get_Glyph_Property( gpos->gdef, IN_GLYPH( j ),
- &property );
- if ( error )
- return error;
+ property = _hb_ot_layout_get_glyph_properties (gpos->layout, IN_GLYPH(j));
+ if ( !property )
+ return HB_Err_Not_Covered;
- 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;
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_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;
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++ )
{
- 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 )
return error;
@@ -3849,12 +3838,12 @@ static HB_Error Lookup_ContextPos2( GPOS_Instance* gpi,
HB_PosClassSet* pcs;
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;
/* 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++ )
{
- 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 )
goto End;
@@ -3954,12 +3943,12 @@ static HB_Error Lookup_ContextPos3( GPOS_Instance* gpi,
HB_GPOSHeader* gpos = gpi->gpos;
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;
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++ )
{
- 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 )
return error;
@@ -4990,12 +4979,12 @@ static HB_Error Lookup_ChainContextPos1(
HB_ChainPosRule* 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;
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-- )
{
- 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 )
return error;
@@ -5056,7 +5045,7 @@ static HB_Error Lookup_ChainContextPos1(
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 )
return error;
@@ -5075,7 +5064,7 @@ static HB_Error Lookup_ChainContextPos1(
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 )
return error;
@@ -5130,12 +5119,12 @@ static HB_Error Lookup_ChainContextPos2(
HB_ChainPosClassSet* cpcs;
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;
/* 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-- )
{
- 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 )
goto End1;
@@ -5230,7 +5219,7 @@ static HB_Error Lookup_ChainContextPos2(
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 )
goto End1;
@@ -5260,7 +5249,7 @@ static HB_Error Lookup_ChainContextPos2(
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 )
goto End1;
@@ -5324,12 +5313,12 @@ static HB_Error Lookup_ChainContextPos3(
HB_Coverage* bc;
HB_Coverage* ic;
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;
bgc = ccpf3->BacktrackGlyphCount;
@@ -5353,7 +5342,7 @@ static HB_Error Lookup_ChainContextPos3(
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 )
return error;
@@ -5374,7 +5363,7 @@ static HB_Error Lookup_ChainContextPos3(
for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ )
{
/* 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 )
return error;
@@ -5396,7 +5385,7 @@ static HB_Error Lookup_ChainContextPos3(
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 )
return error;
diff --git a/src/harfbuzz-gpos.h b/src/harfbuzz-gpos.h
index 8638cf14..b1aa1350 100644
--- a/src/harfbuzz-gpos.h
+++ b/src/harfbuzz-gpos.h
@@ -26,7 +26,7 @@
#ifndef HARFBUZZ_GPOS_H
#define HARFBUZZ_GPOS_H
-#include "harfbuzz-gdef.h"
+#include "harfbuzz-open.h"
#include "harfbuzz-buffer.h"
HB_BEGIN_HEADER
@@ -86,7 +86,7 @@ struct HB_GPOSHeader_
HB_FeatureList FeatureList;
HB_LookupList LookupList;
- HB_GDEFHeader* gdef;
+ hb_ot_layout_t *layout;
/* the next field is used for a callback function to get the
glyph outline. */
@@ -107,7 +107,7 @@ typedef HB_GPOSHeader* HB_GPOS;
HB_Error HB_Load_GPOS_Table( HB_Font font,
HB_GPOSHeader** gpos,
- HB_GDEFHeader* gdef );
+ hb_ot_layout_t *layout );
HB_Error HB_Done_GPOS_Table( HB_GPOSHeader* gpos );
diff --git a/src/harfbuzz-gsub.c b/src/harfbuzz-gsub.c
index c05f20db..38879a85 100644
--- a/src/harfbuzz-gsub.c
+++ b/src/harfbuzz-gsub.c
@@ -47,7 +47,7 @@ static HB_Error GSUB_Do_Glyph_Lookup( HB_GSUBHeader* gsub,
HB_Error HB_Load_GSUB_Table( HB_Font font,
HB_GSUBHeader** retptr,
- HB_GDEFHeader* gdef )
+ hb_ot_layout_t *layout )
{
HB_Stream stream = font->stream;
HB_Error error;
@@ -55,7 +55,7 @@ HB_Error HB_Load_GSUB_Table( HB_Font font,
HB_GSUBHeader* gsub;
- if ( !retptr )
+ if ( !retptr || !layout )
return ERR(HB_Err_Invalid_Argument);
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 )
goto Fail2;
- gsub->gdef = gdef; /* can be NULL */
-
- if ( ( error = _HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( gdef, stream,
- gsub->LookupList.Lookup,
- gsub->LookupList.LookupCount ) ) )
- goto Fail1;
+ gsub->layout = layout; /* can be NULL */
*retptr = gsub;
return HB_Err_Ok;
-Fail1:
- _HB_OPEN_Free_LookupList( &gsub->LookupList, HB_Type_GSUB );
-
Fail2:
_HB_OPEN_Free_FeatureList( &gsub->FeatureList );
@@ -271,14 +263,14 @@ static HB_Error Lookup_SingleSubst( HB_GSUBHeader* gsub,
HB_UShort index, value, property;
HB_Error error;
HB_SingleSubst* ss = &st->single;
- HB_GDEFHeader* gdef = gsub->gdef;
+ hb_ot_layout_t* layout = gsub->layout;
HB_UNUSED(nesting_level);
if ( context_length != 0xFFFF && context_length < 1 )
return HB_Err_Not_Covered;
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
return error;
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);
}
- if ( gdef && gdef->NewGlyphClasses )
+ if ( _hb_ot_layout_has_new_glyph_classes (layout) )
{
/* we inherit the old glyph class to the substituted glyph */
- error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
- if ( error && error != HB_Err_Not_Covered )
- return error;
+ hb_ot_layout_set_glyph_class (layout, value, property);
}
return HB_Err_Ok;
@@ -477,14 +467,14 @@ static HB_Error Lookup_MultipleSubst( HB_GSUBHeader* gsub,
HB_UShort index, property, n, count;
HB_UShort*s;
HB_MultipleSubst* ms = &st->multiple;
- HB_GDEFHeader* gdef = gsub->gdef;
+ hb_ot_layout_t* layout = gsub->layout;
HB_UNUSED(nesting_level);
if ( context_length != 0xFFFF && context_length < 1 )
return HB_Err_Not_Covered;
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
return error;
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 ) )
return error;
- if ( gdef && gdef->NewGlyphClasses )
+ if ( _hb_ot_layout_has_new_glyph_classes (layout) )
{
/* this is a guess only ... */
- if ( property == HB_GDEF_LIGATURE )
- property = HB_GDEF_BASE_GLYPH;
+ if ( property == HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE )
+ property = HB_OT_LAYOUT_GLYPH_CLASS_BASE_GLYPH;
for ( n = 0; n < count; n++ )
- {
- error = _HB_GDEF_Add_Glyph_Property( gdef, s[n], property );
- if ( error && error != HB_Err_Not_Covered )
- return error;
- }
+ hb_ot_layout_set_glyph_class (layout, s[n], property);
}
return HB_Err_Ok;
@@ -674,7 +660,7 @@ static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
HB_Error error;
HB_UShort index, value, alt_index, property;
HB_AlternateSubst* as = &st->alternate;
- HB_GDEFHeader* gdef = gsub->gdef;
+ hb_ot_layout_t* layout = gsub->layout;
HB_AlternateSet aset;
HB_UNUSED(nesting_level);
@@ -682,7 +668,7 @@ static HB_Error Lookup_AlternateSubst( HB_GSUBHeader* gsub,
if ( context_length != 0xFFFF && context_length < 1 )
return HB_Err_Not_Covered;
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
return error;
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 ) )
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 */
-
- error = _HB_GDEF_Add_Glyph_Property( gdef, value, property );
- if ( error && error != HB_Err_Not_Covered )
- return error;
- }
+ hb_ot_layout_set_glyph_class (layout, value, property);
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* c;
HB_LigatureSubst* ls = &st->ligature;
- HB_GDEFHeader* gdef = gsub->gdef;
+ hb_ot_layout_t* layout = gsub->layout;
HB_Ligature* lig;
HB_UNUSED(nesting_level);
- if ( CHECK_Property( gdef, IN_CURITEM(), flags, &property ) )
+ if ( CHECK_Property( layout, IN_CURITEM(), flags, &property ) )
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;
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++ )
{
- 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 )
return error;
@@ -1000,22 +981,16 @@ static HB_Error Lookup_LigatureSubst( HB_GSUBHeader* gsub,
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;
if ( IN_GLYPH( j ) != c[i - 1] )
goto next_ligature;
}
- if ( gdef && gdef->NewGlyphClasses )
- {
+ if ( _hb_ot_layout_has_new_glyph_classes (layout) )
/* this is just a guess ... */
-
- 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;
- }
+ hb_ot_layout_set_glyph_class (layout, lig->LigGlyph, is_mark ? HB_OT_LAYOUT_GLYPH_CLASS_MARK : HB_OT_LAYOUT_GLYPH_CLASS_LIGATURE);
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++ )
{
- while ( CHECK_Property( gdef, IN_CURITEM(),
+ while ( CHECK_Property( layout, IN_CURITEM(),
flags, &property ) )
if ( ADD_Glyph( buffer, IN_CURGLYPH(), i, ligID ) )
return error;
@@ -1813,12 +1788,12 @@ static HB_Error Lookup_ContextSubst1( HB_GSUBHeader* gsub,
HB_Error error;
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;
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++ )
{
- 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 )
return error;
@@ -1880,12 +1855,12 @@ static HB_Error Lookup_ContextSubst2( HB_GSUBHeader* gsub,
HB_SubClassSet* scs;
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;
/* 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++ )
{
- 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 )
goto End;
@@ -1984,12 +1959,12 @@ static HB_Error Lookup_ContextSubst3( HB_GSUBHeader* gsub,
HB_UShort index, i, j, property;
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;
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++ )
{
- 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 )
return error;
@@ -3004,12 +2979,12 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
HB_ChainSubRule* 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;
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-- )
{
- 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 )
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++ )
{
- 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 )
return error;
@@ -3089,7 +3064,7 @@ static HB_Error Lookup_ChainContextSubst1( HB_GSUBHeader* gsub,
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 )
return error;
@@ -3142,12 +3117,12 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
HB_ChainSubClassSet* cscs;
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;
/* 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-- )
{
- 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 )
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++ )
{
- 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 )
goto End1;
@@ -3272,7 +3247,7 @@ static HB_Error Lookup_ChainContextSubst2( HB_GSUBHeader* gsub,
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 )
goto End1;
@@ -3334,12 +3309,12 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
HB_Coverage* bc;
HB_Coverage* ic;
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;
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-- )
{
- 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 )
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++ )
{
/* 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 )
return error;
@@ -3406,7 +3381,7 @@ static HB_Error Lookup_ChainContextSubst3( HB_GSUBHeader* gsub,
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 )
return error;
@@ -3653,14 +3628,14 @@ static HB_Error Lookup_ReverseChainContextSubst( HB_GSUBHeader* gsub,
HB_ReverseChainContextSubst* rccs = &st->reverse;
HB_Coverage* bc;
HB_Coverage* lc;
- HB_GDEFHeader* gdef;
+ hb_ot_layout_t* layout;
if ( nesting_level != 1 || context_length != 0xFFFF )
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;
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-- )
{
- 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 )
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++ )
{
- 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 )
return error;
diff --git a/src/harfbuzz-gsub.h b/src/harfbuzz-gsub.h
index 3d6cfa18..b1e78ce9 100644
--- a/src/harfbuzz-gsub.h
+++ b/src/harfbuzz-gsub.h
@@ -68,7 +68,7 @@ struct HB_GSUBHeader_
HB_FeatureList FeatureList;
HB_LookupList LookupList;
- HB_GDEFHeader* gdef;
+ hb_ot_layout_t *layout;
/* the next two fields are used for an alternate substitution callback
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_GSUBHeader** gsub,
- HB_GDEFHeader* gdef );
+ hb_ot_layout_t *layout );
HB_Error HB_Done_GSUB_Table( HB_GSUBHeader* gsub );
diff --git a/src/harfbuzz-impl.h b/src/harfbuzz-impl.h
index f886e676..29101f87 100644
--- a/src/harfbuzz-impl.h
+++ b/src/harfbuzz-impl.h
@@ -34,6 +34,9 @@
#include <stdlib.h>
+/* XXX */
+#include "hb-ot-layout-private.h"
+
HB_BEGIN_HEADER
#ifndef HB_INTERNAL
@@ -66,8 +69,12 @@ HB_BEGIN_HEADER
# define HB_UNUSED(arg) ((arg) = (arg))
#endif
-#define HB_LIKELY(cond) (cond)
-#define HB_UNLIKELY(cond) (cond)
+#ifndef HB_LIKELY
+# define HB_LIKELY(cond) (cond)
+#endif
+#ifndef HB_UNLIKELY
+# define HB_UNLIKELY(cond) (cond)
+#endif
#define ALLOC(_ptr,_size) \
diff --git a/src/harfbuzz-open.c b/src/harfbuzz-open.c
index e187916e..68b27d4b 100644
--- a/src/harfbuzz-open.c
+++ b/src/harfbuzz-open.c
@@ -124,15 +124,6 @@ static HB_Error Load_Script( HB_ScriptTable* s,
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();
s->LangSysRecord = NULL;
diff --git a/src/harfbuzz.h b/src/harfbuzz.h
index 10d4f74d..d23b6bc2 100644
--- a/src/harfbuzz.h
+++ b/src/harfbuzz.h
@@ -28,7 +28,6 @@
#include "harfbuzz-global.h"
#include "harfbuzz-buffer.h"
-#include "harfbuzz-gdef.h"
#include "harfbuzz-gsub.h"
#include "harfbuzz-gpos.h"
#include "harfbuzz-open.h"
diff --git a/src/hb-common.h b/src/hb-common.h
new file mode 100644
index 00000000..d404353c
--- /dev/null
+++ b/src/hb-common.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 */
diff --git a/src/hb-ot-layout-gdef-private.h b/src/hb-ot-layout-gdef-private.h
new file mode 100644
index 00000000..5418d8b1
--- /dev/null
+++ b/src/hb-ot-layout-gdef-private.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 */
diff --git a/src/hb-ot-layout-gsub-private.h b/src/hb-ot-layout-gsub-private.h
new file mode 100644
index 00000000..c8d5405b
--- /dev/null
+++ b/src/hb-ot-layout-gsub-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 */
diff --git a/src/hb-ot-layout-open-private.h b/src/hb-ot-layout-open-private.h
new file mode 100644
index 00000000..d5ca8105
--- /dev/null
+++ b/src/hb-ot-layout-open-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 */
diff --git a/src/hb-ot-layout-private.h b/src/hb-ot-layout-private.h
new file mode 100644
index 00000000..a1be8aaf
--- /dev/null
+++ b/src/hb-ot-layout-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 */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
new file mode 100644
index 00000000..01923db4
--- /dev/null
+++ b/src/hb-ot-layout.cc
@@ -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;
+}
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
new file mode 100644
index 00000000..c29485c0
--- /dev/null
+++ b/src/hb-ot-layout.h
@@ -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 */
diff --git a/src/hb-private.h b/src/hb-private.h
new file mode 100644
index 00000000..3dca0490
--- /dev/null
+++ b/src/hb-private.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 */
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 00000000..ffd13b4a
--- /dev/null
+++ b/src/main.cc
@@ -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;
+}