bad char
[vg.git] / src / texsheet.c
1 // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved
2
3 #ifdef VG_BUILD
4
5 #include "vg.h"
6 #include "vg_platform.h"
7 #include "vg_log.h"
8 #include "vg_opt.h"
9 #include "vg_build.h"
10
11 u32 optimize_test_compile = 0;
12
13 /*
14 * Scripts
15 * -------------------------------------------------------------------------- */
16
17 void s_build(void){
18 vg_info( "running script: s_build(void)\n" );
19
20 vg_build.optimization = optimize_test_compile;
21 vg_build.fresh = 0;
22 vg_build.platform = k_platform_linux;
23 vg_build.arch = k_architecture_x86_64;
24 vg_build.compiler = k_compiler_clang;
25 vg_build.libc = k_libc_version_native;
26
27 vg_build_new( "texsheet" );
28 vg_add_source( "src/texsheet.c" );
29 vg_compile( "texsheet" );
30
31 vg_success( "Completed 1/1\n" );
32 }
33
34 int main( int argc, char *argv[] ){
35 char *arg;
36 while( vg_argp( argc, argv ) ){
37 if( vg_long_opt( "native" ) )
38 s_build();
39
40 if( vg_opt('r') )
41 optimize_test_compile = 3;
42 }
43
44 if( vg_build.warnings )
45 vg_warn( "Finished with %u warnings\n", vg_build.warnings );
46 else
47 vg_success( "All scripts ran successfully\n" );
48 }
49
50 #else
51
52 #define VG_TOOLS
53 #include "vg.h"
54
55 #define STB_IMAGE_IMPLEMENTATION
56 #include "submodules/stb/stb_image.h"
57
58 #define QOI_IMPLEMENTATION
59 #include "submodules/qoi/qoi.h"
60
61 struct image_src
62 {
63 int x,y,ch;
64
65 u8 *data;
66 };
67
68 int image_sort( const void* a, const void* b)
69 {
70 struct image_src *p_a = (struct image_src *)a;
71 struct image_src *p_b = (struct image_src *)b;
72
73 if( p_a->x == p_b->x )
74 return 0;
75 else if ( p_a->x < p_b->x )
76 return 1;
77 else
78 return -1;
79 }
80
81 int main( int argc, const char *argv[] )
82 {
83 struct image_src *source_images = malloc( sizeof( struct image_src ) * argc );
84
85 u32 num_images = 0;
86
87 if( argc < 4 )
88 {
89 vg_info( "Usage: %s \\\n[output_image output_header name images...]\n",
90 argv[0] );
91 return 0;
92 }
93
94 // Open header handle
95 // ------------------
96 FILE *fp = fopen( argv[2], "w" );
97 if( !fp )
98 {
99 vg_error( "Could not open file for writing\n" );
100 return 0;
101 }
102
103 fprintf( fp, "enum %s_index\n{\n", argv[3] );
104
105 // Load images
106 // -----------
107 stbi_set_flip_vertically_on_load(1);
108
109 for( int i = 4; i < argc; i ++ )
110 {
111 struct image_src *src = &source_images[ num_images ];
112 src->data = (u8 *)stbi_load( argv[i], &src->x, &src->y, &src->ch, 4 );
113
114 char name[ 256 ];
115 int j = 0; int ext = 0;
116 for( ; j < vg_list_size( name )-1; j ++ )
117 {
118 if( argv[i][j] )
119 {
120 name[j] = argv[i][j];
121
122 if( name[j] == '.' )
123 ext = j;
124
125 if( name[j] == '.' || name[j] == '-' )
126 name[j] = '_';
127 }
128 else
129 break;
130 }
131
132 if( ext )
133 name[ext] = 0x00;
134 else
135 name[j] = 0x00;
136
137 fprintf( fp, "\tk_sprite_%s,\n", name );
138
139 if( src->data )
140 {
141 if( src->x != src->y )
142 {
143 vg_error( "Non-square images are currently not supported ('%s')\n", argv[i] );
144 free( src->data );
145 }
146 else
147 num_images ++;
148 }
149 else
150 vg_error( "Could not decode '%s'\n", argv[i] );
151 }
152
153 fprintf( fp, "};\n\n" );
154
155 // Sort by size
156 // ------------
157 qsort( source_images, num_images, sizeof(struct image_src), image_sort );
158
159 // Process images
160 // --------------
161 fprintf( fp, "static struct vg_sprite %s[] = \n{\n", argv[3] );
162
163 u8 *dest = (u8 *)malloc( 1024*1024*4 );
164
165 for( int i = 0; i < 1024*1024; i ++ )
166 {
167 dest[ i*4 + 0 ] = 0;
168 dest[ i*4 + 1 ] = 0;
169 dest[ i*4 + 2 ] = 0;
170 dest[ i*4 + 3 ] = 0;
171 }
172
173 struct region
174 {
175 v2i p0;
176 v2i p1;
177 }
178 region_stack[ 32 ] =
179 {
180 {
181 .p0 = { 0, 0 },
182 .p1 = { 1024, 1024 }
183 }
184 };
185 int stack_h = 0;
186
187 for( int i = 0; i < num_images; i ++ )
188 {
189 struct image_src *psrc = &source_images[ i ];
190
191 // Region checks
192 while( 1 )
193 {
194 struct region *pregion = &region_stack[ stack_h ];
195
196 if( (pregion->p0[ 0 ] + psrc->x <= pregion->p1[0]) && (pregion->p0[ 1 ] + psrc->y <= pregion->p1[1]) )
197 {
198 // Passed, add image and create subdivisions
199 fprintf( fp, "\t{{ %f, %f, %f, %f }}",
200 (float)pregion->p0[0] / 1024.0f,
201 (float)pregion->p0[1] / 1024.0f,
202 (float)psrc->x / 1024.0f,
203 (float)psrc->y / 1024.0f
204 );
205
206 if( i != num_images-1 )
207 fputs( ",\n", fp );
208 else
209 fputc( '\n', fp );
210
211 // Write image
212 for( int y = 0; y < psrc->y; y ++ )
213 {
214 int px = pregion->p0[0];
215 int py = pregion->p0[1] + y;
216
217 memcpy( &dest[ (py*1024+px) * 4 ], &psrc->data[ y*psrc->x*4 ], psrc->x*4 );
218 }
219
220 // Subdivisions
221 stack_h ++;
222 struct region *new_region = &region_stack[ stack_h ];
223
224 new_region->p0[0] = pregion->p0[0] + psrc->x;
225 new_region->p0[1] = pregion->p0[1];
226 new_region->p1[0] = pregion->p1[0];
227 new_region->p1[1] = pregion->p0[1] + psrc->y;
228
229 pregion->p0[ 1 ] += psrc->y;
230 break;
231 }
232 else
233 {
234 // Failed, loop up to next region if can
235 if( stack_h == 0 )
236 {
237 vg_error( "Could not fit image %d. Pack failed\n", i );
238
239 goto IL_END_ERR;
240 }
241 else
242 stack_h --;
243 }
244 }
245 }
246
247 IL_END_ERR:
248 fprintf( fp, "};" );
249 fclose( fp );
250
251 // Write output
252 // ------------
253 qoi_write( argv[1], dest, &(qoi_desc){
254 .width = 1024,
255 .height = 1024,
256 .channels = 4,
257 .colorspace = QOI_SRGB
258 });
259
260 // Free
261 // ----
262 for( int i = 0; i < num_images; i ++ )
263 free( source_images[ i ].data );
264 free( dest );
265 free( source_images );
266
267 vg_success( "Processed %u images\n", num_images );
268
269 }
270
271 #endif