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

DomCR / ACadSharp / 17737244231

15 Sep 2025 02:52PM UTC coverage: 78.246% (+0.001%) from 78.245%
17737244231

Pull #790

github

web-flow
Merge 8b06bd20c into 2bca657be
Pull Request #790: addflag refactor

6647 of 9225 branches covered (72.05%)

Branch coverage included in aggregate %.

70 of 93 new or added lines in 10 files covered. (75.27%)

4 existing lines in 2 files now uncovered.

25703 of 32119 relevant lines covered (80.02%)

108602.48 hits per line

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

60.29
/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,542✔
29

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

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

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

56
                /// <summary>
57
                /// Mirror flags.
58
                /// </summary>
59
                [DxfCodeValue(71)]
60
                public TextMirrorFlag Mirror { get => _mirror; set => _mirror = value; }
1,918✔
61
                /// <summary>
62
                /// Specifies the three-dimensional normal unit vector for the object.
63
                /// </summary>
64
                [DxfCodeValue(210, 220, 230)]
65
                public XYZ Normal { get; set; } = XYZ.AxisZ;
28,571✔
66

67
                /// <inheritdoc/>
68
                public override string ObjectName => DxfFileToken.EntityText;
28,158✔
69

70
                /// <inheritdoc/>
71
                public override ObjectType ObjectType => ObjectType.TEXT;
82✔
72

73
                /// <summary>
74
                /// Specifies the oblique angle of the object.
75
                /// </summary>
76
                /// <value>
77
                /// 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.
78
                /// </value>
79
                [DxfCodeValue(DxfReferenceType.IsAngle, 51)]
80
                public double ObliqueAngle { get; set; } = 0.0;
24,435✔
81

82
                /// <inheritdoc/>
83
                [DxfCodeValue(DxfReferenceType.IsAngle, 50)]
84
                public double Rotation { get; set; }
2,411✔
85

86
                /// <inheritdoc/>
87
                [DxfCodeValue(DxfReferenceType.Name | DxfReferenceType.Optional, 7)]
88
                public TextStyle Style
89
                {
90
                        get { return this._style; }
78,507✔
91
                        set
92
                        {
8,908✔
93
                                if (value == null)
8,908!
94
                                {
×
95
                                        throw new ArgumentNullException(nameof(value));
×
96
                                }
97

98
                                if (this.Document != null)
8,908✔
99
                                {
7,329✔
100
                                        this._style = CadObject.updateCollection(value, this.Document.TextStyles);
7,329✔
101
                                }
7,329✔
102
                                else
103
                                {
1,579✔
104
                                        this._style = value;
1,579✔
105
                                }
1,579✔
106
                        }
8,908✔
107
                }
108

109
                /// <inheritdoc/>
110
                public override string SubclassMarker => DxfSubclassMarker.Text;
141,891✔
111

112
                /// <summary>
113
                /// Specifies the distance a 2D object is extruded above or below its elevation.
114
                /// </summary>
115
                [DxfCodeValue(39)]
116
                public double Thickness { get; set; } = 0.0;
27,550✔
117

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

138
                /// <summary>
139
                /// Vertical text justification type.
140
                /// </summary>
141
                [DxfCodeValue(DxfReferenceType.Optional, 73)]
142
                public virtual TextVerticalAlignmentType VerticalAlignment { get; set; } = TextVerticalAlignmentType.Baseline;
23,957✔
143

144
                /// <summary>
145
                /// Relative X scale factor—widt
146
                /// </summary>
147
                /// <remarks>
148
                /// This value is also adjusted when fit-type text is used
149
                /// </remarks>
150
                [DxfCodeValue(DxfReferenceType.Optional, 41)]
151
                public double WidthFactor { get; set; } = 1.0;
24,436✔
152

153
                private double _height = 0.0;
22,586✔
154
                private TextStyle _style = TextStyle.Default;
22,586✔
155
                private string _value = string.Empty;
22,586✔
156
                private TextMirrorFlag _mirror = TextMirrorFlag.None;
22,586✔
157

158
                public TextEntity() : base()
22,586✔
159
                {
22,586✔
160
                }
22,586✔
161

162
                /// <inheritdoc/>
163
                public override void ApplyTransform(Transform transform)
164
                {
1✔
165
                        bool mirrText = this.Mirror.HasFlag(TextMirrorFlag.Backward);
1✔
166

167
                        XYZ newInsert = transform.ApplyTransform(this.InsertPoint);
1✔
168
                        XYZ newNormal = this.transformNormal(transform, this.Normal);
1✔
169

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

172
                        List<XY> uv = applyRotation(
1✔
173
                                new[]
1✔
174
                                {
1✔
175
                                        this.WidthFactor * this.Height * XY.AxisX,
1✔
176
                                        new XY(this.Height * Math.Tan(this.ObliqueAngle), this.Height)
1✔
177
                                },
1✔
178
                                this.Rotation);
1✔
179

180
                        XYZ v;
181
                        v = transOW * new XYZ(uv[0].X, uv[0].Y, 0.0);
1✔
182
                        v = transformation * v;
1✔
183
                        v = transWO * v;
1✔
184
                        XY newUvector = new XY(v.X, v.Y);
1✔
185

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

191
                        double newRotation = newUvector.GetAngle();
1✔
192
                        double newObliqueAngle = newVvector.GetAngle();
1✔
193

194
                        if (mirrText)
1!
195
                        {
×
196
                                if (XY.Cross(newUvector, newVvector) < 0)
×
197
                                {
×
198
                                        newObliqueAngle = MathHelper.HalfPI - (newRotation - newObliqueAngle);
×
199
                                        if (!(this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Fit)
×
200
                                                || this.HorizontalAlignment.HasFlag(TextHorizontalAlignment.Aligned)))
×
201
                                        {
×
202
                                                newRotation += Math.PI;
×
203
                                        }
×
204

NEW
205
                                        this._mirror.RemoveFlag(TextMirrorFlag.Backward);
×
206
                                }
×
207
                                else
208
                                {
×
209
                                        newObliqueAngle = MathHelper.HalfPI + (newRotation - newObliqueAngle);
×
210
                                }
×
211
                        }
×
212
                        else
213
                        {
1✔
214
                                if (XY.Cross(newUvector, newVvector) < 0.0)
1!
215
                                {
×
216
                                        newObliqueAngle = MathHelper.HalfPI - (newRotation - newObliqueAngle);
×
217

218
                                        if (newUvector.Dot(uv[0]) < 0.0)
×
219
                                        {
×
220
                                                newRotation += Math.PI;
×
221

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

251
                        // the oblique angle is defined between -85 and 85 degrees
252
                        double maxOblique = MathHelper.DegToRad(85);
1✔
253
                        double minOblique = -maxOblique;
1✔
254
                        if (newObliqueAngle > Math.PI)
1!
255
                        {
×
256
                                newObliqueAngle = Math.PI - newObliqueAngle;
×
257
                        }
×
258

259
                        if (newObliqueAngle < minOblique)
1!
260
                        {
×
261
                                newObliqueAngle = minOblique;
×
262
                        }
×
263
                        else if (newObliqueAngle > maxOblique)
1✔
264
                        {
1✔
265
                                newObliqueAngle = maxOblique;
1✔
266
                        }
1✔
267

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

272
                        // the width factor is defined between 0.01 and 100
273
                        double newWidthFactor = newUvector.GetLength() / newHeight;
1✔
274
                        if (newWidthFactor < 0.01)
1!
275
                        {
1✔
276
                                newWidthFactor = 0.01;
1✔
277
                        }
1✔
278
                        else if (newWidthFactor > 100)
×
279
                        {
×
280
                                newWidthFactor = 100;
×
281
                        }
×
282

283
                        this.InsertPoint = newInsert;
1✔
284
                        this.Normal = newNormal;
1✔
285
                        this.Rotation = newRotation;
1✔
286
                        this.Height = newHeight;
1✔
287
                        this.WidthFactor = newWidthFactor;
1✔
288
                        this.ObliqueAngle = newObliqueAngle;
1✔
289
                }
1✔
290

291
                /// <inheritdoc/>
292
                public override CadObject Clone()
293
                {
680✔
294
                        TextEntity clone = (TextEntity)base.Clone();
680✔
295
                        clone.Style = (TextStyle)this.Style.Clone();
680✔
296
                        return clone;
680✔
297
                }
680✔
298

299
                /// <inheritdoc/>
300
                public override BoundingBox GetBoundingBox()
301
                {
9✔
302
                        return new BoundingBox(this.InsertPoint);
9✔
303
                }
9✔
304

305
                internal override void AssignDocument(CadDocument doc)
306
                {
23,517✔
307
                        base.AssignDocument(doc);
23,517✔
308

309
                        this._style = CadObject.updateCollection(this.Style, doc.TextStyles);
23,517✔
310

311
                        doc.DimensionStyles.OnRemove += this.tableOnRemove;
23,517✔
312
                }
23,517✔
313

314
                internal override void UnassignDocument()
315
                {
868✔
316
                        this.Document.DimensionStyles.OnRemove -= this.tableOnRemove;
868✔
317

318
                        base.UnassignDocument();
868✔
319

320
                        this.Style = (TextStyle)this.Style.Clone();
868✔
321
                }
868✔
322

323
                protected override void tableOnRemove(object sender, CollectionChangedEventArgs e)
324
                {
×
325
                        base.tableOnRemove(sender, e);
×
326

327
                        if (e.Item.Equals(this.Style))
×
328
                        {
×
329
                                this.Style = this.Document.TextStyles[TextStyle.DefaultName];
×
330
                        }
×
331
                }
×
332
        }
333
}
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