From 45d75745f0e0b1914b6671ea34b92b095a961f02 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 17 Feb 2019 19:15:57 +0100 Subject: [PATCH] - reworked console font loading to use the glyph sheets directly and allowing to load more than one per font. --- src/gamedata/fonts/font.cpp | 304 ++++++++++++++++------- src/gamedata/fonts/v_font.cpp | 45 ++-- src/gamedata/fonts/v_font.h | 4 + wadsrc/static/confont.lmp | Bin 10302 -> 0 bytes wadsrc/static/fonts/consolefont/0000.png | Bin 0 -> 3827 bytes wadsrc/static/fonts/consolefont/0400.png | Bin 0 -> 2073 bytes wadsrc/static/fonts/consolefont/font.inf | 3 + 7 files changed, 239 insertions(+), 117 deletions(-) delete mode 100644 wadsrc/static/confont.lmp create mode 100644 wadsrc/static/fonts/consolefont/0000.png create mode 100644 wadsrc/static/fonts/consolefont/0400.png create mode 100644 wadsrc/static/fonts/consolefont/font.inf diff --git a/src/gamedata/fonts/font.cpp b/src/gamedata/fonts/font.cpp index 4b7b5b8da7..a151f10956 100644 --- a/src/gamedata/fonts/font.cpp +++ b/src/gamedata/fonts/font.cpp @@ -55,6 +55,7 @@ #include "image.h" #include "utf8.h" #include "textures/formats/fontchars.h" +#include "textures/formats/multipatchtexture.h" #include "fontinternals.h" @@ -91,6 +92,7 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla uint8_t pp = 0; for (auto &p : PatchRemap) p = pp++; translateUntranslated = false; + int FixedWidth = 0; maxyoffs = 0; @@ -151,6 +153,14 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla 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); @@ -172,130 +182,236 @@ FFont::FFont (const char *name, const char *nametemplate, const char *filetempla } } - - if (nametemplate != nullptr) + if (FixedWidth > 0) { - for (i = 0; i < lcount; i++) - { - int position = '!' + 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'. - if (!TexMan.CheckForTexture("STCFN120", ETextureType::MiscPatch).isValid() || - !TexMan.CheckForTexture("STCFN122", ETextureType::MiscPatch).isValid()) - { - // insert the incorrectly named '|' graphic in its correct position. - position = 124; - } - } - if (lump.isValid()) - { - if (position < minchar) minchar = position; - if (position > maxchar) maxchar = position; - charMap.Insert(position, TexMan.GetTexture(lump)); - } - } + ReadSheetFont(folderdata, FixedWidth, FontHeight, Scale); } - if (folderdata.Size() > 0) + else { - // all valid lumps must be named with a hex number that represents its Unicode character index. - for (auto &entry : folderdata) + if (nametemplate != nullptr) { - char *endp; - auto base = ExtractFileBase(entry.name); - auto position = strtoll(base.GetChars(), &endp, 16); - if ((*endp == 0 || (*endp == '.' && position >= '!' && position < 0xffff))) + for (i = 0; i < lcount; i++) { - auto lump = TexMan.CheckForTexture(entry.name, ETextureType::MiscPatch); + int position = '!' + 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'. + if (!TexMan.CheckForTexture("STCFN120", ETextureType::MiscPatch).isValid() || + !TexMan.CheckForTexture("STCFN122", ETextureType::MiscPatch).isValid()) + { + // insert the incorrectly named '|' graphic in its correct position. + position = 124; + } + } 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); + if (position < minchar) minchar = position; + if (position > maxchar) maxchar = position; + charMap.Insert(position, TexMan.GetTexture(lump)); + } + } + } + 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); + } + } + } + } + FirstChar = minchar; + LastChar = maxchar; + auto count = maxchar - minchar + 1; + Chars.Resize(count); + int fontheight = 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; + } + } + + pic->SetUseType(ETextureType::FontChar); + if (!noTranslate) + { + Chars[i].OriginalPic = 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].TranslatedPic); + } + else + { + Chars[i].TranslatedPic = pic; + } + + 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; + + 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->GetWidth() / width; + int numtex_y = tex->GetHeight() / 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(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 (i = 0; i < count; i++) + for (int 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; - } - } + auto b = pic->Get8BitPixels(false); - pic->SetUseType(ETextureType::FontChar); - if (!noTranslate) - { - Chars[i].OriginalPic = 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].TranslatedPic); - } - else - { - Chars[i].TranslatedPic = pic; - } - - Chars[i].XMove = Chars[i].TranslatedPic->GetDisplayWidth(); + Chars[i].OriginalPic = 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].TranslatedPic); } - else + Chars[i].XMove = width; + } + + if (map1252) + { + // Move the Windows-1252 characters to their proper place. + for (int i = 0x80; i < 0xa0; i++) { - Chars[i].TranslatedPic = nullptr; - Chars[i].XMove = INT_MIN; + 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]); + } } } - - 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; - FixXMoves(); - - if (!noTranslate) LoadTranslations(); + SpaceWidth = width; } //========================================================================== diff --git a/src/gamedata/fonts/v_font.cpp b/src/gamedata/fonts/v_font.cpp index 4dbcc53174..4e4a5382f6 100644 --- a/src/gamedata/fonts/v_font.cpp +++ b/src/gamedata/fonts/v_font.cpp @@ -1415,50 +1415,50 @@ EColorRange V_ParseFontColor (const uint8_t *&color_value, int normalcolor, int void V_InitFonts() { InitLowerUpper(); - V_InitCustomFonts (); + V_InitCustomFonts(); // load the heads-up font if (!(SmallFont = V_GetFont("SmallFont", "SMALLFNT"))) { - if (Wads.CheckNumForName ("FONTA_S") >= 0) + if (Wads.CheckNumForName("FONTA_S") >= 0) { - SmallFont = new FFont ("SmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); + SmallFont = new FFont("SmallFont", "FONTA%02u", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); SmallFont->SetCursor('['); } - else if (Wads.CheckNumForName ("STCFN033", ns_graphics) >= 0) + else if (Wads.CheckNumForName("STCFN033", ns_graphics) >= 0) { - SmallFont = new FFont ("SmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); + SmallFont = new FFont("SmallFont", "STCFN%.3d", "defsmallfont", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); } } if (!(SmallFont2 = V_GetFont("SmallFont2"))) // Only used by Strife { - if (Wads.CheckNumForName ("STBFN033", ns_graphics) >= 0) + if (Wads.CheckNumForName("STBFN033", ns_graphics) >= 0) { - SmallFont2 = new FFont ("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); - } + SmallFont2 = new FFont("SmallFont2", "STBFN%.3d", "defsmallfont2", HU_FONTSTART, HU_FONTSIZE, HU_FONTSTART, -1); } + } if (!(BigFont = V_GetFont("BigFont"))) { if (gameinfo.gametype & GAME_Raven) { - BigFont = new FFont ("BigFont", "FONTB%02u", "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); - } + BigFont = new FFont("BigFont", "FONTB%02u", "defbigfont", HU_FONTSTART, HU_FONTSIZE, 1, -1); } + } if (!(ConFont = V_GetFont("ConsoleFont", "CONFONT"))) - { + { ConFont = SmallFont; - } + } if (!(IntermissionFont = FFont::FindFont("IntermissionFont"))) - { + { if (gameinfo.gametype & GAME_DoomChex) - { + { IntermissionFont = FFont::FindFont("IntermissionFont_Doom"); - } - if (IntermissionFont == nullptr) - { - IntermissionFont = BigFont; - } } + if (IntermissionFont == nullptr) + { + IntermissionFont = BigFont; + } + } // This can only happen if gzdoom.pk3 is corrupted. ConFont should always be present. if (ConFont == nullptr) { @@ -1472,12 +1472,11 @@ void V_InitFonts() if (SmallFont2 == nullptr) { SmallFont2 = SmallFont; - } + } if (BigFont == nullptr) - { + { BigFont = SmallFont; - } - + } } void V_ClearFonts() diff --git a/src/gamedata/fonts/v_font.h b/src/gamedata/fonts/v_font.h index a4bf7c7386..0702781e99 100644 --- a/src/gamedata/fonts/v_font.h +++ b/src/gamedata/fonts/v_font.h @@ -35,6 +35,8 @@ #define __V_FONT_H__ #include "doomtype.h" +#include "w_wad.h" +#include "vectors.h" class DCanvas; struct FRemapTable; @@ -114,6 +116,8 @@ protected: static int SimpleTranslation (uint8_t *colorsused, uint8_t *translation, uint8_t *identity, TArray &Luminosity); + void ReadSheetFont(TArray &folderdata, int width, int height, const DVector2 &Scale); + int FirstChar, LastChar; int SpaceWidth; int FontHeight; diff --git a/wadsrc/static/confont.lmp b/wadsrc/static/confont.lmp deleted file mode 100644 index 6b68df2e3e3004a2752dc9b53f65d3a06d0a7ec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10302 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 diff --git a/wadsrc/static/fonts/consolefont/0000.png b/wadsrc/static/fonts/consolefont/0000.png new file mode 100644 index 0000000000000000000000000000000000000000..aa78736f71935569ba563838e0ed9c69c660156e GIT binary patch literal 3827 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 literal 0 HcmV?d00001 diff --git a/wadsrc/static/fonts/consolefont/font.inf b/wadsrc/static/fonts/consolefont/font.inf new file mode 100644 index 0000000000..897845b494 --- /dev/null +++ b/wadsrc/static/fonts/consolefont/font.inf @@ -0,0 +1,3 @@ +TranslationType Console +CellSize 8, 8 // This implies font sheets +