Get the font filename (like tahoma.ttf)

Hi,

Is there a method that can retrive the font filename e.g. tahoma, by passing it the font family




Answer this question

Get the font filename (like tahoma.ttf)

  • JPG

    Indeed, it is a know bug for a long time. Also [ i ] is a big problem because this is a common statement in a for-loop.


  • kaushal.b

    You can't with a existing .NET Class, but you can get it yourself. On codeproject there is a little example written in C++, but it shouldn't be hard to convert.

    You find the article, here.


  • Madhu74

    Hello,

    I am just getting started in C# and I thought this would be a good project to learn with. It's somewhat more complex than I thought it would be. Anyway, i am getting compile errors on the two lines where the little thumbs up icons appear.

    "Cannot implicitly convert type byte[] to byte" and

    "Cannot implicitly convert type byte[] to byte"

    respectively.

    Any suggestions

    Thanks


  • Santiago_

    On wish line of code Have you tried this code:


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.IO;


    #endregion

    namespace FontNameGetter
    {
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_OFFSET_TABLE
    {
    public ushort uMajorVersion;
    public ushort uMinorVersion;
    public ushort uNumOfTables;
    public ushort uSearchRange;
    public ushort uEntrySelector;
    public ushort uRangeShift;

    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_TABLE_DIRECTORY
    {
    public char szTag1;
    public char szTag2;
    public char szTag3;
    public char szTag4;
    public uint uCheckSum; //Check sum
    public uint uOffset; //Offset from beginning of file
    public uint uLength; //length of the table in bytes
    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_NAME_TABLE_HEADER
    {
    public ushort uFSelector;
    public ushort uNRCount;
    public ushort uStorageOffset;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_NAME_RECORD
    {
    public ushort uPlatformID;
    public ushort uEncodingID;
    public ushort uLanguageID;
    public ushort uNameID;
    public ushort uStringLength;
    public ushort uStringOffset;
    }

    partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private TT_OFFSET_TABLE ttOffsetTable;
    private TT_TABLE_DIRECTORY tblDir;
    private TT_NAME_TABLE_HEADER ttNTHeader;
    private TT_NAME_RECORD ttNMRecord;

    private void button1_Click(object sender, EventArgs e)
    {
    FileStream fs = new FileStream("c:\\jami.ttf", FileMode.Open, FileAccess.Read);
    BinaryReader r = new BinaryReader(fs);
    byte[] buff = r.ReadBytes(Marshal.SizeOf(ttOffsetTable));
    buff = BigEndian(buff);
    IntPtr ptr = Marshal.AllocHGlobal(buff.Length);
    Marshal.Copy(buff, 0x0, ptr, buff.Length);
    TT_OFFSET_TABLE ttResult = (TT_OFFSET_TABLE)Marshal.PtrToStructure(ptr, typeof(TT_OFFSET_TABLE));
    Marshal.FreeHGlobal(ptr);

    //Must be maj =1 minor = 0
    if (ttResult.uMajorVersion != 1 || ttResult.uMinorVersion != 0)
    return;

    bool bFound = false;
    TT_TABLE_DIRECTORY tbName = new TT_TABLE_DIRECTORY();
    for (int i = 0; i < ttResult.uNumOfTables; i++)
    {
    byte[] bNameTable = r.ReadBytes(Marshal.SizeOf(tblDir));
    IntPtr ptrName = Marshal.AllocHGlobal(bNameTable.Length);
    Marshal.Copy(bNameTable, 0x0, ptrName, bNameTable.Length);
    tbName = (TT_TABLE_DIRECTORY)Marshal.PtrToStructure(ptrName, typeof(TT_TABLE_DIRECTORY));
    Marshal.FreeHGlobal(ptrName);
    string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString();
    if (szName != null)
    {
    if (szName.ToString() == "name")
    {
    bFound = true;
    byte [] btLength = BitConverter.GetBytes(tbName.uLength);
    byte [] btOffset = BitConverter.GetBytes(tbName.uOffset);
    Array.Reverse(btLength);
    Array.Reverse(btOffset);
    tbName.uLength = BitConverter.ToUInt32(btLength, 0);
    tbName.uOffset = BitConverter.ToUInt32(btOffset, 0);
    break;
    }
    }
    }
    if (bFound)
    {
    fs.Position = tbName.uOffset;
    byte[] btNTHeader = r.ReadBytes(Marshal.SizeOf(ttNTHeader));
    btNTHeader = BigEndian(btNTHeader);
    IntPtr ptrNTHeader = Marshal.AllocHGlobal(btNTHeader.Length);
    Marshal.Copy(btNTHeader, 0x0, ptrNTHeader, btNTHeader.Length);
    TT_NAME_TABLE_HEADER ttNTResult = (TT_NAME_TABLE_HEADER)Marshal.PtrToStructure(ptrNTHeader, typeof(TT_NAME_TABLE_HEADER));
    Marshal.FreeHGlobal(ptrNTHeader);
    bFound = false;
    for (int i = 0; i < ttNTResult.uNRCount; i++)
    {
    byte[] btNMRecord = r.ReadBytes(Marshal.SizeOf(ttNMRecord));
    btNMRecord = BigEndian(btNMRecord);
    IntPtr ptrNMRecord = Marshal.AllocHGlobal(btNMRecord.Length);
    Marshal.Copy(btNMRecord, 0x0, ptrNMRecord, btNMRecord.Length);
    TT_NAME_RECORD ttNMResult = (TT_NAME_RECORD)Marshal.PtrToStructure(ptrNMRecord, typeof(TT_NAME_RECORD));
    Marshal.FreeHGlobal(ptrNMRecord);
    if (ttNMResult.uNameID == 1)
    {
    long fPos = fs.Position;
    fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset;
    char[] szResult = r.ReadChars(ttNMResult.uStringLength);
    if (szResult.Length != 0)
    {
    int y = 0;//szResult now contains the font name.

    }
    }
    }
    }
    }
    private byte[] BigEndian(byte[] bLittle)
    {
    byte[] bBig = new byte[bLittle.Length];
    for (int y = 0; y < (bLittle.Length-1); y += 2)
    {
    byte b1, b2;
    b1 = bLittle[ y ];
    b2 = bLittle[y + 1];
    bBig[ y ] = b2;
    bBig[y + 1] = b1;
    }
    return bBig;
    }
    }
    }




  • developerjj

    Here is the C# code to get the font name out of a font file, so you can iterate trought all font files in the font directory and compaire the name with the name you are searching for. When it matches, you know the filename.


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    using System.IO;


    #endregion

    namespace FontNameGetter
    {
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_OFFSET_TABLE
    {
    public ushort uMajorVersion;
    public ushort uMinorVersion;
    public ushort uNumOfTables;
    public ushort uSearchRange;
    public ushort uEntrySelector;
    public ushort uRangeShift;

    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_TABLE_DIRECTORY
    {
    public char szTag1;
    public char szTag2;
    public char szTag3;
    public char szTag4;
    public uint uCheckSum; //Check sum
    public uint uOffset; //Offset from beginning of file
    public uint uLength; //length of the table in bytes
    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_NAME_TABLE_HEADER
    {
    public ushort uFSelector;
    public ushort uNRCount;
    public ushort uStorageOffset;
    }
    [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
    struct TT_NAME_RECORD
    {
    public ushort uPlatformID;
    public ushort uEncodingID;
    public ushort uLanguageID;
    public ushort uNameID;
    public ushort uStringLength;
    public ushort uStringOffset;
    }

    partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    private TT_OFFSET_TABLE ttOffsetTable;
    private TT_TABLE_DIRECTORY tblDir;
    private TT_NAME_TABLE_HEADER ttNTHeader;
    private TT_NAME_RECORD ttNMRecord;

    private void button1_Click(object sender, EventArgs e)
    {
    FileStream fs = new FileStream("c:\\jami.ttf", FileMode.Open, FileAccess.Read);
    BinaryReader r = new BinaryReader(fs);
    byte[] buff = r.ReadBytes(Marshal.SizeOf(ttOffsetTable));
    buff = BigEndian(buff);
    IntPtr ptr = Marshal.AllocHGlobal(buff.Length);
    Marshal.Copy(buff, 0x0, ptr, buff.Length);
    TT_OFFSET_TABLE ttResult = (TT_OFFSET_TABLE)Marshal.PtrToStructure(ptr, typeof(TT_OFFSET_TABLE));
    Marshal.FreeHGlobal(ptr);

    //Must be maj =1 minor = 0
    if (ttResult.uMajorVersion != 1 || ttResult.uMinorVersion != 0)
    return;

    bool bFound = false;
    TT_TABLE_DIRECTORY tbName = new TT_TABLE_DIRECTORY();
    for (int i = 0; i < ttResult.uNumOfTables; i++)
    {
    byte[] bNameTable = r.ReadBytes(Marshal.SizeOf(tblDir));
    IntPtr ptrName = Marshal.AllocHGlobal(bNameTable.Length);
    Marshal.Copy(bNameTable, 0x0, ptrName, bNameTable.Length);
    tbName = (TT_TABLE_DIRECTORY)Marshal.PtrToStructure(ptrName, typeof(TT_TABLE_DIRECTORY));
    Marshal.FreeHGlobal(ptrName);
    string szName = tbName.szTag1.ToString() + tbName.szTag2.ToString() + tbName.szTag3.ToString() + tbName.szTag4.ToString();
    if (szName != null)
    {
    if (szName.ToString() == "name")
    {
    bFound = true;
    byte [] btLength = BitConverter.GetBytes(tbName.uLength);
    byte [] btOffset = BitConverter.GetBytes(tbName.uOffset);
    Array.Reverse(btLength);
    Array.Reverse(btOffset);
    tbName.uLength = BitConverter.ToUInt32(btLength, 0);
    tbName.uOffset = BitConverter.ToUInt32(btOffset, 0);
    break;
    }
    }
    }
    if (bFound)
    {
    fs.Position = tbName.uOffset;
    byte[] btNTHeader = r.ReadBytes(Marshal.SizeOf(ttNTHeader));
    btNTHeader = BigEndian(btNTHeader);
    IntPtr ptrNTHeader = Marshal.AllocHGlobal(btNTHeader.Length);
    Marshal.Copy(btNTHeader, 0x0, ptrNTHeader, btNTHeader.Length);
    TT_NAME_TABLE_HEADER ttNTResult = (TT_NAME_TABLE_HEADER)Marshal.PtrToStructure(ptrNTHeader, typeof(TT_NAME_TABLE_HEADER));
    Marshal.FreeHGlobal(ptrNTHeader);
    bFound = false;
    for (int i = 0; i < ttNTResult.uNRCount; i++)
    {
    byte[] btNMRecord = r.ReadBytes(Marshal.SizeOf(ttNMRecord));
    btNMRecord = BigEndian(btNMRecord);
    IntPtr ptrNMRecord = Marshal.AllocHGlobal(btNMRecord.Length);
    Marshal.Copy(btNMRecord, 0x0, ptrNMRecord, btNMRecord.Length);
    TT_NAME_RECORD ttNMResult = (TT_NAME_RECORD)Marshal.PtrToStructure(ptrNMRecord, typeof(TT_NAME_RECORD));
    Marshal.FreeHGlobal(ptrNMRecord);
    if (ttNMResult.uNameID == 1)
    {
    long fPos = fs.Position;
    fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset;
    char[] szResult = r.ReadChars(ttNMResult.uStringLength);
    if (szResult.Length != 0)
    {
    int y = 0;//szResult now contains the font name.

    }
    }
    }
    }
    }
    private byte[] BigEndian(byte[] bLittle)
    {
    byte[] bBig = new byte[bLittle.Length];
    for (int y = 0; y < (bLittle.Length-1); y += 2)
    {
    byte b1, b2;
    b1 = bLittleYes;
    b2 = bLittle[y + 1];
    bBigYes = b2;
    bBig[y + 1] = b1;
    }
    return bBig;
    }
    }
    }




  • VB Newbie

    Hi!

    I know the post is old but maybe some one can help me.

    The code is converting values from little-endian to big-endian byte order.

    But TrueType specification (from here) says:
    "All TrueType fonts use Motorola-style byte ordering (Big Endian)"

    I didn't test the code but believe it is working. So why there is such unconformity between code and specification Or am I misunderstanding something

  • Evgueni

    The stupid forum turns [ y ] into Yes if you omit the spaces, even in [code...] sections!
    I posted a bug about this in the forum suggestions topic a while ago.

  • Get the font filename (like tahoma.ttf)