Archive: font name from its file name


font name from its file name
is there a possibility to query a font file for the fonts name?

example: comic.ttf is called 'comic sans ms' and registered as such.

i know one can specify that when one uses font installation functions for nsis, but it would be useful (for my script) to get around that.


Try opening a font into Notepad and see the layout of the file.
You can then probably read from this file and get hold of the chunk you need.

-Stu


Do you want to get the name of a registered or unregistered font?

Do you want to get the file from a name or the name from a file?


i want to read the font name (to register it under that name) from the ttf file. so, unregistered font and name from file.


You can write a plug-in using this code:

http://www.codeproject.com/gdi/fontnamefromfile.asp


So has anyone writen a plug-in fot this?

Vytautas


There is no such plug-in available in the archive, but you can easily write one using the code above.


Only problem is that my C/C++ skills are almost non existent and I do not have access to MS VC copmiler. I think that it would be quite difficult to convert that code into delphi.

Vytautas


I tried to create this plugin with C++ Builder 6 but I get "Undefined Symbol: 'CFile'" and "Undefined Symbol: 'CString'" errors did I miss a really obvious include or do I need VC for this to work?

Vytautas


CFile and CString are MFC classes. Are you building the project with MFC included? I think visual c++ includes this automatically when you use any MFC data type. Sounds like you need to do something different for C++ builder.


OK, in that case are there any equivalents that dont use MFC or is there a way do accomplish this task with just the ANSI C/C++. Cos after a quick look on the net I discovered that getting MFC to work with Borlan C++ Builder is next to impossible, good old Microsoft.

Vytautas


http://www.codeproject.com/gdi/xfont.asp#xx651625xx

GetFontProperties is what you're looking for.


Thanks kichik I will try to make the plugin tomorrow.

I just noticed one thing. The name of the font from the file is used for the display name in the registry, thats the reason I need this plugin, however the name in the registry has (TrueType) appended to the end of the name if its a TTF file however if tis a FON file it has either (All res) or (VGA res).

Is this always the case with TTF files and is there a way to find out which type is the FON font?

Vytautas


Well, TTF stands for TrueType Font, so unless the file name is wrong, it should be TrueType. There is another page in CodeProject, in the same category that shows how to get the font type from the file. Maybe that would help.


That application above gets the name from both registry and file.


Yes joost but I need to get the name of the font so that I can add it to the registry when installing the font. Kichik I will check out that page.

Vytautas


Attached is a plugin to get the name of a TTF Font from the file. Considering that this plugin only works with TTF files the previous post about registry name change can be disregarded.

Vytautas

PS. Attached file contains the source code with the project files for DEV-C++

PPS. I will create an archive page about this plugin later tonight including usage examples.

PPPS. You should call this plugin using this command:

FontName::Name 'Location of TTF font file'

kickik, or someone else, could you please upload this plugin to the archive. For a more detailed example of the plugins usage check out my font registration page in the archive as it utilizes this plugin.

Vytautas


Uploaded.


thats a very nice plugin, but i want suggest adding the fontstyle to the output.

try the plugin on all ttf files of the arial family. the plugin will always display

Arial (TrueType)

not

Arial Bold (TrueType)
Arial Italics (TrueType)
etc.

without fontstyle, fonts of the same family aren't distinguishable.


Thanks, I will try to find out how to add that support.

Vytautas


OK found where the problem was, the original code replaces the name with the family name of the font if the font name was '' and for some reason the code is not reading the name. Will post when a fix is found.

Vytautas


Fixed, also removed unused info from the plugin, made it slightly smaller. :) Could someone please update the archive file with this.

Vytautas


Optimized the plugin size a little more.

Vytautas :D


Updated.


I have struck a problem with my plugin. It seems to generate a BSOD in Win98SE. Could anyone help me test this, e.g. try with different versions of windows to see which platforms have this problem.

Also what is the best way to debug a NSIS Plugin. I used Dev-C++ to create it, source code is included in the plugin.

Any help is greatly appreaciated.

Vytautas :cry:


According to Dev-C++'s changelog, they have added an option to debug DLLs in version 4.9.8.2 so it should be there somewhere if you're using this version. I suggest you first get more information about the crash, the exact text to start with.


The error I get is this:

A fatal exception OE has occured at 0028:C02A3531 in VXD VWIN32(05) + 00002059. The current application will be terminated.
This error only seems to occur in Win9x.

kickik when I asked how to debug a plugin I meant how do I tell NSIS to run the debug dll instead of the normal.

Vytautas

You simply put it in the Plugins directory and use it like every other plug-in. For NSIS it's just another DLL.

.


I'm not so good with C++ so I don't know if I'm on the right path here or not, but I thought that if you wanted to let's say step through the execution of a dll you had to link it the the application that used that dll.

Vytautas


That's true, you need to tell your debugger to run an installer that will use the debug version of the DLL. Once you do that you can set breakpoints and whatnot wherever you want in the DLL.


So I do not need to modify the script in any way for it to work, e.g. I do net have to tell it to use the debug plugin dll instead of the one it got built with.

Vytautas


If they are the same name, you don't have to change a thing. If you have named the debug build MyPluginDebug, then you'll have to change every MyPlugin::func to MyPluginDebug::func. NSIS only cares about the name of the DLL and its exports. If both are the same, you don't have to change anything in the script.


kickik that didn't quite work as expected but I found and fixed the problem with 'creative' debugging. I used lots of message boxes in the plugin to see where it died and then played around with the code.

Here is the fixed plugin. Could someone upload it to the archive.

Vytautas


kickik as an afterthought the bug involved me using a 'char *sFileName' which caused an error in Win9x when I changed it to 'char sFileName[4096]' it worked ok. Is 4096 going to be large enough to hold any path?

Vytautas


The maximum length is MAX_PATH (260).


And you can always add a check just to make sure.

Do you want to upload a new version or is the one you just uploaded good to go?


I'll upload a new version a little later. Just about to finish an implementation of error checking/reporting.

Vytautas


You should use this to get the fonts folder:

System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_...}|${CSIDL_FLAG_CREATE}, *i .r0)"
System::Call "Shell32::SHGetPathFromIDList(i r0, t .r0)"

The code you currently have on the Archive corrupts the stack because of wrong quotes ('System... b 'false' ...) and doesn't work without Internet Explorer 3 or 4 (I don't remember the exact version).

This code is missing the free line for the PIDL though. I can't figure out how to do that in the moment but it is possible thanks to COM support in the latest System.dll. Maybe it'll just be easier to add that to your plug-in, since you already have one...


System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_...}|${CSIDL_FLAG_CREATE}, *i .r0)"
System::Call "Shell32::SHGetPathFromIDList(i r0, t .r1)"

System::Call 'shell32::SHGetMalloc(*i . r2)' ; IMalloc
System::Call '$2->5(i r0)' ; ->Free
System::Call '$2->2()' ; ->Release

Ugly, i know. :)
don't forget to change shgetpathfromidlist output from t.r0 to t.rANOTHER.


Archive: font name from its file name


brainsucker to the rescue! :)

Thanks.


Firstly when I enabled error checking I found that when the plugin failed, sometimes on win9x PC's, it was because it could not open the font file. The GetLastError function returns code 87 - ERROR_INVALID_PARAMETER, yet this function works fine on WinNT family and seams to work on win9x sometimes. I had the installer working on one 98 machine and a few minutes later the same installer failed on the same machine :confused: .

Secondly I will update the archive page with brainsucker's code. BTW what is the define value of CSIDL_FLAG_CREATE.

Vytautas


This is getting weirder by the minute now its comming up with error 32 - ERROR_SHARING_VIOLATION. Which would make more sense but I still can quite figgure this out.

Vytautas :igor:


oops, forgot to attach file just in casesomeone want to play-around with it and maybe help me figgure this problem out. If there is an error in the plugin it will push an error string to the stack instead of the font name. So just check for 'error:' at the start of the poped string and handle as you wish.

Vytautas


According to kichik earlier today, !define CSIDL_FLAG_CREATE 0x8000


OK this appears to have fixed the plugin. I will Update all of the related Archive pages later tonight. This version of the plugin includes error reporting functionality.

brainsucker :up: thank you for your help as the problem does not seem to be with the plugin but with the function I used to get the font folder, certainly very weird.

Vytautas :D


I guess I'll head into the office tomorrow after my holiday dinner (or maybe Friday ;)) and test it out... If there are still issues, I'm bound to run into them... :igor:

Again, thanks for all your hard work on this!

--Matt


Just a little addition so the font directory detection will work on Windows 9x too:

System::Call 'shell32::SHGetMalloc(*i . r2)' ; IMalloc
System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_FONTS}, *i .r0)"
System::Call "Shell32::SHGetPathFromIDList(i r0, t .r1)"
System::Call '$2->5(i r0)' ; ->Free
System::Call '$2->2()' ; ->Release
StrCmp $1 "" 0 done
System::Call "Shell32::SHGetSpecialFolderLocation(i $HWNDPARENT, i ${CSIDL_FONTS}|${CSIDL_FLAG_CREATE}, *i .r0)"
System::Call "Shell32::SHGetPathFromIDList(i r0, t .r1)"
System::Call '$2->5(i r0)' ; ->Free
System::Call '$2->2()' ; ->Release
done:

It seems Windows 9x doesn't like CSIDL_FLAG_FLAG... :(

BTW, soon enough you'll have a NSIS variable named $FONTS which will do this for you.


kichik, didn't the older function work well in Win9x. I did several tests and after I included the 'create' flag as in the old function all the errors seemed to disappear.

Looking forward to the $FONTS variable :D

Vytautas


Well, on all of my tests and according to MSDN CSIDL_FLAG_CREATE doesn't work on Windows 9x. At first I thought Windows 9x would just ignore it, assuming it's an unknown flag, but instead it just failed.