• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 16439156407

22 Jul 2025 08:37AM UTC coverage: 75.146% (+0.09%) from 75.057%
16439156407

Pull #718

github

web-flow
Merge b2d0f7e5b into 4b0db03db
Pull Request #718: SVG tests

6000 of 8787 branches covered (68.28%)

Branch coverage included in aggregate %.

78 of 93 new or added lines in 6 files covered. (83.87%)

108 existing lines in 4 files now uncovered.

23923 of 31033 relevant lines covered (77.09%)

78933.13 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.1
/src/ACadSharp/Entities/TextEntity.cs
1
using ACadSharp.Attributes;
2
using ACadSharp.Tables;
3
using CSMath;
4
using CSUtilities.Extensions;
5
using System;
6
using System.Collections.Generic;
7

8
namespace ACadSharp.Entities
9
{
10
        /// <summary>
11
        /// Represents a <see cref="TextEntity"/>
12
        /// </summary>
13
        /// <remarks>
14
        /// Object name <see cref="DxfFileToken.EntityText"/> <br/>
15
        /// Dxf class name <see cref="DxfSubclassMarker.Text"/>
16
        /// </remarks>
17
        [DxfName(DxfFileToken.EntityText)]
18
        [DxfSubClass(DxfSubclassMarker.Text)]
19
        public class TextEntity : Entity, IText
20
        {
21
                /// <summary>
22
                /// Second alignment point (in OCS)
23
                /// </summary>
24
                /// <remarks>
25
                /// This value is meaningful only if the value of a 72 or 73 group is nonzero (if the justification is anything other than baseline/left)
26
                /// </remarks>
27
                [DxfCodeValue(DxfReferenceType.Optional, 11, 21, 31)]
28
                public XYZ AlignmentPoint { get; set; }
7,360✔
29

30
                /// <inheritdoc/>
31
                [DxfCodeValue(40)]
32
                public double Height
33
                {
34
                        get => _height;
990✔
35
                        set
36
                        {
22,381✔
37
                                if (value < 0)
22,381!
38
                                        throw new ArgumentOutOfRangeException("Height value cannot be negative.");
×
39
                                else
40
                                        this._height = value;
22,381✔
41
                        }
22,381✔
42
                }
43

44
                /// <summary>
45
                /// Horizontal text justification type.
46
                /// </summary>
47
                [DxfCodeValue(72)]
48
                public TextHorizontalAlignment HorizontalAlignment { get; set; } = TextHorizontalAlignment.Left;
24,261✔
49

50
                /// <summary>
51
                /// First alignment point(in OCS)
52
                /// </summary>
53
                [DxfCodeValue(10, 20, 30)]
54
                public XYZ InsertPoint { get; set; } = XYZ.Zero;
134,236✔
55

56
                /// <summary>
57
                /// Mirror flags.
58
                /// </summary>
59
                [DxfCodeValue(71)]
60
                public TextMirrorFlag Mirror { get; set; } = TextMirrorFlag.None;
24,156✔
61

62
                /// <summary>
63
                /// Specifies the three-dimensional normal unit vector for the object.
64
                /// </summary>
65
                [DxfCodeValue(210, 220, 230)]
66
                public XYZ Normal { get; set; } = XYZ.AxisZ;
28,223✔
67

68
                /// <inheritdoc/>
69
                public override string ObjectName => DxfFileToken.EntityText;
24,896✔
70

71
                /// <inheritdoc/>
72
                public override ObjectType ObjectType => ObjectType.TEXT;
18✔
73

74
                /// <summary>
75
                /// Specifies the oblique angle of the object.
76
                /// </summary>
77
                /// <value>
78
                /// The angle in radians within the range of -85 to +85 degrees. A positive angle denotes a lean to the right; a negative value will have 2*PI added to it to convert it to its positive equivalent.
79
                /// </value>
80
                [DxfCodeValue(DxfReferenceType.IsAngle, 51)]
81
                public double ObliqueAngle { get; set; } = 0.0;
24,087✔
82

83
                /// <summary>
84
                /// Specifies the rotation angle for the object.
85
                /// </summary>
86
                /// <value>
87
                /// The rotation angle in radians.
88
                /// </value>
89
                [DxfCodeValue(DxfReferenceType.IsAngle, 50)]
90
                public double Rotation { get; set; }
2,236✔
91

92
                /// <inheritdoc/>
93
                [DxfCodeValue(DxfReferenceType.Name | DxfReferenceType.Optional, 7)]
94
                public TextStyle Style
95
                {
96
                        get { return this._style; }
77,481✔
97
                        set
98
                        {
8,863✔
99
                                if (value == null)
8,863!
UNCOV
100
                                {
×
UNCOV
101
                                        throw new ArgumentNullException(nameof(value));
×
102
                                }
103

104
                                if (this.Document != null)
8,863✔
105
                                {
7,329✔
106
                                        this._style = updateTable(value, this.Document.TextStyles);
7,329✔
107
                                }
7,329✔
108
                                else
109
                                {
1,534✔
110
                                        this._style = value;
1,534✔
111
                                }
1,534✔
112
                        }
8,863✔
113
                }
114

115
                /// <inheritdoc/>
116
                public override string SubclassMarker => DxfSubclassMarker.Text;
141,315✔
117

118
                /// <summary>
119
                /// Specifies the distance a 2D object is extruded above or below its elevation.
120
                /// </summary>
121
                [DxfCodeValue(39)]
122
                public double Thickness { get; set; } = 0.0;
27,267✔
123

124
                /// <inheritdoc/>
125
                /// <value>
126
                /// The maximum length is 256 characters.
127
                /// </value>
128
                [DxfCodeValue(1)]
129
                public string Value
130
                {
131
                        get
132
                        {
987✔
133
                                return _value;
987✔
134
                        }
987✔
135
                        set
136
                        {
22,355✔
137
                                if (value.Length > 256)
22,355!
UNCOV
138
                                        throw new ArgumentException($"Text length cannot be supiror than 256, current: {value.Length}");
×
139
                                else
140
                                        this._value = value;
22,355✔
141
                        }
22,355✔
142
                }
143

144
                /// <summary>
145
                /// Vertical text justification type.
146
                /// </summary>
147
                [DxfCodeValue(DxfReferenceType.Optional, 73)]
148
                public virtual TextVerticalAlignmentType VerticalAlignment { get; set; } = TextVerticalAlignmentType.Baseline;
23,641✔
149

150
                /// <summary>
151
                /// Relative X scale factor—widt
152
                /// </summary>
153
                /// <remarks>
154
                /// This value is also adjusted when fit-type text is used
155
                /// </remarks>
156
                [DxfCodeValue(DxfReferenceType.Optional, 41)]
157
                public double WidthFactor { get; set; } = 1.0;
24,088✔
158

159
                private double _height = 0.0;
22,391✔
160
                private TextStyle _style = TextStyle.Default;
22,391✔
161
                private string _value = string.Empty;
22,391✔
162

163
                public TextEntity() : base()
22,391✔
164
                {
22,391✔
165
                }
22,391✔
166

167
                /// <inheritdoc/>
168
                public override void ApplyTransform(Transform transform)
169
                {
1✔
170
                        bool mirrText = this.Mirror.HasFlag(TextMirrorFlag.Backward);
1✔
171

172
                        XYZ newInsert = transform.ApplyTransform(this.InsertPoint);
1✔
173
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
1✔
174

175
                        var transformation = this.getWorldMatrix(transform, Normal, newNormal, out Matrix3 transOW, out Matrix3 transWO);
1✔
176

177
                        List<XY> uv = applyRotation(
1✔
178
                                new[]
1✔
179
                                {
1✔
180
                                        this.WidthFactor * this.Height * XY.AxisX,
1✔
181
                                        new XY(this.Height * Math.Tan(this.ObliqueAngle), this.Height)
1✔
182
                                },
1✔
183
                                this.Rotation);
1✔
184

185
                        XYZ v;
186
                        v = transOW * new XYZ(uv[0].X, uv[0].Y, 0.0);
1✔
187
                        v = transformation * v;
1✔
188
                        v = transWO * v;
1✔
189
                        XY newUvector = new XY(v.X, v.Y);
1✔
190

191
                        v = transOW * new XYZ(uv[1].X, uv[1].Y, 0.0);
1✔
192
                        v = transformation * v;
1✔
193
                        v = transWO * v;
1✔
194
                        XY newVvector = new XY(v.X, v.Y);
1✔
195

196
                        double newRotation = newUvector.GetAngle();
1✔
197
                        double newObliqueAngle = newVvector.GetAngle();
1✔
198

199
                        if (mirrText)
1!
200
                        {
×
201
                                if (XY.Cross(newUvector, newVvector) < 0)
×
202
                                {
×
203
                                        newObliqueAngle = MathHelper.HalfPI - (newRotation - newObliqueAngle);
×
UNCOV
204
                                        if (!(this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Fit)
×
205
                                                || this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Aligned)))
×
206
                                        {
×
UNCOV
207
                                                newRotation += Math.PI;
×
208
                                        }
×
209

210
                                        this.Mirror = this.Mirror.RemoveFlag(TextMirrorFlag.Backward);
×
211
                                }
×
212
                                else
UNCOV
213
                                {
×
UNCOV
214
                                        newObliqueAngle = MathHelper.HalfPI + (newRotation - newObliqueAngle);
×
215
                                }
×
216
                        }
×
217
                        else
218
                        {
1✔
219
                                if (XY.Cross(newUvector, newVvector) < 0.0)
1!
220
                                {
×
UNCOV
221
                                        newObliqueAngle = MathHelper.HalfPI - (newRotation - newObliqueAngle);
×
222

UNCOV
223
                                        if (newUvector.Dot(uv[0]) < 0.0)
×
UNCOV
224
                                        {
×
225
                                                newRotation += Math.PI;
×
226

UNCOV
227
                                                switch (this.HorizontalAlignment)
×
228
                                                {
229
                                                        case TextHorizontalAlignment.Left:
UNCOV
230
                                                                this.HorizontalAlignment = TextHorizontalAlignment.Right;
×
231
                                                                break;
×
232
                                                        case TextHorizontalAlignment.Right:
233
                                                                this.HorizontalAlignment = TextHorizontalAlignment.Left;
×
234
                                                                break;
×
235
                                                }
UNCOV
236
                                        }
×
237
                                        else
238
                                        {
×
UNCOV
239
                                                switch (this.VerticalAlignment)
×
240
                                                {
241
                                                        case TextVerticalAlignmentType.Top:
UNCOV
242
                                                                this.VerticalAlignment = TextVerticalAlignmentType.Bottom;
×
243
                                                                break;
×
244
                                                        case TextVerticalAlignmentType.Bottom:
UNCOV
245
                                                                this.VerticalAlignment = TextVerticalAlignmentType.Top;
×
UNCOV
246
                                                                break;
×
247
                                                }
UNCOV
248
                                        }
×
UNCOV
249
                                }
×
250
                                else
251
                                {
1✔
252
                                        newObliqueAngle = MathHelper.HalfPI + (newRotation - newObliqueAngle);
1✔
253
                                }
1✔
254
                        }
1✔
255

256
                        // the oblique angle is defined between -85 and 85 degrees
257
                        double maxOblique = MathHelper.DegToRad(85);
1✔
258
                        double minOblique = -maxOblique;
1✔
259
                        if (newObliqueAngle > Math.PI)
1!
260
                        {
×
261
                                newObliqueAngle = Math.PI - newObliqueAngle;
×
262
                        }
×
263

264
                        if (newObliqueAngle < minOblique)
1!
UNCOV
265
                        {
×
UNCOV
266
                                newObliqueAngle = minOblique;
×
UNCOV
267
                        }
×
268
                        else if (newObliqueAngle > maxOblique)
1✔
269
                        {
1✔
270
                                newObliqueAngle = maxOblique;
1✔
271
                        }
1✔
272

273
                        // the height must be greater than zero, the cos is always positive between -85 and 85
274
                        double newHeight = newVvector.GetLength() * Math.Cos(newObliqueAngle);
1✔
275
                        newHeight = MathHelper.IsZero(newHeight) ? MathHelper.Epsilon : newHeight;
1!
276

277
                        // the width factor is defined between 0.01 and 100
278
                        double newWidthFactor = newUvector.GetLength() / newHeight;
1✔
279
                        if (newWidthFactor < 0.01)
1!
280
                        {
1✔
281
                                newWidthFactor = 0.01;
1✔
282
                        }
1✔
UNCOV
283
                        else if (newWidthFactor > 100)
×
UNCOV
284
                        {
×
UNCOV
285
                                newWidthFactor = 100;
×
UNCOV
286
                        }
×
287

288
                        this.InsertPoint = newInsert;
1✔
289
                        this.Normal = newNormal;
1✔
290
                        this.Rotation = newRotation;
1✔
291
                        this.Height = newHeight;
1✔
292
                        this.WidthFactor = newWidthFactor;
1✔
293
                        this.ObliqueAngle = newObliqueAngle;
1✔
294
                }
1✔
295

296
                /// <inheritdoc/>
297
                public override CadObject Clone()
298
                {
662✔
299
                        TextEntity clone = (TextEntity)base.Clone();
662✔
300
                        clone.Style = (TextStyle)this.Style.Clone();
662✔
301
                        return clone;
662✔
302
                }
662✔
303

304
                /// <inheritdoc/>
305
                public override BoundingBox GetBoundingBox()
306
                {
9✔
307
                        return new BoundingBox(this.InsertPoint);
9✔
308
                }
9✔
309

310
                internal override void AssignDocument(CadDocument doc)
311
                {
23,328✔
312
                        base.AssignDocument(doc);
23,328✔
313

314
                        this._style = updateTable(this.Style, doc.TextStyles);
23,328✔
315

316
                        doc.DimensionStyles.OnRemove += this.tableOnRemove;
23,328✔
317
                }
23,328✔
318

319
                internal override void UnassignDocument()
320
                {
868✔
321
                        this.Document.DimensionStyles.OnRemove -= this.tableOnRemove;
868✔
322

323
                        base.UnassignDocument();
868✔
324

325
                        this.Style = (TextStyle)this.Style.Clone();
868✔
326
                }
868✔
327

328
                protected override void tableOnRemove(object sender, CollectionChangedEventArgs e)
329
                {
×
330
                        base.tableOnRemove(sender, e);
×
331

UNCOV
332
                        if (e.Item.Equals(this.Style))
×
UNCOV
333
                        {
×
UNCOV
334
                                this.Style = this.Document.TextStyles[TextStyle.DefaultName];
×
UNCOV
335
                        }
×
UNCOV
336
                }
×
337
        }
338
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc