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