ref: e57ca7dec6a41dcf26c9551525d3645d1d73ab86
parent: 60b32e16e75cd3387160487693a24b61b08684b6
author: David Turner <[email protected]>
date: Wed Nov 6 20:36:29 EST 2002
* src/otlayout/otlayout.h, src/otlyaout/otlconf.h, src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otlparse.c, src/otlayout/otlparse.h, src/otlayout/otlutils.h: updating the OpenType Layout code, adding support fot the first GSUB lookups. Nothing that really compiles for now though * src/autohint/ahhint.c: disabled serif stem width quantization. It produces slightly better shapes though this is not distinguishable with many fonts.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2002-11-07 David Turner <[email protected]>
+
+ * src/otlayout/otlayout.h, src/otlyaout/otlconf.h,
+ src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otlparse.c,
+ src/otlayout/otlparse.h, src/otlayout/otlutils.h:
+
+ updating the OpenType Layout code, adding support fot the first
+ GSUB lookups. Nothing that really compiles for now though
+
2002-11-05 David Turner <[email protected]>
* include/freetype/config/ftoption.h, src/gzip/ftgzip.c: added
--- a/src/otlayout/otlayout.h
+++ b/src/otlayout/otlayout.h
@@ -24,9 +24,13 @@
typedef int OTL_Int;
typedef unsigned int OTL_UInt;
+ typedef long OTL_Long;
+ typedef unsigned long OTL_ULong;
+
typedef short OTL_Int16;
typedef unsigned short OTL_UInt16;
+
#if OTL_SIZEOF_INT == 4
typedef int OTL_Int32;
@@ -58,6 +62,8 @@
OTL_Err_InvalidFormat,
OTL_Err_InvalidOffset,
+ OTL_Err_Max
+
} OTL_Error;
@@ -64,16 +70,47 @@
/************************************************************************/
/************************************************************************/
/***** *****/
+ /***** MEMORY MANAGEMENT *****/
+ /***** *****/
+ /************************************************************************/
+ /************************************************************************/
+
+ typedef OTL_Pointer (*OTL_AllocFunc)( OTL_ULong size,
+ OTL_Pointer data );
+
+ typedef OTL_Pointer (*OTL_ReallocFunc)( OTL_Pointer block,
+ OTL_ULong size,
+ OTL_Pointer data );
+
+ typedef void (*OTL_FreeFunc)( OTL_Pointer block,
+ OTL_Pointer data );
+
+ typedef struct OTL_MemoryRec_
+ {
+ OTL_Pointer mem_data;
+ OTL_AllocFunc mem_alloc;
+ OTL_ReallocFunc mem_realloc;
+ OTL_FreeFunc mem_free;
+
+ } OTL_MemoryRec, *OTL_Memory;
+
+ /************************************************************************/
+ /************************************************************************/
+ /***** *****/
/***** ENUMERATIONS *****/
/***** *****/
/************************************************************************/
/************************************************************************/
+/* re-define OTL_MAKE_TAG to something different if you're not */
+/* using an ASCII-based character set (Vaxes anyone ?) */
+#ifndef OTL_MAKE_TAG
#define OTL_MAKE_TAG(c1,c2,c3,c4) \
( ( (OTL_UInt32)(c1) << 24 ) | \
(OTL_UInt32)(c2) << 16 ) | \
(OTL_UInt32)(c3) << 8 ) | \
(OTL_UInt32)(c4) )
+#endif
typedef enum OTL_ScriptTag_
{
@@ -153,8 +190,8 @@
#define OTL_INVALID(e) otl_validator_error( valid, e )
-#define OTL_INVALID_TOO_SHORT OTL_INVALID( OTL_Err_InvalidOffset );
-#define OTL_INVALID_DATA OTL_INVALID( OTL_Err_InvalidFormat );
+#define OTL_INVALID_TOO_SHORT OTL_INVALID( OTL_Err_InvalidOffset )
+#define OTL_INVALID_DATA OTL_INVALID( OTL_Err_InvalidFormat )
#define OTL_CHECK(_count) OTL_BEGIN_STMNT \
if ( p + (_count) > valid->limit ) \
--- a/src/otlayout/otlconf.h
+++ b/src/otlayout/otlconf.h
@@ -43,10 +43,10 @@
#define OTL_BEGIN_STMNT do {
#define OTL_END_STMNT } while (0)
-#define OTL_DUMMY_STMNT do { } while (0)
+#define OTL_DUMMY_STMNT OTL_BEGIN_STMNT OTL_END_STMNT
#define OTL_UNUSED( x ) (x)=(x)
-#define OTL_UNUSED_CONST(x) (void)(x)
+#define OTL_UNUSED_CONST(x) (void)(x)
#include <limits.h>
@@ -67,6 +67,11 @@
#else
# error "unsupported number of bytes in 'long' type!"
#endif
+
+#include <setjmp.h>
+#define OTL_jmp_buf jmp_buf
+#define otl_setjmp setjmp
+#define otl_longjmp longjmp
/* */
--- a/src/otlayout/otlgsub.c
+++ b/src/otlayout/otlgsub.c
@@ -9,6 +9,28 @@
/************************************************************************/
/************************************************************************/
+ /*
+ * 1: Single Substitution - Table format(s)
+ *
+ * This table is used to substiture individual glyph indices
+ * with another one. There are only two sub-formats:
+ *
+ * Name Offset Size Description
+ * ------------------------------------------
+ * format 0 2 sub-table format (1)
+ * offset 2 2 offset to coverage table
+ * delta 4 2 16-bit delta to apply on all
+ * covered glyph indices
+ *
+ * Name Offset Size Description
+ * ------------------------------------------
+ * format 0 2 sub-table format (2)
+ * offset 2 2 offset to coverage table
+ * count 4 2 coverage table count
+ * substs[] 6 2*count substituted glyph indices,
+ *
+ */
+
static void
otl_gsub_lookup1_validate( OTL_Bytes table,
OTL_Validator valid )
@@ -42,6 +64,10 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2*count );
+
+ /* NB: we don't check that there are at most 'count' */
+ /* elements in the coverage table. This is delayed */
+ /* to the lookup function... */
}
break;
@@ -51,6 +77,63 @@
}
+ static OTL_Bool
+ otl_gsub_lookup1_apply( OTL_Bytes table,
+ OTL_Parser parser )
+ {
+ OTL_Bytes p = table;
+ OTL_Bytes coverage;
+ OTL_UInt format, gindex, property;
+ OTL_Int index;
+ OTL_Bool subst = 0;
+
+ if ( parser->context_len != 0xFFFF && parser->context_len < 1 )
+ goto Exit;
+
+ gindex = otl_parser_get_gindex( parser );
+
+ if ( !otl_parser_check_property( parser, gindex, &property ) )
+ goto Exit;
+
+ format = OTL_NEXT_USHORT(p);
+ coverage = table + OTL_NEXT_USHORT(p);
+ index = otl_coverage_lookup( coverage, gindex );
+
+ if ( index >= 0 )
+ {
+ switch ( format )
+ {
+ case 1:
+ {
+ OTL_Int delta = OTL_NEXT_SHORT(p);
+
+ gindex = ( gindex + delta ) & 0xFFFF;
+ otl_parser_replace_1( parser, gindex );
+ subst = 1;
+ }
+ break;
+
+ case 2:
+ {
+ OTL_UInt count = OTL_NEXT_USHORT(p);
+
+ if ( (OTL_UInt) index < count )
+ {
+ p += index*2;
+ otl_parser_replace_1( parser, OTL_PEEK_USHORT(p) );
+ subst = 1;
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+ Exit:
+ return subst;
+ }
+
/************************************************************************/
/************************************************************************/
/***** *****/
@@ -59,6 +142,26 @@
/************************************************************************/
/************************************************************************/
+ /*
+ * 2: Multiple Substitution - Table format(s)
+ *
+ * Replaces a single glyph with one or more glyphs.
+ *
+ * Name Offset Size Description
+ * -----------------------------------------------------------
+ * format 0 2 sub-table format (1)
+ * offset 2 2 offset to coverage table
+ * count 4 2 coverage table count
+ * sequencess[] 6 2*count offsets to sequence items
+ *
+ * each sequence item has the following format:
+ *
+ * Name Offset Size Description
+ * -----------------------------------------------------------
+ * count 0 2 number of replacement glyphs
+ * gindices[] 2 2*count string of glyph indices
+ */
+
static void
otl_seq_validate( OTL_Bytes table,
OTL_Validator valid )
@@ -69,6 +172,9 @@
OTL_CHECK( 2 );
count = OTL_NEXT_USHORT( p );
+ /* XXX: according to the spec, 'count' should be > 0 */
+ /* we can deal with these cases pretty well however */
+
OTL_CHECK( 2*count );
/* check glyph indices */
}
@@ -106,6 +212,45 @@
}
}
+
+ static OTL_Bool
+ otl_gsub_lookup2_apply( OTL_Bytes table,
+ OTL_Parser parser )
+ {
+ OTL_Bytes p = table;
+ OTL_Bytes coverage, sequence;
+ OTL_UInt format, gindex, index, property;
+ OTL_Int index;
+ OTL_Bool subst = 0;
+
+ if ( context_len != 0xFFFF && context_len < 1 )
+ goto Exit;
+
+ gindex = otl_parser_get_gindex( parser );
+
+ if ( !otl_parser_check_property( parser, gindex, &property ) )
+ goto Exit;
+
+ p += 2; /* skip format */
+ coverage = table + OTL_NEXT_USHORT(p);
+ seq_count = OTL_NEXT_USHORT(p);
+ index = otl_coverage_lookup( coverage, gindex );
+
+ if ( (OTL_UInt) index >= seq_count )
+ goto Exit;
+
+ p += index*2;
+ sequence = table + OTL_PEEK_USHORT(p);
+ p = sequence;
+ count = OTL_NEXT_USHORT(p);
+
+ otl_parser_replace_n( parser, count, p );
+ subst = 1;
+
+ Exit:
+ return subst;
+ }
+
/************************************************************************/
/************************************************************************/
/***** *****/
@@ -114,6 +259,28 @@
/************************************************************************/
/************************************************************************/
+ /*
+ * 3: Alternate Substitution - Table format(s)
+ *
+ * Replaces a single glyph by another one taken liberally
+ * in a list of alternatives
+ *
+ * Name Offset Size Description
+ * -----------------------------------------------------------
+ * format 0 2 sub-table format (1)
+ * offset 2 2 offset to coverage table
+ * count 4 2 coverage table count
+ * alternates[] 6 2*count offsets to alternate items
+ *
+ * each alternate item has the following format:
+ *
+ * Name Offset Size Description
+ * -----------------------------------------------------------
+ * count 0 2 number of replacement glyphs
+ * gindices[] 2 2*count string of glyph indices, each one
+ * is a valid alternative
+ */
+
static void
otl_alternate_set_validate( OTL_Bytes table,
OTL_Validator valid )
@@ -161,6 +328,52 @@
}
}
+
+ static OTL_Bool
+ otl_gsub_lookup3_apply( OTL_Bytes table,
+ OTL_Parser parser )
+ {
+ OTL_Bytes p = table;
+ OTL_Bytes coverage, alternates;
+ OTL_UInt format, gindex, index, property;
+ OTL_Int index;
+ OTL_Bool subst = 0;
+
+ OTL_GSUB_Alternate alternate = parser->alternate;
+
+ if ( context_len != 0xFFFF && context_len < 1 )
+ goto Exit;
+
+ if ( alternate == NULL )
+ goto Exit;
+
+ gindex = otl_parser_get_gindex( parser );
+
+ if ( !otl_parser_check_property( parser, gindex, &property ) )
+ goto Exit;
+
+ p += 2; /* skip format */
+ coverage = table + OTL_NEXT_USHORT(p);
+ seq_count = OTL_NEXT_USHORT(p);
+ index = otl_coverage_lookup( coverage, gindex );
+
+ if ( (OTL_UInt) index >= seq_count )
+ goto Exit;
+
+ p += index*2;
+ alternates = table + OTL_PEEK_USHORT(p);
+ p = alternates;
+ count = OTL_NEXT_USHORT(p);
+
+ gindex = alternate->handler_func(
+ gindex, count, p, alternate->handler_data );
+
+ otl_parser_replace_1( parser, gindex );
+ subst = 1;
+
+ Exit:
+ return subst;
+ }
/************************************************************************/
/************************************************************************/
--- a/src/otlayout/otlgsub.h
+++ b/src/otlayout/otlgsub.h
@@ -5,6 +5,18 @@
OTL_BEGIN_HEADER
+ typedef OTL_UInt (*OTL_GSUB_AlternateFunc)( OTL_UInt gindex,
+ OTL_UInt count,
+ OTL_Bytes alternates,
+ OTL_Pointer data );
+
+ typedef struct OTL_GSUB_AlternateRec_
+ {
+ OTL_GSUB_AlternateFunc handler_func;
+ OTL_Pointer handler_data;
+
+ } OTL_GSUB_AlternateRec, *OTL_GSUB_Alternate;
+
OTL_LOCAL( void )
otl_gsub_validate( OTL_Bytes table,
OTL_Validator valid );
--- /dev/null
+++ b/src/otlayout/otlparse.c
@@ -1,0 +1,142 @@
+#include "otlparse.h"
+#include "otlutils.h"
+
+ static void
+ otl_string_ensure( OTL_String string,
+ OTL_UInt count,
+ OTL_Parser parser )
+ {
+ count += string->length;
+
+ if ( count > string->capacity )
+ {
+ OTL_UInt old_count = string->capacity;
+ OTL_UInt new_count = old_count;
+ OTL_Memory memory = parser->memory;
+
+ while ( new_count < count )
+ new_count += (new_count >> 1) + 16;
+
+ if ( OTL_MEM_RENEW_ARRAY( string->glyphs, old_count, new_count ) )
+ otl_parser_error( parser, OTL_Parse_Err_Memory );
+
+ string->capacity = new_count;
+ }
+ }
+
+#define OTL_STRING_ENSURE(str,count,parser) \
+ OTL_BEGIN_STMNT \
+ if ( (str)->length + (count) > (str)>capacity ) \
+ otl_string_ensure( str, count, parser ); \
+ OTL_END_STMNT
+
+
+ OTL_LOCALDEF( OTL_UInt )
+ otl_parser_get_gindex( OTL_Parser parser )
+ {
+ OTL_String in = parser->str_in;
+
+ if ( in->cursor >= in->num_glyphs )
+ otl_parser_error( parser, OTL_Err_Parser_Internal );
+
+ return in->str[ in->cursor ].gindex;
+ }
+
+
+ OTL_LOCALDEF( void )
+ otl_parser_error( OTL_Parser parser,
+ OTL_ParseError error; )
+ {
+ parser->error = error;
+ otl_longjmp( parser->jump_buffer, 1 );
+ }
+
+#define OTL_PARSER_UNCOVERED(x) otl_parser_error( x, OTL_Parse_Err_UncoveredGlyph );
+
+ OTL_LOCAL( void )
+ otl_parser_check_property( OTL_Parser parser,
+ OTL_UInt gindex,
+ OTL_UInt flags,
+ OTL_UInt *aproperty );
+
+ OTL_LOCALDEF( void )
+ otl_parser_replace_1( OTL_Parser parser,
+ OTL_UInt gindex )
+ {
+ OTL_String in = parser->str_in;
+ OTL_String out = parser->str_out;
+ OTL_StringGlyph glyph, in_glyph;
+
+ /* sanity check */
+ if ( in == NULL ||
+ out == NULL ||
+ in->length == 0 ||
+ in->cursor >= in->length )
+ {
+ /* report as internal error, since these should */
+ /* never happen !! */
+ otl_parser_error( parser, OTL_Err_Parse_Internal );
+ }
+
+ OTL_STRING_ENSURE( out, 1, parser );
+ glyph = out->glyphs + out->length;
+ in_glyph = in->glyphs + in->cursor;
+
+ glyph->gindex = gindex;
+ glyph->property = in_glyph->property;
+ glyph->lig_component = in_glyph->lig_component;
+ glyph->lig_id = in_glyph->lig_id;
+
+ out->length += 1;
+ out->cursor = out->length;
+ in->cursor += 1;
+ }
+
+ OTL_LOCALDEF( void )
+ otl_parser_replace_n( OTL_Parser parser,
+ OTL_UInt count,
+ OTL_Bytes indices )
+ {
+ OTL_UInt lig_component, lig_id, property;
+ OTL_String in = parser->str_in;
+ OTL_String out = parser->str_out;
+ OTL_StringGlyph glyph, in_glyph;
+ OTL_Bytes p = indices;
+
+ /* sanity check */
+ if ( in == NULL ||
+ out == NULL ||
+ in->length == 0 ||
+ in->cursor >= in->length )
+ {
+ /* report as internal error, since these should */
+ /* never happen !! */
+ otl_parser_error( parser, OTL_Err_Parse_Internal );
+ }
+
+ OTL_STRING_ENSURE( out, count, parser );
+ glyph = out->glyphs + out->length;
+ in_glyph = in->glyphs + in->cursor;
+
+ glyph->gindex = gindex;
+
+ lig_component = in_glyph->lig_component;
+ lig_id = in_glyph->lid_id;
+ property = in_glyph->property;
+
+ for ( ; count > 0; count-- )
+ {
+ glyph->gindex = OTL_NEXT_USHORT(p);
+ glyph->property = property;
+ glyph->lig_component = lig_component;
+ glyph->lig_id = lig_id;
+
+ out->length ++;
+ }
+
+ out->cursor = out->length;
+ in->cursor += 1;
+ }
+
+
+
--- /dev/null
+++ b/src/otlayout/otlparse.h
@@ -1,0 +1,99 @@
+#ifndef __OTL_PARSER_H__
+#define __OTL_PARSER_H__
+
+#include "otlayout.h"
+#include "otlgdef.h"
+#include "otlgsub.h"
+#include "otlgpos.h"
+
+OTL_BEGIN_HEADER
+
+ typedef struct OTL_ParserRec_* OTL_Parser;
+
+ typedef struct OTL_StringRec_* OTL_String;
+
+ typedef struct OTL_StringGlyphRec_
+ {
+ OTL_UInt gindex;
+ OTL_UInt properties;
+ OTL_UInt lig_component;
+ OTL_UInt lig_id;
+
+ } OTL_StringGlyphRec, *OTL_StringGlyph;
+
+ typedef struct OTL_StringRec_
+ {
+ OTL_StringGlyph glyphs;
+ OTL_UInt cursor;
+ OTL_UInt length;
+ OTL_UInt capacity;
+
+ } OTL_StringRec;
+
+ typedef struct OTL_ParserRec_
+ {
+ OTL_Bytes tab_gdef;
+ OTL_Bytes tab_gsub;
+ OTL_Bytes tab_gpos;
+ OTL_Bytes tab_base;
+ OTL_Bytes tab_jstf;
+
+ OTL_Alternate alternate; /* external alternate handler */
+
+ OTL_UInt context_len;
+ OTL_UInt markup_flags;
+
+ OTL_jmp_buf jump_buffer;
+ OTL_Memory memory;
+ OTL_Error error;
+
+ OTL_StringRec strings[2];
+ OTL_String str_in;
+ OTL_String str_out;
+
+ } OTL_ParserRec;
+
+ typedef enum
+ {
+ OTL_Err_Parser_Ok = 0,
+ OTL_Err_Parser_InvalidData,
+ OTL_Err_Parser_UncoveredGlyph
+
+ } OTL_ParseError;
+
+ OTL_LOCAL( OTL_UInt )
+ otl_parser_get_gindex( OTL_Parser parser );
+
+
+ OTL_LOCAL( void )
+ otl_parser_error( OTL_Parser parser, OTL_ParserError error );
+
+#define OTL_PARSER_UNCOVERED(x) \
+ otl_parser_error( x, OTL_Err_Parser_UncoveredGlyph )
+
+ OTL_LOCAL( void )
+ otl_parser_check_property( OTL_Parser parser,
+ OTL_UInt gindex,
+ OTL_UInt flags,
+ OTL_UInt *aproperty );
+
+ /* copy current input glyph to output */
+ OTL_LOCAL( void )
+ otl_parser_copy_1( OTL_Parser parser );
+
+ /* copy current input glyph to output, replacing its index */
+ OTL_LOCAL( void )
+ otl_parser_replace_1( OTL_Parser parser,
+ OTL_UInt gindex );
+
+ /* copy current input glyph to output, replacing it by several indices */
+ /* read directly from the table */
+ OTL_LOCAL( void )
+ otl_parser_replace_n( OTL_Parser parser,
+ OTL_UInt count,
+ OTL_Bytes indices );
+
+OTL_END_HEADER
+
+#endif /* __OTL_PARSER_H__ */
+
--- /dev/null
+++ b/src/otlayout/otlutils.h
@@ -1,0 +1,33 @@
+#ifndef __OTLAYOUT_UTILS_H__
+#define __OTLAYOUT_UTILS_H__
+
+#include "otlayout.h"
+
+OTL_BEGIN_HEADER
+
+ OTL_LOCAL( OTL_Error )
+ otl_mem_alloc( OTL_Pointer* pblock,
+ OTL_ULong size,
+ OTL_Memory memory );
+
+ OTL_LOCAL( void )
+ otl_mem_free( OTL_Pointer* pblock,
+ OTL_Memory memory );
+
+ OTL_LOCAL( OTL_Error )
+ otl_mem_realloc( OTL_Pointer *pblock,
+ OTL_ULong cur_size,
+ OTL_ULong new_size,
+ OTL_Memory memory );
+
+#define OTL_MEM_ALLOC(p,s) otl_mem_alloc( (void**)&(p), (s), memory )
+#define OTL_MEM_FREE(p) otl_mem_free( (void**)&(p), memory )
+#define OTL_MEM_REALLOC(p,c,n) otl_mem_realloc( (void**)&(p), (c), (s), memory )
+
+#define OTL_MEM_NEW(p) OTL_MEM_ALLOC(p,sizeof(*(p)))
+#define OTL_MEM_NEW_ARRAY(p,c) OTL_MEM_ALLOC(p,(c)*sizeof(*(p)))
+#define OTL_MEM_RENEW_ARRAY(p,c,n) OTL_MEM_REALLOC(p,(c)*sizeof(*(p)),(n)*sizeof(*(p)))
+
+OTL_END_HEADER
+
+#endif /* __OTLAYOUT_UTILS_H__ */