1 module d2d.font.bmtext;
2 version (BindSDL_Image)  : import d2d;
3 
4 import std.utf : byDchar;
5 
6 /// Implementation containing text drawable functions using an AngelCode BMFont. Nice and fast for unscaled text, reduced memory usage, render time scales with text length, no re-render times, requires some additional shader uniforms.
7 class BMText : Transformable, IText
8 {
9 private:
10 	float _scale = 1.0f;
11 	string _text = "";
12 	BMFont _font;
13 	bool _multiline = false;
14 	RectangleShape unitRect;
15 	float iWidth, iHeight;
16 
17 public:
18 	/// Creates an empty bmfont text
19 	this(BMFont font)
20 	{
21 		_font = font;
22 		iWidth = 1.0f / _font.handle.common.scaleW;
23 		iHeight = 1.0f / _font.handle.common.scaleH;
24 		unitRect = RectangleShape.create(vec2(0, 0), vec2(1, 1));
25 	}
26 
27 	/// Gets the scale in percent.
28 	override @property float scale()
29 	{
30 		return _scale;
31 	}
32 
33 	/// Sets the scale in percent.
34 	override @property void scale(float value)
35 	{
36 		_scale = value;
37 	}
38 
39 	/// Gets the text.
40 	override @property string text()
41 	{
42 		return _text;
43 	}
44 
45 	/// Modifies the text.
46 	override @property void text(string value)
47 	{
48 		_text = value;
49 	}
50 
51 	/// Returns if this text should be rendered multiline.
52 	@property bool multiline()
53 	{
54 		return _multiline;
55 	}
56 
57 	/// Sets if this text should be rendered multiline.
58 	@property void multiline(bool value)
59 	{
60 		_multiline = value;
61 	}
62 
63 	/// Dynamically draws the text onto a target. Requires the shader to have `texRect` vec4(uvX, uvY, uvW, uvH) and `sizeRect` vec4(posX, posY, width, height) uniforms.
64 	override void draw(IRenderTarget target, ShaderProgram shader = null)
65 	{
66 		matrixStack.push();
67 		matrixStack.top *= mat4.scaling(_scale, _scale, 1);
68 		matrixStack.top *= transform;
69 		int x, y;
70 		dchar last;
71 		for (int i = 0; i < _font.textures.length; i++)
72 			_font.textures[i].bind(i);
73 		if (shader)
74 			shader.bind();
75 		foreach (dc; _text.byDchar)
76 		{
77 			auto bmChar = _font.handle.getChar(dc);
78 			if (bmChar.id == dchar.init)
79 			{
80 				if (_multiline && dc == '\n')
81 				{
82 					x = 0;
83 					y += _font.handle.common.lineHeight;
84 				}
85 				continue;
86 			}
87 
88 			shader.set("tex", cast(int) bmChar.page);
89 			shader.set("texRect", vec4(bmChar.x * iWidth, bmChar.y * iHeight,
90 					bmChar.width * iWidth, bmChar.height * iHeight));
91 			shader.set("sizeRect", vec4(x + bmChar.xoffset, y + bmChar.yoffset,
92 					bmChar.width, bmChar.height));
93 			unitRect.draw(target, shader);
94 			if (_multiline && dc == '\n')
95 			{
96 				x = 0;
97 				y += _font.handle.common.lineHeight;
98 				continue;
99 			}
100 			if (last != dchar.init)
101 				x += _font.handle.getKerning(last, dc);
102 			x += bmChar.xadvance;
103 			last = dc;
104 		}
105 		matrixStack.pop();
106 	}
107 
108 	override @property bool valid()
109 	{
110 		return true;
111 	}
112 
113 	override void dispose()
114 	{
115 	}
116 }