home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume6 / yahp2ps / part05 / penctrl.c < prev   
C/C++ Source or Header  |  1989-02-03  |  12KB  |  568 lines

  1. /*
  2.         HPGL to PostScript converter
  3.    Copyright (C) 1988 (and following) Federico Heinz
  4.  
  5. yahp2ps is distributed in the hope that it will be useful, but WITHOUT ANY
  6. WARRANTY.  No author or distributor accepts responsibility to anyone
  7. for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.
  9. Refer to the Free Software Foundation's General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute yahp2ps,
  12. but only under the conditions described in the GNU General Public
  13. License.  A copy of this license is supposed to have been given to you
  14. along with yahp2ps so you can know your rights and responsibilities.  It
  15. should be in a file named COPYING.  Among other things, the copyright
  16. notice and this notice must be preserved on all copies.
  17.  
  18. In other words, go ahead and share yahp2ps, but don't try to stop
  19. anyone else from sharing it farther.  Help stamp out software hoarding!
  20.  
  21. yahp2ps is TOTALLY unrelated to GNU or the Free Software Foundation,
  22. it is only released under the same conditions.
  23.  
  24.     For bug reports, wishes, etc. send e-mail to
  25.  
  26.     ...!mcvax!unido!tub!actisb!federico  (from Europe)
  27.     ...!uunet!pyramid!actisb!federico    (from anywhere else)
  28.  
  29.     For Physical mail:
  30.  
  31.     Federico Heinz
  32.     Beusselstr. 21
  33.     1000 Berlin 21
  34.  
  35.     Tel. (+49 30) 396 77 92
  36.  
  37. */
  38.  
  39. /***************************************************************************
  40.  
  41.   Primitive pen control routines. Provides the interface between the
  42.   ideal plotter and the machinery.
  43.  
  44. ****************************************************************************/
  45.  
  46. #include "defs.h"
  47. #include "mchinery.h"
  48. #include "penctrl.h"
  49. #include "circle.h"
  50. #include "tick.h"
  51. #include "io.h"
  52.  
  53.  
  54. /***************************************************************************
  55.  
  56.    Data defining the plotter's status.
  57.  
  58. ***************************************************************************/
  59.  
  60.  
  61.                     /* Current plotting pen's coordinates */
  62. CoordinatePair PenPosition = { Zero, Zero };
  63.  
  64.                                      /* Pn's position in User Space */
  65. static CoordinatePair UserP1, UserP2;
  66.  
  67.                                      /* Pn's coords in Plotter Space */
  68. CoordinatePair PlotterP1, PlotterP2;
  69.  
  70.                      /* P1-P2 distance              */
  71. Number      P1P2Diagonal;
  72.  
  73.                      /* Size of paper in use        */
  74. static int        PaperSize = A4;
  75.  
  76. static Number LineType;            /* Line type used for stroking */
  77. static Number LinePatternLength;   /* Length of a pattern cicle   */
  78. static Number PenHeld = Zero;      /* Pen we're holding           */
  79.  
  80.  
  81.        Boolean UserMode = False;     /* Plotting in User Space?           */
  82. static Boolean Rotated = False;      /* Is the plot rotated 90 degrees?   */
  83.        Boolean PenIsUp = True;       /* Is the plotting pen up?           */
  84. static Boolean LineDrawn = False;    /* Have we drawn a line?          */
  85.  
  86. CoordinatePair FurthestPoint[] = { { MaxXA,  MaxYA },
  87.                                    { MaxXA4, MaxYA4 },
  88.                                    { MaxXB,  MaxYB },
  89.                                    { MaxXA3, MaxXA3 } };
  90.  
  91. CoordinatePair FurthestPointRotated[] =
  92.                                  { { MaxYA,  MaxXA },
  93.                                    { MaxYA4, MaxXA4 },
  94.                                    { MaxYB,  MaxXB },
  95.                                    { MaxXA3, MaxXA3 } };
  96.  
  97. CoordinatePair DefaultP1[] = { {InitialP1XA,  InitialP1YA},
  98.                    {InitialP1XA4, InitialP1YA4},
  99.                    {InitialP1XB,  InitialP1YB},
  100.                    {InitialP1XA3, InitialP1YA3} };
  101.  
  102. CoordinatePair DefaultP2[] = { {InitialP2XA,  InitialP2YA},
  103.                    {InitialP2XA4, InitialP2YA4},
  104.                    {InitialP2XB,  InitialP2YB},
  105.                    {InitialP2XA3, InitialP2YA3} };
  106.  
  107. CoordinatePair DefaultP1Rotated[] =
  108.                              { {InitialP1XAR,  InitialP1YAR},
  109.                    {InitialP1XA4R, InitialP1YA4R},
  110.                    {InitialP1XBR,  InitialP1YBR},
  111.                    {InitialP1XA3R, InitialP1YA3R} };
  112.  
  113. CoordinatePair DefaultP2Rotated[] =
  114.                              { {InitialP2XAR,  InitialP2YAR},
  115.                    {InitialP2XA4R, InitialP2YA4R},
  116.                    {InitialP2XBR,  InitialP2YBR},
  117.                    {InitialP2XA3R, InitialP2YA3R} };
  118.  
  119.  
  120. /**************************************************************************
  121.  
  122.    Paper size.
  123.  
  124. /*************************************************************************/
  125.  
  126.  
  127. void changePaperSize(newPaperSize)
  128.  
  129. int newPaperSize;
  130.  
  131. { PaperSize = newPaperSize; }
  132.  
  133.  
  134.  
  135. /***************************************************************************
  136.  
  137.    Pen changing.
  138.  
  139. ***************************************************************************/
  140.  
  141. /*
  142.  
  143.   Each pen's width and color.
  144.  
  145. */
  146.   
  147. static Number PenWidth[MaxPen/One] = { 2500, 3500, 5000,
  148.                        7500, 10000, 20000 };
  149. static Number PenColor[MaxPen/One] = { Zero, Zero, Zero, Zero, Zero, Zero };
  150.  
  151.  
  152.  
  153. /*
  154.  
  155.   Change the pen sizes.
  156.  
  157. */
  158.  
  159. void getPenSizes(string)
  160.  
  161. char *string;
  162.  
  163. { int i;
  164.  
  165.   i = 0;
  166.   while (*string && (i < (MaxPen/One)))
  167.     if (!ASCIIToNumber(&PenWidth[i++], &string))
  168.       error("Illegal pen width.");
  169. }
  170.  
  171.  
  172.  
  173. /*
  174.  
  175.   Get a new pen
  176.  
  177.  */
  178.  
  179. void changePen(pen)
  180.  
  181. Number pen;
  182.  
  183. { Boolean penWasDown;
  184.   int oldPen;
  185.  
  186.   if (pen == PenHeld)
  187.     return;
  188.   if ((penWasDown = !PenIsUp)) liftPen();
  189.   if ((pen > Zero) && (pen <= MaxPen))
  190.   { oldPen = (PenHeld/One) - 1;
  191.     PenHeld = pen;
  192.     pen = (pen / One ) - 1;
  193.     if (PenWidth[pen] != PenWidth[oldPen])
  194.       setPenWidth(PenWidth[pen]);
  195.     if (PenColor[pen] != PenColor[oldPen])
  196.       setPenColor(PenColor[pen]);
  197.   }
  198.   else if (!pen)
  199.     PenHeld = Zero;
  200.   else
  201.     warning("Pen number out of range.");
  202.   if (penWasDown) lowerPen();
  203. }
  204.  
  205.  
  206.  
  207. /*
  208.  
  209.   Update the pattern to new parameters.
  210.  
  211. */
  212.  
  213. static void updateLinePattern()
  214.  
  215. { Boolean penWasDown;
  216.  
  217.   if ((penWasDown = !PenIsUp)) liftPen();
  218.   setPattern(LineType, mulNum(LinePatternLength, P1P2Diagonal)/100);
  219.   if (penWasDown) lowerPen();
  220. }
  221.  
  222.  
  223.  
  224. /*
  225.  
  226.   Change the line pattern
  227.  
  228.  */
  229.  
  230. void setDash(pattern, patternLength)
  231.  
  232. Number pattern, patternLength;
  233.  
  234. { Boolean penWasDown;
  235.  
  236.   if ((LineType == pattern) &&
  237.       ((patternLength <= 0) ||
  238.        (patternLength >= (128*One)) ||
  239.        (patternLength == LinePatternLength)))
  240.     return;
  241.   if ((patternLength > 0) && (patternLength < (128*One)))
  242.     LinePatternLength = patternLength;
  243.   LineType = pattern;
  244.   updateLinePattern();
  245. }
  246.  
  247.  
  248.  
  249. /**************************************************************************
  250.  
  251.    Clipping rectangle.
  252.  
  253. **************************************************************************/
  254.  
  255. static CoordinatePair Origin = { Zero, Zero };
  256.  
  257.  
  258. /*
  259.  
  260.   Set a new clipping rectangle.
  261.  
  262. */
  263.  
  264. void setWindow(corner1, corner2)
  265.  
  266. CoordinatePair corner1, corner2;
  267.  
  268. { setClip(corner1, corner2); }
  269.  
  270.  
  271.  
  272. /*
  273.  
  274.   Set the clipping rectangle to the whole plotting area.
  275.  
  276. */
  277.  
  278. void resetWindow()
  279.  
  280.   if (Rotated)
  281.     setWindow(Origin, FurthestPointRotated[PaperSize]);
  282.   else
  283.     setWindow(Origin, FurthestPoint[PaperSize]);
  284. }
  285.  
  286.  
  287.  
  288. /**************************************************************************
  289.  
  290.   Scaling of User Space.
  291.  
  292. **************************************************************************/
  293.  
  294.  
  295. /* Parameters for scaling */
  296.  
  297. Number XScaleFactor = One, YScaleFactor = One;
  298. Number XOrigin = Zero, YOrigin = Zero;
  299.  
  300.  
  301.  
  302. /*
  303.  
  304.   Convert from plotter coordinates to user coordinates.
  305.  
  306. */
  307.  
  308. static void plotterToUser(target, plotterPoint)
  309.  
  310. CoordinatePair target, plotterPoint;
  311.  
  312. {
  313.   target[X] = divNum(plotterPoint[X] - XOrigin, XScaleFactor);
  314.   target[Y] = divNum(plotterPoint[Y] - YOrigin, YScaleFactor);
  315. }
  316.  
  317.  
  318.  
  319. /*
  320.  
  321.   Set the scaling parameters to the appropriate values.
  322.  
  323. */
  324.  
  325. void updateScaling()
  326.  
  327. { CoordinatePair plotterPenPosition;
  328.  
  329.   if (UserMode)
  330.   { plotterPenPosition[X] = plotterXCoord(PenPosition[X]);
  331.     plotterPenPosition[Y] = plotterYCoord(PenPosition[Y]);
  332.     XScaleFactor = divNum((PlotterP2[X] - PlotterP1[X]),
  333.                           (UserP2[X] - UserP1[X]));
  334.     XOrigin = PlotterP1[X] - mulNum(XScaleFactor, UserP1[X]);
  335.     YScaleFactor = divNum((PlotterP2[Y] - PlotterP1[Y]),
  336.                           (UserP2[Y] - UserP1[Y]));
  337.     YOrigin = PlotterP1[Y] - mulNum(YScaleFactor, UserP1[Y]);
  338.     plotterToUser(PenPosition, plotterPenPosition);
  339.   }
  340. }
  341.  
  342.  
  343.  
  344. /*
  345.  
  346.   From now on, coordinates won't be scaled any more.
  347.  
  348. */
  349.  
  350. void turnScalingOff()
  351.  
  352. { PenPosition[X] = plotterXCoord(PenPosition[X]);
  353.   PenPosition[Y] = plotterYCoord(PenPosition[Y]);
  354.   UserMode = False;
  355. }
  356.  
  357.  
  358.  
  359. /*
  360.  
  361.   From now on, coordinates will be scaled according to the user's taste.
  362.  
  363. */
  364.  
  365. void turnScalingOn(newUserP1, newUserP2)
  366.  
  367. CoordinatePair newUserP1, newUserP2;
  368.  
  369. { if ((newUserP1[X] == newUserP2[X]) || (newUserP1[Y] == newUserP2[Y]))
  370.     warning("Invalid scale parameters.");
  371.   else
  372.   { UserMode = True;
  373.     UserP1[X] = newUserP1[X];
  374.     UserP1[Y] = newUserP1[Y];
  375.     UserP2[X] = newUserP2[X];
  376.     UserP2[Y] = newUserP2[Y];
  377.     updateScaling();
  378.   }
  379. }
  380.  
  381.  
  382.  
  383. /*
  384.  
  385.   Change the scaling points and update everything needed.
  386.  
  387. */
  388.  
  389. void changeP1P2(newP1, newP2)
  390.  
  391. CoordinatePair newP1, newP2;
  392.  
  393. { Number dummy;
  394.   CoordinatePair delta;
  395.   
  396.   PlotterP1[X] = newP1[X];
  397.   PlotterP1[Y] = newP1[Y];
  398.   PlotterP2[X] = newP2[X];
  399.   PlotterP2[Y] = newP2[Y];
  400.   delta[X] = PlotterP2[X] - PlotterP1[X];
  401.   delta[Y] = PlotterP2[Y] - PlotterP1[Y];
  402.   cartesianToPolar(&P1P2Diagonal, &dummy, delta);
  403.   updateScaling();
  404.   updateTicks();
  405.   updateLinePattern();
  406. }
  407.  
  408.  
  409.  
  410. /*
  411.  
  412.   Rotate the coordinate system.
  413.  
  414. */
  415.  
  416. void rotate()
  417.  
  418. { CoordinatePair plotterPenPosition;
  419.   
  420.   if (!Rotated)
  421.   { plotterPenPosition[Y] = plotterXCoord(PenPosition[X]);
  422.     plotterPenPosition[X] = FurthestPoint[PaperSize][Y] -
  423.                                 plotterYCoord(PenPosition[Y]);
  424.     plotterToUser(PenPosition, plotterPenPosition);
  425.     doRotation();
  426.     correctClip();
  427.     Rotated = True;
  428.   }
  429. }
  430.  
  431.  
  432.  
  433. /*
  434.  
  435.   Return paper to default orientation.
  436.  
  437. */
  438.  
  439. void unRotate()
  440.  
  441. { CoordinatePair plotterPenPosition;
  442.   
  443.   if (Rotated)
  444.   { plotterPenPosition[X] = plotterYCoord(PenPosition[Y]);
  445.     plotterPenPosition[Y] = FurthestPoint[PaperSize][Y] -
  446.                                 plotterXCoord(PenPosition[X]);
  447.     plotterToUser(PenPosition, plotterPenPosition);
  448.     undoRotation();
  449.     correctClip();
  450.     Rotated = False;
  451.   }
  452. }
  453.  
  454.  
  455. /**************************************************************************
  456.  
  457.   Plotter status initialization.
  458.  
  459. **************************************************************************/
  460.  
  461.  
  462.  
  463. /*
  464.  
  465.   Set the scaling points to the default values.
  466.  
  467. */
  468.  
  469. void resetP1P2()
  470.  
  471. { if (Rotated)
  472.     changeP1P2(DefaultP1Rotated[PaperSize], DefaultP2Rotated[PaperSize]);
  473.   else
  474.     changeP1P2(DefaultP1[PaperSize], DefaultP2[PaperSize]);
  475. }
  476.  
  477.  
  478. /*
  479.  
  480.   Set default parameters of this module's stuff.
  481.  
  482. */
  483.  
  484. void penctrlInit()
  485.  
  486. { liftPen();
  487.   resetP1P2();
  488.   unRotate();
  489. }
  490.  
  491.  
  492.  
  493. /**************************************************************************
  494.  
  495.   Moving the pen around.
  496.  
  497. **************************************************************************/
  498.  
  499.  
  500.  
  501. /*
  502.  
  503.   Move the logical pen in it's current state to some place in User Space.
  504.  
  505. */
  506.  
  507. void doLine(targetX, targetY)
  508.  
  509. Number targetX, targetY;
  510.  
  511. { Number absoluteTargetX, absoluteTargetY;
  512.  
  513.   if (!PenIsUp && PenHeld)
  514.   { LineDrawn = True; 
  515.     if (LineType)
  516.       drawLine(plotterXCoord(targetX),
  517.                plotterYCoord(targetY));
  518.     else            /* Linetype 0: just dots at coords */
  519.     { liftPen();
  520.       PenPosition[X] = targetX;
  521.       PenPosition[Y] = targetY;
  522.       lowerPen();
  523.       return;
  524.     }
  525.   }
  526.   PenPosition[X] = targetX;
  527.   PenPosition[Y] = targetY;
  528. }
  529.  
  530.  
  531.  
  532. /*
  533.  
  534.   Lift the plotting pen.
  535.  
  536. */
  537.  
  538. void liftPen()
  539.  
  540. { if (!PenIsUp)
  541.   { if (LineDrawn)
  542.       LineDrawn = False;
  543.     else
  544.       if (PenHeld)
  545.         drawDot();
  546.     stroke();
  547.     PenIsUp = True;
  548.   }
  549. }
  550.  
  551.  
  552.  
  553. /*
  554.  
  555.   Lower the plotting pen. At least a dot is plotted.
  556.  
  557. */
  558.  
  559. void lowerPen()
  560.  
  561. { if (PenIsUp)
  562.   { setCurrentPoint(plotterXCoord(PenPosition[X]),
  563.                     plotterYCoord(PenPosition[Y]));
  564.     PenIsUp = False;
  565.   }
  566. }
  567.