Initialize raster texture on GPU with given images NOTE: Have to be called after OpenGL initialization.
82{
83 assert(!input.empty());
84 if (input.empty())
85 return {};
86
87
91 }
92
93 int total_surface = 0;
95 total_surface += i.size.x * i.size.y;
96 const int surface_sqrt = (int)sqrt((float)total_surface) + 1;
97
98
99
100 const int TEX_HEIGHT_MAX = 1024 * 32;
101 int width = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512;
102
103 int num_nodes =
width;
104 std::vector<stbrp_node> nodes(num_nodes);
105 stbrp_context context;
106 stbrp_init_target(&context, width, TEX_HEIGHT_MAX, nodes.data(), num_nodes);
107
108 ImVector<stbrp_rect> pack_rects;
109 pack_rects.resize(input.size());
110 memset(pack_rects.Data, 0, (size_t) pack_rects.size_in_bytes());
111 for (size_t i = 0; i < input.size(); i++) {
112 const ImVec2 &size = input[i].size;
113 assert(size.x > 1);
114 assert(size.y > 1);
115 pack_rects[i].w = size.x;
116 pack_rects[i].h = size.y;
117 }
118 int pack_rects_res = stbrp_pack_rects(&context, &pack_rects[0], pack_rects.Size);
119 assert(pack_rects_res == 1);
120 if (pack_rects_res != 1)
121 return {};
122
123 ImVec2 tex_size(width, width);
124 for (const stbrp_rect &rect : pack_rects) {
125 float x = rect.x + rect.w;
126 float y = rect.y + rect.h;
127 if(x > tex_size.x) tex_size.x = x;
128 if(y > tex_size.y) tex_size.y = y;
129 }
130
131 Icons result(input.size());
132 for (int i = 0; i < pack_rects.Size; i++) {
133 const stbrp_rect &rect = pack_rects[i];
134 assert(rect.was_packed);
135 if (!rect.was_packed)
136 return {};
137
138 ImVec2 tl(rect.x / tex_size.x, rect.y / tex_size.y);
139 ImVec2 br((rect.x + rect.w) / tex_size.x, (rect.y + rect.h) / tex_size.y);
140
141 assert(input[i].size.x == rect.w);
142 assert(input[i].size.y == rect.h);
143 Icon icon = {input[i].size, tl, br};
144 result[i] = std::make_shared<Icon>(std::move(icon));
145 }
146
147 NSVGrasterizer *rast = nsvgCreateRasterizer();
148 assert(rast != nullptr);
149 if (rast == nullptr)
150 return {};
151 ScopeGuard sg_rast([rast]() { ::nsvgDeleteRasterizer(rast); });
152
153 int channels = 4;
154 int n_pixels = tex_size.x * tex_size.y;
155
156 std::vector<unsigned char> data(n_pixels * channels, {0});
157
158
159 std::vector<size_t> idx(input.size());
160 std::iota(idx.begin(), idx.end(), 0);
161
162
163
164 std::sort(idx.begin(), idx.end(), [&input](size_t i1, size_t i2) { return input[i1].filepath < input[i2].filepath; });
165 for (size_t j: idx) {
167 if (i.filepath.empty())
168 continue;
169 assert(boost::filesystem::exists(i.filepath));
170 if (!boost::filesystem::exists(i.filepath))
171 continue;
172 assert(boost::algorithm::iends_with(i.filepath, ".svg"));
173 if (!boost::algorithm::iends_with(i.filepath, ".svg"))
174 continue;
175
176 NSVGimage *image =
parse_file(i.filepath.c_str());
177 assert(image != nullptr);
178 if (image == nullptr)
179 return {};
180
181 ScopeGuard sg_image([image]() { ::nsvgDelete(image); });
182
183 float svg_scale = i.size.y / image->height;
184
185 assert(
is_approx(svg_scale, i.size.y / image->width));
186
187 const stbrp_rect &rect = pack_rects[j];
188 int n_pixels = rect.w * rect.h;
189 std::vector<unsigned char> icon_data(n_pixels * channels, {0});
190 ::nsvgRasterize(rast, image, 0, 0, svg_scale, icon_data.data(), i.size.x, i.size.y, i.size.x * channels);
191
192
196 for (size_t k = 0; k < icon_data.size(); k += channels)
197 if (icon_data[k] != 0 || icon_data[k + 1] != 0 || icon_data[k + 2] != 0) {
198 icon_data[k] = value;
199 icon_data[k + 1] = value;
200 icon_data[k + 2] = value;
201 }
202 }
203
204 int start_offset = (rect.y*tex_size.x + rect.x) * channels;
205 int data_stride = tex_size.x * channels;
206 subdata(data.data() + start_offset, data_stride, icon_data, rect.w * channels);
207 }
208
211
219
220
222
223 for (const auto &i : result)
225 return result;
226}
@ gray_only_data
Definition IconManager.hpp:32
@ white_only_data
Definition IconManager.hpp:31
std::vector< std::shared_ptr< Icon > > Icons
Definition IconManager.hpp:66
Definition IconManager.hpp:37
#define GL_TEXTURE_MIN_FILTER
Definition gl.h:1828
#define glPixelStorei
Definition gl.h:4451
#define GL_TEXTURE_MAX_LEVEL
Definition gl.h:1826
#define GL_LINEAR
Definition gl.h:930
#define glTexParameteri
Definition gl.h:4911
#define glTexImage2D
Definition gl.h:4895
#define GL_UNSIGNED_BYTE
Definition gl.h:1937
#define glGenTextures
Definition gl.h:3787
#define GL_UNPACK_ALIGNMENT
Definition gl.h:1924
int GLsizei
Definition gl.h:2065
#define glBindTexture
Definition gl.h:3299
#define GL_RGBA
Definition gl.h:1493
unsigned int GLuint
Definition gl.h:2063
#define GL_TEXTURE_MAG_FILTER
Definition gl.h:1822
#define GL_TEXTURE_2D
Definition gl.h:1739
coord_t width(const BoundingBox &box)
Definition Arrange.cpp:1184
constexpr bool is_approx(Number value, Number test_value, Number precision=EPSILON)
Definition libslic3r.h:320
void subdata(unsigned char *data, size_t data_stride, const std::vector< unsigned char > &data2, size_t data2_row)
Definition IconManager.cpp:72
NSVGimage * parse_file(const char *filepath)
Definition IconManager.cpp:48
Data for render texture with icon.
Definition IconManager.hpp:53