53 #include <pango/pango.h>
75 const char* names[] = {
76 N_(
"none"), N_(
"circle"), N_(
"rectangle"), N_(
"oval"),
89 if (type >= 0 && type <
sizeof(names) /
sizeof(names[0]))
92 return N_(
"<undefined>");
100 const char* names[] = {
101 N_(
"1X linear"), N_(
"10X linear"), N_(
"0.1X linear"), N_(
"0.01X linear"), N_(
"CW circular"),
102 N_(
"CCW circular"), N_(
"poly area start"), N_(
"poly area stop"), N_(
"deleted"),
105 if (interp >= 0 && interp <
sizeof(names) /
sizeof(names[0]))
106 return names[interp];
108 return N_(
"<undefined>");
111 #define NUMBER_OF_DEFAULT_COLORS 18
112 #define NUMBER_OF_DEFAULT_TRANSFORMATIONS 20
114 static int defaultColorIndex = 0;
118 {115, 115, 222, 177},
119 {255, 127, 115, 177},
121 {117, 242, 103, 177},
126 {186, 186, 186, 177},
127 {211, 211, 255, 177},
128 {253, 210, 206, 177},
129 {236, 194, 242, 177},
130 {208, 249, 204, 177},
131 {183, 255, 255, 177},
132 {241, 255, 183, 177},
133 {255, 202, 225, 177},
134 {253, 238, 197, 177},
140 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
141 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
142 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
143 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
144 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
145 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
146 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
147 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
148 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
149 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
150 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
151 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
152 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
153 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
154 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
155 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
156 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
157 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
158 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
159 {0, 0, 1, 1, 0, FALSE, FALSE, FALSE},
169 returnProject->
path = g_get_current_dir();
176 return returnProject;
186 if (gerbvProject->
file[i]) {
188 g_free(gerbvProject->
file[i]);
192 g_free(gerbvProject->
path);
197 g_free(gerbvProject->
file);
198 g_free(gerbvProject);
206 g_free(fileInfo->
name);
216 dprintf(
"Opening filename = %s\n", filename);
218 if (gerbv_open_image(gerbvProject, filename, ++gerbvProject->
last_loaded, FALSE, NULL, 0, TRUE) == -1) {
219 GERB_COMPILE_WARNING(_(
"Could not read \"%s\" (loaded %d)"), filename, gerbvProject->
last_loaded);
224 dprintf(
" Successfully opened file!\n");
231 gerbv_project_t* gerbvProject,
const gchar* filename, guint16 red, guint16 green, guint16 blue, guint16 alpha
234 dprintf(
"Opening filename = %s\n", filename);
236 if (gerbv_open_image(gerbvProject, filename, ++gerbvProject->
last_loaded, FALSE, NULL, 0, TRUE) == -1) {
237 GERB_COMPILE_WARNING(_(
"Could not read \"%s\" (loaded %d)"), filename, gerbvProject->
last_loaded);
242 GdkColor colorTemplate = { 0, red, green, blue };
243 gerbvProject->
file[idx_loaded]->
color = colorTemplate;
244 gerbvProject->
file[idx_loaded]->
alpha = alpha;
245 dprintf(
" Successfully opened file!\n");
251 gerbv_save_layer_from_index(
gerbv_project_t* gerbvProject, gint index, gchar* filename) {
261 _(
"Exporting mirrored file "
270 _(
"Exporting inverted file "
285 _(
"Exporting inverted file "
294 default:
return FALSE;
307 rv = gerbv_open_image(gerbvProject, gerbvProject->
file[idx]->
fullPathname, idx, TRUE, NULL, 0, TRUE);
317 for (idx = 0; idx <= gerbvProject->
last_loaded; idx++) {
319 (void)gerbv_revert_file(gerbvProject, idx);
333 for (i = index; i < (gerbvProject->
last_loaded); i++) {
334 gerbvProject->
file[i] = gerbvProject->
file[i + 1];
348 for (index = gerbvProject->
last_loaded; index >= 0; index--) {
349 if (gerbvProject->
file[index] && gerbvProject->
file[index]->
name) {
350 gerbv_unload_layer(gerbvProject, index);
357 gerbv_change_layer_order(
gerbv_project_t* gerbvProject, gint oldPosition, gint newPosition) {
361 temp_file = gerbvProject->
file[oldPosition];
363 if (oldPosition < newPosition) {
364 for (index = oldPosition; index < newPosition; index++) {
365 gerbvProject->
file[index] = gerbvProject->
file[index + 1];
368 for (index = oldPosition; index > newPosition; index--) {
369 gerbvProject->
file[index] = gerbvProject->
file[index - 1];
372 gerbvProject->
file[newPosition] = temp_file;
377 gerbv_add_parsed_image_to_project(
381 gerb_verify_error_t error = GERB_IMAGE_OK;
384 dprintf(
"In open_image, now error check file....\n");
385 error = gerbv_image_verify(parsed_image);
388 if (error & GERB_IMAGE_MISSING_NETLIST) {
389 GERB_COMPILE_ERROR(_(
"Missing netlist - aborting file read"));
395 if (error & GERB_IMAGE_MISSING_FORMAT)
396 g_warning(_(
"Missing format in file...trying to load anyways\n"));
397 if (error & GERB_IMAGE_MISSING_APERTURES) {
398 g_warning(_(
"Missing apertures/drill sizes...trying to load anyways\n"));
403 if (error & GERB_IMAGE_MISSING_INFO)
404 g_warning(_(
"Missing info...trying to load anyways\n"));
413 gerbvProject->
file[idx]->
image = parsed_image;
418 gerbvProject->
file[idx]->
image = parsed_image;
425 gerbvProject->
file[idx]->
name = g_strdup(baseName);
427 r = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].red * 257;
428 g = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].green * 257;
429 b = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].blue * 257;
431 GdkColor colorTemplate = { 0, r, g, b };
432 gerbvProject->
file[idx]->
color = colorTemplate;
433 gerbvProject->
file[idx]->
alpha = defaultColors[defaultColorIndex % NUMBER_OF_DEFAULT_COLORS].alpha * 257;
435 gerbvProject->
file[idx]->
transform = defaultTransformations[defaultColorIndex % NUMBER_OF_DEFAULT_TRANSFORMATIONS];
447 gerbv_project_t* gerbvProject,
const gchar* filename,
int idx,
int reload, gerbv_HID_Attribute* fattr,
int n_fattr,
448 gboolean forceLoadFile
453 gboolean isPnpFile = FALSE, foundBinary;
454 gerbv_HID_Attribute* attr_list = NULL;
472 if ((idx + 1) >= gerbvProject->
max_files) {
480 dprintf(
"In open_image, about to try opening filename = %s\n", filename);
482 fd = gerb_fopen(filename);
484 GERB_COMPILE_ERROR(_(
"Trying to open \"%s\": %s"), filename, strerror(errno));
488 dprintf(
"In open_image, successfully opened file. Now check its type....\n");
496 dprintf(
"Found RS-274X file\n");
497 if (!foundBinary || forceLoadFile) {
500 gchar* currentLoadDirectory = g_path_get_dirname(filename);
501 parsed_image =
parse_gerb(fd, currentLoadDirectory);
502 g_free(currentLoadDirectory);
504 }
else if (drill_file_p(fd, &foundBinary)) {
505 dprintf(
"Found drill file\n");
506 if (!foundBinary || forceLoadFile)
507 parsed_image = parse_drillfile(fd, attr_list, n_attr, reload);
509 }
else if (pick_and_place_check_file_type(fd, &foundBinary)) {
510 dprintf(
"Found pick-n-place file\n");
511 if (!foundBinary || forceLoadFile) {
513 pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
518 parsed_image2 = (
void*)!NULL;
519 pick_and_place_parse_file_to_images(fd, &parsed_image, &parsed_image2);
520 parsed_image2 = NULL;
524 parsed_image2 = (
void*)!NULL;
525 pick_and_place_parse_file_to_images(fd, &parsed_image2, &parsed_image);
526 parsed_image2 = NULL;
528 default: GERB_COMPILE_ERROR(_(
"%s: unknown pick-and-place board side to reload"), filename);
535 gchar* str = g_strdup_printf(
536 _(
"Most likely found a RS-274D file "
537 "\"%s\" ... trying to open anyways\n"),
541 g_warning(
"%s", str);
544 if (!foundBinary || forceLoadFile) {
547 gchar* currentLoadDirectory = g_path_get_dirname(filename);
548 parsed_image =
parse_gerb(fd, currentLoadDirectory);
549 g_free(currentLoadDirectory);
553 dprintf(
"Unknown filetype");
554 GERB_COMPILE_ERROR(_(
"%s: Unknown file type."), filename);
559 if (parsed_image == NULL) {
565 gchar* baseName = g_path_get_basename(filename);
566 gchar* displayedName;
568 displayedName = g_strconcat(baseName, _(
" (top)"), NULL);
570 displayedName = g_strdup(baseName);
571 retv = gerbv_add_parsed_image_to_project(gerbvProject, parsed_image, filename, displayedName, idx, reload);
573 g_free(displayedName);
583 gchar* baseName = g_path_get_basename(filename);
584 gchar* displayedName;
585 displayedName = g_strconcat(baseName, _(
" (bottom)"), NULL);
586 retv = gerbv_add_parsed_image_to_project(gerbvProject, parsed_image2, filename, displayedName, idx + 1, reload);
588 g_free(displayedName);
599 fd = gerb_fopen(filename);
601 GERB_COMPILE_ERROR(_(
"Trying to open \"%s\": %s"), filename, strerror(errno));
604 gchar* currentLoadDirectory = g_path_get_dirname(filename);
605 returnImage =
parse_gerb(fd, currentLoadDirectory);
606 g_free(currentLoadDirectory);
612 isnormal_or_zero(
double x) {
613 int cl = fpclassify(x);
614 return cl == FP_NORMAL || cl == FP_ZERO;
620 double x1 = HUGE_VAL, y1 = HUGE_VAL, x2 = -HUGE_VAL, y2 = -HUGE_VAL;
623 gdouble minX, minY, maxX, maxY;
639 if (!isnormal_or_zero(minX) || !isnormal_or_zero(minY) || !isnormal_or_zero(maxX)
640 || !isnormal_or_zero(maxY)) {
645 cairo_matrix_t fullMatrix;
646 cairo_matrix_init(&fullMatrix, 1, 0, 0, 1, 0, 0);
648 cairo_matrix_translate(
658 cairo_matrix_scale(&fullMatrix, scaleX, scaleY);
661 cairo_matrix_transform_point(&fullMatrix, &minX, &minY);
662 cairo_matrix_transform_point(&fullMatrix, &maxX, &maxY);
675 boundingbox->
left = x1;
676 boundingbox->
right = x2;
677 boundingbox->
top = y1;
685 double width, height;
686 double x_scale, y_scale;
689 gerbv_render_get_boundingbox(gerbvProject, &bb);
698 if (!isnormal(width) || !isnormal(height) || ((width < 0.01) && (height < 0.01))) {
729 gerbv_render_get_boundingbox(gerbvProject, &bb);
738 gerbv_render_to_pixmap_using_gdk(
742 GdkGC* gc = gdk_gc_new(pixmap);
743 GdkPixmap *colorStamp, *clipmask;
750 gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->
background, FALSE, TRUE);
751 gdk_gc_set_foreground(gc, &gerbvProject->
background);
752 gdk_draw_rectangle(pixmap, gc, TRUE, 0, 0, -1, -1);
771 gdk_colormap_alloc_color(gdk_colormap_get_system(), &gerbvProject->
file[i]->
color, FALSE, TRUE);
772 gdk_gc_set_foreground(gc, &gerbvProject->
file[i]->
color);
776 gdk_gc_set_function(gc, GDK_COPY);
777 gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
780 gdk_gc_set_function(gc, GDK_COPY);
782 gdk_gc_set_function(gc, GDK_XOR);
788 dprintf(
" .... calling image2pixmap on image %d...\n", i);
790 draw_gdk_image_to_pixmap(
802 gdk_gc_set_clip_mask(gc, clipmask);
803 gdk_gc_set_clip_origin(gc, 0, 0);
804 gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
805 gdk_gc_set_clip_mask(gc, NULL);
810 if (selectionInfo && selectionInfo->selectedNodeArray && (selection_length(selectionInfo) != 0)) {
811 if (!selectionColor->pixel)
812 gdk_colormap_alloc_color(gdk_colormap_get_system(), selectionColor, FALSE, TRUE);
814 gdk_gc_set_foreground(gc, selectionColor);
815 gdk_gc_set_function(gc, GDK_COPY);
816 gdk_draw_rectangle(colorStamp, gc, TRUE, 0, 0, -1, -1);
818 gerbv_selection_item_t sItem;
824 file = gerbvProject->
file[j];
828 for (k = 0; k < selection_length(selectionInfo); k++) {
829 sItem = selection_get_item_by_index(selectionInfo, k);
831 if (file->
image != sItem.image)
835 draw_gdk_image_to_pixmap(
839 selectionInfo, renderInfo, file->
transform
842 gdk_gc_set_clip_mask(gc, clipmask);
843 gdk_gc_set_clip_origin(gc, 0, 0);
844 gdk_draw_drawable(pixmap, gc, colorStamp, 0, 0, 0, 0, -1, -1);
845 gdk_gc_set_clip_mask(gc, NULL);
852 gdk_pixmap_unref(colorStamp);
853 gdk_pixmap_unref(clipmask);
859 gerbv_render_all_layers_to_cairo_target_for_vector_output(
866 gerbv_render_cairo_set_scale_and_translation(cr, renderInfo);
870 if ((bg->red != 0xffff || bg->green != 0xffff || bg->blue != 0xffff)
871 && (bg->red != 0x0000 || bg->green != 0x0000 || bg->blue != 0x0000)) {
872 r = (double)bg->red / G_MAXUINT16;
873 g = (
double)bg->green / G_MAXUINT16;
874 b = (double)bg->blue / G_MAXUINT16;
875 cairo_set_source_rgba(cr, r, g, b, 1);
880 cairo_set_user_data(cr, (cairo_user_data_key_t*)0, &r, NULL);
881 cairo_set_user_data(cr, (cairo_user_data_key_t*)1, &g, NULL);
882 cairo_set_user_data(cr, (cairo_user_data_key_t*)2, &b, NULL);
887 gerbv_render_layer_to_cairo_target_without_transforming(cr, gerbvProject->
file[i], renderInfo, FALSE);
898 cairo_set_source_rgba(
899 cr, (
double)gerbvProject->
background.red / G_MAXUINT16, (
double)gerbvProject->
background.green / G_MAXUINT16,
900 (
double)gerbvProject->
background.blue / G_MAXUINT16, 1
906 cairo_push_group(cr);
908 cairo_pop_group_to_source(cr);
909 cairo_paint_with_alpha(cr, (
double)gerbvProject->
file[i]->
alpha / G_MAXUINT16);
917 gerbv_render_cairo_set_scale_and_translation(cr, renderInfo);
918 gerbv_render_layer_to_cairo_target_without_transforming(cr, fileInfo, renderInfo, TRUE);
923 gerbv_render_cairo_set_scale_and_translation(cairo_t* cr,
gerbv_render_info_t* renderInfo) {
924 gdouble translateX, translateY;
932 cairo_set_tolerance(cr, 1.0);
933 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
935 cairo_set_tolerance(cr, 0.1);
936 cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT);
942 cairo_translate(cr, -translateX, translateY + renderInfo->
displayHeight);
950 gerbv_render_layer_to_cairo_target_without_transforming(
953 cairo_set_source_rgba(
954 cr, (
double)fileInfo->
color.red / G_MAXUINT16, (
double)fileInfo->
color.green / G_MAXUINT16,
955 (
double)fileInfo->
color.blue / G_MAXUINT16, 1
961 draw_image_to_cairo_target(
963 renderInfo, TRUE, fileInfo->
transform, pixelOutput
969 gerbv_attribute_destroy_HID_attribute(gerbv_HID_Attribute* attributeList,
int n_attr) {
973 for (i = 0; i < n_attr; i++) {
974 if ((attributeList[i].type == HID_String || attributeList[i].type == HID_Label)
975 && attributeList[i].default_val.str_value != NULL) {
976 free(attributeList[i].default_val.str_value);
981 if (attributeList != NULL) {
988 gerbv_attribute_dup(gerbv_HID_Attribute* attributeList,
int n_attr) {
989 gerbv_HID_Attribute* nl;
992 nl = (gerbv_HID_Attribute*)malloc(n_attr *
sizeof(gerbv_HID_Attribute));
994 fprintf(stderr,
"malloc failed in %s()\n", __FUNCTION__);
999 for (i = 0; i < n_attr; i++) {
1001 if (attributeList[i].type == HID_String || attributeList[i].type == HID_Label) {
1003 if (attributeList[i].default_val.str_value != NULL) {
1004 nl[i].default_val.str_value = strdup(attributeList[i].default_val.str_value);
1006 nl[i].default_val.str_value = NULL;
1010 nl[i] = attributeList[i];
1023 return project->
file[i];
1033 *x = x0 * cos(rad) - *y * sin(rad);
1034 *y = x0 * sin(rad) + *y * cos(rad);
1059 if (fileinfo == NULL) {
1060 dprintf(
"%s(): NULL fileinfo\n", __func__);
1071 int plen = strlen(path);
1072 int elen = strlen(ext);
1075 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.
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.
void gerbv_open_layer_from_filename(gerbv_project_t *gerbvProject, const gchar *filename)
Open a file, parse the contents, and add a new layer to an existing project.
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)
gerbv_image_t * gerbv_create_rs274x_image_from_filename(const gchar *filename)
Parse a RS274X file and return the parsed image.
gerbv_project_t * gerbv_create_project(void)
Create a new project structure and initialize some important variables.
void gerbv_open_layer_from_filename_with_color(gerbv_project_t *gerbvProject, const gchar *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_fileinfo_t * gerbv_get_fileinfo_for_image(const gerbv_image_t *image, const gerbv_project_t *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)
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_layertype_t layertype
gerbv_image_info_t * info
gboolean show_invisible_selection
gboolean check_before_delete
gerbv_render_types_t renderType