diff --git a/CMakeLists.txt b/CMakeLists.txt index 4c6c918..7bc68c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/fonts/chs/font.ini b/fonts/chs/font.ini new file mode 100644 index 0000000..f8a5e8e --- /dev/null +++ b/fonts/chs/font.ini @@ -0,0 +1,55 @@ +[font0] +maxHeight= 10 +maxWidth= 10 +lineSpacing=0 +wordSpacing=4 +letterSpacing=1 +heightOffset=0 +fileName=font.ttf +warpMode=0 +encoding=GBK + +[font1] +maxHeight= 12 +maxWidth= 12 +lineSpacing=1 +wordSpacing=4 +letterSpacing=1 +heightOffset=1 +fileName=zpix.ttf +warpMode=1 +encoding=GBK + +[font2] +maxHeight= 15 +maxWidth= 15 +lineSpacing=1 +wordSpacing=3 +letterSpacing=1 +heightOffset=0 +fileName=font.ttf +warpMode=0 +encoding=GBK + +[font3] +maxHeight= 15 +maxWidth= 15 +lineSpacing=1 +wordSpacing=4 +letterSpacing=1 +heightOffset=0 +fileName=font.ttf +warpMode=0 +encoding=GBK + +[font4] +maxHeight= 22 +maxWidth= 22 +lineSpacing=1 +wordSpacing=12 +letterSpacing=1 +heightOffset=0 +fileName=font.ttf +warpMode=0 +encoding=GBK + diff --git a/fonts/chs/font.ttf b/fonts/chs/font.ttf new file mode 100644 index 0000000..37c28de Binary files /dev/null and b/fonts/chs/font.ttf differ diff --git a/fonts/chs/zpix.ttf b/fonts/chs/zpix.ttf new file mode 100644 index 0000000..64a2e62 Binary files /dev/null and b/fonts/chs/zpix.ttf differ diff --git a/fonts/english/JH_FALLOUT.TTF b/fonts/english/JH_FALLOUT.TTF new file mode 100644 index 0000000..74dedb5 Binary files /dev/null and b/fonts/english/JH_FALLOUT.TTF differ diff --git a/fonts/english/TT0807M_.TTF b/fonts/english/TT0807M_.TTF new file mode 100644 index 0000000..6844476 Binary files /dev/null and b/fonts/english/TT0807M_.TTF differ diff --git a/fonts/english/font.ini b/fonts/english/font.ini new file mode 100644 index 0000000..24d8a3c --- /dev/null +++ b/fonts/english/font.ini @@ -0,0 +1,55 @@ +[font0] +maxHeight=10 +maxWidth=10 +lineSpacing=0 +wordSpacing=4 +letterSpacing=1 +heightOffset=0 +fileName=r_fallouty.ttf +warpMode=0 +encoding=GBK + +[font1] +maxHeight=12 +maxWidth=12 +lineSpacing=0 +wordSpacing=4 +letterSpacing=1 +heightOffset=0 +fileName=r_fallouty.ttf +warpMode=0 +encoding=GBK + +[font2] +maxHeight=15 +maxWidth=15 +lineSpacing=1 +wordSpacing=3 +letterSpacing=1 +heightOffset=0 +fileName=r_fallouty.ttf +warpMode=0 +encoding=GBK + +[font3] +maxHeight=15 +maxWidth=15 +lineSpacing=1 +wordSpacing=4 +letterSpacing=1 +heightOffset=0 +fileName=r_fallouty.ttf +warpMode=0 +encoding=GBK + +[font4] +maxHeight=24 +maxWidth=24 +lineSpacing=1 +wordSpacing=12 +letterSpacing=1 +heightOffset=0 +fileName=TT0807M_.TTF +warpMode=0 +encoding=GBK + diff --git a/fonts/english/r_fallouty.ttf b/fonts/english/r_fallouty.ttf new file mode 100644 index 0000000..8d3342e Binary files /dev/null and b/fonts/english/r_fallouty.ttf differ diff --git a/src/character_editor.cc b/src/character_editor.cc index 70563ec..9a02bb5 100644 --- a/src/character_editor.cc +++ b/src/character_editor.cc @@ -2390,7 +2390,9 @@ static void characterEditorDrawPcStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 32, stringBuffer, 640, 640, color); // EXPERIENCE - y += fontGetLineHeight() + 1; + //y += fontGetLineHeight() + 1; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 10 + 1; if (characterEditorSelectedItem != 8) { color = _colorTable[992]; } else { @@ -2404,7 +2406,9 @@ static void characterEditorDrawPcStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 32, stringBuffer, 640, 640, color); // EXP NEEDED TO NEXT LEVEL - y += fontGetLineHeight() + 1; + //y += fontGetLineHeight() + 1; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 10 + 1; if (characterEditorSelectedItem != 9) { color = _colorTable[992]; } else { @@ -2656,8 +2660,12 @@ static void characterEditorDrawDerivedStats() snprintf(t, sizeof(t), "%d/%d", currHp, maxHp); fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 263, t, 640, 640, color); + + // Poisoned - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_POISONED) { color = critterGetPoison(gDude) != 0 ? _colorTable[32747] : _colorTable[15845]; @@ -2670,7 +2678,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Radiated - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_RADIATED) { color = critterGetRadiation(gDude) != 0 ? _colorTable[32747] : _colorTable[15845]; @@ -2683,7 +2693,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Eye Damage - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_EYE_DAMAGE) { color = (conditions & DAM_BLIND) ? _colorTable[32747] : _colorTable[15845]; @@ -2696,7 +2708,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Crippled Right Arm - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_CRIPPLED_RIGHT_ARM) { color = (conditions & DAM_CRIP_ARM_RIGHT) ? _colorTable[32747] : _colorTable[15845]; @@ -2709,7 +2723,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Crippled Left Arm - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_CRIPPLED_LEFT_ARM) { color = (conditions & DAM_CRIP_ARM_LEFT) ? _colorTable[32747] : _colorTable[15845]; @@ -2722,7 +2738,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Crippled Right Leg - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_CRIPPLED_RIGHT_LEG) { color = (conditions & DAM_CRIP_LEG_RIGHT) ? _colorTable[32747] : _colorTable[15845]; @@ -2735,7 +2753,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 194, t, 640, 640, color); // Crippled Left Leg - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_CRIPPLED_LEFT_LEG) { color = (conditions & DAM_CRIP_LEG_LEFT) ? _colorTable[32747] : _colorTable[15845]; @@ -2766,7 +2786,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Action Points - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_ACTION_POINTS) { color = _colorTable[32747]; @@ -2782,7 +2804,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Carry Weight - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_CARRY_WEIGHT) { color = _colorTable[32747]; @@ -2798,7 +2822,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, critterIsEncumbered(gDude) ? _colorTable[31744] : color); // Melee Damage - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_MELEE_DAMAGE) { color = _colorTable[32747]; @@ -2820,7 +2846,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Damage Resistance - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_DAMAGE_RESISTANCE) { color = _colorTable[32747]; @@ -2836,7 +2864,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Poison Resistance - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_POISON_RESISTANCE) { color = _colorTable[32747]; @@ -2852,7 +2882,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Radiation Resistance - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_RADIATION_RESISTANCE) { color = _colorTable[32747]; @@ -2868,7 +2900,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Sequence - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_SEQUENCE) { color = _colorTable[32747]; @@ -2884,7 +2918,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Healing Rate - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_HEALING_RATE) { color = _colorTable[32747]; @@ -2900,7 +2936,9 @@ static void characterEditorDrawDerivedStats() fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 288, t, 640, 640, color); // Critical Chance - y += fontGetLineHeight() + 3; + //y += fontGetLineHeight() + 3; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + y += 13; if (characterEditorSelectedItem == EDITOR_FIRST_DERIVED_STAT + EDITOR_DERIVED_STAT_CRITICAL_CHANCE) { color = _colorTable[32747]; @@ -2994,11 +3032,15 @@ static void characterEditorDrawSkills(int a1) fontDrawText(gCharacterEditorWindowBuffer + 640 * y + 573, valueString, 640, 640, color); - y += fontGetLineHeight() + 1; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + //y += fontGetLineHeight() + 1; + y += 10 + 1; } if (!gCharacterEditorIsCreationMode) { - y = gCharacterEditorCurrentSkill * (fontGetLineHeight() + 1); + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + //y = gCharacterEditorCurrentSkill * (fontGetLineHeight() + 1); + y = gCharacterEditorCurrentSkill * (10 + 1); gCharacterEditorSkillValueAdjustmentSliderY = y + 27; blitBufferToBufferTrans( @@ -5132,7 +5174,9 @@ static void characterEditorHandleInfoButtonPressed(int eventCode) double mouseY = gCharacterEditorMouseY; double fontLineHeight = fontGetLineHeight(); double y = 353.0; - double step = fontGetLineHeight() + 3 + 0.56; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + //double step = fontGetLineHeight() + 3 + 0.56; + double step = 10 + 3 + 0.56; int index; for (index = 0; index < 8; index++) { if (mouseY >= y - 4.0 && mouseY <= y + fontLineHeight) { @@ -5397,7 +5441,9 @@ static void characterEditorDrawOptionalTraits() traitsSetSelected(gCharacterEditorTempTraits[0], gCharacterEditorTempTraits[1]); - step = fontGetLineHeight() + 3 + 0.56; + //step = fontGetLineHeight() + 3 + 0.56; + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + step = 10 + 3 + 0.56; y = 353; for (i = 0; i < 8; i++) { if (i == v0) { @@ -6300,8 +6346,8 @@ static int perkDialogDrawPerks() qsort(gPerkDialogOptionList, count, sizeof(*gPerkDialogOptionList), perkDialogOptionCompare); int v16 = count - gPerkDialogTopLine; - if (v16 > 11) { - v16 = 11; + if (v16 > 11 * 12 / (fontGetLineHeight() + 2)) { + v16 = 11 * 12 / (fontGetLineHeight() + 2); } v16 += gPerkDialogTopLine; diff --git a/src/character_selector.cc b/src/character_selector.cc index adcb9d1..532eb62 100644 --- a/src/character_selector.cc +++ b/src/character_selector.cc @@ -621,7 +621,10 @@ static bool characterSelectorWindowRenderStats() fontGetCharacterWidth(0x20); - int vh = fontGetLineHeight(); + + // Adapt to other languages, because the pixels here are fixed, so the calculation of LineHeight brings trouble - replaces it with fixed pixel values + //int vh = fontGetLineHeight(); + int vh = 11; int y = 40; // NAME diff --git a/src/dbox.cc b/src/dbox.cc index eee9345..43e11bd 100644 --- a/src/dbox.cc +++ b/src/dbox.cc @@ -456,8 +456,8 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i backgroundFrmImage.getWidth(), titleColor); } - nextY += fontGetLineHeight(); - } + //nextY += fontGetLineHeight(); + nextY += 10; } for (int index = 0; index < bodyLength && nextY < maxY; index++) { int width = fontGetStringWidth(body[index]); @@ -477,7 +477,8 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i backgroundFrmImage.getWidth(), bodyColor); } - nextY += fontGetLineHeight(); + //nextY += fontGetLineHeight(); + nextY += 10; } else { short beginnings[WORD_WRAP_MAX_COUNT]; short count; @@ -515,8 +516,8 @@ int showDialogBox(const char* title, const char** body, int bodyLength, int x, i backgroundFrmImage.getWidth(), bodyColor); } - nextY += fontGetLineHeight(); - } + //nextY += fontGetLineHeight(); + nextY += 10; } } } diff --git a/src/display_monitor.cc b/src/display_monitor.cc index f28e589..bdc27b1 100644 --- a/src/display_monitor.cc +++ b/src/display_monitor.cc @@ -18,6 +18,7 @@ #include "svga.h" #include "text_font.h" #include "window_manager.h" +#include "word_wrap.h" namespace fallout { @@ -26,7 +27,7 @@ namespace fallout { #define DISPLAY_MONITOR_LINES_CAPACITY (100) // The maximum length of a string in display monitor (in characters). -#define DISPLAY_MONITOR_LINE_LENGTH (80) +#define DISPLAY_MONITOR_LINE_LENGTH (280) #define DISPLAY_MONITOR_X (23) #define DISPLAY_MONITOR_Y (24) @@ -113,6 +114,7 @@ int displayMonitorInit() gDisplayMonitorLinesCapacity = DISPLAY_MONITOR_LINES_CAPACITY; _max_disp = DISPLAY_MONITOR_HEIGHT / fontGetLineHeight(); + if (_max_disp < 5) _max_disp = 5; _disp_start = 0; _disp_curr = 0; fontSetCurrent(oldFont); @@ -241,13 +243,6 @@ void displayMonitorAddMessage(char* str) int oldFont = fontGetCurrent(); fontSetCurrent(DISPLAY_MONITOR_FONT); - char knob = '\x95'; - - char knobString[2]; - knobString[0] = knob; - knobString[1] = '\0'; - int knobWidth = fontGetStringWidth(knobString); - if (!isInCombat()) { unsigned int now = _get_bk_time(); if (getTicksBetween(now, gDisplayMonitorLastBeepTimestamp) >= DISPLAY_MONITOR_BEEP_DELAY) { @@ -255,66 +250,31 @@ void displayMonitorAddMessage(char* str) soundPlayFile("monitor"); } } + + short beginnings[WORD_WRAP_MAX_COUNT] = { + -1, + }; + short count = -1; - // TODO: Refactor these two loops. - char* v1 = NULL; - while (true) { - while (fontGetStringWidth(str) < DISPLAY_MONITOR_WIDTH - _max_disp - knobWidth) { - char* temp = gDisplayMonitorLines[_disp_start]; - int length; - if (knob != '\0') { - *temp++ = knob; - length = DISPLAY_MONITOR_LINE_LENGTH - 2; - knob = '\0'; - knobWidth = 0; - } else { - length = DISPLAY_MONITOR_LINE_LENGTH - 1; - } - strncpy(temp, str, length); - gDisplayMonitorLines[_disp_start][DISPLAY_MONITOR_LINE_LENGTH - 1] = '\0'; - _disp_start = (_disp_start + 1) % gDisplayMonitorLinesCapacity; + char start[2048]; - if (v1 == NULL) { - fontSetCurrent(oldFont); - _disp_curr = _disp_start; - displayMonitorRefresh(); - return; - } + start[0] = '\x95'; + strcpy(start + 1, str); - str = v1 + 1; - *v1 = ' '; - v1 = NULL; - } - - char* space = strrchr(str, ' '); - if (space == NULL) { - break; - } - - if (v1 != NULL) { - *v1 = ' '; - } - - v1 = space; - if (space != NULL) { - *space = '\0'; - } + if (wordWrap(start, DISPLAY_MONITOR_WIDTH, beginnings, &count) != 0) { + // FIXME: Leaks handle. + return; } - char* temp = gDisplayMonitorLines[_disp_start]; - int length; - if (knob != '\0') { - temp++; - gDisplayMonitorLines[_disp_start][0] = knob; - length = DISPLAY_MONITOR_LINE_LENGTH - 2; - knob = '\0'; - } else { - length = DISPLAY_MONITOR_LINE_LENGTH - 1; - } - strncpy(temp, str, length); + for (int index = 0; index < count - 1; index++) { + char* beginning = start + beginnings[index]; + char* ending = start + beginnings[index + 1]; - gDisplayMonitorLines[_disp_start][DISPLAY_MONITOR_LINE_LENGTH - 1] = '\0'; - _disp_start = (_disp_start + 1) % gDisplayMonitorLinesCapacity; + memcpy(gDisplayMonitorLines[_disp_start], beginning, ending - beginning); + gDisplayMonitorLines[_disp_start][ending - beginning] = '\0'; + + _disp_start = (_disp_start + 1) % gDisplayMonitorLinesCapacity; + } fontSetCurrent(oldFont); _disp_curr = _disp_start; @@ -362,9 +322,10 @@ static void displayMonitorRefresh() int oldFont = fontGetCurrent(); fontSetCurrent(DISPLAY_MONITOR_FONT); + int tmp = fontGetLineHeight() > 12 ? 12 : fontGetLineHeight(); for (int index = 0; index < _max_disp; index++) { int stringIndex = (_disp_curr + gDisplayMonitorLinesCapacity + index - _max_disp) % gDisplayMonitorLinesCapacity; - fontDrawText(buf + index * _intface_full_width * fontGetLineHeight(), gDisplayMonitorLines[stringIndex], DISPLAY_MONITOR_WIDTH, _intface_full_width, _colorTable[992]); + fontDrawText(buf + index * _intface_full_width * tmp, gDisplayMonitorLines[stringIndex], DISPLAY_MONITOR_WIDTH, _intface_full_width, _colorTable[992]); // Even though the display monitor is rectangular, it's graphic is not. // To give a feel of depth it's covered by some metal canopy and diff --git a/src/font_manager.cc b/src/font_manager.cc index 6a49077..f753085 100644 --- a/src/font_manager.cc +++ b/src/font_manager.cc @@ -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 diff --git a/src/freetype_manager.cc b/src/freetype_manager.cc new file mode 100644 index 0000000..995ab99 --- /dev/null +++ b/src/freetype_manager.cc @@ -0,0 +1,596 @@ +#include "font_manager.h" + +#include +#include + +#include "color.h" +#include "db.h" +#include "memory_manager.h" + +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_BITMAP_H + +#include "config.h" + +#include "word_wrap.h" + +#include +#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 maxWidth; + int letterSpacing; + int wordSpacing; + int lineSpacing; + int heightOffset; + int warpMode; + char encoding[64]; + + std::map 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, "maxWidth", &desc->maxWidth)) { + desc->maxWidth = desc->maxHeight; + } + 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->maxWidth, 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 diff --git a/src/freetype_manager.h b/src/freetype_manager.h new file mode 100644 index 0000000..c37302a --- /dev/null +++ b/src/freetype_manager.h @@ -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 */ diff --git a/src/game.cc b/src/game.cc index abe6613..e2ae2a0 100644 --- a/src/game.cc +++ b/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(); - fontManagerAdd(&gModernFontManager); + 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(); diff --git a/src/game_dialog.cc b/src/game_dialog.cc index 48a6518..6aa4069 100644 --- a/src/game_dialog.cc +++ b/src/game_dialog.cc @@ -40,6 +40,7 @@ #include "text_object.h" #include "tile.h" #include "window_manager.h" +#include "word_wrap.h" namespace fallout { @@ -589,7 +590,7 @@ static void gameDialogTicker(); static void _gdialog_scroll_subwin(int a1, int a2, unsigned char* a3, unsigned char* a4, unsigned char* a5, int a6, int a7); static int _text_num_lines(const char* a1, int a2); static int text_to_rect_wrapped(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color); -static int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color, int a7); +static int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color); static int _gdialog_barter_create_win(); static void _gdialog_barter_destroy_win(); static void _gdialog_barter_cleanup_tables(); @@ -3040,117 +3041,64 @@ int _text_num_lines(const char* a1, int a2) // 0x447F80 static int text_to_rect_wrapped(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color) { - return gameDialogDrawText(buffer, rect, string, a4, height, pitch, color, 1); + return gameDialogDrawText(buffer, rect, string, a4, height, pitch, color); } // display_msg // 0x447FA0 -int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* a4, int height, int pitch, int color, int a7) +int gameDialogDrawText(unsigned char* buffer, Rect* rect, char* string, int* offset, int height, int pitch, int color) { + short beginnings[WORD_WRAP_MAX_COUNT] = { + -1, + }; + short count = -1; + + int maxWidth = rect->right - rect->left; char* start; - if (a4 != NULL) { - start = string + *a4; + + if (offset != NULL) { + start = string + *offset; } else { start = string; } - int maxWidth = rect->right - rect->left; - char* end = NULL; - while (start != NULL && *start != '\0') { - if (fontGetStringWidth(start) > maxWidth) { - end = start + 1; - while (*end != '\0' && *end != ' ') { - end++; - } - - if (*end != '\0') { - char* lookahead = end + 1; - while (lookahead != NULL) { - while (*lookahead != '\0' && *lookahead != ' ') { - lookahead++; - } - - if (*lookahead == '\0') { - lookahead = NULL; - } else { - *lookahead = '\0'; - if (fontGetStringWidth(start) >= maxWidth) { - *lookahead = ' '; - lookahead = NULL; - } else { - end = lookahead; - *lookahead = ' '; - lookahead++; - } - } - } - - if (*end == ' ') { - *end = '\0'; - } - } else { - if (rect->bottom - fontGetLineHeight() < rect->top) { - return rect->top; - } - - if (a7 != 1 || start == string) { - fontDrawText(buffer + pitch * rect->top + 10, start, maxWidth, pitch, color); - } else { - fontDrawText(buffer + pitch * rect->top, start, maxWidth, pitch, color); - } - - if (a4 != NULL) { - *a4 += static_cast(strlen(start)) + 1; - } - - rect->top += height; - return rect->top; + if (wordWrap(start, maxWidth, beginnings, &count) != 0) { + // FIXME: Leaks handle. + return rect->top; + } + + int tmp = 0; + for (int index = 0; index < count - 1; index++) { + if (rect->top + height > rect->bottom) { + if (offset != NULL) { + *offset = tmp; } + return rect->top; } - if (fontGetStringWidth(start) > maxWidth) { - debugPrint("\nError: display_msg: word too long!"); - break; - } + char* beginning = start + beginnings[index]; + char* ending = start + beginnings[index + 1]; - if (a7 != 0) { - if (rect->bottom - fontGetLineHeight() < rect->top) { - if (end != NULL && *end == '\0') { - *end = ' '; - } - return rect->top; - } - - unsigned char* dest; - if (a7 != 1 || start == string) { - dest = buffer + 10; - } else { - dest = buffer; - } - fontDrawText(dest + pitch * rect->top, start, maxWidth, pitch, color); - } - - if (a4 != NULL && end != NULL) { - *a4 += static_cast(strlen(start)) + 1; - } - - rect->top += height; - - if (end != NULL) { - start = end + 1; - if (*end == '\0') { - *end = ' '; - } - end = NULL; + char tmpchar = ending[0]; + ending[0] = '\0'; + if (beginning == string) { + fontDrawText(buffer + pitch * rect->top + 10, beginning, maxWidth, pitch, color); } else { - start = NULL; + fontDrawText(buffer + pitch * rect->top, beginning, maxWidth, pitch, color); } - } + ending[0] = tmpchar; - if (a4 != NULL) { - *a4 = 0; - } + tmp += ending - beginning; + if (offset != NULL) { + *offset += ending - beginning; + } + rect->top += height; + } + + if (offset != NULL) { + *offset = 0; + } return rect->top; } diff --git a/src/inventory.cc b/src/inventory.cc index 351584c..51d399f 100644 --- a/src/inventory.cc +++ b/src/inventory.cc @@ -2894,14 +2894,14 @@ static void inventoryRenderSummary() bufferDrawLine(windowBuffer, INVENTORY_WINDOW_WIDTH, INVENTORY_SUMMARY_X, - 3 * fontGetLineHeight() / 2 + INVENTORY_SUMMARY_Y, + 3 * 10 / 2 + INVENTORY_SUMMARY_Y, INVENTORY_SUMMARY_MAX_X, - 3 * fontGetLineHeight() / 2 + INVENTORY_SUMMARY_Y, + 3 * 10 / 2 + INVENTORY_SUMMARY_Y, _colorTable[992]); MessageListItem messageListItem; - int offset = INVENTORY_WINDOW_WIDTH * 2 * fontGetLineHeight() + INVENTORY_WINDOW_WIDTH * INVENTORY_SUMMARY_Y + INVENTORY_SUMMARY_X; + int offset = INVENTORY_WINDOW_WIDTH * 2 * 10 + INVENTORY_WINDOW_WIDTH * INVENTORY_SUMMARY_Y + INVENTORY_SUMMARY_X; for (int stat = 0; stat < 7; stat++) { messageListItem.num = stat; if (messageListGetItem(&gInventoryMessageList, &messageListItem)) { @@ -2912,10 +2912,10 @@ static void inventoryRenderSummary() snprintf(formattedText, sizeof(formattedText), "%d", value); fontDrawText(windowBuffer + offset + 24, formattedText, 80, INVENTORY_WINDOW_WIDTH, _colorTable[992]); - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; } - offset -= INVENTORY_WINDOW_WIDTH * 7 * fontGetLineHeight(); + offset -= INVENTORY_WINDOW_WIDTH * 7 * 10; for (int index = 0; index < 7; index += 1) { messageListItem.num = 7 + index; @@ -2935,11 +2935,11 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset + 104, formattedText, 80, INVENTORY_WINDOW_WIDTH, _colorTable[992]); - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; } - bufferDrawLine(windowBuffer, INVENTORY_WINDOW_WIDTH, INVENTORY_SUMMARY_X, 18 * fontGetLineHeight() / 2 + 48, INVENTORY_SUMMARY_MAX_X, 18 * fontGetLineHeight() / 2 + 48, _colorTable[992]); - bufferDrawLine(windowBuffer, INVENTORY_WINDOW_WIDTH, INVENTORY_SUMMARY_X, 26 * fontGetLineHeight() / 2 + 48, INVENTORY_SUMMARY_MAX_X, 26 * fontGetLineHeight() / 2 + 48, _colorTable[992]); + bufferDrawLine(windowBuffer, INVENTORY_WINDOW_WIDTH, INVENTORY_SUMMARY_X, 18 * 10 / 2 + 48, INVENTORY_SUMMARY_MAX_X, 18 * 10 / 2 + 48, _colorTable[992]); + bufferDrawLine(windowBuffer, INVENTORY_WINDOW_WIDTH, INVENTORY_SUMMARY_X, 26 * 10 / 2 + 48, INVENTORY_SUMMARY_MAX_X, 26 * 10 / 2 + 48, _colorTable[992]); Object* itemsInHands[2] = { gInventoryLeftHandItem, @@ -2961,7 +2961,7 @@ static void inventoryRenderSummary() HIT_MODE_KICK, }; - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; for (int index = 0; index < 2; index += 1) { Object* item = itemsInHands[index]; @@ -2974,7 +2974,7 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset, messageListItem.text, 120, INVENTORY_WINDOW_WIDTH, _colorTable[992]); } - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; // Unarmed dmg: messageListItem.num = 24; @@ -3010,14 +3010,14 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset, formattedText, 120, INVENTORY_WINDOW_WIDTH, _colorTable[992]); - offset += 3 * INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += 3 * INVENTORY_WINDOW_WIDTH * 10; continue; } const char* itemName = itemGetName(item); fontDrawText(windowBuffer + offset, itemName, 140, INVENTORY_WINDOW_WIDTH, _colorTable[992]); - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; int itemType = itemGetType(item); if (itemType != ITEM_TYPE_WEAPON) { @@ -3029,7 +3029,7 @@ static void inventoryRenderSummary() } } - offset += 3 * INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += 3 * INVENTORY_WINDOW_WIDTH * 10; continue; } @@ -3108,7 +3108,7 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset, formattedText, 140, INVENTORY_WINDOW_WIDTH, _colorTable[992]); } - offset += INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += INVENTORY_WINDOW_WIDTH * 10; if (ammoGetCapacity(item) > 0) { int ammoTypePid = weaponGetAmmoTypePid(item); @@ -3138,7 +3138,7 @@ static void inventoryRenderSummary() fontDrawText(windowBuffer + offset, formattedText, 140, INVENTORY_WINDOW_WIDTH, _colorTable[992]); } - offset += 2 * INVENTORY_WINDOW_WIDTH * fontGetLineHeight(); + offset += 2 * INVENTORY_WINDOW_WIDTH * 10; } // Total wt: @@ -3637,7 +3637,7 @@ static void inventoryExamineItem(Object* critter, Object* item) if (backgroundFrmImage.lock(backgroundFid)) { blitBufferToBuffer(backgroundFrmImage.getData() + INVENTORY_WINDOW_WIDTH * INVENTORY_SUMMARY_Y + INVENTORY_SUMMARY_X, 152, - 188, + 200, INVENTORY_WINDOW_WIDTH, windowBuffer + INVENTORY_WINDOW_WIDTH * INVENTORY_SUMMARY_Y + INVENTORY_SUMMARY_X, INVENTORY_WINDOW_WIDTH); diff --git a/src/loadsave.cc b/src/loadsave.cc index 645dcab..4bb83dc 100644 --- a/src/loadsave.cc +++ b/src/loadsave.cc @@ -554,7 +554,8 @@ int lsgSaveGame(int mode) int mouseY; mouseGetPositionInWindow(gLoadSaveWindow, &mouseX, &mouseY); - _slot_cursor = (mouseY - 79) / (3 * fontGetLineHeight() + 4); + //_slot_cursor = (mouseY - 79) / (3 * fontGetLineHeight() + 4); + _slot_cursor = (mouseY - 79) / (3 * 10 + 4); if (_slot_cursor < 0) { _slot_cursor = 0; } @@ -1059,7 +1060,8 @@ int lsgLoadGame(int mode) int mouseY; mouseGetPositionInWindow(gLoadSaveWindow, &mouseX, &mouseY); - int clickedSlot = (mouseY - 79) / (3 * fontGetLineHeight() + 4); + //int clickedSlot = (mouseY - 79) / (3 * fontGetLineHeight() + 4); + int clickedSlot = (mouseY - 79) / (3 * 10 + 4); if (clickedSlot < 0) { clickedSlot = 0; } else if (clickedSlot > 9) { @@ -2042,7 +2044,8 @@ static void _ShowSlotList(int windowType) snprintf(_str, sizeof(_str), "[ %s %.2d: ]", text, index + 1); fontDrawText(gLoadSaveWindowBuffer + LS_WINDOW_WIDTH * y + 55, _str, LS_WINDOW_WIDTH, LS_WINDOW_WIDTH, color); - y += fontGetLineHeight(); + y += 10; + //fontGetLineHeight(); switch (_LSstatus[index]) { case SLOT_STATE_OCCUPIED: strcpy(_str, _LSData[index].description); @@ -2067,7 +2070,8 @@ static void _ShowSlotList(int windowType) } fontDrawText(gLoadSaveWindowBuffer + LS_WINDOW_WIDTH * y + 55, _str, LS_WINDOW_WIDTH, LS_WINDOW_WIDTH, color); - y += 2 * fontGetLineHeight() + 4; + //y += 2 * fontGetLineHeight() + 4; + y += 2 * 10 + 4; } } @@ -2094,7 +2098,8 @@ static void _DrawInfoBox(int slot) ptr->gameYear, 100 * ((ptr->gameTime / 600) / 60 % 24) + (ptr->gameTime / 600) % 60); - int v2 = fontGetLineHeight(); + int v2 = 10; + //fontGetLineHeight(); fontDrawText(gLoadSaveWindowBuffer + LS_WINDOW_WIDTH * (256 + v2) + 397, _str, LS_WINDOW_WIDTH, LS_WINDOW_WIDTH, color); snprintf(_str, @@ -2303,7 +2308,8 @@ static int _get_input_str2(int win, int doneKeyCode, int cancelKeyCode, char* de { int cursorWidth = fontGetStringWidth("_") - 4; int windowWidth = windowGetWidth(win); - int lineHeight = fontGetLineHeight(); + int lineHeight = 10; + //fontGetLineHeight(); unsigned char* windowBuffer = windowGetBuffer(win); if (maxLength > 255) { maxLength = 255; diff --git a/src/pipboy.cc b/src/pipboy.cc index 45f79db..e5f3c45 100644 --- a/src/pipboy.cc +++ b/src/pipboy.cc @@ -396,6 +396,10 @@ static int gPipboyPrevTab; static FrmImage _pipboyFrmImages[PIPBOY_FRM_COUNT]; +static int pipboyLineMax() +{ + return PIPBOY_HOLODISK_LINES_MAX * 10 / fontGetLineHeight(); +} // 0x497004 int pipboyOpen(int intent) { @@ -506,7 +510,8 @@ static int pipboyWindowInit(int intent) _rest_time = 0; gPipboyCurrentLine = 0; gPipboyWindowButtonCount = 0; - gPipboyLinesCount = PIPBOY_WINDOW_CONTENT_VIEW_HEIGHT / fontGetLineHeight() - 1; + //gPipboyLinesCount = PIPBOY_WINDOW_CONTENT_VIEW_HEIGHT / fontGetLineHeight() - 1; + gPipboyLinesCount = PIPBOY_WINDOW_CONTENT_VIEW_HEIGHT / 10 - 1; gPipboyWindowButtonStart = 0; _hot_back_line = 0; @@ -808,6 +813,43 @@ static void pipboyDrawText(const char* text, int flags, int color) left += 260 - length; } + //fontDrawText(gPipboyWindowBuffer + PIPBOY_WINDOW_WIDTH * (gPipboyCurrentLine * fontGetLineHeight() + PIPBOY_WINDOW_CONTENT_VIEW_Y) + PIPBOY_WINDOW_CONTENT_VIEW_X + left, text, PIPBOY_WINDOW_WIDTH, PIPBOY_WINDOW_WIDTH, color); + fontDrawText(gPipboyWindowBuffer + PIPBOY_WINDOW_WIDTH * (gPipboyCurrentLine * 10 + PIPBOY_WINDOW_CONTENT_VIEW_Y) + PIPBOY_WINDOW_CONTENT_VIEW_X + left, text, PIPBOY_WINDOW_WIDTH, PIPBOY_WINDOW_WIDTH, color); + + if ((flags & PIPBOY_TEXT_STYLE_STRIKE_THROUGH) != 0) { + //int top = gPipboyCurrentLine * fontGetLineHeight() + 49; + int top = gPipboyCurrentLine * 10 + 49; + bufferDrawLine(gPipboyWindowBuffer, PIPBOY_WINDOW_WIDTH, PIPBOY_WINDOW_CONTENT_VIEW_X + left, top, PIPBOY_WINDOW_CONTENT_VIEW_X + left + length, top, color); + } + + if (gPipboyCurrentLine < gPipboyLinesCount) { + gPipboyCurrentLine += 1; + } +} + +static void pipboyDrawTextLegacy(const char* text, int flags, int color) +{ + if ((flags & PIPBOY_TEXT_STYLE_UNDERLINE) != 0) { + color |= FONT_UNDERLINE; + } + + int left = 8; + if ((flags & PIPBOY_TEXT_NO_INDENT) != 0) { + left -= 7; + } + + int length = fontGetStringWidth(text); + + if ((flags & PIPBOY_TEXT_ALIGNMENT_CENTER) != 0) { + left = (350 - length) / 2; + } else if ((flags & PIPBOY_TEXT_ALIGNMENT_RIGHT_COLUMN) != 0) { + left += 175; + } else if ((flags & PIPBOY_TEXT_ALIGNMENT_LEFT_COLUMN_CENTER) != 0) { + left += 86 - length + 16; + } else if ((flags & PIPBOY_TEXT_ALIGNMENT_RIGHT_COLUMN_CENTER) != 0) { + left += 260 - length; + } + fontDrawText(gPipboyWindowBuffer + PIPBOY_WINDOW_WIDTH * (gPipboyCurrentLine * fontGetLineHeight() + PIPBOY_WINDOW_CONTENT_VIEW_Y) + PIPBOY_WINDOW_CONTENT_VIEW_X + left, text, PIPBOY_WINDOW_WIDTH, PIPBOY_WINDOW_WIDTH, color); if ((flags & PIPBOY_TEXT_STYLE_STRIKE_THROUGH) != 0) { @@ -1274,7 +1316,7 @@ static void pipboyRenderHolodiskText() } linesCount += 1; - if (linesCount >= PIPBOY_HOLODISK_LINES_MAX) { + if (linesCount >= pipboyLineMax()) { linesCount = 0; gPipboyHolodiskLastPage += 1; } @@ -1297,7 +1339,7 @@ static void pipboyRenderHolodiskText() } numberOfLines += 1; - if (numberOfLines >= PIPBOY_HOLODISK_LINES_MAX) { + if (numberOfLines >= pipboyLineMax()) { page += 1; if (page >= _view_page) { break; @@ -1331,7 +1373,7 @@ static void pipboyRenderHolodiskText() gPipboyCurrentLine = 3; } - for (int line = 0; line < PIPBOY_HOLODISK_LINES_MAX; line += 1) { + for (int line = 0; line < pipboyLineMax(); line += 1) { const char* text = getmsg(&gPipboyMessageList, &gPipboyMessageListItem, holodiskTextId); if (strcmp(text, "**END-DISK**") == 0) { break; @@ -1340,7 +1382,7 @@ static void pipboyRenderHolodiskText() if (strcmp(text, "**END-PAR**") == 0) { gPipboyCurrentLine += 1; } else { - pipboyDrawText(text, PIPBOY_TEXT_NO_INDENT, _colorTable[992]); + pipboyDrawTextLegacy(text, PIPBOY_TEXT_NO_INDENT, _colorTable[992]); } holodiskTextId += 1; @@ -1896,7 +1938,8 @@ static void pipboyWindowCreateButtons(int start, int count, bool a3) { fontSetCurrent(101); - int height = fontGetLineHeight(); + //int height = fontGetLineHeight(); + int height = 10; gPipboyWindowButtonStart = start; gPipboyWindowButtonCount = count; diff --git a/src/text_font.cc b/src/text_font.cc index a77c16d..f94d709 100644 --- a/src/text_font.cc +++ b/src/text_font.cc @@ -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 diff --git a/src/text_font.h b/src/text_font.h index 2ea5360..fbd531c 100644 --- a/src/text_font.h +++ b/src/text_font.h @@ -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); diff --git a/src/word_wrap.cc b/src/word_wrap.cc index 9953418..9cfb2bb 100644 --- a/src/word_wrap.cc +++ b/src/word_wrap.cc @@ -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; diff --git a/src/word_wrap.h b/src/word_wrap.h index 1f720d1..2048a7c 100644 --- a/src/word_wrap.h +++ b/src/word_wrap.h @@ -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 diff --git a/third_party/freetype/CMakeLists.txt b/third_party/freetype/CMakeLists.txt new file mode 100644 index 0000000..a6d338b --- /dev/null +++ b/third_party/freetype/CMakeLists.txt @@ -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}") + diff --git a/third_party/freetype/ftoption.h b/third_party/freetype/ftoption.h new file mode 100644 index 0000000..9141697 --- /dev/null +++ b/third_party/freetype/ftoption.h @@ -0,0 +1,1029 @@ +/**************************************************************************** + * + * ftoption.h + * + * User-selectable configuration macros (specification only). + * + * Copyright (C) 1996-2022 by + * David Turner, Robert Wilhelm, and Werner Lemberg. + * + * This file is part of the FreeType project, and may only be used, + * modified, and distributed under the terms of the FreeType project + * license, LICENSE.TXT. By continuing to use, modify, or distribute + * this file you indicate that you have read the license and + * understand and accept it fully. + * + */ + + +#ifndef FTOPTION_H_ +#define FTOPTION_H_ + + +#include + + +FT_BEGIN_HEADER + + /************************************************************************** + * + * USER-SELECTABLE CONFIGURATION MACROS + * + * This file contains the default configuration macro definitions for a + * standard build of the FreeType library. There are three ways to use + * this file to build project-specific versions of the library: + * + * - You can modify this file by hand, but this is not recommended in + * cases where you would like to build several versions of the library + * from a single source directory. + * + * - You can put a copy of this file in your build directory, more + * precisely in `$BUILD/freetype/config/ftoption.h`, where `$BUILD` is + * the name of a directory that is included _before_ the FreeType include + * path during compilation. + * + * The default FreeType Makefiles use the build directory + * `builds/` by default, but you can easily change that for your + * own projects. + * + * - Copy the file to `$BUILD/ft2build.h` and modify it + * slightly to pre-define the macro `FT_CONFIG_OPTIONS_H` used to locate + * this file during the build. For example, + * + * ``` + * #define FT_CONFIG_OPTIONS_H + * #include + * ``` + * + * will use `$BUILD/myftoptions.h` instead of this file for macro + * definitions. + * + * Note also that you can similarly pre-define the macro + * `FT_CONFIG_MODULES_H` used to locate the file listing of the modules + * that are statically linked to the library at compile time. By + * default, this file is ``. + * + * We highly recommend using the third method whenever possible. + * + */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** G E N E R A L F R E E T Y P E 2 C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /*#************************************************************************ + * + * If you enable this configuration option, FreeType recognizes an + * environment variable called `FREETYPE_PROPERTIES`, which can be used to + * control the various font drivers and modules. The controllable + * properties are listed in the section @properties. + * + * You have to undefine this configuration option on platforms that lack + * the concept of environment variables (and thus don't have the `getenv` + * function), for example Windows CE. + * + * `FREETYPE_PROPERTIES` has the following syntax form (broken here into + * multiple lines for better readability). + * + * ``` + * + * ':' + * '=' + * + * ':' + * '=' + * ... + * ``` + * + * Example: + * + * ``` + * FREETYPE_PROPERTIES=truetype:interpreter-version=35 \ + * cff:no-stem-darkening=1 + * ``` + * + */ +#define FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES + + + /************************************************************************** + * + * Uncomment the line below if you want to activate LCD rendering + * technology similar to ClearType in this build of the library. This + * technology triples the resolution in the direction color subpixels. To + * mitigate color fringes inherent to this technology, you also need to + * explicitly set up LCD filtering. + * + * When this macro is not defined, FreeType offers alternative LCD + * rendering technology that produces excellent output. + */ +/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */ + + + /************************************************************************** + * + * Many compilers provide a non-ANSI 64-bit data type that can be used by + * FreeType to speed up some computations. However, this will create some + * problems when compiling the library in strict ANSI mode. + * + * For this reason, the use of 64-bit integers is normally disabled when + * the `__STDC__` macro is defined. You can however disable this by + * defining the macro `FT_CONFIG_OPTION_FORCE_INT64` here. + * + * For most compilers, this will only create compilation warnings when + * building the library. + * + * ObNote: The compiler-specific 64-bit integers are detected in the + * file `ftconfig.h` either statically or through the `configure` + * script on supported platforms. + */ +#undef FT_CONFIG_OPTION_FORCE_INT64 + + + /************************************************************************** + * + * If this macro is defined, do not try to use an assembler version of + * performance-critical functions (e.g., @FT_MulFix). You should only do + * that to verify that the assembler function works properly, or to execute + * benchmark tests of the various implementations. + */ +/* #define FT_CONFIG_OPTION_NO_ASSEMBLER */ + + + /************************************************************************** + * + * If this macro is defined, try to use an inlined assembler version of the + * @FT_MulFix function, which is a 'hotspot' when loading and hinting + * glyphs, and which should be executed as fast as possible. + * + * Note that if your compiler or CPU is not supported, this will default to + * the standard and portable implementation found in `ftcalc.c`. + */ +#define FT_CONFIG_OPTION_INLINE_MULFIX + + + /************************************************************************** + * + * LZW-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `compress` program. This is mostly used to parse many of the PCF + * files that come with various X11 distributions. The implementation + * uses NetBSD's `zopen` to partially uncompress the file on the fly (see + * `src/lzw/ftgzip.c`). + * + * Define this macro if you want to enable this 'feature'. + */ +#define FT_CONFIG_OPTION_USE_LZW + + + /************************************************************************** + * + * Gzip-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `gzip` program. This is mostly used to parse many of the PCF files + * that come with XFree86. The implementation uses 'zlib' to partially + * uncompress the file on the fly (see `src/gzip/ftgzip.c`). + * + * Define this macro if you want to enable this 'feature'. See also the + * macro `FT_CONFIG_OPTION_SYSTEM_ZLIB` below. + */ +//#define FT_CONFIG_OPTION_USE_ZLIB + + + /************************************************************************** + * + * ZLib library selection + * + * This macro is only used when `FT_CONFIG_OPTION_USE_ZLIB` is defined. + * It allows FreeType's 'ftgzip' component to link to the system's + * installation of the ZLib library. This is useful on systems like + * Unix or VMS where it generally is already available. + * + * If you let it undefined, the component will use its own copy of the + * zlib sources instead. These have been modified to be included + * directly within the component and **not** export external function + * names. This allows you to link any program with FreeType _and_ ZLib + * without linking conflicts. + * + * Do not `#undef` this macro here since the build system might define + * it for certain configurations only. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + * + * If you use the GNU make build system directly (that is, without the + * `configure` script) and you define this macro, you also have to pass + * `SYSTEM_ZLIB=yes` as an argument to make. + */ +/* #define FT_CONFIG_OPTION_SYSTEM_ZLIB */ + + + /************************************************************************** + * + * Bzip2-compressed file support. + * + * FreeType now handles font files that have been compressed with the + * `bzip2` program. This is mostly used to parse many of the PCF files + * that come with XFree86. The implementation uses `libbz2` to partially + * uncompress the file on the fly (see `src/bzip2/ftbzip2.c`). Contrary + * to gzip, bzip2 currently is not included and need to use the system + * available bzip2 implementation. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_BZIP2 */ + + + /************************************************************************** + * + * Define to disable the use of file stream functions and types, `FILE`, + * `fopen`, etc. Enables the use of smaller system libraries on embedded + * systems that have multiple system libraries, some with or without file + * stream support, in the cases where file stream support is not necessary + * such as memory loading of font files. + */ +/* #define FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT */ + + + /************************************************************************** + * + * PNG bitmap support. + * + * FreeType now handles loading color bitmap glyphs in the PNG format. + * This requires help from the external libpng library. Uncompressed + * color bitmaps do not need any external libraries and will be supported + * regardless of this configuration. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_PNG */ + + + /************************************************************************** + * + * HarfBuzz support. + * + * FreeType uses the HarfBuzz library to improve auto-hinting of OpenType + * fonts. If available, many glyphs not directly addressable by a font's + * character map will be hinted also. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_HARFBUZZ */ + + + /************************************************************************** + * + * Brotli support. + * + * FreeType uses the Brotli library to provide support for decompressing + * WOFF2 streams. + * + * Define this macro if you want to enable this 'feature'. + * + * If you use a build system like cmake or the `configure` script, + * options set by those programs have precedence, overwriting the value + * here with the configured one. + */ +/* #define FT_CONFIG_OPTION_USE_BROTLI */ + + + /************************************************************************** + * + * Glyph Postscript Names handling + * + * By default, FreeType 2 is compiled with the 'psnames' module. This + * module is in charge of converting a glyph name string into a Unicode + * value, or return a Macintosh standard glyph name for the use with the + * TrueType 'post' table. + * + * Undefine this macro if you do not want 'psnames' compiled in your + * build of FreeType. This has the following effects: + * + * - The TrueType driver will provide its own set of glyph names, if you + * build it to support postscript names in the TrueType 'post' table, + * but will not synthesize a missing Unicode charmap. + * + * - The Type~1 driver will not be able to synthesize a Unicode charmap + * out of the glyphs found in the fonts. + * + * You would normally undefine this configuration macro when building a + * version of FreeType that doesn't contain a Type~1 or CFF driver. + */ +#define FT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /************************************************************************** + * + * Postscript Names to Unicode Values support + * + * By default, FreeType~2 is built with the 'psnames' module compiled in. + * Among other things, the module is used to convert a glyph name into a + * Unicode value. This is especially useful in order to synthesize on + * the fly a Unicode charmap from the CFF/Type~1 driver through a big + * table named the 'Adobe Glyph List' (AGL). + * + * Undefine this macro if you do not want the Adobe Glyph List compiled + * in your 'psnames' module. The Type~1 driver will not be able to + * synthesize a Unicode charmap out of the glyphs found in the fonts. + */ +#define FT_CONFIG_OPTION_ADOBE_GLYPH_LIST + + + /************************************************************************** + * + * Support for Mac fonts + * + * Define this macro if you want support for outline fonts in Mac format + * (mac dfont, mac resource, macbinary containing a mac resource) on + * non-Mac platforms. + * + * Note that the 'FOND' resource isn't checked. + */ +#define FT_CONFIG_OPTION_MAC_FONTS + + + /************************************************************************** + * + * Guessing methods to access embedded resource forks + * + * Enable extra Mac fonts support on non-Mac platforms (e.g., GNU/Linux). + * + * Resource forks which include fonts data are stored sometimes in + * locations which users or developers don't expected. In some cases, + * resource forks start with some offset from the head of a file. In + * other cases, the actual resource fork is stored in file different from + * what the user specifies. If this option is activated, FreeType tries + * to guess whether such offsets or different file names must be used. + * + * Note that normal, direct access of resource forks is controlled via + * the `FT_CONFIG_OPTION_MAC_FONTS` option. + */ +#ifdef FT_CONFIG_OPTION_MAC_FONTS +#define FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK +#endif + + + /************************************************************************** + * + * Allow the use of `FT_Incremental_Interface` to load typefaces that + * contain no glyph data, but supply it via a callback function. This is + * required by clients supporting document formats which supply font data + * incrementally as the document is parsed, such as the Ghostscript + * interpreter for the PostScript language. + */ +#define FT_CONFIG_OPTION_INCREMENTAL + + + /************************************************************************** + * + * The size in bytes of the render pool used by the scan-line converter to + * do all of its work. + */ +#define FT_RENDER_POOL_SIZE 16384L + + + /************************************************************************** + * + * FT_MAX_MODULES + * + * The maximum number of modules that can be registered in a single + * FreeType library object. 32~is the default. + */ +#define FT_MAX_MODULES 32 + + + /************************************************************************** + * + * Debug level + * + * FreeType can be compiled in debug or trace mode. In debug mode, + * errors are reported through the 'ftdebug' component. In trace mode, + * additional messages are sent to the standard output during execution. + * + * Define `FT_DEBUG_LEVEL_ERROR` to build the library in debug mode. + * Define `FT_DEBUG_LEVEL_TRACE` to build it in trace mode. + * + * Don't define any of these macros to compile in 'release' mode! + * + * Do not `#undef` these macros here since the build system might define + * them for certain configurations only. + */ +/* #define FT_DEBUG_LEVEL_ERROR */ +/* #define FT_DEBUG_LEVEL_TRACE */ + + + /************************************************************************** + * + * Logging + * + * Compiling FreeType in debug or trace mode makes FreeType write error + * and trace log messages to `stderr`. Enabling this macro + * automatically forces the `FT_DEBUG_LEVEL_ERROR` and + * `FT_DEBUG_LEVEL_TRACE` macros and allows FreeType to write error and + * trace log messages to a file instead of `stderr`. For writing logs + * to a file, FreeType uses an the external `dlg` library (the source + * code is in `src/dlg`). + * + * This option needs a C99 compiler. + */ +/* #define FT_DEBUG_LOGGING */ + + + /************************************************************************** + * + * Autofitter debugging + * + * If `FT_DEBUG_AUTOFIT` is defined, FreeType provides some means to + * control the autofitter behaviour for debugging purposes with global + * boolean variables (consequently, you should **never** enable this + * while compiling in 'release' mode): + * + * ``` + * _af_debug_disable_horz_hints + * _af_debug_disable_vert_hints + * _af_debug_disable_blue_hints + * ``` + * + * Additionally, the following functions provide dumps of various + * internal autofit structures to stdout (using `printf`): + * + * ``` + * af_glyph_hints_dump_points + * af_glyph_hints_dump_segments + * af_glyph_hints_dump_edges + * af_glyph_hints_get_num_segments + * af_glyph_hints_get_segment_offset + * ``` + * + * As an argument, they use another global variable: + * + * ``` + * _af_debug_hints + * ``` + * + * Please have a look at the `ftgrid` demo program to see how those + * variables and macros should be used. + * + * Do not `#undef` these macros here since the build system might define + * them for certain configurations only. + */ +/* #define FT_DEBUG_AUTOFIT */ + + + /************************************************************************** + * + * Memory Debugging + * + * FreeType now comes with an integrated memory debugger that is capable + * of detecting simple errors like memory leaks or double deletes. To + * compile it within your build of the library, you should define + * `FT_DEBUG_MEMORY` here. + * + * Note that the memory debugger is only activated at runtime when when + * the _environment_ variable `FT2_DEBUG_MEMORY` is defined also! + * + * Do not `#undef` this macro here since the build system might define it + * for certain configurations only. + */ +/* #define FT_DEBUG_MEMORY */ + + + /************************************************************************** + * + * Module errors + * + * If this macro is set (which is _not_ the default), the higher byte of + * an error code gives the module in which the error has occurred, while + * the lower byte is the real error code. + * + * Setting this macro makes sense for debugging purposes only, since it + * would break source compatibility of certain programs that use + * FreeType~2. + * + * More details can be found in the files `ftmoderr.h` and `fterrors.h`. + */ +#undef FT_CONFIG_OPTION_USE_MODULE_ERRORS + + + /************************************************************************** + * + * OpenType SVG Glyph Support + * + * Setting this macro enables support for OpenType SVG glyphs. By + * default, FreeType can only fetch SVG documents. However, it can also + * render them if external rendering hook functions are plugged in at + * runtime. + * + * More details on the hooks can be found in file `otsvg.h`. + */ +#define FT_CONFIG_OPTION_SVG + + + /************************************************************************** + * + * Error Strings + * + * If this macro is set, `FT_Error_String` will return meaningful + * descriptions. This is not enabled by default to reduce the overall + * size of FreeType. + * + * More details can be found in the file `fterrors.h`. + */ +/* #define FT_CONFIG_OPTION_ERROR_STRINGS */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** S F N T D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_EMBEDDED_BITMAPS` if you want to support + * embedded bitmaps in all formats using the 'sfnt' module (namely + * TrueType~& OpenType). + */ +#define TT_CONFIG_OPTION_EMBEDDED_BITMAPS + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_COLOR_LAYERS` if you want to support colored + * outlines (from the 'COLR'/'CPAL' tables) in all formats using the 'sfnt' + * module (namely TrueType~& OpenType). + */ +#define TT_CONFIG_OPTION_COLOR_LAYERS + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_POSTSCRIPT_NAMES` if you want to be able to + * load and enumerate the glyph Postscript names in a TrueType or OpenType + * file. + * + * Note that when you do not compile the 'psnames' module by undefining the + * above `FT_CONFIG_OPTION_POSTSCRIPT_NAMES`, the 'sfnt' module will + * contain additional code used to read the PS Names table from a font. + * + * (By default, the module uses 'psnames' to extract glyph names.) + */ +#define TT_CONFIG_OPTION_POSTSCRIPT_NAMES + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_SFNT_NAMES` if your applications need to access + * the internal name table in a SFNT-based format like TrueType or + * OpenType. The name table contains various strings used to describe the + * font, like family name, copyright, version, etc. It does not contain + * any glyph name though. + * + * Accessing SFNT names is done through the functions declared in + * `ftsnames.h`. + */ +#define TT_CONFIG_OPTION_SFNT_NAMES + + + /************************************************************************** + * + * TrueType CMap support + * + * Here you can fine-tune which TrueType CMap table format shall be + * supported. + */ +#define TT_CONFIG_CMAP_FORMAT_0 +#define TT_CONFIG_CMAP_FORMAT_2 +#define TT_CONFIG_CMAP_FORMAT_4 +#define TT_CONFIG_CMAP_FORMAT_6 +#define TT_CONFIG_CMAP_FORMAT_8 +#define TT_CONFIG_CMAP_FORMAT_10 +#define TT_CONFIG_CMAP_FORMAT_12 +#define TT_CONFIG_CMAP_FORMAT_13 +#define TT_CONFIG_CMAP_FORMAT_14 + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T R U E T Y P E D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` if you want to compile a + * bytecode interpreter in the TrueType driver. + * + * By undefining this, you will only compile the code necessary to load + * TrueType glyphs without hinting. + * + * Do not `#undef` this macro here, since the build system might define it + * for certain configurations only. + */ +#define TT_CONFIG_OPTION_BYTECODE_INTERPRETER + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_SUBPIXEL_HINTING` if you want to compile + * subpixel hinting support into the TrueType driver. This modifies the + * TrueType hinting mechanism when anything but `FT_RENDER_MODE_MONO` is + * requested. + * + * In particular, it modifies the bytecode interpreter to interpret (or + * not) instructions in a certain way so that all TrueType fonts look like + * they do in a Windows ClearType (DirectWrite) environment. See [1] for a + * technical overview on what this means. See `ttinterp.h` for more + * details on the LEAN option. + * + * There are three possible values. + * + * Value 1: + * This value is associated with the 'Infinality' moniker, contributed by + * an individual nicknamed Infinality with the goal of making TrueType + * fonts render better than on Windows. A high amount of configurability + * and flexibility, down to rules for single glyphs in fonts, but also + * very slow. Its experimental and slow nature and the original + * developer losing interest meant that this option was never enabled in + * default builds. + * + * The corresponding interpreter version is v38. + * + * Value 2: + * The new default mode for the TrueType driver. The Infinality code + * base was stripped to the bare minimum and all configurability removed + * in the name of speed and simplicity. The configurability was mainly + * aimed at legacy fonts like 'Arial', 'Times New Roman', or 'Courier'. + * Legacy fonts are fonts that modify vertical stems to achieve clean + * black-and-white bitmaps. The new mode focuses on applying a minimal + * set of rules to all fonts indiscriminately so that modern and web + * fonts render well while legacy fonts render okay. + * + * The corresponding interpreter version is v40. + * + * Value 3: + * Compile both, making both v38 and v40 available (the latter is the + * default). + * + * By undefining these, you get rendering behavior like on Windows without + * ClearType, i.e., Windows XP without ClearType enabled and Win9x + * (interpreter version v35). Or not, depending on how much hinting blood + * and testing tears the font designer put into a given font. If you + * define one or both subpixel hinting options, you can switch between + * between v35 and the ones you define (using `FT_Property_Set`). + * + * This option requires `TT_CONFIG_OPTION_BYTECODE_INTERPRETER` to be + * defined. + * + * [1] + * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx + */ +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING 1 */ +#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2 +/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING ( 1 | 2 ) */ + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED` to compile the + * TrueType glyph loader to use Apple's definition of how to handle + * component offsets in composite glyphs. + * + * Apple and MS disagree on the default behavior of component offsets in + * composites. Apple says that they should be scaled by the scaling + * factors in the transformation matrix (roughly, it's more complex) while + * MS says they should not. OpenType defines two bits in the composite + * flags array which can be used to disambiguate, but old fonts will not + * have them. + * + * https://www.microsoft.com/typography/otspec/glyf.htm + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6glyf.html + */ +#undef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_GX_VAR_SUPPORT` if you want to include support + * for Apple's distortable font technology ('fvar', 'gvar', 'cvar', and + * 'avar' tables). Tagged 'Font Variations', this is now part of OpenType + * also. This has many similarities to Type~1 Multiple Masters support. + */ +#define TT_CONFIG_OPTION_GX_VAR_SUPPORT + + + /************************************************************************** + * + * Define `TT_CONFIG_OPTION_BDF` if you want to include support for an + * embedded 'BDF~' table within SFNT-based bitmap formats. + */ +#define TT_CONFIG_OPTION_BDF + + + /************************************************************************** + * + * Option `TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES` controls the maximum + * number of bytecode instructions executed for a single run of the + * bytecode interpreter, needed to prevent infinite loops. You don't want + * to change this except for very special situations (e.g., making a + * library fuzzer spend less time to handle broken fonts). + * + * It is not expected that this value is ever modified by a configuring + * script; instead, it gets surrounded with `#ifndef ... #endif` so that + * the value can be set as a preprocessor option on the compiler's command + * line. + */ +#ifndef TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES +#define TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES 1000000L +#endif + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** T Y P E 1 D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * `T1_MAX_DICT_DEPTH` is the maximum depth of nest dictionaries and arrays + * in the Type~1 stream (see `t1load.c`). A minimum of~4 is required. + */ +#define T1_MAX_DICT_DEPTH 5 + + + /************************************************************************** + * + * `T1_MAX_SUBRS_CALLS` details the maximum number of nested sub-routine + * calls during glyph loading. + */ +#define T1_MAX_SUBRS_CALLS 16 + + + /************************************************************************** + * + * `T1_MAX_CHARSTRING_OPERANDS` is the charstring stack's capacity. A + * minimum of~16 is required. + * + * The Chinese font 'MingTiEG-Medium' (covering the CNS 11643 character + * set) needs 256. + */ +#define T1_MAX_CHARSTRINGS_OPERANDS 256 + + + /************************************************************************** + * + * Define this configuration macro if you want to prevent the compilation + * of the 't1afm' module, which is in charge of reading Type~1 AFM files + * into an existing face. Note that if set, the Type~1 driver will be + * unable to produce kerning distances. + */ +#undef T1_CONFIG_OPTION_NO_AFM + + + /************************************************************************** + * + * Define this configuration macro if you want to prevent the compilation + * of the Multiple Masters font support in the Type~1 driver. + */ +#undef T1_CONFIG_OPTION_NO_MM_SUPPORT + + + /************************************************************************** + * + * `T1_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe Type~1 + * engine gets compiled into FreeType. If defined, it is possible to + * switch between the two engines using the `hinting-engine` property of + * the 'type1' driver module. + */ +/* #define T1_CONFIG_OPTION_OLD_ENGINE */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** C F F D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * Using `CFF_CONFIG_OPTION_DARKENING_PARAMETER_{X,Y}{1,2,3,4}` it is + * possible to set up the default values of the four control points that + * define the stem darkening behaviour of the (new) CFF engine. For more + * details please read the documentation of the `darkening-parameters` + * property (file `ftdriver.h`), which allows the control at run-time. + * + * Do **not** undefine these macros! + */ +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 500 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 400 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 1000 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 1667 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 275 + +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 2333 +#define CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 0 + + + /************************************************************************** + * + * `CFF_CONFIG_OPTION_OLD_ENGINE` controls whether the pre-Adobe CFF engine + * gets compiled into FreeType. If defined, it is possible to switch + * between the two engines using the `hinting-engine` property of the 'cff' + * driver module. + */ +/* #define CFF_CONFIG_OPTION_OLD_ENGINE */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** P C F D R I V E R C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * There are many PCF fonts just called 'Fixed' which look completely + * different, and which have nothing to do with each other. When selecting + * 'Fixed' in KDE or Gnome one gets results that appear rather random, the + * style changes often if one changes the size and one cannot select some + * fonts at all. This option makes the 'pcf' module prepend the foundry + * name (plus a space) to the family name. + * + * We also check whether we have 'wide' characters; all put together, we + * get family names like 'Sony Fixed' or 'Misc Fixed Wide'. + * + * If this option is activated, it can be controlled with the + * `no-long-family-names` property of the 'pcf' driver module. + */ +/* #define PCF_CONFIG_OPTION_LONG_FAMILY_NAMES */ + + + /*************************************************************************/ + /*************************************************************************/ + /**** ****/ + /**** A U T O F I T M O D U L E C O N F I G U R A T I O N ****/ + /**** ****/ + /*************************************************************************/ + /*************************************************************************/ + + + /************************************************************************** + * + * Compile 'autofit' module with CJK (Chinese, Japanese, Korean) script + * support. + */ +#define AF_CONFIG_OPTION_CJK + + + /************************************************************************** + * + * Compile 'autofit' module with fallback Indic script support, covering + * some scripts that the 'latin' submodule of the 'autofit' module doesn't + * (yet) handle. Currently, this needs option `AF_CONFIG_OPTION_CJK`. + */ +#ifdef AF_CONFIG_OPTION_CJK +#define AF_CONFIG_OPTION_INDIC +#endif + + + /************************************************************************** + * + * Use TrueType-like size metrics for 'light' auto-hinting. + * + * It is strongly recommended to avoid this option, which exists only to + * help some legacy applications retain its appearance and behaviour with + * respect to auto-hinted TrueType fonts. + * + * The very reason this option exists at all are GNU/Linux distributions + * like Fedora that did not un-patch the following change (which was + * present in FreeType between versions 2.4.6 and 2.7.1, inclusive). + * + * ``` + * 2011-07-16 Steven Chu + * + * [truetype] Fix metrics on size request for scalable fonts. + * ``` + * + * This problematic commit is now reverted (more or less). + */ +/* #define AF_CONFIG_OPTION_TT_SIZE_METRICS */ + + /* */ + + + /* + * This macro is obsolete. Support has been removed in FreeType version + * 2.5. + */ +/* #define FT_CONFIG_OPTION_OLD_INTERNALS */ + + + /* + * The next three macros are defined if native TrueType hinting is + * requested by the definitions above. Don't change this. + */ +#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER +#define TT_USE_BYTECODE_INTERPRETER + +#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING +#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 1 +#define TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY +#endif + +#if TT_CONFIG_OPTION_SUBPIXEL_HINTING & 2 +#define TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL +#endif +#endif +#endif + + + /* + * The TT_SUPPORT_COLRV1 macro is defined to indicate to clients that this + * version of FreeType has support for 'COLR' v1 API. This definition is + * useful to FreeType clients that want to build in support for 'COLR' v1 + * depending on a tip-of-tree checkout before it is officially released in + * FreeType, and while the feature cannot yet be tested against using + * version macros. Don't change this macro. This may be removed once the + * feature is in a FreeType release version and version macros can be used + * to test for availability. + */ +#ifdef TT_CONFIG_OPTION_COLOR_LAYERS +#define TT_SUPPORT_COLRV1 +#endif + + + /* + * Check CFF darkening parameters. The checks are the same as in function + * `cff_property_set` in file `cffdrivr.c`. + */ +#if CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 < 0 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 < 0 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3 > \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4 || \ + \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3 > 500 || \ + CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4 > 500 +#error "Invalid CFF darkening parameters!" +#endif + + +FT_END_HEADER + +#endif /* FTOPTION_H_ */ + + +/* END */ diff --git a/third_party/iconv/CMakeLists.txt b/third_party/iconv/CMakeLists.txt new file mode 100644 index 0000000..d02344c --- /dev/null +++ b/third_party/iconv/CMakeLists.txt @@ -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) + + +