Exemplo n.º 1
0
// static
IFX_GSUBTable* IFX_GSUBTable::Create(CFX_Font* pFont) {
  if (!pFont) {
    return NULL;
  }
  if (!pFont->GetSubData()) {
    unsigned long length = 0;
    int error = FXFT_Load_Sfnt_Table(
        pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length);
    if (!error) {
      pFont->SetSubData((uint8_t*)FX_Alloc(uint8_t, length));
    }
    if (!pFont->GetSubData()) {
      return NULL;
    }
  }
  int error =
      FXFT_Load_Sfnt_Table(pFont->GetFace(), FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
                           pFont->GetSubData(), NULL);
  if (!error && pFont->GetSubData()) {
    nonstd::unique_ptr<CFX_GSUBTable> pGsubTable(new CFX_GSUBTable);
    if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->GetSubData())) {
      return pGsubTable.release();
    }
  }
  return NULL;
}
Exemplo n.º 2
0
IFX_GSUBTable* FXGE_CreateGSUBTable(CFX_Font* pFont)
{
    if (!pFont) {
        return NULL;
    }
    if (NULL == pFont->m_pGsubData) {
        unsigned long length = 0;
        int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, NULL, &length);
        if (!error) {
            pFont->m_pGsubData = (unsigned char*)FX_Alloc(FX_BYTE, length);
        }
        if (!pFont->m_pGsubData) {
            return NULL;
        }
    }
    int error = FXFT_Load_Sfnt_Table(pFont->m_Face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0, pFont->m_pGsubData, NULL);
    if (!error && pFont->m_pGsubData) {
        CFX_GSUBTable* pGsubTable = FX_NEW CFX_GSUBTable;
        if (!pGsubTable) {
            return NULL;
        }
        if (pGsubTable->m_GsubImp.LoadGSUBTable((FT_Bytes)pFont->m_pGsubData)) {
            return pGsubTable;
        }
        pGsubTable->Release();
    }
    return NULL;
}
Exemplo n.º 3
0
int CPDF_CIDFont::GetGlyphIndex(uint32_t unicode, bool* pVertGlyph) {
  if (pVertGlyph)
    *pVertGlyph = false;

  FXFT_Face face = m_Font.GetFace();
  int index = FXFT_Get_Char_Index(face, unicode);
  if (unicode == 0x2502)
    return index;

  if (!index || !IsVertWriting())
    return index;

  if (m_pTTGSUBTable)
    return GetVerticalGlyph(index, pVertGlyph);

  if (!m_Font.GetSubData()) {
    unsigned long length = 0;
    int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
                                     nullptr, &length);
    if (!error)
      m_Font.SetSubData(FX_Alloc(uint8_t, length));
  }
  int error = FXFT_Load_Sfnt_Table(face, FT_MAKE_TAG('G', 'S', 'U', 'B'), 0,
                                   m_Font.GetSubData(), nullptr);
  if (error || !m_Font.GetSubData())
    return index;

  m_pTTGSUBTable = pdfium::MakeUnique<CFX_CTTGSUBTable>();
  m_pTTGSUBTable->LoadGSUBTable((FT_Bytes)m_Font.GetSubData());
  return GetVerticalGlyph(index, pVertGlyph);
}
Exemplo n.º 4
0
static PangoOTRuleset *
get_gpos_ruleset (FT_Face face, const PangoIndicInfo *indic_info)
{
  PangoOTInfo    *info = pango_ot_info_get (face);
  GQuark          ruleset_quark = g_quark_from_string (indic_info->gposQuarkName);
  PangoOTRuleset *ruleset;

  if (!info)
    return NULL;

  ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);

  if (!ruleset)
    {
      guint    script_index;

      ruleset = pango_ot_ruleset_new (info);

      if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS,
				     indic_info->scriptTag, &script_index))
	{
	  maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','m'), blwm);
	  maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','m'), abvm);
	  maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','i','s','t'), dist);
	}

      g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
			       (GDestroyNotify)g_object_unref);
    }

  return ruleset;
}
Exemplo n.º 5
0
NSFonts::IFontFile* NSFonts::IFontManager::LoadFontFile(NSFonts::CLibrary& library, NSFonts::IFontStream* pStreamI, int lFaceIndex)
{
    CFontStream* pStream = (CFontStream*)pStreamI;
	FT_Open_Args oOpenArgs;
	oOpenArgs.flags			= FT_OPEN_MEMORY | FT_OPEN_PARAMS;
	oOpenArgs.memory_base	= pStream->m_pData;
	oOpenArgs.memory_size	= pStream->m_lSize;

	FT_Parameter *pParams = (FT_Parameter *)::malloc( sizeof(FT_Parameter) * 4 );
	pParams[0].tag  = FT_MAKE_TAG( 'i', 'g', 'p', 'f' );
	pParams[0].data = NULL;
	pParams[1].tag  = FT_MAKE_TAG( 'i', 'g', 'p', 's' );
	pParams[1].data = NULL; 
	pParams[2].tag  = FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY;
	pParams[2].data = NULL; 
	pParams[3].tag  = FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY;
	pParams[3].data = NULL; 

	oOpenArgs.params = pParams;
	oOpenArgs.num_params = 4;

	FT_Face pFace;
    if ( FT_Open_Face( library.m_internal->m_library, &oOpenArgs, lFaceIndex, &pFace ) )
		return NULL;

	::free(pParams);

	CFontFile* pFont = new CFontFile();
	pFont->m_lFaceIndex = lFaceIndex;

	pFont->m_lUnits_Per_Em	= pFace->units_per_EM;
	pFont->m_lAscender		= pFace->ascender;
	pFont->m_lDescender		= pFace->descender;
	pFont->m_lLineHeight	= pFace->height;

	pFont->m_nNum_charmaps	= pFace->num_charmaps;

	pFont->m_pFace = pFace;
	pFont->LoadDefaultCharAndSymbolicCmapIndex();

	if (FT_Set_Char_Size(pFace, 0, (FT_F26Dot6)(pFont->m_dSize * 64), 0, 0))
	{
		FT_Done_Face(pFace);
		delete pFont;
		return NULL;
	}

	pFont->ResetTextMatrix();
	pFont->ResetFontMatrix();

	return pFont;
}
Exemplo n.º 6
0
void ttfInitMAXP(TTFontPtr font)
{
    ULONG tag = FT_MAKE_TAG ('m', 'a', 'x', 'p');
    TableDirPtr ptd;

    if ((ptd = ttfLookUpTableDir(tag,font)) != NULL)
	{
	    font->maxp = XCALLOC1 (MAXP);
	    ttfLoadMAXP(font->fp,font->maxp,ptd->offset);
	}
}
Exemplo n.º 7
0
void ttfInitLTSH(TTFontPtr font)
{
    ULONG tag = FT_MAKE_TAG ('L', 'T', 'S', 'H');
    TableDirPtr ptd;
     
    if ((ptd = ttfLookUpTableDir(tag,font)) != NULL)
	{
	    font->ltsh = XCALLOC1 (LTSH);
	    ttfLoadLTSH(font->fp,font->ltsh,ptd->offset);
	}
}
Exemplo n.º 8
0
void ttfInitGASP(TTFontPtr font)
{
    ULONG tag = FT_MAKE_TAG ('g', 'a', 's', 'p');
    TableDirPtr ptd;
     
    if ((ptd = ttfLookUpTableDir(tag,font)) != NULL)
	{
	    font->gasp = XCALLOC1 (GASP);
	    ttfLoadGASP(font->fp,font->gasp,ptd->offset);
	}
}
Exemplo n.º 9
0
void ttfInitCVT(TTFontPtr font)
{
    ULONG tag = FT_MAKE_TAG ('c', 'v', 't', ' ');
    TableDirPtr ptd;

    if ((ptd = ttfLookUpTableDir(tag,font)) != NULL)
    {
        font->cvtLength = ptd->length / sizeof(FWord);
        font->cvt = XCALLOC (font->cvtLength, FWord);
        ttfLoadCVT(font->fp,font->cvt,font->cvtLength,ptd->offset);
    }
}
Exemplo n.º 10
0
/* Caution: Because of interdependency between tables, 
 * table vhea and maxp should be well initalized before
 * ttfInitVMTX has been called
 */
void ttfInitVMTX(TTFontPtr font)
{
    ULONG tag = FT_MAKE_TAG ('v', 'm', 't', 'x');
    TableDirPtr ptd;
    
    if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) 
	{
	    font->vmtx = XCALLOC1 (VMTX);
	    font->vmtx->numOfLongVerMetrics = 
		font->vhea->numOfLongVerMetrics;
	    font->vmtx->numOfTSB = font->maxp->numGlyphs - 
		font->vhea->numOfLongVerMetrics; 
	    ttfLoadVMTX(font->fp,font->vmtx,ptd->offset);
	}
}
Exemplo n.º 11
0
static char* getTable(char* t, FT_Face face)
      {
      FT_ULong tag = FT_MAKE_TAG(t[0], t[1], t[2], t[3]);
      FT_ULong length = 0;
      int error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length);
      if (error) {
            qDebug("genft: cannot load table LILC");
            exit(-3);
            }
      FT_Byte* buffer = (FT_Byte*)malloc(length + 1);
      error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &length);
      buffer[length] = 0;
      if (error) {
            qDebug("genft: cannot load font table LILC");
            exit(4);
            }
      return (char*)buffer;
      }
Exemplo n.º 12
0
void KernFeature::makeCoverage()
{
	if ( GPOSTableRaw.isEmpty() )
		return;

	quint16 FeatureList_Offset= toUint16 ( 6 );
	quint16 LookupList_Offset = toUint16 ( 8 );

	// Find the offsets of the kern feature tables
	quint16 FeatureCount = toUint16 ( FeatureList_Offset );;
	QList<quint16> FeatureKern_Offset;
	for ( quint16 FeatureRecord ( 0 ); FeatureRecord < FeatureCount; ++ FeatureRecord )
	{
		int rawIdx ( FeatureList_Offset + 2 + ( 6 * FeatureRecord ) );
		quint32 tag ( FT_MAKE_TAG ( GPOSTableRaw.at ( rawIdx ),
		                            GPOSTableRaw.at ( rawIdx + 1 ),
		                            GPOSTableRaw.at ( rawIdx + 2 ),
		                            GPOSTableRaw.at ( rawIdx + 3 ) ) );
		if ( tag == TTAG_kern )
		{
			FeatureKern_Offset << ( toUint16 ( rawIdx + 4 ) + FeatureList_Offset );

		}
	}

	// Extract indices of lookups for feture kern
	QList<quint16> LookupListIndex;
	foreach ( quint16 kern, FeatureKern_Offset )
	{
		quint16 LookupCount ( toUint16 ( kern + 2 ) );
		for ( int llio ( 0 ) ; llio < LookupCount; ++llio )
		{
			quint16 Idx ( toUint16 ( kern + 4 + ( llio * 2 ) ) );
			if ( !LookupListIndex.contains ( Idx ) )
			{
				LookupListIndex <<Idx ;
			}
		}
	}
Exemplo n.º 13
0
static void readGPOSTable(SFFontRef sfFont) {
	FT_ULong length = 0;
    
    FT_Tag tag;
    FT_Byte *buffer;
    
    FT_Error error;
    
	tag = FT_MAKE_TAG('G', 'P', 'O', 'S');
	error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length);
	if (error)
		return;
    
	buffer = malloc(length);
    error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length);
	if (!error) {
		SFReadGPOS(buffer, &sfFont->_gpos);
		sfFont->_availableFontTables |= itGPOS;
	}
    
	free(buffer);
}
Exemplo n.º 14
0
static void readCMAPTable(SFFontRef sfFont) {
	FT_ULong length = 0;
    
    FT_Tag tag;
    FT_Byte *buffer;
    
    FT_Error error;
    
	tag = FT_MAKE_TAG('c', 'm', 'a', 'p');
	error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length);
	if (error)
		return;
    
	buffer = malloc(length);
	error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length);
	if (!error) {
		SFReadCMAP(buffer, &sfFont->_cmap, length);
		sfFont->_availableFontTables |= itCMAP;
	}
    
	free(buffer);
}
Exemplo n.º 15
0
static void readGSUBTable(SFFontRef sfFont) {
	FT_ULong length = 0;
    
    FT_Tag tag;
    FT_Byte *buffer;
    
    FT_Error error;
    
	tag = FT_MAKE_TAG('G', 'S', 'U', 'B');
	error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, NULL, &length);
	if (error)
		return;
    
	buffer = malloc(length);
	error = FT_Load_Sfnt_Table(sfFont->_ftFace, tag, 0, buffer, &length);
	if (!error) {
		SFReadGSUB(buffer, &sfFont->_tables->_gsub);
		sfFont->_tables->_availableTables |= itGSUB;
	}
    
	free(buffer);
}
Exemplo n.º 16
0
static PangoOTRuleset *
get_gsub_ruleset (FT_Face face, const PangoIndicInfo *indic_info)
{
  PangoOTInfo    *info = pango_ot_info_get (face);
  GQuark          ruleset_quark = g_quark_from_string (indic_info->gsubQuarkName);
  PangoOTRuleset *ruleset;

  if (!info)
    return NULL;

  ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);

  if (!ruleset)
    {
      guint    script_index;

      ruleset = pango_ot_ruleset_new (info);

     if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB,
				     indic_info->scriptTag, &script_index))
	{
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('i','n','i','t'), init);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('n','u','k','t'), nukt);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','k','h','n'), akhn);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('r','p','h','f'), rphf);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','f'), blwf);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('h','a','l','f'), half);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','f'), pstf);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('v','a','t','u'), vatu);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','s'), pres);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','s'), blws);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','s'), abvs);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','s'), psts);
	  maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('h','a','l','n'), haln);
	}

      g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
			       (GDestroyNotify)g_object_unref);
    }

  return ruleset;
}
Exemplo n.º 17
0
static PangoOTRuleset *
get_ruleset (FT_Face face)
{
  PangoOTRuleset *ruleset;
  static GQuark ruleset_quark = 0;

  PangoOTInfo *info = pango_ot_info_get (face);

  if (!ruleset_quark)
    ruleset_quark = g_quark_from_string ("pango-khmer-ruleset");

  if (!info)
    return NULL;

  ruleset = g_object_get_qdata (G_OBJECT (info), ruleset_quark);

  if (!ruleset)
    {
      PangoOTTag khmer_tag = FT_MAKE_TAG ('k', 'h', 'm', 'r');
      guint script_index;

      ruleset = pango_ot_ruleset_new (info);

      if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GSUB,
                                      khmer_tag, &script_index))
        {
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','f'), pref);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','f'), blwf);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','f'), abvf);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','f'), pstf);

          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','r','e','s'), pres);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','s'), blws);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','s'), abvs);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('p','s','t','s'), psts);
          maybe_add_GSUB_feature (ruleset, info, script_index, FT_MAKE_TAG ('c','l','i','g'), clig);
        }

      if (pango_ot_info_find_script (info, PANGO_OT_TABLE_GPOS,
                                      khmer_tag, &script_index))
        {
          maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('d','i','s','t'), dist);
          maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('b','l','w','m'), blwm);
          maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('a','b','v','m'), abvm);
          maybe_add_GPOS_feature (ruleset, info, script_index, FT_MAKE_TAG ('m','k','m','k'), mkmk);
        }

      g_object_set_qdata_full (G_OBJECT (info), ruleset_quark, ruleset,
                                (GDestroyNotify)g_object_unref);
    }

  return ruleset;
}
Exemplo n.º 18
0
  /* synthesized into a TTC with one offset table.              */
  static FT_Error
  sfnt_open_font( FT_Stream  stream,
                  TT_Face    face )
  {
    FT_Memory  memory = stream->memory;
    FT_Error   error;
    FT_ULong   tag, offset;

    static const FT_Frame_Field  ttc_header_fields[] =
    {
#undef  FT_STRUCTURE
#define FT_STRUCTURE  TTC_HeaderRec

      FT_FRAME_START( 8 ),
        FT_FRAME_LONG( version ),
        FT_FRAME_LONG( count   ),
      FT_FRAME_END
    };


    face->ttc_header.tag     = 0;
    face->ttc_header.version = 0;
    face->ttc_header.count   = 0;

    offset = FT_STREAM_POS();

    if ( FT_READ_ULONG( tag ) )
      return error;

    if ( tag != 0x00010000UL                      &&
         tag != TTAG_ttcf                         &&
         tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) &&
         tag != TTAG_true                         &&
         tag != 0x00020000UL                      )
      return SFNT_Err_Unknown_File_Format;

    face->ttc_header.tag = TTAG_ttcf;

    if ( tag == TTAG_ttcf )
    {
      FT_Int  n;


      FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));

      if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
        return error;

      /* now read the offsets of each font in the file */
      if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
        return error;

      if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
        return error;

      for ( n = 0; n < face->ttc_header.count; n++ )
        face->ttc_header.offsets[n] = FT_GET_ULONG();

      FT_FRAME_EXIT();
    }
    else
    {
      FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));

      face->ttc_header.version = 1 << 16;
      face->ttc_header.count   = 1;

      if ( FT_NEW( face->ttc_header.offsets) )
        return error;

      face->ttc_header.offsets[0] = offset;
    }

    return error;
  }
Exemplo n.º 19
0
  static FT_Error
  check_table_dir( SFNT_Header  sfnt,
                   FT_Stream    stream )
  {
    FT_Error        error;
    FT_UInt         nn;
    FT_UInt         has_head = 0, has_sing = 0, has_meta = 0;
    FT_ULong        offset = sfnt->offset + 12;

    const FT_ULong  glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
    const FT_ULong  locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );

    static const FT_Frame_Field  table_dir_entry_fields[] =
    {
#undef  FT_STRUCTURE
#define FT_STRUCTURE  TT_TableRec

      FT_FRAME_START( 16 ),
        FT_FRAME_ULONG( Tag ),
        FT_FRAME_ULONG( CheckSum ),
        FT_FRAME_ULONG( Offset ),
        FT_FRAME_ULONG( Length ),
      FT_FRAME_END
    };


    if ( sfnt->num_tables == 0                         ||
         offset + sfnt->num_tables * 16 > stream->size )
      return SFNT_Err_Unknown_File_Format;

    if ( FT_STREAM_SEEK( offset ) )
      return error;

    for ( nn = 0; nn < sfnt->num_tables; nn++ )
    {
      TT_TableRec  table;


      if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
        return error;

      if ( table.Offset + table.Length > stream->size &&
           table.Tag != glyx_tag                      &&
           table.Tag != locx_tag                      )
        return SFNT_Err_Unknown_File_Format;

      if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
      {
        FT_UInt32  magic;


#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
        if ( table.Tag == TTAG_head )
#endif
          has_head = 1;

        /*
         * The table length should be 0x36, but certain font tools make it
         * 0x38, so we will just check that it is greater.
         *
         * Note that according to the specification, the table must be
         * padded to 32-bit lengths, but this doesn't apply to the value of
         * its `Length' field!
         *
         */
        if ( table.Length < 0x36 )
          return SFNT_Err_Unknown_File_Format;

        if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
             FT_READ_ULONG( magic )              )
          return error;

        if ( magic != 0x5F0F3CF5UL )
          return SFNT_Err_Unknown_File_Format;

        if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
          return error;
      }
      else if ( table.Tag == TTAG_SING )
        has_sing = 1;
      else if ( table.Tag == TTAG_META )
        has_meta = 1;
    }

    /* if `sing' and `meta' tables are present, there is no `head' table */
    if ( has_head || ( has_sing && has_meta ) )
      return SFNT_Err_Ok;
    else
      return SFNT_Err_Unknown_File_Format;
  }