Ejemplo n.º 1
0
static TArray<FString> PSR_ReadBaseInstalls(FScanner &sc)
{
	TArray<FString> result;

	// Get a list of possible install directories.
	while(sc.GetToken())
	{
		if(sc.TokenType == '}')
			break;

		sc.TokenMustBe(TK_StringConst);
		FString key(sc.String);
		if(key.Left(18).CompareNoCase("BaseInstallFolder_") == 0)
		{
			sc.MustGetToken(TK_StringConst);
			result.Push(FString(sc.String) + "/steamapps/common");
		}
		else
		{
			if(sc.CheckToken('{'))
				PSR_FindEndBlock(sc);
			else
				sc.MustGetToken(TK_StringConst);
		}
	}

	return result;
}
Ejemplo n.º 2
0
static bool PSR_FindAndEnterBlock(FScanner &sc, const char* keyword)
{
	// Finds a block with a given keyword and then enter it (opening brace)
	// Should be closed with PSR_FindEndBlock
	while(sc.GetToken())
	{
		if(sc.TokenType == '}')
		{
			sc.UnGet();
			return false;
		}

		sc.TokenMustBe(TK_StringConst);
		if(!sc.Compare(keyword))
		{
			if(!sc.CheckToken(TK_StringConst))
				PSR_SkipBlock(sc);
		}
		else
		{
			sc.MustGetToken('{');
			return true;
		}
	}
	return false;
}
Ejemplo n.º 3
0
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)
{
	int i;
	FTextureID lump;
	char buffer[12];
	int maxyoffs;
	bool doomtemplate = (nametemplate && (gameinfo.gametype & GAME_DoomChex)) ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
	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<int, FTexture*> 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<FolderEntry> 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.
		Wads.GetLumpsInFolder(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'.
						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())
					{
						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<FTextureID> 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->SourceLump >= 0 && Wads.GetLumpFile(tex->SourceLump) <= Wads.GetIwadNum() && tex->UseType == 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;

		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();
}
Ejemplo n.º 4
0
void FRemapTable::AddToTranslation(const char *range)
{
	int start,end;
	bool desaturated = false;
	FScanner sc;

	sc.OpenMem("translation", range, int(strlen(range)));
	sc.SetCMode(true);

	try
	{
		sc.MustGetToken(TK_IntConst);
		start = sc.Number;
		sc.MustGetToken(':');
		sc.MustGetToken(TK_IntConst);
		end = sc.Number;
		sc.MustGetToken('=');
		if (start < 0 || start > 255 || end < 0 || end > 255)
		{
			sc.ScriptError("Palette index out of range");
			return;
		}

		sc.MustGetAnyToken();

		if (sc.TokenType != '[' && sc.TokenType != '%')
		{
			int pal1,pal2;

			sc.TokenMustBe(TK_IntConst);
			pal1 = sc.Number;
			sc.MustGetToken(':');
			sc.MustGetToken(TK_IntConst);
			pal2 = sc.Number;
			AddIndexRange(start, end, pal1, pal2);
		}
		else if (sc.TokenType == '[')
		{ 
			// translation using RGB values
			int r1,g1,b1,r2,g2,b2;

			sc.MustGetToken(TK_IntConst);
			r1 = sc.Number;
			sc.MustGetToken(',');

			sc.MustGetToken(TK_IntConst);
			g1 = sc.Number;
			sc.MustGetToken(',');

			sc.MustGetToken(TK_IntConst);
			b1 = sc.Number;
			sc.MustGetToken(']');
			sc.MustGetToken(':');
			sc.MustGetToken('[');

			sc.MustGetToken(TK_IntConst);
			r2 = sc.Number;
			sc.MustGetToken(',');

			sc.MustGetToken(TK_IntConst);
			g2 = sc.Number;
			sc.MustGetToken(',');

			sc.MustGetToken(TK_IntConst);
			b2 = sc.Number;
			sc.MustGetToken(']');

			AddColorRange(start, end, r1, g1, b1, r2, g2, b2);
		}
		else if (sc.TokenType == '%')
		{
			// translation using RGB values
			double r1,g1,b1,r2,g2,b2;

			sc.MustGetToken('[');
			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			r1 = sc.Float;
			sc.MustGetToken(',');

			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			g1 = sc.Float;
			sc.MustGetToken(',');

			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			b1 = sc.Float;
			sc.MustGetToken(']');
			sc.MustGetToken(':');
			sc.MustGetToken('[');

			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			r2 = sc.Float;
			sc.MustGetToken(',');

			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			g2 = sc.Float;
			sc.MustGetToken(',');

			sc.MustGetAnyToken();
			if (sc.TokenType != TK_IntConst) sc.TokenMustBe(TK_FloatConst);
			b2 = sc.Float;
			sc.MustGetToken(']');

			AddDesaturation(start, end, r1, g1, b1, r2, g2, b2);
		}
	}
	catch (CRecoverableError &err)
	{
		Printf("Error in translation '%s':\n%s\n", range, err.GetMessage());
	}
}