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 71 return Vector2(size.x * scale.x, size.y * scale.y); 72 } 73 74 /// 75 Rect getBounds() 76 { 77 Vector3 start = position + getOffset(); 78 Vector2 size = getSize(); 79 80 return Rect(start.x, start.y, size.x, size.y); 81 } 82 83 /// 84 override void draw(RenderTarget renderTarget, Matrix transform) 85 { 86 transform = transform.translate(getOffset()); 87 88 foreach(i; 0 .. _text.length) 89 { 90 Glyph glyph = glyphs[i]; 91 Sprite sprite = sprites[i]; 92 93 sprite.tint = color; 94 95 Vector2 offset = glyph.offset; 96 97 if(i > 0) 98 offset += font.getKerning(_text[i - 1], _text[i]); 99 100 renderTarget.drawSprite(sprite, transform.translate(offset)); 101 102 transform = transform.translate(glyph.advance); 103 } 104 } 105 106 private Vector2 getOffset() 107 { 108 const Vector2 size = getSize(); 109 Vector2 offset; 110 111 if(textAlign == TextAlign.CENTER) 112 offset.x -= size.x / 2; 113 else if(textAlign == TextAlign.RIGHT) 114 offset.x -= size.x; 115 116 final switch(textBaseline) 117 { 118 case TextBaseline.TOP: 119 break; 120 case TextBaseline.MIDDLE: 121 offset.y += (font.ascentLine - font.descentLine) * scale.y / 2; 122 break; 123 case TextBaseline.BOTTOM: 124 offset.y += (font.size - font.descentLine) * scale.y; 125 break; 126 case TextBaseline.HANGING: 127 offset.y += (font.ascentLine - font.size) * scale.y; 128 break; 129 case TextBaseline.ALPHABETIC: 130 offset.y += font.size * scale.y; 131 break; 132 } 133 134 return offset; 135 } 136 }