Audacity  3.0.3
TrackArtist.cpp
Go to the documentation of this file.
1 /**********************************************************************
2 
3  Audacity: A Digital Audio Editor
4 
5  TrackArtist.cpp
6 
7  Dominic Mazzoni
8 
9 
10 *******************************************************************//*******************************************************************/
40 
41 
42 #include "TrackArtist.h"
43 
44 
45 
46 #include "AColor.h"
47 #include "AllThemeResources.h"
48 #include "prefs/GUIPrefs.h"
49 #include "Theme.h"
50 #include "Track.h"
52 #include "ViewInfo.h"
53 
54 #include "prefs/GUISettings.h"
55 #include "prefs/TracksPrefs.h"
56 
57 #include <wx/dc.h>
58 
60  : parent( parent_ )
61 {
63  mShowClipping = false;
64  mSampleDisplay = 1;// Stem plots by default.
65 
66  SetColours(0);
67 
68  UpdatePrefs();
69 }
70 
72 {
73 }
74 
76 {
77  return static_cast< TrackArtist* >( context.pUserData );
78 }
79 
80 void TrackArtist::SetColours( int iColorIndex)
81 {
82  theTheme.SetBrushColour( blankBrush, clrBlank );
83  theTheme.SetBrushColour( unselectedBrush, clrUnselected);
84  theTheme.SetBrushColour( selectedBrush, clrSelected);
85  theTheme.SetBrushColour( sampleBrush, clrSample);
86  theTheme.SetBrushColour( selsampleBrush, clrSelSample);
87  theTheme.SetBrushColour( dragsampleBrush, clrDragSample);
88  theTheme.SetBrushColour( blankSelectedBrush, clrBlankSelected);
89 
90  theTheme.SetPenColour( blankPen, clrBlank);
91  theTheme.SetPenColour( unselectedPen, clrUnselected);
92  theTheme.SetPenColour( selectedPen, clrSelected);
93  theTheme.SetPenColour( muteSamplePen, clrMuteSample);
94  theTheme.SetPenColour( odProgressDonePen, clrProgressDone);
95  theTheme.SetPenColour( odProgressNotYetPen, clrProgressNotYet);
96  theTheme.SetPenColour( shadowPen, clrShadow);
97  theTheme.SetPenColour( clippedPen, clrClipped);
98  theTheme.SetPenColour( muteClippedPen, clrMuteClipped);
99  theTheme.SetPenColour( blankSelectedPen,clrBlankSelected);
100 
101  theTheme.SetPenColour( selsamplePen, clrSelSample);
102  theTheme.SetPenColour( muteRmsPen, clrMuteRms);
103 
104  switch( iColorIndex %4 )
105  {
106  default:
107  case 0:
108  theTheme.SetPenColour( samplePen, clrSample);
109  theTheme.SetPenColour( rmsPen, clrRms);
110  break;
111  case 1: // RED
112  samplePen.SetColour( wxColor( 160,10,10 ) );
113  rmsPen.SetColour( wxColor( 230,80,80 ) );
114  break;
115  case 2: // GREEN
116  samplePen.SetColour( wxColor( 35,110,35 ) );
117  rmsPen.SetColour( wxColor( 75,200,75 ) );
118  break;
119  case 3: //BLACK
120  samplePen.SetColour( wxColor( 0,0,0 ) );
121  rmsPen.SetColour( wxColor( 100,100,100 ) );
122  break;
123 
124  }
125 }
126 
132 int GetWaveYPos(float value, float min, float max,
133  int height, bool dB, bool outer,
134  float dBr, bool clip)
135 {
136  if (dB) {
137  if (height == 0) {
138  return 0;
139  }
140 
141  float sign = (value >= 0 ? 1 : -1);
142 
143  if (value != 0.) {
144  float db = LINEAR_TO_DB(fabs(value));
145  value = (db + dBr) / dBr;
146  if (!outer) {
147  value -= 0.5;
148  }
149  if (value < 0.0) {
150  value = 0.0;
151  }
152  value *= sign;
153  }
154  }
155  else {
156  if (!outer) {
157  if (value >= 0.0) {
158  value -= 0.5;
159  }
160  else {
161  value += 0.5;
162  }
163  }
164  }
165 
166  if (clip) {
167  if (value < min) {
168  value = min;
169  }
170  if (value > max) {
171  value = max;
172  }
173  }
174 
175  value = (max - value) / (max - min);
176  return (int) (value * (height - 1) + 0.5);
177 }
178 
179 float FromDB(float value, double dBRange)
180 {
181  if (value == 0)
182  return 0;
183 
184  double sign = (value >= 0 ? 1 : -1);
185  return DB_TO_LINEAR((fabs(value) * dBRange) - dBRange) * sign;
186 }
187 
188 float ValueOfPixel(int yy, int height, bool offset,
189  bool dB, double dBRange, float zoomMin, float zoomMax)
190 {
191  wxASSERT(height > 0);
192  // Map 0 to max and height - 1 (not height) to min
193  float v =
194  height == 1 ? (zoomMin + zoomMax) / 2 :
195  zoomMax - (yy / (float)(height - 1)) * (zoomMax - zoomMin);
196  if (offset) {
197  if (v > 0.0)
198  v += .5;
199  else
200  v -= .5;
201  }
202 
203  if (dB)
204  v = FromDB(v, dBRange);
205 
206  return v;
207 }
208 
210  TrackPanelDrawingContext &context, const wxRect &rect )
211 {
212  auto &dc = context.dc;
213 
214  // Draws two black arrows on the left side of the track to
215  // indicate the user that the track has been time-shifted
216  // to the left beyond t=0.0.
217 
218  dc.SetPen(*wxBLACK_PEN);
219  AColor::Line(dc,
220  rect.x + 2, rect.y + 6,
221  rect.x + 8, rect.y + 6);
222  AColor::Line(dc,
223  rect.x + 2, rect.y + 6,
224  rect.x + 6, rect.y + 2);
225  AColor::Line(dc,
226  rect.x + 2, rect.y + 6,
227  rect.x + 6, rect.y + 10);
228  AColor::Line(dc,
229  rect.x + 2, rect.y + rect.height - 8,
230  rect.x + 8, rect.y + rect.height - 8);
231  AColor::Line(dc,
232  rect.x + 2, rect.y + rect.height - 8,
233  rect.x + 6, rect.y + rect.height - 4);
234  AColor::Line(dc,
235  rect.x + 2, rect.y + rect.height - 8,
236  rect.x + 6, rect.y + rect.height - 12);
237 }
238 
239 
240 #ifdef USE_MIDI
241 #endif // USE_MIDI
242 
243 
245 {
246  if( id == ShowClippingPrefsID())
247  mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
248  if( id == ShowTrackNameInWaveformPrefsID())
249  mbShowTrackNameInTrack = gPrefs->ReadBool(wxT("/GUI/ShowTrackNameInWaveform"), false);
250 }
251 
253 {
256 
259 
260  SetColours(0);
261 }
262 
263 // Draws the sync-lock bitmap, tiled; always draws stationary relative to the DC
264 //
265 // AWD: now that the tiles don't link together, we're drawing a tilted grid, at
266 // two steps down for every one across. This creates a pattern that repeats in
267 // 5-step by 5-step boxes. Because we're only drawing in 5/25 possible positions
268 // we have a grid spacing somewhat smaller than the image dimensions. Thus we
269 // achieve lower density than with a square grid and eliminate edge cases where
270 // no tiles are displayed.
271 //
272 // The pattern draws in tiles at (0,0), (2,1), (4,2), (1,3), and (3,4) in each
273 // 5x5 box.
274 //
275 // There may be a better way to do this, or a more appealing pattern.
277  TrackPanelDrawingContext &context, const wxRect &rect )
278 {
279  const auto dc = &context.dc;
280 
281  wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockSelTile));
282 
283  // Grid spacing is a bit smaller than actual image size
284  int gridW = syncLockBitmap.GetWidth() - 6;
285  int gridH = syncLockBitmap.GetHeight() - 8;
286 
287  // Horizontal position within the grid, modulo its period
288  int blockX = (rect.x / gridW) % 5;
289 
290  // Amount to offset drawing of first column
291  int xOffset = rect.x % gridW;
292  if (xOffset < 0) xOffset += gridW;
293 
294  // Check if we're missing an extra column to the left (this can happen
295  // because the tiles are bigger than the grid spacing)
296  bool extraCol = false;
297  if (syncLockBitmap.GetWidth() - gridW > xOffset) {
298  extraCol = true;
299  xOffset += gridW;
300  blockX = (blockX - 1) % 5;
301  }
302  // Make sure blockX is non-negative
303  if (blockX < 0) blockX += 5;
304 
305  int xx = 0;
306  while (xx < rect.width) {
307  int width = syncLockBitmap.GetWidth() - xOffset;
308  if (xx + width > rect.width)
309  width = rect.width - xx;
310 
311  //
312  // Draw each row in this column
313  //
314 
315  // Vertical position in the grid, modulo its period
316  int blockY = (rect.y / gridH) % 5;
317 
318  // Amount to offset drawing of first row
319  int yOffset = rect.y % gridH;
320  if (yOffset < 0) yOffset += gridH;
321 
322  // Check if we're missing an extra row on top (this can happen because
323  // the tiles are bigger than the grid spacing)
324  bool extraRow = false;
325  if (syncLockBitmap.GetHeight() - gridH > yOffset) {
326  extraRow = true;
327  yOffset += gridH;
328  blockY = (blockY - 1) % 5;
329  }
330  // Make sure blockY is non-negative
331  if (blockY < 0) blockY += 5;
332 
333  int yy = 0;
334  while (yy < rect.height)
335  {
336  int height = syncLockBitmap.GetHeight() - yOffset;
337  if (yy + height > rect.height)
338  height = rect.height - yy;
339 
340  // AWD: draw blocks according to our pattern
341  if ((blockX == 0 && blockY == 0) || (blockX == 2 && blockY == 1) ||
342  (blockX == 4 && blockY == 2) || (blockX == 1 && blockY == 3) ||
343  (blockX == 3 && blockY == 4))
344  {
345 
346  // Do we need to get a sub-bitmap?
347  if (width != syncLockBitmap.GetWidth() || height != syncLockBitmap.GetHeight()) {
348  wxBitmap subSyncLockBitmap =
349  syncLockBitmap.GetSubBitmap(wxRect(xOffset, yOffset, width, height));
350  dc->DrawBitmap(subSyncLockBitmap, rect.x + xx, rect.y + yy, true);
351  }
352  else {
353  dc->DrawBitmap(syncLockBitmap, rect.x + xx, rect.y + yy, true);
354  }
355  }
356 
357  // Updates for next row
358  if (extraRow) {
359  // Second offset row, still at y = 0; no more extra rows
360  yOffset -= gridH;
361  extraRow = false;
362  }
363  else {
364  // Move on in y, no more offset rows
365  yy += gridH - yOffset;
366  yOffset = 0;
367  }
368  blockY = (blockY + 1) % 5;
369  }
370 
371  // Updates for next column
372  if (extraCol) {
373  // Second offset column, still at x = 0; no more extra columns
374  xOffset -= gridW;
375  extraCol = false;
376  }
377  else {
378  // Move on in x, no more offset rows
379  xx += gridW - xOffset;
380  xOffset = 0;
381  }
382  blockX = (blockX + 1) % 5;
383  }
384 }
385 
387  TrackPanelDrawingContext &context, const wxRect &rect,
388  const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush,
389  bool useSelection)
390 {
391  const auto dc = &context.dc;
392  const auto artist = TrackArtist::Get( context );
393  const auto &selectedRegion = *artist->pSelectedRegion;
394  const auto &zoomInfo = *artist->pZoomInfo;
395 
396  //MM: Draw background. We should optimize that a bit more.
397  const double sel0 = useSelection ? selectedRegion.t0() : 0.0;
398  const double sel1 = useSelection ? selectedRegion.t1() : 0.0;
399 
400  dc->SetPen(*wxTRANSPARENT_PEN);
401  if (track->GetSelected() || track->IsSyncLockSelected())
402  {
403  // Rectangles before, within, after the selection
404  wxRect before = rect;
405  wxRect within = rect;
406  wxRect after = rect;
407 
408  before.width = (int)(zoomInfo.TimeToPosition(sel0) );
409  if (before.GetRight() > rect.GetRight()) {
410  before.width = rect.width;
411  }
412 
413  if (before.width > 0) {
414  dc->SetBrush(unselBrush);
415  dc->DrawRectangle(before);
416 
417  within.x = 1 + before.GetRight();
418  }
419  within.width = rect.x + (int)(zoomInfo.TimeToPosition(sel1) ) - within.x -1;
420 
421  if (within.GetRight() > rect.GetRight()) {
422  within.width = 1 + rect.GetRight() - within.x;
423  }
424 
425  // Bug 2389 - Selection can disappear
426  // This handles case where no waveform is visible.
427  if (within.width < 1)
428  {
429  within.width = 1;
430  }
431 
432  if (within.width > 0) {
433  if (track->GetSelected()) {
434  dc->SetBrush(selBrush);
435  dc->DrawRectangle(within);
436  }
437  else {
438  // Per condition above, track must be sync-lock selected
439  dc->SetBrush(unselBrush);
440  dc->DrawRectangle(within);
441  DrawSyncLockTiles( context, within );
442  }
443 
444  after.x = 1 + within.GetRight();
445  }
446  else {
447  // `within` not drawn; start where it would have gone
448  after.x = within.x;
449  }
450 
451  after.width = 1 + rect.GetRight() - after.x;
452  if (after.width > 0) {
453  dc->SetBrush(unselBrush);
454  dc->DrawRectangle(after);
455  }
456  }
457  else
458  {
459  // Track not selected; just draw background
460  dc->SetBrush(unselBrush);
461  dc->DrawRectangle(rect);
462  }
463 }
464 
ShowClippingPrefsID
int ShowClippingPrefsID()
Definition: GUIPrefs.cpp:277
TrackArtist::UpdateSelectedPrefs
void UpdateSelectedPrefs(int id) override
Definition: TrackArtist.cpp:244
TrackArtist::clippedPen
wxPen clippedPen
Definition: TrackArtist.h:119
TrackArtist::~TrackArtist
~TrackArtist()
Definition: TrackArtist.cpp:71
DB_TO_LINEAR
const double MIN_Threshold_Linear DB_TO_LINEAR(MIN_Threshold_dB)
outer
static const wxPoint2DDouble outer[]
Definition: ASlider.cpp:395
TrackArtist::mdBrange
float mdBrange
Definition: TrackArtist.h:95
TrackArtist.h
TrackArtist::muteClippedPen
wxPen muteClippedPen
Definition: TrackArtist.h:120
gPrefs
FileConfig * gPrefs
Definition: Prefs.cpp:68
AllThemeResources.h
ENV_DB_RANGE
#define ENV_DB_RANGE
Definition: GUISettings.h:16
TrackArtist::odProgressNotYetPen
wxPen odProgressNotYetPen
Definition: TrackArtist.h:116
TrackPanelDrawingContext
Definition: TrackPanelDrawingContext.h:22
TracksPrefs.h
AColor::Line
static void Line(wxDC &dc, wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
Definition: AColor.cpp:112
TrackArtist::UpdatePrefs
void UpdatePrefs() override
Definition: TrackArtist.cpp:252
TrackArtist::selectedPen
wxPen selectedPen
Definition: TrackArtist.h:110
TrackPanelDrawingContext::dc
wxDC & dc
Definition: TrackPanelDrawingContext.h:23
ShowTrackNameInWaveformPrefsID
int ShowTrackNameInWaveformPrefsID()
Definition: GUIPrefs.cpp:283
FromDB
float FromDB(float value, double dBRange)
Definition: TrackArtist.cpp:179
TrackArtist
This class handles the actual rendering of WaveTracks (both waveforms and spectra),...
Definition: TrackArtist.h:58
TrackPanel
The TrackPanel class coordinates updates and operations on the main part of the screen which contains...
Definition: TrackPanel.h:64
TrackArtist::rmsPen
wxPen rmsPen
Definition: TrackArtist.h:112
Track::IsSyncLockSelected
bool IsSyncLockSelected() const
Definition: Track.cpp:245
TrackArtist::muteRmsPen
wxPen muteRmsPen
Definition: TrackArtist.h:113
TrackArt::DrawSyncLockTiles
AUDACITY_DLL_API void DrawSyncLockTiles(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArtist.cpp:276
TrackArtist::unselectedBrush
wxBrush unselectedBrush
Definition: TrackArtist.h:101
TrackArtist::Get
static TrackArtist * Get(TrackPanelDrawingContext &)
Definition: TrackArtist.cpp:75
TrackArtist::mShowClipping
bool mShowClipping
Definition: TrackArtist.h:96
TrackArt::DrawNegativeOffsetTrackArrows
AUDACITY_DLL_API void DrawNegativeOffsetTrackArrows(TrackPanelDrawingContext &context, const wxRect &rect)
Definition: TrackArtist.cpp:209
TrackArtist::dragsampleBrush
wxBrush dragsampleBrush
Definition: TrackArtist.h:105
TrackArtist::blankSelectedBrush
wxBrush blankSelectedBrush
Definition: TrackArtist.h:107
Theme.h
TrackArtist::shadowPen
wxPen shadowPen
Definition: TrackArtist.h:118
ThemeBase::SetBrushColour
void SetBrushColour(wxBrush &Brush, int iIndex)
Definition: Theme.cpp:1200
ThemeBase::Image
wxImage & Image(int iIndex)
Definition: Theme.cpp:1219
TrackArtist::sampleBrush
wxBrush sampleBrush
Definition: TrackArtist.h:103
ENV_DB_KEY
#define ENV_DB_KEY
Definition: GUISettings.h:15
TrackArtist::blankBrush
wxBrush blankBrush
Definition: TrackArtist.h:100
TrackArtist::selsampleBrush
wxBrush selsampleBrush
Definition: TrackArtist.h:104
ViewInfo.h
Track::GetSelected
bool GetSelected() const
Definition: Track.h:414
GUISettings.h
min
int min(int a, int b)
Definition: CompareAudioCommand.cpp:106
TrackPanelDrawingContext.h
TrackArtist::blankSelectedPen
wxPen blankSelectedPen
Definition: TrackArtist.h:121
TrackArtist::mbShowTrackNameInTrack
bool mbShowTrackNameInTrack
Definition: TrackArtist.h:98
TrackPanelDrawingContext::pUserData
void * pUserData
Definition: TrackPanelDrawingContext.h:27
TrackArt::DrawBackgroundWithSelection
AUDACITY_DLL_API void DrawBackgroundWithSelection(TrackPanelDrawingContext &context, const wxRect &rect, const Track *track, const wxBrush &selBrush, const wxBrush &unselBrush, bool useSelection=true)
Definition: TrackArtist.cpp:386
Track
Abstract base class for an object holding data associated with points on a time axis.
Definition: Track.h:238
TrackArtist::mSampleDisplay
int mSampleDisplay
Definition: TrackArtist.h:97
TrackArtist::SetColours
void SetColours(int iColorIndex)
Definition: TrackArtist.cpp:80
GUIPrefs.h
TracksPrefs::SampleViewChoice
static WaveTrackViewConstants::SampleDisplay SampleViewChoice()
Definition: TracksPrefs.cpp:196
GetWaveYPos
int GetWaveYPos(float value, float min, float max, int height, bool dB, bool outer, float dBr, bool clip)
Definition: TrackArtist.cpp:132
TrackArtist::TrackArtist
TrackArtist(TrackPanel *parent_)
Definition: TrackArtist.cpp:59
LINEAR_TO_DB
#define LINEAR_TO_DB(x)
Definition: MemoryX.h:617
Track.h
declares abstract base class Track, TrackList, and iterators over TrackList
TrackArtist::selectedBrush
wxBrush selectedBrush
Definition: TrackArtist.h:102
TrackArtist::blankPen
wxPen blankPen
Definition: TrackArtist.h:108
TrackArtist::muteSamplePen
wxPen muteSamplePen
Definition: TrackArtist.h:115
ValueOfPixel
float ValueOfPixel(int yy, int height, bool offset, bool dB, double dBRange, float zoomMin, float zoomMax)
Definition: TrackArtist.cpp:188
theTheme
AUDACITY_DLL_API Theme theTheme
Definition: Theme.cpp:202
TrackArtist::selsamplePen
wxPen selsamplePen
Definition: TrackArtist.h:114
TrackArtist::samplePen
wxPen samplePen
Definition: TrackArtist.h:111
AColor.h
within
bool within(A a, B b, DIST d)
Definition: TrackPanel.cpp:158
ThemeBase::SetPenColour
void SetPenColour(wxPen &Pen, int iIndex)
Definition: Theme.cpp:1206
TrackArtist::unselectedPen
wxPen unselectedPen
Definition: TrackArtist.h:109
TrackArtist::odProgressDonePen
wxPen odProgressDonePen
Definition: TrackArtist.h:117