HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
pixel_density.hpp
1// Copyright Take Vos 2024.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "pixels_per_inch.hpp"
8#include "dips.hpp"
9#include "pixels.hpp"
10#include "font_size.hpp"
11#include "../utility/utility.hpp"
12#include "../macros.hpp"
13
14namespace hi { inline namespace v1 {
15
18 device_type type;
19
20 template<typename T>
21 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
22 operator*(pixel_density const& lhs, au::Quantity<Dips, T> const& rhs) noexcept
23 {
24 return pixels(lhs.density_scale() * rhs.in(dips));
25 }
26
27 template<typename T>
28 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
29 operator*(au::Quantity<Dips, T> const& lhs, pixel_density const& rhs) noexcept
30 {
31 return rhs * lhs;
32 }
33
34 template<typename T>
35 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
36 operator*(pixel_density const& lhs, au::Quantity<au::Inches, T> const& rhs) noexcept
37 {
38 return lhs.ppi * rhs;
39 }
40
41 template<typename T>
42 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
43 operator*(au::Quantity<au::Inches, T> const& lhs, pixel_density const& rhs) noexcept
44 {
45 return rhs * lhs;
46 }
47
48 template<typename T>
49 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
50 operator*(pixel_density const& lhs, au::Quantity<Pixels, T> const& rhs) noexcept
51 {
52 return rhs;
53 }
54
55 template<typename T>
56 [[nodiscard]] constexpr friend au::Quantity<Pixels, std::common_type_t<float, T>>
57 operator*(au::Quantity<Pixels, T> const& lhs, pixel_density const& rhs) noexcept
58 {
59 return lhs;
60 }
61
62 template<typename T>
63 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
64 operator*(pixel_density const& lhs, au::Quantity<DipsPerEm, T> const& rhs) noexcept
65 {
66 return pixels_per_em(lhs.density_scale() * rhs.in(dips_per_em));
67 }
68
69 template<typename T>
70 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
71 operator*(au::Quantity<DipsPerEm, T> const& lhs, pixel_density const& rhs) noexcept
72 {
73 return rhs * lhs;
74 }
75
76 template<typename T>
77 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
78 operator*(pixel_density const& lhs, au::Quantity<PointsPerEm, T> const& rhs) noexcept
79 {
80 return lhs.ppi * rhs;
81 }
82
83 template<typename T>
84 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
85 operator*(au::Quantity<PointsPerEm, T> const& lhs, pixel_density const& rhs) noexcept
86 {
87 return rhs * lhs;
88 }
89
90 template<typename T>
91 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
92 operator*(pixel_density const& lhs, au::Quantity<PixelsPerEm, T> const& rhs) noexcept
93 {
94 return rhs;
95 }
96
97 template<typename T>
98 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
99 operator*(au::Quantity<PixelsPerEm, T> const& lhs, pixel_density const& rhs) noexcept
100 {
101 return lhs;
102 }
103
104 template<typename T>
105 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
106 operator*(pixel_density const& lhs, font_size_quantity<T> const& rhs) noexcept
107 {
108 if (auto const* dips_per_em_ptr = std::get_if<au::Quantity<DipsPerEm, T>>(&rhs)) {
109 return *dips_per_em_ptr * lhs;
110 } else if (auto const* pixels_per_em_ptr = std::get_if<au::Quantity<PixelsPerEm, T>>(&rhs)) {
111 return *pixels_per_em_ptr * lhs;
112 } else if (auto const* points_per_em_ptr = std::get_if<au::Quantity<PointsPerEm, T>>(&rhs)) {
113 return *points_per_em_ptr * lhs;
114 } else {
115 hi_no_default();
116 }
117 }
118
119 template<typename T>
120 [[nodiscard]] constexpr friend au::Quantity<PixelsPerEm, std::common_type_t<float, T>>
121 operator*(font_size_quantity<T> const& lhs, pixel_density const& rhs) noexcept
122 {
123 return rhs * lhs;
124 }
125
126private:
129 [[nodiscard]] constexpr float density_scale() const noexcept
130 {
131 constexpr auto scale_table = std::array{
132 0.5f,
133 0.5f,
134 0.5f,
135
136 0.75f, // 120 dpi
137
138 1.0f, // 160 dpi
139 1.0f,
140
141 1.5f, // 240 dpi
142 1.5f,
143
144 2.0f, // 320 dpi
145 2.0f,
146 2.0f,
147 2.0f,
148
149 3.0f, // 480 dpi
150 3.0f,
151 3.0f,
152 3.0f,
153 4.0f, // 640 dpi
154 };
155
156 // The base density is based on the device type which determines
157 // the viewing distance. We strip off the last three bits as there
158 // are multiple devices that need unique values but have the same
159 // base density.
160 auto const base_density = std::to_underlying(type) & 0xf8;
161
162 // casting to unsigned int is faster than size_t.
163 auto const index = static_cast<unsigned int>(ppi.in(pixels_per_inch)) * 4 / base_density;
164
165 // Using a table here is faster than the compiler will generate with
166 // a switch statement. The bound check here will result in a conditional
167 // move instead of a conditional jump.
168 if (index < scale_table.size()) {
169 return scale_table[index];
170 } else {
171 return scale_table.back();
172 }
173 }
174};
175
176}} // namespace hi::v1
The HikoGUI namespace.
Definition array_generic.hpp:20
device_type
The device type this application is running on.
Definition device_type.hpp:14
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
Definition font_size.hpp:30
Definition pixel_density.hpp:16
T back(T... args)