1387 lines
46 KiB
C
1387 lines
46 KiB
C
/*
|
||
testapp: An example of using the SDL_ttf library with OpenGL.
|
||
Copyright (C) 2001-2025 Sam Lantinga <slouken@libsdl.org>
|
||
|
||
This software is provided 'as-is', without any express or implied
|
||
warranty. In no event will the authors be held liable for any damages
|
||
arising from the use of this software.
|
||
|
||
Permission is granted to anyone to use this software for any purpose,
|
||
including commercial applications, and to alter it and redistribute it
|
||
freely, subject to the following restrictions:
|
||
|
||
1. The origin of this software must not be misrepresented; you must not
|
||
claim that you wrote the original software. If you use this software
|
||
in a product, an acknowledgment in the product documentation would be
|
||
appreciated but is not required.
|
||
2. Altered source versions must be plainly marked as such, and must not be
|
||
misrepresented as being the original software.
|
||
3. This notice may not be removed or altered from any source distribution.
|
||
*/
|
||
|
||
/* A simple program to test the text rendering feature of the TTF library,
|
||
* and find bugs
|
||
*
|
||
* <F1> for console help
|
||
*
|
||
* Use
|
||
* - fill/replace test_fonts[] with your fonts
|
||
* - replay a case, adding the log at line ~650 (search for 'replay')
|
||
* - add more string to test_strings[]
|
||
*
|
||
*/
|
||
|
||
static const int g_force_no_SDF = 0; /* make random fuzzer faster by disabling SDF rendering */
|
||
|
||
//#define HAVE_LCD
|
||
#define HAVE_SDF
|
||
|
||
#define HAVE_SET_FONT_SIZE_FUNCTION
|
||
// Need patch to set size dynamically
|
||
// https://bugzilla.libsdl.org/show_bug.cgi?id=2487
|
||
|
||
#define HAVE_WRAP_ALIGN
|
||
|
||
|
||
|
||
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <time.h>
|
||
|
||
#include <SDL3/SDL.h>
|
||
#include <SDL3_ttf/SDL_ttf.h>
|
||
|
||
static char *testapp_basename(const char *path) {
|
||
static char buffer[1024];
|
||
const char *pos, *sep, *prev_sep;
|
||
int prev_was_sep = 0;
|
||
|
||
prev_sep = sep = NULL;
|
||
for (pos = path; *pos; pos++) {
|
||
if (*pos == '/' || *pos == '\\') {
|
||
if (!prev_was_sep) {
|
||
prev_sep = sep;
|
||
}
|
||
sep = pos;
|
||
prev_was_sep = 1;
|
||
} else {
|
||
prev_was_sep = 0;
|
||
}
|
||
}
|
||
if (!sep) {
|
||
if (path[0] == '\0') {
|
||
buffer[0] = '.';
|
||
buffer[1] = '\0';
|
||
} else {
|
||
SDL_strlcpy(buffer, path, sizeof(buffer));
|
||
}
|
||
} else {
|
||
if (sep[1] == '\0') {
|
||
if (prev_sep) {
|
||
char *s;
|
||
SDL_strlcpy(buffer, prev_sep + 1, sizeof(buffer));
|
||
SDL_strtok_r(buffer, "/\\", &s);
|
||
} else {
|
||
buffer[0] = *sep;
|
||
buffer[1] = '\0';
|
||
}
|
||
} else {
|
||
SDL_strlcpy(buffer, sep + 1, sizeof(buffer));
|
||
}
|
||
}
|
||
return buffer;
|
||
}
|
||
|
||
static void help(void)
|
||
{
|
||
SDL_Log("up/down : font size -/+");
|
||
SDL_Log("c/v : next/previous font");
|
||
SDL_Log("o/p : outline -/+");
|
||
SDL_Log("q/e : wrap size -/+");
|
||
SDL_Log("a : align wrap: left center right");
|
||
SDL_Log("w : wrap");
|
||
SDL_Log("u : underline");
|
||
SDL_Log("k : kerning");
|
||
SDL_Log("s : strike-through");
|
||
SDL_Log("b : bold");
|
||
SDL_Log("g/h : hinting -/+ (normal, light, light_subpix, mono, none)");
|
||
SDL_Log("i : italic");
|
||
SDL_Log("f : signed distance field");
|
||
SDL_Log("t : ticks elapsed for 50 rendering");
|
||
SDL_Log("d : display normal texture, no screen update, stream texture ");
|
||
SDL_Log("r : start/stop random test");
|
||
SDL_Log("m : render mode Solid/Blended/Shaded");
|
||
SDL_Log("x : text engine None/Surface/Renderer");
|
||
SDL_Log("n : change direction");
|
||
SDL_Log("9/0 : -/+ alpha color fg");
|
||
SDL_Log("7/8 : -/+ alpha color bg (Shaded only)");
|
||
SDL_Log("6 : invert bg/fg colors");
|
||
SDL_Log("345 : increase r/g/b fg color");
|
||
SDL_Log("2 : background color (Black->R->G->B->W)");
|
||
SDL_Log("<space> : next string/rendering function");
|
||
SDL_Log("<backspace> : previous string/rendering function");
|
||
SDL_Log("F1 : help");
|
||
SDL_Log("F2 : save current rendering to .bmp");
|
||
}
|
||
|
||
|
||
static int rand_n(int n);
|
||
static void init_rand(void);
|
||
|
||
static const char *test_fonts[] = {
|
||
"fonts/NotoColorEmoji.ttf", // Colored Emoji
|
||
"fonts/FletcherGothicFLF.ttf",
|
||
#if 1
|
||
/* CFF/OpenType font (.otf) */
|
||
"fonts/ITCAvantGardeStd-Demi.ttf", // BUG 4266
|
||
#endif
|
||
"fonts/DroidSansFallback.ttf", // xstart negative Jap
|
||
"fonts/Папка/Lazy.ttf",
|
||
"fonts/DroidSans.ttf", // no kerning here ?
|
||
"fonts/DejaVuSans.ttf",
|
||
"fonts/digital-7.ttf", // BUG 969
|
||
"fonts/HelveticaNeue-Regular.ttf",// BUG 2622
|
||
"fonts/ttf_amiga/amiga4ever pro2.ttf",
|
||
"fonts/ttf-bitstream-vera-1.10/VeraMoBI.ttf",
|
||
"fonts/ttf-bitstream-vera-1.10/VeraBd.ttf",
|
||
"fonts/ttf-bitstream-vera-1.10/Vera.ttf",
|
||
"fonts/nonscalable/sazanami-gothic.ttf", // BUG 190 crash?. Both Scalable and Fixed Sizes
|
||
"fonts/drakono.ttf", // BUG 2629 ........ ??????
|
||
"fonts/Lazy.ttf", // BUG 2468
|
||
"fonts/font_bug254.ttf", // BUG 254
|
||
"fonts/OpenSansEmoji.ttf", // BUG 3762
|
||
#if 1
|
||
"fonts/nonscalable/pvfixed_20b.pcf.gz",
|
||
"fonts/nonscalable/pvfixed_20r.pcf.gz",
|
||
"fonts/nonscalable/7x13B-ISO8859-15.pcf.gz",
|
||
"fonts/nonscalable/vgasys.fon", // BUG 2574
|
||
"fonts/nonscalable/fixed8.fon", // BUG 2127
|
||
#endif
|
||
#if 0
|
||
# include "fonts/fuzzing_corpora.h"
|
||
#endif
|
||
#if 0
|
||
# include "fonts/android_fonts_others.h"
|
||
# include "fonts/android_fonts.h"
|
||
#endif
|
||
"fonts/Kaumudi.ttf"
|
||
};
|
||
static const int test_fonts_count = SDL_arraysize(test_fonts);
|
||
|
||
|
||
static int wrap_size = 137;
|
||
static int w_align = 0;
|
||
static int outline = 0;
|
||
static int font_style = 0;
|
||
static int kerning = 1;
|
||
static int wrap = 0;
|
||
static int sdf = 0;
|
||
static int hinting = 0;
|
||
static int curr_str = 0;
|
||
static int curr_font = 1;
|
||
static int curr_size = 50;
|
||
static int fg_alpha = 0;
|
||
static int bg_alpha = 0;
|
||
static int background_color = 0;
|
||
|
||
static int seed = 0;
|
||
static int print_elapsed_ticks = 0;
|
||
static int update_screen_mode = 0;
|
||
static int save_to_bmp = 0;
|
||
|
||
/* RENDER_SOLID = 0, RENDER_BLENDED = 1, RENDER_SHADED = 2, RENDER_LCD = 3 } */
|
||
static int render_mode = -1;
|
||
static int render_mode_overwrite;
|
||
static const char *render_mode_desc[] = { "Solid", "Blended", "Shaded", "LCD" };
|
||
static const int render_mode_count = SDL_arraysize(render_mode_desc);
|
||
|
||
static int textengine_mode = 0;
|
||
static const char *textengine_desc[] = { "None", "Surface", "Renderer" };
|
||
static const int textengine_count = SDL_arraysize(textengine_desc);
|
||
|
||
static int direction = 0;
|
||
static const struct {
|
||
const char *description;
|
||
int value;
|
||
} directions[] = {
|
||
{ "LTR", TTF_DIRECTION_LTR },
|
||
{ "RTL", TTF_DIRECTION_RTL },
|
||
{ "TTB", TTF_DIRECTION_TTB },
|
||
{ "BTT", TTF_DIRECTION_BTT }
|
||
};
|
||
static const int direction_count = SDL_arraysize(directions);
|
||
|
||
|
||
//static const char *hinting_desc[] = { "normal", "light", "light_subpix", "lcd_subpix", "mono", "none" };
|
||
static const char *hinting_desc[] = { "normal", "light", "light_subpix", "mono", "none" };
|
||
static const int hinting_count = SDL_arraysize(hinting_desc);
|
||
|
||
static int mode_random_test = 0;
|
||
static int random_cnt = 0;
|
||
|
||
static int saved_curr_font = -1;
|
||
static int saved_curr_size = -1;
|
||
|
||
static SDL_Color boardcol = { 0, 0, 0, 0 };
|
||
static SDL_Color textcol = { 255, 255, 255, 0 };
|
||
|
||
|
||
static const char emoji[5] = { 0xF0, 0x9F, 0x98, 0x81, '\0'};
|
||
|
||
static const char *test_strings[] = {
|
||
// TMP BUG
|
||
#if 0
|
||
"وفي حالة كشف مربع يحتوي على لغم، يخسر اللاعب اللعبة.",
|
||
#endif
|
||
#if 1
|
||
"纸牌接龙",
|
||
//"空当接龙用一副没有大小王的52张扑克牌来玩,这些扑克牌被摆在8列中。",
|
||
#endif
|
||
"ABC",
|
||
"The quick \n brown fox \n jumps over the lazy dog 0123456789",
|
||
"iiiiiiiiiiiiiiiiiiiiiiiiiiiiiii", // test supixel
|
||
emoji,
|
||
/* static const char emoji[5] = { 0xF0, 0x9F, 0x98, 0x81, '\0'}; */
|
||
#if 1
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
,
|
||
#endif
|
||
"aTa kerning iTo",
|
||
"AV VA Te eT Tr rT Td TA LV Vd pV Vq bV", // kerning
|
||
"if fi ifi aif fai aifia substitution",
|
||
"abc \xc4\x80", // String would be both outline and bitmap for Sazami-Gothic
|
||
#if 1
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
"abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz " "abcdefghijklmnopqrstuvwxyz "
|
||
,
|
||
#endif
|
||
"abcdefghijklmnopqrstuvwxyz",
|
||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||
"0123456789",
|
||
"=",
|
||
"~",
|
||
"`~!@#$%^&*()_-+={}|[]\\;:'\",<.>/?",
|
||
#if 1
|
||
"Å", // ystart negative with DroidSans
|
||
"A\n\b\nB",
|
||
"Tap Å",
|
||
/* xstart negative */
|
||
"Jap",
|
||
"A\315\241B", /* 'A' + U+0361 + 'B' */
|
||
"\315\241BC", /* '.' + U+0361 + 'B' + 'C' */
|
||
".\315\241BC", /* '.' + U+0361 + 'B' + 'C' */
|
||
".\315\241BC\naaaaa", /* '.' + U+0361 + 'B' + 'C' */
|
||
".aaaaa\n.\315\241BC", /* '.' + U+0361 + 'B' + 'C' */
|
||
|
||
"aaa\n.\315\241BCaa\n.aaa\n.\315\241BCaaaaa", /* '.' + U+0361 + 'B' + 'C' */
|
||
"Tap Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å"
|
||
"Tap Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å"
|
||
"Tap Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å Å",
|
||
#endif
|
||
"+", "2", ")", "|",
|
||
"a\tsdfsad.f..| I V I A AV A V D \n F G H ",
|
||
"é ê è à â ô î ï fi if ñ ç Ã Â",
|
||
|
||
|
||
"Kl1AqvJAUOOKzdjpGTteM775hTYEuqvV b3EU0RZ88JIAMRVS7rMbyKsF1xMg9RTe",
|
||
"CGOXraiYCL44XSlvqx825GvZT3HQYXNQcVNjgzrccX1eUar8nG0FZ3MsYdB5caGqiG7l7RJCyNZFRUVQ8rEVnc0TJVrY3ef4v8miQpVvYswTjjZKTZLwwFxLbsHhaDQ3",
|
||
"7I8DRXPfbKUIl6SH5V6Twqw6mzEzTlDf",
|
||
"JJsSGv1EA MpN9FIctQxi9D iHgEQZe2Wg",
|
||
"xqKyuaT8H2xmySzWdbo wgMZ4Sp2BLUGj",
|
||
"hUEKUunoouIjw6Cu jdXnPkQzMNGG7U8u",
|
||
"4GDEgeCgEXwxoszBpriddAibgbhh36Vz",
|
||
"FdkAi hx8B3QvmjFXovy64TzYwaZ0uoW8",
|
||
"zAcp1V4PmI5dBv wtnbHqN1ISyrXB7P32",
|
||
"lJq5w9GNhpqveQ67kxyQlgAwgQz1AAj3",
|
||
"yi0jssXmCMjnFjl2rWs0rNIx51iVNLoI",
|
||
"HT1BYxlX3z39XBFEw8JMNwYdWeQrO8h2",
|
||
"aQmJI2hUruwhqvJeWL3 gZCGAZ09q67nR",
|
||
"rxGWF OPfQdxUR0cYRenCccz5XgSpTDqf",
|
||
"4NI1L2KbwybObecSDAAgb0K00oCEkf3E",
|
||
"heBlACb AfcK9G85Gl6mBpBUiblc81FSe",
|
||
"GwWx6pHvWyvxSu82PbJbZI UNwx9JSATu",
|
||
"AFCQd25jnbBJ7LBbaXI3I5IeSwDXqME6",
|
||
"lzSqw9t7hJ03AkTjWWUyd3KqrnGAvPJg",
|
||
"pxwCKuWxUOrIMvqXGL 5fbibttAPNIJFC",
|
||
"Fs6sFtGnRezLttwm8AbSKsuvLGbcqFbZ",
|
||
"hEdVvdwWDwsDA23dX0NjDqzYEaURRC7a",
|
||
"IBrdiqo3g0tj LkXz1a45DJD52tO8FJSw",
|
||
"h5QYsL9S1cfsWzTyyFJ6Npq7vLi1tjEX",
|
||
"zhUkVyCPdhWspT9kBQpOmmREmSU6GPW3",
|
||
"Ud1ih3stL5nq00PJMRoA1Zd1QJi0mOzj",
|
||
"iVppAFr5pGYa4oT8OozDi0oqGvqJg3Eg",
|
||
"YC9YUpKq95nIe7D3ckdc6Yy1cEmmuqf1",
|
||
"pzmZvs5j77aVaXXnPqzcuU9fW4Kfmiv5",
|
||
"04ifd9OyA5XGsLTovRo04MnIKToW9Qu3",
|
||
"iDJcbD5si6xPRcPRBEVeEhcJSs7n65SD",
|
||
"a4oZMmgJQAa72o6sllH4n0zfJE5H0HlA",
|
||
"5eSVmFkJMmPCRKdTZRJeuW71uhprmYHp",
|
||
"LcnSHbxguPfqPNhdDR4XDc2qv01Q4Y1Y",
|
||
"H3wT59MiQmEBZ7tYGMt1xMUu7wajECo6",
|
||
"JNGUtcQz660ApgN54rk2UzpqWimO25Cy",
|
||
"ss887dpFwjPaqAg53K6qZnc1NFiXc9WX",
|
||
"y9Th4vRk1jSpKlzB5soK66ckzl3USZq6",
|
||
"WGWY5YmWhaA5oKCoDmRA3n82XwclqvSP",
|
||
"hvlSZ6jE2BU9ImjUjQiY255GA5ASfUUx",
|
||
"e9o4tBCA9TCpilOI05UyHzes6s8lP9lQ",
|
||
"gJyC26gZsCKR8wSp9kNMYKJRRgA3u45U1DWdzPCWv1SUEKi3Wdo3zNFTWiMcCfcl5A0MzOhbqRee7OP13NruY WP0ufGiB4W9RBWqgSy7umnE6puTyCc9WhPOzdLz168BhQwYetZkADWibObi8jcYajuUv54zxXkXQwC1B8lAi8rIH9lmIy0G10fQ832HKiLx"
|
||
};
|
||
static const int test_strings_count = SDL_arraysize(test_strings);
|
||
static const char *font_path = NULL;
|
||
|
||
static TTF_Font *font = NULL;
|
||
static int iter = 0, sum = 0;
|
||
|
||
static void quit(const char *msg)
|
||
{
|
||
SDL_Log("ERROR: %s", msg);
|
||
SDL_Log("SDL_GetError: %s", SDL_GetError());
|
||
exit(1);
|
||
}
|
||
|
||
static void random_input(void);
|
||
|
||
static int wait_for_input(void)
|
||
{
|
||
int done = 0;
|
||
SDL_Event event;
|
||
|
||
while (!done) {
|
||
if (!SDL_WaitEvent(&event)) {
|
||
quit("Event handling");
|
||
}
|
||
|
||
switch (event.type) {
|
||
case SDL_EVENT_KEY_DOWN:
|
||
if (event.key.key == SDLK_F1) {
|
||
help();
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_SPACE) {
|
||
iter++;
|
||
sum++;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_BACKSPACE) {
|
||
iter--;
|
||
sum++;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_DOWN) {
|
||
curr_size -= 1;
|
||
if (curr_size < -1) curr_size = -1;
|
||
done = 1;
|
||
SDL_Log("size: %d", curr_size);
|
||
}
|
||
if (event.key.key == SDLK_UP) {
|
||
curr_size += 1;
|
||
done = 1;
|
||
SDL_Log("size: %d", curr_size);
|
||
}
|
||
if (event.key.key == SDLK_C) {
|
||
curr_font -= 1;
|
||
if (curr_font < 0) curr_font = 0;
|
||
done = 1;
|
||
SDL_Log("Switch to font %s", test_fonts[curr_font]);
|
||
}
|
||
if (event.key.key == SDLK_V) {
|
||
curr_font += 1;
|
||
done = 1;
|
||
if (curr_font >= test_fonts_count) curr_font = test_fonts_count - 1;
|
||
SDL_Log("Switch to font %s", test_fonts[curr_font]);
|
||
}
|
||
|
||
if (event.key.key == SDLK_O) {
|
||
outline -= 1;
|
||
if (outline < -1) outline = -1;
|
||
done = 1;
|
||
SDL_Log("outline: %d", outline);
|
||
}
|
||
if (event.key.key == SDLK_P) {
|
||
outline += 1;
|
||
done = 1;
|
||
SDL_Log("outline: %d", outline);
|
||
}
|
||
if (event.key.key == SDLK_Q) {
|
||
wrap_size -= 1;
|
||
done = 1;
|
||
SDL_Log("wrap_size: %d", wrap_size);
|
||
}
|
||
if (event.key.key == SDLK_A) {
|
||
w_align += 1;
|
||
if (w_align == 3) w_align = 0;
|
||
done = 1;
|
||
SDL_Log("wrap_align: %d", w_align);
|
||
}
|
||
if (event.key.key == SDLK_E) {
|
||
wrap_size += 1;
|
||
done = 1;
|
||
SDL_Log("wrap_size: %d", wrap_size);
|
||
}
|
||
if (event.key.key == SDLK_I) {
|
||
int s = TTF_STYLE_ITALIC;
|
||
SDL_Log("italic %s", (font_style & s) ? "removed" : "added");
|
||
font_style ^= s;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_B) {
|
||
int s = TTF_STYLE_BOLD;
|
||
SDL_Log("bold %s", (font_style & s) ? "removed" : "added");
|
||
font_style ^= s;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_U) {
|
||
int s = TTF_STYLE_UNDERLINE;
|
||
SDL_Log("underline %s", (font_style & s) ? "removed" : "added");
|
||
font_style ^= s;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_S) {
|
||
int s = TTF_STYLE_STRIKETHROUGH;
|
||
SDL_Log("strike-through %s", (font_style & s) ? "removed" : "added");
|
||
font_style ^= s;
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_K) {
|
||
done = 1;
|
||
kerning ^= 1;
|
||
if (kerning) {
|
||
SDL_Log("kerning allowed");
|
||
} else {
|
||
SDL_Log("kerning removed");
|
||
}
|
||
}
|
||
if (event.key.key == SDLK_W) {
|
||
done = 1;
|
||
wrap ^= 1;
|
||
if (wrap) {
|
||
SDL_Log("wrap allowed");
|
||
} else {
|
||
SDL_Log("wrap removed");
|
||
}
|
||
}
|
||
if (event.key.key == SDLK_F) {
|
||
done = 1;
|
||
sdf ^= 1;
|
||
if (sdf) {
|
||
SDL_Log("SDF allowed");
|
||
} else {
|
||
SDL_Log("SDF removed");
|
||
}
|
||
}
|
||
if (event.key.key == SDLK_T) {
|
||
done = 1;
|
||
print_elapsed_ticks ^= 1;
|
||
if (print_elapsed_ticks) {
|
||
SDL_Log("print_elapsed_ticks displayed");
|
||
} else {
|
||
SDL_Log("print_elapsed_ticks hidden");
|
||
}
|
||
}
|
||
if (event.key.key == SDLK_D) {
|
||
done = 1;
|
||
update_screen_mode += 1;
|
||
update_screen_mode %= 2;
|
||
|
||
if (update_screen_mode == 0) {
|
||
SDL_Log("texture displayed");
|
||
} else if (update_screen_mode == 1) {
|
||
SDL_Log("texture not displayed");
|
||
}
|
||
}
|
||
if (event.key.key == SDLK_G) {
|
||
done = 1;
|
||
hinting -= 1;
|
||
if (hinting < 0) hinting = 0;
|
||
SDL_Log("hinting: %s", hinting_desc[hinting]);
|
||
}
|
||
if (event.key.key == SDLK_H) {
|
||
done = 1;
|
||
hinting += 1;
|
||
hinting %= hinting_count;
|
||
SDL_Log("hinting: %s", hinting_desc[hinting]);
|
||
}
|
||
if (event.key.key == SDLK_R) {
|
||
done = 1;
|
||
mode_random_test = 1;
|
||
random_cnt = 0;
|
||
SDL_Log("start random test");
|
||
}
|
||
if (event.key.key == SDLK_M) {
|
||
done = 1;
|
||
render_mode += 1;
|
||
render_mode %= render_mode_count;
|
||
render_mode_overwrite = render_mode;
|
||
SDL_Log("render mode: %s", render_mode_desc[render_mode]);
|
||
}
|
||
if (event.key.key == SDLK_X) {
|
||
done = 1;
|
||
textengine_mode += 1;
|
||
textengine_mode %= textengine_count;
|
||
SDL_Log("Text Engine: %s", textengine_desc[textengine_mode]);
|
||
}
|
||
|
||
if (event.key.key == SDLK_N) {
|
||
done = 1;
|
||
direction += 1;
|
||
direction %= direction_count;
|
||
SDL_Log("direction: %s", directions[direction].description);
|
||
}
|
||
if (event.key.key == SDLK_F2) {
|
||
done = 1;
|
||
save_to_bmp = 1;
|
||
}
|
||
if (event.key.key == SDLK_9) {
|
||
done = 1;
|
||
fg_alpha -= 1;
|
||
if (fg_alpha < 0) fg_alpha = 0;
|
||
SDL_Log("color fg alpha = %d", fg_alpha);
|
||
}
|
||
if (event.key.key == SDLK_0) {
|
||
done = 1;
|
||
fg_alpha += 1;
|
||
if (fg_alpha > 255) fg_alpha = 255;
|
||
SDL_Log("color fg alpha = %d", fg_alpha);
|
||
}
|
||
if (event.key.key == SDLK_7) {
|
||
done = 1;
|
||
bg_alpha -= 1;
|
||
if (bg_alpha < 0) bg_alpha = 0;
|
||
SDL_Log("color bg alpha = %d", bg_alpha);
|
||
}
|
||
if (event.key.key == SDLK_8) {
|
||
done = 1;
|
||
bg_alpha += 1;
|
||
if (bg_alpha > 255) bg_alpha = 255;
|
||
SDL_Log("color bg alpha = %d", bg_alpha);
|
||
}
|
||
if (event.key.key == SDLK_6) {
|
||
SDL_Color tmp = textcol;
|
||
textcol = boardcol;
|
||
boardcol = tmp;
|
||
textcol.a = 0;
|
||
boardcol.a = 0;
|
||
SDL_Log("Invert BG / FG color");
|
||
done = 1;
|
||
}
|
||
if (event.key.key == SDLK_3) {
|
||
done = 1;
|
||
textcol.r += 1;
|
||
SDL_Log("color fg: r=%d g=%d b=%d alpha=%d", textcol.r, textcol.g, textcol.b, textcol.a);
|
||
}
|
||
if (event.key.key == SDLK_4) {
|
||
done = 1;
|
||
textcol.g += 1;
|
||
SDL_Log("color fg: r=%d g=%d b=%d alpha=%d", textcol.r, textcol.g, textcol.b, textcol.a);
|
||
}
|
||
if (event.key.key == SDLK_5) {
|
||
done = 1;
|
||
textcol.b += 1;
|
||
SDL_Log("color fg: r=%d g=%d b=%d alpha=%d", textcol.r, textcol.g, textcol.b, textcol.a);
|
||
}
|
||
if (event.key.key == SDLK_2) {
|
||
const char *str[6] = {"Black", "Red", "Green", "Blue", "White", "Gray" };
|
||
background_color += 1;
|
||
if (background_color == 6) background_color = 0;
|
||
SDL_Log("Background color '%s", str[background_color]);
|
||
done = 1;
|
||
}
|
||
|
||
if (event.key.key == SDLK_ESCAPE) {
|
||
SDL_Log("ESC");
|
||
return 1;
|
||
}
|
||
break;
|
||
case SDL_EVENT_QUIT:
|
||
return 1;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
SDL_Window *window = NULL;
|
||
SDL_Texture *text_texture = NULL;
|
||
SDL_Surface *text_surface = NULL;
|
||
SDL_Renderer *renderer = NULL;
|
||
TTF_Text *text_obj = NULL;
|
||
TTF_TextEngine *engine_surface = NULL;
|
||
TTF_TextEngine *engine_renderer = NULL;
|
||
|
||
const int windoww = 640;
|
||
const int windowh = 480;
|
||
const char *text;
|
||
char filename[256];
|
||
char infos[256];
|
||
int replay = 0;
|
||
int t1 = 0, t2 = 0, t_sum;
|
||
Uint64 T1 = 0, T2 = 0, T_sum, T_min;
|
||
int count, count_init;
|
||
|
||
#define INIT_VARS \
|
||
t_sum = 0; \
|
||
T_sum = 0; \
|
||
T_min = 999999999999ULL;\
|
||
count = count_init; \
|
||
|
||
#define START_MEASURE \
|
||
t1 = SDL_GetTicks(); \
|
||
T1 = SDL_GetPerformanceCounter(); \
|
||
|
||
|
||
#define END_MEASURE \
|
||
T2 = SDL_GetPerformanceCounter(); \
|
||
t2 = SDL_GetTicks(); \
|
||
\
|
||
t_sum += (t2 - t1); \
|
||
T_sum += (T2 - T1); \
|
||
T_min = SDL_min(T_min, T2 - T1); \
|
||
|
||
|
||
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||
quit("SDL init failed");
|
||
}
|
||
|
||
if (!TTF_Init()) {
|
||
SDL_Quit();
|
||
quit("SDL_ttf init failed");
|
||
}
|
||
|
||
window = SDL_CreateWindow("", windoww, windowh, 0);
|
||
if (window == NULL) {
|
||
quit("SDL windowdow setup failed");
|
||
}
|
||
|
||
// SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||
// SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles2");
|
||
renderer = SDL_CreateRenderer(window, NULL);
|
||
if (renderer == NULL) {
|
||
quit("SDL renderer setup failed");
|
||
}
|
||
|
||
/* Display help */
|
||
help();
|
||
|
||
|
||
#if 0
|
||
/*****************************************/
|
||
/* Copy a log here to replay a rendering */
|
||
/*********************************** *****/
|
||
|
||
/* FreeType issue with FletcherGothicFLF, size=10 and outline at 9 -> error in FT_Glyph_To_Bitmap(). glyph '=' */
|
||
// replay=1; font_style=0; kerning=0; wrap=0; wrap_size=0; outline=8; curr_size=10; render_mode=0; curr_str=5; curr_font=0;
|
||
// do outline +1 (key p)
|
||
// --> SDL_GetError: Couldn't find glyph
|
||
//
|
||
|
||
/* FreeType issue with font/ITCAvantGardeStd-Demi.ttf glyph='Q' */
|
||
// replay=1; font_style=0; kerning=0; wrap=0; wrap_size=0; outline=0; curr_size=4; render_mode=0; curr_str=27; curr_font=1; hinting=3;
|
||
// do outline +1 (key p)
|
||
// --> SDL_GetError: Couldn't find glyph
|
||
|
||
#endif
|
||
|
||
// color
|
||
// replay=1; font_style=0; kerning=0; wrap=0; wrap_size=354; outline=0; curr_size=7; render_mode=1; curr_str=63; curr_font=1522; hinting=0; fg_alpha=255; // light Blended
|
||
|
||
//replay=1; font_style=15; kerning=0; wrap=1; wrap_size=56; outline=0; curr_size=5; render_mode=1; curr_str=68; curr_font=3007; hinting=0; fg_alpha=128; // mono Blended
|
||
|
||
#if 0
|
||
seed=1641805930; replay=1; font_style=9; kerning=1; sdf=1; wrap=0; wrap_size=661; w_align=2; outline=0; curr_size=20; render_mode=3; curr_str=14; curr_font=1777; hinting=1; fg_alpha=65; // light LCD
|
||
#endif
|
||
|
||
//seed=1673390190; replay=1; font_style=12; kerning=0; sdf=1; wrap=0; wrap_size=91; w_align=0; outline=0; curr_size=16; render_mode=0; curr_str=14; curr_font=1288; hinting=0; fg_alpha=77; // none Solid
|
||
|
||
//seed=1673390190; replay=1; font_style=12; kerning=0; sdf=0; wrap=0; wrap_size=91; w_align=0; outline=0; curr_size=30; render_mode=1; curr_str=14; curr_font=1288; hinting=0; fg_alpha=77; // none Solid
|
||
|
||
//seed=1673390190; replay=1; font_style=9; kerning=1; sdf=0; wrap=1; wrap_size=94; w_align=2; outline=7; curr_size=42; render_mode=1; curr_str=75; curr_font=1997; hinting=1; fg_alpha=90; // light Blended
|
||
|
||
if (replay) {
|
||
SDL_Log("Replay with string _%s_", test_strings[curr_str]);
|
||
}
|
||
|
||
while (1)
|
||
{
|
||
/* Normal mode <space>, try all combination {strings}x{render_mode} and exit
|
||
This updates "render_mode" and "curr_str" */
|
||
if (!mode_random_test && !replay) {
|
||
if (iter <= 0) {
|
||
iter = 0;
|
||
}
|
||
|
||
if (iter >= render_mode_count * test_strings_count) {
|
||
SDL_Log("End of rendering!");
|
||
break;
|
||
} else {
|
||
render_mode = iter / test_strings_count;
|
||
curr_str = iter - test_strings_count * render_mode;
|
||
}
|
||
}
|
||
|
||
if (render_mode_overwrite) {
|
||
render_mode = render_mode_overwrite;
|
||
}
|
||
|
||
|
||
textcol.a = fg_alpha;
|
||
boardcol.a = bg_alpha;
|
||
|
||
/* Set all parameters coming from random or user input */
|
||
#if 0
|
||
/* Force a parameter */
|
||
curr_font = 1250;
|
||
curr_size = 1;
|
||
curr_size &=0x3;
|
||
#endif
|
||
|
||
#if 0
|
||
/* From a specific seed, jump to a specific iteration */
|
||
{
|
||
static int skip = 1046;
|
||
if (skip) {
|
||
skip--;
|
||
goto next_loop;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
if (saved_curr_font != curr_font) {
|
||
if (font) {
|
||
TTF_CloseFont(font);
|
||
}
|
||
saved_curr_font = curr_font;
|
||
saved_curr_size = curr_size;
|
||
font_path = test_fonts[curr_font];
|
||
SDL_Log("TTF_OpenFont: %s", font_path);
|
||
font = TTF_OpenFont(font_path, (float)curr_size);
|
||
if (!font) {
|
||
#if 1
|
||
quit("Font load failed");
|
||
#else
|
||
SDL_Log("Font load failed");
|
||
saved_curr_font = -1;
|
||
goto next_loop;
|
||
#endif
|
||
}
|
||
}
|
||
|
||
if (saved_curr_size != curr_size) {
|
||
#if defined(HAVE_SET_FONT_SIZE_FUNCTION)
|
||
TTF_SetFontSize(font, (float)curr_size);
|
||
#else
|
||
if (font) {
|
||
TTF_CloseFont(font);
|
||
}
|
||
font_path = test_fonts[curr_font];
|
||
SDL_Log("Re-TTF_OpenFont: %s to change size from %d to %d", font_path, saved_curr_size, curr_size);
|
||
font = TTF_OpenFont(font_path, curr_size);
|
||
if (!font) {
|
||
#if 1
|
||
quit("Font load failed (2)");
|
||
#else
|
||
SDL_Log("Font load failed (2)");
|
||
saved_curr_font = -1;
|
||
goto next_loop;
|
||
#endif
|
||
|
||
}
|
||
#endif
|
||
saved_curr_size = curr_size;
|
||
}
|
||
|
||
TTF_SetFontDirection(font, directions[direction].value);
|
||
|
||
{
|
||
int tmp;
|
||
tmp = TTF_GetFontOutline(font);
|
||
if (tmp != outline) {
|
||
TTF_SetFontOutline(font, outline);
|
||
}
|
||
tmp = TTF_GetFontStyle(font);
|
||
if (tmp != font_style) {
|
||
TTF_SetFontStyle(font, font_style);
|
||
}
|
||
tmp = TTF_GetFontKerning(font);
|
||
if (tmp != kerning) {
|
||
TTF_SetFontKerning(font, kerning);
|
||
}
|
||
#if defined(HAVE_SDF)
|
||
tmp = TTF_GetFontSDF(font);
|
||
if (tmp != sdf) {
|
||
TTF_SetFontSDF(font, sdf);
|
||
}
|
||
#endif
|
||
|
||
{
|
||
// static const char *hinting_desc[] = { "normal", "light", "light_subpix", "mono", "none" };
|
||
// static const char *hinting_desc[] = { "normal", "light", "light_subpix", "lcd_subpix", "mono", "none" };
|
||
int h = 0;
|
||
if (hinting == 0) h = TTF_HINTING_NORMAL;
|
||
if (hinting == 1) h = TTF_HINTING_LIGHT;
|
||
if (hinting == 2) h = 4; // TTF_HINTING_LIGHT_SUBPIXEL;
|
||
// if (hinting == 3) h = 5; // TTF_HINTING_LCD_SUBPIXEL;
|
||
if (hinting == 3) h = TTF_HINTING_MONO;
|
||
if (hinting == 4) h = TTF_HINTING_NONE;
|
||
tmp = TTF_GetFontHinting(font);
|
||
if (tmp != h) {
|
||
TTF_SetFontHinting(font, h);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* Get some console output out in case we crash next... */
|
||
if (! mode_random_test) {
|
||
char title[1024];
|
||
SDL_snprintf(title, sizeof(title) - 1, "%s Sz=%d outline=%d Hinting=%s %s",
|
||
render_mode_desc[render_mode],
|
||
curr_size,
|
||
outline,
|
||
hinting_desc[hinting],
|
||
testapp_basename(font_path));
|
||
|
||
if (save_to_bmp) {
|
||
SDL_snprintf(filename, sizeof(filename) - 1 ,
|
||
"Render=%s_size=%d_outline=%d_wrap=%d_wrap_size=%d_kerning=%d_sdf=%d_italic=%d_bold=%d_underline=%d_strikethrough=%d_hinting=%s_%s__%" SDL_PRIs64 ".bmp",
|
||
render_mode_desc[render_mode],
|
||
curr_size,
|
||
outline,
|
||
wrap,
|
||
wrap_size,
|
||
kerning,
|
||
sdf,
|
||
!!(font_style & TTF_STYLE_ITALIC),
|
||
!!(font_style & TTF_STYLE_BOLD),
|
||
!!(font_style & TTF_STYLE_UNDERLINE),
|
||
!!(font_style & TTF_STYLE_STRIKETHROUGH),
|
||
hinting_desc[hinting],
|
||
testapp_basename(font_path),
|
||
(Sint64)time(NULL)
|
||
);
|
||
}
|
||
|
||
SDL_snprintf(infos, sizeof(infos) - 1 ,
|
||
"Render=%s size=%d outline=%d wrap=%d wrap_size=%d kerning=%d sdf=%d italic=%d bold=%d underline=%d strikethrough=%d hinting=%s %s",
|
||
render_mode_desc[render_mode],
|
||
curr_size,
|
||
outline,
|
||
wrap,
|
||
wrap_size,
|
||
kerning,
|
||
sdf,
|
||
!!(font_style & TTF_STYLE_ITALIC),
|
||
!!(font_style & TTF_STYLE_BOLD),
|
||
!!(font_style & TTF_STYLE_UNDERLINE),
|
||
!!(font_style & TTF_STYLE_STRIKETHROUGH),
|
||
hinting_desc[hinting],
|
||
font_path
|
||
);
|
||
SDL_SetWindowTitle(window, title);
|
||
SDL_Log("%s", infos);
|
||
#if 0
|
||
SDL_Log("font_style=%d; kerning=%d; wrap=%d; wrap_size=%d; outline=%d; curr_size=%d; render_mode=%d; curr_str=%d; curr_font=%d; hinting=%d;",
|
||
font_style, kerning, wrap, wrap_size, outline, curr_size, render_mode, curr_str, curr_font, hinting);
|
||
#endif
|
||
}
|
||
|
||
/* pick a string */
|
||
text = test_strings[curr_str];
|
||
|
||
/* Skip some string with no chars (all index == 0), zero advance and so zero width at low size
|
||
* That would fail to render because of size 0.
|
||
* */
|
||
{
|
||
int w = 0, h = 0;
|
||
#if defined(HAVE_SDF)
|
||
/* SDF change the str size. if we dont render with it (eg not blended mode).
|
||
* then set it to 0.
|
||
* otherwse it reports a valid size.
|
||
* but the texture isn't renderered.
|
||
*/
|
||
if (render_mode != 1) {
|
||
int tmp = TTF_GetFontSDF(font);
|
||
if (tmp != 0) {
|
||
|
||
TTF_SetFontSDF(font, 0);
|
||
}
|
||
}
|
||
#endif
|
||
if (!TTF_GetStringSize(font, text, 0, &w, &h)) {
|
||
SDL_Log("size failed");
|
||
}
|
||
if (w == 0) {
|
||
SDL_Log("skip size == 0");
|
||
goto next_loop;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
if (textengine_mode != 0) {
|
||
|
||
if (!engine_surface) {
|
||
engine_surface = TTF_CreateSurfaceTextEngine();
|
||
if (!engine_surface) {
|
||
SDL_Log("Couldn't create surface text engine: %s", SDL_GetError());
|
||
}
|
||
}
|
||
|
||
if (!engine_renderer) {
|
||
engine_renderer = TTF_CreateRendererTextEngine(renderer);
|
||
if (!engine_renderer) {
|
||
SDL_Log("Couldn't create renderer text engine: %s", SDL_GetError());
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
count_init = print_elapsed_ticks ? 500 : 1;
|
||
INIT_VARS
|
||
|
||
/* render */
|
||
if (wrap == 0) {
|
||
while (count--) {
|
||
if (text_surface) {
|
||
SDL_DestroySurface(text_surface);
|
||
text_surface = NULL;
|
||
}
|
||
|
||
if (text_obj) {
|
||
TTF_DestroyText(text_obj);
|
||
text_obj = NULL;
|
||
}
|
||
|
||
|
||
if (textengine_mode == 0) {
|
||
|
||
switch (render_mode) {
|
||
case 0:
|
||
text_surface = TTF_RenderText_Solid(font, text, 0, textcol);
|
||
break;
|
||
case 1:
|
||
text_surface = TTF_RenderText_Blended(font, text, 0, textcol);
|
||
break;
|
||
case 2:
|
||
text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
|
||
break;
|
||
case 3:
|
||
#if defined(HAVE_LCD)
|
||
text_surface = TTF_RenderText_LCD(font, text, 0, textcol, boardcol);
|
||
#else
|
||
text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
|
||
#endif
|
||
break;
|
||
}
|
||
} else if (textengine_mode == 1) {
|
||
text_obj = TTF_CreateText(engine_surface, font, text, 0);
|
||
} else {
|
||
text_obj = TTF_CreateText(engine_renderer, font, text, 0);
|
||
}
|
||
|
||
if (text_surface) {
|
||
SDL_DestroySurface(text_surface);
|
||
text_surface = NULL;
|
||
}
|
||
|
||
if (text_obj) {
|
||
TTF_DestroyText(text_obj);
|
||
text_obj = NULL;
|
||
}
|
||
|
||
|
||
|
||
if (print_elapsed_ticks) {
|
||
START_MEASURE
|
||
}
|
||
|
||
if (textengine_mode == 0) {
|
||
switch (render_mode) {
|
||
case 0:
|
||
text_surface = TTF_RenderText_Solid(font, text, 0, textcol);
|
||
break;
|
||
case 1:
|
||
text_surface = TTF_RenderText_Blended(font, text, 0, textcol);
|
||
break;
|
||
case 2:
|
||
text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
|
||
break;
|
||
case 3:
|
||
#if defined(HAVE_LCD)
|
||
text_surface = TTF_RenderText_LCD(font, text, 0, textcol, boardcol);
|
||
#else
|
||
text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
|
||
#endif
|
||
break;
|
||
}
|
||
} else if (textengine_mode == 1) {
|
||
text_obj = TTF_CreateText(engine_surface, font, text, 0);
|
||
} else {
|
||
text_obj = TTF_CreateText(engine_renderer, font, text, 0);
|
||
}
|
||
|
||
|
||
|
||
if (print_elapsed_ticks) {
|
||
END_MEASURE
|
||
}
|
||
}
|
||
} else {
|
||
|
||
#if defined(HAVE_WRAP_ALIGN)
|
||
TTF_SetFontWrapAlignment(font, w_align);
|
||
#endif
|
||
|
||
|
||
while (count--) {
|
||
if (text_surface) {
|
||
SDL_DestroySurface(text_surface);
|
||
text_surface = NULL;
|
||
}
|
||
|
||
if (text_obj) {
|
||
TTF_DestroyText(text_obj);
|
||
text_obj = NULL;
|
||
}
|
||
|
||
if (print_elapsed_ticks) {
|
||
START_MEASURE
|
||
}
|
||
|
||
if (textengine_mode == 0) {
|
||
switch (render_mode) {
|
||
case 0:
|
||
text_surface = TTF_RenderText_Solid_Wrapped(font, text, 0, textcol, wrap_size);
|
||
break;
|
||
case 1:
|
||
text_surface = TTF_RenderText_Blended_Wrapped(font, text, 0, textcol, wrap_size);
|
||
break;
|
||
case 2:
|
||
text_surface = TTF_RenderText_Shaded_Wrapped(font, text, 0, textcol, boardcol, wrap_size);
|
||
break;
|
||
case 3:
|
||
#if defined(HAVE_LCD)
|
||
text_surface = TTF_RenderText_LCD_Wrapped(font, text, 0, textcol, boardcol, wrap_size);
|
||
#else
|
||
text_surface = TTF_RenderText_Shaded_Wrapped(font, text, 0, textcol, boardcol, wrap_size);
|
||
#endif
|
||
break;
|
||
}
|
||
} else if (textengine_mode == 1) {
|
||
text_obj = TTF_CreateText(engine_surface, font, text, 0);
|
||
TTF_SetTextWrapWidth(text_obj, wrap_size);
|
||
} else {
|
||
text_obj = TTF_CreateText(engine_renderer, font, text, 0);
|
||
TTF_SetTextWrapWidth(text_obj, wrap_size);
|
||
}
|
||
|
||
if (print_elapsed_ticks) {
|
||
END_MEASURE
|
||
}
|
||
}
|
||
}
|
||
|
||
if (print_elapsed_ticks) {
|
||
SDL_Log("Avg: %7lg ms Avg Perf: %7" SDL_PRIu64 " (min=%7" SDL_PRIu64 ")", (double)t_sum / (double)count_init, T_sum / count_init, T_min);
|
||
}
|
||
|
||
if (textengine_mode == 0) {
|
||
if (text_surface == NULL && render_mode == 1 && sdf == 1) {
|
||
// sometimes SDF has glyph not found ?? FT issue ?
|
||
SDL_Log("BLENDED/SDF not rendered--> %s", SDL_GetError());
|
||
goto next_loop;
|
||
} else if (text_surface == NULL && render_mode == 3) {
|
||
SDL_Log("LCD not rendered--> %s", SDL_GetError());
|
||
goto next_loop;
|
||
} else if (text_surface == NULL) {
|
||
goto finish;
|
||
}
|
||
} else {
|
||
if (text_obj == NULL) {
|
||
goto finish;
|
||
}
|
||
}
|
||
|
||
|
||
/* update_screen */
|
||
if (save_to_bmp) {
|
||
save_to_bmp = 0;
|
||
SDL_Log("Saving to %s", filename);
|
||
SDL_SaveBMP(text_surface, filename);
|
||
}
|
||
|
||
if (update_screen_mode == 1) {
|
||
/* No display */
|
||
} else if (update_screen_mode == 0) {
|
||
/* Normal texture */
|
||
|
||
if (background_color == 0) SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||
if (background_color == 1) SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
|
||
if (background_color == 2) SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
|
||
if (background_color == 3) SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
|
||
if (background_color == 4) SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
|
||
if (background_color == 5) SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255);
|
||
|
||
SDL_RenderClear(renderer);
|
||
|
||
if (textengine_mode == 0) {
|
||
text_texture = SDL_CreateTextureFromSurface(renderer, text_surface);
|
||
if (text_texture == NULL) {
|
||
SDL_Log("Cannot create texture from surface(w=%d h=%d): %s", text_surface->w, text_surface->h, SDL_GetError());
|
||
} else {
|
||
SDL_Rect dstrect;
|
||
dstrect.x = windoww/2 - text_surface->w/2;
|
||
dstrect.y = windowh/2 - text_surface->h/2;
|
||
dstrect.w = text_surface->w;
|
||
dstrect.h = text_surface->h;
|
||
{
|
||
SDL_FRect d;
|
||
d.x = (float)dstrect.x;
|
||
d.y = (float)dstrect.y;
|
||
d.w = (float)dstrect.w;
|
||
d.h = (float)dstrect.h;
|
||
SDL_RenderTexture(renderer, text_texture, NULL, &d);
|
||
}
|
||
SDL_RenderPresent(renderer);
|
||
|
||
SDL_DestroyTexture(text_texture);
|
||
}
|
||
} else if (textengine_mode == 1) {
|
||
SDL_Surface *window_surface = SDL_GetWindowSurface(window);
|
||
int w, h;
|
||
int x, y;
|
||
TTF_GetTextSize(text_obj, &w, &h);
|
||
|
||
x = windoww/2 - w/2;
|
||
y = windowh/2 - h/2;
|
||
|
||
SDL_ClearSurface(window_surface, 0, 0, 0, 0);
|
||
|
||
TTF_DrawSurfaceText(text_obj, x, y, window_surface);
|
||
|
||
SDL_UpdateWindowSurface(window);
|
||
|
||
} else {
|
||
int w, h;
|
||
float x, y;
|
||
TTF_GetTextSize(text_obj, &w, &h);
|
||
|
||
x = windoww/2.0f - w/2.0f;
|
||
y = windowh/2.0f - h/2.0f;
|
||
|
||
TTF_DrawRendererText(text_obj, x, y);
|
||
SDL_RenderPresent(renderer);
|
||
}
|
||
}
|
||
|
||
if (text_surface) {
|
||
SDL_DestroySurface(text_surface);
|
||
text_surface = NULL;
|
||
}
|
||
|
||
if (text_obj) {
|
||
TTF_DestroyText(text_obj);
|
||
text_obj = NULL;
|
||
}
|
||
|
||
|
||
|
||
|
||
next_loop:
|
||
|
||
if (mode_random_test == 0) {
|
||
if (wait_for_input() > 0) {
|
||
break;
|
||
}
|
||
} else {
|
||
random_input();
|
||
}
|
||
}
|
||
|
||
finish:
|
||
|
||
SDL_Log("SDL_GetError: %s", SDL_GetError());
|
||
SDL_Log("cleanup");
|
||
if (font) {
|
||
TTF_CloseFont(font);
|
||
}
|
||
|
||
if (engine_surface) {
|
||
TTF_DestroySurfaceTextEngine(engine_surface);
|
||
}
|
||
|
||
if (engine_renderer) {
|
||
TTF_DestroyRendererTextEngine(engine_renderer);
|
||
}
|
||
|
||
SDL_DestroyRenderer(renderer);
|
||
SDL_DestroyWindow(window);
|
||
|
||
SDL_Log("SDL_GetError: %s", SDL_GetError());
|
||
TTF_Quit();
|
||
SDL_Quit();
|
||
SDL_Log("SDL_GetError: %s", SDL_GetError());
|
||
|
||
return 0;
|
||
}
|
||
|
||
/* random in [0; n - 1] */
|
||
static int rand_n(int n) {
|
||
return (rand() % n);
|
||
}
|
||
|
||
static void init_rand(void)
|
||
{
|
||
static int once = 0;
|
||
if (once == 0) {
|
||
once = 1;
|
||
/* Let's display the seed if we need to play the test again */
|
||
if (seed == 0) {
|
||
seed = time(NULL);
|
||
SDL_Log("seed %d", seed);
|
||
} else {
|
||
SDL_Log("re-use seed %d", seed);
|
||
}
|
||
srand(seed);
|
||
}
|
||
}
|
||
|
||
static void random_input(void)
|
||
{
|
||
SDL_Event event;
|
||
int r;
|
||
int r0, r1, r2, r3, r4, r5, r6, r7, r8, r9;
|
||
int r10, r11, r12, r13, r14, r15, r16, r17, r18, r19;
|
||
int r20;
|
||
|
||
init_rand();
|
||
|
||
while (SDL_PollEvent(&event) == 1) {
|
||
if (event.type == SDL_EVENT_KEY_DOWN) {
|
||
mode_random_test = 0;
|
||
SDL_Log("stop random test");
|
||
return;
|
||
}
|
||
}
|
||
|
||
random_cnt++;
|
||
|
||
font_style = 0;
|
||
|
||
r = rand();
|
||
r0 = !!(r & (1<<0));
|
||
r1 = !!(r & (1<<1));
|
||
r2 = !!(r & (1<<2));
|
||
r3 = !!(r & (1<<3));
|
||
r4 = !!(r & (1<<4));
|
||
r5 = !!(r & (1<<5));
|
||
r6 = !!(r & (1<<6));
|
||
r7 = !!(r & (1<<7));
|
||
r8 = !!(r & (1<<8));
|
||
r9 = !!(r & (1<<9));
|
||
r10 = !!(r & (1<<10));
|
||
r11 = !!(r & (1<<11));
|
||
r12 = !!(r & (1<<12));
|
||
r13 = !!(r & (1<<13));
|
||
r14 = !!(r & (1<<14));
|
||
r15 = !!(r & (1<<15));
|
||
r16 = !!(r & (1<<16));
|
||
r17 = !!(r & (1<<17));
|
||
r18 = !!(r & (1<<18));
|
||
r19 = !!(r & (1<<19));
|
||
r20 = !!(r & (1<<20));
|
||
|
||
if (r0) font_style |= TTF_STYLE_UNDERLINE;
|
||
if (r1) font_style |= TTF_STYLE_STRIKETHROUGH;
|
||
if (r2) font_style |= TTF_STYLE_BOLD;
|
||
if (r3) font_style |= TTF_STYLE_ITALIC;
|
||
|
||
kerning = r4;
|
||
|
||
wrap = r5;
|
||
|
||
/* wrap size: change less often, arbitrary distribution */
|
||
if (wrap) {
|
||
if (r6) {
|
||
wrap_size = rand_n(200);
|
||
} else if (r7) {
|
||
wrap_size = rand_n(400);
|
||
} else if (r8) {
|
||
wrap_size = rand_n(800);
|
||
} else {
|
||
wrap_size = rand_n(2000);
|
||
}
|
||
|
||
w_align = rand_n(3);
|
||
}
|
||
|
||
/* Current Outline: change less often, arbitrary distribution */
|
||
if (r9) {
|
||
outline = 0;
|
||
} else {
|
||
if (r10) {
|
||
outline = rand_n(10);
|
||
} else {
|
||
outline = rand_n(150);
|
||
}
|
||
}
|
||
|
||
/* Current Size: change less often, arbitrary distribution */
|
||
if (r11 && r12 && r13) {
|
||
if (r14) {
|
||
curr_size = rand_n(14);
|
||
} else {
|
||
if (r15) {
|
||
curr_size = rand_n(30);
|
||
} else if (r16) {
|
||
curr_size = rand_n(60);
|
||
} else {
|
||
curr_size = rand_n(200);
|
||
}
|
||
}
|
||
|
||
curr_size += 1; /* don't test size '0' */
|
||
}
|
||
|
||
/* Current Font: change less often */
|
||
if (r17 && r18 && r19) {
|
||
curr_font = rand_n(test_fonts_count);
|
||
}
|
||
|
||
sdf = r20;
|
||
/* using SDF is too slow */
|
||
if (g_force_no_SDF) {
|
||
sdf = 0;
|
||
} else if (sdf) {
|
||
/* also slow ? */
|
||
if (outline >= 4) {
|
||
outline = 4;
|
||
}
|
||
}
|
||
|
||
render_mode = rand_n(render_mode_count);
|
||
|
||
hinting = rand_n(hinting_count);
|
||
|
||
curr_str = rand_n(test_strings_count);
|
||
|
||
fg_alpha = rand_n(256);
|
||
|
||
SDL_Log("%6d] seed=%d; replay=1; font_style=%d; kerning=%d; sdf=%d; wrap=%d; wrap_size=%d; w_align=%d; outline=%d; curr_size=%d; render_mode=%d; curr_str=%d; curr_font=%d; hinting=%d; fg_alpha=%d; // %s %s",
|
||
random_cnt, seed,
|
||
font_style, kerning, sdf,
|
||
wrap, wrap_size, w_align,
|
||
outline, curr_size, render_mode, curr_str, curr_font, hinting,
|
||
fg_alpha,
|
||
hinting_desc[hinting],
|
||
render_mode_desc[render_mode]
|
||
);
|
||
|
||
return;
|
||
}
|