Chris@1071: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@1071: Chris@1071: /* Chris@1071: Sonic Visualiser Chris@1071: An audio file viewer and annotation editor. Chris@1071: Centre for Digital Music, Queen Mary, University of London. Chris@1071: This file copyright 2006-2016 Chris Cannam and QMUL. Chris@1071: Chris@1071: This program is free software; you can redistribute it and/or Chris@1071: modify it under the terms of the GNU General Public License as Chris@1071: published by the Free Software Foundation; either version 2 of the Chris@1071: License, or (at your option) any later version. See the file Chris@1071: COPYING included with this distribution for more information. Chris@1071: */ Chris@1071: Chris@1071: #ifndef COLOUR_3D_PLOT_RENDERER_H Chris@1071: #define COLOUR_3D_PLOT_RENDERER_H Chris@1071: Chris@1071: #include "ColourScale.h" Chris@1073: #include "ScrollableImageCache.h" Chris@1071: Chris@1071: #include "base/ColumnOp.h" Chris@1073: #include "base/MagnitudeRange.h" Chris@1071: Chris@1073: #include Chris@1073: #include Chris@1073: #include Chris@1073: Chris@1073: class LayerGeometryProvider; Chris@1071: class DenseThreeDimensionalModel; Chris@1071: class Dense3DModelPeakCache; Chris@1071: class FFTModel; Chris@1071: Chris@1071: class Colour3DPlotRenderer Chris@1071: { Chris@1071: public: Chris@1071: enum BinDisplay { Chris@1071: AllBins, Chris@1071: PeakBins, Chris@1071: PeakFrequencies Chris@1071: }; Chris@1071: Chris@1071: enum BinScale { Chris@1071: LinearBinScale, Chris@1071: LogBinScale Chris@1071: }; Chris@1073: Chris@1073: struct Sources { Chris@1073: Sources() : geometryProvider(0), source(0), peaks(0), fft(0) { } Chris@1073: Chris@1073: // These must all outlive this class Chris@1073: LayerGeometryProvider *geometryProvider; // always Chris@1073: DenseThreeDimensionalModel *source; // always Chris@1073: Dense3DModelPeakCache *peaks; // optionally Chris@1073: FFTModel *fft; // optionally Chris@1073: }; Chris@1073: Chris@1071: struct Parameters { Chris@1071: Parameters() : Chris@1071: colourScale(ColourScale::Parameters()), Chris@1071: normalization(ColumnOp::NoNormalization), Chris@1073: binDisplay(AllBins), Chris@1073: binScale(LinearBinScale), Chris@1073: alwaysOpaque(false), Chris@1073: interpolate(false), Chris@1073: invertVertical(false) { } Chris@1071: Chris@1071: ColourScale colourScale; // complete ColourScale object by value Chris@1071: ColumnOp::Normalization normalization; Chris@1071: BinDisplay binDisplay; Chris@1071: BinScale binScale; Chris@1071: bool alwaysOpaque; Chris@1071: bool interpolate; Chris@1071: bool invertVertical; Chris@1071: }; Chris@1073: Chris@1073: Colour3DPlotRenderer(Sources sources, Parameters parameters) : Chris@1073: m_sources(sources), Chris@1073: m_params(parameters), Chris@1073: m_bufferResolution(PixelResolution) Chris@1071: { } Chris@1071: Chris@1073: struct RenderResult { Chris@1073: /** Chris@1073: * The rect that was actually rendered. May be equal to the Chris@1073: * rect that was requested to render, or may be smaller if Chris@1073: * time ran out and the complete flag was not set. Chris@1073: */ Chris@1073: QRect rendered; Chris@1073: Chris@1073: /** Chris@1073: * The magnitude range of the data in the rendered area. Chris@1073: */ Chris@1073: MagnitudeRange range; Chris@1073: }; Chris@1073: Chris@1073: /** Chris@1073: * Render the requested area using the given painter, obtaining Chris@1073: * geometry (e.g. start frame) from the stored Chris@1073: * LayerGeometryProvider. Chris@1073: * Chris@1073: * If complete is false, as much of the rect will be rendered as Chris@1073: * can be managed given internal time constraints. The returned Chris@1073: * QRect (the rendered field in the RenderResult struct) will Chris@1073: * contain the area that was rendered. Note that we always render Chris@1073: * the full requested height, it's only width that is Chris@1073: * time-constrained. Chris@1073: * Chris@1073: * If complete is true, the whole rect will be rendered and the Chris@1073: * returned QRect will be equal to the passed QRect. Chris@1075: * Chris@1075: * If the model to render from is not ready, this will throw a Chris@1075: * std::logic_error exception. The model must be ready and the Chris@1075: * layer requesting the render must not be dormant in its view, so Chris@1075: * that the LayerGeometryProvider returns valid results; it is the Chris@1075: * caller's responsibility to ensure these. Chris@1073: */ Chris@1073: RenderResult render(QPainter &paint, Chris@1073: QRect rect, Chris@1073: bool complete); Chris@1073: Chris@1071: private: Chris@1073: Sources m_sources; Chris@1071: Parameters m_params; Chris@1072: Chris@1073: // Draw buffer is the target of each partial repaint. It is always Chris@1073: // at view height (not model height) and is cleared and repainted Chris@1073: // on each fragment render. The only reason it's stored as a data Chris@1073: // member is to avoid reallocation. Chris@1073: QImage m_drawBuffer; Chris@1072: Chris@1073: // Indicates whether the draw buffer is rendered at bin resolution Chris@1073: // or at pixel resolution. Pixel resolution is used when the zoom Chris@1073: // level is such that each pixel is backed by more than one bin; Chris@1073: // bin resolution is used when the zoom level is such that each Chris@1073: // bin is drawn to more than one pixel. Chris@1073: enum BufferResolution { Chris@1073: BinResolution, Chris@1073: PixelResolution Chris@1073: }; Chris@1073: BufferResolution m_bufferResolution; Chris@1073: Chris@1073: // Image cache is our persistent record of the visible area. It is Chris@1073: // always the same size as the view (i.e. the paint size reported Chris@1073: // by the LayerGeometryProvider) and is scrolled and partially Chris@1073: // repainted internally as appropriate. A render request is Chris@1073: // carried out by repainting to cache (via the draw buffer) any Chris@1073: // area that is being requested but is not valid in the cache, and Chris@1073: // then repainting from cache to the requested painter. Chris@1073: ScrollableImageCache m_cache; Chris@1073: Chris@1073: Chris@1072: //!!! fft model scaling? Chris@1072: Chris@1072: //!!! should we own the Dense3DModelPeakCache here? or should it persist Chris@1071: }; Chris@1071: Chris@1071: #endif Chris@1071: