28 #include "ascension/ui/text.h" |
28 #include "ascension/ui/text.h" |
29 #include "ascension/context.h" |
29 #include "ascension/context.h" |
30 #include "ascension/error.h" |
30 #include "ascension/error.h" |
31 #include "ascension/shader.h" |
31 #include "ascension/shader.h" |
32 |
32 |
|
33 #include <cx/printf.h> |
|
34 |
33 #include <GL/glew.h> |
35 #include <GL/glew.h> |
34 |
36 |
35 static void asc_text_draw(AscText const *node) { |
37 static void asc_text_draw(AscText const *node) { |
36 // Obtain shader |
38 // Obtain shader |
37 AscShaderSprite *shader = &asc_context.active_window->glctx.shader.sprite; |
39 AscShaderSprite *shader = &asc_context.active_window->glctx.shader.sprite; |
56 asc_texture_init_rectangle(&node->tex); |
58 asc_texture_init_rectangle(&node->tex); |
57 } |
59 } |
58 |
60 |
59 // Render text onto a surface |
61 // Render text onto a surface |
60 TTF_Font *font = asc_font_cache_validate(node->font)->ptr; |
62 TTF_Font *font = asc_font_cache_validate(node->font)->ptr; |
|
63 static int alignments[] = { |
|
64 TTF_WRAPPED_ALIGN_LEFT, |
|
65 TTF_WRAPPED_ALIGN_CENTER, |
|
66 TTF_WRAPPED_ALIGN_RIGHT |
|
67 }; |
61 TTF_SetFontWrappedAlign( |
68 TTF_SetFontWrappedAlign( |
62 font, node->centered ? |
69 font, alignments[node->base.flags & ASC_TEXT_ALIGNMENT_MASK]); |
63 TTF_WRAPPED_ALIGN_CENTER : TTF_WRAPPED_ALIGN_LEFT |
|
64 ); |
|
65 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
70 SDL_Surface *surface = TTF_RenderUTF8_Blended_Wrapped( |
66 font, node->text, asc_col_sdl(node->color), node->max_width |
71 font, node->text.ptr, asc_col_sdl(node->color), node->max_width |
67 ); |
72 ); |
68 if (surface == NULL) { |
73 if (surface == NULL) { |
69 asc_error(SDL_GetError()); |
74 asc_error(SDL_GetError()); |
70 return; |
75 return; |
71 } |
76 } |
72 asc_set_scale2d(&node->base, surface->w, surface->h); |
77 asc_set_scale2d(&node->base, surface->w, surface->h); |
73 asc_update_transform((AscSceneNode *) node); |
78 if (asc_test_flag(node->base.flags, ASC_TEXT_CENTERED_FLAG)) { |
|
79 unsigned short newoffx = surface->w / 2; |
|
80 asc_vec2i pos = asc_get_position2d(&node->base); |
|
81 asc_set_position2d(&node->base, pos.x + node->offx - newoffx, pos.y); |
|
82 node->offx = newoffx; |
|
83 } |
74 |
84 |
75 // Transfer Image Data |
85 // Transfer Image Data |
76 asc_texture_from_surface(&node->tex, surface); |
86 asc_texture_from_surface(&node->tex, surface); |
77 |
87 |
78 // Free the surface |
88 // Free the surface |
79 SDL_FreeSurface(surface); |
89 SDL_FreeSurface(surface); |
80 } |
90 } |
81 |
91 |
82 AscSceneNode *asc_text(int x, int y, char const *text) { |
92 AscSceneNode *asc_text(int x, int y, char const *text) { |
|
93 // TODO: implement fancy struct "named param" initialization |
83 AscText *node = calloc(1, sizeof(AscText)); |
94 AscText *node = calloc(1, sizeof(AscText)); |
84 |
95 |
85 node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND; |
96 node->base.render_group = ASC_RENDER_GROUP_SPRITE_BLEND; |
86 node->base.free_func = (asc_scene_free_func) asc_text_free; |
97 node->base.free_func = (asc_scene_free_func) asc_text_free; |
87 node->base.update_func = (asc_scene_update_func) asc_text_update; |
98 node->base.update_func = (asc_scene_update_func) asc_text_update; |
89 |
100 |
90 node->base.position.x = (float) x; |
101 node->base.position.x = (float) x; |
91 node->base.position.y = (float) y; |
102 node->base.position.y = (float) y; |
92 node->font = asc_context.active_font; |
103 node->font = asc_context.active_font; |
93 node->color = asc_context.ink; |
104 node->color = asc_context.ink; |
94 if (text != NULL) { |
105 if (text == NULL) { |
95 node->text = strdup(text); |
106 node->text = cx_mutstr(strdup(" ")); |
|
107 } else { |
|
108 node->text = cx_mutstr(strdup(text)); |
96 } |
109 } |
97 |
110 |
98 // initialize |
111 // initialize |
99 asc_text_update(node); |
112 asc_text_update(node); |
100 |
113 |
101 return &node->base; |
114 return &node->base; |
102 } |
115 } |
103 |
116 |
104 void asc_text_free(AscText *node) { |
117 void asc_text_free(AscText *node) { |
105 asc_texture_destroy(&node->tex); |
118 asc_texture_destroy(&node->tex); |
106 free(node->text); |
119 cx_strfree(&node->text); |
107 free(node); |
120 free(node); |
108 } |
121 } |
|
122 |
|
123 void asc_text_printf( |
|
124 AscSceneNode *node, |
|
125 char const* format, |
|
126 ... |
|
127 ) { |
|
128 cxmutstr text = ((AscText*)node)->text; |
|
129 va_list ap; |
|
130 va_start(ap, format); |
|
131 cx_vsprintf(&text.ptr, &text.length, format, ap); |
|
132 va_end(ap); |
|
133 asc_node_update(node); |
|
134 } |