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

DomCR / ACadSharp / 30440247664

29 Jul 2026 09:33AM UTC coverage: 75.674% (-0.1%) from 75.805%
30440247664

Pull #1164

github

web-flow
Merge 21dc6dbaf into 219e5fc4a
Pull Request #1164: Add DimensionArc entity with DWG and DXF read/write support

9197 of 13140 branches covered (69.99%)

Branch coverage included in aggregate %.

35 of 126 new or added lines in 6 files covered. (27.78%)

149 existing lines in 1 file now uncovered.

32955 of 42562 relevant lines covered (77.43%)

151836.87 hits per line

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

80.01
/src/ACadSharp/IO/DXF/DxfStreamReader/DxfSectionReaderBase.cs
1
using ACadSharp.Entities;
2
using ACadSharp.IO.Templates;
3
using ACadSharp.Objects;
4
using ACadSharp.Tables;
5
using ACadSharp.XData;
6
using CSMath;
7
using CSUtilities.Extensions;
8
using System;
9
using System.Collections.Generic;
10
using System.Diagnostics;
11
using System.Linq;
12
using static ACadSharp.IO.Templates.CadMLeaderAnnotContextTemplate;
13
using static ACadSharp.IO.Templates.CadTableEntityTemplate;
14

15
namespace ACadSharp.IO.DXF.DxfStreamReader;
16

17
internal abstract class DxfSectionReaderBase
18
{
19
        public delegate bool ReadEntityDelegate<T>(CadEntityTemplate template, DxfMap map, string subclass = null) where T : Entity;
20

21
        protected readonly IDxfStreamReader _reader;
22
        protected readonly DxfDocumentBuilder _builder;
23

24
        //Avoid to move the reader to the next line
25
        protected bool lockPointer = false;
1,100✔
26
        protected string currentSubclass = null;
1,100✔
27

28
        public DxfSectionReaderBase(IDxfStreamReader reader, DxfDocumentBuilder builder)
1,100✔
29
        {
1,100✔
30
                this._reader = reader;
1,100✔
31
                this._builder = builder;
1,100✔
32
        }
1,100✔
33

34
        public abstract void Read();
35

36
        protected void readCommonObjectData(out string name, out ulong handle, out ulong? ownerHandle, out ulong? xdictHandle, out HashSet<ulong> reactors)
37
        {
2,403✔
38
                name = null;
2,403✔
39
                handle = 0;
2,403✔
40
                ownerHandle = null;
2,403✔
41
                xdictHandle = null;
2,403✔
42
                reactors = new HashSet<ulong>();
2,403✔
43

44
                if (this._reader.DxfCode == DxfCode.Start
2,403!
45
                                || this._reader.DxfCode == DxfCode.Subclass)
2,403✔
46
                        this._reader.ReadNext();
×
47

48
                //Loop until the common data end
49
                while (this._reader.DxfCode != DxfCode.Start
9,547✔
50
                                && this._reader.DxfCode != DxfCode.Subclass)
9,547✔
51
                {
7,144✔
52
                        switch (this._reader.Code)
7,144!
53
                        {
54
                                //Table name
55
                                case 2:
56
                                        name = this._reader.ValueAsString;
2,403✔
57
                                        break;
2,403✔
58
                                //Handle
59
                                case 5:
60
                                case 105:
61
                                        handle = this._reader.ValueAsHandle;
2,115✔
62
                                        break;
2,115✔
63
                                //Start of application - defined group
64
                                case 102:
65
                                        this.readDefinedGroups(out xdictHandle, out reactors);
223✔
66
                                        break;
223✔
67
                                //Soft - pointer ID / handle to owner BLOCK_RECORD object
68
                                case 330:
69
                                        ownerHandle = this._reader.ValueAsHandle;
2,115✔
70
                                        break;
2,115✔
71
                                case 71:
72
                                //Number of entries for dimension style table
73
                                case 340:
74
                                //Dimension table has the handles of the styles at the begining
75
                                default:
76
                                        this._builder.Notify($"Unhandled dxf code {this._reader.Code} at line {this._reader.Position}.");
288✔
77
                                        break;
288✔
78
                        }
79

80
                        this._reader.ReadNext();
7,144✔
81
                }
7,144✔
82
        }
2,403✔
83

84
        [Obsolete("Only needed for SortEntitiesTable but it should be removed")]
85
        protected void readCommonObjectData(CadTemplate template)
86
        {
612✔
87
                while (this._reader.DxfCode != DxfCode.Subclass)
2,448✔
88
                {
1,836✔
89
                        switch (this._reader.Code)
1,836!
90
                        {
91
                                //object name
92
                                case 0:
93
                                        Debug.Assert(template.CadObject.ObjectName == this._reader.ValueAsString);
×
94
                                        break;
×
95
                                //Handle
96
                                case 5:
97
                                        template.CadObject.Handle = this._reader.ValueAsHandle;
612✔
98
                                        break;
612✔
99
                                //Start of application - defined group
100
                                case 102:
101
                                        this.readDefinedGroups(template);
612✔
102
                                        break;
612✔
103
                                //Soft - pointer ID / handle to owner BLOCK_RECORD object
104
                                case 330:
105
                                        template.OwnerHandle = this._reader.ValueAsHandle;
612✔
106
                                        break;
612✔
107
                                default:
108
                                        this._builder.Notify($"Unhandled dxf code {this._reader.Code} at line {this._reader.Position}.", NotificationType.None);
×
109
                                        break;
×
110
                        }
111

112
                        this._reader.ReadNext();
1,836✔
113
                }
1,836✔
114
        }
612✔
115

116
        protected void readCommonCodes(CadTemplate template, out bool isExtendedData, DxfMap map = null)
117
        {
840,196✔
118
                isExtendedData = false;
840,196✔
119

120
                switch (this._reader.Code)
840,196✔
121
                {
122
                        //Handle
123
                        case 5:
124
                                template.CadObject.Handle = this._reader.ValueAsHandle;
316,807✔
125
                                break;
316,807✔
126
                        //Check with mapper
127
                        case 100:
128
                                this.currentSubclass = this._reader.ValueAsString;
218,686✔
129
                                if (map != null && !map.SubClasses.ContainsKey(this._reader.ValueAsString))
218,686!
130
                                {
924✔
131
                                        this._builder.Notify($"[{template.CadObject.ObjectName}] Unidentified subclass {this._reader.ValueAsString}", NotificationType.Warning);
924✔
132
                                }
924✔
133
                                break;
218,686✔
134
                        //Start of application - defined group
135
                        case 102:
136
                                this.readDefinedGroups(template);
72,194✔
137
                                break;
72,194✔
138
                        //Soft - pointer ID / handle to owner BLOCK_RECORD object
139
                        case 330:
140
                                template.OwnerHandle = this._reader.ValueAsHandle;
179,504✔
141
                                break;
179,504✔
142
                        case 1001:
143
                                isExtendedData = true;
24,767✔
144
                                this.readExtendedData(template.EDataTemplateByAppName);
24,767✔
145
                                break;
24,767✔
146
                        default:
147
                                this._builder.Notify($"[{this.currentSubclass}] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
28,238✔
148
                                break;
28,238✔
149
                }
150
        }
840,196✔
151

152
        protected CadEntityTemplate readEntity()
153
        {
154,967✔
154
                this.currentSubclass = string.Empty;
154,967✔
155
                switch (this._reader.ValueAsString)
154,967!
156
                {
157
                        case DxfFileToken.EntityAttribute:
158
                                return this.readEntityCodes<AttributeEntity>(new CadAttributeTemplate(new AttributeEntity()), this.readAttributeDefinition);
1,008✔
159
                        case DxfFileToken.EntityAttributeDefinition:
160
                                return this.readEntityCodes<AttributeDefinition>(new CadAttributeTemplate(new AttributeDefinition()), this.readAttributeDefinition);
1,190✔
161
                        case DxfFileToken.EntityArc:
162
                                return this.readEntityCodes<Arc>(new CadEntityTemplate<Arc>(), this.readArc);
728✔
163
                        case DxfFileToken.EntityBody:
164
                                return this.readEntityCodes<CadBody>(new CadModelerGeometryTemplate<CadBody>(), this.readModelerGeometry);
×
165
                        case DxfFileToken.EntityCircle:
166
                                return this.readEntityCodes<Circle>(new CadEntityTemplate<Circle>(), this.readCircle);
3,228✔
167
                        case DxfFileToken.EntityArcDimension:
NEW
168
                                return this.readEntityCodes<Dimension>(new CadDimensionTemplate(new DimensionArc()), this.readDimension);
×
169
                        case DxfFileToken.EntityDimension:
170
                                var dimTemplate = this.readEntityCodes<Dimension>(new CadDimensionTemplate(), this.readDimension);
2,772✔
171
                                if (dimTemplate.CadObject is CadDimensionTemplate.DimensionPlaceholder)
2,772✔
172
                                {
36✔
173
                                        this._builder.Notify($"[{DxfFileToken.EntityDimension}] No subtype found, object discarded.", NotificationType.Warning);
36✔
174
                                        return null;
36✔
175
                                }
176
                                return dimTemplate;
2,736✔
177
                        case DxfFileToken.Entity3DFace:
178
                                return this.readEntityCodes<Face3D>(new CadEntityTemplate<Face3D>(), this.readEntitySubclassMap);
252✔
179
                        case DxfFileToken.EntityEllipse:
180
                                return this.readEntityCodes<Ellipse>(new CadEntityTemplate<Ellipse>(), this.readEntitySubclassMap);
216✔
181
                        case DxfFileToken.EntityLeader:
182
                                return this.readEntityCodes<Leader>(new CadLeaderTemplate(), this.readLeader);
216✔
183
                        case DxfFileToken.EntityLine:
184
                                return this.readEntityCodes<Line>(new CadEntityTemplate<Line>(), this.readEntitySubclassMap);
65,420✔
185
                        case DxfFileToken.EntityLwPolyline:
186
                                return this.readEntityCodes<LwPolyline>(new CadEntityTemplate<LwPolyline>(), this.readLwPolyline);
4,975✔
187
                        case DxfFileToken.EntityMesh:
188
                                return this.readEntityCodes<Mesh>(new CadMeshTemplate(), this.readMesh);
432✔
189
                        case DxfFileToken.EntityHatch:
190
                                return this.readEntityCodes<Hatch>(new CadHatchTemplate(), this.readHatch);
1,728✔
191
                        case DxfFileToken.EntityInsert:
192
                                return this.readEntityCodes<Insert>(new CadInsertTemplate(), this.readInsert);
5,857✔
193
                        case DxfFileToken.EntityMText:
194
                                return this.readEntityCodes<MText>(new CadTextEntityTemplate(new MText()), this.readTextEntity);
7,404✔
195
                        case DxfFileToken.EntityMLine:
196
                                return this.readEntityCodes<MLine>(new CadMLineTemplate(), this.readMLine);
648✔
197
                        case DxfFileToken.EntityMultiLeader:
198
                                return this.readEntityCodes<MultiLeader>(new CadMLeaderTemplate(), this.readMLeader);
3,240✔
199
                        case DxfFileToken.EntityPdfUnderlay:
200
                                return this.readEntityCodes<PdfUnderlay>(new CadUnderlayTemplate<PdfUnderlayDefinition>(new PdfUnderlay()), this.readUnderlayEntity<PdfUnderlayDefinition>);
216✔
201
                        case DxfFileToken.EntityPoint:
202
                                return this.readEntityCodes<Point>(new CadEntityTemplate<Point>(), this.readEntitySubclassMap);
9,604✔
203
                        case DxfFileToken.EntityPolyline:
204
                                return this.readPolyline();
11,092✔
205
                        case DxfFileToken.EntityOle2Frame:
UNCOV
206
                                return this.readEntityCodes<Ole2Frame>(new CadOle2FrameTemplate(), this.readOle2Frame);
×
207
                        case DxfFileToken.EntityRay:
208
                                return this.readEntityCodes<Ray>(new CadEntityTemplate<Ray>(), this.readEntitySubclassMap);
216✔
209
                        case DxfFileToken.EndSequence:
210
                                return this.readEntityCodes<Seqend>(new CadEntityTemplate<Seqend>(), this.readEntitySubclassMap);
504✔
211
                        case DxfFileToken.EntityTrace:
212
                        case DxfFileToken.EntitySolid:
213
                                return this.readEntityCodes<Solid>(new CadEntityTemplate<Solid>(), this.readModelerGeometry);
14,600✔
214
                        case DxfFileToken.EntityTable:
215
                                return this.readEntityCodes<TableEntity>(new CadTableEntityTemplate(), this.readTableEntity);
432✔
216
                        case DxfFileToken.EntityText:
217
                                return this.readEntityCodes<TextEntity>(new CadTextEntityTemplate(new TextEntity()), this.readTextEntity);
15,026✔
218
                        case DxfFileToken.EntityTolerance:
219
                                return this.readEntityCodes<Tolerance>(new CadToleranceTemplate(new Tolerance()), this.readTolerance);
648✔
220
                        case DxfFileToken.EntityVertex:
UNCOV
221
                                return this.readEntityCodes<Entity>(new CadVertexTemplate(), this.readVertex);
×
222
                        case DxfFileToken.EntityViewport:
223
                                return this.readEntityCodes<Viewport>(new CadViewportTemplate(), this.readViewport);
1,332✔
224
                        case DxfFileToken.EntityShape:
225
                                return this.readEntityCodes<Shape>(new CadShapeTemplate(new Shape()), this.readShape);
252✔
226
                        case DxfFileToken.EntitySpline:
227
                                return this.readEntityCodes<Spline>(new CadSplineTemplate(), this.readSpline);
432✔
228
                        case DxfFileToken.Entity3DSolid:
229
                                return this.readEntityCodes<Solid3D>(new CadSolid3DTemplate(), this.readSolid3d);
432✔
230
                        case DxfFileToken.EntityRegion:
231
                                return this.readEntityCodes<Region>(new CadModelerGeometryTemplate<Region>(), this.readModelerGeometry);
219✔
232
                        case DxfFileToken.EntityImage:
233
                                return this.readEntityCodes<RasterImage>(new CadWipeoutBaseTemplate(new RasterImage()), this.readWipeoutBase);
216✔
234
                        case DxfFileToken.EntityWipeout:
235
                                return this.readEntityCodes<Wipeout>(new CadWipeoutBaseTemplate(new Wipeout()), this.readWipeoutBase);
216✔
236
                        case DxfFileToken.EntityXline:
237
                                return this.readEntityCodes<XLine>(new CadEntityTemplate<XLine>(), this.readEntitySubclassMap);
216✔
238
                        default:
239
                                DxfMap map = DxfMap.Create<Entity>();
×
240
                                CadUnknownEntityTemplate unknownEntityTemplate = null;
×
241
                                if (this._builder.DocumentToBuild.Classes.TryGetByName(this._reader.ValueAsString, out Classes.DxfClass dxfClass))
×
242
                                {
×
243
                                        this._builder.Notify($"Entity not supported read as an UnknownEntity: {this._reader.ValueAsString}", NotificationType.NotImplemented);
×
244
                                        unknownEntityTemplate = new CadUnknownEntityTemplate(new UnknownEntity(dxfClass));
×
UNCOV
245
                                }
×
246
                                else
247
                                {
×
248
                                        this._builder.Notify($"Entity not supported: {this._reader.ValueAsString}", NotificationType.NotImplemented);
×
UNCOV
249
                                }
×
250

UNCOV
251
                                this._reader.ReadNext();
×
252

253
                                do
254
                                {
×
255
                                        if (unknownEntityTemplate != null && this._builder.KeepUnknownEntities)
×
256
                                        {
×
257
                                                this.readCommonEntityCodes(unknownEntityTemplate, out bool isExtendedData, map);
×
258
                                                if (isExtendedData)
×
259
                                                        continue;
×
UNCOV
260
                                        }
×
261

262
                                        this._reader.ReadNext();
×
263
                                }
×
UNCOV
264
                                while (this._reader.DxfCode != DxfCode.Start);
×
265

UNCOV
266
                                return unknownEntityTemplate;
×
267
                }
268
        }
154,967✔
269

270
        protected CadEntityTemplate readEntityCodes<T>(CadEntityTemplate template, ReadEntityDelegate<T> readEntity)
271
                where T : Entity
272
        {
206,761✔
273
                this._reader.ReadNext();
206,761✔
274

275
                DxfMap map = DxfMap.Create<T>();
206,761✔
276

277
                while (this._reader.DxfCode != DxfCode.Start)
2,799,745✔
278
                {
2,592,984✔
279
                        if (!readEntity(template, map))
2,592,984✔
280
                        {
904,167✔
281
                                this.readCommonEntityCodes(template, out bool isExtendedData, map);
904,167✔
282
                                if (isExtendedData)
904,167✔
283
                                        continue;
14,487✔
284
                        }
889,680✔
285

286
                        if (this.lockPointer)
2,578,497✔
287
                        {
3,168✔
288
                                this.lockPointer = false;
3,168✔
289
                                continue;
3,168✔
290
                        }
291

292
                        if (this._reader.DxfCode != DxfCode.Start)
2,575,329✔
293
                                this._reader.ReadNext();
2,574,827✔
294
                }
2,575,329✔
295

296
                return template;
206,761✔
297
        }
206,761✔
298

299
        protected void readCommonEntityCodes(CadEntityTemplate template, out bool isExtendedData, DxfMap map = null)
300
        {
976,055✔
301
                isExtendedData = false;
976,055✔
302
                switch (this._reader.Code)
976,055✔
303
                {
304
                        case 6:
305
                                template.LineTypeName = this._reader.ValueAsString;
27,278✔
306
                                break;
27,278✔
307
                        case 8:
308
                                template.LayerName = this._reader.ValueAsString;
224,319✔
309
                                break;
224,319✔
310
                        //Absent or zero indicates entity is in model space. 1 indicates entity is in paper space (optional).
311
                        case 67:
312
                                break;
1,344✔
313
                        //Number of bytes Proxy entity graphics data
314
                        case 92:
315
                        case 160:
316
                        //Proxy entity graphics data
317
                        case 310:
318
                                break;
81,072✔
319
                        case 347:
320
                                template.MaterialHandle = this._reader.ValueAsHandle;
720✔
321
                                break;
720✔
322
                        case 430:
323
                                template.BookColorName = this._reader.ValueAsString;
180✔
324
                                break;
180✔
325
                        default:
326
                                if (!this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Entity]))
641,142✔
327
                                {
499,740✔
328
                                        this.readCommonCodes(template, out isExtendedData, map);
499,740✔
329
                                }
499,740✔
330
                                break;
641,142✔
331
                }
332
        }
976,055✔
333

334
        [Obsolete("use lockpointer instead")]
335
        protected bool checkObjectEnd(CadTemplate template, DxfMap map, Func<CadTemplate, DxfMap, bool> func)
336
        {
3,088✔
337
                if (this._reader.DxfCode == DxfCode.Start)
3,088!
338
                {
×
UNCOV
339
                        return true;
×
340
                }
341
                else
342
                {
3,088✔
343
                        return func.Invoke(template, map);
3,088✔
344
                }
345
        }
3,088✔
346

347
        protected bool checkEntityEnd(CadEntityTemplate template, DxfMap map, string subclass, Func<CadEntityTemplate, DxfMap, string, bool> func)
348
        {
432✔
349
                if (this._reader.DxfCode == DxfCode.Start)
432!
350
                {
432✔
351
                        return true;
432✔
352
                }
353
                else
354
                {
×
UNCOV
355
                        return func.Invoke(template, map, subclass);
×
356
                }
357
        }
432✔
358

359
        private bool readCircle(CadEntityTemplate template, DxfMap map, string subclass = null)
360
        {
38,125✔
361
                Circle circle = template.CadObject as Circle;
38,125✔
362

363
                switch (this._reader.Code)
38,125✔
364
                {
365
                        case 40:
366
                                double radius = this._reader.ValueAsDouble;
3,956✔
367
                                if (radius <= 0)
3,956!
368
                                {
×
369
                                        circle.Radius = MathHelper.Epsilon;
×
UNCOV
370
                                }
×
371
                                else
372
                                {
3,956✔
373
                                        circle.Radius = radius;
3,956✔
374
                                }
3,956✔
375
                                return true;
3,956✔
376
                        default:
377
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Circle]);
34,169✔
378
                }
379
        }
38,125✔
380

381
        private bool readArc(CadEntityTemplate template, DxfMap map, string subclass = null)
382
        {
9,544✔
383
                switch (this._reader.Code)
9,544✔
384
                {
385
                        default:
386
                                if (!this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Arc]))
9,544✔
387
                                {
8,088✔
388
                                        return this.readCircle(template, map, DxfSubclassMarker.Circle);
8,088✔
389
                                }
390
                                return true;
1,456✔
391
                }
392
        }
9,544✔
393

394
        private bool readAttributeDefinition(CadEntityTemplate template, DxfMap map, string subclass = null)
395
        {
35,474✔
396
                DxfClassMap emap = map.SubClasses[template.CadObject.SubclassMarker];
35,474✔
397
                CadAttributeTemplate tmp = template as CadAttributeTemplate;
35,474✔
398

399
                switch (this._reader.Code)
35,474!
400
                {
401
                        case 44:
402
                        case 46:
UNCOV
403
                                return true;
×
404
                        case 101:
405
                                var att = tmp.CadObject as AttributeBase;
70✔
406
                                att.MText = new MText();
70✔
407
                                CadTextEntityTemplate mtextTemplate = new CadTextEntityTemplate(att.MText);
70✔
408
                                tmp.MTextTemplate = mtextTemplate;
70✔
409
                                this.readEntityCodes<MText>(mtextTemplate, this.readTextEntity);
70✔
410
                                return true;
70✔
411
                        default:
412
                                if (!this.tryAssignCurrentValue(template.CadObject, emap))
35,404✔
413
                                {
26,786✔
414
                                        return this.readTextEntity(template, map, DxfSubclassMarker.Text);
26,786✔
415
                                }
416
                                return true;
8,618✔
417
                }
418
        }
35,474✔
419

420
        private bool readTableEntity(CadEntityTemplate template, DxfMap map, string subclass = null)
421
        {
142,236✔
422
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
142,236!
423
                CadTableEntityTemplate tmp = template as CadTableEntityTemplate;
142,236✔
424
                TableEntity table = tmp.CadObject as TableEntity;
142,236✔
425

426
                switch (this._reader.Code)
142,236!
427
                {
428
                        case 1:
429
                                TableEntity.CellContent content;
430
                                if (tmp.CurrentCell.Content == null)
2,808!
431
                                {
2,808✔
432
                                        content = new TableEntity.CellContent();
2,808✔
433
                                        content.CadValue.ValueType = CadValueType.String;
2,808✔
434
                                        tmp.CurrentCell.Contents.Add(content);
2,808✔
435
                                }
2,808✔
436
                                else
437
                                {
×
438
                                        content = tmp.CurrentCell.Content;
×
UNCOV
439
                                }
×
440

441
                                if (content.CadValue.Value == null)
2,808!
442
                                {
2,808✔
443
                                        content.CadValue.SetValue(this._reader.ValueAsString, CadValueType.String);
2,808✔
444
                                }
2,808✔
445
                                else
446
                                {
×
447
                                        string str = content.CadValue.Value as string;
×
448
                                        str += this._reader.ValueAsString;
×
449
                                        content.CadValue.SetValue(str, CadValueType.String);
×
UNCOV
450
                                }
×
451
                                return true;
2,808✔
452
                        case 2:
453
                                if (this.currentSubclass.Equals(DxfSubclassMarker.TableEntity, StringComparison.OrdinalIgnoreCase))
432!
454
                                {
×
455
                                        content = tmp.CurrentCell.Content;
×
456
                                        if (content.CadValue.Value == null)
×
457
                                        {
×
458
                                                content.CadValue.SetValue(this._reader.ValueAsString, CadValueType.String);
×
UNCOV
459
                                        }
×
460
                                        else
461
                                        {
×
462
                                                string str = content.CadValue.Value as string;
×
463
                                                str += this._reader.ValueAsString;
×
464
                                                content.CadValue.SetValue(str, CadValueType.String);
×
465
                                        }
×
UNCOV
466
                                }
×
467
                                else
468
                                {
432✔
469
                                        tmp.BlockName = this._reader.ValueAsString;
432✔
470
                                }
432✔
471
                                return true;
432✔
472
                        //Border overrides:
473
                        case 177:
474
                                //Cell override flag value (before AutoCAD 2007)
475
                                return true;
2,952✔
476
                        case 279:
477
                                //Lineweight for the top border of the cell; override applied at the cell level
478
                                tmp.CurrentCell.StyleOverride.TopBorder.LineWeight = (LineWeightType)this._reader.ValueAsShort;
1,512✔
479
                                return true;
1,512✔
480
                        case 275:
481
                                //Lineweight for the right border of the cell; override applied at the cell level
482
                                tmp.CurrentCell.StyleOverride.RightBorder.LineWeight = (LineWeightType)this._reader.ValueAsShort;
432✔
483
                                return true;
432✔
484
                        case 276:
485
                                //Lineweight for the bottom border of the cell; override applied at the cell level
486
                                tmp.CurrentCell.StyleOverride.BottomBorder.LineWeight = (LineWeightType)this._reader.ValueAsShort;
×
UNCOV
487
                                return true;
×
488
                        case 278:
489
                                //Lineweight for the left border of the cell; override applied at the cell level
490
                                tmp.CurrentCell.StyleOverride.LeftBorder.LineWeight = (LineWeightType)this._reader.ValueAsShort;
1,296✔
491
                                return true;
1,296✔
492
                        case 69:
493
                                //True color value for the top border of the cell; override applied at the cell level
494
                                tmp.CurrentCell.StyleOverride.TopBorder.Color = new Color(this._reader.ValueAsShort);
1,512✔
495
                                return true;
1,512✔
496
                        case 65:
497
                                //True color value for the right border of the cell; override applied at the cell level
498
                                tmp.CurrentCell.StyleOverride.RightBorder.Color = new Color(this._reader.ValueAsShort);
432✔
499
                                return true;
432✔
500
                        case 66:
501
                                //True color value for the bottom border of the cell; override applied at the cell level
502
                                tmp.CurrentCell.StyleOverride.BottomBorder.Color = new Color(this._reader.ValueAsShort);
×
UNCOV
503
                                return true;
×
504
                        case 68:
505
                                //True color value for the left border of the cell; override applied at the cell level
506
                                tmp.CurrentCell.StyleOverride.LeftBorder.Color = new Color(this._reader.ValueAsShort);
1,296✔
507
                                return true;
1,296✔
508
                        case 40:
509
                                tmp.HorizontalMargin = this._reader.ValueAsDouble;
216✔
510
                                return true;
216✔
511
                        case 63:
512
                                tmp.CurrentCell.StyleOverride.BackgroundColor = new Color(this._reader.ValueAsShort);
216✔
513
                                return true;
216✔
514
                        case 64:
515
                                tmp.CurrentCell.StyleOverride.ContentColor = new Color(this._reader.ValueAsShort);
216✔
516
                                return true;
216✔
517
                        case 140:
518
                                if (tmp.CurrentCellTemplate != null)
5,184✔
519
                                {
4,536✔
520
                                        tmp.CurrentCellTemplate.FormatTextHeight = this._reader.ValueAsDouble;
4,536✔
521
                                }
4,536✔
522
                                return true;
5,184✔
523
                        case 283:
524
                                tmp.CurrentCell.StyleOverride.IsFillColorOn = this._reader.ValueAsBool;
216✔
525
                                return true;
216✔
526
                        case 342:
527
                                tmp.StyleHandle = this._reader.ValueAsHandle;
432✔
528
                                return true;
432✔
529
                        case 343:
530
                                tmp.BlockOwnerHandle = this._reader.ValueAsHandle;
432✔
531
                                return true;
432✔
532
                        case 141:
533
                                var row = new TableEntity.Row();
2,376✔
534
                                row.Height = this._reader.ValueAsDouble;
2,376✔
535
                                table.Rows.Add(row);
2,376✔
536
                                return true;
2,376✔
537
                        case 142:
538
                                var col = new TableEntity.Column();
1,728✔
539
                                col.Width = this._reader.ValueAsDouble;
1,728✔
540
                                table.Columns.Add(col);
1,728✔
541
                                return true;
1,728✔
542
                        case 144:
543
                                tmp.CurrentCellTemplate.FormatTextHeight = this._reader.ValueAsDouble;
432✔
544
                                return true;
432✔
545
                        case 145:
546
                                tmp.CurrentCell.Rotation = this._reader.ValueAsDouble;
8,856✔
547
                                return true;
8,856✔
548
                        case 170:
549
                                //Has data flag
550
                                return true;
648✔
551
                        case 171:
552
                                tmp.CreateCell((TableEntity.CellType)this._reader.ValueAsInt);
8,856✔
553
                                return true;
8,856✔
554
                        case 172:
555
                                tmp.CurrentCell.EdgeFlags = this._reader.ValueAsShort;
8,856✔
556
                                return true;
8,856✔
557
                        case 173:
558
                                tmp.CurrentCell.MergedValue = this._reader.ValueAsShort;
8,856✔
559
                                return true;
8,856✔
560
                        case 174:
561
                                tmp.CurrentCell.AutoFit = this._reader.ValueAsBool;
8,856✔
562
                                return true;
8,856✔
563
                        case 175:
564
                                tmp.CurrentCell.BorderWidth = this._reader.ValueAsInt;
8,856✔
565
                                return true;
8,856✔
566
                        case 176:
567
                                tmp.CurrentCell.BorderHeight = this._reader.ValueAsInt;
8,856✔
568
                                return true;
8,856✔
569
                        case 178:
570
                                tmp.CurrentCell.VirtualEdgeFlag = this._reader.ValueAsShort;
8,856✔
571
                                return true;
8,856✔
572
                        case 179:
573
                                //Unknown value
574
                                return true;
432✔
575
                        case 301:
576
                                content = new TableEntity.CellContent();
5,904✔
577
                                var contentTemplate = new CadTableCellContentTemplate(content);
5,904✔
578
                                tmp.CurrentCell.Contents.Add(content);
5,904✔
579
                                var valTemplate = readCadValue(content.CadValue);
5,904✔
580
                                contentTemplate.CadValueTemplate = valTemplate;
5,904✔
581
                                return true;
5,904✔
582
                        case 340:
583
                                tmp.CurrentCellTemplate.ValueHandle = this._reader.ValueAsHandle;
432✔
584
                                return true;
432✔
585
                        default:
586
                                if (!this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Insert]))
39,852✔
587
                                {
38,340✔
588
                                        return this.readEntitySubclassMap(template, map, DxfSubclassMarker.TableEntity);
38,340✔
589
                                }
590
                                return true;
1,512✔
591
                }
592
        }
142,236✔
593

594
        protected CadValueTemplate readCadValue(CadValue value)
595
        {
9,848✔
596
                this._reader.ReadNext();
9,848✔
597

598
                CadValueTemplate template = new(value);
9,848✔
599
                var map = DxfClassMap.Create(value.GetType(), "CadValue");
9,848✔
600

601
                while (this._reader.Code != 304)
65,384✔
602
                {
55,536✔
603
                        switch (this._reader.Code)
55,536!
604
                        {
605
                                case 1:
606
                                        value.SetValue(this._reader.ValueAsString);
3,496✔
607
                                        break;
3,496✔
608
                                case 2:
609
                                        value.SetValue((value.Value as string) + this._reader.ValueAsString);
×
UNCOV
610
                                        break;
×
611
                                case 11:
612
                                        XYZ xyz = new XYZ();
280✔
613
                                        xyz.X = this._reader.ValueAsDouble;
280✔
614
                                        value.SetValue(xyz);
280✔
615
                                        break;
280✔
616
                                case 21:
617
                                        {
280✔
618
                                                IVector v = value.Value as IVector;
280✔
619
                                                v[1] = this._reader.ValueAsDouble;
280✔
620
                                                value.SetValue(v);
280✔
621
                                        }
280✔
622
                                        break;
280✔
623
                                case 31:
624
                                        {
280✔
625
                                                IVector v = value.Value as IVector;
280✔
626
                                                v = v.Convert<XYZ>();
280✔
627
                                                v[2] = this._reader.ValueAsDouble;
280✔
628
                                                value.SetValue(v);
280✔
629
                                        }
280✔
630
                                        break;
280✔
631
                                case 90:
632
                                        value.ValueType = (CadValueType)this._reader.ValueAsInt;
9,848✔
633
                                        break;
9,848✔
634
                                case 91:
635
                                        value.SetValue(this._reader.ValueAsInt);
280✔
636
                                        break;
280✔
637
                                case 93:
638
                                        value.Flags = this._reader.ValueAsInt;
9,848✔
639
                                        break;
9,848✔
640
                                case 140:
641
                                        value.SetValue(this._reader.ValueAsDouble);
1,120✔
642
                                        break;
1,120✔
643
                                case 330:
644
                                        template.ValueHandle = this._reader.ValueAsHandle;
×
UNCOV
645
                                        break;
×
646
                                default:
647
                                        if (!this.tryAssignCurrentValue(value, map))
30,104✔
648
                                        {
560✔
649
                                                this._builder.Notify($"Unhandled dxf code {this._reader.Code} value {this._reader.ValueAsString} at {nameof(readCadValue)} method.", NotificationType.None);
560✔
650
                                        }
560✔
651
                                        break;
30,104✔
652
                        }
653

654
                        this._reader.ReadNext();
55,536✔
655
                }
55,536✔
656

657
                return template;
9,848✔
658
        }
9,848✔
659

660
        private bool readTextEntity(CadEntityTemplate template, DxfMap map, string subclass = null)
661
        {
306,634✔
662
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
306,634✔
663
                CadTextEntityTemplate tmp = template as CadTextEntityTemplate;
306,634✔
664

665
                switch (this._reader.Code)
306,634✔
666
                {
667
                        case 1 or 3 when tmp.CadObject is MText mtext:
27,506✔
668
                                mtext.Value += this._reader.ValueAsString;
10,282✔
669
                                return true;
10,282✔
670
                        case 50 when tmp.CadObject is MText mtext://Read only for MText
510!
671
                                double angle = this._reader.ValueAsAngle;
×
672
                                mtext.AlignmentPoint = new XYZ(System.Math.Cos(angle), System.Math.Sin(angle), 0.0);
×
UNCOV
673
                                return true;
×
674
                        case 7:
675
                                tmp.StyleName = this._reader.ValueAsString;
3,024✔
676
                                return true;
3,024✔
677
                        case 101 when tmp.CadObject is MText mtext:
144✔
678
                                this.readColumnData(mtext);
144✔
679
                                this.lockPointer = true;
144✔
680
                                return true;
144✔
681
                        default:
682
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[mapName]);
293,184✔
683
                }
684
        }
306,634✔
685

686
        private void readColumnData(MText mtext)
687
        {
144✔
688
                this._reader.ReadNext();
144✔
689
                while (this._reader.DxfCode != DxfCode.Start)
2,736✔
690
                {
2,592✔
691
                        switch (this._reader.Code)
2,592!
692
                        {
693
                                //Element count?
694
                                case 70:
695
                                        break;
144✔
696
                                case 71:
697
                                        mtext.ColumnData.ColumnType = (ColumnType)this._reader.ValueAsShort;
144✔
698
                                        break;
144✔
699
                                case 72:
700
                                        mtext.ColumnData.ColumnCount = this._reader.ValueAsInt;
144✔
701
                                        break;
144✔
702
                                //X - axis dir 3BD 10
703
                                case 10:
704
                                case 20:
705
                                case 30:
706
                                //Insertion point 3BD 11
707
                                case 11:
708
                                case 21:
709
                                case 31:
710
                                //Rect width BD 40
711
                                case 40:
712
                                //Rect height BD 41
713
                                case 41:
714
                                //Extents width BD 42
715
                                case 42:
716
                                //Extents height BD 43
717
                                case 43:
718
                                        break;
1,440✔
719
                                case 44:
720
                                        mtext.ColumnData.Width = this._reader.ValueAsDouble;
144✔
721
                                        break;
144✔
722
                                case 45:
723
                                        mtext.ColumnData.Gutter = this._reader.ValueAsDouble;
144✔
724
                                        break;
144✔
725
                                case 46:
726
                                        mtext.ColumnData.Heights.Add(this._reader.ValueAsDouble);
144✔
727
                                        break;
144✔
728
                                case 73:
729
                                        mtext.ColumnData.AutoHeight = this._reader.ValueAsBool;
144✔
730
                                        break;
144✔
731
                                case 74:
732
                                        mtext.ColumnData.FlowReversed = this._reader.ValueAsBool;
144✔
733
                                        break;
144✔
734
                                default:
735
                                        this._builder.Notify($"[MText.ColumnData] unkown dxf code {this._reader.Code}.", NotificationType.None);
×
UNCOV
736
                                        break;
×
737
                        }
738

739
                        this._reader.ReadNext();
2,592✔
740
                }
2,592✔
741
        }
144✔
742

743
        private bool readTolerance(CadEntityTemplate template, DxfMap map, string subclass = null)
744
        {
6,480✔
745
                CadToleranceTemplate tmp = template as CadToleranceTemplate;
6,480✔
746

747
                switch (this._reader.Code)
6,480✔
748
                {
749
                        case 3:
750
                                tmp.DimensionStyleName = this._reader.ValueAsString;
648✔
751
                                return true;
648✔
752
                        default:
753
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[template.CadObject.SubclassMarker]);
5,832✔
754
                }
755
        }
6,480✔
756

757
        private bool readDimension(CadEntityTemplate template, DxfMap map, string subclass = null)
758
        {
72,504✔
759
                CadDimensionTemplate tmp = template as CadDimensionTemplate;
72,504✔
760

761
                switch (this._reader.Code)
72,504!
762
                {
763
                        case 2:
764
                                tmp.BlockName = this._reader.ValueAsString;
2,772✔
765
                                return true;
2,772✔
766
                        case 3:
767
                                tmp.StyleName = this._reader.ValueAsString;
2,376✔
768
                                return true;
2,376✔
769
                        case 50:
770
                                if (tmp.CadObject is not DimensionLinear dim)
252✔
771
                                {
216✔
772
                                        dim = new DimensionLinear();
216✔
773
                                        tmp.SetDimensionObject(dim);
216✔
774
                                }
216✔
775
                                dim.Rotation = this._reader.ValueAsAngle;
252✔
776
                                map.SubClasses.TryAdd(DxfSubclassMarker.LinearDimension, DxfClassMap.Create<DimensionLinear>());
252✔
777
                                return true;
252✔
778
                        case 40 when tmp.CadObject is DimensionArc arcStart && this.currentSubclass == DxfSubclassMarker.ArcDimension:
504!
NEW
779
                                arcStart.StartAngle = this._reader.ValueAsDouble;
×
NEW
UNCOV
780
                                return true;
×
NEW
UNCOV
781
                        case 41 when tmp.CadObject is DimensionArc arcEnd && this.currentSubclass == DxfSubclassMarker.ArcDimension:
×
NEW
UNCOV
782
                                arcEnd.EndAngle = this._reader.ValueAsDouble;
×
NEW
UNCOV
783
                                return true;
×
784
                        case 70 when tmp.CadObject is DimensionArc arcPartial && this.currentSubclass == DxfSubclassMarker.ArcDimension:
2,772!
NEW
UNCOV
785
                                arcPartial.IsPartial = this._reader.ValueAsBool;
×
NEW
UNCOV
786
                                return true;
×
787
                        case 71 when tmp.CadObject is DimensionArc arcLeader && this.currentSubclass == DxfSubclassMarker.ArcDimension:
2,376!
NEW
UNCOV
788
                                arcLeader.HasLeader = this._reader.ValueAsBool;
×
NEW
UNCOV
789
                                return true;
×
790
                        case 70:
791
                                //Flags do not have set
792
                                tmp.SetDimensionFlags((DimensionType)this._reader.ValueAsShort);
2,772✔
793

794
                                if (tmp.CadObject is CadDimensionTemplate.DimensionPlaceholder placeholder && this._builder.Version < ACadVersion.AC1012)
2,772!
795
                                {
396✔
796
                                        switch (placeholder.Flags)
396!
797
                                        {
798
                                                case DimensionType.Linear:
799
                                                        tmp.SetDimensionObject(new DimensionLinear());
108✔
800
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.AlignedDimension, DxfClassMap.Create<DimensionAligned>());
108✔
801
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.LinearDimension, DxfClassMap.Create<DimensionLinear>());
108✔
802
                                                        break;
108✔
803
                                                case DimensionType.Aligned:
804
                                                        tmp.SetDimensionObject(new DimensionAligned());
72✔
805
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.AlignedDimension, DxfClassMap.Create<DimensionAligned>());
72✔
806
                                                        break;
72✔
807
                                                case DimensionType.Angular:
808
                                                        tmp.SetDimensionObject(new DimensionAngular2Line());
36✔
809
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.Angular2LineDimension, DxfClassMap.Create<DimensionAngular2Line>());
36✔
810
                                                        break;
36✔
811
                                                case DimensionType.Diameter:
UNCOV
812
                                                        tmp.SetDimensionObject(new DimensionDiameter());
×
UNCOV
813
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.DiametricDimension, DxfClassMap.Create<DimensionDiameter>());
×
UNCOV
814
                                                        break;
×
815
                                                case DimensionType.Radius:
816
                                                        tmp.SetDimensionObject(new DimensionRadius());
36✔
817
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.RadialDimension, DxfClassMap.Create<DimensionRadius>());
36✔
818
                                                        break;
36✔
819
                                                case DimensionType.Angular3Point:
820
                                                        tmp.SetDimensionObject(new DimensionAngular3Pt());
36✔
821
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.Angular3PointDimension, DxfClassMap.Create<DimensionAngular3Pt>());
36✔
822
                                                        break;
36✔
823
                                                case DimensionType.Ordinate:
824
                                                case DimensionType.OrdinateTypeX:
825
                                                case DimensionType.Ordinate | DimensionType.OrdinateTypeX:
826
                                                        tmp.SetDimensionObject(new DimensionOrdinate());
72✔
827
                                                        map.SubClasses.TryAdd(DxfSubclassMarker.OrdinateDimension, DxfClassMap.Create<DimensionOrdinate>());
72✔
828
                                                        break;
72✔
829
                                                case DimensionType.BlockReference:
830
                                                case DimensionType.TextUserDefinedLocation:
831
                                                default:
832
                                                        break;
36✔
833
                                        }
834
                                }
396✔
835
                                return true;
2,772✔
836
                        //Measurement - read only
837
                        case 42:
838
                                return true;
2,376✔
839
                        //Undocumented codes
840
                        case 73:
841
                        case 74:
842
                        case 75:
843
                        case 90:
844
                        case 361:
845
                                return true;
4,752✔
846
                        case 100:
847
                                this.currentSubclass = this._reader.ValueAsString;
7,776✔
848
                                switch (this._reader.ValueAsString)
7,776!
849
                                {
850
                                        case DxfSubclassMarker.Dimension:
851
                                                return true;
2,376✔
852
                                        case DxfSubclassMarker.AlignedDimension:
853
                                                tmp.SetDimensionObject(new DimensionAligned());
1,080✔
854
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionAligned>());
1,080✔
855
                                                return true;
1,080✔
856
                                        case DxfSubclassMarker.DiametricDimension:
857
                                                tmp.SetDimensionObject(new DimensionDiameter());
216✔
858
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionDiameter>());
216✔
859
                                                return true;
216✔
860
                                        case DxfSubclassMarker.Angular2LineDimension:
861
                                                tmp.SetDimensionObject(new DimensionAngular2Line());
216✔
862
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionAngular2Line>());
216✔
863
                                                return true;
216✔
864
                                        case DxfSubclassMarker.Angular3PointDimension:
865
                                                tmp.SetDimensionObject(new DimensionAngular3Pt());
216✔
866
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionAngular3Pt>());
216✔
867
                                                return true;
216✔
868
                                        case DxfSubclassMarker.ArcDimension:
NEW
UNCOV
869
                                                tmp.SetDimensionObject(new DimensionArc());
×
NEW
UNCOV
870
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionArc>());
×
NEW
UNCOV
871
                                                return true;
×
872
                                        case DxfSubclassMarker.RadialDimension:
873
                                                tmp.SetDimensionObject(new DimensionRadius());
216✔
874
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionRadius>());
216✔
875
                                                return true;
216✔
876
                                        case DxfSubclassMarker.OrdinateDimension:
877
                                                tmp.SetDimensionObject(new DimensionOrdinate());
432✔
878
                                                map.SubClasses.TryAdd(this._reader.ValueAsString, DxfClassMap.Create<DimensionOrdinate>());
432✔
879
                                                return true;
432✔
880
                                        case DxfSubclassMarker.LinearDimension:
881
                                                tmp.SetDimensionObject(new DimensionLinear());
648✔
882
                                                map.SubClasses.TryAdd(DxfSubclassMarker.LinearDimension, DxfClassMap.Create<DimensionLinear>());
648✔
883
                                                return true;
648✔
884
                                        default:
885
                                                return false;
2,376✔
886
                                }
887
                        default:
888
                                if (!string.IsNullOrEmpty(this.currentSubclass)
49,428✔
889
                                        && map.SubClasses.TryGetValue(this.currentSubclass, out DxfClassMap currentMap)
49,428✔
890
                                        && this.tryAssignCurrentValue(template.CadObject, currentMap))
49,428✔
891
                                {
34,344✔
892
                                        return true;
34,344✔
893
                                }
894

895
                                if (map.SubClasses.TryGetValue(tmp.CadObject.SubclassMarker, out DxfClassMap dimensionMap))
15,084!
896
                                {
15,084✔
897
                                        return this.tryAssignCurrentValue(template.CadObject, dimensionMap);
15,084✔
898
                                }
NEW
UNCOV
899
                                return false;
×
900
                }
901
        }
72,504✔
902

903
        protected bool readHatch(CadEntityTemplate template, DxfMap map, string subclass = null)
904
        {
46,224✔
905
                CadHatchTemplate tmp = template as CadHatchTemplate;
46,224✔
906
                Hatch hatch = tmp.CadObject;
46,224✔
907

908
                XY seedPoint = new XY();
46,224✔
909

910
                switch (this._reader.Code)
46,224!
911
                {
912
                        case 2:
913
                                hatch.Pattern.Name = this._reader.ValueAsString;
1,728✔
914
                                return true;
1,728✔
915
                        case 10:
916
                                seedPoint.X = this._reader.ValueAsDouble;
3,456✔
917
                                hatch.SeedPoints.Add(seedPoint);
3,456✔
918
                                return true;
3,456✔
919
                        case 20:
920
                                seedPoint = hatch.SeedPoints.LastOrDefault();
3,456✔
921
                                seedPoint.Y = this._reader.ValueAsDouble;
3,456✔
922
                                hatch.SeedPoints[hatch.SeedPoints.Count - 1] = seedPoint;
3,456✔
923
                                return true;
3,456✔
924
                        case 30:
925
                                hatch.Elevation = this._reader.ValueAsDouble;
1,728✔
926
                                return true;
1,728✔
927
                        case 53:
UNCOV
928
                                hatch.PatternAngle = this._reader.ValueAsAngle;
×
UNCOV
929
                                return true;
×
930
                        //TODO: Check hatch undocumented codes
931
                        case 90:
UNCOV
932
                                return true;
×
933
                        //Information about the hatch pattern
934
                        case 75:
935
                                return true;
1,728✔
936
                        //Number of pattern definition lines
937
                        case 78:
938
                                this.readPattern(hatch.Pattern, this._reader.ValueAsInt);
1,296✔
939
                                this.lockPointer = true;
1,296✔
940
                                return true;
1,296✔
941
                        //Number of boundary paths (loops)
942
                        case 91:
943
                                this.readLoops(tmp, this._reader.ValueAsInt);
1,728✔
944
                                this.lockPointer = true;
1,728✔
945
                                return true;
1,728✔
946
                        //Number of seed points
947
                        case 98:
948
                                return true;
1,080✔
949
                        case 450:
950
                                hatch.GradientColor.Enabled = this._reader.ValueAsBool;
360✔
951
                                return true;
360✔
952
                        case 451:
953
                                hatch.GradientColor.Reserved = this._reader.ValueAsInt;
360✔
954
                                return true;
360✔
955
                        case 452:
956
                                hatch.GradientColor.IsSingleColorGradient = this._reader.ValueAsBool;
360✔
957
                                return true;
360✔
958
                        case 453:
959
                                //Number of colors
960
                                return true;
360✔
961
                        case 460:
962
                                hatch.GradientColor.Angle = this._reader.ValueAsDouble;
360✔
963
                                return true;
360✔
964
                        case 461:
965
                                hatch.GradientColor.Shift = this._reader.ValueAsDouble;
360✔
966
                                return true;
360✔
967
                        case 462:
968
                                hatch.GradientColor.ColorTint = this._reader.ValueAsDouble;
360✔
969
                                return true;
360✔
970
                        case 463:
971
                                GradientColor gradient = new GradientColor();
720✔
972
                                gradient.Value = this._reader.ValueAsDouble;
720✔
973
                                hatch.GradientColor.Colors.Add(gradient);
720✔
974
                                return true;
720✔
975
                        case 63:
976
                                GradientColor colorByIndex = hatch.GradientColor.Colors.LastOrDefault();
720✔
977
                                if (colorByIndex != null)
720✔
978
                                {
720✔
979
                                        colorByIndex.Color = new Color((short)this._reader.ValueAsUShort);
720✔
980
                                }
720✔
981
                                return true;
720✔
982
                        case 421:
983
                                GradientColor colorByRgb = hatch.GradientColor.Colors.LastOrDefault();
720✔
984
                                if (colorByRgb != null)
720✔
985
                                {
720✔
986
                                        //TODO: Hatch assign color by true color
987
                                        //TODO: Is always duplicated by 63, is it needed??
988
                                        //colorByRgb.Color = new Color(this._reader.LastValueAsShort);
989
                                }
720✔
990
                                return true;
720✔
991
                        case 470:
992
                                hatch.GradientColor.Name = this._reader.ValueAsString;
360✔
993
                                return true;
360✔
994
                        default:
995
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[template.CadObject.SubclassMarker]);
24,984✔
996
                }
997
        }
46,224✔
998

999
        private bool readInsert(CadEntityTemplate template, DxfMap map, string subclass = null)
1000
        {
62,641✔
1001
                CadInsertTemplate tmp = template as CadInsertTemplate;
62,641✔
1002

1003
                switch (this._reader.Code)
62,641✔
1004
                {
1005
                        case 2:
1006
                                tmp.BlockName = this._reader.ValueAsString;
5,857✔
1007
                                return true;
5,857✔
1008
                        case 100:
1009
                                //AcDbEntity
1010
                                //AcDbBlockReference
1011
                                //AcDbMInsertBlock
1012
                                return true;
5,890✔
1013
                        case 66:
1014
                                return true;
504✔
1015
                        default:
1016
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Insert]);
50,390✔
1017
                }
1018
        }
62,641✔
1019

1020
        private CadEntityTemplate readPolyline()
1021
        {
11,092✔
1022
                if (this._builder.Version == ACadVersion.Unknown
11,092!
1023
                        || this._builder.Version == ACadVersion.AC1009)
11,092✔
1024
                {
10,660✔
1025
                        return this.readLegacyPolyline();
10,660✔
1026
                }
1027

1028
                CadPolyLineTemplate template = null;
432✔
1029
                template = new CadPolyLineTemplate();
432✔
1030
                this.readEntityCodes<Entity>(template, this.readPolyline);
432✔
1031

1032
                if (template.CadObject is CadPolyLineTemplate.PolyLinePlaceholder)
432!
UNCOV
1033
                {
×
UNCOV
1034
                        this._builder.Notify($"[{DxfFileToken.EntityPolyline}] Subclass not found, entity discarded", NotificationType.Warning);
×
UNCOV
1035
                        return null;
×
1036
                }
1037

1038
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EntityVertex)
3,024!
1039
                {
2,592✔
1040
                        var vertexTemplate = this.readEntityCodes<Entity>(new CadVertexTemplate(), this.readVertex);
2,592✔
1041

1042
                        if (vertexTemplate.OwnerHandle == null)
2,592!
1043
                        {
×
1044
                                vertexTemplate.OwnerHandle = template.CadObject.Handle;
×
1045
                        }
×
1046

1047
                        template.OwnedObjectsHandlers.Add(vertexTemplate.CadObject.Handle);
2,592✔
1048
                        _builder.AddTemplate(vertexTemplate);
2,592✔
1049
                }
2,592✔
1050

1051
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EndSequence)
864!
1052
                {
432✔
1053
                        var seqend = new Seqend();
432✔
1054
                        var seqendTemplate = new CadEntityTemplate<Seqend>(seqend);
432✔
1055
                        this.readEntityCodes<Seqend>(seqendTemplate, this.readEntitySubclassMap);
432✔
1056

1057
                        if (seqendTemplate.OwnerHandle == null)
432!
UNCOV
1058
                        {
×
UNCOV
1059
                                seqendTemplate.OwnerHandle = template.CadObject.Handle;
×
UNCOV
1060
                        }
×
1061

1062
                        template.OwnedObjectsHandlers.Add(seqendTemplate.CadObject.Handle);
432✔
1063
                        _builder.AddTemplate(seqendTemplate);
432✔
1064
                }
432✔
1065

1066
                return template;
432✔
1067
        }
11,092✔
1068

1069
        private CadEntityTemplate readLegacyPolyline()
1070
        {
10,660✔
1071
                var polyline = new Polyline2D();
10,660✔
1072
                CadPolyLineTemplate template = new CadPolyLineTemplate(polyline);
10,660✔
1073
                this.readEntityCodes<Polyline2D>(template, this.readPolyline);
10,660✔
1074

1075
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EntityVertex)
48,700!
1076
                {
38,040✔
1077
                        Vertex2D v = new Vertex2D();
38,040✔
1078
                        CadVertexTemplate vertexTemplate = new CadVertexTemplate(v);
38,040✔
1079
                        this.readEntityCodes<Vertex2D>(vertexTemplate, this.readVertex);
38,040✔
1080

1081
                        if (vertexTemplate.Vertex.Handle == 0)
38,040!
UNCOV
1082
                        {
×
UNCOV
1083
                                polyline.Vertices.Add(v);
×
UNCOV
1084
                        }
×
1085
                        else
1086
                        {
38,040✔
1087
                                template.OwnedObjectsHandlers.Add(vertexTemplate.Vertex.Handle);
38,040✔
1088
                                this._builder.AddTemplate(vertexTemplate);
38,040✔
1089
                        }
38,040✔
1090
                }
38,040✔
1091

1092
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EndSequence)
21,320!
1093
                {
10,660✔
1094
                        var seqend = new Seqend();
10,660✔
1095
                        var seqendTemplate = new CadEntityTemplate<Seqend>(seqend);
10,660✔
1096
                        this.readEntityCodes<Seqend>(seqendTemplate, this.readEntitySubclassMap);
10,660✔
1097

1098
                        polyline.Vertices.Seqend = seqend;
10,660✔
1099
                }
10,660✔
1100

1101
                return template;
10,660✔
1102
        }
10,660✔
1103

1104
        private bool readPolyline(CadEntityTemplate template, DxfMap map, string subclass = null)
1105
        {
79,656✔
1106
                CadPolyLineTemplate tmp = template as CadPolyLineTemplate;
79,656✔
1107

1108
                switch (this._reader.Code)
79,656✔
1109
                {
1110
                        //DXF: always 0
1111
                        //APP: a “dummy” point; the X and Y values are always 0, and the Z value is the polyline's elevation (in OCS when 2D, WCS when 3D)
1112
                        case 10:
1113
                        case 20:
1114
                        //Obsolete; formerly an “entities follow flag” (optional; ignore if present)
1115
                        case 66:
1116
                                return true;
33,276✔
1117
                        case 100:
1118
                                switch (this._reader.ValueAsString)
864!
1119
                                {
1120
                                        case DxfSubclassMarker.Polyline:
UNCOV
1121
                                                tmp.SetPolyLineObject(new Polyline2D());
×
UNCOV
1122
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline, DxfClassMap.Create<Polyline2D>());
×
UNCOV
1123
                                                return true;
×
1124
                                        case DxfSubclassMarker.Polyline3d:
1125
                                                tmp.SetPolyLineObject(new Polyline3D());
216✔
1126
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline3d, DxfClassMap.Create<Polyline3D>());
216✔
1127
                                                return true;
216✔
1128
                                        case DxfSubclassMarker.PolyfaceMesh:
1129
                                                tmp.SetPolyLineObject(new PolyfaceMesh());
216✔
1130
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMesh, DxfClassMap.Create<PolyfaceMesh>());
216✔
1131
                                                return true;
216✔
1132
                                        case DxfSubclassMarker.PolygonMesh:
UNCOV
1133
                                                tmp.SetPolyLineObject(new PolygonMesh());
×
UNCOV
1134
                                                map.SubClasses.Add(DxfSubclassMarker.PolygonMesh, DxfClassMap.Create<PolygonMesh>());
×
UNCOV
1135
                                                return true;
×
1136
                                        default:
1137
                                                return false;
432✔
1138
                                }
1139
                        default:
1140
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
45,516✔
1141
                }
1142
        }
79,656✔
1143

1144
        private bool readLeader(CadEntityTemplate template, DxfMap map, string subclass = null)
1145
        {
5,400✔
1146
                CadLeaderTemplate tmp = template as CadLeaderTemplate;
5,400✔
1147

1148
                switch (this._reader.Code)
5,400✔
1149
                {
1150
                        case 3:
1151
                                tmp.DIMSTYLEName = this._reader.ValueAsString;
216✔
1152
                                return true;
216✔
1153
                        case 10:
1154
                                tmp.CadObject.Vertices.Add(new XYZ(this._reader.ValueAsDouble, 0, 0));
864✔
1155
                                return true;
864✔
1156
                        case 20:
1157
                                XYZ y = tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1];
864✔
1158
                                y.Y = this._reader.ValueAsDouble;
864✔
1159
                                tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1] = y;
864✔
1160
                                return true;
864✔
1161
                        case 30:
1162
                                XYZ z = tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1];
864✔
1163
                                z.Z = this._reader.ValueAsDouble;
864✔
1164
                                tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1] = z;
864✔
1165
                                return true;
864✔
1166
                        case 340:
1167
                                tmp.AnnotationHandle = this._reader.ValueAsHandle;
216✔
1168
                                return true;
216✔
1169
                        //Hook line flag - read only
1170
                        case 75:
1171
                        //Vertices count
1172
                        case 76:
1173
                                return true;
432✔
1174
                        default:
1175
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
1,944✔
1176
                }
1177
        }
5,400✔
1178

1179
        private bool readLwPolyline(CadEntityTemplate template, DxfMap map, string subclass = null)
1180
        {
92,700✔
1181
                CadEntityTemplate<LwPolyline> tmp = template as CadEntityTemplate<LwPolyline>;
92,700✔
1182

1183
                LwPolyline.Vertex last = tmp.CadObject.Vertices.LastOrDefault();
92,700✔
1184

1185
                switch (this._reader.Code)
92,700!
1186
                {
1187
                        case 10:
1188
                                tmp.CadObject.Vertices.Add(new LwPolyline.Vertex(new XY(this._reader.ValueAsDouble, 0)));
22,048✔
1189
                                return true;
22,048✔
1190
                        case 20:
1191
                                if (last is not null)
22,048✔
1192
                                {
22,048✔
1193
                                        last.Location = new XY(last.Location.X, this._reader.ValueAsDouble);
22,048✔
1194
                                }
22,048✔
1195
                                return true;
22,048✔
1196
                        case 40:
1197
                                if (last is not null)
2,160✔
1198
                                {
2,160✔
1199
                                        last.StartWidth = this._reader.ValueAsDouble;
2,160✔
1200
                                }
2,160✔
1201
                                return true;
2,160✔
1202
                        case 41:
1203
                                if (last is not null)
2,160✔
1204
                                {
2,160✔
1205
                                        last.EndWidth = this._reader.ValueAsDouble;
2,160✔
1206
                                }
2,160✔
1207
                                return true;
2,160✔
1208
                        case 42:
1209
                                if (last is not null)
2,952✔
1210
                                {
2,952✔
1211
                                        last.Bulge = this._reader.ValueAsDouble;
2,952✔
1212
                                }
2,952✔
1213
                                return true;
2,952✔
1214
                        case 50:
1215
                                if (last is not null)
×
UNCOV
1216
                                {
×
UNCOV
1217
                                        last.CurveTangent = this._reader.ValueAsDouble;
×
UNCOV
1218
                                }
×
UNCOV
1219
                                return true;
×
1220
                        //Obsolete; formerly an “entities follow flag” (optional; ignore if present)
1221
                        case 66:
1222
                        //Vertex count
1223
                        case 90:
1224
                                return true;
4,975✔
1225
                        case 91:
UNCOV
1226
                                if (last is not null)
×
UNCOV
1227
                                {
×
UNCOV
1228
                                        last.Id = this._reader.ValueAsInt;
×
UNCOV
1229
                                }
×
UNCOV
1230
                                return true;
×
1231
                        default:
1232
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
36,357✔
1233
                }
1234
        }
92,700✔
1235

1236
        private bool readMesh(CadEntityTemplate template, DxfMap map, string subclass = null)
1237
        {
38,016✔
1238
                CadMeshTemplate tmp = template as CadMeshTemplate;
38,016✔
1239

1240
                switch (this._reader.Code)
38,016✔
1241
                {
1242
                        case 100:
1243
                                if (this._reader.ValueAsString.Equals(DxfSubclassMarker.Mesh, StringComparison.OrdinalIgnoreCase))
864✔
1244
                                {
432✔
1245
                                        tmp.SubclassMarker = true;
432✔
1246
                                }
432✔
1247
                                return true;
864✔
1248
                        //Count of sub-entity which property has been overridden
1249
                        case 90:
1250
                                //TODO: process further entities
1251
                                return true;
432✔
1252
                        case 92:
1253
                                if (!tmp.SubclassMarker)
648✔
1254
                                {
216✔
1255
                                        return false;
216✔
1256
                                }
1257

1258
                                int nvertices = this._reader.ValueAsInt;
432✔
1259
                                for (int i = 0; i < nvertices; i++)
55,296✔
1260
                                {
27,216✔
1261
                                        this._reader.ReadNext();
27,216✔
1262
                                        double x = this._reader.ValueAsDouble;
27,216✔
1263
                                        this._reader.ReadNext();
27,216✔
1264
                                        double y = this._reader.ValueAsDouble;
27,216✔
1265
                                        this._reader.ReadNext();
27,216✔
1266
                                        double z = this._reader.ValueAsDouble;
27,216✔
1267
                                        tmp.CadObject.Vertices.Add(new XYZ(x, y, z));
27,216✔
1268
                                }
27,216✔
1269
                                return true;
432✔
1270
                        case 93:
1271
                                int size = this._reader.ValueAsInt;
432✔
1272
                                this._reader.ReadNext();
432✔
1273

1274
                                int indexes = 0;
432✔
1275
                                for (int i = 0; i < size; i += indexes + 1)
59,616✔
1276
                                {
29,376✔
1277
                                        indexes = this._reader.ValueAsInt;
29,376✔
1278
                                        this._reader.ReadNext();
29,376✔
1279

1280
                                        int[] face = new int[indexes];
29,376✔
1281
                                        for (int j = 0; j < indexes; j++)
283,392✔
1282
                                        {
112,320✔
1283
                                                face[j] = this._reader.ValueAsInt;
112,320✔
1284

1285
                                                if ((i + j + 2) < size)
112,320✔
1286
                                                {
111,888✔
1287
                                                        this._reader.ReadNext();
111,888✔
1288
                                                }
111,888✔
1289
                                        }
112,320✔
1290

1291
                                        tmp.CadObject.Faces.Add(face);
29,376✔
1292
                                }
29,376✔
1293

1294
                                return true;
432✔
1295
                        case 94:
1296
                                int numEdges = this._reader.ValueAsInt;
432✔
1297
                                this._reader.ReadNext();
432✔
1298
                                for (int i = 0; i < numEdges; i++)
113,184✔
1299
                                {
56,160✔
1300
                                        Mesh.Edge edge = new Mesh.Edge();
56,160✔
1301

1302
                                        edge.Start = this._reader.ValueAsInt;
56,160✔
1303
                                        this._reader.ReadNext();
56,160✔
1304
                                        edge.End = this._reader.ValueAsInt;
56,160✔
1305

1306
                                        if (i < numEdges - 1)
56,160✔
1307
                                        {
55,728✔
1308
                                                this._reader.ReadNext();
55,728✔
1309
                                        }
55,728✔
1310

1311
                                        tmp.CadObject.Edges.Add(edge);
56,160✔
1312
                                }
56,160✔
1313

1314
                                return true;
432✔
1315
                        case 95:
1316
                                this._reader.ReadNext();
432✔
1317
                                for (int i = 0; i < tmp.CadObject.Edges.Count; i++)
113,184✔
1318
                                {
56,160✔
1319
                                        Mesh.Edge edge = tmp.CadObject.Edges[i];
56,160✔
1320
                                        edge.Crease = this._reader.ValueAsDouble;
56,160✔
1321

1322
                                        tmp.CadObject.Edges[i] = edge;
56,160✔
1323

1324
                                        if (i < tmp.CadObject.Edges.Count - 1)
56,160✔
1325
                                        {
55,728✔
1326
                                                this._reader.ReadNext();
55,728✔
1327
                                        }
55,728✔
1328
                                }
56,160✔
1329

1330
                                return true;
432✔
1331
                        default:
1332
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
34,776✔
1333
                }
1334
        }
38,016✔
1335

1336
        private bool readMLine(CadEntityTemplate template, DxfMap map, string subclass = null)
1337
        {
56,160✔
1338
                CadMLineTemplate tmp = template as CadMLineTemplate;
56,160✔
1339

1340
                switch (this._reader.Code)
56,160✔
1341
                {
1342
                        // String of up to 32 characters. The name of the style used for this mline. An entry for this style must exist in the MLINESTYLE dictionary.
1343
                        // Do not modify this field without also updating the associated entry in the MLINESTYLE dictionary
1344
                        case 2:
1345
                                tmp.MLineStyleName = this._reader.ValueAsString;
648✔
1346
                                return true;
648✔
1347
                        case 72:
1348
                                tmp.NVertex = this._reader.ValueAsInt;
648✔
1349
                                return true;
648✔
1350
                        case 73:
1351
                                tmp.NElements = this._reader.ValueAsInt;
648✔
1352
                                return true;
648✔
1353
                        case 340:
1354
                                tmp.MLineStyleHandle = this._reader.ValueAsHandle;
648✔
1355
                                return true;
648✔
1356
                        default:
1357
                                if (!tmp.TryReadVertex(this._reader.Code, this._reader.Value))
53,568✔
1358
                                {
9,072✔
1359
                                        return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
9,072✔
1360
                                }
1361
                                return true;
44,496✔
1362
                }
1363
        }
56,160✔
1364

1365
        private bool readMLeader(CadEntityTemplate template, DxfMap map, string subclass = null)
1366
        {
152,496✔
1367
                CadMLeaderTemplate tmp = template as CadMLeaderTemplate;
152,496✔
1368

1369
                switch (this._reader.Code)
152,496✔
1370
                {
1371
                        case 270:
1372
                                //f270 Version
1373
                                return true;
1,620✔
1374
                        case 300:
1375
                                this.readMultiLeaderObjectContextData(tmp.CadMLeaderAnnotContextTemplate);
3,240✔
1376
                                return true;
3,240✔
1377
                        case 340:
1378
                                tmp.LeaderStyleHandle = this._reader.ValueAsHandle;
3,240✔
1379
                                return true;
3,240✔
1380
                        case 341:
1381
                                tmp.LeaderLineTypeHandle = this._reader.ValueAsHandle;
3,240✔
1382
                                return true;
3,240✔
1383
                        case 343:
1384
                                tmp.MTextStyleHandle = this._reader.ValueAsHandle;
3,240✔
1385
                                return true;
3,240✔
1386
                        default:
1387
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
137,916✔
1388
                }
1389
        }
152,496✔
1390

1391
        private void readMultiLeaderObjectContextData(CadMLeaderAnnotContextTemplate template)
1392
        {
3,240✔
1393
                this._reader.ReadNext();
3,240✔
1394

1395
                var map = DxfClassMap.Create<MultiLeaderObjectContextData>();
3,240✔
1396
                var contextData = template.CadObject as MultiLeaderObjectContextData;
3,240✔
1397

1398
                bool end = false;
3,240✔
1399
                while (this._reader.DxfCode != DxfCode.Start)
181,440✔
1400
                {
181,440✔
1401
                        switch (this._reader.Code)
181,440✔
1402
                        {
1403
                                case 301 when this._reader.ValueAsString.Equals("}"):
3,240✔
1404
                                        end = true;
3,240✔
1405
                                        break;
3,240✔
1406
                                case 302 when this._reader.ValueAsString.Equals("LEADER{"):
3,240✔
1407
                                        contextData.LeaderRoots.Add(this.readMultiLeaderLeader(template));
3,240✔
1408
                                        break;
3,240✔
1409
                                case 340:
1410
                                        template.TextStyleHandle = this._reader.ValueAsHandle;
3,240✔
1411
                                        break;
3,240✔
1412
                                default:
1413
                                        if (!this.tryAssignCurrentValue(contextData, map))
171,720!
UNCOV
1414
                                        {
×
UNCOV
1415
                                                this._builder.Notify($"[AcDbMLeaderObjectContextData] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
UNCOV
1416
                                        }
×
1417
                                        break;
171,720✔
1418
                        }
1419

1420
                        if (end)
181,440✔
1421
                        {
3,240✔
1422
                                break;
3,240✔
1423
                        }
1424

1425
                        this._reader.ReadNext();
178,200✔
1426
                }
178,200✔
1427
        }
3,240✔
1428

1429
        private MultiLeaderObjectContextData.LeaderRoot readMultiLeaderLeader(CadMLeaderAnnotContextTemplate template)
1430
        {
3,240✔
1431
                MultiLeaderObjectContextData.LeaderRoot root = new();
3,240✔
1432
                var map = DxfClassMap.Create(root.GetType(), nameof(MultiLeaderObjectContextData.LeaderRoot));
3,240✔
1433

1434
                this._reader.ReadNext();
3,240✔
1435

1436
                bool end = false;
3,240✔
1437
                while (this._reader.DxfCode != DxfCode.Start)
40,500✔
1438
                {
40,500✔
1439
                        switch (this._reader.Code)
40,500✔
1440
                        {
1441
                                case 303 when this._reader.ValueAsString.Equals("}"):
3,240✔
1442
                                        end = true;
3,240✔
1443
                                        break;
3,240✔
1444
                                case 304 when this._reader.ValueAsString.Equals("LEADER_LINE{"):
3,240✔
1445
                                        var lineTemplate = new LeaderLineTemplate();
3,240✔
1446
                                        template.LeaderLineTemplates.Add(lineTemplate);
3,240✔
1447
                                        root.Lines.Add(this.readMultiLeaderLine(lineTemplate));
3,240✔
1448
                                        break;
3,240✔
1449
                                default:
1450
                                        if (!this.tryAssignCurrentValue(root, map))
34,020!
UNCOV
1451
                                        {
×
UNCOV
1452
                                                this._builder.Notify($"[LeaderRoot] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
UNCOV
1453
                                        }
×
1454
                                        break;
34,020✔
1455
                        }
1456

1457
                        if (end)
40,500✔
1458
                        {
3,240✔
1459
                                break;
3,240✔
1460
                        }
1461

1462
                        this._reader.ReadNext();
37,260✔
1463
                }
37,260✔
1464

1465
                return root;
3,240✔
1466
        }
3,240✔
1467

1468
        private MultiLeaderObjectContextData.LeaderLine readMultiLeaderLine(LeaderLineTemplate template)
1469
        {
3,240✔
1470
                MultiLeaderObjectContextData.LeaderLine line = template.LeaderLine;
3,240✔
1471
                var map = DxfClassMap.Create(line.GetType(), nameof(MultiLeaderObjectContextData.LeaderLine));
3,240✔
1472

1473
                this._reader.ReadNext();
3,240✔
1474

1475
                bool end = false;
3,240✔
1476
                while (this._reader.DxfCode != DxfCode.Start)
16,200✔
1477
                {
16,200✔
1478
                        switch (this._reader.Code)
16,200✔
1479
                        {
1480
                                case 10:
1481
                                        XYZ pt = new XYZ(this._reader.ValueAsDouble, 0, 0);
3,240✔
1482
                                        line.Points.Add(pt);
3,240✔
1483
                                        break;
3,240✔
1484
                                case 20:
1485
                                        pt = line.Points[line.Points.Count - 1];
3,240✔
1486
                                        pt.Y = this._reader.ValueAsDouble;
3,240✔
1487
                                        line.Points[line.Points.Count - 1] = pt;
3,240✔
1488
                                        break;
3,240✔
1489
                                case 30:
1490
                                        pt = line.Points[line.Points.Count - 1];
3,240✔
1491
                                        pt.Z = this._reader.ValueAsDouble;
3,240✔
1492
                                        line.Points[line.Points.Count - 1] = pt;
3,240✔
1493
                                        break;
3,240✔
1494
                                case 305 when this._reader.ValueAsString.Equals("}"):
3,240✔
1495
                                        end = true;
3,240✔
1496
                                        break;
3,240✔
1497
                                default:
1498
                                        if (!this.tryAssignCurrentValue(line, map))
3,240!
UNCOV
1499
                                        {
×
UNCOV
1500
                                                this._builder.Notify($"[LeaderLine] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
UNCOV
1501
                                        }
×
1502
                                        break;
3,240✔
1503
                        }
1504

1505
                        if (end)
16,200✔
1506
                        {
3,240✔
1507
                                break;
3,240✔
1508
                        }
1509

1510
                        this._reader.ReadNext();
12,960✔
1511
                }
12,960✔
1512

1513
                return line;
3,240✔
1514
        }
3,240✔
1515

1516
        private bool readShape(CadEntityTemplate template, DxfMap map, string subclass = null)
1517
        {
2,412✔
1518
                CadShapeTemplate tmp = template as CadShapeTemplate;
2,412✔
1519

1520
                switch (this._reader.Code)
2,412✔
1521
                {
1522
                        case 2:
1523
                                tmp.ShapeFileName = this._reader.ValueAsString;
252✔
1524
                                return true;
252✔
1525
                        default:
1526
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
2,160✔
1527
                }
1528
        }
2,412✔
1529

1530
        private bool readWipeoutBase(CadEntityTemplate template, DxfMap map, string subclass = null)
1531
        {
12,744✔
1532
                CadWipeoutBaseTemplate tmp = template as CadWipeoutBaseTemplate;
12,744✔
1533
                CadWipeoutBase wipeout = tmp.CadObject as CadWipeoutBase;
12,744✔
1534

1535
                switch (this._reader.Code)
12,744✔
1536
                {
1537
                        case 91:
1538
                                var nvertices = this._reader.ValueAsInt;
432✔
1539
                                for (int i = 0; i < nvertices; i++)
3,888✔
1540
                                {
1,512✔
1541
                                        this._reader.ReadNext();
1,512✔
1542
                                        var x = this._reader.ValueAsDouble;
1,512✔
1543
                                        this._reader.ReadNext();
1,512✔
1544
                                        var y = this._reader.ValueAsDouble;
1,512✔
1545

1546
                                        wipeout.ClipBoundaryVertices.Add(new XY(x, y));
1,512✔
1547
                                }
1,512✔
1548

1549
                                this._reader.ReadNext();
432✔
1550

1551
                                return this.checkEntityEnd(template, map, subclass, this.readWipeoutBase);
432✔
1552
                        case 340:
1553
                                tmp.ImgDefHandle = this._reader.ValueAsHandle;
432✔
1554
                                return true;
432✔
1555
                        case 360:
1556
                                tmp.ImgReactorHandle = this._reader.ValueAsHandle;
432✔
1557
                                return true;
432✔
1558
                        default:
1559
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
11,448✔
1560
                }
1561
        }
12,744✔
1562

1563
        private bool readOle2Frame(CadEntityTemplate template, DxfMap map, string subclass = null)
UNCOV
1564
        {
×
1565
                CadOle2FrameTemplate tmp = template as CadOle2FrameTemplate;
×
1566

1567
                switch (this._reader.Code)
×
1568
                {
1569
                        //End of data
1570
                        case 1:
1571
                        //Length of binary data
1572
                        case 90:
1573
                        //Undocumented
1574
                        case 73:
UNCOV
1575
                                return true;
×
1576
                        case 310:
UNCOV
1577
                                tmp.Chunks.Add(this._reader.ValueAsBinaryChunk);
×
UNCOV
1578
                                return true;
×
1579
                        default:
UNCOV
1580
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
×
1581
                }
UNCOV
1582
        }
×
1583

1584
        private bool readModelerGeometry(CadEntityTemplate template, DxfMap map, string subclass = null)
1585
        {
306,674✔
1586
                CadSolid3DTemplate tmp = template as CadSolid3DTemplate;
306,674✔
1587
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
306,674✔
1588
                var geometry = template.CadObject as ModelerGeometry;
306,674✔
1589

1590
                switch (this._reader.Code)
306,674✔
1591
                {
1592
                        case 1:
1593
                                //New SAT line: decoded into the template accumulator, raw into
1594
                                //ProprietaryData to preserve the previous behavior.
1595
                                (template as IAcisDataTemplate)?.AppendAcisLine(this._reader.ValueAsString);
39,928!
1596
                                geometry.ProprietaryData.AppendLine(this._reader.ValueAsString);
39,928✔
1597
                                return true;
39,928✔
1598
                        case 3:
1599
                                //Continuation of the previous SAT line.
1600
                                (template as IAcisDataTemplate)?.AppendAcisContinuation(this._reader.ValueAsString);
1!
1601
                                geometry.ProprietaryData.AppendLine(this._reader.ValueAsString);
1✔
1602
                                return true;
1✔
1603
                        case 2:
1604
                                geometry.Guid = new Guid(this._reader.ValueAsString);
216✔
1605
                                return true;
216✔
1606
                        case 290:
1607
                                return true;
216✔
1608
                        default:
1609
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[mapName]);
266,313✔
1610
                }
1611
        }
306,674✔
1612

1613
        private bool readSolid3d(CadEntityTemplate template, DxfMap map, string subclass = null)
1614
        {
36,936✔
1615
                CadSolid3DTemplate tmp = template as CadSolid3DTemplate;
36,936✔
1616

1617
                switch (this._reader.Code)
36,936✔
1618
                {
1619
                        case 350:
1620
                                tmp.HistoryHandle = this._reader.ValueAsHandle;
288✔
1621
                                return true;
288✔
1622
                        default:
1623
                                return this.readModelerGeometry(template, map, DxfSubclassMarker.ModelerGeometry);
36,648✔
1624
                }
1625
        }
36,936✔
1626

1627
        private bool readSpline(CadEntityTemplate template, DxfMap map, string subclass = null)
1628
        {
15,120✔
1629
                CadSplineTemplate tmp = template as CadSplineTemplate;
15,120✔
1630

1631
                XYZ controlPoint;
1632
                XYZ fitPoint;
1633

1634
                switch (this._reader.Code)
15,120!
1635
                {
1636
                        case 10:
1637
                                controlPoint = new CSMath.XYZ(this._reader.ValueAsDouble, 0, 0);
1,728✔
1638
                                tmp.CadObject.ControlPoints.Add(controlPoint);
1,728✔
1639
                                return true;
1,728✔
1640
                        case 20:
1641
                                controlPoint = tmp.CadObject.ControlPoints.LastOrDefault();
1,728✔
1642
                                controlPoint.Y = this._reader.ValueAsDouble;
1,728✔
1643
                                tmp.CadObject.ControlPoints[tmp.CadObject.ControlPoints.Count - 1] = controlPoint;
1,728✔
1644
                                return true;
1,728✔
1645
                        case 30:
1646
                                controlPoint = tmp.CadObject.ControlPoints.LastOrDefault();
1,728✔
1647
                                controlPoint.Z = this._reader.ValueAsDouble;
1,728✔
1648
                                tmp.CadObject.ControlPoints[tmp.CadObject.ControlPoints.Count - 1] = controlPoint;
1,728✔
1649
                                return true;
1,728✔
1650
                        case 11:
UNCOV
1651
                                fitPoint = new CSMath.XYZ(this._reader.ValueAsDouble, 0, 0);
×
UNCOV
1652
                                tmp.CadObject.FitPoints.Add(fitPoint);
×
1653
                                return true;
×
1654
                        case 21:
UNCOV
1655
                                fitPoint = tmp.CadObject.FitPoints.LastOrDefault();
×
UNCOV
1656
                                fitPoint.Y = this._reader.ValueAsDouble;
×
UNCOV
1657
                                tmp.CadObject.FitPoints[tmp.CadObject.FitPoints.Count - 1] = fitPoint;
×
UNCOV
1658
                                return true;
×
1659
                        case 31:
UNCOV
1660
                                fitPoint = tmp.CadObject.FitPoints.LastOrDefault();
×
UNCOV
1661
                                fitPoint.Z = this._reader.ValueAsDouble;
×
UNCOV
1662
                                tmp.CadObject.FitPoints[tmp.CadObject.FitPoints.Count - 1] = fitPoint;
×
UNCOV
1663
                                return true;
×
1664
                        case 40:
1665
                                tmp.CadObject.Knots.Add(this._reader.ValueAsDouble);
3,456✔
1666
                                return true;
3,456✔
1667
                        case 41:
UNCOV
1668
                                tmp.CadObject.Weights.Add(this._reader.ValueAsDouble);
×
UNCOV
1669
                                return true;
×
1670
                        case 72:
1671
                        case 73:
1672
                        case 74:
1673
                                return true;
1,296✔
1674
                        default:
1675
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
5,184✔
1676
                }
1677
        }
15,120✔
1678

1679
        private bool readUnderlayEntity<T>(CadEntityTemplate template, DxfMap map, string subclass = null)
1680
                where T : PdfUnderlayDefinition
1681
        {
3,420✔
1682
                CadUnderlayTemplate<T> tmp = template as CadUnderlayTemplate<T>;
3,420✔
1683

1684
                switch (this._reader.Code)
3,420✔
1685
                {
1686
                        case 340:
1687
                                tmp.DefinitionHandle = this._reader.ValueAsHandle;
216✔
1688
                                return true;
216✔
1689
                        default:
1690
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
3,204✔
1691
                }
1692
        }
3,420✔
1693

1694
        private bool readVertex(CadEntityTemplate template, DxfMap map, string subclass = null)
1695
        {
252,690✔
1696
                CadVertexTemplate tmp = template as CadVertexTemplate;
252,690✔
1697

1698
                switch (this._reader.Code)
252,690✔
1699
                {
1700
                        case 100:
1701
                                switch (this._reader.ValueAsString)
7,344!
1702
                                {
1703
                                        case DxfSubclassMarker.Vertex:
1704
                                                return true;
2,160✔
1705
                                        case DxfSubclassMarker.PolylineVertex:
UNCOV
1706
                                                tmp.SetVertexObject(new Vertex2D());
×
1707
                                                map.SubClasses.Add(DxfSubclassMarker.PolylineVertex, DxfClassMap.Create<Vertex2D>());
×
1708
                                                return true;
×
1709
                                        case DxfSubclassMarker.Polyline3dVertex:
1710
                                                tmp.SetVertexObject(new Vertex3D());
1,080✔
1711
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline3dVertex, DxfClassMap.Create<Vertex3D>());
1,080✔
1712
                                                return true;
1,080✔
1713
                                        case DxfSubclassMarker.PolyfaceMeshVertex:
1714
                                                tmp.SetVertexObject(new VertexFaceMesh());
1,080✔
1715
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMeshVertex, DxfClassMap.Create<VertexFaceMesh>());
1,080✔
1716
                                                return true;
1,080✔
1717
                                        case DxfSubclassMarker.PolyfaceMeshFace:
1718
                                                tmp.SetVertexObject(new VertexFaceRecord());
432✔
1719
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMeshFace, DxfClassMap.Create<VertexFaceRecord>());
432✔
1720
                                                return true;
432✔
1721
                                        case DxfSubclassMarker.PolygonMeshVertex:
UNCOV
1722
                                                tmp.SetVertexObject(new PolygonMeshVertex());
×
UNCOV
1723
                                                map.SubClasses.Add(DxfSubclassMarker.PolygonMeshVertex, DxfClassMap.Create<PolygonMeshVertex>());
×
UNCOV
1724
                                                return true;
×
1725
                                        default:
1726
                                                return false;
2,592✔
1727
                                }
1728
                        default:
1729
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
245,346✔
1730
                }
1731
        }
252,690✔
1732

1733
        private bool readViewport(CadEntityTemplate template, DxfMap map, string subclass = null)
1734
        {
72,724✔
1735
                CadViewportTemplate tmp = template as CadViewportTemplate;
72,724✔
1736

1737
                switch (this._reader.Code)
72,724!
1738
                {
1739
                        //Undocumented
1740
                        case 67:
1741
                        case 68:
1742
                                return true;
2,664✔
1743
                        case 69:
1744
                                tmp.ViewportId = this._reader.ValueAsShort;
1,332✔
1745
                                return true;
1,332✔
1746
                        case 331:
UNCOV
1747
                                tmp.FrozenLayerHandles.Add(this._reader.ValueAsHandle);
×
UNCOV
1748
                                return true;
×
1749
                        case 348:
1750
                                tmp.VisualStyleHandle = this._reader.ValueAsHandle;
832✔
1751
                                return true;
832✔
1752
                        default:
1753
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Viewport]);
67,896✔
1754
                }
1755
        }
72,724✔
1756

1757
        private bool readEntitySubclassMap(CadEntityTemplate template, DxfMap map, string subclass = null)
1758
        {
855,836✔
1759
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
855,836✔
1760

1761
                switch (this._reader.Code)
855,836✔
1762
                {
1763
                        default:
1764
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[mapName]);
855,836✔
1765
                }
1766
        }
855,836✔
1767

1768
        protected void readExtendedData(Dictionary<string, List<ExtendedDataRecord>> edata)
1769
        {
36,478✔
1770
                List<ExtendedDataRecord> records = new();
36,478✔
1771
                edata.Add(this._reader.ValueAsString, records);
36,478✔
1772

1773
                this._reader.ReadNext();
36,478✔
1774

1775
                while (this._reader.DxfCode >= DxfCode.ExtendedDataAsciiString)
296,896✔
1776
                {
271,933✔
1777
                        if (this._reader.DxfCode == DxfCode.ExtendedDataRegAppName)
271,933✔
1778
                        {
11,515✔
1779
                                this.readExtendedData(edata);
11,515✔
1780
                                break;
11,515✔
1781
                        }
1782

1783
                        ExtendedDataRecord record = null;
260,418✔
1784
                        double x = 0;
260,418✔
1785
                        double y = 0;
260,418✔
1786
                        double z = 0;
260,418✔
1787

1788
                        switch (this._reader.DxfCode)
260,418✔
1789
                        {
1790
                                case DxfCode.ExtendedDataAsciiString:
1791
                                case DxfCode.ExtendedDataRegAppName:
1792
                                        record = new ExtendedDataString(this._reader.ValueAsString);
24,929✔
1793
                                        break;
24,929✔
1794
                                case DxfCode.ExtendedDataControlString:
1795
                                        record = new ExtendedDataControlString(this._reader.ValueAsString == "}");
14,284✔
1796
                                        break;
14,284✔
1797
                                case DxfCode.ExtendedDataLayerName:
1798
                                        if (this._builder.Layers.TryGetValue(this._reader.ValueAsString, out Layer layer))
252✔
1799
                                        {
238✔
1800
                                                record = new ExtendedDataLayer(layer.Handle);
238✔
1801
                                        }
238✔
1802
                                        else
1803
                                        {
14✔
1804
                                                this._builder.Notify($"[XData] Could not found the linked Layer {this._reader.ValueAsString}.", NotificationType.Warning);
14✔
1805
                                        }
14✔
1806
                                        break;
252✔
1807
                                case DxfCode.ExtendedDataBinaryChunk:
1808
                                        record = new ExtendedDataBinaryChunk(this._reader.ValueAsBinaryChunk);
72✔
1809
                                        break;
72✔
1810
                                case DxfCode.ExtendedDataHandle:
1811
                                        record = new ExtendedDataHandle(this._reader.ValueAsHandle);
2,781✔
1812
                                        break;
2,781✔
1813
                                case DxfCode.ExtendedDataXCoordinate:
1814
                                        x = this._reader.ValueAsDouble;
2,873✔
1815
                                        this._reader.ReadNext();
2,873✔
1816
                                        y = this._reader.ValueAsDouble;
2,873✔
1817
                                        this._reader.ReadNext();
2,873✔
1818
                                        z = this._reader.ValueAsDouble;
2,873✔
1819

1820
                                        record = new ExtendedDataCoordinate(
2,873✔
1821
                                                new XYZ(
2,873✔
1822
                                                        x,
2,873✔
1823
                                                        y,
2,873✔
1824
                                                        z)
2,873✔
1825
                                                );
2,873✔
1826
                                        break;
2,873✔
1827
                                case DxfCode.ExtendedDataWorldXCoordinate:
1828
                                        x = this._reader.ValueAsDouble;
1,296✔
1829
                                        this._reader.ReadNext();
1,296✔
1830
                                        y = this._reader.ValueAsDouble;
1,296✔
1831
                                        this._reader.ReadNext();
1,296✔
1832
                                        z = this._reader.ValueAsDouble;
1,296✔
1833

1834
                                        record = new ExtendedDataWorldCoordinate(
1,296✔
1835
                                                new XYZ(
1,296✔
1836
                                                        x,
1,296✔
1837
                                                        y,
1,296✔
1838
                                                        z)
1,296✔
1839
                                                );
1,296✔
1840
                                        break;
1,296✔
1841
                                case DxfCode.ExtendedDataWorldXDisp:
1842
                                        x = this._reader.ValueAsDouble;
252✔
1843
                                        this._reader.ReadNext();
252✔
1844
                                        y = this._reader.ValueAsDouble;
252✔
1845
                                        this._reader.ReadNext();
252✔
1846
                                        z = this._reader.ValueAsDouble;
252✔
1847

1848
                                        record = new ExtendedDataDisplacement(
252✔
1849
                                                new XYZ(
252✔
1850
                                                        x,
252✔
1851
                                                        y,
252✔
1852
                                                        z)
252✔
1853
                                                );
252✔
1854
                                        break;
252✔
1855
                                case DxfCode.ExtendedDataWorldXDir:
1856
                                        x = this._reader.ValueAsDouble;
252✔
1857
                                        this._reader.ReadNext();
252✔
1858
                                        y = this._reader.ValueAsDouble;
252✔
1859
                                        this._reader.ReadNext();
252✔
1860
                                        z = this._reader.ValueAsDouble;
252✔
1861

1862
                                        record = new ExtendedDataDirection(
252✔
1863
                                                new XYZ(
252✔
1864
                                                        x,
252✔
1865
                                                        y,
252✔
1866
                                                        z)
252✔
1867
                                                );
252✔
1868
                                        break;
252✔
1869
                                case DxfCode.ExtendedDataReal:
1870
                                        record = new ExtendedDataReal(this._reader.ValueAsDouble);
126,481✔
1871
                                        break;
126,481✔
1872
                                case DxfCode.ExtendedDataDist:
1873
                                        record = new ExtendedDataDistance(this._reader.ValueAsDouble);
252✔
1874
                                        break;
252✔
1875
                                case DxfCode.ExtendedDataScale:
1876
                                        record = new ExtendedDataScale(this._reader.ValueAsDouble);
252✔
1877
                                        break;
252✔
1878
                                case DxfCode.ExtendedDataInteger16:
1879
                                        record = new ExtendedDataInteger16(this._reader.ValueAsShort);
73,945✔
1880
                                        break;
73,945✔
1881
                                case DxfCode.ExtendedDataInteger32:
1882
                                        record = new ExtendedDataInteger32((int)this._reader.ValueAsInt);
10,193✔
1883
                                        break;
10,193✔
1884
                                default:
1885
                                        this._builder.Notify($"Unknown code for extended data: {this._reader.DxfCode}", NotificationType.Warning);
2,304✔
1886
                                        break;
2,304✔
1887
                        }
1888

1889
                        if (record != null)
260,418✔
1890
                        {
258,100✔
1891
                                records.Add(record);
258,100✔
1892
                        }
258,100✔
1893

1894
                        this._reader.ReadNext();
260,418✔
1895
                }
260,418✔
1896
        }
36,478✔
1897

1898
        private void readPattern(HatchPattern pattern, int nlines)
1899
        {
1,296✔
1900
                //Jump 78 code
1901
                this._reader.ReadNext();
1,296✔
1902

1903
                for (int i = 0; i < nlines; i++)
196,560✔
1904
                {
96,984✔
1905
                        HatchPattern.Line line = new HatchPattern.Line();
96,984✔
1906
                        XY basePoint = new XY();
96,984✔
1907
                        XY offset = new XY();
96,984✔
1908

1909
                        bool end = false;
96,984✔
1910
                        HashSet<int> codes = new();
96,984✔
1911

1912
                        while (!end)
680,184✔
1913
                        {
678,888✔
1914
                                if (codes.Contains(this._reader.Code))
678,888✔
1915
                                {
95,688✔
1916
                                        break;
95,688✔
1917
                                }
1918
                                else
1919
                                {
583,200✔
1920
                                        codes.Add(this._reader.Code);
583,200✔
1921
                                }
583,200✔
1922

1923
                                switch (this._reader.Code)
583,200!
1924
                                {
1925
                                        case 53:
1926
                                                line.Angle = this._reader.ValueAsAngle;
96,984✔
1927
                                                break;
96,984✔
1928
                                        case 43:
1929
                                                basePoint.X = this._reader.ValueAsDouble;
96,984✔
1930
                                                break;
96,984✔
1931
                                        case 44:
1932
                                                basePoint.Y = this._reader.ValueAsDouble;
96,984✔
1933
                                                line.BasePoint = basePoint;
96,984✔
1934
                                                break;
96,984✔
1935
                                        case 45:
1936
                                                offset.X = this._reader.ValueAsDouble;
96,984✔
1937
                                                line.Offset = offset;
96,984✔
1938
                                                break;
96,984✔
1939
                                        case 46:
1940
                                                offset.Y = this._reader.ValueAsDouble;
96,984✔
1941
                                                line.Offset = offset;
96,984✔
1942
                                                break;
96,984✔
1943
                                        //Number of dash length items
1944
                                        case 79:
1945
                                                int ndash = this._reader.ValueAsInt;
96,984✔
1946
                                                for (int j = 0; j < ndash; j++)
581,040✔
1947
                                                {
193,536✔
1948
                                                        this._reader.ReadNext();
193,536✔
1949
                                                        line.DashLengths.Add(this._reader.ValueAsDouble);
193,536✔
1950
                                                }
193,536✔
1951
                                                break;
96,984✔
1952
                                        case 49:
UNCOV
1953
                                                line.DashLengths.Add(this._reader.ValueAsDouble);
×
UNCOV
1954
                                                break;
×
1955
                                        default:
1956
                                                end = true;
1,296✔
1957
                                                break;
1,296✔
1958
                                }
1959
                                this._reader.ReadNext();
583,200✔
1960
                        }
583,200✔
1961

1962
                        pattern.Lines.Add(line);
96,984✔
1963
                }
96,984✔
1964
        }
1,296✔
1965

1966
        private void readLoops(CadHatchTemplate template, int count)
1967
        {
1,728✔
1968
                if (this._reader.Code == 91)
1,728✔
1969
                        this._reader.ReadNext();
1,728✔
1970

1971
                for (int i = 0; i < count; i++)
6,912✔
1972
                {
1,728✔
1973
                        if (this._reader.Code != 92)
1,728!
UNCOV
1974
                        {
×
UNCOV
1975
                                this._builder.Notify($"Boundary path should start with code 92 but was {this._reader.Code}");
×
UNCOV
1976
                                break;
×
1977
                        }
1978

1979
                        CadHatchTemplate.CadBoundaryPathTemplate path = this.readLoop();
1,728✔
1980
                        if (path != null)
1,728✔
1981
                                template.PathTemplates.Add(path);
1,728✔
1982
                }
1,728✔
1983
        }
1,728✔
1984

1985
        private CadHatchTemplate.CadBoundaryPathTemplate readLoop()
1986
        {
1,728✔
1987
                CadHatchTemplate.CadBoundaryPathTemplate template = new CadHatchTemplate.CadBoundaryPathTemplate();
1,728✔
1988
                var flags = (BoundaryPathFlags)this._reader.ValueAsInt;
1,728✔
1989
                template.Path.Flags = flags;
1,728✔
1990

1991
                if (flags.HasFlag(BoundaryPathFlags.Polyline))
1,728✔
1992
                {
648✔
1993
                        Hatch.BoundaryPath.Polyline pl = this.readPolylineBoundary();
648✔
1994
                        template.Path.Edges.Add(pl);
648✔
1995
                }
648✔
1996
                else
1997
                {
1,080✔
1998
                        this._reader.ReadNext();
1,080✔
1999

2000
                        if (this._reader.Code != 93)
1,080!
UNCOV
2001
                        {
×
UNCOV
2002
                                this._builder.Notify($"Edge Boundary path should start with code 93 but was {this._reader.Code}");
×
UNCOV
2003
                                return null;
×
2004
                        }
2005

2006
                        int edges = this._reader.ValueAsInt;
1,080✔
2007
                        this._reader.ReadNext();
1,080✔
2008

2009
                        for (int i = 0; i < edges; i++)
10,800✔
2010
                        {
4,320✔
2011
                                var edge = this.readEdge();
4,320✔
2012
                                if (edge != null)
4,320✔
2013
                                        template.Path.Edges.Add(edge);
4,320✔
2014
                        }
4,320✔
2015
                }
1,080✔
2016

2017
                bool end = false;
1,728✔
2018
                while (!end)
6,696✔
2019
                {
4,968✔
2020
                        switch (this._reader.Code)
4,968✔
2021
                        {
2022
                                //Number of source boundary objects
2023
                                case 97:
2024
                                        break;
1,728✔
2025
                                case 330:
2026
                                        template.Handles.Add(this._reader.ValueAsHandle);
1,512✔
2027
                                        break;
1,512✔
2028
                                default:
2029
                                        end = true;
1,728✔
2030
                                        continue;
1,728✔
2031
                        }
2032

2033
                        this._reader.ReadNext();
3,240✔
2034
                }
3,240✔
2035

2036
                return template;
1,728✔
2037
        }
1,728✔
2038

2039
        private Hatch.BoundaryPath.Polyline readPolylineBoundary()
2040
        {
648✔
2041
                Hatch.BoundaryPath.Polyline boundary = new Hatch.BoundaryPath.Polyline();
648✔
2042

2043
                this._reader.ReadNext();
648✔
2044

2045
                if (this._reader.Code != 72)
648!
UNCOV
2046
                {
×
UNCOV
2047
                        this._builder.Notify($"Polyline Boundary path should start with code 72 but was {this._reader.Code}");
×
UNCOV
2048
                        return null;
×
2049
                }
2050

2051
                bool end = false;
648✔
2052
                bool hasBulge = false;
648✔
2053
                while (!end)
3,240✔
2054
                {
2,592✔
2055
                        switch (this._reader.Code)
2,592✔
2056
                        {
2057
                                case 72:
2058
                                        hasBulge = this._reader.ValueAsBool;
648✔
2059
                                        break;
648✔
2060
                                case 73:
2061
                                        boundary.IsClosed = this._reader.ValueAsBool;
648✔
2062
                                        break;
648✔
2063
                                case 93:
2064
                                        int nvertices = this._reader.ValueAsInt;
648✔
2065
                                        this._reader.ReadNext();
648✔
2066

2067
                                        for (int i = 0; i < nvertices; i++)
6,480✔
2068
                                        {
2,592✔
2069
                                                double bulge = 0.0;
2,592✔
2070

2071
                                                //10
2072
                                                double x = this._reader.ValueAsDouble;
2,592✔
2073
                                                this._reader.ReadNext();
2,592✔
2074
                                                //20
2075
                                                double y = this._reader.ValueAsDouble;
2,592✔
2076
                                                this._reader.ReadNext();
2,592✔
2077

2078
                                                if (hasBulge)
2,592!
UNCOV
2079
                                                {
×
2080
                                                        //42
UNCOV
2081
                                                        bulge = this._reader.ValueAsDouble;
×
UNCOV
2082
                                                        this._reader.ReadNext();
×
UNCOV
2083
                                                }
×
2084

2085
                                                boundary.Vertices.Add(new XYZ(x, y, bulge));
2,592✔
2086
                                        }
2,592✔
2087
                                        continue;
648✔
2088
                                default:
2089
                                        end = true;
648✔
2090
                                        continue;
648✔
2091
                        }
2092

2093
                        this._reader.ReadNext();
1,296✔
2094
                }
1,296✔
2095

2096
                return boundary;
648✔
2097
        }
648✔
2098

2099
        private Hatch.BoundaryPath.Edge readEdge()
2100
        {
4,320✔
2101
                if (this._reader.Code != 72)
4,320!
UNCOV
2102
                {
×
UNCOV
2103
                        this._builder.Notify($"Edge Boundary path should define the type with code 72 but was {this._reader.Code}");
×
UNCOV
2104
                        return null;
×
2105
                }
2106

2107
                Hatch.BoundaryPath.EdgeType type = (Hatch.BoundaryPath.EdgeType)this._reader.ValueAsInt;
4,320✔
2108
                this._reader.ReadNext();
4,320✔
2109

2110
                switch (type)
4,320!
2111
                {
2112
                        case Hatch.BoundaryPath.EdgeType.Line:
2113
                                Hatch.BoundaryPath.Line line = new Hatch.BoundaryPath.Line();
4,320✔
2114
                                while (true)
21,600✔
2115
                                {
21,600✔
2116
                                        switch (this._reader.Code)
21,600✔
2117
                                        {
2118
                                                case 10:
2119
                                                        line.Start = new XY(this._reader.ValueAsDouble, line.Start.Y);
4,320✔
2120
                                                        break;
4,320✔
2121
                                                case 20:
2122
                                                        line.Start = new XY(line.Start.X, this._reader.ValueAsDouble);
4,320✔
2123
                                                        break;
4,320✔
2124
                                                case 11:
2125
                                                        line.End = new XY(this._reader.ValueAsDouble, line.End.Y);
4,320✔
2126
                                                        break;
4,320✔
2127
                                                case 21:
2128
                                                        line.End = new XY(line.End.X, this._reader.ValueAsDouble);
4,320✔
2129
                                                        break;
4,320✔
2130
                                                default:
2131
                                                        return line;
4,320✔
2132
                                        }
2133

2134
                                        this._reader.ReadNext();
17,280✔
2135
                                }
17,280✔
2136
                        case Hatch.BoundaryPath.EdgeType.CircularArc:
2137
                                Hatch.BoundaryPath.Arc arc = new Hatch.BoundaryPath.Arc();
×
2138
                                while (true)
×
UNCOV
2139
                                {
×
2140
                                        switch (this._reader.Code)
×
2141
                                        {
2142
                                                case 10:
2143
                                                        arc.Center = new XY(this._reader.ValueAsDouble, arc.Center.Y);
×
2144
                                                        break;
×
2145
                                                case 20:
2146
                                                        arc.Center = new XY(arc.Center.X, this._reader.ValueAsDouble);
×
UNCOV
2147
                                                        break;
×
2148
                                                case 40:
2149
                                                        arc.Radius = this._reader.ValueAsDouble;
×
2150
                                                        break;
×
2151
                                                case 50:
2152
                                                        arc.StartAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
2153
                                                        break;
×
2154
                                                case 51:
2155
                                                        arc.EndAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
UNCOV
2156
                                                        break;
×
2157
                                                case 73:
2158
                                                        arc.CounterClockWise = this._reader.ValueAsBool;
×
2159
                                                        break;
×
2160
                                                default:
2161
                                                        return arc;
×
2162
                                        }
2163

2164
                                        this._reader.ReadNext();
×
2165
                                }
×
2166
                        case Hatch.BoundaryPath.EdgeType.EllipticArc:
2167
                                Hatch.BoundaryPath.Ellipse ellipse = new Hatch.BoundaryPath.Ellipse();
×
2168
                                while (true)
×
UNCOV
2169
                                {
×
2170
                                        switch (this._reader.Code)
×
2171
                                        {
2172
                                                case 10:
2173
                                                        ellipse.Center = new XY(this._reader.ValueAsDouble, ellipse.Center.Y);
×
2174
                                                        break;
×
2175
                                                case 20:
2176
                                                        ellipse.Center = new XY(ellipse.Center.X, this._reader.ValueAsDouble);
×
2177
                                                        break;
×
2178
                                                case 11:
2179
                                                        ellipse.MajorAxisEndPoint = new XY(this._reader.ValueAsDouble, ellipse.MajorAxisEndPoint.Y);
×
2180
                                                        break;
×
2181
                                                case 21:
2182
                                                        ellipse.MajorAxisEndPoint = new XY(ellipse.MajorAxisEndPoint.X, this._reader.ValueAsDouble);
×
UNCOV
2183
                                                        break;
×
2184
                                                case 40:
2185
                                                        ellipse.RadiusRatio = this._reader.ValueAsDouble;
×
2186
                                                        break;
×
2187
                                                case 50:
2188
                                                        ellipse.StartAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
2189
                                                        break;
×
2190
                                                case 51:
2191
                                                        ellipse.EndAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
UNCOV
2192
                                                        break;
×
2193
                                                case 73:
2194
                                                        ellipse.CounterClockWise = this._reader.ValueAsBool;
×
UNCOV
2195
                                                        break;
×
2196
                                                default:
2197
                                                        return ellipse;
×
2198
                                        }
2199

UNCOV
2200
                                        this._reader.ReadNext();
×
2201
                                }
×
2202
                        case Hatch.BoundaryPath.EdgeType.Spline:
UNCOV
2203
                                Hatch.BoundaryPath.Spline spline = new Hatch.BoundaryPath.Spline();
×
2204
                                int nKnots = 0;
×
2205
                                int nCtrlPoints = 0;
×
2206
                                int nFitPoints = 0;
×
2207

2208
                                XYZ controlPoint = new XYZ();
×
2209
                                XY fitPoint = new XY();
×
2210

2211
                                while (true)
×
2212
                                {
×
2213
                                        switch (this._reader.Code)
×
2214
                                        {
2215
                                                case 10:
2216
                                                        controlPoint = new XYZ(this._reader.ValueAsDouble, 0, 1);
×
2217
                                                        break;
×
2218
                                                case 20:
2219
                                                        controlPoint = new XYZ(controlPoint.X, this._reader.ValueAsDouble, controlPoint.Z);
×
2220
                                                        spline.ControlPoints.Add(controlPoint);
×
UNCOV
2221
                                                        break;
×
2222
                                                case 11:
2223
                                                        fitPoint = new XY(this._reader.ValueAsDouble, 0);
×
UNCOV
2224
                                                        break;
×
2225
                                                case 21:
2226
                                                        fitPoint = new XY(fitPoint.X, this._reader.ValueAsDouble);
×
UNCOV
2227
                                                        spline.FitPoints.Add(fitPoint);
×
2228
                                                        break;
×
2229
                                                case 42:
UNCOV
2230
                                                        var last = spline.ControlPoints[spline.ControlPoints.Count - 1];
×
2231
                                                        spline.ControlPoints[spline.ControlPoints.Count - 1] = new XYZ(last.X, last.Y, this._reader.ValueAsDouble);
×
2232
                                                        break;
×
2233
                                                case 12:
2234
                                                        spline.StartTangent = new XY(this._reader.ValueAsDouble, spline.StartTangent.Y);
×
2235
                                                        break;
×
2236
                                                case 22:
2237
                                                        spline.StartTangent = new XY(spline.StartTangent.X, this._reader.ValueAsDouble);
×
2238
                                                        break;
×
2239
                                                case 13:
2240
                                                        spline.EndTangent = new XY(this._reader.ValueAsDouble, spline.EndTangent.Y);
×
2241
                                                        break;
×
2242
                                                case 23:
2243
                                                        spline.EndTangent = new XY(spline.EndTangent.X, this._reader.ValueAsDouble);
×
2244
                                                        break;
×
2245
                                                case 94:
2246
                                                        spline.Degree = this._reader.ValueAsInt;
×
2247
                                                        break;
×
2248
                                                case 73:
2249
                                                        spline.IsRational = this._reader.ValueAsBool;
×
2250
                                                        break;
×
2251
                                                case 74:
2252
                                                        spline.IsPeriodic = this._reader.ValueAsBool;
×
UNCOV
2253
                                                        break;
×
2254
                                                case 95:
2255
                                                        nKnots = this._reader.ValueAsInt;
×
2256
                                                        break;
×
2257
                                                case 96:
UNCOV
2258
                                                        nCtrlPoints = this._reader.ValueAsInt;
×
2259
                                                        break;
×
2260
                                                case 97:
UNCOV
2261
                                                        nFitPoints = this._reader.ValueAsInt;
×
UNCOV
2262
                                                        break;
×
2263
                                                case 40:
UNCOV
2264
                                                        spline.Knots.Add(this._reader.ValueAsDouble);
×
UNCOV
2265
                                                        break;
×
2266
                                                default:
UNCOV
2267
                                                        return spline;
×
2268
                                        }
2269

UNCOV
2270
                                        this._reader.ReadNext();
×
UNCOV
2271
                                }
×
2272
                }
2273

UNCOV
2274
                return null;
×
2275
        }
4,320✔
2276

2277
        private void readDefinedGroups(CadTemplate template)
2278
        {
72,806✔
2279
                this.readDefinedGroups(out ulong? xdict, out HashSet<ulong> reactorsHandles);
72,806✔
2280

2281
                if (xdict.HasValue)
72,806✔
2282
                {
10,487✔
2283
                        template.XDictHandle = xdict;
10,487✔
2284
                }
10,487✔
2285
                template.ReactorsHandles.UnionWith(reactorsHandles);
72,806✔
2286
        }
72,806✔
2287

2288
        private void readDefinedGroups(out ulong? xdictHandle, out HashSet<ulong> reactors)
2289
        {
73,029✔
2290
                xdictHandle = null;
73,029✔
2291
                reactors = new HashSet<ulong>();
73,029✔
2292

2293
                switch (this._reader.ValueAsString)
73,029✔
2294
                {
2295
                        case DxfFileToken.DictionaryToken:
2296
                                this._reader.ReadNext();
10,710✔
2297
                                xdictHandle = this._reader.ValueAsHandle;
10,710✔
2298
                                this._reader.ReadNext();
10,710✔
2299
                                Debug.Assert(this._reader.DxfCode == DxfCode.ControlString);
10,710✔
2300
                                return;
10,710✔
2301
                        case DxfFileToken.ReactorsToken:
2302
                                reactors = this.readReactors();
60,142✔
2303
                                break;
60,142✔
2304
                        case DxfFileToken.BlkRefToken:
2305
                        default:
2306
                                do
2307
                                {
5,650✔
2308
                                        this._reader.ReadNext();
5,650✔
2309
                                }
5,650✔
2310
                                while (this._reader.DxfCode != DxfCode.ControlString);
5,650✔
2311
                                return;
2,177✔
2312
                }
2313
        }
73,029✔
2314

2315
        private HashSet<ulong> readReactors()
2316
        {
60,142✔
2317
                HashSet<ulong> reactors = new();
60,142✔
2318

2319
                this._reader.ReadNext();
60,142✔
2320

2321
                while (this._reader.DxfCode != DxfCode.ControlString)
127,184✔
2322
                {
67,042✔
2323
                        reactors.Add(this._reader.ValueAsHandle);
67,042✔
2324

2325
                        this._reader.ReadNext();
67,042✔
2326
                }
67,042✔
2327

2328
                return reactors;
60,142✔
2329
        }
60,142✔
2330

2331
        protected bool tryAssignCurrentValue(object cadObject, DxfMap map)
2332
        {
11,175✔
2333
                if (string.IsNullOrEmpty(this.currentSubclass))
11,175✔
2334
                {
1,242✔
2335
                        return false;
1,242✔
2336
                }
2337

2338
                if (map.SubClasses.TryGetValue(this.currentSubclass, out var subClass))
9,933!
2339
                {
9,933✔
2340
                        return this.tryAssignCurrentValue(cadObject, subClass);
9,933✔
2341
                }
2342
                else
UNCOV
2343
                {
×
UNCOV
2344
                        return false;
×
2345
                }
2346
        }
11,175✔
2347

2348
        protected bool tryAssignCurrentValue(object cadObject, DxfClassMap map)
2349
        {
4,482,415✔
2350
                try
2351
                {
4,482,415✔
2352
                        //Use this method only if the value is not a link between objects
2353
                        if (map.DxfProperties.TryGetValue(this._reader.Code, out DxfProperty dxfProperty))
4,482,415✔
2354
                        {
2,353,975✔
2355
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Count))
2,353,975✔
2356
                                {
13,738✔
2357
                                        return true;
13,738✔
2358
                                }
2359

2360
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Handle)
2,340,237✔
2361
                                        || dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Name))
2,340,237✔
2362
                                {
19,741✔
2363
                                        return false;
19,741✔
2364
                                }
2365

2366
                                object value = this._reader.Value;
2,320,496✔
2367

2368
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.IsAngle))
2,320,496✔
2369
                                {
26,368✔
2370
                                        value = MathHelper.DegToRad((double)value);
26,368✔
2371
                                }
26,368✔
2372

2373
                                dxfProperty.SetValue(this._reader.Code, cadObject, value);
2,320,496✔
2374

2375
                                return true;
2,320,496✔
2376
                        }
2377
                }
2,128,440✔
UNCOV
2378
                catch (Exception ex)
×
UNCOV
2379
                {
×
UNCOV
2380
                        if (!this._builder.Configuration.Failsafe)
×
UNCOV
2381
                        {
×
UNCOV
2382
                                throw ex;
×
2383
                        }
2384
                        else
UNCOV
2385
                        {
×
UNCOV
2386
                                this._builder.Notify("An error occurred while assigning a property using mapper", NotificationType.Error, ex);
×
UNCOV
2387
                        }
×
UNCOV
2388
                }
×
2389

2390
                return false;
2,128,440✔
2391
        }
4,482,415✔
2392
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc