@@ -266,7 +266,8 @@ static uint16_t gds_convert_unsigned_int16(const char *data)
266266 * @param library_ptr Return of newly created library.
267267 * @return Newly created list pointer
268268 */
269- static GList * append_library (GList * curr_list , struct gds_library * * library_ptr )
269+ static GList * append_library (GList * curr_list , const struct gds_library_parsing_opts * opts ,
270+ struct gds_library * * library_ptr )
270271{
271272 struct gds_library * lib ;
272273
@@ -276,6 +277,8 @@ static GList *append_library(GList *curr_list, struct gds_library **library_ptr)
276277 lib -> name [0 ] = 0 ;
277278 lib -> unit_in_meters = GDS_DEFAULT_UNITS ; // Default. Will be overwritten
278279 lib -> cell_names = NULL ;
280+ /* Copy the settings into the library */
281+ memcpy (& lib -> parsing_opts , opts , sizeof (struct gds_library_parsing_opts ));
279282 } else
280283 return NULL ;
281284 if (library_ptr )
@@ -488,20 +491,102 @@ static void parse_reference_list(gpointer gcell_ref, gpointer glibrary)
488491}
489492
490493/**
491- * @brief Scans cell references inside cell
492- This function searches all the references in \p gcell and updates the gds_cell_instance::cell_ref field in each instance
494+ * @brief Simplify graphics objects
495+ * @param graphics gfx struct
496+ * @param user_data GDS library
497+ */
498+ static void simplify_graphics (gpointer graphics , gpointer user_data )
499+ {
500+ struct gds_graphics * gfx ;
501+ const struct gds_point * first_vertex = NULL ;
502+ const struct gds_point * prev_vertex = NULL ;
503+ const struct gds_point * current_vertex ;
504+ GList * vertex_iter ;
505+ GList * next_iter ;
506+ (void )user_data ;
507+ size_t processed_count = 0U ;
508+ size_t removed_count = 0U ;
509+
510+ gfx = (struct gds_graphics * )graphics ;
511+ if (gfx -> gfx_type == GRAPHIC_POLYGON ) {
512+ GDS_INF ("\t\t\tPolygon found\n" );
513+
514+ /* Loop over all vertices */
515+ for (vertex_iter = gfx -> vertices ; vertex_iter ;) {
516+ current_vertex = (const struct gds_point * )vertex_iter -> data ;
517+ next_iter = g_list_next (vertex_iter );
518+ processed_count ++ ;
519+
520+ if (vertex_iter == gfx -> vertices ) {
521+ /* This is the first vertex */
522+ first_vertex = current_vertex ;
523+ prev_vertex = NULL ;
524+ }
525+
526+ if (prev_vertex ) {
527+ if (current_vertex -> x == prev_vertex -> x && current_vertex -> y == prev_vertex -> y ) {
528+ /* Vertex is the same as the previous one */
529+ GDS_INF ("\t\t\t\tDuplicate vertex (%d,%d). Removing...\n" ,
530+ current_vertex -> x , current_vertex -> y );
531+
532+ /* Delete the current one from the list */
533+ gfx -> vertices = g_list_remove_link (gfx -> vertices , vertex_iter );
534+
535+ /* Free the data */
536+ if (vertex_iter -> data )
537+ free (vertex_iter -> data );
538+ vertex_iter -> data = NULL ;
539+ g_list_free_1 (vertex_iter );
540+ removed_count ++ ;
541+ } else if (!g_list_next (vertex_iter )) {
542+ /* This is the last element in the list */
543+ if (current_vertex -> x == first_vertex -> x &&
544+ current_vertex -> y == first_vertex -> y ) {
545+ GDS_INF ("\t\t\t\tLast vertex is identical to first vertex (%d,%d). Removing\n" ,
546+ current_vertex -> x , current_vertex -> y );
547+ gfx -> vertices = g_list_remove_link (gfx -> vertices , vertex_iter );
548+ if (vertex_iter -> data )
549+ free (vertex_iter -> data );
550+ g_list_free_1 (vertex_iter );
551+ removed_count ++ ;
552+ } else {
553+ GDS_WARN ("First vertex is not coincident with first vertex, although the GDS file format specifies this. However, this is not a problem." );
554+ }
555+ }
556+ }
557+
558+ vertex_iter = next_iter ;
559+ prev_vertex = current_vertex ;
560+ }
561+ GDS_INF ("\t\t\tProcessed %zu vertices. %zu removed.\n" , processed_count , removed_count );
562+ }
563+ }
564+
565+ /**
566+ * @brief Scans cell and resolves references and simplifies polygons
567+ * This function searches all the references in \p gcell and updates the gds_cell_instance::cell_ref field in each instance
568+ *
493569 * @param gcell pointer cast of #gds_cell *
494570 * @param library Library where the cell references are searched in
495571 */
496- static void scan_cell_reference_dependencies (gpointer gcell , gpointer library )
572+ static void scan_cell_references_and_polygons (gpointer gcell , gpointer library )
497573{
498574 struct gds_cell * cell = (struct gds_cell * )gcell ;
575+ struct gds_library * my_lib = (struct gds_library * )library ;
576+ int simplify_polygons ;
499577
500- GDS_INF ( "\tScanning cell: %s\n" , cell -> name ) ;
578+ simplify_polygons = my_lib -> parsing_opts . simplified_polygons ;
501579
580+ GDS_INF ("\tScanning cell: %s\n" , cell -> name );
581+ GDS_INF ("\t\tCell references\n" );
502582 /* Scan all library references */
503583 g_list_foreach (cell -> child_cells , parse_reference_list , library );
504584
585+
586+ GDS_INF ("\t\tSimplifying Polygons%s\n" , simplify_polygons ? "" : ": skipped" );
587+ if (simplify_polygons ) {
588+ g_list_foreach (cell -> graphic_objs , simplify_graphics , library );
589+ }
505590}
506591
507592/**
@@ -517,7 +602,7 @@ static void scan_library_references(gpointer library_list_item, gpointer user)
517602 (void )user ;
518603
519604 GDS_INF ("Scanning Library: %s\n" , lib -> name );
520- g_list_foreach (lib -> cells , scan_cell_reference_dependencies , lib );
605+ g_list_foreach (lib -> cells , scan_cell_references_and_polygons , lib );
521606}
522607
523608/**
@@ -617,7 +702,8 @@ static void convert_aref_to_sref(struct gds_cell_array_instance *aref, struct gd
617702 GDS_INF ("Converted AREF to SREFs\n" );
618703}
619704
620- int parse_gds_from_file (const char * filename , GList * * library_list )
705+ int parse_gds_from_file (const char * filename , GList * * library_list ,
706+ const struct gds_library_parsing_opts * parsing_options )
621707{
622708 char * workbuff ;
623709 int read ;
@@ -697,7 +783,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
697783 /* if begin: Allocate structures */
698784 switch (rec_type ) {
699785 case BGNLIB :
700- lib_list = append_library (lib_list , & current_lib );
786+ lib_list = append_library (lib_list , parsing_options , & current_lib );
701787 if (lib_list == NULL ) {
702788 GDS_ERROR ("Allocating memory failed" );
703789 run = -3 ;
@@ -771,7 +857,7 @@ int parse_gds_from_file(const char *filename, GList **library_list)
771857 run = -4 ;
772858 break ;
773859 }
774- GDS_INF ("\tEntering boundary/Box\n " );
860+ GDS_INF ("\tEntering boundary of type %s\n" , rec_type == BOUNDARY ? "polygon" : "box " );
775861 break ;
776862 case SREF :
777863 if (current_cell == NULL ) {
@@ -806,7 +892,9 @@ int parse_gds_from_file(const char *filename, GList **library_list)
806892 break ;
807893 case ENDEL :
808894 if (current_graphics != NULL ) {
809- GDS_INF ("\tLeaving %s\n" , (current_graphics -> gfx_type == GRAPHIC_POLYGON ? "boundary" : "path" ));
895+ GDS_INF ("\tLeaving %s\n" , (current_graphics -> gfx_type == GRAPHIC_POLYGON ? "boundary"
896+ : (current_graphics -> gfx_type == GRAPHIC_PATH ? "path"
897+ : "box" )));
810898 current_graphics = NULL ;
811899 }
812900 if (current_s_reference != NULL ) {
@@ -825,11 +913,11 @@ int parse_gds_from_file(const char *filename, GList **library_list)
825913
826914 } else if (current_s_reference ) {
827915 if (rec_data_length != 8 ) {
828- GDS_WARN ("Instance has weird coordinates. Rendered output might be screwed !" );
916+ GDS_WARN ("Instance has weird coordinates. Rendered output might be wrong !" );
829917 }
830918 } else if (current_a_reference ) {
831919 if (rec_data_length != (3 * (4 + 4 )))
832- GDS_WARN ("Array instance has weird coordinates. Rendered output might be screwed !" );
920+ GDS_WARN ("Array instance has weird coordinates. Rendered output might be wrong !" );
833921 }
834922 break ;
835923 case AREF :
0 commit comments