Click here to Skip to main content
Click here to Skip to main content

Retrieving font name from TTF file

By , 12 Dec 2002
 

Introduction

Everyone can get a font name of one of installed fonts. But what if the font is still not installed in the system and you want to know what is that, programmatically? Of course you can temporary add it to system fonts and get its properties then (hmm... but how you will find now what was the font installed?). Well, maybe you can think about other ways, but I decided to look for specification of the TrueType and OpenType fonts file. Fortunately, Microsoft has very good articles on these files. If you want to know more about them, look at the end of this article for links.

Writing the code

Since all that interested me (and you in most cases) is only the font name and not other properties in the TTF file, our code is gonna be simple (actually only one function). The function will retrieve font name from given file and return it to calling program.

Data types definition

Since there is no structures defined in Windows header files (or I didn't find them), we gonna make our own. We need 4 structures and 2 macros (I will explain later, about them).

A TTF file consists of several tables, each table represent some data, regarding of its type. Some tables are required, some are not. We actually need only one of them, called "name", e.g. names table. This is the place where the font information is stored, like font name, copyright, trademark and more.

//This is TTF file header
typedef struct _tagTT_OFFSET_TABLE{
    USHORT uMajorVersion;
    USHORT uMinorVersion;
    USHORT uNumOfTables;
    USHORT uSearchRange;
    USHORT uEntrySelector;
    USHORT uRangeShift;
}TT_OFFSET_TABLE;

//Tables in TTF file and there placement and name (tag)
typedef struct _tagTT_TABLE_DIRECTORY{
    char szTag[4]; //table name
    ULONG uCheckSum; //Check sum
    ULONG uOffset; //Offset from beginning of file
    ULONG uLength; //length of the table in bytes
}TT_TABLE_DIRECTORY;

//Header of names table
typedef struct _tagTT_NAME_TABLE_HEADER{
    USHORT uFSelector; //format selector. Always 0
    USHORT uNRCount; //Name Records count
    USHORT uStorageOffset; //Offset for strings storage, 
                           //from start of the table
}TT_NAME_TABLE_HEADER;

//Record in names table
typedef struct _tagTT_NAME_RECORD{
    USHORT uPlatformID;
    USHORT uEncodingID;
    USHORT uLanguageID;
    USHORT uNameID;
    USHORT uStringLength;
    USHORT uStringOffset; //from start of storage area
}TT_NAME_RECORD;
Macros

Now only thing left is macros I was talking before. The macros definition looks like:

#define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
#define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))

Now what is that? The reason we need those macros is that TTF files are stored in Big-Endian format, unlike in Windows systems, where all files are in Little Endian. Yeah I know it sounds silly with all those "endians" :). Big Endian is used by Motorolla processors for example, where the higher byte is stored first, while in Little Endian (for Intel processors) the higher byte is the last. For example you have an integer variable 1 (which is 4 bytes long). Try to save it to file and open in any hexadecimal editor, you will see:

01 00 00 00    //Little Endian - Intel

This is Little Endian system (Intel). But for Big-Endian (Motorolla), the number will be stored vise versa:

00 00 00 01    //Big Endian - Motorolla

So these formats are incompatible. And TTF file as I said, is stored in Motorolla style (Big Endian). That's why we need those 2 macros to rearrange bytes in variables retrieved from TrueType font file.

Reading the file

Now we are prepared to read the TTF file. So let's get started.

First of all we need to read the file header (TT_OFFSET_TABLE structure):

CFile f;
CString csRetVal;

//lpszFilePath is the path to our font file
if(f.Open(lpszFilePath, CFile::modeRead|CFile::shareDenyWrite)){

    //define and read file header
    TT_OFFSET_TABLE ttOffsetTable;
    f.Read(&ttOffsetTable, sizeof(TT_OFFSET_TABLE));

    //remember to rearrange bytes in the field you gonna use
    ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
    ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
    ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);

    //check is this is a true type font and the version is 1.0
    if(ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
        return csRetVal;

Right after the file header goes Offsets Table. You can find here an offset to interesting you table, "name" in our case.

    TT_TABLE_DIRECTORY tblDir;
    BOOL bFound = FALSE;
    CString csTemp;

    for(int i=0; i< ttOffsetTable.uNumOfTables; i++){
        f.Read(&tblDir, sizeof(TT_TABLE_DIRECTORY));
        csTemp.Empty();

        //table's tag cannot exceed 4 characters
        strncpy(csTemp.GetBuffer(4), tblDir.szTag, 4);
        csTemp.ReleaseBuffer();
        if(csTemp.CompareNoCase(_T("name")) == 0){
            //we found our table. Rearrange order and quit the loop
            bFound = TRUE;
            tblDir.uLength = SWAPLONG(tblDir.uLength);
            tblDir.uOffset = SWAPLONG(tblDir.uOffset);
            break;
        }
    }

We finally found the names table, so let's read its header:

    if(bFound){
        //move to offset we got from Offsets Table
        f.Seek(tblDir.uOffset, CFile::begin);
        TT_NAME_TABLE_HEADER ttNTHeader;
        f.Read(&ttNTHeader, sizeof(TT_NAME_TABLE_HEADER));

        //again, don't forget to swap bytes!
        ttNTHeader.uNRCount = SWAPWORD(ttNTHeader.uNRCount);
        ttNTHeader.uStorageOffset = SWAPWORD(ttNTHeader.uStorageOffset);
        TT_NAME_RECORD ttRecord;
        bFound = FALSE;

Right after the Names Table header, go records in it. So we need to run through all records to find information interesting to us - font name.

    for(int i=0; i<ttNTHeader.uNRCount; i++){
    f.Read(&ttRecord, sizeof(TT_NAME_RECORD));
    ttRecord.uNameID = SWAPWORD(ttRecord.uNameID);

    //1 says that this is font name. 0 for example determines copyright info
    if(ttRecord.uNameID == 1){
        ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
        ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);

        //save file position, so we can return to continue with search
        int nPos = f.GetPosition();
        f.Seek(tblDir.uOffset + ttRecord.uStringOffset + 
                 ttNTHeader.uStorageOffset, CFile::begin);

        //bug fix: see the post by SimonSays to read more about it
        TCHAR lpszNameBuf = csTemp.GetBuffer(ttRecord.uStringLength + 1);
        ZeroMemory(lpszNameBuf, ttRecord.uStringLength + 1);
        f.Read(lpszNameBuf, ttRecord.uStringLength);
        csTemp.ReleaseBuffer();

        //yes, still need to check if the font name is not empty
        //if it is, continue the search
        if(csTemp.GetLength() > 0){
            csRetVal = csTemp;
            break;
        }
        f.Seek(nPos, CFile::begin);
    }
}

That's all! Now we can return csRetVal containing our font name.

You can download the full working function and use in your code. I included also a demo project with same function, but customized a bit, so it returned also copyright and trademark information.

If you want to continue with TTF files, you can look at Microsoft's specification on them. But remember that deeper you are going to TTF, more differences between TrueType and OpenType you may find. Anyway, below are the links to articles about TTF.

References

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Philip Patrick
Team Leader Varonis
Israel Israel
Member
I was born in small town Penza, Russia, in October 13th, 1975 yr. So my mother tongue is Russian. I finished the school there and learned in University, then I came to Israel and since then, I live there (or here *s*)
My profession is a C++ programmer under MS Windows platforms, but my hobby is Web development and ASP programming.
 
I started interesting in computers and programming somewere in 1990-1991 yrs., when my father brought home our first computer - Sinclair ZX Spectrum (he made it by himself). So I learned Basic and joined the Basic programmers club at my school (me and my friend were the only 2 guys from all school there, lol). After I finished the school (1992yr) I decided to continue my study at University and got specialization Operation Systems and Software Engineer. Although I still like my profession, but I always wanted something new, thus I learned HTML, Javascript and ASP which turned to be my hobby Smile | :)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralPragmatical VB-Versionmemberchriha19 Mar '08 - 7:18 
If you are only interested in the general name of the font (typeface name, font family) like "Arial" and not "Arial Bold Italic" you can use the following code:
 

Imports System.Drawing.Text
Imports Microsoft.VisualBasic
 
Module StartUp
 
Sub Main(ByVal args As String())
MsgBox(GetFontName("C:\Temp\palabi.ttf"))
End Sub
 
Public Function GetFontName(ByVal aFileName As String) As String
Dim myFC As New PrivateFontCollection
Try
myFC.AddFontFile(aFileName)
Return myFC.Families(0).Name
Finally
myFC.Dispose()
End Try
End Function
 
End Module

 
But there still remains the question how to get the exact name, eg. "Palatino Linotype Bold Italic"...
 
Best regards
chha
QuestionSome Help ??membertp200017 Feb '08 - 20:30 
Hi Thanks a lot for this information, it works for most of the files, when i tried for FREE3OF9.TTF it gives name as "New" when i look into fontview.exe it shows "Free 3 of 9" any idea ?
 
If you can post updated c# version will be very very helpful to me.
 
Also there is API GetFontResourceInfoW in GDI32.DLL, i am not sure how to use and what are all parameters.
 
Thanks in advance.
GeneralRe: Some Help ??memberPhilip Patrick17 Feb '08 - 20:45 
Hi,
 
For C# Solution, see one of the posts below, someone has already ported this to C#.
 
Not sure what is the problem with that TTF file, as I do not have it - you will have to debug it yourself Smile | :)
 
And finally for GetFontResourceInfo function - this is undocumented method. So it really depends on where you are trying to use it, because remember, any undocumented function may change at any given time, without backward compatibility. Sure this doesn't happen a lot though Smile | :) For example, the same FontView uses this function. If you want to use it, below is its declaration. But remember, this declaration several years old - when I was interested in it. I do not know if it has been changed or not.

DWORD GetFontResourceInfoW(
LPCWCHAR wzFontName,
DWORD dwBufSize,
LPWCHAR wzBuffer,
DWORD dwInfo);

Neither I do no recall how to use it - you will have to find out this yourself, sorry Smile | :)
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer

GeneralRe: Some Help ??membertp200017 Feb '08 - 23:50 
Hi,
 
Thanks a lot for quick reply, I have tried to debug the code but couldn't find out the reason for not getting correct name Frown | :(
 
I appreciate if you can download font files from following site
http://www.barcodesinc.com/free-barcode-font
 
Some how i am getting the TT_NAME_RECORD.uStringLength as 3 only Frown | :(
 
Thanks,
AnswerRe: Some Help ??memberArun Rajan21 Sep '10 - 9:48 
You can find the csharp implementation in the below link
 
http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/d3ec5763-b7e8-4a29-9c50-1d6576ae6eae
Generalfonts related querymemberGanesh Kundapur3 Jan '08 - 0:49 
Hi,
I have some query related to fonts. It would be very helpful if you give me some pointers for
the fallowing querries.
 
1.Is there any way to check for typeface such as symbol typeface/serif/sans serif etc.
2.How to calculate baseline/baselineoffset, charwidth/MaxCharWidth?
3.How to get the font attributes such as font style, ascent, descent etc.
 
I tried by using WIN32 GDI API's, but not able to get the info.
 
--
Ganesh
QuestionWhere are the old comments gone?membersoftcode10 Dec '07 - 18:44 
I want to see the old comments!
Thanks.
QuestionHow to actually use?memberSimon Kittle22 Nov '07 - 23:31 
With the source code you provide, is this an MFC code? Or ATL code?
 
I've been trying to get it to work as a basic command line application but can't get it to compile no matter which headers I include.
 
Any tips would be great.

AnswerRe: How to actually use?memberPhilip Patrick23 Nov '07 - 0:44 
The application is MFC based. You should replace all CFile and CString, etc., with alternatives or include MFC headers and libs in your command line application
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer

GeneralGREAT!!! just a little problemmemberJihodg5 Mar '06 - 8:21 
Thank you very, very, very much!!! it's just what I needed.
 
There is just a little problem... it seems that some truetype fonts store the name in unicode or some other 2 bytes per character encoding; but I think I read somewhere in the specifications that the names should be exactly the same in unicode and ansi, so it was a matter of checking and eliminate the interleaved (zero) bytes to get an ansi compatible string. There is probably some place in the file where it states the character encoding convension, but I was to lazy to check, since this little trick worked for every font file I have.
 
Jihodg
Question00 00 00 01?membersoonhong.kwon6 Feb '06 - 20:48 
I tried to save integer 1 to the UTF16 LE file and UTF16 BE file.
UTF16 LE file shows "FF FE 00 01 00 00" as you said upper... it's okay.
But UTF16 BE file shows like below.
"FE FF 00 01 00 00"
 
What's wrong?
 


QuestionCan we use the GetFontData method toRetrieving font name from TTF filememberRangashan4 Oct '05 - 0:02 
Can we use the GetFontData for this task. If so please help me.
 
Pls check the below links
 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_mfc_cdc.3a3a.getfontdata.asp
 

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_8d7l.asp
 

 
Thanks In Advance
 
Rangashan
AnswerRe: Can we use the GetFontData method toRetrieving font name from TTF filememberPhilip Patrick4 Oct '05 - 0:25 
GetFontData works with DC, which means font has to be already installed in the system and applied to target DC, which, in turns, means you cannot use it get information about font that has not been yet installed
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
QuestionRe: Can we use the GetFontData method toRetrieving font name from TTF filememberArif Saiyed15 Mar '07 - 1:51 
Hi,
 
Where can i find the sample code for GetfontData?
 
I see the prototype in MSDN @ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/fontext_8d7l.asp
 
but I don't not know anything other then the first parameter,
How am i suppose to extract
the Font Face, Font Style, Font size, Font Color,Font Bck color from the 'lpvBuffer'
When I do not know the format/structure of 'lpvBuffer' .
 
Any help on this will be appreciated.
-Arif

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
FROM MSDN
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
GetFontData
 
The GetFontData function retrieves font metric data for a TrueType font.
 
DWORD GetFontData(
HDC hdc, // handle to DC
DWORD dwTable, // metric table name
DWORD dwOffset, // offset into table
LPVOID lpvBuffer, // buffer for returned data
DWORD cbData // length of data
);
 
Parameters
 
hdc
[in] Handle to the device context.
dwTable
[in] Specifies the name of a font metric table from which the font data is to be retrieved. This parameter can identify one of the metric tables documented in the TrueType Font Files specification published by Microsoft Corporation. If this parameter is zero, the information is retrieved starting at the beginning of the file for TrueType font files or from the beginning of the data for the currently selected font for TrueType Collection files. To retrieve the data from the beginning of the file for TrueType Collection files specify 'ttcf' (0x66637474).
dwOffset
[in] Specifies the offset from the beginning of the font metric table to the location where the function should begin retrieving information. If this parameter is zero, the information is retrieved starting at the beginning of the table specified by the dwTable parameter. If this value is greater than or equal to the size of the table, an error occurs.
lpvBuffer
[out] Pointer to a buffer that receives the font information. If this parameter is NULL, the function returns the size of the buffer required for the font data.
cbData
[in] Specifies the length, in bytes, of the information to be retrieved. If this parameter is zero, GetFontData returns the size of the data specified in the dwTable parameter.
 
Return Values
 
If the function succeeds, the return value is the number of bytes returned.
 
If the function fails, the return value is GDI_ERROR.
 

 
http://groups.yahoo.com/group/programmers-town/

AnswerRe: Can we use the GetFontData method toRetrieving font name from TTF filememberGanesh Kundapur16 Oct '07 - 19:45 
Please give me some example on using GetFontData API.
QuestionIs there any windows API to get the Font Face name from a TTF filememberRangashan3 Oct '05 - 19:43 
Sigh | :sigh: Without reading the ttf file is there any windows API to get the Font Face name from a TTF file.
 
Rangashan
AnswerRe: Is there any windows API to get the Font Face name from a TTF filememberPhilip Patrick3 Oct '05 - 19:56 
Not that I know, otherwise I wouldn't post this article Wink | ;)
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
AnswerRe: Is there any windows API to get the Font Face name from a TTF filememberJongBock, Seon8 Aug '11 - 22:42 
Use undocumented font resource api which is GetFontResourceInfoW in gdi32.dll
GeneralGetting OpenType informationmemberReunion2 Apr '05 - 18:18 
Hello!
This article is very helpful! Thank you.
I've got a problem with OpenType (*.ttf). They have information at ttRecord.uNameID > 0 and <= 20 (First 7 or 8 are similar to TrueType and they can easyly be read). But I need to read information when ttRecord.uNameID is more than 7. How can I do that.
Thank you in advance.
GeneralOpenType fontsusshadel7 Mar '05 - 9:18 
Smile | :) I really need help in that... Does anyone know how i can use a .otf file from inside c# in order to view the font inside the application. I know that GDI+ does not support otf files, but if anyone knows a method to be called or something, that would be great. Thanks alot in advance
 
H Adel
GeneralNumber of Fontssusswhils26 Jan '05 - 18:17 
Great work!!
 
I am knew of looking at the fonts but I have a project that requires me to find out how may fonts inside the TTF. The application is like characted mapping but only displaying fonts that is usable.Confused | :confused:
 
Any help would be great.
 
ThanksBig Grin | :-D
GeneralC# Versionmemberbeaverdown27 Sep '04 - 5:59 
This immensely helpful article insprired me to do the C# version. Not a 100% match (c++ to c#), but I am able to get a font name. For this code to work, you'll need to change where I have "C:\\jami.ttf" to a font file on your system.
 
Thanks again Philip.
 
#region Using directives
 
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;
            }
      }
}
GeneralRe: C# VersionmemberAsad Palekar20 Jul '10 - 19:40 
thank you for the information. i have a requirement of displaying all the glphys in a selected font file. Please suggest on how i could do that.
 
Thanks in advance
GeneralBold and italicmembertommywang10 Jul '04 - 21:45 
Thanks for the excellent work. But I have noted that it can get the font family name only. For example, it gets the same name "Arial" from arial.ttf and arialbd.ttf. How can I get the bold and italic info?
 

 
tommy
GeneralRe: Bold and italicmemberrimuk21 Jul '04 - 19:00 
You must read record with uNameID=1.
Read Microsoft documentation.
 
Rimuk
GeneralRe: Bold and italicmemberrimuk21 Jul '04 - 19:01 
Sorry,
You must read record with uNameID=2.
Read Microsoft documentation.
 
Rimuk
Generalhelpmemberyanlong wang19 Nov '03 - 21:34 
your article is very good. May I ask a question?
I want to outline text charecters after choosing a font from the fonts common dialog; that is to have a border surronding text characters in different color ? the border of each character can be changed. How can i implement this function.
Would you like helping me?Confused | :confused:
Questionhow???memberManikandan29 Aug '03 - 2:34 
how to know a particular font file is a unicode font file like japanese, chinese or korean font fileConfused | :confused:
GeneralExcellet, but small bug foundmemberSimonSays13 Dec '02 - 5:17 
You don't know how long I have needed this snipped of code. It seems like a terrible hole in the Windows API, considering they have functions to install a font based on its filename, but no way to determine the face name of the font you just installed.
 
I have hit a small snag with the code, however. Specifically, when you are reading the face name from the file, sometimes an extra character is appended to the name of the face. The problem lies with this code here:
 
f.Read(csTemp.GetBuffer(ttRecord.uStringLength + 1), ttRecord.uStringLength);
 
I was able to correct this problem as follows:
 
char *buf = csTemp.GetBuffer(ttRecord.uStringLength + 1);
ZeroMemory(buf, ttRecord.uStringLength + 1);
f.Read(buf, ttRecord.uStringLength);
 
I am sure that there is a more elegant solution, but it worked for me. Hopefully this helps you. And again, I really appreciate this code!!!!
 


GeneralRe: Excellet, but small bug foundmemberPhilip Patrick13 Dec '02 - 6:30 
Thank you Smile | :)
 

SimonSays wrote:
I have hit a small snag with the code, however
 
And thanx for founding this bug, sure I'll fix it in the article's code as well Smile | :)
 
Edited
The source code and the article have been changed
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
GeneralRe: Excellet, but small bug foundmemberSetzer-16 Oct '06 - 9:38 
The error is, in fact, very simple.
 
The string in the file isn't null-terminated. All you have to do is to insert a '\0' at the end of csTemp after reading from the file.
 
Therefore, a slightly simpler solution would be:
 
char *buf = csTemp.GetBuffer(ttRecord.uStringLength + 1);
f.Read(buf, ttRecord.uStringLength);
buf[ttRecord.uStringLength] = '\0';
 
though the actual perf gain is neglectible, but at least we now know what went wrong.
GeneralRe: Excellet, but small bug foundmemberLin Jinfa8 Oct '07 - 7:57 
I really appreciate to you and this article author. Thank you!Smile | :)
GeneralA very Cool articlememberSamy Abdyl-Rahman24 Aug '02 - 22:40 
Thanks for the good article
 
Samy Abdul-Rahman
Development Manager
Harf Informatiom Technology
GeneralRe: A very Cool articlememberPhilip Patrick24 Aug '02 - 23:00 
You are always welcome Smile | :)
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
GeneralRe: A very Cool articlememberQuantumFlux14 May '04 - 1:55 
This was very useful to me, I'd been staring at the Windows API trying to work out if it was possible and I was just about to resort to disecting the TTF header myself but you've saved me the bother. Yay! Smile | :)
GeneralNeed to read the string when the Name Id is 19.sussJiju13 Aug '02 - 15:44 
The code was very useful ....
 
I have a particular application where I have to read the sample text provided with the TTF. As per the documentation i figure that this to be the string when the Name ID is 19. But when i used the code that was provided here, I saw that the Name ID contains value only up to 12.
 
Can you please throw some light on this subject.

GeneralRe: Need to read the string when the Name Id is 19.memberPhilip Patrick14 Aug '02 - 9:09 
Jiju wrote:
Name ID contains value only up to 12
 
You mean the length of the string is only 12? Or what? Have you tried to read the text stored in offset specified? What you get in such case?
 
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
GeneralExcellent, used with FileTipmemberPhilippe Lhoste21 May '02 - 7:27 
I wanted to search this information for a long time, but didn't found the time.
You made the work for me Smile | :)
 
I immediately converted it to pure API (no MFC) and included it (the code from demo, a bit more complete) in a new FileTip module, it works perfectly!
 
FYI, FileTip is a useful shell extension: when the cursor hover on a file in Explorer, a tooltip appears giving informations on the file (image size, uncompressed Zip size, version information, etc.
An interesting feature is that this program accepts DLLs as plug-ins, ie. you can write your own file handler.
 
You can find it on the PCMag site, at http://www.pcmag.com/article/0,2997,a=12518,00.asp but you need to register ([non longer] free [alas]) to download it.
 
For this TTF module, I actually copied the FTI_ZipInfo module, renamed everywhere Zip to Ttf, changed a bit the resource and replaced the core code with my API version of Philip's code. And it works!
 
Thank you for the useful code.
 
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://Phi.Lho.free.fr

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 13 Dec 2002
Article Copyright 2002 by Philip Patrick
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid