- /* it is important that this returns an integral value, so that we
- * can ensure correct single pixel behaviour.
- *
- * we need (_height - max(wave_line_width))
- * wave_line_width == 1 IFF top==bottom (1 sample per pixel or flat line)
- * wave_line_width == 2 otherwise
- * then round away from the zero line, towards peak
- */
- if (_shape == Rectified) {
- // we only ever have 1 point and align to the bottom (not center)
- return floor ((1.0 - s) * (_height - 2.0));
- } else {
- /* currently canvas rectangle is off-by-one and we
- * cannot draw a pixel at 0 (-.5 .. +.5) without it being
- * clipped. A value 1.0 (ideally one point at y=0) ends
- * up a pixel down. and a value of -1.0 (ideally y = _height-1)
- * currently is on the bottom separator line :(
- * So to make the complete waveform appear centered in
- * a region, we translate by +.5 (instead of -.5)
- * and waste two pixel of height: -4 (instad of -2)
- *
- * This needs fixing in canvas/rectangle the intersect
- * functions and probably a couple of other places as well...
+ const double effective_height = _height;
+
+ /* remember: canvas (and cairo) coordinate space puts the origin at the upper left.
+
+ So, a sample value of 1.0 (0dbFS) will be computed as:
+
+ (1.0 - 1.0) * 0.5 * effective_height
+
+ which evaluates to 0, or the top of the image.
+
+ A sample value of -1.0 will be computed as
+
+ (1.0 + 1.0) * 0.5 * effective height
+
+ which evaluates to effective height, or the bottom of the image.
+ */
+
+ const double pmax = (1.0 - peak.max) * 0.5 * effective_height;
+ const double pmin = (1.0 - peak.min) * 0.5 * effective_height;
+
+ /* remember that the bottom of the image (pmin) has larger y-coordinates
+ than the top (pmax).
+ */
+
+ double spread = (pmin - pmax) * 0.5;
+
+ /* find the nearest pixel to the nominal center. */
+ const double center = round (pmin - spread);
+
+ if (spread < 1.0) {
+ /* minimum distance between line ends is 1 pixel, and we want it "centered" on a pixel,
+ as per cairo single-pixel line issues.
+
+ NOTE: the caller will not draw a line between these two points if the spread is
+ less than 2 pixels. So only the tips.top value matters, which is where we will
+ draw a single pixel as part of the outline.