1 /* 2 Copyright (c) 2013 Andrey Penechko 3 4 Boost Software License - Version 1.0 - August 17th, 2003 5 6 Permission is hereby granted, free of charge, to any person or organization 7 obtaining a copy of the software and accompanying documentation covered by 8 this license the "Software" to use, reproduce, display, distribute, 9 execute, and transmit the Software, and to prepare derivative works of the 10 Software, and to permit third-parties to whom the Software is furnished to 11 do so, all subject to the following: 12 13 The copyright notices in the Software and this entire statement, including 14 the above license grant, this restriction and the following disclaimer, 15 must be included in all copies of the Software, in whole or in part, and 16 all derivative works of the Software, unless such copies or derivative 17 works are solely in the form of machine-executable object code generated by 18 a source language processor. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 DEALINGS IN THE SOFTWARE. 27 */ 28 29 module anchovy.gui.textline; 30 31 import anchovy.gui; 32 public import anchovy.graphics.texrectarray; 33 import anchovy.graphics.interfaces.irenderer; 34 import anchovy.graphics.font.fontmanager; 35 36 class TextLine 37 { 38 39 public: 40 41 this() 42 { 43 _text = ""; 44 } 45 46 void font(Font newFont) @property 47 { 48 if (newFont is null) return; 49 _font = newFont; 50 if (!_isInited || newFont != _font) 51 init(); 52 } 53 54 Font font() @property 55 { 56 return _font; 57 } 58 59 bool isInited() @property 60 { 61 return _isInited; 62 } 63 64 void update() 65 { 66 if (text.length == 0 || !_isInited) return; 67 if (_isDirty) 68 { 69 _geometry.load; 70 _isDirty = false; 71 } 72 } 73 74 uint width() @property 75 { 76 return _width; 77 } 78 79 uint height() @property 80 { 81 return _height; 82 } 83 84 ivec2 size() @property 85 { 86 return ivec2(_width, _height); 87 } 88 89 TexRectArray geometry() @property 90 { 91 return _geometry; 92 } 93 94 dstring text() @property 95 { 96 return _text; 97 } 98 99 dstring text(in string newText) @property 100 { 101 return text = to!dstring(newText); 102 } 103 104 dstring text(in dstring newText) @property 105 { 106 if (_text == newText) 107 { 108 return _text; 109 } 110 111 _text = newText; 112 if (!_isInited) return _text; 113 114 _geometry.vertieces = null; 115 _cursorX = 0; 116 117 appendGlyphs(_text, _font); 118 _isDirty = true; 119 120 return _text; 121 } 122 123 string fontName() @property 124 { 125 return _fontName; 126 } 127 128 void fontName(string newFontName) @property 129 { 130 _fontName = newFontName; 131 } 132 133 ///Supports chaining 134 TextLine append(in string text) 135 { 136 return append(to!dstring(text)); 137 } 138 139 TextLine append(in dstring text) 140 { 141 appendGlyphs(_text, _font); 142 _isDirty = true; 143 return this; 144 } 145 146 protected: 147 148 void init() 149 { 150 _geometry = new TexRectArray; 151 _height = _font.size; 152 appendGlyphs(_text, _font); 153 _isInited = true; 154 } 155 156 void appendGlyphs(in dstring text, Font font) 157 { 158 foreach(dchar chr; text) 159 { 160 Glyph* glyph = font.getGlyph(chr); 161 if (glyph !is null && chr == '\t') 162 { 163 _cursorX += glyph.metrics.advanceX * _tabSize; 164 continue; 165 } 166 if (glyph is null) glyph = font.getGlyph('?'); 167 168 int x = glyph.metrics.offsetX + _cursorX; 169 int y = font.verticalOffset - glyph.metrics.offsetY; 170 int w = glyph.metrics.width; 171 int h = glyph.metrics.height; 172 int tx = glyph.atlasPosition.x; 173 int ty = glyph.atlasPosition.y; 174 175 //whitespace 176 if (w == 0 || h == 0) 177 { 178 _cursorX += glyph.metrics.advanceX; 179 continue; 180 } 181 182 _geometry.appendQuad(Rect(x, y, w, h), Rect(tx, ty, w, h)); 183 _cursorX += glyph.metrics.advanceX; 184 } 185 186 _width = _cursorX; 187 } 188 189 protected: 190 uint _width; 191 uint _height; 192 dstring _text; 193 bool _isInited = false; 194 195 TexRectArray _geometry; 196 uint _cursorX; 197 bool _isDirty = true; 198 199 Font _font; 200 string _fontName; 201 202 ubyte _tabSize = 4; 203 }