54 #include <pango/pango.h>
69 #define DPRINTF(...) do { if (DEBUG) printf(__VA_ARGS__); } while (0)
76 const char *names[] = {
94 if (type >=0 && type <
sizeof(names)/
sizeof(names[0]))
97 return N_(
"<undefined>");
102 const char* names[] = {
108 if (state >= 0 && state <
sizeof(names) /
sizeof(names[0])) {
112 return N_(
"<undefined>");
120 const char *names[] = {
127 N_(
"poly area start"),
128 N_(
"poly area stop"),
132 if (interp >= 0 && interp <
sizeof(names)/
sizeof(names[0]))
133 return names[interp];
135 return N_(
"<undefined>");
138 #define NUMBER_OF_DEFAULT_COLORS 18
139 #define NUMBER_OF_DEFAULT_TRANSFORMATIONS 20
141 static int defaultColorIndex = 0;
167 {0,0,1,1,0,FALSE,FALSE,FALSE},
168 {0,0,1,1,0,FALSE,FALSE,FALSE},
169 {0,0,1,1,0,FALSE,FALSE,FALSE},
170 {0,0,1,1,0,FALSE,FALSE,FALSE},
171 {0,0,1,1,0,FALSE,FALSE,FALSE},
172 {0,0,1,1,0,FALSE,FALSE,FALSE},
173 {0,0,1,1,0,FALSE,FALSE,FALSE},
174 {0,0,1,1,0,FALSE,FALSE,FALSE},
175 {0,0,1,1,0,FALSE,FALSE,FALSE},
176 {0,0,1,1,0,FALSE,FALSE,FALSE},
177 {0,0,1,1,0,FALSE,FALSE,FALSE},
178 {0,0,1,1,0,FALSE,FALSE,FALSE},
179 {0,0,1,1,0,FALSE,FALSE,FALSE},
180 {0,0,1,1,0,FALSE,FALSE,FALSE},
181 {0,0,1,1,0,FALSE,FALSE,FALSE},
182 {0,0,1,1,0,FALSE,FALSE,FALSE},
183 {0,0,1,1,0,FALSE,FALSE,FALSE},
184 {0,0,1,1,0,FALSE,FALSE,FALSE},
185 {0,0,1,1,0,FALSE,FALSE,FALSE},
186 {0,0,1,1,0,FALSE,FALSE,FALSE},
196 returnProject->
path = g_get_current_dir ();
203 return returnProject;
214 if (gerbvProject->
file[i]) {
216 g_free(gerbvProject->
file[i]);
220 g_free (gerbvProject->
path);
223 g_free (gerbvProject->
project);
225 g_free (gerbvProject->
file);
226 g_free (gerbvProject);
234 g_free (fileInfo->
name);
236 cairo_surface_destroy ((cairo_surface_t *)
246 DPRINTF(
"Opening filename = %s\n", filename);
249 GERB_COMPILE_WARNING(_(
"Could not read \"%s\" (loaded %d)"),
255 DPRINTF(
" Successfully opened file!\n");
262 guint16 red, guint16 green, guint16 blue, guint16 alpha)
265 DPRINTF(
"Opening filename = %s\n", filename);
268 GERB_COMPILE_WARNING(_(
"Could not read \"%s\" (loaded %d)"),
274 GdkColor colorTemplate = {0, red, green, blue};
275 gerbvProject->
file[idx_loaded]->
color = colorTemplate;
276 gerbvProject->
file[idx_loaded]->
alpha = alpha;
277 DPRINTF(
" Successfully opened file!\n");
283 gerbv_save_layer_from_index(
gerbv_project_t *gerbvProject, gint index, gchar *filename)
293 GERB_COMPILE_ERROR(_(
"Exporting mirrored file "
294 "is not supported!"));
300 GERB_COMPILE_ERROR(_(
"Exporting inverted file "
301 "is not supported!"));
314 GERB_COMPILE_ERROR(_(
"Exporting inverted file "
315 "is not supported!"));
349 for (idx = 0; idx <= gerbvProject->
last_loaded; idx++) {
351 (void) gerbv_revert_file (gerbvProject, idx);
364 g_free (gerbvProject->
file[index]);
367 for (i=index; i<(gerbvProject->
last_loaded); i++) {
368 gerbvProject->
file[i]=gerbvProject->
file[i+1];
383 for (index = gerbvProject->
last_loaded ; index >= 0; index--) {
384 if (gerbvProject->
file[index] && gerbvProject->
file[index]->
name) {
385 gerbv_unload_layer (gerbvProject, index);
393 gerbv_change_layer_order(
gerbv_project_t *gerbvProject, gint oldPosition, gint newPosition)
398 temp_file = gerbvProject->
file[oldPosition];
400 if (oldPosition < newPosition){
401 for (index = oldPosition; index < newPosition; index++) {
402 gerbvProject->
file[index] = gerbvProject->
file[index + 1];
405 for (index = oldPosition; index > newPosition; index--) {
406 gerbvProject->
file[index] = gerbvProject->
file[index - 1];
409 gerbvProject->
file[newPosition] = temp_file;
416 gchar
const* filename, gchar
const* baseName,
int idx,
int reload){
417 gerb_verify_error_t error = GERB_IMAGE_OK;
420 DPRINTF(
"In open_image, now error check file....\n");
421 error = gerbv_image_verify(parsed_image);
424 if (error & GERB_IMAGE_MISSING_NETLIST) {
425 GERB_COMPILE_ERROR(_(
"Missing netlist - aborting file read"));
431 if (error & GERB_IMAGE_MISSING_FORMAT)
432 g_warning(_(
"Missing format in file...trying to load anyways\n"));
433 if (error & GERB_IMAGE_MISSING_APERTURES) {
434 g_warning(_(
"Missing apertures/drill sizes...trying to load anyways\n"));
439 if (error & GERB_IMAGE_MISSING_INFO)
440 g_warning(_(
"Missing info...trying to load anyways\n"));
449 gerbvProject->
file[idx]->
image = parsed_image;
454 gerbvProject->
file[idx]->
image = parsed_image;
461 gerbvProject->
file[idx]->
name = g_strdup (baseName);
464 r = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].red*257;
465 g = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].green*257;
466 b = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].blue*257;
468 GdkColor colorTemplate = {0, r, g, b};
469 gerbvProject->
file[idx]->
color = colorTemplate;
470 gerbvProject->
file[idx]->
alpha = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].alpha*257;
472 gerbvProject->
file[idx]->
transform = defaultTransformations[defaultColorIndex % NUMBER_OF_DEFAULT_TRANSFORMATIONS];
484 gerbv_HID_Attribute *fattr,
int n_fattr, gboolean forceLoadFile)
489 gboolean isPnpFile = FALSE, foundBinary;
490 gerbv_HID_Attribute *attr_list = NULL;
511 if ((idx+1) >= gerbvProject->
max_files) {
520 DPRINTF(
"In open_image, about to try opening filename = %s\n", filename);
522 fd = gerb_fopen(filename);
524 GERB_COMPILE_ERROR(_(
"Trying to open \"%s\": %s"),
525 filename, strerror(errno));
529 DPRINTF(
"In open_image, successfully opened file. Now check its type....\n");
537 DPRINTF(
"Found RS-274X file\n");
538 if (!foundBinary || forceLoadFile) {
541 gchar *currentLoadDirectory = g_path_get_dirname (filename);
542 parsed_image =
parse_gerb(fd, currentLoadDirectory);
543 g_free (currentLoadDirectory);
545 }
else if(drill_file_p(fd, &foundBinary)) {
546 DPRINTF(
"Found drill file\n");
547 if (!foundBinary || forceLoadFile)
548 parsed_image = parse_drillfile(fd, attr_list, n_attr, reload);
550 }
else if (pick_and_place_check_file_type(fd, &foundBinary)) {
551 DPRINTF(
"Found pick-n-place file\n");
552 if (!foundBinary || forceLoadFile) {
554 pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
561 parsed_image2 = (
void *)1;
562 pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
563 parsed_image2 = NULL;
569 parsed_image2 = (
void *)1;
570 pick_and_place_parse_file_to_images(fd, &parsed_image2, &parsed_image);
571 parsed_image2 = NULL;
574 GERB_COMPILE_ERROR(_(
"%s: unknown pick-and-place board side to reload"), filename);
581 gchar *str = g_strdup_printf(_(
"Most likely found a RS-274D file "
582 "\"%s\" ... trying to open anyways\n"), filename);
584 g_warning(
"%s", str);
587 if (!foundBinary || forceLoadFile) {
590 gchar *currentLoadDirectory = g_path_get_dirname (filename);
591 parsed_image =
parse_gerb(fd, currentLoadDirectory);
592 g_free (currentLoadDirectory);
596 DPRINTF(
"Unknown filetype");
597 GERB_COMPILE_ERROR(_(
"%s: Unknown file type."), filename);
602 if (parsed_image == NULL) {
608 if ((parsed_image->
netlist != NULL)
615 _(
"File \"%s\" contains no drill hits or routes"),
621 _(
"File \"%s\" contains no drawing elements"),
627 gchar *baseName = g_path_get_basename (filename);
628 gchar *displayedName;
630 displayedName = g_strconcat (baseName, _(
" (top)"), NULL);
632 displayedName = g_strdup (baseName);
633 retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image, filename, displayedName, idx, reload);
635 g_free (displayedName);
645 gchar *baseName = g_path_get_basename (filename);
646 gchar *displayedName;
647 displayedName = g_strconcat (baseName, _(
" (bottom)"), NULL);
648 retv = gerbv_add_parsed_image_to_project (gerbvProject, parsed_image2, filename, displayedName, idx + 1, reload);
650 g_free (displayedName);
660 gboolean foundBinary;
662 fd = gerb_fopen(filename);
667 || drill_file_p(fd, &foundBinary)
668 || pick_and_place_check_file_type(fd, &foundBinary)
681 fd = gerb_fopen(filename);
683 GERB_COMPILE_ERROR(_(
"Trying to open \"%s\": %s"),
684 filename, strerror(errno));
687 returnImage = parse_drillfile(fd, NULL, 0, 0);
697 fd = gerb_fopen(filename);
699 GERB_COMPILE_ERROR(_(
"Trying to open \"%s\": %s"),
700 filename, strerror(errno));
703 gchar *currentLoadDirectory = g_path_get_dirname (filename);
704 returnImage =
parse_gerb(fd, currentLoadDirectory);
705 g_free (currentLoadDirectory);
710 static inline int isnormal_or_zero(
double x)
712 int cl = fpclassify(x);
713 return cl == FP_NORMAL || cl == FP_ZERO;
720 double x1=HUGE_VAL,y1=HUGE_VAL, x2=-HUGE_VAL,y2=-HUGE_VAL;
723 gdouble minX, minY, maxX, maxY;
740 if (!isnormal_or_zero(minX) || !isnormal_or_zero(minY)
741 || !isnormal_or_zero(maxX) || !isnormal_or_zero(maxY)) {
746 cairo_matrix_t fullMatrix;
747 cairo_matrix_init (&fullMatrix, 1, 0, 0, 1, 0, 0);
758 cairo_matrix_scale (&fullMatrix, scaleX, scaleY);
761 cairo_matrix_transform_point (&fullMatrix, &minX, &minY);
762 cairo_matrix_transform_point (&fullMatrix, &maxX, &maxY);
775 boundingbox->
left = x1;
776 boundingbox->
right = x2;
777 boundingbox->
top = y1;
786 double width, height;
787 double x_scale, y_scale;
790 gerbv_render_get_boundingbox(gerbvProject, &bb);
799 if (!isnormal(width)||!isnormal(height)||((width < 0.01) && (height < 0.01))) {
815 renderInfo->
scaleFactorX = MIN((gdouble)GERBV_SCALE_MAX,
817 renderInfo->
scaleFactorX = MAX((gdouble)GERBV_SCALE_MIN,
832 gerbv_render_get_boundingbox(gerbvProject, &bb);
841 gerbv_render_to_pixmap_using_gdk (
gerbv_project_t *gerbvProject, GdkPixmap *pixmap,
843 GdkColor *selectionColor){
844 GdkGC *gc = gdk_gc_new(pixmap);
845 GdkPixmap *colorStamp, *clipmask;
852 gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->
background, FALSE, TRUE);
853 gdk_gc_set_foreground(gc, &gerbvProject->
background);
854 gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, -1, -1);
859 colorStamp = gdk_pixmap_new(pixmap, renderInfo->
displayWidth,
861 clipmask = gdk_pixmap_new(NULL, renderInfo->
displayWidth,
875 gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->
file[i]->
color, FALSE, TRUE);
876 gdk_gc_set_foreground(gc, &gerbvProject->
file[i]->
color);
880 gdk_gc_set_function(gc, GDK_COPY);
881 gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
884 gdk_gc_set_function(gc, GDK_COPY);
887 gdk_gc_set_function(gc, GDK_XOR);
893 DPRINTF(
" .... calling image2pixmap on image %d...\n", i);
895 draw_gdk_image_to_pixmap(&clipmask, gerbvProject->
file[i]->
image,
898 DRAW_IMAGE, NULL, renderInfo, gerbvProject->
file[i]->
transform);
905 gdk_gc_set_clip_mask(gc, clipmask);
906 gdk_gc_set_clip_origin(gc, 0, 0);
907 gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
908 gdk_gc_set_clip_mask(gc, NULL);
913 if (selectionInfo && selectionInfo->selectedNodeArray
914 && (selection_length (selectionInfo) != 0)) {
915 if (!selectionColor->pixel)
916 gdk_colormap_alloc_color(gdk_colormap_get_system(), selectionColor, FALSE, TRUE);
918 gdk_gc_set_foreground(gc, selectionColor);
919 gdk_gc_set_function(gc, GDK_COPY);
920 gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
922 gerbv_selection_item_t sItem;
928 file = gerbvProject->
file[j];
932 for (k = 0; k < selection_length (selectionInfo); k++) {
933 sItem = selection_get_item_by_index (selectionInfo, k);
935 if (file->
image != sItem.image)
939 draw_gdk_image_to_pixmap(&clipmask, file->
image,
943 DRAW_SELECTIONS, selectionInfo,
946 gdk_gc_set_clip_mask(gc, clipmask);
947 gdk_gc_set_clip_origin(gc, 0, 0);
948 gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
949 gdk_gc_set_clip_mask(gc, NULL);
956 gdk_pixmap_unref(colorStamp);
957 gdk_pixmap_unref(clipmask);
963 gerbv_render_all_layers_to_cairo_target_for_vector_output (
971 gerbv_render_cairo_set_scale_and_translation (cr, renderInfo);
975 if ((bg->red != 0xffff || bg->green != 0xffff || bg->blue != 0xffff)
976 && (bg->red != 0x0000 || bg->green != 0x0000 || bg->blue != 0x0000)) {
977 r = (double) bg->red/G_MAXUINT16;
978 g = (
double) bg->green/G_MAXUINT16;
979 b = (double) bg->blue/G_MAXUINT16;
980 cairo_set_source_rgba (cr, r, g, b, 1);
985 cairo_set_user_data (cr, (cairo_user_data_key_t *)0, &r, NULL);
986 cairo_set_user_data (cr, (cairo_user_data_key_t *)1, &g, NULL);
987 cairo_set_user_data (cr, (cairo_user_data_key_t *)2, &b, NULL);
992 gerbv_render_layer_to_cairo_target_without_transforming(
993 cr, gerbvProject->
file[i],
1001 gerbv_render_all_layers_to_cairo_target (
gerbv_project_t *gerbvProject,
1007 cairo_set_source_rgba (cr,
1008 (
double) gerbvProject->
background.red/G_MAXUINT16,
1009 (
double) gerbvProject->
background.green/G_MAXUINT16,
1010 (
double) gerbvProject->
background.blue/G_MAXUINT16, 1);
1013 for (i = gerbvProject->
last_loaded; i >= 0; i--) {
1015 cairo_push_group (cr);
1017 gerbvProject->
file[i], renderInfo);
1018 cairo_pop_group_to_source (cr);
1019 cairo_paint_with_alpha (cr, (
double)
1020 gerbvProject->
file[i]->
alpha/G_MAXUINT16);
1029 gerbv_render_cairo_set_scale_and_translation(cr, renderInfo);
1030 gerbv_render_layer_to_cairo_target_without_transforming(cr, fileInfo, renderInfo, TRUE);
1035 gerbv_render_cairo_set_scale_and_translation(cairo_t *cr,
gerbv_render_info_t *renderInfo){
1036 gdouble translateX, translateY;
1044 cairo_set_tolerance (cr, 1.0);
1045 cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
1048 cairo_set_tolerance (cr, 0.1);
1049 cairo_set_antialias (cr, CAIRO_ANTIALIAS_DEFAULT);
1055 cairo_translate (cr, -translateX, translateY + renderInfo->
displayHeight);
1064 cairo_set_source_rgba (cr, (
double) fileInfo->
color.red/G_MAXUINT16,
1065 (
double) fileInfo->
color.green/G_MAXUINT16,
1066 (
double) fileInfo->
color.blue/G_MAXUINT16, 1);
1071 draw_image_to_cairo_target (cr, fileInfo->
image,
1073 renderInfo, TRUE, fileInfo->
transform, pixelOutput);
1078 gerbv_attribute_destroy_HID_attribute (gerbv_HID_Attribute *attributeList,
int n_attr)
1083 for (i = 0 ; i < n_attr ; i++) {
1084 if ( (attributeList[i].type == HID_String ||
1085 attributeList[i].type == HID_Label) &&
1086 attributeList[i].default_val.str_value != NULL) {
1087 free (attributeList[i].default_val.str_value);
1089 if (attributeList[i].name != NULL) {
1090 free (attributeList[i].name);
1095 if (attributeList != NULL) {
1096 free (attributeList);
1102 gerbv_HID_Attribute *
1103 gerbv_attribute_dup (gerbv_HID_Attribute *attributeList,
int n_attr)
1105 gerbv_HID_Attribute *nl;
1108 nl = (gerbv_HID_Attribute *) malloc (n_attr *
sizeof (gerbv_HID_Attribute));
1110 fprintf (stderr,
"malloc failed in %s()\n", __FUNCTION__);
1116 for (i = 0 ; i < n_attr ; i++) {
1117 nl[i] = attributeList[i];
1118 nl[i].name = attributeList[i].name ? strdup (attributeList[i].name) : NULL;
1120 if (attributeList[i].type == HID_String ||
1121 attributeList[i].type == HID_Label) {
1122 nl[i].default_val.str_value =
1123 attributeList[i].default_val.str_value
1124 ? strdup (attributeList[i].default_val.str_value) : NULL;
1139 return project->
file[i];
1150 *x = x0*cos(rad) - *y*sin(rad);
1151 *y = x0*sin(rad) + *y*cos(rad);
1181 if (fileinfo == NULL) {
1182 DPRINTF(
"%s(): NULL fileinfo\n", __func__);
1193 int plen = strlen(path);
1194 int elen = strlen(ext);
1195 if ( plen < elen )
return FALSE;
1196 return (strcmp(path+plen-elen, ext) == 0) ? TRUE
Header info for the GDK rendering functions.
Header info for the cairo rendering functions and the related selection calculating functions.
Header info for the Excellon drill parsing functions.
gboolean gerbv_export_drill_file_from_image(const gchar *filename, gerbv_image_t *inputImage, gerbv_user_transformation_t *transform)
Export an image to a new file in Excellon drill format.
gboolean gerbv_export_rs274x_file_from_image(const gchar *filename, gerbv_image_t *inputImage, gerbv_user_transformation_t *transform)
Export an image to a new file in RS274X format.
void gerbv_destroy_image(gerbv_image_t *image)
Free an image structure.
void gerbv_image_create_dummy_apertures(gerbv_image_t *parsed_image)
Create any missing apertures in the specified image.
Header info for the statistics generating functions for RS274X files.
gboolean gerber_is_rs274d_p(gerb_file_t *fd)
gboolean gerber_is_rs274x_p(gerb_file_t *fd, gboolean *returnFoundBinary)
gerbv_image_t * parse_gerb(gerb_file_t *fd, gchar *directoryPath)
Header info for the RS274X parsing functions.
int gerbv_open_image(gerbv_project_t *gerbvProject, gchar const *filename, int idx, int reload, gerbv_HID_Attribute *fattr, int n_fattr, gboolean forceLoadFile)
gerbv_image_t * gerbv_create_rs274x_image_from_filename(gchar const *filename)
Parse a RS274X file and return the parsed image.
void gerbv_destroy_project(gerbv_project_t *gerbvProject)
Free a project and all related variables.
const char * gerbv_interpolation_name(gerbv_interpolation_t interp)
Return string name of gerbv_interpolation_t interpolation.
void gerbv_rotate_coord(double *x, double *y, double rad)
void gerbv_open_layer_from_filename_with_color(gerbv_project_t *gerbvProject, gchar const *filename, guint16 red, guint16 green, guint16 blue, guint16 alpha)
Open a file, parse the contents, and add a new layer to an existing project while setting the color o...
gerbv_project_t * gerbv_create_project(void)
Create a new project structure and initialize some important variables.
const char * gerbv_aperture_state_name(gerbv_aperture_state_t state)
gboolean gerbv_is_loadable_file(const char *filename)
gerbv_fileinfo_t * gerbv_get_fileinfo_for_image(const gerbv_image_t *image, const gerbv_project_t *project)
void gerbv_open_layer_from_filename(gerbv_project_t *gerbvProject, gchar const *filename)
Open a file, parse the contents, and add a new layer to an existing project.
void gerbv_transform_coord(double *x, double *y, const gerbv_user_transformation_t *trans)
gboolean gerbv_endswith(const char *path, const char *ext)
void gerbv_destroy_fileinfo(gerbv_fileinfo_t *fileInfo)
Free a fileinfo structure.
const char * gerbv_aperture_type_name(gerbv_aperture_type_t type)
Return string name of gerbv_aperture_type_t aperture type.
void gerbv_render_zoom_to_fit_display(gerbv_project_t *gerbvProject, gerbv_render_info_t *renderInfo)
Calculate the zoom and translations to fit the rendered scene inside the given scene size.
int gerbv_transform_coord_for_image(double *x, double *y, const gerbv_image_t *image, const gerbv_project_t *project)
gerbv_image_t * gerbv_create_excellon_image_from_filename(const gchar *filename)
Parse an Excellon drill file and return the parsed image.
void gerbv_render_layer_to_cairo_target(cairo_t *cr, gerbv_fileinfo_t *fileInfo, gerbv_render_info_t *renderInfo)
Render a layer to a cairo context.
The main header file for the libgerbv library.
@ GERBV_RENDER_TYPE_CAIRO_HIGH_QUALITY
@ GERBV_RENDER_TYPE_GDK_XOR
@ GERBV_RENDER_TYPE_CAIRO_NORMAL
@ GERBV_LAYERTYPE_PICKANDPLACE_BOT
@ GERBV_LAYERTYPE_PICKANDPLACE_TOP
Header info for the PNP (pick-and-place) parsing functions.
Header info for the selection support functions for libgerbv.
gerbv_user_transformation_t transform
gpointer privateRenderData
gerbv_stats_t * gerbv_stats
gerbv_layertype_t layertype
gerbv_drill_stats_t * drill_stats
gerbv_image_info_t * info
gboolean show_invisible_selection
gboolean check_before_delete
gerbv_render_types_t renderType