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

DomCR / ACadSharp / 26559234176

28 May 2026 06:43AM UTC coverage: 77.005% (+0.005%) from 77.0%
26559234176

Pull #1100

github

web-flow
Merge 174276351 into 3d543055b
Pull Request #1100: issue-1099 dxf hatch ellipse

8615 of 12143 branches covered (70.95%)

Branch coverage included in aggregate %.

1105 of 1337 new or added lines in 1 file covered. (82.65%)

22 existing lines in 1 file now uncovered.

31119 of 39456 relevant lines covered (78.87%)

157400.4 hits per line

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

80.66
/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 System;
8
using System.Collections.Generic;
9
using System.Diagnostics;
10
using System.Linq;
11
using static ACadSharp.IO.Templates.CadMLeaderAnnotContextTemplate;
12
using static ACadSharp.IO.Templates.CadTableEntityTemplate;
13

14
namespace ACadSharp.IO.DXF.DxfStreamReader;
15

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

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

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

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

33
        public abstract void Read();
34

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

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

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

79
                        this._reader.ReadNext();
7,088✔
80
                }
7,088✔
81
        }
2,385✔
82

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

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

115
        protected void readCommonCodes(CadTemplate template, out bool isExtendedData, DxfMap map = null)
116
        {
837,558✔
117
                isExtendedData = false;
837,558✔
118

119
                switch (this._reader.Code)
837,558✔
120
                {
121
                        //Handle
122
                        case 5:
123
                                template.CadObject.Handle = this._reader.ValueAsHandle;
315,646✔
124
                                break;
315,646✔
125
                        //Check with mapper
126
                        case 100:
127
                                this.currentSubclass = this._reader.ValueAsString;
219,195✔
128
                                if (map != null && !map.SubClasses.ContainsKey(this._reader.ValueAsString))
219,195!
129
                                {
1,068✔
130
                                        this._builder.Notify($"[{template.CadObject.ObjectName}] Unidentified subclass {this._reader.ValueAsString}", NotificationType.Warning);
1,068✔
131
                                }
1,068✔
132
                                break;
219,195✔
133
                        //Start of application - defined group
134
                        case 102:
135
                                this.readDefinedGroups(template);
71,780✔
136
                                break;
71,780✔
137
                        //Soft - pointer ID / handle to owner BLOCK_RECORD object
138
                        case 330:
139
                                template.OwnerHandle = this._reader.ValueAsHandle;
178,356✔
140
                                break;
178,356✔
141
                        case 1001:
142
                                isExtendedData = true;
24,551✔
143
                                this.readExtendedData(template.EDataTemplateByAppName);
24,551✔
144
                                break;
24,551✔
145
                        default:
146
                                this._builder.Notify($"[{this.currentSubclass}] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
28,030✔
147
                                break;
28,030✔
148
                }
149
        }
837,558✔
150

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

NEW
248
                                this._reader.ReadNext();
×
249

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

NEW
259
                                        this._reader.ReadNext();
×
NEW
260
                                }
×
NEW
261
                                while (this._reader.DxfCode != DxfCode.Start);
×
262

NEW
263
                                return unknownEntityTemplate;
×
264
                }
265
        }
154,947✔
266

267
        protected CadEntityTemplate readEntityCodes<T>(CadEntityTemplate template, ReadEntityDelegate<T> readEntity)
268
                where T : Entity
269
        {
206,741✔
270
                this._reader.ReadNext();
206,741✔
271

272
                DxfMap map = DxfMap.Create<T>();
206,741✔
273

274
                while (this._reader.DxfCode != DxfCode.Start)
2,799,473✔
275
                {
2,592,732✔
276
                        if (!readEntity(template, map))
2,592,732✔
277
                        {
907,630✔
278
                                this.readCommonEntityCodes(template, out bool isExtendedData, map);
907,630✔
279
                                if (isExtendedData)
907,630✔
280
                                        continue;
14,476✔
281
                        }
893,154✔
282

283
                        if (this.lockPointer)
2,578,256✔
284
                        {
3,168✔
285
                                this.lockPointer = false;
3,168✔
286
                                continue;
3,168✔
287
                        }
288

289
                        if (this._reader.DxfCode != DxfCode.Start)
2,575,088✔
290
                                this._reader.ReadNext();
2,574,586✔
291
                }
2,575,088✔
292

293
                return template;
206,741✔
294
        }
206,741✔
295

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

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

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

356
        private bool readCircle(CadEntityTemplate template, DxfMap map, string subclass = null)
357
        {
38,105✔
358
                Circle circle = template.CadObject as Circle;
38,105✔
359

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

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

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

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

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

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

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

591
        protected CadValueTemplate readCadValue(CadValue value)
592
        {
9,848✔
593
                this._reader.ReadNext();
9,848✔
594

595
                CadValueTemplate template = new(value);
9,848✔
596
                var map = DxfClassMap.Create(value.GetType(), "CadValue");
9,848✔
597

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

651
                        this._reader.ReadNext();
55,536✔
652
                }
55,536✔
653

654
                return template;
9,848✔
655
        }
9,848✔
656

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

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

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

736
                        this._reader.ReadNext();
2,592✔
737
                }
2,592✔
738
        }
144✔
739

740
        private bool readTolerance(CadEntityTemplate template, DxfMap map, string subclass = null)
741
        {
6,480✔
742
                CadToleranceTemplate tmp = template as CadToleranceTemplate;
6,480✔
743

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

754
        private bool readDimension(CadEntityTemplate template, DxfMap map, string subclass = null)
755
        {
72,504✔
756
                CadDimensionTemplate tmp = template as CadDimensionTemplate;
72,504✔
757

758
                switch (this._reader.Code)
72,504✔
759
                {
760
                        case 2:
761
                                tmp.BlockName = this._reader.ValueAsString;
2,772✔
762
                                return true;
2,772✔
763
                        case 3:
764
                                tmp.StyleName = this._reader.ValueAsString;
2,376✔
765
                                return true;
2,376✔
766
                        case 50:
767
                                var dim = new DimensionLinear();
252✔
768
                                tmp.SetDimensionObject(dim);
252✔
769
                                dim.Rotation = this._reader.ValueAsAngle;
252✔
770
                                if (!map.SubClasses.ContainsKey(DxfSubclassMarker.LinearDimension))
252✔
771
                                {
216✔
772
                                        map.SubClasses.Add(DxfSubclassMarker.LinearDimension, DxfClassMap.Create<DimensionLinear>());
216✔
773
                                }
216✔
774
                                return true;
252✔
775
                        case 70:
776
                                //Flags do not have set
777
                                tmp.SetDimensionFlags((DimensionType)this._reader.ValueAsShort);
2,772✔
778

779
                                if (tmp.CadObject is CadDimensionTemplate.DimensionPlaceholder placeholder && this._builder.Version < ACadVersion.AC1012)
2,772!
780
                                {
396✔
781
                                        switch (placeholder.Flags)
396!
782
                                        {
783
                                                case DimensionType.Linear:
784
                                                        tmp.SetDimensionObject(new DimensionLinear());
108✔
785
                                                        map.SubClasses.Add(DxfSubclassMarker.AlignedDimension, DxfClassMap.Create<DimensionAligned>());
108✔
786
                                                        map.SubClasses.Add(DxfSubclassMarker.LinearDimension, DxfClassMap.Create<DimensionLinear>());
108✔
787
                                                        break;
108✔
788
                                                case DimensionType.Aligned:
789
                                                        tmp.SetDimensionObject(new DimensionAligned());
72✔
790
                                                        map.SubClasses.Add(DxfSubclassMarker.AlignedDimension, DxfClassMap.Create<DimensionAligned>());
72✔
791
                                                        break;
72✔
792
                                                case DimensionType.Angular:
793
                                                        tmp.SetDimensionObject(new DimensionAngular2Line());
36✔
794
                                                        map.SubClasses.Add(DxfSubclassMarker.Angular2LineDimension, DxfClassMap.Create<DimensionAngular2Line>());
36✔
795
                                                        break;
36✔
796
                                                case DimensionType.Diameter:
NEW
797
                                                        tmp.SetDimensionObject(new DimensionDiameter());
×
NEW
798
                                                        map.SubClasses.Add(DxfSubclassMarker.DiametricDimension, DxfClassMap.Create<DimensionDiameter>());
×
NEW
799
                                                        break;
×
800
                                                case DimensionType.Radius:
801
                                                        tmp.SetDimensionObject(new DimensionRadius());
36✔
802
                                                        map.SubClasses.Add(DxfSubclassMarker.RadialDimension, DxfClassMap.Create<DimensionRadius>());
36✔
803
                                                        break;
36✔
804
                                                case DimensionType.Angular3Point:
805
                                                        tmp.SetDimensionObject(new DimensionAngular3Pt());
36✔
806
                                                        map.SubClasses.Add(DxfSubclassMarker.Angular3PointDimension, DxfClassMap.Create<DimensionAngular3Pt>());
36✔
807
                                                        break;
36✔
808
                                                case DimensionType.Ordinate:
809
                                                case DimensionType.OrdinateTypeX:
810
                                                case DimensionType.Ordinate | DimensionType.OrdinateTypeX:
811
                                                        tmp.SetDimensionObject(new DimensionOrdinate());
72✔
812
                                                        map.SubClasses.Add(DxfSubclassMarker.OrdinateDimension, DxfClassMap.Create<DimensionOrdinate>());
72✔
813
                                                        break;
72✔
814
                                                case DimensionType.BlockReference:
815
                                                case DimensionType.TextUserDefinedLocation:
816
                                                default:
817
                                                        break;
36✔
818
                                        }
819
                                }
396✔
820
                                return true;
2,772✔
821
                        //Measurement - read only
822
                        case 42:
823
                                return true;
2,376✔
824
                        //Undocumented codes
825
                        case 73:
826
                        case 74:
827
                        case 75:
828
                        case 90:
829
                        case 361:
830
                                return true;
4,752✔
831
                        case 100:
832
                                switch (this._reader.ValueAsString)
7,776✔
833
                                {
834
                                        case DxfSubclassMarker.Dimension:
835
                                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Dimension]);
2,376✔
836
                                        case DxfSubclassMarker.AlignedDimension:
837
                                                tmp.SetDimensionObject(new DimensionAligned());
1,080✔
838
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionAligned>());
1,080✔
839
                                                return true;
1,080✔
840
                                        case DxfSubclassMarker.DiametricDimension:
841
                                                tmp.SetDimensionObject(new DimensionDiameter());
216✔
842
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionDiameter>());
216✔
843
                                                return true;
216✔
844
                                        case DxfSubclassMarker.Angular2LineDimension:
845
                                                tmp.SetDimensionObject(new DimensionAngular2Line());
216✔
846
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionAngular2Line>());
216✔
847
                                                return true;
216✔
848
                                        case DxfSubclassMarker.Angular3PointDimension:
849
                                                tmp.SetDimensionObject(new DimensionAngular3Pt());
216✔
850
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionAngular3Pt>());
216✔
851
                                                return true;
216✔
852
                                        case DxfSubclassMarker.RadialDimension:
853
                                                tmp.SetDimensionObject(new DimensionRadius());
216✔
854
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionRadius>());
216✔
855
                                                return true;
216✔
856
                                        case DxfSubclassMarker.OrdinateDimension:
857
                                                tmp.SetDimensionObject(new DimensionOrdinate());
432✔
858
                                                map.SubClasses.Add(this._reader.ValueAsString, DxfClassMap.Create<DimensionOrdinate>());
432✔
859
                                                return true;
432✔
860
                                        case DxfSubclassMarker.LinearDimension:
861
                                                return true;
648✔
862
                                        default:
863
                                                return false;
2,376✔
864
                                }
865
                        default:
866
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
49,428✔
867
                }
868
        }
72,504✔
869

870
        protected bool readHatch(CadEntityTemplate template, DxfMap map, string subclass = null)
871
        {
46,224✔
872
                CadHatchTemplate tmp = template as CadHatchTemplate;
46,224✔
873
                Hatch hatch = tmp.CadObject;
46,224✔
874

875
                XY seedPoint = new XY();
46,224✔
876

877
                switch (this._reader.Code)
46,224!
878
                {
879
                        case 2:
880
                                hatch.Pattern.Name = this._reader.ValueAsString;
1,728✔
881
                                return true;
1,728✔
882
                        case 10:
883
                                seedPoint.X = this._reader.ValueAsDouble;
3,456✔
884
                                hatch.SeedPoints.Add(seedPoint);
3,456✔
885
                                return true;
3,456✔
886
                        case 20:
887
                                seedPoint = hatch.SeedPoints.LastOrDefault();
3,456✔
888
                                seedPoint.Y = this._reader.ValueAsDouble;
3,456✔
889
                                hatch.SeedPoints[hatch.SeedPoints.Count - 1] = seedPoint;
3,456✔
890
                                return true;
3,456✔
891
                        case 30:
892
                                hatch.Elevation = this._reader.ValueAsDouble;
1,728✔
893
                                return true;
1,728✔
894
                        case 53:
NEW
895
                                hatch.PatternAngle = this._reader.ValueAsAngle;
×
NEW
896
                                return true;
×
897
                        //TODO: Check hatch undocumented codes
898
                        case 90:
NEW
899
                                return true;
×
900
                        //Information about the hatch pattern
901
                        case 75:
902
                                return true;
1,728✔
903
                        //Number of pattern definition lines
904
                        case 78:
905
                                this.readPattern(hatch.Pattern, this._reader.ValueAsInt);
1,296✔
906
                                this.lockPointer = true;
1,296✔
907
                                return true;
1,296✔
908
                        //Number of boundary paths (loops)
909
                        case 91:
910
                                this.readLoops(tmp, this._reader.ValueAsInt);
1,728✔
911
                                this.lockPointer = true;
1,728✔
912
                                return true;
1,728✔
913
                        //Number of seed points
914
                        case 98:
915
                                return true;
1,080✔
916
                        case 450:
917
                                hatch.GradientColor.Enabled = this._reader.ValueAsBool;
360✔
918
                                return true;
360✔
919
                        case 451:
920
                                hatch.GradientColor.Reserved = this._reader.ValueAsInt;
360✔
921
                                return true;
360✔
922
                        case 452:
923
                                hatch.GradientColor.IsSingleColorGradient = this._reader.ValueAsBool;
360✔
924
                                return true;
360✔
925
                        case 453:
926
                                //Number of colors
927
                                return true;
360✔
928
                        case 460:
929
                                hatch.GradientColor.Angle = this._reader.ValueAsDouble;
360✔
930
                                return true;
360✔
931
                        case 461:
932
                                hatch.GradientColor.Shift = this._reader.ValueAsDouble;
360✔
933
                                return true;
360✔
934
                        case 462:
935
                                hatch.GradientColor.ColorTint = this._reader.ValueAsDouble;
360✔
936
                                return true;
360✔
937
                        case 463:
938
                                GradientColor gradient = new GradientColor();
720✔
939
                                gradient.Value = this._reader.ValueAsDouble;
720✔
940
                                hatch.GradientColor.Colors.Add(gradient);
720✔
941
                                return true;
720✔
942
                        case 63:
943
                                GradientColor colorByIndex = hatch.GradientColor.Colors.LastOrDefault();
720✔
944
                                if (colorByIndex != null)
720✔
945
                                {
720✔
946
                                        colorByIndex.Color = new Color((short)this._reader.ValueAsUShort);
720✔
947
                                }
720✔
948
                                return true;
720✔
949
                        case 421:
950
                                GradientColor colorByRgb = hatch.GradientColor.Colors.LastOrDefault();
720✔
951
                                if (colorByRgb != null)
720✔
952
                                {
720✔
953
                                        //TODO: Hatch assign color by true color
954
                                        //TODO: Is always duplicated by 63, is it needed??
955
                                        //colorByRgb.Color = new Color(this._reader.LastValueAsShort);
956
                                }
720✔
957
                                return true;
720✔
958
                        case 470:
959
                                hatch.GradientColor.Name = this._reader.ValueAsString;
360✔
960
                                return true;
360✔
961
                        default:
962
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[template.CadObject.SubclassMarker]);
24,984✔
963
                }
964
        }
46,224✔
965

966
        private bool readInsert(CadEntityTemplate template, DxfMap map, string subclass = null)
967
        {
62,582✔
968
                CadInsertTemplate tmp = template as CadInsertTemplate;
62,582✔
969

970
                switch (this._reader.Code)
62,582✔
971
                {
972
                        case 2:
973
                                tmp.BlockName = this._reader.ValueAsString;
5,851✔
974
                                return true;
5,851✔
975
                        case 100:
976
                                //AcDbEntity
977
                                //AcDbBlockReference
978
                                //AcDbMInsertBlock
979
                                return true;
5,878✔
980
                        case 66:
981
                                return true;
504✔
982
                        default:
983
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Insert]);
50,349✔
984
                }
985
        }
62,582✔
986

987
        private CadEntityTemplate readPolyline()
988
        {
11,092✔
989
                if (this._builder.Version == ACadVersion.Unknown
11,092!
990
                        || this._builder.Version == ACadVersion.AC1009)
11,092✔
991
                {
10,660✔
992
                        return this.readLegacyPolyline();
10,660✔
993
                }
994

995
                CadPolyLineTemplate template = null;
432✔
996
                template = new CadPolyLineTemplate();
432✔
997
                this.readEntityCodes<Entity>(template, this.readPolyline);
432✔
998

999
                if (template.CadObject is CadPolyLineTemplate.PolyLinePlaceholder)
432!
NEW
1000
                {
×
NEW
1001
                        this._builder.Notify($"[{DxfFileToken.EntityPolyline}] Subclass not found, entity discarded", NotificationType.Warning);
×
NEW
1002
                        return null;
×
1003
                }
1004

1005
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EntityVertex)
3,024!
1006
                {
2,592✔
1007
                        var vertexTemplate = this.readEntityCodes<Entity>(new CadVertexTemplate(), this.readVertex);
2,592✔
1008

1009
                        if (vertexTemplate.OwnerHandle == null)
2,592!
NEW
1010
                        {
×
NEW
1011
                                vertexTemplate.OwnerHandle = template.CadObject.Handle;
×
UNCOV
1012
                        }
×
1013

1014
                        template.OwnedObjectsHandlers.Add(vertexTemplate.CadObject.Handle);
2,592✔
1015
                        _builder.AddTemplate(vertexTemplate);
2,592✔
1016
                }
2,592✔
1017

1018
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EndSequence)
864!
1019
                {
432✔
1020
                        var seqend = new Seqend();
432✔
1021
                        var seqendTemplate = new CadEntityTemplate<Seqend>(seqend);
432✔
1022
                        this.readEntityCodes<Seqend>(seqendTemplate, this.readEntitySubclassMap);
432✔
1023

1024
                        if (seqendTemplate.OwnerHandle == null)
432!
UNCOV
1025
                        {
×
NEW
1026
                                seqendTemplate.OwnerHandle = template.CadObject.Handle;
×
UNCOV
1027
                        }
×
1028

1029
                        template.OwnedObjectsHandlers.Add(seqendTemplate.CadObject.Handle);
432✔
1030
                        _builder.AddTemplate(seqendTemplate);
432✔
1031
                }
432✔
1032

1033
                return template;
432✔
1034
        }
11,092✔
1035

1036
        private CadEntityTemplate readLegacyPolyline()
1037
        {
10,660✔
1038
                var polyline = new Polyline2D();
10,660✔
1039
                CadPolyLineTemplate template = new CadPolyLineTemplate(polyline);
10,660✔
1040
                this.readEntityCodes<Polyline2D>(template, this.readPolyline);
10,660✔
1041

1042
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EntityVertex)
48,700!
1043
                {
38,040✔
1044
                        Vertex2D v = new Vertex2D();
38,040✔
1045
                        CadVertexTemplate vertexTemplate = new CadVertexTemplate(v);
38,040✔
1046
                        this.readEntityCodes<Vertex2D>(vertexTemplate, this.readVertex);
38,040✔
1047

1048
                        if (vertexTemplate.Vertex.Handle == 0)
38,040!
UNCOV
1049
                        {
×
NEW
1050
                                polyline.Vertices.Add(v);
×
NEW
1051
                        }
×
1052
                        else
1053
                        {
38,040✔
1054
                                template.OwnedObjectsHandlers.Add(vertexTemplate.Vertex.Handle);
38,040✔
1055
                                this._builder.AddTemplate(vertexTemplate);
38,040✔
1056
                        }
38,040✔
1057
                }
38,040✔
1058

1059
                while (this._reader.Code == 0 && this._reader.ValueAsString == DxfFileToken.EndSequence)
21,320!
1060
                {
10,660✔
1061
                        var seqend = new Seqend();
10,660✔
1062
                        var seqendTemplate = new CadEntityTemplate<Seqend>(seqend);
10,660✔
1063
                        this.readEntityCodes<Seqend>(seqendTemplate, this.readEntitySubclassMap);
10,660✔
1064

1065
                        polyline.Vertices.Seqend = seqend;
10,660✔
1066
                }
10,660✔
1067

1068
                return template;
10,660✔
1069
        }
10,660✔
1070

1071
        private bool readPolyline(CadEntityTemplate template, DxfMap map, string subclass = null)
1072
        {
79,656✔
1073
                CadPolyLineTemplate tmp = template as CadPolyLineTemplate;
79,656✔
1074

1075
                switch (this._reader.Code)
79,656✔
1076
                {
1077
                        //DXF: always 0
1078
                        //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)
1079
                        case 10:
1080
                        case 20:
1081
                        //Obsolete; formerly an “entities follow flag” (optional; ignore if present)
1082
                        case 66:
1083
                                return true;
33,276✔
1084
                        case 100:
1085
                                switch (this._reader.ValueAsString)
864!
1086
                                {
1087
                                        case DxfSubclassMarker.Polyline:
NEW
1088
                                                tmp.SetPolyLineObject(new Polyline2D());
×
NEW
1089
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline, DxfClassMap.Create<Polyline2D>());
×
NEW
1090
                                                return true;
×
1091
                                        case DxfSubclassMarker.Polyline3d:
1092
                                                tmp.SetPolyLineObject(new Polyline3D());
216✔
1093
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline3d, DxfClassMap.Create<Polyline3D>());
216✔
1094
                                                return true;
216✔
1095
                                        case DxfSubclassMarker.PolyfaceMesh:
1096
                                                tmp.SetPolyLineObject(new PolyfaceMesh());
216✔
1097
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMesh, DxfClassMap.Create<PolyfaceMesh>());
216✔
1098
                                                return true;
216✔
1099
                                        case DxfSubclassMarker.PolygonMesh:
NEW
1100
                                                tmp.SetPolyLineObject(new PolygonMesh());
×
NEW
1101
                                                map.SubClasses.Add(DxfSubclassMarker.PolygonMesh, DxfClassMap.Create<PolygonMesh>());
×
NEW
1102
                                                return true;
×
1103
                                        default:
1104
                                                return false;
432✔
1105
                                }
1106
                        default:
1107
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
45,516✔
1108
                }
1109
        }
79,656✔
1110

1111
        private bool readLeader(CadEntityTemplate template, DxfMap map, string subclass = null)
1112
        {
5,400✔
1113
                CadLeaderTemplate tmp = template as CadLeaderTemplate;
5,400✔
1114

1115
                switch (this._reader.Code)
5,400✔
1116
                {
1117
                        case 3:
1118
                                tmp.DIMSTYLEName = this._reader.ValueAsString;
216✔
1119
                                return true;
216✔
1120
                        case 10:
1121
                                tmp.CadObject.Vertices.Add(new XYZ(this._reader.ValueAsDouble, 0, 0));
864✔
1122
                                return true;
864✔
1123
                        case 20:
1124
                                XYZ y = tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1];
864✔
1125
                                y.Y = this._reader.ValueAsDouble;
864✔
1126
                                tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1] = y;
864✔
1127
                                return true;
864✔
1128
                        case 30:
1129
                                XYZ z = tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1];
864✔
1130
                                z.Z = this._reader.ValueAsDouble;
864✔
1131
                                tmp.CadObject.Vertices[tmp.CadObject.Vertices.Count - 1] = z;
864✔
1132
                                return true;
864✔
1133
                        case 340:
1134
                                tmp.AnnotationHandle = this._reader.ValueAsHandle;
216✔
1135
                                return true;
216✔
1136
                        //Hook line flag - read only
1137
                        case 75:
1138
                        //Vertices count
1139
                        case 76:
1140
                                return true;
432✔
1141
                        default:
1142
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
1,944✔
1143
                }
1144
        }
5,400✔
1145

1146
        private bool readLwPolyline(CadEntityTemplate template, DxfMap map, string subclass = null)
1147
        {
92,547✔
1148
                CadEntityTemplate<LwPolyline> tmp = template as CadEntityTemplate<LwPolyline>;
92,547✔
1149

1150
                LwPolyline.Vertex last = tmp.CadObject.Vertices.LastOrDefault();
92,547✔
1151

1152
                switch (this._reader.Code)
92,547!
1153
                {
1154
                        case 10:
1155
                                tmp.CadObject.Vertices.Add(new LwPolyline.Vertex(new XY(this._reader.ValueAsDouble, 0)));
22,012✔
1156
                                return true;
22,012✔
1157
                        case 20:
1158
                                if (last is not null)
22,012✔
1159
                                {
22,012✔
1160
                                        last.Location = new XY(last.Location.X, this._reader.ValueAsDouble);
22,012✔
1161
                                }
22,012✔
1162
                                return true;
22,012✔
1163
                        case 40:
1164
                                if (last is not null)
2,160✔
1165
                                {
2,160✔
1166
                                        last.StartWidth = this._reader.ValueAsDouble;
2,160✔
1167
                                }
2,160✔
1168
                                return true;
2,160✔
1169
                        case 41:
1170
                                if (last is not null)
2,160✔
1171
                                {
2,160✔
1172
                                        last.EndWidth = this._reader.ValueAsDouble;
2,160✔
1173
                                }
2,160✔
1174
                                return true;
2,160✔
1175
                        case 42:
1176
                                if (last is not null)
2,952✔
1177
                                {
2,952✔
1178
                                        last.Bulge = this._reader.ValueAsDouble;
2,952✔
1179
                                }
2,952✔
1180
                                return true;
2,952✔
1181
                        case 50:
NEW
1182
                                if (last is not null)
×
NEW
1183
                                {
×
NEW
1184
                                        last.CurveTangent = this._reader.ValueAsDouble;
×
NEW
1185
                                }
×
NEW
1186
                                return true;
×
1187
                        //Obsolete; formerly an “entities follow flag” (optional; ignore if present)
1188
                        case 66:
1189
                        //Vertex count
1190
                        case 90:
1191
                                return true;
4,966✔
1192
                        case 91:
NEW
1193
                                if (last is not null)
×
NEW
1194
                                {
×
NEW
1195
                                        last.Id = this._reader.ValueAsInt;
×
NEW
1196
                                }
×
NEW
1197
                                return true;
×
1198
                        default:
1199
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
36,285✔
1200
                }
1201
        }
92,547✔
1202

1203
        private bool readMesh(CadEntityTemplate template, DxfMap map, string subclass = null)
1204
        {
38,016✔
1205
                CadMeshTemplate tmp = template as CadMeshTemplate;
38,016✔
1206

1207
                switch (this._reader.Code)
38,016✔
1208
                {
1209
                        case 100:
1210
                                if (this._reader.ValueAsString.Equals(DxfSubclassMarker.Mesh, StringComparison.OrdinalIgnoreCase))
864✔
1211
                                {
432✔
1212
                                        tmp.SubclassMarker = true;
432✔
1213
                                }
432✔
1214
                                return true;
864✔
1215
                        //Count of sub-entity which property has been overridden
1216
                        case 90:
1217
                                //TODO: process further entities
1218
                                return true;
432✔
1219
                        case 92:
1220
                                if (!tmp.SubclassMarker)
648✔
1221
                                {
216✔
1222
                                        return false;
216✔
1223
                                }
1224

1225
                                int nvertices = this._reader.ValueAsInt;
432✔
1226
                                for (int i = 0; i < nvertices; i++)
55,296✔
1227
                                {
27,216✔
1228
                                        this._reader.ReadNext();
27,216✔
1229
                                        double x = this._reader.ValueAsDouble;
27,216✔
1230
                                        this._reader.ReadNext();
27,216✔
1231
                                        double y = this._reader.ValueAsDouble;
27,216✔
1232
                                        this._reader.ReadNext();
27,216✔
1233
                                        double z = this._reader.ValueAsDouble;
27,216✔
1234
                                        tmp.CadObject.Vertices.Add(new XYZ(x, y, z));
27,216✔
1235
                                }
27,216✔
1236
                                return true;
432✔
1237
                        case 93:
1238
                                int size = this._reader.ValueAsInt;
432✔
1239
                                this._reader.ReadNext();
432✔
1240

1241
                                int indexes = 0;
432✔
1242
                                for (int i = 0; i < size; i += indexes + 1)
59,616✔
1243
                                {
29,376✔
1244
                                        indexes = this._reader.ValueAsInt;
29,376✔
1245
                                        this._reader.ReadNext();
29,376✔
1246

1247
                                        int[] face = new int[indexes];
29,376✔
1248
                                        for (int j = 0; j < indexes; j++)
283,392✔
1249
                                        {
112,320✔
1250
                                                face[j] = this._reader.ValueAsInt;
112,320✔
1251

1252
                                                if ((i + j + 2) < size)
112,320✔
1253
                                                {
111,888✔
1254
                                                        this._reader.ReadNext();
111,888✔
1255
                                                }
111,888✔
1256
                                        }
112,320✔
1257

1258
                                        tmp.CadObject.Faces.Add(face);
29,376✔
1259
                                }
29,376✔
1260

1261
                                return true;
432✔
1262
                        case 94:
1263
                                int numEdges = this._reader.ValueAsInt;
432✔
1264
                                this._reader.ReadNext();
432✔
1265
                                for (int i = 0; i < numEdges; i++)
113,184✔
1266
                                {
56,160✔
1267
                                        Mesh.Edge edge = new Mesh.Edge();
56,160✔
1268

1269
                                        edge.Start = this._reader.ValueAsInt;
56,160✔
1270
                                        this._reader.ReadNext();
56,160✔
1271
                                        edge.End = this._reader.ValueAsInt;
56,160✔
1272

1273
                                        if (i < numEdges - 1)
56,160✔
1274
                                        {
55,728✔
1275
                                                this._reader.ReadNext();
55,728✔
1276
                                        }
55,728✔
1277

1278
                                        tmp.CadObject.Edges.Add(edge);
56,160✔
1279
                                }
56,160✔
1280

1281
                                return true;
432✔
1282
                        case 95:
1283
                                this._reader.ReadNext();
432✔
1284
                                for (int i = 0; i < tmp.CadObject.Edges.Count; i++)
113,184✔
1285
                                {
56,160✔
1286
                                        Mesh.Edge edge = tmp.CadObject.Edges[i];
56,160✔
1287
                                        edge.Crease = this._reader.ValueAsDouble;
56,160✔
1288

1289
                                        tmp.CadObject.Edges[i] = edge;
56,160✔
1290

1291
                                        if (i < tmp.CadObject.Edges.Count - 1)
56,160✔
1292
                                        {
55,728✔
1293
                                                this._reader.ReadNext();
55,728✔
1294
                                        }
55,728✔
1295
                                }
56,160✔
1296

1297
                                return true;
432✔
1298
                        default:
1299
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
34,776✔
1300
                }
1301
        }
38,016✔
1302

1303
        private bool readMLine(CadEntityTemplate template, DxfMap map, string subclass = null)
1304
        {
56,160✔
1305
                CadMLineTemplate tmp = template as CadMLineTemplate;
56,160✔
1306

1307
                switch (this._reader.Code)
56,160✔
1308
                {
1309
                        // 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.
1310
                        // Do not modify this field without also updating the associated entry in the MLINESTYLE dictionary
1311
                        case 2:
1312
                                tmp.MLineStyleName = this._reader.ValueAsString;
648✔
1313
                                return true;
648✔
1314
                        case 72:
1315
                                tmp.NVertex = this._reader.ValueAsInt;
648✔
1316
                                return true;
648✔
1317
                        case 73:
1318
                                tmp.NElements = this._reader.ValueAsInt;
648✔
1319
                                return true;
648✔
1320
                        case 340:
1321
                                tmp.MLineStyleHandle = this._reader.ValueAsHandle;
648✔
1322
                                return true;
648✔
1323
                        default:
1324
                                if (!tmp.TryReadVertex(this._reader.Code, this._reader.Value))
53,568✔
1325
                                {
9,072✔
1326
                                        return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
9,072✔
1327
                                }
1328
                                return true;
44,496✔
1329
                }
1330
        }
56,160✔
1331

1332
        private bool readMLeader(CadEntityTemplate template, DxfMap map, string subclass = null)
1333
        {
152,496✔
1334
                CadMLeaderTemplate tmp = template as CadMLeaderTemplate;
152,496✔
1335

1336
                switch (this._reader.Code)
152,496✔
1337
                {
1338
                        case 270:
1339
                                //f270 Version
1340
                                return true;
1,620✔
1341
                        case 300:
1342
                                this.readMultiLeaderObjectContextData(tmp.CadMLeaderAnnotContextTemplate);
3,240✔
1343
                                return true;
3,240✔
1344
                        case 340:
1345
                                tmp.LeaderStyleHandle = this._reader.ValueAsHandle;
3,240✔
1346
                                return true;
3,240✔
1347
                        case 341:
1348
                                tmp.LeaderLineTypeHandle = this._reader.ValueAsHandle;
3,240✔
1349
                                return true;
3,240✔
1350
                        case 343:
1351
                                tmp.MTextStyleHandle = this._reader.ValueAsHandle;
3,240✔
1352
                                return true;
3,240✔
1353
                        default:
1354
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
137,916✔
1355
                }
1356
        }
152,496✔
1357

1358
        private void readMultiLeaderObjectContextData(CadMLeaderAnnotContextTemplate template)
1359
        {
3,240✔
1360
                this._reader.ReadNext();
3,240✔
1361

1362
                var map = DxfClassMap.Create<MultiLeaderObjectContextData>();
3,240✔
1363
                var contextData = template.CadObject as MultiLeaderObjectContextData;
3,240✔
1364

1365
                bool end = false;
3,240✔
1366
                while (this._reader.DxfCode != DxfCode.Start)
181,440✔
1367
                {
181,440✔
1368
                        switch (this._reader.Code)
181,440✔
1369
                        {
1370
                                case 301 when this._reader.ValueAsString.Equals("}"):
3,240✔
1371
                                        end = true;
3,240✔
1372
                                        break;
3,240✔
1373
                                case 302 when this._reader.ValueAsString.Equals("LEADER{"):
3,240✔
1374
                                        contextData.LeaderRoots.Add(this.readMultiLeaderLeader(template));
3,240✔
1375
                                        break;
3,240✔
1376
                                case 340:
1377
                                        template.TextStyleHandle = this._reader.ValueAsHandle;
3,240✔
1378
                                        break;
3,240✔
1379
                                default:
1380
                                        if (!this.tryAssignCurrentValue(contextData, map))
171,720!
NEW
1381
                                        {
×
NEW
1382
                                                this._builder.Notify($"[AcDbMLeaderObjectContextData] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
NEW
1383
                                        }
×
1384
                                        break;
171,720✔
1385
                        }
1386

1387
                        if (end)
181,440✔
1388
                        {
3,240✔
1389
                                break;
3,240✔
1390
                        }
1391

1392
                        this._reader.ReadNext();
178,200✔
1393
                }
178,200✔
1394
        }
3,240✔
1395

1396
        private MultiLeaderObjectContextData.LeaderRoot readMultiLeaderLeader(CadMLeaderAnnotContextTemplate template)
1397
        {
3,240✔
1398
                MultiLeaderObjectContextData.LeaderRoot root = new();
3,240✔
1399
                var map = DxfClassMap.Create(root.GetType(), nameof(MultiLeaderObjectContextData.LeaderRoot));
3,240✔
1400

1401
                this._reader.ReadNext();
3,240✔
1402

1403
                bool end = false;
3,240✔
1404
                while (this._reader.DxfCode != DxfCode.Start)
40,500✔
1405
                {
40,500✔
1406
                        switch (this._reader.Code)
40,500✔
1407
                        {
1408
                                case 303 when this._reader.ValueAsString.Equals("}"):
3,240✔
1409
                                        end = true;
3,240✔
1410
                                        break;
3,240✔
1411
                                case 304 when this._reader.ValueAsString.Equals("LEADER_LINE{"):
3,240✔
1412
                                        var lineTemplate = new LeaderLineTemplate();
3,240✔
1413
                                        template.LeaderLineTemplates.Add(lineTemplate);
3,240✔
1414
                                        root.Lines.Add(this.readMultiLeaderLine(lineTemplate));
3,240✔
1415
                                        break;
3,240✔
1416
                                default:
1417
                                        if (!this.tryAssignCurrentValue(root, map))
34,020!
NEW
1418
                                        {
×
NEW
1419
                                                this._builder.Notify($"[LeaderRoot] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
NEW
1420
                                        }
×
1421
                                        break;
34,020✔
1422
                        }
1423

1424
                        if (end)
40,500✔
1425
                        {
3,240✔
1426
                                break;
3,240✔
1427
                        }
1428

1429
                        this._reader.ReadNext();
37,260✔
1430
                }
37,260✔
1431

1432
                return root;
3,240✔
1433
        }
3,240✔
1434

1435
        private MultiLeaderObjectContextData.LeaderLine readMultiLeaderLine(LeaderLineTemplate template)
1436
        {
3,240✔
1437
                MultiLeaderObjectContextData.LeaderLine line = template.LeaderLine;
3,240✔
1438
                var map = DxfClassMap.Create(line.GetType(), nameof(MultiLeaderObjectContextData.LeaderLine));
3,240✔
1439

1440
                this._reader.ReadNext();
3,240✔
1441

1442
                bool end = false;
3,240✔
1443
                while (this._reader.DxfCode != DxfCode.Start)
16,200✔
1444
                {
16,200✔
1445
                        switch (this._reader.Code)
16,200✔
1446
                        {
1447
                                case 10:
1448
                                        XYZ pt = new XYZ(this._reader.ValueAsDouble, 0, 0);
3,240✔
1449
                                        line.Points.Add(pt);
3,240✔
1450
                                        break;
3,240✔
1451
                                case 20:
1452
                                        pt = line.Points[line.Points.Count - 1];
3,240✔
1453
                                        pt.Y = this._reader.ValueAsDouble;
3,240✔
1454
                                        line.Points[line.Points.Count - 1] = pt;
3,240✔
1455
                                        break;
3,240✔
1456
                                case 30:
1457
                                        pt = line.Points[line.Points.Count - 1];
3,240✔
1458
                                        pt.Z = this._reader.ValueAsDouble;
3,240✔
1459
                                        line.Points[line.Points.Count - 1] = pt;
3,240✔
1460
                                        break;
3,240✔
1461
                                case 305 when this._reader.ValueAsString.Equals("}"):
3,240✔
1462
                                        end = true;
3,240✔
1463
                                        break;
3,240✔
1464
                                default:
1465
                                        if (!this.tryAssignCurrentValue(line, map))
3,240!
NEW
1466
                                        {
×
NEW
1467
                                                this._builder.Notify($"[LeaderLine] Unhandled dxf code {this._reader.Code} with value {this._reader.ValueAsString}", NotificationType.None);
×
NEW
1468
                                        }
×
1469
                                        break;
3,240✔
1470
                        }
1471

1472
                        if (end)
16,200✔
1473
                        {
3,240✔
1474
                                break;
3,240✔
1475
                        }
1476

1477
                        this._reader.ReadNext();
12,960✔
1478
                }
12,960✔
1479

1480
                return line;
3,240✔
1481
        }
3,240✔
1482

1483
        private bool readShape(CadEntityTemplate template, DxfMap map, string subclass = null)
1484
        {
2,412✔
1485
                CadShapeTemplate tmp = template as CadShapeTemplate;
2,412✔
1486

1487
                switch (this._reader.Code)
2,412✔
1488
                {
1489
                        case 2:
1490
                                tmp.ShapeFileName = this._reader.ValueAsString;
252✔
1491
                                return true;
252✔
1492
                        default:
1493
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
2,160✔
1494
                }
1495
        }
2,412✔
1496

1497
        private bool readWipeoutBase(CadEntityTemplate template, DxfMap map, string subclass = null)
1498
        {
12,744✔
1499
                CadWipeoutBaseTemplate tmp = template as CadWipeoutBaseTemplate;
12,744✔
1500
                CadWipeoutBase wipeout = tmp.CadObject as CadWipeoutBase;
12,744✔
1501

1502
                switch (this._reader.Code)
12,744✔
1503
                {
1504
                        case 91:
1505
                                var nvertices = this._reader.ValueAsInt;
432✔
1506
                                for (int i = 0; i < nvertices; i++)
3,888✔
1507
                                {
1,512✔
1508
                                        this._reader.ReadNext();
1,512✔
1509
                                        var x = this._reader.ValueAsDouble;
1,512✔
1510
                                        this._reader.ReadNext();
1,512✔
1511
                                        var y = this._reader.ValueAsDouble;
1,512✔
1512

1513
                                        wipeout.ClipBoundaryVertices.Add(new XY(x, y));
1,512✔
1514
                                }
1,512✔
1515

1516
                                this._reader.ReadNext();
432✔
1517

1518
                                return this.checkEntityEnd(template, map, subclass, this.readWipeoutBase);
432✔
1519
                        case 340:
1520
                                tmp.ImgDefHandle = this._reader.ValueAsHandle;
432✔
1521
                                return true;
432✔
1522
                        case 360:
1523
                                tmp.ImgReactorHandle = this._reader.ValueAsHandle;
432✔
1524
                                return true;
432✔
1525
                        default:
1526
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
11,448✔
1527
                }
1528
        }
12,744✔
1529

1530
        private bool readOle2Frame(CadEntityTemplate template, DxfMap map, string subclass = null)
NEW
1531
        {
×
NEW
1532
                CadOle2FrameTemplate tmp = template as CadOle2FrameTemplate;
×
1533

NEW
1534
                switch (this._reader.Code)
×
1535
                {
1536
                        //End of data
1537
                        case 1:
1538
                        //Length of binary data
1539
                        case 90:
1540
                        //Undocumented
1541
                        case 73:
NEW
1542
                                return true;
×
1543
                        case 310:
NEW
1544
                                tmp.Chunks.Add(this._reader.ValueAsBinaryChunk);
×
NEW
1545
                                return true;
×
1546
                        default:
NEW
1547
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
×
1548
                }
NEW
1549
        }
×
1550

1551
        private bool readModelerGeometry(CadEntityTemplate template, DxfMap map, string subclass = null)
1552
        {
306,654✔
1553
                CadSolid3DTemplate tmp = template as CadSolid3DTemplate;
306,654✔
1554
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
306,654✔
1555
                var geometry = template.CadObject as ModelerGeometry;
306,654✔
1556

1557
                switch (this._reader.Code)
306,654✔
1558
                {
1559
                        case 1:
1560
                        case 3:
1561
                                geometry.ProprietaryData.AppendLine(this._reader.ValueAsString);
39,924✔
1562
                                return true;
39,924✔
1563
                        case 2:
1564
                                geometry.Guid = new Guid(this._reader.ValueAsString);
216✔
1565
                                return true;
216✔
1566
                        case 290:
1567
                                return true;
216✔
1568
                        default:
1569
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[mapName]);
266,298✔
1570
                }
1571
        }
306,654✔
1572

1573
        private bool readSolid3d(CadEntityTemplate template, DxfMap map, string subclass = null)
1574
        {
36,936✔
1575
                CadSolid3DTemplate tmp = template as CadSolid3DTemplate;
36,936✔
1576

1577
                switch (this._reader.Code)
36,936✔
1578
                {
1579
                        case 350:
1580
                                tmp.HistoryHandle = this._reader.ValueAsHandle;
288✔
1581
                                return true;
288✔
1582
                        default:
1583
                                return this.readModelerGeometry(template, map, DxfSubclassMarker.ModelerGeometry);
36,648✔
1584
                }
1585
        }
36,936✔
1586

1587
        private bool readSpline(CadEntityTemplate template, DxfMap map, string subclass = null)
1588
        {
15,120✔
1589
                CadSplineTemplate tmp = template as CadSplineTemplate;
15,120✔
1590

1591
                XYZ controlPoint;
1592
                XYZ fitPoint;
1593

1594
                switch (this._reader.Code)
15,120!
1595
                {
1596
                        case 10:
1597
                                controlPoint = new CSMath.XYZ(this._reader.ValueAsDouble, 0, 0);
1,728✔
1598
                                tmp.CadObject.ControlPoints.Add(controlPoint);
1,728✔
1599
                                return true;
1,728✔
1600
                        case 20:
1601
                                controlPoint = tmp.CadObject.ControlPoints.LastOrDefault();
1,728✔
1602
                                controlPoint.Y = this._reader.ValueAsDouble;
1,728✔
1603
                                tmp.CadObject.ControlPoints[tmp.CadObject.ControlPoints.Count - 1] = controlPoint;
1,728✔
1604
                                return true;
1,728✔
1605
                        case 30:
1606
                                controlPoint = tmp.CadObject.ControlPoints.LastOrDefault();
1,728✔
1607
                                controlPoint.Z = this._reader.ValueAsDouble;
1,728✔
1608
                                tmp.CadObject.ControlPoints[tmp.CadObject.ControlPoints.Count - 1] = controlPoint;
1,728✔
1609
                                return true;
1,728✔
1610
                        case 11:
NEW
1611
                                fitPoint = new CSMath.XYZ(this._reader.ValueAsDouble, 0, 0);
×
NEW
1612
                                tmp.CadObject.FitPoints.Add(fitPoint);
×
NEW
1613
                                return true;
×
1614
                        case 21:
NEW
1615
                                fitPoint = tmp.CadObject.FitPoints.LastOrDefault();
×
NEW
1616
                                fitPoint.Y = this._reader.ValueAsDouble;
×
NEW
1617
                                tmp.CadObject.FitPoints[tmp.CadObject.FitPoints.Count - 1] = fitPoint;
×
NEW
1618
                                return true;
×
1619
                        case 31:
NEW
1620
                                fitPoint = tmp.CadObject.FitPoints.LastOrDefault();
×
NEW
1621
                                fitPoint.Z = this._reader.ValueAsDouble;
×
NEW
1622
                                tmp.CadObject.FitPoints[tmp.CadObject.FitPoints.Count - 1] = fitPoint;
×
NEW
1623
                                return true;
×
1624
                        case 40:
1625
                                tmp.CadObject.Knots.Add(this._reader.ValueAsDouble);
3,456✔
1626
                                return true;
3,456✔
1627
                        case 41:
NEW
1628
                                tmp.CadObject.Weights.Add(this._reader.ValueAsDouble);
×
NEW
1629
                                return true;
×
1630
                        case 72:
1631
                        case 73:
1632
                        case 74:
1633
                                return true;
1,296✔
1634
                        default:
1635
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
5,184✔
1636
                }
1637
        }
15,120✔
1638

1639
        private bool readUnderlayEntity<T>(CadEntityTemplate template, DxfMap map, string subclass = null)
1640
                where T : PdfUnderlayDefinition
1641
        {
3,420✔
1642
                CadUnderlayTemplate<T> tmp = template as CadUnderlayTemplate<T>;
3,420✔
1643

1644
                switch (this._reader.Code)
3,420✔
1645
                {
1646
                        case 340:
1647
                                tmp.DefinitionHandle = this._reader.ValueAsHandle;
216✔
1648
                                return true;
216✔
1649
                        default:
1650
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
3,204✔
1651
                }
1652
        }
3,420✔
1653

1654
        private bool readVertex(CadEntityTemplate template, DxfMap map, string subclass = null)
1655
        {
252,690✔
1656
                CadVertexTemplate tmp = template as CadVertexTemplate;
252,690✔
1657

1658
                switch (this._reader.Code)
252,690✔
1659
                {
1660
                        case 100:
1661
                                switch (this._reader.ValueAsString)
7,344!
1662
                                {
1663
                                        case DxfSubclassMarker.Vertex:
1664
                                                return true;
2,160✔
1665
                                        case DxfSubclassMarker.PolylineVertex:
NEW
1666
                                                tmp.SetVertexObject(new Vertex2D());
×
NEW
1667
                                                map.SubClasses.Add(DxfSubclassMarker.PolylineVertex, DxfClassMap.Create<Vertex2D>());
×
NEW
1668
                                                return true;
×
1669
                                        case DxfSubclassMarker.Polyline3dVertex:
1670
                                                tmp.SetVertexObject(new Vertex3D());
1,080✔
1671
                                                map.SubClasses.Add(DxfSubclassMarker.Polyline3dVertex, DxfClassMap.Create<Vertex3D>());
1,080✔
1672
                                                return true;
1,080✔
1673
                                        case DxfSubclassMarker.PolyfaceMeshVertex:
1674
                                                tmp.SetVertexObject(new VertexFaceMesh());
1,080✔
1675
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMeshVertex, DxfClassMap.Create<VertexFaceMesh>());
1,080✔
1676
                                                return true;
1,080✔
1677
                                        case DxfSubclassMarker.PolyfaceMeshFace:
1678
                                                tmp.SetVertexObject(new VertexFaceRecord());
432✔
1679
                                                map.SubClasses.Add(DxfSubclassMarker.PolyfaceMeshFace, DxfClassMap.Create<VertexFaceRecord>());
432✔
1680
                                                return true;
432✔
1681
                                        case DxfSubclassMarker.PolygonMeshVertex:
NEW
1682
                                                tmp.SetVertexObject(new PolygonMeshVertex());
×
NEW
1683
                                                map.SubClasses.Add(DxfSubclassMarker.PolygonMeshVertex, DxfClassMap.Create<PolygonMeshVertex>());
×
NEW
1684
                                                return true;
×
1685
                                        default:
1686
                                                return false;
2,592✔
1687
                                }
1688
                        default:
1689
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[tmp.CadObject.SubclassMarker]);
245,346✔
1690
                }
1691
        }
252,690✔
1692

1693
        private bool readViewport(CadEntityTemplate template, DxfMap map, string subclass = null)
1694
        {
72,724✔
1695
                CadViewportTemplate tmp = template as CadViewportTemplate;
72,724✔
1696

1697
                switch (this._reader.Code)
72,724!
1698
                {
1699
                        //Undocumented
1700
                        case 67:
1701
                        case 68:
1702
                                return true;
2,664✔
1703
                        case 69:
1704
                                tmp.ViewportId = this._reader.ValueAsShort;
1,332✔
1705
                                return true;
1,332✔
1706
                        case 331:
NEW
1707
                                tmp.FrozenLayerHandles.Add(this._reader.ValueAsHandle);
×
NEW
1708
                                return true;
×
1709
                        case 348:
1710
                                tmp.VisualStyleHandle = this._reader.ValueAsHandle;
832✔
1711
                                return true;
832✔
1712
                        default:
1713
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[DxfSubclassMarker.Viewport]);
67,896✔
1714
                }
1715
        }
72,724✔
1716

1717
        private bool readEntitySubclassMap(CadEntityTemplate template, DxfMap map, string subclass = null)
1718
        {
855,836✔
1719
                string mapName = string.IsNullOrEmpty(subclass) ? template.CadObject.SubclassMarker : subclass;
855,836✔
1720

1721
                switch (this._reader.Code)
855,836✔
1722
                {
1723
                        default:
1724
                                return this.tryAssignCurrentValue(template.CadObject, map.SubClasses[mapName]);
855,836✔
1725
                }
1726
        }
855,836✔
1727

1728
        protected void readExtendedData(Dictionary<string, List<ExtendedDataRecord>> edata)
1729
        {
36,252✔
1730
                List<ExtendedDataRecord> records = new();
36,252✔
1731
                edata.Add(this._reader.ValueAsString, records);
36,252✔
1732

1733
                this._reader.ReadNext();
36,252✔
1734

1735
                while (this._reader.DxfCode >= DxfCode.ExtendedDataAsciiString)
296,377✔
1736
                {
271,630✔
1737
                        if (this._reader.DxfCode == DxfCode.ExtendedDataRegAppName)
271,630✔
1738
                        {
11,505✔
1739
                                this.readExtendedData(edata);
11,505✔
1740
                                break;
11,505✔
1741
                        }
1742

1743
                        ExtendedDataRecord record = null;
260,125✔
1744
                        double x = 0;
260,125✔
1745
                        double y = 0;
260,125✔
1746
                        double z = 0;
260,125✔
1747

1748
                        switch (this._reader.DxfCode)
260,125✔
1749
                        {
1750
                                case DxfCode.ExtendedDataAsciiString:
1751
                                case DxfCode.ExtendedDataRegAppName:
1752
                                        record = new ExtendedDataString(this._reader.ValueAsString);
24,915✔
1753
                                        break;
24,915✔
1754
                                case DxfCode.ExtendedDataControlString:
1755
                                        record = new ExtendedDataControlString(this._reader.ValueAsString == "}");
14,276✔
1756
                                        break;
14,276✔
1757
                                case DxfCode.ExtendedDataLayerName:
1758
                                        if (this._builder.Layers.TryGetValue(this._reader.ValueAsString, out Layer layer))
252✔
1759
                                        {
238✔
1760
                                                record = new ExtendedDataLayer(layer.Handle);
238✔
1761
                                        }
238✔
1762
                                        else
1763
                                        {
14✔
1764
                                                this._builder.Notify($"[XData] Could not found the linked Layer {this._reader.ValueAsString}.", NotificationType.Warning);
14✔
1765
                                        }
14✔
1766
                                        break;
252✔
1767
                                case DxfCode.ExtendedDataBinaryChunk:
1768
                                        record = new ExtendedDataBinaryChunk(this._reader.ValueAsBinaryChunk);
72✔
1769
                                        break;
72✔
1770
                                case DxfCode.ExtendedDataHandle:
1771
                                        record = new ExtendedDataHandle(this._reader.ValueAsHandle);
2,761✔
1772
                                        break;
2,761✔
1773
                                case DxfCode.ExtendedDataXCoordinate:
1774
                                        x = this._reader.ValueAsDouble;
2,689✔
1775
                                        this._reader.ReadNext();
2,689✔
1776
                                        y = this._reader.ValueAsDouble;
2,689✔
1777
                                        this._reader.ReadNext();
2,689✔
1778
                                        z = this._reader.ValueAsDouble;
2,689✔
1779

1780
                                        record = new ExtendedDataCoordinate(
2,689✔
1781
                                                new XYZ(
2,689✔
1782
                                                        x,
2,689✔
1783
                                                        y,
2,689✔
1784
                                                        z)
2,689✔
1785
                                                );
2,689✔
1786
                                        break;
2,689✔
1787
                                case DxfCode.ExtendedDataWorldXCoordinate:
1788
                                        x = this._reader.ValueAsDouble;
1,296✔
1789
                                        this._reader.ReadNext();
1,296✔
1790
                                        y = this._reader.ValueAsDouble;
1,296✔
1791
                                        this._reader.ReadNext();
1,296✔
1792
                                        z = this._reader.ValueAsDouble;
1,296✔
1793

1794
                                        record = new ExtendedDataWorldCoordinate(
1,296✔
1795
                                                new XYZ(
1,296✔
1796
                                                        x,
1,296✔
1797
                                                        y,
1,296✔
1798
                                                        z)
1,296✔
1799
                                                );
1,296✔
1800
                                        break;
1,296✔
1801
                                case DxfCode.ExtendedDataWorldXDisp:
1802
                                        x = this._reader.ValueAsDouble;
252✔
1803
                                        this._reader.ReadNext();
252✔
1804
                                        y = this._reader.ValueAsDouble;
252✔
1805
                                        this._reader.ReadNext();
252✔
1806
                                        z = this._reader.ValueAsDouble;
252✔
1807

1808
                                        record = new ExtendedDataDisplacement(
252✔
1809
                                                new XYZ(
252✔
1810
                                                        x,
252✔
1811
                                                        y,
252✔
1812
                                                        z)
252✔
1813
                                                );
252✔
1814
                                        break;
252✔
1815
                                case DxfCode.ExtendedDataWorldXDir:
1816
                                        x = this._reader.ValueAsDouble;
252✔
1817
                                        this._reader.ReadNext();
252✔
1818
                                        y = this._reader.ValueAsDouble;
252✔
1819
                                        this._reader.ReadNext();
252✔
1820
                                        z = this._reader.ValueAsDouble;
252✔
1821

1822
                                        record = new ExtendedDataDirection(
252✔
1823
                                                new XYZ(
252✔
1824
                                                        x,
252✔
1825
                                                        y,
252✔
1826
                                                        z)
252✔
1827
                                                );
252✔
1828
                                        break;
252✔
1829
                                case DxfCode.ExtendedDataReal:
1830
                                        record = new ExtendedDataReal(this._reader.ValueAsDouble);
126,479✔
1831
                                        break;
126,479✔
1832
                                case DxfCode.ExtendedDataDist:
1833
                                        record = new ExtendedDataDistance(this._reader.ValueAsDouble);
252✔
1834
                                        break;
252✔
1835
                                case DxfCode.ExtendedDataScale:
1836
                                        record = new ExtendedDataScale(this._reader.ValueAsDouble);
252✔
1837
                                        break;
252✔
1838
                                case DxfCode.ExtendedDataInteger16:
1839
                                        record = new ExtendedDataInteger16(this._reader.ValueAsShort);
73,899✔
1840
                                        break;
73,899✔
1841
                                case DxfCode.ExtendedDataInteger32:
1842
                                        record = new ExtendedDataInteger32((int)this._reader.ValueAsInt);
10,174✔
1843
                                        break;
10,174✔
1844
                                default:
1845
                                        this._builder.Notify($"Unknown code for extended data: {this._reader.DxfCode}", NotificationType.Warning);
2,304✔
1846
                                        break;
2,304✔
1847
                        }
1848

1849
                        if (record != null)
260,125✔
1850
                        {
257,807✔
1851
                                records.Add(record);
257,807✔
1852
                        }
257,807✔
1853

1854
                        this._reader.ReadNext();
260,125✔
1855
                }
260,125✔
1856
        }
36,252✔
1857

1858
        private void readPattern(HatchPattern pattern, int nlines)
1859
        {
1,296✔
1860
                //Jump 78 code
1861
                this._reader.ReadNext();
1,296✔
1862

1863
                for (int i = 0; i < nlines; i++)
196,560✔
1864
                {
96,984✔
1865
                        HatchPattern.Line line = new HatchPattern.Line();
96,984✔
1866
                        XY basePoint = new XY();
96,984✔
1867
                        XY offset = new XY();
96,984✔
1868

1869
                        bool end = false;
96,984✔
1870
                        HashSet<int> codes = new();
96,984✔
1871

1872
                        while (!end)
680,184✔
1873
                        {
678,888✔
1874
                                if (codes.Contains(this._reader.Code))
678,888✔
1875
                                {
95,688✔
1876
                                        break;
95,688✔
1877
                                }
1878
                                else
1879
                                {
583,200✔
1880
                                        codes.Add(this._reader.Code);
583,200✔
1881
                                }
583,200✔
1882

1883
                                switch (this._reader.Code)
583,200!
1884
                                {
1885
                                        case 53:
1886
                                                line.Angle = this._reader.ValueAsAngle;
96,984✔
1887
                                                break;
96,984✔
1888
                                        case 43:
1889
                                                basePoint.X = this._reader.ValueAsDouble;
96,984✔
1890
                                                break;
96,984✔
1891
                                        case 44:
1892
                                                basePoint.Y = this._reader.ValueAsDouble;
96,984✔
1893
                                                line.BasePoint = basePoint;
96,984✔
1894
                                                break;
96,984✔
1895
                                        case 45:
1896
                                                offset.X = this._reader.ValueAsDouble;
96,984✔
1897
                                                line.Offset = offset;
96,984✔
1898
                                                break;
96,984✔
1899
                                        case 46:
1900
                                                offset.Y = this._reader.ValueAsDouble;
96,984✔
1901
                                                line.Offset = offset;
96,984✔
1902
                                                break;
96,984✔
1903
                                        //Number of dash length items
1904
                                        case 79:
1905
                                                int ndash = this._reader.ValueAsInt;
96,984✔
1906
                                                for (int j = 0; j < ndash; j++)
581,040✔
1907
                                                {
193,536✔
1908
                                                        this._reader.ReadNext();
193,536✔
1909
                                                        line.DashLengths.Add(this._reader.ValueAsDouble);
193,536✔
1910
                                                }
193,536✔
1911
                                                break;
96,984✔
1912
                                        case 49:
NEW
1913
                                                line.DashLengths.Add(this._reader.ValueAsDouble);
×
UNCOV
1914
                                                break;
×
1915
                                        default:
1916
                                                end = true;
1,296✔
1917
                                                break;
1,296✔
1918
                                }
1919
                                this._reader.ReadNext();
583,200✔
1920
                        }
583,200✔
1921

1922
                        pattern.Lines.Add(line);
96,984✔
1923
                }
96,984✔
1924
        }
1,296✔
1925

1926
        private void readLoops(CadHatchTemplate template, int count)
1927
        {
1,728✔
1928
                if (this._reader.Code == 91)
1,728✔
1929
                        this._reader.ReadNext();
1,728✔
1930

1931
                for (int i = 0; i < count; i++)
6,912✔
1932
                {
1,728✔
1933
                        if (this._reader.Code != 92)
1,728!
1934
                        {
×
NEW
1935
                                this._builder.Notify($"Boundary path should start with code 92 but was {this._reader.Code}");
×
NEW
1936
                                break;
×
1937
                        }
1938

1939
                        CadHatchTemplate.CadBoundaryPathTemplate path = this.readLoop();
1,728✔
1940
                        if (path != null)
1,728✔
1941
                                template.PathTemplates.Add(path);
1,728✔
1942
                }
1,728✔
1943
        }
1,728✔
1944

1945
        private CadHatchTemplate.CadBoundaryPathTemplate readLoop()
1946
        {
1,728✔
1947
                CadHatchTemplate.CadBoundaryPathTemplate template = new CadHatchTemplate.CadBoundaryPathTemplate();
1,728✔
1948
                var flags = (BoundaryPathFlags)this._reader.ValueAsInt;
1,728✔
1949
                template.Path.Flags = flags;
1,728✔
1950

1951
                if (flags.HasFlag(BoundaryPathFlags.Polyline))
1,728✔
1952
                {
648✔
1953
                        Hatch.BoundaryPath.Polyline pl = this.readPolylineBoundary();
648✔
1954
                        template.Path.Edges.Add(pl);
648✔
1955
                }
648✔
1956
                else
1957
                {
1,080✔
1958
                        this._reader.ReadNext();
1,080✔
1959

1960
                        if (this._reader.Code != 93)
1,080!
NEW
1961
                        {
×
NEW
1962
                                this._builder.Notify($"Edge Boundary path should start with code 93 but was {this._reader.Code}");
×
NEW
1963
                                return null;
×
1964
                        }
1965

1966
                        int edges = this._reader.ValueAsInt;
1,080✔
1967
                        this._reader.ReadNext();
1,080✔
1968

1969
                        for (int i = 0; i < edges; i++)
10,800✔
1970
                        {
4,320✔
1971
                                var edge = this.readEdge();
4,320✔
1972
                                if (edge != null)
4,320✔
1973
                                        template.Path.Edges.Add(edge);
4,320✔
1974
                        }
4,320✔
1975
                }
1,080✔
1976

1977
                bool end = false;
1,728✔
1978
                while (!end)
6,696✔
1979
                {
4,968✔
1980
                        switch (this._reader.Code)
4,968✔
1981
                        {
1982
                                //Number of source boundary objects
1983
                                case 97:
1984
                                        break;
1,728✔
1985
                                case 330:
1986
                                        template.Handles.Add(this._reader.ValueAsHandle);
1,512✔
1987
                                        break;
1,512✔
1988
                                default:
1989
                                        end = true;
1,728✔
1990
                                        continue;
1,728✔
1991
                        }
1992

1993
                        this._reader.ReadNext();
3,240✔
1994
                }
3,240✔
1995

1996
                return template;
1,728✔
1997
        }
1,728✔
1998

1999
        private Hatch.BoundaryPath.Polyline readPolylineBoundary()
2000
        {
648✔
2001
                Hatch.BoundaryPath.Polyline boundary = new Hatch.BoundaryPath.Polyline();
648✔
2002

2003
                this._reader.ReadNext();
648✔
2004

2005
                if (this._reader.Code != 72)
648!
NEW
2006
                {
×
NEW
2007
                        this._builder.Notify($"Polyline Boundary path should start with code 72 but was {this._reader.Code}");
×
NEW
2008
                        return null;
×
2009
                }
2010

2011
                bool end = false;
648✔
2012
                bool hasBulge = false;
648✔
2013
                while (!end)
3,240✔
2014
                {
2,592✔
2015
                        switch (this._reader.Code)
2,592✔
2016
                        {
2017
                                case 72:
2018
                                        hasBulge = this._reader.ValueAsBool;
648✔
2019
                                        break;
648✔
2020
                                case 73:
2021
                                        boundary.IsClosed = this._reader.ValueAsBool;
648✔
2022
                                        break;
648✔
2023
                                case 93:
2024
                                        int nvertices = this._reader.ValueAsInt;
648✔
2025
                                        this._reader.ReadNext();
648✔
2026

2027
                                        for (int i = 0; i < nvertices; i++)
6,480✔
2028
                                        {
2,592✔
2029
                                                double bulge = 0.0;
2,592✔
2030

2031
                                                //10
2032
                                                double x = this._reader.ValueAsDouble;
2,592✔
2033
                                                this._reader.ReadNext();
2,592✔
2034
                                                //20
2035
                                                double y = this._reader.ValueAsDouble;
2,592✔
2036
                                                this._reader.ReadNext();
2,592✔
2037

2038
                                                if (hasBulge)
2,592!
2039
                                                {
×
2040
                                                        //42
NEW
2041
                                                        bulge = this._reader.ValueAsDouble;
×
NEW
2042
                                                        this._reader.ReadNext();
×
UNCOV
2043
                                                }
×
2044

2045
                                                boundary.Vertices.Add(new XYZ(x, y, bulge));
2,592✔
2046
                                        }
2,592✔
2047
                                        continue;
648✔
2048
                                default:
2049
                                        end = true;
648✔
2050
                                        continue;
648✔
2051
                        }
2052

2053
                        this._reader.ReadNext();
1,296✔
2054
                }
1,296✔
2055

2056
                return boundary;
648✔
2057
        }
648✔
2058

2059
        private Hatch.BoundaryPath.Edge readEdge()
2060
        {
4,320✔
2061
                if (this._reader.Code != 72)
4,320!
NEW
2062
                {
×
NEW
2063
                        this._builder.Notify($"Edge Boundary path should define the type with code 72 but was {this._reader.Code}");
×
NEW
2064
                        return null;
×
2065
                }
2066

2067
                Hatch.BoundaryPath.EdgeType type = (Hatch.BoundaryPath.EdgeType)this._reader.ValueAsInt;
4,320✔
2068
                this._reader.ReadNext();
4,320✔
2069

2070
                switch (type)
4,320!
2071
                {
2072
                        case Hatch.BoundaryPath.EdgeType.Line:
2073
                                Hatch.BoundaryPath.Line line = new Hatch.BoundaryPath.Line();
4,320✔
2074
                                while (true)
21,600✔
2075
                                {
21,600✔
2076
                                        switch (this._reader.Code)
21,600✔
2077
                                        {
2078
                                                case 10:
2079
                                                        line.Start = new XY(this._reader.ValueAsDouble, line.Start.Y);
4,320✔
2080
                                                        break;
4,320✔
2081
                                                case 20:
2082
                                                        line.Start = new XY(line.Start.X, this._reader.ValueAsDouble);
4,320✔
2083
                                                        break;
4,320✔
2084
                                                case 11:
2085
                                                        line.End = new XY(this._reader.ValueAsDouble, line.End.Y);
4,320✔
2086
                                                        break;
4,320✔
2087
                                                case 21:
2088
                                                        line.End = new XY(line.End.X, this._reader.ValueAsDouble);
4,320✔
2089
                                                        break;
4,320✔
2090
                                                default:
2091
                                                        return line;
4,320✔
2092
                                        }
2093

2094
                                        this._reader.ReadNext();
17,280✔
2095
                                }
17,280✔
2096
                        case Hatch.BoundaryPath.EdgeType.CircularArc:
NEW
2097
                                Hatch.BoundaryPath.Arc arc = new Hatch.BoundaryPath.Arc();
×
NEW
2098
                                while (true)
×
NEW
2099
                                {
×
NEW
2100
                                        switch (this._reader.Code)
×
2101
                                        {
2102
                                                case 10:
NEW
2103
                                                        arc.Center = new XY(this._reader.ValueAsDouble, arc.Center.Y);
×
NEW
2104
                                                        break;
×
2105
                                                case 20:
NEW
2106
                                                        arc.Center = new XY(arc.Center.X, this._reader.ValueAsDouble);
×
NEW
2107
                                                        break;
×
2108
                                                case 40:
NEW
2109
                                                        arc.Radius = this._reader.ValueAsDouble;
×
NEW
2110
                                                        break;
×
2111
                                                case 50:
NEW
2112
                                                        arc.StartAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
NEW
2113
                                                        break;
×
2114
                                                case 51:
NEW
2115
                                                        arc.EndAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
NEW
2116
                                                        break;
×
2117
                                                case 73:
NEW
2118
                                                        arc.CounterClockWise = this._reader.ValueAsBool;
×
NEW
2119
                                                        break;
×
2120
                                                default:
NEW
2121
                                                        return arc;
×
2122
                                        }
2123

UNCOV
2124
                                        this._reader.ReadNext();
×
NEW
2125
                                }
×
2126
                        case Hatch.BoundaryPath.EdgeType.EllipticArc:
NEW
2127
                                Hatch.BoundaryPath.Ellipse ellipse = new Hatch.BoundaryPath.Ellipse();
×
NEW
2128
                                while (true)
×
NEW
2129
                                {
×
NEW
2130
                                        switch (this._reader.Code)
×
2131
                                        {
2132
                                                case 10:
NEW
2133
                                                        ellipse.Center = new XY(this._reader.ValueAsDouble, ellipse.Center.Y);
×
NEW
2134
                                                        break;
×
2135
                                                case 20:
NEW
2136
                                                        ellipse.Center = new XY(ellipse.Center.X, this._reader.ValueAsDouble);
×
NEW
2137
                                                        break;
×
2138
                                                case 11:
NEW
2139
                                                        ellipse.MajorAxisEndPoint = new XY(this._reader.ValueAsDouble, ellipse.MajorAxisEndPoint.Y);
×
NEW
2140
                                                        break;
×
2141
                                                case 21:
NEW
2142
                                                        ellipse.MajorAxisEndPoint = new XY(ellipse.MajorAxisEndPoint.X, this._reader.ValueAsDouble);
×
NEW
2143
                                                        break;
×
2144
                                                case 40:
NEW
2145
                                                        ellipse.RadiusRatio = this._reader.ValueAsDouble;
×
NEW
2146
                                                        break;
×
2147
                                                case 50:
NEW
2148
                                                        ellipse.StartAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
NEW
2149
                                                        break;
×
2150
                                                case 51:
NEW
2151
                                                        ellipse.EndAngle = MathHelper.DegToRad(this._reader.ValueAsDouble);
×
NEW
2152
                                                        break;
×
2153
                                                case 73:
NEW
2154
                                                        ellipse.CounterClockWise = this._reader.ValueAsBool;
×
NEW
2155
                                                        break;
×
2156
                                                default:
NEW
2157
                                                        return ellipse;
×
2158
                                        }
2159

UNCOV
2160
                                        this._reader.ReadNext();
×
NEW
2161
                                }
×
2162
                        case Hatch.BoundaryPath.EdgeType.Spline:
NEW
2163
                                Hatch.BoundaryPath.Spline spline = new Hatch.BoundaryPath.Spline();
×
NEW
2164
                                int nKnots = 0;
×
NEW
2165
                                int nCtrlPoints = 0;
×
NEW
2166
                                int nFitPoints = 0;
×
2167

NEW
2168
                                XYZ controlPoint = new XYZ();
×
NEW
2169
                                XY fitPoint = new XY();
×
2170

NEW
2171
                                while (true)
×
NEW
2172
                                {
×
NEW
2173
                                        switch (this._reader.Code)
×
2174
                                        {
2175
                                                case 10:
NEW
2176
                                                        controlPoint = new XYZ(this._reader.ValueAsDouble, 0, 1);
×
NEW
2177
                                                        break;
×
2178
                                                case 20:
NEW
2179
                                                        controlPoint = new XYZ(controlPoint.X, this._reader.ValueAsDouble, controlPoint.Z);
×
NEW
2180
                                                        spline.ControlPoints.Add(controlPoint);
×
NEW
2181
                                                        break;
×
2182
                                                case 11:
NEW
2183
                                                        fitPoint = new XY(this._reader.ValueAsDouble, 0);
×
NEW
2184
                                                        break;
×
2185
                                                case 21:
NEW
2186
                                                        fitPoint = new XY(fitPoint.X, this._reader.ValueAsDouble);
×
NEW
2187
                                                        spline.FitPoints.Add(fitPoint);
×
NEW
2188
                                                        break;
×
2189
                                                case 42:
NEW
2190
                                                        var last = spline.ControlPoints[spline.ControlPoints.Count - 1];
×
NEW
2191
                                                        spline.ControlPoints[spline.ControlPoints.Count - 1] = new XYZ(last.X, last.Y, this._reader.ValueAsDouble);
×
NEW
2192
                                                        break;
×
2193
                                                case 12:
NEW
2194
                                                        spline.StartTangent = new XY(this._reader.ValueAsDouble, spline.StartTangent.Y);
×
NEW
2195
                                                        break;
×
2196
                                                case 22:
NEW
2197
                                                        spline.StartTangent = new XY(spline.StartTangent.X, this._reader.ValueAsDouble);
×
NEW
2198
                                                        break;
×
2199
                                                case 13:
NEW
2200
                                                        spline.EndTangent = new XY(this._reader.ValueAsDouble, spline.EndTangent.Y);
×
NEW
2201
                                                        break;
×
2202
                                                case 23:
NEW
2203
                                                        spline.EndTangent = new XY(spline.EndTangent.X, this._reader.ValueAsDouble);
×
NEW
2204
                                                        break;
×
2205
                                                case 94:
NEW
2206
                                                        spline.Degree = this._reader.ValueAsInt;
×
NEW
2207
                                                        break;
×
2208
                                                case 73:
NEW
2209
                                                        spline.IsRational = this._reader.ValueAsBool;
×
NEW
2210
                                                        break;
×
2211
                                                case 74:
NEW
2212
                                                        spline.IsPeriodic = this._reader.ValueAsBool;
×
NEW
2213
                                                        break;
×
2214
                                                case 95:
NEW
2215
                                                        nKnots = this._reader.ValueAsInt;
×
NEW
2216
                                                        break;
×
2217
                                                case 96:
NEW
2218
                                                        nCtrlPoints = this._reader.ValueAsInt;
×
NEW
2219
                                                        break;
×
2220
                                                case 97:
NEW
2221
                                                        nFitPoints = this._reader.ValueAsInt;
×
NEW
2222
                                                        break;
×
2223
                                                case 40:
NEW
2224
                                                        spline.Knots.Add(this._reader.ValueAsDouble);
×
NEW
2225
                                                        break;
×
2226
                                                default:
NEW
2227
                                                        return spline;
×
2228
                                        }
2229

NEW
2230
                                        this._reader.ReadNext();
×
NEW
2231
                                }
×
2232
                }
2233

NEW
2234
                return null;
×
2235
        }
4,320✔
2236

2237
        private void readDefinedGroups(CadTemplate template)
2238
        {
72,392✔
2239
                this.readDefinedGroups(out ulong? xdict, out HashSet<ulong> reactorsHandles);
72,392✔
2240

2241
                if (xdict.HasValue)
72,392✔
2242
                {
10,457✔
2243
                        template.XDictHandle = xdict;
10,457✔
2244
                }
10,457✔
2245
                template.ReactorsHandles.UnionWith(reactorsHandles);
72,392✔
2246
        }
72,392✔
2247

2248
        private void readDefinedGroups(out ulong? xdictHandle, out HashSet<ulong> reactors)
2249
        {
72,613✔
2250
                xdictHandle = null;
72,613✔
2251
                reactors = new HashSet<ulong>();
72,613✔
2252

2253
                switch (this._reader.ValueAsString)
72,613✔
2254
                {
2255
                        case DxfFileToken.DictionaryToken:
2256
                                this._reader.ReadNext();
10,678✔
2257
                                xdictHandle = this._reader.ValueAsHandle;
10,678✔
2258
                                this._reader.ReadNext();
10,678✔
2259
                                Debug.Assert(this._reader.DxfCode == DxfCode.ControlString);
10,678✔
2260
                                return;
10,678✔
2261
                        case DxfFileToken.ReactorsToken:
2262
                                reactors = this.readReactors();
59,764✔
2263
                                break;
59,764✔
2264
                        case DxfFileToken.BlkRefToken:
2265
                        default:
2266
                                do
2267
                                {
5,638✔
2268
                                        this._reader.ReadNext();
5,638✔
2269
                                }
5,638✔
2270
                                while (this._reader.DxfCode != DxfCode.ControlString);
5,638✔
2271
                                return;
2,171✔
2272
                }
2273
        }
72,613✔
2274

2275
        private HashSet<ulong> readReactors()
2276
        {
59,764✔
2277
                HashSet<ulong> reactors = new();
59,764✔
2278

2279
                this._reader.ReadNext();
59,764✔
2280

2281
                while (this._reader.DxfCode != DxfCode.ControlString)
126,428✔
2282
                {
66,664✔
2283
                        reactors.Add(this._reader.ValueAsHandle);
66,664✔
2284

2285
                        this._reader.ReadNext();
66,664✔
2286
                }
66,664✔
2287

2288
                return reactors;
59,764✔
2289
        }
59,764✔
2290

2291
        protected bool tryAssignCurrentValue(object cadObject, DxfMap map)
2292
        {
59✔
2293
                if (string.IsNullOrEmpty(this.currentSubclass))
59✔
2294
                {
6✔
2295
                        return false;
6✔
2296
                }
2297

2298
                if (map.SubClasses.TryGetValue(this.currentSubclass, out var subClass))
53!
2299
                {
53✔
2300
                        return this.tryAssignCurrentValue(cadObject, subClass);
53✔
2301
                }
2302
                else
NEW
2303
                {
×
NEW
2304
                        return false;
×
2305
                }
2306
        }
59✔
2307

2308
        protected bool tryAssignCurrentValue(object cadObject, DxfClassMap map)
2309
        {
4,458,169✔
2310
                try
2311
                {
4,458,169✔
2312
                        //Use this method only if the value is not a link between objects
2313
                        if (map.DxfProperties.TryGetValue(this._reader.Code, out DxfProperty dxfProperty))
4,458,169✔
2314
                        {
2,344,626✔
2315
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Count))
2,344,626✔
2316
                                {
13,723✔
2317
                                        return true;
13,723✔
2318
                                }
2319

2320
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Handle)
2,330,903✔
2321
                                        || dxfProperty.ReferenceType.HasFlag(DxfReferenceType.Name))
2,330,903✔
2322
                                {
17,354✔
2323
                                        return false;
17,354✔
2324
                                }
2325

2326
                                object value = this._reader.Value;
2,313,549✔
2327

2328
                                if (dxfProperty.ReferenceType.HasFlag(DxfReferenceType.IsAngle))
2,313,549✔
2329
                                {
26,314✔
2330
                                        value = MathHelper.DegToRad((double)value);
26,314✔
2331
                                }
26,314✔
2332

2333
                                dxfProperty.SetValue(this._reader.Code, cadObject, value);
2,313,549✔
2334

2335
                                return true;
2,313,549✔
2336
                        }
2337
                }
2,113,543✔
NEW
2338
                catch (Exception ex)
×
NEW
2339
                {
×
NEW
2340
                        if (!this._builder.Configuration.Failsafe)
×
2341
                        {
×
NEW
2342
                                throw ex;
×
2343
                        }
2344
                        else
NEW
2345
                        {
×
NEW
2346
                                this._builder.Notify("An error occurred while assigning a property using mapper", NotificationType.Error, ex);
×
UNCOV
2347
                        }
×
UNCOV
2348
                }
×
2349

2350
                return false;
2,113,543✔
2351
        }
4,458,169✔
2352
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc