From bd215b34bca7174725632d408aec99ea03a7012e Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Sun, 22 Nov 2020 13:01:52 +1100 Subject: [PATCH] viewer: simplified sizing algorithm and add padding for fit so gizmos are easier to use --- app/widget/viewer/viewerdisplay.cpp | 4 +- app/widget/viewer/viewersizer.cpp | 159 +++++++++++----------------- 2 files changed, 62 insertions(+), 101 deletions(-) diff --git a/app/widget/viewer/viewerdisplay.cpp b/app/widget/viewer/viewerdisplay.cpp index f29f50c0e..165717de4 100644 --- a/app/widget/viewer/viewerdisplay.cpp +++ b/app/widget/viewer/viewerdisplay.cpp @@ -315,9 +315,9 @@ void ViewerDisplayWidget::OnPaint() int device_width = width() * devicePixelRatioF(); int device_height = height() * devicePixelRatioF(); VideoParams::Format device_format = static_cast(Config::Current()["OfflinePixelFormat"].toInt()); + VideoParams device_params(device_width, device_height, device_format, VideoParams::kInternalChannelCount); - renderer()->BlitColorManaged(color_service(), texture_to_draw, true, - VideoParams(device_width, device_height, device_format, VideoParams::kInternalChannelCount), + renderer()->BlitColorManaged(color_service(), texture_to_draw, true, device_params, combined_matrix_flipped_); } diff --git a/app/widget/viewer/viewersizer.cpp b/app/widget/viewer/viewersizer.cpp index 2db30c9d4..1e740d73c 100644 --- a/app/widget/viewer/viewersizer.cpp +++ b/app/widget/viewer/viewersizer.cpp @@ -107,117 +107,78 @@ void ViewerSizer::UpdateSize() return; } - widget_->setVisible(true); - - QSize child_size; - QMatrix4x4 child_matrix; - + // Calculate how much UI space is available (it will be less if we have to show scrollbars) int available_width = width(); int available_height = height(); - double sequence_aspect_ratio = static_cast(width_) / static_cast(height_) + + // Determine if we need scrollbars for the zoom we want + horiz_scrollbar_->setVisible(zoom_ > 0 && GetZoomedValue(width_) > available_width); + vert_scrollbar_->setVisible(zoom_ > 0 && GetZoomedValue(height_) > available_height); + + // Horizontal scrollbar will reduce the available height + if (horiz_scrollbar_->isVisible()) { + available_height -= horiz_scrollbar_->sizeHint().height(); + } + + // Vertical scrollbar will reduce the available width + if (vert_scrollbar_->isVisible()) { + available_width -= vert_scrollbar_->sizeHint().width(); + } + + // Set correct values on horizontal scrollbar + if (horiz_scrollbar_->isVisible()) { + horiz_scrollbar_->resize(available_width, horiz_scrollbar_->sizeHint().height()); + horiz_scrollbar_->move(0, this->height() - horiz_scrollbar_->height() - 1); + horiz_scrollbar_->setMaximum(GetZoomedValue(width_) - available_width); + horiz_scrollbar_->setPageStep(available_width); + } + + // Set correct values on vertical scrollbar + if (vert_scrollbar_->isVisible()) { + vert_scrollbar_->resize(vert_scrollbar_->sizeHint().width(), available_height); + vert_scrollbar_->move(this->width() - vert_scrollbar_->width() - 1, 0); + vert_scrollbar_->setMaximum(GetZoomedValue(height_) - available_height); + vert_scrollbar_->setPageStep(available_height); + } + + // Size widget to the UI space we've calculated + widget_->setVisible(true); + widget_->resize(available_width, available_height); + + // Adjust to aspect ratio + double sequence_aspect_ratio = double(width_) / double(height_) * pixel_aspect_.toDouble(); + double our_aspect_ratio = double(available_width) / double(available_height); - if (zoom_ <= 0) { + QMatrix4x4 child_matrix; + double current_scale; - // If zoom is zero or negative, we auto-fit - double our_aspect_ratio = static_cast(available_width) / static_cast(available_height); + if (our_aspect_ratio > sequence_aspect_ratio) { - child_size = size(); - - if (our_aspect_ratio > sequence_aspect_ratio) { - // This container is wider than the image, scale by height - child_size = QSize(qRound(child_size.height() * sequence_aspect_ratio), available_height); - } else { - // This container is taller than the image, scale by width - child_size = QSize(available_width, qRound(child_size.width() / sequence_aspect_ratio)); - } - - // No scrollbars necessary for auto-fit - horiz_scrollbar_->setVisible(false); - vert_scrollbar_->setVisible(false); + // This container is wider than the image, scale by height + child_matrix.scale(sequence_aspect_ratio / our_aspect_ratio, 1.0); + current_scale = double(available_height) / double(height_); } else { - float x_scale = 1.0f; - float y_scale = 1.0f; + // This container is taller than the image, scale by width + child_matrix.scale(1.0, our_aspect_ratio / sequence_aspect_ratio); + current_scale = double(available_width) / double(width_); - int zoomed_width = GetZoomedValue(width_); - int zoomed_height = GetZoomedValue(height_); - - bool child_exceeds_parent_width = (zoomed_width > available_width); - bool child_exceeds_parent_height = (zoomed_height > available_height); - - if (child_exceeds_parent_width != child_exceeds_parent_height) { - // One scrollbar definitely needs to be shown, so it's a matter of determining if the other - // does too since adding one scrollbar necessary limits the total area - - if (child_exceeds_parent_height) { - // A vertical scrollbar will need to be shown, which limits the width - child_exceeds_parent_width = (zoomed_width > available_width - vert_scrollbar_->sizeHint().width()); - } else { - // A horizontal scrollbar will need to be shown, which limits the height - child_exceeds_parent_height = (zoomed_height > available_height - horiz_scrollbar_->sizeHint().height()); - } - } - - horiz_scrollbar_->setVisible(child_exceeds_parent_width); - vert_scrollbar_->setVisible(child_exceeds_parent_height); - - if (vert_scrollbar_->isVisible()) { - // Limit available width for further calculations - available_width -= vert_scrollbar_->sizeHint().width(); - } - - if (horiz_scrollbar_->isVisible()) { - // Limit available height for further calculations - available_height -= horiz_scrollbar_->sizeHint().height(); - } - - if (horiz_scrollbar_->isVisible()) { - x_scale = static_cast(zoomed_width) / static_cast(available_width); - - // Update scrollbar sizes - int horiz_width = this->width(); - - if (vert_scrollbar_->isVisible()) { - horiz_width -= vert_scrollbar_->sizeHint().width(); - } - - horiz_scrollbar_->resize(horiz_width, horiz_scrollbar_->sizeHint().height()); - horiz_scrollbar_->move(0, this->height() - horiz_scrollbar_->height() - 1); - horiz_scrollbar_->setMaximum(zoomed_width - available_width); - horiz_scrollbar_->setPageStep(available_width); - - zoomed_width = available_width; - } - - if (vert_scrollbar_->isVisible()) { - y_scale = static_cast(zoomed_height) / static_cast(available_height); - - // Update scrollbar sizes - int vert_height = this->height(); - - if (horiz_scrollbar_->isVisible()) { - vert_height -= horiz_scrollbar_->sizeHint().height(); - } - - vert_scrollbar_->resize(vert_scrollbar_->sizeHint().width(), vert_height); - vert_scrollbar_->move(this->width() - vert_scrollbar_->width() - 1, 0); - vert_scrollbar_->setMaximum(zoomed_height - available_height); - vert_scrollbar_->setPageStep(available_height); - - zoomed_height = available_height; - } - - // Rather than make a huge surface, we still crop at our width/height and then signal a matrix - child_matrix.scale(x_scale, y_scale, 1.0F); - - child_size = QSize(zoomed_width, zoomed_height); } - widget_->resize(child_size); - widget_->move(available_width / 2 - child_size.width() / 2, - available_height / 2 - child_size.height() / 2); + if (zoom_ > 0) { + + // Scale to get to the requested zoom + double zoom_diff = (zoom_ * 0.01) / current_scale; + child_matrix.scale(zoom_diff, zoom_diff, 1.0); + + } else { + + // Fit - add a small amount of padding + child_matrix.scale(0.95, 0.95); + + } emit RequestScale(child_matrix);