diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-04-18 23:56:56 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-04-20 21:18:19 +0200 |
| commit | 34e88d2353cc6976356e011f79dc5177b200941a (patch) | |
| tree | 98d6031ca977ffa71b489086e0eb45943fad3f43 | |
| parent | 9a4ccc554f5c8784b7b34ccaa0f760b491e5a7ab (diff) | |
add scales
| -rw-r--r-- | src/wx/simple_meters.cc | 79 | ||||
| -rw-r--r-- | src/wx/simple_meters.h | 3 | ||||
| -rw-r--r-- | src/wx/text_size_cache.cc | 47 | ||||
| -rw-r--r-- | src/wx/text_size_cache.h | 40 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
5 files changed, 138 insertions, 32 deletions
diff --git a/src/wx/simple_meters.cc b/src/wx/simple_meters.cc index 06eabce8b..c4af8c0fe 100644 --- a/src/wx/simple_meters.cc +++ b/src/wx/simple_meters.cc @@ -32,9 +32,6 @@ LIBDCP_ENABLE_WARNINGS #include <algorithm> -static auto constexpr min_db = -70.0f; - - using std::shared_ptr; #if BOOST_VERSION >= 106100 using namespace boost::placeholders; @@ -58,31 +55,34 @@ SimpleMeters::get() const void SimpleMeters::paint() { + auto constexpr min_db = -70.0f; + auto constexpr border = 16; + auto constexpr scale_label_width = 28; + wxPaintDC dc(_panel); dc.SetBackground(*wxBLACK_BRUSH); dc.Clear(); - if (_peaks.empty()) { - return; - } - auto const scale = 1 / dpi_scale_factor(_panel); - dc.SetLogicalScale(scale, scale); - auto const panel_size = dcp::Size(_panel->GetSize().GetWidth() / scale, _panel->GetSize().GetHeight() / scale); + auto const meter_height = panel_size.height - 24 - 2 * border; + dc.SetLogicalScale(scale, scale); - auto const channel_width = panel_size.width / _peaks.size(); - auto const meter_height = panel_size.height - 24; - - int x = 0; - dc.SetBrush(*wxGREEN_BRUSH); - for (auto peak: _peaks) { - auto const peak_db = std::max(min_db, 20 * log10(peak)); - auto const height = (peak_db - min_db) * meter_height / -min_db; - dc.DrawRectangle(x, meter_height - height, channel_width, height); - x += channel_width; - } + auto db_to_y = [meter_height](float db) { + return border + meter_height - (db - min_db) * meter_height / -min_db; + }; + + static auto const scales = std::vector<std::pair<int, wxString>>{ + { 0, wxT("0dB") }, + { -10, wxT("-10dB") }, + { -20, wxT("-20dB") }, + { -30, wxT("-30dB") }, + { -40, wxT("-40dB") }, + { -50, wxT("-50dB") }, + { -60, wxT("-60dB") }, + { -70, wxT("-70dB") }, + }; auto gc = wxGraphicsContext::Create(dc); if (!gc) { @@ -92,20 +92,37 @@ SimpleMeters::paint() gc->SetAntialiasMode(wxANTIALIAS_DEFAULT); gc->SetFont(gc->CreateFont(*wxSMALL_FONT, *wxWHITE)); - if (_label_widths.empty()) { - _label_widths.resize(MAX_DCP_AUDIO_CHANNELS); - for (auto i = 0; i < MAX_DCP_AUDIO_CHANNELS; ++i) { - wxDouble label_width; - wxDouble label_height; - wxDouble label_descent; - wxDouble label_leading; - gc->GetTextExtent(std_to_wx(short_audio_channel_name(i)), &label_width, &label_height, &label_descent, &label_leading); - _label_widths[i] = label_width; - } + /* Scale lines and labels (0dB, -10dB etc.) */ + dc.SetPen(*wxGREY_PEN); + for (auto const& scale: scales) { + auto const y = static_cast<int>(std::round(db_to_y(scale.first))); + dc.DrawLine({ border + scale_label_width, y }, { panel_size.width - border, y }); + auto const size = _sizes.get(gc, scale.second); + gc->DrawText(scale.second, border + scale_label_width - size.width - 4, y - size.height / 2); + } + + if (_peaks.empty()) { + delete gc; + return; + } + + auto const channel_width = (panel_size.width - 2 * border - scale_label_width) / _peaks.size(); + + /* Meter bars */ + int x = border + scale_label_width; + dc.SetBrush(*wxGREEN_BRUSH); + dc.SetPen(*wxBLACK_PEN); + for (auto peak: _peaks) { + auto const peak_db = std::max(min_db, 20 * log10(peak)); + auto const y = db_to_y(peak_db); + dc.DrawRectangle(x, y, channel_width, meter_height - y + border); + x += channel_width; } + /* Channel name labels */ for (auto i = 0; i < MAX_DCP_AUDIO_CHANNELS; ++i) { - gc->DrawText(std_to_wx(short_audio_channel_name(i)), i * channel_width + (channel_width - _label_widths[i]) / 2, panel_size.height - 24); + auto name = std_to_wx(short_audio_channel_name(i)); + gc->DrawText(name, border + scale_label_width + i * channel_width + (channel_width - _sizes.get(gc, name).width) / 2, panel_size.height - 24); } delete gc; diff --git a/src/wx/simple_meters.h b/src/wx/simple_meters.h index 779a12b9b..fc96dd8cb 100644 --- a/src/wx/simple_meters.h +++ b/src/wx/simple_meters.h @@ -24,6 +24,7 @@ #include "lib/dcpomatic_time.h" +#include "text_size_cache.h" #include <memory> #include <vector> @@ -57,7 +58,7 @@ private: std::weak_ptr<LevelCalculator> _level_calculator; - std::vector<float> _label_widths; + TextSizeCache _sizes; }; diff --git a/src/wx/text_size_cache.cc b/src/wx/text_size_cache.cc new file mode 100644 index 000000000..03b7e62ff --- /dev/null +++ b/src/wx/text_size_cache.cc @@ -0,0 +1,47 @@ +/* + Copyright (C) 2025 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include "text_size_cache.h" +LIBDCP_DISABLE_WARNINGS +#include <wx/graphics.h> +LIBDCP_ENABLE_WARNINGS +#include <wx/wx.h> + + +dcp::Size +TextSizeCache::get(wxGraphicsContext* gc, wxString const& text) +{ + auto iter = _known.find(text); + if (iter != _known.end()) { + return iter->second; + } + + wxDouble width; + wxDouble height; + wxDouble descent; + wxDouble leading; + gc->GetTextExtent(text, &width, &height, &descent, &leading); + auto size = dcp::Size{static_cast<int>(std::round(width)), static_cast<int>(std::round(height))}; + _known[text] = size; + + return size; +} + diff --git a/src/wx/text_size_cache.h b/src/wx/text_size_cache.h new file mode 100644 index 000000000..58fb9c82a --- /dev/null +++ b/src/wx/text_size_cache.h @@ -0,0 +1,40 @@ +/* + Copyright (C) 2025 Carl Hetherington <cth@carlh.net> + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>. + +*/ + + +#include <dcp/types.h> +#include <wx/wx.h> +#include <unordered_map> + + +class wxGraphicsContext; +class wxString; + + +class TextSizeCache +{ +public: + TextSizeCache() = default; + + dcp::Size get(wxGraphicsContext* gc, wxString const& text); + +private: + std::unordered_map<wxString, dcp::Size> _known; +}; diff --git a/src/wx/wscript b/src/wx/wscript index 9a9a79d9c..a2939adb1 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -176,6 +176,7 @@ sources = """ tall_kdm_output_panel.cc templates_dialog.cc text_panel.cc + text_size_cache.cc text_view.cc time_picker.cc timer_display.cc |
