mirror of
https://github.com/quelsolaar/MergeSource
synced 2025-02-01 09:58:42 -05:00
894 lines
27 KiB
C
894 lines
27 KiB
C
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
|
|
#include "seduce.h"
|
|
|
|
#define SUI_TEXTURE_DRAW_CASH_SIZE 512
|
|
#define SUI_TEXTURE_LETTER_SIZE 2.0
|
|
#define SUI_TEXTURE_LETTER_BASE (0.5)
|
|
|
|
extern boolean betray_set_screen_mode(uint x_size, uint y_size, boolean fullscreen);
|
|
extern double betray_screen_mode_get(uint *x_size, uint *y_size, boolean *fullscreen);
|
|
extern void betray_set_frustum_mode(double far, double near, double fov);
|
|
extern void betray_get_frustum_mode(double *far, double *near, double *fov);
|
|
|
|
extern void seduce_font_init();
|
|
|
|
void *sui_font_shader;
|
|
uint sui_font_shader_location_shader;
|
|
|
|
char *r_font_shader_vertex =
|
|
"attribute vec2 vertex;\n"
|
|
"uniform block{\n"
|
|
" vec2 pos;\n"
|
|
"};\n"
|
|
"uniform mat4 ModelViewProjectionMatrix;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_Position = ModelViewProjectionMatrix * vec4(vertex + pos, 0.0, 1.0);\n"
|
|
"}\n";
|
|
char *r_font_shader_fragment =
|
|
"uniform vec4 color;\n"
|
|
"void main()\n"
|
|
"{\n"
|
|
" gl_FragColor = color;\n"
|
|
"}\n";
|
|
|
|
|
|
void seduce_text_init()
|
|
{
|
|
char buf[2000];
|
|
sui_font_shader = r_shader_create_simple(buf, 2000, r_font_shader_vertex, r_font_shader_fragment, "color font");
|
|
r_shader_state_set_blend_mode(sui_font_shader, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
printf(buf);
|
|
sui_font_shader_location_shader = r_shader_uniform_location(sui_font_shader, "color");
|
|
}
|
|
|
|
float seduce_text_kern(float *k, float *k2)
|
|
{
|
|
float f, f2;
|
|
f = k[1] - k2[0];
|
|
f2 = k[3] - k2[2];
|
|
if(f2 > f)
|
|
f = f2;
|
|
f2 = k[5] - k2[4];
|
|
if(f2 > f)
|
|
f = f2;
|
|
f2 = k[7]- k2[6];
|
|
if(f2 > f)
|
|
f = f2;
|
|
return f;
|
|
}
|
|
|
|
|
|
uint seduce_text_line_draw_monospace(SeduceRenderFont *font, float pos_x, float pos_y, float character_size, float space_size, const char *text, uint *pos, float red, float green, float blue, float alpha, uint start, uint end, uint length)
|
|
{
|
|
RShader *s;
|
|
RMatrix *m;
|
|
SeduceFontCharacter *character = NULL;
|
|
unsigned int j = 0, placement = 0;
|
|
static void **sections = NULL;
|
|
static float *data;
|
|
uint32 character_id;
|
|
uint location, block_size, calls = 0;
|
|
float *c;
|
|
if(text == NULL || *text == '\0')
|
|
return 0.0;
|
|
m = r_matrix_get();
|
|
r_matrix_push(m);
|
|
r_matrix_translate(m, pos_x, pos_y, 0);
|
|
r_matrix_scale(m, character_size, character_size, 1.0);
|
|
r_shader_set(sui_font_shader);
|
|
r_shader_vec4_set(NULL, sui_font_shader_location_shader, red, green, blue, alpha);
|
|
block_size = r_shader_uniform_block_size(sui_font_shader, 0);
|
|
if(sections == NULL)
|
|
{
|
|
sections = malloc((sizeof *sections) * 1024);
|
|
data = malloc(1024 * block_size);
|
|
}
|
|
block_size /= sizeof(float);
|
|
space_size /= character_size;
|
|
data[0] = 0;
|
|
data[1] = 0;
|
|
while(*pos < end && text[*pos] != 0 && placement < length)
|
|
{
|
|
while(*pos < end && text[*pos] != 0 && calls < 1024 && placement < length)
|
|
{
|
|
character_id = f_utf8_to_uint32(text, pos);
|
|
if(placement >= start)
|
|
{
|
|
character = seduce_character_find(font, character_id);
|
|
if(character != NULL)
|
|
{
|
|
data[calls * block_size] = ((float)(placement - start) + (1 - character->size) * 0.5) * space_size;
|
|
data[calls * block_size + 1] = 0;
|
|
sections[calls] = character->sections;
|
|
calls++;
|
|
if(calls == 1024)
|
|
break;
|
|
}
|
|
}
|
|
placement++;
|
|
if(character_id == '\t')
|
|
placement = ((placement + 3) / 4) * 4;
|
|
}
|
|
if(calls != 0)
|
|
r_array_references_draw(font->pool, sections, GL_TRIANGLES, data, NULL, calls);
|
|
calls = 0;
|
|
}
|
|
r_matrix_pop(m);
|
|
return placement;
|
|
}
|
|
|
|
uint seduce_text_box_draw_monospace(SeduceRenderFont *font, float pos_x, float pos_y, float character_size, float space_size, float line_size, const char *text, uint line_count, uint line_length, uint *scroll, STextBlockMode *modes, uint mode_count)
|
|
{
|
|
uint pos = 0, p, i, j, end, add, block = 0, indent;
|
|
uint32 character_id;
|
|
if(font == NULL)
|
|
font = seduce_font_default_get();
|
|
if(scroll[1] != 0)
|
|
{
|
|
for(i = 0; text[pos] != 0; pos++)
|
|
{
|
|
if(text[pos] == '\n')
|
|
{
|
|
if(++i == scroll[1])
|
|
{
|
|
pos++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(text[pos] == 0)
|
|
return pos;
|
|
|
|
for(i = 0; i < line_count && text[pos] != 0; i++)
|
|
{
|
|
end = pos;
|
|
add = 0;
|
|
for(end = pos; text[end] != 0 && text[end] != '\n'; end++);
|
|
character_id = 0;
|
|
for(j = 0; j < scroll[0] && pos != end; j++)
|
|
{
|
|
character_id = f_utf8_to_uint32(text, &pos);
|
|
if(character_id == '\t')
|
|
j += 3;
|
|
}
|
|
if(character_id == '\t' && scroll[0] % 4 != 0)
|
|
add = (4 - scroll[0] % 4);
|
|
if(pos != end)
|
|
{
|
|
while(block + 1 < mode_count && modes[block + 1].character_position < end)
|
|
{
|
|
add += seduce_text_line_draw_monospace(font, pos_x + space_size * (float)add, pos_y - line_size * (float)(i + 1), character_size, space_size, text, &pos, modes[block].red, modes[block].green, modes[block].blue, modes[block].alpha, 0, modes[block + 1].character_position, line_length - add);
|
|
block++;
|
|
}
|
|
seduce_text_line_draw_monospace(font, pos_x + space_size * (float)add, pos_y - line_size * (float)(i + 1), character_size, space_size, text, &pos, modes[block].red, modes[block].green, modes[block].blue, modes[block].alpha, 0, end, line_length - add);
|
|
if(text[end] == 0)
|
|
return end;
|
|
}
|
|
pos = end + 1;
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
uint seduce_text_box_draw_monospace_find(const char *text, uint pos, uint scroll, uint line_length)
|
|
{
|
|
uint i, j, character_id;
|
|
for(i = j = 0; i < pos; j++)
|
|
{
|
|
character_id = f_utf8_to_uint32(text, &i);
|
|
if(character_id == '\t')
|
|
j += 3;
|
|
}
|
|
// if(j > scroll)
|
|
{
|
|
// j -= scroll;
|
|
if(j < line_length)
|
|
return j;
|
|
return line_length;
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
void seduce_text_box_draw_monospace_select(BInputState *input, float pos_x, float pos_y, float character_size, float space_size, float line_size, const char *text, uint line_count, uint line_length, uint *scroll, uint select_start, uint select_end)
|
|
{
|
|
uint pos = 0, p, i, j, end, a, b, block = 0, indent;
|
|
uint32 character_id;
|
|
float center[3] = {0, 0, 0};
|
|
|
|
|
|
if(select_start > select_end)
|
|
{
|
|
i = select_start;
|
|
select_start = select_end;
|
|
select_end = i;
|
|
}
|
|
|
|
if(scroll[1] != 0)
|
|
{
|
|
for(i = 0; text[pos] != 0; pos++)
|
|
{
|
|
if(text[pos] == '\n')
|
|
{
|
|
if(++i == scroll[1])
|
|
{
|
|
pos++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(/*text[pos] == 0 || */pos > select_end)
|
|
return;
|
|
|
|
for(i = 0; i < line_count; i++)
|
|
{
|
|
end = pos;
|
|
for(end = pos; text[end] != 0 && text[end] != '\n'; end++);
|
|
character_id = 0;
|
|
for(j = 0; j < scroll[0] && pos != end; j++)
|
|
{
|
|
character_id = f_utf8_to_uint32(text, &pos);
|
|
if(character_id == '\t')
|
|
j += 3;
|
|
}
|
|
|
|
if(select_start <= end)
|
|
{
|
|
if(pos > select_start)
|
|
a = 0;
|
|
else
|
|
a = seduce_text_box_draw_monospace_find(&text[pos], select_start - pos, scroll[0], line_length);
|
|
if(select_start == select_end)
|
|
{
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + space_size * (float)a, pos_y - line_size - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a - space_size * 0.2, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a - space_size * 0.2, pos_y - line_size - character_size * 0.5, 0,
|
|
0.2, 0, 0,
|
|
0, 0, 0, 0.0);
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + space_size * (float)a + space_size * 0.2, pos_y - line_size - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a + space_size * 0.2, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a, pos_y - line_size - character_size * 0.5, 0,
|
|
-0.2, 0, 0,
|
|
0, 0, 0, 0.0);
|
|
break;
|
|
}
|
|
if(select_end < end)
|
|
b = seduce_text_box_draw_monospace_find(&text[pos], select_end - pos, scroll[0], line_length);
|
|
else
|
|
b = seduce_text_box_draw_monospace_find(&text[pos], end - pos, scroll[0], line_length);
|
|
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + space_size * (float)a, pos_y - line_size - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)a, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)b, pos_y - character_size * 0.5, 0,
|
|
pos_x + space_size * (float)b, pos_y - line_size - character_size * 0.5, 0,
|
|
0, 0, 0,
|
|
0, 0, 0, 0.0);
|
|
|
|
}
|
|
if(end >= select_end || text[end] == 0/* || text[end + 1] == 0*/)
|
|
break;
|
|
pos = end + 1;
|
|
pos_y -= line_size;
|
|
}
|
|
seduce_background_polygon_flush(input, center, 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
float seduce_text_line_draw_internal(SeduceRenderFont *font, float pos_x, float pos_y, float size, float spacing, float space_length_add, const char *text, float red, float green, float blue, float alpha, uint length)
|
|
{
|
|
RShader *s;
|
|
RMatrix *m;
|
|
SeduceFontCharacter *character = NULL, *last;
|
|
unsigned int i = 0, j = 0, k;
|
|
float f, f2, pos;
|
|
static void **sections = NULL;
|
|
static float *data;
|
|
uint location, block_size, calls = 0;
|
|
float *c;
|
|
if(text == NULL || *text == '\0')
|
|
return 0.0;
|
|
m = r_matrix_get();
|
|
r_matrix_push(m);
|
|
r_matrix_translate(m, pos_x, pos_y, 0);
|
|
r_matrix_scale(m, size, size, 1.0);
|
|
r_shader_set(sui_font_shader);
|
|
r_shader_vec4_set(NULL, sui_font_shader_location_shader, red, green, blue, alpha);
|
|
block_size = r_shader_uniform_block_size(sui_font_shader, 0);
|
|
if(sections == NULL)
|
|
{
|
|
sections = malloc((sizeof *sections) * 1024);
|
|
data = malloc(1024 * block_size);
|
|
}
|
|
space_length_add /= size;
|
|
block_size /= sizeof(float);
|
|
data[0] = 0;
|
|
data[1] = 0;
|
|
pos = -(1.0 + spacing);
|
|
pos = -spacing;
|
|
while(i < length && text[i] != 0)
|
|
{
|
|
while(i < length && calls < 1024)
|
|
{
|
|
last = character;
|
|
character = seduce_character_find(font, f_utf8_to_uint32(text, &i));
|
|
if(character != NULL)
|
|
{
|
|
if(last != NULL)
|
|
pos += spacing + seduce_text_kern(last->kerning, character->kerning);
|
|
else
|
|
pos += spacing;
|
|
data[calls * block_size] = pos;
|
|
data[calls * block_size + 1] = 0;
|
|
sections[calls] = character->sections;
|
|
if(sections[calls] != NULL)
|
|
{
|
|
calls++;
|
|
if(calls == 1024)
|
|
break;
|
|
}
|
|
}else
|
|
{
|
|
if(last != NULL)
|
|
pos += last->size;
|
|
pos += 1 + space_length_add + spacing;
|
|
}
|
|
if(text[i] == 0)
|
|
break;
|
|
}
|
|
r_array_references_draw(font->pool, sections, GL_TRIANGLES, data, NULL, calls);
|
|
calls = 0;
|
|
}
|
|
if(character != NULL)
|
|
pos += character->size;
|
|
r_matrix_pop(m);
|
|
return pos * size;
|
|
}
|
|
|
|
|
|
float seduce_text_line_draw(SeduceRenderFont *font, float pos_x, float pos_y, float size, float spacing, const char *text, float red, float green, float blue, float alpha, uint length)
|
|
{
|
|
if(font == NULL)
|
|
font = seduce_font_default_get();
|
|
return seduce_text_line_draw_internal(font, pos_x, pos_y, size, spacing, 0, text, red, green, blue, alpha, length);
|
|
}
|
|
|
|
float seduce_text_line_length_internal(SeduceRenderFont *font, float size, float spacing, float space_length_add, const char *text, uint *length, float distance)
|
|
{
|
|
SeduceFontCharacter *character = NULL, *last;
|
|
unsigned int i = 0, j = 0, k, old_i = 0;
|
|
float add, pos;
|
|
uint location, block_size, calls = 0;
|
|
float *c;
|
|
if(font == NULL)
|
|
font = seduce_font_default_get();
|
|
if(text == NULL || *text == '\0')
|
|
{
|
|
*length = 0;
|
|
return 0.0;
|
|
}
|
|
|
|
space_length_add /= size;
|
|
distance /= size;
|
|
pos = -spacing;
|
|
distance -= spacing;
|
|
while(i < *length && text[i] != 0)
|
|
{
|
|
last = character;
|
|
old_i = i;
|
|
character = seduce_character_find(font, f_utf8_to_uint32(text, &i));
|
|
if(character != NULL)
|
|
{
|
|
if(last != NULL)
|
|
add = spacing + seduce_text_kern(last->kerning, character->kerning);
|
|
else
|
|
add = spacing;
|
|
}else
|
|
{
|
|
add = 1 + space_length_add + spacing;
|
|
if(last != NULL)
|
|
add += last->size;
|
|
}
|
|
/* if(text[i] == 0)
|
|
break;*/
|
|
if(distance < pos + add * 0.5)
|
|
{
|
|
*length = old_i;
|
|
return pos * size;
|
|
}
|
|
pos += add;
|
|
calls = 0;
|
|
}
|
|
*length = i;
|
|
if(character != NULL)
|
|
pos += character->size;
|
|
return pos * size;
|
|
}
|
|
|
|
|
|
float seduce_text_line_length(SeduceRenderFont *font, float size, float spacing, const char *text, uint end)
|
|
{
|
|
return seduce_text_line_length_internal(font, size, spacing, 0, text, &end, 10000000);
|
|
}
|
|
|
|
uint seduce_text_line_hit_test(SeduceRenderFont *font, float letter_size, float letter_spacing, const char *text, float pos_x)
|
|
{
|
|
uint end = -1;
|
|
seduce_text_line_length_internal(font, letter_size, letter_spacing, 0, text, &end, pos_x - letter_size);
|
|
return end;
|
|
}
|
|
|
|
uint seduce_text_block_hit_test(SeduceRenderFont *font, float *size, uint *gaps, float letter_size, float letter_spacing, const char *text, float pos_x, uint end)
|
|
{
|
|
SeduceFontCharacter *character = NULL, *last;
|
|
unsigned int i = 0, last_i = 0, space_count, space_pos = 0;
|
|
float f, pos, last_pos = 0;
|
|
if(font == NULL)
|
|
font = seduce_font_default_get();
|
|
if(text == NULL || *text == '\0')
|
|
return 0.0;
|
|
pos_x /= letter_size;
|
|
pos = -(letter_spacing);
|
|
space_count = 0;
|
|
while(i < end && text[i] != 0)
|
|
{
|
|
last = character;
|
|
last_i = i;
|
|
character = seduce_character_find(font, f_utf8_to_uint32(text, &i));
|
|
if(character != NULL)
|
|
{
|
|
if(last != NULL)
|
|
pos += letter_spacing + seduce_text_kern(last->kerning, character->kerning);
|
|
else
|
|
pos += letter_spacing;
|
|
if(pos_x < pos + character->size)
|
|
{
|
|
if(*gaps + space_count > 0)
|
|
{
|
|
*gaps += space_count;
|
|
*size = last_pos;
|
|
return space_pos;
|
|
}else
|
|
{
|
|
*gaps += space_count;
|
|
*size = pos;
|
|
return last_i;
|
|
}
|
|
}
|
|
}else
|
|
{
|
|
space_pos = last_i;
|
|
space_count++;
|
|
if(last != NULL)
|
|
pos += last->size;
|
|
last_pos = pos;
|
|
pos += 1 + letter_spacing;
|
|
}
|
|
}
|
|
if(character != NULL)
|
|
pos += letter_spacing + character->size;
|
|
else
|
|
pos += 1 + letter_spacing;
|
|
|
|
*gaps += space_count;
|
|
*size = pos;
|
|
return i;
|
|
}
|
|
|
|
uint seduce_text_block_draw(float pos_x, float pos_y, float line_size, float height, float line_spacing, STextBlockAlignmentStyle style, const char *text, uint pos, STextBlockMode *modes, uint mode_count)
|
|
{
|
|
uint i, j, next, gaps, start_block = 0, block, line_end, accum;
|
|
float f, size, space_size, x, y, highest;
|
|
y = 0;
|
|
height = -height;
|
|
for(start_block = 0; start_block + 1 < mode_count && pos > modes[start_block + 1].character_position; start_block++);
|
|
for(i = 0; text[pos] != 0; i++)
|
|
{
|
|
accum = pos;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &accum)))
|
|
pos = accum;
|
|
else
|
|
accum = pos;
|
|
x = line_size;
|
|
highest = modes[start_block].letter_size;
|
|
gaps = 0;
|
|
for(block = start_block; ; block++)
|
|
{
|
|
if(block + 1 < mode_count)
|
|
line_end = modes[block + 1].character_position - accum;
|
|
else
|
|
line_end = -1;
|
|
next = seduce_text_block_hit_test(modes[block].font, &size, &gaps, modes[block].letter_size, modes[block].letter_spacing, &text[accum], x, line_end);
|
|
x -= size * modes[block].letter_size;
|
|
accum += next;
|
|
if(next != line_end)
|
|
break;
|
|
if(highest < modes[block + 1].letter_size)
|
|
highest = modes[block + 1].letter_size;
|
|
}
|
|
j = accum;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &j)))
|
|
gaps--;
|
|
y -= line_spacing * highest;
|
|
if(y < height)
|
|
return pos;
|
|
space_size = 0.0;
|
|
switch(style)
|
|
{
|
|
case SEDUCE_TBAS_LEFT :
|
|
x = 0;
|
|
break;
|
|
case SEDUCE_TBAS_RIGHT :
|
|
x = x;
|
|
break;
|
|
case SEDUCE_TBAS_CENTER :
|
|
x = x * 0.5;
|
|
break;
|
|
case SEDUCE_TBAS_STRETCH :
|
|
if(text[accum] != 0)
|
|
space_size = x / (float)gaps;
|
|
x = 0;
|
|
break;
|
|
}
|
|
|
|
|
|
for(start_block; start_block <= block; start_block++)
|
|
{
|
|
if(start_block + 1 < mode_count)
|
|
line_end = modes[start_block + 1].character_position - pos;
|
|
else
|
|
line_end = -1;
|
|
if(line_end > accum - pos)
|
|
line_end = accum - pos;
|
|
x += seduce_text_line_draw_internal(modes[start_block].font, pos_x + x, pos_y + y, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], modes[start_block].red, modes[start_block].green, modes[start_block].blue, modes[start_block].alpha, line_end);
|
|
pos += line_end;
|
|
if(pos >= accum)
|
|
break;
|
|
}
|
|
}
|
|
return pos;
|
|
}
|
|
|
|
|
|
|
|
void seduce_text_block_select_draw(BInputState *input, float pos_x, float pos_y, float line_size, float height, float line_spacing, STextBlockAlignmentStyle style, const char *text, uint pos, STextBlockMode *modes, uint mode_count, uint select_start, uint select_end)
|
|
{
|
|
uint i, j, next, gaps, start_block = 0, block, line_end, line_start, accum;
|
|
float f, size, space_size, x, y, highest, f_start, f_end;
|
|
y = 0;
|
|
height = -height;
|
|
if(pos >= select_end)
|
|
return;
|
|
for(start_block = 0; start_block + 1 < mode_count && pos > modes[start_block + 1].character_position; start_block++);
|
|
for(i = 0; text[pos] != 0; i++)
|
|
{
|
|
accum = pos;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &accum)))
|
|
pos = accum;
|
|
else
|
|
accum = pos;
|
|
x = line_size;
|
|
highest = modes[start_block].letter_size;
|
|
gaps = 0;
|
|
for(block = start_block; ; block++)
|
|
{
|
|
if(block + 1 < mode_count)
|
|
line_end = modes[block + 1].character_position - accum;
|
|
else
|
|
line_end = -1;
|
|
next = seduce_text_block_hit_test(modes[block].font, &size, &gaps, modes[block].letter_size, modes[block].letter_spacing, &text[accum], x, line_end);
|
|
x -= size * modes[block].letter_size;
|
|
accum += next;
|
|
if(next != line_end)
|
|
break;
|
|
if(highest < modes[block + 1].letter_size)
|
|
highest = modes[block + 1].letter_size;
|
|
}
|
|
j = accum;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &j)))
|
|
gaps--;
|
|
y -= line_spacing * highest;
|
|
if(y < height)
|
|
return;
|
|
switch(style)
|
|
{
|
|
case SEDUCE_TBAS_LEFT :
|
|
x = 0;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_RIGHT :
|
|
x = x;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_CENTER :
|
|
x = x * 0.5;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_STRETCH :
|
|
space_size = x / (float)gaps;
|
|
x = 0;
|
|
break;
|
|
}
|
|
for(start_block; start_block <= block; start_block++)
|
|
{
|
|
if(start_block + 1 < mode_count)
|
|
line_end = modes[start_block + 1].character_position - pos;
|
|
else
|
|
line_end = -1;
|
|
if(line_end > accum - pos)
|
|
line_end = accum - pos;
|
|
// x += seduce_text_line_draw_internal(modes[start_block].font, pos_x + x, pos_y + y, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], modes[start_block].red, modes[start_block].green, modes[start_block].blue, modes[start_block].alpha, line_end);
|
|
if(pos + line_end > select_start)
|
|
{
|
|
|
|
if(pos < select_start)
|
|
{
|
|
line_start = select_start - pos;
|
|
f_start = x + seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &line_start, line_size + 1);
|
|
}else
|
|
f_start = x;
|
|
|
|
if(select_start == select_end)
|
|
{
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + f_start, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
pos_x + f_start, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size * 0.5, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size * 0.5, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
-0.2, 0, 0,
|
|
0, 0, 0, 1.0);
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size * 0.5, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size * 0.5, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_start + modes[start_block].letter_spacing * modes[start_block].letter_size, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
0.2, 0, 0,
|
|
0, 0, 0, 1.0);
|
|
}else
|
|
{
|
|
if(pos + line_end > select_end)
|
|
{
|
|
if(line_end > select_end - pos)
|
|
line_end = select_end - pos;
|
|
f_end = x + seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &line_end, line_size + 1);
|
|
}else
|
|
{
|
|
if(pos + line_end >= accum)
|
|
f_end = line_size;
|
|
else
|
|
f_end = x + seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &line_end, line_size + 1);
|
|
}
|
|
seduce_background_quad_draw(input, NULL, 0,
|
|
pos_x + f_start, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
pos_x + f_start, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_end, pos_y + y + modes[start_block].letter_size * 1.5, 0,
|
|
pos_x + f_end, pos_y + y - modes[start_block].letter_size * 0.5, 0,
|
|
0, 0, 0,
|
|
0, 0, 0, 0.0);
|
|
}
|
|
if(pos + line_end >= select_end)
|
|
{
|
|
float center[3] = {0, 0, 0};
|
|
seduce_background_polygon_flush(input,center, 1.0);
|
|
return;
|
|
}
|
|
}
|
|
x += seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &line_end, line_size + 1);
|
|
pos += line_end;
|
|
if(pos >= accum)
|
|
break;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
boolean seduce_text_block_length(float *output, float pos_x, float pos_y, float line_size, float height, float line_spacing, STextBlockAlignmentStyle style, const char *text, uint pos, STextBlockMode *modes, uint mode_count, uint end)
|
|
{
|
|
uint i, j, next, gaps, start_block = 0, block, line_end, accum;
|
|
float f, size, space_size, x = 0, y = 0, highest;
|
|
height = -height;
|
|
for(start_block = 0; start_block + 1 < mode_count && pos > modes[start_block + 1].character_position; start_block++);
|
|
for(i = 0; text[pos] != 0; i++)
|
|
{
|
|
accum = pos;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &accum)))
|
|
pos = accum;
|
|
else
|
|
accum = pos;
|
|
x = line_size;
|
|
highest = modes[start_block].letter_size;
|
|
gaps = 0;
|
|
for(block = start_block; ; block++)
|
|
{
|
|
if(block + 1 < mode_count)
|
|
line_end = modes[block + 1].character_position - accum;
|
|
else
|
|
line_end = -1;
|
|
next = seduce_text_block_hit_test(modes[block].font, &size, &gaps, modes[block].letter_size, modes[block].letter_spacing, &text[accum], x, line_end);
|
|
x -= size * modes[block].letter_size;
|
|
accum += next;
|
|
if(next != line_end)
|
|
break;
|
|
if(highest < modes[block + 1].letter_size)
|
|
highest = modes[block + 1].letter_size;
|
|
}
|
|
j = accum;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &j)))
|
|
gaps--;
|
|
|
|
y -= line_spacing * highest;
|
|
if(y < height)
|
|
{
|
|
output[0] = pos_x + x;
|
|
output[1] = pos_y + y;
|
|
return FALSE;
|
|
}
|
|
if(accum >= end)
|
|
{
|
|
|
|
switch(style)
|
|
{
|
|
case SEDUCE_TBAS_LEFT :
|
|
x = 0;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_RIGHT :
|
|
x = x;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_CENTER :
|
|
x = x * 0.5;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_STRETCH :
|
|
space_size = x / (float)gaps;
|
|
x = 0;
|
|
break;
|
|
}
|
|
for(start_block; start_block <= block; start_block++)
|
|
{
|
|
if(start_block + 1 < mode_count)
|
|
line_end = modes[start_block + 1].character_position - pos;
|
|
else
|
|
line_end = -1;
|
|
if(line_end > accum - pos)
|
|
line_end = accum - pos;
|
|
if(line_end > end - pos)
|
|
line_end = end - pos;
|
|
x += seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &line_end, line_size + 1);
|
|
if(line_end == end - pos)
|
|
{
|
|
output[0] = pos_x + x;
|
|
output[1] = pos_y + y;
|
|
return TRUE;
|
|
}
|
|
pos += line_end;
|
|
|
|
|
|
if(pos >= accum)
|
|
break;
|
|
}
|
|
}else
|
|
{
|
|
pos = accum;
|
|
for(start_block; start_block + 1 < mode_count && modes[start_block + 1].character_position <= pos; start_block++);
|
|
}
|
|
}
|
|
output[0] = pos_x + x;
|
|
output[1] = pos_y + y;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
float seduce_text_block_height(float line_size, float line_spacing, STextBlockAlignmentStyle style, const char *text, uint pos, STextBlockMode *modes, uint mode_count, uint end)
|
|
{
|
|
float output[2];
|
|
seduce_text_block_length(output, 0, 0, line_size, 100000000000, line_spacing, style, text, pos, modes, mode_count, end);
|
|
return -output[1];
|
|
}
|
|
|
|
|
|
uint seduce_text_block_hit_detect(float pos_x, float pos_y, float line_size, float height, float line_spacing, STextBlockAlignmentStyle style, const char *text, uint pos, STextBlockMode *modes, uint mode_count, float pointer_x, float pointer_y)
|
|
{
|
|
uint i, j, next, gaps, start_block = 0, block, line_end, accum;
|
|
float f, size, space_size, x, y, highest;
|
|
|
|
if(pointer_y > pos_y)
|
|
return 0;
|
|
height = -height;
|
|
y = 0;
|
|
for(start_block = 0; start_block + 1 < mode_count && pos > modes[start_block + 1].character_position; start_block++);
|
|
for(i = 0; text[pos] != 0; i++)
|
|
{
|
|
accum = pos;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &accum)))
|
|
pos = accum;
|
|
else
|
|
accum = pos;
|
|
x = line_size;
|
|
highest = modes[start_block].letter_size;
|
|
gaps = 0;
|
|
for(block = start_block; ; block++)
|
|
{
|
|
if(block + 1 < mode_count)
|
|
line_end = modes[block + 1].character_position - accum;
|
|
else
|
|
line_end = -1;
|
|
next = seduce_text_block_hit_test(modes[block].font, &size, &gaps, modes[block].letter_size, modes[block].letter_spacing, &text[accum], x, line_end);
|
|
x -= size * modes[block].letter_size;
|
|
accum += next;
|
|
if(next != line_end)
|
|
break;
|
|
if(highest < modes[block + 1].letter_size)
|
|
highest = modes[block + 1].letter_size;
|
|
}
|
|
j = accum;
|
|
if(NULL == seduce_character_find(modes[start_block].font, f_utf8_to_uint32(text, &j)))
|
|
gaps--;
|
|
|
|
y -= line_spacing * highest;
|
|
if(y < height)
|
|
return pos;
|
|
if(pos_y + y - highest < pointer_y)
|
|
{
|
|
switch(style)
|
|
{
|
|
case SEDUCE_TBAS_LEFT :
|
|
x = 0;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_RIGHT :
|
|
x = x;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_CENTER :
|
|
x = x * 0.5;
|
|
space_size = 0.0;
|
|
break;
|
|
case SEDUCE_TBAS_STRETCH :
|
|
space_size = x / (float)gaps;
|
|
x = 0;
|
|
break;
|
|
}
|
|
for(start_block; start_block <= block; start_block++)
|
|
{
|
|
if(start_block + 1 < mode_count)
|
|
line_end = modes[start_block + 1].character_position - pos;
|
|
else
|
|
line_end = -1;
|
|
if(line_end > accum - pos)
|
|
line_end = accum - pos;
|
|
|
|
j = line_end;
|
|
x += seduce_text_line_length_internal(modes[start_block].font, modes[start_block].letter_size, modes[start_block].letter_spacing, space_size, &text[pos], &j, pointer_x - x - pos_x);
|
|
if(line_end != j)
|
|
return pos + j;
|
|
pos += line_end;
|
|
if(pos >= accum)
|
|
break;
|
|
}
|
|
return pos;
|
|
}else
|
|
{
|
|
pos = accum;
|
|
for(start_block; start_block + 1 < mode_count && modes[start_block + 1].character_position <= pos; start_block++);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|