Author: cazfi
Date: Thu Jan 15 20:59:55 2015
New Revision: 27706

URL: http://svn.gna.org/viewcvs/freeciv?rev=27706&view=rev
Log:
Added set of utility functions for handling utf8 to sdl2-client

See patch #5701

Added:
    trunk/client/gui-sdl2/utf8string.c   (with props)
    trunk/client/gui-sdl2/utf8string.h   (with props)
Modified:
    trunk/client/gui-sdl2/Makefile.am
    trunk/client/gui-sdl2/gui_string.c
    trunk/client/gui-sdl2/gui_string.h

Modified: trunk/client/gui-sdl2/Makefile.am
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-sdl2/Makefile.am?rev=27706&r1=27705&r2=27706&view=diff
==============================================================================
--- trunk/client/gui-sdl2/Makefile.am   (original)
+++ trunk/client/gui-sdl2/Makefile.am   Thu Jan 15 20:59:55 2015
@@ -83,6 +83,8 @@
        themespec.h     \
        unistring.c     \
        unistring.h     \
+       utf8string.c    \
+       utf8string.h    \
        voteinfo_bar.c  \
        voteinfo_bar.h  \
        widget.c        \

Modified: trunk/client/gui-sdl2/gui_string.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-sdl2/gui_string.c?rev=27706&r1=27705&r2=27706&view=diff
==============================================================================
--- trunk/client/gui-sdl2/gui_string.c  (original)
+++ trunk/client/gui-sdl2/gui_string.c  Thu Jan 15 20:59:55 2015
@@ -38,6 +38,7 @@
 #include "gui_main.h"
 #include "themespec.h"
 #include "unistring.h"
+#include "utf8string.h"
 
 #include "gui_string.h"
 
@@ -57,6 +58,9 @@
 
 static SDL_Surface *create_str16_surf(SDL_String16 *pString);
 static SDL_Surface *create_str16_multi_surf(SDL_String16 *pString);
+
+static SDL_Surface *create_utf8_surf(utf8_str *pstr);
+static SDL_Surface *create_utf8_multi_surf(utf8_str *pstr);
 
 /**************************************************************************
   Adjust font sizes for small screen.
@@ -154,6 +158,71 @@
 }
 
 /**************************************************************************
+  Calculate display size of string.
+**************************************************************************/
+SDL_Rect utf8_str_size(utf8_str *pstr)
+{
+  SDL_Rect ret = {0, 0, 0, 0};
+
+  if (pstr != NULL && pstr->text != NULL && pstr->text != '\0') {
+    char *current = pstr->text;
+    char c = *current;
+    bool new_line = FALSE;
+    int w, h;
+
+    /* find '\n' */
+    while (c != '\0') {
+      if (c == '\n') {
+       new_line = TRUE;
+       break;
+      }
+      current++;
+      c = *current;
+    }
+
+    if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+      TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
+    }
+
+    if (new_line) {
+      int ww, hh, count = 0;
+      char **utf8_texts = create_new_line_utf8strs(pstr->text);
+
+      w = 0;
+      h = 0;
+      while (utf8_texts[count]) {
+        if (TTF_SizeUTF8(pstr->font, utf8_texts[count], &ww, &hh) < 0) {
+          do {
+            FC_FREE(utf8_texts[count]);
+            count++;
+          } while (utf8_texts[count]);
+          log_error("TTF_SizeUTF8() return ERROR !");
+        }
+        w = MAX(w, ww);
+        h += hh;
+        FC_FREE(utf8_texts[count]);
+        count++;
+      }
+    } else {
+      if (TTF_SizeUTF8(pstr->font, pstr->text, &w, &h) < 0) {
+        log_error("TTF_SizeUTF8() return ERROR !");
+      }
+    }
+
+    if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+      TTF_SetFontStyle(pstr->font, TTF_STYLE_NORMAL);
+    }
+
+    ret.w = w;
+    ret.h = h;
+  } else {
+    ret.h = (pstr ? TTF_FontHeight(pstr->font) : 0);
+  }
+
+  return ret;
+}
+
+/**************************************************************************
   Create string16 struct with ptsize font.
   Font will be loaded or aliased with existing font of that size.
   pInTextString must be allocated in memory (MALLOC/fc_calloc)
@@ -231,6 +300,27 @@
   }
 
   FREESURFACE(pText);
+  return 0;
+}
+
+/**************************************************************************
+  Blit text to surface.
+**************************************************************************/
+int write_utf8(SDL_Surface *dest, Sint16 x, Sint16 y,
+               utf8_str *pstr)
+{
+  SDL_Rect dst_rect = { x, y, 0, 0 };
+  SDL_Surface *text = create_text_surf_from_utf8(pstr);
+
+  if (alphablit(text, NULL, dest, &dst_rect, 255) < 0) {
+    log_error("write_utf8(): couldn't blit text to display: %s",
+              SDL_GetError());
+    FREESURFACE(text);
+    return -1;
+  }
+
+  FREESURFACE(text);
+
   return 0;
 }
 
@@ -293,6 +383,51 @@
   }
 
   return pText;
+}
+
+/**************************************************************************
+  Create Text Surface from utf8_str
+**************************************************************************/
+static SDL_Surface *create_utf8_surf(utf8_str *pstr)
+{
+  SDL_Surface *text = NULL;
+
+  if (pstr == NULL) {
+    return NULL;
+  }
+
+  if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+    TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
+  }
+
+  switch (pstr->render) {
+  case 0:
+    text = TTF_RenderUTF8_Shaded(pstr->font,
+                                 pstr->text, pstr->fgcol,
+                                 pstr->bgcol);
+    break;
+  case 1:
+    text = TTF_RenderUTF8_Solid(pstr->font, pstr->text, pstr->fgcol);
+    break;
+  case 2:
+    text = TTF_RenderUTF8_Blended(pstr->font, pstr->text, pstr->fgcol);
+    break;
+  }
+
+  if (text != NULL) {
+    log_debug("create_utf8_surf: Font is generally %d big, and "
+              "string is %d big", TTF_FontHeight(pstr->font), text->h);
+    log_debug("create_utf8_surf: String is %d length", text->w);
+  } else {
+    log_debug("create_utf8_surf: text NULL");
+    text = create_surf(0, 0, SDL_SWSURFACE);
+  }
+
+  if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+    TTF_SetFontStyle(pstr->font, TTF_STYLE_NORMAL);
+  }
+
+  return text;
 }
 
 /**************************************************************************
@@ -377,6 +512,85 @@
 }
 
 /**************************************************************************
+  Create surface with multiline text drawn.
+**************************************************************************/
+static SDL_Surface *create_utf8_multi_surf(utf8_str *pstr)
+{
+  SDL_Rect des = {0, 0, 0, 0};
+  SDL_Surface *text = NULL, **tmp = NULL;
+  Uint16 i, w = 0, count = 0;
+  Uint32 color;
+  char *buf = pstr->text;
+  char **utf8_texts = create_new_line_utf8strs(pstr->text);
+
+  while (utf8_texts[count]) {
+    count++;
+  }
+
+  tmp = fc_calloc(count, sizeof(SDL_Surface *));
+
+  for (i = 0; i < count; i++) {
+    pstr->text = utf8_texts[i];
+    tmp[i] = create_utf8_surf(pstr);
+
+    /* find max len */
+    if (tmp[i]->w > w) {
+      w = tmp[i]->w;
+    }
+  }
+
+  pstr->text = buf;
+
+  /* create and fill surface */
+
+  SDL_GetColorKey(tmp[0], &color);
+
+  switch (pstr->render) {
+  case 1:
+    text = create_surf(w, count * tmp[0]->h, SDL_SWSURFACE);
+    SDL_FillRect(text, NULL, color);
+    SDL_SetColorKey(text, SDL_TRUE, color);
+    break;
+  case 2:
+      text = create_surf_with_format(tmp[0]->format,
+                                     w, count * tmp[0]->h, tmp[0]->flags);
+      SDL_FillRect(text, NULL, color);
+    break;
+  default:
+    text = create_surf(w, count * tmp[0]->h, SDL_SWSURFACE);
+    SDL_FillRect(text, NULL, color);
+    break;
+  }
+
+  /* blit (default: center left) */
+  for (i = 0; i < count; i++) {
+    if (pstr->style & SF_CENTER) {
+      des.x = (w - tmp[i]->w) / 2;
+    } else {
+      if (pstr->style & SF_CENTER_RIGHT) {
+       des.x = w - tmp[i]->w;
+      } else {
+       des.x = 0;
+      }
+    }
+
+    alphablit(tmp[i], NULL, text, &des, 255);
+    des.y += tmp[i]->h;
+  }
+
+
+  /* Free Memmory */
+  for (i = 0; i < count; i++) {
+    FC_FREE(utf8_texts[i]);
+    FREESURFACE(tmp[i]);
+  }
+
+  FC_FREE(tmp);
+
+  return text;
+}
+
+/**************************************************************************
   Generic function to create surface with any kind of text, single line or
   multiline, drawn.
 **************************************************************************/
@@ -396,6 +610,31 @@
     }
 
     return create_str16_surf(pString);
+  }
+
+  return NULL;
+}
+
+/**************************************************************************
+  Generic function to create surface with any kind of text, single line or
+  multiline, drawn.
+**************************************************************************/
+SDL_Surface *create_text_surf_from_utf8(utf8_str *pstr)
+{
+  if (pstr != NULL && pstr->text != NULL) {
+    char *current = pstr->text;
+    char c = *(pstr->text);
+
+    /* find '\n' */
+    while (c != '\0') {
+      if (c == '\n') {
+        return create_utf8_multi_surf(pstr);
+      }
+      current++;
+      c = *current;
+    }
+
+    return create_utf8_surf(pstr);
   }
 
   return NULL;
@@ -541,6 +780,87 @@
 }
 
 /**************************************************************************
+  Wrap text to make it fit to given screen width.
+**************************************************************************/
+bool convert_utf8_str_to_const_surface_width(utf8_str *pstr, int width)
+{  
+  int w;
+  bool converted = FALSE;
+
+  fc_assert_ret_val(pstr != NULL, FALSE);
+  fc_assert_ret_val(pstr->text != NULL, FALSE);
+
+  w = utf8_str_size(pstr).w;
+  if (w > width) {
+    /* cut string length to w length by replacing space " " with new line "\n" 
*/
+    bool resize = FALSE;
+    int len = 0, adv;
+    char *ptr_rev, *ptr = pstr->text;
+
+    converted = TRUE;
+
+    do {
+      if (!resize) {
+
+        if (*ptr == '\0') {
+          resize = TRUE;
+          continue;
+        }
+
+        if (*ptr == '\n') {
+          len = 0;
+          ptr++;
+          continue;
+        }
+
+        if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+          TTF_SetFontStyle(pstr->font, (pstr->style & 0x0F));
+        }
+        TTF_GlyphMetrics(pstr->font, *ptr, NULL, NULL, NULL, NULL, &adv);
+        if (!((pstr->style & 0x0F) & TTF_STYLE_NORMAL)) {
+          TTF_SetFontStyle(pstr->font, TTF_STYLE_NORMAL);
+        }
+
+        len += adv;
+
+        if (len > width) {
+          ptr_rev = ptr;
+          while (ptr_rev != pstr->text) {
+            if (*ptr_rev == ' ') {
+              *ptr_rev = '\n';
+              w = utf8_str_size(pstr).w;
+              len = 0;
+              break;
+            }
+            if (*ptr_rev == '\n') {
+              resize = TRUE;
+              break;
+            }
+            ptr_rev--;
+          }
+          if (ptr_rev == pstr->text) {
+            resize = TRUE;
+          }
+        }
+
+        ptr++;
+      } else {
+        if (pstr->ptsize > 8) {
+          change_ptsize_utf8(pstr, pstr->ptsize - 1);
+          w = utf8_str_size(pstr).w;
+        } else {
+          log_error("Can't convert string to const width");
+          break;
+        }
+     }
+
+    } while (w > width);
+  }
+
+  return converted;
+}
+
+/**************************************************************************
   Create surface with text drawn to it. Wrap text as needed to make it
   fit in given width.
 **************************************************************************/
@@ -562,6 +882,27 @@
 }
 
 /**************************************************************************
+  Create surface with text drawn to it. Wrap text as needed to make it
+  fit in given width.
+**************************************************************************/
+SDL_Surface *create_text_surf_smaller_than_w(utf8_str *pstr, int w)
+{
+  int ptsize;
+  SDL_Surface *text;
+
+  fc_assert_ret_val(pstr != NULL, NULL);
+
+  ptsize = pstr->ptsize;
+  convert_utf8_str_to_const_surface_width(pstr, w);
+  text = create_text_surf_from_utf8(pstr);
+  if (pstr->ptsize != ptsize) {
+    change_ptsize_utf8(pstr, ptsize);
+  }
+
+  return text;
+}
+
+/**************************************************************************
   Change font size of text.
 **************************************************************************/
 void change_ptsize16(SDL_String16 *pString, Uint16 new_ptsize)
@@ -580,6 +921,27 @@
   unload_font(pString->ptsize);
   pString->ptsize = new_ptsize;
   pString->font = pBuf;
+}
+
+/**************************************************************************
+  Change font size of text.
+**************************************************************************/
+void change_ptsize_utf8(utf8_str *pstr, Uint16 new_ptsize)
+{
+  TTF_Font *buf;
+
+  if (pstr->ptsize == new_ptsize) {
+    return;
+  }
+
+  if ((buf = load_font(new_ptsize)) == NULL) {
+    log_error("change_ptsize: load_font() failed");
+    return;
+  }
+
+  unload_font(pstr->ptsize);
+  pstr->ptsize = new_ptsize;
+  pstr->font = buf;
 }
 
 /* =================================================== */

Modified: trunk/client/gui-sdl2/gui_string.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-sdl2/gui_string.h?rev=27706&r1=27705&r2=27706&view=diff
==============================================================================
--- trunk/client/gui-sdl2/gui_string.h  (original)
+++ trunk/client/gui-sdl2/gui_string.h  Thu Jan 15 20:59:55 2015
@@ -44,6 +44,17 @@
        SF_CENTER_RIGHT         0x20    - use with multi string, must be > 0x0f
 */
 
+typedef struct utf8_str {
+  Uint8 style;
+  Uint8 render;
+  Uint16 ptsize;
+  size_t n_alloc;  /* total allocated text memory */
+  SDL_Color fgcol;
+  SDL_Color bgcol;
+  TTF_Font *font;
+  char *text;
+} utf8_str;
+
 typedef struct SDL_String16 {
   Uint8 style;
   Uint8 render;
@@ -67,6 +78,15 @@
 SDL_Surface *create_text_surf_smaller_that_w(SDL_String16 *pString, int w);
 SDL_Rect str16size(SDL_String16 *pString16);
 void change_ptsize16(SDL_String16 *pString, Uint16 new_ptsize);
+
+bool convert_utf8_str_to_const_surface_width(utf8_str *pstr,
+                                             int width);
+int write_utf8(SDL_Surface *dest, Sint16 x, Sint16 y,
+               utf8_str *pstr);
+SDL_Surface *create_text_surf_from_utf8(utf8_str *pstr);
+SDL_Surface *create_text_surf_smaller_than_w(utf8_str *pstr, int w);
+SDL_Rect utf8_str_size(utf8_str *pstr);
+void change_ptsize_utf8(utf8_str *pstr, Uint16 new_ptsize);
 
 void unload_font(Uint16 ptsize);
 void free_font_system(void);

Added: trunk/client/gui-sdl2/utf8string.c
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-sdl2/utf8string.c?rev=27706&view=auto
==============================================================================
--- trunk/client/gui-sdl2/utf8string.c  (added)
+++ trunk/client/gui-sdl2/utf8string.c  Thu Jan 15 20:59:55 2015
@@ -0,0 +1,90 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+/***************************************************************************
+                          unistring.c  -  description
+                             -------------------
+    begin                : Mon Jul 08 2002
+    copyright            : (C) 2002 by Rafał Bursig
+    email                : Rafał Bursig <bur...@poczta.fm>
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <fc_config.h>
+#endif
+
+#include <string.h>
+
+/* SDL */
+#include <SDL_types.h>
+
+/* utility */
+#include "mem.h"
+
+#include "utf8string.h"
+
+/**************************************************************************
+  Return number of characters in UTF-8 string
+**************************************************************************/
+size_t utf8_strlen(const char *pstr)
+{
+  size_t ret = 0;
+  int i = 0;
+
+  while (pstr[i] != '\0') {
+    if (pstr[i++] >= 128) {
+      while ((pstr[i] & (128 + 64)) == 128) {
+        i++;
+      }
+    }
+    ret++;
+  }
+
+  return ret;
+}
+
+/**************************************************************************
+  Don't free return array, only arrays members. This is not re-entrant.
+**************************************************************************/
+char **create_new_line_utf8strs(const char *pstr)
+{
+  static char *buf[512];
+  const char *start = pstr;
+  size_t len = 0, count = 0;
+
+  while (*start != '\0') {
+    if (*pstr == '\n') { /* find a new line char */
+      if (len) {
+        buf[count] = fc_calloc(len + 1, 1);
+        memcpy(buf[count], start, len);
+      } else {
+        buf[count] = fc_calloc(2, 1);
+        buf[count][0] = ' ';
+      }
+      start = pstr + 1;
+      len = 0;
+      count++;
+    } else {
+      len++;
+    }
+
+    pstr++;
+
+    if ((*pstr == 0) && len) {
+      buf[count] = fc_calloc(len + 1, 1);
+      memcpy(buf[count], start, len);
+    }
+  }
+
+  return buf;
+}

Propchange: trunk/client/gui-sdl2/utf8string.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: trunk/client/gui-sdl2/utf8string.h
URL: 
http://svn.gna.org/viewcvs/freeciv/trunk/client/gui-sdl2/utf8string.h?rev=27706&view=auto
==============================================================================
--- trunk/client/gui-sdl2/utf8string.h  (added)
+++ trunk/client/gui-sdl2/utf8string.h  Thu Jan 15 20:59:55 2015
@@ -0,0 +1,23 @@
+/********************************************************************** 
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+***********************************************************************/
+
+#ifndef FC__UTF8STRING_H
+#define FC__UTF8STRING_H
+
+/* SDL */
+#include <SDL.h>
+
+size_t utf8_strlen(const char *pstr);
+char **create_new_line_utf8strs(const char *pstr);
+
+#endif /* FC__UTF8STRING_H */

Propchange: trunk/client/gui-sdl2/utf8string.h
------------------------------------------------------------------------------
    svn:eol-style = native


_______________________________________________
Freeciv-commits mailing list
Freeciv-commits@gna.org
https://mail.gna.org/listinfo/freeciv-commits

Reply via email to