1 // Aseprite Render Library
2 // Copyright (c) 2001-2016 David Capello
3 //
4 // This file is released under the terms of the MIT license.
5 // Read LICENSE.txt for more information.
6 
7 #ifndef RENDER_ZOOM_H_INCLUDED
8 #define RENDER_ZOOM_H_INCLUDED
9 #pragma once
10 
11 #include "gfx/rect.h"
12 
13 namespace render {
14 
15   class Zoom {
16   public:
17     Zoom(int num, int den);
18 
scale()19     double scale() const {
20       return static_cast<double>(m_num) / static_cast<double>(m_den);
21     }
22 
23     // This value isn't used in operator==() or operator!=()
internalScale()24     double internalScale() const {
25       return m_internalScale;
26     }
27 
28     template<typename T>
apply(T x)29     T apply(T x) const { return (x * m_num / m_den); }
30 
31     template<typename T>
remove(T x)32     T remove(T x) const { return (x * m_den / m_num); }
33 
34     gfx::Rect apply(const gfx::Rect& r) const;
35     gfx::Rect remove(const gfx::Rect& r) const;
36 
37     bool in();
38     bool out();
39 
40     // Returns an linear zoom scale. This position can be incremented
41     // or decremented to get a new zoom value.
42     int linearScale() const;
43 
44     bool operator==(const Zoom& other) const {
45       return m_num == other.m_num && m_den == other.m_den;
46     }
47 
48     bool operator!=(const Zoom& other) const {
49       return !operator==(other);
50     }
51 
52     static Zoom fromScale(double scale);
53     static Zoom fromLinearScale(int i);
54     static int linearValues();
55 
56   private:
57     static int findClosestLinearScale(double scale);
58 
59     int m_num;
60     int m_den;
61 
62     // Internal scale value used for precise zooming purposes.
63     double m_internalScale;
64   };
65 
66   template<>
remove(int x)67   inline int Zoom::remove(int x) const {
68     if (x < 0)
69       return (x * m_den / m_num) - 1;
70     else
71       return (x * m_den / m_num);
72   }
73 
apply(const gfx::Rect & r)74   inline gfx::Rect Zoom::apply(const gfx::Rect& r) const {
75     return gfx::Rect(
76       apply(r.x), apply(r.y),
77       apply(r.x+r.w) - apply(r.x),
78       apply(r.y+r.h) - apply(r.y));
79   }
80 
remove(const gfx::Rect & r)81   inline gfx::Rect Zoom::remove(const gfx::Rect& r) const {
82     return gfx::Rect(
83       remove(r.x), remove(r.y),
84       remove(r.x+r.w) - remove(r.x),
85       remove(r.y+r.h) - remove(r.y));
86   }
87 
88 } // namespace render
89 
90 #endif // RENDER_ZOOM_H_INCLUDED
91