view ueda/uschem-print/printpage.c @ 139:bf188727e606

donl-rename-parts reader: no tEDAx-style escapes
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Sep 2020 04:25:11 +0000
parents cd92449fdb51
children
line wrap: on
line source

#include <sys/types.h>
#include <stdio.h>
#include <strings.h>
#include "../libuschem/schemstruct.h"
#include "../libuschem/graphsym.h"

extern FILE *reopen_schem_for_graphblocks();
extern char *get_compinst_attr();
extern char *pinname_to_pinnumber();

extern struct schem **schem_pages;
extern int npages;

struct schem *schem_being_printed;
FILE *schemfile_for_graphblocks;

static enum {LINEWIDTH_UNDEF, LINEWIDTH_NET, LINEWIDTH_BUS} pagelevel_linewidth;

print_schem_page(pageno)
	int pageno;	/* zero-based */
{
	register struct schem *schem;
	register struct schemobj *obj;

	schem = schem_pages[pageno];
	schem_being_printed = schem;
	schemfile_for_graphblocks = reopen_schem_for_graphblocks(schem);
	printf("%%%%Page: %s %d\n", schem->orig_filename, pageno + 1);
	puts("save $uschem begin");
	printf("/drawingsize_x %d def\n", schem->graph_xsize);
	printf("/drawingsize_y %d def\n", schem->graph_ysize);
	puts("setscale");
	pagelevel_linewidth = LINEWIDTH_UNDEF;
	reset_decor_font();
	for (obj = schem->obj_next; obj != (struct schemobj *) schem;
	     obj = obj->obj_next)
		print_schem_obj(obj);
	if (schemfile_for_graphblocks)
		fclose(schemfile_for_graphblocks);
	puts("end restore showpage");
	return(0);
}

print_schem_obj(obj)
	register struct schemobj *obj;
{
	switch (obj->obj_type) {
	case OBJTYPE_COMPINST:
		if (!obj->compobj_isgraph)
			return;
		/* FALL THRU */
	case OBJTYPE_GRAPHSYM:
		print_graph_compinst(obj);
		return;
	case OBJTYPE_GRAPHNET:
		if (pagelevel_linewidth != LINEWIDTH_NET) {
			puts("netlinewidth setlinewidth");
			pagelevel_linewidth = LINEWIDTH_NET;
		}
		print_graphnet(obj);
		print_obj_decors(obj);
		return;
	case OBJTYPE_NETLINE:
		if (pagelevel_linewidth != LINEWIDTH_NET) {
			puts("netlinewidth setlinewidth");
			pagelevel_linewidth = LINEWIDTH_NET;
		}
		printf("%d %d moveto %d %d lineto stroke\n", obj->lineobj_x1,
			obj->lineobj_y1, obj->lineobj_x2, obj->lineobj_y2);
		print_obj_decors(obj);
		return;
	case OBJTYPE_BUSSEG:
		if (pagelevel_linewidth != LINEWIDTH_BUS) {
			puts("buslinewidth setlinewidth");
			pagelevel_linewidth = LINEWIDTH_BUS;
		}
		printf("%d %d moveto %d %d lineto stroke\n", obj->lineobj_x1,
			obj->lineobj_y1, obj->lineobj_x2, obj->lineobj_y2);
		print_obj_decors(obj);
		return;
	case OBJTYPE_GRAPHBLOCK:
		print_graphblock(obj->graphblockobj_body);
		return;
	}
}

print_graph_compinst(obj)
	register struct schemobj *obj;
{
	register struct graphsym *gs;
	char *slot;

	gs = obj->compobj_graphsym;
	printf("save %d %d translate", obj->compobj_x, obj->compobj_y);
	if (obj->compobj_rotate)
		printf(" %d rotate", obj->compobj_rotate);
	putchar('\n');
	printf("/mirrored %s def\n", obj->compobj_mirror ? "true" : "false");
	if (gs->gs_varpins) {
		if (obj->obj_type != OBJTYPE_COMPINST) {
			fprintf(stderr,
"%s: line %d: symbol \"%s\" has variable pins; may not be used w/o component\n",
				schem_being_printed->orig_filename,
				obj->obj_lineno, gs->gs_name);
			exit(1);
		}
		slot = get_compinst_attr(obj, "slot");
		define_varpins(gs, obj->compobj_mclcomp, slot);
	}
	printf("symbols /%s get exec restore\n", gs->gs_name);
	print_obj_decors(obj);
}

define_varpins(gs, comp, slot)
	struct graphsym *gs;
	struct component *comp;
	char *slot;
{
	register struct graphsym_pindef *pin;
	register char *cp;

	puts("/pins [");
	for (pin = gs->gs_pins; pin; pin = pin->gspd_next)
		if (pin->gspd_pinnumber && !strcmp(pin->gspd_pinnumber, "%d")) {
			if (pin->gspd_pinname)
				cp = pinname_to_pinnumber(comp,
						pin->gspd_pinname, slot);
			else {
				fprintf(stderr,
			"Symbol %s: variable pin has no pinname attribute\n",
					gs->gs_name);
				cp = NULL;
			}
			putchar(' ');
			if (cp)
				emit_ps_string(cp);
			else {
				putchar('(');
				putchar(')');
			}
			putchar('\n');
		}
	puts("] def");
}

print_graphnet(obj)
	struct schemobj *obj;
{
	register struct netpoint *netpt;
	register int first;

	for (netpt = obj->netobj_points, first = 1; netpt;
	     netpt = netpt->netpt_next) {
		if (!netpt->netpt_coord_valid) {
			fprintf(stderr,
	"%s: line %d: GraphNet contains Pin w/o coordinates, not printed\n",
				schem_being_printed->orig_filename,
				obj->obj_lineno);
			puts("newpath");	/* kludge in lieu of abort */
			return;
		}
		printf("%d %d %s\n", netpt->netpt_x, netpt->netpt_y,
			first ? "moveto" : "lineto");
		first = 0;
	}
	puts("stroke");
	/* connection dots */
	for (netpt = obj->netobj_points, first = 1; netpt;
	     netpt = netpt->netpt_next, first = 0)
		switch (netpt->netpt_type) {
		case NETPT_TYPE_PIN:
		case NETPT_TYPE_PSEUDO:
			if (first || !netpt->netpt_next)
				continue;
			/* FALL THRU */
		case NETPT_TYPE_TJOIN:
			printf("%d %d conndot\n", netpt->netpt_x,
				netpt->netpt_y);
			continue;
		}
}

print_graphblock(blk)
	register struct graphblock *blk;
{
	puts("save");
	switch (blk->type) {
	case GRAPHBLOCK_TYPE_PS:
		write_graphblock_to_file(blk, schemfile_for_graphblocks,
						stdout);
		break;
	case GRAPHBLOCK_TYPE_GSCHEM:
		print_gschem_code_graphblk(schemfile_for_graphblocks, blk,
					schem_being_printed->orig_filename);
		break;
	default:
		fprintf(stderr,
	"Fatal internal error: unknown graphblock type %d (from %s line %d)\n",
			blk->type, schem_being_printed->orig_filename,
			blk->lineno);
		exit(1);
	}
	puts("restore");
}