1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
|
#include "drape_frontend/visual_params.hpp"
#include "base/macros.hpp"
#include "base/math.hpp"
#include "base/assert.hpp"
#include "geometry/mercator.hpp"
#include "indexer/scales.hpp"
#include "std/target_os.hpp"
#include <algorithm>
#include <cmath>
#include <limits>
#include <utility>
namespace df
{
using VisualScale = std::pair<std::string, double>;
#ifdef DEBUG
static bool g_isInited = false;
#define RISE_INITED g_isInited = true
#define ASSERT_INITED ASSERT(g_isInited, ())
#else
#define RISE_INITED
#define ASSERT_INITED
#endif
double const VisualParams::kMdpiScale = 1.0;
double const VisualParams::kHdpiScale = 1.5;
double const VisualParams::kXhdpiScale = 2.0;
double const VisualParams::k6plusScale = 2.4;
double const VisualParams::kXxhdpiScale = 3.0;
double const VisualParams::kXxxhdpiScale = 3.5;
VisualParams::VisualParams()
: m_tileSize(0)
, m_visualScale(0.0)
, m_fontScale(1.0)
{}
VisualParams & VisualParams::Instance()
{
static VisualParams vizParams;
return vizParams;
}
void VisualParams::Init(double vs, uint32_t tileSize)
{
VisualParams & vizParams = Instance();
vizParams.m_tileSize = tileSize;
vizParams.m_visualScale = vs;
// Here we set up glyphs rendering parameters separately for high-res and low-res screens.
if (vs <= 1.0)
vizParams.m_glyphVisualParams = { 0.48f, 0.08f, 0.2f, 0.01f, 0.49f, 0.04f };
else
vizParams.m_glyphVisualParams = { 0.5f, 0.06f, 0.2f, 0.01f, 0.49f, 0.04f };
RISE_INITED;
}
uint32_t VisualParams::GetGlyphSdfScale() const
{
ASSERT_INITED;
return (m_visualScale <= 1.0) ? 3 : 4;
}
bool VisualParams::IsSdfPrefered() const
{
ASSERT_INITED;
return m_visualScale >= kHdpiScale;
}
uint32_t VisualParams::GetGlyphBaseSize() const
{
ASSERT_INITED;
return 22;
}
double VisualParams::GetFontScale() const
{
ASSERT_INITED;
return m_fontScale;
}
void VisualParams::SetFontScale(double fontScale)
{
ASSERT_INITED;
m_fontScale = fontScale;
}
void VisualParams::SetVisualScale(double visualScale)
{
ASSERT_INITED;
m_visualScale = visualScale;
}
std::string const & VisualParams::GetResourcePostfix(double visualScale)
{
ASSERT_INITED;
static VisualScale postfixes[] =
{
std::make_pair("mdpi", kMdpiScale),
std::make_pair("hdpi", kHdpiScale),
std::make_pair("xhdpi", kXhdpiScale),
std::make_pair("6plus", k6plusScale),
std::make_pair("xxhdpi", kXxhdpiScale),
std::make_pair("xxxhdpi", kXxxhdpiScale),
};
// Looking for the nearest available scale.
int postfixIndex = -1;
double minValue = std::numeric_limits<double>::max();
for (int i = 0; i < static_cast<int>(ARRAY_SIZE(postfixes)); i++)
{
double val = fabs(postfixes[i].second - visualScale);
if (val < minValue)
{
minValue = val;
postfixIndex = i;
}
}
ASSERT_GREATER_OR_EQUAL(postfixIndex, 0, ());
return postfixes[postfixIndex].first;
}
std::string const & VisualParams::GetResourcePostfix() const
{
ASSERT_INITED;
return VisualParams::GetResourcePostfix(m_visualScale);
}
double VisualParams::GetVisualScale() const
{
ASSERT_INITED;
return m_visualScale;
}
uint32_t VisualParams::GetTileSize() const
{
ASSERT_INITED;
return m_tileSize;
}
uint32_t VisualParams::GetTouchRectRadius() const
{
ASSERT_INITED;
float const kRadiusInPixels = 20.0f;
return static_cast<uint32_t>(kRadiusInPixels * GetVisualScale());
}
double VisualParams::GetDragThreshold() const
{
ASSERT_INITED;
double const kDragThresholdInPixels = 10.0;
return kDragThresholdInPixels * GetVisualScale();
}
double VisualParams::GetScaleThreshold() const
{
ASSERT_INITED;
double const kScaleThresholdInPixels = 2.0;
return kScaleThresholdInPixels * GetVisualScale();
}
VisualParams::GlyphVisualParams const & VisualParams::GetGlyphVisualParams() const
{
ASSERT_INITED;
return m_glyphVisualParams;
}
m2::RectD const & GetWorldRect()
{
static m2::RectD const worldRect = MercatorBounds::FullRect();
return worldRect;
}
int GetTileScaleBase(ScreenBase const & s, uint32_t tileSize)
{
ScreenBase tmpS = s;
tmpS.Rotate(-tmpS.GetAngle());
auto const halfSize = tileSize / 2;
m2::RectD glbRect;
m2::PointD const pxCenter = tmpS.PixelRect().Center();
tmpS.PtoG(m2::RectD(pxCenter - m2::PointD(halfSize, halfSize),
pxCenter + m2::PointD(halfSize, halfSize)),
glbRect);
return GetTileScaleBase(glbRect);
}
int GetTileScaleBase(ScreenBase const & s)
{
return GetTileScaleBase(s, VisualParams::Instance().GetTileSize());
}
int GetTileScaleBase(m2::RectD const & r)
{
double const sz = std::max(r.SizeX(), r.SizeY());
return std::max(1, base::rounds(log(MercatorBounds::kRangeX / sz) / log(2.0)));
}
double GetTileScaleBase(double drawScale)
{
return std::max(1.0, drawScale - GetTileScaleIncrement());
}
int GetTileScaleIncrement(uint32_t tileSize, double visualScale)
{
return static_cast<int>(log(tileSize / 256.0 / visualScale) / log(2.0));
}
int GetTileScaleIncrement()
{
VisualParams const & p = VisualParams::Instance();
return GetTileScaleIncrement(p.GetTileSize(), p.GetVisualScale());
}
m2::RectD GetRectForDrawScale(int drawScale, m2::PointD const & center, uint32_t tileSize, double visualScale)
{
// +1 - we will calculate half length for each side
double const factor = 1 << (std::max(1, drawScale - GetTileScaleIncrement(tileSize, visualScale)) + 1);
double const len = MercatorBounds::kRangeX / factor;
return m2::RectD(MercatorBounds::ClampX(center.x - len),
MercatorBounds::ClampY(center.y - len),
MercatorBounds::ClampX(center.x + len),
MercatorBounds::ClampY(center.y + len));
}
m2::RectD GetRectForDrawScale(int drawScale, m2::PointD const & center)
{
VisualParams const & p = VisualParams::Instance();
return GetRectForDrawScale(drawScale, center, p.GetTileSize(), p.GetVisualScale());
}
m2::RectD GetRectForDrawScale(double drawScale, m2::PointD const & center, uint32_t tileSize, double visualScale)
{
return GetRectForDrawScale(base::rounds(drawScale), center, tileSize, visualScale);
}
m2::RectD GetRectForDrawScale(double drawScale, m2::PointD const & center)
{
return GetRectForDrawScale(base::rounds(drawScale), center);
}
uint32_t CalculateTileSize(uint32_t screenWidth, uint32_t screenHeight)
{
uint32_t const maxSz = std::max(screenWidth, screenHeight);
// we're calculating the tileSize based on (maxSz > 1024 ? rounded : ceiled)
// to the nearest power of two value of the maxSz
int const ceiledSz = 1 << static_cast<int>(ceil(log(double(maxSz + 1)) / log(2.0)));
int res = 0;
if (maxSz < 1024)
{
res = ceiledSz;
}
else
{
int const flooredSz = ceiledSz / 2;
// rounding to the nearest power of two.
if (ceiledSz - maxSz < maxSz - flooredSz)
res = ceiledSz;
else
res = flooredSz;
}
#ifndef OMIM_OS_DESKTOP
return static_cast<uint32_t>(base::clamp(res / 2, 256, 1024));
#else
return static_cast<uint32_t>(base::clamp(res / 2, 512, 1024));
#endif
}
int GetDrawTileScale(int baseScale, uint32_t tileSize, double visualScale)
{
return std::max(1, baseScale + GetTileScaleIncrement(tileSize, visualScale));
}
int GetDrawTileScale(ScreenBase const & s, uint32_t tileSize, double visualScale)
{
return GetDrawTileScale(GetTileScaleBase(s, tileSize), tileSize, visualScale);
}
int GetDrawTileScale(m2::RectD const & r, uint32_t tileSize, double visualScale)
{
return GetDrawTileScale(GetTileScaleBase(r), tileSize, visualScale);
}
int GetDrawTileScale(int baseScale)
{
VisualParams const & p = VisualParams::Instance();
return GetDrawTileScale(baseScale, p.GetTileSize(), p.GetVisualScale());
}
double GetDrawTileScale(double baseScale)
{
return std::max(1.0, baseScale + GetTileScaleIncrement());
}
int GetDrawTileScale(ScreenBase const & s)
{
VisualParams const & p = VisualParams::Instance();
return GetDrawTileScale(s, p.GetTileSize(), p.GetVisualScale());
}
int GetDrawTileScale(m2::RectD const & r)
{
VisualParams const & p = VisualParams::Instance();
return GetDrawTileScale(r, p.GetTileSize(), p.GetVisualScale());
}
void ExtractZoomFactors(ScreenBase const & s, double & zoom, int & index, float & lerpCoef)
{
double const zoomLevel = GetZoomLevel(s.GetScale());
zoom = trunc(zoomLevel);
index = static_cast<int>(zoom - 1.0);
lerpCoef = static_cast<float>(zoomLevel - zoom);
}
float InterpolateByZoomLevels(int index, float lerpCoef, std::vector<float> const & values)
{
ASSERT_GREATER_OR_EQUAL(index, 0, ());
ASSERT_GREATER(values.size(), scales::UPPER_STYLE_SCALE, ());
if (index < scales::UPPER_STYLE_SCALE)
return values[index] + lerpCoef * (values[index + 1] - values[index]);
return values[scales::UPPER_STYLE_SCALE];
}
m2::PointF InterpolateByZoomLevels(int index, float lerpCoef, std::vector<m2::PointF> const & values)
{
ASSERT_GREATER_OR_EQUAL(index, 0, ());
ASSERT_GREATER(values.size(), scales::UPPER_STYLE_SCALE, ());
if (index < scales::UPPER_STYLE_SCALE)
return values[index] + (values[index + 1] - values[index]) * lerpCoef;
return values[scales::UPPER_STYLE_SCALE];
}
double GetNormalizedZoomLevel(double screenScale, int minZoom)
{
double const kMaxZoom = scales::GetUpperStyleScale() + 1.0;
return base::clamp((GetZoomLevel(screenScale) - minZoom) / (kMaxZoom - minZoom), 0.0, 1.0);
}
double GetScreenScale(double zoomLevel)
{
VisualParams const & p = VisualParams::Instance();
auto const factor = pow(2.0, GetTileScaleBase(zoomLevel));
auto const len = MercatorBounds::kRangeX / factor;
auto const pxLen = static_cast<double>(p.GetTileSize());
return len / pxLen;
}
double GetZoomLevel(double screenScale)
{
VisualParams const & p = VisualParams::Instance();
auto const pxLen = static_cast<double>(p.GetTileSize());
auto const len = pxLen * screenScale;
auto const factor = MercatorBounds::kRangeX / len;
static double const kLog2 = log(2.0);
return base::clamp(GetDrawTileScale(fabs(log(factor) / kLog2)), 1.0, scales::GetUpperStyleScale() + 1.0);
}
} // namespace df
|