57#define PNG_MAGIC "\x89PNG\x0D\x0A\x1A\x0A"
58#define PS_MAGIC "%!PS-Adobe-"
60#define GIF_MAGIC "GIF8"
61#define JPEG_MAGIC "\xFF\xD8\xFF"
62#define PDF_MAGIC "%PDF-"
63#define EPS_MAGIC "\xC5\xD0\xD3\xC6"
64#define XML_MAGIC "<?xml"
65#define SVG_MAGIC "<svg"
66#define RIFF_MAGIC "RIFF"
67#define WEBP_MAGIC "WEBP"
68#define ICO_MAGIC "\x00\x00\x01\x00"
98 }
else if (c ==
'>') {
105 if (fread(tag, 1,
sizeof(tag), us->
f) !=
sizeof(tag)) {
113 int c = fgetc(us->
f);
117 memmove(&tag[0], &tag[1],
sizeof(tag) - 1);
118 tag[
sizeof(tag) - 1] = (
char)c;
143 for (
size_t i = 0; i < sz; i++) {
147 value |= (unsigned)ch << 8 * i;
149 if (value > INT_MAX) {
160 for (
size_t i = 0; i < sz; i++) {
165 value |= (unsigned)ch;
167 if (value > INT_MAX) {
175 if (strcmp(u,
"in") == 0)
177 if (strcmp(u,
"px") == 0)
179 if (strcmp(u,
"pc") == 0)
181 if (strcmp(u,
"pt") == 0 || strcmp(u,
"\"") == 0)
183 if (strcmp(u,
"cm") == 0)
185 if (strcmp(u,
"mm") == 0)
198 for (
size_t i = 0;
s[i] !=
'\0'; ) {
199 if (
s[i] >=
'a' &&
s[i] <=
'z') {
203 while ((
s[i] >=
'a' &&
s[i] <=
'z') || (
s[i] >=
'A' &&
s[i] <=
'Z')) {
207 if (
s[i] ==
'=' &&
s[i + 1] ==
'"') {
211 while (
s[i] !=
'"' &&
s[i] !=
'\0') {
237 typedef struct {
bool has_value;
double value; } optional_double_t;
238#define SET(me, val) \
240 *(me) = (optional_double_t){.has_value = true, .value = (val)}; \
242#define VALUE_OR(me, val) ((me).has_value ? (me).value : (val))
245 optional_double_t hard_height = {0};
246 optional_double_t hard_width = {0};
249 optional_double_t soft_height = {0};
250 optional_double_t soft_width = {0};
253 while (!eof && (!hard_width.has_value || !hard_height.has_value)) {
256 int c = fgetc(us->
f);
260 }
else if (c ==
'\n') {
266 const char *re_string =
agxbuse(&line);
273 if (sscanf(value,
"%lf%2s", &n, u) == 2) {
276 else if (sscanf(value,
"%lf", &n) == 1) {
280 if (hard_height.has_value)
285 if (sscanf(value,
"%lf%2s", &n, u) == 2) {
288 else if (sscanf(value,
"%lf", &n) == 1) {
292 if (hard_width.has_value)
298 if (sscanf(value,
"%*f %*f %lf %lf", &w, &h) == 2) {
300 SET(&soft_height, h);
308 if (soft_height.has_value && soft_width.has_value) {
309 if (!hard_height.has_value) {
310 SET(&hard_height, soft_height.value);
312 if (!hard_width.has_value) {
313 SET(&hard_width, soft_width.value);
319 const double h =
VALUE_OR(hard_height, 0);
320 const double w =
VALUE_OR(hard_width, 0);
321 assert(w >= 0 && w <= INT_MAX);
323 assert(h >= 0 && h <= INT_MAX);
336 fseek(us->
f, 16, SEEK_SET);
348 fseek(us->
f, 6, SEEK_SET);
360 fseek(us->
f, 15, SEEK_SET);
361 if (fgetc(us->
f) ==
'X') {
362 fseek(us->
f, 24, SEEK_SET);
369 fseek(us->
f, 26, SEEK_SET);
382 fseek(us->
f, 6, SEEK_SET);
390 int size_x_msw, size_x_lsw, size_y_msw, size_y_lsw;
393 fseek (us->
f, 16, SEEK_SET);
398 us->
w = size_x_msw << 16 | size_x_lsw;
399 us->
h = size_y_msw << 16 | size_y_lsw;
404 int marker, length, size_x, size_y;
409 static const unsigned char standalone_markers[] = {
411 0xd0, 0xd1, 0xd2, 0xd3,
437 if (memchr(standalone_markers, marker,
sizeof(standalone_markers)))
441 if (marker == 0xc0) {
443 if (fseek(us->
f, 3, SEEK_CUR) == 0 &&
455 if (marker == 0xc2) {
457 if (fseek(us->
f, 3, SEEK_CUR) != 0)
473 fseek (us->
f, length - 2, SEEK_CUR);
486 while (fgets(line,
sizeof(line), us->
f)) {
495 if (!(linep = strstr (line,
"%%BoundingBox:")))
497 if (sscanf (linep,
"%%%%BoundingBox: %d %d %d %d", &lx, &ly, &ux, &uy) == 4) {
510#define KEY "/MediaBox"
519 if (fgets(
str->buf, BUFSIZ,
str->fp)) {
527#define strc(x) (*(x->s)?*(x->s):nxtc(x))
528#define stradv(x) (x->s++)
544 double d = strtod(
tok, &endp);
546 if (
tok == endp)
return 1;
560 if (
len == BUFSIZ-1)
break;
573 if (
strc(
str) !=
'[')
return 1;
592 while (fgets(buf, BUFSIZ, fp)) {
593 if ((
s = strstr(buf,
KEY))) {
647#define MAX_USERSHAPE_FILES_OPEN 50
650 static int usershape_files_open_cnt;
666 agwarningf(
"%s while opening %s\n", strerror(errno), fn);
672 usershape_files_open_cnt++;
717 agwarningf(
"\"%s\" was not found as a file or as a shape library member\n", us->
name);
774 dpi.
x = dpi.
y = us->
dpi;
790 static char* oldpath;
794 if (!name || (*name ==
'\0')) {
810 dpi.
x = dpi.
y = DEFAULT_DPI;
size_t match(char *str, char *pat)
static void agxbfree(agxbuf *xb)
free any malloced resources
static WUR char * agxbuse(agxbuf *xb)
static int agxbputc(agxbuf *xb, char c)
add character to buffer
Memory allocation wrappers that exit on failure.
static void * gv_alloc(size_t size)
CDT_API Dtmethod_t * Dttree
CDT_API int dtclose(Dt_t *)
CDT_API Dt_t * dtopen(Dtdisc_t *, Dtmethod_t *)
const char * safefile(const char *filename)
static double len(glCompPoint p)
void agwarningf(const char *fmt,...)
int agstrfree(Agraph_t *, const char *, bool is_html)
char * agstrdup(Agraph_t *, const char *)
returns a pointer to a reference-counted copy of the argument string, creating one if necessary
bool gvusershape_file_access(usershape_t *us)
replacements for ctype.h functions
static bool gv_isdigit(int c)
static bool gv_isspace(int c)
FILE * gv_fopen(const char *filename, const char *mode)
wrapper around fopen for internal library usage
static void ico_size(usershape_t *us)
static void freeUsershape(usershape_t *us)
static char nxtc(stream_t *str)
#define MAX_USERSHAPE_FILES_OPEN
static bool get_int_msb_first(FILE *f, size_t sz, int *val)
shape_desc * find_user_shape(const char *)
static bool get_int_lsb_first(FILE *f, size_t sz, int *val)
static void skipWS(stream_t *str)
static Dtdisc_t ImageDictDisc
static int find_attribute(const char *s, match_t *result)
static void webp_size(usershape_t *us)
usershape_t * gvusershape_find(const char *name)
void gvusershape_file_release(usershape_t *us)
point gvusershape_size(graph_t *g, char *name)
point gvusershape_size_dpi(usershape_t *us, pointf dpi)
static int boxof(stream_t *str, boxf *bp)
static void jpeg_size(usershape_t *us)
static usershape_t * gvusershape_open(const char *name)
static int bboxPDF(FILE *fp, boxf *bp)
static knowntype_t knowntypes[]
static void png_size(usershape_t *us)
static void gif_size(usershape_t *us)
static imagetype_t imagetype(usershape_t *us)
static int scanNum(char *tok, double *dp)
static Dict_t * ImageDict
static double svg_units_convert(double n, char *u)
static void pdf_size(usershape_t *us)
static void ps_size(usershape_t *us)
static void svg_size(usershape_t *us)
static void bmp_size(usershape_t *us)
static void getNum(stream_t *str, char *buf)
#define VALUE_OR(me, val)
static void usershape_close(void *p)
textitem scanner parser str
a non-owning string reference
const char * data
start of the pointed to string
size_t size
extent of the string in bytes
void(* datafree)(usershape_t *us)
Non-owning string references.
static bool strview_str_eq(strview_t a, const char *b)
compare a string reference to a string for equality
static char * strview_str(strview_t source)
make a heap-allocated string from this string view
static tok_t tok(const char *input, const char *separators)
begin tokenization of a new string
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t