KernFeature::KernFeature ( FT_Face face )
		:m_valid ( true )
{
	FontName = QString ( face->family_name ) + " " + QString ( face->style_name )   ;
// 	qDebug() <<"KF"<<FontName;
// 	QTime t;
// 	t.start();
	FT_ULong length = 0;
	if ( !FT_Load_Sfnt_Table ( face, TTAG_GPOS , 0, NULL, &length ) )
	{
// 		qDebug() <<"\t"<<"GPOS table len"<<length;
		if ( length > 32 )
		{
			GPOSTableRaw.resize ( length );
			FT_Load_Sfnt_Table ( face, TTAG_GPOS, 0, reinterpret_cast<FT_Byte*> ( GPOSTableRaw.data() ), &length );

			makeCoverage();
		}
		else
			m_valid = false;

		GPOSTableRaw.clear();
//		coverages.clear();
	}
	else
		m_valid = false;

	if ( !m_valid )
		pairs.clear();
// 	qDebug() <<"\t"<<m_valid;
// 	qDebug() <<"\t"<<t.elapsed();
}
PassRefPtr<SharedBuffer> FontPlatformData::openTypeTable(uint32_t table) const
{
    FT_Face freeTypeFace = cairo_ft_scaled_font_lock_face(m_scaledFont);
    if (!freeTypeFace)
        return 0;

    FT_ULong tableSize = 0;
    // Tag bytes need to be reversed because OT_MAKE_TAG uses big-endian order.
    uint32_t tag = FT_MAKE_TAG((table & 0xff), (table & 0xff00) >> 8, (table & 0xff0000) >> 16, table >> 24);
    if (FT_Load_Sfnt_Table(freeTypeFace, tag, 0, 0, &tableSize))
        return 0;

    RefPtr<SharedBuffer> buffer = SharedBuffer::create(tableSize);
    FT_ULong expectedTableSize = tableSize;
    if (buffer->size() != tableSize)
        return 0;

    FT_Error error = FT_Load_Sfnt_Table(freeTypeFace, tag, 0, reinterpret_cast<FT_Byte*>(const_cast<char*>(buffer->data())), &tableSize);
    if (error || tableSize != expectedTableSize)
        return 0;

    cairo_ft_scaled_font_unlock_face(m_scaledFont);

    return buffer.release();
}
Exemple #3
0
/**
 * Checks face, which must be sfnt based, for the subtype.
 * Possible values: TTF, CFF, OTF
 */
void getSFontType(FT_Face face, ScFace::FontType & type) 
{
	if (FT_IS_SFNT(face)) 
	{
		FT_ULong ret = 0;
		bool hasGlyph = ! FT_Load_Sfnt_Table(face, TTAG_glyf, 0, NULL,  &ret);
		hasGlyph &= ret > 0;
		bool hasCFF = ! FT_Load_Sfnt_Table(face, TTAG_CFF, 0, NULL,  &ret);
		hasCFF &= ret > 0;
		if (hasGlyph)
			type = ScFace::TTF;
		else if (hasCFF)
			type = ScFace::OTF;
		// TODO: CID or no
	}
} 
bool MinikinFontFreeType::GetTable(uint32_t tag, uint8_t *buf, size_t *size) {
	FT_ULong ftsize = *size;
	FT_Error error = FT_Load_Sfnt_Table(mTypeface, tag, 0, buf, &ftsize);
	if (error != 0) {
		return false;
	}
	*size = ftsize;
	return true;
}
Exemple #5
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;
      }
Exemple #6
0
void *
XeTeXFontInst::getFontTable(OTTag tag) const
{
    FT_ULong tmpLength = 0;
    FT_Error error = FT_Load_Sfnt_Table(m_ftFace, tag, 0, NULL, &tmpLength);
    if (error)
        return NULL;

    void* table = xmalloc(tmpLength * sizeof(char));
    if (table != NULL) {
        error = FT_Load_Sfnt_Table(m_ftFace, tag, 0, (FT_Byte*)table, &tmpLength);
        if (error) {
            free((void *) table);
            return NULL;
        }
    }

    return table;
}
const void *XeTeXFontInst_FT2::readTable(LETag tag, le_uint32 *length) const
{
	*length = 0;
	FT_ULong	tmpLength = 0;
	FT_Error err = FT_Load_Sfnt_Table(face, tag, 0, NULL, &tmpLength);
	if (err != 0)
		return NULL;
	
	void*	table = LE_NEW_ARRAY(char, tmpLength);
	if (table != NULL) {
		err = FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte*)table, &tmpLength);
		if (err != 0) {
			LE_DELETE_ARRAY(table);
			return NULL;
		}
		*length = tmpLength;
	}

    return table;
}
HB_Error
hb_freetype_table_sfnt_get(void *voidface, const HB_Tag tag, HB_Byte *buffer, HB_UInt *len) {
  FT_Face face = (FT_Face) voidface;
  FT_ULong ftlen = *len;

  if (!FT_IS_SFNT(face))
    return HB_Err_Invalid_Argument;

  const FT_Error error = FT_Load_Sfnt_Table(face, tag, 0, buffer, &ftlen);
  *len = ftlen;
  return (HB_Error) error;
}
Exemple #9
0
static hb_blob_t* referenceTable(hb_face_t*, hb_tag_t tag, void *userData)
{
	FT_Face ftFace = reinterpret_cast<FT_Face>(userData);
	FT_Byte *buffer;
	FT_ULong length = 0;

	if (FT_Load_Sfnt_Table(ftFace, tag, 0, NULL, &length))
		return NULL;

	buffer = reinterpret_cast<FT_Byte*>(malloc(length));
	if (buffer == NULL)
		return NULL;

	if (FT_Load_Sfnt_Table(ftFace, tag, 0, buffer, &length))
	{
		free(buffer);
		return NULL;
	}

	return hb_blob_create((const char *) buffer, length, HB_MEMORY_MODE_WRITABLE, buffer, free);
}
Exemple #10
0
static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length)
{
    FT_Face face = (FT_Face)font;
    FT_ULong ftlen = *length;
    FT_Error error = 0;

    if (!FT_IS_SFNT(face))
        return HB_Err_Invalid_Argument;

    error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen);
    *length = ftlen;
    return (HB_Error)error;
}
Exemple #11
0
const void *FreeTypeFontCache::GetFontTable(uint32 tag, size_t &length)
{
	const FontTable::iterator iter = this->font_tables.Find(tag);
	if (iter != this->font_tables.End()) {
		length = iter->second.first;
		return iter->second.second;
	}

	FT_ULong len = 0;
	FT_Byte *result = NULL;

	FT_Load_Sfnt_Table(this->face, tag, 0, NULL, &len);

	if (len > 0) {
		result = MallocT<FT_Byte>(len);
		FT_Load_Sfnt_Table(this->face, tag, 0, result, &len);
	}
	length = len;

	this->font_tables.Insert(tag, SmallPair<size_t, const void *>(length, result));
	return result;
}
Exemple #12
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);
}
Exemple #13
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);
}
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);
}
PRBool
gfxFT2LockedFace::GetFontTable(PRUint32 aTag, FallibleTArray<PRUint8>& aBuffer)
{
    if (!mFace || !FT_IS_SFNT(mFace))
        return PR_FALSE;

    FT_ULong length = 0;
    // TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
    FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
    if (error != 0)
        return PR_FALSE;

    if (NS_UNLIKELY(length > static_cast<FallibleTArray<PRUint8>::size_type>(-1))
        || NS_UNLIKELY(!aBuffer.SetLength(length)))
        return PR_FALSE;
        
    error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
    if (NS_UNLIKELY(error != 0)) {
        aBuffer.Clear();
        return PR_FALSE;
    }

    return PR_TRUE;
}
Exemple #16
0
  static FT_Error
  otv_load_table( FT_Face             face,
                  FT_Tag              tag,
                  FT_Byte* volatile*  table,
                  FT_ULong*           table_len )
  {
    FT_Error   error;
    FT_Memory  memory = FT_FACE_MEMORY( face );


    error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len );
    if ( error == OTV_Err_Table_Missing )
      return OTV_Err_Ok;
    if ( error )
      goto Exit;

    if ( FT_ALLOC( *table, *table_len ) )
      goto Exit;

    error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len );

  Exit:
    return error;
  }
bool
gfxFT2LockedFace::GetFontTable(uint32_t aTag, FallibleTArray<uint8_t>& aBuffer)
{
    if (!mFace || !FT_IS_SFNT(mFace))
        return false;

    FT_ULong length = 0;
    // TRUETYPE_TAG is defined equivalent to FT_MAKE_TAG
    FT_Error error = FT_Load_Sfnt_Table(mFace, aTag, 0, NULL, &length);
    if (error != 0)
        return false;

    if (MOZ_UNLIKELY(length > static_cast<FallibleTArray<uint8_t>::size_type>(-1))
        || MOZ_UNLIKELY(!aBuffer.SetLength(length)))
        return false;
        
    error = FT_Load_Sfnt_Table(mFace, aTag, 0, aBuffer.Elements(), &length);
    if (MOZ_UNLIKELY(error != 0)) {
        aBuffer.Clear();
        return false;
    }

    return true;
}
Exemple #18
0
static hb_blob_t *
_get_table(hb_face_t *, hb_tag_t tag, void *user_data)
{
    FT_Face face = (FT_Face) user_data;
    FT_ULong length = 0;
    FT_Byte *table;
    FT_Error error;
    hb_blob_t* blob = NULL;

    error = FT_Load_Sfnt_Table(face, tag, 0, NULL, &length);
    if (!error) {
        table = (FT_Byte *) xmalloc(length * sizeof(char));
        if (table != NULL) {
            error = FT_Load_Sfnt_Table(face, tag, 0, (FT_Byte*)table, &length);
            if (!error) {
                blob = hb_blob_create((const char*) table, length, HB_MEMORY_MODE_WRITABLE, table, free);
            } else {
                free(table);
            }
        }
    }

    return blob;
}
Exemple #19
0
static hb_blob_t *
_get_table  (hb_tag_t tag, void *user_data)
{
  PangoOTInfo *info = (PangoOTInfo *) user_data;
  FT_Byte *buffer;
  FT_ULong  length = 0;
  FT_Error error;

  error = FT_Load_Sfnt_Table (info->face, tag, 0, NULL, &length);
  if (error)
    return hb_blob_create_empty ();

  buffer = g_malloc (length);
  if (buffer == NULL)
    return hb_blob_create_empty ();

  error = FT_Load_Sfnt_Table (info->face, tag, 0, buffer, &length);
  if (error)
    return hb_blob_create_empty ();

  return hb_blob_create ((const char *) buffer, length,
			 HB_MEMORY_MODE_WRITABLE,
			 g_free, buffer);
}
Exemple #20
0
static hb_blob_t *reference_table(hb_face_t * face HB_UNUSED, hb_tag_t tag,
				  void *user_data)
{
	FT_Face ft_face;
	FT_Byte *buffer;
	FT_ULong length;
	FT_Error error;

	ft_face = (FT_Face) user_data;
	length = 0;

	/*Note: FreeType like HarfBuzz uses the NONE tag for fetching the
	  entire blob */

	error = FT_Load_Sfnt_Table(ft_face, tag, 0, NULL, &length);
	if (error)
		return NULL;

	buffer = (FT_Byte *) malloc(length);
	if (buffer == NULL)
		return NULL;

	error = FT_Load_Sfnt_Table(ft_face, tag, 0, buffer, &length);
	if (error)
		return NULL;

	return hb_blob_create((const char *)buffer, length,
			      HB_MEMORY_MODE_WRITABLE, buffer, free);
}
Exemple #21
0
bool FreeTypeSysFontData::Init(LPCTSTR name, int weight, bool italic)
{
	const CGdippSettings* pSettings = CGdippSettings::GetInstance();
	void* pNameFromGDI		= NULL; // Windows 偐傜庢摼偟偨 name 僞僌偺撪梕
	void* pNameFromFreeType	= NULL; // FreeType 偐傜庢摼偟偨 name 僞僌偺撪梕
	HFONT hf = NULL;
	DWORD cbNameTable;
	DWORD cbFontData;
	int index;
	DWORD buf;
	FT_StreamRec& fsr = m_ftStream;
	m_name.assign(name);
	m_hdc = CreateCompatibleDC(NULL);
	if(m_hdc == NULL) {
		return false;
	}
	// 柤慜埲奜揔摉
	if (pSettings->FontSubstitutes() < SETTING_FONTSUBSTITUTE_ALL)
	{
		hf = CreateFont(
					12, 0, 0, 0, weight,
					italic, FALSE, FALSE,
					DEFAULT_CHARSET,
					OUT_DEFAULT_PRECIS,
					FONT_MAGIC_NUMBER,
					DEFAULT_QUALITY,
					DEFAULT_PITCH | FF_DONTCARE,
					name);
	}
	else
		hf = CreateFont(
					12, 0, 0, 0, weight,
					italic, FALSE, FALSE,
					DEFAULT_CHARSET,
					OUT_DEFAULT_PRECIS,
					CLIP_DEFAULT_PRECIS,
					DEFAULT_QUALITY,
					DEFAULT_PITCH | FF_DONTCARE,
					name);

	if(hf == NULL){
		return false;
	}

	m_hOldFont = SelectFont(m_hdc, hf);
	// 僼僅儞僩僨乕僞偑摼傜傟偦偆偐僠僃僢僋
	cbNameTable = ::GetFontData(m_hdc, TVP_TT_TABLE_name, 0, NULL, 0);
	if(cbNameTable == GDI_ERROR){
		goto ERROR_Init;
	}

	pNameFromGDI		= malloc(cbNameTable);
	if (!pNameFromGDI) {
		goto ERROR_Init;
	}
	pNameFromFreeType	= malloc(cbNameTable);
	if (!pNameFromFreeType) {
		goto ERROR_Init;
	}

	//- name 僞僌偺撪梕傪儊儌儕偵撉傒崬傓
	if(GetFontData(m_hdc, TVP_TT_TABLE_name, 0, pNameFromGDI, cbNameTable) == GDI_ERROR){
		goto ERROR_Init;
	}

	// 僼僅儞僩僒僀僘庢摼張棟
	cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, &buf, 1);
	if(cbFontData == 1){
		// TTC 僼傽僀儖偩偲巚傢傟傞
		cbFontData = ::GetFontData(m_hdc, TVP_TT_TABLE_ttcf, 0, NULL, 0);
		m_isTTC = true;
	}
	else{
		cbFontData = ::GetFontData(m_hdc, 0, 0, NULL, 0);
	}
	if(cbFontData == GDI_ERROR){
		// 僄儔乕; GetFontData 偱偼埖偊側偐偭偨
		goto ERROR_Init;
	}

	if (pSettings->UseMapping()) {
		HANDLE hmap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_COMMIT | SEC_NOCACHE, 0, cbFontData, NULL);
		if (!hmap) {
			goto ERROR_Init;
		}
		m_pMapping = MapViewOfFile(hmap, FILE_MAP_ALL_ACCESS, 0, 0, cbFontData);
		m_dwSize = cbFontData;
		CloseHandle(hmap);

		if (m_pMapping) {
			::GetFontData(m_hdc, m_isTTC ? TVP_TT_TABLE_ttcf : 0, 0, m_pMapping, cbFontData);
		}
	}

	// FT_StreamRec 偺奺僼傿乕儖僪傪杽傔傞
	fsr.base				= 0;
	fsr.size				= cbFontData;
	fsr.pos					= 0;
	fsr.descriptor.pointer	= this;
	fsr.pathname.pointer	= NULL;
	fsr.read				= IoFunc;
	fsr.close				= CloseFunc;

	index = 0;
	m_locked = true;
	if(!OpenFaceByIndex(index)){
		goto ERROR_Init;
	}

	for(;;) {
		// FreeType 偐傜丄name 僞僌偺僒僀僘傪庢摼偡傞
		FT_ULong length = 0;
		FT_Error err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, NULL, &length);
		if(err){
			goto ERROR_Init;
		}

		// FreeType 偐傜摼偨 name 僞僌偺挿偝傪 Windows 偐傜摼偨挿偝偲斾妑
		if(length == cbNameTable){
			// FreeType 偐傜 name 僞僌傪庢摼
			err = FT_Load_Sfnt_Table(m_ftFace, TTAG_name, 0, (unsigned char*)pNameFromFreeType, &length);
			if(err){
				goto ERROR_Init;
			}
			// FreeType 偐傜撉傒崬傫偩 name 僞僌偺撪梕偲丄Windows 偐傜撉傒崬傫偩
			// name 僞僌偺撪梕傪斾妑偡傞丅
			// 堦抳偟偰偄傟偽偦偺 index 偺僼僅儞僩傪巊偆丅
			if(!memcmp(pNameFromGDI, pNameFromFreeType, cbNameTable)){
				// 堦抳偟偨
				// face 偼奐偄偨傑傑
				break; // 儖乕僾傪敳偗傞
			}
		}

		// 堦抳偟側偐偭偨
		// 僀儞僨僢僋僗傪堦偮憹傗偟丄偦偺 face 傪奐偔
		index ++;

		if(!OpenFaceByIndex(index)){
			// 堦抳偡傞 face 偑側偄傑傑 僀儞僨僢僋僗偑斖埻傪挻偊偨偲尒傜傟傞
			// index 傪 0 偵愝掕偟偰偦偺 index 傪奐偒丄儖乕僾傪敳偗傞
			index = 0;
			if(!OpenFaceByIndex(index)){
				goto ERROR_Init;
			}
			break;
		}
	}

	free(pNameFromGDI);
	free(pNameFromFreeType);
	m_locked = false;
	return true;

ERROR_Init:
	m_locked = false;
	if (hf) {
		SelectFont(m_hdc, m_hOldFont);
		DeleteFont(hf);
		m_hOldFont = NULL;
	}
	free(pNameFromGDI);
	free(pNameFromFreeType);
	return false;
}
Exemple #22
0
static inline void
fetch_GSUB (void)
{
  FT_Error error;
  int i, j;

  FT_ULong Script_List_ptr, Feature_List_ptr, Lookup_List_ptr;

  /*
   *   Fetch GSUB table
   */
  if ((error = FT_Load_Sfnt_Table(face, TTAG_GSUB, 0, NULL, &GSUB_length)))
  {
#ifdef  DEBUG
    warning("No GSUB data available for vertical glyph presentation forms.");
#endif
    return;
  }
  GSUB_table = mymalloc(GSUB_length);
  if ((error = FT_Load_Sfnt_Table(face, TTAG_GSUB, 0, GSUB_table, &GSUB_length)))
  {
    warning("Cannot load GSUB table (error code = 0x%x).", error);
    return;
  }

  /*
   *   Read GSUB header
   */
  need(10);
  if (get_ULong() != 0x00010000)
    oops("GSUB: Bad version.");
  Script_List_ptr = get_UShort();
  Feature_List_ptr = get_UShort();
  Lookup_List_ptr = get_UShort();

  /*
   *   Read Script_List
   */
  GSUB_ptr = Script_List_ptr;
  need(2);
  Script_Count = get_UShort();
#ifdef  DEBUG
  warning("GSUB: Script List with %d entries at 0x%04x.", Script_Count, Script_List_ptr);
#endif
  Script_List = mycalloc (Script_Count, sizeof(Script_Record));

  need (6 * Script_Count);
  for (i = 0; i < Script_Count; i++)
  {
    FT_Tag tag = get_ULong();
    FT_ULong ptr = Script_List_ptr + get_UShort();
    for (j = 0; j < num_Script_Lang; j++)
      if (tag == Script_Lang[j].script)
      {
        Script_List[i].tag = tag;
        Script_List[i].ltag = Script_Lang[j].language;
        Script_List[i].ptr = ptr;
      }
  }

  /*
   *   Read Feature_List
   */
  GSUB_ptr = Feature_List_ptr;
  need(2);
  Feature_Count = get_UShort();
#ifdef  DEBUG
  warning("GSUB: Feature List with %d entries at 0x%04x.", Feature_Count, Feature_List_ptr);
#endif
  Feature_List = mycalloc (Feature_Count, sizeof(Feature_Record));

  need (6 * Feature_Count);
  for (i = 0; i < Feature_Count; i++)
  {
    FT_Tag tag = get_ULong();
    FT_ULong ptr = Feature_List_ptr + get_UShort();
    if (tag == FEATURE_vert || tag == FEATURE_vrt2)
    {
      Feature_List[i].tag = tag;
      Feature_List[i].ptr = ptr;
    }
  }

  /*
   *   Read Lookup_List
   */
  GSUB_ptr = Lookup_List_ptr;
  need(2);
  Lookup_Count = get_UShort();
#ifdef  DEBUG
  warning("GSUB: Lookup List with %d entries at 0x%04x.", Lookup_Count, Lookup_List_ptr);
#endif
  Lookup_List = mycalloc (Lookup_Count, sizeof(Lookup_Record));

  need (2 * Lookup_Count);
  for (i = 0; i < Lookup_Count; i++)
    Lookup_List[i].ptr = Lookup_List_ptr + get_UShort();

  /*
   *   Read Script_List entries
   */
  for (i = 0; i < Script_Count && !has_gsub; i++)
    fetch_Script (i);
}
Exemple #23
0
/**
 * コンストラクタ
 * @param fontname	フォント名
 * @param options	オプション
 */
tNativeFreeTypeFace::tNativeFreeTypeFace(const std::wstring &fontname,
        tjs_uint32 options)
{
    // フィールドのクリア
    FaceName = fontname;
    Face = NULL;
    memset(&Stream, 0, sizeof(Stream));
    DC = NULL;
    OldFont = NULL;
    IsTTC = false;

    unsigned char *name_content    = NULL; // Windows から取得した name タグの内容
    unsigned char *name_content_ft = NULL; // FreeType から取得した name タグの内容
    tjs_int name_content_size;

    // TrueType ライブラリをフック
    try
    {
        // 指定のフォントを持ったデバイスコンテキストを作成する
        // TODO: Italic, Bold handling

        DC = GetDC(0);
        LOGFONT l;
        l.lfHeight = -12;
        l.lfWidth = 0;
        l.lfEscapement = 0;
        l.lfOrientation = 0;
        l.lfWeight = 400;
        l.lfItalic = FALSE;
        l.lfUnderline = FALSE;
        l.lfStrikeOut = FALSE;
        l.lfCharSet = DEFAULT_CHARSET;
        l.lfOutPrecision = OUT_DEFAULT_PRECIS;
        l.lfQuality = DEFAULT_QUALITY;
        l.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
        _tcscpy( l.lfFaceName, fontname.c_str() );
        l.lfFaceName[LF_FACESIZE-1] = TJS_W('\0');

        HFONT newfont = CreateFontIndirect(&l);
        OldFont = static_cast<HFONT>(SelectObject(DC, newfont));

        // このフォントが GetFontData API で扱えるかどうかを
        // 'name' タグの内容を取得しようとすることでチェックする
        // (name タグは GetFontData が扱うような TrueType/OpenType フォントには
        //  必ず入っている)
        DWORD result = GetFontData(DC, TVP_TT_TABLE_name, 0, NULL, 0);
        if(result == GDI_ERROR)
        {
            // エラー; GetFontData では扱えなかった
            TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
        }

        //- この時点で result は name タグの内容が入るのに必要なバイト数
        name_content_size = result;
        name_content = new unsigned char [name_content_size]; // メモリを確保
        name_content_ft = new unsigned char [name_content_size]; // メモリを確保

        //- name タグの内容をメモリに読み込む
        result = GetFontData(DC, TVP_TT_TABLE_name, 0, name_content, name_content_size);
        if(result == GDI_ERROR)
        {
            // エラー; メモリに読み込むことが出来なかった
            TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
        }

        // フォントファイルのサイズを取得する
        tjs_int fontsize;

        //- TTC (True Type Collection) ファイルのチェック
        //- GetFontData API の仕様では、TTC ファイルに対しては、現在選択されている
        //- フォントに対する情報しか返さない。しかし FreeType は TTC ファイル全体の
        //- 情報を必要とする。この場合、GetFontData に 'ttcf' を得るように指示すると
        //- ファイル全体の情報を得ることが出来る。
        //- 参照 : microsoft.public.win32.programmer.gdi GetFontData and TTC fonts
        unsigned char buf[4];
        result = GetFontData(DC, TVP_TT_TABLE_ttcf, 0, &buf, 1);
        if(result == 1)
        {
            // TTC ファイルだと思われる
            result = GetFontData(DC, TVP_TT_TABLE_ttcf, 0, NULL, 0);
            IsTTC = true;
        }
        else
        {
            result = GetFontData(DC, 0, 0, NULL, 0);
        }

        if(result == GDI_ERROR)
        {
            // エラー; GetFontData では扱えなかった
            TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
        }
        fontsize = result;

        // FT_StreamRec の各フィールドを埋める
        FT_StreamRec * fsr = &Stream;
        fsr->base = 0;
        fsr->size = fontsize;
        fsr->pos = 0;
        fsr->descriptor.pointer = this;
        fsr->pathname.pointer = NULL;
        fsr->read = IoFunc;
        fsr->close = CloseFunc;

        // FreeType で開く
        // 試しに 0 番の Face を開く
        // (この時点で開くことが出来なければ例外を発生させる)
        int index = 0;
        if(!OpenFaceByIndex(index))
        {
            TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
        }

        // GDIが現在選択しているファイルとFreeTypeがアクセスしているファイルが
        // 実際に合致しているかどうかを、name タグの一致で見る。
        // とくに TTC ファイルの場合は、name タグの一致を見ながら、face のインデッ
        // クスを一つずつ増やしながら、対象とするフォントを探さなければならない。
        while(true)
        {
            // FreeType から、name タグのサイズを取得する
            FT_ULong length = 0;
            FT_Error err = FT_Load_Sfnt_Table(Face, TTAG_name, 0, NULL, &length);
            if(err)
            {
                TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
            }

            // FreeType から得た name タグの長さを Windows から得た長さと比較
            if(length == name_content_size)
            {
                // FreeType から name タグを取得
                err = FT_Load_Sfnt_Table(Face, TTAG_name, 0, name_content_ft, &length);
                if(err)
                {
                    TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
                }
                // FreeType から読み込んだ name タグの内容と、Windows から読み込んだ
                // name タグの内容を比較する。
                // 一致していればその index のフォントを使う。
                if(!memcmp(name_content, name_content_ft, name_content_size))
                {
                    // 一致した
                    // face は開いたまま
                    break; // ループを抜ける
                }
            }

            // 一致しなかった
            // インデックスを一つ増やし、その face を開く
            index ++;

            if(!OpenFaceByIndex(index))
            {
                // 一致する face がないまま インデックスが範囲を超えたと見られる
                // index を 0 に設定してその index を開き、ループを抜ける
                index = 0;
                if(!OpenFaceByIndex(index))
                {
                    TVPThrowExceptionMessage( TJS_W("Font '%1$s' cannot be used"), fontname );
                }
                break;
            }
        }

    }
    catch(...)
    {
        Clear();
        if(name_content) delete [] name_content;
        if(name_content_ft) delete [] name_content_ft;
        throw;
    }
    delete [] name_content;
    delete [] name_content_ft;

}