[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1142
  • Last Modified:

How to get the font name of font file?

I want to fill the ListBox with font names of the fonts, which are stored as not installed font files on harddisk. Window dialog "Add Fonts" does it! When I select some directory with not installed font files in it, it shows font names. How can I do it in delphi application? Thanks
0
JackKuti
Asked:
JackKuti
  • 2
1 Solution
 
ZhaawZSoftware DeveloperCommented:
well, here's what I used to use in PHP for getting info from .ttf
hope this helps.

<?php
///////////////////////////
// Benjamin Kuz
// 09/10/2002
// http://ben.ursux.com
// ben@slax0rnet.com
///////////////////////////
//
// array ttfName(string $font)
//
// where $font is a string pointing to the font file
//
// Purpose:
//
// Reads a font and stores all information related to the font name and
// copyright in an associative array
//
// Returns:
//
// $array["copy"] = copyright information
// $array["font family"] = font family information
// $array["font subfamily"] = font subfamily name
// $array["id"] = unique font identification
// $array["name"] = full font name
// $array["version"] = font version
// $array["postscript name"] = postscript name for the font
// $array["tm"] = trademark information
// $array["manufacturer"] = font manufacturer name
// $array["designer"] = font designer name
// $array["description"] = font description
// $array["vendor url"] = vendor url
// $array["designer url"] = designer url
// $array["license"] = the terms under which the font may be used
// $array["license url"] = the url pointing to information about the font license
// $array["sample text"] = sample text included with the font for preview displays
// $array["platform"] = platform the font was designed under
//
// or
//
// returns boolean false if name tag can't be found, if the file
// doesn't exist, or if the magic number is not valid.
///////////////////////////

function ttfName($font) {
  $found=false;
  if (!$fp = @fopen ("$font","r")) {
    return false;
  }
  $magic=false;
  $pos=0;
 
  // here we check to see if a magic number is there, which
  // should be common to all truetype fonts
  // The header should appear somewhere in the first 1k,
    // if not, this is not a truetype font file.in this event,
  // return false
  while (($magic==false) && (ftell($fp)<=1024)) {
    $data=fread($fp,4);
   
    // if we find the head tag, try to get the
    // location of the head table
    if ($data=="head") {
      $data=fread($fp, 12);
      $headData=unpack("N3",$data);

      // jump to the offset of the header table
      fseek($fp,$headData[2], SEEK_SET);
      $data=fread($fp,16);
      $headTableData=unpack("N4",$data);

      // is this our magic number ?
      if ($headTableData[4]==0x5F0F3CF5) {
        $magic=true;
      } else {
        return false;
      }
    }
  }
 
  // if we never found the head to begin with,
  // no magic at all
  if ($magic==false) {
    return false;
  }
 
  // return to the start of the file to begin processing
  // the font name information
  fseek($fp,0,SEEK_SET);
  while (!feof($fp)) {
    $data=fread($fp,4);

    // continue to loop until the 'name' tag is located
    if ($data=="name") {

      // read data present after tag, 2 unsigned Long, big endian
      $tableDir=fread($fp, 8);
      $tableDirData=unpack("N2",$tableDir);
      $found=true;
      break;
    }
  }
  if ($found) {
    // jump to offset of table, from beginning of file
    fseek($fp,$tableDirData[2], SEEK_SET);
 
      // read three unsigned short, big endian.get next table offset,
    // and number of records present, as well as the platform ID
    $data=fread($fp, 8);
    $info=unpack("n4", $data);
   
    // figure out the platform ID, and add it to our final array
    switch($info[4]) {
      case 0:
        $name["platform"]="Unicode";
        break;
      case 1:
        $name["platform"]="Apple Macintosh";
        break;
      case 2:
        $name["platform"]="ISO";
        break;
      case 3:
        $name["platform"]="Microsoft Windows";
        break;
      case 4:
        $name["platform"]="Custom";
        break;
      default:
        $name["platform"]="unknown";
    }
   
    //jump back 2 bytes, so we're in the right place
    fseek($fp, ftell($fp)-2, SEEK_SET);
   
    // read six unsigned integers, big endian - loop through all records
    // the number of records is defined in the pervious table
    $i=0;
    for ($x=0; $x<=$info[2]; $x++) {
      $a=fread($fp, 12);
      $data=unpack("n6",$a);
      // in these IF statements we find the first occurances of each specific
      // piece of data, and store the appropriate information
      if (($data[4]==0) && (!isset($indexData["copy"]))) {
        $indexData["copy"]=$data;
      } else
      if (($data[4]==1) && (!isset($indexData["font family"]))) {
        $indexData["font family"]=$data;
      } else
      if (($data[4]==2) && (!isset($indexData["font subfamily"]))) {
        $indexData["font subfamily"]=$data;
      } else
      if (($data[4]==3) && (!isset($indexData["id"]))) {
        $indexData["id"]=$data;
      } else
      if (($data[4]==4) && (!isset($indexData["name"]))) {
        $indexData["name"]=$data;
      } else
      if (($data[4]==5) && (!isset($indexData["version"]))) {
        $indexData["version"]=$data;
      } else
      if (($data[4]==6) && (!isset($indexData["postscript name"]))) {
        $indexData["postscript name"]=$data;
      } else
      if (($data[4]==7) && (!isset($indexData["tm"]))) {
        $indexData["tm"]=$data;
      } else
      if (($data[4]==8) && (!isset($indexData["manufacturer"]))) {
        $indexData["manufacturer"]=$data;
      } else
      if (($data[4]==9) && (!isset($indexData["designer"]))) {
        $indexData["designer"]=$data;
      } else
      if (($data[4]==10) && (!isset($indexData["description"]))) {
        $indexData["description"]=$data;
      } else
      if (($data[4]==11) && (!isset($indexData["vendor url"]))) {
        $indexData["vendor url"]=$data;
      } else
      if (($data[4]==12) && (!isset($indexData["designer url"]))) {
        $indexData["designer url"]=$data;
      } else
      if (($data[4]==13) && (!isset($indexData["license"]))) {
        $indexData["license"]=$data;
      } else
      if (($data[4]==14) && (!isset($indexData["license url"]))) {
        $indexData["license url"]=$data;
      } else
      if (($data[4]==19) && (!isset($indexData["sample text"]))) {
        $indexData["sample text"]=$data;
      }
    }
   
    // set the beginning of the variable area
    $stringStorageStart=ftell($fp)-12;
    foreach ($indexData as $key=>$val) {
      fseek($fp, ($stringStorageStart+$indexData[$key][6]), SEEK_SET);
      $name[$key]=fread($fp, $indexData[$key][5]);
    }
   
    // remove pointless characters users put in to be l33t
    $name=str_replace("\n"," ",$name);
    $name=str_replace("\r","",$name);
    $name=str_replace("\x00","",$name);
    fclose($fp);
    return $name;
  } else {
    fclose($fp);
    return false;
  }
}
?>
0
 
Slick812Commented:
hello JackKuti, , This is a very difficult thing to do, not only do you have to know and interpret the True Type file format, it's table headers and IDs, you also need to try and get the different platform and text array (ASCII and Unicode 2 Byte) settings so you can read the FontName text array. The code below works for me for most of the fonts that I have used it for, however, the people that make a TT font file can almost put anything in them that they want, so most well made font files are OK, but there are some "Old" font files and some "Free" font files made by
ametures that this fails to correctly read. Also there were some settings for fonts that I never could never find a Font that had those, so I could not test it on that font setting. Only used for english language font, I have no idea how it does on font of other languages.

function GetFontName(const FileName: String): String; // result is a font name in file

type
  POffSets = ^TOffSets;
  TOffSets = packed record // size 12
    TTF_ID: Cardinal; // always 256
    TagCount: Word;
    SearchRange: Word;
    EntrySelector: Word;
    RangeShift: Word;
    end;

  PTags = ^TTags;
  TTags = packed record  // size 16
    Tag: array[0..3] of Char;
    CheckSum: Cardinal;
    Offset: Cardinal;
    Length: Cardinal;
    end;

  PNameHdr = ^TNameHdr;
  TNameHdr = packed record // size 6
    Format: Word;
    NameCount: Word;
    Offset: Word;
    end;

   PNameInfo = ^TNameInfo;
   TNameInfo = packed record // size 12
     PlatformID: Word;
     EncodingID: Word;
     LanguageID: Word;
     NameID: Word;
     NameSize: Word;
     NameOffset: Word;
     end;


   function Re2Byte(aWord: Word): Word;
   begin
   Result := (aWord shr 8) or (aWord shl 8);
   end;

   function Re4Byte(aDWord: Cardinal): Cardinal;
   begin
   Result := ((aDWord and $FF000000) shr 24) or ((aDWord and $FF0000) shr 8) or
             ((aDWord and $FF) shl 24) or ((aDWord and $FF00) shl 8);
   end;


var
fileStm: TFileStream;
pFile: Pointer;
Count, offName, strPos, WstrPos: Cardinal;
readSize, i, strLen, WstrLen: Integer;
pTag: PTags;
pHdrName: PNameHdr;
pInfoName: PNameInfo;
pRe: PChar;

begin
Result := '';
fileStm := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
  fileStm.ReadBuffer(Count, SizeOf(Count));
  if (fileStm.Size < 50) or (Count <> 256) then
    begin
    ShowMessage('ERROR GetFontName - the file is NOT a True Type Font');
    Exit;
    end;
  fileStm.Position := 0;
  readSize := MaxWord * 3;
  if fileStm.Size < readSize then
    readSize := fileStm.Size;
  GetMem(pFile, readSize);
  if fileStm.Read(pFile^, readSize) <> readSize then
    begin
    FreeMem(pFile);
    ShowMessage('ERROR GetFontName - System Can Not Read Font File');
    Exit;
    end;
  finally
  FreeAndNil(fileStm);
  end;

try
  Count := Re2Byte(POffSets(pFile).TagCount)-1;
  pTag := PTags(Cardinal(pFile) + SizeOf(TOffSets));

  offName := 0;
  for i := 0 to Count do
    begin
    if pTag.Tag = 'name' then
      begin
      offName := Re4Byte(pTag.Offset);
      Break;
      end;
    Inc(pTag);
    end;

  if (offName < 11) or (Integer(offName) > readSize) then
    begin
    ShowMessage('ERROR GetFontName - Font File does not have a Name Tag');
    Exit;
    end;

  pHdrName := PNameHdr(Cardinal(pFile) + offName);

  Count := Re2Byte(pHdrName.NameCount)-1;

  pInfoName := PNameInfo(Cardinal(pFile) + offName + SizeOf(TNameHdr));
  Inc(offName, Re2Byte(pHdrName.Offset));
  strLen := -1;
  WstrLen := -1;
  strPos := 0;
  WstrPos := 0;
  for i := 0 to Count do
    begin
    with pInfoName^ do
    if NameID = $0400 then
      if (PlatformID = $0100) then
        begin
        strPos := Re2Byte(NameOffset);
        strLen := Re2Byte(NameSize);
        Break;
        end else
        if (PlatformID = $0300) then
        begin
        WstrPos := Re2Byte(NameOffset);
        WstrLen := Re2Byte(NameSize) div 2;
        end;
    Inc(pInfoName);
    end;

  if (strLen < 1) or (strLen > LF_FACESIZE) then
    if (WstrLen > 1) then
    begin
    Inc(offName, WstrPos+1);
    if offName > Cardinal(readSize) then Exit;
    pRe := PChar(Cardinal(pFile) + offName);
    for i := 1 to WstrLen do
      begin
      Result := Result + pRe^;
      Inc(pRe, 2);
      end;
    Exit;
    end else
    begin
    ShowMessage('ERROR GetFontName - NameInfo does not have a Name Position');
    Exit;
    end;

  Inc(offName, strPos);
  if offName > Cardinal(readSize) then Exit;
  SetLength(Result, strLen);
  CopyMemory(PChar(Result),Pointer(Cardinal(pFile)+ offName), strLen);
  finally
  FreeMem(pFile);
  end;
end;

 = = = = = = = = = = = = = = = = = = = = = = = =
ask questions if you need more info
0
 
JackKutiAuthor Commented:
Thank you Slick812
0
 
Slick812Commented:
I am glad I could help, , good luck with your project
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now