12
12
#define STB_IMAGE_IMPLEMENTATION
13
13
#include < stb_image.h>
14
14
15
+ #include < lunasvg.h>
16
+
15
17
#include < set>
16
18
#include < string>
17
19
18
-
19
20
#include < hex/api/imhex_api.hpp>
20
21
21
22
#include < hex/api/task_manager.hpp>
@@ -40,74 +41,167 @@ namespace ImGuiExt {
40
41
return GL_NEAREST;
41
42
}
42
43
44
+ GLuint createTextureFromRGBA8Array (const ImU8 *buffer, int width, int height, Texture::Filter filter) {
45
+ GLuint texture;
46
+
47
+ // Generate texture
48
+ glGenTextures (1 , &texture);
49
+ glBindTexture (GL_TEXTURE_2D, texture);
50
+
51
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter (filter));
52
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter (filter));
53
+
54
+ #if defined(GL_UNPACK_ROW_LENGTH)
55
+ glPixelStorei (GL_UNPACK_ROW_LENGTH, 0 );
56
+ #endif
57
+
58
+ // Allocate storage for the texture
59
+ glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA8, width, height, 0 , GL_RGBA, GL_UNSIGNED_BYTE, buffer);
60
+
61
+ return texture;
62
+ }
63
+
64
+ GLuint createMultisampleTextureFromRGBA8Array (const ImU8 *buffer, int width, int height, Texture::Filter filter) {
65
+ // Create a regular texture from the RGBA8 array
66
+ GLuint texture = createTextureFromRGBA8Array (buffer, width, height, filter);
67
+
68
+ if (filter == Texture::Filter::Nearest)
69
+ return texture;
70
+
71
+ constexpr static auto SampleCount = 8 ;
72
+
73
+ // Generate renderbuffer
74
+ GLuint renderbuffer;
75
+ glGenRenderbuffers (1 , &renderbuffer);
76
+ glBindRenderbuffer (GL_RENDERBUFFER, renderbuffer);
77
+ glRenderbufferStorageMultisample (GL_RENDERBUFFER, SampleCount, GL_DEPTH24_STENCIL8, width, height);
78
+
79
+ // Generate framebuffer
80
+ GLuint framebuffer;
81
+ glGenFramebuffers (1 , &framebuffer);
82
+ glBindFramebuffer (GL_FRAMEBUFFER, framebuffer);
83
+
84
+ // Attach texture to color attachment 0
85
+ glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0 );
86
+
87
+ // Attach renderbuffer to depth-stencil attachment
88
+ glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
89
+
90
+ // Check framebuffer status
91
+ if (glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
92
+ return 0 ;
93
+ }
94
+
95
+ // Unbind framebuffer
96
+ glBindFramebuffer (GL_FRAMEBUFFER, 0 );
97
+
98
+ return texture;
99
+ }
100
+
43
101
}
44
102
45
- Texture::Texture (const ImU8 *buffer, int size, Filter filter, int width, int height ) {
103
+ Texture Texture::fromImage (const ImU8 *buffer, int size, Filter filter) {
46
104
if (size == 0 )
47
- return ;
105
+ return {} ;
48
106
49
107
unsigned char *imageData = nullptr ;
50
108
51
- if (width == 0 || height == 0 )
52
- imageData = stbi_load_from_memory (buffer, size, &m_width, &m_height, nullptr , 4 );
109
+ Texture result;
110
+ imageData = stbi_load_from_memory (buffer, size, &result.m_width , &result.m_height , nullptr , 4 );
111
+ if (imageData == nullptr )
112
+ return {};
53
113
54
- if (imageData == nullptr ) {
55
- if (width * height * 4 > size)
56
- return ;
114
+ GLuint texture = createMultisampleTextureFromRGBA8Array (imageData, result.m_width , result.m_height , filter);
57
115
58
- imageData = static_cast <unsigned char *>(STBI_MALLOC (size));
59
- std::memcpy (imageData, buffer, size);
60
- m_width = width;
61
- m_height = height;
62
- }
63
- if (imageData == nullptr )
64
- return ;
116
+ STBI_FREE (imageData);
65
117
66
- GLuint texture;
67
- glGenTextures (1 , &texture);
68
- glBindTexture (GL_TEXTURE_2D, texture);
118
+ result.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
69
119
70
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter (filter));
71
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter (filter));
120
+ return result;
121
+ }
122
+
123
+ Texture Texture::fromImage (std::span<const std::byte> buffer, Filter filter) {
124
+ return Texture::fromImage (reinterpret_cast <const ImU8*>(buffer.data ()), buffer.size (), filter);
125
+ }
126
+
127
+
128
+ Texture Texture::fromImage (const std::fs::path &path, Filter filter) {
129
+ return Texture::fromImage (wolv::util::toUTF8String (path).c_str (), filter);
130
+ }
72
131
73
- #if defined(GL_UNPACK_ROW_LENGTH)
74
- glPixelStorei (GL_UNPACK_ROW_LENGTH, 0 );
75
- #endif
132
+ Texture Texture::fromImage (const char *path, Filter filter) {
133
+ Texture result;
134
+ unsigned char *imageData = stbi_load (path, &result.m_width , &result.m_height , nullptr , 4 );
135
+ if (imageData == nullptr )
136
+ return {};
137
+
138
+ GLuint texture = createMultisampleTextureFromRGBA8Array (imageData, result.m_width , result.m_height , filter);
76
139
77
- glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, m_width, m_height, 0 , GL_RGBA, GL_UNSIGNED_BYTE, imageData);
78
140
STBI_FREE (imageData);
79
141
80
- m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
142
+ result.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
143
+
144
+ return result;
81
145
}
82
146
83
- Texture::Texture (std::span<const std::byte> bytes, Filter filter, int width, int height) : Texture(reinterpret_cast <const ImU8*>(bytes.data()), bytes.size(), filter, width, height) { }
147
+ Texture Texture::fromGLTexture (unsigned int glTexture, int width, int height) {
148
+ Texture texture;
149
+ texture.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(glTexture));
150
+ texture.m_width = width;
151
+ texture.m_height = height;
84
152
85
- Texture::Texture (const std::fs::path &path, Filter filter) : Texture(reinterpret_cast <const char *>(path.u8string().c_str()), filter) { }
153
+ return texture;
154
+ }
86
155
87
- Texture::Texture (const char *path, Filter filter) {
88
- unsigned char *imageData = stbi_load (path, &m_width, &m_height, nullptr , 4 );
89
- if (imageData == nullptr )
90
- return ;
156
+ Texture Texture::fromBitmap (std::span<const std::byte> buffer, int width, int height, Filter filter) {
157
+ return Texture::fromBitmap (reinterpret_cast <const ImU8*>(buffer.data ()), buffer.size (), width, height, filter);
158
+ }
91
159
92
- GLuint texture;
93
- glGenTextures ( 1 , &texture);
94
- glBindTexture (GL_TEXTURE_2D, texture) ;
160
+ Texture Texture::fromBitmap ( const ImU8 *buffer, int size, int width, int height, Filter filter) {
161
+ if (width * height * 4 > size)
162
+ return {} ;
95
163
96
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter (filter));
97
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter (filter));
164
+ GLuint texture = createMultisampleTextureFromRGBA8Array (buffer, width, height, filter);
98
165
99
- #if defined(GL_UNPACK_ROW_LENGTH)
100
- glPixelStorei (GL_UNPACK_ROW_LENGTH, 0 );
101
- #endif
166
+ Texture result;
167
+ result.m_width = width;
168
+ result.m_height = height;
169
+ result.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
102
170
103
- glTexImage2D (GL_TEXTURE_2D, 0 , GL_RGBA, m_width, m_height, 0 , GL_RGBA, GL_UNSIGNED_BYTE, imageData);
104
- STBI_FREE (imageData);
171
+ return result;
172
+ }
173
+
174
+ Texture Texture::fromSVG (const char *path, int width, int height, Filter filter) {
175
+ auto document = lunasvg::Document::loadFromFile (path);
176
+ auto bitmap = document->renderToBitmap (width, height);
177
+
178
+ auto texture = createMultisampleTextureFromRGBA8Array (bitmap.data (), bitmap.width (), bitmap.height (), filter);
179
+
180
+ Texture result;
181
+ result.m_width = bitmap.width ();
182
+ result.m_height = bitmap.height ();
183
+ result.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
105
184
106
- m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
185
+ return result;
186
+ }
187
+
188
+ Texture Texture::fromSVG (const std::fs::path &path, int width, int height, Filter filter) {
189
+ return Texture::fromSVG (wolv::util::toUTF8String (path).c_str (), width, height, filter);
107
190
}
108
191
109
- Texture::Texture (unsigned int texture, int width, int height) : m_textureId(reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture))), m_width(width), m_height(height) {
192
+ Texture Texture::fromSVG (std::span<const std::byte> buffer, int width, int height, Filter filter) {
193
+ auto document = lunasvg::Document::loadFromData (reinterpret_cast <const char *>(buffer.data ()), buffer.size ());
194
+ auto bitmap = document->renderToBitmap (width, height);
195
+ bitmap.convertToRGBA ();
110
196
197
+ auto texture = createMultisampleTextureFromRGBA8Array (bitmap.data (), bitmap.width (), bitmap.height (), filter);
198
+
199
+ Texture result;
200
+ result.m_width = bitmap.width ();
201
+ result.m_height = bitmap.height ();
202
+ result.m_textureId = reinterpret_cast <ImTextureID>(static_cast <intptr_t >(texture));
203
+
204
+ return result;
111
205
}
112
206
113
207
Texture::Texture (Texture&& other) noexcept {
0 commit comments