From db318af9284626430f5e55834ca62222155b60cc Mon Sep 17 00:00:00 2001
From: William Kendrick
Date: Thu, 22 May 2003 08:51:41 +0000
Subject: [PATCH] Right-to-left UTF8 text blitting. Hebrew now displays
properly (I think)!
---
docs/CHANGES.txt | 2 +-
docs/README.txt | 2 +-
docs/TODO.txt | 8 ++-
docs/html/README.html | 2 +-
src/tuxpaint.c | 142 ++++++++++++++++++++++++++++++++++--------
5 files changed, 126 insertions(+), 30 deletions(-)
diff --git a/docs/CHANGES.txt b/docs/CHANGES.txt
index fb1571ee3..f9e9eb4f4 100644
--- a/docs/CHANGES.txt
+++ b/docs/CHANGES.txt
@@ -7,7 +7,7 @@ bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
-2003.May.11 (0.9.11) [cvs]
+2003.May.22 (0.9.11) [cvs]
* Windows bugfixes.
John Popplewell
diff --git a/docs/README.txt b/docs/README.txt
index 497c8b89f..e228f2acf 100644
--- a/docs/README.txt
+++ b/docs/README.txt
@@ -9,7 +9,7 @@
bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
- June 14, 2002 - May 11, 2003
+ June 14, 2002 - May 22, 2003
----------------------------------------------------------------------
diff --git a/docs/TODO.txt b/docs/TODO.txt
index 181da3ef2..16a38a6a5 100644
--- a/docs/TODO.txt
+++ b/docs/TODO.txt
@@ -6,7 +6,7 @@ Copyright (c) 2003 by Bill Kendrick
bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
-May 20, 2003
+May 22, 2003
LOW-PRIORITY DOCUMENTATION CHANGES:
@@ -79,6 +79,8 @@ PLATFORM-SPECIFIC BUGS:
HIGH-PRIORITY TRANSLATION STUFF:
--------------------------------
+ * Right-justify right-to-left strings.
+
* Finish current translations.
* Fix Romanian!
@@ -90,7 +92,9 @@ LOW-PRIORITY TRANSLATION STUFF:
-------------------------------
* Support more languages!
* Hindi
- * ...
+ * Arabic
+ * Thai
+ ...
* Update Czech and Slovak translations (so they use accents/etc.!)
diff --git a/docs/html/README.html b/docs/html/README.html
index 5ee7698be..39f836803 100644
--- a/docs/html/README.html
+++ b/docs/html/README.html
@@ -21,7 +21,7 @@ New Breed Software
bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
-June 14, 2002 - May 11, 2003
+June 14, 2002 - May 22, 2003
diff --git a/src/tuxpaint.c b/src/tuxpaint.c
index 6258ba393..0ea4ff4b1 100644
--- a/src/tuxpaint.c
+++ b/src/tuxpaint.c
@@ -7,12 +7,12 @@
bill@newbreedsoftware.com
http://www.newbreedsoftware.com/tuxpaint/
- June 14, 2002 - May 11, 2003
+ June 14, 2002 - May 22, 2003
*/
#define VER_VERSION "0.9.11"
-#define VER_DATE "2003.05.11"
+#define VER_DATE "2003.05.22"
/* #define DEBUG */
@@ -302,6 +302,12 @@ int lang_use_utf8[] = {
-1
};
+int lang_use_right_to_left[] = {
+ LANG_EN,
+ LANG_HE,
+ -1
+};
+
typedef struct info_type {
int colorable;
@@ -522,6 +528,7 @@ void strip_trailing_whitespace(char * buf);
void do_render_cur_text(int do_blit);
void loadfonts(char * dir, int fatal);
char * uppercase(char * str);
+unsigned char * textdir(unsigned char * str);
SDL_Surface * do_render_button_label(char * label);
static void create_button_labels(void);
int colors_close(Uint32 c1, Uint32 c2);
@@ -538,6 +545,7 @@ void draw_image_title(int t, int x);
int need_unicode(int l);
int need_utf8(int l);
int need_own_font(int l);
+int need_right_to_left(int l);
void handle_keymouse(SDLKey key, Uint8 updown);
void move_keymouse(void);
void handle_active(SDL_Event * event);
@@ -4464,7 +4472,7 @@ void setup(int argc, char * argv[])
strcmp(gettext(title_names[i]), title_names[i]) != 0)
{
tmp_surf = TTF_RenderUNICODE_Blended(locale_font,
- (Uint16 *) gettext(title_names[i]),
+ (Uint16 *) textdir(gettext(title_names[i])),
black);
img_title_names[i] = thumbnail(tmp_surf,
min(84, tmp_surf->w), tmp_surf->h, 0);
@@ -4474,14 +4482,14 @@ void setup(int argc, char * argv[])
strcmp(gettext(title_names[i]), title_names[i]) != 0)
{
tmp_surf = TTF_RenderUTF8_Blended(locale_font,
- gettext(title_names[i]), black);
+ textdir(gettext(title_names[i])), black);
img_title_names[i] = thumbnail(tmp_surf,
min(84, tmp_surf->w), tmp_surf->h, 0);
SDL_FreeSurface(tmp_surf);
}
else
{
- upstr = uppercase(gettext(title_names[i]));
+ upstr = uppercase(textdir(gettext(title_names[i])));
tmp_surf = RENDER_TEXT(large_font, upstr, black);
img_title_names[i] = thumbnail(tmp_surf,
min(84, tmp_surf->w), tmp_surf->h, 0);
@@ -4594,19 +4602,19 @@ SDL_Surface * do_render_button_label(char * label)
if (need_unicode(language) && locale_font != NULL &&
strcmp(gettext(label), label) != 0)
{
- tmp_surf = TTF_RenderUNICODE_Blended(locale_font, (Uint16 *) gettext(label),
+ tmp_surf = TTF_RenderUNICODE_Blended(locale_font, (Uint16 *) textdir(gettext(label)),
black);
surf = thumbnail(tmp_surf, min(48, tmp_surf->w), tmp_surf->h, 0);
}
else if (need_utf8(language) && locale_font != NULL &&
strcmp(gettext(label), label) != 0)
{
- tmp_surf = TTF_RenderUTF8_Blended(locale_font, gettext(label), black);
+ tmp_surf = TTF_RenderUTF8_Blended(locale_font, textdir(gettext(label)), black);
surf = thumbnail(tmp_surf, min(48, tmp_surf->w), tmp_surf->h, 0);
}
else
{
- str = uppercase(gettext(label));
+ str = uppercase(textdir(gettext(label)));
tmp_surf = RENDER_TEXT(small_font, str, black);
surf = thumbnail(tmp_surf, min(48, tmp_surf->w), tmp_surf->h, 0);
free(str);
@@ -4632,17 +4640,17 @@ static void create_button_labels(void)
/* 'Open' label: */
- img_openlabels_open = do_render_button_label(gettext_noop("Open"));
+ img_openlabels_open = do_render_button_label(textdir(gettext_noop("Open")));
/* 'Erase' label: */
- img_openlabels_erase = do_render_button_label(gettext_noop("Erase"));
+ img_openlabels_erase = do_render_button_label(textdir(gettext_noop("Erase")));
/* 'Back' label: */
- img_openlabels_back = do_render_button_label(gettext_noop("Back"));
+ img_openlabels_back = do_render_button_label(textdir(gettext_noop("Back")));
}
@@ -6348,7 +6356,7 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
if (want_utf8)
locale_str = strdup(str);
else
- locale_str = strdup(gettext(str));
+ locale_str = strdup(textdir(gettext(str)));
/* For each UTF8 character: */
@@ -6391,8 +6399,6 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
for (j = 0; j < utf8_str_len; j++)
{
- printf("%d of %d\n", j, utf8_str_len); fflush(stdout);
-
/* How many bytes does this character need? */
if (utf8_str[j] < 128) /* 0xxx xxxx - 1 byte */
@@ -6438,7 +6444,11 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
y = y + text->h;
}
- dest.x = x;
+ //if (need_right_to_left(language) == 0)
+ dest.x = x;
+ //else
+ // dest.x = right - (x - left) - text->w;
+
dest.y = y;
SDL_BlitSurface(text, NULL, screen, &dest);
@@ -6461,7 +6471,11 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
y = y + text->h;
}
- dest.x = x;
+ //if (need_right_to_left(language) == 0)
+ dest.x = x;
+ //else
+ // dest.x = right - (x - left) - text->w;
+
dest.y = y;
SDL_BlitSurface(text, NULL, screen, &dest);
@@ -6505,7 +6519,7 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
else if (need_unicode(language) && locale_font != NULL &&
strcmp(gettext(str), str) != 0 && strcmp(str, "") != 0)
{
- locale_str = strdup(gettext(str));
+ locale_str = strdup(textdir(gettext(str)));
/* For each pair of bytes... */
@@ -6529,7 +6543,11 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
}
- dest.x = x;
+ //if (need_right_to_left(language) == 0)
+ dest.x = x;
+ //else
+ // dest.x = right - (x - left) - text->w;
+
dest.y = y;
SDL_BlitSurface(text, NULL, screen, &dest);
@@ -6545,7 +6563,7 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
{
/* Truncate if too big! (sorry!) */
- tstr = strdup(uppercase(gettext(str)));
+ tstr = strdup(uppercase(textdir(gettext(str))));
if (strlen(tstr) > sizeof(substr) - 1)
tstr[sizeof(substr) - 1] = '\0';
@@ -6587,7 +6605,11 @@ void wordwrap_text(TTF_Font * font, char * str, SDL_Color color,
/* Draw the word: */
- dest.x = x;
+ //if (need_right_to_left(language) == 0)
+ dest.x = x;
+ //else
+ // dest.x = right - (x - left) - text->w;
+
dest.y = y;
SDL_BlitSurface(text, NULL, screen, &dest);
@@ -7162,10 +7184,10 @@ int do_prompt(char * text, char * btn_yes, char * btn_no)
/* FIXME: Move elsewhere! Or not?! */
- strcpy(keystr, gettext("Yes"));
+ strcpy(keystr, textdir(gettext("Yes")));
key_y = tolower(keystr[0]);
- strcpy(keystr, gettext("No"));
+ strcpy(keystr, textdir(gettext("No")));
key_n = tolower(keystr[0]);
@@ -8548,8 +8570,8 @@ int do_open(int want_new_tool)
/* Let user choose an image: */
draw_tux_text(TUX_BORED,
- gettext_noop("Choose the picture you want, "
- "then click 'Open'"), 0, 0);
+ textdir(gettext_noop("Choose the picture you want, "
+ "then click 'Open'")), 0, 0);
cur = 0;
update_list = 1;
@@ -10108,6 +10130,8 @@ void loadfonts(char * dir, int fatal)
}
+/* Return string as uppercase if that option is set: */
+
char * uppercase(char * str)
{
char * ustr;
@@ -10130,6 +10154,55 @@ char * uppercase(char * str)
}
+/* Return string in right-to-left mode, if necessary: */
+
+unsigned char * textdir(unsigned char * str)
+{
+ unsigned char * dstr;
+ int i, j;
+
+ dstr = (unsigned char *) malloc((strlen(str) + 5) * sizeof(unsigned char));
+
+ if (need_right_to_left(language))
+ {
+ dstr[strlen(str)] = '\0';
+
+ for (i = 0; i < strlen(str); i++)
+ {
+ j = (strlen(str) - i - 1);
+
+ if (str[i] < 128) /* 0xxx xxxx - 1 byte */
+ {
+ dstr[j] = str[i];
+ }
+ else if ((str[i] & 0xE0) == 0xC0) /* 110x xxxx - 2 bytes */
+ {
+ dstr[j - 1] = str[i + 0];
+ dstr[j - 0] = str[i + 1];
+ i = i + 1;
+ }
+ else if ((str[i] & 0xF0) == 0xE0) /* 1110 xxxx - 3 bytes */
+ {
+ dstr[j - 2] = str[i + 0];
+ dstr[j - 1] = str[i + 1];
+ dstr[j - 0] = str[i + 2];
+ i = i + 2;
+ }
+ else /* 1111 0xxx - 4 bytes */
+ {
+ dstr[j - 3] = str[i + 0];
+ dstr[j - 2] = str[i + 1];
+ dstr[j - 1] = str[i + 2];
+ dstr[j - 0] = str[i + 3];
+ i = i + 3;
+ }
+ }
+ }
+
+ return (dstr);
+}
+
+
/* For flood fill... */
int colors_close(Uint32 c1, Uint32 c2)
@@ -10562,7 +10635,7 @@ int need_utf8(int l)
}
}
-return need;
+ return need;
}
@@ -10575,6 +10648,25 @@ int need_own_font(int l)
}
+int need_right_to_left(int l)
+{
+ int i, need;
+
+ need = 0;
+
+ for (i = 0; lang_use_right_to_left[i] != -1 && need == 0; i++)
+ {
+ if (lang_use_right_to_left[i] == l)
+ {
+ need = 1;
+ }
+ }
+
+ return need;
+}
+
+
+
/* Handle keyboard events to control the mouse: */
void handle_keymouse(SDLKey key, Uint8 updown)