Freeciv-3.3
Loading...
Searching...
No Matches
gui_string.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14/***********************************************************************
15 gui_string.c - description
16 -------------------
17 begin : June 30 2002
18 copyright : (C) 2002 by Rafał Bursig
19 email : Rafał Bursig <bursig@poczta.fm>
20***********************************************************************/
21
22#ifdef HAVE_CONFIG_H
23#include <fc_config.h>
24#endif
25
26/* SDL3 */
27#include <SDL3/SDL.h>
28
29/* utility */
30#include "fcintl.h"
31#include "log.h"
32#include "mem.h"
33
34/* client/gui-sdl3 */
35#include "colors.h"
36#include "graphics.h"
37#include "gui_main.h"
38#include "themespec.h"
39#include "utf8string.h"
40
41#include "gui_string.h"
42
43/* =================================================== */
44
45static struct ttf_font_chain {
46 struct ttf_font_chain *next;
48 Uint16 ptsize; /* Size of font */
49 Uint16 count; /* Number of strings alliased with this font */
51
53
55
58
59/* Adjust font sizes on 320x240 screen */
60#ifdef GUI_SDL3_SMALL_SCREEN
61 static int adj_font(int size);
62#else /* GUI_SDL3_SMALL_SCREEN */
63 #define adj_font(size) size
64#endif /* GUI_SDL3_SMALL_SCREEN */
65
66#define ptsize_default() adj_font(default_font_size(active_theme))
67
68/**********************************************************************/
71#ifdef GUI_SDL3_SMALL_SCREEN
72static int adj_font(int size)
73{
74 switch (size) {
75 case 24:
76 return 12;
77 case 20:
78 return 12;
79 case 16:
80 return 10;
81 case 14:
82 return 8;
83 case 13:
84 return 8;
85 case 12:
86 return 8;
87 case 11:
88 return 7;
89 case 10:
90 return 7;
91 case 8:
92 return 6;
93 default:
94 return size;
95 }
96}
97#endif /* GUI_SDL3_SMALL_SCREEN */
98
99/**********************************************************************/
103{
104 if (pstr != NULL && pstr->text != NULL && pstr->text[0] != '\0') {
105 char *current = pstr->text;
106 char c = *current;
107 bool new_line = FALSE;
108 int w, h;
109
110 /* Find '\n' */
111 while (c != '\0') {
112 if (c == '\n') {
113 new_line = TRUE;
114 break;
115 }
116 current++;
117 c = *current;
118 }
119
120 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
121 TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
122 }
123
124 if (new_line) {
125 int ww, hh, count = 0;
127
128 w = 0;
129 h = 0;
130 while (utf8_texts[count]) {
131 if (!TTF_GetStringSize(pstr->font, utf8_texts[count], 0,
132 &ww, &hh)) {
133 do {
135 count++;
136 } while (utf8_texts[count]);
137 log_error("TTF_GetStringSize() return ERROR!");
138 }
139 w = MAX(w, ww);
140 h += hh;
142 count++;
143 }
144 } else {
145 if (!TTF_GetStringSize(pstr->font, pstr->text, 0,
146 &w, &h)) {
147 log_error("TTF_GetStringSize() return ERROR!");
148 }
149 }
150
151 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
153 }
154
155 fill->w = w;
156 fill->h = h;
157 } else {
158 fill->w = 0;
159 fill->h = (pstr ? TTF_GetFontHeight(pstr->font) : 0);
160 }
161}
162
163/**********************************************************************/
166static Uint16 fonto_ptsize(enum font_origin origin)
167{
168 int def;
169
170 switch (origin) {
171 case FONTO_DEFAULT:
172 /* Rely on create_utf8_str() default */
173 return 0;
175 def = ptsize_default();
176 return adj_font(MAX(def + 0, def * 1.1)); /* Same as def, when def < 10 */
177 case FONTO_ATTENTION:
178 def = ptsize_default();
179 return adj_font(MAX(def + 1, def * 1.2));
181 def = ptsize_default();
182 return adj_font(MAX(def + 1, def * 1.2)); /* Same as FONTO_ATTENTION, when def < 10 */
183 case FONTO_HEADING:
184 def = ptsize_default();
185 return adj_font(MAX(def + 2, def * 1.4));
186 case FONTO_BIG:
187 def = ptsize_default();
188 return adj_font(MAX(def + 3, def * 1.6));
189 case FONTO_MAX:
190 def = ptsize_default();
191 return adj_font(MAX(def + 7, def * 2.4));
192 }
193
194 return 0;
195}
196
197/**********************************************************************/
205{
206 utf8_str *str = fc_calloc(1, sizeof(utf8_str));
207
208 if (ptsize == 0) {
209 str->ptsize = ptsize_default();
210 } else {
211 str->ptsize = ptsize;
212 }
213
214 if ((str->font = load_font(str->ptsize)) == NULL) {
215 log_error("create_utf8_str(): load_font() failed");
216 FC_FREE(str);
217
218 return NULL;
219 }
220
221 str->style = TTF_STYLE_NORMAL;
222 str->bgcol = (SDL_Color) {0, 0, 0, 0};
224 str->render = 2;
225
226 /* in_text must be allocated in memory (fc_malloc() / fc_calloc() ) */
227 str->text = in_text;
228 str->n_alloc = n_alloc;
229
230 return str;
231}
232
233/**********************************************************************/
240 enum font_origin origin)
241{
243}
244
245/**********************************************************************/
250{
251 size_t n;
252
255
256 n = (strlen(pchars) + 1);
257
258 if (n > pstr->n_alloc) {
259 /* Allocated more if this is only a small increase on before: */
260 size_t n1 = (3 * pstr->n_alloc) / 2;
261
262 pstr->n_alloc = (n > n1) ? n : n1;
263 pstr->text = fc_realloc(pstr->text, pstr->n_alloc);
264 }
265
266 fc_snprintf(pstr->text, pstr->n_alloc, "%s", pchars);
267
268 return pstr;
269}
270
271/**********************************************************************/
275 utf8_str *pstr)
276{
277 SDL_Rect dst_rect = { x, y, 0, 0 };
279
280 if (alphablit(text, NULL, dest, &dst_rect, 255) < 0) {
281 log_error("write_utf8(): couldn't blit text to display: %s",
282 SDL_GetError());
283 FREESURFACE(text);
284
285 return -1;
286 }
287
288 FREESURFACE(text);
289
290 return 0;
291}
292
293/**********************************************************************/
297{
298 SDL_Surface *text = NULL;
299
300 if (pstr == NULL) {
301 return NULL;
302 }
303
304 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
305 TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
306 }
307
308 switch (pstr->render) {
309 case 0:
310 text = TTF_RenderText_Shaded(pstr->font,
311 pstr->text, 0, pstr->fgcol,
312 pstr->bgcol);
313 break;
314 case 1:
315 text = TTF_RenderText_LCD(pstr->font, pstr->text, 0,
316 pstr->fgcol, pstr->bgcol);
317 break;
318 case 2:
319 text = TTF_RenderText_Blended(pstr->font, pstr->text, 0, pstr->fgcol);
320 break;
321 }
322
323 if (text != NULL) {
324 log_debug("create_utf8_surf: Font is generally %d big, and "
325 "string is %d big",
326 TTF_GetFontHeight(pstr->font), text->h);
327 log_debug("create_utf8_surf: String is %d length", text->w);
328 } else {
329 log_debug("create_utf8_surf: text NULL");
330 text = create_surf(0, 0);
331 }
332
333 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
335 }
336
337 return text;
338}
339
340/**********************************************************************/
344{
345 SDL_Rect des = {0, 0, 0, 0};
346 SDL_Surface *text = NULL, **tmp = NULL;
347 Uint16 i, w = 0, count = 0;
349 char *buf = pstr->text;
351
352 while (utf8_texts[count]) {
353 count++;
354 }
355
356 tmp = fc_calloc(count, sizeof(SDL_Surface *));
357
358 for (i = 0; i < count; i++) {
359 pstr->text = utf8_texts[i];
361
362 /* Find max len */
363 if (tmp[i]->w > w) {
364 w = tmp[i]->w;
365 }
366 }
367
368 pstr->text = buf;
369
370 /* Create and fill surface */
371
372 if (!SDL_GetSurfaceColorKey(tmp[0], &color)) {
374 0, 0, 0, 0);
375 }
376
377 switch (pstr->render) {
378 case 1:
379 text = create_surf(w, count * tmp[0]->h);
381 SDL_SetSurfaceColorKey(text, true, color);
382 break;
383 case 2:
384 text = create_surf_with_format(tmp[0]->format,
385 w, count * tmp[0]->h);
387 break;
388 default:
389 text = create_surf(w, count * tmp[0]->h);
391 break;
392 }
393
394 /* Blit (default: center left) */
395 for (i = 0; i < count; i++) {
396 if (pstr->style & SF_CENTER) {
397 des.x = (w - tmp[i]->w) / 2;
398 } else {
399 if (pstr->style & SF_CENTER_RIGHT) {
400 des.x = w - tmp[i]->w;
401 } else {
402 des.x = 0;
403 }
404 }
405
406 alphablit(tmp[i], NULL, text, &des, 255);
407 des.y += tmp[i]->h;
408 }
409
410
411 /* Free Memory */
412 for (i = 0; i < count; i++) {
414 FREESURFACE(tmp[i]);
415 }
416
417 FC_FREE(tmp);
418
419 return text;
420}
421
422/**********************************************************************/
427{
428 if (pstr != NULL && pstr->text != NULL) {
429 char *current = pstr->text;
430 char c = *(pstr->text);
431
432 /* Find '\n' */
433 while (c != '\0') {
434 if (c == '\n') {
436 }
437 current++;
438 c = *current;
439 }
440
441 return create_utf8_surf(pstr);
442 }
443
444 return NULL;
445}
446
447/**********************************************************************/
451{
453 bool converted = FALSE;
454
456 fc_assert_ret_val(pstr->text != NULL, FALSE);
457
459 if (size.w > width) {
460 /* Cut string length to w length by replacing space " " with new line "\n" */
461 bool resize = FALSE;
462 int len = 0;
463 char *ptr_rev, *ptr = pstr->text;
464
465 converted = TRUE;
466
467 do {
468 if (!resize) {
469 char utf8char[9];
470 int i;
471 int fw, fh;
472
473 if (*ptr == '\0') {
474 resize = TRUE;
475 continue;
476 }
477
478 if (*ptr == '\n') {
479 len = 0;
480 ptr++;
481 continue;
482 }
483
484 utf8char[0] = ptr[0];
485 for (i = 1; i < 8 && (ptr[i] & (128 + 64)) == 128; i++) {
486 utf8char[i] = ptr[i];
487 }
488 utf8char[i] = '\0';
489 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
490 TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
491 }
492 TTF_GetStringSize(pstr->font, utf8char, 0, &fw, &fh);
493 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
495 }
496
497 len += fw;
498
499 if (len > width) {
500 ptr_rev = ptr;
501 while (ptr_rev != pstr->text) {
502 if (*ptr_rev == ' ') {
503 *ptr_rev = '\n';
505 len = 0;
506 break;
507 }
508 if (*ptr_rev == '\n') {
509 resize = TRUE;
510 break;
511 }
512 ptr_rev--;
513 }
514 if (ptr_rev == pstr->text) {
515 resize = TRUE;
516 }
517 }
518
519 ptr += i;
520 } else {
521 if (pstr->ptsize > 8) {
522 change_ptsize_utf8(pstr, pstr->ptsize - 1);
524 } else {
525 log_error("Can't convert string to const width");
526 break;
527 }
528 }
529
530 } while (size.w > width);
531 }
532
533 return converted;
534}
535
536/**********************************************************************/
541{
542 int ptsize;
543 SDL_Surface *text;
544
546
547 ptsize = pstr->ptsize;
550 if (pstr->ptsize != ptsize) {
552 }
553
554 return text;
555}
556
557/**********************************************************************/
561{
562 TTF_Font *buf;
563
564 if (new_ptsize == 0) {
566 }
567
568 if (pstr->ptsize == new_ptsize) {
569 return;
570 }
571
572 if ((buf = load_font(new_ptsize)) == NULL) {
573 log_error("change_ptsize: load_font() failed");
574 return;
575 }
576
577 unload_font(pstr->ptsize);
578 pstr->ptsize = new_ptsize;
579 pstr->font = buf;
580}
581
582/**********************************************************************/
586{
588}
589
590/* =================================================== */
591
592/**********************************************************************/
596{
599
600 /* Find existing font and return pointer to it */
601 if (font_tab != NULL) {
602
603 while (font_tab_tmp != NULL) {
604 if (font_tab_tmp->ptsize == ptsize) {
606
607 return font_tab_tmp->font;
608 }
609
611 }
612 }
613
614 if (!font_with_full_path) {
615 const char *path = theme_font_filename(active_theme);
616
619 }
620
621 /* Load Font */
623 log_error("load_font: Couldn't load %d pt font from %s: %s",
625 return NULL;
626 }
627
628 /* Add new font to list */
629 if (font_tab == NULL) {
630 font_tab_tmp = fc_calloc(1, sizeof(struct ttf_font_chain));
632 } else {
633 /* Go to end of chain */
635 while (font_tab_tmp->next) {
637 }
638
639 font_tab_tmp->next = fc_calloc(1, sizeof(struct ttf_font_chain));
641 }
642
643 font_tab_tmp->ptsize = ptsize;
644 font_tab_tmp->count = 1;
645 font_tab_tmp->font = font_tmp;
646 font_tab_tmp->next = NULL;
647
648 return font_tmp;
649}
650
651/**********************************************************************/
655{
658
659 if (font_tab == NULL) {
660 log_error("unload_font: Trying unload from empty Font ARRAY");
661 return;
662 }
663
664 while (font_tab_tmp != NULL) {
665 if (font_tab_tmp->ptsize == ptsize) {
666 break;
667 }
670 }
671
672 if (font_tab_tmp == NULL) {
673 log_error("unload_font: Trying unload Font which is "
674 "not included in Font ARRAY");
675 return;
676 }
677
678 if (--font_tab_tmp->count > 0) {
679 return;
680 }
681
683 font_tab_tmp->font = NULL;
684
685 if (font_tab_prev == NULL) {
687 } else {
689 }
690
692
694}
695
696/**********************************************************************/
700{
702
704 while (font_tab) {
705 if (font_tab->next) {
708 if (font_tab_tmp->font) {
710 }
712 } else {
713 if (font_tab->font) {
715 }
717 }
718 }
719}
#define n_alloc
Definition astring.c:78
#define str
Definition astring.c:76
#define n
Definition astring.c:77
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:76
SDL_Color * get_theme_color(enum theme_color themecolor)
Definition colors.c:47
SDL_Surface * create_surf_with_format(SDL_PixelFormat *pf, int width, int height, Uint32 flags)
Definition graphics.c:328
int alphablit(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect, unsigned char alpha_mod)
Definition graphics.c:199
SDL_Surface * create_surf(int width, int height, Uint32 flags)
Definition graphics.c:351
#define FREESURFACE(ptr)
Definition graphics.h:322
static TTF_Font * load_font(Uint16 ptsize)
Definition gui_string.c:594
#define ptsize_default()
Definition gui_string.c:70
void change_ptsize_utf8(utf8_str *pstr, Uint16 new_ptsize)
Definition gui_string.c:559
void utf8_str_size(utf8_str *pstr, SDL_Rect *fill)
Definition gui_string.c:106
utf8_str * copy_chars_to_utf8_str(utf8_str *pstr, const char *pchars)
Definition gui_string.c:251
SDL_Surface * create_text_surf_from_utf8(utf8_str *pstr)
Definition gui_string.c:425
void change_fonto_utf8(utf8_str *pstr, enum font_origin origin)
Definition gui_string.c:584
static char * font_with_full_path
Definition gui_string.c:56
void unload_font(Uint16 ptsize)
Definition gui_string.c:653
utf8_str * create_utf8_str(char *in_text, size_t n_alloc, Uint16 ptsize)
Definition gui_string.c:206
utf8_str * create_utf8_str_fonto(char *in_text, size_t n_alloc, enum font_origin origin)
Definition gui_string.c:241
static struct ttf_font_chain * font_tab
int write_utf8(SDL_Surface *dest, Sint16 x, Sint16 y, utf8_str *pstr)
Definition gui_string.c:276
static SDL_Surface * create_utf8_multi_surf(utf8_str *pstr)
Definition gui_string.c:343
bool convert_utf8_str_to_const_surface_width(utf8_str *pstr, int width)
Definition gui_string.c:449
static SDL_Surface * create_utf8_surf(utf8_str *pstr)
Definition gui_string.c:298
void free_font_system(void)
Definition gui_string.c:698
SDL_Surface * create_text_surf_smaller_than_w(utf8_str *pstr, int w)
Definition gui_string.c:539
#define adj_font(size)
Definition gui_string.c:67
static Uint16 fonto_ptsize(enum font_origin origin)
Definition gui_string.c:168
#define SF_CENTER
Definition gui_string.h:40
#define SF_CENTER_RIGHT
Definition gui_string.h:41
font_origin
Definition gui_string.h:64
@ FONTO_HEADING
Definition gui_string.h:69
@ FONTO_DEFAULT
Definition gui_string.h:65
@ FONTO_DEFAULT_PLUS
Definition gui_string.h:66
@ FONTO_BIG
Definition gui_string.h:70
@ FONTO_ATTENTION
Definition gui_string.h:67
@ FONTO_ATTENTION_PLUS
Definition gui_string.h:68
@ FONTO_MAX
Definition gui_string.h:71
@ COLOR_THEME_TEXT
Definition themecolors.h:38
const char * theme_font_filename(const struct theme *t)
Definition themespec.c:169
struct theme * active_theme
Definition themespec.c:154
char ** create_new_line_utf8strs(const char *pstr)
Definition utf8string.c:35
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_debug(message,...)
Definition log.h:116
#define log_error(message,...)
Definition log.h:104
#define fc_calloc(n, esz)
Definition mem.h:38
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
#define fc_realloc(ptr, sz)
Definition mem.h:36
int len
Definition packhand.c:127
#define MAX(x, y)
Definition shared.h:54
size_t size
Definition specvec.h:72
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
Definition colors.h:21
TTF_Font * font
Definition gui_string.c:51
struct ttf_font_chain * next
Definition gui_string.c:50
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47