1 /* This file is part of the GNU plotutils package.  Copyright (C) 1995,
2    1996, 1997, 1998, 1999, 2000, 2005, 2008, Free Software Foundation, Inc.
3 
4    The GNU plotutils package is free software.  You may redistribute it
5    and/or modify it under the terms of the GNU General Public License as
6    published by the Free Software foundation; either version 2, or (at your
7    option) any later version.
8 
9    The GNU plotutils package is distributed in the hope that it will be
10    useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License along
15    with the GNU plotutils package; see the file COPYING.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin St., Fifth Floor,
17    Boston, MA 02110-1301, USA. */
18 
19 /* This file contains the low-level _pl_t_tek_vector() method, which takes
20    two integer arguments and writes them, in the format used by a Tektronix
21    4014 terminal for addresses while in vector or point-plot mode, to a
22    specified output stream.  It is called by several TekPlotter methods.
23 
24    Original Tek 4014 resolution was 1024 by 1024, with 1024 by 780
25    displayable, i.e. 0x400 by 0x30c.  Extended (EGM) resolution, supported
26    by 4014's with the Enhanced Graphics Module, is four times that: 4096 by
27    3120.  This is the resolution of the xterm Tektronix emulator.
28 
29    With EGM, have an allowed range of 12 bits (0 <= x,y <=4095).  A Tek
30    code for a point address (x,y) consists of a sequence of bytes:
31 
32    	[Hi_Y] [EGM] [Lo_Y] [Hi_X] Lo_X.
33 
34    Since the EGM byte was added later, to improve resolution, it contains
35    the lowest 2 bits of each of the X and Y bytes, packed into the lowest
36    four bits of the byte.  The remaining 10 bits are subdivided as follows
37    among the remaining four code bytes.  Lo=lowest 5 of the 10 bits,
38    Hi=highest 5 of the 10 bits, all packed into the lowest 5 bits of the
39    byte.  Code bytes are distinguished from each other by the pattern of
40    the high three bits.  (Hi_Y = ?01, EGM = ?11, Lo_Y = ?11, Hi_X = ?01,
41    Lo_X = ?10, where ? is ignored [or should be].)  If EGM is included then
42    Lo_Y must be included to prevent ambiguity.  Also if Hi_X is included
43    then Lo_Y must be included.
44 
45    If a byte is omitted, then its value defaults to the value of the
46    corresponding byte in the most recently received point.  The exception
47    is the EGM byte; if omitted, it defaults to zero.
48 
49    Warning: some emulators, the xterm emulator in particular, get this
50    scheme wrong.  The xterm emulator will behave unpredicably if Lo_Y is
51    omitted.  And if EGM is omitted, its value (as far as the xterm emulator
52    goes) is not zero, but is equal to the value of the EGM byte in the most
53    recently received point. */
54 
55 #include "sys-defines.h"
56 #include "extern.h"
57 
58 #define FIVEBITS 0x1F
59 #define TWOBITS 0x03		/* a dollar and six bits for a haircut... */
60 
61 void
_pl_t_tek_vector(R___ (Plotter * _plotter)int xx,int yy)62 _pl_t_tek_vector (R___(Plotter *_plotter) int xx, int yy)
63 {
64   unsigned char xx_high, yy_high;
65   unsigned char xx_low, yy_low;
66   unsigned char xx_topsig, yy_topsig;
67   unsigned char egm;
68   unsigned char byte_buf[5];
69   int num_bytes = 0;
70 
71 #ifdef NO_WRAP			/* could completely restrict to box */
72   if (xx < 0)
73     xx = 0;
74   if (yy < 0)
75     yy = 0;
76 #endif
77 
78   xx_high = (xx>>7) & FIVEBITS;	/* bits 11 through 7 of xx */
79   yy_high = (yy>>7) & FIVEBITS;	/* bits 11 through 7 of yy */
80 
81   xx_low = (xx>>2) & FIVEBITS;	/* bits 6 through 2 of xx */
82   yy_low = (yy>>2) & FIVEBITS;	/* bits 6 through 2 of yy */
83 
84   xx_topsig = xx & TWOBITS;	/* bits 1 through 0 of xx */
85   yy_topsig = yy & TWOBITS;	/* bits 1 through 0 of yy */
86   egm = (yy_topsig<<2) + xx_topsig;
87 
88   /* The bit patterns 0x20, 0x40, 0x60 are magic */
89 
90   byte_buf[num_bytes++] = yy_high | 0x20; /* bits 5 through 9 of yy */
91 #ifdef CAN_OMIT_EGM
92   if (egm)
93 #endif
94     byte_buf[num_bytes++] =   egm | 0x60;
95   byte_buf[num_bytes++] = yy_low  | 0x60; /* bits 0 through 4 of yy */
96   byte_buf[num_bytes++] = xx_high | 0x20; /* bits 5 through 9 of xx */
97   byte_buf[num_bytes++] = xx_low  | 0x40;  /* bits 0 through 4 of xx */
98 
99   /* invoke low-level output routine */
100   _write_bytes (_plotter->data, num_bytes, byte_buf);
101 
102   return;
103 }
104 
105 /* This version checks whether the supplied x and y coordinates are similar
106    to the x and y coordinates of another point, presumed to be the most
107    recently output point.  If they are, the Tek code is shortened by the
108    omission of optional bytes.  Hi_Y, Lo_Y and Hi_X are all held in memory,
109    so need not be transmitted if they did not change.  Lo_X must always be
110    transmitted.  EGM is not held in memory; if not transmitted, it defaults
111    to zero.
112 
113    The `force' argument will force output even if the vector has zero
114    length. */
115 
116 void
_pl_t_tek_vector_compressed(R___ (Plotter * _plotter)int xx,int yy,int oldxx,int oldyy,bool force)117 _pl_t_tek_vector_compressed (R___(Plotter *_plotter) int xx, int yy, int oldxx, int oldyy, bool force)
118 {
119   unsigned char xx_high, yy_high, oldxx_high, oldyy_high;
120   unsigned char xx_low, yy_low, oldyy_low;
121   unsigned char xx_top, yy_top;
122   unsigned char egm;
123   unsigned char byte_buf[5];
124   int num_bytes = 0;
125 
126 #ifdef NO_WRAP			/* could completely restrict to box */
127   if (xx < 0)
128     xx = 0;
129   if (yy < 0)
130     yy = 0;
131 #endif
132 
133   /* if line segment has zero length, do nothing unless forcing an output */
134   if (!force && (xx == oldxx) && (yy == oldyy))
135     return;
136 
137   xx_high = (xx>>7) & FIVEBITS;	/* bits 11 through 7 of xx */
138   yy_high = (yy>>7) & FIVEBITS;	/* bits 11 through 7 of yy */
139   oldxx_high = (oldxx>>7) & FIVEBITS; /* bits 11 through 7 of oldxx */
140   oldyy_high = (oldyy>>7) & FIVEBITS; /* bits 11 through 7 of oldyy */
141 
142   xx_low = (xx>>2) & FIVEBITS;	/* bits 6 through 2 of xx */
143   yy_low = (yy>>2) & FIVEBITS;	/* bits 6 through 2 of yy */
144   oldyy_low = (oldyy>>2) & FIVEBITS;	/* bits 4 through 0 of oldyy */
145 
146   xx_top = xx & TWOBITS;	/* bits 1 through 0 of xx */
147   yy_top = yy & TWOBITS;	/* bits 1 through 0 of yy */
148 
149   egm = (yy_top<<2) + xx_top;
150 
151   /* The bit patterns 0x20, 0x40, 0x60 are magic */
152 
153   if (yy_high != oldyy_high)
154     byte_buf[num_bytes++] = yy_high | 0x20; /* bits 11 through 7 of yy: Hi_Y */
155 
156 #ifdef CAN_OMIT_EGM
157   if (egm)
158 #endif
159     byte_buf[num_bytes++] = egm     | 0x60; /* bits 1 through 0 of xx and yy */
160 #ifdef CAN_OMIT_LO_Y
161   if ((yy_low != oldyy_low) || (xx_high != oldxx_high) || egm)
162 #endif
163     byte_buf[num_bytes++] = yy_low  | 0x60; /* bits 6 through 2 of yy: Lo_Y */
164   if (xx_high != oldxx_high)
165     byte_buf[num_bytes++] = xx_high | 0x20; /* bits 11 through 7 of xx: Hi_X */
166   byte_buf[num_bytes++] = xx_low    | 0x40; /* bits 6 through 2 of xx: Lo_X */
167 
168   /* invoke low-level output routine */
169   _write_bytes (_plotter->data, num_bytes, byte_buf);
170 
171   return;
172 }
173