Jelajahi Sumber

ImageViewer: Change how scaling works

- Store scale as a (float) factor (not as %)
- Make scaling exponential so that matches PixelPaint and another
image viewers/editors/etc
Maciej 3 tahun lalu
induk
melakukan
ab324c1dae

+ 14 - 18
Userland/Applications/ImageViewer/ViewWidget.cpp

@@ -118,22 +118,21 @@ void ViewWidget::navigate(Directions direction)
     this->load_from_file(m_files_in_same_dir.at(index));
 }
 
-void ViewWidget::set_scale(int scale)
+void ViewWidget::set_scale(float scale)
 {
     if (m_bitmap.is_null())
         return;
 
-    if (scale < 10)
-        scale = 10;
-    if (scale > 1000)
-        scale = 1000;
+    if (scale < 0.1f)
+        scale = 0.1f;
+    if (scale > 10.f)
+        scale = 10.f;
 
     m_scale = scale;
-    float scale_factor = (float)m_scale / 100.0f;
 
     Gfx::IntSize new_size;
-    new_size.set_width(m_bitmap->width() * scale_factor);
-    new_size.set_height(m_bitmap->height() * scale_factor);
+    new_size.set_width(m_bitmap->width() * m_scale);
+    new_size.set_height(m_bitmap->height() * m_scale);
     m_bitmap_rect.set_size(new_size);
 
     if (on_scale_change)
@@ -207,19 +206,16 @@ void ViewWidget::mousemove_event(GUI::MouseEvent& event)
 
 void ViewWidget::mousewheel_event(GUI::MouseEvent& event)
 {
-    int new_scale = m_scale - event.wheel_delta() * 10;
-    if (new_scale < 10)
-        new_scale = 10;
-    if (new_scale > 1000)
-        new_scale = 1000;
+    float new_scale = m_scale / AK::exp2(event.wheel_delta() / 8.f);
+    if (new_scale < 0.1f)
+        new_scale = 0.1f;
+    if (new_scale > 10.f)
+        new_scale = 10.f;
 
     if (new_scale == m_scale) {
         return;
     }
 
-    auto old_scale_factor = (float)m_scale / 100.0f;
-    auto new_scale_factor = (float)new_scale / 100.0f;
-
     // focus_point is the window position the cursor is pointing to.
     // The pixel (in image space) the cursor points to is located at
     // (m_pan_origin + focus_point) / scale_factor.
@@ -232,7 +228,7 @@ void ViewWidget::mousewheel_event(GUI::MouseEvent& event)
     };
 
     // A little algebra shows that new m_pan_origin equals to:
-    m_pan_origin = (m_pan_origin + focus_point) * (new_scale_factor / old_scale_factor) - focus_point;
+    m_pan_origin = (m_pan_origin + focus_point) * (new_scale / m_scale) - focus_point;
 
     set_scale(new_scale);
 }
@@ -313,7 +309,7 @@ void ViewWidget::resize_window()
 void ViewWidget::reset_view()
 {
     m_pan_origin = { 0, 0 };
-    set_scale(100);
+    set_scale(1.f);
 }
 
 void ViewWidget::set_bitmap(const Gfx::Bitmap* bitmap)

+ 4 - 4
Userland/Applications/ImageViewer/ViewWidget.h

@@ -29,8 +29,8 @@ public:
 
     const Gfx::Bitmap* bitmap() const { return m_bitmap.ptr(); }
     const String& path() const { return m_path; }
-    void set_scale(int);
-    int scale() { return m_scale; }
+    void set_scale(float);
+    float scale() { return m_scale; }
     void set_toolbar_height(int height) { m_toolbar_height = height; }
     int toolbar_height() { return m_toolbar_height; }
     bool scaled_for_first_image() { return m_scaled_for_first_image; }
@@ -47,7 +47,7 @@ public:
     void navigate(Directions);
     void load_from_file(const String&);
 
-    Function<void(int)> on_scale_change;
+    Function<void(float)> on_scale_change;
     Function<void()> on_doubleclick;
     Function<void(const GUI::DropEvent&)> on_drop;
     Function<void(const Gfx::Bitmap*)> on_image_change;
@@ -78,7 +78,7 @@ private:
     size_t m_loops_completed { 0 };
     NonnullRefPtr<Core::Timer> m_timer;
 
-    int m_scale { -1 };
+    float m_scale { -1 };
     int m_toolbar_height { 28 };
     bool m_scaled_for_first_image { false };
     Gfx::FloatPoint m_pan_origin;

+ 5 - 5
Userland/Applications/ImageViewer/main.cpp

@@ -67,13 +67,13 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
     if (path) {
         widget.set_path(path);
     }
-    widget.on_scale_change = [&](int scale) {
+    widget.on_scale_change = [&](float scale) {
         if (!widget.bitmap()) {
             window->set_title("Image Viewer");
             return;
         }
 
-        window->set_title(String::formatted("{} {} {}% - Image Viewer", widget.path(), widget.bitmap()->size().to_string(), scale));
+        window->set_title(String::formatted("{} {} {}% - Image Viewer", widget.path(), widget.bitmap()->size().to_string(), (int)(scale * 100)));
 
         if (scale == 100 && !widget.scaled_for_first_image()) {
             widget.set_scaled_for_first_image(true);
@@ -200,19 +200,19 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
 
     auto zoom_in_action = GUI::CommonActions::make_zoom_in_action(
         [&](auto&) {
-            widget.set_scale(widget.scale() + 10);
+            widget.set_scale(widget.scale() * 1.44f);
         },
         window);
 
     auto reset_zoom_action = GUI::CommonActions::make_reset_zoom_action(
         [&](auto&) {
-            widget.set_scale(100);
+            widget.set_scale(1.f);
         },
         window);
 
     auto zoom_out_action = GUI::CommonActions::make_zoom_out_action(
         [&](auto&) {
-            widget.set_scale(widget.scale() - 10);
+            widget.set_scale(widget.scale() / 1.44f);
         },
         window);