Chris@1532: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1532: Chris@1532: /* Chris@1532: Sonic Visualiser Chris@1532: An audio file viewer and annotation editor. Chris@1532: Centre for Digital Music, Queen Mary, University of London. Chris@1532: Chris@1532: This program is free software; you can redistribute it and/or Chris@1532: modify it under the terms of the GNU General Public License as Chris@1532: published by the Free Software Foundation; either version 2 of the Chris@1532: License, or (at your option) any later version. See the file Chris@1532: COPYING included with this distribution for more information. Chris@1532: */ Chris@1532: Chris@1532: #ifndef SV_ZOOM_LEVEL_H Chris@1532: #define SV_ZOOM_LEVEL_H Chris@1532: Chris@1534: #include "BaseTypes.h" Chris@1534: Chris@1532: #include Chris@1533: #include Chris@1532: Chris@1532: /** Display zoom level. Can be an integer number of samples per pixel, Chris@1532: * or an integer number of pixels per sample. Chris@1532: */ Chris@1532: struct ZoomLevel { Chris@1532: Chris@1532: enum Zone { Chris@1532: FramesPerPixel, // zoomed out (as in classic SV) Chris@1532: PixelsPerFrame // zoomed in beyond 1-1 (interpolating the waveform) Chris@1532: }; Chris@1533: Chris@1532: Zone zone; Chris@1532: int level; Chris@1532: Chris@1532: ZoomLevel() : zone(FramesPerPixel), level(1) { } Chris@1532: ZoomLevel(Zone z, int lev) : zone(z), level(lev) { } Chris@1532: Chris@1532: bool operator<(const ZoomLevel &other) const { Chris@1532: if (zone == FramesPerPixel) { Chris@1532: if (other.zone == zone) { Chris@1532: return level < other.level; Chris@1532: } else { Chris@1532: return false; Chris@1532: } Chris@1532: } else { Chris@1532: if (other.zone == zone) { Chris@1532: return level > other.level; Chris@1532: } else { Chris@1532: return false; Chris@1532: } Chris@1532: } Chris@1532: } Chris@1532: Chris@1532: bool operator==(const ZoomLevel &other) const { Chris@1532: return (zone == other.zone && level == other.level); Chris@1532: } Chris@1532: Chris@1532: ZoomLevel incremented() const { Chris@1532: if (zone == FramesPerPixel) { Chris@1532: return { zone, level + 1 }; Chris@1532: } else if (level == 1) { Chris@1532: return { FramesPerPixel, 2 }; Chris@1532: } else if (level == 2) { Chris@1532: return { FramesPerPixel, 1 }; Chris@1532: } else { Chris@1532: return { zone, level - 1 }; Chris@1532: } Chris@1532: } Chris@1532: Chris@1532: ZoomLevel decremented() const { Chris@1532: if (zone == PixelsPerFrame) { Chris@1532: return { zone, level + 1 }; Chris@1532: } else if (level == 1) { Chris@1532: return { PixelsPerFrame, 2 }; Chris@1532: } else { Chris@1532: return { zone, level - 1 }; Chris@1532: } Chris@1532: } Chris@1532: Chris@1533: /** Inexact conversion. The result is a whole number if we are Chris@1533: * zoomed in enough (in PixelsPerFrame zone), a fraction Chris@1533: * otherwise. Chris@1533: */ Chris@1532: double framesToPixels(double frames) const { Chris@1532: if (zone == PixelsPerFrame) { Chris@1532: return frames * level; Chris@1532: } else { Chris@1532: return frames / level; Chris@1532: } Chris@1532: } Chris@1532: Chris@1533: /** Inexact conversion. The result is a whole number if we are Chris@1533: * zoomed out enough (in FramesPerPixel zone), a fraction Chris@1533: * otherwise. Chris@1533: */ Chris@1532: double pixelsToFrames(double pixels) const { Chris@1532: if (zone == PixelsPerFrame) { Chris@1532: return pixels / level; Chris@1532: } else { Chris@1532: return pixels * level; Chris@1532: } Chris@1532: } Chris@1533: Chris@1533: /** Return a ZoomLevel that approximates the given ratio of pixels Chris@1533: * to frames. Chris@1533: */ Chris@1534: static ZoomLevel fromRatio(int pixels, sv_frame_t frames) { Chris@1533: if (pixels < frames) { Chris@1534: return { FramesPerPixel, int(round(double(frames)/pixels)) }; Chris@1533: } else { Chris@1534: int r = int(round(pixels/double(frames))); Chris@1533: if (r > 1) { Chris@1533: return { PixelsPerFrame, r }; Chris@1533: } else { Chris@1533: return { FramesPerPixel, 1 }; Chris@1533: } Chris@1533: } Chris@1533: } Chris@1532: }; Chris@1532: Chris@1532: std::ostream &operator<<(std::ostream &s, const ZoomLevel &z); Chris@1532: Chris@1532: #endif