1 /*
2 
3  dxf_parser.c -- implements DXF support [parsing]
4 
5  version 5.0, 2020 August 1
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29 
30 Contributor(s):
31 
32 Alternatively, the contents of this file may be used under the terms of
33 either the GNU General Public License Version 2 or later (the "GPL"), or
34 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
35 in which case the provisions of the GPL or the LGPL are applicable instead
36 of those above. If you wish to allow use of your version of this file only
37 under the terms of either the GPL or the LGPL, and not to allow others to
38 use your version of this file under the terms of the MPL, indicate your
39 decision by deleting the provisions above and replace them with the notice
40 and other provisions required by the GPL or the LGPL. If you do not delete
41 the provisions above, a recipient may use your version of this file under
42 the terms of any one of the MPL, the GPL or the LGPL.
43 
44 */
45 
46 /*
47 
48 CREDITS:
49 
50 inital development of the DXF module has been funded by:
51 Regione Toscana - Settore Sistema Informativo Territoriale ed Ambientale
52 
53 */
54 
55 #include <stdlib.h>
56 #include <stdio.h>
57 #include <string.h>
58 #include <math.h>
59 
60 #if defined(_WIN32) && !defined(__MINGW32__)
61 #include "config-msvc.h"
62 #else
63 #include "config.h"
64 #endif
65 
66 #include <spatialite/sqlite.h>
67 #include <spatialite/debug.h>
68 
69 #include <spatialite/gaiageo.h>
70 #include <spatialite/gg_dxf.h>
71 #include <spatialite.h>
72 
73 #include "dxf_private.h"
74 
75 #ifndef OMIT_GEOS		/* only if GEOS is enabled */
76 
77 typedef struct dxf_segment
78 {
79 /* a DXF segment */
80     int valid;
81     double ax;
82     double ay;
83     double az;
84     double bx;
85     double by;
86     double bz;
87 } dxfSegment;
88 typedef dxfSegment *dxfSegmentPtr;
89 
90 typedef struct dxf_linked_segments
91 {
92 /* a collection of DXF segments */
93     int count;
94     dxfSegmentPtr segments;
95 } dxfLinkedSegments;
96 typedef dxfLinkedSegments *dxfLinkedSegmentsPtr;
97 
98 typedef struct dxf_rings_collection
99 {
100 /* a collection of rings */
101     gaiaDxfPolylinePtr first;
102     gaiaDxfPolylinePtr last;
103 } dxfRingsCollection;
104 typedef dxfRingsCollection *dxfRingsCollectionPtr;
105 
106 static gaiaDxfHatchSegmPtr
alloc_dxf_hatch_segm(double x0,double y0,double x1,double y1)107 alloc_dxf_hatch_segm (double x0, double y0, double x1, double y1)
108 {
109 /* allocating and initializing a DXF Hatch Segment object */
110     gaiaDxfHatchSegmPtr segm = malloc (sizeof (gaiaDxfHatchSegm));
111     segm->x0 = x0;
112     segm->y0 = y0;
113     segm->x1 = x1;
114     segm->y1 = y1;
115     segm->next = NULL;
116     return segm;
117 }
118 
119 static void
destroy_dxf_hatch_segm(gaiaDxfHatchSegmPtr segm)120 destroy_dxf_hatch_segm (gaiaDxfHatchSegmPtr segm)
121 {
122 /* memory cleanup - destroying a DXF Hatch Segment object */
123     if (segm == NULL)
124 	return;
125     free (segm);
126 }
127 
128 static gaiaDxfBoundaryPathPtr
alloc_dxf_boundary_path()129 alloc_dxf_boundary_path ()
130 {
131 /* allocating and initializing a DXF Boundary Path object */
132     gaiaDxfBoundaryPathPtr path = malloc (sizeof (gaiaDxfBoundaryPath));
133     path->first = NULL;
134     path->last = NULL;
135     path->next = NULL;
136     return path;
137 }
138 
139 static void
insert_dxf_boundary_segm(gaiaDxfBoundaryPathPtr path,gaiaDxfHatchSegmPtr segm)140 insert_dxf_boundary_segm (gaiaDxfBoundaryPathPtr path, gaiaDxfHatchSegmPtr segm)
141 {
142 /* inserting a Segment into a Boundary Path */
143     if (path->first == NULL)
144 	path->first = segm;
145     if (path->last != NULL)
146 	path->last->next = segm;
147     path->last = segm;
148 }
149 
150 static void
destroy_dxf_boundary_path(gaiaDxfBoundaryPathPtr path)151 destroy_dxf_boundary_path (gaiaDxfBoundaryPathPtr path)
152 {
153 /* memory cleanup - destroying a DXF Boundary Path object */
154     gaiaDxfHatchSegmPtr segm;
155     gaiaDxfHatchSegmPtr n_segm;
156     if (path == NULL)
157 	return;
158     segm = path->first;
159     while (segm != NULL)
160       {
161 	  n_segm = segm->next;
162 	  destroy_dxf_hatch_segm (segm);
163 	  segm = n_segm;
164       }
165     free (path);
166 }
167 
168 static gaiaDxfHatchPtr
alloc_dxf_hatch()169 alloc_dxf_hatch ()
170 {
171 /* allocating and initializing a DXF Pattern Hatch object */
172     gaiaDxfHatchPtr hatch = malloc (sizeof (gaiaDxfHatch));
173     hatch->spacing = 0.0;
174     hatch->angle = 0.0;
175     hatch->base_x = 0.0;
176     hatch->base_y = 0.0;
177     hatch->offset_x = 0.0;
178     hatch->offset_y = 0.0;
179     hatch->first = NULL;
180     hatch->last = NULL;
181     hatch->boundary = NULL;
182     hatch->first_out = NULL;
183     hatch->last_out = NULL;
184     hatch->next = NULL;
185     return hatch;
186 }
187 
188 static void
insert_dxf_boundary_path(gaiaDxfHatchPtr hatch,gaiaDxfBoundaryPathPtr path)189 insert_dxf_boundary_path (gaiaDxfHatchPtr hatch, gaiaDxfBoundaryPathPtr path)
190 {
191 /* inserting a Boundary Path into a Hatch */
192     if (hatch->first == NULL)
193 	hatch->first = path;
194     if (hatch->last != NULL)
195 	hatch->last->next = path;
196     hatch->last = path;
197 }
198 
199 static void
insert_dxf_hatch_out(gaiaDxfHatchPtr hatch,gaiaDxfHatchSegmPtr segm)200 insert_dxf_hatch_out (gaiaDxfHatchPtr hatch, gaiaDxfHatchSegmPtr segm)
201 {
202 /* inserting a Segment into a Hatch */
203     if (hatch->first_out == NULL)
204 	hatch->first_out = segm;
205     if (hatch->last_out != NULL)
206 	hatch->last_out->next = segm;
207     hatch->last_out = segm;
208 }
209 
210 static void
destroy_dxf_hatch(gaiaDxfHatchPtr hatch)211 destroy_dxf_hatch (gaiaDxfHatchPtr hatch)
212 {
213 /* memory cleanup - destroying a DXF Pattern Hatch object */
214     gaiaDxfBoundaryPathPtr path;
215     gaiaDxfBoundaryPathPtr n_path;
216     gaiaDxfHatchSegmPtr out;
217     gaiaDxfHatchSegmPtr n_out;
218     if (hatch == NULL)
219 	return;
220     path = hatch->first;
221     while (path != NULL)
222       {
223 	  n_path = path->next;
224 	  destroy_dxf_boundary_path (path);
225 	  path = n_path;
226       }
227     if (hatch->boundary != NULL)
228 	gaiaFreeGeomColl (hatch->boundary);
229     out = hatch->first_out;
230     while (out != NULL)
231       {
232 	  n_out = out->next;
233 	  destroy_dxf_hatch_segm (out);
234 	  out = n_out;
235       }
236     free (hatch);
237 }
238 
239 static int
is_valid_dxf_hatch(gaiaDxfHatchPtr hatch)240 is_valid_dxf_hatch (gaiaDxfHatchPtr hatch)
241 {
242 /* testing for a valid Pattern Hatch */
243     if (hatch->first == NULL)
244 	return 0;
245     return 1;
246 }
247 
248 static void
apply_vertical_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double spacing,double base_x)249 apply_vertical_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
250 		      double spacing, double base_x)
251 {
252 /* vertical Pattern Hatch Lines */
253     double min_x = boundary->MinX;
254     double max_x = boundary->MaxX;
255     double min_y = boundary->MinY;
256     double max_y = boundary->MaxY;
257     double x;
258     gaiaLinestringPtr ln;
259 /* inserting all Hatch Lines into the collection */
260     x = base_x + boundary->MinX;
261     while (x < max_x)
262       {
263 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
264 	  gaiaSetPoint (ln->Coords, 0, x, min_y);
265 	  gaiaSetPoint (ln->Coords, 1, x, max_y);
266 	  x += spacing;
267       }
268     x = base_x + boundary->MinX - spacing;
269     while (x > min_x)
270       {
271 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
272 	  gaiaSetPoint (ln->Coords, 0, x, min_y);
273 	  gaiaSetPoint (ln->Coords, 1, x, max_y);
274 	  x -= spacing;
275       }
276 }
277 
278 static void
apply_horizontal_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double spacing,double base_y)279 apply_horizontal_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom,
280 			double spacing, double base_y)
281 {
282 /* horizontal Pattern Hatch Lines */
283     double min_x = boundary->MinX;
284     double max_x = boundary->MaxX;
285     double min_y = boundary->MinY;
286     double max_y = boundary->MaxY;
287     double y;
288     gaiaLinestringPtr ln;
289 /* inserting all Hatch Lines into the collection */
290     y = base_y + boundary->MinY;
291     while (y < max_y)
292       {
293 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
294 	  gaiaSetPoint (ln->Coords, 0, min_x, y);
295 	  gaiaSetPoint (ln->Coords, 1, max_x, y);
296 	  y += spacing;
297       }
298     y = base_y + boundary->MinY - spacing;
299     while (y > min_y)
300       {
301 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
302 	  gaiaSetPoint (ln->Coords, 0, min_x, y);
303 	  gaiaSetPoint (ln->Coords, 1, max_x, y);
304 	  y -= spacing;
305       }
306 }
307 
308 static void
apply_hatch(gaiaGeomCollPtr boundary,gaiaGeomCollPtr geom,double angle,double spacing,double base_x,double base_y)309 apply_hatch (gaiaGeomCollPtr boundary, gaiaGeomCollPtr geom, double angle,
310 	     double spacing, double base_x, double base_y)
311 {
312 /* ordinary (slant) Pattern Hatch Lines */
313     double min_x = boundary->MinX;
314     double max_x = boundary->MaxX;
315     double min_y = boundary->MinY;
316     double max_y = boundary->MaxY;
317     double ext_x = max_x - min_x;
318     double ext_y = max_y - min_y;
319     double ext = (ext_x > ext_y) ? ext_x : ext_y;
320     double mnx = (ext * 2.0) * -1.0;
321     double mxx = ext * 3.0;
322     double mny = (ext * 2.0) * -1.0;
323     double mxy = ext * 3.0;
324     gaiaLinestringPtr ln;
325     double y;
326 /* inserting all horizontal Hatch Lines into the collection */
327     y = 0.0;
328     while (y < mxy)
329       {
330 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
331 	  gaiaSetPoint (ln->Coords, 0, mnx, y);
332 	  gaiaSetPoint (ln->Coords, 1, mxx, y);
333 	  y += spacing;
334       }
335     y = 0.0 - spacing;
336     while (y > mny)
337       {
338 	  ln = gaiaAddLinestringToGeomColl (geom, 2);
339 	  gaiaSetPoint (ln->Coords, 0, mnx, y);
340 	  gaiaSetPoint (ln->Coords, 1, mxx, y);
341 	  y -= spacing;
342       }
343 /* applying the required rotation */
344     gaiaRotateCoords (geom, angle * -1.0);
345 /* translating into base position */
346     gaiaShiftCoords (geom, base_x + min_x, base_y + min_y);
347 }
348 
349 static void
create_dxf_hatch_lines(const void * p_cache,gaiaDxfHatchPtr hatch,int srid)350 create_dxf_hatch_lines (const void *p_cache, gaiaDxfHatchPtr hatch, int srid)
351 {
352 /* creating Pattern Hatch lines */
353     gaiaDxfBoundaryPathPtr path;
354     gaiaDxfHatchSegmPtr out;
355     gaiaDxfHatchSegmPtr n_out;
356     gaiaGeomCollPtr geom;
357     gaiaGeomCollPtr result;
358     gaiaGeomCollPtr clipped;
359     double angle;
360     double x0;
361     double y0;
362     double x1;
363     double y1;
364     gaiaLinestringPtr ln;
365 
366     if (hatch == NULL)
367 	return;
368     if (hatch->boundary != NULL)
369 	gaiaFreeGeomColl (hatch->boundary);
370     out = hatch->first_out;
371     while (out != NULL)
372       {
373 	  /* cleaning all Pattern Hatch lines */
374 	  n_out = out->next;
375 	  destroy_dxf_hatch_segm (out);
376 	  out = n_out;
377       }
378     hatch->boundary = NULL;
379     hatch->first_out = NULL;
380     hatch->last_out = NULL;
381 
382 /* creating the Pattern Boundary */
383     geom = gaiaAllocGeomColl ();
384     path = hatch->first;
385     while (path != NULL)
386       {
387 	  /* inserting Boundary lines */
388 	  out = path->first;
389 	  while (out != NULL)
390 	    {
391 		/* inserting all Boundary segments into the collection */
392 		ln = gaiaAddLinestringToGeomColl (geom, 2);
393 		gaiaSetPoint (ln->Coords, 0, out->x0, out->y0);
394 		gaiaSetPoint (ln->Coords, 1, out->x1, out->y1);
395 		out = out->next;
396 	    }
397 	  path = path->next;
398       }
399 /* attempting to reassemble the Boundary */
400     if (p_cache != NULL)
401 	result = gaiaPolygonize_r (p_cache, geom, 0);
402     else
403 	result = gaiaPolygonize (geom, 0);
404     gaiaFreeGeomColl (geom);
405     if (result == NULL)
406 	return;
407     gaiaMbrGeometry (result);
408     result->Srid = srid;
409     result->DeclaredType = GAIA_MULTIPOLYGON;
410     hatch->boundary = result;
411     if (hatch->spacing == 0.0)
412       {
413 	  /* no pattern filling, just the boundary */
414 	  return;
415       }
416 /* normalizing the angle */
417     angle = hatch->angle;
418     while (angle >= 360.0)
419 	angle -= 360.0;
420     while (angle <= -360.0)
421 	angle += 360;
422 /* preparing the Hatch filling lines */
423     geom = gaiaAllocGeomColl ();
424     if (angle == 90.0 || angle == -90.0 || angle == 270.0 || angle == -270.0)
425 	apply_vertical_hatch (result, geom, hatch->spacing, hatch->base_x);
426     else if (angle == 0.0 || angle == 180 || angle == -180)
427 	apply_horizontal_hatch (result, geom, hatch->spacing, hatch->base_y);
428     else
429 	apply_hatch (result, geom, angle, hatch->spacing, hatch->base_x,
430 		     hatch->base_y);
431     gaiaMbrGeometry (geom);
432     if (p_cache != NULL)
433 	clipped = gaiaGeometryIntersection_r (p_cache, geom, result);
434     else
435 	clipped = gaiaGeometryIntersection (geom, result);
436     gaiaFreeGeomColl (geom);
437     if (clipped == NULL)
438 	return;
439     ln = clipped->FirstLinestring;
440     while (ln != NULL)
441       {
442 	  if (ln->Points == 2)
443 	    {
444 		gaiaGetPoint (ln->Coords, 0, &x0, &y0);
445 		gaiaGetPoint (ln->Coords, 1, &x1, &y1);
446 		n_out = alloc_dxf_hatch_segm (x0, y0, x1, y1);
447 		insert_dxf_hatch_out (hatch, n_out);
448 	    }
449 	  ln = ln->Next;
450       }
451     gaiaFreeGeomColl (clipped);
452 }
453 
454 static gaiaDxfHolePtr
alloc_dxf_hole(int points)455 alloc_dxf_hole (int points)
456 {
457 /* allocating and initializing a DXF Polygon Hole object */
458     int i;
459     gaiaDxfHolePtr hole = malloc (sizeof (gaiaDxfHole));
460     hole->points = points;
461     hole->x = malloc (sizeof (double) * points);
462     hole->y = malloc (sizeof (double) * points);
463     hole->z = malloc (sizeof (double) * points);
464     for (i = 0; i < points; i++)
465       {
466 	  *(hole->x + i) = 0.0;
467 	  *(hole->y + i) = 0.0;
468 	  *(hole->z + i) = 0.0;
469       }
470     hole->next = NULL;
471     return hole;
472 }
473 
474 static void
insert_dxf_hole(gaiaDxfPolylinePtr line,gaiaDxfHolePtr hole)475 insert_dxf_hole (gaiaDxfPolylinePtr line, gaiaDxfHolePtr hole)
476 {
477 /* inserting an Hole into a Polygon */
478     if (line->first_hole == NULL)
479 	line->first_hole = hole;
480     if (line->last_hole != NULL)
481 	line->last_hole->next = hole;
482     line->last_hole = hole;
483 }
484 
485 static void
destroy_dxf_hole(gaiaDxfHolePtr hole)486 destroy_dxf_hole (gaiaDxfHolePtr hole)
487 {
488 /* memory cleanup - destroying a DXF Hole object */
489     if (hole == NULL)
490 	return;
491     if (hole->x != NULL)
492 	free (hole->x);
493     if (hole->y != NULL)
494 	free (hole->y);
495     if (hole->z != NULL)
496 	free (hole->z);
497     free (hole);
498 }
499 
500 static int
force_closure(gaiaDxfPolylinePtr line)501 force_closure (gaiaDxfPolylinePtr line)
502 {
503 /* checking (and eventually forcing) first/last vertex coherency */
504     if (check_unclosed_polyg (line, 1))
505       {
506 	  /* not properly closed: forcing the last vertex */
507 	  double *ptr_x;
508 	  double *ptr_y;
509 	  double *ptr_z;
510 	  ptr_x = realloc (line->x, sizeof (double) * (line->points + 1));
511 	  ptr_y = realloc (line->y, sizeof (double) * (line->points + 1));
512 	  ptr_z = realloc (line->z, sizeof (double) * (line->points + 1));
513 	  if (ptr_x == NULL || ptr_y == NULL || ptr_z == NULL)
514 	    {
515 		/* some unexpected error happened - giving up */
516 		if (ptr_x == NULL)
517 		    free (ptr_x);
518 		if (ptr_y == NULL)
519 		    free (ptr_y);
520 		if (ptr_z == NULL)
521 		    free (ptr_z);
522 		return 0;
523 	    }
524 	  line->x = ptr_x;
525 	  line->y = ptr_y;
526 	  line->z = ptr_z;
527 	  *(line->x + line->points) = *(line->x + 0);
528 	  *(line->y + line->points) = *(line->y + 0);
529 	  *(line->z + line->points) = *(line->z + 0);
530 	  line->points += 1;
531       }
532     return 1;
533 }
534 
535 static void
linked_rings(const void * p_cache,gaiaDxfPolylinePtr line)536 linked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
537 {
538 /* attempt to identify linked Polygon rings */
539     int i;
540     int i2;
541     int match = 0;
542     double x;
543     double y;
544     double z;
545     gaiaDxfHolePtr hole;
546     dxfLinkedSegmentsPtr coll;
547     dxfSegmentPtr seg;
548     dxfSegmentPtr seg2;
549     gaiaGeomCollPtr geom;
550     gaiaGeomCollPtr result;
551     gaiaPolygonPtr pg;
552     gaiaRingPtr rng;
553     int pgs;
554     int ok;
555 
556     if (line == NULL)
557 	return;
558     if (line->points <= 0)
559 	return;
560     if (line->is_closed == 0)
561 	return;
562 
563     if (!force_closure (line))
564 	return;
565 
566     coll = malloc (sizeof (dxfLinkedSegments));
567     coll->count = line->points - 1;
568     coll->segments = malloc (sizeof (dxfSegment) * coll->count);
569     x = *(line->x + 0);
570     y = *(line->y + 0);
571     z = *(line->z + 0);
572     for (i2 = 0, i = 1; i < line->points; i++, i2++)
573       {
574 	  /* initializing all segments */
575 	  seg = &(coll->segments[i2]);
576 	  seg->valid = 1;
577 	  seg->ax = x;
578 	  seg->ay = y;
579 	  seg->az = z;
580 	  x = *(line->x + i);
581 	  y = *(line->y + i);
582 	  z = *(line->z + i);
583 	  seg->bx = x;
584 	  seg->by = y;
585 	  seg->bz = z;
586       }
587 
588     for (i = 0; i < coll->count - 1; i++)
589       {
590 	  /* testing for linked polygon holes */
591 	  seg = &(coll->segments[i]);
592 	  if (seg->valid == 0)
593 	      continue;
594 	  for (i2 = i + 1; i2 < coll->count; i2++)
595 	    {
596 		seg2 = &(coll->segments[i2]);
597 		if (seg2->valid == 0)
598 		    continue;
599 		if ((seg->ax == seg2->ax && seg->ay == seg2->ay
600 		     && seg->az == seg2->az && seg->bx == seg2->bx
601 		     && seg->by == seg2->by && seg->bz == seg2->bz)
602 		    || (seg->ax == seg2->bx && seg->ay == seg2->by
603 			&& seg->az == seg2->bz && seg->bx == seg2->ax
604 			&& seg->by == seg2->ay && seg->bz == seg2->az))
605 		  {
606 		      /* found a linked segment */
607 		      seg->valid = 0;
608 		      seg2->valid = 0;
609 		      match = 1;
610 		  }
611 	    }
612       }
613 
614     if (match == 0)
615       {
616 	  /* no link segment was found - quitting */
617 	  free (coll->segments);
618 	  free (coll);
619 	  return;
620       }
621 
622 /* building a candidate geometry (multilinestring) */
623     geom = gaiaAllocGeomCollXYZ ();
624     for (i = 0; i < coll->count; i++)
625       {
626 	  seg = &(coll->segments[i]);
627 	  if (seg->valid)
628 	    {
629 		/* inserting a valid segment into the collection */
630 		gaiaLinestringPtr ln = gaiaAddLinestringToGeomColl (geom, 2);
631 		gaiaSetPointXYZ (ln->Coords, 0, seg->ax, seg->ay, seg->az);
632 		gaiaSetPointXYZ (ln->Coords, 1, seg->bx, seg->by, seg->bz);
633 	    }
634       }
635 /* freeing the linked segments list */
636     free (coll->segments);
637     free (coll);
638 
639 /* attempting to reassemble a polygon */
640     if (p_cache != NULL)
641 	result = gaiaPolygonize_r (p_cache, geom, 0);
642     else
643 	result = gaiaPolygonize (geom, 0);
644     gaiaFreeGeomColl (geom);
645     if (result == NULL)
646 	return;
647 
648 /* checking the returned polygon for validity */
649     pgs = 0;
650     ok = 1;
651     pg = result->FirstPolygon;
652     while (pg != NULL)
653       {
654 	  pgs++;
655 	  if (pg->NumInteriors == 0)
656 	      ok = 0;
657 	  pg = pg->Next;
658       }
659     if (ok == 1 && pgs == 1)
660       {
661 	  /* found a valid Polygon with internal holes(s) */
662 	  pg = result->FirstPolygon;
663 	  rng = pg->Exterior;
664 	  /* rebuilding the exterior ring */
665 	  free (line->x);
666 	  free (line->y);
667 	  free (line->z);
668 	  line->points = rng->Points;
669 	  line->x = malloc (sizeof (double) * line->points);
670 	  line->y = malloc (sizeof (double) * line->points);
671 	  line->z = malloc (sizeof (double) * line->points);
672 	  for (i = 0; i < line->points; i++)
673 	    {
674 		/* setting the exterior ring points */
675 		gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
676 		*(line->x + i) = x;
677 		*(line->y + i) = y;
678 		*(line->z + i) = z;
679 	    }
680 	  for (i2 = 0; i2 < pg->NumInteriors; i2++)
681 	    {
682 		/* saving the Holes */
683 		rng = pg->Interiors + i2;
684 		hole = alloc_dxf_hole (rng->Points);
685 		insert_dxf_hole (line, hole);
686 		for (i = 0; i < hole->points; i++)
687 		  {
688 		      /* setting the interior ring points */
689 		      gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
690 		      *(hole->x + i) = x;
691 		      *(hole->y + i) = y;
692 		      *(hole->z + i) = z;
693 		  }
694 	    }
695       }
696     gaiaFreeGeomColl (result);
697 /* forcing the closure flag */
698     line->is_closed = 1;
699 }
700 
701 static void
insert_dxf_hatch(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfHatchPtr hatch)702 insert_dxf_hatch (gaiaDxfParserPtr dxf, const char *layer_name,
703 		  gaiaDxfHatchPtr hatch)
704 {
705 /* inserting a HATCH object into the appropriate Layer */
706     gaiaDxfLayerPtr lyr = dxf->first_layer;
707     while (lyr != NULL)
708       {
709 	  if (strcmp (lyr->layer_name, layer_name) == 0)
710 	    {
711 		/* found the matching Layer */
712 		if (lyr->first_hatch == NULL)
713 		    lyr->first_hatch = hatch;
714 		if (lyr->last_hatch != NULL)
715 		    lyr->last_hatch->next = hatch;
716 		lyr->last_hatch = hatch;
717 		return;
718 	    }
719 	  lyr = lyr->next;
720       }
721     destroy_dxf_hatch (hatch);
722 }
723 
724 static void
insert_dxf_block_hatch(gaiaDxfParserPtr dxf,gaiaDxfHatchPtr hatch)725 insert_dxf_block_hatch (gaiaDxfParserPtr dxf, gaiaDxfHatchPtr hatch)
726 {
727 /* inserting a HATCH object into the current Block */
728     if (dxf->curr_block.first_hatch == NULL)
729 	dxf->curr_block.first_hatch = hatch;
730     if (dxf->curr_block.last_hatch != NULL)
731 	dxf->curr_block.last_hatch->next = hatch;
732     dxf->curr_block.last_hatch = hatch;
733 }
734 
735 static gaiaDxfExtraAttrPtr
alloc_dxf_extra()736 alloc_dxf_extra ()
737 {
738 /* allocating and initializing a DXF Extra Attribute object */
739     gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
740     ext->key = NULL;
741     ext->value = NULL;
742     ext->next = NULL;
743     return ext;
744 }
745 
746 static gaiaDxfExtraAttrPtr
clone_dxf_extra(gaiaDxfExtraAttrPtr org)747 clone_dxf_extra (gaiaDxfExtraAttrPtr org)
748 {
749 /* cloning a DXF Extra Attribute object */
750     int len;
751     gaiaDxfExtraAttrPtr ext = malloc (sizeof (gaiaDxfExtraAttr));
752     len = strlen (org->key);
753     ext->key = malloc (len + 1);
754     strcpy (ext->key, org->key);
755     len = strlen (org->value);
756     ext->value = malloc (len + 1);
757     strcpy (ext->value, org->value);
758     ext->next = NULL;
759     return ext;
760 }
761 
762 static void
destroy_dxf_extra(gaiaDxfExtraAttrPtr ext)763 destroy_dxf_extra (gaiaDxfExtraAttrPtr ext)
764 {
765 /* memory cleanup - destroying a DXF Extra Attribute object */
766     if (ext == NULL)
767 	return;
768     if (ext->key != NULL)
769 	free (ext->key);
770     if (ext->value != NULL)
771 	free (ext->value);
772     free (ext);
773 }
774 
775 static gaiaDxfTextPtr
alloc_dxf_text(const char * label,double x,double y,double z,double angle)776 alloc_dxf_text (const char *label, double x, double y, double z, double angle)
777 {
778 /* allocating and initializing a DXF Text object */
779     int len;
780     gaiaDxfTextPtr txt = malloc (sizeof (gaiaDxfText));
781     len = strlen (label);
782     txt->label = malloc (len + 1);
783     strcpy (txt->label, label);
784     txt->x = x;
785     txt->y = y;
786     txt->z = z;
787     txt->angle = angle;
788     txt->first = NULL;
789     txt->last = NULL;
790     txt->next = NULL;
791     return txt;
792 }
793 
794 static void
destroy_dxf_text(gaiaDxfTextPtr txt)795 destroy_dxf_text (gaiaDxfTextPtr txt)
796 {
797 /* memory cleanup - destroying a DXF Text object */
798     gaiaDxfExtraAttrPtr ext;
799     gaiaDxfExtraAttrPtr n_ext;
800     if (txt == NULL)
801 	return;
802     if (txt->label != NULL)
803 	free (txt->label);
804     ext = txt->first;
805     while (ext != NULL)
806       {
807 	  n_ext = ext->next;
808 	  destroy_dxf_extra (ext);
809 	  ext = n_ext;
810       }
811     free (txt);
812 }
813 
814 static int
is_3d_text(gaiaDxfTextPtr txt)815 is_3d_text (gaiaDxfTextPtr txt)
816 {
817 /* testing if it's really a 3D Text */
818     if (txt->z == 0.0)
819 	return 0;
820     return 1;
821 }
822 
823 static void
insert_dxf_text(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfTextPtr txt)824 insert_dxf_text (gaiaDxfParserPtr dxf, const char *layer_name,
825 		 gaiaDxfTextPtr txt)
826 {
827 /* inserting a TEXT object into the appropriate Layer */
828     gaiaDxfLayerPtr lyr = dxf->first_layer;
829     while (lyr != NULL)
830       {
831 	  if (strcmp (lyr->layer_name, layer_name) == 0)
832 	    {
833 		/* found the matching Layer */
834 		if (lyr->first_text == NULL)
835 		    lyr->first_text = txt;
836 		if (lyr->last_text != NULL)
837 		    lyr->last_text->next = txt;
838 		lyr->last_text = txt;
839 		if (dxf->force_dims == GAIA_DXF_FORCE_2D
840 		    || dxf->force_dims == GAIA_DXF_FORCE_3D)
841 		    ;
842 		else
843 		  {
844 		      if (is_3d_text (txt))
845 			  lyr->is3Dtext = 1;
846 		  }
847 		txt->first = dxf->first_ext;
848 		txt->last = dxf->last_ext;
849 		dxf->first_ext = NULL;
850 		dxf->last_ext = NULL;
851 		if (txt->first != NULL)
852 		    lyr->hasExtraText = 1;
853 		return;
854 	    }
855 	  lyr = lyr->next;
856       }
857     destroy_dxf_text (txt);
858 }
859 
860 static void
insert_dxf_block_text(gaiaDxfParserPtr dxf,gaiaDxfTextPtr txt)861 insert_dxf_block_text (gaiaDxfParserPtr dxf, gaiaDxfTextPtr txt)
862 {
863 /* inserting a TEXT object into the current Block */
864     if (dxf->curr_block.first_text == NULL)
865 	dxf->curr_block.first_text = txt;
866     if (dxf->curr_block.last_text != NULL)
867 	dxf->curr_block.last_text->next = txt;
868     dxf->curr_block.last_text = txt;
869     if (dxf->force_dims == GAIA_DXF_FORCE_2D
870 	|| dxf->force_dims == GAIA_DXF_FORCE_3D)
871 	;
872     else
873       {
874 	  if (is_3d_text (txt))
875 	      dxf->curr_block.is3Dtext = 1;
876       }
877 }
878 
879 static gaiaDxfInsertPtr
alloc_dxf_insert(const char * block_id,double x,double y,double z,double scale_x,double scale_y,double scale_z,double angle)880 alloc_dxf_insert (const char *block_id, double x, double y, double z,
881 		  double scale_x, double scale_y, double scale_z, double angle)
882 {
883 /* allocating and initializing a DXF Insertt object */
884     int len;
885     gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
886     len = strlen (block_id);
887     ins->block_id = malloc (len + 1);
888     strcpy (ins->block_id, block_id);
889     ins->x = x;
890     ins->y = y;
891     ins->z = z;
892     ins->scale_x = scale_x;
893     ins->scale_y = scale_y;
894     ins->scale_z = scale_z;
895     ins->angle = angle;
896     ins->hasText = 0;
897     ins->hasPoint = 0;
898     ins->hasLine = 0;
899     ins->hasPolyg = 0;
900     ins->hasHatch = 0;
901     ins->is3Dtext = 0;
902     ins->is3Dpoint = 0;
903     ins->is3Dline = 0;
904     ins->is3Dpolyg = 0;
905     ins->first = NULL;
906     ins->last = NULL;
907     ins->next = NULL;
908     return ins;
909 }
910 
911 static gaiaDxfInsertPtr
clone_dxf_insert(gaiaDxfInsertPtr org)912 clone_dxf_insert (gaiaDxfInsertPtr org)
913 {
914 /* cloning a DXF Insertt object */
915     gaiaDxfExtraAttrPtr ext_org;
916     gaiaDxfExtraAttrPtr ext;
917     int len;
918     gaiaDxfInsertPtr ins = malloc (sizeof (gaiaDxfInsert));
919     len = strlen (org->block_id);
920     ins->block_id = malloc (len + 1);
921     strcpy (ins->block_id, org->block_id);
922     ins->x = org->x;
923     ins->y = org->y;
924     ins->z = org->z;
925     ins->scale_x = org->scale_x;
926     ins->scale_y = org->scale_y;
927     ins->scale_z = org->scale_z;
928     ins->angle = org->angle;
929     ins->hasText = org->hasText;
930     ins->hasPoint = org->hasPoint;
931     ins->hasLine = org->hasLine;
932     ins->hasPolyg = org->hasPolyg;
933     ins->hasHatch = org->hasHatch;
934     ins->is3Dtext = org->is3Dtext;
935     ins->is3Dpoint = org->is3Dpoint;
936     ins->is3Dline = org->is3Dline;
937     ins->is3Dpolyg = org->is3Dpolyg;
938     ins->first = NULL;
939     ins->last = NULL;
940     ext_org = org->first;
941     while (ext_org != NULL)
942       {
943 	  ext = clone_dxf_extra (ext_org);
944 	  if (ins->first == NULL)
945 	      ins->first = ext;
946 	  if (ins->last != NULL)
947 	      ins->last->next = ext;
948 	  ins->last = ext;
949 	  ext_org = ext_org->next;
950       }
951     ins->next = NULL;
952     return ins;
953 }
954 
955 static void
destroy_dxf_insert(gaiaDxfInsertPtr ins)956 destroy_dxf_insert (gaiaDxfInsertPtr ins)
957 {
958 /* memory cleanup - destroying a DXF Insert object */
959     gaiaDxfExtraAttrPtr ext;
960     gaiaDxfExtraAttrPtr n_ext;
961     if (ins == NULL)
962 	return;
963     if (ins->block_id != NULL)
964 	free (ins->block_id);
965     ext = ins->first;
966     while (ext != NULL)
967       {
968 	  n_ext = ext->next;
969 	  destroy_dxf_extra (ext);
970 	  ext = n_ext;
971       }
972     free (ins);
973 }
974 
975 static void
insert_dxf_insert(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfInsertPtr ins)976 insert_dxf_insert (gaiaDxfParserPtr dxf, const char *layer_name,
977 		   gaiaDxfInsertPtr ins)
978 {
979 /* inserting an INSERT object into the appropriate Layer */
980     gaiaDxfLayerPtr lyr = dxf->first_layer;
981     while (lyr != NULL)
982       {
983 	  if (strcmp (lyr->layer_name, layer_name) == 0)
984 	    {
985 		/* found the matching Layer */
986 		ins->first = dxf->first_ext;
987 		ins->last = dxf->last_ext;
988 		dxf->first_ext = NULL;
989 		dxf->last_ext = NULL;
990 		if (ins->hasText)
991 		  {
992 		      /* indirect Text reference */
993 		      gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
994 		      if (lyr->first_ins_text == NULL)
995 			  lyr->first_ins_text = ins2;
996 		      if (lyr->last_ins_text != NULL)
997 			  lyr->last_ins_text->next = ins2;
998 		      lyr->last_ins_text = ins2;
999 		      if (ins2->is3Dtext)
1000 			  lyr->is3DinsText = 1;
1001 		      if (ins2->first != NULL)
1002 			  lyr->hasExtraInsText = 1;
1003 		  }
1004 		if (ins->hasPoint)
1005 		  {
1006 		      /* indirect Point reference */
1007 		      gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1008 		      if (lyr->first_ins_point == NULL)
1009 			  lyr->first_ins_point = ins2;
1010 		      if (lyr->last_ins_point != NULL)
1011 			  lyr->last_ins_point->next = ins2;
1012 		      lyr->last_ins_point = ins2;
1013 		      if (ins2->is3Dpoint)
1014 			  lyr->is3DinsPoint = 1;
1015 		      if (ins2->first != NULL)
1016 			  lyr->hasExtraInsPoint = 1;
1017 		  }
1018 		if (ins->hasLine)
1019 		  {
1020 		      /* indirect Polyline (Linestring) reference */
1021 		      gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1022 		      if (lyr->first_ins_line == NULL)
1023 			  lyr->first_ins_line = ins2;
1024 		      if (lyr->last_ins_line != NULL)
1025 			  lyr->last_ins_line->next = ins2;
1026 		      lyr->last_ins_line = ins2;
1027 		      if (ins2->is3Dline)
1028 			  lyr->is3DinsLine = 1;
1029 		      if (ins2->first != NULL)
1030 			  lyr->hasExtraInsLine = 1;
1031 		  }
1032 		if (ins->hasPolyg)
1033 		  {
1034 		      /* indirect Polyline (Polygon) reference */
1035 		      gaiaDxfInsertPtr ins2 = clone_dxf_insert (ins);
1036 		      if (lyr->first_ins_polyg == NULL)
1037 			  lyr->first_ins_polyg = ins2;
1038 		      if (lyr->last_ins_polyg != NULL)
1039 			  lyr->last_ins_polyg->next = ins2;
1040 		      lyr->last_ins_polyg = ins2;
1041 		      if (ins2->is3Dpolyg)
1042 			  lyr->is3DinsPolyg = 1;
1043 		      if (ins2->first != NULL)
1044 			  lyr->hasExtraInsPolyg = 1;
1045 		  }
1046 		destroy_dxf_insert (ins);
1047 		return;
1048 	    }
1049 	  lyr = lyr->next;
1050       }
1051     destroy_dxf_insert (ins);
1052 }
1053 
1054 static gaiaDxfPointPtr
alloc_dxf_point(double x,double y,double z)1055 alloc_dxf_point (double x, double y, double z)
1056 {
1057 /* allocating and initializing a DXF Point object */
1058     gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
1059     pt->x = x;
1060     pt->y = y;
1061     pt->z = z;
1062     pt->next = NULL;
1063     pt->first = NULL;
1064     pt->last = NULL;
1065     return pt;
1066 }
1067 
1068 static void
destroy_dxf_point(gaiaDxfPointPtr pt)1069 destroy_dxf_point (gaiaDxfPointPtr pt)
1070 {
1071 /* memory cleanup - destroying a DXF Point object */
1072     gaiaDxfExtraAttrPtr ext;
1073     gaiaDxfExtraAttrPtr n_ext;
1074     if (pt == NULL)
1075 	return;
1076     ext = pt->first;
1077     while (ext != NULL)
1078       {
1079 	  n_ext = ext->next;
1080 	  destroy_dxf_extra (ext);
1081 	  ext = n_ext;
1082       }
1083     free (pt);
1084 }
1085 
1086 static int
is_3d_point(gaiaDxfPointPtr pt)1087 is_3d_point (gaiaDxfPointPtr pt)
1088 {
1089 /* testing if it's really a 3D Point */
1090     if (pt->z == 0.0)
1091 	return 0;
1092     return 1;
1093 }
1094 
1095 static void
insert_dxf_point(gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfPointPtr pt)1096 insert_dxf_point (gaiaDxfParserPtr dxf, const char *layer_name,
1097 		  gaiaDxfPointPtr pt)
1098 {
1099 /* inserting a POINT object into the appropriate Layer */
1100     gaiaDxfLayerPtr lyr = dxf->first_layer;
1101     while (lyr != NULL)
1102       {
1103 	  if (strcmp (lyr->layer_name, layer_name) == 0)
1104 	    {
1105 		/* found the matching Layer */
1106 		if (lyr->first_point == NULL)
1107 		    lyr->first_point = pt;
1108 		if (lyr->last_point != NULL)
1109 		    lyr->last_point->next = pt;
1110 		lyr->last_point = pt;
1111 		if (dxf->force_dims == GAIA_DXF_FORCE_2D
1112 		    || dxf->force_dims == GAIA_DXF_FORCE_3D)
1113 		    ;
1114 		else
1115 		  {
1116 		      if (is_3d_point (pt))
1117 			  lyr->is3Dpoint = 1;
1118 		  }
1119 		pt->first = dxf->first_ext;
1120 		pt->last = dxf->last_ext;
1121 		dxf->first_ext = NULL;
1122 		dxf->last_ext = NULL;
1123 		if (pt->first != NULL)
1124 		    lyr->hasExtraPoint = 1;
1125 		return;
1126 	    }
1127 	  lyr = lyr->next;
1128       }
1129     destroy_dxf_point (pt);
1130 }
1131 
1132 static void
insert_dxf_block_point(gaiaDxfParserPtr dxf,gaiaDxfPointPtr pt)1133 insert_dxf_block_point (gaiaDxfParserPtr dxf, gaiaDxfPointPtr pt)
1134 {
1135 /* inserting a POINT object into the current Block */
1136     if (dxf->curr_block.first_point == NULL)
1137 	dxf->curr_block.first_point = pt;
1138     if (dxf->curr_block.last_point != NULL)
1139 	dxf->curr_block.last_point->next = pt;
1140     dxf->curr_block.last_point = pt;
1141     if (dxf->force_dims == GAIA_DXF_FORCE_2D
1142 	|| dxf->force_dims == GAIA_DXF_FORCE_3D)
1143 	;
1144     else
1145       {
1146 	  if (is_3d_point (pt))
1147 	      dxf->curr_block.is3Dpoint = 1;
1148       }
1149 }
1150 
1151 static gaiaDxfPolylinePtr
alloc_dxf_polyline(int is_closed,int points)1152 alloc_dxf_polyline (int is_closed, int points)
1153 {
1154 /* allocating and initializing a DXF Polyline object */
1155     int i;
1156     gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
1157     ln->is_closed = is_closed;
1158     ln->points = points;
1159     ln->x = malloc (sizeof (double) * points);
1160     ln->y = malloc (sizeof (double) * points);
1161     ln->z = malloc (sizeof (double) * points);
1162     for (i = 0; i < points; i++)
1163       {
1164 	  *(ln->x + i) = 0.0;
1165 	  *(ln->y + i) = 0.0;
1166 	  *(ln->z + i) = 0.0;
1167       }
1168     ln->first_hole = NULL;
1169     ln->last_hole = NULL;
1170     ln->first = NULL;
1171     ln->last = NULL;
1172     ln->next = NULL;
1173     return ln;
1174 }
1175 
1176 static gaiaDxfPolylinePtr
alloc_dxf_line(double x0,double y0,double z0,double x1,double y1,double z1)1177 alloc_dxf_line (double x0, double y0, double z0, double x1, double y1,
1178 		double z1)
1179 {
1180 /* allocating and initializing a DXF Line object */
1181     gaiaDxfPolylinePtr ln = malloc (sizeof (gaiaDxfPolyline));
1182     ln->is_closed = 0;
1183     ln->points = 2;
1184     ln->x = malloc (sizeof (double) * 2);
1185     ln->y = malloc (sizeof (double) * 2);
1186     ln->z = malloc (sizeof (double) * 2);
1187     *(ln->x + 0) = x0;
1188     *(ln->y + 0) = y0;
1189     *(ln->z + 0) = z0;
1190     *(ln->x + 1) = x1;
1191     *(ln->y + 1) = y1;
1192     *(ln->z + 1) = z1;
1193     ln->first_hole = NULL;
1194     ln->last_hole = NULL;
1195     ln->first = NULL;
1196     ln->last = NULL;
1197     ln->next = NULL;
1198     return ln;
1199 }
1200 
1201 static void
destroy_dxf_polyline(gaiaDxfPolylinePtr ln)1202 destroy_dxf_polyline (gaiaDxfPolylinePtr ln)
1203 {
1204 /* memory cleanup - destroying a DXF Polyline object */
1205     gaiaDxfExtraAttrPtr ext;
1206     gaiaDxfExtraAttrPtr n_ext;
1207     gaiaDxfHolePtr hole;
1208     gaiaDxfHolePtr n_hole;
1209     if (ln == NULL)
1210 	return;
1211     if (ln->x != NULL)
1212 	free (ln->x);
1213     if (ln->y != NULL)
1214 	free (ln->y);
1215     if (ln->z != NULL)
1216 	free (ln->z);
1217     ext = ln->first;
1218     while (ext != NULL)
1219       {
1220 	  n_ext = ext->next;
1221 	  destroy_dxf_extra (ext);
1222 	  ext = n_ext;
1223       }
1224     hole = ln->first_hole;
1225     while (hole != NULL)
1226       {
1227 	  n_hole = hole->next;
1228 	  destroy_dxf_hole (hole);
1229 	  hole = n_hole;
1230       }
1231     free (ln);
1232 }
1233 
1234 static int
is_3d_line(gaiaDxfPolylinePtr ln)1235 is_3d_line (gaiaDxfPolylinePtr ln)
1236 {
1237 /* testing if it's really a 3D Polyline */
1238     gaiaDxfHolePtr hole;
1239     int i;
1240     for (i = 0; i < ln->points; i++)
1241       {
1242 	  if (*(ln->z + i) != 0.0)
1243 	      return 1;
1244       }
1245     hole = ln->first_hole;
1246     while (hole != NULL)
1247       {
1248 	  for (i = 0; i < hole->points; i++)
1249 	    {
1250 		if (*(hole->z + i) != 0.0)
1251 		    return 1;
1252 	    }
1253       }
1254     return 0;
1255 }
1256 
1257 static dxfRingsCollectionPtr
alloc_dxf_rings()1258 alloc_dxf_rings ()
1259 {
1260 /* allocating an empty Rings Collection */
1261     dxfRingsCollectionPtr coll = malloc (sizeof (dxfRingsCollection));
1262     coll->first = NULL;
1263     coll->last = NULL;
1264     return coll;
1265 }
1266 
1267 static void
destroy_dxf_rings(dxfRingsCollectionPtr coll)1268 destroy_dxf_rings (dxfRingsCollectionPtr coll)
1269 {
1270 /* memory cleanup - destroying a Rings Collection */
1271     gaiaDxfPolylinePtr ln;
1272     gaiaDxfPolylinePtr n_ln;
1273     if (coll == NULL)
1274 	return;
1275     ln = coll->first;
1276     while (ln != NULL)
1277       {
1278 	  n_ln = ln->next;
1279 	  destroy_dxf_polyline (ln);
1280 	  ln = n_ln;
1281       }
1282     free (coll);
1283 }
1284 
1285 static void
insert_dxf_ring(dxfRingsCollectionPtr coll,gaiaDxfPolylinePtr line,int start,int end)1286 insert_dxf_ring (dxfRingsCollectionPtr coll, gaiaDxfPolylinePtr line, int start,
1287 		 int end)
1288 {
1289 /* inserting a Ring into the collection */
1290     int i;
1291     int i2;
1292     int points = end - start + 1;
1293     gaiaDxfPolylinePtr out = alloc_dxf_polyline (1, points);
1294     for (i2 = 0, i = start; i <= end; i++, i2++)
1295       {
1296 	  *(out->x + i2) = *(line->x + i);
1297 	  *(out->y + i2) = *(line->y + i);
1298 	  *(out->z + i2) = *(line->z + i);
1299       }
1300     if (coll->first == NULL)
1301 	coll->first = out;
1302     if (coll->last != NULL)
1303 	coll->last->next = out;
1304     coll->last = out;
1305 }
1306 
1307 static void
unlinked_rings(const void * p_cache,gaiaDxfPolylinePtr line)1308 unlinked_rings (const void *p_cache, gaiaDxfPolylinePtr line)
1309 {
1310 /* attempt to identify unlinked Polygon rings */
1311     int invalid = 0;
1312     int start;
1313     int count;
1314     double x;
1315     double y;
1316     double z;
1317     int i;
1318     int i2;
1319     gaiaDxfHolePtr hole;
1320     dxfRingsCollectionPtr coll;
1321     gaiaDxfPolylinePtr ring;
1322     gaiaGeomCollPtr geom;
1323     gaiaGeomCollPtr result;
1324     gaiaPolygonPtr pg;
1325     gaiaRingPtr rng;
1326     int pgs;
1327     int ok;
1328 
1329     if (line == NULL)
1330 	return;
1331     if (line->points <= 0)
1332 	return;
1333     if (line->is_closed == 0)
1334 	return;
1335 
1336     if (!force_closure (line))
1337 	return;
1338 
1339     coll = alloc_dxf_rings ();
1340     start = 0;
1341     while (start < line->points - 1)
1342       {
1343 	  /* looping on candidate rings */
1344 	  x = *(line->x + start);
1345 	  y = *(line->y + start);
1346 	  z = *(line->z + start);
1347 	  invalid = 1;
1348 	  for (i = start + 1; i < line->points; i++)
1349 	    {
1350 		if (*(line->x + i) == x && *(line->y + i) == y
1351 		    && *(line->z + i) == z)
1352 		  {
1353 		      insert_dxf_ring (coll, line, start, i);
1354 		      start = i + 1;
1355 		      invalid = 0;
1356 		      break;
1357 		  }
1358 	    }
1359 	  if (invalid)
1360 	      break;
1361       }
1362 
1363     count = 0;
1364     ring = coll->first;
1365     while (ring != NULL)
1366       {
1367 	  count++;
1368 	  ring = ring->next;
1369       }
1370     if (count < 2)
1371 	invalid = 1;
1372     if (invalid)
1373       {
1374 	  /* no unlinked rings were found - quitting */
1375 	  destroy_dxf_rings (coll);
1376 	  return;
1377       }
1378 
1379 /* building a candidate geometry (multilinestring) */
1380     geom = gaiaAllocGeomCollXYZ ();
1381     ring = coll->first;
1382     while (ring != NULL)
1383       {
1384 	  /* inserting a ring into the collection */
1385 	  gaiaLinestringPtr ln =
1386 	      gaiaAddLinestringToGeomColl (geom, ring->points);
1387 	  for (i = 0; i < ring->points; i++)
1388 	    {
1389 		gaiaSetPointXYZ (ln->Coords, i, *(ring->x + i), *(ring->y + i),
1390 				 *(ring->z + i));
1391 	    }
1392 	  ring = ring->next;
1393       }
1394 /* freeing the rings list */
1395     destroy_dxf_rings (coll);
1396 
1397 /* attempting to reassemble a polygon */
1398     if (p_cache != NULL)
1399 	result = gaiaPolygonize_r (p_cache, geom, 0);
1400     else
1401 	result = gaiaPolygonize (geom, 0);
1402     gaiaFreeGeomColl (geom);
1403     if (result == NULL)
1404 	return;
1405 
1406 /* checking the returned polygon for validity */
1407     pgs = 0;
1408     ok = 1;
1409     pg = result->FirstPolygon;
1410     while (pg != NULL)
1411       {
1412 	  pgs++;
1413 	  if (pg->NumInteriors == 0)
1414 	      ok = 0;
1415 	  pg = pg->Next;
1416       }
1417     if (ok == 1 && pgs == 1)
1418       {
1419 	  /* found a valid Polygon with internal holes(s) */
1420 	  pg = result->FirstPolygon;
1421 	  rng = pg->Exterior;
1422 	  /* rebuilding the exterior ring */
1423 	  free (line->x);
1424 	  free (line->y);
1425 	  free (line->z);
1426 	  line->points = rng->Points;
1427 	  line->x = malloc (sizeof (double) * line->points);
1428 	  line->y = malloc (sizeof (double) * line->points);
1429 	  line->z = malloc (sizeof (double) * line->points);
1430 	  for (i = 0; i < line->points; i++)
1431 	    {
1432 		/* setting the exterior ring points */
1433 		gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
1434 		*(line->x + i) = x;
1435 		*(line->y + i) = y;
1436 		*(line->z + i) = z;
1437 	    }
1438 	  for (i2 = 0; i2 < pg->NumInteriors; i2++)
1439 	    {
1440 		/* saving the Holes */
1441 		rng = pg->Interiors + i2;
1442 		hole = alloc_dxf_hole (rng->Points);
1443 		insert_dxf_hole (line, hole);
1444 		for (i = 0; i < hole->points; i++)
1445 		  {
1446 		      /* setting the interior ring points */
1447 		      gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z);
1448 		      *(hole->x + i) = x;
1449 		      *(hole->y + i) = y;
1450 		      *(hole->z + i) = z;
1451 		  }
1452 	    }
1453       }
1454     gaiaFreeGeomColl (result);
1455 /* forcing the closure flag */
1456     line->is_closed = 1;
1457 }
1458 
1459 static void
insert_dxf_polyline(const void * p_cache,gaiaDxfParserPtr dxf,const char * layer_name,gaiaDxfPolylinePtr ln)1460 insert_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
1461 		     const char *layer_name, gaiaDxfPolylinePtr ln)
1462 {
1463 /* inserting a POLYLINE object into the appropriate Layer */
1464     gaiaDxfLayerPtr lyr = dxf->first_layer;
1465     while (lyr != NULL)
1466       {
1467 	  if (strcmp (lyr->layer_name, layer_name) == 0)
1468 	    {
1469 		/* found the matching Layer */
1470 		if (dxf->linked_rings)
1471 		    linked_rings (p_cache, ln);
1472 		if (dxf->unlinked_rings)
1473 		    unlinked_rings (p_cache, ln);
1474 		if (ln->is_closed)
1475 		  {
1476 		      /* it's a Ring */
1477 		      if (lyr->first_polyg == NULL)
1478 			  lyr->first_polyg = ln;
1479 		      if (lyr->last_polyg != NULL)
1480 			  lyr->last_polyg->next = ln;
1481 		      lyr->last_polyg = ln;
1482 		      if (dxf->force_dims == GAIA_DXF_FORCE_2D
1483 			  || dxf->force_dims == GAIA_DXF_FORCE_3D)
1484 			  ;
1485 		      else
1486 			{
1487 			    if (is_3d_line (ln))
1488 				lyr->is3Dpolyg = 1;
1489 			}
1490 		  }
1491 		else
1492 		  {
1493 		      /* it's a Linestring */
1494 		      if (lyr->first_line == NULL)
1495 			  lyr->first_line = ln;
1496 		      if (lyr->last_line != NULL)
1497 			  lyr->last_line->next = ln;
1498 		      lyr->last_line = ln;
1499 		      if (dxf->force_dims == GAIA_DXF_FORCE_2D
1500 			  || dxf->force_dims == GAIA_DXF_FORCE_3D)
1501 			  ;
1502 		      else
1503 			{
1504 			    if (is_3d_line (ln))
1505 				lyr->is3Dline = 1;
1506 			}
1507 		  }
1508 		ln->first = dxf->first_ext;
1509 		ln->last = dxf->last_ext;
1510 		dxf->first_ext = NULL;
1511 		dxf->last_ext = NULL;
1512 		if (ln->is_closed && ln->first != NULL)
1513 		    lyr->hasExtraPolyg = 1;
1514 		if (ln->is_closed == 0 && ln->first != NULL)
1515 		    lyr->hasExtraLine = 1;
1516 		return;
1517 	    }
1518 	  lyr = lyr->next;
1519       }
1520     destroy_dxf_polyline (ln);
1521 }
1522 
1523 static void
insert_dxf_block_polyline(const void * p_cache,gaiaDxfParserPtr dxf,gaiaDxfPolylinePtr ln)1524 insert_dxf_block_polyline (const void *p_cache, gaiaDxfParserPtr dxf,
1525 			   gaiaDxfPolylinePtr ln)
1526 {
1527 /* inserting a POLYLINE object into the current Block */
1528     if (dxf->linked_rings)
1529 	linked_rings (p_cache, ln);
1530     if (dxf->unlinked_rings)
1531 	unlinked_rings (p_cache, ln);
1532     if (ln->is_closed)
1533       {
1534 	  /* it's a Ring */
1535 	  if (dxf->curr_block.first_polyg == NULL)
1536 	      dxf->curr_block.first_polyg = ln;
1537 	  if (dxf->curr_block.last_polyg != NULL)
1538 	      dxf->curr_block.last_polyg->next = ln;
1539 	  dxf->curr_block.last_polyg = ln;
1540 	  if (dxf->force_dims == GAIA_DXF_FORCE_2D
1541 	      || dxf->force_dims == GAIA_DXF_FORCE_3D)
1542 	      ;
1543 	  else
1544 	    {
1545 		if (is_3d_line (ln))
1546 		    dxf->curr_block.is3Dpolyg = 1;
1547 	    }
1548       }
1549     else
1550       {
1551 	  /* it's a Linestring */
1552 	  if (dxf->curr_block.first_line == NULL)
1553 	      dxf->curr_block.first_line = ln;
1554 	  if (dxf->curr_block.last_line != NULL)
1555 	      dxf->curr_block.last_line->next = ln;
1556 	  dxf->curr_block.last_line = ln;
1557 	  if (dxf->force_dims == GAIA_DXF_FORCE_2D
1558 	      || dxf->force_dims == GAIA_DXF_FORCE_3D)
1559 	      ;
1560 	  else
1561 	    {
1562 		if (is_3d_line (ln))
1563 		    dxf->curr_block.is3Dline = 1;
1564 	    }
1565       }
1566     ln->first = dxf->first_ext;
1567     ln->last = dxf->last_ext;
1568     dxf->first_ext = NULL;
1569     dxf->last_ext = NULL;
1570 }
1571 
1572 static gaiaDxfBlockPtr
alloc_dxf_block(const char * layer,const char * id)1573 alloc_dxf_block (const char *layer, const char *id)
1574 {
1575 /* allocating and initializing a DXF Block object */
1576     int len;
1577     gaiaDxfBlockPtr blk = malloc (sizeof (gaiaDxfBlock));
1578     blk->hasInsert = 0;
1579     len = strlen (layer);
1580     blk->layer_name = malloc (len + 1);
1581     strcpy (blk->layer_name, layer);
1582     len = strlen (id);
1583     blk->block_id = malloc (len + 1);
1584     strcpy (blk->block_id, id);
1585     blk->first_text = NULL;
1586     blk->last_text = NULL;
1587     blk->first_point = NULL;
1588     blk->last_point = NULL;
1589     blk->first_line = NULL;
1590     blk->last_line = NULL;
1591     blk->first_polyg = NULL;
1592     blk->last_polyg = NULL;
1593     blk->first_hatch = NULL;
1594     blk->last_hatch = NULL;
1595     blk->is3Dtext = 0;
1596     blk->is3Dpoint = 0;
1597     blk->is3Dline = 0;
1598     blk->is3Dpolyg = 0;
1599     blk->next = NULL;
1600     return blk;
1601 }
1602 
1603 static void
destroy_dxf_block(gaiaDxfBlockPtr blk)1604 destroy_dxf_block (gaiaDxfBlockPtr blk)
1605 {
1606 /* memory cleanup - destroying a DXF Block object */
1607     gaiaDxfTextPtr txt;
1608     gaiaDxfTextPtr n_txt;
1609     gaiaDxfPointPtr pt;
1610     gaiaDxfPointPtr n_pt;
1611     gaiaDxfPolylinePtr ln;
1612     gaiaDxfPolylinePtr n_ln;
1613     gaiaDxfHatchPtr htc;
1614     gaiaDxfHatchPtr n_htc;
1615     if (blk == NULL)
1616 	return;
1617     if (blk->layer_name != NULL)
1618 	free (blk->layer_name);
1619     if (blk->block_id != NULL)
1620 	free (blk->block_id);
1621     txt = blk->first_text;
1622     while (txt != NULL)
1623       {
1624 	  n_txt = txt->next;
1625 	  destroy_dxf_text (txt);
1626 	  txt = n_txt;
1627       }
1628     pt = blk->first_point;
1629     while (pt != NULL)
1630       {
1631 	  n_pt = pt->next;
1632 	  destroy_dxf_point (pt);
1633 	  pt = n_pt;
1634       }
1635     ln = blk->first_line;
1636     while (ln != NULL)
1637       {
1638 	  n_ln = ln->next;
1639 	  destroy_dxf_polyline (ln);
1640 	  ln = n_ln;
1641       }
1642     ln = blk->first_polyg;
1643     while (ln != NULL)
1644       {
1645 	  n_ln = ln->next;
1646 	  destroy_dxf_polyline (ln);
1647 	  ln = n_ln;
1648       }
1649     htc = blk->first_hatch;
1650     while (htc != NULL)
1651       {
1652 	  n_htc = htc->next;
1653 	  destroy_dxf_hatch (htc);
1654 	  htc = n_htc;
1655       }
1656     free (blk);
1657 }
1658 
1659 static void
insert_dxf_block(gaiaDxfParserPtr dxf)1660 insert_dxf_block (gaiaDxfParserPtr dxf)
1661 {
1662 /* inserting a DXF Block object */
1663     gaiaDxfBlockPtr blk;
1664     int ok = 0;
1665     if (dxf->curr_block.layer_name == NULL)
1666 	return;
1667     if (dxf->curr_block.block_id == NULL)
1668 	return;
1669     if (dxf->curr_block.first_text != NULL)
1670 	ok++;
1671     if (dxf->curr_block.first_point != NULL)
1672 	ok++;
1673     if (dxf->curr_block.first_line != NULL)
1674 	ok++;
1675     if (dxf->curr_block.first_polyg != NULL)
1676 	ok++;
1677     if (dxf->curr_block.first_hatch != NULL)
1678 	ok++;
1679     if (ok == 0)
1680 	return;
1681     blk =
1682 	alloc_dxf_block (dxf->curr_block.layer_name, dxf->curr_block.block_id);
1683     blk->first_text = dxf->curr_block.first_text;
1684     blk->last_text = dxf->curr_block.last_text;
1685     dxf->curr_block.first_text = NULL;
1686     dxf->curr_block.last_text = NULL;
1687     blk->first_point = dxf->curr_block.first_point;
1688     blk->last_point = dxf->curr_block.last_point;
1689     dxf->curr_block.first_point = NULL;
1690     dxf->curr_block.last_point = NULL;
1691     blk->first_line = dxf->curr_block.first_line;
1692     blk->last_line = dxf->curr_block.last_line;
1693     dxf->curr_block.first_line = NULL;
1694     dxf->curr_block.last_line = NULL;
1695     blk->first_polyg = dxf->curr_block.first_polyg;
1696     blk->last_polyg = dxf->curr_block.last_polyg;
1697     dxf->curr_block.first_polyg = NULL;
1698     dxf->curr_block.last_polyg = NULL;
1699     blk->first_hatch = dxf->curr_block.first_hatch;
1700     blk->last_hatch = dxf->curr_block.last_hatch;
1701     dxf->curr_block.first_hatch = NULL;
1702     dxf->curr_block.last_hatch = NULL;
1703 
1704     if (dxf->first_block == NULL)
1705 	dxf->first_block = blk;
1706     if (dxf->last_block != NULL)
1707 	dxf->last_block->next = blk;
1708     dxf->last_block = blk;
1709 }
1710 
1711 static gaiaDxfLayerPtr
alloc_dxf_layer(const char * name,int force_dims)1712 alloc_dxf_layer (const char *name, int force_dims)
1713 {
1714 /* allocating and initializing a DXF Layer object */
1715     int len;
1716     gaiaDxfLayerPtr lyr = malloc (sizeof (gaiaDxfLayer));
1717     len = strlen (name);
1718     lyr->layer_name = malloc (len + 1);
1719     strcpy (lyr->layer_name, name);
1720     lyr->first_text = NULL;
1721     lyr->last_text = NULL;
1722     lyr->first_point = NULL;
1723     lyr->last_point = NULL;
1724     lyr->first_line = NULL;
1725     lyr->last_line = NULL;
1726     lyr->first_polyg = NULL;
1727     lyr->last_polyg = NULL;
1728     lyr->first_hatch = NULL;
1729     lyr->last_hatch = NULL;
1730     lyr->first_ins_text = NULL;
1731     lyr->last_ins_text = NULL;
1732     lyr->first_ins_point = NULL;
1733     lyr->last_ins_point = NULL;
1734     lyr->first_ins_line = NULL;
1735     lyr->last_ins_line = NULL;
1736     lyr->first_ins_polyg = NULL;
1737     lyr->last_ins_polyg = NULL;
1738     lyr->first_ins_hatch = NULL;
1739     lyr->last_ins_hatch = NULL;
1740     if (force_dims == GAIA_DXF_FORCE_3D)
1741       {
1742 	  lyr->is3Dtext = 1;
1743 	  lyr->is3Dpoint = 1;
1744 	  lyr->is3Dline = 1;
1745 	  lyr->is3Dpolyg = 1;
1746 	  lyr->is3DinsText = 1;
1747 	  lyr->is3DinsPoint = 1;
1748 	  lyr->is3DinsLine = 1;
1749 	  lyr->is3DinsPolyg = 1;
1750       }
1751     else
1752       {
1753 	  lyr->is3Dtext = 0;
1754 	  lyr->is3Dpoint = 0;
1755 	  lyr->is3Dline = 0;
1756 	  lyr->is3Dpolyg = 0;
1757 	  lyr->is3DinsText = 0;
1758 	  lyr->is3DinsPoint = 0;
1759 	  lyr->is3DinsLine = 0;
1760 	  lyr->is3DinsPolyg = 0;
1761       }
1762     lyr->hasExtraText = 0;
1763     lyr->hasExtraPoint = 0;
1764     lyr->hasExtraLine = 0;
1765     lyr->hasExtraPolyg = 0;
1766     lyr->hasExtraInsText = 0;
1767     lyr->hasExtraInsPoint = 0;
1768     lyr->hasExtraInsLine = 0;
1769     lyr->hasExtraInsPolyg = 0;
1770     lyr->next = NULL;
1771     return lyr;
1772 }
1773 
1774 static void
destroy_dxf_layer(gaiaDxfLayerPtr lyr)1775 destroy_dxf_layer (gaiaDxfLayerPtr lyr)
1776 {
1777 /* memory cleanup - destroying a DXF Layer object */
1778     gaiaDxfTextPtr txt;
1779     gaiaDxfTextPtr n_txt;
1780     gaiaDxfPointPtr pt;
1781     gaiaDxfPointPtr n_pt;
1782     gaiaDxfPolylinePtr ln;
1783     gaiaDxfPolylinePtr n_ln;
1784     gaiaDxfHatchPtr ht;
1785     gaiaDxfHatchPtr n_ht;
1786     gaiaDxfInsertPtr ins;
1787     gaiaDxfInsertPtr n_ins;
1788     if (lyr == NULL)
1789 	return;
1790     txt = lyr->first_text;
1791     while (txt != NULL)
1792       {
1793 	  n_txt = txt->next;
1794 	  destroy_dxf_text (txt);
1795 	  txt = n_txt;
1796       }
1797     pt = lyr->first_point;
1798     while (pt != NULL)
1799       {
1800 	  n_pt = pt->next;
1801 	  destroy_dxf_point (pt);
1802 	  pt = n_pt;
1803       }
1804     ln = lyr->first_line;
1805     while (ln != NULL)
1806       {
1807 	  n_ln = ln->next;
1808 	  destroy_dxf_polyline (ln);
1809 	  ln = n_ln;
1810       }
1811     ln = lyr->first_polyg;
1812     while (ln != NULL)
1813       {
1814 	  n_ln = ln->next;
1815 	  destroy_dxf_polyline (ln);
1816 	  ln = n_ln;
1817       }
1818     ht = lyr->first_hatch;
1819     while (ht != NULL)
1820       {
1821 	  n_ht = ht->next;
1822 	  destroy_dxf_hatch (ht);
1823 	  ht = n_ht;
1824       }
1825     ins = lyr->first_ins_text;
1826     while (ins != NULL)
1827       {
1828 	  n_ins = ins->next;
1829 	  destroy_dxf_insert (ins);
1830 	  ins = n_ins;
1831       }
1832     ins = lyr->first_ins_point;
1833     while (ins != NULL)
1834       {
1835 	  n_ins = ins->next;
1836 	  destroy_dxf_insert (ins);
1837 	  ins = n_ins;
1838       }
1839     ins = lyr->first_ins_line;
1840     while (ins != NULL)
1841       {
1842 	  n_ins = ins->next;
1843 	  destroy_dxf_insert (ins);
1844 	  ins = n_ins;
1845       }
1846     ins = lyr->first_ins_polyg;
1847     while (ins != NULL)
1848       {
1849 	  n_ins = ins->next;
1850 	  destroy_dxf_insert (ins);
1851 	  ins = n_ins;
1852       }
1853     ins = lyr->first_ins_hatch;
1854     while (ins != NULL)
1855       {
1856 	  n_ins = ins->next;
1857 	  destroy_dxf_insert (ins);
1858 	  ins = n_ins;
1859       }
1860     if (lyr->layer_name != NULL)
1861 	free (lyr->layer_name);
1862     free (lyr);
1863 }
1864 
1865 static void
insert_dxf_layer(gaiaDxfParserPtr dxf,gaiaDxfLayerPtr lyr)1866 insert_dxf_layer (gaiaDxfParserPtr dxf, gaiaDxfLayerPtr lyr)
1867 {
1868 /* inserting a Layer object into the DXF struct */
1869     if (dxf->first_layer == NULL)
1870 	dxf->first_layer = lyr;
1871     if (dxf->last_layer != NULL)
1872 	dxf->last_layer->next = lyr;
1873     dxf->last_layer = lyr;
1874 }
1875 
1876 static void
force_missing_layer(gaiaDxfParserPtr dxf)1877 force_missing_layer (gaiaDxfParserPtr dxf)
1878 {
1879 /* forcing undeclared layers [missing TABLES section] */
1880     int ok_layer = 1;
1881     if (dxf->undeclared_layers == 0)
1882 	return;
1883     if (dxf->selected_layer != NULL)
1884       {
1885 	  ok_layer = 0;
1886 	  if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
1887 	      ok_layer = 1;
1888       }
1889     if (ok_layer)
1890       {
1891 	  int already_defined = 0;
1892 	  gaiaDxfLayerPtr lyr = dxf->first_layer;
1893 	  while (lyr != NULL)
1894 	    {
1895 		if (strcmp (lyr->layer_name, dxf->curr_layer_name) == 0)
1896 		  {
1897 		      already_defined = 1;
1898 		      break;
1899 		  }
1900 		lyr = lyr->next;
1901 	    }
1902 	  if (already_defined)
1903 	      return;
1904 	  lyr = alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
1905 	  insert_dxf_layer (dxf, lyr);
1906       }
1907 }
1908 
1909 static void
set_dxf_vertex(gaiaDxfParserPtr dxf)1910 set_dxf_vertex (gaiaDxfParserPtr dxf)
1911 {
1912 /* saving the current Polyline Vertex */
1913     gaiaDxfPointPtr pt = malloc (sizeof (gaiaDxfPoint));
1914     pt->x = dxf->curr_point.x;
1915     pt->y = dxf->curr_point.y;
1916     pt->z = dxf->curr_point.z;
1917     pt->first = NULL;
1918     pt->last = NULL;
1919     pt->next = NULL;
1920     if (dxf->first_pt == NULL)
1921 	dxf->first_pt = pt;
1922     if (dxf->last_pt != NULL)
1923 	dxf->last_pt->next = pt;
1924     dxf->last_pt = pt;
1925     dxf->curr_point.x = 0.0;
1926     dxf->curr_point.y = 0.0;
1927     dxf->curr_point.z = 0.0;
1928 }
1929 
1930 static void
save_current_polyline(const void * p_cache,gaiaDxfParserPtr dxf)1931 save_current_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
1932 {
1933 /* saving the current Polyline */
1934     int points = 0;
1935     gaiaDxfPolylinePtr ln;
1936     gaiaDxfPointPtr n_pt;
1937     gaiaDxfPointPtr pt;
1938     if (dxf->curr_layer_name == NULL)
1939 	goto clear;
1940     pt = dxf->first_pt;
1941     while (pt != NULL)
1942       {
1943 	  /* counting how many vertices are into the polyline */
1944 	  points++;
1945 	  pt = pt->next;
1946       }
1947     ln = alloc_dxf_polyline (dxf->is_closed_polyline, points);
1948     points = 0;
1949     pt = dxf->first_pt;
1950     while (pt != NULL)
1951       {
1952 	  /* setting vertices into the polyline */
1953 	  *(ln->x + points) = pt->x;
1954 	  *(ln->y + points) = pt->y;
1955 	  *(ln->z + points) = pt->z;
1956 	  points++;
1957 	  pt = pt->next;
1958       }
1959     if (dxf->is_block)
1960 	insert_dxf_block_polyline (p_cache, dxf, ln);
1961     else
1962       {
1963 	  force_missing_layer (dxf);
1964 	  insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
1965       }
1966     /* resetting the current polyline */
1967   clear:
1968     pt = dxf->first_pt;
1969     while (pt != NULL)
1970       {
1971 	  n_pt = pt->next;
1972 	  destroy_dxf_point (pt);
1973 	  pt = n_pt;
1974       }
1975     /* resetting curr_layer */
1976     if (dxf->curr_layer_name != NULL)
1977 	free (dxf->curr_layer_name);
1978     dxf->curr_layer_name = NULL;
1979     dxf->first_pt = NULL;
1980     dxf->last_pt = NULL;
1981 }
1982 
1983 static void
reset_dxf_polyline(const void * p_cache,gaiaDxfParserPtr dxf)1984 reset_dxf_polyline (const void *p_cache, gaiaDxfParserPtr dxf)
1985 {
1986 /* resetting the current DXF polyline */
1987     if (dxf->is_polyline)
1988       {
1989 	  if (dxf->first_pt != NULL)
1990 	      save_current_polyline (p_cache, dxf);
1991 	  dxf->is_polyline = 0;
1992       }
1993 }
1994 
1995 static void
reset_dxf_block(gaiaDxfParserPtr dxf)1996 reset_dxf_block (gaiaDxfParserPtr dxf)
1997 {
1998 /* memory cleanup - resetting the current DXF Block */
1999     gaiaDxfTextPtr txt;
2000     gaiaDxfTextPtr n_txt;
2001     gaiaDxfPointPtr pt;
2002     gaiaDxfPointPtr n_pt;
2003     gaiaDxfPolylinePtr ln;
2004     gaiaDxfPolylinePtr n_ln;
2005     gaiaDxfHatchPtr htc;
2006     gaiaDxfHatchPtr n_htc;
2007     if (dxf->curr_block.layer_name != NULL)
2008 	free (dxf->curr_block.layer_name);
2009     if (dxf->curr_block.block_id != NULL)
2010 	free (dxf->curr_block.block_id);
2011     txt = dxf->curr_block.first_text;
2012     while (txt != NULL)
2013       {
2014 	  n_txt = txt->next;
2015 	  destroy_dxf_text (txt);
2016 	  txt = n_txt;
2017       }
2018     pt = dxf->curr_block.first_point;
2019     while (pt != NULL)
2020       {
2021 	  n_pt = pt->next;
2022 	  destroy_dxf_point (pt);
2023 	  pt = n_pt;
2024       }
2025     ln = dxf->curr_block.first_line;
2026     while (ln != NULL)
2027       {
2028 	  n_ln = ln->next;
2029 	  destroy_dxf_polyline (ln);
2030 	  ln = n_ln;
2031       }
2032     ln = dxf->curr_block.first_polyg;
2033     while (ln != NULL)
2034       {
2035 	  n_ln = ln->next;
2036 	  destroy_dxf_polyline (ln);
2037 	  ln = n_ln;
2038       }
2039     htc = dxf->curr_block.first_hatch;
2040     while (htc != NULL)
2041       {
2042 	  n_htc = htc->next;
2043 	  destroy_dxf_hatch (htc);
2044 	  htc = n_htc;
2045       }
2046     dxf->curr_block.layer_name = NULL;
2047     dxf->curr_block.block_id = NULL;
2048     dxf->curr_block.first_text = NULL;
2049     dxf->curr_block.last_text = NULL;
2050     dxf->curr_block.first_point = NULL;
2051     dxf->curr_block.last_point = NULL;
2052     dxf->curr_block.first_line = NULL;
2053     dxf->curr_block.last_line = NULL;
2054     dxf->curr_block.first_polyg = NULL;
2055     dxf->curr_block.last_polyg = NULL;
2056     dxf->curr_block.first_hatch = NULL;
2057     dxf->curr_block.last_hatch = NULL;
2058     dxf->curr_block.is3Dtext = 0;
2059     dxf->curr_block.is3Dpoint = 0;
2060     dxf->curr_block.is3Dline = 0;
2061     dxf->curr_block.is3Dpolyg = 0;
2062 }
2063 
2064 static gaiaDxfBlockPtr
find_dxf_block(gaiaDxfParserPtr dxf,const char * layer_name,const char * block_id)2065 find_dxf_block (gaiaDxfParserPtr dxf, const char *layer_name,
2066 		const char *block_id)
2067 {
2068 /* attempting to find a Block object by its Id */
2069     gaiaDxfBlockPtr blk = dxf->first_block;
2070     while (blk != NULL)
2071       {
2072 	  if (layer_name != NULL && block_id != NULL)
2073 	    {
2074 		if (strcmp (blk->layer_name, layer_name) == 0
2075 		    && strcmp (blk->block_id, block_id) == 0)
2076 		  {
2077 		      /* ok, matching item found */
2078 		      return blk;
2079 		  }
2080 	    }
2081 	  blk = blk->next;
2082       }
2083     return NULL;
2084 }
2085 
2086 static void
save_current_circle(const void * p_cache,gaiaDxfParserPtr dxf)2087 save_current_circle (const void *p_cache, gaiaDxfParserPtr dxf)
2088 {
2089 /* saving the current Circle */
2090     int iv;
2091     double x;
2092     double y;
2093     gaiaGeomCollPtr geom = NULL;
2094     gaiaLinestringPtr circle;
2095     gaiaDxfPolylinePtr ln;
2096     if (dxf->curr_layer_name == NULL)
2097 	return;
2098     geom =
2099 	gaiaMakeCircle (dxf->curr_circle.cx, dxf->curr_circle.cy,
2100 			dxf->curr_circle.radius, 2.5);
2101     if (geom == NULL)
2102 	goto stop;
2103     circle = geom->FirstLinestring;
2104     if (circle == NULL)
2105 	goto stop;
2106     ln = alloc_dxf_polyline (0, circle->Points);
2107     for (iv = 0; iv < circle->Points; iv++)
2108       {
2109 	  /* setting vertices into the polyline */
2110 	  gaiaGetPoint (circle->Coords, iv, &x, &y);
2111 	  *(ln->x + iv) = x;
2112 	  *(ln->y + iv) = y;
2113 	  *(ln->z + iv) = dxf->curr_circle.cz;
2114       }
2115     if (dxf->is_block)
2116 	insert_dxf_block_polyline (p_cache, dxf, ln);
2117     else
2118       {
2119 	  force_missing_layer (dxf);
2120 	  insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2121       }
2122   stop:
2123     /* resetting curr_layer */
2124     if (dxf->curr_layer_name != NULL)
2125 	free (dxf->curr_layer_name);
2126     dxf->curr_layer_name = NULL;
2127     if (geom != NULL)
2128 	gaiaFreeGeomColl (geom);
2129 }
2130 
2131 static void
save_current_arc(const void * p_cache,gaiaDxfParserPtr dxf)2132 save_current_arc (const void *p_cache, gaiaDxfParserPtr dxf)
2133 {
2134 /* saving the current Arc */
2135     int iv;
2136     double x;
2137     double y;
2138     gaiaGeomCollPtr geom;
2139     gaiaLinestringPtr arc;
2140     gaiaDxfPolylinePtr ln;
2141     if (dxf->curr_layer_name == NULL)
2142 	return;
2143     geom =
2144 	gaiaMakeArc (dxf->curr_arc.cx, dxf->curr_arc.cy, dxf->curr_arc.radius,
2145 		     dxf->curr_arc.start, dxf->curr_arc.stop, 2.5);
2146     if (geom == NULL)
2147 	goto stop;
2148     arc = geom->FirstLinestring;
2149     if (arc == NULL)
2150 	goto stop;
2151     ln = alloc_dxf_polyline (0, arc->Points);
2152     for (iv = 0; iv < arc->Points; iv++)
2153       {
2154 	  /* setting vertices into the polyline */
2155 	  gaiaGetPoint (arc->Coords, iv, &x, &y);
2156 	  *(ln->x + iv) = x;
2157 	  *(ln->y + iv) = y;
2158 	  *(ln->z + iv) = dxf->curr_arc.cz;
2159       }
2160     if (dxf->is_block)
2161 	insert_dxf_block_polyline (p_cache, dxf, ln);
2162     else
2163       {
2164 	  force_missing_layer (dxf);
2165 	  insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2166       }
2167   stop:
2168     /* resetting curr_layer */
2169     if (dxf->curr_layer_name != NULL)
2170 	free (dxf->curr_layer_name);
2171     dxf->curr_layer_name = NULL;
2172     if (geom != NULL)
2173 	gaiaFreeGeomColl (geom);
2174 }
2175 
2176 static void
reset_dxf_entity(const void * p_cache,gaiaDxfParserPtr dxf)2177 reset_dxf_entity (const void *p_cache, gaiaDxfParserPtr dxf)
2178 {
2179 /* resetting the current DXF entity */
2180     gaiaDxfExtraAttrPtr ext;
2181     gaiaDxfExtraAttrPtr n_ext;
2182     if (dxf->is_vertex)
2183       {
2184 	  /* saving the current Vertex */
2185 	  set_dxf_vertex (dxf);
2186 	  dxf->is_vertex = 0;
2187 	  return;
2188       }
2189     if (dxf->is_polyline)
2190 	return;
2191     if (dxf->is_layer)
2192       {
2193 	  /* saving the current Table aka Layer */
2194 	  int ok_layer = 1;
2195 	  if (dxf->selected_layer != NULL)
2196 	    {
2197 		ok_layer = 0;
2198 		if (strcmp (dxf->selected_layer, dxf->curr_layer_name) == 0)
2199 		    ok_layer = 1;
2200 	    }
2201 	  if (ok_layer)
2202 	    {
2203 		gaiaDxfLayerPtr lyr =
2204 		    alloc_dxf_layer (dxf->curr_layer_name, dxf->force_dims);
2205 		insert_dxf_layer (dxf, lyr);
2206 		dxf->undeclared_layers = 0;
2207 	    }
2208 	  /* resetting curr_layer */
2209 	  if (dxf->curr_layer_name != NULL)
2210 	      free (dxf->curr_layer_name);
2211 	  dxf->curr_layer_name = NULL;
2212 	  dxf->is_layer = 0;
2213       }
2214     if (dxf->is_insert)
2215       {
2216 	  gaiaDxfBlockPtr blk = find_dxf_block (dxf, dxf->curr_layer_name,
2217 						dxf->curr_insert.block_id);
2218 	  if (blk != NULL)
2219 	    {
2220 		/* saving the current Insert */
2221 		gaiaDxfInsertPtr ins =
2222 		    alloc_dxf_insert (dxf->curr_insert.block_id,
2223 				      dxf->curr_insert.x,
2224 				      dxf->curr_insert.y, dxf->curr_insert.z,
2225 				      dxf->curr_insert.scale_x,
2226 				      dxf->curr_insert.scale_y,
2227 				      dxf->curr_insert.scale_z,
2228 				      dxf->curr_insert.angle);
2229 		blk->hasInsert = 1;
2230 		if (blk->first_text != NULL)
2231 		  {
2232 		      ins->hasText = 1;
2233 		      if (blk->is3Dtext)
2234 			  ins->is3Dtext = 1;
2235 		  }
2236 		if (blk->first_point != NULL)
2237 		  {
2238 		      ins->hasPoint = 1;
2239 		      if (blk->is3Dpoint)
2240 			  ins->is3Dpoint = 1;
2241 		  }
2242 		if (blk->first_line != NULL)
2243 		  {
2244 		      ins->hasLine = 1;
2245 		      if (blk->is3Dline)
2246 			  ins->is3Dline = 1;
2247 		  }
2248 		if (blk->first_polyg != NULL)
2249 		  {
2250 		      ins->hasPolyg = 1;
2251 		      if (blk->is3Dpolyg)
2252 			  ins->is3Dpolyg = 1;
2253 		  }
2254 		if (blk->first_hatch != NULL)
2255 		    ins->hasHatch = 1;
2256 		force_missing_layer (dxf);
2257 		insert_dxf_insert (dxf, dxf->curr_layer_name, ins);
2258 	    }
2259 	  /* resetting curr_insert */
2260 	  dxf->curr_insert.x = 0.0;
2261 	  dxf->curr_insert.y = 0.0;
2262 	  dxf->curr_insert.z = 0.0;
2263 	  dxf->curr_insert.scale_x = 0.0;
2264 	  dxf->curr_insert.scale_y = 0.0;
2265 	  dxf->curr_insert.scale_z = 0.0;
2266 	  dxf->curr_insert.angle = 0.0;
2267 	  dxf->curr_insert.is3Dtext = 0;
2268 	  dxf->curr_insert.is3Dpoint = 0;
2269 	  dxf->curr_insert.is3Dline = 0;
2270 	  dxf->curr_insert.is3Dpolyg = 0;
2271 	  if (dxf->curr_insert.block_id != NULL)
2272 	      free (dxf->curr_insert.block_id);
2273 	  dxf->curr_insert.block_id = NULL;
2274 	  dxf->is_insert = 0;
2275 	  /* resetting curr_layer */
2276 	  if (dxf->curr_layer_name != NULL)
2277 	      free (dxf->curr_layer_name);
2278 	  dxf->curr_layer_name = NULL;
2279       }
2280     if (dxf->is_line)
2281       {
2282 	  /* saving the current Line */
2283 	  gaiaDxfPolylinePtr ln =
2284 	      alloc_dxf_line (dxf->curr_point.x, dxf->curr_point.y,
2285 			      dxf->curr_point.z,
2286 			      dxf->curr_end_point.x, dxf->curr_end_point.y,
2287 			      dxf->curr_end_point.z);
2288 	  if (dxf->is_block)
2289 	      insert_dxf_block_polyline (p_cache, dxf, ln);
2290 	  else
2291 	    {
2292 		force_missing_layer (dxf);
2293 		insert_dxf_polyline (p_cache, dxf, dxf->curr_layer_name, ln);
2294 	    }
2295 	  /* resetting curr_line */
2296 	  dxf->curr_point.x = 0.0;
2297 	  dxf->curr_point.y = 0.0;
2298 	  dxf->curr_point.z = 0.0;
2299 	  dxf->curr_end_point.x = 0.0;
2300 	  dxf->curr_end_point.y = 0.0;
2301 	  dxf->curr_end_point.z = 0.0;
2302 	  dxf->is_line = 0;
2303 	  /* resetting curr_layer */
2304 	  if (dxf->curr_layer_name != NULL)
2305 	      free (dxf->curr_layer_name);
2306 	  dxf->curr_layer_name = NULL;
2307       }
2308     if (dxf->is_hatch)
2309       {
2310 	  /* saving the current hatch */
2311 	  if (dxf->curr_hatch != NULL)
2312 	    {
2313 		if (is_valid_dxf_hatch (dxf->curr_hatch))
2314 		  {
2315 		      create_dxf_hatch_lines (p_cache, dxf->curr_hatch,
2316 					      dxf->srid);
2317 		      if (dxf->is_block)
2318 			  insert_dxf_block_hatch (dxf, dxf->curr_hatch);
2319 		      else
2320 			{
2321 			    force_missing_layer (dxf);
2322 			    insert_dxf_hatch (dxf, dxf->curr_layer_name,
2323 					      dxf->curr_hatch);
2324 			}
2325 		      dxf->curr_hatch = NULL;
2326 		  }
2327 	    }
2328 	  dxf->is_hatch = 0;
2329 	  /* resetting curr_layer */
2330 	  if (dxf->curr_layer_name != NULL)
2331 	      free (dxf->curr_layer_name);
2332 	  dxf->curr_layer_name = NULL;
2333       }
2334     if (dxf->is_text)
2335       {
2336 	  /* saving the current Text */
2337 	  gaiaDxfTextPtr txt =
2338 	      alloc_dxf_text (dxf->curr_text.label, dxf->curr_text.x,
2339 			      dxf->curr_text.y, dxf->curr_text.z,
2340 			      dxf->curr_text.angle);
2341 	  if (dxf->is_block)
2342 	      insert_dxf_block_text (dxf, txt);
2343 	  else
2344 	    {
2345 		force_missing_layer (dxf);
2346 		insert_dxf_text (dxf, dxf->curr_layer_name, txt);
2347 	    }
2348 	  /* resetting curr_text */
2349 	  dxf->curr_text.x = 0.0;
2350 	  dxf->curr_text.y = 0.0;
2351 	  dxf->curr_text.z = 0.0;
2352 	  dxf->curr_text.angle = 0.0;
2353 	  if (dxf->curr_text.label != NULL)
2354 	      free (dxf->curr_text.label);
2355 	  dxf->curr_text.label = NULL;
2356 	  dxf->is_text = 0;
2357 	  /* resetting curr_layer */
2358 	  if (dxf->curr_layer_name != NULL)
2359 	      free (dxf->curr_layer_name);
2360 	  dxf->curr_layer_name = NULL;
2361       }
2362     if (dxf->is_point)
2363       {
2364 	  /* saving the current Point */
2365 	  gaiaDxfPointPtr pt =
2366 	      alloc_dxf_point (dxf->curr_point.x, dxf->curr_point.y,
2367 			       dxf->curr_point.z);
2368 	  if (dxf->is_block)
2369 	      insert_dxf_block_point (dxf, pt);
2370 	  else
2371 	    {
2372 		force_missing_layer (dxf);
2373 		insert_dxf_point (dxf, dxf->curr_layer_name, pt);
2374 	    }
2375 	  /* resetting curr_point */
2376 	  dxf->curr_point.x = 0.0;
2377 	  dxf->curr_point.y = 0.0;
2378 	  dxf->curr_point.z = 0.0;
2379 	  dxf->is_point = 0;
2380 	  /* resetting curr_layer */
2381 	  if (dxf->curr_layer_name != NULL)
2382 	      free (dxf->curr_layer_name);
2383 	  dxf->curr_layer_name = NULL;
2384       }
2385     if (dxf->is_lwpolyline)
2386       {
2387 	  /* saving the current Polyline */
2388 	  save_current_polyline (p_cache, dxf);
2389 	  dxf->is_lwpolyline = 0;
2390       }
2391     if (dxf->is_circle)
2392       {
2393 	  /* saving the current Circle */
2394 	  save_current_circle (p_cache, dxf);
2395 	  /* resetting curr_circle */
2396 	  dxf->curr_circle.cx = 0.0;
2397 	  dxf->curr_circle.cy = 0.0;
2398 	  dxf->curr_circle.cz = 0.0;
2399 	  dxf->curr_circle.radius = 0.0;
2400 	  dxf->is_circle = 0;
2401 	  /* resetting curr_layer */
2402 	  if (dxf->curr_layer_name != NULL)
2403 	      free (dxf->curr_layer_name);
2404 	  dxf->curr_layer_name = NULL;
2405       }
2406     if (dxf->is_arc)
2407       {
2408 	  /* saving the current Arc */
2409 	  save_current_arc (p_cache, dxf);
2410 	  /* resetting curr_arc */
2411 	  dxf->curr_arc.cx = 0.0;
2412 	  dxf->curr_arc.cy = 0.0;
2413 	  dxf->curr_arc.cz = 0.0;
2414 	  dxf->curr_arc.radius = 0.0;
2415 	  dxf->curr_arc.start = 0.0;
2416 	  dxf->curr_arc.stop = 0.0;
2417 	  dxf->is_arc = 0;
2418 	  /* resetting curr_layer */
2419 	  if (dxf->curr_layer_name != NULL)
2420 	      free (dxf->curr_layer_name);
2421 	  dxf->curr_layer_name = NULL;
2422       }
2423     if (dxf->extra_key != NULL)
2424       {
2425 	  free (dxf->extra_key);
2426 	  dxf->extra_key = NULL;
2427       }
2428     if (dxf->extra_value != NULL)
2429       {
2430 	  free (dxf->extra_value);
2431 	  dxf->extra_value = NULL;
2432       }
2433     ext = dxf->first_ext;
2434     while (ext != NULL)
2435       {
2436 	  n_ext = ext->next;
2437 	  destroy_dxf_extra (ext);
2438 	  ext = n_ext;
2439       }
2440     dxf->first_ext = NULL;
2441     dxf->last_ext = NULL;
2442     if (dxf->curr_hatch != NULL)
2443 	destroy_dxf_hatch (dxf->curr_hatch);
2444     dxf->curr_hatch = NULL;
2445 }
2446 
2447 static void
set_dxf_layer_name(gaiaDxfParserPtr dxf,const char * name)2448 set_dxf_layer_name (gaiaDxfParserPtr dxf, const char *name)
2449 {
2450 /* saving the current Layer Name */
2451     int len;
2452     if (dxf->curr_layer_name != NULL)
2453 	free (dxf->curr_layer_name);
2454     len = strlen (name);
2455     dxf->curr_layer_name = malloc (len + 1);
2456     strcpy (dxf->curr_layer_name, name);
2457 }
2458 
2459 static void
set_dxf_block_layer_name(gaiaDxfParserPtr dxf,const char * name)2460 set_dxf_block_layer_name (gaiaDxfParserPtr dxf, const char *name)
2461 {
2462 /* saving the current Block Layer Name */
2463     int len;
2464     if (dxf->curr_block.layer_name != NULL)
2465 	free (dxf->curr_block.layer_name);
2466     len = strlen (name);
2467     dxf->curr_block.layer_name = malloc (len + 1);
2468     strcpy (dxf->curr_block.layer_name, name);
2469 }
2470 
2471 static void
set_dxf_block_id(gaiaDxfParserPtr dxf,const char * id)2472 set_dxf_block_id (gaiaDxfParserPtr dxf, const char *id)
2473 {
2474 /* saving the current Block Id */
2475     int len;
2476     if (dxf->curr_block.block_id != NULL)
2477 	free (dxf->curr_block.block_id);
2478     len = strlen (id);
2479     dxf->curr_block.block_id = malloc (len + 1);
2480     strcpy (dxf->curr_block.block_id, id);
2481 }
2482 
2483 static void
set_dxf_insert_block_id(gaiaDxfParserPtr dxf,const char * id)2484 set_dxf_insert_block_id (gaiaDxfParserPtr dxf, const char *id)
2485 {
2486 /* saving the current Block Id */
2487     int len;
2488     if (dxf->curr_insert.block_id != NULL)
2489 	free (dxf->curr_insert.block_id);
2490     len = strlen (id);
2491     dxf->curr_insert.block_id = malloc (len + 1);
2492     strcpy (dxf->curr_insert.block_id, id);
2493 }
2494 
2495 static void
set_dxf_label(gaiaDxfParserPtr dxf,const char * label)2496 set_dxf_label (gaiaDxfParserPtr dxf, const char *label)
2497 {
2498 /* saving the current Text Label */
2499     int len;
2500     if (dxf->curr_text.label != NULL)
2501 	free (dxf->curr_text.label);
2502     len = strlen (label);
2503     dxf->curr_text.label = malloc (len + 1);
2504     strcpy (dxf->curr_text.label, label);
2505 }
2506 
2507 static void
set_dxf_extra_attr(gaiaDxfParserPtr dxf)2508 set_dxf_extra_attr (gaiaDxfParserPtr dxf)
2509 {
2510 /* saving the current Extra Attribute */
2511     gaiaDxfExtraAttrPtr ext = alloc_dxf_extra ();
2512     ext->key = dxf->extra_key;
2513     ext->value = dxf->extra_value;
2514     if (dxf->first_ext == NULL)
2515 	dxf->first_ext = ext;
2516     if (dxf->last_ext != NULL)
2517 	dxf->last_ext->next = ext;
2518     dxf->last_ext = ext;
2519     dxf->extra_key = NULL;
2520     dxf->extra_value = NULL;
2521 }
2522 
2523 static void
set_dxf_extra_key(gaiaDxfParserPtr dxf,const char * key)2524 set_dxf_extra_key (gaiaDxfParserPtr dxf, const char *key)
2525 {
2526 /* saving the current Extra Attribute Key */
2527     int len;
2528     if (dxf->extra_key != NULL)
2529 	free (dxf->extra_key);
2530     len = strlen (key);
2531     dxf->extra_key = malloc (len + 1);
2532     strcpy (dxf->extra_key, key);
2533     if (dxf->extra_key != NULL && dxf->extra_value != NULL)
2534 	set_dxf_extra_attr (dxf);
2535 }
2536 
2537 static void
set_dxf_extra_value(gaiaDxfParserPtr dxf,const char * value)2538 set_dxf_extra_value (gaiaDxfParserPtr dxf, const char *value)
2539 {
2540 /* saving the current Extra Attribute Value */
2541     int len;
2542     if (dxf->extra_value != NULL)
2543 	free (dxf->extra_value);
2544     len = strlen (value);
2545     dxf->extra_value = malloc (len + 1);
2546     strcpy (dxf->extra_value, value);
2547     if (dxf->extra_key != NULL && dxf->extra_value != NULL)
2548 	set_dxf_extra_attr (dxf);
2549 }
2550 
2551 static void
create_dxf_curr_hatch(gaiaDxfParserPtr dxf)2552 create_dxf_curr_hatch (gaiaDxfParserPtr dxf)
2553 {
2554 /* creating the current Hatch being parsed */
2555     if (dxf->curr_hatch != NULL)
2556 	destroy_dxf_hatch (dxf->curr_hatch);
2557     dxf->curr_hatch = alloc_dxf_hatch ();
2558 }
2559 
2560 static void
start_dxf_hatch_boundary(gaiaDxfParserPtr dxf)2561 start_dxf_hatch_boundary (gaiaDxfParserPtr dxf)
2562 {
2563 /* starting a new Hatch Boundary Path */
2564     if (dxf->curr_hatch != NULL)
2565       {
2566 	  gaiaDxfBoundaryPathPtr path = alloc_dxf_boundary_path ();
2567 	  insert_dxf_boundary_path (dxf->curr_hatch, path);
2568 	  dxf->is_hatch_boundary = 1;
2569       }
2570 }
2571 
2572 static void
insert_dxf_hatch_boundary_segm(gaiaDxfParserPtr dxf)2573 insert_dxf_hatch_boundary_segm (gaiaDxfParserPtr dxf)
2574 {
2575     if (dxf->curr_hatch != NULL)
2576       {
2577 	  gaiaDxfBoundaryPathPtr path = dxf->curr_hatch->last;
2578 	  if (path != NULL)
2579 	    {
2580 		gaiaDxfHatchSegmPtr segm =
2581 		    alloc_dxf_hatch_segm (dxf->curr_point.x, dxf->curr_point.y,
2582 					  dxf->curr_end_point.x,
2583 					  dxf->curr_end_point.y);
2584 		insert_dxf_boundary_segm (path, segm);
2585 	    }
2586       }
2587     dxf->curr_point.x = 0.0;
2588     dxf->curr_point.y = 0.0;
2589     dxf->curr_point.z = 0.0;
2590     dxf->curr_end_point.x = 0.0;
2591     dxf->curr_end_point.y = 0.0;
2592     dxf->curr_end_point.z = 0.0;
2593 }
2594 
2595 static void
set_dxf_hatch_spacing(gaiaDxfParserPtr dxf,double spacing)2596 set_dxf_hatch_spacing (gaiaDxfParserPtr dxf, double spacing)
2597 {
2598 /* saving the current Hatch spacing */
2599     if (dxf->curr_hatch != NULL)
2600 	dxf->curr_hatch->spacing = spacing;
2601 }
2602 
2603 static void
set_dxf_hatch_angle(gaiaDxfParserPtr dxf,double angle)2604 set_dxf_hatch_angle (gaiaDxfParserPtr dxf, double angle)
2605 {
2606 /* saving the current Hatch angle */
2607     if (dxf->curr_hatch != NULL)
2608 	dxf->curr_hatch->angle = angle;
2609 }
2610 
2611 static void
set_dxf_hatch_base_x(gaiaDxfParserPtr dxf,double x)2612 set_dxf_hatch_base_x (gaiaDxfParserPtr dxf, double x)
2613 {
2614 /* saving the current Hatch base X */
2615     if (dxf->curr_hatch != NULL)
2616 	dxf->curr_hatch->base_x = x;
2617 }
2618 
2619 static void
set_dxf_hatch_base_y(gaiaDxfParserPtr dxf,double y)2620 set_dxf_hatch_base_y (gaiaDxfParserPtr dxf, double y)
2621 {
2622 /* saving the current Hatch base Y */
2623     if (dxf->curr_hatch != NULL)
2624 	dxf->curr_hatch->base_y = y;
2625 }
2626 
2627 static void
set_dxf_hatch_offset_x(gaiaDxfParserPtr dxf,double x)2628 set_dxf_hatch_offset_x (gaiaDxfParserPtr dxf, double x)
2629 {
2630 /* saving the current Hatch offset X */
2631     if (dxf->curr_hatch != NULL)
2632 	dxf->curr_hatch->offset_x = x;
2633 }
2634 
2635 static void
set_dxf_hatch_offset_y(gaiaDxfParserPtr dxf,double y)2636 set_dxf_hatch_offset_y (gaiaDxfParserPtr dxf, double y)
2637 {
2638 /* saving the current Hatch offset Y */
2639     if (dxf->curr_hatch != NULL)
2640 	dxf->curr_hatch->offset_y = y;
2641 }
2642 
2643 static int
op_code_line(const char * line)2644 op_code_line (const char *line)
2645 {
2646 /* checking for a valid op-code */
2647     int numdigit = 0;
2648     int invalid = 0;
2649     const char *p = line;
2650     while (*p != '\0')
2651       {
2652 	  /* skipping leading white-spaces */
2653 	  if (*p == ' ' || *p == '\t')
2654 	    {
2655 		p++;
2656 		continue;
2657 	    }
2658 	  else
2659 	      break;
2660       }
2661     while (*p != '\0')
2662       {
2663 	  /* evaluating each character */
2664 	  if (*p >= '0' && *p <= '9')
2665 	    {
2666 		numdigit++;
2667 		p++;
2668 		continue;
2669 	    }
2670 	  else
2671 	    {
2672 		invalid = 1;
2673 		break;
2674 	    }
2675       }
2676     if (numdigit > 0 && invalid == 0)
2677 	return 1;
2678     return 0;
2679 }
2680 
2681 static int
parse_dxf_line(const void * p_cache,gaiaDxfParserPtr dxf,const char * line)2682 parse_dxf_line (const void *p_cache, gaiaDxfParserPtr dxf, const char *line)
2683 {
2684 /* parsing a DXF line */
2685     dxf->line_no += 1;
2686 
2687     if (dxf->tables || dxf->entities || dxf->blocks)
2688       {
2689 	  /* handling OP-CODE lines */
2690 	  if (dxf->op_code_line)
2691 	    {
2692 		if (!op_code_line (line))
2693 		  {
2694 		      /* unexpected value */
2695 		      spatialite_e
2696 			  ("ERROR on line %d: expected on OP-CODE to be found\n",
2697 			   dxf->line_no);
2698 		      return 0;
2699 		  }
2700 		dxf->op_code = atoi (line);
2701 		if (dxf->op_code == 0)
2702 		    reset_dxf_entity (p_cache, dxf);
2703 		dxf->op_code_line = 0;
2704 		return 1;
2705 	    }
2706 	  dxf->op_code_line = 1;
2707       }
2708     if (dxf->eof)
2709       {
2710 	  /* reading past the end */
2711 	  spatialite_e ("ERROR on line %d: attempting to read past EOF\n",
2712 			dxf->line_no);
2713 	  return 0;
2714       }
2715     if (strcmp (line, "SECTION") == 0)
2716       {
2717 	  /* start SECTION tag */
2718 	  reset_dxf_polyline (p_cache, dxf);
2719 	  if (dxf->section)
2720 	    {
2721 		spatialite_e ("ERROR on line %d: unexpected SECTION\n",
2722 			      dxf->line_no);
2723 		dxf->error = 1;
2724 		return 0;
2725 	    }
2726 	  dxf->section = 1;
2727 	  return 1;
2728       }
2729     if (strcmp (line, "ENDSEC") == 0)
2730       {
2731 	  /* end SECTION tag */
2732 	  reset_dxf_polyline (p_cache, dxf);
2733 	  if (!dxf->section)
2734 	    {
2735 		spatialite_e ("ERROR on line %d: unexpected ENDSEC\n",
2736 			      dxf->line_no);
2737 		dxf->error = 1;
2738 		return 0;
2739 	    }
2740 	  dxf->section = 0;
2741 	  dxf->tables = 0;
2742 	  dxf->blocks = 0;
2743 	  dxf->is_block = 0;
2744 	  dxf->entities = 0;
2745 	  return 1;
2746       }
2747     if (strcmp (line, "TABLES") == 0)
2748       {
2749 	  /* start TABLES tag */
2750 	  reset_dxf_polyline (p_cache, dxf);
2751 	  if (dxf->section)
2752 	    {
2753 		dxf->tables = 1;
2754 		dxf->op_code_line = 1;
2755 		return 1;
2756 	    }
2757       }
2758     if (strcmp (line, "BLOCKS") == 0)
2759       {
2760 	  /* start BLOCKS tag */
2761 	  reset_dxf_polyline (p_cache, dxf);
2762 	  if (dxf->section)
2763 	    {
2764 		dxf->blocks = 1;
2765 		dxf->op_code_line = 1;
2766 		return 1;
2767 	    }
2768       }
2769     if (strcmp (line, "BLOCK") == 0)
2770       {
2771 	  /* start BLOCK tag */
2772 	  reset_dxf_polyline (p_cache, dxf);
2773 	  if (dxf->blocks)
2774 	    {
2775 		dxf->is_block = 1;
2776 		dxf->op_code_line = 1;
2777 		return 1;
2778 	    }
2779       }
2780     if (strcmp (line, "ENDBLK") == 0)
2781       {
2782 	  /* end BLOCK tag */
2783 	  reset_dxf_polyline (p_cache, dxf);
2784 	  if (dxf->is_block)
2785 	    {
2786 		insert_dxf_block (dxf);
2787 		dxf->is_block = 0;
2788 		dxf->op_code_line = 1;
2789 		return 1;
2790 	    }
2791       }
2792     if (strcmp (line, "ENTITIES") == 0)
2793       {
2794 	  /* start ENTITIES tag */
2795 	  reset_dxf_polyline (p_cache, dxf);
2796 	  if (dxf->section)
2797 	    {
2798 		dxf->entities = 1;
2799 		dxf->op_code_line = 1;
2800 		return 1;
2801 	    }
2802       }
2803     if (strcmp (line, "LAYER") == 0)
2804       {
2805 	  /* start LAYER tag */
2806 	  reset_dxf_polyline (p_cache, dxf);
2807 	  if (dxf->tables && dxf->op_code == 0)
2808 	    {
2809 		dxf->is_layer = 1;
2810 		return 1;
2811 	    }
2812       }
2813     if (strcmp (line, "INSERT") == 0)
2814       {
2815 	  /* start INSERT tag */
2816 	  reset_dxf_polyline (p_cache, dxf);
2817 	  if (dxf->entities && dxf->op_code == 0)
2818 	    {
2819 		dxf->is_insert = 1;
2820 		return 1;
2821 	    }
2822       }
2823     if (strcmp (line, "INSERT") == 0)
2824       {
2825 	  /* start INSERT tag */
2826 	  reset_dxf_polyline (p_cache, dxf);
2827 	  if (dxf->entities && dxf->op_code == 0)
2828 	    {
2829 		dxf->is_insert = 1;
2830 		return 1;
2831 	    }
2832       }
2833     if (strcmp (line, "TEXT") == 0)
2834       {
2835 	  /* start TEXT tag */
2836 	  reset_dxf_polyline (p_cache, dxf);
2837 	  if (dxf->entities && dxf->op_code == 0)
2838 	    {
2839 		dxf->is_text = 1;
2840 		return 1;
2841 	    }
2842 	  if (dxf->is_block && dxf->op_code == 0)
2843 	    {
2844 		dxf->is_text = 1;
2845 		return 1;
2846 	    }
2847       }
2848     if (strcmp (line, "POINT") == 0)
2849       {
2850 	  /* start POINT tag */
2851 	  reset_dxf_polyline (p_cache, dxf);
2852 	  if (dxf->entities && dxf->op_code == 0)
2853 	    {
2854 		dxf->is_point = 1;
2855 		return 1;
2856 	    }
2857 	  if (dxf->is_block && dxf->op_code == 0)
2858 	    {
2859 		dxf->is_point = 1;
2860 		return 1;
2861 	    }
2862       }
2863     if (strcmp (line, "POLYLINE") == 0)
2864       {
2865 	  /* start POLYLINE tag */
2866 	  reset_dxf_polyline (p_cache, dxf);
2867 	  if (dxf->entities && dxf->op_code == 0)
2868 	    {
2869 		dxf->is_polyline = 1;
2870 		return 1;
2871 	    }
2872 	  if (dxf->is_block && dxf->op_code == 0)
2873 	    {
2874 		dxf->is_polyline = 1;
2875 		return 1;
2876 	    }
2877       }
2878     if (strcmp (line, "LWPOLYLINE") == 0)
2879       {
2880 	  /* start LWPOLYLINE tag */
2881 	  reset_dxf_polyline (p_cache, dxf);
2882 	  if (dxf->entities && dxf->op_code == 0)
2883 	    {
2884 		dxf->is_lwpolyline = 1;
2885 		return 1;
2886 	    }
2887 	  if (dxf->is_block && dxf->op_code == 0)
2888 	    {
2889 		dxf->is_lwpolyline = 1;
2890 		return 1;
2891 	    }
2892       }
2893     if (strcmp (line, "LINE") == 0)
2894       {
2895 	  /* start LINE tag */
2896 	  reset_dxf_polyline (p_cache, dxf);
2897 	  if (dxf->entities && dxf->op_code == 0)
2898 	    {
2899 		dxf->is_line = 1;
2900 		return 1;
2901 	    }
2902 	  if (dxf->is_block && dxf->op_code == 0)
2903 	    {
2904 		dxf->is_line = 1;
2905 		return 1;
2906 	    }
2907       }
2908     if (strcmp (line, "CIRCLE") == 0)
2909       {
2910 	  /* start CIRCLE tag */
2911 	  reset_dxf_polyline (p_cache, dxf);
2912 	  if (dxf->entities && dxf->op_code == 0)
2913 	    {
2914 		dxf->is_circle = 1;
2915 		return 1;
2916 	    }
2917 	  if (dxf->is_block && dxf->op_code == 0)
2918 	    {
2919 		dxf->is_circle = 1;
2920 		return 1;
2921 	    }
2922       }
2923     if (strcmp (line, "ARC") == 0)
2924       {
2925 	  /* start ARC tag */
2926 	  reset_dxf_polyline (p_cache, dxf);
2927 	  if (dxf->entities && dxf->op_code == 0)
2928 	    {
2929 		dxf->is_arc = 1;
2930 		return 1;
2931 	    }
2932 	  if (dxf->is_block && dxf->op_code == 0)
2933 	    {
2934 		dxf->is_arc = 1;
2935 		return 1;
2936 	    }
2937       }
2938     if (strcmp (line, "VERTEX") == 0)
2939       {
2940 	  /* start VERTEX tag */
2941 	  if (dxf->is_polyline && dxf->op_code == 0)
2942 	    {
2943 		dxf->is_vertex = 1;
2944 		return 1;
2945 	    }
2946       }
2947     if (strcmp (line, "HATCH") == 0)
2948       {
2949 	  /* start HATCH tag */
2950 	  if (dxf->entities && dxf->op_code == 0)
2951 	    {
2952 		dxf->is_hatch = 1;
2953 		return 1;
2954 	    }
2955 	  if (dxf->is_block && dxf->op_code == 0)
2956 	    {
2957 		dxf->is_hatch = 1;
2958 		return 1;
2959 	    }
2960       }
2961     if (strcmp (line, "EOF") == 0)
2962       {
2963 	  /* end of file marker tag */
2964 	  reset_dxf_polyline (p_cache, dxf);
2965 	  dxf->eof = 1;
2966 	  return 1;
2967       }
2968     if (dxf->is_layer)
2969       {
2970 	  /* parsing Table attributes */
2971 	  switch (dxf->op_code)
2972 	    {
2973 	    case 2:
2974 		set_dxf_layer_name (dxf, line);
2975 		break;
2976 	    };
2977       }
2978     if (dxf->is_block)
2979       {
2980 	  /* parsing Block attributes */
2981 	  switch (dxf->op_code)
2982 	    {
2983 	    case 2:
2984 		set_dxf_block_id (dxf, line);
2985 		break;
2986 	    case 8:
2987 		set_dxf_block_layer_name (dxf, line);
2988 		break;
2989 	    };
2990       }
2991     if (dxf->is_line)
2992       {
2993 	  /* parsing Line attributes */
2994 	  switch (dxf->op_code)
2995 	    {
2996 	    case 8:
2997 		set_dxf_layer_name (dxf, line);
2998 		break;
2999 	    case 10:
3000 		dxf->curr_point.x = atof (line);
3001 		break;
3002 	    case 20:
3003 		dxf->curr_point.y = atof (line);
3004 		break;
3005 	    case 30:
3006 		dxf->curr_point.z = atof (line);
3007 		break;
3008 	    case 11:
3009 		dxf->curr_end_point.x = atof (line);
3010 		break;
3011 	    case 21:
3012 		dxf->curr_end_point.y = atof (line);
3013 		break;
3014 	    case 31:
3015 		dxf->curr_end_point.z = atof (line);
3016 		break;
3017 	    };
3018       }
3019     if (dxf->is_circle)
3020       {
3021 	  /* parsing Circle attributes */
3022 	  switch (dxf->op_code)
3023 	    {
3024 	    case 8:
3025 		set_dxf_layer_name (dxf, line);
3026 		break;
3027 	    case 10:
3028 		dxf->curr_circle.cx = atof (line);
3029 		break;
3030 	    case 20:
3031 		dxf->curr_circle.cy = atof (line);
3032 		break;
3033 	    case 30:
3034 		dxf->curr_circle.cz = atof (line);
3035 		break;
3036 	    case 40:
3037 		dxf->curr_circle.radius = atof (line);
3038 		break;
3039 	    };
3040       }
3041     if (dxf->is_arc)
3042       {
3043 	  /* parsing Arc attributes */
3044 	  switch (dxf->op_code)
3045 	    {
3046 	    case 8:
3047 		set_dxf_layer_name (dxf, line);
3048 		break;
3049 	    case 10:
3050 		dxf->curr_arc.cx = atof (line);
3051 		break;
3052 	    case 20:
3053 		dxf->curr_arc.cy = atof (line);
3054 		break;
3055 	    case 30:
3056 		dxf->curr_arc.cz = atof (line);
3057 		break;
3058 	    case 40:
3059 		dxf->curr_arc.radius = atof (line);
3060 		break;
3061 	    case 50:
3062 		dxf->curr_arc.start = atof (line);
3063 		break;
3064 	    case 51:
3065 		dxf->curr_arc.stop = atof (line);
3066 		break;
3067 	    };
3068       }
3069     if (dxf->is_insert)
3070       {
3071 	  /* parsing Insert attributes */
3072 	  switch (dxf->op_code)
3073 	    {
3074 	    case 2:
3075 		set_dxf_insert_block_id (dxf, line);
3076 		break;
3077 	    case 8:
3078 		set_dxf_layer_name (dxf, line);
3079 		break;
3080 	    case 10:
3081 		dxf->curr_insert.x = atof (line);
3082 		break;
3083 	    case 20:
3084 		dxf->curr_insert.y = atof (line);
3085 		break;
3086 	    case 30:
3087 		dxf->curr_insert.z = atof (line);
3088 		break;
3089 	    case 41:
3090 		dxf->curr_insert.scale_x = atof (line);
3091 		break;
3092 	    case 42:
3093 		dxf->curr_insert.scale_y = atof (line);
3094 		break;
3095 	    case 43:
3096 		dxf->curr_insert.scale_z = atof (line);
3097 		break;
3098 	    case 50:
3099 		dxf->curr_insert.angle = atof (line);
3100 		break;
3101 	    case 1000:
3102 		set_dxf_extra_value (dxf, line);
3103 		break;
3104 	    case 1001:
3105 		set_dxf_extra_key (dxf, line);
3106 		break;
3107 	    };
3108       }
3109     if (dxf->is_text)
3110       {
3111 	  /* parsing Text attributes */
3112 	  switch (dxf->op_code)
3113 	    {
3114 	    case 1:
3115 		set_dxf_label (dxf, line);
3116 		break;
3117 	    case 8:
3118 		set_dxf_layer_name (dxf, line);
3119 		break;
3120 	    case 10:
3121 		dxf->curr_text.x = atof (line);
3122 		break;
3123 	    case 20:
3124 		dxf->curr_text.y = atof (line);
3125 		break;
3126 	    case 30:
3127 		dxf->curr_text.z = atof (line);
3128 		break;
3129 	    case 50:
3130 		dxf->curr_text.angle = atof (line);
3131 		break;
3132 	    case 1000:
3133 		set_dxf_extra_value (dxf, line);
3134 		break;
3135 	    case 1001:
3136 		set_dxf_extra_key (dxf, line);
3137 		break;
3138 	    };
3139       }
3140     if (dxf->is_point)
3141       {
3142 	  /* parsing Point attributes */
3143 	  switch (dxf->op_code)
3144 	    {
3145 	    case 8:
3146 		set_dxf_layer_name (dxf, line);
3147 		break;
3148 	    case 10:
3149 		dxf->curr_point.x = atof (line);
3150 		break;
3151 	    case 20:
3152 		dxf->curr_point.y = atof (line);
3153 		break;
3154 	    case 30:
3155 		dxf->curr_point.z = atof (line);
3156 		break;
3157 	    case 1000:
3158 		set_dxf_extra_value (dxf, line);
3159 		break;
3160 	    case 1001:
3161 		set_dxf_extra_key (dxf, line);
3162 		break;
3163 	    };
3164       }
3165     if (dxf->is_lwpolyline)
3166       {
3167 	  /* parsing LwPolyline attributes */
3168 	  switch (dxf->op_code)
3169 	    {
3170 	    case 8:
3171 		set_dxf_layer_name (dxf, line);
3172 		break;
3173 	    case 10:
3174 		dxf->curr_point.x = atof (line);
3175 		break;
3176 	    case 20:
3177 		dxf->curr_point.y = atof (line);
3178 		set_dxf_vertex (dxf);
3179 		break;
3180 	    case 70:
3181 		if ((atoi (line) & 0x01) == 0x01)
3182 		    dxf->is_closed_polyline = 1;
3183 		else
3184 		    dxf->is_closed_polyline = 0;
3185 		break;
3186 	    case 1000:
3187 		set_dxf_extra_value (dxf, line);
3188 		break;
3189 	    case 1001:
3190 		set_dxf_extra_key (dxf, line);
3191 		break;
3192 	    };
3193       }
3194     if (dxf->is_polyline && dxf->is_vertex != 1)
3195       {
3196 	  /* parsing Polyline attributes */
3197 	  switch (dxf->op_code)
3198 	    {
3199 	    case 8:
3200 		set_dxf_layer_name (dxf, line);
3201 		break;
3202 	    case 70:
3203 		if ((atoi (line) & 0x01) == 0x01)
3204 		    dxf->is_closed_polyline = 1;
3205 		else
3206 		    dxf->is_closed_polyline = 0;
3207 		break;
3208 	    case 1000:
3209 		set_dxf_extra_value (dxf, line);
3210 		break;
3211 	    case 1001:
3212 		set_dxf_extra_key (dxf, line);
3213 		break;
3214 	    };
3215       }
3216     if (dxf->is_vertex)
3217       {
3218 	  /* parsing Vertex attributes */
3219 	  switch (dxf->op_code)
3220 	    {
3221 	    case 10:
3222 		dxf->curr_point.x = atof (line);
3223 		break;
3224 	    case 20:
3225 		dxf->curr_point.y = atof (line);
3226 		break;
3227 	    case 30:
3228 		dxf->curr_point.z = atof (line);
3229 		break;
3230 	    };
3231       }
3232     if (dxf->is_hatch)
3233       {
3234 	  /* parsing Hatch attributes */
3235 	  switch (dxf->op_code)
3236 	    {
3237 	    case 8:
3238 		set_dxf_layer_name (dxf, line);
3239 		create_dxf_curr_hatch (dxf);
3240 		break;
3241 	    case 10:
3242 		if (dxf->is_hatch_boundary)
3243 		    dxf->curr_point.x = atof (line);
3244 		break;
3245 	    case 20:
3246 		if (dxf->is_hatch_boundary)
3247 		    dxf->curr_point.y = atof (line);
3248 		break;
3249 	    case 11:
3250 		if (dxf->is_hatch_boundary)
3251 		    dxf->curr_end_point.x = atof (line);
3252 		break;
3253 	    case 21:
3254 		dxf->curr_end_point.y = atof (line);
3255 		insert_dxf_hatch_boundary_segm (dxf);
3256 		break;
3257 	    case 41:
3258 		set_dxf_hatch_spacing (dxf, atof (line));
3259 		break;
3260 	    case 43:
3261 		set_dxf_hatch_base_x (dxf, atof (line));
3262 		break;
3263 	    case 44:
3264 		set_dxf_hatch_base_y (dxf, atof (line));
3265 		break;
3266 	    case 45:
3267 		set_dxf_hatch_offset_x (dxf, atof (line));
3268 		break;
3269 	    case 46:
3270 		set_dxf_hatch_offset_y (dxf, atof (line));
3271 		break;
3272 	    case 53:
3273 		set_dxf_hatch_angle (dxf, atof (line));
3274 		break;
3275 	    case 92:
3276 		start_dxf_hatch_boundary (dxf);
3277 		break;
3278 	    case 97:
3279 		dxf->is_hatch_boundary = 0;
3280 		break;
3281 	    };
3282       }
3283     return 1;
3284 }
3285 
3286 GAIAGEO_DECLARE gaiaDxfParserPtr
gaiaCreateDxfParser(int srid,int force_dims,const char * prefix,const char * selected_layer,int special_rings)3287 gaiaCreateDxfParser (int srid,
3288 		     int force_dims,
3289 		     const char *prefix,
3290 		     const char *selected_layer, int special_rings)
3291 {
3292 /* allocating and initializing a DXF parser object */
3293     gaiaDxfParserPtr dxf = malloc (sizeof (gaiaDxfParser));
3294     dxf->line_no = 0;
3295     dxf->op_code_line = 0;
3296     dxf->op_code = -1;
3297     dxf->section = 0;
3298     dxf->tables = 0;
3299     dxf->blocks = 0;
3300     dxf->entities = 0;
3301     dxf->is_layer = 0;
3302     dxf->is_block = 0;
3303     dxf->is_text = 0;
3304     dxf->is_point = 0;
3305     dxf->is_polyline = 0;
3306     dxf->is_lwpolyline = 0;
3307     dxf->is_line = 0;
3308     dxf->is_circle = 0;
3309     dxf->is_arc = 0;
3310     dxf->is_vertex = 0;
3311     dxf->is_hatch = 0;
3312     dxf->is_hatch_boundary = 0;
3313     dxf->is_insert = 0;
3314     dxf->eof = 0;
3315     dxf->error = 0;
3316     dxf->curr_layer_name = NULL;
3317     dxf->curr_insert.x = 0.0;
3318     dxf->curr_insert.y = 0.0;
3319     dxf->curr_insert.z = 0.0;
3320     dxf->curr_insert.scale_x = 0.0;
3321     dxf->curr_insert.scale_y = 0.0;
3322     dxf->curr_insert.scale_z = 0.0;
3323     dxf->curr_insert.angle = 0.0;
3324     dxf->curr_insert.block_id = NULL;
3325     dxf->curr_insert.is3Dtext = 0;
3326     dxf->curr_insert.is3Dpoint = 0;
3327     dxf->curr_insert.is3Dline = 0;
3328     dxf->curr_insert.is3Dpolyg = 0;
3329     dxf->curr_text.x = 0.0;
3330     dxf->curr_text.y = 0.0;
3331     dxf->curr_text.z = 0.0;
3332     dxf->curr_text.angle = 0.0;
3333     dxf->curr_text.label = NULL;
3334     dxf->curr_point.x = 0.0;
3335     dxf->curr_point.y = 0.0;
3336     dxf->curr_point.z = 0.0;
3337     dxf->curr_block.layer_name = NULL;
3338     dxf->curr_block.block_id = NULL;
3339     dxf->curr_block.first_text = NULL;
3340     dxf->curr_block.last_text = NULL;
3341     dxf->curr_block.first_point = NULL;
3342     dxf->curr_block.last_point = NULL;
3343     dxf->curr_block.first_line = NULL;
3344     dxf->curr_block.last_line = NULL;
3345     dxf->curr_block.first_polyg = NULL;
3346     dxf->curr_block.last_polyg = NULL;
3347     dxf->curr_block.first_hatch = NULL;
3348     dxf->curr_block.last_hatch = NULL;
3349     dxf->curr_block.is3Dtext = 0;
3350     dxf->curr_block.is3Dpoint = 0;
3351     dxf->curr_block.is3Dline = 0;
3352     dxf->curr_block.is3Dpolyg = 0;
3353     dxf->curr_end_point.x = 0.0;
3354     dxf->curr_end_point.y = 0.0;
3355     dxf->curr_end_point.z = 0.0;
3356     dxf->curr_circle.cx = 0.0;
3357     dxf->curr_circle.cy = 0.0;
3358     dxf->curr_circle.cz = 0.0;
3359     dxf->curr_circle.radius = 0.0;
3360     dxf->curr_arc.cx = 0.0;
3361     dxf->curr_arc.cy = 0.0;
3362     dxf->curr_arc.cz = 0.0;
3363     dxf->curr_arc.radius = 0.0;
3364     dxf->curr_arc.start = 0.0;
3365     dxf->curr_arc.stop = 0.0;
3366     dxf->is_closed_polyline = 0;
3367     dxf->extra_key = NULL;
3368     dxf->extra_value = NULL;
3369     dxf->first_pt = NULL;
3370     dxf->last_pt = NULL;
3371     dxf->first_ext = NULL;
3372     dxf->last_ext = NULL;
3373     dxf->filename = NULL;
3374     dxf->first_layer = NULL;
3375     dxf->last_layer = NULL;
3376     dxf->first_block = NULL;
3377     dxf->last_block = NULL;
3378     dxf->curr_hatch = NULL;
3379     dxf->force_dims = force_dims;
3380     if (srid <= 0)
3381 	srid = -1;
3382     dxf->srid = srid;
3383     dxf->prefix = prefix;
3384     dxf->selected_layer = selected_layer;
3385     dxf->linked_rings = 0;
3386     dxf->unlinked_rings = 0;
3387     if (special_rings == GAIA_DXF_RING_LINKED)
3388 	dxf->linked_rings = 1;
3389     if (special_rings == GAIA_DXF_RING_UNLINKED)
3390 	dxf->unlinked_rings = 1;
3391     dxf->undeclared_layers = 1;
3392     return dxf;
3393 }
3394 
3395 GAIAGEO_DECLARE void
gaiaDestroyDxfParser(gaiaDxfParserPtr dxf)3396 gaiaDestroyDxfParser (gaiaDxfParserPtr dxf)
3397 {
3398 /* memory cleanup: destroying a DXF parser object */
3399     gaiaDxfLayerPtr lyr;
3400     gaiaDxfLayerPtr n_lyr;
3401     gaiaDxfPointPtr pt;
3402     gaiaDxfPointPtr n_pt;
3403     gaiaDxfExtraAttrPtr ext;
3404     gaiaDxfExtraAttrPtr n_ext;
3405     gaiaDxfBlockPtr blk;
3406     gaiaDxfBlockPtr n_blk;
3407     if (dxf == NULL)
3408 	return;
3409     if (dxf->curr_text.label != NULL)
3410 	free (dxf->curr_text.label);
3411     if (dxf->curr_layer_name != NULL)
3412 	free (dxf->curr_layer_name);
3413     if (dxf->filename != NULL)
3414 	free (dxf->filename);
3415     lyr = dxf->first_layer;
3416     while (lyr != NULL)
3417       {
3418 	  n_lyr = lyr->next;
3419 	  destroy_dxf_layer (lyr);
3420 	  lyr = n_lyr;
3421       }
3422     pt = dxf->first_pt;
3423     while (pt != NULL)
3424       {
3425 	  n_pt = pt->next;
3426 	  destroy_dxf_point (pt);
3427 	  pt = n_pt;
3428       }
3429     if (dxf->extra_key != NULL)
3430 	free (dxf->extra_key);
3431     if (dxf->extra_value != NULL)
3432 	free (dxf->extra_value);
3433     ext = dxf->first_ext;
3434     while (ext != NULL)
3435       {
3436 	  n_ext = ext->next;
3437 	  destroy_dxf_extra (ext);
3438 	  ext = n_ext;
3439       }
3440     blk = dxf->first_block;
3441     while (blk != NULL)
3442       {
3443 	  n_blk = blk->next;
3444 	  destroy_dxf_block (blk);
3445 	  blk = n_blk;
3446       }
3447     if (dxf->curr_hatch != NULL)
3448 	destroy_dxf_hatch (dxf->curr_hatch);
3449     reset_dxf_block (dxf);
3450     free (dxf);
3451 }
3452 
3453 static void
save_dxf_filename(gaiaDxfParserPtr dxf,const char * path)3454 save_dxf_filename (gaiaDxfParserPtr dxf, const char *path)
3455 {
3456 /* saving the input/origin filename */
3457     int len = strlen (path);
3458     const char *start = path;
3459     const char *stop = path + len - 1;
3460     const char *p = path;
3461     if (dxf->filename != NULL)
3462 	free (dxf->filename);
3463     dxf->filename = NULL;
3464     if (path == NULL)
3465 	return;
3466 
3467     while (*p != '\0')
3468       {
3469 	  if (*p == '/' || *p == '\\')
3470 	      start = p + 1;
3471 	  p++;
3472       }
3473     p = stop;
3474     while (p > path)
3475       {
3476 	  if (*p == '.')
3477 	    {
3478 		stop = p - 1;
3479 		break;
3480 	    }
3481 	  p--;
3482       }
3483     if (stop > start)
3484       {
3485 	  len = stop - start + 1;
3486 	  dxf->filename = malloc (len + 1);
3487 	  memset (dxf->filename, '\0', len + 1);
3488 	  memcpy (dxf->filename, start, len);
3489       }
3490     else
3491       {
3492 	  dxf->filename = malloc (len + 1);
3493 	  strcpy (dxf->filename, path);
3494       }
3495 }
3496 
3497 static int
gaiaParseDxfFileCommon(const void * p_cache,gaiaDxfParserPtr dxf,const char * path)3498 gaiaParseDxfFileCommon (const void *p_cache, gaiaDxfParserPtr dxf,
3499 			const char *path)
3500 {
3501 /* parsing the whole DXF file */
3502     int c;
3503     char line[4192];
3504     char *p = line;
3505     FILE *fl;
3506 
3507     if (dxf == NULL)
3508 	return 0;
3509     save_dxf_filename (dxf, path);
3510     if (dxf->first_layer != NULL || dxf->first_block != NULL)
3511 	return 0;
3512 
3513 /* attempting to open the input file */
3514 #ifdef _WIN32
3515     fl = gaia_win_fopen (path, "rb");
3516 #else
3517     fl = fopen (path, "rb");
3518 #endif
3519     if (fl == NULL)
3520 	return 0;
3521 
3522 /* scanning the DXF file */
3523     while ((c = getc (fl)) != EOF)
3524       {
3525 	  if (c == '\r')
3526 	    {
3527 		/* ignoring any CR */
3528 		continue;
3529 	    }
3530 	  if (c == '\n')
3531 	    {
3532 		/* end line found */
3533 		*p = '\0';
3534 		if (!parse_dxf_line (p_cache, dxf, line))
3535 		    goto stop;
3536 		if (dxf->eof)
3537 		  {
3538 		      /* EOF marker found - quitting */
3539 		      break;
3540 		  }
3541 		p = line;
3542 		continue;
3543 	    }
3544 	  *p++ = (char) c;
3545 	  /* Even Rouault 2013-06-02 - avoiding a potential buffer overflow */
3546 	  if (p - line == sizeof (line) - 1)
3547 	      goto stop;
3548 	  /* END - Even Rouault 2013-06-02 */
3549       }
3550 
3551     fclose (fl);
3552     return 1;
3553   stop:
3554     fclose (fl);
3555     return 0;
3556 }
3557 
3558 GAIAGEO_DECLARE int
gaiaParseDxfFile(gaiaDxfParserPtr dxf,const char * path)3559 gaiaParseDxfFile (gaiaDxfParserPtr dxf, const char *path)
3560 {
3561     return gaiaParseDxfFileCommon (NULL, dxf, path);
3562 }
3563 
3564 GAIAGEO_DECLARE int
gaiaParseDxfFile_r(const void * p_cache,gaiaDxfParserPtr dxf,const char * path)3565 gaiaParseDxfFile_r (const void *p_cache, gaiaDxfParserPtr dxf, const char *path)
3566 {
3567     return gaiaParseDxfFileCommon (p_cache, dxf, path);
3568 }
3569 
3570 #endif /* GEOS enabled */
3571