4 * PCB, interactive printed circuit board design
6 * NELMA (Numerical capacitance calculator) export HID
7 * Copyright (C) 2006 Tomaz Solc (tomaz.solc@tablix.org)
9 * PNG export code is based on the PNG export HID
10 * Copyright (C) 2006 Dan McMahill
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 * This HID exports a PCB layout into: o One layer mask file (PNG format) per
30 * copper layer. o Nelma configuration file that contains netlist and pin
37 * If you have a section of a net that does not contain any pins then that
38 * section will be missing from the Nelma's copper geometry.
42 * this section will be ignored by Nelma | |
44 * || ||=======|| || component layer ||
45 * || || || ||=============|| ||============||
50 * Single layer layouts are always exported correctly.
72 #include "../hidint.h"
73 #include "hid/common/draw_helpers.h"
78 #ifdef HAVE_LIBDMALLOC
84 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", __FUNCTION__); abort()
86 /* Needed for PNG export */
89 /* the descriptor used by the gd library */
92 /* so I can figure out what rgb value c refers to */
96 struct hid_gc_struct
{
100 unsigned char r
, g
, b
;
103 struct color_struct
*color
;
107 static struct color_struct
*black
= NULL
, *white
= NULL
;
108 static int linewidth
= -1;
109 static int lastgroup
= -1;
110 static gdImagePtr lastbrush
= (void *) -1;
111 static int lastcap
= -1;
112 static int lastcolor
= -1;
114 /* gd image and file for PNG export */
115 static gdImagePtr nelma_im
= NULL
;
116 static FILE *nelma_f
= NULL
;
122 * Which groups of layers to export into PNG layer masks. 1 means export, 0
123 * means do not export.
125 static int nelma_export_group
[MAX_LAYER
];
127 /* Group that is currently exported. */
128 static int nelma_cur_group
;
130 /* Filename prefix that will be used when saving files. */
131 static char *nelma_basename
= NULL
;
133 /* Horizontal DPI (grid points per inch) */
134 static int nelma_dpi
= -1;
136 /* Height of the copper layers in micrometers. */
139 * The height of the copper layer is currently taken as the vertical grid
140 * step, since this is the smallest vertical feature in the layout.
142 static int nelma_copperh
= -1;
143 /* Height of the substrate layers in micrometers. */
144 static int nelma_substrateh
= -1;
145 /* Relative permittivity of the substrate. */
146 static double nelma_substratee
= -1;
148 /* Permittivity of empty space (As/Vm) */
149 static const double nelma_air_epsilon
= 8.85e-12;
151 HID_Attribute nelma_attribute_list
[] = {
152 /* other HIDs expect this to be first. */
153 {"basename", "File name prefix",
154 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
155 #define HA_basename 0
157 {"dpi", "Horizontal scale factor (grid points/inch).",
158 HID_Integer
, 0, 1000, {100, 0, 0}, 0, 0},
161 {"copper-height", "Copper layer height (um).",
162 HID_Integer
, 0, 200, {100, 0, 0}, 0, 0},
165 {"substrate-height", "Substrate layer height (um).",
166 HID_Integer
, 0, 10000, {2000, 0, 0}, 0, 0},
167 #define HA_substrateh 3
169 {"substrate-epsilon", "Substrate relative epsilon.",
170 HID_Real
, 0, 100, {0, 0, 4.0}, 0, 0},
171 #define HA_substratee 4
174 #define NUM_OPTIONS (sizeof(nelma_attribute_list)/sizeof(nelma_attribute_list[0]))
176 REGISTER_ATTRIBUTES(nelma_attribute_list
)
177 static HID_Attr_Val nelma_values
[NUM_OPTIONS
];
179 /* *** Utility funcions **************************************************** */
181 /* convert from default PCB units (1/100 mil) to nelma units */
182 static int pcb_to_nelma(int pcb
)
186 nelma
= (pcb
* nelma_dpi
) / 100000;
192 nelma_get_png_name(const char *basename
, const char *suffix
)
197 len
= strlen(basename
) + strlen(suffix
) + 6;
198 buf
= malloc(sizeof(*buf
) * len
);
200 sprintf(buf
, "%s.%s.png", basename
, suffix
);
205 /* Retrieves coordinates (in default PCB units) of a pin or pad. */
206 /* Copied from netlist.c */
208 pin_name_to_xy(LibraryEntryType
* pin
, int *x
, int *y
)
211 if (!SeekPad(pin
, &conn
, false))
215 *x
= ((PinType
*) (conn
.ptr2
))->X
;
216 *y
= ((PinType
*) (conn
.ptr2
))->Y
;
219 *x
= ((PadType
*) (conn
.ptr2
))->Point1
.X
;
220 *y
= ((PadType
*) (conn
.ptr2
))->Point1
.Y
;
226 /* *** Exporting netlist data and geometry to the nelma config file ******** */
229 nelma_write_space(FILE * out
)
237 xh
= 2.54e-2 / ((double) nelma_dpi
);
238 zh
= nelma_copperh
* 1e-6;
240 fprintf(out
, "\n/* **** Space **** */\n\n");
242 fprintf(out
, "space pcb {\n");
243 fprintf(out
, "\tstep = { %e, %e, %e }\n", xh
, xh
, zh
);
244 fprintf(out
, "\tlayers = {\n");
246 fprintf(out
, "\t\t\"air-top\",\n");
247 fprintf(out
, "\t\t\"air-bottom\"");
250 for (i
= 0; i
< MAX_LAYER
; i
++)
251 if (nelma_export_group
[i
]) {
252 idx
= (i
>= 0 && i
< max_layer
) ?
253 PCB
->LayerGroups
.Entries
[i
][0] : i
;
254 ext
= layer_type_to_file_name(idx
);
258 fprintf(out
, "\t\t\"substrate-%d\"", z
);
262 fprintf(out
, "\t\t\"%s\"", ext
);
265 fprintf(out
, "\n\t}\n");
271 nelma_write_material(FILE * out
, char *name
, char *type
, double e
)
273 fprintf(out
, "material %s {\n", name
);
274 fprintf(out
, "\ttype = \"%s\"\n", type
);
275 fprintf(out
, "\tpermittivity = %e\n", e
);
276 fprintf(out
, "\tconductivity = 0.0\n");
277 fprintf(out
, "\tpermeability = 0.0\n");
282 nelma_write_materials(FILE * out
)
284 fprintf(out
, "\n/* **** Materials **** */\n\n");
286 nelma_write_material(out
, "copper", "metal", nelma_air_epsilon
);
287 nelma_write_material(out
, "air", "dielectric", nelma_air_epsilon
);
288 nelma_write_material(out
, "composite", "dielectric",
289 nelma_air_epsilon
* nelma_substratee
);
293 nelma_write_nets(FILE * out
)
296 LibraryMenuTypePtr net
;
297 LibraryEntryTypePtr pin
;
303 netlist
= PCB
->NetlistLib
;
305 fprintf(out
, "\n/* **** Nets **** */\n\n");
307 for (n
= 0; n
< netlist
.MenuN
; n
++) {
308 net
= &netlist
.Menu
[n
];
310 /* Weird, but correct */
311 fprintf(out
, "net %s {\n", &net
->Name
[2]);
313 fprintf(out
, "\tobjects = {\n");
315 for (m
= 0; m
< net
->EntryN
; m
++) {
316 pin
= &net
->Entry
[m
];
318 /* pin_name_to_xy(pin, &x, &y); */
320 for (i
= 0; i
< MAX_LAYER
; i
++)
321 if (nelma_export_group
[i
]) {
322 idx
= (i
>= 0 && i
< max_layer
) ?
323 PCB
->LayerGroups
.Entries
[i
][0] : i
;
324 ext
= layer_type_to_file_name(idx
);
326 if (m
!= 0 || i
!= 0)
328 fprintf(out
, "\t\t\"%s-%s\"", pin
->ListEntry
,
334 fprintf(out
, "\t}\n");
340 nelma_write_layer(FILE * out
, int z
, int h
,
341 const char *name
, int full
,
345 LibraryMenuTypePtr net
;
346 LibraryEntryTypePtr pin
;
350 fprintf(out
, "layer %s {\n", name
);
351 fprintf(out
, "\theight = %d\n", h
);
352 fprintf(out
, "\tz-order = %d\n", z
);
353 fprintf(out
, "\tmaterial = \"%s\"\n", mat
);
356 fprintf(out
, "\tobjects = {\n");
357 netlist
= PCB
->NetlistLib
;
359 for (n
= 0; n
< netlist
.MenuN
; n
++) {
360 net
= &netlist
.Menu
[n
];
362 for (m
= 0; m
< net
->EntryN
; m
++) {
363 pin
= &net
->Entry
[m
];
365 if (m
!= 0 || n
!= 0)
367 fprintf(out
, "\t\t\"%s-%s\"", pin
->ListEntry
,
372 fprintf(out
, "\n\t}\n");
378 nelma_write_layers(FILE * out
)
388 subh
= nelma_substrateh
/ nelma_copperh
;
390 fprintf(out
, "\n/* **** Layers **** */\n\n");
392 /* Air layers on top and bottom of the stack */
393 /* Their height is double substrate height. */
394 nelma_write_layer(out
, 1, 2 * subh
, "air-top", 0, "air");
395 nelma_write_layer(out
, 1000, 2 * subh
, "air-bottom", 0, "air");
398 for (i
= 0; i
< MAX_LAYER
; i
++)
399 if (nelma_export_group
[i
]) {
400 idx
= (i
>= 0 && i
< max_layer
) ?
401 PCB
->LayerGroups
.Entries
[i
][0] : i
;
402 ext
= layer_type_to_file_name(idx
);
405 sprintf(buf
, "substrate-%d", z
);
406 nelma_write_layer(out
,
415 * FIXME: for layers that are not on top or bottom,
416 * the material should be "composite"
418 nelma_write_layer(out
, z
, 1, ext
, 1, "air");
425 nelma_write_object(FILE * out
, LibraryEntryTypePtr pin
)
433 pin_name_to_xy(pin
, &x
, &y
);
438 for (i
= 0; i
< MAX_LAYER
; i
++)
439 if (nelma_export_group
[i
]) {
440 idx
= (i
>= 0 && i
< max_layer
) ?
441 PCB
->LayerGroups
.Entries
[i
][0] : i
;
442 ext
= layer_type_to_file_name(idx
);
444 fprintf(out
, "object %s-%s {\n", pin
->ListEntry
, ext
);
445 fprintf(out
, "\tposition = { 0, 0 }\n");
446 fprintf(out
, "\tmaterial = \"copper\"\n");
447 fprintf(out
, "\ttype = \"image\"\n");
448 fprintf(out
, "\trole = \"net\"\n");
450 f
= nelma_get_png_name(nelma_basename
, ext
);
452 fprintf(out
, "\tfile = \"%s\"\n", f
);
456 fprintf(out
, "\tfile-pos = { %d, %d }\n", x
, y
);
462 nelma_write_objects(FILE * out
)
465 LibraryMenuTypePtr net
;
466 LibraryEntryTypePtr pin
;
470 netlist
= PCB
->NetlistLib
;
472 fprintf(out
, "\n/* **** Objects **** */\n\n");
474 for (n
= 0; n
< netlist
.MenuN
; n
++) {
475 net
= &netlist
.Menu
[n
];
477 for (m
= 0; m
< net
->EntryN
; m
++) {
478 pin
= &net
->Entry
[m
];
480 nelma_write_object(out
, pin
);
485 /* *** Main export callback ************************************************ */
487 extern void hid_parse_command_line(int *argc
, char ***argv
);
490 nelma_parse_arguments(int *argc
, char ***argv
)
492 hid_register_attributes(nelma_attribute_list
,
493 sizeof(nelma_attribute_list
) /
494 sizeof(nelma_attribute_list
[0]));
495 hid_parse_command_line(argc
, argv
);
498 static HID_Attribute
*
499 nelma_get_export_options(int *n
)
501 static char *last_made_filename
= 0;
504 derive_default_filename(PCB
->Filename
,
505 &nelma_attribute_list
[HA_basename
],
507 &last_made_filename
);
512 return nelma_attribute_list
;
515 /* Populates nelma_export_group array */
517 nelma_choose_groups()
522 /* Set entire array to 0 (don't export any layer groups by default */
523 memset(nelma_export_group
, 0, sizeof(nelma_export_group
));
525 for (n
= 0; n
< max_layer
; n
++) {
526 layer
= &PCB
->Data
->Layer
[n
];
528 if (layer
->LineN
|| layer
->TextN
|| layer
->ArcN
||
530 /* layer isn't empty */
533 * is this check necessary? It seems that special
534 * layers have negative indexes?
537 if (SL_TYPE(n
) == 0) {
538 /* layer is a copper layer */
539 m
= GetLayerGroupNumberByNumber(n
);
541 /* the export layer */
542 nelma_export_group
[m
] = 1;
552 * Allocate white and black -- the first color allocated becomes the
556 white
= (struct color_struct
*) malloc(sizeof(*white
));
557 white
->r
= white
->g
= white
->b
= 255;
558 white
->c
= gdImageColorAllocate(nelma_im
, white
->r
, white
->g
, white
->b
);
560 black
= (struct color_struct
*) malloc(sizeof(*black
));
561 black
->r
= black
->g
= black
->b
= 0;
562 black
->c
= gdImageColorAllocate(nelma_im
, black
->r
, black
->g
, black
->b
);
566 nelma_start_png(const char *basename
, const char *suffix
)
571 buf
= nelma_get_png_name(basename
, suffix
);
573 h
= pcb_to_nelma(PCB
->MaxHeight
);
574 w
= pcb_to_nelma(PCB
->MaxWidth
);
576 /* nelma_im = gdImageCreate (w, h); */
578 /* Nelma only works with true color images */
579 nelma_im
= gdImageCreate(w
, h
);
580 nelma_f
= fopen(buf
, "wb");
582 nelma_alloc_colors();
590 #ifdef HAVE_GDIMAGEPNG
591 gdImagePng(nelma_im
, nelma_f
);
593 Message("NELMA: PNG not supported by gd. Can't write layer mask.\n");
595 gdImageDestroy(nelma_im
);
606 nelma_start_png_export()
612 region
.X2
= PCB
->MaxWidth
;
613 region
.Y2
= PCB
->MaxHeight
;
616 lastbrush
= (void *) -1;
622 hid_expose_callback(&nelma_hid
, ®ion
, 0);
626 nelma_do_export(HID_Attr_Val
* options
)
628 int save_ons
[MAX_LAYER
+ 2];
637 nelma_get_export_options(0);
638 for (i
= 0; i
< NUM_OPTIONS
; i
++) {
639 nelma_values
[i
] = nelma_attribute_list
[i
].default_val
;
641 options
= nelma_values
;
643 nelma_basename
= options
[HA_basename
].str_value
;
644 if (!nelma_basename
) {
645 nelma_basename
= "pcb-out";
647 nelma_dpi
= options
[HA_dpi
].int_value
;
649 fprintf(stderr
, "ERROR: dpi may not be < 0\n");
652 nelma_copperh
= options
[HA_copperh
].int_value
;
653 nelma_substrateh
= options
[HA_substrateh
].int_value
;
654 nelma_substratee
= options
[HA_substratee
].real_value
;
656 nelma_choose_groups();
658 for (i
= 0; i
< MAX_LAYER
; i
++) {
659 if (nelma_export_group
[i
]) {
664 idx
= (i
>= 0 && i
< max_layer
) ?
665 PCB
->LayerGroups
.Entries
[i
][0] : i
;
667 nelma_start_png(nelma_basename
,
668 layer_type_to_file_name(idx
));
670 hid_save_and_show_layer_ons(save_ons
);
671 nelma_start_png_export();
672 hid_restore_layer_ons(save_ons
);
678 len
= strlen(nelma_basename
) + 4;
679 buf
= malloc(sizeof(*buf
) * len
);
681 sprintf(buf
, "%s.em", nelma_basename
);
682 nelma_config
= fopen(buf
, "w");
686 fprintf(nelma_config
, "/* Made with PCB Nelma export HID */");
688 fprintf(nelma_config
, "/* %s */", ctime(&t
));
690 nelma_write_nets(nelma_config
);
691 nelma_write_objects(nelma_config
);
692 nelma_write_layers(nelma_config
);
693 nelma_write_materials(nelma_config
);
694 nelma_write_space(nelma_config
);
696 fclose(nelma_config
);
699 /* *** PNG export (slightly modified code from PNG export HID) ************* */
702 nelma_set_layer(const char *name
, int group
, int empty
)
704 int idx
= (group
>= 0 && group
< max_layer
) ?
705 PCB
->LayerGroups
.Entries
[group
][0] : group
;
708 name
= PCB
->Data
->Layer
[idx
].Name
;
710 if (strcmp(name
, "invisible") == 0) {
713 is_drill
= (SL_TYPE(idx
) == SL_PDRILL
|| SL_TYPE(idx
) == SL_UDRILL
);
714 is_mask
= (SL_TYPE(idx
) == SL_MASK
);
717 /* Don't print masks */
722 * Print 'holes', so that we can fill gaps in the copper
727 if (group
== nelma_cur_group
) {
736 hidGC rv
= (hidGC
) malloc(sizeof(struct hid_gc_struct
));
737 rv
->me_pointer
= &nelma_hid
;
740 rv
->color
= (struct color_struct
*) malloc(sizeof(*rv
->color
));
741 rv
->color
->r
= rv
->color
->g
= rv
->color
->b
= 0;
747 nelma_destroy_gc(hidGC gc
)
753 nelma_use_mask(int use_it
)
759 nelma_set_color(hidGC gc
, const char *name
)
761 if (nelma_im
== NULL
) {
767 if (!strcmp(name
, "drill")) {
772 if (!strcmp(name
, "erase")) {
773 /* FIXME -- should be background, not white */
784 nelma_set_line_cap(hidGC gc
, EndCapStyle style
)
790 nelma_set_line_width(hidGC gc
, int width
)
796 nelma_set_draw_xor(hidGC gc
, int xor)
802 nelma_set_draw_faded(hidGC gc
, int faded
)
808 nelma_set_line_cap_angle(hidGC gc
, int x1
, int y1
, int x2
, int y2
)
818 if (gc
->me_pointer
!= &nelma_hid
) {
819 fprintf(stderr
, "Fatal: GC from another HID passed to nelma HID\n");
822 if (linewidth
!= gc
->width
) {
823 /* Make sure the scaling doesn't erase lines completely */
825 if (SCALE (gc->width) == 0 && gc->width > 0)
826 gdImageSetThickness (im, 1);
829 gdImageSetThickness(nelma_im
, pcb_to_nelma(gc
->width
));
830 linewidth
= gc
->width
;
833 if (lastbrush
!= gc
->brush
|| need_brush
) {
834 static void *bcache
= 0;
844 r
= pcb_to_nelma(gc
->width
/ 2);
848 r
= pcb_to_nelma(gc
->width
);
852 sprintf(name
, "#%.2x%.2x%.2x_%c_%d", gc
->color
->r
, gc
->color
->g
,
853 gc
->color
->b
, type
, r
);
855 if (hid_cache_color(0, name
, &bval
, &bcache
)) {
856 gc
->brush
= bval
.ptr
;
860 gc
->brush
= gdImageCreate(2 * r
+ 1, 2 * r
+ 1);
862 gc
->brush
= gdImageCreate(r
+ 1, r
+ 1);
863 bg
= gdImageColorAllocate(gc
->brush
, 255, 255, 255);
865 gdImageColorAllocate(gc
->brush
, gc
->color
->r
, gc
->color
->g
,
867 gdImageColorTransparent(gc
->brush
, bg
);
870 * if we shrunk to a radius/box width of zero, then just use
871 * a single pixel to draw with.
874 gdImageFilledRectangle(gc
->brush
, 0, 0, 0, 0, fg
);
877 gdImageFilledEllipse(gc
->brush
, r
, r
, 2 * r
, 2 * r
, fg
);
879 gdImageFilledRectangle(gc
->brush
, 0, 0, r
, r
, fg
);
881 bval
.ptr
= gc
->brush
;
882 hid_cache_color(1, name
, &bval
, &bcache
);
885 gdImageSetBrush(nelma_im
, gc
->brush
);
886 lastbrush
= gc
->brush
;
889 #define CBLEND(gc) (((gc->r)<<24)|((gc->g)<<16)|((gc->b)<<8)|(gc->faded))
890 if (lastcolor
!= CBLEND(gc
)) {
891 if (is_drill
|| is_mask
) {
893 fprintf(f
, "%d gray\n", gc
->erase
? 0 : 1);
902 r
= 0.8 * 255 + 0.2 * r
;
903 g
= 0.8 * 255 + 0.2 * g
;
904 b
= 0.8 * 255 + 0.2 * b
;
907 if (gc
->r
== gc
->g
&& gc
->g
== gc
->b
)
908 fprintf(f
, "%g gray\n", r
/ 255.0);
910 fprintf(f
, "%g %g %g rgb\n", r
/ 255.0, g
/ 255.0, b
/ 255.0);
912 lastcolor
= CBLEND(gc
);
918 nelma_draw_rect(hidGC gc
, int x1
, int y1
, int x2
, int y2
)
921 gdImageRectangle(nelma_im
,
922 pcb_to_nelma(x1
), pcb_to_nelma(y1
),
923 pcb_to_nelma(x2
), pcb_to_nelma(y2
), gc
->color
->c
);
927 nelma_fill_rect(hidGC gc
, int x1
, int y1
, int x2
, int y2
)
930 gdImageSetThickness(nelma_im
, 0);
932 gdImageFilledRectangle(nelma_im
, pcb_to_nelma(x1
), pcb_to_nelma(y1
),
933 pcb_to_nelma(x2
), pcb_to_nelma(y2
), gc
->color
->c
);
937 nelma_draw_line(hidGC gc
, int x1
, int y1
, int x2
, int y2
)
939 if (x1
== x2
&& y1
== y2
) {
940 int w
= gc
->width
/ 2;
941 nelma_fill_rect(gc
, x1
- w
, y1
- w
, x1
+ w
, y1
+ w
);
946 gdImageSetThickness(nelma_im
, 0);
948 gdImageLine(nelma_im
, pcb_to_nelma(x1
), pcb_to_nelma(y1
),
949 pcb_to_nelma(x2
), pcb_to_nelma(y2
), gdBrushed
);
953 nelma_draw_arc(hidGC gc
, int cx
, int cy
, int width
, int height
,
954 int start_angle
, int delta_angle
)
959 * in gdImageArc, 0 degrees is to the right and +90 degrees is down
960 * in pcb, 0 degrees is to the left and +90 degrees is down
962 start_angle
= 180 - start_angle
;
963 delta_angle
= -delta_angle
;
964 if (delta_angle
> 0) {
966 ea
= start_angle
+ delta_angle
;
968 sa
= start_angle
+ delta_angle
;
973 * make sure we start between 0 and 360 otherwise gd does strange
986 printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
987 cx
, cy
, width
, height
, start_angle
, delta_angle
, sa
, ea
);
988 printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n",
989 im
, SCALE_X(cx
), SCALE_Y(cy
),
990 SCALE(width
), SCALE(height
), sa
, ea
, gc
->color
->c
);
993 gdImageSetThickness(nelma_im
, 0);
995 gdImageArc(nelma_im
, pcb_to_nelma(cx
), pcb_to_nelma(cy
),
996 pcb_to_nelma(2 * width
), pcb_to_nelma(2 * height
), sa
, ea
, gdBrushed
);
1000 nelma_fill_circle(hidGC gc
, int cx
, int cy
, int radius
)
1004 gdImageSetThickness(nelma_im
, 0);
1006 gdImageFilledEllipse(nelma_im
, pcb_to_nelma(cx
), pcb_to_nelma(cy
),
1007 pcb_to_nelma(2 * radius
), pcb_to_nelma(2 * radius
), gc
->color
->c
);
1012 nelma_fill_polygon(hidGC gc
, int n_coords
, int *x
, int *y
)
1017 points
= (gdPoint
*) malloc(n_coords
* sizeof(gdPoint
));
1018 if (points
== NULL
) {
1019 fprintf(stderr
, "ERROR: nelma_fill_polygon(): malloc failed\n");
1023 for (i
= 0; i
< n_coords
; i
++) {
1024 points
[i
].x
= pcb_to_nelma(x
[i
]);
1025 points
[i
].y
= pcb_to_nelma(y
[i
]);
1027 gdImageSetThickness(nelma_im
, 0);
1029 gdImageFilledPolygon(nelma_im
, points
, n_coords
, gc
->color
->c
);
1034 nelma_calibrate(double xval
, double yval
)
1040 nelma_set_crosshair(int x
, int y
, int a
)
1044 /* *** Miscellaneous ******************************************************* */
1049 "Numerical analysis package export.",
1053 1, /* poly before */
1056 nelma_get_export_options
,
1058 nelma_parse_arguments
,
1059 0 /* nelma_invalidate_lr */ ,
1060 0 /* nelma_invalidate_all */ ,
1067 nelma_set_line_width
,
1069 nelma_set_draw_faded
,
1070 nelma_set_line_cap_angle
,
1076 common_fill_pcb_polygon
,
1077 0 /* nelma_thindraw_pcb_polygon */ ,
1080 0 /* nelma_shift_is_pressed */ ,
1081 0 /* nelma_control_is_pressed */ ,
1082 0 /* nelma_mod1_is_pressed */ ,
1083 0 /* nelma_get_coords */ ,
1084 nelma_set_crosshair
,
1085 0 /* nelma_add_timer */ ,
1086 0 /* nelma_stop_timer */ ,
1087 0 /* nelma_watch_file */ ,
1088 0 /* nelma_unwatch_file */ ,
1089 0 /* nelma_add_block_hook */ ,
1090 0 /* nelma_stop_block_hook */ ,
1092 0 /* nelma_logv */ ,
1093 0 /* nelma_confirm_dialog */ ,
1094 0 /* nelma_close_confirm_dialog */ ,
1095 0 /* nelma_report_dialog */ ,
1096 0 /* nelma_prompt_for */ ,
1097 0 /* nelma_fileselect */ ,
1098 0 /* nelma_attribute_dialog */ ,
1099 0 /* nelma_show_item */ ,
1100 0 /* nelma_beep */ ,
1101 0 /* nelma_progress */ ,
1102 0 /* nelma_drc_gui */ ,
1103 0 /* nelma_edit_attributes */
1106 #include "dolists.h"
1111 apply_default_hid(&nelma_hid
, 0);
1112 hid_register_hid(&nelma_hid
);
1114 #include "nelma_lists.h"