| name | acad-linetypes-textstyles |
| description | Linetype and text style creation, loading from .lin files, TrueType/SHX fonts |
AutoCAD Linetypes and Text Styles
Use this skill when creating, loading, or modifying linetypes and text styles — accessing linetype and text style tables, loading linetypes from .lin files, configuring linetype scale variables, creating text styles with TrueType or SHX fonts, and setting up complex linetypes that embed text or shape elements.
Linetype Table Access
Database db = doc.Database;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead);
bool exists = ltt.Has("DASHED");
ObjectId ltId = ltt["DASHED"];
LinetypeTableRecord ltr = (LinetypeTableRecord)tr.GetObject(ltId, OpenMode.ForRead);
foreach (ObjectId id in ltt)
{
LinetypeTableRecord rec = (LinetypeTableRecord)tr.GetObject(id, OpenMode.ForRead);
if (rec.IsDependent) continue;
ed.WriteMessage($"\n{rec.Name}: {rec.AsciiDescription}");
}
tr.Commit();
}
System Linetypes
Three linetypes are always present and cannot be deleted:
ObjectId byLayerId = db.ByLayerLinetype;
ObjectId byBlockId = db.ByBlockLinetype;
ObjectId continuousId = db.ContinuousLinetype;
ObjectId currentId = db.Celtype;
db.Celtype = ltt["HIDDEN"];
Loading Linetypes from .lin Files
db.LoadLineTypeFile("HIDDEN", "acad.lin");
db.LoadLineTypeFile("HIDDEN2", "acadiso.lin");
db.LoadLineTypeFile("MY_LINETYPE", @"C:\Standards\custom.lin");
Safe Load with Existence Check
private static ObjectId EnsureLinetypeLoaded(
Database db, Transaction tr, string linetypeName, string linFile = "acad.lin")
{
LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead);
if (ltt.Has(linetypeName))
return ltt[linetypeName];
try
{
db.LoadLineTypeFile(linetypeName, linFile);
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
when (ex.ErrorStatus == ErrorStatus.FilerError)
{
return db.ContinuousLinetype;
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
when (ex.ErrorStatus == ErrorStatus.DuplicateKey)
{
}
ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForRead);
return ltt.Has(linetypeName) ? ltt[linetypeName] : db.ContinuousLinetype;
}
Reading Dash Pattern Elements
for (int i = 0; i < ltr.NumDashes; i++)
{
double dashLength = ltr.DashLengthAt(i);
int shapeNumber = ltr.ShapeNumberAt(i);
ObjectId shapeStyleId = ltr.ShapeStyleAt(i);
string textAt = ltr.TextAt(i);
double shapeScale = ltr.ShapeScaleAt(i);
double shapeRotation = ltr.ShapeRotationAt(i);
Vector2d shapeOffset = ltr.ShapeOffsetAt(i);
bool ucsOriented = ltr.ShapeIsUcsOrientedAt(i);
}
Simple vs Complex Linetypes
Simple Linetypes
Simple linetypes contain only dashes, gaps, and dots — defined purely by numeric values:
;; .lin file definition
*DASHED,Dashed __ __ __ __
A,.5,-.25
All dash elements have ShapeNumberAt(i) == 0 and TextAt(i) == "".
Complex Linetypes — Text Elements
Complex linetypes embed text characters within the dash-gap pattern. The text element references a text style.
*HOT_WATER_SUPPLY,Hot water supply ----HW----HW----
A,.5,-.2,["HW",STANDARD,S=.1,R=0.0,X=-0.1,Y=-.05],-.2
Text elements appear as dash entries where TextAt(i) returns a non-empty string. ShapeStyleAt(i) returns the text style ObjectId used for rendering.
Complex Linetypes — Shape Elements
Shape elements reference SHX shapes via a text style with IsShapeFile = true:
*FENCELINE1,Fenceline circle ----0-----0----0-----0----
A,.25,-.1,[CIRC1,ltypeshp.shx,x=-.1,s=.1],-.1,1
Shape elements have ShapeNumberAt(i) != 0. ShapeStyleAt(i) returns the shape-file text style ObjectId.
Creating Linetypes Programmatically
LinetypeTable ltt = (LinetypeTable)tr.GetObject(db.LinetypeTableId, OpenMode.ForWrite);
LinetypeTableRecord ltr = new LinetypeTableRecord();
ltr.Name = "MY_DASH_DOT";
ltr.AsciiDescription = "Custom dash dot __.__.__";
ltr.NumDashes = 4;
ltr.SetDashLengthAt(0, 0.5);
ltr.SetDashLengthAt(1, -0.25);
ltr.SetDashLengthAt(2, 0.0);
ltr.SetDashLengthAt(3, -0.25);
ltt.Add(ltr);
tr.AddNewlyCreatedDBObject(ltr, true);
Complex Linetype with Text
LinetypeTableRecord ltr = new LinetypeTableRecord();
ltr.Name = "GAS_LINE";
ltr.AsciiDescription = "Gas line ----GAS----GAS----";
ltr.NumDashes = 3;
ltr.SetDashLengthAt(0, 0.75);
ltr.SetDashLengthAt(1, -0.45);
ltr.SetTextAt(1, "GAS");
ltr.SetShapeStyleAt(1, tst["STANDARD"]);
ltr.SetShapeScaleAt(1, 0.1);
ltr.SetShapeRotationAt(1, 0.0);
ltr.SetShapeOffsetAt(1, new Vector2d(-0.1, -0.05));
ltr.SetShapeIsUcsOrientedAt(1, false);
ltr.SetDashLengthAt(2, -0.2);
ltt.UpgradeOpen();
ltt.Add(ltr);
tr.AddNewlyCreatedDBObject(ltr, true);
Linetype Scale System Variables
LTSCALE — Global Linetype Scale
double ltscale = db.Ltscale;
db.Ltscale = 1.0;
CELTSCALE — Current Entity Linetype Scale
double celtscale = db.Celtscale;
db.Celtscale = 0.5;
entity.LinetypeScale = 2.0;
PSLTSCALE — Paper Space Linetype Scale
Application.SetSystemVariable("PSLTSCALE", (short)1);
Effective scale for an entity = LTSCALE * Entity.LinetypeScale
(CELTSCALE is baked into Entity.LinetypeScale at creation time.)
Assigning Linetypes to Entities
Line line = new Line(pt1, pt2);
line.LinetypeId = ltt["HIDDEN"];
line.LinetypeId = db.ByLayerLinetype;
line.LinetypeId = db.ByBlockLinetype;
line.LinetypeScale = 0.5;
TextStyleTable Access
TextStyleTable tst = (TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForRead);
bool exists = tst.Has("MyStyle");
ObjectId styleId = tst["MyStyle"];
TextStyleTableRecord style = (TextStyleTableRecord)tr.GetObject(styleId, OpenMode.ForRead);
ObjectId currentStyleId = db.Textstyle;
db.Textstyle = tst["STANDARD"];
foreach (ObjectId id in tst)
{
TextStyleTableRecord rec = (TextStyleTableRecord)tr.GetObject(id, OpenMode.ForRead);
if (rec.IsDependent || rec.IsShapeFile) continue;
ed.WriteMessage($"\n{rec.Name}: {rec.FileName}");
}
Creating Text Styles
TrueType Font Style
TextStyleTable tst = (TextStyleTable)tr.GetObject(db.TextStyleTableId, OpenMode.ForWrite);
TextStyleTableRecord style = new TextStyleTableRecord();
style.Name = "ARIAL_NARROW";
style.FileName = "arialn.ttf";
style.BigFontFileName = "";
style.TextSize = 0.0;
style.XScale = 1.0;
style.ObliquingAngle = 0.0;
style.IsVertical = false;
ObjectId styleId = tst.Add(style);
tr.AddNewlyCreatedDBObject(style, true);
style.Font = new FontDescriptor("Arial Narrow", false, false, 0, 0);
SHX Font Style
TextStyleTableRecord style = new TextStyleTableRecord();
style.Name = "ROMANS_STYLE";
style.FileName = "romans.shx";
style.BigFontFileName = "";
style.TextSize = 2.5;
style.XScale = 0.8;
style.ObliquingAngle = 0.2618;
tst.UpgradeOpen();
tst.Add(style);
tr.AddNewlyCreatedDBObject(style, true);
Detecting Font Type
FontDescriptor fd = style.Font;
bool isTrueType = !string.IsNullOrEmpty(fd.TypeFace);
bool isShx = style.FileName.EndsWith(".shx", StringComparison.OrdinalIgnoreCase);
TrueType vs SHX Fonts
| Aspect | TrueType (.ttf) | SHX (.shx) |
|---|
| Rendering | Filled outlines | Stroke-based vectors |
| PDF export | Embedded as fonts | Converted to geometry |
| Big fonts | Not supported | Supported via BigFontFileName |
| Performance | Slower for many entities | Faster for many entities |
| Font property | Populated TypeFace | Empty TypeFace |
Common SHX: txt.shx, simplex.shx, romans.shx, complex.shx, monotxt.shx, isocp.shx
Loading SHX Shapes for Complex Linetypes
Complex linetypes that embed shapes need a text style with IsShapeFile = true:
private static ObjectId EnsureShapeFileStyle(
Database db, Transaction tr, string shxFileName)
{
TextStyleTable tst = (TextStyleTable)tr.GetObject(
db.TextStyleTableId, OpenMode.ForRead);
foreach (ObjectId id in tst)
{
TextStyleTableRecord existing = (TextStyleTableRecord)tr.GetObject(
id, OpenMode.ForRead);
if (existing.IsShapeFile &&
existing.FileName.Equals(shxFileName, StringComparison.OrdinalIgnoreCase))
return id;
}
tst.UpgradeOpen();
TextStyleTableRecord shapeStyle = new TextStyleTableRecord();
shapeStyle.Name = Path.GetFileNameWithoutExtension(shxFileName).ToUpperInvariant();
shapeStyle.FileName = shxFileName;
shapeStyle.IsShapeFile = true;
shapeStyle.TextSize = 0.0;
ObjectId newId = tst.Add(shapeStyle);
tr.AddNewlyCreatedDBObject(shapeStyle, true);
return newId;
}
Standard shape files: ltypeshp.shx (circles, boxes, diamonds), gdt.shx (GD&T symbols).
Gotchas
db.LoadLineTypeFile() throws if the name is not in the .lin file — always try/catch; also throws DuplicateKey if already loaded
- System linetypes (ByLayer, ByBlock, Continuous) cannot be deleted, renamed, or modified
LinetypeTable.Has() is case-insensitive
PatternLength is read-only — computed from sum of absolute dash lengths
NumDashes must be set before SetDashLengthAt() — it allocates the internal array
- Dot elements use dash length of exactly
0.0 (not a small positive number)
- Complex text elements require the referenced text style to exist — missing style = text won't render
- Complex shape elements require a text style with
IsShapeFile = true — not a regular text style
- Shape-file text styles appear in TextStyleTable but are hidden from user-facing style list
FileName accepts just the file name (arial.ttf, romans.shx) — AutoCAD resolves from its fonts/support paths
TextSize = 0.0 means variable height — non-zero forces all entities to that fixed height
ObliquingAngle is in radians, not degrees
- The STANDARD text style always exists and cannot be deleted, but can be modified
db.Textstyle (lowercase 's') is the current text style ObjectId — not TextStyleTableId
- PSLTSCALE only takes effect after
REGEN in each viewport
Entity.LinetypeScale incorporates CELTSCALE from creation — changing CELTSCALE later does not update existing entities
Related Skills
acad-layers — linetype assignment on layers via LinetypeObjectId property
acad-mtext — text style usage in MText and DBText entities
acad-dimensions — dimension styles reference text styles for dimension text formatting
acad-polylines — linetypes applied to polylines; linetype generation (PLINEGEN) across vertices