mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 07:12:02 +00:00
Merge remote-tracking branch 'origin/Texture_Cleanup' into softwarescaling
This commit is contained in:
commit
3fc9dd4144
16 changed files with 179 additions and 253 deletions
|
@ -223,8 +223,7 @@ DEFINE_FIELD_X(DehInfo, DehInfo, BlueAC)
|
||||||
|
|
||||||
TArray<PClassActor *> TouchedActors;
|
TArray<PClassActor *> TouchedActors;
|
||||||
|
|
||||||
char *UnchangedSpriteNames;
|
TArray<uint32_t> UnchangedSpriteNames;
|
||||||
int NumUnchangedSprites;
|
|
||||||
bool changedStates;
|
bool changedStates;
|
||||||
|
|
||||||
// Sprite<->Class map for DehackedPickup::DetermineType
|
// Sprite<->Class map for DehackedPickup::DetermineType
|
||||||
|
@ -395,17 +394,10 @@ static bool HandleKey (const struct Key *keys, void *structure, const char *key,
|
||||||
|
|
||||||
static int FindSprite (const char *sprname)
|
static int FindSprite (const char *sprname)
|
||||||
{
|
{
|
||||||
int i;
|
uint32_t nameint;
|
||||||
uint32_t nameint = *((uint32_t *)sprname);
|
memcpy(&nameint, sprname, 4);
|
||||||
|
auto f = UnchangedSpriteNames.Find(nameint);
|
||||||
for (i = 0; i < NumUnchangedSprites; ++i)
|
return f == UnchangedSpriteNames.Size() ? -1 : f;
|
||||||
{
|
|
||||||
if (*((uint32_t *)&UnchangedSpriteNames[i*4]) == nameint)
|
|
||||||
{
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static FState *FindState (int statenum)
|
static FState *FindState (int statenum)
|
||||||
|
@ -2665,31 +2657,16 @@ static void UnloadDehSupp ()
|
||||||
// that was altered by the first. So we need to keep the
|
// that was altered by the first. So we need to keep the
|
||||||
// StateMap around until all patches have been applied.
|
// StateMap around until all patches have been applied.
|
||||||
DehUseCount = 0;
|
DehUseCount = 0;
|
||||||
Actions.Clear();
|
Actions.Reset();
|
||||||
Actions.ShrinkToFit();
|
OrgHeights.Reset();
|
||||||
OrgHeights.Clear();
|
CodePConv.Reset();
|
||||||
OrgHeights.ShrinkToFit();
|
OrgSprNames.Reset();
|
||||||
CodePConv.Clear();
|
SoundMap.Reset();
|
||||||
CodePConv.ShrinkToFit();
|
InfoNames.Reset();
|
||||||
OrgSprNames.Clear();
|
BitNames.Reset();
|
||||||
OrgSprNames.ShrinkToFit();
|
StyleNames.Reset();
|
||||||
SoundMap.Clear();
|
AmmoNames.Reset();
|
||||||
SoundMap.ShrinkToFit();
|
UnchangedSpriteNames.Reset();
|
||||||
InfoNames.Clear();
|
|
||||||
InfoNames.ShrinkToFit();
|
|
||||||
BitNames.Clear();
|
|
||||||
BitNames.ShrinkToFit();
|
|
||||||
StyleNames.Clear();
|
|
||||||
StyleNames.ShrinkToFit();
|
|
||||||
AmmoNames.Clear();
|
|
||||||
AmmoNames.ShrinkToFit();
|
|
||||||
|
|
||||||
if (UnchangedSpriteNames != NULL)
|
|
||||||
{
|
|
||||||
delete[] UnchangedSpriteNames;
|
|
||||||
UnchangedSpriteNames = NULL;
|
|
||||||
NumUnchangedSprites = 0;
|
|
||||||
}
|
|
||||||
if (EnglishStrings != NULL)
|
if (EnglishStrings != NULL)
|
||||||
{
|
{
|
||||||
delete EnglishStrings;
|
delete EnglishStrings;
|
||||||
|
@ -2731,14 +2708,11 @@ static bool LoadDehSupp ()
|
||||||
EnglishStrings->LoadStrings (true);
|
EnglishStrings->LoadStrings (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UnchangedSpriteNames == NULL)
|
|
||||||
|
UnchangedSpriteNames.Resize(sprites.Size());
|
||||||
|
for (unsigned i = 0; i < UnchangedSpriteNames.Size(); ++i)
|
||||||
{
|
{
|
||||||
UnchangedSpriteNames = new char[sprites.Size()*4];
|
memcpy (&UnchangedSpriteNames[i], &sprites[i].name, 4);
|
||||||
NumUnchangedSprites = sprites.Size();
|
|
||||||
for (i = 0; i < NumUnchangedSprites; ++i)
|
|
||||||
{
|
|
||||||
memcpy (UnchangedSpriteNames+i*4, &sprites[i].name, 4);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FScanner sc;
|
FScanner sc;
|
||||||
|
|
|
@ -2709,7 +2709,7 @@ void D_DoomMain (void)
|
||||||
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
|
DestroyCVarsFlagged(CVAR_MOD); // Delete any cvar left by mods
|
||||||
FS_Close(); // destroy the global FraggleScript.
|
FS_Close(); // destroy the global FraggleScript.
|
||||||
DeinitMenus();
|
DeinitMenus();
|
||||||
LightDefaults.Clear(); // this can leak heap memory if it isn't cleared.
|
LightDefaults.DeleteAndClear(); // this can leak heap memory if it isn't cleared.
|
||||||
|
|
||||||
// delete DoomStartupInfo data
|
// delete DoomStartupInfo data
|
||||||
DoomStartupInfo.Name = (const char*)0;
|
DoomStartupInfo.Name = (const char*)0;
|
||||||
|
|
|
@ -85,7 +85,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
FName m_Name;
|
FName m_Name = NAME_None;
|
||||||
int m_Args[5] = { 0,0,0,0,0 };
|
int m_Args[5] = { 0,0,0,0,0 };
|
||||||
double m_Param = 0;
|
double m_Param = 0;
|
||||||
DVector3 m_Pos = { 0,0,0 };
|
DVector3 m_Pos = { 0,0,0 };
|
||||||
|
|
|
@ -1379,7 +1379,8 @@ public:
|
||||||
width = font->GetCharWidth((unsigned char) *str);
|
width = font->GetCharWidth((unsigned char) *str);
|
||||||
else
|
else
|
||||||
width = font->GetCharWidth((unsigned char) script->spacingCharacter);
|
width = font->GetCharWidth((unsigned char) script->spacingCharacter);
|
||||||
FTexture* c = font->GetChar((unsigned char) *str, &width);
|
bool redirected = false;
|
||||||
|
FTexture* c = font->GetChar((unsigned char) *str, fontcolor, &width);
|
||||||
if(c == NULL) //missing character.
|
if(c == NULL) //missing character.
|
||||||
{
|
{
|
||||||
str++;
|
str++;
|
||||||
|
|
|
@ -1513,7 +1513,7 @@ void DBaseStatusBar::DrawString(FFont *font, const FString &cstring, double x, d
|
||||||
}
|
}
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
FTexture* c = font->GetChar((unsigned char)ch, &width);
|
FTexture* c = font->GetChar((unsigned char)ch, fontcolor, &width);
|
||||||
if (c == NULL) //missing character.
|
if (c == NULL) //missing character.
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -966,11 +966,11 @@ void FGLRenderBuffers::RenderEffect(const FString &name)
|
||||||
auto &shader = GLShaders[step.ShaderName];
|
auto &shader = GLShaders[step.ShaderName];
|
||||||
|
|
||||||
// Set uniforms
|
// Set uniforms
|
||||||
if (step.Uniforms.Size > 0)
|
if (step.Uniforms.Data.Size() > 0)
|
||||||
{
|
{
|
||||||
if (!shader->Uniforms)
|
if (!shader->Uniforms)
|
||||||
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false));
|
shader->Uniforms.reset(screen->CreateDataBuffer(POSTPROCESS_BINDINGPOINT, false));
|
||||||
shader->Uniforms->SetData(step.Uniforms.Size, step.Uniforms.Data);
|
shader->Uniforms->SetData(step.Uniforms.Data.Size(), step.Uniforms.Data.Data());
|
||||||
shader->Uniforms->BindBase();
|
shader->Uniforms->BindBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,12 +38,7 @@ public:
|
||||||
|
|
||||||
PPUniforms(const PPUniforms &src)
|
PPUniforms(const PPUniforms &src)
|
||||||
{
|
{
|
||||||
if (src.Size > 0)
|
Data = src.Data;
|
||||||
{
|
|
||||||
Data = new uint8_t[src.Size];
|
|
||||||
Size = src.Size;
|
|
||||||
memcpy(Data, src.Data, Size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~PPUniforms()
|
~PPUniforms()
|
||||||
|
@ -53,49 +48,26 @@ public:
|
||||||
|
|
||||||
PPUniforms &operator=(const PPUniforms &src)
|
PPUniforms &operator=(const PPUniforms &src)
|
||||||
{
|
{
|
||||||
if (this != &src)
|
Data = src.Data;
|
||||||
{
|
|
||||||
if (src.Size > 0)
|
|
||||||
{
|
|
||||||
Data = new uint8_t[src.Size];
|
|
||||||
Size = src.Size;
|
|
||||||
memcpy(Data, src.Data, Size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete[] Data;
|
|
||||||
Data = nullptr;
|
|
||||||
Size = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear()
|
void Clear()
|
||||||
{
|
{
|
||||||
delete[] Data;
|
Data.Clear();
|
||||||
Data = nullptr;
|
|
||||||
Size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void Set(const T &v)
|
void Set(const T &v)
|
||||||
{
|
{
|
||||||
if (Size != (int)sizeof(T))
|
if (Data.Size() != (int)sizeof(T))
|
||||||
{
|
{
|
||||||
delete[] Data;
|
Data.Resize(sizeof(T));
|
||||||
Data = nullptr;
|
memcpy(Data.Data(), &v, Data.Size());
|
||||||
Size = 0;
|
|
||||||
|
|
||||||
Data = new uint8_t[sizeof(T)];
|
|
||||||
Size = sizeof(T);
|
|
||||||
memcpy(Data, &v, Size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *Data = nullptr;
|
TArray<uint8_t> Data;
|
||||||
int Size = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class PPStep
|
class PPStep
|
||||||
|
|
|
@ -337,7 +337,7 @@ void DIntermissionScreenText::Drawer ()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
pic = SmallFont->GetChar (c, &w);
|
pic = SmallFont->GetChar (c, mTextColor, &w);
|
||||||
w += kerning;
|
w += kerning;
|
||||||
w *= CleanXfac;
|
w *= CleanXfac;
|
||||||
if (cx + w > SCREENWIDTH)
|
if (cx + w > SCREENWIDTH)
|
||||||
|
|
|
@ -59,10 +59,9 @@ FRandom pr_railtrail("RailTrail");
|
||||||
#define FADEFROMTTL(a) (1.f/(a))
|
#define FADEFROMTTL(a) (1.f/(a))
|
||||||
|
|
||||||
// [RH] particle globals
|
// [RH] particle globals
|
||||||
uint16_t NumParticles;
|
uint32_t ActiveParticles;
|
||||||
uint16_t ActiveParticles;
|
uint32_t InactiveParticles;
|
||||||
uint16_t InactiveParticles;
|
TArray<particle_t> Particles;
|
||||||
particle_t *Particles;
|
|
||||||
TArray<uint16_t> ParticlesInSubsec;
|
TArray<uint16_t> ParticlesInSubsec;
|
||||||
|
|
||||||
static int grey1, grey2, grey3, grey4, red, green, blue, yellow, black,
|
static int grey1, grey2, grey3, grey4, red, green, blue, yellow, black,
|
||||||
|
@ -105,13 +104,13 @@ static const struct ColorList {
|
||||||
|
|
||||||
inline particle_t *NewParticle (void)
|
inline particle_t *NewParticle (void)
|
||||||
{
|
{
|
||||||
particle_t *result = NULL;
|
particle_t *result = nullptr;
|
||||||
if (InactiveParticles != NO_PARTICLE)
|
if (InactiveParticles != NO_PARTICLE)
|
||||||
{
|
{
|
||||||
result = Particles + InactiveParticles;
|
result = &Particles[InactiveParticles];
|
||||||
InactiveParticles = result->tnext;
|
InactiveParticles = result->tnext;
|
||||||
result->tnext = ActiveParticles;
|
result->tnext = ActiveParticles;
|
||||||
ActiveParticles = uint16_t(result - Particles);
|
ActiveParticles = uint32_t(result - Particles.Data());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +119,6 @@ inline particle_t *NewParticle (void)
|
||||||
// [RH] Particle functions
|
// [RH] Particle functions
|
||||||
//
|
//
|
||||||
void P_InitParticles ();
|
void P_InitParticles ();
|
||||||
void P_DeinitParticles ();
|
|
||||||
|
|
||||||
// [BC] Allow the maximum number of particles to be specified by a cvar (so people
|
// [BC] Allow the maximum number of particles to be specified by a cvar (so people
|
||||||
// with lots of nice hardware can have lots of particles!).
|
// with lots of nice hardware can have lots of particles!).
|
||||||
|
@ -135,7 +133,6 @@ CUSTOM_CVAR( Int, r_maxparticles, 4000, CVAR_ARCHIVE )
|
||||||
|
|
||||||
if ( gamestate != GS_STARTUP )
|
if ( gamestate != GS_STARTUP )
|
||||||
{
|
{
|
||||||
P_DeinitParticles( );
|
|
||||||
P_InitParticles( );
|
P_InitParticles( );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,33 +149,21 @@ void P_InitParticles ()
|
||||||
num = r_maxparticles;
|
num = r_maxparticles;
|
||||||
|
|
||||||
// This should be good, but eh...
|
// This should be good, but eh...
|
||||||
NumParticles = (uint16_t)clamp<int>(num, 100, 65535);
|
int NumParticles = clamp<int>(num, 100, 65535);
|
||||||
|
|
||||||
P_DeinitParticles();
|
Particles.Resize(NumParticles);
|
||||||
Particles = new particle_t[NumParticles];
|
|
||||||
P_ClearParticles ();
|
P_ClearParticles ();
|
||||||
atterm (P_DeinitParticles);
|
|
||||||
}
|
|
||||||
|
|
||||||
void P_DeinitParticles()
|
|
||||||
{
|
|
||||||
if (Particles != NULL)
|
|
||||||
{
|
|
||||||
delete[] Particles;
|
|
||||||
Particles = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void P_ClearParticles ()
|
void P_ClearParticles ()
|
||||||
{
|
{
|
||||||
int i;
|
int i = 0;
|
||||||
|
memset (Particles.Data(), 0, Particles.Size() * sizeof(particle_t));
|
||||||
memset (Particles, 0, NumParticles * sizeof(particle_t));
|
|
||||||
ActiveParticles = NO_PARTICLE;
|
ActiveParticles = NO_PARTICLE;
|
||||||
InactiveParticles = 0;
|
InactiveParticles = 0;
|
||||||
for (i = 0; i < NumParticles-1; i++)
|
for (auto &p : Particles)
|
||||||
Particles[i].tnext = i + 1;
|
p.tnext = ++i;
|
||||||
Particles[i].tnext = NO_PARTICLE;
|
Particles.Last().tnext = NO_PARTICLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group particles by subsectors. Because particles are always
|
// Group particles by subsectors. Because particles are always
|
||||||
|
@ -255,7 +240,7 @@ void P_ThinkParticles ()
|
||||||
prev = NULL;
|
prev = NULL;
|
||||||
while (i != NO_PARTICLE)
|
while (i != NO_PARTICLE)
|
||||||
{
|
{
|
||||||
particle = Particles + i;
|
particle = &Particles[i];
|
||||||
i = particle->tnext;
|
i = particle->tnext;
|
||||||
if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN)))
|
if (!particle->notimefreeze && ((bglobal.freeze) || (level.flags2 & LEVEL2_FROZEN)))
|
||||||
{
|
{
|
||||||
|
@ -274,7 +259,7 @@ void P_ThinkParticles ()
|
||||||
else
|
else
|
||||||
ActiveParticles = i;
|
ActiveParticles = i;
|
||||||
particle->tnext = InactiveParticles;
|
particle->tnext = InactiveParticles;
|
||||||
InactiveParticles = (int)(particle - Particles);
|
InactiveParticles = (int)(particle - Particles.Data());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ struct particle_t
|
||||||
uint16_t snext;
|
uint16_t snext;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern particle_t *Particles;
|
extern TArray<particle_t> Particles;
|
||||||
extern TArray<uint16_t> ParticlesInSubsec;
|
extern TArray<uint16_t> ParticlesInSubsec;
|
||||||
|
|
||||||
const uint16_t NO_PARTICLE = 0xffff;
|
const uint16_t NO_PARTICLE = 0xffff;
|
||||||
|
|
|
@ -189,7 +189,7 @@ void RenderPolyScene::RenderSubsector(PolyRenderThread *thread, subsector_t *sub
|
||||||
int subsectorIndex = sub->Index();
|
int subsectorIndex = sub->Index();
|
||||||
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
|
for (int i = ParticlesInSubsec[subsectorIndex]; i != NO_PARTICLE; i = Particles[i].snext)
|
||||||
{
|
{
|
||||||
particle_t *particle = Particles + i;
|
particle_t *particle = &Particles[i];
|
||||||
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue));
|
thread->TranslucentObjects.push_back(thread->FrameMemory->NewObject<PolyTranslucentParticle>(particle, sub, subsectorDepth, CurrentViewpoint->StencilValue));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1758,7 +1758,7 @@ void ParseGLDefs()
|
||||||
{
|
{
|
||||||
const char *defsLump = NULL;
|
const char *defsLump = NULL;
|
||||||
|
|
||||||
LightDefaults.Clear();
|
LightDefaults.DeleteAndClear();
|
||||||
//gl_DestroyUserShaders(); function says 'todo'
|
//gl_DestroyUserShaders(); function says 'todo'
|
||||||
switch (gameinfo.gametype)
|
switch (gameinfo.gametype)
|
||||||
{
|
{
|
||||||
|
|
|
@ -616,7 +616,7 @@ namespace swrenderer
|
||||||
int shade = LightVisibility::LightLevelToShade((floorlightlevel + ceilinglightlevel) / 2 + LightVisibility::ActualExtraLight(foggy, Thread->Viewport.get()), foggy);
|
int shade = LightVisibility::LightLevelToShade((floorlightlevel + ceilinglightlevel) / 2 + LightVisibility::ActualExtraLight(foggy, Thread->Viewport.get()), foggy);
|
||||||
for (int i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext)
|
for (int i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext)
|
||||||
{
|
{
|
||||||
RenderParticle::Project(Thread, Particles + i, sub->sector, shade, FakeSide, foggy);
|
RenderParticle::Project(Thread, &Particles[i], sub->sector, shade, FakeSide, foggy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
232
src/v_font.cpp
232
src/v_font.cpp
|
@ -195,7 +195,7 @@ extern int PrintColors[];
|
||||||
|
|
||||||
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
// PUBLIC DATA DEFINITIONS -------------------------------------------------
|
||||||
|
|
||||||
FFont *FFont::FirstFont = NULL;
|
FFont *FFont::FirstFont = nullptr;
|
||||||
int NumTextColors;
|
int NumTextColors;
|
||||||
|
|
||||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||||
|
@ -266,7 +266,7 @@ static int stripaccent(int code)
|
||||||
FFont *V_GetFont(const char *name)
|
FFont *V_GetFont(const char *name)
|
||||||
{
|
{
|
||||||
FFont *font = FFont::FindFont (name);
|
FFont *font = FFont::FindFont (name);
|
||||||
if (font == NULL)
|
if (font == nullptr)
|
||||||
{
|
{
|
||||||
int lump = -1;
|
int lump = -1;
|
||||||
|
|
||||||
|
@ -285,7 +285,7 @@ FFont *V_GetFont(const char *name)
|
||||||
font = new FSingleLumpFont (name, lump);
|
font = new FSingleLumpFont (name, lump);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (font == NULL)
|
if (font == nullptr)
|
||||||
{
|
{
|
||||||
FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any);
|
FTextureID picnum = TexMan.CheckForTexture (name, ETextureType::Any);
|
||||||
if (picnum.isValid())
|
if (picnum.isValid())
|
||||||
|
@ -310,16 +310,14 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
int i;
|
int i;
|
||||||
FTextureID lump;
|
FTextureID lump;
|
||||||
char buffer[12];
|
char buffer[12];
|
||||||
TArray<FTexture*> charLumps;
|
TArray<FTexture*> charLumps(count, true);
|
||||||
int maxyoffs;
|
int maxyoffs;
|
||||||
bool doomtemplate = gameinfo.gametype & GAME_DoomChex ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
|
bool doomtemplate = gameinfo.gametype & GAME_DoomChex ? strncmp (nametemplate, "STCFN", 5) == 0 : false;
|
||||||
bool stcfn121 = false;
|
bool stcfn121 = false;
|
||||||
|
|
||||||
noTranslate = notranslate;
|
noTranslate = notranslate;
|
||||||
Lump = fdlump;
|
Lump = fdlump;
|
||||||
Chars = new CharData[count];
|
Chars.Resize(count);
|
||||||
charLumps.Resize(count);
|
|
||||||
PatchRemap = new uint8_t[256];
|
|
||||||
FirstChar = first;
|
FirstChar = first;
|
||||||
LastChar = first + count - 1;
|
LastChar = first + count - 1;
|
||||||
FontHeight = 0;
|
FontHeight = 0;
|
||||||
|
@ -329,13 +327,15 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
FirstFont = this;
|
FirstFont = this;
|
||||||
Cursor = '_';
|
Cursor = '_';
|
||||||
ActiveColors = 0;
|
ActiveColors = 0;
|
||||||
|
uint8_t pp = 0;
|
||||||
|
for (auto &p : PatchRemap) p = pp++;
|
||||||
translateUntranslated = false;
|
translateUntranslated = false;
|
||||||
|
|
||||||
maxyoffs = 0;
|
maxyoffs = 0;
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
charLumps[i] = NULL;
|
charLumps[i] = nullptr;
|
||||||
mysnprintf (buffer, countof(buffer), nametemplate, i + start);
|
mysnprintf (buffer, countof(buffer), nametemplate, i + start);
|
||||||
|
|
||||||
lump = TexMan.CheckForTexture(buffer, ETextureType::MiscPatch);
|
lump = TexMan.CheckForTexture(buffer, ETextureType::MiscPatch);
|
||||||
|
@ -358,7 +358,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
if (lump.isValid())
|
if (lump.isValid())
|
||||||
{
|
{
|
||||||
FTexture *pic = TexMan.GetTexture(lump);
|
FTexture *pic = TexMan.GetTexture(lump);
|
||||||
if (pic != NULL)
|
if (pic != nullptr)
|
||||||
{
|
{
|
||||||
// set the lump here only if it represents a valid texture
|
// set the lump here only if it represents a valid texture
|
||||||
if (i != 124-start || !stcfn121)
|
if (i != 124-start || !stcfn121)
|
||||||
|
@ -381,17 +381,20 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
|
|
||||||
if (charLumps[i] != nullptr)
|
if (charLumps[i] != nullptr)
|
||||||
{
|
{
|
||||||
|
Chars[i].OriginalPic = charLumps[i];
|
||||||
|
|
||||||
if (!noTranslate)
|
if (!noTranslate)
|
||||||
{
|
{
|
||||||
Chars[i].Pic = new FImageTexture(new FFontChar1 (charLumps[i]->GetImage()));
|
Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charLumps[i]->GetImage()), "");
|
||||||
TexMan.AddTexture(Chars[i].Pic);
|
TexMan.AddTexture(Chars[i].TranslatedPic);
|
||||||
}
|
}
|
||||||
else Chars[i].Pic = charLumps[i];
|
else Chars[i].TranslatedPic = charLumps[i];
|
||||||
Chars[i].XMove = Chars[i].Pic->GetDisplayWidth();
|
|
||||||
|
Chars[i].XMove = Chars[i].OriginalPic->GetDisplayWidth();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Chars[i].Pic = NULL;
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = nullptr;
|
||||||
Chars[i].XMove = INT_MIN;
|
Chars[i].XMove = INT_MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,7 +403,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
{
|
{
|
||||||
SpaceWidth = spacewidth;
|
SpaceWidth = spacewidth;
|
||||||
}
|
}
|
||||||
else if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
|
else if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].OriginalPic != nullptr)
|
||||||
{
|
{
|
||||||
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
||||||
}
|
}
|
||||||
|
@ -422,29 +425,16 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
|
||||||
|
|
||||||
FFont::~FFont ()
|
FFont::~FFont ()
|
||||||
{
|
{
|
||||||
if (Chars)
|
|
||||||
{
|
|
||||||
int count = LastChar - FirstChar + 1;
|
|
||||||
|
|
||||||
delete[] Chars;
|
|
||||||
Chars = NULL;
|
|
||||||
}
|
|
||||||
if (PatchRemap)
|
|
||||||
{
|
|
||||||
delete[] PatchRemap;
|
|
||||||
PatchRemap = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
FFont **prev = &FirstFont;
|
FFont **prev = &FirstFont;
|
||||||
FFont *font = *prev;
|
FFont *font = *prev;
|
||||||
|
|
||||||
while (font != NULL && font != this)
|
while (font != nullptr && font != this)
|
||||||
{
|
{
|
||||||
prev = &font->Next;
|
prev = &font->Next;
|
||||||
font = *prev;
|
font = *prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font != NULL)
|
if (font != nullptr)
|
||||||
{
|
{
|
||||||
*prev = font->Next;
|
*prev = font->Next;
|
||||||
}
|
}
|
||||||
|
@ -537,7 +527,7 @@ static int compare (const void *arg1, const void *arg2)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
int FFont::SimpleTranslation (uint8_t *colorsused, uint8_t *translation, uint8_t *reverse, double **luminosity)
|
int FFont::SimpleTranslation (uint8_t *colorsused, uint8_t *translation, uint8_t *reverse, TArray<double> &Luminosity)
|
||||||
{
|
{
|
||||||
double min, max, diver;
|
double min, max, diver;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
@ -555,26 +545,26 @@ int FFont::SimpleTranslation (uint8_t *colorsused, uint8_t *translation, uint8_t
|
||||||
|
|
||||||
qsort (reverse+1, j-1, 1, compare);
|
qsort (reverse+1, j-1, 1, compare);
|
||||||
|
|
||||||
*luminosity = new double[j];
|
Luminosity.Resize(j);
|
||||||
(*luminosity)[0] = 0.0; // [BL] Prevent uninitalized memory
|
Luminosity[0] = 0.0; // [BL] Prevent uninitalized memory
|
||||||
max = 0.0;
|
max = 0.0;
|
||||||
min = 100000000.0;
|
min = 100000000.0;
|
||||||
for (i = 1; i < j; i++)
|
for (i = 1; i < j; i++)
|
||||||
{
|
{
|
||||||
translation[reverse[i]] = i;
|
translation[reverse[i]] = i;
|
||||||
|
|
||||||
(*luminosity)[i] = RPART(GPalette.BaseColors[reverse[i]]) * 0.299 +
|
Luminosity[i] = RPART(GPalette.BaseColors[reverse[i]]) * 0.299 +
|
||||||
GPART(GPalette.BaseColors[reverse[i]]) * 0.587 +
|
GPART(GPalette.BaseColors[reverse[i]]) * 0.587 +
|
||||||
BPART(GPalette.BaseColors[reverse[i]]) * 0.114;
|
BPART(GPalette.BaseColors[reverse[i]]) * 0.114;
|
||||||
if ((*luminosity)[i] > max)
|
if (Luminosity[i] > max)
|
||||||
max = (*luminosity)[i];
|
max = Luminosity[i];
|
||||||
if ((*luminosity)[i] < min)
|
if (Luminosity[i] < min)
|
||||||
min = (*luminosity)[i];
|
min = Luminosity[i];
|
||||||
}
|
}
|
||||||
diver = 1.0 / (max - min);
|
diver = 1.0 / (max - min);
|
||||||
for (i = 1; i < j; i++)
|
for (i = 1; i < j; i++)
|
||||||
{
|
{
|
||||||
(*luminosity)[i] = ((*luminosity)[i] - min) * diver;
|
Luminosity[i] = (Luminosity[i] - min) * diver;
|
||||||
}
|
}
|
||||||
|
|
||||||
return j;
|
return j;
|
||||||
|
@ -608,10 +598,10 @@ void FFont::BuildTranslations (const double *luminosity, const uint8_t *identity
|
||||||
{
|
{
|
||||||
if (i == CR_UNTRANSLATED)
|
if (i == CR_UNTRANSLATED)
|
||||||
{
|
{
|
||||||
if (identity != NULL)
|
if (identity != nullptr)
|
||||||
{
|
{
|
||||||
memcpy (remap.Remap, identity, ActiveColors);
|
memcpy (remap.Remap, identity, ActiveColors);
|
||||||
if (palette != NULL)
|
if (palette != nullptr)
|
||||||
{
|
{
|
||||||
memcpy (remap.Palette, palette, ActiveColors*sizeof(PalEntry));
|
memcpy (remap.Palette, palette, ActiveColors*sizeof(PalEntry));
|
||||||
}
|
}
|
||||||
|
@ -692,7 +682,7 @@ FRemapTable *FFont::GetColorTranslation (EColorRange range, PalEntry *color) con
|
||||||
if (color != nullptr) *color = retcolor;
|
if (color != nullptr) *color = retcolor;
|
||||||
}
|
}
|
||||||
if (ActiveColors == 0)
|
if (ActiveColors == 0)
|
||||||
return NULL;
|
return nullptr;
|
||||||
else if (range >= NumTextColors)
|
else if (range >= NumTextColors)
|
||||||
range = CR_UNTRANSLATED;
|
range = CR_UNTRANSLATED;
|
||||||
//if (range == CR_UNTRANSLATED && !translateUntranslated) return nullptr;
|
//if (range == CR_UNTRANSLATED && !translateUntranslated) return nullptr;
|
||||||
|
@ -716,7 +706,7 @@ int FFont::GetCharCode(int code, bool needpic) const
|
||||||
// regular chars turn negative when the 8th bit is set.
|
// regular chars turn negative when the 8th bit is set.
|
||||||
code &= 255;
|
code &= 255;
|
||||||
}
|
}
|
||||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
|
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr))
|
||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -724,7 +714,7 @@ int FFont::GetCharCode(int code, bool needpic) const
|
||||||
if (myislower(code))
|
if (myislower(code))
|
||||||
{
|
{
|
||||||
code -= 32;
|
code -= 32;
|
||||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
|
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr))
|
||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -734,7 +724,7 @@ int FFont::GetCharCode(int code, bool needpic) const
|
||||||
if (newcode != code)
|
if (newcode != code)
|
||||||
{
|
{
|
||||||
code = newcode;
|
code = newcode;
|
||||||
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].Pic != NULL))
|
if (code >= FirstChar && code <= LastChar && (!needpic || Chars[code - FirstChar].OriginalPic != nullptr))
|
||||||
{
|
{
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
@ -748,7 +738,7 @@ int FFont::GetCharCode(int code, bool needpic) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FTexture *FFont::GetChar (int code, int *const width) const
|
FTexture *FFont::GetChar (int code, int translation, int *const width, bool *redirected) const
|
||||||
{
|
{
|
||||||
code = GetCharCode(code, false);
|
code = GetCharCode(code, false);
|
||||||
int xmove = SpaceWidth;
|
int xmove = SpaceWidth;
|
||||||
|
@ -757,7 +747,7 @@ FTexture *FFont::GetChar (int code, int *const width) const
|
||||||
{
|
{
|
||||||
code -= FirstChar;
|
code -= FirstChar;
|
||||||
xmove = Chars[code].XMove;
|
xmove = Chars[code].XMove;
|
||||||
if (Chars[code].Pic == NULL)
|
if (Chars[code].OriginalPic == nullptr)
|
||||||
{
|
{
|
||||||
code = GetCharCode(code + FirstChar, true);
|
code = GetCharCode(code + FirstChar, true);
|
||||||
if (code >= 0)
|
if (code >= 0)
|
||||||
|
@ -767,11 +757,21 @@ FTexture *FFont::GetChar (int code, int *const width) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (width != NULL)
|
if (width != nullptr)
|
||||||
{
|
{
|
||||||
*width = xmove;
|
*width = xmove;
|
||||||
}
|
}
|
||||||
return (code < 0) ? NULL : Chars[code].Pic;
|
if (code < 0) return nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
if (translation == CR_UNTRANSLATED)
|
||||||
|
{
|
||||||
|
if (redirected)
|
||||||
|
*redirected = Chars[code].OriginalPic != Chars[code].TranslatedPic;
|
||||||
|
return Chars[code].OriginalPic;
|
||||||
|
}
|
||||||
|
if (redirected) *redirected = false;
|
||||||
|
return Chars[code].TranslatedPic;
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -795,8 +795,8 @@ int FFont::GetCharWidth (int code) const
|
||||||
double GetBottomAlignOffset(FFont *font, int c)
|
double GetBottomAlignOffset(FFont *font, int c)
|
||||||
{
|
{
|
||||||
int w;
|
int w;
|
||||||
FTexture *tex_zero = font->GetChar('0', &w);
|
FTexture *tex_zero = font->GetChar('0', CR_UNDEFINED, &w);
|
||||||
FTexture *texc = font->GetChar(c, &w);
|
FTexture *texc = font->GetChar(c, CR_UNDEFINED, &w);
|
||||||
double offset = 0;
|
double offset = 0;
|
||||||
if (texc) offset += texc->GetDisplayTopOffsetDouble();
|
if (texc) offset += texc->GetDisplayTopOffsetDouble();
|
||||||
if (tex_zero) offset += -tex_zero->GetDisplayTopOffsetDouble() + tex_zero->GetDisplayHeightDouble();
|
if (tex_zero) offset += -tex_zero->GetDisplayTopOffsetDouble() + tex_zero->GetDisplayHeightDouble();
|
||||||
|
@ -858,17 +858,17 @@ void FFont::LoadTranslations()
|
||||||
{
|
{
|
||||||
unsigned int count = LastChar - FirstChar + 1;
|
unsigned int count = LastChar - FirstChar + 1;
|
||||||
uint8_t usedcolors[256], identity[256];
|
uint8_t usedcolors[256], identity[256];
|
||||||
double *luminosity;
|
TArray<double> Luminosity;
|
||||||
|
|
||||||
memset (usedcolors, 0, 256);
|
memset (usedcolors, 0, 256);
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (Chars[i].Pic)
|
if (Chars[i].TranslatedPic)
|
||||||
{
|
{
|
||||||
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic->GetImage());
|
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage());
|
||||||
if (pic)
|
if (pic)
|
||||||
{
|
{
|
||||||
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
|
pic->SetSourceRemap(nullptr); // Force the FFontChar1 to return the same pixels as the base texture
|
||||||
RecordTextureColors(pic, usedcolors);
|
RecordTextureColors(pic, usedcolors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -876,17 +876,15 @@ void FFont::LoadTranslations()
|
||||||
|
|
||||||
// Fixme: This needs to build a translation based on the source palette, not some intermediate 'ordered' table.
|
// Fixme: This needs to build a translation based on the source palette, not some intermediate 'ordered' table.
|
||||||
|
|
||||||
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
|
ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, Luminosity);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < count; i++)
|
for (unsigned int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if(Chars[i].Pic)
|
if(Chars[i].TranslatedPic)
|
||||||
static_cast<FFontChar1 *>(Chars[i].Pic->GetImage())->SetSourceRemap(PatchRemap);
|
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildTranslations (luminosity, identity, &TranslationParms[0][0], ActiveColors, NULL);
|
BuildTranslations (Luminosity.Data(), identity, &TranslationParms[0][0], ActiveColors, nullptr);
|
||||||
|
|
||||||
delete[] luminosity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -898,8 +896,6 @@ void FFont::LoadTranslations()
|
||||||
FFont::FFont (int lump)
|
FFont::FFont (int lump)
|
||||||
{
|
{
|
||||||
Lump = lump;
|
Lump = lump;
|
||||||
Chars = NULL;
|
|
||||||
PatchRemap = NULL;
|
|
||||||
FontName = NAME_None;
|
FontName = NAME_None;
|
||||||
Cursor = '_';
|
Cursor = '_';
|
||||||
noTranslate = false;
|
noTranslate = false;
|
||||||
|
@ -964,8 +960,8 @@ void FSingleLumpFont::CreateFontFromPic (FTextureID picnum)
|
||||||
GlobalKerning = 0;
|
GlobalKerning = 0;
|
||||||
|
|
||||||
FirstChar = LastChar = 'A';
|
FirstChar = LastChar = 'A';
|
||||||
Chars = new CharData[1];
|
Chars.Resize(1);
|
||||||
Chars->Pic = pic;
|
Chars[0].TranslatedPic = Chars[0].OriginalPic = pic;
|
||||||
|
|
||||||
// Only one color range. Don't bother with the others.
|
// Only one color range. Don't bother with the others.
|
||||||
ActiveColors = 0;
|
ActiveColors = 0;
|
||||||
|
@ -1011,11 +1007,11 @@ void FSingleLumpFont::LoadTranslations()
|
||||||
|
|
||||||
for(unsigned int i = 0;i < count;++i)
|
for(unsigned int i = 0;i < count;++i)
|
||||||
{
|
{
|
||||||
if(Chars[i].Pic)
|
if(Chars[i].TranslatedPic)
|
||||||
static_cast<FFontChar2*>(Chars[i].Pic->GetImage())->SetSourceRemap(PatchRemap);
|
static_cast<FFontChar2*>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildTranslations (luminosity, useidentity ? identity : NULL, ranges, ActiveColors, usepalette ? local_palette : NULL);
|
BuildTranslations (luminosity, useidentity ? identity : nullptr, ranges, ActiveColors, usepalette ? local_palette : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1030,7 +1026,7 @@ void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data)
|
||||||
{
|
{
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
||||||
Chars = new CharData[256];
|
Chars.Resize(256);
|
||||||
|
|
||||||
w = data[4] + data[5]*256;
|
w = data[4] + data[5]*256;
|
||||||
h = data[6] + data[7]*256;
|
h = data[6] + data[7]*256;
|
||||||
|
@ -1042,10 +1038,9 @@ void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data)
|
||||||
LastChar = 255;
|
LastChar = 255;
|
||||||
GlobalKerning = 0;
|
GlobalKerning = 0;
|
||||||
translateUntranslated = true;
|
translateUntranslated = true;
|
||||||
PatchRemap = new uint8_t[256];
|
|
||||||
|
|
||||||
for(unsigned int i = 0;i < 256;++i)
|
for(unsigned int i = 0;i < 256;++i)
|
||||||
Chars[i].Pic = NULL;
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = nullptr;
|
||||||
|
|
||||||
LoadTranslations();
|
LoadTranslations();
|
||||||
}
|
}
|
||||||
|
@ -1062,7 +1057,6 @@ void FSingleLumpFont::LoadFON1 (int lump, const uint8_t *data)
|
||||||
void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
|
void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
|
||||||
{
|
{
|
||||||
int count, i, totalwidth;
|
int count, i, totalwidth;
|
||||||
int *widths2;
|
|
||||||
uint16_t *widths;
|
uint16_t *widths;
|
||||||
const uint8_t *palette;
|
const uint8_t *palette;
|
||||||
const uint8_t *data_p;
|
const uint8_t *data_p;
|
||||||
|
@ -1072,12 +1066,11 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
|
||||||
FirstChar = data[6];
|
FirstChar = data[6];
|
||||||
LastChar = data[7];
|
LastChar = data[7];
|
||||||
ActiveColors = data[10]+1;
|
ActiveColors = data[10]+1;
|
||||||
PatchRemap = NULL;
|
|
||||||
RescalePalette = data[9] == 0;
|
RescalePalette = data[9] == 0;
|
||||||
|
|
||||||
count = LastChar - FirstChar + 1;
|
count = LastChar - FirstChar + 1;
|
||||||
Chars = new CharData[count];
|
Chars.Resize(count);
|
||||||
widths2 = new int[count];
|
TArray<int> widths2(count, true);
|
||||||
if (data[11] & 1)
|
if (data[11] & 1)
|
||||||
{ // Font specifies a kerning value.
|
{ // Font specifies a kerning value.
|
||||||
GlobalKerning = LittleShort(*(int16_t *)&data[12]);
|
GlobalKerning = LittleShort(*(int16_t *)&data[12]);
|
||||||
|
@ -1133,12 +1126,12 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
|
||||||
Chars[i].XMove = widths2[i];
|
Chars[i].XMove = widths2[i];
|
||||||
if (destSize <= 0)
|
if (destSize <= 0)
|
||||||
{
|
{
|
||||||
Chars[i].Pic = NULL;
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Chars[i].Pic = new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight));
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = new FImageTexture(new FFontChar2 (lump, int(data_p - data), widths2[i], FontHeight));
|
||||||
TexMan.AddTexture(Chars[i].Pic);
|
TexMan.AddTexture(Chars[i].OriginalPic);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int8_t code = *data_p++;
|
int8_t code = *data_p++;
|
||||||
|
@ -1162,7 +1155,6 @@ void FSingleLumpFont::LoadFON2 (int lump, const uint8_t *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadTranslations();
|
LoadTranslations();
|
||||||
delete[] widths2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1221,10 +1213,10 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
|
||||||
I_FatalError("BMF font defines no characters");
|
I_FatalError("BMF font defines no characters");
|
||||||
}
|
}
|
||||||
count = LastChar - FirstChar + 1;
|
count = LastChar - FirstChar + 1;
|
||||||
Chars = new CharData[count];
|
Chars.Resize(count);
|
||||||
for (i = 0; i < count; ++i)
|
for (i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
Chars[i].Pic = NULL;
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = nullptr;
|
||||||
Chars[i].XMove = INT_MIN;
|
Chars[i].XMove = INT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1247,7 +1239,6 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
|
||||||
qsort(sort_palette + 1, ActiveColors - 1, sizeof(PalEntry), BMFCompare);
|
qsort(sort_palette + 1, ActiveColors - 1, sizeof(PalEntry), BMFCompare);
|
||||||
|
|
||||||
// Create the PatchRemap table from the sorted "alpha" values.
|
// Create the PatchRemap table from the sorted "alpha" values.
|
||||||
PatchRemap = new uint8_t[ActiveColors];
|
|
||||||
PatchRemap[0] = 0;
|
PatchRemap[0] = 0;
|
||||||
for (i = 1; i < ActiveColors; ++i)
|
for (i = 1; i < ActiveColors; ++i)
|
||||||
{
|
{
|
||||||
|
@ -1280,7 +1271,7 @@ void FSingleLumpFont::LoadBMF(int lump, const uint8_t *data)
|
||||||
-(int8_t)chardata[chari+3], // x offset
|
-(int8_t)chardata[chari+3], // x offset
|
||||||
-(int8_t)chardata[chari+4] // y offset
|
-(int8_t)chardata[chari+4] // y offset
|
||||||
));
|
));
|
||||||
Chars[chardata[chari] - FirstChar].Pic = tex;
|
Chars[chardata[chari] - FirstChar].TranslatedPic = Chars[chardata[chari] - FirstChar].OriginalPic = tex;
|
||||||
TexMan.AddTexture(tex);
|
TexMan.AddTexture(tex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1344,12 +1335,13 @@ void FSingleLumpFont::CheckFON1Chars (double *luminosity)
|
||||||
{
|
{
|
||||||
int destSize = SpaceWidth * FontHeight;
|
int destSize = SpaceWidth * FontHeight;
|
||||||
|
|
||||||
if(!Chars[i].Pic)
|
if(!Chars[i].OriginalPic)
|
||||||
{
|
{
|
||||||
Chars[i].Pic = new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight));
|
Chars[i].OriginalPic = new FImageTexture(new FFontChar2 (Lump, int(data_p - data), SpaceWidth, FontHeight));
|
||||||
Chars[i].XMove = SpaceWidth;
|
Chars[i].XMove = SpaceWidth;
|
||||||
TexMan.AddTexture(Chars[i].Pic);
|
TexMan.AddTexture(Chars[i].OriginalPic);
|
||||||
}
|
}
|
||||||
|
Chars[i].TranslatedPic = Chars[i].OriginalPic;
|
||||||
|
|
||||||
// Advance to next char's data and count the used colors.
|
// Advance to next char's data and count the used colors.
|
||||||
do
|
do
|
||||||
|
@ -1478,7 +1470,7 @@ FSinglePicFont::FSinglePicFont(const char *picname) :
|
||||||
//
|
//
|
||||||
// FSinglePicFont :: GetChar
|
// FSinglePicFont :: GetChar
|
||||||
//
|
//
|
||||||
// Returns the texture if code is 'a' or 'A', otherwise NULL.
|
// Returns the texture if code is 'a' or 'A', otherwise nullptr.
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
@ -1491,7 +1483,7 @@ FTexture *FSinglePicFont::GetChar (int code, int *const width) const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1515,10 +1507,11 @@ int FSinglePicFont::GetCharWidth (int code) const
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate) : FFont(lump)
|
FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate)
|
||||||
|
: FFont(lump)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
FTexture **charlumps;
|
TArray<FTexture *> charlumps(count, true);
|
||||||
int maxyoffs;
|
int maxyoffs;
|
||||||
FTexture *pic;
|
FTexture *pic;
|
||||||
|
|
||||||
|
@ -1526,9 +1519,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
||||||
|
|
||||||
noTranslate = donttranslate;
|
noTranslate = donttranslate;
|
||||||
FontName = name;
|
FontName = name;
|
||||||
Chars = new CharData[count];
|
Chars.Resize(count);
|
||||||
charlumps = new FTexture*[count];
|
|
||||||
PatchRemap = new uint8_t[256];
|
|
||||||
FirstChar = first;
|
FirstChar = first;
|
||||||
LastChar = first + count - 1;
|
LastChar = first + count - 1;
|
||||||
FontHeight = 0;
|
FontHeight = 0;
|
||||||
|
@ -1541,7 +1532,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
pic = charlumps[i] = lumplist[i];
|
pic = charlumps[i] = lumplist[i];
|
||||||
if (pic != NULL)
|
if (pic != nullptr)
|
||||||
{
|
{
|
||||||
int height = pic->GetDisplayHeight();
|
int height = pic->GetDisplayHeight();
|
||||||
int yoffs = pic->GetDisplayTopOffset();
|
int yoffs = pic->GetDisplayTopOffset();
|
||||||
|
@ -1557,25 +1548,26 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (charlumps[i] != NULL)
|
if (charlumps[i] != nullptr)
|
||||||
{
|
{
|
||||||
|
Chars[i].OriginalPic = charlumps[i];
|
||||||
if (!noTranslate)
|
if (!noTranslate)
|
||||||
{
|
{
|
||||||
Chars[i].Pic = new FImageTexture(new FFontChar1 (charlumps[i]->GetImage()));
|
Chars[i].TranslatedPic = new FImageTexture(new FFontChar1 (charlumps[i]->GetImage()), "");
|
||||||
TexMan.AddTexture(Chars[i].Pic);
|
TexMan.AddTexture(Chars[i].TranslatedPic);
|
||||||
}
|
}
|
||||||
else Chars[i].Pic = charlumps[i];
|
else Chars[i].TranslatedPic = charlumps[i];
|
||||||
Chars[i].XMove = Chars[i].Pic->GetDisplayWidth();
|
Chars[i].XMove = Chars[i].OriginalPic->GetDisplayWidth();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Chars[i].Pic = NULL;
|
Chars[i].TranslatedPic = Chars[i].OriginalPic = nullptr;
|
||||||
Chars[i].XMove = INT_MIN;
|
Chars[i].XMove = INT_MIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special fonts normally don't have all characters so be careful here!
|
// Special fonts normally don't have all characters so be careful here!
|
||||||
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].Pic != NULL)
|
if ('N'-first >= 0 && 'N'-first < count && Chars['N' - first].OriginalPic != nullptr)
|
||||||
{
|
{
|
||||||
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
SpaceWidth = (Chars['N' - first].XMove + 1) / 2;
|
||||||
}
|
}
|
||||||
|
@ -1594,8 +1586,6 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
|
||||||
{
|
{
|
||||||
LoadTranslations();
|
LoadTranslations();
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] charlumps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1608,19 +1598,19 @@ void FSpecialFont::LoadTranslations()
|
||||||
{
|
{
|
||||||
int count = LastChar - FirstChar + 1;
|
int count = LastChar - FirstChar + 1;
|
||||||
uint8_t usedcolors[256], identity[256];
|
uint8_t usedcolors[256], identity[256];
|
||||||
double *luminosity;
|
TArray<double> Luminosity;
|
||||||
int TotalColors;
|
int TotalColors;
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
memset (usedcolors, 0, 256);
|
memset (usedcolors, 0, 256);
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if (Chars[i].Pic)
|
if (Chars[i].TranslatedPic)
|
||||||
{
|
{
|
||||||
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].Pic->GetImage());
|
FFontChar1 *pic = static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage());
|
||||||
if (pic)
|
if (pic)
|
||||||
{
|
{
|
||||||
pic->SetSourceRemap(NULL); // Force the FFontChar1 to return the same pixels as the base texture
|
pic->SetSourceRemap(nullptr); // Force the FFontChar1 to return the same pixels as the base texture
|
||||||
RecordTextureColors(pic, usedcolors);
|
RecordTextureColors(pic, usedcolors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1631,7 +1621,7 @@ void FSpecialFont::LoadTranslations()
|
||||||
if (notranslate[i])
|
if (notranslate[i])
|
||||||
usedcolors[i] = false;
|
usedcolors[i] = false;
|
||||||
|
|
||||||
TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, &luminosity);
|
TotalColors = ActiveColors = SimpleTranslation (usedcolors, PatchRemap, identity, Luminosity);
|
||||||
|
|
||||||
// Map all untranslated colors into the table of used colors
|
// Map all untranslated colors into the table of used colors
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
|
@ -1646,11 +1636,11 @@ void FSpecialFont::LoadTranslations()
|
||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
if(Chars[i].Pic)
|
if(Chars[i].TranslatedPic)
|
||||||
static_cast<FFontChar1 *>(Chars[i].Pic->GetImage())->SetSourceRemap(PatchRemap);
|
static_cast<FFontChar1 *>(Chars[i].TranslatedPic->GetImage())->SetSourceRemap(PatchRemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildTranslations (luminosity, identity, &TranslationParms[0][0], TotalColors, NULL);
|
BuildTranslations (Luminosity.Data(), identity, &TranslationParms[0][0], TotalColors, nullptr);
|
||||||
|
|
||||||
// add the untranslated colors to the Ranges tables
|
// add the untranslated colors to the Ranges tables
|
||||||
if (ActiveColors < TotalColors)
|
if (ActiveColors < TotalColors)
|
||||||
|
@ -1667,8 +1657,6 @@ void FSpecialFont::LoadTranslations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveColors = TotalColors;
|
ActiveColors = TotalColors;
|
||||||
|
|
||||||
delete[] luminosity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1838,7 +1826,7 @@ void V_InitCustomFonts()
|
||||||
{
|
{
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
{
|
{
|
||||||
if (lumplist[i] != NULL)
|
if (lumplist[i] != nullptr)
|
||||||
{
|
{
|
||||||
first = i;
|
first = i;
|
||||||
break;
|
break;
|
||||||
|
@ -1846,7 +1834,7 @@ void V_InitCustomFonts()
|
||||||
}
|
}
|
||||||
for (i = 255; i >= 0; i--)
|
for (i = 255; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (lumplist[i] != NULL)
|
if (lumplist[i] != nullptr)
|
||||||
{
|
{
|
||||||
count = i - first + 1;
|
count = i - first + 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1950,19 +1938,19 @@ void V_InitFontColors ()
|
||||||
else if (sc.Compare ("Flat:"))
|
else if (sc.Compare ("Flat:"))
|
||||||
{
|
{
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
logcolor = V_GetColor (NULL, sc);
|
logcolor = V_GetColor (nullptr, sc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get first color
|
// Get first color
|
||||||
c = V_GetColor (NULL, sc);
|
c = V_GetColor (nullptr, sc);
|
||||||
tparm.Start[0] = RPART(c);
|
tparm.Start[0] = RPART(c);
|
||||||
tparm.Start[1] = GPART(c);
|
tparm.Start[1] = GPART(c);
|
||||||
tparm.Start[2] = BPART(c);
|
tparm.Start[2] = BPART(c);
|
||||||
|
|
||||||
// Get second color
|
// Get second color
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
c = V_GetColor (NULL, sc);
|
c = V_GetColor (nullptr, sc);
|
||||||
tparm.End[0] = RPART(c);
|
tparm.End[0] = RPART(c);
|
||||||
tparm.End[1] = GPART(c);
|
tparm.End[1] = GPART(c);
|
||||||
tparm.End[2] = BPART(c);
|
tparm.End[2] = BPART(c);
|
||||||
|
@ -2290,7 +2278,7 @@ void V_InitFonts()
|
||||||
{
|
{
|
||||||
IntermissionFont = FFont::FindFont("IntermissionFont_Doom");
|
IntermissionFont = FFont::FindFont("IntermissionFont_Doom");
|
||||||
}
|
}
|
||||||
if (IntermissionFont == NULL)
|
if (IntermissionFont == nullptr)
|
||||||
{
|
{
|
||||||
IntermissionFont = BigFont;
|
IntermissionFont = BigFont;
|
||||||
}
|
}
|
||||||
|
@ -2299,11 +2287,11 @@ void V_InitFonts()
|
||||||
|
|
||||||
void V_ClearFonts()
|
void V_ClearFonts()
|
||||||
{
|
{
|
||||||
while (FFont::FirstFont != NULL)
|
while (FFont::FirstFont != nullptr)
|
||||||
{
|
{
|
||||||
delete FFont::FirstFont;
|
delete FFont::FirstFont;
|
||||||
}
|
}
|
||||||
FFont::FirstFont = NULL;
|
FFont::FirstFont = nullptr;
|
||||||
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = NULL;
|
SmallFont = SmallFont2 = BigFont = ConFont = IntermissionFont = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
12
src/v_font.h
12
src/v_font.h
|
@ -82,7 +82,7 @@ public:
|
||||||
FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump, int spacewidth=-1, bool notranslate = false);
|
FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump, int spacewidth=-1, bool notranslate = false);
|
||||||
virtual ~FFont ();
|
virtual ~FFont ();
|
||||||
|
|
||||||
virtual FTexture *GetChar (int code, int *const width) const;
|
FTexture *GetChar (int code, int translation, int *const width, bool *redirected = nullptr) const;
|
||||||
virtual int GetCharWidth (int code) const;
|
virtual int GetCharWidth (int code) const;
|
||||||
FRemapTable *GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
|
FRemapTable *GetColorTranslation (EColorRange range, PalEntry *color = nullptr) const;
|
||||||
int GetLump() const { return Lump; }
|
int GetLump() const { return Lump; }
|
||||||
|
@ -112,7 +112,7 @@ protected:
|
||||||
void FixXMoves();
|
void FixXMoves();
|
||||||
|
|
||||||
static int SimpleTranslation (uint8_t *colorsused, uint8_t *translation,
|
static int SimpleTranslation (uint8_t *colorsused, uint8_t *translation,
|
||||||
uint8_t *identity, double **luminosity);
|
uint8_t *identity, TArray<double> &Luminosity);
|
||||||
|
|
||||||
int FirstChar, LastChar;
|
int FirstChar, LastChar;
|
||||||
int SpaceWidth;
|
int SpaceWidth;
|
||||||
|
@ -123,12 +123,14 @@ protected:
|
||||||
bool translateUntranslated;
|
bool translateUntranslated;
|
||||||
struct CharData
|
struct CharData
|
||||||
{
|
{
|
||||||
FTexture *Pic;
|
FTexture *TranslatedPic; // Texture for use with font translations.
|
||||||
|
FTexture *OriginalPic; // Texture for use with CR_UNTRANSLATED or font colorization.
|
||||||
int XMove;
|
int XMove;
|
||||||
} *Chars;
|
};
|
||||||
|
TArray<CharData> Chars;
|
||||||
int ActiveColors;
|
int ActiveColors;
|
||||||
TArray<FRemapTable> Ranges;
|
TArray<FRemapTable> Ranges;
|
||||||
uint8_t *PatchRemap;
|
uint8_t PatchRemap[256];
|
||||||
|
|
||||||
int Lump;
|
int Lump;
|
||||||
FName FontName = NAME_None;
|
FName FontName = NAME_None;
|
||||||
|
|
|
@ -139,8 +139,9 @@ void DFrameBuffer::DrawChar (FFont *font, int normalcolor, double x, double y, i
|
||||||
|
|
||||||
FTexture *pic;
|
FTexture *pic;
|
||||||
int dummy;
|
int dummy;
|
||||||
|
bool redirected;
|
||||||
|
|
||||||
if (NULL != (pic = font->GetChar (character, &dummy)))
|
if (NULL != (pic = font->GetChar (character, normalcolor, &dummy, &redirected)))
|
||||||
{
|
{
|
||||||
DrawParms parms;
|
DrawParms parms;
|
||||||
Va_List tags;
|
Va_List tags;
|
||||||
|
@ -152,7 +153,7 @@ void DFrameBuffer::DrawChar (FFont *font, int normalcolor, double x, double y, i
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PalEntry color = 0xffffffff;
|
PalEntry color = 0xffffffff;
|
||||||
parms.remap = font->GetColorTranslation((EColorRange)normalcolor, &color);
|
parms.remap = redirected? nullptr : font->GetColorTranslation((EColorRange)normalcolor, &color);
|
||||||
parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
|
parms.color = PalEntry((color.a * parms.color.a) / 255, (color.r * parms.color.r) / 255, (color.g * parms.color.g) / 255, (color.b * parms.color.b) / 255);
|
||||||
DrawTextureParms(pic, parms);
|
DrawTextureParms(pic, parms);
|
||||||
}
|
}
|
||||||
|
@ -169,7 +170,7 @@ void DFrameBuffer::DrawChar(FFont *font, int normalcolor, double x, double y, in
|
||||||
FTexture *pic;
|
FTexture *pic;
|
||||||
int dummy;
|
int dummy;
|
||||||
|
|
||||||
if (NULL != (pic = font->GetChar(character, &dummy)))
|
if (NULL != (pic = font->GetChar(character, normalcolor, &dummy)))
|
||||||
{
|
{
|
||||||
DrawParms parms;
|
DrawParms parms;
|
||||||
uint32_t tag = ListGetInt(args);
|
uint32_t tag = ListGetInt(args);
|
||||||
|
@ -238,6 +239,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
|
||||||
cy = y;
|
cy = y;
|
||||||
|
|
||||||
|
|
||||||
|
auto currentcolor = normalcolor;
|
||||||
while ((const char *)ch - string < parms.maxstrlen)
|
while ((const char *)ch - string < parms.maxstrlen)
|
||||||
{
|
{
|
||||||
c = GetCharFromString(ch);
|
c = GetCharFromString(ch);
|
||||||
|
@ -251,6 +253,7 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
|
||||||
{
|
{
|
||||||
range = font->GetColorTranslation(newcolor, &color);
|
range = font->GetColorTranslation(newcolor, &color);
|
||||||
parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255);
|
parms.color = PalEntry(colorparm.a, (color.r * colorparm.r) / 255, (color.g * colorparm.g) / 255, (color.b * colorparm.b) / 255);
|
||||||
|
currentcolor = newcolor;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -262,9 +265,10 @@ void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL != (pic = font->GetChar(c, &w)))
|
bool redirected = false;
|
||||||
|
if (NULL != (pic = font->GetChar(c, currentcolor, &w, &redirected)))
|
||||||
{
|
{
|
||||||
parms.remap = range;
|
parms.remap = redirected? nullptr : range;
|
||||||
SetTextureParms(&parms, pic, cx, cy);
|
SetTextureParms(&parms, pic, cx, cy);
|
||||||
if (parms.cellx)
|
if (parms.cellx)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue