commit
fd47245c23
7 changed files with 306 additions and 118 deletions
5
Makefile
5
Makefile
|
@ -15,8 +15,8 @@ ifeq ($(FIX_BUGS), 1)
|
||||||
CXXFLAGS += -DFIX_BUGS
|
CXXFLAGS += -DFIX_BUGS
|
||||||
endif
|
endif
|
||||||
|
|
||||||
CXXFLAGS += `sdl2-config --cflags`
|
CXXFLAGS += `sdl2-config --cflags` `pkg-config freetype2 --cflags`
|
||||||
LIBS += `sdl2-config --static-libs` -lSDL2_ttf -lfreetype -lharfbuzz -lfreetype -lbz2 -lpng -lz -lgraphite2 -lRpcrt4 -lDwrite -lusp10
|
LIBS += `sdl2-config --static-libs` -lfreetype -lharfbuzz -lfreetype -lbz2 -lpng -lz -lgraphite2 -lRpcrt4 -lDwrite -lusp10 -liconv
|
||||||
|
|
||||||
# For an accurate result to the original's code, compile in alphabetical order
|
# For an accurate result to the original's code, compile in alphabetical order
|
||||||
SOURCES = \
|
SOURCES = \
|
||||||
|
@ -27,6 +27,7 @@ SOURCES = \
|
||||||
Escape \
|
Escape \
|
||||||
Fade \
|
Fade \
|
||||||
Flags \
|
Flags \
|
||||||
|
Font \
|
||||||
Game \
|
Game \
|
||||||
Generic \
|
Generic \
|
||||||
GenericLoad \
|
GenericLoad \
|
||||||
|
|
BIN
build/data/msgothic.ttc
Normal file
BIN
build/data/msgothic.ttc
Normal file
Binary file not shown.
135
src/Draw.cpp
135
src/Draw.cpp
|
@ -7,10 +7,11 @@
|
||||||
#include <SDL_render.h>
|
#include <SDL_render.h>
|
||||||
#include <SDL_rwops.h>
|
#include <SDL_rwops.h>
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
#include <SDL_ttf.h>
|
|
||||||
#include "WindowsWrapper.h"
|
#include "WindowsWrapper.h"
|
||||||
|
|
||||||
#include "Draw.h"
|
#include "Draw.h"
|
||||||
|
#include "Font.h"
|
||||||
#include "Tags.h"
|
#include "Tags.h"
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
|
|
||||||
|
@ -19,8 +20,7 @@ RECT grcFull = {0, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||||
|
|
||||||
SURFACE surf[SURFACE_ID_MAX];
|
SURFACE surf[SURFACE_ID_MAX];
|
||||||
|
|
||||||
TTF_Font *gFont;
|
FontObject *gFont;
|
||||||
double gFontXStretch; //This is something normally done by DirectX, but... well... we're not using DirectX.
|
|
||||||
|
|
||||||
#define FRAMERATE 20
|
#define FRAMERATE 20
|
||||||
|
|
||||||
|
@ -206,7 +206,7 @@ bool MakeSurface_Generic(int bxsize, int bysize, int surf_no)
|
||||||
ReleaseSurface(surf_no);
|
ReleaseSurface(surf_no);
|
||||||
|
|
||||||
//Create surface
|
//Create surface
|
||||||
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, bxsize * gWindowScale, bysize * gWindowScale);
|
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, bxsize * gWindowScale, bysize * gWindowScale);
|
||||||
|
|
||||||
if (!surf[surf_no].texture)
|
if (!surf[surf_no].texture)
|
||||||
{
|
{
|
||||||
|
@ -231,7 +231,7 @@ void BackupSurface(int surf_no, RECT *rect)
|
||||||
SDL_GetRendererOutputSize(gRenderer, &w, &h);
|
SDL_GetRendererOutputSize(gRenderer, &w, &h);
|
||||||
|
|
||||||
//Get texture of what's currently rendered on screen
|
//Get texture of what's currently rendered on screen
|
||||||
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(SDL_TEXTUREACCESS_TARGET, w, h, 0, SDL_PIXELFORMAT_RGB888);
|
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32);
|
||||||
SDL_RenderReadPixels(gRenderer, nullptr, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
SDL_RenderReadPixels(gRenderer, nullptr, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||||
|
|
||||||
SDL_Texture *screenTexture = SDL_CreateTextureFromSurface(gRenderer, surface);
|
SDL_Texture *screenTexture = SDL_CreateTextureFromSurface(gRenderer, surface);
|
||||||
|
@ -247,6 +247,8 @@ void BackupSurface(int surf_no, RECT *rect)
|
||||||
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
|
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
|
||||||
SDL_RenderCopy(gRenderer, screenTexture, &frameRect, &destRect);
|
SDL_RenderCopy(gRenderer, screenTexture, &frameRect, &destRect);
|
||||||
SDL_SetRenderTarget(gRenderer, NULL);
|
SDL_SetRenderTarget(gRenderer, NULL);
|
||||||
|
|
||||||
|
SDL_DestroyTexture(screenTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency
|
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency
|
||||||
|
@ -369,140 +371,43 @@ void CortBox2(RECT *rect, uint32_t col, int surf_no)
|
||||||
|
|
||||||
void InitTextObject()
|
void InitTextObject()
|
||||||
{
|
{
|
||||||
//Initialize SDL_TTF
|
|
||||||
if(!TTF_WasInit() && TTF_Init() < 0)
|
|
||||||
{
|
|
||||||
printf("TTF_Init: %s\n", TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If font already exists, delete
|
|
||||||
if (gFont)
|
|
||||||
TTF_CloseFont(gFont);
|
|
||||||
|
|
||||||
//Get font size
|
//Get font size
|
||||||
unsigned int fontWidth, fontHeight;
|
unsigned int fontWidth, fontHeight;
|
||||||
if (gWindowScale == 1)
|
if (gWindowScale == 1)
|
||||||
{
|
{
|
||||||
fontWidth = 5;
|
fontWidth = 6;
|
||||||
fontHeight = 10;
|
fontHeight = 12;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fontWidth = 5 * gWindowScale;
|
fontWidth = 5 * gWindowScale;
|
||||||
fontHeight = 8 * gWindowScale + (gWindowScale >> 1);
|
fontHeight = 10 * gWindowScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Open Font.ttf
|
//Open Font.ttf
|
||||||
char path[PATH_LENGTH];
|
char path[PATH_LENGTH];
|
||||||
sprintf(path, "%s/Font.ttf", gDataPath);
|
#ifdef JAPANESE
|
||||||
|
sprintf(path, "%s/msgothic.ttc", gDataPath);
|
||||||
gFont = TTF_OpenFont(path, fontHeight);
|
#else
|
||||||
if(!gFont)
|
sprintf(path, "%s/cour.ttf", gDataPath);
|
||||||
{
|
#endif
|
||||||
printf("TTF_OpenFont: %s\n", TTF_GetError());
|
|
||||||
return;
|
gFont = LoadFont(fontWidth, fontHeight, path);
|
||||||
}
|
|
||||||
|
|
||||||
//Get the average width of the font, and make it so the average width is the font width above.
|
|
||||||
char string[0xE1];
|
|
||||||
for (int i = 0; i < 0xE0; i++)
|
|
||||||
string[i] = i + 0x20;
|
|
||||||
string[0xE1] = 0;
|
|
||||||
|
|
||||||
int width, height;
|
|
||||||
if (TTF_SizeText(gFont, string, &width, &height))
|
|
||||||
{
|
|
||||||
printf("TTF_SizeText: %s\n", TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gFontXStretch = (double)fontWidth / ((double)width / (double)0xE0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutText(int x, int y, const char *text, uint32_t color)
|
void PutText(int x, int y, const char *text, uint32_t color)
|
||||||
{
|
{
|
||||||
SDL_Color textColor = {(uint8_t)((color & 0xFF0000) >> 16), (uint8_t)((color & 0xFF00) >> 8), (uint8_t)(color & 0xFF)};
|
DrawText(gFont, gRenderer, NULL, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||||
SDL_Color backColor = {0, 0, 0};
|
|
||||||
|
|
||||||
//Draw text
|
|
||||||
SDL_Surface *textSurface = TTF_RenderText_Shaded(gFont, text, textColor, backColor);
|
|
||||||
|
|
||||||
if (!textSurface)
|
|
||||||
{
|
|
||||||
printf("TTF_RenderText_Shaded: %s\n", TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetColorKey(textSurface, SDL_TRUE, 0x000000);
|
|
||||||
|
|
||||||
//Convert to texture
|
|
||||||
SDL_Texture *textTexture = SDL_CreateTextureFromSurface(gRenderer, textSurface);
|
|
||||||
|
|
||||||
if (!textTexture)
|
|
||||||
{
|
|
||||||
printf("Failed to convert SDL_Surface to SDL_Texture to draw text: %s\nTTF Error: %s\n", text, TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Draw to screen
|
|
||||||
SDL_Rect destRect = {x * gWindowScale, y * gWindowScale, (int)(textSurface->w * gFontXStretch), textSurface->h};
|
|
||||||
SDL_RenderCopy(gRenderer, textTexture, NULL, &destRect);
|
|
||||||
|
|
||||||
//Destroy surface and texture
|
|
||||||
SDL_FreeSurface(textSurface);
|
|
||||||
SDL_DestroyTexture(textTexture);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PutText2(int x, int y, const char *text, uint32_t color, int surf_no)
|
void PutText2(int x, int y, const char *text, uint32_t color, int surf_no)
|
||||||
{
|
{
|
||||||
SDL_Color textColor = {(uint8_t)((color & 0xFF0000) >> 16), (uint8_t)((color & 0xFF00) >> 8), (uint8_t)(color & 0xFF)};
|
DrawText(gFont, gRenderer, surf[surf_no].texture, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||||
SDL_Color backColor = {0, 0, 0};
|
|
||||||
|
|
||||||
//Draw text
|
|
||||||
SDL_Surface *textSurface = TTF_RenderText_Shaded(gFont, text, textColor, backColor);
|
|
||||||
|
|
||||||
if (!textSurface)
|
|
||||||
{
|
|
||||||
printf("TTF_RenderText_Shaded: %s\n", TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetColorKey(textSurface, SDL_TRUE, 0x000000);
|
|
||||||
|
|
||||||
//Convert to texture
|
|
||||||
SDL_Texture *textTexture = SDL_CreateTextureFromSurface(gRenderer, textSurface);
|
|
||||||
|
|
||||||
if (!textTexture)
|
|
||||||
{
|
|
||||||
printf("Failed to convert SDL_Surface to SDL_Texture to draw text: %s\nTTF Error: %s\n", text, TTF_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Target surface
|
|
||||||
if (!surf[surf_no].texture)
|
|
||||||
{
|
|
||||||
printf("Tried to draw text to surface %s, which doesn't exist\n", surf_no);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
|
|
||||||
|
|
||||||
//Draw to screen
|
|
||||||
SDL_Rect destRect = {x * gWindowScale, y * gWindowScale, (int)(textSurface->w * gFontXStretch), textSurface->h};
|
|
||||||
SDL_RenderCopy(gRenderer, textTexture, NULL, &destRect);
|
|
||||||
|
|
||||||
//Destroy surface and texture
|
|
||||||
SDL_FreeSurface(textSurface);
|
|
||||||
SDL_DestroyTexture(textTexture);
|
|
||||||
|
|
||||||
//Stop targetting surface
|
|
||||||
SDL_SetRenderTarget(gRenderer, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EndTextObject()
|
void EndTextObject()
|
||||||
{
|
{
|
||||||
//Destroy font
|
//Destroy font
|
||||||
TTF_CloseFont(gFont);
|
UnloadFont(gFont);
|
||||||
gFont = nullptr;
|
gFont = nullptr;
|
||||||
}
|
}
|
||||||
|
|
258
src/Font.cpp
Normal file
258
src/Font.cpp
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
#include "Font.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_LCD_FILTER_H
|
||||||
|
#include FT_BITMAP_H
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
// Uncomment for that authentic pre-Windows Vista feel
|
||||||
|
//#define DISABLE_FONT_ANTIALIASING
|
||||||
|
|
||||||
|
#undef MIN
|
||||||
|
#undef MAX
|
||||||
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
static unsigned long UTF8ToCode(const unsigned char *string, unsigned int *bytes_read)
|
||||||
|
{
|
||||||
|
unsigned int length;
|
||||||
|
unsigned long charcode;
|
||||||
|
|
||||||
|
if ((string[0] & 0x80) == 0)
|
||||||
|
{
|
||||||
|
length = 1;
|
||||||
|
charcode = string[0] & 0x7F;
|
||||||
|
}
|
||||||
|
else if ((string[0] & 0xE0) == 0xC0)
|
||||||
|
{
|
||||||
|
length = 2;
|
||||||
|
charcode = ((string[0] & ~0xE0) << 6) | (string[1] & 0x3F);
|
||||||
|
}
|
||||||
|
else if ((string[0] & 0xF0) == 0xE0)
|
||||||
|
{
|
||||||
|
length = 3;
|
||||||
|
charcode = ((string[0] & ~0xF0) << (6 * 2)) | ((string[1] & 0x3F) << 6) | (string[2] & 0x3F);
|
||||||
|
}
|
||||||
|
else //if (string[0] & 0xF8 == 0xF0)
|
||||||
|
{
|
||||||
|
length = 4;
|
||||||
|
charcode = ((string[0] & ~0xF8) << (6 * 3)) | ((string[1] & 0x3F) << (6 * 2)) | ((string[2] & 0x3F) << 6) | (string[3] & 0x3F);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read)
|
||||||
|
*bytes_read = length;
|
||||||
|
|
||||||
|
return charcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontObject* LoadFont(unsigned int cell_width, unsigned int cell_height, char *font_filename)
|
||||||
|
{
|
||||||
|
FontObject *font_object = (FontObject*)malloc(sizeof(FontObject));
|
||||||
|
|
||||||
|
FT_Init_FreeType(&font_object->library);
|
||||||
|
|
||||||
|
#ifndef DISABLE_FONT_ANTIALIASING
|
||||||
|
font_object->lcd_mode = FT_Library_SetLcdFilter(font_object->library, FT_LCD_FILTER_DEFAULT) != FT_Err_Unimplemented_Feature;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FT_New_Face(font_object->library, font_filename, 0, &font_object->face);
|
||||||
|
|
||||||
|
unsigned int best_cell_width = 0;
|
||||||
|
unsigned int best_cell_height = 0;
|
||||||
|
unsigned int best_pixel_width = 0;
|
||||||
|
unsigned int best_pixel_height = 0;
|
||||||
|
|
||||||
|
for (unsigned int i = 0;; ++i)
|
||||||
|
{
|
||||||
|
FT_Set_Pixel_Sizes(font_object->face, i, i);
|
||||||
|
|
||||||
|
const unsigned int current_cell_width = font_object->face->size->metrics.max_advance / 64;
|
||||||
|
const unsigned int current_cell_height = font_object->face->size->metrics.height / 64;
|
||||||
|
|
||||||
|
if (current_cell_width > cell_width && current_cell_height > cell_height)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (current_cell_width <= cell_width)
|
||||||
|
{
|
||||||
|
best_pixel_width = i;
|
||||||
|
best_cell_width = current_cell_width;
|
||||||
|
}
|
||||||
|
if (current_cell_height <= cell_height)
|
||||||
|
{
|
||||||
|
best_pixel_height = i;
|
||||||
|
best_cell_height = current_cell_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef JAPANESE
|
||||||
|
best_pixel_width = 0; // Cheap hack to make the font square
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FT_Set_Pixel_Sizes(font_object->face, best_pixel_width, best_pixel_height);
|
||||||
|
|
||||||
|
#ifdef JAPANESE
|
||||||
|
font_object->conv = iconv_open("UTF-8", "SHIFT-JIS");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return font_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length)
|
||||||
|
{
|
||||||
|
const unsigned char colours[3] = {(unsigned char)(colour >> 16), (unsigned char)(colour >> 8), (unsigned char)colour};
|
||||||
|
|
||||||
|
SDL_Texture *old_render_target = SDL_GetRenderTarget(renderer);
|
||||||
|
SDL_SetRenderTarget(renderer, texture);
|
||||||
|
|
||||||
|
int surface_width, surface_height;
|
||||||
|
SDL_GetRendererOutputSize(renderer, &surface_width, &surface_height);
|
||||||
|
|
||||||
|
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||||
|
unsigned char (*surface_buffer)[surface->pitch / 4][4] = (unsigned char (*)[surface->pitch / 4][4])surface->pixels;
|
||||||
|
|
||||||
|
FT_Face face = font_object->face;
|
||||||
|
|
||||||
|
unsigned int pen_x = 0;
|
||||||
|
|
||||||
|
const unsigned char *string_pointer = (unsigned char*)string;
|
||||||
|
const unsigned char *string_end = (unsigned char*)string + string_length;
|
||||||
|
|
||||||
|
while (string_pointer != string_end)
|
||||||
|
{
|
||||||
|
#ifdef JAPANESE
|
||||||
|
size_t out_size = 4;
|
||||||
|
unsigned char out_buffer[4]; // Max UTF-8 length is four bytes
|
||||||
|
unsigned char *out_pointer = out_buffer;
|
||||||
|
|
||||||
|
size_t in_size = ((*string_pointer >= 0x81 && *string_pointer <= 0x9F) || (*string_pointer >= 0xE0 && *string_pointer <= 0xEF)) ? 2 : 1;
|
||||||
|
unsigned char in_buffer[2];
|
||||||
|
unsigned char *in_pointer = in_buffer;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < in_size; ++i)
|
||||||
|
in_buffer[i] = string_pointer[i];
|
||||||
|
|
||||||
|
string_pointer += in_size;
|
||||||
|
|
||||||
|
iconv(font_object->conv, (char**)&in_pointer, &in_size, (char**)&out_pointer, &out_size);
|
||||||
|
|
||||||
|
const unsigned long val = UTF8ToCode(out_buffer, NULL);
|
||||||
|
#else
|
||||||
|
unsigned int bytes_read;
|
||||||
|
const unsigned long val = UTF8ToCode(string_pointer, &bytes_read);
|
||||||
|
string_pointer += bytes_read;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int glyph_index = FT_Get_Char_Index(face, val);
|
||||||
|
|
||||||
|
#ifndef DISABLE_FONT_ANTIALIASING
|
||||||
|
FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER | (font_object->lcd_mode ? FT_LOAD_TARGET_LCD : 0));
|
||||||
|
#else
|
||||||
|
FT_Load_Glyph(face, glyph_index, FT_LOAD_RENDER | FT_LOAD_MONOCHROME);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FT_Bitmap converted;
|
||||||
|
FT_Bitmap_New(&converted);
|
||||||
|
FT_Bitmap_Convert(font_object->library, &face->glyph->bitmap, &converted, 1);
|
||||||
|
|
||||||
|
const int letter_x = x + pen_x + face->glyph->bitmap_left;
|
||||||
|
const int letter_y = y + ((FT_MulFix(face->ascender, face->size->metrics.y_scale) + (64 - 1)) / 64) - (face->glyph->metrics.horiBearingY / 64);
|
||||||
|
|
||||||
|
for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface_height); ++iy)
|
||||||
|
{
|
||||||
|
if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
|
||||||
|
{
|
||||||
|
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface_width); ++ix)
|
||||||
|
{
|
||||||
|
unsigned char (*font_buffer)[converted.pitch / 3][3] = (unsigned char (*)[converted.pitch / 3][3])converted.buffer;
|
||||||
|
|
||||||
|
unsigned char *font_pixel = font_buffer[iy][ix];
|
||||||
|
unsigned char *surface_pixel = surface_buffer[letter_y + iy][letter_x + ix];
|
||||||
|
|
||||||
|
if (font_pixel[0] || font_pixel[1] || font_pixel[2])
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
unsigned char colour_accumulator = surface_pixel[j];
|
||||||
|
|
||||||
|
colour_accumulator = ((colours[j] * font_pixel[j]) / 0xFF) + ((colour_accumulator * (0xFF - font_pixel[j])) / 0xFF); // Alpha blending
|
||||||
|
colour_accumulator = 255.0 * pow((colour_accumulator / 255.0), 1.0 / 1.8); // Gamma correction
|
||||||
|
|
||||||
|
surface_pixel[j] = colour_accumulator;
|
||||||
|
}
|
||||||
|
|
||||||
|
surface_pixel[3] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
|
||||||
|
{
|
||||||
|
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix)
|
||||||
|
{
|
||||||
|
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
|
||||||
|
|
||||||
|
const double raw_alpha = (double)font_buffer[iy][ix] / (converted.num_grays - 1);
|
||||||
|
const double alpha = pow(raw_alpha, 1.0 / 1.8); // Gamma-corrected
|
||||||
|
|
||||||
|
unsigned char *surface_pixel = surface_buffer[letter_y + iy][letter_x + ix];
|
||||||
|
|
||||||
|
if (alpha)
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < 3; ++j)
|
||||||
|
surface_pixel[j] = (colours[j] * alpha) + (surface_pixel[j] * (1.0 - alpha)); // Alpha blending
|
||||||
|
|
||||||
|
surface_pixel[3] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
|
||||||
|
{
|
||||||
|
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix)
|
||||||
|
{
|
||||||
|
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
|
||||||
|
|
||||||
|
unsigned char *surface_pixel = surface_buffer[letter_y + iy][letter_x + ix];
|
||||||
|
|
||||||
|
if (font_buffer[iy][ix])
|
||||||
|
{
|
||||||
|
for (unsigned int j = 0; j < 3; ++j)
|
||||||
|
surface_pixel[j] = colours[j];
|
||||||
|
|
||||||
|
surface_pixel[3] = 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Bitmap_Done(font_object->library, &converted);
|
||||||
|
|
||||||
|
pen_x += face->glyph->advance.x / 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||||
|
SDL_DestroyTexture(screen_texture);
|
||||||
|
SDL_SetRenderTarget(renderer, old_render_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnloadFont(FontObject *font_object)
|
||||||
|
{
|
||||||
|
#ifdef JAPANESE
|
||||||
|
iconv_close(font_object->conv);
|
||||||
|
#endif
|
||||||
|
FT_Done_Face(font_object->face);
|
||||||
|
FT_Done_FreeType(font_object->library);
|
||||||
|
}
|
24
src/Font.h
Normal file
24
src/Font.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
typedef struct FontObject
|
||||||
|
{
|
||||||
|
FT_Library library;
|
||||||
|
FT_Face face;
|
||||||
|
#ifndef DISABLE_FONT_ANTIALIASING
|
||||||
|
bool lcd_mode;
|
||||||
|
#endif
|
||||||
|
#ifdef JAPANESE
|
||||||
|
iconv_t conv;
|
||||||
|
#endif
|
||||||
|
} FontObject;
|
||||||
|
|
||||||
|
FontObject* LoadFont(unsigned int cell_width, unsigned int cell_height, char *font_filename);
|
||||||
|
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length);
|
||||||
|
void UnloadFont(FontObject *font_object);
|
|
@ -16,7 +16,7 @@ void ReadyMapName(char *str)
|
||||||
|
|
||||||
//Handle "Studio Pixel presents" text in the intro
|
//Handle "Studio Pixel presents" text in the intro
|
||||||
#ifdef JAPANESE
|
#ifdef JAPANESE
|
||||||
char presentText[24] = "開発室Pixel presents\x00\x01\x01\x01";
|
char presentText[24] = "ŠJ”ŽºPixel presents";
|
||||||
#else
|
#else
|
||||||
char presentText[24] = " Studio Pixel presents";
|
char presentText[24] = " Studio Pixel presents";
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue