Parsix Posted Monday at 09:49 PM Posted Monday at 09:49 PM How to Read Font Title from File Property ?
WildByDesign Posted Monday at 10:17 PM Posted Monday at 10:17 PM I only had to use this once before but you need _WinAPI_GetFontResourceInfo() to read font name directly from a font file properties. Example: #include <WinAPIGdi.au3> Example() Func Example() Local $sFile = "C:\Windows\Fonts\segoeui.ttf" ConsoleWrite(_WinAPI_GetFontResourceInfo($sFile, True) & @CRLF) ConsoleWrite(@CRLF) FontGetInfoFromFile($sFile, 0, "Copyright") FontGetInfoFromFile($sFile, 1, "Font Family name") FontGetInfoFromFile($sFile, 2, "Font SubFamily name") FontGetInfoFromFile($sFile, 3, "Unique font identifier") FontGetInfoFromFile($sFile, 4, "Font full name") FontGetInfoFromFile($sFile, 5, "Version string") FontGetInfoFromFile($sFile, 6, "Postscript name") FontGetInfoFromFile($sFile, 7, "Trademark") FontGetInfoFromFile($sFile, 8, "Manufacturer Name") FontGetInfoFromFile($sFile, 9, "Designer") FontGetInfoFromFile($sFile, 10, "Description") FontGetInfoFromFile($sFile, 11, "URL Vendor") FontGetInfoFromFile($sFile, 16, "Preferred Family (Windows only)") FontGetInfoFromFile($sFile, 17, "Preferred SubFamily (Windows only)") FontGetInfoFromFile($sFile, 18, "Compatible Full (Mac OS only)") FontGetInfoFromFile($sFile, 19, "Sample text") FontGetInfoFromFile($sFile, 20, "PostScript CID findfont name") FontGetInfoFromFile($sFile, 256, "Font-specific names") EndFunc ;==>Example Func FontGetInfoFromFile($sFile, $n, $sElement) Local $s = _WinAPI_GetFontResourceInfo($sFile, Default, $n) If Not @error And $s Then ConsoleWrite($sElement & " = " & $s & @CRLF) EndFunc ;==>FontGetInfoFromFile Parsix and ioa747 1 1
Parsix Posted Tuesday at 05:13 AM Author Posted Tuesday at 05:13 AM (edited) thanks WildByDesign Title needed Edited Tuesday at 05:19 AM by Parsix
WildByDesign Posted Tuesday at 10:59 AM Posted Tuesday at 10:59 AM The following script, shared by @BrewManNH and has a few authors listed in the script, can get the Title from a font file. But what I've noticed is that it will not get the Title when it's located in C:\Windows\Fonts directory. If you check the same font in any other directory, it shows the Title. I even tried adding #RequireAdmin hoping that it would work there but it does not. So this script will work for you as long as it's not within C:\Windows\Fonts I've adapted the script to copy the file from C:\Windows\Fonts to a Temp folder if folder (if it's located in C:\Windows\Fonts) expandcollapse popup#include <FileConstants.au3> #include <File.au3> Global $sFontLocation = "C:\Windows\Fonts\MonaspaceNeon-Italic.otf" Global $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "" Global $aPathSplit = _PathSplit($sFontLocation, $sDrive, $sDir, $sFileName, $sExtension) If StringInStr($sFontLocation, "C:\Windows\Fonts") Then FileCopy($sFontLocation, @TempDir & "\" & $aPathSplit[3] & $aPathSplit[4], $FC_OVERWRITE) $sFontLocation = @TempDir & "\" & $aPathSplit[3] & $aPathSplit[4] EndIf Global $sTitle = _FileGetProperty($sFontLocation, "Title") ConsoleWrite("Font Title: " & $sTitle & @CRLF) ;=============================================================================== ; Function Name.....: _FileGetProperty ; Description.......: Returns a property or all properties for a file. ; Version...........: 1.0.2 ; Change Date.......: 05-16-2012 ; AutoIt Version....: 3.2.12.1+ ; Parameter(s)......: $FGP_Path - String containing the file path to return the property from. ; $FGP_PROPERTY - [optional] String containing the name of the property to return. (default = "") ; $iPropertyCount - [optional] The number of properties to search through for $FGP_PROPERTY, or the number of items ; returned in the array if $FGP_PROPERTY is blank. (default = 300) ; Requirements(s)...: None ; Return Value(s)...: Success: Returns a string containing the property value. ; If $FGP_PROPERTY is blank, a two-dimensional array is returned: ; $av_array[0][0] = Number of properties. ; $av_array[1][0] = 1st property name. ; $as_array[1][1] = 1st property value. ; $av_array[n][0] = nth property name. ; $as_array[n][1] = nth property value. ; Failure: Returns an empty string and sets @error to: ; 1 = The folder $FGP_Path does not exist. ; 2 = The property $FGP_PROPERTY does not exist or the array could not be created. ; 3 = Unable to create the "Shell.Application" object $objShell. ; Author(s).........: - Simucal <Simucal@gmail.com> ; - Modified by: Sean Hart <autoit@hartmail.ca> ; - Modified by: teh_hahn <sPiTsHiT@gmx.de> ; - Modified by: BrewManNH ; URL...............: http://www.autoitscript.com/forum/topic/34732-udf-getfileproperty/page__view__findpost__p__557571 ; Note(s)...........: Modified the script that teh_hahn posted at the above link to include the properties that ; Vista and Win 7 include that Windows XP doesn't. Also removed the ReDims for the $av_ret array and ; replaced it with a single ReDim after it has found all the properties, this should speed things up. ; I further updated the code so there's a single point of return except for any errors encountered. ; $iPropertyCount is now a function parameter instead of being hardcoded in the function itself. ;=============================================================================== Func _FileGetProperty($FGP_Path, $FGP_PROPERTY = "", $iPropertyCount = 500) If $FGP_PROPERTY = Default Then $FGP_PROPERTY = "" $FGP_Path = StringRegExpReplace($FGP_Path, '["'']', "") ; strip the quotes, if any from the incoming string If Not FileExists($FGP_Path) Then Return SetError(1, 0, "") ; path not found Local Const $objShell = ObjCreate("Shell.Application") If @error Then Return SetError(3, 0, "") Local Const $FGP_File = StringTrimLeft($FGP_Path, StringInStr($FGP_Path, "\", 0, -1)) Local Const $FGP_Dir = StringTrimRight($FGP_Path, StringLen($FGP_File) + 1) Local Const $objFolder = $objShell.NameSpace($FGP_Dir) Local Const $objFolderItem = $objFolder.Parsename($FGP_File) Local $Return = "", $iError = 0 If $FGP_PROPERTY Then For $I = 0 To $iPropertyCount If $objFolder.GetDetailsOf($objFolder.Items, $I) = $FGP_PROPERTY Then $Return = $objFolder.GetDetailsOf($objFolderItem, $I) EndIf Next If $Return = "" Then $iError = 2 EndIf Else Local $av_ret[$iPropertyCount + 1][2] = [[0]] For $I = 1 To $iPropertyCount If $objFolder.GetDetailsOf($objFolder.Items, $I) Then $av_ret[$I][0] = $objFolder.GetDetailsOf($objFolder.Items, $I - 1) $av_ret[$I][1] = $objFolder.GetDetailsOf($objFolderItem, $I - 1) ;~ $av_ret[0][0] += 1 $av_ret[0][0] = $I EndIf Next ReDim $av_ret[$av_ret[0][0] + 1][2] If Not $av_ret[1][0] Then $iError = 2 $av_ret = $Return Else $Return = $av_ret EndIf EndIf Return SetError($iError, 0, $Return) EndFunc ;==>_FileGetProperty Parsix 1
Solution UEZ Posted Tuesday at 11:21 AM Solution Posted Tuesday at 11:21 AM (edited) Does this work? ;Coded by UEZ build 2025-10-07 #include <WinAPIGdi.au3> Local $sFontFile = FileOpenDialog("Select a font", "", "Fonts (*.ttf)") If $sFontFile = "" Or @error Then Exit ConsoleWrite("Title: " & _WinAPI_GetFontTitle($sFontFile) & @CRLF) Func _WinAPI_GetFontTitle($sFont) If Not _WinAPI_AddFontResourceEx($sFontFile, $FR_PRIVATE) Then Return SetError(1, 0, 0) Local $tFont = DllStructCreate("wchar title[4096]") Local $aRet = DllCall("gdi32.dll", "bool", "GetFontResourceInfoW", "wstr", $sFontFile, "dword*", DllStructGetSize($tFont), "struct*", $tFont, "dword", 1) If @error Or Not $aRet[0] Then _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return SetError(2, 0, 0) EndIf _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return $tFont.title EndFunc Edited Tuesday at 11:51 AM by UEZ WildByDesign and Parsix 2 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted Tuesday at 11:44 AM Posted Tuesday at 11:44 AM 22 minutes ago, UEZ said: Does this work? Yes this works great. Works in C:\Windows\Fonts directory as well. Parsix 1
WildByDesign Posted Tuesday at 11:46 AM Posted Tuesday at 11:46 AM (edited) Although some of them show really long Title which does not show on Properties - Details tab: Title: Monaspace Argon Var ExtraLight Wide Italic & Monaspace Argon Var Light Wide Italic & Monaspace Argon Var Wide Italic & Monaspace Argon Var Medium Wide Italic & Monaspace Argon Var SemiBold Wide Italic & Monaspace Argon Var Bold Wide Italic & Monaspace Argon Var ExtraBold Wide Italic & Monaspace Argon Var ExtraLight Italic & Monaspace Argon Var Light Italic & Monaspace Argon Var Italic & Monaspace Argon Var Medium Italic & Monaspace Argon Var SemiBold Italic & Monaspace Argon Var Bold Italic & Monaspace Argon Var ExtraBold Italic & Monaspace Argon Var ExtraLight SemiWide Wide Italic & Monaspace Argon Var Light SemiWide Wide Italic & Monaspace Argon Var SemiWide Wide Italic & Monaspace Argon Var Medium SemiWide Wide Italic & Monaspace Argon Var SemiBold SemiWide Wide Italic & Monaspace Argon Var Bold SemiWide Wide Italic & Monaspace Argon Var ExtraBold SemiWide Wide Italic & Monaspace Argon Var ExtraLight SemiWide Italic & Monaspace Argon Var Light SemiWide Italic & Monaspace Argon Var SemiWide Italic & Monaspace Argon Var Medium SemiWide Italic & Monaspace Argon Var SemiBold SemiWide Italic & Monaspace Argon Var Bold SemiWide Italic & Monaspace Argon Var ExtraBold SemiWide Italic & Monaspace Argon Var ExtraLight Wide Wide Italic & Monaspace Argon Var Light Wide Wide Italic & Monaspace Argon Var Wide Wide Italic & Monaspace Argon Var Medium Wide Wide Italic & Monaspace Argon Var SemiBold Wide Wide Italic & Monaspace Argon Var Bold Wide Wide Italic & Monaspace Argon Var ExtraBold Wide Wide Italic & Monaspace Argon Var ExtraLight Wide Italic & Monaspace Argon Var Light Wide Italic & Monaspace Argon Var Wide Italic & Monaspace Argon Var Medium Wide Italic & Monaspace Argon Var SemiBold Wide Italic & Monaspace Argon Var Bold Wide Italic & Monaspace Argon Var ExtraBold Wide Italic EDIT: Now that I think of it, though, I think that yours is probably more accurate than what MS shows in Explorer's Properties - Details tab. MS seems to just cut it off at a certain amount of characters, I can only assume. Edited Tuesday at 11:52 AM by WildByDesign Parsix 1
MattyD Posted Tuesday at 12:21 PM Posted Tuesday at 12:21 PM (edited) UEZ's solution is better - but I did the work so... Technically it'll be in the ttf/otf itself in the name table expandcollapse popup#include <AutoitConstants.au3> #include <FileConstants.au3> Local $hFontFile = FileOpen("C:\Windows\Fonts\wingding.ttf", $FO_BINARY) Local $tagTTCHeader = "align 4; uint sfntVersion; ushort numTables; ushort searchRange; ushort entrySelector; ushort rangeShift" Local $tTTCHeader = DllStructCreate($tagTTCHeader) Local $iTTCHeaderLen = DllStructGetSize($tTTCHeader) Local $tTTCHeaderBuff = DllStructCreate(StringFormat("byte data[%d]", $iTTCHeaderLen), DllStructGetPtr($tTTCHeader)) $tTTCHeaderBuff.Data = FileRead($hFontFile, $iTTCHeaderLen) Local $iNumTables = _ByteSwap($tTTCHeader.numTables, 16) Local $tagTableRecord = "align 4; char tag[4]; uint checksum; uint offset; uint length" Local $tTableRecord = DllStructCreate($tagTableRecord) Local $iTableRecordLen = DllStructGetSize($tTableRecord) Local $tTableRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iTableRecordLen), DllStructGetPtr($tTableRecord)) Local $iNameTabOffset, $iNameTabTotalLen For $i = 1 To $iNumTables $tTableRecordBuff.Data = FileRead($hFontFile, $iTableRecordLen) ConsoleWrite(StringFormat("table: %s Offset: %08x Length: %08x\r\n", _ $tTableRecord.tag, _ByteSwap($tTableRecord.Offset), _ByteSwap($tTableRecord.Length))) If $tTableRecord.tag = "name" Then $iNameTabOffset = _ByteSwap($tTableRecord.Offset) $iNameTabLen = _ByteSwap($tTableRecord.Length) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset, $FILE_BEGIN) Local $tagNameTable = "align 4; ushort version; ushort count; ushort storageOffset" Local $tNameTable = DllStructCreate($tagNameTable) Local $iNameTabLen = DllStructGetSize($tNameTable) Local $tNameTableBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameTabLen), DllStructGetPtr($tNameTable)) $tNameTableBuff.data = FileRead($hFontFile, $iNameTabLen) Local $iNameRecordCount = _ByteSwap($tNameTable.count, 16) Local $iNameStorageOffset = _ByteSwap($tNameTable.storageOffset, 16) Local $tagNameRecord = "align 4; ushort platformID; ushort encodingID; ushort languageID; ushort nameID; ushort length; ushort stringOffset;" Local $tNameRecord = DllStructCreate($tagNameRecord) Local $iNameRecordLen = DllStructGetSize($tNameRecord) Local $tNameRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameRecordLen), DllStructGetPtr($tNameRecord)) Local $iFontFamilyNameOffset, $iFontFamilyNameLen For $i = 1 To $iNameRecordCount $tNameRecordBuff.data = FileRead($hFontFile, $iNameRecordLen) ConsoleWrite(StringFormat("NameRecord: nameID: %04x length %04x offset %04x", _ _ByteSwap($tNameRecord.nameID, 16), _ByteSwap($tNameRecord.length, 16), _ByteSwap($tNameRecord.stringOffset, 16)) & @CRLF) If _ByteSwap($tNameRecord.nameID, 16) = 1 Then ; Font Family name. $iFontFamilyNameLen = _ByteSwap($tNameRecord.length, 16) $iFontFamilyNameOffset = _ByteSwap($tNameRecord.stringOffset, 16) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset + $iNameStorageOffset + $iFontFamilyNameOffset, $FILE_BEGIN) Local $tFontFamilyName = DllStructCreate(StringFormat("char Name[%d]", $iFontFamilyNameLen)) Local $tFontFamilyNameBuff = DllStructCreate(StringFormat("byte data[%d]", $iFontFamilyNameLen), DllStructGetPtr($tFontFamilyName)) $tFontFamilyNameBuff.Data = FileRead($hFontFile, $iFontFamilyNameLen) MsgBox(0, "Font Family Name", $tFontFamilyName.Name) FileClose($hFontFile) Func _ByteSwap($iInt, $iSize = 32) Switch $iSize Case 16 Return BitAND(0xFFFF, BitOR(BitAND(0xFF00, BitShift($iInt, -8)), BitShift($iInt, 8))) Case 32 Local $tBuff = DllStructCreate("byte[4]") For $i = 1 To 4 DllStructSetData($tBuff, 1, BitAND($iInt, 0xFF), 5-$i) $iInt = BitShift($iInt, 8) Next Local $tInt = DllStructCreate("int", DllStructGetPtr($tBuff)) Return DllStructGetData($tInt, 1) EndSwitch EndFunc Edited Tuesday at 12:31 PM by MattyD tidy WildByDesign, UEZ and ioa747 3
ioa747 Posted Tuesday at 12:33 PM Posted Tuesday at 12:33 PM some observations #include <WinAPIGdi.au3> ;Coded by WildByDesign 1st post Local $sFontFile = "C:\Windows\Fonts\Rubik-VariableFont_wght.ttf" ConsoleWrite("Title: " & _WinAPI_GetFontResourceInfo($sFontFile, True) & @CRLF) ConsoleWrite(@CRLF) ;Coded by UEZ build 2025-10-07 ;~ Local $sFontFile = FileOpenDialog("Select a font", "", "Fonts (*.ttf)") If $sFontFile = "" Or @error Then Exit ConsoleWrite("Title: " & _WinAPI_GetFontTitle($sFontFile) & @CRLF) Func _WinAPI_GetFontTitle($sFont) If Not _WinAPI_AddFontResourceEx($sFontFile, $FR_PRIVATE) Then Return SetError(1, 0, 0) Local $tFont = DllStructCreate("wchar title[4096]") Local $aRet = DllCall("gdi32.dll", "bool", "GetFontResourceInfoW", "wstr", $sFontFile, "dword*", DllStructGetSize($tFont), "struct*", $tFont, "dword", 1) If @error Or Not $aRet[0] Then _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return SetError(2, 0, 0) EndIf _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return $tFont.title EndFunc From what I understand, Parsix is looking for this, which WildByDesign already published in the 1st post ;Coded by WildByDesign 1st post #include <WinAPIGdi.au3> Local $sFontFile = "C:\Windows\Fonts\Rubik-VariableFont_wght.ttf" FontGetInfoFromFile($sFontFile, 1, "Font Family name") FontGetInfoFromFile($sFontFile, 4, "Font full name") Func FontGetInfoFromFile($sFile, $n, $sElement) Local $s = _WinAPI_GetFontResourceInfo($sFile, Default, $n) If Not @error And $s Then ConsoleWrite($sElement & " = " & $s & @CRLF) EndFunc ;==>FontGetInfoFromFile WildByDesign the only thing that confused me is the 256 FontGetInfoFromFile($sFile, 256, "Font-specific names") since _WinAPI_GetFontMemoryResourceInfo only shows up to 20 (maybe undocumented)? Parsix and WildByDesign 2 I know that I know nothing
WildByDesign Posted Tuesday at 12:37 PM Posted Tuesday at 12:37 PM 2 minutes ago, ioa747 said: From what I understand, Parsix is looking for this, I agree, the title generally should be equal to the information pulled from that first function. Although I have not checked too many fonts to compare. 3 minutes ago, ioa747 said: the only thing that confused me is the 256 Probably undocumented, not sure. I got that from the _WinAPI_GetFontResourceInfo docs, Example 3. Parsix and ioa747 2
Parsix Posted Wednesday at 05:54 AM Author Posted Wednesday at 05:54 AM 17 hours ago, WildByDesign said: I agree, the title generally should be equal to the information pulled from that first function. Although I have not checked too many fonts to compare. Probably undocumented, not sure. I got that from the _WinAPI_GetFontResourceInfo docs, Example 3. thanks all I was also skeptical due to the discrepancy in the features. On the other hand, the file attribute indicated something else. WildByDesign 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now