#pragma once #include "foundation/result.h" #include #include #include #include #include namespace pp::app { inline constexpr std::array document_resolution_values { 512, 1024, 1536, 2048, 4096, 8192, }; inline constexpr std::array document_resolution_labels { "2K", "4K", "6K", "8K", "16K", "32K", }; struct RecordingFrameLabel { bool visible = false; std::string text; }; struct RendererDiagnosticsInput { bool framebuffer_fetch = false; bool float32_render_targets = false; bool float32_linear_filtering = false; bool float16_render_targets = false; }; struct RendererDiagnosticIndicator { bool supported = false; std::string_view label; }; struct RendererDiagnosticsPlan { RendererDiagnosticIndicator framebuffer_fetch; RendererDiagnosticIndicator floating_point_targets; }; [[nodiscard]] inline pp::foundation::Result display_resolution_from_index(int index) { if (index < 0 || static_cast(index) >= document_resolution_values.size()) { return pp::foundation::Result::failure( pp::foundation::Status::out_of_range("document resolution index is out of range")); } return pp::foundation::Result::success( document_resolution_values[static_cast(index)]); } [[nodiscard]] inline pp::foundation::Result document_resolution_to_index(int resolution) { for (std::size_t index = 0; index < document_resolution_values.size(); ++index) { if (document_resolution_values[index] == resolution) { return pp::foundation::Result::success(index); } } return pp::foundation::Result::failure( pp::foundation::Status::out_of_range("document resolution is not supported")); } [[nodiscard]] inline pp::foundation::Result document_resolution_label(int resolution) { const auto index = document_resolution_to_index(resolution); if (!index) { return pp::foundation::Result::failure(index.status()); } return pp::foundation::Result::success(document_resolution_labels[index.value()]); } [[nodiscard]] inline std::string make_document_title( std::string_view document_name, bool has_unsaved_changes, int resolution) { const auto label = document_resolution_label(resolution); const auto resolution_label = label ? label.value() : std::string_view("unknown"); std::string title = "Panodoc: "; title.append(document_name); if (has_unsaved_changes) { title.push_back('*'); } title.append(" ("); title.append(resolution_label); title.push_back(')'); return title; } [[nodiscard]] inline std::string make_dpi_label(float zoom) { char buffer[64] {}; std::snprintf(buffer, sizeof(buffer), "%.1fx-dpi", zoom); return buffer; } [[nodiscard]] inline std::string make_history_memory_label(std::size_t bytes) { char buffer[128] {}; std::snprintf( buffer, sizeof(buffer), "History memory: %.2f Mb", static_cast(bytes) / 1024.0 / 1024.0); return buffer; } [[nodiscard]] inline RecordingFrameLabel make_recording_frame_label( bool is_recording, bool encoder_available, int encoded_frames) { if (!is_recording || !encoder_available) { return {}; } char buffer[128] {}; std::snprintf(buffer, sizeof(buffer), "Recorded %d frames", encoded_frames); return { true, buffer, }; } [[nodiscard]] inline RendererDiagnosticsPlan plan_renderer_diagnostics( RendererDiagnosticsInput input) noexcept { RendererDiagnosticsPlan plan; plan.framebuffer_fetch = { input.framebuffer_fetch, "FBF", }; if (input.float32_linear_filtering) { plan.floating_point_targets = { true, "F32L", }; } else if (input.float32_render_targets) { plan.floating_point_targets = { true, "F32", }; } else if (input.float16_render_targets) { plan.floating_point_targets = { true, "F16", }; } else { plan.floating_point_targets = { false, "", }; } return plan; } }