Audacity 3.2.0
Overlay.h
Go to the documentation of this file.
1//
2// Overlay.h
3// Audacity
4//
5// Created by Paul Licameli on 5/7/16.
6//
7//
8
9#ifndef __AUDACITY_OVERLAY__
10#define __AUDACITY_OVERLAY__
11
12
13
14#include <utility>
15
16class OverlayPanel;
17class wxDC;
18class wxRect;
19class wxSize;
20
21/*
22<b>How Audacity Redisplay Works \n
23 Roger Dannenberg</b> \n
24Oct 2010 \n
25
26This is a brief guide to Audacity redisplay -- it may not be complete. It
27is my attempt to understand the complicated graphics strategy.
28
29One basic idea is that redrawing waveforms is rather slow, so Audacity
30saves waveform images in bitmaps to make redrawing faster. In particular,
31during audio playback (and recording), the vertical time indicator is
32drawn over the waveform about 20 times per second. To avoid unnecessary
33computation, the indicator is erased by copying a column of pixels from
34a bitmap image of the waveform. Notice that this implies a two-stage
35process: first, waveforms are drawn to the bitmap; then, the bitmap
36(or pieces of it) are copied to the screen, perhaps along with other
37graphics.
38
39The bitmap is for the entire track panel, i.e. multiple tracks, and
40includes things like the Gain and Pan slders to the left of the
41waveform images.
42
43The screen update uses a mixture of direct drawing and indirect paint
44events. The "normal" way to update a graphical display is to call
45the Refresh() method when something invalidates the screen. Later, the
46system calls OnPaint(), which the application overrides to (re)draw the
47screen. In wxWidgets, you can also draw directly to the screen without
48calling Refresh() and without waiting for OnPaint() to be called.
49
50I would expect there to be a 2-level invalidation scheme: Some changes
51invalidate the bitmap, forcing a bitmap redraw *and* a screen redraw.
52Other changes merely update the screen using pre-existing bitmaps. In
53Audacity, the "2-level" invalidation works like this: Anything
54that invalidates the bitmap calls TrackPanel::Refresh(), which
55has an eraseBackground parameter. This flag says to redraw the
56bitmap when OnPaint() is called. If eraseBackground is false, the
57existing bitmap can be used for waveform images. Audacity also
58draws directly to the screen to update the time indicator during
59playback. To move the indicator, one column of pixels is drawn to
60the screen to remove the indicator. Then the indicator is drawn at
61a NEW time location.
62
63Notice that the zoom guidelines, the focused track highlight,
64and snap guidelines could be drawn directly to the screen rather than to
65the bitmap, generally eliminating redraw work.
66
67One problem is slider updates. Sliders are in the left area of the track
68panel. They are not wxWindows like wxSliders, but instead are just drawn
69on the TrackPanel. When slider state changes, *all* tracks do a full
70refresh, including recomputing the backing store. It would make more sense
71to just invalidate the region containing the slider. However, doing that
72would require either incrementally updating the bitmap (not currently done),
73or maintaining the sliders and other track info on the screen and not in
74the bitmap.
75
76*/
77
78/*
79PRL: above explanation was formerly in TrackArtist.cpp.
80
81What it says is correct but also applies to other things than the play
82indicator, such as the point editing cursor and the quick-play indicator
83line. I abstracted out class Overlay to describe these drawables, and
84cooperating class OverlayPanel that can manage multiple Overlays, figuring
85out when the invalidation of one of them necessitates invalidation of other
86overlapping ones.
87
88The base class OverlayPanel, of TrackPanel, was also reused by the
89AdornedRulerPanel.
90
91*/
92
93class AUDACITY_DLL_API Overlay
94{
95public:
96 Overlay() = default;
97 Overlay( const Overlay & ) = delete;
98 Overlay &operator=( const Overlay & ) = delete;
99 virtual ~Overlay() = 0;
100
103 virtual unsigned SequenceNumber() const = 0;
104
105 // nonvirtual wrapper
106 std::pair<wxRect, bool> GetRectangle(wxSize size);
107
108 // size passes the dimensions of the backing dc
109 // First member of pair is the rectangle that would be erased
110 // Second member of pair indicates whether the overlay is out of date
111 virtual std::pair<wxRect, bool> DoGetRectangle(wxSize size) = 0;
112
113 // Default implementation blits from backing store over GetRectangle().first
114 virtual void Erase(wxDC &dc, wxDC &src);
115
116 // Draw; dc.GetSize() tells you the total dimensions, and the panel is supplied
117 // as context
118 virtual void Draw(OverlayPanel &panel, wxDC &dc) = 0;
119};
120
121#endif
Overlay()=default
virtual std::pair< wxRect, bool > DoGetRectangle(wxSize size)=0
Overlay(const Overlay &)=delete
virtual void Draw(OverlayPanel &panel, wxDC &dc)=0
virtual unsigned SequenceNumber() const =0
This number determines an ordering of overlays, so that those with higher numbers overpaint those wit...
Overlay & operator=(const Overlay &)=delete