Improved text rendering in Truetype mode (with and without antialias), thanks to the improved brush remapping. Still todo: bitmap fonts, colored and monochrome cases.

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@1707 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2011-02-05 00:07:28 +00:00
parent 5a8972d0f9
commit 065503ef64
3 changed files with 182 additions and 61 deletions

View File

@ -4767,6 +4767,7 @@ void Button_Text(void)
static short is_italic=0; static short is_italic=0;
byte * new_brush=NULL; byte * new_brush=NULL;
T_Palette text_palette;
int new_width; int new_width;
int new_height; int new_height;
int clicked_button; int clicked_button;
@ -4846,23 +4847,86 @@ void Button_Text(void)
if (preview_is_needed) if (preview_is_needed)
{ {
const char * preview_string = "AaBbCcDdEeFf012345"; const char * preview_string = "AaBbCcDdEeFf012345";
byte is_truetype;
if (str[0]) if (str[0])
preview_string=str; preview_string=str;
Window_rectangle(8, 106, 273, 50,Back_color); is_truetype=TrueType_font(selected_font_index);
Window_rectangle(8, 106, 273, 50,(antialias&&is_truetype)?MC_Black:Back_color);
free(new_brush); free(new_brush);
new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height); new_brush = Render_text(preview_string, selected_font_index, font_size, antialias, is_bold, is_italic, &new_width, &new_height, text_palette);
if (new_brush) if (new_brush)
{ {
Display_brush( if (is_truetype&&antialias)
new_brush, {
Window_pos_X+preview_button->Pos_X*Menu_factor_X, // Display brush in remapped form.
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y, byte *remapped_brush;
0,
0, remapped_brush=(byte *)malloc(new_width*new_height);
Min(preview_button->Width*Menu_factor_X, new_width), if (remapped_brush)
Min(preview_button->Height*Menu_factor_Y, new_height), {
Back_color, // This code is mostly copied from Remap_brush()
new_width); short x_pos;
short y_pos;
int color;
byte colmap[256];
for (color=0;color<=255;color++)
colmap[color]=0;
for (y_pos=0;y_pos<new_height;y_pos++)
for (x_pos=0;x_pos<new_width;x_pos++)
colmap[*(new_brush + y_pos * new_width + x_pos)]=1;
colmap[Back_color]=0;
for (color=0;color<=255;color++)
if (colmap[color] != 0)
{
byte r,g,b;
r=text_palette[color].R;
g=text_palette[color].G;
b=text_palette[color].B;
//if (r==Main_palette[color].R && g==Main_palette[color].G && b==Main_palette[color].B)
// colmap[color]=color;
//else
colmap[color]=Best_color_perceptual(r,g,b);
}
colmap[Back_color]=Back_color;
Remap_general_lowlevel(colmap,new_brush,remapped_brush,new_width,new_height,new_width);
Display_brush(
remapped_brush,
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
free(remapped_brush);
}
}
else
{
// Solid
Display_brush(
new_brush,
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
0,
0,
Min(preview_button->Width*Menu_factor_X, new_width),
Min(preview_button->Height*Menu_factor_Y, new_height),
Back_color,
new_width);
}
} }
Update_rect( Update_rect(
Window_pos_X+preview_button->Pos_X*Menu_factor_X, Window_pos_X+preview_button->Pos_X*Menu_factor_X,
@ -4987,8 +5051,8 @@ void Button_Text(void)
Error(0); Error(0);
} }
// Grab palette // Grab palette
memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette)); memcpy(Brush_original_palette, text_palette,sizeof(T_Palette));
// Remap (no change) // Remap to image's palette
Remap_brush(); Remap_brush();
Brush_offset_X=Brush_width>>1; Brush_offset_X=Brush_width>>1;

View File

@ -56,6 +56,7 @@
#include "io.h" #include "io.h"
#include "errors.h" #include "errors.h"
#include "windows.h" #include "windows.h"
#include "misc.h"
typedef struct T_Font typedef struct T_Font
{ {
@ -373,13 +374,11 @@ int TrueType_is_supported()
#ifndef NOTTF #ifndef NOTTF
byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height) byte *Render_text_TTF(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette)
{ {
TTF_Font *font; TTF_Font *font;
SDL_Surface * TexteColore; SDL_Surface * text_surface;
SDL_Surface * Texte8Bit;
byte * new_brush; byte * new_brush;
int index;
int style; int style;
SDL_Color fg_color; SDL_Color fg_color;
@ -400,64 +399,119 @@ byte *Render_text_TTF(const char *str, int font_number, int size, int antialias,
style|=TTF_STYLE_BOLD; style|=TTF_STYLE_BOLD;
TTF_SetFontStyle(font, style); TTF_SetFontStyle(font, style);
// Couleurs // Colors: Text will be generated as white on black.
fg_color.r=fg_color.g=fg_color.b=255; fg_color.r=fg_color.g=fg_color.b=255;
bg_color.r=bg_color.g=bg_color.b=0; bg_color.r=bg_color.g=bg_color.b=0;
// The following is alpha, supposedly unused // The following is alpha, supposedly unused
bg_color.unused=fg_color.unused=255; bg_color.unused=fg_color.unused=255;
// Rendu du texte: crée une surface SDL RGB 24bits // Text rendering: creates a 8bit surface with its dedicated palette
if (antialias) if (antialias)
TexteColore=TTF_RenderText_Shaded(font, str, fg_color, bg_color ); text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color );
else else
TexteColore=TTF_RenderText_Solid(font, str, fg_color); text_surface=TTF_RenderText_Solid(font, str, fg_color);
if (!TexteColore) if (!text_surface)
{ {
TTF_CloseFont(font); TTF_CloseFont(font);
return NULL; return NULL;
} }
new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush)
{
SDL_FreeSurface(text_surface);
TTF_CloseFont(font);
return NULL;
}
Texte8Bit=SDL_DisplayFormat(TexteColore); // Import palette
Get_SDL_Palette(text_surface->format->palette, palette);
SDL_FreeSurface(TexteColore);
if (antialias)
{
int black_col;
// Shaded text: X-Swap the color that is pure black with the BG color number,
// so that the brush is immediately 'transparent'
new_brush=Surface_to_bytefield(Texte8Bit, NULL); // Find black (c)
if (!new_brush) for (black_col=0; black_col<256; black_col++)
{
SDL_FreeSurface(TexteColore);
SDL_FreeSurface(Texte8Bit);
TTF_CloseFont(font);
return NULL;
}
if (!antialias)
{
// Map colors: white->fg, black->bg
for (index=0; index < Texte8Bit->w * Texte8Bit->h; index++)
{ {
int sum; if (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0)
sum = Main_palette[*(new_brush+index)].R break;
+ Main_palette[*(new_brush+index)].G } // If not found: c = 256 = 0 (byte)
+ Main_palette[*(new_brush+index)].B;
if (sum < 128 * 3) if (black_col != Back_color)
*(new_brush+index)=Back_color; {
else int c;
*(new_brush+index)=Fore_color; byte colmap[256];
// Swap palette entries
SWAP_BYTES(palette[black_col].R, palette[Back_color].R)
SWAP_BYTES(palette[black_col].G, palette[Back_color].G)
SWAP_BYTES(palette[black_col].B, palette[Back_color].B)
// Define a colormap
for (c=0; c<256; c++)
colmap[c]=c;
// The swap
colmap[black_col]=Back_color;
colmap[Back_color]=black_col;
Remap_general_lowlevel(colmap, new_brush, new_brush, text_surface->w,text_surface->h, text_surface->w);
// Also, make the BG color in brush palette have same RGB values as
// the current BG color : this will help for remaps.
palette[Back_color].R=Main_palette[Back_color].R;
palette[Back_color].G=Main_palette[Back_color].G;
palette[Back_color].B=Main_palette[Back_color].B;
} }
} }
*width=Texte8Bit->w; else
*height=Texte8Bit->h; {
SDL_FreeSurface(Texte8Bit); // Solid text: Was rendered as white on black. Now map colors:
// White becomes FG color, black becomes BG. 2-color palette.
// Exception: if BG==FG, FG will be set to black or white - any different color.
long index;
byte new_fore=Fore_color;
if (Fore_color==Back_color)
{
if (Main_palette[Back_color].R+Main_palette[Back_color].G+Main_palette[Back_color].B > 128*3)
// Back color is rather light:
new_fore=MC_Black;
else
// Back color is rather dark:
new_fore=MC_White;
}
for (index=0; index < text_surface->w * text_surface->h; index++)
{
if (palette[*(new_brush+index)].G < 128)
*(new_brush+index)=Back_color;
else
*(new_brush+index)=new_fore;
}
// Now copy the current palette to brushe's, for consistency
// with the indices.
memcpy(palette, Main_palette, sizeof(T_Palette));
}
*width=text_surface->w;
*height=text_surface->h;
SDL_FreeSurface(text_surface);
TTF_CloseFont(font); TTF_CloseFont(font);
return new_brush; return new_brush;
} }
#endif #endif
byte *Render_text_SFont(const char *str, int font_number, int *width, int *height) byte *Render_text_SFont(const char *str, int font_number, int *width, int *height, T_Palette palette)
{ {
SFont_Font *font; SFont_Font *font;
SDL_Surface * TexteColore; SDL_Surface * TexteColore;
SDL_Surface * Texte8Bit; SDL_Surface * text_surface;
SDL_Surface *Surface_fonte; SDL_Surface *Surface_fonte;
byte * new_brush; byte * new_brush;
SDL_Rect rectangle; SDL_Rect rectangle;
@ -476,6 +530,8 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
return NULL; return NULL;
} }
memcpy(palette, Main_palette, sizeof(T_Palette));
// Calcul des dimensions // Calcul des dimensions
*height=SFont_TextHeight(font); *height=SFont_TextHeight(font);
*width=SFont_TextWidth(font, str); *width=SFont_TextWidth(font, str);
@ -501,19 +557,19 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
return NULL; return NULL;
} }
Texte8Bit=SDL_DisplayFormat(TexteColore); text_surface=SDL_DisplayFormat(TexteColore);
SDL_FreeSurface(TexteColore); SDL_FreeSurface(TexteColore);
new_brush=Surface_to_bytefield(Texte8Bit, NULL); new_brush=Surface_to_bytefield(text_surface, NULL);
if (!new_brush) if (!new_brush)
{ {
DEBUG("Converting failed",3); DEBUG("Converting failed",3);
SDL_FreeSurface(TexteColore); SDL_FreeSurface(TexteColore);
SDL_FreeSurface(Texte8Bit); SDL_FreeSurface(text_surface);
SFont_FreeFont(font); SFont_FreeFont(font);
return NULL; return NULL;
} }
SDL_FreeSurface(Texte8Bit); SDL_FreeSurface(text_surface);
SFont_FreeFont(font); SFont_FreeFont(font);
return new_brush; return new_brush;
@ -528,7 +584,7 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh
// Crée une brosse à partir des paramètres de texte demandés. // Crée une brosse à partir des paramètres de texte demandés.
// Si cela réussit, la fonction place les dimensions dans width et height, // Si cela réussit, la fonction place les dimensions dans width et height,
// et retourne l'adresse du bloc d'octets. // et retourne l'adresse du bloc d'octets.
byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height) byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONLY antialias, TTFONLY int bold, TTFONLY int italic, int *width, int *height, T_Palette palette)
{ {
T_Font *font = font_list_start; T_Font *font = font_list_start;
int index=font_number; int index=font_number;
@ -542,14 +598,14 @@ byte *Render_text(const char *str, int font_number, TTFONLY int size, int TTFONL
if (font->Is_truetype) if (font->Is_truetype)
{ {
#ifndef NOTTF #ifndef NOTTF
return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height); return Render_text_TTF(str, font_number, size, antialias, bold, italic, width, height, palette);
#else #else
return NULL; return NULL;
#endif #endif
} }
else else
{ {
return Render_text_SFont(str, font_number, width, height); return Render_text_SFont(str, font_number, width, height, palette);
} }
} }

View File

@ -41,15 +41,16 @@ void Add_font(const char *name);
/// @param italic Boolean, true to use italic rendering in TrueType /// @param italic Boolean, true to use italic rendering in TrueType
/// @param width Returns the width of the created brush, in pixels. /// @param width Returns the width of the created brush, in pixels.
/// @param height Returns the height of the created brush, in pixels. /// @param height Returns the height of the created brush, in pixels.
/// @param palette Returns the custom palette for the brush.
/// Returns true on success. /// Returns true on success.
byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height); byte *Render_text(const char *str, int font_number, int size, int antialias, int bold, int italic, int *width, int *height, T_Palette palette);
/// Finds a label to display for a font declared with ::Add_font(). /// Finds a label to display for a font declared with ::Add_font().
char * Font_label(int index); char * Font_label(int index);
/// Finds the filename of a font declared with ::Add_font(). /// Finds the filename of a font declared with ::Add_font().
char * Font_name(int index); char * Font_name(int index);
/// Returns true if the font of this number is TrueType, false if it's a SFont bitmap. /// Returns true if the font of this number is TrueType, false if it's a SFont bitmap.
char * TrueType_font(int index); int TrueType_font(int index);
/// ///
/// Number of fonts declared with a series of ::Add_font(). This is public for /// Number of fonts declared with a series of ::Add_font(). This is public for
/// convenience, but functionaly it is read-only. /// convenience, but functionaly it is read-only.