#include #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 = 0; 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 = 1; 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 = 1; 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 = 0; 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; } FT_EXPORT_DEF( FT_Bool ) FT_Face_CheckTrueTypePatents( FT_Face face ) { FT_Bool result = 0; if ( face && FT_IS_SFNT(face) ) { result = _tt_face_check_patents( face ); } return result; }