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_SizeUTF8(pstr->font, utf8_texts[count], &ww, &hh) < 0) {
132 do {
134 count++;
135 } while (utf8_texts[count]);
136 log_error("TTF_SizeUTF8() return ERROR!");
137 }
138 w = MAX(w, ww);
139 h += hh;
141 count++;
142 }
143 } else {
144 if (TTF_SizeUTF8(pstr->font, pstr->text, &w, &h) < 0) {
145 log_error("TTF_SizeUTF8() return ERROR!");
146 }
147 }
148
149 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
151 }
152
153 fill->w = w;
154 fill->h = h;
155 } else {
156 fill->w = 0;
157 fill->h = (pstr ? TTF_FontHeight(pstr->font) : 0);
158 }
159}
160
161/**********************************************************************/
164static Uint16 fonto_ptsize(enum font_origin origin)
165{
166 int def;
167
168 switch (origin) {
169 case FONTO_DEFAULT:
170 /* Rely on create_utf8_str() default */
171 return 0;
173 def = ptsize_default();
174 return adj_font(MAX(def + 0, def * 1.1)); /* Same as def, when def < 10 */
175 case FONTO_ATTENTION:
176 def = ptsize_default();
177 return adj_font(MAX(def + 1, def * 1.2));
179 def = ptsize_default();
180 return adj_font(MAX(def + 1, def * 1.2)); /* Same as FONTO_ATTENTION, when def < 10 */
181 case FONTO_HEADING:
182 def = ptsize_default();
183 return adj_font(MAX(def + 2, def * 1.4));
184 case FONTO_BIG:
185 def = ptsize_default();
186 return adj_font(MAX(def + 3, def * 1.6));
187 case FONTO_MAX:
188 def = ptsize_default();
189 return adj_font(MAX(def + 7, def * 2.4));
190 }
191
192 return 0;
193}
194
195/**********************************************************************/
203{
204 utf8_str *str = fc_calloc(1, sizeof(utf8_str));
205
206 if (ptsize == 0) {
207 str->ptsize = ptsize_default();
208 } else {
209 str->ptsize = ptsize;
210 }
211
212 if ((str->font = load_font(str->ptsize)) == NULL) {
213 log_error("create_utf8_str(): load_font() failed");
214 FC_FREE(str);
215
216 return NULL;
217 }
218
219 str->style = TTF_STYLE_NORMAL;
220 str->bgcol = (SDL_Color) {0, 0, 0, 0};
222 str->render = 2;
223
224 /* in_text must be allocated in memory (fc_malloc() / fc_calloc() ) */
225 str->text = in_text;
226 str->n_alloc = n_alloc;
227
228 return str;
229}
230
231/**********************************************************************/
238 enum font_origin origin)
239{
241}
242
243/**********************************************************************/
248{
249 size_t n;
250
253
254 n = (strlen(pchars) + 1);
255
256 if (n > pstr->n_alloc) {
257 /* allocated more if this is only a small increase on before: */
258 size_t n1 = (3 * pstr->n_alloc) / 2;
259
260 pstr->n_alloc = (n > n1) ? n : n1;
261 pstr->text = fc_realloc(pstr->text, pstr->n_alloc);
262 }
263
264 fc_snprintf(pstr->text, pstr->n_alloc, "%s", pchars);
265
266 return pstr;
267}
268
269/**********************************************************************/
273 utf8_str *pstr)
274{
275 SDL_Rect dst_rect = { x, y, 0, 0 };
277
278 if (alphablit(text, NULL, dest, &dst_rect, 255) < 0) {
279 log_error("write_utf8(): couldn't blit text to display: %s",
280 SDL_GetError());
281 FREESURFACE(text);
282
283 return -1;
284 }
285
286 FREESURFACE(text);
287
288 return 0;
289}
290
291/**********************************************************************/
295{
296 SDL_Surface *text = NULL;
297
298 if (pstr == NULL) {
299 return NULL;
300 }
301
302 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
303 TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
304 }
305
306 switch (pstr->render) {
307 case 0:
308 text = TTF_RenderUTF8_Shaded(pstr->font,
309 pstr->text, pstr->fgcol,
310 pstr->bgcol);
311 break;
312 case 1:
313 text = TTF_RenderUTF8_Solid(pstr->font, pstr->text, pstr->fgcol);
314 break;
315 case 2:
316 text = TTF_RenderUTF8_Blended(pstr->font, pstr->text, pstr->fgcol);
317 break;
318 }
319
320 if (text != NULL) {
321 log_debug("create_utf8_surf: Font is generally %d big, and "
322 "string is %d big", TTF_FontHeight(pstr->font), text->h);
323 log_debug("create_utf8_surf: String is %d length", text->w);
324 } else {
325 log_debug("create_utf8_surf: text NULL");
326 text = create_surf(0, 0, SDL_SWSURFACE);
327 }
328
329 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
331 }
332
333 return text;
334}
335
336/**********************************************************************/
340{
341 SDL_Rect des = {0, 0, 0, 0};
342 SDL_Surface *text = NULL, **tmp = NULL;
343 Uint16 i, w = 0, count = 0;
345 char *buf = pstr->text;
347
348 while (utf8_texts[count]) {
349 count++;
350 }
351
352 tmp = fc_calloc(count, sizeof(SDL_Surface *));
353
354 for (i = 0; i < count; i++) {
355 pstr->text = utf8_texts[i];
357
358 /* Find max len */
359 if (tmp[i]->w > w) {
360 w = tmp[i]->w;
361 }
362 }
363
364 pstr->text = buf;
365
366 /* Create and fill surface */
367
368 if (SDL_GetSurfaceColorKey(tmp[0], &color) < 0) {
369 color = SDL_MapRGBA(tmp[0]->format, 0, 0, 0, 0);
370 }
371
372 switch (pstr->render) {
373 case 1:
374 text = create_surf(w, count * tmp[0]->h, SDL_SWSURFACE);
377 break;
378 case 2:
379 text = create_surf_with_format(tmp[0]->format,
380 w, count * tmp[0]->h);
382 break;
383 default:
384 text = create_surf(w, count * tmp[0]->h, SDL_SWSURFACE);
386 break;
387 }
388
389 /* Blit (default: center left) */
390 for (i = 0; i < count; i++) {
391 if (pstr->style & SF_CENTER) {
392 des.x = (w - tmp[i]->w) / 2;
393 } else {
394 if (pstr->style & SF_CENTER_RIGHT) {
395 des.x = w - tmp[i]->w;
396 } else {
397 des.x = 0;
398 }
399 }
400
401 alphablit(tmp[i], NULL, text, &des, 255);
402 des.y += tmp[i]->h;
403 }
404
405
406 /* Free Memory */
407 for (i = 0; i < count; i++) {
409 FREESURFACE(tmp[i]);
410 }
411
412 FC_FREE(tmp);
413
414 return text;
415}
416
417/**********************************************************************/
422{
423 if (pstr != NULL && pstr->text != NULL) {
424 char *current = pstr->text;
425 char c = *(pstr->text);
426
427 /* find '\n' */
428 while (c != '\0') {
429 if (c == '\n') {
431 }
432 current++;
433 c = *current;
434 }
435
436 return create_utf8_surf(pstr);
437 }
438
439 return NULL;
440}
441
442/**********************************************************************/
446{
448 bool converted = FALSE;
449
451 fc_assert_ret_val(pstr->text != NULL, FALSE);
452
454 if (size.w > width) {
455 /* cut string length to w length by replacing space " " with new line "\n" */
456 bool resize = FALSE;
457 int len = 0;
458 char *ptr_rev, *ptr = pstr->text;
459
460 converted = TRUE;
461
462 do {
463 if (!resize) {
464 char utf8char[9];
465 int i;
466 int fw, fh;
467
468 if (*ptr == '\0') {
469 resize = TRUE;
470 continue;
471 }
472
473 if (*ptr == '\n') {
474 len = 0;
475 ptr++;
476 continue;
477 }
478
479 utf8char[0] = ptr[0];
480 for (i = 1; i < 8 && (ptr[i] & (128 + 64)) == 128; i++) {
481 utf8char[i] = ptr[i];
482 }
483 utf8char[i] = '\0';
484 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
485 TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
486 }
487 TTF_SizeUTF8(pstr->font, utf8char, &fw, &fh);
488 if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
490 }
491
492 len += fw;
493
494 if (len > width) {
495 ptr_rev = ptr;
496 while (ptr_rev != pstr->text) {
497 if (*ptr_rev == ' ') {
498 *ptr_rev = '\n';
500 len = 0;
501 break;
502 }
503 if (*ptr_rev == '\n') {
504 resize = TRUE;
505 break;
506 }
507 ptr_rev--;
508 }
509 if (ptr_rev == pstr->text) {
510 resize = TRUE;
511 }
512 }
513
514 ptr += i;
515 } else {
516 if (pstr->ptsize > 8) {
517 change_ptsize_utf8(pstr, pstr->ptsize - 1);
519 } else {
520 log_error("Can't convert string to const width");
521 break;
522 }
523 }
524
525 } while (size.w > width);
526 }
527
528 return converted;
529}
530
531/**********************************************************************/
536{
537 int ptsize;
538 SDL_Surface *text;
539
541
542 ptsize = pstr->ptsize;
545 if (pstr->ptsize != ptsize) {
547 }
548
549 return text;
550}
551
552/**********************************************************************/
556{
557 TTF_Font *buf;
558
559 if (new_ptsize == 0) {
561 }
562
563 if (pstr->ptsize == new_ptsize) {
564 return;
565 }
566
567 if ((buf = load_font(new_ptsize)) == NULL) {
568 log_error("change_ptsize: load_font() failed");
569 return;
570 }
571
572 unload_font(pstr->ptsize);
573 pstr->ptsize = new_ptsize;
574 pstr->font = buf;
575}
576
577/**********************************************************************/
581{
583}
584
585/* =================================================== */
586
587/**********************************************************************/
591{
594
595 /* Find existing font and return pointer to it */
596 if (font_tab != NULL) {
597
598 while (font_tab_tmp != NULL) {
599 if (font_tab_tmp->ptsize == ptsize) {
601
602 return font_tab_tmp->font;
603 }
604
606 }
607 }
608
609 if (!font_with_full_path) {
610 const char *path = theme_font_filename(active_theme);
611
614 }
615
616 /* Load Font */
618 log_error("load_font: Couldn't load %d pt font from %s: %s",
620 return NULL;
621 }
622
623 /* Add new font to list */
624 if (font_tab == NULL) {
625 font_tab_tmp = fc_calloc(1, sizeof(struct ttf_font_chain));
627 } else {
628 /* Go to end of chain */
630 while (font_tab_tmp->next) {
632 }
633
634 font_tab_tmp->next = fc_calloc(1, sizeof(struct ttf_font_chain));
636 }
637
638 font_tab_tmp->ptsize = ptsize;
639 font_tab_tmp->count = 1;
640 font_tab_tmp->font = font_tmp;
641 font_tab_tmp->next = NULL;
642
643 return font_tmp;
644}
645
646/**********************************************************************/
650{
653
654 if (font_tab == NULL) {
655 log_error("unload_font: Trying unload from empty Font ARRAY");
656 return;
657 }
658
659 while (font_tab_tmp != NULL) {
660 if (font_tab_tmp->ptsize == ptsize) {
661 break;
662 }
665 }
666
667 if (font_tab_tmp == NULL) {
668 log_error("unload_font: Trying unload Font which is "
669 "not included in Font ARRAY");
670 return;
671 }
672
673 if (--font_tab_tmp->count > 0) {
674 return;
675 }
676
678 font_tab_tmp->font = NULL;
679
680 if (font_tab_prev == NULL) {
682 } else {
684 }
685
687
689}
690
691/**********************************************************************/
695{
697
699 while (font_tab) {
700 if (font_tab->next) {
703 if (font_tab_tmp->font) {
705 }
707 } else {
708 if (font_tab->font) {
710 }
712 }
713 }
714}
#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:74
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:194
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
#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