summaryrefslogtreecommitdiffstats
path: root/src/base/ftpatent.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/ftpatent.c')
-rw-r--r--src/base/ftpatent.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/base/ftpatent.c b/src/base/ftpatent.c
new file mode 100644
index 0000000..d63f191
--- /dev/null
+++ b/src/base/ftpatent.c
@@ -0,0 +1,281 @@
+/***************************************************************************/
+/* */
+/* ftpatent.c */
+/* */
+/* FreeType API for checking patented TrueType bytecode instructions */
+/* (body). */
+/* */
+/* Copyright 2007 by David Turner. */
+/* */
+/* This file is part of the FreeType project, and may only be used, */
+/* modified, and distributed under the terms of the FreeType project */
+/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
+/* this file you indicate that you have read the license and */
+/* understand and accept it fully. */
+/* */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_STREAM_H
+#include FT_SERVICE_SFNT_H
+#include FT_SERVICE_TRUETYPE_GLYF_H
+
+
+ static FT_Bool
+ _tt_check_patents_in_range( FT_Stream stream,
+ FT_ULong size )
+ {
+ FT_Bool result = FALSE;
+ FT_Error error;
+ FT_Bytes p, end;
+
+
+ if ( FT_FRAME_ENTER( size ) )
+ return 0;
+
+ p = stream->cursor;
+ end = p + size;
+
+ while ( p < end )
+ {
+ switch (p[0])
+ {
+ case 0x06: /* SPvTL // */
+ case 0x07: /* SPvTL + */
+ case 0x08: /* SFvTL // */
+ case 0x09: /* SFvTL + */
+ case 0x0A: /* SPvFS */
+ case 0x0B: /* SFvFS */
+ result = TRUE;
+ goto Exit;
+
+ case 0x40:
+ if ( p + 1 >= end )
+ goto Exit;
+
+ p += p[1] + 2;
+ break;
+
+ case 0x41:
+ if ( p + 1 >= end )
+ goto Exit;
+
+ p += p[1] * 2 + 2;
+ break;
+
+ case 0x71: /* DELTAP2 */
+ case 0x72: /* DELTAP3 */
+ case 0x73: /* DELTAC0 */
+ case 0x74: /* DELTAC1 */
+ case 0x75: /* DELTAC2 */
+ result = TRUE;
+ goto Exit;
+
+ case 0xB0:
+ case 0xB1:
+ case 0xB2:
+ case 0xB3:
+ case 0xB4:
+ case 0xB5:
+ case 0xB6:
+ case 0xB7:
+ p += ( p[0] - 0xB0 ) + 2;
+ break;
+
+ case 0xB8:
+ case 0xB9:
+ case 0xBA:
+ case 0xBB:
+ case 0xBC:
+ case 0xBD:
+ case 0xBE:
+ case 0xBF:
+ p += ( p[0] - 0xB8 ) * 2 + 3;
+ break;
+
+ default:
+ p += 1;
+ break;
+ }
+ }
+
+ Exit:
+ FT_FRAME_EXIT();
+ return result;
+ }
+
+
+ static FT_Bool
+ _tt_check_patents_in_table( FT_Face face,
+ FT_ULong tag )
+ {
+ FT_Stream stream = face->stream;
+ FT_Error error;
+ FT_Service_SFNT_Table service;
+ FT_Bool result = FALSE;
+
+
+ FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
+
+ if ( service )
+ {
+ FT_ULong offset, size;
+
+
+ error = service->table_info( face, tag, &offset, &size );
+ if ( error ||
+ FT_STREAM_SEEK( offset ) )
+ goto Exit;
+
+ result = _tt_check_patents_in_range( stream, size );
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ static FT_Bool
+ _tt_face_check_patents( FT_Face face )
+ {
+ FT_Stream stream = face->stream;
+ FT_UInt gindex;
+ FT_Error error;
+ FT_Bool result;
+
+ FT_Service_TTGlyf service;
+
+
+ result = _tt_check_patents_in_table( face, TTAG_fpgm );
+ if ( result )
+ goto Exit;
+
+ result = _tt_check_patents_in_table( face, TTAG_prep );
+ if ( result )
+ goto Exit;
+
+ FT_FACE_FIND_SERVICE( face, service, TT_GLYF );
+ if ( service == NULL )
+ goto Exit;
+
+ for ( gindex = 0; gindex < (FT_UInt)face->num_glyphs; gindex++ )
+ {
+ FT_ULong offset, num_ins, size;
+ FT_Int num_contours;
+
+
+ offset = service->get_location( face, gindex, &size );
+ if ( size == 0 )
+ continue;
+
+ if ( FT_STREAM_SEEK( offset ) ||
+ FT_READ_SHORT( num_contours ) )
+ continue;
+
+ if ( num_contours >= 0 ) /* simple glyph */
+ {
+ if ( FT_STREAM_SKIP( 8 + num_contours * 2 ) )
+ continue;
+ }
+ else /* compound glyph */
+ {
+ FT_Bool has_instr = 0;
+
+
+ if ( FT_STREAM_SKIP( 8 ) )
+ continue;
+
+ /* now read each component */
+ for (;;)
+ {
+ FT_UInt flags, toskip;
+
+
+ if( FT_READ_USHORT( flags ) )
+ break;
+
+ toskip = 2 + 1 + 1;
+
+ if ( ( flags & ( 1 << 0 ) ) != 0 ) /* ARGS_ARE_WORDS */
+ toskip += 2;
+
+ if ( ( flags & ( 1 << 3 ) ) != 0 ) /* WE_HAVE_A_SCALE */
+ toskip += 2;
+ else if ( ( flags & ( 1 << 6 ) ) != 0 ) /* WE_HAVE_X_Y_SCALE */
+ toskip += 4;
+ else if ( ( flags & ( 1 << 7 ) ) != 0 ) /* WE_HAVE_A_2x2 */
+ toskip += 8;
+
+ if ( ( flags & ( 1 << 8 ) ) != 0 ) /* WE_HAVE_INSTRUCTIONS */
+ has_instr = 1;
+
+ if ( FT_STREAM_SKIP( toskip ) )
+ goto NextGlyph;
+
+ if ( ( flags & ( 1 << 5 ) ) == 0 ) /* MORE_COMPONENTS */
+ break;
+ }
+
+ if ( !has_instr )
+ goto NextGlyph;
+ }
+
+ if ( FT_READ_USHORT( num_ins ) )
+ continue;
+
+ result = _tt_check_patents_in_range( stream, num_ins );
+ if ( result )
+ goto Exit;
+
+ NextGlyph:
+ ;
+ }
+
+ Exit:
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Bool )
+ FT_Face_CheckTrueTypePatents( FT_Face face )
+ {
+ FT_Bool result = FALSE;
+
+
+ if ( face && FT_IS_SFNT( face ) )
+ result = _tt_face_check_patents( face );
+
+ return result;
+ }
+
+
+ /* documentation is in freetype.h */
+
+ FT_EXPORT_DEF( FT_Bool )
+ FT_Face_SetUnpatentedHinting( FT_Face face,
+ FT_Bool value )
+ {
+ FT_Bool result = 0;
+
+
+#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \
+ !defined( TT_CONFIG_OPTION_BYTECODE_INTEPRETER )
+ if ( face && FT_IS_SFNT( face ) )
+ {
+ result = !face->internal->ignore_unpatented_hinter;
+ face->internal->ignore_unpatented_hinter = !value;
+ }
+#else
+ FT_UNUSED( face );
+ FT_UNUSED( value );
+#endif
+
+ return result;
+ }
+
+/* END */