[Done] Improved fonts

Moderator: GZDoom Developers

Improved fonts

Postby Graf Zahl » Sun Mar 27, 2005 8:49 am

After all that discussions about non-productive nonsense like auto-update etc. let's return to some features that actually do have a purpose and benefit mappers.

I recently dug out some code I experimented with and one of the featues it had were custom multilump fonts (like STCFN***). It didn't take me long to port it to ZDoom's font management system and here's the result:

Code: Select allExpand view
//===========================================================================
//
// 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, int * lumplist, const bool * notranslate);
};


FSpecialFont::FSpecialFont (const char *name, int first, int count, int * lumplist, const bool * notranslate)
{
   int i, j, lump;
   char buffer[12];
   int *charlumps;
   byte usedcolors[256], identity[256];
   double *luminosity;
   int maxyoffs;
   int TotalColors;

   Name=copystring(name);
   Chars = new CharData[count];
   charlumps = new int[count];
   PatchRemap = new BYTE[256];
   Ranges = NULL;
   FirstChar = first;
   LastChar = first + count - 1;
   FontHeight = 0;
   GlobalKerning = false;
   memset (usedcolors, 0, 256);
   Name = copystring (name);
   Next = FirstFont;
   FirstFont = this;

   maxyoffs = 0;

   for (i = 0; i < count; i++)
   {
      lump = charlumps[i] = lumplist[i];
      if (lump >= 0)
      {
         Wads.GetLumpName(buffer,lump);
         FTexture *pic = TexMan[TexMan.AddPatch (buffer)];
         int height = pic->GetHeight();
         int yoffs = pic->TopOffset;

         if (yoffs > maxyoffs)
         {
            maxyoffs = yoffs;
         }
         height += abs (yoffs);
         if (height > FontHeight)
         {
            FontHeight = height;
         }

         /* experimental True Color OpenGL font support ;)
         if (TexMan.GLSupport())
         {
            RecordGLTextureColors(lump, usedcolors);
         }
         else
         */
         {
            RecordTextureColors (pic, usedcolors);
         }
      }
   }

   // exclude the non-translated colors from the translation calculation
   if (notranslate!=NULL)
   {
      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
   if (notranslate!=NULL)
   {
      for(i=0;i<256;i++)
      {
         if (notranslate[i])
         {
            PatchRemap[i]=TotalColors;
            identity[TotalColors]=i;
            TotalColors++;
         }
      }
   }

   for (i = 0; i < count; i++)
   {
      if (charlumps[i] >= 0)
      {
         /* experimental True Color OpenGL font support ;)
         if (TexMan.GLSupport())
         {
            Chars[i].Pic = new FGLFontChar1(charlumps[i], PatchRemap, TotalColors, &Ranges);
         }
         else
         */
         {
            Chars[i].Pic = new FFontChar1 (charlumps[i], PatchRemap);
         }
      }
      else
      {
         Chars[i].Pic = NULL;
      }
   }

   // Special fonts normally don't have all characters so be careful here!
   if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
   {
      SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;
   }
   else SpaceWidth=4;

   BuildTranslations (luminosity, identity/*, TexMan.GLSupport()*/);


   // add the untranslated colors to the Ranges table
   if (ActiveColors<TotalColors)
   {
      int factor = 1;//3 * TexMan.GLSupport();
      byte * oldranges=Ranges;
      Ranges = new byte[NUM_TEXT_COLORS * TotalColors * factor ];

      for (i = 0; i < CR_UNTRANSLATED; i++)
      {
         memcpy(&Ranges[i * TotalColors * factor], &oldranges[i * ActiveColors * factor], ActiveColors * factor);

         for(j=ActiveColors;j<TotalColors;j++)
         {
            /* experimental True Color OpenGL font support ;)
            if (TexMan.GLSupport())
            {
               Ranges[(TotalColors*i + j)*3 + 0]=GPalette.BaseColors[identity[j]].r;
               Ranges[(TotalColors*i + j)*3 + 1]=GPalette.BaseColors[identity[j]].g;
               Ranges[(TotalColors*i + j)*3 + 2]=GPalette.BaseColors[identity[j]].b;
            }
            else
            */
            {
               Ranges[TotalColors*i + j]=identity[j];
            }
         }
      }
      delete [] oldranges;
   }
   ActiveColors=TotalColors;

   delete[] luminosity;
   delete[] charlumps;
}


//===========================================================================
//
// Initialize a list of custom multipatch fonts
//
//===========================================================================
BOOL SC_CheckNumber (void);

void V_InitCustomFonts()
{
   int lumplist[256];
   bool notranslate[256];
   char namebuffer[16],templatebuf[16];
   int adder=0;
   int i;
   int llump,lastlump=-1;
   int format=0;
   int start=33;
   int first=33;
   int count=223;


   while ((llump = Wads.FindLump ("FONTDEFS", &lastlump)) != -1)
   {
      SC_OpenLumpNum(llump,"FONTDEFS");
      while (SC_GetString())
      {
         memset(lumplist,-1,sizeof(lumplist));
         memset(notranslate,0,sizeof(notranslate));
         strncpy(namebuffer,sc_String,16);
         namebuffer[15]=0;
         format=0;
         start=33;
         first=33;
         count=223;

         SC_MustGetStringName("{");
         while (!SC_CheckString("}"))
         {
            SC_MustGetString();
            if (SC_Compare("TEMPLATE"))
            {
               if (format==2) goto wrong;
               SC_MustGetString();
               strncpy(templatebuf,sc_String,16);
               templatebuf[15]=0;
               format=1;
            }
            else if (SC_Compare("BASE"))
            {
               if (format==2) goto wrong;
               SC_MustGetNumber();
               start=sc_Number;
               format=1;
            }
            else if (SC_Compare("FIRST"))
            {
               if (format==2) goto wrong;
               SC_MustGetNumber();
               first=sc_Number;
               format=1;
            }
            else if (SC_Compare("COUNT"))
            {
               if (format==2) goto wrong;
               SC_MustGetNumber();
               count=sc_Number;
               format=1;
            }
            else if (SC_Compare("NOTRANSLATION"))
            {
               if (format==1) goto wrong;
               while (SC_CheckNumber() && !sc_Crossed)
               {
                  if (sc_Number>=0 && sc_Number<256) notranslate[sc_Number]=true;
               }
               format=2;
            }
            else
            {
               if (format==1) goto wrong;
               int * p=&lumplist[*(unsigned char*)sc_String];
               SC_MustGetString();
               *p=Wads.CheckNumForName(sc_String);
               format=2;
            }
         }
         if (format==1)
         {
            new FFont(namebuffer, templatebuf, first, count, start);
         }
         else if (format==2)
         {
            for(i=0;i<256;i++)
            {
               if (lumplist[i]!=-1)
               {
                  first=i;
                  break;
               }
            }
            for(i=255;i>=0;i--)
            {
               if (lumplist[i]!=-1)
               {
                  count=i-first+1;
                  break;
               }
            }
            if (count>0) new FSpecialFont(namebuffer, first, count, &lumplist[first], notranslate);
         }
         else goto wrong;
      }
      SC_Close();
   }
   return;

wrong:
   SC_ScriptError("Invalid combination of properties in font '%s'", namebuffer);

}



Just copy and paste it to the end of V_Font.cpp, change the line

Code: Select allExpand view
   SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;


in FFont::FFont to

Code: Select allExpand view
   if ('N'-first>=0 && 'N'-first<count && Chars['N' - first].Pic)
   {
      SpaceWidth = (Chars['N' - first].Pic->GetWidth() + 1) / 2;
   }
   else SpaceWidth=4;


(this is important. It will crash there for incomplete fonts!)

and call V_InitCustomFonts from V_Init and it should work.

And here's a small WAD that demonstrates it.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby Graf Zahl » Sun Mar 27, 2005 8:50 am

And here's a screenshot:

Image
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby Xaser » Sun Mar 27, 2005 8:51 am

Heh, cool, does this mean that we can make new fonts by adding the individual letter graphics instead of making one of those annoying font files?
User avatar
Xaser
anarchivist
 
 
 
Joined: 20 Jul 2003

Postby Graf Zahl » Sun Mar 27, 2005 8:53 am

Yes, exactly! The word 'annoying' perfectly sums it up! ;)
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby Chilvence » Sun Mar 27, 2005 9:06 am

It's still headache inducing making a nice graphical font. Creating the graphic itself is great, with a nice ttf you can slap together something that looks amazing in 10 minutes. But seperating the individual letters, getting the alpha right, and naming them....
User avatar
Chilvence
I had been waiting for Doomscript....
 
Joined: 11 Aug 2003

Postby Infurnus » Sun Mar 27, 2005 9:52 am

Now THIS is a good idea. Lots of cool things you could do with this...
User avatar
Infurnus
"what in the hells"
 
Joined: 07 Aug 2003

Postby Enjay » Sun Mar 27, 2005 9:57 am

In some ways the "annoying" font is better IMO. The fact that it is a single lump, rather than all those small lumps is tidier. If Zdoom could read the graphic directly, rather than having to convert it to the font format(that proprietary graphics tools can't read), it would be an easy, tidy format to produce and edit.

However, if you are just ripping an already produced, multi-lump font, Graf's solution would probably be quicker.

52
User avatar
Enjay
Everyone is a moon, and has a dark side which he never shows to anybody. Twain
 
 
 
Joined: 15 Jul 2003
Location: Scotland

Postby Graf Zahl » Sun Mar 27, 2005 10:03 am

You know what: The code is there, it works and it can be copied in without any change. There's really no need to discuss which solution is more efficient if both are available. ;)
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby Chris » Sun Mar 27, 2005 10:55 am

After all that discussions about non-productive nonsense like auto-update etc. let's return to some features that actually do have a purpose and benefit mappers.

That makes you feel all mighty and superior to say that, don't it?
User avatar
Chris
 
Joined: 17 Jul 2003

Postby Graf Zahl » Sun Mar 27, 2005 11:11 am

At least I have the common sense to recognize that as such. ZDoom should focus on the gaming/mapping experience, not on some 1337 crap nobody really needs Do I need to say 'ACS networking'? It's the same kind of overblown nonsense which doesn't make the game better but requires a lot of work.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby Bio Hazard » Sun Mar 27, 2005 11:36 am

Isint ACS networking part of the "Mapping experience" you mentioned? sure seems like it to me...
User avatar
Bio Hazard
Lord of the Lord of Nitpicking.
 
Joined: 15 Aug 2003
Location: ferret ~/C/ZDL $

Postby Graf Zahl » Sun Mar 27, 2005 11:51 am

If you could do something useful with it it might. But despite being discussed to death there wasn't a single practicable use with larger appeal. Investing time in such features isn't worth it.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany

Postby wildweasel » Sun Mar 27, 2005 11:55 am

Please don't let that thread bleed into this one. It'll only balloon this one's size exponentially and decrease the likelihood that Randy will bother looking at it.
User avatar
wildweasel
from a different perspective.
Moderator Team Lead
 
Joined: 15 Jul 2003

Postby Chris » Sun Mar 27, 2005 8:19 pm

Please don't let that thread bleed into this one.

Ask mister big-shot that just had to mention it in the first place where it had no bussiness being. But alright, I'll shut up about it here.

As for the font idea itself, it's not terribly bad. Though honestly I'm with Enjay. Single-lump fonts are the way to go (especially if you want to factor in compression if it's a PNG image). You don't seem to have mentioned how it's used, though.
User avatar
Chris
 
Joined: 17 Jul 2003

Postby wildweasel » Sun Mar 27, 2005 8:58 pm

I was speaking to everybody, including Graf.
User avatar
wildweasel
from a different perspective.
Moderator Team Lead
 
Joined: 15 Jul 2003

Next

Return to Closed Feature Suggestions

Who is online

Users browsing this forum: No registered users and 0 guests