command console is visible when activated
[bioacid.git] / fonts.d
blob81f9a974f051a82c340785c1403c5de7c8aab742
1 /* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module fonts is aliced;
19 import iv.cmdcon;
20 import iv.nanovega;
21 import iv.nanovega.textlayouter;
24 // ////////////////////////////////////////////////////////////////////////// //
25 alias LayTextClass = LayTextD;
28 // ////////////////////////////////////////////////////////////////////////// //
29 enum TTFontStyle : ubyte { Normal = 0, Italic = 1, Bold = 2 }
31 __gshared FONScontext* fstash;
32 __gshared LayFontStash laf;
34 __gshared string[4] textFontNames = [
35 "PT Sans", //"Arial:noaa", //"~/ttf/ms/arial.ttf:noaa", // normal
36 "PT Sans:italic", //"~/ttf/ms/ariali.ttf:noaa", // italic
37 "PT Sans:bold", //"~/ttf/ms/arialbd.ttf:noaa", // bold
38 "PT Sans:italic:bold", //"~/ttf/ms/arialbi.ttf:noaa", // italic+bold
40 __gshared string[4] monoFontNames = [
41 //"/usr/share/fonts/ms/andalemo.ttf:noaa", // normal
42 "PT Mono", //"Courier New:noaa", //"~/ttf/ms/cour.ttf:noaa", // normal
43 "PT Mono:italic", //"~/ttf/ms/couri.ttf:noaa", // italic
44 "PT Mono:bold", //"~/ttf/ms/courbd.ttf:noaa", // bold
45 "PT Mono:italic:bold", //"~/ttf/ms/courbi.ttf:noaa", // italic+bold
47 __gshared string[4] uiFontNames = [
48 "PT Sans", //"Arial:noaa", //"~/ttf/ms/verdana.ttf:noaa", // normal
49 "PT Sans:italic", //"~/ttf/ms/ariali.ttf:noaa", // italic
50 "PT Sans:bold", //"~/ttf/ms/arialbd.ttf:noaa", // bold
51 "PT Sans:italic:bold", //"~/ttf/ms/arialbi.ttf:noaa", // italic+bold
55 // ////////////////////////////////////////////////////////////////////////// //
56 void fixFontForStyleEx (string normalFontPfx, LayFontStash laf, ref LayFontStyle st) nothrow @trusted @nogc {
57 //{ import core.stdc.stdio; printf("monospace=%d; italic=%d; bold=%d\n", (st.monospace ? 1 : 0), (st.italic ? 1 : 0), (st.bold ? 1 : 0)); }
58 char[12] tbuf;
59 int tbufpos = 0;
60 void put (const(char)[] s...) nothrow @trusted @nogc {
61 if (s.length == 0) return;
62 if (tbuf.length-tbufpos < s.length) assert(0, "wtf?!");
63 tbuf.ptr[tbufpos..tbufpos+s.length] = s[];
64 tbufpos += cast(int)s.length;
66 put(st.monospace ? "mono" : normalFontPfx);
67 if (st.italic) put("i");
68 if (st.bold) put("b");
69 st.fontface = laf.fontFaceId(tbuf[0..tbufpos]);
72 void fixFontForStyleText (LayFontStash laf, ref LayFontStyle st) nothrow @trusted @nogc { fixFontForStyleEx("text", laf, st); }
73 void fixFontForStyleUI (LayFontStash laf, ref LayFontStyle st) nothrow @trusted @nogc { fixFontForStyleEx("ui", laf, st); }
75 private void loadFmtFonts () {
76 import std.functional : toDelegate;
78 laf = new LayFontStash();
79 laf.fs.fonsAddStashFonts(fstash);
80 laf.fixFontDG = toDelegate(&fixFontForStyleText);
84 // ////////////////////////////////////////////////////////////////////////// //
85 // create dummy fontstash and load fonts
86 void loadAllFonts () {
87 assert(fstash is null);
88 FONSparams fp;
89 fp.width = 32;
90 fp.height = 32;
91 fp.flags = FONS_ZERO_TOPLEFT;
92 fstash = fonsCreateInternal(&fp);
93 if (fstash is null) assert(0, "error creating font stash");
95 void loadFont (string name, string path) {
96 auto fid = fstash.fonsAddFont(name, path, false); // no AA
97 if (fid < 0) assert(0, "can't load font '"~name~"' from '"~path~"'");
98 //conwriteln("created font [", name, "] (", path, "): ", fid);
101 void loadFontSet (string namebase, string[] pathes) {
102 static immutable string[4] pfx = ["", "i", "b", "ib"];
103 assert(pathes.length >= 4);
104 foreach (immutable idx; 0..4) loadFont(namebase~pfx[idx], pathes[idx]);
107 loadFontSet("text", textFontNames[]);
108 loadFontSet("mono", monoFontNames[]);
109 loadFontSet("ui", uiFontNames[]);
111 //loadFont("arial", "arial");
112 loadFont("arial", "/home/ketmar/sofonts/arialn.ttf");
113 loadFont("tahoma", "tahoma");
114 loadFont("verdana", "verdana");
116 //loadFont("test", "/mnt/bigfoot/dprj/bioacid/_ttf/ms/ttc/Sitka.ttc");
118 loadFmtFonts();
122 // ////////////////////////////////////////////////////////////////////////// //
123 //vg.fillColor(NVGColor.orange);
124 void drawLayouter(LT) (NVGContext vg, LT lay, int layTopY, int x0, int y0, int hgt) if (is(LT : LayTextImpl!CT, CT)) {
125 if (vg is null || lay is null || hgt < 1 || lay.lineCount == 0 || lay.width < 1) return;
126 int drawY = y0;
127 //FIXME: not GHeight!
128 int lidx = lay.findLineAtY(layTopY);
129 if (lidx >= 0 && lidx < lay.lineCount) {
130 vg.save();
131 scope(exit) vg.restore();
132 vg.strokeWidth = 1;
133 vg.beginPath();
134 vg.intersectScissor(x0, y0, lay.width, hgt);
135 drawY -= layTopY-lay.line(lidx).y;
136 vg.textAlign(NVGTextAlign.H.Left, NVGTextAlign.V.Baseline);
137 LayFontStyle lastStyle;
138 int startx = x0;
139 bool setColor = true;
140 while (lidx < lay.lineCount && hgt > 0) {
141 auto ln = lay.line(lidx);
142 foreach (ref LayWord w; lay.lineWords(lidx)) {
143 if (lastStyle != w.style || setColor) {
144 if (w.style.fontface != lastStyle.fontface) vg.fontFace = lay.fontFace(w.style.fontface);
145 vg.fontSize(w.style.fontsize);
146 auto c = NVGColor(w.style.color);
147 vg.fillColor = c;
148 vg.strokeColor = c;
149 lastStyle = w.style;
150 setColor = false;
151 //conprintfln("new color: 0x%08x; fontid=%d; fontsize=%d", w.style.color, w.style.fontface, w.style.fontsize);
153 // background color
155 auto c = NVGColor(w.style.bgcolor);
156 if (!c.isTransparent) {
158 vg.save();
159 scope(exit) vg.restore();
160 vg.beginPath();
161 vg.fillColor(c);
162 vg.rect(startx+w.x+0.5f, drawY+0.5, w.fullwidth+1, ln.h);
163 vg.fill();
165 vg.beginPath();
168 // element
169 auto oid = w.objectIdx;
170 if (oid >= 0) {
171 //vg.fill();
173 vg.save();
174 scope(exit) vg.restore();
175 vg.beginPath();
176 lay.objectAtIndex(oid).draw(vg, startx+w.x, drawY+ln.h+ln.desc);
178 vg.beginPath();
179 } else if (!w.expander) {
180 vg.text(startx+w.x, drawY+ln.h+ln.desc, lay.wordText(w));
182 //TODO: draw lines over whitespace
183 bool doStroke = false;
184 if (lastStyle.underline || lastStyle.href) { doStroke = true; vg.rect(startx+w.x+0.5f, drawY+ln.h+ln.desc+1+0.5f, w.w, 1); }
185 if (lastStyle.strike) { doStroke = true; vg.rect(startx+w.x+0.5f, drawY+ln.h+ln.desc-w.asc/3+0.5f, w.w, 2); }
186 if (lastStyle.overline) { doStroke = true; vg.rect(startx+w.x+0.5f, drawY+ln.h+ln.desc-w.asc-1+0.5f, w.w, 1); }
187 if (doStroke) {
188 vg.stroke();
189 vg.beginPath();
192 drawY += ln.h;
193 hgt -= ln.h;
194 ++lidx;