2020-08-08 15:47:34 +02:00
|
|
|
/* File: psprint.c
|
2020-10-12 13:13:31 +02:00
|
|
|
*
|
2020-08-08 15:47:34 +02:00
|
|
|
* This file is part of XSCHEM,
|
2020-10-12 13:13:31 +02:00
|
|
|
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
|
2020-08-08 15:47:34 +02:00
|
|
|
* simulation.
|
2023-05-21 12:52:19 +02:00
|
|
|
* Copyright (C) 1998-2023 Stefan Frederik Schippers
|
2020-08-08 15:47:34 +02:00
|
|
|
*
|
|
|
|
|
* 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
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "xschem.h"
|
2020-10-15 17:39:21 +02:00
|
|
|
#define X_TO_PS(x) ( (x+xctx->xorigin)* xctx->mooz )
|
|
|
|
|
#define Y_TO_PS(y) ( (y+xctx->yorigin)* xctx->mooz )
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-01-07 04:33:19 +01:00
|
|
|
char *utf8_enc[]={
|
|
|
|
|
"/recodedict 24 dict def\n",
|
|
|
|
|
"/recode {recodedict begin /nco&na exch def\n",
|
|
|
|
|
"/nfnam exch def /basefontname exch def /basefontdict basefontname findfont def\n",
|
|
|
|
|
"/newfont basefontdict maxlength dict def basefontdict {exch dup /FID ne\n",
|
|
|
|
|
"{dup /Encoding eq {exch dup length array copy newfont 3 1 roll put} {exch\n",
|
|
|
|
|
"newfont 3 1 roll put} ifelse} {pop pop} ifelse } forall newfont\n",
|
|
|
|
|
"/FontName nfnam put nco&na aload pop nco&na length 2 idiv {newfont\n",
|
|
|
|
|
"/Encoding get 3 1 roll put} repeat nfnam newfont definefont pop end } def\n",
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
char *utf8[]={
|
|
|
|
|
"/chararr [\n",
|
|
|
|
|
/* 0xC2 2-byte characters */
|
|
|
|
|
" 161 /exclamdown\n", " 162 /cent\n", " 163 /sterling\n", " 164 /currency\n",
|
|
|
|
|
" 165 /yen\n", " 166 /bar\n", " 167 /section\n", " 168 /dieresis\n",
|
|
|
|
|
" 169 /copyright\n", " 170 /ordfeminine\n", " 171 /guillemotleft\n", " 172 /logicalnot\n",
|
|
|
|
|
" 173 /emdash\n", " 174 /registered\n", " 175 /macron\n", " 176 /degree\n",
|
|
|
|
|
" 177 /plusminus\n", " 178 /twosuperior\n", " 179 /threesuperior\n", " 180 /acute\n",
|
|
|
|
|
" 181 /mu\n", " 182 /paragraph\n", " 183 /periodcentered\n", " 184 /cedilla\n",
|
|
|
|
|
" 185 /onesuperior\n", " 186 /ordmasculine\n", " 187 /guillemotright\n", " 188 /onequarter\n",
|
|
|
|
|
" 189 /onehalf\n", " 190 /threequarters\n", " 191 /questiondown\n",
|
|
|
|
|
/* 0xC3 2-byte characters */
|
|
|
|
|
" 192 /Agrave\n", " 193 /Aacute\n", " 194 /Acircumflex\n", " 195 /Atilde\n",
|
|
|
|
|
" 196 /Adieresis\n", " 197 /Aring\n", " 198 /AE\n", " 199 /Ccedilla\n",
|
|
|
|
|
" 200 /Egrave\n", " 201 /Eacute\n", " 202 /Ecircumflex\n", " 203 /Edieresis\n",
|
|
|
|
|
" 204 /Igrave\n", " 205 /Iacute\n", " 206 /Icircumflex\n", " 207 /Idieresis\n",
|
|
|
|
|
" 208 /Eth\n", " 209 /Ntilde\n", " 210 /Ograve\n", " 211 /Oacute\n",
|
|
|
|
|
" 212 /Ocircumflex\n", " 213 /Otilde\n", " 214 /Odieresis\n", " 215 /multiply\n",
|
|
|
|
|
" 216 /Oslash\n", " 217 /Ugrave\n", " 218 /Uacute\n", " 219 /Ucircumflex\n",
|
|
|
|
|
" 220 /Udieresis\n", " 221 /Yacute\n", " 222 /Thorn\n", " 223 /germandbls\n",
|
|
|
|
|
" 224 /agrave\n", " 225 /aacute\n", " 226 /acircumflex\n", " 227 /atilde\n",
|
|
|
|
|
" 228 /adieresis\n", " 229 /aring\n", " 230 /ae\n", " 231 /ccedilla\n",
|
|
|
|
|
" 232 /egrave\n", " 233 /eacute\n", " 234 /ecircumflex\n", " 235 /edieresis\n",
|
|
|
|
|
" 236 /igrave\n", " 237 /iacute\n", " 238 /icircumflex\n", " 239 /idieresis\n",
|
|
|
|
|
" 240 /eth\n", " 241 /ntilde\n", " 242 /ograve\n", " 243 /oacute\n",
|
|
|
|
|
" 244 /ocircumflex\n", " 245 /otilde\n", " 246 /odieresis\n", " 247 /divide\n",
|
|
|
|
|
" 248 /oslash\n", " 249 /ugrave\n", " 250 /uacute\n", " 251 /ucircumflex\n",
|
|
|
|
|
" 252 /udieresis\n", " 253 /yacute\n", " 254 /thorn\n", " 255 /ydieresis\n",
|
|
|
|
|
" ] def\n"};
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
static FILE *fd;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
typedef struct {
|
2022-04-28 10:12:16 +02:00
|
|
|
unsigned int red;
|
|
|
|
|
unsigned int green;
|
|
|
|
|
unsigned int blue;
|
2020-08-08 15:47:34 +02:00
|
|
|
} Ps_color;
|
|
|
|
|
|
|
|
|
|
static Ps_color *ps_colors;
|
2021-01-07 04:33:19 +01:00
|
|
|
static char ps_font_name[80] = "Helvetica"; /* Courier Times Helvetica Symbol */
|
|
|
|
|
static char ps_font_family[80] = "Helvetica"; /* Courier Times Helvetica Symbol */
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2024-03-18 01:08:51 +01:00
|
|
|
int ps_embedded_image(xRect* r, double x1, double y1, double x2, double y2, int rot, int flip)
|
2023-01-16 05:34:43 +01:00
|
|
|
{
|
2023-04-09 15:36:06 +02:00
|
|
|
#if defined(HAS_LIBJPEG) && HAS_CAIRO==1
|
2024-03-18 01:08:51 +01:00
|
|
|
int i, jpg;
|
|
|
|
|
int size_x, size_y;
|
2024-03-18 11:53:51 +01:00
|
|
|
unsigned char *ptr = NULL;
|
2023-01-16 18:06:50 +01:00
|
|
|
int invertImage;
|
2023-01-23 03:35:10 +01:00
|
|
|
unsigned char* ascii85EncodedJpeg;
|
2024-03-18 01:08:51 +01:00
|
|
|
const char* attr;
|
|
|
|
|
cairo_surface_t *surface = NULL, *orig_sfc = NULL;
|
|
|
|
|
xEmb_image *emb_ptr;
|
2023-01-16 16:31:18 +01:00
|
|
|
unsigned char* jpgData = NULL;
|
|
|
|
|
size_t fileSize = 0;
|
2023-12-09 23:39:33 +01:00
|
|
|
int quality=40;
|
2023-01-18 04:09:30 +01:00
|
|
|
const char *quality_attr;
|
2024-03-18 01:08:51 +01:00
|
|
|
size_t oLength, attr_len;
|
|
|
|
|
cairo_t *ct;
|
2023-01-16 16:31:18 +01:00
|
|
|
|
2024-03-18 01:08:51 +01:00
|
|
|
invertImage = !strboolcmp(get_tok_value(r->prop_ptr, "InvertOnExport", 0), "true");
|
|
|
|
|
if(!invertImage)
|
|
|
|
|
invertImage = !strboolcmp(get_tok_value(r->prop_ptr, "ps_invert", 0), "true");
|
2023-01-18 04:09:30 +01:00
|
|
|
quality_attr = get_tok_value(r->prop_ptr, "jpeg_quality", 0);
|
|
|
|
|
if(quality_attr[0]) quality = atoi(quality_attr);
|
2023-01-20 18:25:43 +01:00
|
|
|
else {
|
|
|
|
|
quality_attr = get_tok_value(r->prop_ptr, "jpg_quality", 0);
|
|
|
|
|
if(quality_attr[0]) quality = atoi(quality_attr);
|
|
|
|
|
}
|
2024-03-18 01:08:51 +01:00
|
|
|
attr = get_tok_value(r->prop_ptr, "image_data", 0);
|
|
|
|
|
attr_len = strlen(attr);
|
|
|
|
|
if(attr_len > 5) {
|
|
|
|
|
if(!strncmp(attr, "/9j/", 4)) jpg = 1;
|
|
|
|
|
else if(!strncmp(attr, "iVBOR", 5)) jpg = 0;
|
|
|
|
|
else jpg = -1; /* some invalid data */
|
|
|
|
|
} else {
|
|
|
|
|
jpg = -1;
|
2023-01-16 19:33:59 +01:00
|
|
|
}
|
2024-03-18 01:08:51 +01:00
|
|
|
emb_ptr = r->extraptr;
|
|
|
|
|
if(jpg == -1 || !(emb_ptr && emb_ptr->image)) {
|
|
|
|
|
return 0;
|
2023-01-16 19:33:59 +01:00
|
|
|
}
|
2024-03-18 01:08:51 +01:00
|
|
|
orig_sfc = emb_ptr->image;
|
|
|
|
|
cairo_surface_flush(orig_sfc);
|
|
|
|
|
/* create a copy of image surface with no alpha */
|
|
|
|
|
size_x = cairo_image_surface_get_width(orig_sfc);
|
|
|
|
|
size_y = cairo_image_surface_get_height(orig_sfc);
|
|
|
|
|
surface = cairo_surface_create_similar_image(orig_sfc, CAIRO_FORMAT_RGB24, size_x, size_y);
|
|
|
|
|
ct = cairo_create(surface);
|
|
|
|
|
cairo_set_source_surface(ct, orig_sfc, 0, 0);
|
|
|
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_paint(ct);
|
|
|
|
|
cairo_destroy(ct);
|
2023-01-16 12:21:35 +01:00
|
|
|
|
2024-03-18 11:53:51 +01:00
|
|
|
ptr = cairo_image_surface_get_data(surface);
|
2023-01-16 12:21:35 +01:00
|
|
|
|
2024-03-18 01:08:51 +01:00
|
|
|
for (i = 0; i < (size_x * size_y * 4); i += 4)
|
2023-01-16 19:33:59 +01:00
|
|
|
{
|
2024-03-18 11:53:51 +01:00
|
|
|
unsigned char a = ptr[i + 3];
|
|
|
|
|
unsigned char r = ptr[i + 2];
|
|
|
|
|
unsigned char g = ptr[i + 1];
|
|
|
|
|
unsigned char b = ptr[i + 0];
|
|
|
|
|
/* invert colors */
|
2024-03-18 01:08:51 +01:00
|
|
|
if(invertImage) {
|
2024-03-18 11:53:51 +01:00
|
|
|
r = a - r;
|
|
|
|
|
g = a - g;
|
|
|
|
|
b = a - b;
|
2023-01-16 05:34:43 +01:00
|
|
|
}
|
2024-03-18 11:53:51 +01:00
|
|
|
/* blend with white, remove alpha */
|
|
|
|
|
r += (unsigned char)(0xff - a);
|
|
|
|
|
g += (unsigned char)(0xff - a);
|
|
|
|
|
b += (unsigned char)(0xff - a);
|
|
|
|
|
a = (unsigned char) 0xff;
|
|
|
|
|
/* write result back */
|
|
|
|
|
ptr[i + 3] = a;
|
|
|
|
|
ptr[i + 2] = r;
|
|
|
|
|
ptr[i + 1] = g;
|
|
|
|
|
ptr[i + 0] = b;
|
2023-01-16 19:33:59 +01:00
|
|
|
}
|
|
|
|
|
cairo_surface_mark_dirty(surface);
|
2024-03-18 01:08:51 +01:00
|
|
|
if(invertImage || jpg == 0) {
|
|
|
|
|
cairo_image_surface_write_to_jpeg_mem(surface, &jpgData, &fileSize, quality);
|
|
|
|
|
} else {
|
|
|
|
|
jpgData = base64_decode(attr, attr_len, &fileSize);
|
|
|
|
|
}
|
|
|
|
|
cairo_surface_destroy(surface);
|
2023-01-23 18:23:18 +01:00
|
|
|
ascii85EncodedJpeg = ascii85_encode(jpgData, fileSize, &oLength);
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "gsave\n");
|
|
|
|
|
fprintf(fd, "save\n");
|
|
|
|
|
fprintf(fd, "/RawData currentfile /ASCII85Decode filter def\n");
|
|
|
|
|
fprintf(fd, "/Data RawData << >> /DCTDecode filter def\n");
|
2023-01-16 19:33:59 +01:00
|
|
|
fprintf(fd, "%g %g translate\n", X_TO_PS(x1), Y_TO_PS(y1));
|
2023-01-16 19:54:39 +01:00
|
|
|
if(rot==1) fprintf(fd, "90 rotate\n");
|
|
|
|
|
if(rot==2) fprintf(fd, "180 rotate\n");
|
|
|
|
|
if(rot==3) fprintf(fd, "270 rotate\n");
|
|
|
|
|
fprintf(fd, "%g %g scale\n", (X_TO_PS(x2) - X_TO_PS(x1))*0.97, (Y_TO_PS(y2) - Y_TO_PS(y1))*0.97);
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "/DeviceRGB setcolorspace\n");
|
|
|
|
|
fprintf(fd, "{ << /ImageType 1\n");
|
2024-03-18 01:08:51 +01:00
|
|
|
fprintf(fd, " /Width %g\n", (double)size_x);
|
|
|
|
|
fprintf(fd, " /Height %g\n", (double)size_y);
|
2023-01-16 19:54:39 +01:00
|
|
|
|
|
|
|
|
if(!flip)
|
|
|
|
|
{
|
2023-01-23 11:49:08 +01:00
|
|
|
if(rot==1) fprintf(fd, " /ImageMatrix [%g 0 0 %g 0 %g]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
(double)size_y, (double)size_x, (double)size_y);
|
2023-01-23 11:49:08 +01:00
|
|
|
else if(rot==2) fprintf(fd, " /ImageMatrix [%g 0 0 %g %g %g]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
(double)size_x, (double)size_y, (double)size_x, (double)size_y);
|
2023-01-23 11:49:08 +01:00
|
|
|
else if(rot==3) fprintf(fd, " /ImageMatrix [%g 0 0 %g %g 0]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
(double)size_y, (double)size_x, (double)size_x);
|
|
|
|
|
else fprintf(fd, " /ImageMatrix [%g 0 0 %g 0 0]\n", (double)size_x, (double)size_y);
|
2023-01-16 19:54:39 +01:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2023-01-23 11:49:08 +01:00
|
|
|
if(rot==1) fprintf(fd, " /ImageMatrix [%g 0 0 %g %g %g]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
-(double)size_y, (double)size_x, (double)size_x, (double)size_y);
|
2023-01-23 11:49:08 +01:00
|
|
|
else if(rot==2) fprintf(fd, " /ImageMatrix [%g 0 0 %g 0 %g]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
-(double)size_x, (double)size_y, (double)size_y);
|
2023-01-23 11:49:08 +01:00
|
|
|
else if(rot==3) fprintf(fd, " /ImageMatrix [%g 0 0 %g 0 0]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
-(double)size_y, (double)size_x);
|
2023-01-23 11:49:08 +01:00
|
|
|
else fprintf(fd, " /ImageMatrix [%g 0 0 %g %g 0]\n",
|
2024-03-18 01:08:51 +01:00
|
|
|
-(double)size_x, (double)size_y, (double)size_x);
|
2023-01-16 19:54:39 +01:00
|
|
|
}
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, " /DataSource Data\n");
|
|
|
|
|
fprintf(fd, " /BitsPerComponent 8\n");
|
|
|
|
|
fprintf(fd, " /Decode [0 1 0 1 0 1]\n");
|
|
|
|
|
fprintf(fd, " >> image\n");
|
|
|
|
|
fprintf(fd, " Data closefile\n");
|
|
|
|
|
fprintf(fd, " RawData flushfile\n");
|
|
|
|
|
fprintf(fd, " restore\n");
|
|
|
|
|
fprintf(fd, "} exec\n");
|
|
|
|
|
|
2023-01-23 18:23:18 +01:00
|
|
|
#if 1 /* break lines */
|
2023-02-18 09:44:11 +01:00
|
|
|
for (i = 0; i < oLength; ++i)
|
2023-01-23 03:35:10 +01:00
|
|
|
{
|
|
|
|
|
fputc(ascii85EncodedJpeg[i],fd);
|
2023-01-23 18:23:18 +01:00
|
|
|
if(i > 0 && (i % 64) == 0)
|
2023-01-23 03:35:10 +01:00
|
|
|
{
|
|
|
|
|
fputc('\n',fd);
|
2023-01-23 11:49:08 +01:00
|
|
|
/* if (ascii85Encode[i+1]=='%') idx=63; imageMagic does this for some reason?!
|
|
|
|
|
* Doesn't seem to be necesary. */
|
2023-01-23 03:35:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-23 18:23:18 +01:00
|
|
|
#else
|
|
|
|
|
fprintf(fd, "%s", ascii85EncodedJpeg);
|
|
|
|
|
#endif
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "~>\n");
|
2023-01-16 19:54:39 +01:00
|
|
|
|
2023-01-16 19:33:59 +01:00
|
|
|
fprintf(fd, "grestore\n");
|
2023-02-09 21:06:27 +01:00
|
|
|
my_free(_ALLOC_ID_, &ascii85EncodedJpeg);
|
2023-01-16 16:31:18 +01:00
|
|
|
free(jpgData);
|
2023-01-23 03:51:38 +01:00
|
|
|
#endif
|
2024-03-18 01:08:51 +01:00
|
|
|
return 1;
|
2023-01-16 05:34:43 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ps_embedded_graph(xRect* r, double rx1, double ry1, double rx2, double ry2)
|
|
|
|
|
{
|
2023-04-09 15:36:06 +02:00
|
|
|
#if defined(HAS_LIBJPEG) && HAS_CAIRO==1
|
2023-12-11 10:43:09 +01:00
|
|
|
Zoom_info zi;
|
2023-01-16 13:51:35 +01:00
|
|
|
double rw, rh, scale;
|
|
|
|
|
cairo_surface_t* png_sfc;
|
2023-04-27 08:49:52 +02:00
|
|
|
int save, save_draw_window, save_draw_grid, rwi, rhi;
|
2023-12-11 16:06:49 +01:00
|
|
|
const double max_size = 3000.0;
|
2023-01-16 13:51:35 +01:00
|
|
|
int d_c;
|
2023-01-16 16:31:18 +01:00
|
|
|
unsigned char* jpgData = NULL;
|
|
|
|
|
size_t fileSize = 0;
|
|
|
|
|
/*
|
|
|
|
|
* FILE* fp;
|
|
|
|
|
* static char str[PATH_MAX];
|
|
|
|
|
*/
|
2023-01-23 03:35:10 +01:00
|
|
|
unsigned char *ascii85EncodedJpeg;
|
2023-12-09 23:39:33 +01:00
|
|
|
int quality=40;
|
2023-01-18 04:09:30 +01:00
|
|
|
const char *quality_attr;
|
2023-01-23 11:49:08 +01:00
|
|
|
size_t oLength;
|
2023-01-23 18:23:18 +01:00
|
|
|
int i;
|
2023-01-18 04:09:30 +01:00
|
|
|
|
|
|
|
|
quality_attr = get_tok_value(r->prop_ptr, "jpeg_quality", 0);
|
|
|
|
|
if(quality_attr[0]) quality = atoi(quality_attr);
|
2023-01-20 18:25:43 +01:00
|
|
|
else {
|
|
|
|
|
quality_attr = get_tok_value(r->prop_ptr, "jpg_quality", 0);
|
|
|
|
|
if(quality_attr[0]) quality = atoi(quality_attr);
|
|
|
|
|
}
|
|
|
|
|
if(quality_attr[0]) quality = atoi(quality_attr);
|
2023-01-16 13:51:35 +01:00
|
|
|
if (!has_x) return;
|
|
|
|
|
rw = fabs(rx2 - rx1);
|
|
|
|
|
rh = fabs(ry2 - ry1);
|
2023-12-09 23:39:33 +01:00
|
|
|
scale = 3.0;
|
2023-01-16 13:51:35 +01:00
|
|
|
if (rw > rh && rw > max_size) {
|
|
|
|
|
scale = max_size / rw;
|
|
|
|
|
}
|
|
|
|
|
else if (rh > max_size) {
|
|
|
|
|
scale = max_size / rh;
|
|
|
|
|
}
|
|
|
|
|
rwi = (int)(rw * scale + 1.0);
|
|
|
|
|
rhi = (int)(rh * scale + 1.0);
|
2023-12-09 23:39:33 +01:00
|
|
|
dbg(1, "graph size: %dx%d\n", rwi, rhi);
|
2023-12-11 10:43:09 +01:00
|
|
|
save_restore_zoom(1, &zi);
|
2023-01-20 13:25:23 +01:00
|
|
|
set_viewport_size(rwi, rhi, xctx->lw);
|
2023-12-11 10:43:09 +01:00
|
|
|
|
|
|
|
|
/* zoom_box(rx1 - xctx->lw, ry1 - xctx->lw, rx2 + xctx->lw, ry2 + xctx->lw, 1.0); */
|
|
|
|
|
|
|
|
|
|
xctx->xorigin = -rx1;
|
|
|
|
|
xctx->yorigin = -ry1;
|
|
|
|
|
xctx->zoom=(rx2-rx1)/(rwi - 1);
|
|
|
|
|
xctx->mooz = 1 / xctx->zoom;
|
|
|
|
|
|
2023-01-16 13:51:35 +01:00
|
|
|
resetwin(1, 1, 1, rwi, rhi);
|
2023-07-13 13:24:17 +02:00
|
|
|
dbg(1, "lw=%g\n", xctx->lw);
|
2023-01-16 13:51:35 +01:00
|
|
|
save_draw_grid = tclgetboolvar("draw_grid");
|
|
|
|
|
tclsetvar("draw_grid", "0");
|
|
|
|
|
save_draw_window = xctx->draw_window;
|
|
|
|
|
xctx->draw_window = 0;
|
|
|
|
|
xctx->draw_pixmap = 1;
|
2023-04-27 08:49:52 +02:00
|
|
|
save = xctx->do_copy_area;
|
2023-01-16 13:51:35 +01:00
|
|
|
xctx->do_copy_area = 0;
|
|
|
|
|
d_c = tclgetboolvar("dark_colorscheme");
|
|
|
|
|
tclsetboolvar("dark_colorscheme", 0);
|
|
|
|
|
build_colors(0, 0);
|
|
|
|
|
draw();
|
2023-12-11 10:43:09 +01:00
|
|
|
dbg(1, "width=%d, rwi=%d height=%d rhi=%d\n", xctx->xrect[0].width, rwi, xctx->xrect[0].height, rhi);
|
2023-01-16 13:51:35 +01:00
|
|
|
#ifdef __unix__
|
|
|
|
|
png_sfc = cairo_xlib_surface_create(display, xctx->save_pixmap, visual,
|
2024-03-12 18:21:28 +01:00
|
|
|
xctx->xrect[0].width, xctx->xrect[0].height);
|
2023-01-16 13:51:35 +01:00
|
|
|
#else
|
|
|
|
|
/* pixmap doesn't work on windows
|
|
|
|
|
Copy from cairo_save_sfc and use cairo
|
|
|
|
|
to draw in the data points to embed the graph */
|
|
|
|
|
png_sfc = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, xctx->xrect[0].width, xctx->xrect[0].height);
|
|
|
|
|
cairo_t* ct = cairo_create(png_sfc);
|
|
|
|
|
cairo_set_source_surface(ct, xctx->cairo_save_sfc, 0, 0);
|
|
|
|
|
cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
|
|
|
|
|
cairo_paint(ct);
|
2023-02-18 09:44:11 +01:00
|
|
|
for (i = 0; i < xctx->rects[GRIDLAYER]; ++i) {
|
2023-01-16 13:51:35 +01:00
|
|
|
xRect* r2 = &xctx->rect[GRIDLAYER][i];
|
|
|
|
|
if (r2->flags & 1) {
|
2023-02-26 11:22:19 +01:00
|
|
|
setup_graph_data(i, 0, &xctx->graph_struct);
|
2023-01-16 13:51:35 +01:00
|
|
|
draw_graph(i, 8, &xctx->graph_struct, (void*)ct);
|
2023-01-16 05:34:43 +01:00
|
|
|
}
|
2023-01-16 13:51:35 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
2023-01-18 04:09:30 +01:00
|
|
|
cairo_image_surface_write_to_jpeg_mem(png_sfc, &jpgData, &fileSize, quality);
|
2023-01-16 13:51:35 +01:00
|
|
|
|
2023-01-23 18:23:18 +01:00
|
|
|
ascii85EncodedJpeg = ascii85_encode(jpgData, fileSize, &oLength);
|
2023-01-17 01:23:34 +01:00
|
|
|
free(jpgData);
|
2023-01-16 13:51:35 +01:00
|
|
|
|
|
|
|
|
cairo_surface_destroy(png_sfc);
|
|
|
|
|
xctx->draw_pixmap = 1;
|
|
|
|
|
tclsetboolvar("draw_grid", save_draw_grid);
|
2023-12-11 10:43:09 +01:00
|
|
|
save_restore_zoom(0, &zi);
|
2023-12-11 15:18:46 +01:00
|
|
|
resetwin(1, 1, 1, xctx->xrect[0].width, xctx->xrect[0].height);
|
2023-07-13 13:24:17 +02:00
|
|
|
change_linewidth(xctx->lw);
|
2023-01-16 05:34:43 +01:00
|
|
|
tclsetboolvar("dark_colorscheme", d_c);
|
|
|
|
|
build_colors(0, 0);
|
|
|
|
|
draw();
|
2023-07-13 13:24:17 +02:00
|
|
|
xctx->do_copy_area = save;
|
|
|
|
|
xctx->draw_window = save_draw_window;
|
2023-01-16 13:51:35 +01:00
|
|
|
fprintf(fd, "gsave\n");
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "save\n");
|
|
|
|
|
fprintf(fd, "/RawData currentfile /ASCII85Decode filter def\n");
|
|
|
|
|
fprintf(fd, "/Data RawData << >> /DCTDecode filter def\n");
|
2023-01-16 13:51:35 +01:00
|
|
|
fprintf(fd, "%f %f translate\n", X_TO_PS(rx1), Y_TO_PS(ry1));
|
|
|
|
|
fprintf(fd, "%f %f scale\n", X_TO_PS(rx2) - X_TO_PS(rx1), Y_TO_PS(ry2) - Y_TO_PS(ry1));
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "/DeviceRGB setcolorspace\n");
|
|
|
|
|
fprintf(fd, "{ << /ImageType 1\n");
|
|
|
|
|
fprintf(fd, " /Width %d\n", rwi);
|
|
|
|
|
fprintf(fd, " /Height %d\n", rhi);
|
|
|
|
|
fprintf(fd, " /ImageMatrix [%d 0 0 %d 0 0]\n", rwi, rhi);
|
|
|
|
|
fprintf(fd, " /DataSource Data\n");
|
|
|
|
|
fprintf(fd, " /BitsPerComponent 8\n");
|
|
|
|
|
fprintf(fd, " /Decode [0 1 0 1 0 1]\n");
|
|
|
|
|
fprintf(fd, " >> image\n");
|
|
|
|
|
fprintf(fd, " Data closefile\n");
|
|
|
|
|
fprintf(fd, " RawData flushfile\n");
|
|
|
|
|
fprintf(fd, " restore\n");
|
|
|
|
|
fprintf(fd, "} exec\n");
|
|
|
|
|
|
2023-01-23 18:23:18 +01:00
|
|
|
#if 1 /* break lines */
|
2023-02-18 09:44:11 +01:00
|
|
|
for (i = 0; i < oLength; ++i)
|
2023-01-23 03:35:10 +01:00
|
|
|
{
|
|
|
|
|
fputc(ascii85EncodedJpeg[i],fd);
|
2023-01-23 18:23:18 +01:00
|
|
|
if(i > 0 && (i % 64) == 0)
|
2023-01-23 03:35:10 +01:00
|
|
|
{
|
|
|
|
|
fputc('\n',fd);
|
2023-01-23 11:49:08 +01:00
|
|
|
/* if (ascii85Encode[i+1]=='%') idx=63; imageMagic does this for some reason?!
|
|
|
|
|
* Doesn't seem to be necesary. */
|
2023-01-23 03:35:10 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-01-23 18:23:18 +01:00
|
|
|
#else
|
|
|
|
|
fprintf(fd, "%s", ascii85EncodedJpeg);
|
|
|
|
|
#endif
|
2023-01-23 03:35:10 +01:00
|
|
|
fprintf(fd, "~>\n");
|
|
|
|
|
|
2023-01-16 13:51:35 +01:00
|
|
|
fprintf(fd, "grestore\n");
|
2023-01-23 03:35:10 +01:00
|
|
|
|
2023-02-09 21:06:27 +01:00
|
|
|
my_free(_ALLOC_ID_, &ascii85EncodedJpeg);
|
2023-01-23 03:44:58 +01:00
|
|
|
|
2023-01-16 13:51:35 +01:00
|
|
|
#endif
|
2023-01-16 05:34:43 +01:00
|
|
|
}
|
2020-12-16 18:30:33 +01:00
|
|
|
static void set_lw(void)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-17 00:53:19 +02:00
|
|
|
if(xctx->lw==0.0)
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g setlinewidth\n",0.5);
|
2020-08-08 15:47:34 +02:00
|
|
|
else
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g setlinewidth\n",xctx->lw/1.2);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void set_ps_colors(unsigned int pixel)
|
|
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2023-04-27 00:36:50 +02:00
|
|
|
dbg(1, "set_ps_colors(): setting color %u\n", pixel);
|
2020-12-16 18:56:38 +01:00
|
|
|
if(color_ps) fprintf(fd, "%g %g %g RGB\n",
|
2023-01-16 18:06:50 +01:00
|
|
|
(double)ps_colors[pixel].red/256.0, (double)ps_colors[pixel].green/256.0,
|
|
|
|
|
(double)ps_colors[pixel].blue/256.0);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps_xdrawarc(int layer, int fillarc, double x, double y, double r, double a, double b)
|
|
|
|
|
{
|
2022-08-28 23:50:57 +02:00
|
|
|
if(xctx->fill_pattern && xctx->fill_type[layer] && fillarc)
|
2023-04-26 23:00:20 +02:00
|
|
|
fprintf(fd, "%g %g MT %g %g %g %g %g A %g %g LT C F S\n",
|
|
|
|
|
x, y, x, y, r, -a, -a-b, x, y);
|
2020-08-08 15:47:34 +02:00
|
|
|
else
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g %g %g %g %g A S\n", x, y, r, -a, -a-b);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
static void ps_xdrawline(int layer, double x1, double y1, double x2,
|
2020-08-08 15:47:34 +02:00
|
|
|
double y2)
|
|
|
|
|
{
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%.6g %.6g %.6g %.6g L\n", x2, y2, x1, y1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps_xdrawpoint(int layer, double x1, double y1)
|
|
|
|
|
{
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g %g %g %g L\n", x1, y1,x1,y1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps_xfillrectange(int layer, double x1, double y1, double x2,
|
2022-10-29 23:49:00 +02:00
|
|
|
double y2, int fill)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g %g %g %g R\n", x1,y1,x2-x1,y2-y1);
|
2022-10-29 23:49:00 +02:00
|
|
|
if(fill && (xctx->fill_type[layer] == 1) && xctx->fill_pattern) {
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g %g %g %g RF\n", x1,y1,x2-x1,y2-y1);
|
2020-08-08 15:47:34 +02:00
|
|
|
/* fprintf(fd,"fill\n"); */
|
|
|
|
|
}
|
|
|
|
|
/*fprintf(fd,"stroke\n"); */
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-01 17:23:49 +01:00
|
|
|
static void ps_drawbezier(double *x, double *y, int points)
|
|
|
|
|
{
|
|
|
|
|
const double bez_steps = 1.0/32.0; /* divide the t = [0,1] interval into 32 steps */
|
|
|
|
|
int b, i;
|
|
|
|
|
double t;
|
|
|
|
|
double xp, yp;
|
|
|
|
|
double x0, x1, x2, y0, y1, y2;
|
|
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
|
for(b = 0; b < points - 2; b++) {
|
|
|
|
|
if(points == 3) { /* 3 points: only one bezier */
|
|
|
|
|
x0 = x[0];
|
|
|
|
|
y0 = y[0];
|
|
|
|
|
x1 = x[1];
|
|
|
|
|
y1 = y[1];
|
|
|
|
|
x2 = x[2];
|
|
|
|
|
y2 = y[2];
|
|
|
|
|
} else if(b == points - 3) { /* last bezier */
|
|
|
|
|
x0 = (x[points - 3] + x[points - 2]) / 2.0;
|
|
|
|
|
y0 = (y[points - 3] + y[points - 2]) / 2.0;
|
|
|
|
|
x1 = x[points - 2];
|
|
|
|
|
y1 = y[points - 2];
|
|
|
|
|
x2 = x[points - 1];
|
|
|
|
|
y2 = y[points - 1];
|
|
|
|
|
} else if(b == 0) { /* first bezier */
|
|
|
|
|
x0 = x[0];
|
|
|
|
|
y0 = y[0];
|
|
|
|
|
x1 = x[1];
|
|
|
|
|
y1 = y[1];
|
|
|
|
|
x2 = (x[1] + x[2]) / 2.0;
|
|
|
|
|
y2 = (y[1] + y[2]) / 2.0;
|
|
|
|
|
} else { /* beziers in the middle */
|
|
|
|
|
x0 = (x[b] + x[b + 1]) / 2.0;
|
|
|
|
|
y0 = (y[b] + y[b + 1]) / 2.0;
|
|
|
|
|
x1 = x[b + 1];
|
|
|
|
|
y1 = y[b + 1];
|
|
|
|
|
x2 = (x[b + 1] + x[b + 2]) / 2.0;
|
|
|
|
|
y2 = (y[b + 1] + y[b + 2]) / 2.0;
|
|
|
|
|
}
|
|
|
|
|
for(t = 0; t <= 1.0; t += bez_steps) {
|
|
|
|
|
xp = (1 - t) * (1 - t) * x0 + 2 * (1 - t) * t * x1 + t * t * x2;
|
|
|
|
|
yp = (1 - t) * (1 - t) * y0 + 2 * (1 - t) * t * y1 + t * t * y2;
|
|
|
|
|
if(i==0) fprintf(fd, "NP\n%g %g MT\n", X_TO_PS(xp), Y_TO_PS(yp));
|
|
|
|
|
else fprintf(fd, "%g %g LT\n", X_TO_PS(xp), Y_TO_PS(yp));
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* Convex Nonconvex Complex */
|
|
|
|
|
#define Polygontype Nonconvex
|
2024-03-01 17:23:49 +01:00
|
|
|
static void ps_drawpolygon(int c, int what, double *x, double *y, int points, int poly_fill, int dash, int flags)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
double x1,y1,x2,y2;
|
|
|
|
|
double xx, yy;
|
2020-09-03 10:05:48 +02:00
|
|
|
double psdash;
|
2024-03-01 17:23:49 +01:00
|
|
|
int i, bezier;
|
2020-08-08 15:47:34 +02:00
|
|
|
polygon_bbox(x, y, points, &x1,&y1,&x2,&y2);
|
|
|
|
|
x1=X_TO_PS(x1);
|
|
|
|
|
y1=Y_TO_PS(y1);
|
|
|
|
|
x2=X_TO_PS(x2);
|
|
|
|
|
y2=Y_TO_PS(y2);
|
2020-12-02 15:10:47 +01:00
|
|
|
if( !rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) ) {
|
2020-08-08 15:47:34 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
psdash = dash / xctx->zoom;
|
2020-09-03 10:05:48 +02:00
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
|
|
|
|
|
}
|
2024-03-01 17:23:49 +01:00
|
|
|
bezier = flags && (points > 2);
|
|
|
|
|
if(bezier) {
|
|
|
|
|
ps_drawbezier(x, y, points);
|
|
|
|
|
} else {
|
|
|
|
|
for(i=0;i<points; ++i) {
|
|
|
|
|
xx = X_TO_PS(x[i]);
|
|
|
|
|
yy = Y_TO_PS(y[i]);
|
|
|
|
|
if(i==0) fprintf(fd, "NP\n%g %g MT\n", xx, yy);
|
|
|
|
|
else fprintf(fd, "%g %g LT\n", xx, yy);
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-11-16 22:28:10 +01:00
|
|
|
if(xctx->fill_pattern && xctx->fill_type[c] && poly_fill) {
|
2023-04-26 23:00:20 +02:00
|
|
|
fprintf(fd, "GS C F GR S\n");
|
2020-09-03 10:05:48 +02:00
|
|
|
} else {
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "S\n");
|
2020-09-03 10:05:48 +02:00
|
|
|
}
|
|
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[] 0 setdash\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-10-29 23:49:00 +02:00
|
|
|
static void ps_filledrect(int gc, double rectx1,double recty1,double rectx2,double recty2, int dash, int fill)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-07-13 13:24:17 +02:00
|
|
|
double x1,y1,x2,y2, tmp;
|
2020-09-03 10:05:48 +02:00
|
|
|
double psdash;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
x1=X_TO_PS(rectx1);
|
|
|
|
|
y1=Y_TO_PS(recty1);
|
|
|
|
|
x2=X_TO_PS(rectx2);
|
|
|
|
|
y2=Y_TO_PS(recty2);
|
2023-07-13 13:24:17 +02:00
|
|
|
if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&tmp,&tmp,&tmp,&tmp) )
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
psdash = dash / xctx->zoom;
|
2020-09-03 10:05:48 +02:00
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
|
|
|
|
|
}
|
2022-10-29 23:49:00 +02:00
|
|
|
ps_xfillrectange(gc, x1,y1,x2,y2, fill);
|
2020-09-03 10:05:48 +02:00
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[] 0 setdash\n");
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-03 10:05:48 +02:00
|
|
|
static void ps_drawarc(int gc, int fillarc, double x,double y,double r,double a, double b, int dash)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
double xx,yy,rr;
|
|
|
|
|
double x1, y1, x2, y2;
|
2020-09-03 10:05:48 +02:00
|
|
|
double psdash;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
xx=X_TO_PS(x);
|
|
|
|
|
yy=Y_TO_PS(y);
|
2020-10-15 17:39:21 +02:00
|
|
|
rr=r*xctx->mooz;
|
2020-08-08 15:47:34 +02:00
|
|
|
arc_bbox(x, y, r, a, b, &x1,&y1,&x2,&y2);
|
|
|
|
|
x1=X_TO_PS(x1);
|
|
|
|
|
y1=Y_TO_PS(y1);
|
|
|
|
|
x2=X_TO_PS(x2);
|
|
|
|
|
y2=Y_TO_PS(y2);
|
|
|
|
|
|
2020-12-02 15:10:47 +01:00
|
|
|
if( rectclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,&x1,&y1,&x2,&y2) )
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
psdash = dash / xctx->zoom;
|
2020-09-03 10:05:48 +02:00
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
|
|
|
|
|
}
|
|
|
|
|
ps_xdrawarc(gc, fillarc, xx, yy, rr, a, b);
|
|
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[] 0 setdash\n");
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-09-03 10:05:48 +02:00
|
|
|
static void ps_drawline(int gc, double linex1,double liney1,double linex2,double liney2, int dash)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
double x1,y1,x2,y2;
|
2020-09-03 10:05:48 +02:00
|
|
|
double psdash;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
x1=X_TO_PS(linex1);
|
|
|
|
|
y1=Y_TO_PS(liney1);
|
|
|
|
|
x2=X_TO_PS(linex2);
|
|
|
|
|
y2=Y_TO_PS(liney2);
|
|
|
|
|
if( clip(&x1,&y1,&x2,&y2) )
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
psdash = dash / xctx->zoom;
|
2020-09-03 10:05:48 +02:00
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[%g %g] 0 setdash\n", psdash, psdash);
|
|
|
|
|
}
|
|
|
|
|
ps_xdrawline(gc, x1, y1, x2, y2);
|
|
|
|
|
if(dash) {
|
|
|
|
|
fprintf(fd, "[] 0 setdash\n");
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-16 18:30:33 +01:00
|
|
|
|
|
|
|
|
|
2020-12-23 05:07:39 +01:00
|
|
|
static void ps_draw_string_line(int layer, char *s, double x, double y, double size,
|
|
|
|
|
short rot, short flip, int lineno, double fontheight, double fontascent,
|
2022-04-28 00:00:51 +02:00
|
|
|
double fontdescent, int llength, int no_of_lines, double longest_line)
|
2020-12-16 18:30:33 +01:00
|
|
|
{
|
|
|
|
|
double ix, iy;
|
|
|
|
|
short rot1;
|
2022-04-27 13:18:45 +02:00
|
|
|
unsigned char c, offset;
|
|
|
|
|
double line_delta;
|
2020-12-16 18:30:33 +01:00
|
|
|
double lines;
|
2023-04-27 00:36:50 +02:00
|
|
|
dbg(1, "ps_draw_string_line(): drawing |%s| on layer %d\n", s, layer);
|
2020-12-16 18:30:33 +01:00
|
|
|
if(s==NULL) return;
|
|
|
|
|
if(llength==0) return;
|
2023-04-27 00:36:50 +02:00
|
|
|
fprintf(fd, "GS\n");
|
|
|
|
|
set_ps_colors(layer);
|
2020-12-16 18:30:33 +01:00
|
|
|
|
|
|
|
|
line_delta = lineno*fontheight;
|
2020-12-23 05:07:39 +01:00
|
|
|
lines = (no_of_lines-1)*fontheight;
|
2020-12-16 18:30:33 +01:00
|
|
|
|
|
|
|
|
ix=X_TO_PS(x);
|
|
|
|
|
iy=Y_TO_PS(y);
|
|
|
|
|
if(rot&1) {
|
|
|
|
|
rot1=3;
|
|
|
|
|
} else rot1=0;
|
|
|
|
|
|
|
|
|
|
if( rot==0 && flip==0) {iy+=line_delta+fontascent;}
|
|
|
|
|
else if(rot==1 && flip==0) {ix=ix-fontheight+fontascent-lines+line_delta;}
|
|
|
|
|
else if(rot==2 && flip==0) {iy=iy-fontheight-lines+line_delta+fontascent;}
|
|
|
|
|
else if(rot==3 && flip==0) {ix+=line_delta+fontascent;}
|
|
|
|
|
else if(rot==0 && flip==1) {iy+=line_delta+fontascent;}
|
|
|
|
|
else if(rot==1 && flip==1) {ix=ix-fontheight+line_delta-lines+fontascent;}
|
|
|
|
|
else if(rot==2 && flip==1) {iy=iy-fontheight-lines+line_delta+fontascent;}
|
|
|
|
|
else if(rot==3 && flip==1) {ix+=line_delta+fontascent;}
|
|
|
|
|
|
2021-01-07 04:33:19 +01:00
|
|
|
fprintf(fd, "/%s", ps_font_family);
|
|
|
|
|
fprintf(fd, " FF\n");
|
2020-12-16 18:30:33 +01:00
|
|
|
fprintf(fd, "%g SCF\n", size * xctx->mooz);
|
|
|
|
|
fprintf(fd, "SF\n");
|
|
|
|
|
fprintf(fd, "NP\n");
|
|
|
|
|
fprintf(fd, "%g %g MT\n", ix, iy);
|
|
|
|
|
if(rot1) fprintf(fd, "%d rotate\n", rot1*90);
|
|
|
|
|
fprintf(fd, "1 -1 scale\n");
|
2020-12-17 02:49:37 +01:00
|
|
|
fprintf(fd, "(");
|
2021-01-07 04:33:19 +01:00
|
|
|
offset = 0;
|
|
|
|
|
while( (c = (unsigned char) *s) ) {
|
|
|
|
|
if(c > 127) {
|
|
|
|
|
if(c == 195) {offset = 64;s++; continue;}
|
|
|
|
|
if(c == 194) {s++; continue;}
|
|
|
|
|
fprintf(fd, "\\%03o", c + offset);
|
|
|
|
|
offset = 0;
|
|
|
|
|
} else
|
|
|
|
|
switch(c) {
|
2020-12-17 02:49:37 +01:00
|
|
|
case '(':
|
|
|
|
|
fputs("\\(", fd);
|
|
|
|
|
break;
|
|
|
|
|
case ')':
|
|
|
|
|
fputs("\\)", fd);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2021-01-07 04:33:19 +01:00
|
|
|
fputc(c, fd);
|
2020-12-17 02:49:37 +01:00
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
++s;
|
2020-12-17 02:49:37 +01:00
|
|
|
}
|
|
|
|
|
fprintf(fd, ")\n");
|
2020-12-16 18:30:33 +01:00
|
|
|
if (rot==1 && flip==0) {fprintf(fd, "dup SW pop neg 0 RMT\n");}
|
|
|
|
|
else if(rot==2 && flip==0) {fprintf(fd, "dup SW pop neg 0 RMT\n");}
|
|
|
|
|
else if(rot==0 && flip==1) {fprintf(fd, "dup SW pop neg 0 RMT\n");}
|
|
|
|
|
else if(rot==3 && flip==1) {fprintf(fd, "dup SW pop neg 0 RMT\n");}
|
|
|
|
|
|
|
|
|
|
fprintf(fd, "show\n");
|
|
|
|
|
fprintf(fd, "GR\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ps_draw_string(int layer, const char *str, short rot, short flip, int hcenter, int vcenter,
|
|
|
|
|
double x,double y, double xscale, double yscale)
|
|
|
|
|
{
|
|
|
|
|
char *tt, *ss, *sss=NULL;
|
|
|
|
|
double textx1,textx2,texty1,texty2;
|
|
|
|
|
char c;
|
|
|
|
|
int lineno=0;
|
|
|
|
|
double size, height, ascent, descent;
|
2022-04-28 00:00:51 +02:00
|
|
|
int llength=0, no_of_lines;
|
|
|
|
|
double longest_line;
|
2020-12-23 05:07:39 +01:00
|
|
|
|
2022-01-19 10:44:15 +01:00
|
|
|
if(str==NULL) return;
|
2024-03-24 19:59:28 +01:00
|
|
|
size = xscale*53. * cairo_font_scale;
|
2020-12-16 18:30:33 +01:00
|
|
|
height = size*xctx->mooz * 1.147; /* was 1.147 */
|
|
|
|
|
ascent = size*xctx->mooz * 0.808; /* was 0.908 */
|
|
|
|
|
descent = size*xctx->mooz * 0.219; /* was 0.219 */
|
|
|
|
|
|
2024-03-12 03:04:10 +01:00
|
|
|
text_bbox(str, xscale, yscale, rot, flip, hcenter, vcenter,
|
|
|
|
|
x,y, &textx1,&texty1,&textx2,&texty2, &no_of_lines, &longest_line);
|
2022-01-19 10:44:15 +01:00
|
|
|
|
2020-12-23 05:07:39 +01:00
|
|
|
if(!textclip(xctx->areax1,xctx->areay1,xctx->areax2,
|
|
|
|
|
xctx->areay2,textx1,texty1,textx2,texty2)) {
|
2020-12-16 18:30:33 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(hcenter) {
|
|
|
|
|
if(rot == 0 && flip == 0 ) { x=textx1;}
|
|
|
|
|
if(rot == 1 && flip == 0 ) { y=texty1;}
|
|
|
|
|
if(rot == 2 && flip == 0 ) { x=textx2;}
|
|
|
|
|
if(rot == 3 && flip == 0 ) { y=texty2;}
|
|
|
|
|
if(rot == 0 && flip == 1 ) { x=textx2;}
|
|
|
|
|
if(rot == 1 && flip == 1 ) { y=texty2;}
|
|
|
|
|
if(rot == 2 && flip == 1 ) { x=textx1;}
|
|
|
|
|
if(rot == 3 && flip == 1 ) { y=texty1;}
|
|
|
|
|
}
|
|
|
|
|
if(vcenter) {
|
|
|
|
|
if(rot == 0 && flip == 0 ) { y=texty1;}
|
|
|
|
|
if(rot == 1 && flip == 0 ) { x=textx2;}
|
|
|
|
|
if(rot == 2 && flip == 0 ) { y=texty2;}
|
|
|
|
|
if(rot == 3 && flip == 0 ) { x=textx1;}
|
|
|
|
|
if(rot == 0 && flip == 1 ) { y=texty1;}
|
|
|
|
|
if(rot == 1 && flip == 1 ) { x=textx2;}
|
|
|
|
|
if(rot == 2 && flip == 1 ) { y=texty2;}
|
|
|
|
|
if(rot == 3 && flip == 1 ) { x=textx1;}
|
|
|
|
|
}
|
|
|
|
|
llength=0;
|
2023-02-09 21:06:27 +01:00
|
|
|
my_strdup2(_ALLOC_ID_, &sss, str);
|
2020-12-16 18:30:33 +01:00
|
|
|
tt=ss=sss;
|
|
|
|
|
for(;;) {
|
|
|
|
|
c=*ss;
|
|
|
|
|
if(c=='\n' || c==0) {
|
|
|
|
|
*ss='\0';
|
2020-12-23 05:07:39 +01:00
|
|
|
ps_draw_string_line(layer, tt, x, y, size, rot, flip, lineno,
|
|
|
|
|
height, ascent, descent, llength, no_of_lines, longest_line);
|
2023-02-18 09:44:11 +01:00
|
|
|
++lineno;
|
2020-12-16 18:30:33 +01:00
|
|
|
if(c==0) break;
|
|
|
|
|
*ss='\n';
|
|
|
|
|
tt=ss+1;
|
|
|
|
|
llength=0;
|
|
|
|
|
} else {
|
2023-02-18 09:44:11 +01:00
|
|
|
++llength;
|
2020-12-16 18:30:33 +01:00
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
++ss;
|
2020-12-16 18:30:33 +01:00
|
|
|
}
|
2023-02-09 21:06:27 +01:00
|
|
|
my_free(_ALLOC_ID_, &sss);
|
2020-12-16 18:30:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void old_ps_draw_string(int gctext, const char *str,
|
2020-12-05 03:16:01 +01:00
|
|
|
short rot, short flip, int hcenter, int vcenter,
|
2020-08-08 15:47:34 +02:00
|
|
|
double x1,double y1,
|
2020-10-12 13:13:31 +02:00
|
|
|
double xscale, double yscale)
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
double a,yy,curr_x1,curr_y1,curr_x2,curr_y2,rx1,rx2,ry1,ry2;
|
|
|
|
|
int pos=0,cc,pos2=0;
|
2022-04-28 00:00:51 +02:00
|
|
|
int i, no_of_lines;
|
|
|
|
|
double longest_line;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
if(str==NULL) return;
|
2020-12-07 20:04:57 +01:00
|
|
|
#if HAS_CAIRO==1
|
2020-12-23 05:07:39 +01:00
|
|
|
text_bbox_nocairo(str, xscale, yscale, rot, flip, hcenter, vcenter,
|
|
|
|
|
x1,y1, &rx1,&ry1,&rx2,&ry2, &no_of_lines, &longest_line);
|
2020-08-08 15:47:34 +02:00
|
|
|
#else
|
2020-12-23 05:07:39 +01:00
|
|
|
text_bbox(str, xscale, yscale, rot, flip, hcenter, vcenter,
|
2020-12-24 12:23:48 +01:00
|
|
|
x1,y1, &rx1,&ry1,&rx2,&ry2, &no_of_lines, &longest_line);
|
2020-08-08 15:47:34 +02:00
|
|
|
#endif
|
2021-11-10 13:43:08 +01:00
|
|
|
xscale*=tclgetdoublevar("nocairo_font_xscale");
|
|
|
|
|
yscale*=tclgetdoublevar("nocairo_font_yscale");
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-12-02 15:10:47 +01:00
|
|
|
if(!textclip(xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2,rx1,ry1,rx2,ry2)) return;
|
2020-08-29 11:58:50 +02:00
|
|
|
set_ps_colors(gctext);
|
2020-08-08 15:47:34 +02:00
|
|
|
x1=rx1;y1=ry1;
|
|
|
|
|
if(rot&1) {y1=ry2;rot=3;}
|
|
|
|
|
else rot=0;
|
|
|
|
|
flip = 0; yy=y1;
|
|
|
|
|
while(str[pos2])
|
|
|
|
|
{
|
2020-11-13 12:54:07 +01:00
|
|
|
cc = (unsigned char)str[pos2++];
|
|
|
|
|
if(cc>127) cc= '?';
|
2020-10-12 13:13:31 +02:00
|
|
|
if(cc=='\n')
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
yy+=(FONTHEIGHT+FONTDESCENT+FONTWHITESPACE)*
|
|
|
|
|
yscale;
|
|
|
|
|
pos=0;
|
|
|
|
|
continue;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
a = pos*(FONTWIDTH+FONTWHITESPACE);
|
|
|
|
|
for(i=0;i<character[cc][0]*4;i+=4)
|
|
|
|
|
{
|
|
|
|
|
curr_x1 = ( character[cc][i+1]+ a ) * xscale + x1;
|
|
|
|
|
curr_y1 = ( character[cc][i+2] ) * yscale+yy;
|
|
|
|
|
curr_x2 = ( character[cc][i+3]+ a ) * xscale + x1;
|
|
|
|
|
curr_y2 = ( character[cc][i+4] ) * yscale+yy;
|
2020-11-03 12:10:55 +01:00
|
|
|
ROTATION(rot, flip, x1,y1,curr_x1,curr_y1,rx1,ry1);
|
|
|
|
|
ROTATION(rot, flip, x1,y1,curr_x2,curr_y2,rx2,ry2);
|
2020-08-08 15:47:34 +02:00
|
|
|
ORDER(rx1,ry1,rx2,ry2);
|
2020-09-03 10:05:48 +02:00
|
|
|
ps_drawline(gctext, rx1, ry1, rx2, ry2, 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
++pos;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ps_drawgrid()
|
|
|
|
|
{
|
|
|
|
|
double x,y;
|
|
|
|
|
double delta,tmp;
|
2021-11-10 13:43:08 +01:00
|
|
|
if( !tclgetboolvar("draw_grid")) return;
|
|
|
|
|
delta=tclgetdoublevar("cadgrid")* xctx->mooz;
|
2020-08-08 15:47:34 +02:00
|
|
|
while(delta<CADGRIDTHRESHOLD) delta*=CADGRIDMULTIPLY; /* <-- to be improved,but works */
|
2020-10-15 17:39:21 +02:00
|
|
|
x = xctx->xorigin* xctx->mooz;y = xctx->yorigin* xctx->mooz;
|
2020-08-08 15:47:34 +02:00
|
|
|
set_ps_colors(GRIDLAYER);
|
2020-12-02 15:10:47 +01:00
|
|
|
if(y>xctx->areay1 && y<xctx->areay2)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
ps_xdrawline(GRIDLAYER,xctx->areax1+1,(int)y, xctx->areax2-1, (int)y);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
if(x>xctx->areax1 && x<xctx->areax2)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
ps_xdrawline(GRIDLAYER,(int)x,xctx->areay1+1, (int)x, xctx->areay2-1);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
set_ps_colors(GRIDLAYER);
|
2020-12-02 15:10:47 +01:00
|
|
|
tmp = floor((xctx->areay1+1)/delta)*delta-fmod(-xctx->yorigin* xctx->mooz,delta);
|
|
|
|
|
for(x=floor((xctx->areax1+1)/delta)*delta-fmod(-xctx->xorigin* xctx->mooz,delta);x<xctx->areax2;x+=delta)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-02 15:10:47 +01:00
|
|
|
for(y=tmp;y<xctx->areay2;y+=delta)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
ps_xdrawpoint(GRIDLAYER,(int)(x), (int)(y));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-12-30 19:06:22 +01:00
|
|
|
static void ps_draw_symbol(int n,int layer, int what, short tmp_flip, short rot, double xoffset, double yoffset)
|
2020-08-08 15:47:34 +02:00
|
|
|
/* draws current layer only, should be called within */
|
2023-02-18 09:44:11 +01:00
|
|
|
{ /* a "for(i=0;i<cadlayers; ++i)" loop */
|
2022-03-01 19:36:08 +01:00
|
|
|
int j, hide = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
double x0,y0,x1,y1,x2,y2;
|
2020-12-05 03:16:01 +01:00
|
|
|
short flip;
|
|
|
|
|
int textlayer;
|
2020-10-12 13:13:31 +02:00
|
|
|
xLine line;
|
2021-12-19 01:28:39 +01:00
|
|
|
xRect rect;
|
2020-10-12 13:13:31 +02:00
|
|
|
xText text;
|
2020-08-08 15:47:34 +02:00
|
|
|
xArc arc;
|
2024-03-01 17:23:49 +01:00
|
|
|
xPoly *polygon;
|
2020-12-16 18:30:33 +01:00
|
|
|
xSymbol *symptr;
|
|
|
|
|
char *textfont;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
if(xctx->inst[n].ptr == -1) return;
|
2021-11-16 22:28:10 +01:00
|
|
|
if( (layer != PINLAYER && !xctx->enable_layer[layer]) ) return;
|
2022-03-01 19:36:08 +01:00
|
|
|
if( (xctx->hide_symbols==1 && (xctx->inst[n].ptr+ xctx->sym)->prop_ptr &&
|
|
|
|
|
!strcmp( (xctx->inst[n].ptr+ xctx->sym)->type, "subcircuit") ) || (xctx->hide_symbols == 2) ) {
|
|
|
|
|
hide = 1;
|
|
|
|
|
} else {
|
|
|
|
|
hide = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
if(layer==0)
|
|
|
|
|
{
|
2021-12-31 12:37:28 +01:00
|
|
|
x1=X_TO_PS(xctx->inst[n].x1);
|
|
|
|
|
x2=X_TO_PS(xctx->inst[n].x2);
|
|
|
|
|
y1=Y_TO_PS(xctx->inst[n].y1);
|
|
|
|
|
y2=Y_TO_PS(xctx->inst[n].y2);
|
2023-10-30 18:03:52 +01:00
|
|
|
if(RECT_OUTSIDE(x1,y1,x2,y2,xctx->areax1,xctx->areay1,xctx->areax2,xctx->areay2))
|
2021-12-31 12:37:28 +01:00
|
|
|
{
|
|
|
|
|
xctx->inst[n].flags|=1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else xctx->inst[n].flags&=~1;
|
|
|
|
|
|
|
|
|
|
/* pdfmarks, only if doing hierarchy print and if symbol has a subcircuit */
|
|
|
|
|
if(what != 7) {
|
2023-04-26 18:50:39 +02:00
|
|
|
char fname[PATH_MAX];
|
2023-05-21 23:58:17 +02:00
|
|
|
if(!strcmp(xctx->sym[xctx->inst[n].ptr].type, "subcircuit")) {
|
2024-02-09 17:00:56 +01:00
|
|
|
get_sch_from_sym(fname, xctx->inst[n].ptr+ xctx->sym, n, 0);
|
2021-12-31 12:37:28 +01:00
|
|
|
fprintf(fd,
|
|
|
|
|
"[ "
|
|
|
|
|
"/Rect [ %g %g %g %g ] "
|
|
|
|
|
"/Border [0 0 0] "
|
|
|
|
|
"/Dest /%s "
|
|
|
|
|
"/Subtype /Link "
|
|
|
|
|
"/ANN pdfmark\n",
|
|
|
|
|
x1, y1, x2, y2,
|
2023-04-26 18:50:39 +02:00
|
|
|
sanitize(get_cell_w_ext(fname, 0)));
|
2021-12-31 12:37:28 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
else if(xctx->inst[n].flags&1)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
dbg(1, "draw_symbol(): skippinginst %d\n", n);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
flip = xctx->inst[n].flip;
|
2020-08-08 15:47:34 +02:00
|
|
|
if(tmp_flip) flip = !flip;
|
2020-10-15 17:39:21 +02:00
|
|
|
rot = (xctx->inst[n].rot + rot ) & 0x3;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
x0=xctx->inst[n].x0 + xoffset;
|
|
|
|
|
y0=xctx->inst[n].y0 + yoffset;
|
2020-12-16 18:30:33 +01:00
|
|
|
symptr = (xctx->inst[n].ptr+ xctx->sym);
|
2023-05-12 12:09:20 +02:00
|
|
|
for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->lines[layer]; ++j)
|
|
|
|
|
{
|
|
|
|
|
line = ((xctx->inst[n].ptr+ xctx->sym)->line[layer])[j];
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,line.x1,line.y1,x1,y1);
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,line.x2,line.y2,x2,y2);
|
|
|
|
|
ORDER(x1,y1,x2,y2);
|
|
|
|
|
ps_drawline(layer, x0+x1, y0+y1, x0+x2, y0+y2, line.dash);
|
|
|
|
|
}
|
|
|
|
|
for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->polygons[layer]; ++j)
|
|
|
|
|
{
|
2024-03-01 17:23:49 +01:00
|
|
|
polygon = &((xctx->inst[n].ptr+ xctx->sym)->poly[layer])[j];
|
2023-05-12 12:09:20 +02:00
|
|
|
{ /* scope block so we declare some auxiliary arrays for coord transforms. 20171115 */
|
2024-03-01 17:23:49 +01:00
|
|
|
int k, bezier;
|
|
|
|
|
double *x = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
|
|
|
|
|
double *y = my_malloc(_ALLOC_ID_, sizeof(double) * polygon->points);
|
|
|
|
|
for(k=0;k<polygon->points; ++k) {
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,polygon->x[k],polygon->y[k],x[k],y[k]);
|
2023-05-12 12:09:20 +02:00
|
|
|
x[k]+= x0;
|
|
|
|
|
y[k] += y0;
|
|
|
|
|
}
|
2024-03-01 17:23:49 +01:00
|
|
|
bezier = !strboolcmp(get_tok_value(polygon->prop_ptr, "bezier", 0), "true");
|
|
|
|
|
ps_drawpolygon(layer, NOW, x, y, polygon->points, polygon->fill, polygon->dash, bezier);
|
2023-05-12 12:09:20 +02:00
|
|
|
my_free(_ALLOC_ID_, &x);
|
|
|
|
|
my_free(_ALLOC_ID_, &y);
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2023-05-12 12:09:20 +02:00
|
|
|
}
|
2023-07-13 13:24:17 +02:00
|
|
|
if((xctx->inst[n].ptr+ xctx->sym)->arcs[layer]) fprintf(fd, "NP\n"); /* newpath */
|
2023-05-12 12:09:20 +02:00
|
|
|
for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->arcs[layer]; ++j)
|
|
|
|
|
{
|
|
|
|
|
double angle;
|
|
|
|
|
arc = ((xctx->inst[n].ptr+ xctx->sym)->arc[layer])[j];
|
|
|
|
|
if(flip) {
|
|
|
|
|
angle = 270.*rot+180.-arc.b-arc.a;
|
|
|
|
|
} else {
|
|
|
|
|
angle = arc.a+rot*270.;
|
|
|
|
|
}
|
|
|
|
|
angle = fmod(angle, 360.);
|
|
|
|
|
if(angle<0.) angle+=360.;
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,arc.x,arc.y,x1,y1);
|
|
|
|
|
ps_drawarc(layer, arc.fill, x0+x1, y0+y1, arc.r, angle, arc.b, arc.dash);
|
|
|
|
|
}
|
|
|
|
|
if( xctx->enable_layer[layer] ) for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->rects[layer]; ++j)
|
|
|
|
|
{
|
|
|
|
|
rect = ((xctx->inst[n].ptr+ xctx->sym)->rect[layer])[j];
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,rect.x1,rect.y1,x1,y1);
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,rect.x2,rect.y2,x2,y2);
|
|
|
|
|
RECTORDER(x1,y1,x2,y2);
|
|
|
|
|
if (rect.flags & 1024) /* image */
|
|
|
|
|
{
|
2024-03-13 16:03:27 +01:00
|
|
|
ps_embedded_image(&rect, x0 + x1, y0 + y1, x0 + x2, y0 + y2, rot, flip);
|
2023-05-12 12:09:20 +02:00
|
|
|
continue;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-05-12 12:09:20 +02:00
|
|
|
ps_filledrect(layer, x0+x1, y0+y1, x0+x2, y0+y2, rect.dash, rect.fill);
|
|
|
|
|
}
|
|
|
|
|
if(
|
|
|
|
|
!(xctx->inst[n].flags & HIDE_SYMBOL_TEXTS) &&
|
|
|
|
|
(
|
|
|
|
|
(layer==TEXTWIRELAYER && (xctx->inst[n].flags & PIN_OR_LABEL) ) ||
|
|
|
|
|
(xctx->sym_txt && (layer==TEXTLAYER) && !(xctx->inst[n].flags & PIN_OR_LABEL))
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
{
|
2020-08-31 02:25:41 +02:00
|
|
|
const char *txtptr;
|
2023-02-18 09:44:11 +01:00
|
|
|
for(j=0;j< (xctx->inst[n].ptr+ xctx->sym)->texts; ++j)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2023-12-03 12:26:18 +01:00
|
|
|
double xscale, yscale;
|
|
|
|
|
|
|
|
|
|
get_sym_text_size(n, j, &xscale, &yscale);
|
2023-05-12 12:09:20 +02:00
|
|
|
text = (xctx->inst[n].ptr+ xctx->sym)->text[j];
|
2023-12-03 12:26:18 +01:00
|
|
|
/* if(xscale*FONTWIDTH* xctx->mooz<1) continue; */
|
2024-01-08 15:47:01 +01:00
|
|
|
if(!xctx->show_hidden_texts && (text.flags & (HIDE_TEXT | HIDE_TEXT_INSTANTIATED))) continue;
|
2023-05-12 12:09:20 +02:00
|
|
|
if( hide && text.txt_ptr && strcmp(text.txt_ptr, "@symname") && strcmp(text.txt_ptr, "@name") ) continue;
|
|
|
|
|
txtptr= translate(n, text.txt_ptr);
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,text.x0,text.y0,x1,y1);
|
|
|
|
|
textlayer = layer;
|
|
|
|
|
/* do not allow custom text color on PINLAYER hilighted instances */
|
|
|
|
|
if( !(xctx->inst[n].color == -PINLAYER)) {
|
|
|
|
|
textlayer = (xctx->inst[n].ptr+ xctx->sym)->text[j].layer;
|
|
|
|
|
if(textlayer < 0 || textlayer >= cadlayers) textlayer = layer;
|
|
|
|
|
}
|
|
|
|
|
/* display PINLAYER colored instance texts even if PINLAYER disabled */
|
|
|
|
|
if(xctx->inst[n].color == -PINLAYER || xctx->enable_layer[textlayer]) {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_name), "Helvetica");
|
|
|
|
|
my_snprintf(ps_font_name, S(ps_font_name), "Helvetica");
|
|
|
|
|
textfont = symptr->text[j].font;
|
|
|
|
|
if( (textfont && textfont[0])) {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), textfont);
|
|
|
|
|
my_snprintf(ps_font_name, S(ps_font_name), textfont);
|
|
|
|
|
}
|
|
|
|
|
if( symptr->text[j].flags & TEXT_BOLD) {
|
|
|
|
|
if( (symptr->text[j].flags & TEXT_ITALIC) || (symptr->text[j].flags & TEXT_OBLIQUE) ) {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-BoldOblique", ps_font_name);
|
|
|
|
|
} else {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Bold", ps_font_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( symptr->text[j].flags & TEXT_ITALIC)
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Oblique", ps_font_name);
|
|
|
|
|
else if( symptr->text[j].flags & TEXT_OBLIQUE)
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Oblique", ps_font_name);
|
|
|
|
|
if(text_ps) {
|
|
|
|
|
ps_draw_string(textlayer, txtptr,
|
|
|
|
|
(text.rot + ( (flip && (text.rot & 1) ) ? rot+2 : rot) ) & 0x3,
|
|
|
|
|
flip^text.flip, text.hcenter, text.vcenter,
|
2023-12-03 12:26:18 +01:00
|
|
|
x0+x1, y0+y1, xscale, yscale);
|
2023-05-12 12:09:20 +02:00
|
|
|
} else {
|
|
|
|
|
old_ps_draw_string(textlayer, txtptr,
|
|
|
|
|
(text.rot + ( (flip && (text.rot & 1) ) ? rot+2 : rot) ) & 0x3,
|
|
|
|
|
flip^text.flip, text.hcenter, text.vcenter,
|
2023-12-03 12:26:18 +01:00
|
|
|
x0+x1, y0+y1, xscale, yscale);
|
2023-05-12 12:09:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-05-12 12:09:20 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void fill_ps_colors()
|
|
|
|
|
{
|
|
|
|
|
char s[200]; /* overflow safe 20161122 */
|
|
|
|
|
unsigned int i,c;
|
2021-11-22 12:42:33 +01:00
|
|
|
/* if(debug_var>=1) {
|
|
|
|
|
* tcleval( "puts $ps_colors");
|
|
|
|
|
* }
|
|
|
|
|
*/
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<cadlayers; ++i) {
|
2022-04-28 10:12:16 +02:00
|
|
|
my_snprintf(s, S(s), "lindex $ps_colors %u", i);
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval( s);
|
2020-08-16 03:34:45 +02:00
|
|
|
sscanf(tclresult(),"%x", &c);
|
2020-08-08 15:47:34 +02:00
|
|
|
ps_colors[i].red = (c & 0xff0000) >> 16;
|
|
|
|
|
ps_colors[i].green = (c & 0x00ff00) >> 8;
|
|
|
|
|
ps_colors[i].blue = (c & 0x0000ff);
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2023-12-11 15:18:46 +01:00
|
|
|
/* fullzoom:
|
|
|
|
|
* 0: Print area displayed in window
|
|
|
|
|
* 1: Do a full zoom before generating ps/pdf
|
|
|
|
|
* 2: set paper size to bounding box instead of a4/letter
|
|
|
|
|
*/
|
2023-12-12 01:14:40 +01:00
|
|
|
void create_ps(char **psfile, int what, int fullzoom, int eps)
|
2021-01-28 23:09:37 +01:00
|
|
|
{
|
|
|
|
|
double dx, dy, scale, scaley;
|
|
|
|
|
int landscape=1;
|
2021-06-13 23:55:17 +02:00
|
|
|
static int numpages = 0;
|
2021-01-28 23:09:37 +01:00
|
|
|
double margin=10; /* in postscript points, (1/72)". No need to add margin as xschem zoom full already has margins.*/
|
2023-07-12 08:10:00 +02:00
|
|
|
char papername[80] = "a4";
|
|
|
|
|
double pagex = 842;
|
|
|
|
|
double pagey = 595;
|
2021-01-28 23:09:37 +01:00
|
|
|
xRect boundbox;
|
|
|
|
|
int c,i, textlayer;
|
|
|
|
|
int old_grid;
|
2022-02-22 12:09:04 +01:00
|
|
|
const char *textfont;
|
2023-12-11 15:18:46 +01:00
|
|
|
static Zoom_info zi;
|
2022-03-09 00:29:16 +01:00
|
|
|
|
2023-07-13 13:24:17 +02:00
|
|
|
dbg(1, "create_ps(): what = %d, fullzoom=%d\n", what, fullzoom);
|
2023-07-12 08:10:00 +02:00
|
|
|
if(tcleval("info exists ps_paper_size")[0] == '1') {
|
2023-07-13 13:24:17 +02:00
|
|
|
double tmp;
|
2023-07-12 08:10:00 +02:00
|
|
|
my_strncpy(papername, tcleval("lindex $ps_paper_size 0"), S(papername));
|
|
|
|
|
pagex = my_atod(tcleval("lindex $ps_paper_size 1"));
|
|
|
|
|
pagey = my_atod(tcleval("lindex $ps_paper_size 2"));
|
2023-07-13 13:24:17 +02:00
|
|
|
if(pagex < pagey) { /* start with landscape; later we decide paper orientation */
|
|
|
|
|
tmp = pagex;
|
|
|
|
|
pagex = pagey;
|
|
|
|
|
pagey = tmp;
|
|
|
|
|
}
|
2023-07-12 08:10:00 +02:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
if(what & 1) { /* prolog */
|
|
|
|
|
numpages = 0;
|
|
|
|
|
if(!(fd = open_tmpfile("psplot_", psfile)) ) {
|
|
|
|
|
fprintf(errfp, "ps_draw(): can not create tmpfile %s\n", *psfile);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
2023-01-23 11:49:08 +01:00
|
|
|
setbuf(fd, NULL); /*To prevent buffer errors, still investigating cause. */
|
2023-02-09 21:06:27 +01:00
|
|
|
ps_colors=my_calloc(_ALLOC_ID_, cadlayers, sizeof(Ps_color));
|
2021-01-28 23:09:37 +01:00
|
|
|
if(ps_colors==NULL){
|
2021-11-29 17:29:09 +01:00
|
|
|
fprintf(errfp, "create_ps(): calloc error\n");
|
|
|
|
|
return;
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fill_ps_colors();
|
2021-11-10 13:43:08 +01:00
|
|
|
old_grid=tclgetboolvar("draw_grid");
|
|
|
|
|
tclsetvar("draw_grid", "0");
|
|
|
|
|
|
2023-07-13 13:24:17 +02:00
|
|
|
/* xschem window aspect ratio decides if portrait or landscape */
|
2021-01-28 23:09:37 +01:00
|
|
|
boundbox.x1 = xctx->areax1;
|
|
|
|
|
boundbox.x2 = xctx->areax2;
|
|
|
|
|
boundbox.y1 = xctx->areay1;
|
|
|
|
|
boundbox.y2 = xctx->areay2;
|
|
|
|
|
dx=boundbox.x2-boundbox.x1;
|
|
|
|
|
dy=boundbox.y2-boundbox.y1;
|
|
|
|
|
|
2023-07-13 13:24:17 +02:00
|
|
|
/* xschem drawing bbox decides if portrait or landscape */
|
2023-12-11 15:18:46 +01:00
|
|
|
if(fullzoom == 1) {
|
2023-07-13 13:24:17 +02:00
|
|
|
calc_drawing_bbox(&boundbox, 0);
|
|
|
|
|
dx=boundbox.x2-boundbox.x1;
|
|
|
|
|
dy=boundbox.y2-boundbox.y1;
|
|
|
|
|
}
|
|
|
|
|
if(dx >= dy) {
|
|
|
|
|
landscape = 1;
|
|
|
|
|
} else {
|
|
|
|
|
landscape = 0;
|
|
|
|
|
}
|
|
|
|
|
dbg(1, "dx=%g, dy=%g\n", dx, dy);
|
|
|
|
|
|
|
|
|
|
|
2023-12-11 15:18:46 +01:00
|
|
|
if(fullzoom == 1) {
|
2023-07-13 13:24:17 +02:00
|
|
|
/* save size and zoom factor */
|
2023-12-11 15:18:46 +01:00
|
|
|
save_restore_zoom(1, &zi);
|
2023-07-13 13:24:17 +02:00
|
|
|
/* this zoom only done to reset lw */
|
|
|
|
|
zoom_full(0, 0, 1 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
|
|
|
|
|
/* adjust aspect ratio to paper size */
|
|
|
|
|
if(landscape)
|
|
|
|
|
xctx->xrect[0].height = (short unsigned int) (xctx->xrect[0].width * pagey / pagex);
|
|
|
|
|
else
|
|
|
|
|
xctx->xrect[0].width = (short unsigned int) (xctx->xrect[0].height * pagey / pagex);
|
|
|
|
|
dbg(1, "xrect.width=%d, xrect.height=%d\n", xctx->xrect[0].width, xctx->xrect[0].height);
|
|
|
|
|
xctx->areax1 = -2*INT_WIDTH(xctx->lw);
|
|
|
|
|
xctx->areay1 = -2*INT_WIDTH(xctx->lw);
|
|
|
|
|
xctx->areax2 = xctx->xrect[0].width+2*INT_WIDTH(xctx->lw);
|
|
|
|
|
xctx->areay2 = xctx->xrect[0].height+2*INT_WIDTH(xctx->lw);
|
|
|
|
|
xctx->areaw = xctx->areax2-xctx->areax1;
|
|
|
|
|
xctx->areah = xctx->areay2 - xctx->areay1;
|
|
|
|
|
dbg(1, "dx=%g, dy=%g\n", dx, dy);
|
|
|
|
|
/* fit schematic into adjusted size */
|
|
|
|
|
zoom_full(0, 0, 0 + 2 * tclgetboolvar("zoom_full_center"), 0.97);
|
|
|
|
|
boundbox.x1 = xctx->areax1;
|
|
|
|
|
boundbox.x2 = xctx->areax2;
|
|
|
|
|
boundbox.y1 = xctx->areay1;
|
|
|
|
|
boundbox.y2 = xctx->areay2;
|
|
|
|
|
dx=boundbox.x2-boundbox.x1;
|
|
|
|
|
dy=boundbox.y2-boundbox.y1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!landscape) { /* decide paper orientation for best schematic fit */
|
2021-01-28 23:09:37 +01:00
|
|
|
double tmp;
|
|
|
|
|
tmp = pagex;
|
|
|
|
|
pagex = pagey;
|
|
|
|
|
pagey = tmp;
|
|
|
|
|
}
|
2023-12-11 15:18:46 +01:00
|
|
|
if(fullzoom == 2) { /* set media size to bbox */
|
2023-12-12 01:14:40 +01:00
|
|
|
double sc;
|
2023-12-11 15:18:46 +01:00
|
|
|
my_strncpy(papername, "bbox", S(papername));
|
|
|
|
|
pagex = xctx->xrect[0].width;
|
|
|
|
|
pagey = xctx->xrect[0].height;
|
2023-12-12 01:14:40 +01:00
|
|
|
if(pagex > pagey) {
|
|
|
|
|
sc = 842. / pagex;
|
|
|
|
|
pagex = my_round(pagex * sc);
|
|
|
|
|
pagey = my_round(pagey * sc);
|
|
|
|
|
} else {
|
|
|
|
|
sc = 842. / pagey;
|
|
|
|
|
pagex = my_round(pagex * sc);
|
|
|
|
|
pagey = my_round(pagey * sc);
|
|
|
|
|
}
|
2023-12-11 15:18:46 +01:00
|
|
|
margin = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-13 23:55:17 +02:00
|
|
|
if(what & 1) {/* prolog */
|
|
|
|
|
dbg(1, "ps_draw(): bbox: x1=%g y1=%g x2=%g y2=%g\n", boundbox.x1, boundbox.y1, boundbox.x2, boundbox.y2);
|
2023-12-12 01:14:40 +01:00
|
|
|
if(!eps) {
|
|
|
|
|
fprintf(fd, "%%!PS-Adobe-3.0\n");
|
|
|
|
|
} else {
|
|
|
|
|
fprintf(fd, "%%!PS-Adobe-2.0 EPSF-2.0\n");
|
|
|
|
|
fprintf(fd, "%%%%BoundingBox: 0 0 %g %g\n", pagex, pagey);
|
|
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
/* fprintf(fd, "%%%%DocumentMedia: %s %g %g 80 () ()\n", landscape ? "a4land" : "a4", pagex, pagey); */
|
2023-07-12 08:10:00 +02:00
|
|
|
fprintf(fd, "%%%%DocumentMedia: %s %g %g 80 () ()\n", papername, pagex, pagey);
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "%%%%PageOrientation: %s\n", landscape ? "Landscape" : "Portrait");
|
|
|
|
|
fprintf(fd, "%%%%Title: xschem plot\n");
|
|
|
|
|
fprintf(fd, "%%%%Creator: xschem\n");
|
2023-12-12 01:14:40 +01:00
|
|
|
if(!eps) fprintf(fd, "%%%%Pages: (atend)\n");
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "%%%%EndComments\n");
|
2023-12-12 01:14:40 +01:00
|
|
|
|
|
|
|
|
if(eps) {
|
|
|
|
|
fprintf(fd, "%%%%BeginProlog\n");
|
|
|
|
|
fprintf(fd, "save\n");
|
|
|
|
|
fprintf(fd, "countdictstack\n");
|
|
|
|
|
fprintf(fd, "mark\n");
|
|
|
|
|
fprintf(fd, "newpath\n");
|
|
|
|
|
fprintf(fd, "/showpage {} def\n");
|
|
|
|
|
fprintf(fd, "/setpagedevice {pop} def\n");
|
|
|
|
|
fprintf(fd, "%%%%EndProlog\n");
|
|
|
|
|
fprintf(fd, "%%%%Page 1 1\n");
|
|
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "%%%%BeginProlog\n\n");
|
|
|
|
|
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i = 0; i < sizeof(utf8_enc)/sizeof(char *); ++i) {
|
2021-10-27 10:12:16 +02:00
|
|
|
fprintf(fd, "%s", utf8_enc[i]);
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i = 0; i < sizeof(utf8)/sizeof(char *); ++i) {
|
2021-10-27 10:12:16 +02:00
|
|
|
fprintf(fd, "%s", utf8[i]);
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(fd, "/Times /Times chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Times-Bold /Times-Bold chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Times-Oblique /Times-Oblique chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Times-BoldOblique /Times-BoldOblique chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Helvetica /Helvetica chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Helvetica-Bold /Helvetica-Bold chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Helvetica-Oblique /Helvetica-Oblique chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Helvetica-BoldOblique /Helvetica-BoldOblique chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Courier /Courier chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Courier-Bold /Courier-Bold chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Courier-Oblique /Courier-Oblique chararr recode\n");
|
|
|
|
|
fprintf(fd, "/Courier-BoldOblique /Courier-BoldOblique chararr recode\n");
|
|
|
|
|
|
|
|
|
|
fprintf(fd,"/cm {28.346457 mul} bind def\n");
|
|
|
|
|
fprintf(fd,"/LT {lineto} bind def\n");
|
|
|
|
|
fprintf(fd,"/MT {moveto} bind def\n");
|
|
|
|
|
fprintf(fd,"/RMT {rmoveto} bind def\n");
|
|
|
|
|
fprintf(fd,"/L {moveto lineto stroke} bind def\n");
|
|
|
|
|
fprintf(fd,"/RGB {setrgbcolor} bind def\n");
|
|
|
|
|
fprintf(fd,"/FF {findfont} bind def\n");
|
|
|
|
|
fprintf(fd,"/SF {setfont} bind def\n");
|
|
|
|
|
fprintf(fd,"/SCF {scalefont} bind def\n");
|
|
|
|
|
fprintf(fd,"/SW {stringwidth} bind def\n");
|
|
|
|
|
fprintf(fd,"/GS {gsave} bind def\n");
|
|
|
|
|
fprintf(fd,"/GR {grestore} bind def\n");
|
|
|
|
|
fprintf(fd,"/NP {newpath} bind def\n");
|
|
|
|
|
fprintf(fd,"/A {arcn} bind def\n");
|
|
|
|
|
fprintf(fd,"/R {rectstroke} bind def\n");
|
|
|
|
|
fprintf(fd,"/S {stroke} bind def\n");
|
|
|
|
|
fprintf(fd,"/C {closepath} bind def\n");
|
|
|
|
|
fprintf(fd,"/F {fill} bind def\n");
|
|
|
|
|
fprintf(fd,"/RF {rectfill} bind def\n");
|
|
|
|
|
fprintf(fd, "%%%%EndProlog\n");
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
|
|
|
|
|
2021-06-13 23:55:17 +02:00
|
|
|
|
|
|
|
|
if(what & 2) { /* page */
|
2023-02-18 09:44:11 +01:00
|
|
|
++numpages;
|
2023-12-12 02:18:31 +01:00
|
|
|
|
|
|
|
|
if(!eps) {
|
|
|
|
|
fprintf(fd, "%%%%BeginSetup\n");
|
|
|
|
|
fprintf(fd, "<< /PageSize [%g %g] /Orientation 0 >> setpagedevice\n", pagex, pagey);
|
|
|
|
|
fprintf(fd, "%%%%EndSetup\n");
|
|
|
|
|
fprintf(fd, "%%%%Page: %d %d\n\n", numpages, numpages);
|
|
|
|
|
fprintf(fd, "%%%%BeginPageSetup\n");
|
|
|
|
|
fprintf(fd, "%%%%EndPageSetup\n");
|
|
|
|
|
}
|
2021-12-30 17:15:50 +01:00
|
|
|
/* add small page title */
|
2023-12-11 18:28:23 +01:00
|
|
|
if(tclgetboolvar("ps_page_title") && fullzoom != 2)
|
2023-12-11 10:43:09 +01:00
|
|
|
fprintf(fd, "/Helvetica FF 10 SCF SF NP 20 %g MT (%s) show\n", pagey - 20, xctx->current_name);
|
2021-12-30 19:06:22 +01:00
|
|
|
|
|
|
|
|
/* Add anchor for pdfmarks */
|
|
|
|
|
fprintf(fd,
|
|
|
|
|
"[ "
|
|
|
|
|
"/Dest /%s "
|
2023-04-26 11:35:32 +02:00
|
|
|
"/DEST pdfmark\n", get_cell_w_ext(sanitize(xctx->current_name), 0));
|
2021-06-13 23:55:17 +02:00
|
|
|
scaley = scale = (pagey-2 * margin) / dy;
|
|
|
|
|
dbg(1, "scale=%g pagex=%g pagey=%g dx=%g dy=%g\n", scale, pagex, pagey, dx, dy);
|
|
|
|
|
if(dx * scale > (pagex - 2 * margin)) {
|
|
|
|
|
scale = (pagex - 2 * margin) / dx;
|
|
|
|
|
dbg(1, "scale=%g\n", scale);
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "%g %g translate\n",
|
|
|
|
|
-scale * boundbox.x1 + margin, pagey - (scaley - scale) * dy - margin + scale * boundbox.y1);
|
|
|
|
|
fprintf(fd, "%g %g scale\n", scale, -scale);
|
|
|
|
|
fprintf(fd, "1 setlinejoin 1 setlinecap\n");
|
2021-12-30 17:15:50 +01:00
|
|
|
|
2021-06-13 23:55:17 +02:00
|
|
|
set_lw();
|
|
|
|
|
ps_drawgrid();
|
|
|
|
|
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->texts; ++i)
|
2021-06-13 23:55:17 +02:00
|
|
|
{
|
|
|
|
|
textlayer = xctx->text[i].layer;
|
2022-09-16 13:19:26 +02:00
|
|
|
if(!xctx->show_hidden_texts && (xctx->text[i].flags & HIDE_TEXT)) continue;
|
2021-06-13 23:55:17 +02:00
|
|
|
if(textlayer < 0 || textlayer >= cadlayers) textlayer = TEXTLAYER;
|
|
|
|
|
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_name), "Helvetica");
|
|
|
|
|
my_snprintf(ps_font_name, S(ps_font_name), "Helvetica");
|
|
|
|
|
textfont = xctx->text[i].font;
|
|
|
|
|
if( (textfont && textfont[0])) {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), textfont);
|
|
|
|
|
my_snprintf(ps_font_name, S(ps_font_name), textfont);
|
|
|
|
|
}
|
|
|
|
|
if( xctx->text[i].flags & TEXT_BOLD) {
|
|
|
|
|
if( (xctx->text[i].flags & TEXT_ITALIC) || (xctx->text[i].flags & TEXT_OBLIQUE) ) {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-BoldOblique", ps_font_name);
|
|
|
|
|
} else {
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Bold", ps_font_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else if( xctx->text[i].flags & TEXT_ITALIC)
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Oblique", ps_font_name);
|
|
|
|
|
else if( xctx->text[i].flags & TEXT_OBLIQUE)
|
|
|
|
|
my_snprintf(ps_font_family, S(ps_font_family), "%s-Oblique", ps_font_name);
|
|
|
|
|
|
|
|
|
|
if(text_ps) {
|
2023-05-13 13:13:35 +02:00
|
|
|
ps_draw_string(textlayer, get_text_floater(i),
|
2021-06-13 23:55:17 +02:00
|
|
|
xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter,
|
|
|
|
|
xctx->text[i].x0,xctx->text[i].y0,
|
|
|
|
|
xctx->text[i].xscale, xctx->text[i].yscale);
|
2021-01-28 23:09:37 +01:00
|
|
|
} else {
|
2023-05-13 13:13:35 +02:00
|
|
|
old_ps_draw_string(textlayer, get_text_floater(i),
|
2021-06-13 23:55:17 +02:00
|
|
|
xctx->text[i].rot, xctx->text[i].flip, xctx->text[i].hcenter, xctx->text[i].vcenter,
|
|
|
|
|
xctx->text[i].x0,xctx->text[i].y0,
|
|
|
|
|
xctx->text[i].xscale, xctx->text[i].yscale);
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
for(c=0;c<cadlayers; ++c)
|
2021-01-28 23:09:37 +01:00
|
|
|
{
|
2021-06-13 23:55:17 +02:00
|
|
|
set_ps_colors(c);
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->lines[c]; ++i)
|
2021-06-13 23:55:17 +02:00
|
|
|
ps_drawline(c, xctx->line[c][i].x1, xctx->line[c][i].y1,
|
|
|
|
|
xctx->line[c][i].x2, xctx->line[c][i].y2, xctx->line[c][i].dash);
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->rects[c]; ++i)
|
2021-06-13 23:55:17 +02:00
|
|
|
{
|
2023-01-16 19:33:59 +01:00
|
|
|
|
2023-01-16 05:34:43 +01:00
|
|
|
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1024)) { /* image */
|
2023-07-13 13:24:17 +02:00
|
|
|
xRect* r = &xctx->rect[c][i];
|
|
|
|
|
/* PNG Code Here */
|
2024-03-13 16:03:27 +01:00
|
|
|
ps_embedded_image(r, r->x1, r->y1, r->x2, r->y2,0 ,0);
|
2023-07-13 13:24:17 +02:00
|
|
|
continue;
|
2023-01-16 19:33:59 +01:00
|
|
|
}
|
|
|
|
|
if (c == GRIDLAYER && (xctx->rect[c][i].flags & 1)) { /* graph */
|
2023-07-13 13:24:17 +02:00
|
|
|
xRect* r = &xctx->rect[c][i];
|
|
|
|
|
ps_embedded_graph(r, r->x1, r->y1, r->x2, r->y2);
|
2023-01-16 19:33:59 +01:00
|
|
|
}
|
|
|
|
|
if(c != GRIDLAYER || !(xctx->rect[c][i].flags & 1) ) {
|
|
|
|
|
ps_filledrect(c, xctx->rect[c][i].x1, xctx->rect[c][i].y1,
|
|
|
|
|
xctx->rect[c][i].x2, xctx->rect[c][i].y2, xctx->rect[c][i].dash, xctx->rect[c][i].fill);
|
2023-01-16 05:34:43 +01:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
2023-07-13 13:24:17 +02:00
|
|
|
if(xctx->arcs[c]) fprintf(fd, "NP\n"); /* newpath */
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->arcs[c]; ++i)
|
2021-06-13 23:55:17 +02:00
|
|
|
{
|
|
|
|
|
ps_drawarc(c, xctx->arc[c][i].fill, xctx->arc[c][i].x, xctx->arc[c][i].y,
|
|
|
|
|
xctx->arc[c][i].r, xctx->arc[c][i].a, xctx->arc[c][i].b, xctx->arc[c][i].dash);
|
|
|
|
|
}
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->polygons[c]; ++i) {
|
2024-03-01 17:23:49 +01:00
|
|
|
int bezier = !strboolcmp(get_tok_value(xctx->poly[c][i].prop_ptr, "bezier", 0), "true");
|
2021-06-13 23:55:17 +02:00
|
|
|
ps_drawpolygon(c, NOW, xctx->poly[c][i].x, xctx->poly[c][i].y, xctx->poly[c][i].points,
|
2024-03-01 17:23:49 +01:00
|
|
|
xctx->poly[c][i].fill, xctx->poly[c][i].dash, bezier);
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
2023-04-27 00:36:50 +02:00
|
|
|
dbg(1, "create_ps(): starting drawing symbols on layer %d\n", c);
|
2023-07-13 13:24:17 +02:00
|
|
|
} /* for(c=0;c<cadlayers; ++c) */
|
|
|
|
|
|
|
|
|
|
/* bring outside previous for(c=0...) loop since ps_embedded_graph() calls ps_draw_symbol() */
|
|
|
|
|
for(c=0;c<cadlayers; ++c) {
|
|
|
|
|
set_ps_colors(c);
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->instances; ++i)
|
2021-12-30 19:06:22 +01:00
|
|
|
ps_draw_symbol(i,c,what,0,0,0.0,0.0);
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
set_ps_colors(WIRELAYER);
|
2023-02-18 09:44:11 +01:00
|
|
|
for(i=0;i<xctx->wires; ++i)
|
2021-01-28 23:09:37 +01:00
|
|
|
{
|
2021-06-13 23:55:17 +02:00
|
|
|
ps_drawline(WIRELAYER, xctx->wire[i].x1,xctx->wire[i].y1,xctx->wire[i].x2,xctx->wire[i].y2, 0);
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
|
|
|
|
|
{
|
|
|
|
|
double x1, y1, x2, y2;
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *wireptr;
|
2021-06-13 23:55:17 +02:00
|
|
|
int i;
|
2023-07-13 13:24:17 +02:00
|
|
|
int first = 1;
|
2021-12-28 01:33:01 +01:00
|
|
|
Iterator_ctx ctx;
|
2022-11-07 14:23:57 +01:00
|
|
|
update_conn_cues(WIRELAYER, 0, 0);
|
2021-06-13 23:55:17 +02:00
|
|
|
/* draw connecting dots */
|
|
|
|
|
x1 = X_TO_XSCHEM(xctx->areax1);
|
|
|
|
|
y1 = Y_TO_XSCHEM(xctx->areay1);
|
|
|
|
|
x2 = X_TO_XSCHEM(xctx->areax2);
|
|
|
|
|
y2 = Y_TO_XSCHEM(xctx->areay2);
|
|
|
|
|
for(init_wire_iterator(&ctx, x1, y1, x2, y2); ( wireptr = wire_iterator_next(&ctx) ) ;) {
|
2023-07-13 13:24:17 +02:00
|
|
|
if(first) {
|
|
|
|
|
fprintf(fd, "NP\n"); /* newpath */
|
|
|
|
|
first = 0;
|
|
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
i = wireptr->n;
|
2021-10-26 00:04:13 +02:00
|
|
|
if( xctx->wire[i].end1 >1 ) {
|
2024-03-01 00:12:44 +01:00
|
|
|
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x1, xctx->wire[i].y1, xctx->cadhalfdotsize, 0, 360, 0);
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
2021-10-26 00:04:13 +02:00
|
|
|
if( xctx->wire[i].end2 >1 ) {
|
2024-03-01 00:12:44 +01:00
|
|
|
ps_drawarc(WIRELAYER, 1, xctx->wire[i].x2, xctx->wire[i].y2, xctx->cadhalfdotsize, 0, 360, 0);
|
2021-06-13 23:55:17 +02:00
|
|
|
}
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-07-14 01:43:29 +02:00
|
|
|
dbg(1, "ps_draw(): INT_WIDTH(lw)=%d plotfile=%s\n",INT_WIDTH(xctx->lw), xctx->plotfile);
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "showpage\n\n");
|
|
|
|
|
}
|
|
|
|
|
if(what & 4) { /* trailer */
|
|
|
|
|
fprintf(fd, "%%%%trailer\n");
|
|
|
|
|
fprintf(fd, "%%%%Pages: %d\n", numpages);
|
2023-12-12 01:14:40 +01:00
|
|
|
if(eps) {
|
|
|
|
|
fprintf(fd, "cleartomark\n");
|
|
|
|
|
fprintf(fd, "countdictstack\n");
|
|
|
|
|
fprintf(fd, "exch sub { end } repeat\n");
|
|
|
|
|
fprintf(fd, "restore\n");
|
|
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
fprintf(fd, "%%%%EOF\n");
|
|
|
|
|
fclose(fd);
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
2021-11-10 13:43:08 +01:00
|
|
|
tclsetboolvar("draw_grid", old_grid);
|
2023-02-09 21:06:27 +01:00
|
|
|
my_free(_ALLOC_ID_, &ps_colors);
|
2023-07-13 13:24:17 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* restore original size and zoom factor */
|
2023-12-11 15:18:46 +01:00
|
|
|
if(fullzoom == 1) {
|
|
|
|
|
save_restore_zoom(0, &zi);
|
2023-07-13 13:24:17 +02:00
|
|
|
}
|
|
|
|
|
|
2021-01-28 23:09:37 +01:00
|
|
|
}
|
|
|
|
|
|
2023-12-12 01:14:40 +01:00
|
|
|
int ps_draw(int what, int fullzoom, int eps)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-16 18:30:33 +01:00
|
|
|
char tmp[2*PATH_MAX+40];
|
2020-12-27 22:59:15 +01:00
|
|
|
static char lastdir[PATH_MAX] = "";
|
2021-01-28 23:09:37 +01:00
|
|
|
const char *r;
|
2021-06-13 23:55:17 +02:00
|
|
|
static char *psfile;
|
|
|
|
|
|
|
|
|
|
if(what & 1) { /* prolog */
|
|
|
|
|
if(!lastdir[0]) my_strncpy(lastdir, pwd_dir, S(lastdir));
|
2021-12-05 15:31:26 +01:00
|
|
|
if(has_x && !xctx->plotfile[0]) {
|
2023-08-30 00:42:09 +02:00
|
|
|
/* tclvareval("tk_getSaveFile -title {Select destination file} -initialfile {",
|
|
|
|
|
* get_cell(xctx->sch[xctx->currsch], 0) , ".pdf} -initialdir {", lastdir, "}", NULL); */
|
|
|
|
|
tclvareval("save_file_dialog {Select destination file} *.{ps,pdf} INITIALLOADDIR {", pwd_dir, "/",
|
2023-12-12 01:14:40 +01:00
|
|
|
get_cell(xctx->sch[xctx->currsch], 0), eps ? ".eps}": ".pdf}", NULL);
|
2021-06-13 23:55:17 +02:00
|
|
|
r = tclresult();
|
|
|
|
|
if(r[0]) {
|
2021-07-14 01:43:29 +02:00
|
|
|
my_strncpy(xctx->plotfile, r, S(xctx->plotfile));
|
2021-12-05 12:39:05 +01:00
|
|
|
tclvareval("file dirname {", xctx->plotfile, "}", NULL);
|
2021-06-13 23:55:17 +02:00
|
|
|
my_strncpy(lastdir, tclresult(), S(lastdir));
|
|
|
|
|
}
|
|
|
|
|
else return 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2023-12-12 01:14:40 +01:00
|
|
|
create_ps(&psfile, what, fullzoom, eps);
|
2021-06-13 23:55:17 +02:00
|
|
|
if(what & 4) { /* trailer */
|
2021-07-14 01:43:29 +02:00
|
|
|
if(xctx->plotfile[0]) {
|
|
|
|
|
my_snprintf(tmp, S(tmp), "convert_to_pdf {%s} {%s}", psfile, xctx->plotfile);
|
2021-06-13 23:55:17 +02:00
|
|
|
} else {
|
|
|
|
|
my_snprintf(tmp, S(tmp), "convert_to_pdf {%s} plot.pdf", psfile);
|
|
|
|
|
}
|
2021-07-14 01:43:29 +02:00
|
|
|
my_strncpy(xctx->plotfile,"", S(xctx->plotfile));
|
2021-06-13 23:55:17 +02:00
|
|
|
tcleval( tmp);
|
|
|
|
|
Tcl_SetResult(interp,"",TCL_STATIC);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2021-06-13 23:55:17 +02:00
|
|
|
return 1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|