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
;
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)); }
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);
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");
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;
127 //FIXME: not GHeight!
128 int lidx
= lay
.findLineAtY(layTopY
);
129 if (lidx
>= 0 && lidx
< lay
.lineCount
) {
131 scope(exit
) vg
.restore();
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
;
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
);
151 //conprintfln("new color: 0x%08x; fontid=%d; fontsize=%d", w.style.color, w.style.fontface, w.style.fontsize);
155 auto c
= NVGColor(w
.style
.bgcolor
);
156 if (!c
.isTransparent
) {
159 scope(exit
) vg
.restore();
162 vg
.rect(startx
+w
.x
+0.5f, drawY
+0.5, w
.fullwidth
+1, ln
.h
);
169 auto oid
= w
.objectIdx
;
174 scope(exit
) vg
.restore();
176 lay
.objectAtIndex(oid
).draw(vg
, startx
+w
.x
, drawY
+ln
.h
+ln
.desc
);
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); }