1#pragma once
2
3#include <cstring>
4#include <cmath>
5#include <string>
6#include <Core/Types.h>
7
8#define UNICODE_BAR_CHAR_SIZE (strlen("█"))
9
10
11/** Allows you to draw a unicode-art bar whose width is displayed with a resolution of 1/8 character.
12 */
13
14
15namespace UnicodeBar
16{
17 using DB::Int64;
18
19 inline double getWidth(Int64 x, Int64 min, Int64 max, double max_width)
20 {
21 if (x <= min)
22 return 0;
23
24 if (x >= max)
25 return max_width;
26
27 return (x - min) * max_width / (max - min);
28 }
29
30 inline size_t getWidthInBytes(double width)
31 {
32 return ceil(width - 1.0 / 8) * UNICODE_BAR_CHAR_SIZE;
33 }
34
35 /// In `dst` there must be a space for barWidthInBytes(width) characters and a trailing zero.
36 inline void render(double width, char * dst)
37 {
38 size_t floor_width = floor(width);
39
40 for (size_t i = 0; i < floor_width; ++i)
41 {
42 memcpy(dst, "█", UNICODE_BAR_CHAR_SIZE);
43 dst += UNICODE_BAR_CHAR_SIZE;
44 }
45
46 size_t remainder = floor((width - floor_width) * 8);
47
48 if (remainder)
49 {
50 memcpy(dst, &"▏▎▍▌▋▋▊▉"[(remainder - 1) * UNICODE_BAR_CHAR_SIZE], UNICODE_BAR_CHAR_SIZE);
51 dst += UNICODE_BAR_CHAR_SIZE;
52 }
53
54 *dst = 0;
55 }
56
57 inline std::string render(double width)
58 {
59 std::string res(getWidthInBytes(width), '\0');
60 render(width, res.data());
61 return res;
62 }
63}
64