Создание текстового стиля 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; }
    }

За корявость кода прошу ногами в прыжках по голове не охаживать ;)

Размещено в .NET, Функции LISP · Метки: , , ,



Комментарии

Есть 4 коммент. к “Создание текстового стиля NET”
  1. Евгений пишет:

    Рядом с темой:
    Пару месяцев назад хотел написать утилиту для создания текстового шрифта shx (не стиля). Т. к. все ГОСТ шрифты только похожи. А может уже есть что-то готовое?

  2. Кулик Алексей aka kpblc пишет:

    По-моему, такого не существует. В конце концов, есть отличный шрифт mipgost : https://dwg.ru/dnl/147 - и похож, и автор при необходимости его модифицирует / дополняет.

  3. Капитан Немо пишет:

    Тема разжёвана здесь: http://bushman-andrey.blogspot.com/2014/06/autocad_8329.html

  4. Кулик Алексей aka kpblc пишет:

    Капитан Немо, так я и не претендую на оригинальность кода :)

Поделитесь своим мнением


Я не робот.