1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-11-21 16:37:12 +01:00

Mutable cache for ruler updates, so Draw functions can be const

This commit is contained in:
Paul Licameli
2020-01-23 11:32:49 -05:00
parent a2babc646f
commit 580ad8221e
2 changed files with 67 additions and 50 deletions

View File

@@ -111,8 +111,6 @@ Ruler::Ruler()
mLength = 0;
mValid = false;
mCustom = false;
mbMinor = true;
@@ -289,6 +287,7 @@ void Ruler::SetFonts(const wxFont &minorFont, const wxFont &majorFont, const wxF
wxCoord height;
FindFontHeights( height, mpUserFonts->lead, dc, majorFont );
mpFonts.reset();
mpFonts.reset();
Invalidate();
}
@@ -346,14 +345,12 @@ void Ruler::SetBounds(int left, int top, int right, int bottom)
void Ruler::Invalidate()
{
mValid = false;
if (mOrientation == wxHORIZONTAL)
mLength = mRight-mLeft;
else
mLength = mBottom-mTop;
mBits.clear();
mpCache.reset();
mUserBits.clear();
}
@@ -908,6 +905,12 @@ struct Ruler::Updater {
const;
};
struct Ruler::Cache {
Bits mBits;
Labels mMajorLabels, mMinorLabels, mMinorMinorLabels;
wxRect mRect;
};
struct Ruler::Updater::TickOutputs{ Labels &labels; Bits &bits; wxRect &box; };
struct Ruler::Updater::UpdateOutputs {
Labels &majorLabels, &minorLabels, &minorMinorLabels;
@@ -1328,9 +1331,13 @@ void Ruler::ChooseFonts( wxDC &dc ) const
);
}
void Ruler::Update(
wxDC &dc, const Envelope* envelope )// Envelope *speedEnv, long minSpeed, long maxSpeed )
void Ruler::UpdateCache(
wxDC &dc, const Envelope* envelope )
const // Envelope *speedEnv, long minSpeed, long maxSpeed )
{
if ( mpCache )
return;
const ZoomInfo *zoomInfo = NULL;
if (!mLog && mOrientation == wxHORIZONTAL)
zoomInfo = mUseZoomInfo;
@@ -1340,6 +1347,8 @@ void Ruler::Update(
// tick positions and font size.
ChooseFonts( dc );
mpCache = std::make_unique< Cache >();
auto &cache = *mpCache;
// If ruler is being resized, we could end up with it being too small.
// Values of mLength of zero or below cause bad array allocations and
@@ -1349,33 +1358,31 @@ void Ruler::Update(
return;
if (mOrientation == wxHORIZONTAL)
mRect = wxRect(0,0, mLength,0);
cache.mRect = { 0, 0, mLength, 0 };
else
mRect = wxRect(0,0, 0,mLength);
cache.mRect = { 0, 0, 0, mLength };
// FIXME: Surely we do not need to allocate storage for the labels?
// We can just recompute them as we need them? Yes, but only if
// mCustom is false!!!!
if(!mCustom) {
mMajorLabels.clear();
mMinorLabels.clear();
mMinorMinorLabels.clear();
cache.mMajorLabels.clear();
cache.mMinorLabels.clear();
cache.mMinorMinorLabels.clear();
}
mBits = mUserBits;
mBits.resize( static_cast<size_t>(mLength + 1), false );
cache.mBits = mUserBits;
cache.mBits.resize( static_cast<size_t>(mLength + 1), false );
// Keep Updater const! We want no hidden state changes affecting its
// computations.
const Updater updater{ *this, zoomInfo };
Updater::UpdateOutputs allOutputs{
mMajorLabels, mMinorLabels, mMinorMinorLabels,
mBits, mRect
cache.mMajorLabels, cache.mMinorLabels, cache.mMinorMinorLabels,
cache.mBits, cache.mRect
};
updater.Update(dc, envelope, allOutputs);
mValid = true;
}
auto Ruler::GetFonts() const -> Fonts
@@ -1388,18 +1395,18 @@ auto Ruler::GetFonts() const -> Fonts
return *mpFonts;
}
void Ruler::Draw(wxDC& dc)
void Ruler::Draw(wxDC& dc) const
{
Draw( dc, NULL);
}
void Ruler::Draw(wxDC& dc, const Envelope* envelope)
void Ruler::Draw(wxDC& dc, const Envelope* envelope) const
{
if( mLength <=0 )
return;
if (!mValid)
Update( dc, envelope );
UpdateCache( dc, envelope );
auto &cache = *mpCache;
dc.SetTextForeground( mTickColour );
#ifdef EXPERIMENTAL_THEMING
@@ -1464,18 +1471,18 @@ void Ruler::Draw(wxDC& dc, const Envelope* envelope)
label.Draw(dc, mTwoTone, mTickColour);
};
for( const auto &label : mMajorLabels )
for( const auto &label : cache.mMajorLabels )
drawLabel( label, 4 );
if( mbMinor ) {
dc.SetFont( mpFonts->minor );
for( const auto &label : mMinorLabels )
for( const auto &label : cache.mMinorLabels )
drawLabel( label, 2 );
}
dc.SetFont( mpFonts->minorMinor );
for( const auto &label : mMinorMinorLabels )
for( const auto &label : cache.mMinorMinorLabels )
if ( !label.text.empty() )
drawLabel( label, 2 );
}
@@ -1484,9 +1491,10 @@ void Ruler::Draw(wxDC& dc, const Envelope* envelope)
void Ruler::DrawGrid(wxDC& dc,
const int gridLineLength,
const bool minorGrid, const bool majorGrid, int xOffset, int yOffset)
const
{
if ( !mValid )
Update( dc, nullptr );
UpdateCache( dc, nullptr );
auto &cache = *mpCache;
int gridPos;
wxPen gridPen;
@@ -1494,7 +1502,7 @@ void Ruler::DrawGrid(wxDC& dc,
if(mbMinor && (minorGrid && (gridLineLength != 0 ))) {
gridPen.SetColour(178, 178, 178); // very light grey
dc.SetPen(gridPen);
for( const auto &label : mMinorLabels ) {
for( const auto &label : cache.mMinorLabels ) {
gridPos = label.pos;
if(mOrientation == wxHORIZONTAL) {
if((gridPos != 0) && (gridPos != gridLineLength))
@@ -1510,7 +1518,7 @@ void Ruler::DrawGrid(wxDC& dc,
if(majorGrid && (gridLineLength != 0 )) {
gridPen.SetColour(127, 127, 127); // light grey
dc.SetPen(gridPen);
for( const auto &label : mMajorLabels ) {
for( const auto &label : cache.mMajorLabels ) {
gridPos = label.pos;
if(mOrientation == wxHORIZONTAL) {
if((gridPos != 0) && (gridPos != gridLineLength))
@@ -1553,25 +1561,28 @@ int Ruler::FindZero( const Labels &labels ) const
int Ruler::GetZeroPosition() const
{
wxASSERT( mpCache );
auto &cache = *mpCache;
int zero;
if( (zero = FindZero( mMajorLabels ) ) < 0)
zero = FindZero( mMinorLabels );
if( (zero = FindZero( cache.mMajorLabels ) ) < 0)
zero = FindZero( cache.mMinorLabels );
// PRL: don't consult minor minor??
return zero;
}
void Ruler::GetMaxSize(wxCoord *width, wxCoord *height)
{
if (!mValid) {
if ( !mpCache ) {
wxScreenDC sdc;
Update( sdc, nullptr );
UpdateCache( sdc, nullptr );
}
auto &cache = *mpCache;
if (width)
*width = mRect.GetWidth();
*width = cache.mRect.GetWidth();
if (height)
*height = mRect.GetHeight();
*height = cache.mRect.GetHeight();
}
@@ -1583,9 +1594,17 @@ void Ruler::SetCustomMode(bool value)
}
}
#if 0
// These two unused functions need reconsideration of their interactions with
// the cache and update
void Ruler::SetCustomMajorLabels(
const TranslatableStrings &labels, int start, int step)
{
SetCustomMode( true );
mpCache = std::make_unique<Cache>();
auto &cache = *mpCache;
auto &mMajorLabels = cache.mMajorLabels;
const auto numLabel = labels.size();
mMajorLabels.resize( numLabel );
@@ -1593,12 +1612,16 @@ void Ruler::SetCustomMajorLabels(
mMajorLabels[i].text = labels[i];
mMajorLabels[i].pos = start + i*step;
}
//Remember: DELETE majorlabels....
}
void Ruler::SetCustomMinorLabels(
const TranslatableStrings &labels, int start, int step)
{
SetCustomMode( true );
mpCache = std::make_unique<Cache>();
auto &cache = *mpCache;
auto &mMinorLabels = cache.mMinorLabels;
const auto numLabel = labels.size();
mMinorLabels.resize( numLabel );
@@ -1606,8 +1629,8 @@ void Ruler::SetCustomMinorLabels(
mMinorLabels[i].text = labels[i];
mMinorLabels[i].pos = start + i*step;
}
//Remember: DELETE majorlabels....
}
#endif
void Ruler::Label::Draw(wxDC&dc, bool twoTone, wxColour c) const
{

View File

@@ -138,12 +138,12 @@ class AUDACITY_DLL_API Ruler {
//
// Note that it will not erase for you...
void Draw(wxDC& dc);
void Draw(wxDC& dc, const Envelope* envelope);
void Draw(wxDC& dc) const;
void Draw(wxDC& dc, const Envelope* envelope) const;
// If length <> 0, draws lines perpendiculars to ruler corresponding
// to selected ticks (major, minor, or both), in an adjacent window.
// You may need to use the offsets if you are using part of the dc for rulers, borders etc.
void DrawGrid(wxDC& dc, int length, bool minor = true, bool major = true, int xOffset = 0, int yOffset = 0);
void DrawGrid(wxDC& dc, int length, bool minor = true, bool major = true, int xOffset = 0, int yOffset = 0) const;
// So we can have white ticks on black...
void SetTickColour( const wxColour & colour)
@@ -169,14 +169,14 @@ class AUDACITY_DLL_API Ruler {
using Bits = std::vector< bool >;
void ChooseFonts( wxDC &dc ) const;
void Update( wxDC &dc, const Envelope* envelope );
void UpdateCache( wxDC &dc, const Envelope* envelope ) const;
struct Updater;
public:
bool mbTicksOnly; // true => no line the length of the ruler
bool mbTicksAtExtremes;
wxRect mRect;
private:
wxColour mTickColour;
@@ -192,9 +192,6 @@ private:
double mHiddenMin, mHiddenMax;
Bits mUserBits;
Bits mBits;
bool mValid;
static std::pair< wxRect, Label > MakeTick(
Label lab,
@@ -203,17 +200,14 @@ private:
int left, int top, int spacing, int lead,
bool flip, int orientation );
Labels mMajorLabels;
Labels mMinorLabels;
Labels mMinorMinorLabels;
struct Cache;
mutable std::unique_ptr<Cache> mpCache;
// Returns 'zero' label coordinate (for grid drawing)
int FindZero( const Labels &labels ) const;
public:
int GetZeroPosition() const;
private:
int mOrientation;
int mSpacing;
double mDbMirrorValue;