add truetype support
This commit is contained in:
parent
37e4822ed5
commit
85e534f2d7
|
@ -95,6 +95,8 @@ target_sources(${EXECUTABLE_NAME} PUBLIC
|
|||
"src/file_utils.h"
|
||||
"src/font_manager.cc"
|
||||
"src/font_manager.h"
|
||||
"src/freetype_manager.cc"
|
||||
"src/freetype_manager.h"
|
||||
"src/game_config.cc"
|
||||
"src/game_config.h"
|
||||
"src/game_dialog.cc"
|
||||
|
@ -374,6 +376,19 @@ target_include_directories(${EXECUTABLE_NAME} PRIVATE ${ZLIB_INCLUDE_DIRS})
|
|||
target_link_libraries(${EXECUTABLE_NAME} ${SDL2_LIBRARIES})
|
||||
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${SDL2_INCLUDE_DIRS})
|
||||
|
||||
add_subdirectory("third_party/freetype")
|
||||
target_link_libraries(${EXECUTABLE_NAME} ${FREETYPE_LIBRARIES})
|
||||
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${FREETYPE_INCLUDE_DIRS})
|
||||
|
||||
add_subdirectory("third_party/iconv")
|
||||
target_link_libraries(${EXECUTABLE_NAME} ${ICONV_LIBRARIES})
|
||||
target_include_directories(${EXECUTABLE_NAME} PRIVATE ${ICONV_INCLUDE_DIRS})
|
||||
|
||||
message(status "${ZLIB_INCLUDE_DIRS}")
|
||||
message(status "${SDL2_INCLUDE_DIRS}")
|
||||
message(status "${FREETYPE_INCLUDE_DIRS}")
|
||||
message(status "${ICONV_INCLUDE_DIRS}")
|
||||
|
||||
if(APPLE)
|
||||
if(IOS)
|
||||
install(TARGETS ${EXECUTABLE_NAME} DESTINATION "Payload")
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "color.h"
|
||||
#include "db.h"
|
||||
#include "memory_manager.h"
|
||||
#include "word_wrap.h"
|
||||
|
||||
// The maximum number of interface fonts.
|
||||
#define INTERFACE_FONT_MAX (16)
|
||||
|
@ -63,6 +64,7 @@ FontManager gModernFontManager = {
|
|||
interfaceFontGetLetterSpacingImpl,
|
||||
interfaceFontGetBufferSizeImpl,
|
||||
interfaceFontGetMonospacedCharacterWidthImpl,
|
||||
leagcyWordWrap,
|
||||
};
|
||||
|
||||
// 0x586838
|
||||
|
|
|
@ -0,0 +1,592 @@
|
|||
#include "font_manager.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "color.h"
|
||||
#include "db.h"
|
||||
#include "memory_manager.h"
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_GLYPH_H
|
||||
#include FT_BITMAP_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "word_wrap.h"
|
||||
|
||||
#include <map>
|
||||
#include "iconv.h"
|
||||
#include "settings.h"
|
||||
|
||||
// The maximum number of interface fonts.
|
||||
#define FT_FONT_MAX (16)
|
||||
|
||||
namespace fallout {
|
||||
|
||||
typedef struct FtFontGlyph {
|
||||
short width;
|
||||
short rows;
|
||||
short left;
|
||||
short top;
|
||||
unsigned char* buffer;
|
||||
} FtFontGlyph;
|
||||
|
||||
typedef struct FtFontDescriptor {
|
||||
FT_Library library;
|
||||
FT_Face face;
|
||||
|
||||
unsigned char* filebuffer;
|
||||
|
||||
int maxHeight;
|
||||
int letterSpacing;
|
||||
int wordSpacing;
|
||||
int lineSpacing;
|
||||
int heightOffset;
|
||||
int warpMode;
|
||||
char encoding[64];
|
||||
|
||||
std::map<uint32_t, FtFontGlyph> map;
|
||||
} FtFontDescriptor;
|
||||
|
||||
static int FtFontLoad(int font);
|
||||
static void FtFontSetCurrentImpl(int font);
|
||||
static int FtFontGetLineHeightImpl();
|
||||
static int FtFontGetStringWidthImpl(const char* string);
|
||||
static int FtFontGetCharacterWidthImpl(int ch);
|
||||
static int FtFontGetMonospacedStringWidthImpl(const char* string);
|
||||
static int FtFontGetLetterSpacingImpl();
|
||||
static int FtFontGetBufferSizeImpl(const char* string);
|
||||
static int FtFontGetMonospacedCharacterWidthImpl();
|
||||
static void FtFontDrawImpl(unsigned char* buf, const char* string, int length, int pitch, int color);
|
||||
|
||||
static int FtFonteWordWrapImpl(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr);
|
||||
// 0x518680
|
||||
static bool gFtFontsInitialized = false;
|
||||
|
||||
// 0x518684
|
||||
static int gFtFontsLength = 0;
|
||||
|
||||
static int knobWidth = 5;
|
||||
static int knobHeight = 7;
|
||||
|
||||
static unsigned char knobDump[35] = {
|
||||
0x34, 0x82, 0xb6, 0x82,
|
||||
0x34, 0x82, 0xb6, 0xb6,
|
||||
0xb6, 0x82, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0x82,
|
||||
0xb6, 0xb6, 0xb6, 0x82,
|
||||
0x34, 0x82, 0xb6, 0x82,
|
||||
0x34, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0
|
||||
};
|
||||
|
||||
// 0x518688
|
||||
FontManager gFtFontManager = {
|
||||
100,
|
||||
110,
|
||||
FtFontSetCurrentImpl,
|
||||
FtFontDrawImpl,
|
||||
FtFontGetLineHeightImpl,
|
||||
FtFontGetStringWidthImpl,
|
||||
FtFontGetCharacterWidthImpl,
|
||||
FtFontGetMonospacedStringWidthImpl,
|
||||
FtFontGetLetterSpacingImpl,
|
||||
FtFontGetBufferSizeImpl,
|
||||
FtFontGetMonospacedCharacterWidthImpl,
|
||||
FtFonteWordWrapImpl,
|
||||
};
|
||||
|
||||
// 0x586838
|
||||
static FtFontDescriptor gFtFontDescriptors[FT_FONT_MAX];
|
||||
|
||||
// 0x58E938
|
||||
static int gCurrentFtFont;
|
||||
|
||||
// 0x58E93C
|
||||
static FtFontDescriptor* current;
|
||||
|
||||
static uint32_t output[1024] = {
|
||||
0x0,
|
||||
};
|
||||
|
||||
static int LtoU(const char* input, size_t charInPutLen)
|
||||
{
|
||||
if (input[0] == '\x95') {
|
||||
size_t output_size = 1024;
|
||||
iconv_t cd = iconv_open("UCS-4-INTERNAL", current->encoding);
|
||||
char* tmp = (char*)(output + 1);
|
||||
const char* tmp2 = (const char *)(input + 1);
|
||||
charInPutLen -= 1;
|
||||
iconv(cd, &tmp2, &charInPutLen, &tmp, &output_size);
|
||||
iconv_close(cd);
|
||||
|
||||
output[0] = '\x95';
|
||||
return (1024 - output_size) / 4 + 1;
|
||||
} else {
|
||||
size_t output_size = 1024;
|
||||
iconv_t cd = iconv_open("UCS-4-INTERNAL", current->encoding);
|
||||
char* tmp = (char*)output;
|
||||
iconv(cd, &input, &charInPutLen, &tmp, &output_size);
|
||||
iconv_close(cd);
|
||||
|
||||
return (1024 - output_size) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
static int UtoL(const char* input, size_t charInPutLen)
|
||||
{
|
||||
size_t output_size = 1024;
|
||||
iconv_t cd = iconv_open(current->encoding, "UCS-4-INTERNAL");
|
||||
char* tmp = (char*)output;
|
||||
iconv(cd, &input, &charInPutLen, &tmp, &output_size);
|
||||
iconv_close(cd);
|
||||
|
||||
return (1024 - output_size);
|
||||
}
|
||||
|
||||
static FtFontGlyph GetFtFontGlyph(uint32_t unicode)
|
||||
{
|
||||
if (current->map.count(unicode) > 0) {
|
||||
return current->map[unicode];
|
||||
} else {
|
||||
if (unicode == '\x95') {
|
||||
current->map[unicode].left = 0;
|
||||
current->map[unicode].top = current->maxHeight / 2;
|
||||
current->map[unicode].width = knobWidth;
|
||||
current->map[unicode].rows = knobHeight;
|
||||
current->map[unicode].buffer = knobDump;
|
||||
} else {
|
||||
FT_Load_Glyph(current->face, FT_Get_Char_Index(current->face, unicode), FT_LOAD_DEFAULT | FT_LOAD_NO_BITMAP);
|
||||
FT_Render_Glyph(current->face->glyph, FT_RENDER_MODE_NORMAL);
|
||||
|
||||
current->map[unicode].left = current->face->glyph->bitmap_left;
|
||||
current->map[unicode].top = current->face->glyph->bitmap_top;
|
||||
current->map[unicode].width = current->face->glyph->bitmap.width;
|
||||
current->map[unicode].rows = current->face->glyph->bitmap.rows;
|
||||
|
||||
int count = current->face->glyph->bitmap.width * current->face->glyph->bitmap.rows;
|
||||
|
||||
if (count > 0) {
|
||||
current->map[unicode].buffer = (unsigned char*)internal_malloc_safe(count, __FILE__, __LINE__); // FONTMGR.C, 259
|
||||
memcpy(current->map[unicode].buffer, current->face->glyph->bitmap.buffer, count);
|
||||
} else {
|
||||
current->map[unicode].buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return current->map[unicode];
|
||||
}
|
||||
}
|
||||
|
||||
// 0x441C80
|
||||
int FtFontsInit()
|
||||
{
|
||||
int currentFont = -1;
|
||||
|
||||
for (int font = 0; font < FT_FONT_MAX; font++) {
|
||||
if (FtFontLoad(font) == -1) {
|
||||
gFtFontDescriptors[font].maxHeight = 0;
|
||||
gFtFontDescriptors[font].filebuffer = NULL;
|
||||
} else {
|
||||
++gFtFontsLength;
|
||||
|
||||
if (currentFont == -1) {
|
||||
currentFont = font;
|
||||
}
|
||||
|
||||
gFtFontManager.maxFont = gFtFontsLength + 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFont == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
gFtFontsInitialized = true;
|
||||
|
||||
FtFontSetCurrentImpl(currentFont + 100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 0x441CEC
|
||||
void FtFontsExit()
|
||||
{
|
||||
for (int font = 0; font < FT_FONT_MAX; font++) {
|
||||
if (gFtFontDescriptors[font].filebuffer != NULL) {
|
||||
internal_free_safe(gFtFontDescriptors[font].filebuffer, __FILE__, __LINE__); // FONTMGR.C, 124
|
||||
}
|
||||
}
|
||||
//TODO: clean up
|
||||
}
|
||||
|
||||
// 0x441D20
|
||||
static int FtFontLoad(int font_index)
|
||||
{
|
||||
char string[56];
|
||||
FtFontDescriptor* desc = &(gFtFontDescriptors[font_index]);
|
||||
|
||||
Config config;
|
||||
if (!configInit(&config)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(string, "fonts/%s/font.ini", settings.system.language.c_str());
|
||||
if (!configRead(&config, string, false)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(string, "font%d", font_index);
|
||||
|
||||
if (!configGetInt(&config, string, "maxHeight", &desc->maxHeight)) {
|
||||
return -1;
|
||||
}
|
||||
if (!configGetInt(&config, string, "lineSpacing", &desc->lineSpacing)) {
|
||||
return -1;
|
||||
}
|
||||
if (!configGetInt(&config, string, "wordSpacing", &desc->wordSpacing)) {
|
||||
return -1;
|
||||
}
|
||||
if (!configGetInt(&config, string, "letterSpacing", &desc->letterSpacing)) {
|
||||
return -1;
|
||||
}
|
||||
if (!configGetInt(&config, string, "heightOffset", &desc->heightOffset)) {
|
||||
return -1;
|
||||
}
|
||||
if (!configGetInt(&config, string, "warpMode", &desc->warpMode)) {
|
||||
return -1;
|
||||
}
|
||||
char* encoding = NULL;
|
||||
if (!configGetString(&config, string, "encoding", &encoding)) {
|
||||
return -1;
|
||||
}
|
||||
strcpy(desc->encoding, encoding);
|
||||
|
||||
char *fontFileName = NULL;
|
||||
if (!configGetString(&config, string, "fileName", &fontFileName)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(string, "fonts/%s/%s", settings.system.language.c_str(), fontFileName);
|
||||
|
||||
File* stream = fileOpen(string, "rb");
|
||||
if (stream == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fileSize = fileGetSize(stream); //19647736
|
||||
|
||||
desc->filebuffer = (unsigned char*)internal_malloc_safe(fileSize, __FILE__, __LINE__); // FONTMGR.C, 259
|
||||
|
||||
int readleft = fileSize;
|
||||
unsigned char* ptr = desc->filebuffer;
|
||||
|
||||
while (readleft > 10000) {
|
||||
int readsize = fileRead(ptr, 1, 10000, stream);
|
||||
if (readsize != 10000) {
|
||||
return -1;
|
||||
}
|
||||
readleft -= 10000;
|
||||
ptr += 10000;
|
||||
}
|
||||
|
||||
if (fileRead(ptr, 1, readleft, stream) != readleft) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
FT_Init_FreeType(&(desc->library));
|
||||
FT_New_Memory_Face(desc->library, desc->filebuffer, fileSize, 0, &desc->face);
|
||||
|
||||
FT_Select_Charmap(desc->face, FT_ENCODING_UNICODE);
|
||||
FT_Set_Pixel_Sizes(desc->face, desc->maxHeight, desc->maxHeight);
|
||||
|
||||
fileClose(stream);
|
||||
configFree(&config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 0x442120
|
||||
static void FtFontSetCurrentImpl(int font)
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
font -= 100;
|
||||
|
||||
if (gFtFontDescriptors[font].filebuffer != NULL) {
|
||||
gCurrentFtFont = font;
|
||||
current = &(gFtFontDescriptors[font]);
|
||||
}
|
||||
}
|
||||
|
||||
// 0x442168
|
||||
static int FtFontGetLineHeightImpl()
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return current->lineSpacing + current->maxHeight + current->heightOffset;
|
||||
}
|
||||
|
||||
// 0x442188
|
||||
static int FtFontGetStringWidthImpl(const char* string)
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strlen(string) == 1 && string[0] < 0) {
|
||||
return current->wordSpacing;
|
||||
} else {
|
||||
int count;
|
||||
int width = 0;
|
||||
|
||||
count = LtoU((char*)string, strlen(string));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint32_t ch = output[i];
|
||||
|
||||
if (ch == L'\n' || ch == L'\r') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch == '\x95') {
|
||||
FtFontGlyph g = GetFtFontGlyph(ch);
|
||||
width += g.width + current->letterSpacing + 2;
|
||||
} else if (ch == L' ' || (ch < 256 && ch > 128)) {
|
||||
width += current->wordSpacing + current->letterSpacing;
|
||||
} else {
|
||||
FtFontGlyph g = GetFtFontGlyph(ch);
|
||||
width += g.width + current->letterSpacing;
|
||||
}
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
}
|
||||
|
||||
// 0x4421DC
|
||||
static int FtFontGetCharacterWidthImpl(int ch)
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return current->wordSpacing;
|
||||
}
|
||||
|
||||
// 0x442210
|
||||
static int FtFontGetMonospacedStringWidthImpl(const char* str)
|
||||
{
|
||||
return FtFontGetStringWidthImpl(str);
|
||||
}
|
||||
|
||||
// 0x442240
|
||||
static int FtFontGetLetterSpacingImpl()
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return current->letterSpacing;
|
||||
}
|
||||
|
||||
// 0x442258
|
||||
static int FtFontGetBufferSizeImpl(const char* str)
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return FtFontGetStringWidthImpl(str) * (current->lineSpacing + current->maxHeight + current->heightOffset);
|
||||
}
|
||||
|
||||
// 0x442278
|
||||
static int FtFontGetMonospacedCharacterWidthImpl()
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return current->lineSpacing + current->maxHeight;
|
||||
}
|
||||
|
||||
// 0x4422B4
|
||||
static void FtFontDrawImpl(unsigned char* buf, const char* string, int length, int pitch, int color)
|
||||
{
|
||||
if (!gFtFontsInitialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((color & FONT_SHADOW) != 0) {
|
||||
color &= ~FONT_SHADOW;
|
||||
// NOTE: Other font options preserved. This is different from text font
|
||||
// shadows.
|
||||
FtFontDrawImpl(buf + pitch + 1, string, length, pitch, (color & ~0xFF) | _colorTable[0]);
|
||||
}
|
||||
|
||||
unsigned char* palette = _getColorBlendTable(color & 0xFF);
|
||||
int count = LtoU((char*)string, strlen(string));
|
||||
int maxTop = -1;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint32_t ch = output[i];
|
||||
|
||||
FtFontGlyph g = GetFtFontGlyph(ch);
|
||||
if (maxTop < g.top)
|
||||
maxTop = g.top;
|
||||
}
|
||||
|
||||
maxTop = current->maxHeight - maxTop;
|
||||
|
||||
unsigned char* ptr = buf;
|
||||
for (int i = 0; i < count; i++) {
|
||||
uint32_t ch = output[i];
|
||||
|
||||
FtFontGlyph g = GetFtFontGlyph(ch);
|
||||
|
||||
int characterWidth;
|
||||
if (ch == L'\n' || ch == L'\r') {
|
||||
continue;
|
||||
} else if (ch == L' ') {
|
||||
characterWidth = current->wordSpacing;
|
||||
} else if (ch == '\x95') {
|
||||
characterWidth = g.width + 2;
|
||||
} else {
|
||||
characterWidth = g.width;
|
||||
}
|
||||
|
||||
unsigned char* end = ptr + characterWidth + current->letterSpacing;
|
||||
if (end - buf > length) {
|
||||
break;
|
||||
}
|
||||
|
||||
ptr += (current->maxHeight - g.top - maxTop) * pitch;
|
||||
|
||||
unsigned char* glyphDataPtr = g.buffer;
|
||||
|
||||
for (int y = 0; y < g.rows && y < current->maxHeight; y++) {
|
||||
for (int x = 0; x < g.width; x++) {
|
||||
unsigned char byte = *glyphDataPtr++;
|
||||
byte /= 26;
|
||||
|
||||
*ptr++ = palette[(byte << 8) + *ptr];
|
||||
}
|
||||
|
||||
ptr += pitch - g.width;
|
||||
}
|
||||
|
||||
ptr = end;
|
||||
}
|
||||
|
||||
if ((color & FONT_UNDERLINE) != 0) {
|
||||
int length = ptr - buf;
|
||||
unsigned char* underlinePtr = buf + pitch * (current->maxHeight - 1);
|
||||
for (int index = 0; index < length; index++) {
|
||||
*underlinePtr++ = color & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
_freeColorBlendTable(color & 0xFF);
|
||||
}
|
||||
|
||||
static int FtFonteWordWrapImpl(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr)
|
||||
{
|
||||
breakpoints[0] = 0;
|
||||
*breakpointsLengthPtr = 1;
|
||||
|
||||
for (int index = 1; index < WORD_WRAP_MAX_COUNT; index++) {
|
||||
breakpoints[index] = -1;
|
||||
}
|
||||
|
||||
if (fontGetStringWidth(string) < width) {
|
||||
breakpoints[*breakpointsLengthPtr] = (short)strlen(string);
|
||||
*breakpointsLengthPtr += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int accum = 0;
|
||||
int prevSpaceOrHyphen = -1;
|
||||
|
||||
int count = LtoU((char*)string, strlen(string));
|
||||
|
||||
int PreCharIndex;
|
||||
|
||||
int uint32Index;
|
||||
int CharIndex = 0;
|
||||
|
||||
for (int i = 0; i < count;)
|
||||
{
|
||||
const uint32_t ch = output[i];
|
||||
|
||||
if (ch == L'\n' || ch == L'\r') {
|
||||
continue;
|
||||
}
|
||||
|
||||
FtFontGlyph g = GetFtFontGlyph(ch);
|
||||
|
||||
PreCharIndex = CharIndex;
|
||||
|
||||
if (ch == L' ' || (ch > 128 && ch < 256)) {
|
||||
accum += current->letterSpacing + current->wordSpacing;
|
||||
CharIndex += 1;
|
||||
} else {
|
||||
if (ch == '\x95')
|
||||
accum += current->letterSpacing + g.width + 2;
|
||||
else
|
||||
accum += current->letterSpacing + g.width;
|
||||
|
||||
if ((ch > 0 && ch < 128) || ch == '\x95')
|
||||
CharIndex += 1;
|
||||
else
|
||||
CharIndex += UtoL((char*)(&(output[i])), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (accum <= width) {
|
||||
// NOTE: quests.txt #807 uses extended ascii.
|
||||
if (ch == L' ' || ch == L'-') {
|
||||
prevSpaceOrHyphen = CharIndex;
|
||||
uint32Index = i;
|
||||
} else if (current->warpMode == 1) {
|
||||
prevSpaceOrHyphen = -1;
|
||||
}
|
||||
i++;
|
||||
} else {
|
||||
if (*breakpointsLengthPtr == WORD_WRAP_MAX_COUNT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (prevSpaceOrHyphen != -1) {
|
||||
// Word wrap.
|
||||
breakpoints[*breakpointsLengthPtr] = prevSpaceOrHyphen;
|
||||
|
||||
i = uint32Index + 1;
|
||||
CharIndex = prevSpaceOrHyphen + 1;
|
||||
} else {
|
||||
// Character wrap.
|
||||
breakpoints[*breakpointsLengthPtr] = PreCharIndex;
|
||||
CharIndex = PreCharIndex;
|
||||
}
|
||||
|
||||
*breakpointsLengthPtr += 1;
|
||||
prevSpaceOrHyphen = -1;
|
||||
accum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*breakpointsLengthPtr == WORD_WRAP_MAX_COUNT) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
breakpoints[*breakpointsLengthPtr] = CharIndex;
|
||||
*breakpointsLengthPtr += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace fallout
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef FREETYPE_MANAGER_H
|
||||
#define FREETYPE_MANAGER_H
|
||||
|
||||
#include "text_font.h"
|
||||
|
||||
namespace fallout {
|
||||
|
||||
extern FontManager gFtFontManager;
|
||||
|
||||
int FtFontsInit();
|
||||
void FtFontsExit();
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
#endif /* FONT_MANAGER_H */
|
10
src/game.cc
10
src/game.cc
|
@ -21,6 +21,7 @@
|
|||
#include "draw.h"
|
||||
#include "endgame.h"
|
||||
#include "font_manager.h"
|
||||
#include "freetype_manager.h"
|
||||
#include "game_dialog.h"
|
||||
#include "game_memory.h"
|
||||
#include "game_mouse.h"
|
||||
|
@ -168,8 +169,14 @@ int gameInitWithOptions(const char* windowTitle, bool isMapper, int font, int a4
|
|||
showSplash();
|
||||
}
|
||||
|
||||
interfaceFontsInit();
|
||||
if (!FtFontsInit()) {
|
||||
fontManagerAdd(&gFtFontManager);
|
||||
}
|
||||
|
||||
if (!interfaceFontsInit()) {
|
||||
fontManagerAdd(&gModernFontManager);
|
||||
}
|
||||
|
||||
fontSetCurrent(font);
|
||||
|
||||
screenshotHandlerConfigure(KEY_F12, gameTakeScreenshot);
|
||||
|
@ -461,6 +468,7 @@ void gameExit()
|
|||
wmWorldMap_exit();
|
||||
partyMembersExit();
|
||||
endgameDeathEndingExit();
|
||||
FtFontsExit();
|
||||
interfaceFontsExit();
|
||||
_windowClose();
|
||||
messageListRepositoryExit();
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "memory.h"
|
||||
#include "platform_compat.h"
|
||||
|
||||
#include "word_wrap.h"
|
||||
|
||||
namespace fallout {
|
||||
|
||||
// The maximum number of text fonts.
|
||||
|
@ -62,6 +64,7 @@ FontManager gTextFontManager = {
|
|||
textFontGetLetterSpacingImpl,
|
||||
textFontGetBufferSizeImpl,
|
||||
textFontGetMonospacedCharacterWidthImpl,
|
||||
leagcyWordWrap,
|
||||
};
|
||||
|
||||
// 0x51E3B0
|
||||
|
@ -94,6 +97,7 @@ FontManagerGetBufferSizeProc* fontGetBufferSize = NULL;
|
|||
// 0x51E3D4
|
||||
FontManagerGetMonospacedCharacterWidth* fontGetMonospacedCharacterWidth = NULL;
|
||||
|
||||
FontManageWordWrapProc* wordWrap = NULL;
|
||||
// 0x6ADB08
|
||||
static TextFontDescriptor gTextFontDescriptors[TEXT_FONT_MAX];
|
||||
|
||||
|
@ -281,6 +285,7 @@ void fontSetCurrent(int font)
|
|||
fontGetLetterSpacing = fontManager->getLetterSpacingProc;
|
||||
fontGetBufferSize = fontManager->getBufferSizeProc;
|
||||
fontGetMonospacedCharacterWidth = fontManager->getMonospacedCharacterWidthProc;
|
||||
wordWrap = fontManager->wordWrap;
|
||||
|
||||
gCurrentFont = font;
|
||||
|
||||
|
@ -427,5 +432,4 @@ static int textFontGetMonospacedCharacterWidthImpl()
|
|||
|
||||
return width + gCurrentTextFontDescriptor->letterSpacing;
|
||||
}
|
||||
|
||||
} // namespace fallout
|
||||
|
|
|
@ -13,6 +13,8 @@ typedef int FontManagerGetLetterSpacingProc();
|
|||
typedef int FontManagerGetBufferSizeProc(const char* string);
|
||||
typedef int FontManagerGetMonospacedCharacterWidth();
|
||||
|
||||
typedef int FontManageWordWrapProc(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr);
|
||||
|
||||
typedef struct FontManager {
|
||||
int minFont;
|
||||
int maxFont;
|
||||
|
@ -25,6 +27,8 @@ typedef struct FontManager {
|
|||
FontManagerGetLetterSpacingProc* getLetterSpacingProc;
|
||||
FontManagerGetBufferSizeProc* getBufferSizeProc;
|
||||
FontManagerGetMonospacedCharacterWidth* getMonospacedCharacterWidthProc;
|
||||
|
||||
FontManageWordWrapProc* wordWrap;
|
||||
} FontManager;
|
||||
|
||||
#define FONT_SHADOW (0x10000)
|
||||
|
@ -43,6 +47,8 @@ extern FontManagerGetLetterSpacingProc* fontGetLetterSpacing;
|
|||
extern FontManagerGetBufferSizeProc* fontGetBufferSize;
|
||||
extern FontManagerGetMonospacedCharacterWidth* fontGetMonospacedCharacterWidth;
|
||||
|
||||
extern FontManageWordWrapProc* wordWrap;
|
||||
|
||||
int textFontsInit();
|
||||
void textFontsExit();
|
||||
int textFontLoad(int font);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
namespace fallout {
|
||||
|
||||
// 0x4BC6F0
|
||||
int wordWrap(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr)
|
||||
extern int leagcyWordWrap(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr)
|
||||
{
|
||||
breakpoints[0] = 0;
|
||||
*breakpointsLengthPtr = 1;
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace fallout {
|
|||
|
||||
#define WORD_WRAP_MAX_COUNT (64)
|
||||
|
||||
int wordWrap(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr);
|
||||
extern int leagcyWordWrap(const char* string, int width, short* breakpoints, short* breakpointsLengthPtr);
|
||||
|
||||
} // namespace fallout
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
SET(BUILD_SHARED_LIBS FALSE)
|
||||
SET(FT_DISABLE_HARFBUZZ ON)
|
||||
SET(FT_DISABLE_PNG ON)
|
||||
SET(FT_DISABLE_BROTLI ON)
|
||||
SET(FT_DISABLE_BZIP2 ON)
|
||||
SET(FT_DISABLE_ZLIB ON)
|
||||
SET(FT_CONFIG_OPTION_USE_ZLIB OFF)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(freetype
|
||||
GIT_REPOSITORY "https://github.com/freetype/freetype"
|
||||
GIT_TAG "VER-2-12-1"
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(freetype)
|
||||
if (NOT freetype_POPULATED)
|
||||
FetchContent_Populate(freetype)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${freetype_SOURCE_DIR} ${freetype_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
|
||||
set(FREETYPE_LIBRARIES "freetype" PARENT_SCOPE)
|
||||
set(FREETYPE_INCLUDE_DIRS ${freetype_SOURCE_DIR} ${freetype_BINARY_DIR} PARENT_SCOPE)
|
||||
|
||||
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/ftoption.h" ORIGINAL_FTOPTION_H)
|
||||
file(WRITE "${freetype_BINARY_DIR}/include/freetype/config/ftoption.h" "${ORIGINAL_FTOPTION_H}")
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(iconv
|
||||
GIT_REPOSITORY "https://github.com/sonilyan/libiconv_for_fallout2ce.git"
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(iconv)
|
||||
if (NOT iconv_POPULATED)
|
||||
FetchContent_Populate(iconv)
|
||||
endif()
|
||||
|
||||
add_subdirectory(${iconv_SOURCE_DIR} ${iconv_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
|
||||
set(ICONV_LIBRARIES "iconv-static" PARENT_SCOPE)
|
||||
set(ICONV_INCLUDE_DIRS ${iconv_SOURCE_DIR} ${iconv_BINARY_DIR}/include PARENT_SCOPE)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue