/// <summary> /// Submit a text string of sprites for drawing in the current batch. /// </summary> /// <param name="spriteFont">A font.</param> /// <param name="text">The text which will be drawn.</param> /// <param name="position">The drawing location on screen.</param> /// <param name="color">A color mask.</param> /// <param name="rotation">A rotation of this string.</param> /// <param name="origin">Center of the rotation. 0,0 by default.</param> /// <param name="scale">A scaling of this string.</param> /// <param name="effects">Modificators for drawing. Can be combined.</param> /// <param name="layerDepth">A depth of the layer of this string.</param> public static void drawString( this Batcher batcher, BitmapFont bitmapFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth ) { var scaleVec = new Vector2( scale, scale ); var source = new FontCharacterSource( text ); bitmapFont.drawInto( batcher, ref source, position, color, rotation, origin, scaleVec, effects, layerDepth ); }
/// <summary> /// Returns the size of the contents of a StringBuilder when /// rendered in this font. /// </summary> /// <param name="text">The text to measure.</param> /// <returns>The size, in pixels, of 'text' when rendered in /// this font.</returns> public Vector2 measureString( StringBuilder text ) { var source = new FontCharacterSource( text ); Vector2 size; measureString( ref source, out size ); return size; }
public static void drawString( this Batcher batcher, NezSpriteFont spriteFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth ) { Assert.isFalse( text == null ); if( text.Length == 0 ) return; var source = new FontCharacterSource( text ); spriteFont.drawInto( batcher, ref source, position, color, rotation, origin, scale, effects, layerDepth ); }
void measureString( ref FontCharacterSource text, out Vector2 size ) { if( text.Length == 0 ) { size = Vector2.Zero; return; } // Get the default glyph here once. SpriteFont.Glyph? defaultGlyph = null; if( _font.DefaultCharacter.HasValue ) defaultGlyph = _glyphs[_font.DefaultCharacter.Value]; var width = 0.0f; var finalLineHeight = (float)_font.LineSpacing; var currentGlyph = SpriteFont.Glyph.Empty; var offset = Vector2.Zero; var firstGlyphOfLine = true; for( var i = 0; i < text.Length; ++i ) { var c = text[i]; if( c == '\r' ) continue; if( c == '\n' ) { finalLineHeight = _font.LineSpacing; offset.X = 0; offset.Y += _font.LineSpacing; firstGlyphOfLine = true; continue; } if( !_glyphs.TryGetValue( c, out currentGlyph ) ) { if( !defaultGlyph.HasValue ) throw new ArgumentException( "Errors.TextContainsUnresolvableCharacters", "text" ); currentGlyph = defaultGlyph.Value; } // The first character on a line might have a negative left side bearing. // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, // so that text does not hang off the left side of its rectangle. if( firstGlyphOfLine ) { offset.X = Math.Max( currentGlyph.LeftSideBearing, 0 ); firstGlyphOfLine = false; } else { offset.X += _font.Spacing + currentGlyph.LeftSideBearing; } offset.X += currentGlyph.Width; var proposedWidth = offset.X + Math.Max( currentGlyph.RightSideBearing, 0 ); if( proposedWidth > width ) width = proposedWidth; offset.X += currentGlyph.RightSideBearing; if( currentGlyph.Cropping.Height > finalLineHeight ) finalLineHeight = currentGlyph.Cropping.Height; } size.X = width; size.Y = offset.Y + finalLineHeight; }
public void drawInto( Batcher batcher, ref FontCharacterSource text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth ) { var flipAdjustment = Vector2.Zero; var flippedVert = ( effect & SpriteEffects.FlipVertically ) == SpriteEffects.FlipVertically; var flippedHorz = ( effect & SpriteEffects.FlipHorizontally ) == SpriteEffects.FlipHorizontally; if( flippedVert || flippedHorz ) { Vector2 size; measureString( ref text, out size ); if( flippedHorz ) { origin.X *= -1; flipAdjustment.X = -size.X; } if( flippedVert ) { origin.Y *= -1; flipAdjustment.Y = _font.LineSpacing - size.Y; } } // TODO: This looks excessive... i suspect we could do most of this with simple vector math and avoid this much matrix work. var requiresTransformation = flippedHorz || flippedVert || rotation != 0f || scale != Vector2.One; if( requiresTransformation ) { Matrix2D temp; Matrix2D.createTranslation( -origin.X, -origin.Y, out _transformationMatrix ); Matrix2D.createScale( ( flippedHorz ? -scale.X : scale.X ), ( flippedVert ? -scale.Y : scale.Y ), out temp ); Matrix2D.multiply( ref _transformationMatrix, ref temp, out _transformationMatrix ); Matrix2D.createTranslation( flipAdjustment.X, flipAdjustment.Y, out temp ); Matrix2D.multiply( ref temp, ref _transformationMatrix, out _transformationMatrix ); Matrix2D.createRotation( rotation, out temp ); Matrix2D.multiply( ref _transformationMatrix, ref temp, out _transformationMatrix ); Matrix2D.createTranslation( position.X, position.Y, out temp ); Matrix2D.multiply( ref _transformationMatrix, ref temp, out _transformationMatrix ); } // Get the default glyph here once. SpriteFont.Glyph? defaultGlyph = null; if( _font.DefaultCharacter.HasValue ) defaultGlyph = _glyphs[_font.DefaultCharacter.Value]; var currentGlyph = SpriteFont.Glyph.Empty; var offset = requiresTransformation ? Vector2.Zero : position - origin; var firstGlyphOfLine = true; for( var i = 0; i < text.Length; ++i ) { var c = text[i]; if( c == '\r' ) continue; if( c == '\n' ) { offset.X = requiresTransformation ? 0f : position.X - origin.X; offset.Y += _font.LineSpacing; firstGlyphOfLine = true; continue; } if( !_glyphs.TryGetValue( c, out currentGlyph ) ) { if( !defaultGlyph.HasValue ) throw new ArgumentException( "Errors.TextContainsUnresolvableCharacters", "text" ); currentGlyph = defaultGlyph.Value; } // The first character on a line might have a negative left side bearing. // In this scenario, SpriteBatch/SpriteFont normally offset the text to the right, // so that text does not hang off the left side of its rectangle. if( firstGlyphOfLine ) { offset.X += Math.Max( currentGlyph.LeftSideBearing, 0 ); firstGlyphOfLine = false; } else { offset.X += _font.Spacing + currentGlyph.LeftSideBearing; } var p = offset; if( flippedHorz ) p.X += currentGlyph.BoundsInTexture.Width; p.X += currentGlyph.Cropping.X; if( flippedVert ) p.Y += currentGlyph.BoundsInTexture.Height - _font.LineSpacing; p.Y += currentGlyph.Cropping.Y; // transform our point if we need to if( requiresTransformation ) Vector2Ext.transform( ref p, ref _transformationMatrix, out p ); var destRect = RectangleExt.fromFloats( p.X, p.Y, currentGlyph.BoundsInTexture.Width * scale.X, currentGlyph.BoundsInTexture.Height * scale.Y ); batcher.draw( _font.Texture, destRect, currentGlyph.BoundsInTexture, color, rotation, Vector2.Zero, effect, depth ); offset.X += currentGlyph.Width + currentGlyph.RightSideBearing; } }
void IFont.drawInto( Batcher batcher, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effect, float depth ) { var source = new FontCharacterSource( text ); drawInto( batcher, ref source, position, color, rotation, origin, scale, effect, depth ); }
/// <summary> /// Submit a text string of sprites for drawing in the current batch. /// </summary> /// <param name="spriteFont">A font.</param> /// <param name="text">The text which will be drawn.</param> /// <param name="position">The drawing location on screen.</param> /// <param name="color">A color mask.</param> public static void drawString( this Batcher batcher, BitmapFont bitmapFont, StringBuilder text, Vector2 position, Color color ) { var source = new FontCharacterSource( text ); bitmapFont.drawInto( batcher, ref source, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f ); }
/// <summary> /// Submit a text string of sprites for drawing in the current batch. /// </summary> /// <param name="spriteFont">A font.</param> /// <param name="text">The text which will be drawn.</param> /// <param name="position">The drawing location on screen.</param> /// <param name="color">A color mask.</param> /// <param name="rotation">A rotation of this string.</param> /// <param name="origin">Center of the rotation. 0,0 by default.</param> /// <param name="scale">A scaling of this string.</param> /// <param name="effects">Modificators for drawing. Can be combined.</param> /// <param name="layerDepth">A depth of the layer of this string.</param> public static void DrawString( this SpriteBatch spriteBatch, BitmapFont bitmapFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth ) { var source = new FontCharacterSource( text ); bitmapFont.drawInto( spriteBatch, ref source, position, color, rotation, origin, scale, effects, layerDepth ); }
/// <summary> /// Submit a text string of sprites for drawing in the current batch. /// </summary> /// <param name="spriteFont">A font.</param> /// <param name="text">The text which will be drawn.</param> /// <param name="position">The drawing location on screen.</param> /// <param name="color">A color mask.</param> public static void DrawString( this SpriteBatch spriteBatch, BitmapFont bitmapFont, string text, Vector2 position, Color color ) { var source = new FontCharacterSource( text ); bitmapFont.drawInto( spriteBatch, ref source, position, color, 0, Vector2.Zero, Vector2.One, SpriteEffects.None, 0f ); }