Can anyone who is good with text glyphs give me a pointer

If anyone can take a look at the pic im having trouble getting a dead on accurate sum of pixel width for letters on a line using the glyph widths, even with spacing set to 0 and kerning off.

What im doing is shown in the pic. Sized cut wrapped text to within a rectangle that’s pretty much the code in the pic there is not much too it its just a test to replace the measure string version i ignored forever, but the formula is giving me a hard time, Do you add cropping to spacing ect…
You can see the letters are just barely being measured wrong…

This is prep work for helper methods that will go with a chunked stringbuilder wrapper class and some other classes it will support.

So, if I understand is correctly, you want to wrap the text inside the yellow image? Like a popup window with text? I did it nem long ago, though the code is quite basic as I did not have time to polish it and I have not used my own popup, but if you need, I can share the code with you.

Basically, you need to split your text into words (do not forget to add the spaces!), measure them with the SpriteFont.MeasureString method, grab the X as the word’s width from it and calculate the overall length. When this length exceeds the width of your popup, add a linebreak, set the length back to 0 and continue the process. If you dont want to use linebreaks, then yu can create a HashSet or List and instead of adding linebreaks to your string, just add the actual substring to this list, set the substring to emtpy and start building it again.

Edit i think there is some differences between measure string and the actual draw into version. Specifically the flip methods i think in the matrixes which are honestly redundant.
Has anyone done there own implementation of directly drawing text to screen bypassing drawtext and knows if there are any performance problems with that, im seriously considering trying to do that at this point.

At the moment im not trying to use measure string im trying to ensure i can get a accurate pixel count of a pre-measured stringbuilder in relation to a preset rectangle representing a box which encloses it.
For my purposes the measuring of each word being wrapped as well is not always desired at times. If i do not want to wrap the text at all unless the it is by a user specified linebreak, and i instead want to cut off a line of text possibly in the middle of a word.

The real problem is that there seems to be inconsistency between the internal drawinto method and what the measure string calculates both from the method and internally im trying to isolate exactly what that is. Not interested in the old xna way at this point. Im pretty sure it didn’t work 100% right in xna as well. I just want a accurate version for the future that abstracts away most of these difficulty’s with scaling and cutting text…
The measure string itself is basically summing up a line of text anyways.
Further i have noticed when text is scaled as it will be at times the discrepancy is much more. Unless im just seeing some weird behavior i still have 3.4 in atm

Could this be something fractional with the matrix functions in drawinto ?
Well im still trying to get it to work even if i manually draw each character positionally i get different results.

Or maybe with my old font its not loading the same or something.
With a font generated with monogame a regular arial font gives this result under the exact same settings which is even more confusing turning off kerning.

Im trying to count per char exactly how many pixels mg will draw for each character width wise, the main thing i need is consistent behavior so i can simply set the spacing.

This is glyph data with no kerning, point size 10, no scaling, but i can see no combination that adds up to what mg is outputting to screen in pixel width
char=( Width 1 boundsX 58 boundsWidth 1 Left 0 rightB 0 cropX 0 cropWidth 4 includedberings 1
char=(! Width 1 boundsX 60 boundsWidth 1 Left 0 rightB 0 cropX 0 cropWidth 3 includedberings 1
char=(" Width 3 boundsX 55 boundsWidth 3 Left 0 rightB 0 cropX 0 cropWidth 5 includedberings 3
char=(# Width 8 boundsX 79 boundsWidth 8 Left 0 rightB 0 cropX 0 cropWidth 7 includedberings 8
char=($ Width 5 boundsX 61 boundsWidth 5 Left 0 rightB 0 cropX 0 cropWidth 7 includedberings 5
char=(% Width 10 boundsX 109 boundsWidth 10 Left 0 rightB 0 cropX 0 cropWidth 12 includedberings 10

Measuring by chars and string are the same. If you have too long texts, do it by char and when you reach the end of the available space, add a line break. I did the same in my game, though I am wrapping by words and not char (but the logic is the same):

As you can see, there are additional line breaks in the text, not only word wraping by length. I have not refactored my code, so it may be not fully polished, as I said, but it is fully working (obviously it does not handle 345623423429385723-char-long words, but in my case this will never happen in my game, or if it will, then I will do some additional code logic to handle that.

On top of these, my code also handles font scaling. So if you scale down the text by 50%, then more or less double amount of words will fit in one line.

Ill definitely be doing that as well but that later is not only not the major concern it is less of a problem as the former is.

Ok so i did a lot of digging and looking at the spritefont class and testing
It looks like it is going to pay off for everyone …

After im done im going to be posting up a optimization to the SpriteFont.cs DrawInto method.

That will save, i don’t even know how many cpu cycles, A shit ton that’s how many.
If no one sees it here and adds it ill post it to the issues page.

The jist of it is below there is a bit more too it then that but that is the idea.

        // EXTRA flipping crap 
        // cant remember the last time i actually flipped text first some reordering
        Vector2 flipAdjustment = Vector2.Zero;
        bool flippedVert = false;
        bool flippedHorz = false;
        Matrix transformation = Matrix.Identity;// 99% of usage cases ill bet this is a waste
        Matrix temp;// just a ref now
        
        // ill add a bool to skip a ton of calculations 
        // in fact ill put it right here so it immediately pops on and off the il stack
        // i cant imagine how many cycles this is gonna save.
        bool flip = false;
        if (effect != SpriteEffects.None)
            flip = true;

        if (flip) // allow us to skip this junk
        {
            flippedVert = (effect & SpriteEffects.FlipVertically) == SpriteEffects.FlipVertically;
            flippedHorz = (effect & SpriteEffects.FlipHorizontally) == SpriteEffects.FlipHorizontally;

            if (flippedVert || flippedHorz)
            {
                Vector2 size;
                MeasureString(sf, ref text, out size);

                if (flippedHorz)
                {
                    origin.X *= -1;
                    flipAdjustment.X = -size.X;
                }

                if (flippedVert)
                {
                    origin.Y *= -1;
                    flipAdjustment.Y = LineSpacing - size.Y;
                }
            }
            Matrix.CreateTranslation(-origin.X, -origin.Y, 0f, out transformation);
            Matrix.CreateScale((flippedHorz ? -scale.X : scale.X), (flippedVert ? -scale.Y : scale.Y), 1f, out temp);
            Matrix.Multiply(ref transformation, ref temp, out transformation);
            Matrix.CreateTranslation(flipAdjustment.X, flipAdjustment.Y, 0, out temp);
            Matrix.Multiply(ref temp, ref transformation, out transformation);
            Matrix.CreateRotationZ(rotation, out temp);
            Matrix.Multiply(ref transformation, ref temp, out transformation);
            Matrix.CreateTranslation(position.X, position.Y, 0f, out temp);
            Matrix.Multiply(ref transformation, ref temp, out transformation);
        }
        // EXTRA flipping crap ends for now but there is more later

        // there is some more code then later the below can also get skipped
        var p = offset;

            // EXTRA flipping crap...
            if (flip) // skip it
            {
                if (flippedHorz)
                    p.X += currentGlyph.BoundsInTexture.Width;
                if (flippedVert)
                    p.Y += currentGlyph.BoundsInTexture.Height - LineSpacing;
            }
            // EXTRA flipping crap...end
            //
            // Replace with
            p.X += currentGlyph.Cropping.X;
            p.Y += currentGlyph.Cropping.Y;

            // EXTRA flipping crap...
            Vector2.Transform(ref p, ref transformation, out p);
            // EXTRA flipping crap... end

`

This is just a quick mimic version of the actual method.
Didn’t feel like doing the whole github thing right now, i normally use the installer.
id guess that 99% of the time you dont call flip effects on text and 100% of the time normally all the code is executing in the inner loop who knows how many times per frame for nothing.
All those matrix operations can be skiped the transforms the bit wise flag checks ect.

I really wish i could extend into that class as well as spritebatch or it was partial so i could simply implement custom overloads of drawinto and spritebatch that would be ideal.

So what i would have to do as it is each time monogame gets a update is rebuild it with my custom methods in it. As it is, that makes its more difficult when i want to increase functionallity such as adding a method, that might automatically allow a bounding rectangle to be passed and automatically newline on that or stop drawing when out of bounds.

vertical flipping is ok but doing both horizonal and vertical with rotation messes up the current transforms.


This is one of the things i was trying to allow but this is best done internally. Further this eliminates the redundancy for calling measure string as well which is like having to call the same method twice…
Here the boundry is the background rectangle r.
Im calling the method like so.

        if (rotation > 6.28f) { rotation = 0f; }
        rotation += .01f * rotdir;

        Vector2 pos = new Vector2(50, 100);
        Rectangle r = new Rectangle((int)pos.X, (int)pos.Y, 400, 200);
        SimpleDraw.DrawBasicSquare(r, 1, Color.Gray, true);
        Engien.CurrentFont.Spacing = 2;
        // SpriteEffects.FlipVertically | SpriteEffects.FlipHorizontally | SpriteEffects.None
        bmt.DrawFont(Engien.spritebatch, tsb03, Engien.CurrentFont, pos, Color.Black, rotation, Vector2.Zero, Vector2.One, SpriteEffects.FlipVertically , 0f, r);

latest image monogame text is in blue.
My drawinto mimiced call is in black i have eliminated the matrix calls from it but the linear math isn’t quite done yet to replace the flip effects.