diff --git a/libc3/window/sdl2/demo/matrix_utf8.c b/libc3/window/sdl2/demo/matrix_utf8.c
index b38ce5d..5b46fd1 100644
--- a/libc3/window/sdl2/demo/matrix_utf8.c
+++ b/libc3/window/sdl2/demo/matrix_utf8.c
@@ -70,42 +70,22 @@ bool matrix_utf8_text_init (s_tag *tag, f32 y)
{
char a[1024];
s_buf buf;
- character c;
- FT_Face face;
u8 i;
u8 len;
s_map *map;
f32 spacing;
- s_str str;
s_gl_text *text;
if (! tag_map(tag, 3))
return false;
buf_init(&buf, false, sizeof(a), a);
- u8_random_uniform(&len, 40);
- len += 10;
- face = g_matrix_utf8_font.ft_face;
- i = 0;
- while (i < len) {
- do {
- u32_random(&c);
- } while (! FT_Get_Char_Index(face, c));
- if (buf_write_character_utf8(&buf, c) < 0) {
- err_puts("matrix_utf8_init_text: buffer overflow");
- assert(! "matrix_utf8_init_text: buffer overflow");
- return false;
- }
- i++;
- }
- buf_read_to_str(&buf, &str);
- u8_random_uniform(&i, 15);
+ u8_random_uniform(&i, 10);
spacing = i * G_MATRIX_UTF8_FONT_SIZE;
- text = gl_vtext_new_str(&g_matrix_utf8_font, &str);
- if (! text)
+ u8_random_uniform(&len, 10);
+ len += 10;
+ text = gl_vtext_new(&g_matrix_utf8_font);
+ if (! text ||
+ ! gl_vtext_render_to_texture_random(text, len))
return false;
- gl_vtext_update(text);
- err_inspect_str(&str);
- err_write_1("\n");
- str_clean(&str);
map = &tag->data.map;
tag_init_sym( map->key + 0, sym_1("spacing"));
tag_init_f32(map->value + 0, spacing);
diff --git a/libc3/window/sdl2/gl_vtext.c b/libc3/window/sdl2/gl_vtext.c
index 2d9472a..dd3aaa0 100644
--- a/libc3/window/sdl2/gl_vtext.c
+++ b/libc3/window/sdl2/gl_vtext.c
@@ -57,6 +57,22 @@ s_gl_text * gl_vtext_init_str (s_gl_text *text, const s_gl_font *font,
return text;
}
+s_gl_text * gl_vtext_new (const s_gl_font *font)
+{
+ s_gl_text *text;
+ text = calloc(1, sizeof(s_gl_text));
+ if (! text) {
+ err_puts("gl_vtext_new: failed to allocate memory");
+ assert(! "gl_vtext_new: failed to allocate memory");
+ return NULL;
+ }
+ if (! gl_vtext_init(text, font)) {
+ free(text);
+ return NULL;
+ }
+ return text;
+}
+
s_gl_text * gl_vtext_new_1 (const s_gl_font *font, const char *p)
{
s_gl_text *text;
@@ -190,6 +206,121 @@ bool gl_vtext_render_to_texture (s_gl_text *text)
return true;
}
+bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len)
+{
+ FT_UInt *glyphs;
+ u8 *data;
+ uw data_w;
+ uw data_h;
+ u8 *data_pixel;
+ uw data_size;
+ uw data_x;
+ uw data_y;
+ FT_Face face;
+ const s_gl_font *font;
+ FT_GlyphSlot glyph;
+ FT_UInt glyph_index;
+ uw i;
+ uw j;
+ uw k;
+ uw line_height;
+ uw max_ascent;
+ uw max_descent;
+ f32 scale_y;
+ uw x;
+ uw y;
+ assert(text);
+ assert(text->font);
+ assert(text->texture);
+ assert(glGetError() == GL_NO_ERROR);
+ glBindTexture(GL_TEXTURE_2D, text->texture);
+ assert(glGetError() == GL_NO_ERROR);
+ font = text->font;
+ face = font->ft_face;
+ glyphs = calloc(len, sizeof(FT_UInt));
+ if (! glyphs) {
+ err_puts("gl_vtext_render_to_texture_random:"
+ " failed to allocate memory");
+ assert(! "gl_vtext_render_to_texture_random:"
+ " failed to allocate memory");
+ return false;
+ }
+ for (i = 0; i < len; i++) {
+ do {
+ u32_random_uniform(glyphs + i, face->num_glyphs - 2);
+ glyphs[i]++;
+ if (FT_Load_Glyph(face, glyphs[i], FT_LOAD_RENDER))
+ continue;
+ glyph = face->glyph;
+ printf("width %ld\n", glyph->metrics.width);
+ } while (! glyph->metrics.width);
+ }
+ scale_y = face->size->metrics.y_scale / 65536.0;
+ max_ascent = (u32) (face->ascender * scale_y) >> 6;
+ max_descent = (u32) abs((int) (face->descender * scale_y)) >> 6;
+ line_height = max_ascent + max_descent;
+ data_w = 0;
+ data_h = 0;
+ x = 0;
+ for (i = 0; i < len; i++) {
+ glyph_index = glyphs[i];
+ if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER)) {
+ err_write_1("gl_vtext_render_to_texture_random: failed to load glyph: ");
+ err_inspect_u32(&glyph_index);
+ err_write_1("\n");
+ continue;
+ }
+ glyph = face->glyph;
+ x = glyph->metrics.horiAdvance >> 6;
+ if (x > data_w)
+ data_w = x;
+ data_h += line_height;
+ }
+ data_size = data_w * data_h * 4;
+ data = calloc(1, data_size);
+ x = 0;
+ y = 0;
+ for (i = 0; i < len; i++) {
+ glyph_index = glyphs[i];
+ if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER))
+ continue;
+ glyph = face->glyph;
+ x = (data_w - (glyph->metrics.width >> 6)) / 2;
+ j = 0;
+ while (j < glyph->bitmap.rows) {
+ data_y = data_h - 1 - (y + j + max_ascent - glyph->bitmap_top);
+ //printf("\n");
+ k = 0;
+ while (k < glyph->bitmap.width) {
+ data_x = x + k;
+ data_pixel = data + (data_y * data_w + data_x) * 4;
+ u8 value = glyph->bitmap.buffer[j * glyph->bitmap.width + k];
+ data_pixel[0] = 255;
+ data_pixel[1] = 255;
+ data_pixel[2] = 255;
+ data_pixel[3] = value;
+ //printf("%s", g_gray_3_bits_utf8[value / 32]);
+ k++;
+ }
+ j++;
+ }
+ y += line_height;
+ }
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, data_w, data_h, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, data);
+ assert(glGetError() == GL_NO_ERROR);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ assert(glGetError() == GL_NO_ERROR);
+ free(data);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ text->pix_w = data_w;
+ text->pix_h = data_h;
+ text->pt_w = text->pix_w * text->font->point_per_pixel;
+ text->pt_h = text->pix_h * text->font->point_per_pixel;
+ //printf("\n");
+ return true;
+}
+
bool gl_vtext_set_font (s_gl_text *text, const s_gl_font *font)
{
assert(text);
diff --git a/libc3/window/sdl2/gl_vtext.h b/libc3/window/sdl2/gl_vtext.h
index 9018700..e23528f 100644
--- a/libc3/window/sdl2/gl_vtext.h
+++ b/libc3/window/sdl2/gl_vtext.h
@@ -26,11 +26,13 @@ s_gl_text * gl_vtext_init_str (s_gl_text *text, const s_gl_font *font,
/* Heap-allocation functions, call gl_vtext_delete after use. */
void gl_vtext_delete (s_gl_text *text);
+s_gl_text * gl_vtext_new (const s_gl_font *font);
s_gl_text * gl_vtext_new_1 (const s_gl_font *font, const char *p);
s_gl_text * gl_vtext_new_str (const s_gl_font *font, const s_str *str);
/* Operators. */
bool gl_vtext_render_to_texture (s_gl_text *text);
+bool gl_vtext_render_to_texture_random (s_gl_text *text, uw len);
bool gl_vtext_set_font (s_gl_text *text, const s_gl_font *font);
bool gl_vtext_set_text (s_gl_text *text, const s_str *str);
bool gl_vtext_set_text_1 (s_gl_text *text, const char *p);