Add the ability to print unicode characters in addition to "Latin1" ones

This commit is contained in:
Thomas Bernard 2018-02-11 21:43:44 +01:00
parent b564a4d4f4
commit 545308265b
11 changed files with 236 additions and 38 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1459,7 +1459,7 @@ void Button_Skins(void)
T_Fileselector_item* fontName;
selected_font = Window_attribute2; // Get the index of the chosen font.
fontName = Get_item_by_index(&Font_files_list,selected_font);
new_font = Load_font(fontName->Full_name);
new_font = Load_font(fontName->Full_name, 1);
if (new_font)
{
free(Menu_font);
@ -1498,7 +1498,7 @@ void Button_Skins(void)
Set_current_skin(skinsdir, gfx);
}
// (Re-)load the selected font
new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name);
new_font = Load_font(Get_item_by_index(&Font_files_list,selected_font)->Full_name, 1);
if (new_font)
{
const char * fname;

View File

@ -646,6 +646,9 @@ GFX2_GLOBAL byte Resolution_in_command_line;
/// Pointer to the font selected for menus.
GFX2_GLOBAL byte * Menu_font;
/// additional fonts for unicode characters
GFX2_GLOBAL T_Unicode_Font * Unicode_fonts;
/// Pointer to the current active skin.
GFX2_GLOBAL T_Gui_skin * Gfx;

View File

@ -701,27 +701,36 @@ T_Gui_skin * Load_graphics(const char * skin_file, T_Gradient_array *gradients)
// ---- font loading -----
byte Parse_font(SDL_Surface * image, byte * font)
static byte * Parse_font(SDL_Surface * image, int is_main)
{
byte * font;
int character;
byte color;
int x, y;
int chars_per_line;
int character_count;
// Check image size
if (image->w % 8)
{
sprintf(Gui_loading_error_message, "Error in font file: Image width is not a multiple of 8.\n");
return 1;
return NULL;
}
if (image->w * image->h < 8*8*256)
character_count = (image->w * image->h) / (8*8);
if (is_main && character_count < 256)
{
sprintf(Gui_loading_error_message, "Error in font file: Image is too small to be a 256-character 8x8 font.\n");
return 1;
return NULL;
}
font = (byte *)malloc(8*8*character_count);
if (font == NULL)
{
sprintf(Gui_loading_error_message, "Not enough memory to read font file\n");
return NULL;
}
chars_per_line = image->w/8;
for (character=0; character < 256; character++)
for (character=0; character < character_count; character++)
{
for (y=0; y<8; y++)
{
@ -732,19 +741,20 @@ byte Parse_font(SDL_Surface * image, byte * font)
if (color > 1)
{
sprintf(Gui_loading_error_message, "Error in font file: Only colors 0 and 1 can be used for the font.\n");
return 1;
free(font);
return NULL;
}
// Put it in font. 0 = BG, 1 = FG.
font[character*64 + y*8 + x]=color;
}
}
}
return 0;
return font;
}
byte * Load_font(const char * font_name)
byte * Load_font(const char * font_name, int is_main)
{
byte * font;
byte * font = NULL;
char filename[MAX_PATH_CHARACTERS];
SDL_Surface * image;
@ -754,13 +764,6 @@ byte * Load_font(const char * font_name)
return NULL;
}
font = (byte *)malloc(8*8*256);
if (font == NULL)
{
sprintf(Gui_loading_error_message, "Not enough memory to read font file\n");
return NULL;
}
// Read the file containing the image
sprintf(filename,"%s" SKINS_SUBDIRECTORY "%s%s", Data_directory, PATH_SEPARATOR, font_name);
@ -768,19 +771,41 @@ byte * Load_font(const char * font_name)
if (!image)
{
sprintf(Gui_loading_error_message, "Unable to load the skin image (missing? not an image file?)\n");
free(font);
return NULL;
}
if (Parse_font(image, font))
{
SDL_FreeSurface(image);
free(font);
return NULL;
}
font = Parse_font(image, is_main);
SDL_FreeSurface(image);
return font;
}
static void Load_Unicode_font(const char * filename)
{
T_Unicode_Font * ufont;
byte * font;
unsigned int first, last;
if (sscanf(filename, "unicode_%04X-%04X.png", &first, &last) == 2)
{
font = Load_font(filename, 0);
if (font)
{
ufont = malloc(sizeof(T_Unicode_Font));
ufont->FirstChar = first;
ufont->LastChar = last;
ufont->FontData = font;
ufont->Next = Unicode_fonts;
Unicode_fonts = ufont;
}
}
else
Warning("Could not parse filename");
}
void Load_Unicode_fonts(void)
{
// TODO : for each unicode*.png file in skin directory
Load_Unicode_font("unicode_0410-044F.png");
}
// Initialisation des boutons:

View File

@ -47,4 +47,7 @@ extern char Gui_loading_error_message[512];
/// successful.
/// If an error is encountered, it frees what needs it, prints an error message
/// in ::Gui_loading_error_message, and returns NULL.
byte * Load_font(const char * font_name);
byte * Load_font(const char * font_name, int is_main);
/// Load fonts for additional Unicode characters
void Load_Unicode_fonts(void);

View File

@ -745,12 +745,13 @@ int Init_program(int argc,char * argv[])
Copy_preset_sieve(0);
// Font
if (!(Menu_font=Load_font(Config.Font_file)))
if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME)))
if (!(Menu_font=Load_font(Config.Font_file, 1)))
if (!(Menu_font=Load_font(DEFAULT_FONT_FILENAME, 1)))
{
printf("Unable to open the default font file: %s\n", DEFAULT_FONT_FILENAME);
Error(ERROR_GUI_MISSING);
}
Load_Unicode_fonts();
memcpy(Main.palette, Gfx->Default_palette, sizeof(T_Palette));
@ -993,6 +994,16 @@ void Program_shutdown(void)
free(Gfx);
Gfx=NULL;
free(Menu_font);
Menu_font = NULL;
while (Unicode_fonts != NULL)
{
T_Unicode_Font * ufont = Unicode_fonts->Next;
free(Unicode_fonts->FontData);
free(Unicode_fonts);
Unicode_fonts = ufont;
}
// On prend bien soin de passer dans le répertoire initial:
if (chdir(Initial_directory)!=-1)
{

View File

@ -549,7 +549,7 @@ typedef struct T_Selector_settings
char Directory[MAX_PATH_CHARACTERS]; ///< Directory currently browsed
} T_Selector_settings;
// structure for Main or Spare page global data
/// structure for Main or Spare page global data
typedef struct
{
/// Palette
@ -618,4 +618,12 @@ typedef struct
T_List_of_pages * backups;
} T_Document;
typedef struct T_Unicode_Font
{
struct T_Unicode_Font * Next;
dword FirstChar;
dword LastChar;
byte * FontData;
} T_Unicode_Font;
#endif

81
src/unicode.c Normal file
View File

@ -0,0 +1,81 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2018 Thomas Bernard
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
#include <stdlib.h>
#include <string.h>
#include "unicode.h"
size_t Unicode_strlen(const word * str)
{
size_t len;
len = 0;
while(str[len] != 0)
len++;
return len;
}
/// equivalent of strdup() for our Unicode strings
word * Unicode_strdup(const word * str)
{
size_t byte_size;
word * new_str;
byte_size = Unicode_strlen(str) * 2 + 2;
new_str = malloc(byte_size);
if (new_str != NULL)
memcpy(new_str, str, byte_size);
return new_str;
}
/// Compare an unicode string with a regular Latin1 string
int Unicode_char_strcmp(const word * s1, const char * s2)
{
const byte * str2 = (const byte *)s2;
while (*s1 == *str2)
{
if (*s1 == 0) return 0;
s1++;
str2++;
}
return (*s1 > *str2) ? 1 : -1;
}
/// Copy a regular Latin1 string to an unicode string
void Unicode_char_strlcpy(word * dst, const char * src, size_t len)
{
const byte * s = (const byte *)src;
if (len == 0)
return;
while (len > 1)
{
*dst = *s;
if (*s == '\0')
return;
dst++;
s++;
len--;
}
*dst = 0;
}

39
src/unicode.h Normal file
View File

@ -0,0 +1,39 @@
/* vim:expandtab:ts=2 sw=2:
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2018 Thomas Bernard
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
Grafx2 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; version 2
of the License.
Grafx2 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.
You should have received a copy of the GNU General Public License
along with Grafx2; if not, see <http://www.gnu.org/licenses/>
*/
#ifndef UNICODE_H_INCLUDED
#define UNICODE_H_INCLUDED
#include "struct.h"
/// equivalent of strlen() for out Unicode strings
/// return the number of characters (words), so there is twice as much bytes
size_t Unicode_strlen(const word * str);
/// equivalent of strdup() for our Unicode strings
word * Unicode_strdup(const word * str);
/// Compare an unicode string with a regular Latin1 string
int Unicode_char_strcmp(const word * s1, const char * s2);
/// Copy a regular Latin1 string to an unicode string
void Unicode_char_strlcpy(word * dst, const char * src, size_t len);
#endif

View File

@ -708,13 +708,25 @@ void Print_general(short x,short y,const char * str,byte text_color,byte backgro
}
/// Draws a char in a window
void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color)
void Print_char_in_window(short x_pos, short y_pos, unsigned int c,byte text_color,byte background_color)
{
short x,y;
byte *pixel;
const byte *pixel;
// Premier pixel du caractère
pixel=Menu_font + (c<<6);
if (c < 256)
pixel=Menu_font + (c<<6);
else
{
T_Unicode_Font * ufont;
pixel=Menu_font + (1<<6); // dummy character
for (ufont = Unicode_fonts; ufont != NULL; ufont = ufont->Next)
if (ufont->FirstChar <= c && c <= ufont->LastChar)
{
pixel = ufont->FontData + ((c - ufont->FirstChar) << 6);
break;
}
}
for (y=0;y<8;y++)
for (x=0;x<8;x++)
Pixel_in_window(x_pos+x, y_pos+y,
@ -739,16 +751,31 @@ void Print_in_window_limited(short x,short y,const char * str,byte size,byte tex
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color)
{
short x_pos = x;
int index;
const unsigned char * p = (const unsigned char *)str;
for (index=0;str[index]!='\0';index++)
while (*p !='\0')
{
Print_char_in_window(x,y,str[index],text_color,background_color);
Print_char_in_window(x,y,*p++,text_color,background_color);
x+=8;
}
Update_window_area(x_pos,y,8*strlen(str),8);
Update_window_area(x_pos,y,x-x_pos,8);
}
/// Draws a string in a window
void Print_in_window_utf16(short x,short y,const word * str,byte text_color,byte background_color)
{
short x_pos = x;
const word * p = str;
while (*p != 0)
{
Print_char_in_window(x,y,*p++,text_color,background_color);
x+=8;
}
Update_window_area(x_pos,y,x-x_pos,8);
}
// Draws a string in the menu's status bar
void Print_in_menu(const char * str, short position)
{

View File

@ -67,8 +67,9 @@ word Palette_cells_Y(void);
void Print_general(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window_utf16(short x,short y,const word * str,byte text_color,byte background_color);
void Print_in_window_limited(short x,short y,const char * str,byte size,byte text_color,byte background_color);
void Print_char_in_window(short x_pos,short y_pos,const unsigned char c,byte text_color,byte background_color);
void Print_char_in_window(short x_pos,short y_pos, unsigned int c,byte text_color,byte background_color);
void Print_in_menu(const char * str, short position);
void Print_coordinates(void);
void Print_filename(void);