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 | |
15 | namespace 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 | |