diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 9a1487747..658b4b001 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -605,7 +605,6 @@ file( GLOB HEADER_FILES libxmp-lite/src/*.h core/*.h core/2d/*.h - core/fonts/*.h core/utility/*.h core/utility/rapidjson/*.h core/console/*.h @@ -626,6 +625,7 @@ file( GLOB HEADER_FILES common/console/*.h common/utility/*.h common/engine/*.h + common/fonts/*.h common/objects/*.h common/filesystem/*.h common/textures/*.h @@ -756,11 +756,6 @@ set (PCH_SOURCES core/2d/v_drawtext.cpp core/2d/screentext.cpp - core/fonts/font.cpp - core/fonts/hexfont.cpp - core/fonts/singlelumpfont.cpp - core/fonts/v_font.cpp - core/console/c_console.cpp core/console/d_event.cpp @@ -774,8 +769,12 @@ set (PCH_SOURCES common/audio/music/i_soundfont.cpp common/audio/music/music_config.cpp common/thirdparty/sfmt/SFMT.cpp - common/textures/texture.cpp - common/textures/animtexture.cpp + common/fonts/singlelumpfont.cpp + common/fonts/singlepicfont.cpp + common/fonts/specialfont.cpp + common/fonts/font.cpp + common/fonts/hexfont.cpp + common/fonts/v_font.cpp common/textures/hw_ihwtexture.cpp common/textures/hw_material.cpp common/fonts/v_text.cpp @@ -787,6 +786,7 @@ set (PCH_SOURCES common/textures/texturemanager.cpp common/textures/multipatchtexturebuilder.cpp common/textures/skyboxtexture.cpp + common/textures/animtexture.cpp common/textures/formats/automaptexture.cpp common/textures/formats/brightmaptexture.cpp common/textures/formats/buildtexture.cpp @@ -1019,6 +1019,7 @@ include_directories( common/utility common/console common/engine + common/fonts common/objects common/rendering common/rendering/gl_load @@ -1123,7 +1124,6 @@ source_group("Core\\Textures\\Formats" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOUR source_group("Core\\Utility" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/utility/.+") source_group("Core\\2D" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/2d/.+") source_group("Core\\Console" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/console/.+") -source_group("Core\\Fonts" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/fonts/.+") source_group("Core\\DObject" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/dobject/.+") source_group("Core\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/menu/.+") source_group("Core\\Rendering" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/core/rendering/.+") diff --git a/source/build/include/palette.h b/source/build/include/palette.h index c9d0db980..8c0827167 100644 --- a/source/build/include/palette.h +++ b/source/build/include/palette.h @@ -49,7 +49,7 @@ inline void paletteClearLookupTable(int num) enum { - Translation_BasePalettes, + Translation_BasePalettes = 1, Translation_Remap, }; diff --git a/source/build/src/palette.cpp b/source/build/src/palette.cpp index f1a25ee83..e0ea263ca 100644 --- a/source/build/src/palette.cpp +++ b/source/build/src/palette.cpp @@ -21,6 +21,7 @@ #include "colormatcher.h" #include "m_swap.h" #include "v_colortables.h" +#include "v_font.h" #include "../../glbackend/glbackend.h" // FString is a nice and convenient way to have automatically managed shared storage. @@ -40,6 +41,7 @@ palette_t palookupfog[MAXPALOOKUPS]; // NOTE: g_noFloorPal[0] is irrelevant as it's never checked. int8_t g_noFloorPal[MAXPALOOKUPS]; + //========================================================================== // // Adds a palette to the global list of base palettes @@ -262,7 +264,7 @@ void palettePostLoadLookups(void) remap.Palette[j] = palette->Palette[remap.Remap[j]]; } remap.NumEntries = 256; - GPalette.UpdateTranslation(TRANSLATION(i + 1, l), &remap); + GPalette.UpdateTranslation(TRANSLATION(i + Translation_Remap, l), &remap); } if (palette != basepalette) palette->Inactive = false; // clear the marker flag } @@ -287,7 +289,7 @@ void palettePostLoadLookups(void) for (auto remap : GPalette.uniqueRemaps) { - colorswap(remap); + if (!remap->ForFont) colorswap(remap); } colorswap(&GPalette.GlobalBrightmap); std::swap(GPalette.BaseColors[0], GPalette.BaseColors[255]); diff --git a/source/common/engine/palettecontainer.cpp b/source/common/engine/palettecontainer.cpp index 1f8732db9..a4ee23b82 100644 --- a/source/common/engine/palettecontainer.cpp +++ b/source/common/engine/palettecontainer.cpp @@ -53,14 +53,15 @@ extern uint8_t IcePalette[16][3]; void PaletteContainer::Init(int numslots) // This cannot be a constructor!!! { + if (numslots < 1) numslots = 1; Clear(); HasGlobalBrightmap = false; // Make sure that index 0 is always the identity translation. FRemapTable remap; remap.MakeIdentity(); remap.Inactive = true; - AddRemap(&remap); TranslationTables.Resize(numslots); + StoreTranslation(0, &remap); // make sure that translation ID 0 is the identity. ColorMatcher.SetPalette(BaseColors); } @@ -263,7 +264,7 @@ FRemapTable *PaletteContainer::TranslationToTable(int translation) unsigned int type = GetTranslationType(translation); unsigned int index = GetTranslationIndex(translation); - if (type <= 0 || type >= TranslationTables.Size() || index >= NumTranslations(type)) + if (type < 0 || type >= TranslationTables.Size() || index >= NumTranslations(type)) { return uniqueRemaps[0]; // this is the identity table. } diff --git a/source/common/engine/palettecontainer.h b/source/common/engine/palettecontainer.h index fa9d010dc..c8c5499d3 100644 --- a/source/common/engine/palettecontainer.h +++ b/source/common/engine/palettecontainer.h @@ -6,6 +6,12 @@ class FileReader; +enum +{ + TRANSLATION_Internal = 0 +}; + + struct FRemapTable { FRemapTable(int count = 256) { NumEntries = count; } @@ -28,6 +34,7 @@ struct FRemapTable int Index; int NumEntries; // # of elements in this table (usually 256) bool Inactive = false; // This table is inactive and should be treated as if it was passed as NULL + bool ForFont = false; // Mark font translations because they may require different handling than the ones for sprites- private: }; diff --git a/source/core/fonts/font.cpp b/source/common/fonts/font.cpp similarity index 63% rename from source/core/fonts/font.cpp rename to source/common/fonts/font.cpp index f2215c7cb..4f38b4794 100644 --- a/source/core/fonts/font.cpp +++ b/source/common/fonts/font.cpp @@ -38,28 +38,441 @@ #include #include #include -#include #include #include "templates.h" #include "m_swap.h" #include "v_font.h" +#include "printf.h" +#include "textures.h" +#include "filesystem.h" #include "cmdlib.h" #include "sc_man.h" -#include "v_text.h" +#include "gstrings.h" #include "image.h" #include "utf8.h" #include "myiswalpha.h" #include "fontchars.h" -#include "imagehelpers.h" -#include "glbackend/glbackend.h" -#include "palettecontainer.h" -#include "textures.h" +#include "multipatchtexture.h" +#include "texturemanager.h" #include "fontinternals.h" +//========================================================================== +// +// FFont :: FFont +// +// Loads a multi-texture font. +// +//========================================================================== + +FFont::FFont (const char *name, const char *nametemplate, const char *filetemplate, int lfirst, int lcount, int start, int fdlump, int spacewidth, bool notranslate, bool iwadonly, bool doomtemplate) +{ + int i; + FTextureID lump; + char buffer[12]; + int maxyoffs; + DVector2 Scale = { 1, 1 }; + + noTranslate = notranslate; + Lump = fdlump; + GlobalKerning = false; + FontName = name; + Next = FirstFont; + FirstFont = this; + Cursor = '_'; + ActiveColors = 0; + SpaceWidth = 0; + FontHeight = 0; + uint8_t pp = 0; + for (auto &p : PatchRemap) p = pp++; + translateUntranslated = false; + int FixedWidth = 0; + + maxyoffs = 0; + + TMap charMap; + int minchar = INT_MAX; + int maxchar = INT_MIN; + + // Read the font's configuration. + // This will not be done for the default fonts, because they are not atomic and the default content does not need it. + + TArray folderdata; + if (filetemplate != nullptr) + { + FStringf path("fonts/%s/", filetemplate); + // If a name template is given, collect data from all resource files. + // For anything else, each folder is being treated as an atomic, self-contained unit and mixing from different glyph sets is blocked. + fileSystem.GetFilesInFolder(path, folderdata, nametemplate == nullptr); + + //if (nametemplate == nullptr) + { + FStringf infpath("fonts/%s/font.inf", filetemplate); + + unsigned index = folderdata.FindEx([=](const FolderEntry &entry) + { + return infpath.CompareNoCase(entry.name) == 0; + }); + + if (index < folderdata.Size()) + { + FScanner sc; + sc.OpenLumpNum(folderdata[index].lumpnum); + while (sc.GetToken()) + { + sc.TokenMustBe(TK_Identifier); + if (sc.Compare("Kerning")) + { + sc.MustGetValue(false); + GlobalKerning = sc.Number; + } + else if (sc.Compare("Scale")) + { + sc.MustGetValue(true); + Scale.Y = Scale.X = sc.Float; + if (sc.CheckToken(',')) + { + sc.MustGetValue(true); + Scale.Y = sc.Float; + } + } + else if (sc.Compare("SpaceWidth")) + { + sc.MustGetValue(false); + SpaceWidth = sc.Number; + } + else if (sc.Compare("FontHeight")) + { + sc.MustGetValue(false); + FontHeight = sc.Number; + } + else if (sc.Compare("CellSize")) + { + sc.MustGetValue(false); + FixedWidth = sc.Number; + sc.MustGetToken(','); + sc.MustGetValue(false); + FontHeight = sc.Number; + } + else if (sc.Compare("Translationtype")) + { + sc.MustGetToken(TK_Identifier); + if (sc.Compare("console")) + { + TranslationType = 1; + } + else if (sc.Compare("standard")) + { + TranslationType = 0; + } + else + { + sc.ScriptError("Unknown translation type %s", sc.String); + } + } + } + } + } + } + + if (FixedWidth > 0) + { + ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale); + Type = Folder; + } + else + { + if (nametemplate != nullptr) + { + if (!iwadonly) + { + for (i = 0; i < lcount; i++) + { + int position = lfirst + i; + mysnprintf(buffer, countof(buffer), nametemplate, i + start); + + lump = TexMan.CheckForTexture(buffer, ETextureType::MiscPatch); + if (doomtemplate && lump.isValid() && i + start == 121) + { // HACKHACK: Don't load STCFN121 in doom(2), because + // it's not really a lower-case 'y' but a '|'. + // Because a lot of wads with their own font seem to foolishly + // copy STCFN121 and make it a '|' themselves, wads must + // provide STCFN120 (x) and STCFN122 (z) for STCFN121 to load as a 'y'. + FStringf c120("%s120", nametemplate); + FStringf c122("%s122", nametemplate); + if (!TexMan.CheckForTexture(c120, ETextureType::MiscPatch).isValid() || + !TexMan.CheckForTexture(c122, ETextureType::MiscPatch).isValid()) + { + // insert the incorrectly named '|' graphic in its correct position. + position = 124; + } + } + if (lump.isValid()) + { + Type = Multilump; + if (position < minchar) minchar = position; + if (position > maxchar) maxchar = position; + charMap.Insert(position, TexMan.GetTexture(lump)); + } + } + } + else + { + FTexture *texs[256] = {}; + if (lcount > 256 - start) lcount = 256 - start; + for (i = 0; i < lcount; i++) + { + TArray array; + mysnprintf(buffer, countof(buffer), nametemplate, i + start); + + TexMan.ListTextures(buffer, array, true); + for (auto entry : array) + { + FTexture *tex = TexMan.GetTexture(entry, false); + if (tex && tex->GetSourceLump() >= 0 && fileSystem.GetFileContainer(tex->GetSourceLump()) <= fileSystem.GetMaxIwadNum() && tex->GetUseType() == ETextureType::MiscPatch) + { + texs[i] = tex; + } + } + } + if (doomtemplate) + { + // Handle the misplaced '|'. + if (texs[121 - '!'] && !texs[120 - '!'] && !texs[122 - '!'] && !texs[124 - '!']) + { + texs[124 - '!'] = texs[121 - '!']; + texs[121 - '!'] = nullptr; + } + } + + for (i = 0; i < lcount; i++) + { + if (texs[i]) + { + int position = lfirst + i; + Type = Multilump; + if (position < minchar) minchar = position; + if (position > maxchar) maxchar = position; + charMap.Insert(position, texs[i]); + } + } + } + } + if (folderdata.Size() > 0) + { + // all valid lumps must be named with a hex number that represents its Unicode character index. + for (auto &entry : folderdata) + { + char *endp; + auto base = ExtractFileBase(entry.name); + auto position = strtoll(base.GetChars(), &endp, 16); + if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff))) + { + auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); + if (lump.isValid()) + { + if ((int)position < minchar) minchar = (int)position; + if ((int)position > maxchar) maxchar = (int)position; + auto tex = TexMan.GetTexture(lump); + tex->SetScale(Scale); + charMap.Insert((int)position, tex); + Type = Folder; + } + } + } + } + FirstChar = minchar; + LastChar = maxchar; + auto count = maxchar - minchar + 1; + Chars.Resize(count); + int fontheight = 0; + int asciiheight = 0; + + for (i = 0; i < count; i++) + { + auto lump = charMap.CheckKey(FirstChar + i); + if (lump != nullptr) + { + FTexture *pic = *lump; + if (pic != nullptr) + { + int height = pic->GetDisplayHeight(); + int yoffs = pic->GetDisplayTopOffset(); + + if (yoffs > maxyoffs) + { + maxyoffs = yoffs; + } + height += abs(yoffs); + if (height > fontheight) + { + fontheight = height; + } + if (height > asciiheight && FirstChar + 1 < 128) + { + asciiheight = height; + } + } + + Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), ""); + Chars[i].OriginalPic->SetUseType(ETextureType::FontChar); + Chars[i].OriginalPic->CopySize(pic); + TexMan.AddTexture(Chars[i].OriginalPic); + + if (!noTranslate) + { + Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), ""); + Chars[i].TranslatedPic->CopySize(pic); + Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); + TexMan.AddTexture(Chars[i].TranslatedPic); + } + else + { + Chars[i].TranslatedPic = Chars[i].OriginalPic; + } + + Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth(); + } + else + { + Chars[i].TranslatedPic = nullptr; + Chars[i].XMove = INT_MIN; + } + } + + if (SpaceWidth == 0) // An explicit override from the .inf file must always take precedence + { + if (spacewidth != -1) + { + SpaceWidth = spacewidth; + } + else if ('N' - FirstChar >= 0 && 'N' - FirstChar < count && Chars['N' - FirstChar].TranslatedPic != nullptr) + { + SpaceWidth = (Chars['N' - FirstChar].XMove + 1) / 2; + } + else + { + SpaceWidth = 4; + } + } + if (FontHeight == 0) FontHeight = fontheight; + if (AsciiHeight == 0) AsciiHeight = asciiheight; + + FixXMoves(); + } + + if (!noTranslate) LoadTranslations(); + + +} + +void FFont::ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale) +{ + // all valid lumps must be named with a hex number that represents the Unicode character index for its first character, + TArray part(1, true); + TMap charMap; + int minchar = INT_MAX; + int maxchar = INT_MIN; + for (auto &entry : folderdata) + { + char *endp; + auto base = ExtractFileBase(entry.name); + auto position = strtoll(base.GetChars(), &endp, 16); + if ((*endp == 0 || (*endp == '.' && position >= 0 && position < 0xffff))) // Sheet fonts may fill in the low control chars. + { + auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); + if (lump.isValid()) + { + auto tex = TexMan.GetTexture(lump); + int numtex_x = tex->GetTexelWidth() / width; + int numtex_y = tex->GetTexelHeight() / height; + int maxinsheet = int(position) + numtex_x * numtex_y - 1; + if (minchar > position) minchar = int(position); + if (maxchar < maxinsheet) maxchar = maxinsheet; + + for (int y = 0; y < numtex_y; y++) + { + for (int x = 0; x < numtex_x; x++) + { + part[0].OriginX = -width * x; + part[0].OriginY = -height * y; + part[0].Image = tex->GetImage(); + FMultiPatchTexture *image = new FMultiPatchTexture(width, height, part, false, false); + FImageTexture *tex = new FImageTexture(image, ""); + tex->SetUseType(ETextureType::FontChar); + tex->bMultiPatch = true; + tex->Width = width; + tex->Height = height; + tex->_LeftOffset[0] = + tex->_LeftOffset[1] = + tex->_TopOffset[0] = + tex->_TopOffset[1] = 0; + tex->Scale = Scale; + tex->bMasked = true; + tex->bTranslucent = -1; + tex->bWorldPanning = true; + tex->bNoDecals = false; + tex->SourceLump = -1; // We do not really care. + TexMan.AddTexture(tex); + charMap.Insert(int(position) + x + y * numtex_x, tex); + } + } + } + } + } + + + FirstChar = minchar; + bool map1252 = false; + if (minchar < 0x80 && maxchar >= 0xa0) // should be a settable option, but that'd probably cause more problems than it'd solve. + { + if (maxchar < 0x2122) maxchar = 0x2122; + map1252 = true; + } + LastChar = maxchar; + auto count = maxchar - minchar + 1; + Chars.Resize(count); + int fontheight = 0; + + for (int i = 0; i < count; i++) + { + auto lump = charMap.CheckKey(FirstChar + i); + if (lump != nullptr) + { + FTexture *pic = *lump; + + auto b = pic->Get8BitPixels(false); + + Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), ""); + Chars[i].OriginalPic->SetUseType(ETextureType::FontChar); + Chars[i].OriginalPic->CopySize(pic); + Chars[i].TranslatedPic = new FImageTexture(new FFontChar1(pic->GetImage()), ""); + Chars[i].TranslatedPic->CopySize(pic); + Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); + TexMan.AddTexture(Chars[i].OriginalPic); + TexMan.AddTexture(Chars[i].TranslatedPic); + } + Chars[i].XMove = width; + } + + if (map1252) + { + // Move the Windows-1252 characters to their proper place. + for (int i = 0x80; i < 0xa0; i++) + { + if (win1252map[i - 0x80] != i && Chars[i - minchar].TranslatedPic != nullptr && Chars[win1252map[i - 0x80] - minchar].TranslatedPic == nullptr) + { + std::swap(Chars[i - minchar], Chars[win1252map[i - 0x80] - minchar]); + } + } + } + + SpaceWidth = width; +} + //========================================================================== // // FFont :: ~FFont @@ -224,6 +637,7 @@ void FFont::SetDefaultTranslation(uint32_t *othercolors) FRemapTable remap(ActiveColors); remap.Remap[0] = 0; remap.Palette[0] = 0; + remap.ForFont = true; for (unsigned l = 1; l < myluminosity.Size(); l++) { @@ -251,7 +665,7 @@ void FFont::SetDefaultTranslation(uint32_t *othercolors) } } } - Ranges[CR_UNTRANSLATED] = GLInterface.GetPaletteIndex(remap.Palette); + Translations[CR_UNTRANSLATED] = GPalette.StoreTranslation(TRANSLATION_Internal, &remap); forceremap = true; } @@ -354,44 +768,49 @@ int FFont::SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_ //========================================================================== void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity, - const void *ranges, int total_colors, const PalEntry *palette) + const void *ranges, int total_colors, const PalEntry *palette, std::function post) { int i, j; const TranslationParm *parmstart = (const TranslationParm *)ranges; - FRemapTable remap; + FRemapTable remap(total_colors); + remap.ForFont = true; // Create different translations for different color ranges - Ranges.Clear(); + Translations.Clear(); for (i = 0; i < NumTextColors; i++) { if (i == CR_UNTRANSLATED) { if (identity != nullptr) { + memcpy(remap.Remap, identity, ActiveColors); if (palette != nullptr) { - memcpy (remap.Palette, palette, ActiveColors*sizeof(PalEntry)); + memcpy(remap.Palette, palette, ActiveColors * sizeof(PalEntry)); } else { - remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0,255,255,255); + remap.Palette[0] = GPalette.BaseColors[identity[0]] & MAKEARGB(0, 255, 255, 255); for (j = 1; j < ActiveColors; ++j) { - remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255,0,0,0); + remap.Palette[j] = GPalette.BaseColors[identity[j]] | MAKEARGB(255, 0, 0, 0); } } + Translations.Push(GPalette.StoreTranslation(TRANSLATION_Internal, &remap)); } else { + Translations.Push(Translations[0]); } - Ranges.Push(GLInterface.GetPaletteIndex(remap.Palette)); continue; } assert(parmstart->RangeStart >= 0); + remap.Remap[0] = 0; remap.Palette[0] = 0; + remap.ForFont = true; for (j = 1; j < ActiveColors; j++) { @@ -415,10 +834,11 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity r = clamp(r, 0, 255); g = clamp(g, 0, 255); b = clamp(b, 0, 255); + remap.Remap[j] = ColorMatcher.Pick(r, g, b); remap.Palette[j] = PalEntry(255,r,g,b); } - - Ranges.Push(GLInterface.GetPaletteIndex(remap.Palette)); + if (post) post(&remap); + Translations.Push(GPalette.StoreTranslation(TRANSLATION_Internal, &remap)); // Advance to the next color range. while (parmstart[1].RangeStart > parmstart[0].RangeEnd) @@ -452,7 +872,7 @@ int FFont::GetColorTranslation (EColorRange range, PalEntry *color) const else if (range >= NumTextColors) range = CR_UNTRANSLATED; //if (range == CR_UNTRANSLATED && !translateUntranslated) return nullptr; - return Ranges[range]; + return Translations[range]; } //========================================================================== @@ -581,11 +1001,11 @@ FTexture *FFont::GetChar (int code, int translation, int *const width, bool *red //========================================================================== // -// FFont :: CharWidth +// FFont :: GetCharWidth // //========================================================================== -int FFont::CharWidth (int code) const +int FFont::GetCharWidth (int code) const { code = GetCharCode(code, true); if (code >= 0) return Chars[code - FirstChar].XMove; @@ -641,7 +1061,7 @@ bool FFont::CanPrint(const uint8_t *string) const else if (chr != '\n') { int cc = GetCharCode(chr, true); - if (chr != cc && myiswalpha(chr))// && cc != getAlternative(chr)) + if (chr != cc && myiswalpha(chr) && cc != getAlternative(chr)) { return false; } @@ -689,11 +1109,11 @@ int FFont::StringWidth(const uint8_t *string) const } else { - w += CharWidth(chr) + GlobalKerning; + w += GetCharWidth(chr) + GlobalKerning; } } - return std::max(maxw, w); + return MAX(maxw, w); } //========================================================================== @@ -786,8 +1206,9 @@ void FFont::LoadTranslations() // //========================================================================== -FFont::FFont () +FFont::FFont (int lump) { + Lump = lump; FontName = NAME_None; Cursor = '_'; noTranslate = false; @@ -807,6 +1228,19 @@ FFont::FFont () void FFont::FixXMoves() { + if (FirstChar < 'a' && LastChar >= 'z') + { + MixedCase = true; + // First check if this is a mixed case font. + // For this the basic Latin small characters all need to be present. + for (int i = 'a'; i <= 'z'; i++) + if (Chars[i - FirstChar].OriginalPic == nullptr) + { + MixedCase = false; + break; + } + } + for (int i = 0; i <= LastChar - FirstChar; ++i) { if (Chars[i].XMove == INT_MIN) diff --git a/source/core/fonts/fontinternals.h b/source/common/fonts/fontinternals.h similarity index 81% rename from source/core/fonts/fontinternals.h rename to source/common/fonts/fontinternals.h index 6d68c6aa8..dc942319e 100644 --- a/source/core/fonts/fontinternals.h +++ b/source/common/fonts/fontinternals.h @@ -34,13 +34,7 @@ struct TranslationMap extern TArray TranslationParms[2]; extern TArray TranslationLookup; extern TArray TranslationColors; -extern uint16_t lowerforupper[65536]; -extern uint16_t upperforlower[65536]; class FImageSource; void RecordTextureColors (FImageSource *pic, uint32_t *usedcolors); -bool myislower(int code); -bool myisupper(int code); -int stripaccent(int code); -int getAlternative(int code); diff --git a/source/core/fonts/hexfont.cpp b/source/common/fonts/hexfont.cpp similarity index 95% rename from source/core/fonts/hexfont.cpp rename to source/common/fonts/hexfont.cpp index 2ddf48c3b..1b3bca2e4 100644 --- a/source/core/fonts/hexfont.cpp +++ b/source/common/fonts/hexfont.cpp @@ -32,15 +32,13 @@ ** */ +#include "engineerrors.h" #include "textures.h" #include "image.h" #include "v_font.h" +#include "filesystem.h" #include "utf8.h" #include "sc_man.h" -#include "imagehelpers.h" -#include "v_draw.h" -#include "glbackend/glbackend.h" -#include "palettecontainer.h" #include "texturemanager.h" #include "fontinternals.h" @@ -58,10 +56,11 @@ struct HexDataSource // //========================================================================== - void ParseDefinition(const char *fname) + void ParseDefinition(int lumpnum) { FScanner sc; - sc.Open(fname); + + sc.OpenLumpNum(lumpnum); sc.SetCMode(true); glyphdata.Push(0); // ensure that index 0 can be used as 'not present'. while (sc.GetString()) @@ -243,8 +242,11 @@ public: // //========================================================================== - FHexFont (const char *fontname, const char *lump) + FHexFont (const char *fontname, int lump) + : FFont(lump) { + assert(lump >= 0); + FontName = fontname; FirstChar = hexdata.FirstChar; @@ -313,9 +315,10 @@ public: // //========================================================================== - FHexFont2(const char *fontname, const char *lump) + FHexFont2(const char *fontname, int lump) + : FFont(lump) { - assert(lump != nullptr); + assert(lump >= 0); FontName = fontname; @@ -388,6 +391,7 @@ public: FRemapTable remap(ActiveColors); remap.Remap[0] = 0; remap.Palette[0] = 0; + remap.ForFont = true; for (unsigned l = 1; l < 18; l++) { @@ -415,8 +419,8 @@ public: } } } + Translations[CR_UNTRANSLATED] = GPalette.StoreTranslation(TRANSLATION_Internal, &remap); forceremap = true; - Ranges[CR_UNTRANSLATED] = GLInterface.GetPaletteIndex(remap.Palette); } @@ -429,7 +433,7 @@ public: // //========================================================================== -FFont *CreateHexLumpFont (const char *fontname, const char * lump) +FFont *CreateHexLumpFont (const char *fontname, int lump) { if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump); return new FHexFont(fontname, lump); @@ -441,7 +445,7 @@ FFont *CreateHexLumpFont (const char *fontname, const char * lump) // //========================================================================== -FFont *CreateHexLumpFont2(const char *fontname, const char* lump) +FFont *CreateHexLumpFont2(const char *fontname, int lump) { if (hexdata.FirstChar == INT_MAX) hexdata.ParseDefinition(lump); return new FHexFont2(fontname, lump); diff --git a/source/core/fonts/myiswalpha.h b/source/common/fonts/myiswalpha.h similarity index 100% rename from source/core/fonts/myiswalpha.h rename to source/common/fonts/myiswalpha.h diff --git a/source/core/fonts/singlelumpfont.cpp b/source/common/fonts/singlelumpfont.cpp similarity index 89% rename from source/core/fonts/singlelumpfont.cpp rename to source/common/fonts/singlelumpfont.cpp index bbf4df705..4b4fc3d9a 100644 --- a/source/core/fonts/singlelumpfont.cpp +++ b/source/common/fonts/singlelumpfont.cpp @@ -33,16 +33,14 @@ ** */ +#include "engineerrors.h" #include "textures.h" #include "image.h" #include "v_font.h" +#include "filesystem.h" #include "utf8.h" #include "fontchars.h" #include "texturemanager.h" -#include "printf.h" -#include "imagehelpers.h" -#include "filesystem.h" -#include "colormatcher.h" #include "fontinternals.h" @@ -88,7 +86,7 @@ The FON2 header is followed by variable length data: class FSingleLumpFont : public FFont { public: - FSingleLumpFont (const char *fontname, const char * lump); + FSingleLumpFont (const char *fontname, int lump); protected: void CheckFON1Chars (double *luminosity); @@ -96,9 +94,10 @@ protected: void FixupPalette (uint8_t *identity, double *luminosity, const uint8_t *palette, bool rescale, PalEntry *out_palette); void LoadTranslations (); - void LoadFON1 (const char * lump, const uint8_t *data); - void LoadFON2 (const char* lump, const uint8_t *data); - void LoadBMF (const char* lump, const uint8_t *data); + void LoadFON1 (int lump, const uint8_t *data); + void LoadFON2 (int lump, const uint8_t *data); + void LoadBMF (int lump, const uint8_t *data); + void CreateFontFromPic (FTextureID picnum); static int BMFCompare(const void *a, const void *b); @@ -121,18 +120,18 @@ protected: // //========================================================================== -FSingleLumpFont::FSingleLumpFont (const char *name, const char * lump) +FSingleLumpFont::FSingleLumpFont (const char *name, int lump) : FFont(lump) { - assert(lump != nullptr); + assert(lump >= 0); FontName = name; - rawData = fileSystem.LoadFile(lump, 0); - auto& data = rawData; + FileData data1 = fileSystem.ReadFile (lump); + const uint8_t *data = (const uint8_t *)data1.GetMem(); if (data[0] == 0xE1 && data[1] == 0xE6 && data[2] == 0xD5 && data[3] == 0x1A) { - LoadBMF(name, data.Data()); + LoadBMF(lump, data); Type = BMF; } else if (data[0] != 'F' || data[1] != 'O' || data[2] != 'N' || @@ -145,12 +144,12 @@ FSingleLumpFont::FSingleLumpFont (const char *name, const char * lump) switch (data[3]) { case '1': - LoadFON1 (name, data.Data()); + LoadFON1 (lump, data); Type = Fon1; break; case '2': - LoadFON2 (name, data.Data()); + LoadFON2 (lump, data); Type = Fon2; break; } @@ -160,6 +159,28 @@ FSingleLumpFont::FSingleLumpFont (const char *name, const char * lump) FirstFont = this; } +//========================================================================== +// +// FSingleLumpFont :: CreateFontFromPic +// +//========================================================================== + +void FSingleLumpFont::CreateFontFromPic (FTextureID picnum) +{ + FTexture *pic = TexMan.GetTexture(picnum); + + FontHeight = pic->GetDisplayHeight (); + SpaceWidth = pic->GetDisplayWidth (); + GlobalKerning = 0; + + FirstChar = LastChar = 'A'; + Chars.Resize(1); + Chars[0].TranslatedPic = pic; + + // Only one color range. Don't bother with the others. + ActiveColors = 0; +} + //========================================================================== // // FSingleLumpFont :: LoadTranslations @@ -215,7 +236,7 @@ void FSingleLumpFont::LoadTranslations() // //========================================================================== -void FSingleLumpFont::LoadFON1 (const char * lump, const uint8_t *data) +void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data) { int w, h; @@ -256,7 +277,7 @@ void FSingleLumpFont::LoadFON1 (const char * lump, const uint8_t *data) // //========================================================================== -void FSingleLumpFont::LoadFON2 (const char * lump, const uint8_t *data) +void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data) { int count, i, totalwidth; uint16_t *widths; @@ -332,7 +353,7 @@ void FSingleLumpFont::LoadFON2 (const char * lump, const uint8_t *data) } else { - Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (fileSystem.FindFile(lump), int(data_p - data), widths2[i], FontHeight)); + Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight)); Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); TexMan.AddTexture(Chars[i].TranslatedPic); do @@ -369,7 +390,7 @@ void FSingleLumpFont::LoadFON2 (const char * lump, const uint8_t *data) // //========================================================================== -void FSingleLumpFont::LoadBMF(const char *lump, const uint8_t *data) +void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data) { const uint8_t *chardata; int numchars, count, totalwidth, nwidth; @@ -462,7 +483,7 @@ void FSingleLumpFont::LoadBMF(const char *lump, const uint8_t *data) { // Empty character: skip it. continue; } - auto tex = new FImageTexture(new FFontChar2(fileSystem.FindFile(lump), int(chardata + chari + 6 - data), + auto tex = new FImageTexture(new FFontChar2(lump, int(chardata + chari + 6 - data), chardata[chari+1], // width chardata[chari+2], // height -(int8_t)chardata[chari+3], // x offset @@ -519,15 +540,15 @@ int FSingleLumpFont::BMFCompare(const void *a, const void *b) void FSingleLumpFont::CheckFON1Chars (double *luminosity) { - auto &data = rawData; - if (data.Size() < 8) return; + FileData memLump = fileSystem.ReadFile(Lump); + const uint8_t* data = (const uint8_t*) memLump.GetMem(); uint8_t used[256], reverse[256]; const uint8_t *data_p; int i, j; memset (used, 0, 256); - data_p = data.Data() + 8; + data_p = data + 8; for (i = 0; i < 256; ++i) { @@ -535,7 +556,7 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity) if(!Chars[i].TranslatedPic) { - Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (0, int(data_p - data.Data()), SpaceWidth, FontHeight)); + Chars[i].TranslatedPic = new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight)); Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); Chars[i].XMove = SpaceWidth; TexMan.AddTexture(Chars[i].TranslatedPic); @@ -630,7 +651,7 @@ void FSingleLumpFont::FixupPalette (uint8_t *identity, double *luminosity, const } } -FFont *CreateSingleLumpFont (const char *fontname, const char * lump) +FFont *CreateSingleLumpFont (const char *fontname, int lump) { return new FSingleLumpFont(fontname, lump); } diff --git a/source/common/fonts/singlepicfont.cpp b/source/common/fonts/singlepicfont.cpp new file mode 100644 index 000000000..8d289944d --- /dev/null +++ b/source/common/fonts/singlepicfont.cpp @@ -0,0 +1,128 @@ +/* +** v_font.cpp +** Font management +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2005-2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "engineerrors.h" +#include "textures.h" +#include "v_font.h" +#include "filesystem.h" +#include "texturemanager.h" + +class FSinglePicFont : public FFont +{ +public: + FSinglePicFont(const char *picname); + + // FFont interface + FTexture *GetChar(int code, int translation, int *const width, bool *redirected = nullptr) const override; + int GetCharWidth (int code) const; + +protected: + FTextureID PicNum; +}; + +//========================================================================== +// +// FSinglePicFont :: FSinglePicFont +// +// Creates a font to wrap a texture so that you can use hudmessage as if it +// were a hudpic command. It does not support translation, but animation +// is supported, unlike all the real fonts. +// +//========================================================================== + +FSinglePicFont::FSinglePicFont(const char *picname) : + FFont(-1) // Since lump is only needed for priority information we don't need to worry about this here. +{ + FTextureID picnum = TexMan.CheckForTexture (picname, ETextureType::Any); + + if (!picnum.isValid()) + { + I_FatalError ("%s is not a font or texture", picname); + } + + FTexture *pic = TexMan.GetTexture(picnum); + + FontName = picname; + FontHeight = pic->GetDisplayHeight(); + SpaceWidth = pic->GetDisplayWidth(); + GlobalKerning = 0; + FirstChar = LastChar = 'A'; + ActiveColors = 0; + PicNum = picnum; + + Next = FirstFont; + FirstFont = this; +} + +//========================================================================== +// +// FSinglePicFont :: GetChar +// +// Returns the texture if code is 'a' or 'A', otherwise nullptr. +// +//========================================================================== + +FTexture *FSinglePicFont::GetChar (int code, int translation, int *const width, bool *redirected) const +{ + *width = SpaceWidth; + if (redirected) *redirected = false; + if (code == 'a' || code == 'A') + { + return TexMan.GetPalettedTexture(PicNum, true); + } + else + { + return nullptr; + } +} + +//========================================================================== +// +// FSinglePicFont :: GetCharWidth +// +// Don't expect the text functions to work properly if I actually allowed +// the character width to vary depending on the animation frame. +// +//========================================================================== + +int FSinglePicFont::GetCharWidth (int code) const +{ + return SpaceWidth; +} + +FFont *CreateSinglePicFont(const char *picname) +{ + return new FSinglePicFont(picname); +} diff --git a/source/common/fonts/specialfont.cpp b/source/common/fonts/specialfont.cpp new file mode 100644 index 000000000..519ccf8dd --- /dev/null +++ b/source/common/fonts/specialfont.cpp @@ -0,0 +1,223 @@ +/* +** v_font.cpp +** Font management +** +**--------------------------------------------------------------------------- +** Copyright 1998-2016 Randy Heit +** Copyright 2005-2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "v_font.h" +#include "textures.h" +#include "image.h" +#include "fontchars.h" +#include "texturemanager.h" + +#include "fontinternals.h" + +// Essentially a normal multilump font but with an explicit list of character patches +class FSpecialFont : public FFont +{ +public: + FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate); + + void LoadTranslations(); + +protected: + bool notranslate[256]; +}; + + +//========================================================================== +// +// FSpecialFont :: FSpecialFont +// +//========================================================================== + +FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate) + : FFont(lump) +{ + int i; + TArray charlumps(count, true); + int maxyoffs; + FTexture *pic; + + memcpy(this->notranslate, notranslate, 256*sizeof(bool)); + + noTranslate = donttranslate; + FontName = name; + Chars.Resize(count); + FirstChar = first; + LastChar = first + count - 1; + FontHeight = 0; + GlobalKerning = false; + Next = FirstFont; + FirstFont = this; + + maxyoffs = 0; + + for (i = 0; i < count; i++) + { + pic = charlumps[i] = lumplist[i]; + if (pic != nullptr) + { + int height = pic->GetDisplayHeight(); + int yoffs = pic->GetDisplayTopOffset(); + + if (yoffs > maxyoffs) + { + maxyoffs = yoffs; + } + height += abs (yoffs); + if (height > FontHeight) + { + FontHeight = height; + } + } + + if (charlumps[i] != nullptr) + { + auto pic = charlumps[i]; + Chars[i].OriginalPic = new FImageTexture(pic->GetImage(), ""); + Chars[i].OriginalPic->SetUseType(ETextureType::FontChar); + Chars[i].OriginalPic->CopySize(pic); + TexMan.AddTexture(Chars[i].OriginalPic); + + if (!noTranslate) + { + Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charlumps[i]->GetImage()), ""); + Chars[i].TranslatedPic->CopySize(charlumps[i]); + Chars[i].TranslatedPic->SetUseType(ETextureType::FontChar); + TexMan.AddTexture(Chars[i].TranslatedPic); + } + else Chars[i].TranslatedPic = Chars[i].OriginalPic; + Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth(); + } + else + { + Chars[i].TranslatedPic = nullptr; + Chars[i].XMove = INT_MIN; + } + } + + // Special fonts normally don't have all characters so be careful here! + if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].TranslatedPic != nullptr) + { + SpaceWidth = (Chars['N' - first].XMove + 1) / 2; + } + else + { + SpaceWidth = 4; + } + + FixXMoves(); + + if (noTranslate) + { + ActiveColors = 0; + } + else + { + LoadTranslations(); + } +} + +//========================================================================== +// +// FSpecialFont :: LoadTranslations +// +//========================================================================== + +void FSpecialFont::LoadTranslations() +{ + int count = LastChar - FirstChar + 1; + uint32_t usedcolors[256] = {}; + uint8_t identity[256]; + TArray Luminosity; + int TotalColors; + int i; + + for (i = 0; i < count; i++) + { + if (Chars[i].TranslatedPic) + { + FFontChar1 *pic = static_cast(Chars[i].TranslatedPic->GetImage()); + if (pic) + { + pic->SetSourceRemap(nullptr); // Force the FFontChar1 to return the same pixels as the base texture + RecordTextureColors(pic, usedcolors); + } + } + } + + // exclude the non-translated colors from the translation calculation + for (i = 0; i < 256; i++) + if (notranslate[i]) + usedcolors[i] = false; + + TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, Luminosity); + + // Map all untranslated colors into the table of used colors + for (i = 0; i < 256; i++) + { + if (notranslate[i]) + { + PatchRemap[i] = TotalColors; + identity[TotalColors] = i; + TotalColors++; + } + } + + for (i = 0; i < count; i++) + { + if(Chars[i].TranslatedPic) + static_cast(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap); + } + + BuildTranslations(Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr, [=](FRemapTable* remap) + { + // add the untranslated colors to the Ranges tables + if (ActiveColors < TotalColors) + { + for (int j = ActiveColors; j < TotalColors; ++j) + { + remap->Remap[j] = identity[j]; + remap->Palette[j] = GPalette.BaseColors[identity[j]]; + remap->Palette[j].a = 0xff; + } + } + }); + + ActiveColors = TotalColors; +} + +FFont *CreateSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate) +{ + return new FSpecialFont(name, first, count, lumplist, notranslate, lump, donttranslate); +} diff --git a/source/core/fonts/v_font.cpp b/source/common/fonts/v_font.cpp similarity index 68% rename from source/core/fonts/v_font.cpp rename to source/common/fonts/v_font.cpp index 20a56d976..8fe004f7f 100644 --- a/source/core/fonts/v_font.cpp +++ b/source/common/fonts/v_font.cpp @@ -42,15 +42,17 @@ #include "templates.h" #include "m_swap.h" #include "v_font.h" +#include "filesystem.h" #include "cmdlib.h" #include "sc_man.h" -#include "v_text.h" +#include "gstrings.h" #include "image.h" #include "utf8.h" - -#include "m_png.h" +#include "fontchars.h" +#include "textures.h" +#include "texturemanager.h" #include "printf.h" -#include "filesystem.h" +#include "palentry.h" #include "fontinternals.h" @@ -58,24 +60,32 @@ #define DEFAULT_LOG_COLOR PalEntry(223,223,223) +// +// Globally visible constants. +// +#define HU_FONTSTART uint8_t('!') // the first font characters +#define HU_FONTEND uint8_t('\377') // the last font characters + +// Calculate # of glyphs in font. +#define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1) + + // TYPES ------------------------------------------------------------------- -int V_GetColor(const char* cstr); // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- -FFont* SmallFont, * SmallFont2, * BigFont, * BigUpper, * ConFont, * IntermissionFont, * NewConsoleFont, * NewSmallFont, * CurrentConsoleFont, * OriginalSmallFont, * AlternativeSmallFont, * OriginalBigFont; // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int TranslationMapCompare (const void *a, const void *b); -//void UpdateGenericUI(bool cvar); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int PrintColors[]; // PUBLIC DATA DEFINITIONS ------------------------------------------------- +FFont* SmallFont, * SmallFont2, * BigFont, * BigUpper, * ConFont, * IntermissionFont, * NewConsoleFont, * NewSmallFont, * CurrentConsoleFont, * OriginalSmallFont, * AlternativeSmallFont, * OriginalBigFont; FFont *FFont::FirstFont = nullptr; int NumTextColors; @@ -90,19 +100,60 @@ TArray TranslationColors; FFont *V_GetFont(const char *name, const char *fontlumpname) { + if (!stricmp(name, "DBIGFONT")) name = "BigFont"; + else if (!stricmp(name, "CONFONT")) name = "ConsoleFont"; // several mods have used the name CONFONT directly and effectively duplicated the font. FFont *font = FFont::FindFont (name); if (font == nullptr) { - auto lumpy = fileSystem.OpenFileReader(fontlumpname); - if (!lumpy.isOpen()) return nullptr; - uint32_t head; - lumpy.Read (&head, 4); - if ((head & MAKE_ID(255,255,255,0)) == MAKE_ID('F','O','N',0) || - head == MAKE_ID(0xE1,0xE6,0xD5,0x1A)) + if (!stricmp(name, "BIGUPPER")) { - FFont *CreateSingleLumpFont (const char *fontname, const char *lump); - lumpy.Close(); - return CreateSingleLumpFont (name, fontlumpname); + font = FFont::FindFont("BIGFONT"); + if (font) return font; + } + + int lump = -1; + int folderfile = -1; + + TArray folderdata; + FStringf path("fonts/%s/", name); + + // Use a folder-based font only if it comes from a later file than the single lump version. + if (fileSystem.GetFilesInFolder(path, folderdata, true)) + { + // This assumes that any custom font comes in one piece and not distributed across multiple resource files. + folderfile = fileSystem.GetFileContainer(folderdata[0].lumpnum); + } + + + lump = fileSystem.CheckNumForFullName(fontlumpname? fontlumpname : name, true); + + if (lump != -1 && fileSystem.GetFileContainer(lump) >= folderfile) + { + uint32_t head; + { + auto lumpy = fileSystem.OpenFileReader (lump); + lumpy.Read (&head, 4); + } + if ((head & MAKE_ID(255,255,255,0)) == MAKE_ID('F','O','N',0) || + head == MAKE_ID(0xE1,0xE6,0xD5,0x1A)) + { + FFont *CreateSingleLumpFont (const char *fontname, int lump); + return CreateSingleLumpFont (name, lump); + } + } + FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any); + if (picnum.isValid()) + { + FTexture *tex = TexMan.GetTexture(picnum); + if (tex && tex->GetSourceLump() >= folderfile) + { + FFont *CreateSinglePicFont(const char *name); + return CreateSinglePicFont (name); + } + } + if (folderdata.Size() > 0) + { + return new FFont(name, nullptr, name, HU_FONTSTART, HU_FONTSIZE, 1, -1); } } return font; @@ -118,7 +169,6 @@ FFont *V_GetFont(const char *name, const char *fontlumpname) void V_InitCustomFonts() { -#if 0 FScanner sc; FTexture *lumplist[256]; bool notranslate[256]; @@ -134,7 +184,7 @@ void V_InitCustomFonts() int kerning; char cursor = '_'; - while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1) + while ((llump = fileSystem.FindLump ("FONTDEFS", &lastlump)) != -1) { sc.OpenLumpNum(llump); while (sc.GetString()) @@ -223,7 +273,7 @@ void V_InitCustomFonts() { *p = TexMan.GetTexture(texid); } - else if (Wads.GetLumpFile(sc.LumpNum) >= Wads.GetIwadNum()) + else if (fileSystem.GetFileContainer(sc.LumpNum) >= fileSystem.GetIwadNum()) { // Print a message only if this isn't in zdoom.pk3 sc.ScriptMessage("%s: Unable to find texture in font definition for %s", sc.String, namebuffer.GetChars()); @@ -271,107 +321,6 @@ void V_InitCustomFonts() wrong: sc.ScriptError ("Invalid combination of properties in font '%s'", namebuffer.GetChars()); -#endif -} - -//========================================================================== -// -// V_GetColorFromString -// -// Passed a string of the form "#RGB", "#RRGGBB", "R G B", or "RR GG BB", -// returns a number representing that color. If palette is non-NULL, the -// index of the best match in the palette is returned, otherwise the -// RRGGBB value is returned directly. -// -//========================================================================== - -int V_GetColor(const char* cstr) -{ - int c[3], i, p; - char val[3]; - - val[2] = '\0'; - - // Check for HTML-style #RRGGBB or #RGB color string - if (cstr[0] == '#') - { - size_t len = strlen(cstr); - - if (len == 7) - { - // Extract each eight-bit component into c[]. - for (i = 0; i < 3; ++i) - { - val[0] = cstr[1 + i * 2]; - val[1] = cstr[2 + i * 2]; - c[i] = ParseHex(val, nullptr); - } - } - else if (len == 4) - { - // Extract each four-bit component into c[], expanding to eight bits. - for (i = 0; i < 3; ++i) - { - val[1] = val[0] = cstr[1 + i]; - c[i] = ParseHex(val, nullptr); - } - } - else - { - // Bad HTML-style; pretend it's black. - c[2] = c[1] = c[0] = 0; - } - } - else - { - if (strlen(cstr) == 6) - { - char* p; - int color = strtol(cstr, &p, 16); - if (*p == 0) - { - // RRGGBB string - c[0] = (color & 0xff0000) >> 16; - c[1] = (color & 0xff00) >> 8; - c[2] = (color & 0xff); - } - else goto normal; - } - else - { - normal: - // Treat it as a space-delimited hexadecimal string - for (i = 0; i < 3; ++i) - { - // Skip leading whitespace - while (*cstr <= ' ' && *cstr != '\0') - { - cstr++; - } - // Extract a component and convert it to eight-bit - for (p = 0; *cstr > ' '; ++p, ++cstr) - { - if (p < 2) - { - val[p] = *cstr; - } - } - if (p == 0) - { - c[i] = 0; - } - else - { - if (p == 1) - { - val[1] = val[0]; - } - c[i] = ParseHex(val, nullptr); - } - } - } - } - return MAKERGB(c[0], c[1], c[2]); } //========================================================================== @@ -404,7 +353,7 @@ void V_InitFontColors () TranslationLookup.Clear(); TranslationColors.Clear(); - while ((lump = fileSystem.FindLumpFullName("engine/textcolors.txt", &lastlump)) != -1) + while ((lump = fileSystem.FindLump ("TEXTCOLO", &lastlump)) != -1) { FScanner sc(lump); while (sc.GetString()) @@ -447,19 +396,19 @@ void V_InitFontColors () else if (sc.Compare ("Flat:")) { sc.MustGetString(); - logcolor = V_GetColor (sc.String); + logcolor = V_GetColor (nullptr, sc); } else { // Get first color - c = V_GetColor (sc.String); + c = V_GetColor (nullptr, sc); tparm.Start[0] = RPART(c); tparm.Start[1] = GPART(c); tparm.Start[2] = BPART(c); // Get second color sc.MustGetString(); - c = V_GetColor (sc.String); + c = V_GetColor (nullptr, sc); tparm.End[0] = RPART(c); tparm.End[1] = GPART(c); tparm.End[2] = BPART(c); @@ -670,6 +619,14 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int { newcolor = boldcolor; } + else if (newcolor == '!') // Team chat + { + newcolor = PrintColors[PRINT_TEAMCHAT]; + } + else if (newcolor == '*') // Chat + { + newcolor = PrintColors[PRINT_CHAT]; + } else if (newcolor == '[') // Named { const uint8_t *namestart = ch; @@ -705,23 +662,170 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int // // V_InitFonts // +// Fixme: This really needs to be a bit more flexible +// and less rigidly tied to the original game data. +// //========================================================================== void V_InitFonts() { V_InitCustomFonts(); - FFont *CreateHexLumpFont(const char *fontname, const char* lump); - FFont *CreateHexLumpFont2(const char *fontname, const char * lump); + FFont *CreateHexLumpFont(const char *fontname, int lump); + FFont *CreateHexLumpFont2(const char *fontname, int lump); - if (fileSystem.FindFile("engine/newconsolefont.hex") < 0) - I_Error("newconsolefont.hex not found"); // This font is needed - do not start up without it. - NewConsoleFont = CreateHexLumpFont("NewConsoleFont", "engine/newconsolefont.hex"); - NewSmallFont = CreateHexLumpFont2("NewSmallFont", "engine/newconsolefont.hex"); + auto lump = fileSystem.CheckNumForFullName("newconsolefont.hex", 0); // This is always loaded from gzdoom.pk3 to prevent overriding it with incomplete replacements. + if (lump == -1) I_FatalError("newconsolefont.hex not found"); // This font is needed - do not start up without it. + NewConsoleFont = CreateHexLumpFont("NewConsoleFont", lump); + NewSmallFont = CreateHexLumpFont2("NewSmallFont", lump); CurrentConsoleFont = NewConsoleFont; - ConFont = V_GetFont("ConsoleFont", "engine/confont.lmp"); // The con font is needed for the slider graphics - SmallFont = ConFont; // This is so that it doesn't crash and that it immediately gets seen as a proble. The SmallFont should later be mapped to the small game font. + // load the heads-up font + if (!(SmallFont = V_GetFont("SmallFont", "SMALLFNT"))) + { + if (fileSystem.CheckNumForName("FONTA_S") >= 0) + { + int wadfile = -1; + auto a = fileSystem.CheckNumForName("FONTA33", ns_graphics); + if (a != -1) wadfile = fileSystem.GetFileContainer(a); + if (wadfile > fileSystem.GetIwadNum()) + { + // The font has been replaced, so we need to create a copy of the original as well. + SmallFont = new FFont("SmallFont", "FONTA%02u", nullptr, HU_FONTSTART, HU_FONTSIZE, 1, -1); + SmallFont->SetCursor('['); + } + else + { + SmallFont = new FFont("SmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); + SmallFont->SetCursor('['); + } + } + else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + { + int wadfile = -1; + auto a = fileSystem.CheckNumForName("STCFN065", ns_graphics); + if (a != -1) wadfile = fileSystem.GetFileContainer(a); + if (wadfile > fileSystem.GetIwadNum()) + { + // The font has been replaced, so we need to create a copy of the original as well. + SmallFont = new FFont("SmallFont", "STCFN%.3d", nullptr, HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, false, true); + } + else + { + SmallFont = new FFont("SmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, false, true); + } + } + } + + // Create the original small font as a fallback for incomplete definitions. + if (fileSystem.CheckNumForName("FONTA_S") >= 0) + { + OriginalSmallFont = new FFont("OriginalSmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1, -1, false, true); + OriginalSmallFont->SetCursor('['); + } + else if (fileSystem.CheckNumForName("STCFN033", ns_graphics) >= 0) + { + OriginalSmallFont = new FFont("OriginalSmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1, -1, false, true); + } + + if (SmallFont) + { + uint32_t colors[256] = {}; + SmallFont->RecordAllTextureColors(colors); + if (OriginalSmallFont != nullptr) OriginalSmallFont->SetDefaultTranslation(colors); + NewSmallFont->SetDefaultTranslation(colors); + } + + if (!(SmallFont2 = V_GetFont("SmallFont2"))) // Only used by Strife + { + if (fileSystem.CheckNumForName("STBFN033", ns_graphics) >= 0) + { + SmallFont2 = new FFont("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); + } + } + + //This must be read before BigFont so that it can be properly substituted. + BigUpper = V_GetFont("BigUpper"); + + if (!(BigFont = V_GetFont("BigFont"))) + { + if (fileSystem.CheckNumForName("FONTB_S") >= 0) + { + BigFont = new FFont("BigFont", "FONTB%02u", "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); + } + } + + if (!BigFont) + { + // Load the generic fallback if no BigFont is found. + BigFont = V_GetFont("BigFont", "ZBIGFONT"); + } + + if (fileSystem.CheckNumForName("FONTB_S") >= 0) + { + OriginalBigFont = new FFont("OriginalBigFont", "FONTB%02u", "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1, -1, false, true); + } + else + { + OriginalBigFont = new FFont("OriginalBigFont", nullptr, "bigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1, -1, false, true); + } + + if (BigFont) + { + uint32_t colors[256] = {}; + BigFont->RecordAllTextureColors(colors); + if (OriginalBigFont != nullptr) OriginalBigFont->SetDefaultTranslation(colors); + } + + // let PWAD BIGFONTs override the stock BIGUPPER font. (This check needs to be made smarter.) + if (BigUpper && BigFont->Type != FFont::Folder && BigUpper->Type == FFont::Folder) + { + delete BigUpper; + BigUpper = BigFont; + } + + if (BigUpper == nullptr) + { + BigUpper = BigFont; + } + if (!(ConFont = V_GetFont("ConsoleFont", "CONFONT"))) + { + ConFont = SmallFont; + } + if (!(IntermissionFont = FFont::FindFont("IntermissionFont"))) + { + if (fileSystem.CheckNumForName("WINUM0") >= 0) + { + IntermissionFont = FFont::FindFont("IntermissionFont_Doom"); + } + if (IntermissionFont == nullptr) + { + IntermissionFont = BigFont; + } + } + // This can only happen if gzdoom.pk3 is corrupted. ConFont should always be present. + if (ConFont == nullptr) + { + I_FatalError("Console font not found."); + } + // SmallFont and SmallFont2 have no default provided by the engine. BigFont only has in non-Raven games. + if (OriginalSmallFont == nullptr) + { + OriginalSmallFont = ConFont; + } + if (SmallFont == nullptr) + { + SmallFont = OriginalSmallFont; + } + if (SmallFont2 == nullptr) + { + SmallFont2 = SmallFont; + } + if (BigFont == nullptr) + { + BigFont = OriginalBigFont; + } + AlternativeSmallFont = OriginalSmallFont; } void V_ClearFonts() diff --git a/source/core/fonts/v_font.h b/source/common/fonts/v_font.h similarity index 90% rename from source/core/fonts/v_font.h rename to source/common/fonts/v_font.h index 21264a266..74d47d3da 100644 --- a/source/core/fonts/v_font.h +++ b/source/common/fonts/v_font.h @@ -34,15 +34,14 @@ #ifndef __V_FONT_H__ #define __V_FONT_H__ +#include "filesystem.h" #include "vectors.h" -#include "name.h" #include "palentry.h" -#include "tarray.h" -#include "zstring.h" +#include "name.h" class DCanvas; -struct FRemapTable; class FTexture; +struct FRemapTable; enum EColorRange : int { @@ -95,11 +94,13 @@ public: Custom }; + FFont (const char *fontname, const char *nametemplate, const char *filetemplate, int first, int count, int base, int fdlump, int spacewidth=-1, bool notranslate = false, bool iwadonly = false, bool doomtemplate = false); virtual ~FFont (); virtual FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const; - virtual int CharWidth (int code) const; + virtual int GetCharWidth (int code) const; int GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const; + int GetLump() const { return Lump; } int GetSpaceWidth () const { return SpaceWidth; } int GetHeight () const { return FontHeight; } int GetDefaultKerning () const { return GlobalKerning; } @@ -134,15 +135,17 @@ public: protected: - FFont (); + FFont (int lump); void BuildTranslations (const double *luminosity, const uint8_t *identity, - const void *ranges, int total_colors, const PalEntry *palette); + const void *ranges, int total_colors, const PalEntry *palette, std::function post = nullptr); void FixXMoves(); static int SimpleTranslation (uint32_t *colorsused, uint8_t *translation, uint8_t *identity, TArray &Luminosity); + void ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale); + EFontType Type = EFontType::Unknown; int FirstChar, LastChar; int SpaceWidth; @@ -164,11 +167,11 @@ protected: }; TArray Chars; int ActiveColors; - TArray Ranges; + TArray Translations; uint8_t PatchRemap[256]; + int Lump; FName FontName = NAME_None; - TArray rawData; FFont *Next; static FFont *FirstFont; @@ -190,4 +193,5 @@ FFont *V_GetFont(const char *fontname, const char *fontlumpname = nullptr); void V_InitFontColors(); char* CleanseString(char* str); + #endif //__V_FONT_H__ diff --git a/source/common/fonts/v_text.cpp b/source/common/fonts/v_text.cpp index f4c7ddc0c..375e2d67b 100644 --- a/source/common/fonts/v_text.cpp +++ b/source/common/fonts/v_text.cpp @@ -119,7 +119,7 @@ TArray V_BreakLines (FFont *font, int maxwidth, const uint8_t *str lastWasSpace = false; } - nw = font->CharWidth (c); + nw = font->GetCharWidth (c); if ((w > 0 && w + nw > maxwidth) || c == '\n') { // Time to break the line diff --git a/source/common/textures/textures.h b/source/common/textures/textures.h index 9dc891fdb..a4cb09e82 100644 --- a/source/common/textures/textures.h +++ b/source/common/textures/textures.h @@ -432,7 +432,7 @@ protected: uint16_t Width, Height; int16_t _LeftOffset[2], _TopOffset[2]; - FTexture(const char *name = NULL, int lumpnum = -1); + FTexture (const char *name = NULL, int lumpnum = -1); public: FTextureBuffer CreateTexBuffer(int translation, int flags = 0); diff --git a/source/core/console/c_console.cpp b/source/core/console/c_console.cpp index 17141589e..3da41fdfc 100644 --- a/source/core/console/c_console.cpp +++ b/source/core/console/c_console.cpp @@ -202,13 +202,13 @@ public: if (scale == 1) { DrawChar(twod, CurrentConsoleFont, CR_ORANGE, x, y, '\x1c', TAG_DONE); - DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->CharWidth(0x1c), y, + DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, &Text[StartPos], TAG_DONE); if (cursor) { DrawChar(twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->CharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->CharWidth(0xb), + x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), y, '\xb', TAG_DONE); } } @@ -219,7 +219,7 @@ public: DTA_VirtualHeight, screen->GetHeight() / scale, DTA_KeepRatio, true, TAG_DONE); - DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->CharWidth(0x1c), y, + DrawText(twod, CurrentConsoleFont, CR_ORANGE, x + CurrentConsoleFont->GetCharWidth(0x1c), y, &Text[StartPos], DTA_VirtualWidth, screen->GetWidth() / scale, DTA_VirtualHeight, screen->GetHeight() / scale, @@ -228,7 +228,7 @@ public: if (cursor) { DrawChar(twod, CurrentConsoleFont, CR_YELLOW, - x + CurrentConsoleFont->CharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->CharWidth(0xb), + x + CurrentConsoleFont->GetCharWidth(0x1c) + (CursorPosCells - StartPosCells) * CurrentConsoleFont->GetCharWidth(0xb), y, '\xb', DTA_VirtualWidth, screen->GetWidth() / scale, DTA_VirtualHeight, screen->GetHeight() / scale, @@ -612,7 +612,7 @@ void C_InitConsole (int width, int height, bool ingame) vidactive = ingame; if (CurrentConsoleFont != NULL) { - cwidth = CurrentConsoleFont->CharWidth ('M'); + cwidth = CurrentConsoleFont->GetCharWidth ('M'); cheight = CurrentConsoleFont->GetHeight(); } else diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index bc24e6847..d787c6d20 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -712,6 +712,7 @@ int RunGame() { playername = userConfig.CommandName; } + GPalette.Init(MAXPALOOKUPS + 2); // one slot for each translation, plus a separate one for the base palettes and the internal one TexMan.Init([]() {}, [](BuildInfo &) {}); V_InitFonts(); TileFiles.Init(); diff --git a/source/glbackend/gl_texture.cpp b/source/glbackend/gl_texture.cpp index 7598cdb0c..eaa614574 100644 --- a/source/glbackend/gl_texture.cpp +++ b/source/glbackend/gl_texture.cpp @@ -255,7 +255,7 @@ bool GLInstance::SetTextureInternal(int picnum, FTexture* tex, int palette, int applytint = true; if (!(h.f & HICTINT_APPLYOVERPALSWAP)) usepalswap = 0; } - lookuppal = palmanager.LookupPalette(usepalette, usepalswap, false, 0); + lookuppal = TRANSLATION(usepalette + Translation_Remap, usepalswap); } } diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp index 2aaae3603..4af19143d 100644 --- a/source/glbackend/hw_draw2d.cpp +++ b/source/glbackend/hw_draw2d.cpp @@ -177,7 +177,8 @@ void GLInstance::Draw2D(F2DDrawer *drawer) auto saved = curbasepal; // screw Build's dependencies on global state variables. We only need to change this for the following SetTexture call. curbasepal = (cmd.mRemapIndex >> 8) & 0xff; auto savedf = globalflags; - if (curbasepal > 0) globalflags |= GLOBAL_NO_GL_FULLBRIGHT; // temp. hack to disable brightmaps. + if (curbasepal > 0) + globalflags |= GLOBAL_NO_GL_FULLBRIGHT; // temp. hack to disable brightmaps. SetTexture(-1, tex, cmd.mRemapIndex & 0xff, 4/*DAMETH_CLAMPED*/, cmd.mFlags & F2DDrawer::DTF_Wrap ? SamplerRepeat : SamplerClampXY); curbasepal = saved; globalflags = savedf; diff --git a/wadsrc/static/engine/Roboto-Regular.ttf b/wadsrc/static/engine/Roboto-Regular.ttf deleted file mode 100644 index 2c97eeadf..000000000 Binary files a/wadsrc/static/engine/Roboto-Regular.ttf and /dev/null differ diff --git a/wadsrc/static/engine/confont.lmp b/wadsrc/static/engine/confont.lmp deleted file mode 100644 index 3d46a3ca4..000000000 Binary files a/wadsrc/static/engine/confont.lmp and /dev/null differ diff --git a/wadsrc/static/engine/newconsolefont.hex b/wadsrc/static/newconsolefont.hex similarity index 100% rename from wadsrc/static/engine/newconsolefont.hex rename to wadsrc/static/newconsolefont.hex diff --git a/wadsrc/static/engine/textcolors.txt b/wadsrc/static/textcolors.txt similarity index 100% rename from wadsrc/static/engine/textcolors.txt rename to wadsrc/static/textcolors.txt