1 module prova.graphics.text.text; 2 3 import prova.core, 4 prova.graphics, 5 prova.math; 6 7 /// 8 enum TextAlign { LEFT, CENTER, RIGHT } 9 /// 10 enum TextBaseline { TOP, MIDDLE, BOTTOM, HANGING, ALPHABETIC } 11 12 /// 13 class Text : Entity 14 { 15 /// 16 Color color; 17 /// 18 TextAlign textAlign; 19 /// 20 TextBaseline textBaseline; 21 private Sprite[] sprites; 22 private Glyph[] glyphs; 23 private Font font; 24 private string _text; 25 26 /// 27 this(string text, Font font) 28 { 29 this.font = font; 30 this.text = text; 31 } 32 33 /// 34 @property string text() 35 { 36 return _text; 37 } 38 39 /// 40 @property void text(string text) 41 { 42 sprites.length = text.length; 43 glyphs.length = text.length; 44 45 foreach(i; 0 .. text.length) 46 { 47 const int c = text[i]; 48 49 if(!font.hasGlyph(c)) 50 continue; 51 52 const Glyph glyph = font.getGlyph(c); 53 54 Sprite sprite = new Sprite(); 55 sprite.texture = font.texture; 56 sprite.clip = glyph.clip; 57 sprite.origin = Vector2(-glyph.clip.width / 2, glyph.clip.height / 2); 58 59 sprites[i] = sprite; 60 glyphs[i] = glyph; 61 } 62 63 _text = text; 64 } 65 66 /// 67 Vector2 getSize() 68 { 69 Vector2 size = font.measureString(_text); 70 Vector3 scale = getWorldScale(); 71 72 return Vector2(size.x * scale.x, size.y * scale.y); 73 } 74 75 /// 76 override void draw(RenderTarget renderTarget, Matrix transform) 77 { 78 Matrix glyphTransform = Matrix.identity; 79 glyphTransform = glyphTransform.translate(getOffset()); 80 81 foreach(i; 0 .. _text.length) 82 { 83 Glyph glyph = glyphs[i]; 84 Sprite sprite = sprites[i]; 85 86 sprite.tint = color; 87 88 Vector2 offset = glyph.offset; 89 90 if(i > 0) 91 offset += font.getKerning(_text[i - 1], _text[i]); 92 93 renderTarget.drawSprite( 94 sprite, 95 transform * glyphTransform.translate(offset) 96 ); 97 98 glyphTransform = glyphTransform.translate(glyph.advance); 99 } 100 } 101 102 private Vector2 getOffset() 103 { 104 const Vector2 size = font.measureString(_text); 105 Vector2 offset; 106 107 if(textAlign == TextAlign.CENTER) 108 offset.x -= size.x / 2; 109 else if(textAlign == TextAlign.RIGHT) 110 offset.x -= size.x; 111 112 final switch(textBaseline) 113 { 114 case TextBaseline.TOP: 115 break; 116 case TextBaseline.MIDDLE: 117 offset.y += (font.ascentLine - font.descentLine) * scale.y / 2; 118 break; 119 case TextBaseline.BOTTOM: 120 offset.y += (font.size - font.descentLine) * scale.y; 121 break; 122 case TextBaseline.HANGING: 123 offset.y += (font.ascentLine - font.size) * scale.y; 124 break; 125 case TextBaseline.ALPHABETIC: 126 offset.y += font.size * scale.y; 127 break; 128 } 129 130 return offset; 131 } 132 }