diff --git a/.ic3_history b/.ic3_history
index 70bbea2..e8eab8f 100644
--- a/.ic3_history
+++ b/.ic3_history
@@ -1,7 +1,3 @@
-123.123
-123.1230
-123.123000001
-123.12300000001
123.123000000001
123.1230000000001
123.123
@@ -97,3 +93,7 @@ hello = fn (name) { "Hello, #{name} !" }
hello("Paul")
quote hello("Paul")
hello
+quote unquote 1
+quote quote unquote 1
+quote unquote 1
+quote quote unquote 1
diff --git a/libc3/buf_parse.c b/libc3/buf_parse.c
index b459a17..f889f10 100644
--- a/libc3/buf_parse.c
+++ b/libc3/buf_parse.c
@@ -2408,8 +2408,14 @@ sw buf_parse_quote (s_buf *buf, s_quote *dest)
goto restore;
result += r;
quote.tag = tag_new();
- if ((r = buf_parse_tag(buf, quote.tag)) <= 0)
+ if (! quote.tag) {
+ r = -2;
+ goto restore;
+ }
+ if ((r = buf_parse_tag(buf, quote.tag)) <= 0) {
+ free(quote.tag);
goto restore;
+ }
result += r;
*dest = quote;
r = result;
@@ -3132,6 +3138,7 @@ sw buf_parse_tag_primary (s_buf *buf, s_tag *dest)
(r = buf_parse_tag_str(buf, dest)) != 0 ||
(r = buf_parse_tag_tuple(buf, dest)) != 0 ||
(r = buf_parse_tag_quote(buf, dest)) != 0 ||
+ (r = buf_parse_tag_unquote(buf, dest)) != 0 ||
(r = buf_parse_tag_cfn(buf, dest)) != 0 ||
(r = buf_parse_tag_fn(buf, dest)) != 0 ||
(r = buf_parse_tag_struct(buf, dest)) != 0 ||
@@ -3207,6 +3214,16 @@ sw buf_parse_tag_tuple (s_buf *buf, s_tag *dest)
return r;
}
+sw buf_parse_tag_unquote (s_buf *buf, s_tag *dest)
+{
+ sw r;
+ assert(buf);
+ assert(dest);
+ if ((r = buf_parse_unquote(buf, &dest->data.unquote)) > 0)
+ dest->type = TAG_UNQUOTE;
+ return r;
+}
+
sw buf_parse_tag_void (s_buf *buf, s_tag *dest)
{
sw r;
@@ -3336,6 +3353,39 @@ sw buf_parse_u64_hex (s_buf *buf, u64 *dest)
return r;
}
+sw buf_parse_unquote (s_buf *buf, s_unquote *dest)
+{
+ s_unquote unquote;
+ sw r;
+ sw result = 0;
+ s_buf_save save;
+ buf_save_init(buf, &save);
+ if ((r = buf_read_1(buf, "unquote")) <= 0)
+ goto clean;
+ result += r;
+ if ((r = buf_ignore_spaces(buf)) <= 0)
+ goto restore;
+ result += r;
+ unquote.tag = tag_new();
+ if (! unquote.tag) {
+ r = -2;
+ goto restore;
+ }
+ if ((r = buf_parse_tag(buf, unquote.tag)) <= 0) {
+ free(unquote.tag);
+ goto restore;
+ }
+ result += r;
+ *dest = unquote;
+ r = result;
+ goto clean;
+ restore:
+ buf_save_restore_rpos(buf, &save);
+ clean:
+ buf_save_clean(buf, &save);
+ return r;
+}
+
sw buf_parse_var (s_buf *buf, void *dest)
{
character c;
diff --git a/libc3/buf_parse.h b/libc3/buf_parse.h
index 441d6a8..ff097a9 100644
--- a/libc3/buf_parse.h
+++ b/libc3/buf_parse.h
@@ -123,9 +123,11 @@ sw buf_parse_tag_str (s_buf *buf, s_tag *dest);
sw buf_parse_tag_struct (s_buf *buf, s_tag *dest);
sw buf_parse_tag_sym (s_buf *buf, s_tag *dest);
sw buf_parse_tag_tuple (s_buf *buf, s_tag *dest);
+sw buf_parse_tag_unquote (s_buf *buf, s_tag *dest);
sw buf_parse_tag_void (s_buf *buf, s_tag *dest);
sw buf_parse_tuple (s_buf *buf, s_tuple *dest);
sw buf_parse_u64_hex (s_buf *buf, u64 *dest);
+sw buf_parse_unquote (s_buf *buf, s_unquote *dest);
sw buf_parse_var (s_buf *buf, void *dest);
sw buf_parse_void (s_buf *buf, void *dest);
diff --git a/libc3/env.c b/libc3/env.c
index 9fd4b88..a3d1bb1 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -736,6 +736,32 @@ bool env_eval_quote_call (s_env *env, const s_call *call, s_tag *dest)
return false;
}
+bool env_eval_quote_list (s_env *env, const s_list *list, s_tag *dest)
+{
+ s_list *next;
+ s_list *tmp = NULL;
+ s_list **tail = &tmp;
+ assert(env);
+ assert(dest);
+ while (list) {
+ *tail = list_new(NULL);
+ if (! env_eval_quote_tag(env, &list->tag, &(*tail)->tag))
+ goto ko;
+ next = list_next(list);
+ if (! next)
+ if (! env_eval_quote_tag(env, &list->next, &(*tail)->next))
+ goto ko;
+ tail = &(*tail)->next.data.list;
+ list = next;
+ }
+ dest->type = TAG_LIST;
+ dest->data.list = tmp;
+ return true;
+ ko:
+ list_delete_all(tmp);
+ return false;
+}
+
bool env_eval_quote_map (s_env *env, const s_map *map, s_tag *dest)
{
s_map tmp;
@@ -779,6 +805,24 @@ bool env_eval_quote_quote (s_env *env, const s_quote *quote, s_tag *dest)
return true;
}
+bool env_eval_quote_str (s_env *env, const s_str *str, s_tag *dest)
+{
+ bool r = true;
+ s_tag tmp;
+ if (! str_parse_eval(str, &tmp)) {
+ err_puts("env_eval_str: invalid Str");
+ assert(! "env_eval_str: invalid Str");
+ return false;
+ }
+ if (tmp.type == TAG_STR) {
+ *dest = tmp;
+ return true;
+ }
+ r = env_eval_quote_tag(env, &tmp, dest);
+ tag_clean(&tmp);
+ return r;
+}
+
bool env_eval_quote_struct (s_env *env, const s_struct *s, s_tag *dest)
{
uw i;
@@ -877,6 +921,27 @@ bool env_eval_quote_tag (s_env *env, const s_tag *tag, s_tag *dest)
return true;
}
+bool env_eval_quote_tuple (s_env *env, const s_tuple *tuple, s_tag *dest)
+{
+ uw i = 0;
+ s_tuple tmp;
+ assert(env);
+ assert(tuple);
+ assert(dest);
+ tuple_init(&tmp, tuple->count);
+ while (i < tuple->count) {
+ if (! env_eval_quote_tag(env, tuple->tag + i, tmp.tag + i))
+ goto ko;
+ i++;
+ }
+ dest->type = TAG_TUPLE;
+ dest->data.tuple = tmp;
+ return true;
+ ko:
+ tuple_clean(&tmp);
+ return false;
+}
+
bool env_eval_quote_unquote (s_env *env, const s_unquote *unquote, s_tag *dest)
{
bool r;
@@ -884,7 +949,7 @@ bool env_eval_quote_unquote (s_env *env, const s_unquote *unquote, s_tag *dest)
assert(env);
assert(unquote);
assert(dest);
- if (env->unquote_level + 1 >= env->quote_level) {
+ if (env->unquote_level >= env->quote_level) {
err_puts("env_eval_quote_unquote: unquote outside of a quote");
assert(! "env_eval_quote_unquote: unquote outside of a quote");
return false;
@@ -1042,7 +1107,7 @@ bool env_eval_tuple (s_env *env, const s_tuple *tuple, s_tag *dest)
assert(dest);
tuple_init(&tmp, tuple->count);
while (i < tuple->count) {
- if (! env_eval_tag(env, &tuple->tag[i], &tmp.tag[i]))
+ if (! env_eval_tag(env, tuple->tag + i, tmp.tag + i))
return false;
i++;
}
diff --git a/libc3/window/sdl2/demo/mandelbrot_f128.c b/libc3/window/sdl2/demo/mandelbrot_f128.c
index 2a1fcaa..7a59e7f 100644
--- a/libc3/window/sdl2/demo/mandelbrot_f128.c
+++ b/libc3/window/sdl2/demo/mandelbrot_f128.c
@@ -13,12 +13,15 @@
#include <math.h>
#include <libc3/c3.h>
#include "../gl_deprecated.h"
+#include "../gl_font.h"
#include "../gl_matrix_4f.h"
#include "../gl_ortho.h"
+#include "../gl_text.h"
#include "mandelbrot_f128.h"
#include "window_sdl2_demo.h"
-// FIXME: move g_mandelbrot_f128_texture to seq->tag
+static s_gl_font g_mandelbrot_f128_font = {0};
+static s_gl_text g_mandelbrot_f128_text = {0};
static GLuint g_mandelbrot_f128_texture = 0;
static bool mandelbrot_f128_resize (s_sequence *seq);
@@ -30,7 +33,7 @@ bool mandelbrot_f128_button (s_sequence *seq, u8 button, sw x, sw y)
f128 *next_x;
f128 *next_y;
f128 *next_z;
- s_window_cairo *win;
+ s_window_sdl2 *win;
assert(seq);
win = seq->window;
assert(win);
@@ -64,8 +67,13 @@ bool mandelbrot_f128_button (s_sequence *seq, u8 button, sw x, sw y)
bool mandelbrot_f128_load (s_sequence *seq)
{
+ f32 point_per_pixel;
s_map *map;
+ s_window_sdl2 *window;
assert(seq);
+ window = seq->window;
+ assert(window);
+ point_per_pixel = (f32) window->w / window->gl_w;
if (! tag_map(&seq->tag, 9))
return false;
map = &seq->tag.data.map;
@@ -87,19 +95,27 @@ bool mandelbrot_f128_load (s_sequence *seq)
tag_init_f128( map->value + 7, 0.0);
tag_init_sym( map->key + 8, sym_1("z"));
tag_init_f128( map->value + 8, 0.0);
+ if (! gl_font_init(&g_mandelbrot_f128_font,
+ "fonts/Courier New/Courier New.ttf",
+ point_per_pixel))
+ return false;
+ gl_font_set_size(&g_mandelbrot_f128_font, 20.0);
+ if (! gl_text_init_1(&g_mandelbrot_f128_text, &g_mandelbrot_f128_font,
+ "x: 0.0\n"
+ "y: 0.0\n"
+ "z: 0.01"))
+ return false;
+ gl_text_update(&g_mandelbrot_f128_text);
return true;
}
bool mandelbrot_f128_render (s_sequence *seq)
{
- char a[80];
- s_buf buf;
uw *h;
s_map *map;
f128 next_x;
f128 next_y;
f128 next_z;
- s_str str;
uw *w;
s_window_sdl2 *win;
f128 *x;
@@ -159,6 +175,8 @@ bool mandelbrot_f128_render (s_sequence *seq)
gl_matrix_4f_init_identity(&g_ortho.model_matrix);
gl_ortho_bind_texture(&g_ortho, g_mandelbrot_f128_texture);
gl_ortho_rect(&g_ortho, 0, 0, win->w, win->h);
+ gl_ortho_text_render_outline(&g_ortho, &g_mandelbrot_f128_text,
+ 20.0, 120.0);
return true;
}
@@ -200,7 +218,6 @@ static bool mandelbrot_f128_update (s_sequence *seq)
f128 _2z_xz_y;
f128 c_x;
f128 c_y;
- u8 *data;
uw i;
uw j;
u8 k;
@@ -209,9 +226,9 @@ static bool mandelbrot_f128_update (s_sequence *seq)
f128 next_x;
f128 next_y;
f128 next_z;
+ s_array *pixels;
u8 *pix;
- uw stride;
- s_window_cairo *win;
+ s_window_sdl2 *win;
f128 z_x;
f128 z_y;
f128 z_x2;
@@ -240,11 +257,9 @@ static bool mandelbrot_f128_update (s_sequence *seq)
pixels = &map->value[4].data.array;
pix = pixels->data;
assert(pix);
- stride = win->w * 4;
i = 0;
while (i < win->h) {
c_y = next_y + next_z * ((f128) i - win->h / 2);
- pix = data + i * stride;
j = 0;
while (j < win->w) {
c_x = next_x + next_z * ((f128) j - win->w / 2);
@@ -283,5 +298,15 @@ static bool mandelbrot_f128_update (s_sequence *seq)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, win->w, win->h, 0,
GL_RGBA, GL_UNSIGNED_BYTE, pixels->data);
assert(glGetError() == GL_NO_ERROR);
+ char a[512];
+ s_buf buf;
+ buf_init(&buf, false, sizeof(a), a);
+ buf_write_1(&buf, "x: ");
+ buf_inspect_f128(&buf, &next_x);
+ buf_write_1(&buf, "\ny: ");
+ buf_inspect_f128(&buf, &next_y);
+ buf_write_1(&buf, "\nz: ");
+ buf_inspect_f128(&buf, &next_z);
+ gl_text_update_buf(&g_mandelbrot_f128_text, &buf);
return true;
}
diff --git a/libc3/window/sdl2/demo/mandelbrot_f128.h b/libc3/window/sdl2/demo/mandelbrot_f128.h
index 43a2047..02414ec 100644
--- a/libc3/window/sdl2/demo/mandelbrot_f128.h
+++ b/libc3/window/sdl2/demo/mandelbrot_f128.h
@@ -15,6 +15,7 @@
#include "../types.h"
+bool mandelbrot_f128_button (s_sequence *seq, u8 button, sw x, sw y);
bool mandelbrot_f128_load (s_sequence *seq);
bool mandelbrot_f128_render (s_sequence *seq);
bool mandelbrot_f128_unload (s_sequence *seq);
diff --git a/libc3/window/sdl2/demo/window_sdl2_demo.c b/libc3/window/sdl2/demo/window_sdl2_demo.c
index c207186..a7c9e1e 100644
--- a/libc3/window/sdl2/demo/window_sdl2_demo.c
+++ b/libc3/window/sdl2/demo/window_sdl2_demo.c
@@ -88,6 +88,9 @@ bool window_sdl2_demo_button (s_window_sdl2 *window, u8 button,
assert(window);
(void) window;
printf("c3_window_sdl2_demo_button: %lu (%ld, %ld)\n", (uw) button, x, y);
+ if (window->seq && window->seq->button &&
+ ! window->seq->button(window->seq, button, x, y))
+ return false;
return true;
}
@@ -207,63 +210,11 @@ bool window_sdl2_demo_load (s_window_sdl2 *window)
sequence_init(window->sequence + 5, 3600.0, "06. Mandelbrot (f128)",
mandelbrot_f128_load, mandelbrot_f128_render,
mandelbrot_f128_unload, window);
+ window->sequence[5].button = mandelbrot_f128_button;
window_set_sequence_pos((s_window *) window, 0);
return true;
}
-static void render_text (s_gl_text *text, f64 x, f64 y)
-{
- s_gl_matrix_4f matrix;
- assert(glGetError() == GL_NO_ERROR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_LINEAR);
- glEnable(GL_BLEND);
- glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
- GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- assert(glGetError() == GL_NO_ERROR);
- matrix = g_ortho.model_matrix;
- gl_matrix_4f_translate(&g_ortho.model_matrix, x - 1.0, y - 1.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_color(&g_ortho, 1.0f, 1.0f, 1.0f, 1.0f);
- assert(glGetError() == GL_NO_ERROR);
- gl_ortho_text_render(&g_ortho, text);
- assert(glGetError() == GL_NO_ERROR);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 0.0, 1.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, -1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, -1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 0.0, 1.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- assert(glGetError() == GL_NO_ERROR);
- gl_matrix_4f_translate(&g_ortho.model_matrix, 1.0, 0.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- gl_ortho_text_render(&g_ortho, text);
- assert(glGetError() == GL_NO_ERROR);
- gl_ortho_color(&g_ortho, 0.0f, 0.0f, 0.0f, 1.0f);
- assert(glGetError() == GL_NO_ERROR);
- gl_matrix_4f_translate(&g_ortho.model_matrix, -1.0, -1.0, 0.0);
- gl_ortho_update_model_matrix(&g_ortho);
- assert(glGetError() == GL_NO_ERROR);
- gl_ortho_text_render(&g_ortho, text);
- assert(glGetError() == GL_NO_ERROR);
- g_ortho.model_matrix = matrix;
-}
-
bool window_sdl2_demo_render (s_window_sdl2 *window)
{
s_sequence *seq;
@@ -291,7 +242,8 @@ bool window_sdl2_demo_render (s_window_sdl2 *window)
gl_font_set_size(&g_font_courier_new, 20);
gl_text_update_1(&g_text_seq_title, seq->title);
gl_matrix_4f_init_identity(&g_ortho.model_matrix);
- render_text(&g_text_seq_title, 20.0f, 30.0f);
+ gl_ortho_text_render_outline(&g_ortho, &g_text_seq_title,
+ 20.0f, 30.0f);
/* progress bar */
gl_matrix_4f_init_identity(&g_ortho.model_matrix);
glDisable(GL_BLEND);
@@ -312,7 +264,8 @@ bool window_sdl2_demo_render (s_window_sdl2 *window)
gl_matrix_4f_init_identity(&g_ortho.model_matrix);
gl_text_update_1(&g_text_fps, fps);
glEnable(GL_BLEND);
- render_text(&g_text_fps, 20, window->h - 30);
+ gl_ortho_text_render_outline(&g_ortho, &g_text_fps,
+ 20, window->h - 30);
gl_ortho_render_end(&g_ortho);
return true;
}
diff --git a/libc3/window/sdl2/gl_ortho.c b/libc3/window/sdl2/gl_ortho.c
index e2ee51f..25291e8 100644
--- a/libc3/window/sdl2/gl_ortho.c
+++ b/libc3/window/sdl2/gl_ortho.c
@@ -280,6 +280,38 @@ void gl_ortho_text_render (s_gl_ortho *ortho, const s_gl_text *text)
gl_ortho_bind_texture(ortho, 0);
}
+void gl_ortho_text_render_outline (s_gl_ortho *ortho, s_gl_text *text,
+ f64 x, f64 y)
+{
+ s_gl_matrix_4f matrix;
+ assert(glGetError() == GL_NO_ERROR);
+ glEnable(GL_BLEND);
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
+ GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ assert(glGetError() == GL_NO_ERROR);
+ gl_ortho_bind_texture(ortho, text->texture);
+ assert(glGetError() == GL_NO_ERROR);
+ gl_ortho_color(ortho, 1.0f, 1.0f, 1.0f, 1.0f);
+ assert(glGetError() == GL_NO_ERROR);
+ matrix = ortho->model_matrix;
+ gl_ortho_rect(ortho, x - 1.0, y - 1.0, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x, y - 1.0, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x + 1.0, y - 1.0, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x - 1.0, y, text->pt_w, text->pt_h);
+ //gl_ortho_rect(ortho, x, y, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x + 1.0, y, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x - 1.0, y + 1.0, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x, y + 1.0, text->pt_w, text->pt_h);
+ gl_ortho_rect(ortho, x + 1.0, y + 1.0, text->pt_w, text->pt_h);
+ gl_ortho_color(ortho, 0.0f, 0.0f, 0.0f, 1.0f);
+ assert(glGetError() == GL_NO_ERROR);
+ gl_ortho_rect(ortho, x, y, text->pt_w, text->pt_h);
+ assert(glGetError() == GL_NO_ERROR);
+ ortho->model_matrix = matrix;
+ gl_ortho_update_model_matrix(ortho);
+ assert(glGetError() == GL_NO_ERROR);
+}
+
void gl_ortho_update_model_matrix (s_gl_ortho *ortho)
{
assert(ortho);
diff --git a/libc3/window/sdl2/gl_ortho.h b/libc3/window/sdl2/gl_ortho.h
index c31264a..bf99e25 100644
--- a/libc3/window/sdl2/gl_ortho.h
+++ b/libc3/window/sdl2/gl_ortho.h
@@ -36,6 +36,9 @@ void gl_ortho_resize (s_gl_ortho *ortho, f32 x1, f32 x2, f32 y1,
f32 y2, f32 clip_z_near, f32 clip_z_far);
void gl_ortho_text_render (s_gl_ortho *ortho,
const s_gl_text *text);
+void gl_ortho_text_render_outline (s_gl_ortho *ortho,
+ s_gl_text *text,
+ f64 x, f64 y);
void gl_ortho_update_model_matrix (s_gl_ortho *ortho);
void gl_ortho_update_view_matrix (s_gl_ortho *ortho);
diff --git a/libc3/window/sdl2/gl_text.c b/libc3/window/sdl2/gl_text.c
index 4e7b9e5..c4081ee 100644
--- a/libc3/window/sdl2/gl_text.c
+++ b/libc3/window/sdl2/gl_text.c
@@ -75,12 +75,14 @@ bool gl_text_render_to_texture (s_gl_text *text)
FT_UInt glyph_index;
uw i;
uw j;
+ uw line_height;
uw max_ascent;
uw max_descent;
- FT_UInt prev_glyph_index = 0;
+ FT_UInt prev_glyph_index;
s_str s;
f32 scale_y;
- f32 x;
+ uw x;
+ uw y;
assert(text);
assert(text->font);
assert(text->texture);
@@ -95,14 +97,25 @@ bool gl_text_render_to_texture (s_gl_text *text)
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 = max_ascent + max_descent;
+ data_h = line_height;
+ x = 0;
+ prev_glyph_index = 0;
while (str_read_character_utf8(&s, &c) > 0) {
+ if (c == '\n') {
+ if (x > data_w)
+ data_w = x;
+ x = 0;
+ data_h += line_height;
+ prev_glyph_index = 0;
+ continue;
+ }
glyph_index = FT_Get_Char_Index(face, c);
if (prev_glyph_index && glyph_index) {
FT_Get_Kerning(face, prev_glyph_index, glyph_index,
FT_KERNING_DEFAULT, &delta);
- data_w += delta.x >> 6;
+ x += delta.x >> 6;
}
if (FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER)) {
err_write_1("gl_font_render_to_texture: failed to load glyph: ");
@@ -111,15 +124,24 @@ bool gl_text_render_to_texture (s_gl_text *text)
continue;
}
glyph = face->glyph;
- data_w += glyph->metrics.horiAdvance >> 6;
+ x += glyph->metrics.horiAdvance >> 6;
prev_glyph_index = glyph_index;
}
+ if (x > data_w)
+ data_w = x;
data_size = data_w * data_h * 4;
data = calloc(1, data_size);
x = 0;
+ y = 0;
prev_glyph_index = 0;
s = text->str;
while (str_read_character_utf8(&s, &c) > 0) {
+ if (c == '\n') {
+ x = 0;
+ y += line_height;
+ prev_glyph_index = 0;
+ continue;
+ }
glyph_index = FT_Get_Char_Index(face, c);
if (prev_glyph_index && glyph_index) {
FT_Vector delta;
@@ -132,7 +154,7 @@ bool gl_text_render_to_texture (s_gl_text *text)
glyph = face->glyph;
i = 0;
while (i < glyph->bitmap.rows) {
- data_y = data_h - 1 - i - max_ascent + glyph->bitmap_top;
+ data_y = data_h - 1 - (y + i + max_ascent - glyph->bitmap_top);
//printf("\n");
j = 0;
while (j < glyph->bitmap.width) {