1 // $Id: Banner.cc 5748 2014-10-11 19:38:53Z flaterco $
2 
3 /*  Banner  Graph printed sideways on tractor feed dot matrix printer
4 
5     Copyright (C) 1998  David Flater.
6 
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation, either version 3 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #include "libxtide.hh"
22 #include "Graph.hh"
23 #include "PixelatedGraph.hh"
24 #include "TTYGraph.hh"
25 #include "Banner.hh"
26 
27 namespace libxtide {
28 
29 
30 // Fudge factor to correct aspect ratio on line printer
31 // Correct 10x6 of Pica type to be 1:1
32 static const double LPaspectfudge (0.6);
33 
34 
Banner(unsigned xSize,unsigned ySize)35 Banner::Banner (unsigned xSize, unsigned ySize): TTYGraph (ySize, xSize) {
36   //                                         turn sideways ^^^^^^^^^^^^
37 }
38 
39 
factory(const Station & station,unsigned xSize,Timestamp startTime,Timestamp endTime)40 Banner * const Banner::factory (const Station &station,
41 				unsigned xSize,
42 				Timestamp startTime,
43 				Timestamp endTime) {
44   // Everything is sideways.
45   Interval increment (std::max (
46     (interval_rep_t)1,
47     Global::intervalround (Global::aspectMagicNumber /
48                            (double)xSize /
49                            (station.aspect * LPaspectfudge))));
50 
51   // I really painted myself into a corner this time.  To create a
52   // Banner I need to know the length.  The length I want depends on
53   // labelWidth (the amount by which Graph fudges the start position
54   // to avoid clobbering it with depth labels).  To get labelWidth I
55   // need an instance of Banner.  Catch-22.
56 
57   // In the absence of a better idea, I create one Banner just to get
58   // labelWidth and then do it right.  Thankfully, banners are not the
59   // sort of objects that get created often.
60   Banner throwawayBanner (xSize, Global::minTTYwidth);
61 
62   // Stuff duplicated from Graph::drawTides, but with confusion of X and Y.
63   const double ymin (vertGraphMargin * (double)xSize);
64   const double ymax ((double)xSize - ymin);
65   const double valmin (station.minLevelHeuristic().val());
66   const double valmax (station.maxLevelHeuristic().val());
67   assert (valmin < valmax);
68 
69   unsigned lineStep, labelWidth, labelRight;
70   int minDepth, maxDepth;
71   const Dstr unitsDesc (Units::shortName (station.predictUnits()));
72   throwawayBanner.figureLabels (ymax, ymin, valmax, valmin, unitsDesc,
73 				lineStep, labelWidth,
74 				labelRight, minDepth, maxDepth);
75 
76   // At last we have labelWidth and can proceed.
77   unsigned ySize (std::max (Global::iround ((endTime - startTime) / increment +
78 				    throwawayBanner.startPosition(labelWidth)),
79 			    (int)Global::minTTYwidth));
80   return new Banner (xSize, ySize);
81 }
82 
83 
drawHorizontalLineP(int xlo,int xhi,int y,Colors::Colorchoice c unusedParameter)84 void Banner::drawHorizontalLineP (int xlo, int xhi, int y,
85 			         Colors::Colorchoice c unusedParameter) {
86   const char bar (VT100_mode ? '�' : '|');
87   for (int i=xlo; i<=xhi; ++i)
88     setPixel (i, y, bar);
89 }
90 
91 
drawHourTick(double x,Colors::Colorchoice c unusedParameter,bool thick)92 void Banner::drawHourTick (double x, Colors::Colorchoice c unusedParameter,
93 bool thick) {
94   int ix = Global::ifloor(x);
95   setPixel (ix, _ySize-1, '-');
96   if (thick) {
97     setPixel (ix-1, _ySize-1, '-');
98     setPixel (ix+1, _ySize-1, '-');
99   }
100 }
101 
102 
print(Dstr & text_out)103 void Banner::print (Dstr &text_out) {
104   // Everything is sideways.
105   text_out = (char *)NULL;
106   SafeVector<char> buf (_ySize+2);
107   buf[_ySize]   = '\n';
108   buf[_ySize+1] = '\0';
109   for (unsigned x=0; x<_xSize; ++x) {
110     for (unsigned y=0; y<_ySize; ++y)
111       buf[y] = tty[(_ySize-1-y)*_xSize+x];
112     text_out += &(buf[0]);
113   }
114   if (VT100_mode)
115     VT100_postproc (text_out);
116 }
117 
118 
aspectFudgeFactor() const119 const double Banner::aspectFudgeFactor() const {
120   return LPaspectfudge;
121 }
122 
123 
drawStringSideways(int x,int y,const Dstr & s)124 void Banner::drawStringSideways (int x, int y, const Dstr &s) {
125   for (unsigned a=0; a<s.length(); ++a)
126     setPixel (x, y-a, s[a]);
127 }
128 
129 
labelHourTick(double x,const Dstr & label)130 void Banner::labelHourTick (double x, const Dstr &label) {
131   drawStringSideways (Global::ifloor(x),
132 		      _ySize - hourTickLen() - 1,
133 		      label);
134 }
135 
136 
labelEvent(int topLine,const EventBlurb & blurb)137 void Banner::labelEvent (int topLine, const EventBlurb &blurb) {
138   int x = Global::ifloor (blurb.x);
139   if (topLine >= 0) {
140     drawStringSideways (x-1, blurb.line1.length()-1, blurb.line1);
141     drawStringSideways (x,   blurb.line2.length()-1, blurb.line2);
142   } else {
143     int y (_ySize - hourTickLen() - 4);
144     drawStringSideways (x-1, y, blurb.line1);
145     drawStringSideways (x,   y, blurb.line2);
146   }
147 }
148 
149 
150 // This has to agree with labelEvent.
measureBlurb(EventBlurb & blurb) const151 void Banner::measureBlurb (EventBlurb &blurb) const {
152   blurb.deltaLeft  = -1;
153   blurb.deltaRight = 0;
154 }
155 
156 
drawTitleLine(const Dstr & title unusedParameter)157 void Banner::drawTitleLine (const Dstr &title unusedParameter) {
158   // Lose it.
159 }
160 
161 
isBanner() const162 const bool Banner::isBanner() const {
163   return true;
164 }
165 
166 }
167