Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 36278) +++ trunk/scconfig/Rev.h (revision 36279) @@ -1 +1 @@ -static const int myrev = 36260; +static const int myrev = 36279; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 36278) +++ trunk/scconfig/Rev.tab (revision 36279) @@ -1,4 +1,4 @@ -36260 configure export plugin generalization for librnd +36279 configure export plugin generalization for librnd 36043 configure version bump: 3.0.4-dev 35941 configure moving generic part of diag and preferences dialog to librnd 3.1.0 35866 configure diag plugin generalization for librnd move Index: trunk/src_plugins/export_svg/Plug.tmpasm =================================================================== --- trunk/src_plugins/export_svg/Plug.tmpasm (revision 36278) +++ trunk/src_plugins/export_svg/Plug.tmpasm (revision 36279) @@ -1,5 +1,8 @@ put /local/pcb/mod {export_svg} -put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_svg/svg.o @] +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_svg/svg.o + $(PLUGDIR)/export_svg/draw_svg.o +@] switch /local/pcb/export_svg/controls case {buildin} include /local/pcb/tmpasm/buildin; end; Index: trunk/src_plugins/export_svg/draw_svg.c =================================================================== --- trunk/src_plugins/export_svg/draw_svg.c (nonexistent) +++ trunk/src_plugins/export_svg/draw_svg.c (revision 36279) @@ -0,0 +1,638 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * (this file is based on PCB, interactive printed circuit board design) + * Copyright (C) 2006 Dan McMahill + * Copyright (C) 2016,2022 Tibor 'Igor2' Palinkas + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact: + * Project page: http://repo.hu/projects/pcb-rnd + * lead developer: http://repo.hu/projects/pcb-rnd/contact.html + * mailing list: pcb-rnd (at) list.repo.hu (send "subscribe") + */ + +/* Based on the png exporter by Dan McMahill */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "draw_svg.h" + +typedef struct rnd_hid_gc_s { + rnd_core_gc_t core_gc; + rnd_hid_t *me_pointer; + rnd_cap_style_t cap; + int width; + char *color; + int drill; + unsigned warned_elliptical:1; +} rnd_hid_gc_s; + +static const char *CAPS(rnd_cap_style_t cap) +{ + switch (cap) { + case rnd_cap_round: + return "round"; + case rnd_cap_square: + return "square"; + default: + assert(!"unhandled cap"); + return "round"; + } + return ""; +} + +/* Photo mode colors and hacks */ +static const char *rnd_svg_board_color = "#464646"; +static const char *mask_color = "#00ff00"; +static float mask_opacity_factor = 0.5; + +rnd_svg_photo_color_t rnd_svg_photo_color; + +static struct { + const char *bright; + const char *normal; + const char *dark; + rnd_coord_t offs; +} photo_palette[] = { + /* MASK */ { "#00ff00", "#00ff00", "#00ff00", RND_MM_TO_COORD(0) }, + /* SILK */ { "#ffffff", "#eeeeee", "#aaaaaa", RND_MM_TO_COORD(0) }, + /* COPPER */ { "#bbbbbb", "#707090", "#555555", RND_MM_TO_COORD(0.05) }, + /* INNER */ { "#222222", "#111111", "#000000", RND_MM_TO_COORD(0) } +}; + +#define TRX(x) +#define TRY(y) \ +do { \ + if (pctx->flip) \ + y = pctx->hidlib->size_y - y; \ +} while(0) + +void rnd_svg_init(rnd_svg_t *pctx, rnd_hidlib_t *hidlib, FILE *f, int opacity, int flip, int true_size) +{ + memset(pctx, 0, sizeof(rnd_svg_t)); + pctx->hidlib = hidlib; + pctx->outf = f; + pctx->opacity = opacity; + pctx->flip = flip; + pctx->true_size = true_size; +} + +void rnd_svg_uninit(rnd_svg_t *pctx) +{ + gds_uninit(&pctx->sbright); + gds_uninit(&pctx->sdark); + gds_uninit(&pctx->snormal); + gds_uninit(&pctx->sclip); +} + +static void group_close(rnd_svg_t *pctx) +{ + if (pctx->group_open == 1) { + if (gds_len(&pctx->sdark) > 0) { + fprintf(pctx->outf, "\n"); + fprintf(pctx->outf, "%s", pctx->sdark.array); + gds_truncate(&pctx->sdark, 0); + } + + if (gds_len(&pctx->sbright) > 0) { + fprintf(pctx->outf, "\n"); + fprintf(pctx->outf, "%s", pctx->sbright.array); + gds_truncate(&pctx->sbright, 0); + } + + if (gds_len(&pctx->snormal) > 0) { + fprintf(pctx->outf, "\n"); + fprintf(pctx->outf, "%s", pctx->snormal.array); + gds_truncate(&pctx->snormal, 0); + } + + } + fprintf(pctx->outf, "\n"); +} + +void rnd_svg_header(rnd_svg_t *pctx) +{ + rnd_coord_t w, h, x1, y1, x2, y2; + + fprintf(pctx->outf, "\n"); + w = pctx->hidlib->size_x; + h = pctx->hidlib->size_y; + while((w < RND_MM_TO_COORD(1024)) && (h < RND_MM_TO_COORD(1024))) { + w *= 2; + h *= 2; + } + + x2 = pctx->hidlib->size_x; + y2 = pctx->hidlib->size_y; + if (pctx->true_size) { + rnd_fprintf(pctx->outf, "\n", x2, y2, x2, y2); + } + else { + x1 = RND_MM_TO_COORD(2); + y1 = RND_MM_TO_COORD(2); + x2 += RND_MM_TO_COORD(5); + y2 += RND_MM_TO_COORD(5); + rnd_fprintf(pctx->outf, "\n", w, h, x1, y1, x2, y2); + } +} + +void rnd_svg_footer(rnd_svg_t *pctx) +{ + while(pctx->group_open) { + group_close(pctx); + pctx->group_open--; + } + + /* blend some noise on top to make it a bit more artificial */ + if (pctx->photo_mode && pctx->photo_noise) { + fprintf(pctx->outf, "\n"); + fprintf(pctx->outf, " \n"); + fprintf(pctx->outf, "\n"); + fprintf(pctx->outf, "\n"); + rnd_fprintf(pctx->outf, " \n", + 0, 0, pctx->hidlib->size_x, pctx->hidlib->size_y); + fprintf(pctx->outf, "\n"); + } + + fprintf(pctx->outf, "\n"); +} + +int rnd_svg_new_file(rnd_svg_t *pctx, FILE *f, const char *fn) +{ + int ern = errno; + + if (pctx->outf != NULL) { + rnd_svg_footer(pctx); + fclose(pctx->outf); + } + + if (f == NULL) { + TODO("copy error print from ps"); + perror(fn); + return -1; + } + + pctx->outf = f; + return 0; +} + +void rnd_svg_background(rnd_svg_t *pctx) +{ + if (pctx->photo_mode) { + rnd_fprintf(pctx->outf, "\n", + 0, 0, pctx->hidlib->size_x, pctx->hidlib->size_y, rnd_svg_board_color); + } +} + +void rnd_svg_layer_group_begin(rnd_svg_t *pctx, long group, const char *name, int is_our_mask) +{ + int opa; + + while(pctx->group_open) { + group_close(pctx); + pctx->group_open--; + } + fprintf(pctx->outf, "opacity; + if (is_our_mask) + opa *= mask_opacity_factor; + if (opa != 100) + fprintf(pctx->outf, " opacity=\"%.2f\"", ((float)opa) / 100.0); + fprintf(pctx->outf, ">\n"); + pctx->group_open = 1; +} + +static int rnd_svg_me; + +rnd_hid_gc_t rnd_svg_make_gc(rnd_hid_t *hid) +{ + rnd_hid_gc_t rv = (rnd_hid_gc_t) calloc(sizeof(rnd_hid_gc_s), 1); + rv->me_pointer = (rnd_hid_t *)&rnd_svg_me; + rv->cap = rnd_cap_round; + rv->width = 1; + rv->color = NULL; + return rv; +} + +void rnd_svg_destroy_gc(rnd_hid_gc_t gc) +{ + free(gc); +} + +void rnd_svg_set_drawing_mode(rnd_svg_t *pctx, rnd_hid_t *hid, rnd_composite_op_t op, rnd_bool direct, const rnd_box_t *screen) +{ + pctx->drawing_mode = op; + + if (direct) + return; + + switch(op) { + case RND_HID_COMP_RESET: + pctx->comp_cnt++; + gds_init(&pctx->sclip); + rnd_append_printf(&pctx->snormal, "\n"); + rnd_append_printf(&pctx->snormal, "\n"); + rnd_append_printf(&pctx->snormal, "\n", pctx->comp_cnt); + rnd_append_printf(&pctx->sclip, "\n", pctx->comp_cnt, pctx->hidlib->size_x, pctx->hidlib->size_y); + break; + + case RND_HID_COMP_POSITIVE: + case RND_HID_COMP_POSITIVE_XOR: + case RND_HID_COMP_NEGATIVE: + break; + + case RND_HID_COMP_FLUSH: + rnd_append_printf(&pctx->snormal, "\n"); + rnd_append_printf(&pctx->sclip, "\n"); + gds_append_str(&pctx->snormal, pctx->sclip.array); + rnd_append_printf(&pctx->snormal, "\n"); + rnd_append_printf(&pctx->snormal, "\n", pctx->comp_cnt, pctx->comp_cnt); + rnd_append_printf(&pctx->snormal, "\n"); + gds_uninit(&pctx->sclip); + break; + } +} + +static const char *svg_color(rnd_hid_gc_t gc) +{ + return gc->color; +} + +static const char *svg_clip_color(rnd_svg_t *pctx, rnd_hid_gc_t gc) +{ + if ((pctx->drawing_mode == RND_HID_COMP_POSITIVE) || (pctx->drawing_mode == RND_HID_COMP_POSITIVE_XOR)) + return "#FFFFFF"; + if (pctx->drawing_mode == RND_HID_COMP_NEGATIVE) + return "#000000"; + return NULL; +} + +void rnd_svg_set_color(rnd_svg_t *pctx, rnd_hid_gc_t gc, const rnd_color_t *color) +{ + const char *name; + gc->drill = 0; + + if (color == NULL) + name = "#ff0000"; + else + name = color->str; + + if (rnd_color_is_drill(color)) { + name = "#ffffff"; + gc->drill = 1; + } + if (pctx->drawing_mask) + name = mask_color; + if ((gc->color != NULL) && (strcmp(gc->color, name) == 0)) + return; + free(gc->color); + gc->color = rnd_strdup(name); +} + +void rnd_svg_set_line_cap(rnd_hid_gc_t gc, rnd_cap_style_t style) +{ + gc->cap = style; +} + +void rnd_svg_set_line_width(rnd_hid_gc_t gc, rnd_coord_t width) +{ + gc->width = width < RND_MM_TO_COORD(0.01) ? RND_MM_TO_COORD(0.01) : width; +} + +void rnd_svg_set_draw_xor(rnd_hid_gc_t gc, int xor_) +{ + ; +} + +static void indent(rnd_svg_t *pctx, gds_t *s) +{ + static char ind[] = " "; + if (pctx->group_open < sizeof(ind)-1) { + ind[pctx->group_open] = '\0'; + if (s == NULL) + rnd_fprintf(pctx->outf, ind); + else + rnd_append_printf(s, ind); + ind[pctx->group_open] = ' '; + return; + } + + if (s == NULL) + rnd_fprintf(pctx->outf, ind); + else + rnd_append_printf(s, ind); +} + + +#define fix_rect_coords() \ + if (x1 > x2) {\ + rnd_coord_t t = x1; \ + x1 = x2; \ + x2 = t; \ + } \ + if (y1 > y2) { \ + rnd_coord_t t = y1; \ + y1 = y2; \ + y2 = t; \ + } + +static void draw_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t w, rnd_coord_t h, rnd_coord_t stroke) +{ + const char *clip_color = svg_clip_color(pctx, gc); + + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, w, h, stroke, svg_color(gc), CAPS(gc->cap)); + if (clip_color != NULL) { + indent(pctx, &pctx->sclip); + rnd_append_printf(&pctx->sclip, "\n", + x1, y1, w, h, stroke, clip_color, CAPS(gc->cap)); + } +} + +void rnd_svg_draw_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) +{ + pctx->drawn_objs++; + fix_rect_coords(); + draw_rect(pctx, gc, x1, y1, x2-x1, y2-y1, gc->width); +} + +static void draw_fill_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t w, rnd_coord_t h) +{ + const char *clip_color = svg_clip_color(pctx, gc); + if (pctx->photo_mode) { + rnd_coord_t photo_offs = photo_palette[rnd_svg_photo_color].offs; + if (photo_offs != 0) { + indent(pctx, &pctx->sdark); + rnd_append_printf(&pctx->sdark, "\n", + x1+photo_offs, y1+photo_offs, w, h, photo_palette[rnd_svg_photo_color].dark); + indent(pctx, &pctx->sbright); + rnd_append_printf(&pctx->sbright, "\n", + x1-photo_offs, y1-photo_offs, w, h, photo_palette[rnd_svg_photo_color].bright); + } + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, w, h, photo_palette[rnd_svg_photo_color].normal); + } + else { + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, w, h, svg_color(gc)); + } + if (clip_color != NULL) + rnd_append_printf(&pctx->sclip, "\n", + x1, y1, w, h, clip_color); +} + +void rnd_svg_fill_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) +{ + pctx->drawn_objs++; + TRX(x1); TRY(y1); TRX(x2); TRY(y2); + fix_rect_coords(); + draw_fill_rect(pctx, gc, x1, y1, x2-x1, y2-y1); +} + +static void pcb_line_draw(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) +{ + const char *clip_color = svg_clip_color(pctx, gc); + if (pctx->photo_mode) { + rnd_coord_t photo_offs = photo_palette[rnd_svg_photo_color].offs; + if (photo_offs != 0) { + indent(pctx, &pctx->sbright); + rnd_append_printf(&pctx->sbright, "\n", + x1-photo_offs, y1-photo_offs, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[rnd_svg_photo_color].bright, CAPS(gc->cap)); + indent(pctx, &pctx->sdark); + rnd_append_printf(&pctx->sdark, "\n", + x1+photo_offs, y1+photo_offs, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[rnd_svg_photo_color].dark, CAPS(gc->cap)); + } + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, x2, y2, gc->width, photo_palette[rnd_svg_photo_color].normal, CAPS(gc->cap)); + } + else { + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); + } + if (clip_color != NULL) { + rnd_append_printf(&pctx->sclip, "\n", + x1, y1, x2, y2, gc->width, clip_color, CAPS(gc->cap)); + } +} + +void rnd_svg_draw_line(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) +{ + pctx->drawn_objs++; + TRX(x1); TRY(y1); TRX(x2); TRY(y2); + pcb_line_draw(pctx, gc, x1, y1, x2, y2); +} + +static void pcb_arc_draw(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t r, rnd_coord_t x2, rnd_coord_t y2, rnd_coord_t stroke, int large, int sweep) +{ + const char *clip_color = svg_clip_color(pctx, gc); + TRX(x1); TRY(y1); TRX(x2); TRY(y2); + if (pctx->photo_mode) { + rnd_coord_t photo_offs = photo_palette[rnd_svg_photo_color].offs; + if (photo_offs != 0) { + indent(pctx, &pctx->sbright); + rnd_append_printf(&pctx->sbright, "\n", + x1-photo_offs, y1-photo_offs, r, r, large, sweep, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[rnd_svg_photo_color].bright, CAPS(gc->cap)); + indent(pctx, &pctx->sdark); + rnd_append_printf(&pctx->sdark, "\n", + x1+photo_offs, y1+photo_offs, r, r, large, sweep, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[rnd_svg_photo_color].dark, CAPS(gc->cap)); + } + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, photo_palette[rnd_svg_photo_color].normal, CAPS(gc->cap)); + } + else { + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); + } + if (clip_color != NULL) + rnd_append_printf(&pctx->sclip, "\n", + x1, y1, r, r, large, sweep, x2, y2, gc->width, clip_color, CAPS(gc->cap)); +} + +void rnd_svg_draw_arc(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t width, rnd_coord_t height, rnd_angle_t start_angle, rnd_angle_t delta_angle) +{ + rnd_coord_t x1, y1, x2, y2, diff = 0, diff2, maxdiff; + rnd_angle_t sa, ea; + + pctx->drawn_objs++; + + /* degenerate case: r=0 means a single dot */ + if ((width == 0) && (height == 0)) { + pcb_line_draw(pctx, gc, cx, cy, cx, cy); + return; + } + + /* detect elliptical arcs: if diff between radii is above 0.1% */ + diff2 = width - height; + if (diff2 < 0) + diff2 = -diff2; + maxdiff = width; + if (height > maxdiff) + maxdiff = height; + if (diff2 > maxdiff / 1000) { + if (!gc->warned_elliptical) { + rnd_message(RND_MSG_ERROR, "Can't draw elliptical arc on svg; object omitted; expect BROKEN TRACE\n"); + gc->warned_elliptical = 1; + } + return; + } + + TRX(cx); TRY(cy); + + /* calculate start and end angles considering flip */ + start_angle = 180 - start_angle; + delta_angle = -delta_angle; + if (pctx->flip) { + start_angle = -start_angle; + delta_angle = -delta_angle; + } + + /* workaround for near-360 deg rendering bugs */ + if ((delta_angle >= +360.0) || (delta_angle <= -360.0)) { + rnd_svg_draw_arc(pctx, gc, cx, cy, width, height, 0, 180); + rnd_svg_draw_arc(pctx, gc, cx, cy, width, height, 180, 180); + return; + } + + if (fabs(delta_angle) <= 0.001) { delta_angle = 0.001; diff=1; } + + sa = start_angle; + ea = start_angle + delta_angle; + + /* calculate the endpoints */ + x2 = rnd_round((double)cx + ((double)width * cos(sa * M_PI / 180))); + y2 = rnd_round((double)cy + ((double)width * sin(sa * M_PI / 180))); + x1 = rnd_round((double)cx + ((double)width * cos(ea * M_PI / 180))+diff); + y1 = rnd_round((double)cy + ((double)width * sin(ea * M_PI / 180))+diff); + + pcb_arc_draw(pctx, gc, x1, y1, width, x2, y2, gc->width, (fabs(delta_angle) > 180), (delta_angle < 0.0)); +} + +static void draw_fill_circle(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t r, rnd_coord_t stroke) +{ + const char *clip_color = svg_clip_color(pctx, gc); + + pctx->drawn_objs++; + + if (pctx->photo_mode) { + if (!pctx->drawing_hole) { + rnd_coord_t photo_offs = photo_palette[rnd_svg_photo_color].offs; + if ((!gc->drill) && (photo_offs != 0)) { + indent(pctx, &pctx->sbright); + rnd_append_printf(&pctx->sbright, "\n", + cx-photo_offs, cy-photo_offs, r, stroke, photo_palette[rnd_svg_photo_color].bright); + + indent(pctx, &pctx->sdark); + rnd_append_printf(&pctx->sdark, "\n", + cx+photo_offs, cy+photo_offs, r, stroke, photo_palette[rnd_svg_photo_color].dark); + } + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + cx, cy, r, stroke, photo_palette[rnd_svg_photo_color].normal); + } + else { + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + cx, cy, r, stroke, "#000000"); + } + } + else{ + indent(pctx, &pctx->snormal); + rnd_append_printf(&pctx->snormal, "\n", + cx, cy, r, stroke, svg_color(gc)); + } + if (clip_color != NULL) + rnd_append_printf(&pctx->sclip, "\n", + cx, cy, r, stroke, clip_color); +} + +void rnd_svg_fill_circle(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t radius) +{ + pctx->drawn_objs++; + TRX(cx); TRY(cy); + draw_fill_circle(pctx, gc, cx, cy, radius, 0); +} + +static void draw_poly(rnd_svg_t *pctx, gds_t *s, rnd_hid_gc_t gc, int n_coords, rnd_coord_t * x, rnd_coord_t * y, rnd_coord_t dx, rnd_coord_t dy, const char *clr) +{ + int i; + float poly_bloat = 0.01; + + indent(pctx, s); + gds_append_str(s, "\n", poly_bloat, clr, clr); +} + +void rnd_svg_fill_polygon_offs(rnd_svg_t *pctx, rnd_hid_gc_t gc, int n_coords, rnd_coord_t *x, rnd_coord_t *y, rnd_coord_t dx, rnd_coord_t dy) +{ + const char *clip_color = svg_clip_color(pctx, gc); + pctx->drawn_objs++; + if (pctx->photo_mode) { + rnd_coord_t photo_offs_x = photo_palette[rnd_svg_photo_color].offs, photo_offs_y = photo_palette[rnd_svg_photo_color].offs; + if (photo_offs_x != 0) { + if (pctx->flip) + photo_offs_y = -photo_offs_y; + draw_poly(pctx, &pctx->sbright, gc, n_coords, x, y, dx-photo_offs_x, dy-photo_offs_y, photo_palette[rnd_svg_photo_color].bright); + draw_poly(pctx, &pctx->sdark, gc, n_coords, x, y, dx+photo_offs_x, dy+photo_offs_y, photo_palette[rnd_svg_photo_color].dark); + } + draw_poly(pctx, &pctx->snormal, gc, n_coords, x, y, dx, dy, photo_palette[rnd_svg_photo_color].normal); + } + else + draw_poly(pctx, &pctx->snormal, gc, n_coords, x, y, dx, dy, svg_color(gc)); + + if (clip_color != NULL) + draw_poly(pctx, &pctx->sclip, gc, n_coords, x, y, dx, dy, clip_color); +} + +void rnd_svg_set_crosshair(rnd_hid_t *hid, rnd_coord_t x, rnd_coord_t y, int a) +{ +} Index: trunk/src_plugins/export_svg/draw_svg.h =================================================================== --- trunk/src_plugins/export_svg/draw_svg.h (nonexistent) +++ trunk/src_plugins/export_svg/draw_svg.h (revision 36279) @@ -0,0 +1,65 @@ +#include + +typedef struct { + /* public: config */ + rnd_hidlib_t *hidlib; + FILE *outf; + gds_t sbright, sdark, snormal, sclip; /* accumulators for various groups generated parallel */ + int opacity; + int flip; + int true_size; + + /* public: result */ + long drawn_objs; + + /* private: cache */ + int group_open, comp_cnt; + rnd_composite_op_t drawing_mode; + + /* private: pcb-rnd leftover */ + int photo_mode, photo_noise, drawing_mask, drawing_hole; +} rnd_svg_t; + + +void rnd_svg_init(rnd_svg_t *pctx, rnd_hidlib_t *hidlib, FILE *f, int opacity, int flip, int true_size); +void rnd_svg_uninit(rnd_svg_t *pctx); + +/* Write header or footer. Footer also writes cached groups and closes them. */ +void rnd_svg_header(rnd_svg_t *pctx); +void rnd_svg_footer(rnd_svg_t *pctx); + +int rnd_svg_new_file(rnd_svg_t *pctx, FILE *f, const char *fn); +void rnd_svg_layer_group_begin(rnd_svg_t *pctx, long group, const char *name, int is_our_mask); + +void rnd_svg_background(rnd_svg_t *pctx); + + +rnd_hid_gc_t rnd_svg_make_gc(rnd_hid_t *hid); +void rnd_svg_destroy_gc(rnd_hid_gc_t gc); +void rnd_svg_set_line_cap(rnd_hid_gc_t gc, rnd_cap_style_t style); +void rnd_svg_set_line_width(rnd_hid_gc_t gc, rnd_coord_t width); +void rnd_svg_set_draw_xor(rnd_hid_gc_t gc, int xor_); +void rnd_svg_set_crosshair(rnd_hid_t *hid, rnd_coord_t x, rnd_coord_t y, int a); + + + +void rnd_svg_set_drawing_mode(rnd_svg_t *pctx, rnd_hid_t *hid, rnd_composite_op_t op, rnd_bool direct, const rnd_box_t *screen); +void rnd_svg_set_color(rnd_svg_t *pctx, rnd_hid_gc_t gc, const rnd_color_t *color); +void rnd_svg_draw_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2); +void rnd_svg_fill_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2); +void rnd_svg_draw_line(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2); +void rnd_svg_draw_arc(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t width, rnd_coord_t height, rnd_angle_t start_angle, rnd_angle_t delta_angle); +void rnd_svg_fill_circle(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t radius); +void rnd_svg_fill_polygon_offs(rnd_svg_t *pctx, rnd_hid_gc_t gc, int n_coords, rnd_coord_t *x, rnd_coord_t *y, rnd_coord_t dx, rnd_coord_t dy); + +/* leftover for pcb-rnd */ +typedef enum { + RND_SVG_PHOTO_MASK, + RND_SVG_PHOTO_SILK, + RND_SVG_PHOTO_COPPER, + RND_SVG_PHOTO_INNER +} rnd_svg_photo_color_t; + +extern rnd_svg_photo_color_t rnd_svg_photo_color; + + Index: trunk/src_plugins/export_svg/svg.c =================================================================== --- trunk/src_plugins/export_svg/svg.c (revision 36278) +++ trunk/src_plugins/export_svg/svg.c (revision 36279) @@ -36,7 +36,6 @@ #include #include #include -#include #include #include @@ -61,6 +60,7 @@ #include #include "hid_cam.h" +#include "draw_svg.h" static rnd_hid_t svg_hid; @@ -68,76 +68,8 @@ static pcb_cam_t svg_cam; -typedef struct rnd_hid_gc_s { - rnd_core_gc_t core_gc; - rnd_hid_t *me_pointer; - rnd_cap_style_t cap; - int width; - char *color; - int drill; - unsigned warned_elliptical:1; -} rnd_hid_gc_s; - -static const char *CAPS(rnd_cap_style_t cap) -{ - switch (cap) { - case rnd_cap_round: - return "round"; - case rnd_cap_square: - return "square"; - default: - assert(!"unhandled cap"); - return "round"; - } - return ""; -} - -typedef struct { - /* public: config */ - rnd_hidlib_t *hidlib; - FILE *outf; - gds_t sbright, sdark, snormal, sclip; /* accumulators for various groups generated parallel */ - int opacity; - int flip; - int true_size; - - /* public: result */ - long drawn_objs; - - /* private: cache */ - int group_open, comp_cnt; - rnd_composite_op_t drawing_mode; - - /* private: pcb-rnd leftover */ - int photo_mode, photo_noise, drawing_mask, drawing_hole; -} rnd_svg_t; - static rnd_svg_t pctx_, *pctx = &pctx_; -/* Photo mode colors and hacks */ -static const char *board_color = "#464646"; -static const char *mask_color = "#00ff00"; -static float mask_opacity_factor = 0.5; - -static enum { - PHOTO_MASK, - PHOTO_SILK, - PHOTO_COPPER, - PHOTO_INNER -} photo_color; - -static struct { - const char *bright; - const char *normal; - const char *dark; - rnd_coord_t offs; -} photo_palette[] = { - /* MASK */ { "#00ff00", "#00ff00", "#00ff00", RND_MM_TO_COORD(0) }, - /* SILK */ { "#ffffff", "#eeeeee", "#aaaaaa", RND_MM_TO_COORD(0) }, - /* COPPER */ { "#bbbbbb", "#707090", "#555555", RND_MM_TO_COORD(0.05) }, - /* INNER */ { "#222222", "#111111", "#000000", RND_MM_TO_COORD(0) } -}; - static const rnd_export_opt_t svg_attribute_list[] = { /* other HIDs expect this to be first. */ @@ -207,13 +139,6 @@ #define NUM_OPTIONS (sizeof(svg_attribute_list)/sizeof(svg_attribute_list[0])) -#define TRX(x) -#define TRY(y) \ -do { \ - if (pctx->flip) \ - y = pctx->hidlib->size_y - y; \ -} while(0) - static rnd_hid_attr_val_t svg_values[NUM_OPTIONS]; static const rnd_export_opt_t *svg_get_export_options(rnd_hid_t *hid, int *n) @@ -229,24 +154,6 @@ return svg_attribute_list; } -void rnd_svg_init(rnd_svg_t *pctx, rnd_hidlib_t *hidlib, FILE *f, int opacity, int flip, int true_size) -{ - memset(pctx, 0, sizeof(rnd_svg_t)); - pctx->hidlib = hidlib; - pctx->outf = f; - pctx->opacity = opacity; - pctx->flip = flip; - pctx->true_size = true_size; -} - -void rnd_svg_uninit(rnd_svg_t *pctx) -{ - gds_uninit(&pctx->sbright); - gds_uninit(&pctx->sdark); - gds_uninit(&pctx->snormal); - gds_uninit(&pctx->sclip); -} - void svg_hid_export_to_file(FILE * the_file, rnd_hid_attr_val_t * options, rnd_xform_t *xform) { static int saved_layer_stack[PCB_MAX_LAYER]; @@ -289,10 +196,7 @@ } } - if (pctx->photo_mode) { - rnd_fprintf(pctx->outf, "\n", - 0, 0, pctx->hidlib->size_x, pctx->hidlib->size_y, board_color); - } + rnd_svg_background(pctx); if (options[HA_as_shown].lng) { pcb_draw_setup_default_gui_xform(xform); @@ -310,78 +214,6 @@ rnd_conf_update(NULL, -1); /* restore forced sets */ } -static void group_close(rnd_svg_t *pctx) -{ - if (pctx->group_open == 1) { - if (gds_len(&pctx->sdark) > 0) { - fprintf(pctx->outf, "\n"); - fprintf(pctx->outf, "%s", pctx->sdark.array); - gds_truncate(&pctx->sdark, 0); - } - - if (gds_len(&pctx->sbright) > 0) { - fprintf(pctx->outf, "\n"); - fprintf(pctx->outf, "%s", pctx->sbright.array); - gds_truncate(&pctx->sbright, 0); - } - - if (gds_len(&pctx->snormal) > 0) { - fprintf(pctx->outf, "\n"); - fprintf(pctx->outf, "%s", pctx->snormal.array); - gds_truncate(&pctx->snormal, 0); - } - - } - fprintf(pctx->outf, "\n"); -} - -void rnd_svg_header(rnd_svg_t *pctx) -{ - rnd_coord_t w, h, x1, y1, x2, y2; - - fprintf(pctx->outf, "\n"); - w = pctx->hidlib->size_x; - h = pctx->hidlib->size_y; - while((w < RND_MM_TO_COORD(1024)) && (h < RND_MM_TO_COORD(1024))) { - w *= 2; - h *= 2; - } - - x2 = pctx->hidlib->size_x; - y2 = pctx->hidlib->size_y; - if (pctx->true_size) { - rnd_fprintf(pctx->outf, "\n", x2, y2, x2, y2); - } - else { - x1 = RND_MM_TO_COORD(2); - y1 = RND_MM_TO_COORD(2); - x2 += RND_MM_TO_COORD(5); - y2 += RND_MM_TO_COORD(5); - rnd_fprintf(pctx->outf, "\n", w, h, x1, y1, x2, y2); - } -} - -void rnd_svg_footer(rnd_svg_t *pctx) -{ - while(pctx->group_open) { - group_close(pctx); - pctx->group_open--; - } - - /* blend some noise on top to make it a bit more artificial */ - if (pctx->photo_mode && pctx->photo_noise) { - fprintf(pctx->outf, "\n"); - fprintf(pctx->outf, " \n"); - fprintf(pctx->outf, "\n"); - fprintf(pctx->outf, "\n"); - rnd_fprintf(pctx->outf, " \n", - 0, 0, pctx->hidlib->size_x, pctx->hidlib->size_y); - fprintf(pctx->outf, "\n"); - } - - fprintf(pctx->outf, "\n"); -} - static void svg_do_export(rnd_hid_t *hid, rnd_hid_attr_val_t *options) { const char *filename; @@ -453,45 +285,6 @@ return rnd_hid_parse_command_line(argc, argv); } -int rnd_svg_new_file(rnd_svg_t *pctx, FILE *f, const char *fn) -{ - int ern = errno; - - if (pctx->outf != NULL) { - rnd_svg_footer(pctx); - fclose(pctx->outf); - } - - if (f == NULL) { - TODO("copy error print from ps"); - perror(fn); - return -1; - } - - pctx->outf = f; - return 0; -} - -void rnd_svg_layer_group_begin(rnd_svg_t *pctx, long group, const char *name, int is_our_mask) -{ - int opa; - - while(pctx->group_open) { - group_close(pctx); - pctx->group_open--; - } - fprintf(pctx->outf, "opacity; - if (is_our_mask) - opa *= mask_opacity_factor; - if (opa != 100) - fprintf(pctx->outf, " opacity=\"%.2f\"", ((float)opa) / 100.0); - fprintf(pctx->outf, ">\n"); - pctx->group_open = 1; - -} - static int svg_set_layer_group(rnd_hid_t *hid, rnd_layergrp_id_t group, const char *purpose, int purpi, rnd_layer_id_t layer, unsigned int flags, int is_empty, rnd_xform_t **xform) { int is_our_mask = 0, is_our_silk = 0; @@ -550,14 +343,14 @@ if (pctx->photo_mode) { if (is_our_silk) - photo_color = PHOTO_SILK; + rnd_svg_photo_color = RND_SVG_PHOTO_SILK; else if (is_our_mask) - photo_color = PHOTO_MASK; + rnd_svg_photo_color = RND_SVG_PHOTO_MASK; else if (group >= 0) { if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags)) - photo_color = PHOTO_COPPER; + rnd_svg_photo_color = RND_SVG_PHOTO_COPPER; else - photo_color = PHOTO_INNER; + rnd_svg_photo_color = RND_SVG_PHOTO_INNER; } } @@ -565,435 +358,41 @@ return 1; } - -rnd_hid_gc_t rnd_svg_make_gc(rnd_hid_t *hid) -{ - rnd_hid_gc_t rv = (rnd_hid_gc_t) calloc(sizeof(rnd_hid_gc_s), 1); - rv->me_pointer = &svg_hid; - rv->cap = rnd_cap_round; - rv->width = 1; - rv->color = NULL; - return rv; -} - -void rnd_svg_destroy_gc(rnd_hid_gc_t gc) -{ - free(gc); -} - -void rnd_svg_set_drawing_mode(rnd_svg_t *pctx, rnd_hid_t *hid, rnd_composite_op_t op, rnd_bool direct, const rnd_box_t *screen) -{ - pctx->drawing_mode = op; - - if (direct) - return; - - switch(op) { - case RND_HID_COMP_RESET: - pctx->comp_cnt++; - gds_init(&pctx->sclip); - rnd_append_printf(&pctx->snormal, "\n"); - rnd_append_printf(&pctx->snormal, "\n"); - rnd_append_printf(&pctx->snormal, "\n", pctx->comp_cnt); - rnd_append_printf(&pctx->sclip, "\n", pctx->comp_cnt, pctx->hidlib->size_x, pctx->hidlib->size_y); - break; - - case RND_HID_COMP_POSITIVE: - case RND_HID_COMP_POSITIVE_XOR: - case RND_HID_COMP_NEGATIVE: - break; - - case RND_HID_COMP_FLUSH: - rnd_append_printf(&pctx->snormal, "\n"); - rnd_append_printf(&pctx->sclip, "\n"); - gds_append_str(&pctx->snormal, pctx->sclip.array); - rnd_append_printf(&pctx->snormal, "\n"); - rnd_append_printf(&pctx->snormal, "\n", pctx->comp_cnt, pctx->comp_cnt); - rnd_append_printf(&pctx->snormal, "\n"); - gds_uninit(&pctx->sclip); - break; - } -} - static void svg_set_drawing_mode(rnd_hid_t *hid, rnd_composite_op_t op, rnd_bool direct, const rnd_box_t *screen) { rnd_svg_set_drawing_mode(pctx, hid, op, direct, screen); } -static const char *svg_color(rnd_hid_gc_t gc) -{ - return gc->color; -} - -static const char *svg_clip_color(rnd_hid_gc_t gc) -{ - if ((pctx->drawing_mode == RND_HID_COMP_POSITIVE) || (pctx->drawing_mode == RND_HID_COMP_POSITIVE_XOR)) - return "#FFFFFF"; - if (pctx->drawing_mode == RND_HID_COMP_NEGATIVE) - return "#000000"; - return NULL; -} - -void rnd_svg_set_color(rnd_svg_t *pctx, rnd_hid_gc_t gc, const rnd_color_t *color) -{ - const char *name; - gc->drill = 0; - - if (color == NULL) - name = "#ff0000"; - else - name = color->str; - - if (rnd_color_is_drill(color)) { - name = "#ffffff"; - gc->drill = 1; - } - if (pctx->drawing_mask) - name = mask_color; - if ((gc->color != NULL) && (strcmp(gc->color, name) == 0)) - return; - free(gc->color); - gc->color = rnd_strdup(name); -} - static void svg_set_color(rnd_hid_gc_t gc, const rnd_color_t *color) { rnd_svg_set_color(pctx, gc, color); } - -void rnd_svg_set_line_cap(rnd_hid_gc_t gc, rnd_cap_style_t style) -{ - gc->cap = style; -} - -void rnd_svg_set_line_width(rnd_hid_gc_t gc, rnd_coord_t width) -{ - gc->width = width < RND_MM_TO_COORD(0.01) ? RND_MM_TO_COORD(0.01) : width; -} - -void rnd_svg_set_draw_xor(rnd_hid_gc_t gc, int xor_) -{ - ; -} - -static void indent(rnd_svg_t *pctx, gds_t *s) -{ - static char ind[] = " "; - if (pctx->group_open < sizeof(ind)-1) { - ind[pctx->group_open] = '\0'; - if (s == NULL) - rnd_fprintf(pctx->outf, ind); - else - rnd_append_printf(s, ind); - ind[pctx->group_open] = ' '; - return; - } - - if (s == NULL) - rnd_fprintf(pctx->outf, ind); - else - rnd_append_printf(s, ind); -} - - -#define fix_rect_coords() \ - if (x1 > x2) {\ - rnd_coord_t t = x1; \ - x1 = x2; \ - x2 = t; \ - } \ - if (y1 > y2) { \ - rnd_coord_t t = y1; \ - y1 = y2; \ - y2 = t; \ - } - -void draw_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t w, rnd_coord_t h, rnd_coord_t stroke) -{ - const char *clip_color = svg_clip_color(gc); - - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, w, h, stroke, svg_color(gc), CAPS(gc->cap)); - if (clip_color != NULL) { - indent(pctx, &pctx->sclip); - rnd_append_printf(&pctx->sclip, "\n", - x1, y1, w, h, stroke, clip_color, CAPS(gc->cap)); - } -} - -void rnd_svg_draw_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) -{ - pctx->drawn_objs++; - fix_rect_coords(); - draw_rect(pctx, gc, x1, y1, x2-x1, y2-y1, gc->width); -} - static void svg_draw_rect(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) { rnd_svg_draw_rect(pctx, gc, x1, y1, x2, y2); } -static void draw_fill_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t w, rnd_coord_t h) -{ - const char *clip_color = svg_clip_color(gc); - if (pctx->photo_mode) { - rnd_coord_t photo_offs = photo_palette[photo_color].offs; - if (photo_offs != 0) { - indent(pctx, &pctx->sdark); - rnd_append_printf(&pctx->sdark, "\n", - x1+photo_offs, y1+photo_offs, w, h, photo_palette[photo_color].dark); - indent(pctx, &pctx->sbright); - rnd_append_printf(&pctx->sbright, "\n", - x1-photo_offs, y1-photo_offs, w, h, photo_palette[photo_color].bright); - } - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, w, h, photo_palette[photo_color].normal); - } - else { - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, w, h, svg_color(gc)); - } - if (clip_color != NULL) - rnd_append_printf(&pctx->sclip, "\n", - x1, y1, w, h, clip_color); -} - -void rnd_svg_fill_rect(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) -{ - pctx->drawn_objs++; - TRX(x1); TRY(y1); TRX(x2); TRY(y2); - fix_rect_coords(); - draw_fill_rect(pctx, gc, x1, y1, x2-x1, y2-y1); -} - static void svg_fill_rect(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) { rnd_svg_fill_rect(pctx, gc, x1, y1, x2, y2); } -static void pcb_line_draw(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) -{ - const char *clip_color = svg_clip_color(gc); - if (pctx->photo_mode) { - rnd_coord_t photo_offs = photo_palette[photo_color].offs; - if (photo_offs != 0) { - indent(pctx, &pctx->sbright); - rnd_append_printf(&pctx->sbright, "\n", - x1-photo_offs, y1-photo_offs, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[photo_color].bright, CAPS(gc->cap)); - indent(pctx, &pctx->sdark); - rnd_append_printf(&pctx->sdark, "\n", - x1+photo_offs, y1+photo_offs, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[photo_color].dark, CAPS(gc->cap)); - } - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, x2, y2, gc->width, photo_palette[photo_color].normal, CAPS(gc->cap)); - } - else { - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); - } - if (clip_color != NULL) { - rnd_append_printf(&pctx->sclip, "\n", - x1, y1, x2, y2, gc->width, clip_color, CAPS(gc->cap)); - } -} - -void rnd_svg_draw_line(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) -{ - pctx->drawn_objs++; - TRX(x1); TRY(y1); TRX(x2); TRY(y2); - pcb_line_draw(pctx, gc, x1, y1, x2, y2); -} - static void svg_draw_line(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2) { rnd_svg_draw_line(pctx, gc, x1, y1, x2, y2); } -static void pcb_arc_draw(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t r, rnd_coord_t x2, rnd_coord_t y2, rnd_coord_t stroke, int large, int sweep) -{ - const char *clip_color = svg_clip_color(gc); - TRX(x1); TRY(y1); TRX(x2); TRY(y2); - if (pctx->photo_mode) { - rnd_coord_t photo_offs = photo_palette[photo_color].offs; - if (photo_offs != 0) { - indent(pctx, &pctx->sbright); - rnd_append_printf(&pctx->sbright, "\n", - x1-photo_offs, y1-photo_offs, r, r, large, sweep, x2-photo_offs, y2-photo_offs, gc->width, photo_palette[photo_color].bright, CAPS(gc->cap)); - indent(pctx, &pctx->sdark); - rnd_append_printf(&pctx->sdark, "\n", - x1+photo_offs, y1+photo_offs, r, r, large, sweep, x2+photo_offs, y2+photo_offs, gc->width, photo_palette[photo_color].dark, CAPS(gc->cap)); - } - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, r, r, large, sweep, x2, y2, gc->width, photo_palette[photo_color].normal, CAPS(gc->cap)); - } - else { - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - x1, y1, r, r, large, sweep, x2, y2, gc->width, svg_color(gc), CAPS(gc->cap)); - } - if (clip_color != NULL) - rnd_append_printf(&pctx->sclip, "\n", - x1, y1, r, r, large, sweep, x2, y2, gc->width, clip_color, CAPS(gc->cap)); -} - -void rnd_svg_draw_arc(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t width, rnd_coord_t height, rnd_angle_t start_angle, rnd_angle_t delta_angle) -{ - rnd_coord_t x1, y1, x2, y2, diff = 0, diff2, maxdiff; - rnd_angle_t sa, ea; - - pctx->drawn_objs++; - - /* degenerate case: r=0 means a single dot */ - if ((width == 0) && (height == 0)) { - pcb_line_draw(pctx, gc, cx, cy, cx, cy); - return; - } - - /* detect elliptical arcs: if diff between radii is above 0.1% */ - diff2 = width - height; - if (diff2 < 0) - diff2 = -diff2; - maxdiff = width; - if (height > maxdiff) - maxdiff = height; - if (diff2 > maxdiff / 1000) { - if (!gc->warned_elliptical) { - rnd_message(RND_MSG_ERROR, "Can't draw elliptical arc on svg; object omitted; expect BROKEN TRACE\n"); - gc->warned_elliptical = 1; - } - return; - } - - TRX(cx); TRY(cy); - - /* calculate start and end angles considering flip */ - start_angle = 180 - start_angle; - delta_angle = -delta_angle; - if (pctx->flip) { - start_angle = -start_angle; - delta_angle = -delta_angle; - } - - /* workaround for near-360 deg rendering bugs */ - if ((delta_angle >= +360.0) || (delta_angle <= -360.0)) { - rnd_svg_draw_arc(pctx, gc, cx, cy, width, height, 0, 180); - rnd_svg_draw_arc(pctx, gc, cx, cy, width, height, 180, 180); - return; - } - - if (fabs(delta_angle) <= 0.001) { delta_angle = 0.001; diff=1; } - - sa = start_angle; - ea = start_angle + delta_angle; - - /* calculate the endpoints */ - x2 = rnd_round((double)cx + ((double)width * cos(sa * M_PI / 180))); - y2 = rnd_round((double)cy + ((double)width * sin(sa * M_PI / 180))); - x1 = rnd_round((double)cx + ((double)width * cos(ea * M_PI / 180))+diff); - y1 = rnd_round((double)cy + ((double)width * sin(ea * M_PI / 180))+diff); - - pcb_arc_draw(pctx, gc, x1, y1, width, x2, y2, gc->width, (fabs(delta_angle) > 180), (delta_angle < 0.0)); -} - static void svg_draw_arc(rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t width, rnd_coord_t height, rnd_angle_t start_angle, rnd_angle_t delta_angle) { rnd_svg_draw_arc(pctx, gc, cx, cy, width, height, start_angle, delta_angle); } - -static void draw_fill_circle(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t r, rnd_coord_t stroke) -{ - const char *clip_color = svg_clip_color(gc); - - pctx->drawn_objs++; - - if (pctx->photo_mode) { - if (!pctx->drawing_hole) { - rnd_coord_t photo_offs = photo_palette[photo_color].offs; - if ((!gc->drill) && (photo_offs != 0)) { - indent(pctx, &pctx->sbright); - rnd_append_printf(&pctx->sbright, "\n", - cx-photo_offs, cy-photo_offs, r, stroke, photo_palette[photo_color].bright); - - indent(pctx, &pctx->sdark); - rnd_append_printf(&pctx->sdark, "\n", - cx+photo_offs, cy+photo_offs, r, stroke, photo_palette[photo_color].dark); - } - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - cx, cy, r, stroke, photo_palette[photo_color].normal); - } - else { - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - cx, cy, r, stroke, "#000000"); - } - } - else{ - indent(pctx, &pctx->snormal); - rnd_append_printf(&pctx->snormal, "\n", - cx, cy, r, stroke, svg_color(gc)); - } - if (clip_color != NULL) - rnd_append_printf(&pctx->sclip, "\n", - cx, cy, r, stroke, clip_color); -} - -void rnd_svg_fill_circle(rnd_svg_t *pctx, rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t radius) -{ - pctx->drawn_objs++; - TRX(cx); TRY(cy); - draw_fill_circle(pctx, gc, cx, cy, radius, 0); -} - static void svg_fill_circle(rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t radius) { rnd_svg_fill_circle(pctx, gc, cx, cy, radius); } -static void draw_poly(rnd_svg_t *pctx, gds_t *s, rnd_hid_gc_t gc, int n_coords, rnd_coord_t * x, rnd_coord_t * y, rnd_coord_t dx, rnd_coord_t dy, const char *clr) -{ - int i; - float poly_bloat = 0.01; - - indent(pctx, s); - gds_append_str(s, "\n", poly_bloat, clr, clr); -} - -void rnd_svg_fill_polygon_offs(rnd_svg_t *pctx, rnd_hid_gc_t gc, int n_coords, rnd_coord_t *x, rnd_coord_t *y, rnd_coord_t dx, rnd_coord_t dy) -{ - const char *clip_color = svg_clip_color(gc); - pctx->drawn_objs++; - if (pctx->photo_mode) { - rnd_coord_t photo_offs_x = photo_palette[photo_color].offs, photo_offs_y = photo_palette[photo_color].offs; - if (photo_offs_x != 0) { - if (pctx->flip) - photo_offs_y = -photo_offs_y; - draw_poly(pctx, &pctx->sbright, gc, n_coords, x, y, dx-photo_offs_x, dy-photo_offs_y, photo_palette[photo_color].bright); - draw_poly(pctx, &pctx->sdark, gc, n_coords, x, y, dx+photo_offs_x, dy+photo_offs_y, photo_palette[photo_color].dark); - } - draw_poly(pctx, &pctx->snormal, gc, n_coords, x, y, dx, dy, photo_palette[photo_color].normal); - } - else - draw_poly(pctx, &pctx->snormal, gc, n_coords, x, y, dx, dy, svg_color(gc)); - - if (clip_color != NULL) - draw_poly(pctx, &pctx->sclip, gc, n_coords, x, y, dx, dy, clip_color); -} - static void svg_fill_polygon_offs(rnd_hid_gc_t gc, int n_coords, rnd_coord_t *x, rnd_coord_t *y, rnd_coord_t dx, rnd_coord_t dy) { rnd_svg_fill_polygon_offs(pctx, gc, n_coords, x, y, dx, dy); @@ -1004,10 +403,6 @@ rnd_svg_fill_polygon_offs(pctx, gc, n_coords, x, y, 0, 0); } -void rnd_svg_set_crosshair(rnd_hid_t *hid, rnd_coord_t x, rnd_coord_t y, int a) -{ -} - static int svg_usage(rnd_hid_t *hid, const char *topic) { fprintf(stderr, "\nsvg exporter command line arguments:\n\n");