Glyphs ate my spaces?

Hey embers,

I’m trying to get a string with leading spaces to display in a series of several lines. For example the following text:

std::string atext =
"    Impressive OS   \n"
" 3000 Bytes of mem   \n";

mGlyphs = mTextureFont->getGlyphPlacements( atext );

When I then eventually render this via the call

ci::gl::color( mColorLightBlue );
mTextureFont->drawGlyphs( mGlyphs, mOffsetGlyphs );

what eventually pops out is:

Impressive OS
3000 Bytes of mem

All leading spaces gobbled up. I looked at the drawOptions, like clipHorizontal and clipVertical, but that didn’t seem to do what I’d hoped for. A side note, if I have some sort of leading character, the spaces do not vanish. :confused: But I don’t really want that, and any attempts at perhaps finding some sort of invisible specialty character to lead with such as \x20 has also gone nowhere.

I’m all ears to advice!

I’m quite not sure what you’re running into because I wasn’t able to reproduce it. I tried using the sample TextureFontApp and switching out:

mTextureFont->drawStringWrapped( str, boundsRect + offset);

with:

std::string atext =
"    Impressive OS   \n"
" 3000 Bytes of mem   \n";
auto mGlyphs = mTextureFont->getGlyphPlacements( atext );
vec2 mOffsetGlyphs( 50, 50 );
ci::gl::color( ColorA( 0, 0, 1, 1 ) );
mTextureFont->drawGlyphs( mGlyphs, mOffsetGlyphs );

And I got:

Which looks like it’s preserving the spaces. So I’d look through the code between there and see if something is modifying mGlyphs.

1 Like

Hey @drewish,

Thanks for taking the time to run a test I should have run myself. :frowning:

My apologies for my lack of diligence. Thanks to your insight, I’ve more thoroughly looked at the matter, and it seems what’s happening is that all but the very first line will have its leading spaces consumed. So my example was indeed misleading. A better one would be:

" Spaces will be preserved\n"
“Edge\n”
" My space has been devoured :(\n"

I’ve tried switching out the newline (\n) escape character for carriage return (\r), but to no avail. I know a solution to this would be to simply render every line on its own, and perhaps I’ll have to resort to that anyway, but this still seems like unintended behavior?

If you peek into the glyph’s dimensions for the character on the next line what does it show for the width? Are the spaces even present? Is their width zeroed out?

I’ve peeked in the returned vector of glyphs - it seems the spaces are literally being removed.

The following three texts will return exactly the same vector of glyphs:

std::string atext = " A\n"
	"                      A\n";

std::string atext2 = " A\n"
	"A\n";

std::string atext3 = " A\n                  A\n";

In other words - the spaces aren’t even present.

Can you provide a longer sample of the code you’re using? Those snippets don’t quite make sense to me.

Hey @drewish,

Thanks for still engaging me in the matter. If you put any text strings I’ve provided you with into the TextureFontApp, you’ll see the spaces disappear. In fact, in your initial screenshot, the first space before the characters ‘3000’ is also missing. It’s just hard to tell because there’s no other line to compare it too. If you want some easy copy-paste code, you can just substitute this into the draw function:

void TextureFontApp::draw()
{
gl::setMatricesWindow( getWindowSize() );
gl::enableAlphaBlending();
gl::clear( Color( 0, 0, 0 ) );

std::string str( "Granted, then, that certain transformations do happen, it is essential that we should regard them in the philosophic manner of fairy tales, not in the unphilosophic manner of science and the \"Laws of Nature.\" When we are asked why eggs turn into birds or fruits fall in autumn, we must answer exactly as the fairy godmother would answer if Cinderella asked her why mice turned into horses or her clothes fell from her at twelve o'clock. We must answer that it is MAGIC. It is not a \"law,\" for we do not understand its general formula." );

str = "          a\n"
	"           a\n";

Rectf boundsRect( 40, mTextureFont->getAscent() + 40, getWindowWidth() - 40, getWindowHeight() - 40 );

gl::color( ColorA( 1, 0.5f, 0.25f, 1.0f ) );

mTextureFont->drawStringWrapped( str, boundsRect );

auto mGlyphs = mTextureFont->getGlyphPlacements( str );

// Draw FPS
gl::color( Color::white() );
mTextureFont->drawString( toString( floor(getAverageFps()) ) + " FPS", vec2( 10, getWindowHeight() - mTextureFont->getDescent() ) );

// Draw Font Name
float fontNameWidth = mTextureFont->measureString( mTextureFont->getName() ).x;
mTextureFont->drawString( mTextureFont->getName(), vec2( getWindowWidth() - fontNameWidth - 10, getWindowHeight() - mTextureFont->getDescent() ) );

}

I debugged the process myself now that I got my head on a little better and in the Unicode.cpp file at line 296 (which is part of Cinder), I found the following snippet:

	// eat any spaces we'd start on on the next line
	size_t tempByte = lineStartByte;
	while( nextCharUtf8( line, &tempByte, lengthInBytes ) == (uint32_t)' ') {
		lineStartByte = tempByte;
		++lineStartChar;
	}

So… I suppose this behavior is intended? Which honestly surprises me a tad…

1 Like