From 065503ef643706393676ef3639decc266a016c50 Mon Sep 17 00:00:00 2001 From: Yves Rizoud Date: Sat, 5 Feb 2011 00:07:28 +0000 Subject: [PATCH] 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 --- src/buttons.c | 92 ++++++++++++++++++++++++++----- src/text.c | 146 ++++++++++++++++++++++++++++++++++---------------- src/text.h | 5 +- 3 files changed, 182 insertions(+), 61 deletions(-) diff --git a/src/buttons.c b/src/buttons.c index 759cbbe0..98f8f0c0 100644 --- a/src/buttons.c +++ b/src/buttons.c @@ -4767,6 +4767,7 @@ void Button_Text(void) static short is_italic=0; byte * new_brush=NULL; + T_Palette text_palette; int new_width; int new_height; int clicked_button; @@ -4846,23 +4847,86 @@ void Button_Text(void) if (preview_is_needed) { const char * preview_string = "AaBbCcDdEeFf012345"; + byte is_truetype; + if (str[0]) 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); - 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) { - 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); + 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_posPos_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( Window_pos_X+preview_button->Pos_X*Menu_factor_X, @@ -4987,8 +5051,8 @@ void Button_Text(void) Error(0); } // Grab palette - memcpy(Brush_original_palette, Main_palette,sizeof(T_Palette)); - // Remap (no change) + memcpy(Brush_original_palette, text_palette,sizeof(T_Palette)); + // Remap to image's palette Remap_brush(); Brush_offset_X=Brush_width>>1; diff --git a/src/text.c b/src/text.c index 69bbd515..cc3ac114 100644 --- a/src/text.c +++ b/src/text.c @@ -56,6 +56,7 @@ #include "io.h" #include "errors.h" #include "windows.h" +#include "misc.h" typedef struct T_Font { @@ -373,13 +374,11 @@ int TrueType_is_supported() #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; - SDL_Surface * TexteColore; - SDL_Surface * Texte8Bit; + TTF_Font *font; + SDL_Surface * text_surface; byte * new_brush; - int index; int style; 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; TTF_SetFontStyle(font, style); - // Couleurs + // Colors: Text will be generated as white on black. fg_color.r=fg_color.g=fg_color.b=255; bg_color.r=bg_color.g=bg_color.b=0; // The following is alpha, supposedly unused 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) - TexteColore=TTF_RenderText_Shaded(font, str, fg_color, bg_color ); + text_surface=TTF_RenderText_Shaded(font, str, fg_color, bg_color ); else - TexteColore=TTF_RenderText_Solid(font, str, fg_color); - if (!TexteColore) + text_surface=TTF_RenderText_Solid(font, str, fg_color); + if (!text_surface) { TTF_CloseFont(font); 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); - - SDL_FreeSurface(TexteColore); + // Import palette + Get_SDL_Palette(text_surface->format->palette, palette); + + 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); - if (!new_brush) - { - 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++) + // Find black (c) + for (black_col=0; black_col<256; black_col++) { - int sum; - sum = Main_palette[*(new_brush+index)].R - + Main_palette[*(new_brush+index)].G - + Main_palette[*(new_brush+index)].B; - if (sum < 128 * 3) - *(new_brush+index)=Back_color; - else - *(new_brush+index)=Fore_color; + if (palette[black_col].R==0 && palette[black_col].G==0 && palette[black_col].B==0) + break; + } // If not found: c = 256 = 0 (byte) + + 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; } } - *width=Texte8Bit->w; - *height=Texte8Bit->h; - SDL_FreeSurface(Texte8Bit); + 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; + 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); return new_brush; } #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; SDL_Surface * TexteColore; - SDL_Surface * Texte8Bit; + SDL_Surface * text_surface; SDL_Surface *Surface_fonte; byte * new_brush; SDL_Rect rectangle; @@ -476,6 +530,8 @@ byte *Render_text_SFont(const char *str, int font_number, int *width, int *heigh return NULL; } + memcpy(palette, Main_palette, sizeof(T_Palette)); + // Calcul des dimensions *height=SFont_TextHeight(font); *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; } - Texte8Bit=SDL_DisplayFormat(TexteColore); + text_surface=SDL_DisplayFormat(TexteColore); SDL_FreeSurface(TexteColore); - new_brush=Surface_to_bytefield(Texte8Bit, NULL); + new_brush=Surface_to_bytefield(text_surface, NULL); if (!new_brush) { DEBUG("Converting failed",3); SDL_FreeSurface(TexteColore); - SDL_FreeSurface(Texte8Bit); + SDL_FreeSurface(text_surface); SFont_FreeFont(font); return NULL; } - SDL_FreeSurface(Texte8Bit); + SDL_FreeSurface(text_surface); SFont_FreeFont(font); 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. // Si cela réussit, la fonction place les dimensions dans width et height, // 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; 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) { #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 return NULL; #endif } else { - return Render_text_SFont(str, font_number, width, height); + return Render_text_SFont(str, font_number, width, height, palette); } } diff --git a/src/text.h b/src/text.h index 48b3e20b..6d65b274 100644 --- a/src/text.h +++ b/src/text.h @@ -41,15 +41,16 @@ void Add_font(const char *name); /// @param italic Boolean, true to use italic rendering in TrueType /// @param width Returns the width 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. -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(). char * Font_label(int index); /// Finds the filename of a font declared with ::Add_font(). char * Font_name(int index); /// 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 /// convenience, but functionaly it is read-only.