void XPSFillPolygon(Display *display, Drawable drawable, GC context, Coord *coord, int ncoords, int shape, int mode) { int i; int pcount; if (output_flag == XOUT) { XFillPolygon(display, drawable, context, (XPoint *)coord, ncoords, shape, mode); } else { XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth, &values); if (ncoords <= 0) { return; } PSNewpath(); PSSetPixel(display, values.foreground); PSMoveto(coord[0].x, coord[0].y); pcount = 0; for (i = 1; i < ncoords; i++) { PSLineto(coord[i].x, coord[i].y); /* * break it up into managable cuhnks */ if (pcount > MAXSTROKES) { PSClosefill(); PSMoveto(coord[i].x, coord[i].y); pcount = 0; } pcount++; } PSClosefill(); } }
void XPSFillArc(Display *display, Drawable drawable, GC context, int x, int y, int w, int h, int angle1, int angle2) { if (output_flag == XOUT) { XFillArc(display, drawable, context, x, y, w, h, angle1, angle2); } else { XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth | GCArcMode, &values); PSNewpath(); PSSetPixel(display, values.foreground); PSSetLineWidth(values.line_width); if (values.arc_mode == ArcPieSlice) PSMoveto(x + w / 2, y + h / 2); PSArc(x + w / 2.0, y + h / 2.0, w / 2.0, angle1 / 64.0, angle2 / 64.0); PSClosefill(); } }
void XPSDrawLine(Display *display, Drawable drawable, GC context, int x1, int y1, int x2, int y2) { if (output_flag == XOUT) { XDrawLine(display, drawable, context, x1, y1, x2, y2); } else { /* * get the current foreground color from the graphics context */ XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth, &values); PSSetPixel(display, values.foreground); PSSetLineWidth(values.line_width); PSNewpath(); PSMoveto(x1, y1); PSLineto(x2, y2); PSStroke(); } }
void XPSDrawDot(Display *display, Drawable drawable, GC context, int x1, int y1) { if (output_flag == XOUT) { XDrawLine(display, drawable, context, x1, y1, x1, y1 + 1); } else { /* Hack: this isn't a good way to draw PS dots */ XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth, &values); PSSetPixel(display, values.foreground); PSSetLineWidth(values.line_width); PSNewpath(); PSMoveto(x1, y1); PSLineto(x1, y1 + 1); PSStroke(); } }
void XPSFillRectangle(Display *display, Drawable drawable, GC context, int x, int y, int w, int h) { if (output_flag == XOUT) { XFillRectangle(display, drawable, context, x, y, w, h); } else { XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth, &values); PSSetPixel(display, values.foreground); PSNewpath(); PSMoveto(x, y); PSLineto(x + w, y); PSLineto(x + w, y + h); PSLineto(x, y + h); PSClosefill(); } }
void XPSDrawText(Display *display, Drawable drawable, GC context, int x, int y, char *s) { XFontStruct *finfo; int height; if (s == NULL) return; if (output_flag == XOUT) { XDrawImageString(display, drawable, context, x, y, s, strlen(s)); } else { finfo = XQueryFont(display, context->gid); height = finfo->ascent + finfo->descent; PSFont(height); PSMoveto(x, y); PSShow(s); } }
/* ** We call this routine to emmit the PostScript code ** for the character we have loaded with load_char(). */ void GlyphToType3::PSConvert(TTStreamWriter& stream) { int i,j,k; assert(area_ctr == NULL); area_ctr=(double*)calloc(num_ctr, sizeof(double)); memset(area_ctr, 0, (num_ctr*sizeof(double))); assert(check_ctr == NULL); check_ctr=(char*)calloc(num_ctr, sizeof(char)); memset(check_ctr, 0, (num_ctr*sizeof(char))); assert(ctrset == NULL); ctrset=(int*)calloc(num_ctr, 2*sizeof(int)); memset(ctrset, 0, (num_ctr*2*sizeof(int))); check_ctr[0]=1; area_ctr[0]=area(xcoor, ycoor, epts_ctr[0]+1); for (i=1; i<num_ctr; i++) { area_ctr[i]=area(xcoor+epts_ctr[i-1]+1, ycoor+epts_ctr[i-1]+1, epts_ctr[i]-epts_ctr[i-1]); } for (i=0; i<num_ctr; i++) { if (area_ctr[i]>0) { ctrset[2*i]=i; ctrset[2*i+1]=nearout(i); } else { ctrset[2*i]=-1; ctrset[2*i+1]=-1; } } /* Step thru the coutours. */ /* I believe that a contour is a detatched */ /* set of curves and lines. */ for(i = j = k = 0; i != NOMOREOUTCTR && i < num_ctr; k = nextinctr(i, k), (k == NOMOREINCTR && (i = k = nextoutctr(i)))) { // A TrueType contour consists of on-path and off-path points. // Two consecutive on-path points are to be joined with a // line; off-path points between on-path points indicate a // quadratic spline, where the off-path point is the control // point. Two consecutive off-path points have an implicit // on-path point midway between them. std::list<FlaggedPoint> points; // Represent flags and x/y coordinates as a C++ list for (; j <= epts_ctr[k]; j++) { if (!(tt_flags[j] & 1)) { points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j])); } else { points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j])); } } if (points.size() == 0) { // Don't try to access the last element of an empty list continue; } // For any two consecutive off-path points, insert the implied // on-path point. FlaggedPoint prev = points.back(); for (std::list<FlaggedPoint>::iterator it = points.begin(); it != points.end(); it++) { if (prev.flag == OFF_PATH && it->flag == OFF_PATH) { points.insert(it, FlaggedPoint(ON_PATH, (prev.x + it->x) / 2, (prev.y + it->y) / 2)); } prev = *it; } // Handle the wrap-around: insert a point either at the beginning // or at the end that has the same coordinates as the opposite point. // This also ensures that the initial point is ON_PATH. if (points.front().flag == OFF_PATH) { assert(points.back().flag == ON_PATH); points.insert(points.begin(), points.back()); } else { assert(points.front().flag == ON_PATH); points.push_back(points.front()); } // The first point stack(stream, 3); PSMoveto(stream, points.front().x, points.front().y); // Step through the remaining points std::list<FlaggedPoint>::const_iterator it = points.begin(); for (it++; it != points.end(); /* incremented inside */) { const FlaggedPoint& point = *it; if (point.flag == ON_PATH) { stack(stream, 3); PSLineto(stream, point.x, point.y); it++; } else { std::list<FlaggedPoint>::const_iterator prev = it, next = it; prev--; next++; assert(prev->flag == ON_PATH); assert(next->flag == ON_PATH); stack(stream, 7); PSCurveto(stream, prev->x, prev->y, point.x, point.y, next->x, next->y); it++; it++; } } } /* Now, we can fill the whole thing. */ stack(stream, 1); stream.puts( pdf_mode ? "f" : "_cl" ); /* Free our work arrays. */ free(area_ctr); free(check_ctr); free(ctrset); area_ctr = NULL; check_ctr = NULL; ctrset = NULL; } /* end of PSConvert() */
/* ** We call this routine to emmit the PostScript code ** for the character we have loaded with load_char(). */ void GlyphToType3::PSConvert(TTStreamWriter& stream) { int j, k; /* Step thru the contours. * j = index to xcoor, ycoor, tt_flags (point data) * k = index to epts_ctr (which points belong to the same contour) */ for(j = k = 0; k < num_ctr; k++) { // A TrueType contour consists of on-path and off-path points. // Two consecutive on-path points are to be joined with a // line; off-path points between on-path points indicate a // quadratic spline, where the off-path point is the control // point. Two consecutive off-path points have an implicit // on-path point midway between them. std::list<FlaggedPoint> points; // Represent flags and x/y coordinates as a C++ list for (; j <= epts_ctr[k]; j++) { if (!(tt_flags[j] & 1)) { points.push_back(FlaggedPoint(OFF_PATH, xcoor[j], ycoor[j])); } else { points.push_back(FlaggedPoint(ON_PATH, xcoor[j], ycoor[j])); } } if (points.size() == 0) { // Don't try to access the last element of an empty list continue; } // For any two consecutive off-path points, insert the implied // on-path point. FlaggedPoint prev = points.back(); for (std::list<FlaggedPoint>::iterator it = points.begin(); it != points.end(); it++) { if (prev.flag == OFF_PATH && it->flag == OFF_PATH) { points.insert(it, FlaggedPoint(ON_PATH, (prev.x + it->x) / 2, (prev.y + it->y) / 2)); } prev = *it; } // Handle the wrap-around: insert a point either at the beginning // or at the end that has the same coordinates as the opposite point. // This also ensures that the initial point is ON_PATH. if (points.front().flag == OFF_PATH) { assert(points.back().flag == ON_PATH); points.insert(points.begin(), points.back()); } else { assert(points.front().flag == ON_PATH); points.push_back(points.front()); } // The first point stack(stream, 3); PSMoveto(stream, points.front().x, points.front().y); // Step through the remaining points std::list<FlaggedPoint>::const_iterator it = points.begin(); for (it++; it != points.end(); /* incremented inside */) { const FlaggedPoint& point = *it; if (point.flag == ON_PATH) { stack(stream, 3); PSLineto(stream, point.x, point.y); it++; } else { std::list<FlaggedPoint>::const_iterator prev = it, next = it; prev--; next++; assert(prev->flag == ON_PATH); assert(next->flag == ON_PATH); stack(stream, 7); PSCurveto(stream, prev->x, prev->y, point.x, point.y, next->x, next->y); it++; it++; } } } /* Now, we can fill the whole thing. */ stack(stream, 1); stream.puts( pdf_mode ? "f" : "_cl" ); } /* end of PSConvert() */
void PSHeader(XWindowAttributes *info, float requested_scale, int box, int header) { float scale, scalex, scaley; float tx, ty; int bbxmin, bbxmax, bbymin, bbymax; long clock; char headerstr[200]; char *namestr; char *ptr; char clockstr[100]; /* * -------------------------------------------- * calculate translation, scales, bounding box * -------------------------------------------- */ global_window_width = info->width; global_window_height = info->height; /* * calculate the scale factors in inches/screenpixel */ scalex = PAGEWIDTH / global_window_width; scaley = PAGEHEIGHT / global_window_height; /* * use the smaller scale factor so everything will fit on the page */ scale = requested_scale * ((scalex < scaley) ? scalex : scaley); /* * calculate the dots/screenpixel scale factor */ pix_scale = scale * DPI; /* * convert to postscriptpoints/screenpixel */ page_scale = scale * DEFAULTRES; /* * center it on the page for printer output * leave it at (0, 0) for file_output */ if (file_output) { tx = 0.0; ty = 0.0; } else { tx = DEFAULTRES * (PAGEWIDTH - scale * global_window_width) / 2.0; ty = DEFAULTRES * (PAGEHEIGHT - scale * global_window_height) / 2.0; } /* * bounding box */ bbxmin = tx; bbymin = ty; bbxmax = tx + page_scale * global_window_width + 1; bbymax = ty + page_scale * global_window_height + 1; /* * ----------- * COMMENTS * ----------- */ fprintf(PSfp, "%%!\n"); fprintf(PSfp, "%%%%BoundingBox: %d %d %d %d\n", bbxmin, bbymin, bbxmax, bbymax); fprintf(PSfp, "%%%%EndComments\n"); fprintf(PSfp, "initgraphics\n"); fprintf(PSfp, "/M { moveto } def\n"); fprintf(PSfp, "/L { lineto } def\n"); fprintf(PSfp, "/A { arc } def\n"); fprintf(PSfp, "/AN { arcn } def\n"); fprintf(PSfp, "/S { stroke } def\n"); fprintf(PSfp, "/N { newpath } def\n"); fprintf(PSfp, "/C { closepath fill } def\n"); fprintf(PSfp, "/G { setgray } def\n"); if (box) { fprintf(PSfp, "0.5 G\n"); PSNewpath(); PSMoveto(bbxmin, global_window_height - bbymin); PSLineto(bbxmin, global_window_height - bbymax); PSLineto(bbxmax, global_window_height - bbymax); PSLineto(bbxmax, global_window_height - bbymin); PSLineto(bbxmin, global_window_height - bbymin); PSStroke(); fprintf(PSfp, "0 G\n"); } fprintf(PSfp, "%f %f translate\n", tx, ty); fprintf(PSfp, "%f %f scale\n", page_scale, page_scale); if (header) { if ((namestr = getenv("NAME")) == ((char *)NULL)) { namestr = ""; } time(&clock); strcpy(clockstr, ctime(&clock)); if ((ptr = strchr(clockstr, '\n'))) { *ptr = '\0'; } sprintf(headerstr, "%s :: %s :: %s", clockstr, getcwd(NULL, 200), namestr); PSNewpath(); PSFont(9); fprintf(PSfp, "15 15 M\n"); PSShow(headerstr); PSStroke(); } PSNewpath(); PSMoveto(0, 0); PSLineto(0, global_window_height); PSLineto(global_window_width, global_window_height); PSLineto(global_window_width, 0); PSLineto(0, 0); fprintf(PSfp, "eoclip\n"); }
void XPSDrawLines(Display *display, Drawable drawable, GC context, Coord *coord, int ncoords, int mode) { int i; int pcount; int nchunks; int chunksize; if (output_flag == XOUT) { /* * avoid the limit on the length of a multiple line vector * by doing it in multiple calls */ nchunks = (ncoords - 1) / MAXCHUNK + 1; for (i = 0; i < nchunks; i++) { if ((chunksize = (ncoords - i * MAXCHUNK)) > MAXCHUNK) { chunksize = MAXCHUNK; } /* * Draw one point past to connect this chunk with the * next. Don't do it for the last chunk. */ if (i < nchunks - 1) chunksize++; XDrawLines(display, drawable, context, (XPoint *)(coord + i * MAXCHUNK), chunksize, mode); } } else { XGCValues values; XGetGCValues(display, context, GCForeground | GCLineWidth, &values); if (ncoords <= 0) { return; } PSNewpath(); PSSetPixel(display, values.foreground); PSSetLineWidth(values.line_width); PSMoveto(coord[0].x, coord[0].y); pcount = 0; for (i = 1; i < ncoords; i++) { if ((coord[i].x == coord[i - 1].x) && (coord[i].y == coord[i - 1].y) && i < ncoords - 1) { continue; } PSLineto(coord[i].x, coord[i].y); /* * break it up into managable cuhnks */ if (pcount > MAXSTROKES) { PSStroke(); PSNewpath(); PSMoveto(coord[i].x, coord[i].y); pcount = 0; } pcount++; } PSStroke(); } }