[comp.sources.misc] v06i008: HPGL to PostScript converter

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (01/22/89)

Posting-number: Volume 6, Issue 8
Submitted-by: federico@actisb.UUCP (Federico Heinz)
Archive-name: yahp2ps/part06

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 6 (of 6)."
# Contents:  mchinery.c
# Wrapped by federico@actisb on Wed Jan  4 13:34:50 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'mchinery.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mchinery.c'\"
else
echo shar: Extracting \"'mchinery.c'\" \(13950 characters\)
sed "s/^X//" >'mchinery.c' <<'END_OF_FILE'
X/*
X        HPGL to PostScript converter
X   Copyright (C) 1988 (and following) Federico Heinz
X
Xyahp2ps is distributed in the hope that it will be useful, but WITHOUT ANY
XWARRANTY.  No author or distributor accepts responsibility to anyone
Xfor the consequences of using it or for whether it serves any
Xparticular purpose or works at all, unless he says so in writing.
XRefer to the Free Software Foundation's General Public License for full details.
X
XEveryone is granted permission to copy, modify and redistribute yahp2ps,
Xbut only under the conditions described in the GNU General Public
XLicense.  A copy of this license is supposed to have been given to you
Xalong with yahp2ps so you can know your rights and responsibilities.  It
Xshould be in a file named COPYING.  Among other things, the copyright
Xnotice and this notice must be preserved on all copies.
X
XIn other words, go ahead and share yahp2ps, but don't try to stop
Xanyone else from sharing it farther.  Help stamp out software hoarding!
X
Xyahp2ps is TOTALLY unrelated to GNU or the Free Software Foundation,
Xit is only released under the same conditions.
X
X    For bug reports, wishes, etc. send e-mail to
X
X    ...!mcvax!unido!tub!actisb!federico  (from Europe)
X    ...!uunet!pyramid!actisb!federico    (from anywhere else)
X
X    For Physical mail:
X
X    Federico Heinz
X    Beusselstr. 21
X    1000 Berlin 21
X
X    Tel. (+49 30) 396 77 92
X
X*/
X/***************************************************************************
X   Mapping of plotter primitives onto PostScript. All coordinates are
X   considered to be in plotter space.
X
X***************************************************************************/
X
X#include <stdio.h>
X#include "defs.h"
X#include "penctrl.h"
X#include "io.h"
X#include "mchinery.h"
X#include "circle.h"
X#include "shade.h"
X
X
Xstatic Number PenWidth;		/* Current pen's width in plotter units */
Xstatic Number PenColor;		/* Current Pen's color			*/
Xstatic Boolean StrokePending;   /* Should a stroke be done on penUp?    */
X
Xstatic Boolean PenWidthChange;	/* Pen width changed (for delayed change) */
Xstatic Boolean PatternChange;	/* Pattern changed (for delayed change)   */
Xstatic Boolean ColorChange;	/* Color changed (for delayed change)	  */
X
X
X/************************************************************************
X
X   Different line patterns.
X
X***********************************************************************/
X
X
X
Xstatic void pattern1(length)
X
XNumber length;
X
X{ if (length <= PenWidth) return;
X  writeNumber(Zero);
X  writeNumber(length);
X}
X
X
X
Xstatic void pattern2(length)
X
XNumber length;
X
X{ Number halfLength;
X
X  halfLength = length/2;
X  if (halfLength <= PenWidth) return;
X  writeNumber(halfLength);
X  writeNumber(halfLength);
X}
X
X
X
Xstatic void pattern3(length)
X
XNumber length;
X
X{ Number threeQuarterLength;
X
X  if (length/4 <= PenWidth) return;
X  threeQuarterLength = (3 * length) / 4;
X  writeNumber(threeQuarterLength);
X  writeNumber(length - threeQuarterLength);
X}
X
X
X
Xstatic void pattern4(length)
X
XNumber length;
X
X{ Number fourFifthLength, whiteSpace;
X
X  fourFifthLength = (4 * length) / 5;
X  whiteSpace = (length - fourFifthLength - PenWidth) / 2;
X  if (whiteSpace <= PenWidth) return;
X  writeNumber(fourFifthLength);
X  writeNumber(whiteSpace);
X  writeNumber(Zero);
X  writeNumber(length - (fourFifthLength + whiteSpace));
X}
X
X
X
Xstatic void pattern5(length)
X
XNumber length;
X
X{ Number threeQuarterLength, dashLength;
X
X  threeQuarterLength = (3 * length) / 4;
X  dashLength = (length - threeQuarterLength) / 3;
X  if (dashLength <= PenWidth) return;
X  writeNumber(threeQuarterLength);
X  writeNumber(dashLength);
X  writeNumber(dashLength);
X  writeNumber(length - (threeQuarterLength + 2 * dashLength));
X}
X
X
X
Xstatic void pattern6(length)
X
XNumber length;
X
X{ Number halfLength, dashLength;
X
X  halfLength = length/2;
X  dashLength = halfLength/5;
X  if (dashLength <= PenWidth) return;
X  writeNumber(halfLength);
X  writeNumber(dashLength);
X  writeNumber(dashLength);
X  writeNumber(dashLength);
X  writeNumber(dashLength);
X  writeNumber(length - (halfLength + 4 * dashLength));
X}
X
X
X
Xtypedef void (*DashFnct)();
X
Xstatic DashFnct DashPattern[] =
X	{ pattern1, pattern2, pattern3,
X	  pattern4, pattern5, pattern6 };
X
X
Xstatic DashFnct NewDashFnct;	/* Pointer to function to change pattern */
Xstatic Number PatternLength;	/* Total length of a cicle		 */
X
X
X/*
X
X  Change the line pattern.
X
X*/
X
Xvoid setPattern(pattern, patternLength)
X
XNumber pattern, patternLength;
X
X{ if ((pattern > Zero) && (pattern != FullLine))
X    NewDashFnct = DashPattern[(pattern/One)-1];
X  else
X    NewDashFnct = NULL;
X  PatternLength = patternLength;
X  PatternChange = True;
X}
X
X
X
X/***************************************************************************
X
X   PostScript pen control.
X
X***************************************************************************/
X
X
X
X/*
X
X  Draw a line for internal purposes. Call only after doing a stroke()!
X
X*/
X
Xstatic void invisibleLine(toX, toY)
X
X{ writeNumber(toX);
X  writeNumber(toY);
X  writeString("L\n");
X}
X
X
X
X/*
X
X  Do the real ink-dropping if needed.
X
X*/
X
Xvoid stroke()
X
X{ if (StrokePending)
X  { if (PenWidthChange)
X    { writeNumber(PenWidth);
X      writeString("W\n");
X      PenWidthChange = False;
X    }
X    if (ColorChange)
X    { writeNumber(PenColor);
X      writeString("G\n");
X      ColorChange = False;
X    }
X    if (PatternChange)
X    { writeString("[");
X      if (NewDashFnct != NULL)
X        (*NewDashFnct)(PatternLength);
X      writeString("] D\n");
X      PatternChange = False;
X    }
X    writeString("S\n");
X    StrokePending = False;
X  }
X}
X
X
X
X/*
X
X  Draw a line from the current pen position to the target.
X
X*/
X
Xvoid drawLine(targetX, targetY)
X
XNumber targetX, targetY;
X
X{ writeNumber(targetX);
X  writeNumber(targetY);
X  writeString("L\n");
X  StrokePending = True;
X}
X
X
X/*
X
X  Draw a dot at current pen position.
X
X*/
X
Xvoid drawDot()
X{ writeString("CD\n");
X}
X
X
X/*
X
X  Move the PostScript pen to the specified coordinates.
X
X*/
X
Xvoid setCurrentPoint(targetX, targetY)
X
XNumber targetX, targetY;
X
X{ writeNumber(targetX);
X  writeNumber(targetY);
X  writeString("M\n");
X}
X
X
X/**************************************************************************
X
X  Rotate/unrotate coordinate System
X
X**************************************************************************/
X
X/*
X
X   Rotate the coordinate system.
X
X*/
X
Xvoid doRotation()
X
X{ writeString("POR\n"); }
X
X
X
X/*
X
X  Undo the rotation.
X
X*/
X
Xvoid undoRotation()
X
X{ writeString("LND\n"); }
X 
X
X
X/**************************************************************************
X
X   Set/reset clipping path.
X
X**************************************************************************/
X
Xstatic CoordinatePair ClipCorner1, ClipCorner2;
X
X
X/*
X
X  Set the clipping window to the given rectangle.
X
X*/
X
Xvoid setClip(corner1, corner2)
X
XCoordinatePair corner1, corner2;
X
X{ Boolean penWasDown;
X
X  if (penWasDown = !PenIsUp)
X    liftPen();
X  writeString("RC\n");
X  setCurrentPoint(corner1[X], corner1[Y]);
X  invisibleLine(corner1[X], corner2[Y]);
X  invisibleLine(corner2[X], corner2[Y]);
X  invisibleLine(corner2[X], corner1[Y]);
X  invisibleLine(corner1[X], corner1[Y]);
X  writeString("SC\n");
X  ClipCorner1[X] = corner1[X];
X  ClipCorner1[Y] = corner1[Y];
X  ClipCorner2[X] = corner2[X];
X  ClipCorner2[Y] = corner2[Y];
X  if (penWasDown)
X    lowerPen();
X}
X
X
X
X/*
X
X  Make sure the clipping path is the one that was last set.
X
X*/
X
Xvoid correctClip()
X
X{ setClip(ClipCorner1, ClipCorner2);
X}
X
X
X/**************************************************************************
X
X  Initialize/shut down the machinery
X
X***************************************************************************/
X
Xchar *PreludeFile = DEFAULT_PRELUDE;
X
X
Xvoid initializeMachinery()
X
X{ FILE *fp;
X  char c;
X
X  if (PreludeFile == NULL) return;
X  if ((fp = fopen(PreludeFile, "r")) == NULL)
X    error("Cannot open prelude file.");
X  while ((c = getc(fp)) != EOF)
X    putChar(c);
X  fclose(fp);
X}
X
X
X
Xvoid shutdownMachinery()
X
X{ stroke();
X  writeString("showpage\n");
X}
X
X
X
X/**************************************************************************
X
X  Change the parameters of the pen we're plotting with.
X
X**************************************************************************/
X
X
X/*
X
X  From now on, the pen will be 'width' mm thick.
X
X*/
X
Xvoid setPenWidth(width)
X
XNumber width;
X
X{ PenWidth = width * PlotterUnitsFactor;
X  PenWidthChange = True;
X}
X
X
X
X/*
X
X  From now on, the pen has the given color.
X
X*/
X
Xvoid setPenColor(color)
X
XNumber color;
X
X{ PenColor = color;
X  ColorChange = True;
X}
X
X
X
X/**************************************************************************
X
X  Filling squares & wedges
X
X**************************************************************************/
X
X
X
Xstatic void fillPath(fillType, spacing, angle)
X
XNumber fillType, spacing, angle;
X
X{ writeString("C ");
X  if (fillType < ParallelLines)
X    writeString("fill\n");
X  else
X  { writeString("gsave clip\n");
X    if (angle)
X    { writeNumber(angle);
X      writeString("R\n");
X    }
X    writeString("T ");
X    writeNumber(spacing);
X    if (fillType == ParallelLines)
X      writeString("false ");
X    else
X      writeString("true ");
X    writeString("H\n");
X  }
X}
X
X
X
X/*
X
X  Shade a rectangle with one corner at current position and the opposite
X  at the specified absolute (but maybe User) CoordinatePair.
X
X*/
X
X
Xvoid doShadeRectangle(oppositeCorner, fillType, spacing, angle)
X
XCoordinatePair oppositeCorner;
XNumber fillType, spacing, angle;
X
X{ CoordinatePair thisCorner;
X  Boolean penWasDown;
X
X  if (penWasDown = !PenIsUp)
X    liftPen();
X  setCurrentPoint(PenPosition[X], PenPosition[Y]);
X  thisCorner[X] = PenPosition[X]; thisCorner[Y] = PenPosition[Y];
X  invisibleLine(plotterXCoord(thisCorner[X]), 
X                plotterYCoord(oppositeCorner[Y]));
X  invisibleLine(plotterXCoord(oppositeCorner[X]),
X                plotterYCoord(oppositeCorner[Y]));
X  invisibleLine(plotterXCoord(oppositeCorner[X]),
X                plotterYCoord(thisCorner[Y]));
X  invisibleLine(plotterXCoord(thisCorner[X]),
X                plotterYCoord(thisCorner[Y]));
X  fillPath(fillType, spacing, angle);
X  if (penWasDown) lowerPen();
X}
X
X
X/*
X
X  Shade a circle wedge.
X  The chordAngle should divide the sweepAngle and (of course)
X  be != 0. If it does not divide the sweepAngle, then the last chord
X  will be shorter.
X
X*/
X
Xvoid doShadeWedge(center, radius, startAngle, sweepAngle, chordAngle,
X		fillType, spacing, angle)
X
XCoordinatePair center;
XNumber radius, startAngle, sweepAngle, chordAngle;
X
X{ Number currentAngle, endAngle;
X  CoordinatePair thisPoint;
X  Boolean penWasDown;
X  int times;
X
X  if (penWasDown = !PenIsUp)
X    liftPen();
X  else
X    setCurrentPoint(plotterXCoord(PenPosition[X]),
X                    plotterYCoord(PenPosition[Y]));
X  polarToCartesian(thisPoint, center, radius, startAngle);
X  invisibleLine(plotterXCoord(thisPoint[X]),
X                plotterYCoord(thisPoint[Y]));
X  times = sweepAngle / chordAngle;
X  if (times < 0)
X  { chordAngle = -chordAngle;
X    times = -times;
X  }
X  currentAngle = startAngle;
X  while (times--)
X  { currentAngle = currentAngle + chordAngle;
X    polarToCartesian(thisPoint, center, radius, currentAngle);
X    invisibleLine(plotterXCoord(thisPoint[X]),
X                  plotterYCoord(thisPoint[Y]));
X  }
X  if (sweepAngle % chordAngle)
X  { polarToCartesian(thisPoint, center, radius, startAngle + sweepAngle);
X    invisibleLine(thisPoint[X], thisPoint[Y]);
X  }
X  invisibleLine(plotterXCoord(center[X]),
X                plotterYCoord(center[Y]));
X  fillPath(fillType, spacing, angle);
X  if (penWasDown) lowerPen();
X}
X
X
X
X/*****************************************************************************
X
X    Maximum resolution arc stuff
X
X*****************************************************************************/
X
X
X
X/*
X
X  Distort plotter space so as to reflex the user coordinate system. This is
X  intended as a means for doing arcs at maximum resolution in user space.
X  IT IS NOT ALLOWED TO DO TWO distortSpace CALLS IN A ROW. The only way is
X  distort, undistort, and distort again.
X
X*/
X
Xstatic void distortSpace()
X
X{ writeNumber(XScaleFactor);
X  writeNumber(YScaleFactor);
X  writeNumber(XOrigin);
X  writeNumber(YOrigin);
X  writeString("TS\n");
X}
X
X
X
X/*
X
X  Undo the distortion caused by the last call to distortSpace.
X
X*/
X
Xstatic void undistortSpace()
X
X{ writeString("SSM\n");
X}
X
X
X
X/*
X
X   Do an arc at maximum resolution. Center and radius are in user units.
X
X*/
X
Xvoid doHRArc(center, radius, startAngle, sweepAngle)
X
X{ if (UserMode)
X    distortSpace();
X  writeCoordinatePair(center);
X  writeNumber(radius);
X  writeNumber(startAngle);
X  writeNumber(startAngle + sweepAngle);
X  writeString("A\n");
X  StrokePending = True;
X  if (UserMode)
X    undistortSpace();
X}
X
X
X
X/****************************************************************************
X
X  Tick drawing. At list one of the legths must be != Zero.
X
X****************************************************************************/
X
X
X
X/*
X
X  Draw a tick.
X
X*/
X
Xstatic void drawTick(fromX, fromY, toX, toY)
X
XNumber fromX, fromY, toX, toY;
X
X{ writeString("TB ");
X  writeNumber(fromX);
X  writeNumber(fromY);
X  writeString("M ");
X  writeNumber(toX);
X  writeNumber(toY);
X  writeString("TE\n");
X}
X
X
X
X/*
X
X  Do a horizontal tick.
X
X*/
X
Xvoid doYTick(positiveLength, negativeLength)
X
XNumber positiveLength, negativeLength;
X
X{ Number plotterXPenPosition, plotterYPenPosition;
X
X  plotterXPenPosition = plotterXCoord(PenPosition[X]);
X  plotterYPenPosition = plotterYCoord(PenPosition[Y]);
X  drawTick(plotterXPenPosition - negativeLength, plotterYPenPosition,
X           plotterXPenPosition + positiveLength, plotterYPenPosition);
X}
X
X
X
X/*
X
X  Do a vertical tick.
X
X*/
X
Xvoid doXTick(positiveLength, negativeLength)
X
XNumber positiveLength, negativeLength;
X
X{ Number plotterXPenPosition, plotterYPenPosition;
X
X  plotterXPenPosition = plotterXCoord(PenPosition[X]);
X  plotterYPenPosition = plotterYCoord(PenPosition[Y]);
X  drawTick(plotterXPenPosition, plotterYPenPosition - negativeLength,
X           plotterXPenPosition, plotterYPenPosition + positiveLength);
X}
X
END_OF_FILE
if test 13950 -ne `wc -c <'mchinery.c'`; then
    echo shar: \"'mchinery.c'\" unpacked with wrong size!
fi
# end of 'mchinery.c'
fi
echo shar: End of archive 6 \(of 6\).
cp /dev/null ark6isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0