static int svg_endpath(gx_device_vector *vdev, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; /* hack single-page output */ if (svg->page_count) return 0; /* skip non-drawing paths for now */ if (!(type & gx_path_type_fill) && !(type & gx_path_type_stroke)) return 0; dprintf("svg_endpath "); svg_print_path_type(svg, type); dprintf("\n"); /* close the path data attribute */ svg_write(svg, "'"); /* override the inherited stroke attribute if we're not stroking */ if (!(type & gx_path_type_stroke) && svg->strokecolor) svg_write(svg, " stroke='none'"); /* override the inherited fill attribute if we're not filling */ if (!(type & gx_path_type_fill) && svg->fillcolor) svg_write(svg, " fill='none'"); svg_write(svg, "/>\n"); return 0; }
/* Close the device */ static int svg_close_device(gx_device *dev) { gx_device_svg *const svg = (gx_device_svg*)dev; svg_write(svg, "\n<!-- svg_close_device -->\n"); /* close any open group elements */ while (svg->mark > 0) { svg_write(svg, "</g>\n"); svg->mark--; } if (svg->header) { svg_write(svg, "</svg>\n"); svg->header = 0; } if (svg->fillcolor) gs_free_string(svg->memory, (byte *)svg->fillcolor, 8, "svg_close_device"); if (svg->strokecolor) gs_free_string(svg->memory, (byte *)svg->strokecolor, 8, "svg_close_device"); if (ferror(svg->file)) return gs_throw_code(gs_error_ioerror); return gdev_vector_close_file((gx_device_vector*)dev); }
static int svg_curveto(gx_device_vector *vdev, floatp x0, floatp y0, floatp x1, floatp y1, floatp x2, floatp y2, floatp x3, floatp y3, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; char line[SVG_LINESIZE]; /* hack single-page output */ if (svg->page_count) return 0; /* skip non-drawing paths for now */ if (!(type & gx_path_type_fill) && !(type & gx_path_type_stroke)) return 0; dprintf8("svg_curveto(%lf,%lf, %lf,%lf, %lf,%lf, %lf,%lf) ", x0,y0, x1,y1, x2,y2, x3,y3); svg_print_path_type(svg, type); dprintf("\n"); sprintf(line, " C%lf,%lf %lf,%lf %lf,%lf", x1,y1, x2,y2, x3,y3); svg_write(svg, line); return 0; }
/* Complete a page */ static int svg_output_page(gx_device *dev, int num_copies, int flush) { gx_device_svg *const svg = (gx_device_svg*)dev; svg->page_count++; svg_write(svg, "\n<!-- svg_output_page -->\n"); if (ferror(svg->file)) return gs_throw_code(gs_error_ioerror); return gx_finish_output_page(dev, num_copies, flush); }
static int svg_closepath(gx_device_vector *vdev, floatp x, floatp y, floatp x_start, floatp y_start, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; /* hack single-page output */ if (svg->page_count) return 0; /* skip non-drawing paths for now */ if (!(type & gx_path_type_fill) && !(type & gx_path_type_stroke)) return 0; dprintf("svg_closepath "); svg_print_path_type(svg, type); dprintf("\n"); svg_write(svg, " z"); return 0; }
static int svg_beginpath(gx_device_vector *vdev, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; /* hack single-page output */ if (svg->page_count) return 0; /* skip non-drawing paths for now */ if (!(type & gx_path_type_fill) && !(type & gx_path_type_stroke)) return 0; dprintf("svg_beginpath "); svg_print_path_type(svg, type); dprintf("\n"); svg_write_state(svg); svg_write(svg, "<path d='"); return 0; }
/* Complete a page */ static int svg_output_page(gx_device *dev, int num_copies, int flush) { gx_device_svg *const svg = (gx_device_svg*)dev; int code; svg->page_count++; svg_write(svg, "\n<!-- svg_output_page -->\n"); if (ferror(svg->file)) return gs_throw_code(gs_error_ioerror); if ((code=gx_finish_output_page(dev, num_copies, flush)) < 0) return code; /* Check if we need to change the output file for separate pages */ if (gx_outputfile_is_separate_pages(((gx_device_vector *)dev)->fname, dev->memory)) { if ((code = svg_close_device(dev)) < 0) return code; code = svg_open_device(dev); } return code; }
static int svg_lineto(gx_device_vector *vdev, floatp x0, floatp y0, floatp x, floatp y, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; char line[SVG_LINESIZE]; /* hack single-page output */ if (svg->page_count) return 0; /* skip non-drawing paths for now */ if (!(type & gx_path_type_fill) && !(type & gx_path_type_stroke)) return 0; if_debug4('_', "svg_lineto(%lf,%lf,%lf,%lf) ", x0,y0, x,y); svg_print_path_type(svg, type); if_debug0('_', "\n"); sprintf(line, " L%lf,%lf", x, y); svg_write(svg, line); return 0; }
static int svg_dorect(gx_device_vector *vdev, fixed x0, fixed y0, fixed x1, fixed y1, gx_path_type_t type) { gx_device_svg *svg = (gx_device_svg *)vdev; char line[300]; /* hack single-page output */ if (svg->page_count) return 0; dprintf("svg_dorect "); svg_print_path_type(svg, type); dprintf("\n"); svg_write_state(svg); if (type & gx_path_type_clip) { svg_write(svg, "<clipPath>\n"); } sprintf(line, "<rect x='%lf' y='%lf' width='%lf' height='%lf'", fixed2float(x0), fixed2float(y0), fixed2float(x1 - x0), fixed2float(y1 - y0)); svg_write(svg, line); /* override the inherited stroke attribute if we're not stroking */ if (!(type & gx_path_type_stroke) && svg->strokecolor) svg_write(svg, " stroke='none'"); /* override the inherited fill attribute if we're not filling */ if (!(type & gx_path_type_fill) && svg->fillcolor) svg_write(svg, " fill='none'"); svg_write(svg, "/>\n"); if (type & gx_path_type_clip) { svg_write(svg, "</clipPath>\n"); } return 0; }
static int svg_write_state(gx_device_svg *svg) { char line[SVG_LINESIZE]; /* has anything changed? */ if (!svg->dirty) return 0; /* close the current graphics state element, if any */ if (svg->mark > 1) { svg_write(svg, "</g>\n"); svg->mark--; } /* write out the new current state */ svg_write(svg, "<g "); if (svg->strokecolor) { sprintf(line, " stroke='%s'", svg->strokecolor); svg_write(svg, line); } else { svg_write(svg, " stroke='none'"); } if (svg->fillcolor) { sprintf(line, " fill='%s'", svg->fillcolor); svg_write(svg, line); } else { svg_write(svg, " fill='none'"); } if (svg->linewidth != 1.0) { sprintf(line, " stroke-width='%lf'", svg->linewidth); svg_write(svg, line); } if (svg->linecap != SVG_DEFAULT_LINECAP) { switch (svg->linecap) { case gs_cap_round: svg_write(svg, " stroke-linecap='round'"); break; case gs_cap_square: svg_write(svg, " stroke-linecap='square'"); break; case gs_cap_butt: default: /* treat all the other options as the default */ svg_write(svg, " stroke-linecap='butt'"); break; } } if (svg->linejoin != SVG_DEFAULT_LINEJOIN) { switch (svg->linejoin) { case gs_join_round: svg_write(svg, " stroke-linejoin='round'"); break; case gs_join_bevel: svg_write(svg, " stroke-linejoin='bevel'"); break; case gs_join_miter: default: /* SVG doesn't support any other variants */ svg_write(svg, " stroke-linejoin='miter'"); break; } } if (svg->miterlimit != SVG_DEFAULT_MITERLIMIT) { sprintf(line, " stroke-miterlimit='%lf'", svg->miterlimit); svg_write(svg, line); } svg_write(svg, ">\n"); svg->mark++; svg->dirty = 0; return 0; }
extern int pssvg(pssvg_opt_t opt) { int err = 0; grd5_t *grd5; switch (grd5_read(opt.file.input, &grd5)) { case GRD5_READ_OK: break; case GRD5_READ_FOPEN: btrace("failed to read %s", (opt.file.input ? opt.file.input : "stdin")); return 1; case GRD5_READ_FREAD: btrace("failed read from stream"); return 1; case GRD5_READ_PARSE: btrace("failed to parse input"); return 1; case GRD5_READ_NOT_GRD: btrace("not a GRD file"); return 1; case GRD5_READ_NOT_GRD5: btrace("not a PhotoShop GRD file"); return 1; case GRD5_READ_MALLOC: btrace("out of memory"); return 1; case GRD5_READ_BUG: /* fall-through */ default: btrace("internal error - please report this"); return 1; } if (grd5->n == 0) { btrace("no gradients parsed"); err++; goto cleanup_grd5; } if (opt.verbose) printf("parsed %i grd5 gradient%s\n", grd5->n, (grd5->n == 1) ? "" : "s"); svgset_t *svgset; if ((svgset = svgset_new()) == NULL) goto cleanup_grd5; if (pssvg_convert(grd5, svgset, opt) != 0) { btrace("conversion failed"); err++; goto cleanup_svgset; } if (svgset->n == 0) { btrace("no svg gradients converted"); err++; goto cleanup_svgset; } svg_preview_t preview; preview.use = false; if (svg_write(opt.file.output, svgset->n, (const svg_t**)svgset->svg, &preview) != 0) { btrace("failed write of svg"); err++; goto cleanup_svgset; } cleanup_svgset: svgset_destroy(svgset); cleanup_grd5: grd5_destroy(grd5); return err; }
extern int gimpsvg(const char *infile, const char *outfile, gimpsvg_opt_t opt) { gradient_t *gradient; svg_t *svg; int err; /* load the gradient */ if ((gradient = grad_load_gradient(infile)) == NULL) { btrace("failed to load gradient from %s", (infile ? infile : "<stdin>")); return 1; } /* create a svg struct */ if ((svg = svg_new()) == NULL) { btrace("failed to get new cpt strcture"); return 1; } /* transfer the gradient data to the svg_t struct */ if ((err = gimpsvg_convert(gradient, svg, opt)) != 0) { switch (err) { case ERR_SEGMENT_RGBA: btrace("error gretting colour from segment"); break; case ERR_NULL: btrace("null structure"); break; case ERR_INSERT: btrace("failed structure insert"); break; default: btrace("unknown error"); } return 1; } if (opt.verbose) printf("converted to %i stops\n",svg_num_stops(svg)); /* write the cpt file */ if (svg_write(outfile, 1, (const svg_t**)(&svg), &(opt.preview)) != 0) { btrace("failed to write gradient to %s", (outfile ? outfile : "<stdout>")); return 1; } /* tidy */ svg_destroy(svg); grad_free_gradient(gradient); return 0; }
/* -- write buffer contents, break at full pages -- */ void write_buffer(void) { char *p_buf; int l, np; float p1, dp; int outft_sav; if (mbf == outbuf || multicol_start != 0) return; if (!in_page && !epsf) init_page(); outft_sav = outft; p1 = 0; p_buf = outbuf; for (l = 0; l < ln_num; l++) { if (ln_pos[l] > 0) { /* if in multicol */ int ll; float pos; for (ll = l + 1; ll < ln_num; ll++) { if (ln_pos[ll] <= 0) { pos = ln_pos[ll]; while (--ll >= l) ln_pos[ll] = pos; break; } } } dp = ln_pos[l] - p1; np = remy + dp < 0 && !epsf; if (np) { close_page(); init_page(); if (ln_font[l] >= 0) { struct FONTSPEC *f; f = &cfmt.font_tb[ln_font[l]]; output(fout, "%.1f F%d\n", f->size, f->fnum); } } if (ln_scale[l] != cur_scale) { output(fout, "%.3f dup scale\n", ln_scale[l] / cur_scale); cur_scale = ln_scale[l]; } if (ln_lmarg[l] != cur_lmarg) { output(fout, "%.2f 0 T\n", (ln_lmarg[l] - cur_lmarg) / cur_scale); cur_lmarg = ln_lmarg[l]; } if (np) { output(fout, "0 %.2f T\n", -cfmt.topspace); remy -= cfmt.topspace * cfmt.scale; } if (*p_buf != '\001') { if (epsf > 1 || svg) svg_write(p_buf, ln_buf[l] - p_buf); else fwrite(p_buf, 1, ln_buf[l] - p_buf, fout); } else { /* %%EPS - see parse.c */ FILE *f; char line[BSIZE], *p, *q; p = strchr(p_buf + 1, '\n'); fwrite(p_buf + 1, 1, p - p_buf, fout); p_buf = p + 1; p = strchr(p_buf, '%'); *p++ = '\0'; q = strchr(p, '\n'); *q = '\0'; if ((f = fopen(p, "r")) == NULL) { error(1, NULL, "Cannot open EPS file '%s'", p); } else { if (epsf > 1 || svg) { fprintf(fout, "<!--Begin document %s-->\n", p); svg_output(fout, "gsave\n" "%s T\n", p_buf); while (fgets(line, sizeof line, f)) /* copy the file */ svg_write(line, strlen(line)); svg_output(fout, "grestore\n" "%s T\n", p_buf); fprintf(fout, "<!--End document %s-->\n", p); } else { fprintf(fout, "save\n" "/showpage{}def/setpagedevice{pop}def\n" "%s T\n" "%%%%BeginDocument: %s\n", p_buf, p); while (fgets(line, sizeof line, f)) /* copy the file */ fwrite(line, 1, strlen(line), fout); fprintf(fout, "%%%%EndDocument\n" "restore\n"); } fclose(f); } } p_buf = ln_buf[l]; remy += dp; p1 = ln_pos[l]; } #if 1 //fixme:test if (*p_buf != '\0') { // fprintf(stderr, "??? bug - buffer not empty:\n%s\n", p_buf); memcpy(outbuf, p_buf, strlen(p_buf) + 1); mbf = &outbuf[strlen(outbuf)]; } else { mbf = outbuf; } #endif outft = outft_sav; bposy = 0; ln_num = 0; use_buffer = 0; }
/* -- output the header or footer -- */ static float headfooter(int header, float pwidth, float pheight) { char tmp[2048], str[TEX_BUF_SZ + 512]; char *p, *q, *r, *outbuf_sav, *mbf_sav; float size, y, wsize; struct FONTSPEC *f, f_sav; int cft_sav, dft_sav, outbufsz_sav; if (header) { p = cfmt.header; f = &cfmt.font_tb[HEADERFONT]; size = f->size; y = -size; } else { p = cfmt.footer; f = &cfmt.font_tb[FOOTERFONT]; size = f->size; y = - (pheight - cfmt.topmargin - cfmt.botmargin) + size; } if (*p == '-') { if (pagenum == 1) return 0; p++; } get_str_font(&cft_sav, &dft_sav); memcpy(&f_sav, &cfmt.font_tb[0], sizeof f_sav); str_font(f - cfmt.font_tb); output(fout, "%.1f F%d ", size, f->fnum); outft = f - cfmt.font_tb; /* may have 2 lines */ wsize = size; if ((r = strstr(p, "\\n")) != NULL) { if (!header) y += size; wsize += size; *r = '\0'; } mbf_sav = mbf; outbuf_sav = outbuf; outbufsz_sav = outbufsz; outbuf = tmp; outbufsz = sizeof tmp; for (;;) { tex_str(p); strcpy(tmp, tex_buf); format_hf(str, tmp); /* left side */ p = str; if ((q = strchr(p, '\t')) != NULL) { if (q != p) { *q = '\0'; output(fout, "%.1f %.1f M ", p_fmt->leftmargin, y); mbf = tmp; str_out(p, A_LEFT); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } p = q + 1; } if ((q = strchr(p, '\t')) != NULL) *q = '\0'; /* center */ if (q != p) { output(fout, "%.1f %.1f M ", pwidth * 0.5, y); mbf = tmp; str_out(p, A_CENTER); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } /* right side */ if (q) { p = q + 1; if (*p != '\0') { output(fout, "%.1f %.1f M ", pwidth - p_fmt->rightmargin, y); mbf = tmp; str_out(p, A_RIGHT); a2b("\n"); if (svg) svg_write(tmp, strlen(tmp)); else fputs(tmp, fout); } } if (!r) break; *r = '\\'; p = r + 2; r = NULL; y -= size; } /* restore the buffer and fonts */ outbuf = outbuf_sav; outbufsz = outbufsz_sav; mbf = mbf_sav; memcpy(&cfmt.font_tb[0], &f_sav, sizeof cfmt.font_tb[0]); set_str_font(cft_sav, dft_sav); return wsize; }