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.
67 #include "error.h" /* Message() */
74 #include "../hidint.h"
75 #include "hid/common/hidnogui.h"
76 #include "hid/common/draw_helpers.h"
80 #include "hid/common/hidinit.h"
82 #ifdef HAVE_LIBDMALLOC
86 #define CRASH fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", __FUNCTION__); abort()
88 /* Needed for PNG export */
91 /* the descriptor used by the gd library */
94 /* so I can figure out what rgb value c refers to */
98 typedef struct nelma_gc_struct
{
99 struct hid_gc_struct hid_gc
; /* Parent */
103 unsigned char r
, g
, b
;
105 struct color_struct
*color
;
109 static HID nelma_hid
;
110 static HID_DRAW nelma_graphics
;
111 static HID_DRAW_CLASS nelma_graphics_class
;
113 static struct color_struct
*black
= NULL
, *white
= NULL
;
114 static Coord linewidth
= -1;
115 static gdImagePtr lastbrush
= (gdImagePtr
)((void *) -1);
117 /* gd image and file for PNG export */
118 static gdImagePtr nelma_im
= NULL
;
119 static FILE *nelma_f
= NULL
;
125 * Which groups of layers to export into PNG layer masks. 1 means export, 0
126 * means do not export.
128 static int nelma_export_group
[MAX_GROUP
];
130 /* Group that is currently exported. */
131 static int nelma_cur_group
;
133 /* Filename prefix that will be used when saving files. */
134 static const char *nelma_basename
= NULL
;
136 /* Horizontal DPI (grid points per inch) */
137 static int nelma_dpi
= -1;
139 /* Height of the copper layers in micrometers. */
142 * The height of the copper layer is currently taken as the vertical grid
143 * step, since this is the smallest vertical feature in the layout.
145 static int nelma_copperh
= -1;
146 /* Height of the substrate layers in micrometers. */
147 static int nelma_substrateh
= -1;
148 /* Relative permittivity of the substrate. */
149 static double nelma_substratee
= -1;
151 /* Permittivity of empty space (As/Vm) */
152 static const double nelma_air_epsilon
= 8.85e-12;
154 HID_Attribute nelma_attribute_list
[] = {
155 /* other HIDs expect this to be first. */
157 /* %start-doc options "nelma Options"
159 @item -- basename <string>
164 {"basename", "File name prefix",
165 HID_String
, 0, 0, {0, 0, 0}, 0, 0},
166 #define HA_basename 0
168 /* %start-doc options "nelma Options"
171 Horizontal scale factor (grid points/inch).
175 {"dpi", "Horizontal scale factor (grid points/inch)",
176 HID_Integer
, 0, 1000, {100, 0, 0}, 0, 0},
179 /* %start-doc options "nelma Options"
181 @item --copper-height <num>
182 Copper layer height (um).
186 {"copper-height", "Copper layer height (um)",
187 HID_Integer
, 0, 200, {100, 0, 0}, 0, 0},
190 /* %start-doc options "nelma Options"
192 @item --substrate-height <num>
193 Substrate layer height (um).
197 {"substrate-height", "Substrate layer height (um)",
198 HID_Integer
, 0, 10000, {2000, 0, 0}, 0, 0},
199 #define HA_substrateh 3
201 /* %start-doc options "nelma Options"
203 @item --substrate-epsilon <num>
204 Substrate relative epsilon.
208 {"substrate-epsilon", "Substrate relative epsilon",
209 HID_Real
, 0, 100, {0, 0, 4.0}, 0, 0},
210 #define HA_substratee 4
213 #define NUM_OPTIONS (sizeof(nelma_attribute_list)/sizeof(nelma_attribute_list[0]))
215 REGISTER_ATTRIBUTES(nelma_attribute_list
)
216 static HID_Attr_Val nelma_values
[NUM_OPTIONS
];
218 /* *** Utility funcions **************************************************** */
220 /* convert from default PCB units to nelma units */
221 static int pcb_to_nelma (Coord pcb
)
223 return COORD_TO_INCH(pcb
) * nelma_dpi
;
227 nelma_get_png_name(const char *basename
, const char *suffix
)
232 len
= strlen(basename
) + strlen(suffix
) + 6;
233 buf
= (char *)malloc(sizeof(*buf
) * len
);
235 sprintf(buf
, "%s.%s.png", basename
, suffix
);
240 /* Retrieves coordinates (in default PCB units) of a pin or pad. */
241 /* Copied from netlist.c */
243 pin_name_to_xy (LibraryEntryType
* pin
, Coord
*x
, Coord
*y
)
246 if (!SeekPad(pin
, &conn
, false))
250 *x
= ((PinType
*) (conn
.ptr2
))->X
;
251 *y
= ((PinType
*) (conn
.ptr2
))->Y
;
254 *x
= ((PadType
*) (conn
.ptr2
))->Point1
.X
;
255 *y
= ((PadType
*) (conn
.ptr2
))->Point1
.Y
;
261 /* *** Exporting netlist data and geometry to the nelma config file ******** */
264 nelma_write_space(FILE * out
)
272 xh
= 2.54e-2 / ((double) nelma_dpi
);
273 zh
= nelma_copperh
* 1e-6;
275 fprintf(out
, "\n/* **** Space **** */\n\n");
277 fprintf(out
, "space pcb {\n");
278 fprintf(out
, "\tstep = { %e, %e, %e }\n", xh
, xh
, zh
);
279 fprintf(out
, "\tlayers = {\n");
281 fprintf(out
, "\t\t\"air-top\",\n");
282 fprintf(out
, "\t\t\"air-bottom\"");
285 for (i
= 0; i
< MAX_GROUP
; i
++)
286 if (nelma_export_group
[i
]) {
287 idx
= (i
>= 0 && i
< max_group
) ?
288 PCB
->LayerGroups
.Entries
[i
][0] : i
;
289 ext
= layer_type_to_file_name(idx
, FNS_fixed
);
293 fprintf(out
, "\t\t\"substrate-%d\"", z
);
297 fprintf(out
, "\t\t\"%s\"", ext
);
300 fprintf(out
, "\n\t}\n");
306 nelma_write_material(FILE * out
, char *name
, char *type
, double e
)
308 fprintf(out
, "material %s {\n", name
);
309 fprintf(out
, "\ttype = \"%s\"\n", type
);
310 fprintf(out
, "\tpermittivity = %e\n", e
);
311 fprintf(out
, "\tconductivity = 0.0\n");
312 fprintf(out
, "\tpermeability = 0.0\n");
317 nelma_write_materials(FILE * out
)
319 fprintf(out
, "\n/* **** Materials **** */\n\n");
321 nelma_write_material(out
, "copper", "metal", nelma_air_epsilon
);
322 nelma_write_material(out
, "air", "dielectric", nelma_air_epsilon
);
323 nelma_write_material(out
, "composite", "dielectric",
324 nelma_air_epsilon
* nelma_substratee
);
328 nelma_write_nets(FILE * out
)
331 LibraryMenuType
*net
;
332 LibraryEntryType
*pin
;
338 netlist
= PCB
->NetlistLib
;
340 fprintf(out
, "\n/* **** Nets **** */\n\n");
342 for (n
= 0; n
< netlist
.MenuN
; n
++) {
343 net
= &netlist
.Menu
[n
];
345 /* Weird, but correct */
346 fprintf(out
, "net %s {\n", &net
->Name
[2]);
348 fprintf(out
, "\tobjects = {\n");
350 for (m
= 0; m
< net
->EntryN
; m
++) {
351 pin
= &net
->Entry
[m
];
353 /* pin_name_to_xy(pin, &x, &y); */
355 for (i
= 0; i
< MAX_GROUP
; i
++)
356 if (nelma_export_group
[i
]) {
357 idx
= (i
>= 0 && i
< max_group
) ?
358 PCB
->LayerGroups
.Entries
[i
][0] : i
;
359 ext
= layer_type_to_file_name(idx
, FNS_fixed
);
361 if (m
!= 0 || i
!= 0)
363 fprintf(out
, "\t\t\"%s-%s\"", pin
->ListEntry
,
369 fprintf(out
, "\t}\n");
375 nelma_write_layer(FILE * out
, int z
, int h
,
376 const char *name
, int full
,
380 LibraryMenuType
*net
;
381 LibraryEntryType
*pin
;
385 fprintf(out
, "layer %s {\n", name
);
386 fprintf(out
, "\theight = %d\n", h
);
387 fprintf(out
, "\tz-order = %d\n", z
);
388 fprintf(out
, "\tmaterial = \"%s\"\n", mat
);
391 fprintf(out
, "\tobjects = {\n");
392 netlist
= PCB
->NetlistLib
;
394 for (n
= 0; n
< netlist
.MenuN
; n
++) {
395 net
= &netlist
.Menu
[n
];
397 for (m
= 0; m
< net
->EntryN
; m
++) {
398 pin
= &net
->Entry
[m
];
400 if (m
!= 0 || n
!= 0)
402 fprintf(out
, "\t\t\"%s-%s\"", pin
->ListEntry
,
407 fprintf(out
, "\n\t}\n");
413 nelma_write_layers(FILE * out
)
423 subh
= nelma_substrateh
/ nelma_copperh
;
425 fprintf(out
, "\n/* **** Layers **** */\n\n");
427 /* Air layers on top and bottom of the stack */
428 /* Their height is double substrate height. */
429 nelma_write_layer(out
, 1, 2 * subh
, "air-top", 0, "air");
430 nelma_write_layer(out
, 1000, 2 * subh
, "air-bottom", 0, "air");
433 for (i
= 0; i
< MAX_GROUP
; i
++)
434 if (nelma_export_group
[i
]) {
435 idx
= (i
>= 0 && i
< max_group
) ?
436 PCB
->LayerGroups
.Entries
[i
][0] : i
;
437 ext
= layer_type_to_file_name(idx
, FNS_fixed
);
440 sprintf(buf
, "substrate-%d", z
);
441 nelma_write_layer(out
,
450 * FIXME: for layers that are not on top or bottom,
451 * the material should be "composite"
453 nelma_write_layer(out
, z
, 1, ext
, 1, "air");
460 nelma_write_object(FILE * out
, LibraryEntryType
*pin
)
463 Coord px
= 0, py
= 0;
469 pin_name_to_xy (pin
, &px
, &py
);
471 x
= pcb_to_nelma (px
);
472 y
= pcb_to_nelma (py
);
474 for (i
= 0; i
< MAX_GROUP
; i
++)
475 if (nelma_export_group
[i
]) {
476 idx
= (i
>= 0 && i
< max_group
) ?
477 PCB
->LayerGroups
.Entries
[i
][0] : i
;
478 ext
= layer_type_to_file_name(idx
, FNS_fixed
);
480 fprintf(out
, "object %s-%s {\n", pin
->ListEntry
, ext
);
481 fprintf(out
, "\tposition = { 0, 0 }\n");
482 fprintf(out
, "\tmaterial = \"copper\"\n");
483 fprintf(out
, "\ttype = \"image\"\n");
484 fprintf(out
, "\trole = \"net\"\n");
486 f
= nelma_get_png_name(nelma_basename
, ext
);
488 fprintf(out
, "\tfile = \"%s\"\n", f
);
492 fprintf(out
, "\tfile-pos = { %d, %d }\n", x
, y
);
498 nelma_write_objects(FILE * out
)
501 LibraryMenuType
*net
;
502 LibraryEntryType
*pin
;
506 netlist
= PCB
->NetlistLib
;
508 fprintf(out
, "\n/* **** Objects **** */\n\n");
510 for (n
= 0; n
< netlist
.MenuN
; n
++) {
511 net
= &netlist
.Menu
[n
];
513 for (m
= 0; m
< net
->EntryN
; m
++) {
514 pin
= &net
->Entry
[m
];
516 nelma_write_object(out
, pin
);
521 /* *** Main export callback ************************************************ */
524 nelma_parse_arguments(int *argc
, char ***argv
)
526 hid_register_attributes(nelma_attribute_list
,
527 sizeof(nelma_attribute_list
) /
528 sizeof(nelma_attribute_list
[0]));
529 hid_parse_command_line(argc
, argv
);
532 static HID_Attribute
*
533 nelma_get_export_options(int *n
)
535 static char *last_made_filename
= 0;
538 derive_default_filename(PCB
->Filename
,
539 &nelma_attribute_list
[HA_basename
],
541 &last_made_filename
);
546 return nelma_attribute_list
;
549 /* Populates nelma_export_group array */
551 nelma_choose_groups()
556 /* Set entire array to 0 (don't export any layer groups by default */
557 memset(nelma_export_group
, 0, sizeof(nelma_export_group
));
559 for (n
= 0; n
< max_copper_layer
; n
++) {
560 layer
= &PCB
->Data
->Layer
[n
];
562 if (layer
->LineN
|| layer
->TextN
|| layer
->ArcN
||
564 /* layer isn't empty */
567 * is this check necessary? It seems that special
568 * layers have negative indexes?
571 if (SL_TYPE(n
) == 0) {
572 /* layer is a copper layer */
573 m
= GetLayerGroupNumberByNumber(n
);
575 /* the export layer */
576 nelma_export_group
[m
] = 1;
586 * Allocate white and black -- the first color allocated becomes the
590 white
= (struct color_struct
*) malloc(sizeof(*white
));
591 white
->r
= white
->g
= white
->b
= 255;
592 white
->c
= gdImageColorAllocate(nelma_im
, white
->r
, white
->g
, white
->b
);
594 black
= (struct color_struct
*) malloc(sizeof(*black
));
595 black
->r
= black
->g
= black
->b
= 0;
596 black
->c
= gdImageColorAllocate(nelma_im
, black
->r
, black
->g
, black
->b
);
600 nelma_start_png(const char *basename
, const char *suffix
)
605 buf
= nelma_get_png_name(basename
, suffix
);
607 h
= pcb_to_nelma(PCB
->MaxHeight
);
608 w
= pcb_to_nelma(PCB
->MaxWidth
);
610 /* nelma_im = gdImageCreate (w, h); */
612 /* Nelma only works with true color images */
613 nelma_im
= gdImageCreate(w
, h
);
614 nelma_f
= fopen(buf
, "wb");
616 nelma_alloc_colors();
624 #ifdef HAVE_GDIMAGEPNG
625 gdImagePng(nelma_im
, nelma_f
);
627 Message("NELMA: PNG not supported by gd. Can't write layer mask.\n");
629 gdImageDestroy(nelma_im
);
640 nelma_start_png_export()
646 region
.X2
= PCB
->MaxWidth
;
647 region
.Y2
= PCB
->MaxHeight
;
650 lastbrush
= (gdImagePtr
)((void *) -1);
652 hid_expose_callback(&nelma_graphics
, ®ion
, 0);
656 nelma_do_export(HID_Attr_Val
* options
)
658 int save_ons
[MAX_LAYER
+ EXTRA_LAYERS
];
667 nelma_get_export_options(0);
668 for (i
= 0; i
< NUM_OPTIONS
; i
++) {
669 nelma_values
[i
] = nelma_attribute_list
[i
].default_val
;
671 options
= nelma_values
;
673 nelma_basename
= options
[HA_basename
].str_value
;
674 if (!nelma_basename
) {
675 nelma_basename
= "pcb-out";
677 nelma_dpi
= options
[HA_dpi
].int_value
;
679 fprintf(stderr
, "ERROR: dpi may not be < 0\n");
682 nelma_copperh
= options
[HA_copperh
].int_value
;
683 nelma_substrateh
= options
[HA_substrateh
].int_value
;
684 nelma_substratee
= options
[HA_substratee
].real_value
;
686 nelma_choose_groups();
688 for (i
= 0; i
< MAX_GROUP
; i
++) {
689 if (nelma_export_group
[i
]) {
694 idx
= (i
>= 0 && i
< max_group
) ?
695 PCB
->LayerGroups
.Entries
[i
][0] : i
;
697 nelma_start_png(nelma_basename
,
698 layer_type_to_file_name(idx
, FNS_fixed
));
700 hid_save_and_show_layer_ons(save_ons
);
701 nelma_start_png_export();
702 hid_restore_layer_ons(save_ons
);
708 len
= strlen(nelma_basename
) + 4;
709 buf
= (char *)malloc(sizeof(*buf
) * len
);
711 sprintf(buf
, "%s.em", nelma_basename
);
712 nelma_config
= fopen(buf
, "w");
716 fprintf(nelma_config
, "/* Made with PCB Nelma export HID */");
718 fprintf(nelma_config
, "/* %s */", ctime(&t
));
720 nelma_write_nets(nelma_config
);
721 nelma_write_objects(nelma_config
);
722 nelma_write_layers(nelma_config
);
723 nelma_write_materials(nelma_config
);
724 nelma_write_space(nelma_config
);
726 fclose(nelma_config
);
729 /* *** PNG export (slightly modified code from PNG export HID) ************* */
732 nelma_set_layer(const char *name
, int group
, int empty
)
734 int idx
= (group
>= 0 && group
< max_group
) ?
735 PCB
->LayerGroups
.Entries
[group
][0] : group
;
738 name
= PCB
->Data
->Layer
[idx
].Name
;
740 if (strcmp(name
, "invisible") == 0) {
743 is_drill
= (SL_TYPE(idx
) == SL_PDRILL
|| SL_TYPE(idx
) == SL_UDRILL
);
744 is_mask
= (SL_TYPE(idx
) == SL_MASK
);
747 /* Don't print masks */
752 * Print 'holes', so that we can fill gaps in the copper
757 if (group
== nelma_cur_group
) {
766 hidGC gc
= (hidGC
) calloc (1, sizeof(struct hid_gc_struct
));
767 nelmaGC nelma_gc
= (nelmaGC
)gc
;
769 gc
->hid
= &nelma_hid
;
770 gc
->hid_draw
= &nelma_graphics
;
772 nelma_gc
->cap
= Trace_Cap
;
774 nelma_gc
->color
= (struct color_struct
*) malloc(sizeof(*nelma_gc
->color
));
775 nelma_gc
->color
->r
= nelma_gc
->color
->g
= nelma_gc
->color
->b
= 0;
776 nelma_gc
->color
->c
= 0;
782 nelma_destroy_gc(hidGC gc
)
788 nelma_use_mask(enum mask_mode mode
)
794 nelma_set_color(hidGC gc
, const char *name
)
796 nelmaGC nelma_gc
= (nelmaGC
)gc
;
798 if (nelma_im
== NULL
) {
804 if (!strcmp(name
, "drill")) {
805 nelma_gc
->color
= black
;
809 if (!strcmp(name
, "erase")) {
810 /* FIXME -- should be background, not white */
811 nelma_gc
->color
= white
;
815 nelma_gc
->color
= black
;
821 nelma_set_line_cap(hidGC gc
, EndCapStyle style
)
823 nelmaGC nelma_gc
= (nelmaGC
)gc
;
825 nelma_gc
->cap
= style
;
829 nelma_set_line_width(hidGC gc
, Coord width
)
831 nelmaGC nelma_gc
= (nelmaGC
)gc
;
833 nelma_gc
->width
= width
;
837 nelma_set_draw_xor(hidGC gc
, int xor_
)
843 nelma_set_draw_faded(hidGC gc
, int faded
)
850 nelmaGC nelma_gc
= (nelmaGC
)gc
;
853 if (gc
->hid
!= &nelma_hid
) {
854 fprintf(stderr
, "Fatal: GC from another HID passed to nelma HID\n");
857 if (linewidth
!= nelma_gc
->width
) {
858 /* Make sure the scaling doesn't erase lines completely */
860 if (SCALE (nelma_gc->width) == 0 && nelma_gc->width > 0)
861 gdImageSetThickness (im, 1);
864 gdImageSetThickness(nelma_im
, pcb_to_nelma(nelma_gc
->width
));
865 linewidth
= nelma_gc
->width
;
868 if (lastbrush
!= nelma_gc
->brush
|| need_brush
) {
869 static void *bcache
= 0;
875 switch (nelma_gc
->cap
) {
879 r
= pcb_to_nelma(nelma_gc
->width
/ 2);
883 r
= pcb_to_nelma(nelma_gc
->width
);
887 sprintf(name
, "#%.2x%.2x%.2x_%c_%d", nelma_gc
->color
->r
, nelma_gc
->color
->g
,
888 nelma_gc
->color
->b
, type
, r
);
890 if (hid_cache_color(0, name
, &bval
, &bcache
)) {
891 nelma_gc
->brush
= (gdImagePtr
)bval
.ptr
;
895 nelma_gc
->brush
= gdImageCreate(2 * r
+ 1, 2 * r
+ 1);
897 nelma_gc
->brush
= gdImageCreate(r
+ 1, r
+ 1);
898 bg
= gdImageColorAllocate(nelma_gc
->brush
, 255, 255, 255);
900 gdImageColorAllocate(nelma_gc
->brush
, nelma_gc
->color
->r
, nelma_gc
->color
->g
,
902 gdImageColorTransparent(nelma_gc
->brush
, bg
);
905 * if we shrunk to a radius/box width of zero, then just use
906 * a single pixel to draw with.
909 gdImageFilledRectangle(nelma_gc
->brush
, 0, 0, 0, 0, fg
);
912 gdImageFilledEllipse(nelma_gc
->brush
, r
, r
, 2 * r
, 2 * r
, fg
);
914 gdImageFilledRectangle(nelma_gc
->brush
, 0, 0, r
, r
, fg
);
916 bval
.ptr
= nelma_gc
->brush
;
917 hid_cache_color(1, name
, &bval
, &bcache
);
920 gdImageSetBrush(nelma_im
, nelma_gc
->brush
);
921 lastbrush
= nelma_gc
->brush
;
927 nelma_draw_rect(hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
929 nelmaGC nelma_gc
= (nelmaGC
)gc
;
932 gdImageRectangle(nelma_im
,
933 pcb_to_nelma(x1
), pcb_to_nelma(y1
),
934 pcb_to_nelma(x2
), pcb_to_nelma(y2
), nelma_gc
->color
->c
);
938 nelma_fill_rect(hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
940 nelmaGC nelma_gc
= (nelmaGC
)gc
;
943 gdImageSetThickness(nelma_im
, 0);
945 gdImageFilledRectangle(nelma_im
, pcb_to_nelma(x1
), pcb_to_nelma(y1
),
946 pcb_to_nelma(x2
), pcb_to_nelma(y2
), nelma_gc
->color
->c
);
950 nelma_draw_line(hidGC gc
, Coord x1
, Coord y1
, Coord x2
, Coord y2
)
952 nelmaGC nelma_gc
= (nelmaGC
)gc
;
954 if (x1
== x2
&& y1
== y2
) {
955 Coord w
= nelma_gc
->width
/ 2;
956 nelma_fill_rect(gc
, x1
- w
, y1
- w
, x1
+ w
, y1
+ w
);
961 gdImageSetThickness(nelma_im
, 0);
963 gdImageLine(nelma_im
, pcb_to_nelma(x1
), pcb_to_nelma(y1
),
964 pcb_to_nelma(x2
), pcb_to_nelma(y2
), gdBrushed
);
968 nelma_draw_arc(hidGC gc
, Coord cx
, Coord cy
, Coord width
, Coord height
,
969 Angle start_angle
, Angle delta_angle
)
974 * in gdImageArc, 0 degrees is to the right and +90 degrees is down
975 * in pcb, 0 degrees is to the left and +90 degrees is down
977 start_angle
= 180 - start_angle
;
978 delta_angle
= -delta_angle
;
979 if (delta_angle
> 0) {
981 ea
= start_angle
+ delta_angle
;
983 sa
= start_angle
+ delta_angle
;
988 * make sure we start between 0 and 360 otherwise gd does strange
991 sa
= NormalizeAngle (sa
);
992 ea
= NormalizeAngle (ea
);
995 printf("draw_arc %d,%d %dx%d %d..%d %d..%d\n",
996 cx
, cy
, width
, height
, start_angle
, delta_angle
, sa
, ea
);
997 printf("gdImageArc (%p, %d, %d, %d, %d, %d, %d, %d)\n",
998 im
, SCALE_X(cx
), SCALE_Y(cy
),
999 SCALE(width
), SCALE(height
), sa
, ea
, nelma_gc
->color
->c
);
1002 gdImageSetThickness(nelma_im
, 0);
1004 gdImageArc(nelma_im
, pcb_to_nelma(cx
), pcb_to_nelma(cy
),
1005 pcb_to_nelma(2 * width
), pcb_to_nelma(2 * height
), sa
, ea
, gdBrushed
);
1009 nelma_fill_circle(hidGC gc
, Coord cx
, Coord cy
, Coord radius
)
1011 nelmaGC nelma_gc
= (nelmaGC
)gc
;
1015 gdImageSetThickness(nelma_im
, 0);
1017 gdImageFilledEllipse(nelma_im
, pcb_to_nelma(cx
), pcb_to_nelma(cy
),
1018 pcb_to_nelma(2 * radius
), pcb_to_nelma(2 * radius
), nelma_gc
->color
->c
);
1023 nelma_fill_polygon(hidGC gc
, int n_coords
, Coord
*x
, Coord
*y
)
1025 nelmaGC nelma_gc
= (nelmaGC
)gc
;
1029 points
= (gdPoint
*) malloc(n_coords
* sizeof(gdPoint
));
1030 if (points
== NULL
) {
1031 fprintf(stderr
, "ERROR: nelma_fill_polygon(): malloc failed\n");
1035 for (i
= 0; i
< n_coords
; i
++) {
1036 points
[i
].x
= pcb_to_nelma(x
[i
]);
1037 points
[i
].y
= pcb_to_nelma(y
[i
]);
1039 gdImageSetThickness(nelma_im
, 0);
1041 gdImageFilledPolygon(nelma_im
, points
, n_coords
, nelma_gc
->color
->c
);
1046 nelma_calibrate(double xval
, double yval
)
1052 nelma_set_crosshair(int x
, int y
, int a
)
1056 /* *** Miscellaneous ******************************************************* */
1058 #include "dolists.h"
1063 memset (&nelma_hid
, 0, sizeof (HID
));
1064 memset (&nelma_graphics
, 0, sizeof (HID_DRAW
));
1065 memset (&nelma_graphics_class
, 0, sizeof (HID_DRAW_CLASS
));
1067 common_nogui_init (&nelma_hid
);
1069 nelma_hid
.struct_size
= sizeof (HID
);
1070 nelma_hid
.name
= "nelma";
1071 nelma_hid
.description
= "Numerical analysis package export";
1072 nelma_hid
.exporter
= 1;
1074 nelma_hid
.get_export_options
= nelma_get_export_options
;
1075 nelma_hid
.do_export
= nelma_do_export
;
1076 nelma_hid
.parse_arguments
= nelma_parse_arguments
;
1077 nelma_hid
.calibrate
= nelma_calibrate
;
1078 nelma_hid
.set_crosshair
= nelma_set_crosshair
;
1080 common_nogui_graphics_class_init (&nelma_graphics_class
);
1081 common_draw_helpers_class_init (&nelma_graphics_class
);
1083 nelma_graphics_class
.set_layer
= nelma_set_layer
;
1084 nelma_graphics_class
.make_gc
= nelma_make_gc
;
1085 nelma_graphics_class
.destroy_gc
= nelma_destroy_gc
;
1086 nelma_graphics_class
.use_mask
= nelma_use_mask
;
1087 nelma_graphics_class
.set_color
= nelma_set_color
;
1088 nelma_graphics_class
.set_line_cap
= nelma_set_line_cap
;
1089 nelma_graphics_class
.set_line_width
= nelma_set_line_width
;
1090 nelma_graphics_class
.set_draw_xor
= nelma_set_draw_xor
;
1091 nelma_graphics_class
.set_draw_faded
= nelma_set_draw_faded
;
1092 nelma_graphics_class
.draw_line
= nelma_draw_line
;
1093 nelma_graphics_class
.draw_arc
= nelma_draw_arc
;
1094 nelma_graphics_class
.draw_rect
= nelma_draw_rect
;
1095 nelma_graphics_class
.fill_circle
= nelma_fill_circle
;
1096 nelma_graphics_class
.fill_polygon
= nelma_fill_polygon
;
1097 nelma_graphics_class
.fill_rect
= nelma_fill_rect
;
1099 nelma_graphics
.klass
= &nelma_graphics_class
;
1100 nelma_graphics
.poly_before
= true;
1101 common_nogui_graphics_init (&nelma_graphics
);
1102 common_draw_helpers_init (&nelma_graphics
);
1104 hid_register_hid (&nelma_hid
);
1106 #include "nelma_lists.h"