Создание текстового стиля NET
Захотелось мне тут на C# нарисовать создание и настройку текстового стиля. Причем так, чтобы можно было вызывать из-под lisp'а.
Поскольку знаний чуть меньше чем ноль, первым делом полез в сеть. Да, много кода уже есть - но мне-то хотелось сделать немного свое. И причем так, чтобы можно было создавать любые стили - хоть с ttf, хоть с shx. И вызывать это дело лиспом
Да, можно попробовать использовать код из старой статьи, но захотелось посмотреть, что и как получится через NET.
Чутка оффтопа: попробовал самостоятельно написать, но получилось с первого раза "хереновато": то стиль не отображался, то шрифты подставлялись "не те", то еще что-то. Ну раз так, то мне прямая дорога на http://adn-cis.org: http://adn-cis.org/forum/index.php?topic=9310.0
Правда, я так и не понял, как высчитываются соответствующие параметры для стилей с ttf-шрифтами, так что тупо подставляю значения "по умолчанию". Буду надеяться, что все же прочитаю соответствующую литературу и до меня "дойдет".
Возвращаемся обратно к коду. Собственно вопрос - а каким образом вызывать-то? После недолгих размышлений пришел к выводу, что в лиспе будет использоваться 2 параметра: название стиля и перечень его параметров. Перечень - список точечных пар. То есть вызываться будет как-то так:
1 2 | (_kpblc-textstyle-create "test1" '(("width" . 1.0) ("height" . 0.0) ("obliqueangle" . 0.0) ("fontfile" . "arial") ("ttf" . t)) (_kpblc-textstyle-create "test2" '(("width" . 1.0) ("height" . 0.0) ("obliqueangle" . 0.0) ("fontfile" . "simplex")) |
Указывать, использовать ttf или нет, решил "снаружи". По крайней мере пока
Для усложнения собственной жизни (ну и немного по привычке) в коде используются псевдонимы пространств имен:
1 2 3 4 5 6 | using AcAp = Autodesk.AutoCAD.ApplicationServices; using AcDb = Autodesk.AutoCAD.DatabaseServices; using AcEd = Autodesk.AutoCAD.EditorInput; using AcGe = Autodesk.AutoCAD.Geometry; using AcGr = Autodesk.AutoCAD.GraphicsInterface; using AcRt = Autodesk.AutoCAD.Runtime; |
Для гарантии корректных данных создал класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public class StyleSettings { private string m_Name; private string m_FontFileName; private double m_Width; private double m_Height; public StyleSettings(string StyleName) { m_Name = StyleName; m_Width = 1.0; } public string Name { get { return m_Name; } } public string fontFile { get { return m_FontFileName; } set { m_FontFileName = Path.GetFileNameWithoutExtension(value); } } public bool Bold { get; set; } public bool Italic { get; set; } public double ObliqAngle { get; set; } public double Width { get { return m_Width; } set { m_Width = value <= 0.1 ? 1.0 : value; } } public bool Annotative { get; set; } public bool Vertical { get; set; } public double Height { get { return m_Height; } set { m_Height = value < 0.0 ? 0.0 : value; } } public bool UpsideDown { get; set; } public bool UseTtfFont { get; set; } public string BigFont { get; set; } } |
Теперь, используя экземпляр такого класса, собственно создание стиля выглядит достаточно просто:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | private static object GetOrCreateTextStyle(string TextStyleName, StyleSettings settings) { AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument; AcDb.Database db = doc.Database; AcDb.ObjectId styleId; using (doc.LockDocument()) { using (AcDb.Transaction tr = db.TransactionManager.StartTransaction()) { AcDb.TextStyleTable styleTable = (AcDb.TextStyleTable)tr.GetObject(db.TextStyleTableId, AcDb.OpenMode.ForRead); AcDb.TextStyleTableRecord styleRec; if (!styleTable.Has(TextStyleName)) { styleTable.UpgradeOpen(); styleRec = new AcDb.TextStyleTableRecord(); styleRec.Name = TextStyleName; styleTable.Add(styleRec); tr.AddNewlyCreatedDBObject(styleRec, true); styleTable.DowngradeOpen(); } styleRec = (AcDb.TextStyleTableRecord)tr.GetObject(styleTable[TextStyleName], AcDb.OpenMode.ForWrite, false); if (settings.UseTtfFont) { styleRec.Font = new AcGr.FontDescriptor(Path.GetFileNameWithoutExtension(settings.fontFile), settings.Bold, settings.Italic, 0, 34); // Теоретически тут надо устанавливать BigFontFileName в пустую строку: // styleRec.BigFontFileName = settings.BigFont; // но я этого делать не стал. } else { styleRec.FileName = Path.GetFileNameWithoutExtension(settings.fontFile) + ".shx"; } styleRec.ObliquingAngle = settings.ObliqAngle * Math.PI / 180.0; styleRec.TextSize = settings.Height; styleRec.XScale = settings.Width; styleRec.Annotative = (settings.Annotative ? AcDb.AnnotativeStates.True : AcDb.AnnotativeStates.False); styleId = styleRec.ObjectId; tr.Commit(); } } return styleId; } |
И, последний штрих - собственно объявление функции и ее код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | [AcRt.LispFunction("_kpblc-textstyle-create")] public static object LispCreateTextStyle(AcDb.ResultBuffer rb) { if (rb != null) { Array args = rb.AsArray(); StyleSettings settings = new StyleSettings(((AcDb.TypedValue)(args.GetValue(0))).Value.ToString()); if (((AcDb.TypedValue)(args.GetValue(1))).Value != null) { for (int pos = 1; pos < args.Length; pos++) { if ((int)((AcDb.TypedValue)(args.GetValue(pos))).TypeCode == (int)AcRt.LispDataType.DottedPair/* && pos > 2*/) { string key = ((AcDb.TypedValue)(args.GetValue(pos - 2))).Value.ToString().ToLower(); switch (key) { case "fontfile": settings.fontFile = ((AcDb.TypedValue)(args.GetValue(pos - 1))).Value.ToString(); break; case "angle": case "obliqueangle": settings.ObliqAngle = System.Convert.ToDouble(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "bold": settings.Bold = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "italic": settings.Italic = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "anno": settings.Annotative = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "height": settings.Height = System.Convert.ToDouble(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "upside": settings.UpsideDown = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "vert": settings.Vertical = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "width": settings.Width = System.Convert.ToDouble(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; case "ttf": settings.UseTtfFont = System.Convert.ToBoolean(((AcDb.TypedValue)(args.GetValue(pos - 1))).Value); break; /* case "bigfont": settings.BigFont = ((AcDb.TypedValue)(args.GetValue(pos - 1))).Value.ToString(); break; */ default: break; } } } } return GetOrCreateTextStyle(settings.Name, settings); } else { return null; } } |
За корявость кода прошу ногами в прыжках по голове не охаживать
Рядом с темой:
Пару месяцев назад хотел написать утилиту для создания текстового шрифта shx (не стиля). Т. к. все ГОСТ шрифты только похожи. А может уже есть что-то готовое?
По-моему, такого не существует. В конце концов, есть отличный шрифт mipgost : https://dwg.ru/dnl/147 - и похож, и автор при необходимости его модифицирует / дополняет.
Тема разжёвана здесь: http://bushman-andrey.blogspot.com/2014/06/autocad_8329.html
Капитан Немо, так я и не претендую на оригинальность кода