Achievement
Hi! In AutoCAD, there's a yellow icon displayed if the font is missing.
I'm working on AutoCAD .net api in C#. I want to check if there's any font file missing in AutoCAD.
Approaches
My idea to approach this is:
- Implement a method
checkIsFontFileMissingwith aTextStyleTableRecordinput, it returns abooleanindicates that if the font file of this text style is missing.(missing icon is shown in AutoCAD) - Iterate all text style and check them with
checkIsFontFileMissing
something like below:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
[CommandMethod("TT")]
public void TT()
{
Document doc = AcadApplication.DocumentManager.MdiActiveDocument;
Database database = doc.Database;
Editor editor = doc.Editor;
using (var tr = database.TransactionManager.StartTransaction())
{
var textStyleTbl = database.TextStyleTableId.GetObject(OpenMode.ForRead) as TextStyleTable;
foreach (ObjectId objId in textStyleTbl)
{
var textStyle = objId.GetObject(OpenMode.ForRead) as TextStyleTableRecord;
checkIsFontFileMissing(textStyle);
}
}
}
for checkIsFontFileMissing:
- if any of
FileName/BigFontFileNamenot exists, return true(some file missing) - only if both of
FileName/BigFontFileNameexist, return false(all file not missing) - if
FileName/BigFontFileNameis empty string, regard it as not missing.
My idea is to find font file from all paths in support search path in AutoCAD. it looks like:
bool checkIsFontFileMissing(TextStyleTableRecord textStyle)
{
//get all support search path in AutoCAD
object acadObject = AcadApplication.AcadApplication;
object preferences = acadObject.GetType().InvokeMember("Preferences", System.Reflection.BindingFlags.GetProperty, null, acadObject, null);
object files = preferences.GetType().InvokeMember("Files", System.Reflection.BindingFlags.GetProperty, null, preferences, null);
string supportPathStr = (string)files.GetType().InvokeMember("SupportPath", System.Reflection.BindingFlags.GetProperty, null, files, null);
string[] supportPaths = supportPathStr.Split(';');
//access file name of font
string fontFile = textStyle.FileName;
string bigFontFile = textStyle.BigFontFileName;
//try to find font file in all support search path
bool isFontFileMissing = fontFile == "" ? false : true;
bool isBigFontFileMissing = bigFontFile == "" ? false : true;
foreach (string supportPath in supportPaths)
{
string fontFilePath = System.IO.Path.Combine(supportPath, fontFile);
string bigFontFilePath = System.IO.Path.Combine(supportPath, bigFontFile);
if (System.IO.File.Exists(fontFilePath)) isFontFileMissing = false;
if (System.IO.File.Exists(bigFontFilePath)) isBigFontFileMissing = false;
}
return isFontFileMissing || isBigFontFileMissing;
}
Problems
most of
FileNameproperty contains ".shx" at the end. but some of them do not. for example we have txt.shx in some path, butFileNameproperty return txt (not txt.shx), so it's unable to find a file incheckIsFontFileMissingsome files that can't be found from all paths, but shown not missing in AutoCAD. for example I have a font stylu.ttf , this file can't be found from all paths, but shown not missing in AutoCAD. is it because there are some built-in font or something?
In summary, my approach seems not to be a good one. is there a better approach to do this? Any suggestion is really appreciated!
