Fixed Width in FontDef

What it says on the tin: a place to discuss proposed new features.
Post Reply
digitalgibs
Gnoblar
Posts: 15
Joined: Wed Aug 04, 2010 8:22 pm
x 1

Fixed Width in FontDef

Post by digitalgibs »

It would be nice to get this into the next Ogre release. Below is the unified diff of the changes. This is especially useful when you have a fixed font (like a console font) but Ogre insists on using variable spacing. Adding this makes it SOO much easier to display formatted text.

Example:

Code: Select all

Console
{
	type          truetype
	source      console.ttf
	size          32
	resolution 72
	fixed_width true
}
OgreFont.cpp

Code: Select all

@@ -59,7 +59,8 @@
 	Font::Font(ResourceManager* creator, const String& name, ResourceHandle handle,
 		const String& group, bool isManual, ManualResourceLoader* loader)
 		:Resource (creator, name, handle, group, isManual, loader),
-		mType(FT_TRUETYPE), mTtfSize(0), mTtfResolution(0), mTtfMaxBearingY(0), mAntialiasColour(false)
+		mType(FT_TRUETYPE), mTtfSize(0), mTtfResolution(0), mTtfMaxBearingY(0), mAntialiasColour(false),
+		mTtfFixedWidth(false)
     {
 
 		if (createParamDictionary("Font"))
@@ -101,6 +102,16 @@
         return mType;
     }
     //---------------------------------------------------------------------
+    void Font::setFixedWidth(const bool enabled)
+    {
+        mTtfFixedWidth = enabled;
+    }
+    //---------------------------------------------------------------------
+    bool Font::getFixedWidth(void) const
+    {
+        return mTtfFixedWidth;
+    }
+    //---------------------------------------------------------------------
     void Font::setSource(const String& source)
     {
         mSource = source;
@@ -267,6 +278,7 @@
         //FILE *fo_def = stdout;
 
         int max_height = 0, max_width = 0;
+		int max_fixed_width = 0;
 
 		// Backwards compatibility - if codepoints not supplied, assume 33-166
 		if (mCodePointRangeList.empty())
@@ -290,7 +302,10 @@
 					mTtfMaxBearingY = face->glyph->metrics.horiBearingY;
 
 				if( (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 ) > max_width)
-					max_width = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );
+				{
+					max_fixed_width = (face->glyph->advance.x >> 6 );
+					max_width = max_fixed_width + ( face->glyph->metrics.horiBearingX >> 6 );
+				}
 			}
 
 		}
@@ -390,10 +405,21 @@
 					}
 				}
 
+				Real u2;
+
+				if( mTtfFixedWidth )
+				{
+					u2 = (Real)( l + max_fixed_width ) / (Real)finalWidth;
+				}
+				else
+				{
+					u2 = (Real)( l + ( face->glyph->advance.x >> 6 ) ) / (Real)finalWidth;
+				}
+
 				this->setGlyphTexCoords(cp,
 					(Real)l / (Real)finalWidth,  // u1
 					(Real)m / (Real)finalHeight,  // v1
-					(Real)( l + ( face->glyph->advance.x >> 6 ) ) / (Real)finalWidth, // u2
+					u2, // u2
 					( m + ( max_height >> 6 ) ) / (Real)finalHeight, // v2
 					textureAspect
 					);
OgreFont.h

Code: Select all

@@ -123,6 +123,8 @@
 		/// Max distance to baseline of this (truetype) font
 		int mTtfMaxBearingY;
 
+        /// If 'true', all characters are set to a common width
+        bool mTtfFixedWidth;
 
 	public:
 		typedef Ogre::uint32 CodePoint;
@@ -184,6 +186,18 @@
         /** Gets the type of font. */
         FontType getType(void) const;
 
+        /** Enables fixed width font generation.
+        @remarks
+            If 'true', all characters are set to a common width.
+        @param enabled Enables fixed width fonts.
+        */
+        void setFixedWidth(const bool enabled);
+
+        /** Gets the fixed width state.
+        */
+        bool getFixedWidth(void) const;
+		
+
         /** Sets the source of the font.
         @remarks
             If you have created a font of type FT_IMAGE, this method tells the
OgreFontManager.cpp

Code: Select all

@@ -226,6 +226,17 @@
         	// Set
             pFont->setAntialiasColour(StringConverter::parseBool(params[1]));
         }
+        else if (attrib == "fixed_width")
+        {
+        	// Check params
+        	if (params.size() != 2)
+        	{
+                logBadAttrib(line, pFont);
+                return;
+        	}
+        	// Set
+            pFont->setFixedWidth(StringConverter::parseBool(params[1]));
+        }
 		else if (attrib == "code_points")
 		{
 			for (size_t c = 1; c < params.size(); ++c)
In short, I added the following:

OgreFont.h

Code: Select all

/// If 'true', all characters are set to a common width
bool mTtfFixedWidth;

/** Enables fixed width font generation.
@remarks
    If 'true', all characters are set to a common width.
@param enabled Enables fixed width fonts.
*/
void setFixedWidth(const bool enabled);

/** Gets the fixed width state.
*/
bool getFixedWidth(void) const;
OgreFont.cpp

Code: Select all

... in Font::setSource()

int max_fixed_width = 0;

...

if( (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 ) > max_width)
	max_width = (face->glyph->advance.x >> 6 ) + ( face->glyph->metrics.horiBearingX >> 6 );
{
	max_fixed_width = (face->glyph->advance.x >> 6 );
	max_width = max_fixed_width + ( face->glyph->metrics.horiBearingX >> 6 );
}

...

Real u2;

if( mTtfFixedWidth )
{
	u2 = (Real)( l + max_fixed_width ) / (Real)finalWidth;
}
else
{
	u2 = (Real)( l + ( face->glyph->advance.x >> 6 ) ) / (Real)finalWidth;
}

this->setGlyphTexCoords(cp,
	(Real)l / (Real)finalWidth,  // u1
	(Real)m / (Real)finalHeight,  // v1
	(Real)( l + ( face->glyph->advance.x >> 6 ) ) / (Real)finalWidth, // u2
	u2, // u2
	( m + ( max_height >> 6 ) ) / (Real)finalHeight, // v2
	textureAspect
	);
OgreFontManager.cpp

Code: Select all

... in FontManager::parseAttribute()
else if (attrib == "fixed_width")
{
	// Check params
	if (params.size() != 2)
	{
        logBadAttrib(line, pFont);
        return;
	}
	// Set
    pFont->setFixedWidth(StringConverter::parseBool(params[1]));
}
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Fixed Width in FontDef

Post by Jabberwocky »

Nice patch, that's been bugging me too.

The chances of the patch being incorporated into ogre are a lot higher if you follow the official patch submission procedure:
http://www.ogre3d.org/developers/submit-patch

I notice it mentions SVN at the top, but that's obsolete, SVN isn't used anymore.
Image
User avatar
Jabberwocky
OGRE Moderator
OGRE Moderator
Posts: 2819
Joined: Mon Mar 05, 2007 11:17 pm
Location: Canada
x 218
Contact:

Re: Fixed Width in FontDef

Post by Jabberwocky »

I use a debug console window for testing and debugging stuff in my game. My console window uses ogre overlays. I found the following issue with space characters written into ogre overlays (ogre v1.7.1):

Every space character written to an ogre overlay window seems to render as 2 spaces. This is particularly annoying when you're trying to format text output into rows and columns. For example, if I call Ogre::OverlayElement::setCaption( "This is some text"), it renders like this:

Code: Select all

This  is  some  text
instead of

Code: Select all

This is some text
The problem seems to be with ogretextareaoverlayelement.cpp:

Code: Select all

mSpaceWidth = mpFont->getGlyphAspectRatio(UNICODE_ZERO) * mCharHeight * 2.0f * mViewportAspectCoef;
That *2.0f multiplier makes all spaces twice as wide as the other characters. This must have been an explicit change at some point, because I'm pretty sure older versions of ogre didn't have this problem. Anyway, I fixed the issue by removing the * 2.0f multiplier:

Code: Select all

mSpaceWidth = mpFont->getGlyphAspectRatio(UNICODE_ZERO) * mCharHeight * mViewportAspectCoef;
It's unclear to me if this is a bug, or is somehow desired behavior for some people. But I thought I'd at least mention it here, as it seemed relevant for this thread.
Image
BaffledMollusc
Halfling
Posts: 59
Joined: Wed Feb 09, 2005 10:58 am

Re: Fixed Width in FontDef

Post by BaffledMollusc »

I'm resurrecting this thread because I had the same problem as Jabberwocky and traced it to same piece of code.

I can confirm that the *2.0f multiplier gives ridiculous spacing, and after removing it and recompiling the overlay text looks much more reasonable. So presumably it's a bug.

I had a quick look at the patch submission process, but given I'm not using any VCS (just downloaded the 1.7.1 source code and built it) I'm not sure how to generate or submit a patch. Still, I'm flagging it, and if anyone feels like submitting this trivial change, I'd be all for it :)
Taklu
Gnoblar
Posts: 1
Joined: Fri Oct 21, 2011 9:30 am

Re: Fixed Width in FontDef

Post by Taklu »

Thanks for letting me know this useful stuff. I could use your code and fixed my issue. Now the system works fine.
Post Reply