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:
parent
5a8972d0f9
commit
065503ef64
@ -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,13 +4847,74 @@ 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)
|
||||||
{
|
{
|
||||||
|
if (is_truetype&&antialias)
|
||||||
|
{
|
||||||
|
// Display brush in remapped form.
|
||||||
|
byte *remapped_brush;
|
||||||
|
|
||||||
|
remapped_brush=(byte *)malloc(new_width*new_height);
|
||||||
|
if (remapped_brush)
|
||||||
|
{
|
||||||
|
// This code is mostly copied from Remap_brush()
|
||||||
|
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(
|
Display_brush(
|
||||||
new_brush,
|
new_brush,
|
||||||
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
|
Window_pos_X+preview_button->Pos_X*Menu_factor_X,
|
||||||
@ -4864,6 +4926,8 @@ void Button_Text(void)
|
|||||||
Back_color,
|
Back_color,
|
||||||
new_width);
|
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,
|
||||||
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
|
Window_pos_Y+preview_button->Pos_Y*Menu_factor_Y,
|
||||||
@ -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;
|
||||||
|
|||||||
130
src/text.c
130
src/text.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
Texte8Bit=SDL_DisplayFormat(TexteColore);
|
new_brush=Surface_to_bytefield(text_surface, NULL);
|
||||||
|
|
||||||
SDL_FreeSurface(TexteColore);
|
|
||||||
|
|
||||||
new_brush=Surface_to_bytefield(Texte8Bit, NULL);
|
|
||||||
if (!new_brush)
|
if (!new_brush)
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(TexteColore);
|
SDL_FreeSurface(text_surface);
|
||||||
SDL_FreeSurface(Texte8Bit);
|
|
||||||
TTF_CloseFont(font);
|
TTF_CloseFont(font);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!antialias)
|
|
||||||
|
// Import palette
|
||||||
|
Get_SDL_Palette(text_surface->format->palette, palette);
|
||||||
|
|
||||||
|
if (antialias)
|
||||||
{
|
{
|
||||||
// Map colors: white->fg, black->bg
|
int black_col;
|
||||||
for (index=0; index < Texte8Bit->w * Texte8Bit->h; index++)
|
// Shaded text: X-Swap the color that is pure black with the BG color number,
|
||||||
|
// so that the brush is immediately 'transparent'
|
||||||
|
|
||||||
|
// Find black (c)
|
||||||
|
for (black_col=0; black_col<256; black_col++)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 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;
|
*(new_brush+index)=Back_color;
|
||||||
else
|
else
|
||||||
*(new_brush+index)=Fore_color;
|
*(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=Texte8Bit->w;
|
*width=text_surface->w;
|
||||||
*height=Texte8Bit->h;
|
*height=text_surface->h;
|
||||||
SDL_FreeSurface(Texte8Bit);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user