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, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 module fonts
is aliced
;
20 import iv
.nanovega
.textlayouter
;
23 // ////////////////////////////////////////////////////////////////////////// //
24 alias LayTextClass
= LayTextD
;
27 // ////////////////////////////////////////////////////////////////////////// //
28 enum TTFontStyle
: ubyte { Normal
= 0, Italic
= 1, Bold
= 2 }
30 __gshared FONSContext fstash
;
31 __gshared LayFontStash laf
;
33 __gshared string
[4] textFontNames
= [
34 "PT Sans", //"Arial:noaa", //"~/ttf/ms/arial.ttf:noaa", // normal
35 "PT Sans:italic", //"~/ttf/ms/ariali.ttf:noaa", // italic
36 "PT Sans:bold", //"~/ttf/ms/arialbd.ttf:noaa", // bold
37 "PT Sans:italic:bold", //"~/ttf/ms/arialbi.ttf:noaa", // italic+bold
39 __gshared string
[4] monoFontNames
= [
40 //"/usr/share/fonts/ms/andalemo.ttf:noaa", // normal
41 "PT Mono", //"Courier New:noaa", //"~/ttf/ms/cour.ttf:noaa", // normal
42 "PT Mono:italic", //"~/ttf/ms/couri.ttf:noaa", // italic
43 "PT Mono:bold", //"~/ttf/ms/courbd.ttf:noaa", // bold
44 "PT Mono:italic:bold", //"~/ttf/ms/courbi.ttf:noaa", // italic+bold
46 __gshared string
[4] uiFontNames
= [
47 "PT Sans", //"Arial:noaa", //"~/ttf/ms/verdana.ttf:noaa", // normal
48 "PT Sans:italic", //"~/ttf/ms/ariali.ttf:noaa", // italic
49 "PT Sans:bold", //"~/ttf/ms/arialbd.ttf:noaa", // bold
50 "PT Sans:italic:bold", //"~/ttf/ms/arialbi.ttf:noaa", // italic+bold
54 // ////////////////////////////////////////////////////////////////////////// //
55 void fixFontForStyleEx (string normalFontPfx
, LayFontStash laf
, ref LayFontStyle st
) nothrow @trusted @nogc {
56 //{ import core.stdc.stdio; printf("monospace=%d; italic=%d; bold=%d\n", (st.monospace ? 1 : 0), (st.italic ? 1 : 0), (st.bold ? 1 : 0)); }
59 void put (const(char)[] s
...) nothrow @trusted @nogc {
60 if (s
.length
== 0) return;
61 if (tbuf
.length
-tbufpos
< s
.length
) assert(0, "wtf?!");
62 tbuf
.ptr
[tbufpos
..tbufpos
+s
.length
] = s
[];
63 tbufpos
+= cast(int)s
.length
;
65 put(st
.monospace ?
"mono" : normalFontPfx
);
66 if (st
.italic
) put("i");
67 if (st
.bold
) put("b");
68 st
.fontface
= laf
.fontFaceId(tbuf
[0..tbufpos
]);
71 void fixFontForStyleText (LayFontStash laf
, ref LayFontStyle st
) nothrow @trusted @nogc { fixFontForStyleEx("text", laf
, st
); }
72 void fixFontForStyleUI (LayFontStash laf
, ref LayFontStyle st
) nothrow @trusted @nogc { fixFontForStyleEx("ui", laf
, st
); }
74 private void loadFmtFonts () {
75 import std
.functional
: toDelegate
;
77 laf
= new LayFontStash();
78 laf
.fs
.addFontsFrom(fstash
);
79 laf
.fixFontDG
= toDelegate(&fixFontForStyleText
);
83 // ////////////////////////////////////////////////////////////////////////// //
84 // create dummy fontstash and load fonts
85 void loadAllFonts () {
86 assert(fstash
is null);
87 fstash
= FONSContext
.create(FONSParams
.init
);
88 if (fstash
is null) assert(0, "error creating font stash");
90 void loadFont (string name
, string path
) {
91 auto fid
= fstash
.addFont(name
, path
, false); // no AA
92 if (fid
< 0) assert(0, "can't load font '"~name
~"' from '"~path
~"'");
93 //conwriteln("created font [", name, "] (", path, "): ", fid);
96 void loadFontSet (string namebase
, string
[] pathes
) {
97 static immutable string
[4] pfx
= ["", "i", "b", "ib"];
98 assert(pathes
.length
>= 4);
99 foreach (immutable idx
; 0..4) loadFont(namebase
~pfx
[idx
], pathes
[idx
]);
102 loadFontSet("text", textFontNames
[]);
103 loadFontSet("mono", monoFontNames
[]);
104 loadFontSet("ui", uiFontNames
[]);
106 //loadFont("arial", "arial");
107 loadFont("arial", "/home/ketmar/sofonts/arialn.ttf");
108 loadFont("tahoma", "tahoma");
109 loadFont("verdana", "verdana");
111 //loadFont("test", "/mnt/bigfoot/dprj/bioacid/_ttf/ms/ttc/Sitka.ttc");
117 // ////////////////////////////////////////////////////////////////////////// //
118 //vg.fillColor(NVGColor.orange);
119 void drawLayouter(LT
) (NVGContext vg
, LT lay
, int layTopY
, int x0
, int y0
, int hgt
)
120 if (is(LT
: LayTextImpl
!CT
, CT
))
122 if (vg
is null || lay
is null || hgt
< 1 || lay
.lineCount
== 0 || lay
.width
< 1) return;
124 //FIXME: not GHeight!
125 int lidx
= lay
.findLineAtY(layTopY
);
126 if (lidx
>= 0 && lidx
< lay
.lineCount
) {
128 scope(exit
) vg
.restore();
131 vg
.intersectScissor(x0
, y0
, lay
.width
, hgt
);
132 drawY
-= layTopY
-lay
.line(lidx
).y
;
133 vg
.textAlign(NVGTextAlign
.H
.Left
, NVGTextAlign
.V
.Baseline
);
134 LayFontStyle lastStyle
;
136 bool setColor
= true;
137 while (lidx
< lay
.lineCount
&& hgt
> 0) {
138 auto ln
= lay
.line(lidx
);
139 foreach (ref LayWord w
; lay
.lineWords(lidx
)) {
140 if (lastStyle
!= w
.style || setColor
) {
141 if (w
.style
.fontface
!= lastStyle
.fontface
) vg
.fontFace
= lay
.fontFace(w
.style
.fontface
);
142 vg
.fontSize(w
.style
.fontsize
);
143 auto c
= NVGColor(w
.style
.color
);
148 //conprintfln("new color: 0x%08x; fontid=%d; fontsize=%d", w.style.color, w.style.fontface, w.style.fontsize);
152 auto c
= NVGColor(w
.style
.bgcolor
);
153 if (!c
.isTransparent
) {
156 scope(exit
) vg
.restore();
159 vg
.rect(cast(int)(startx
+w
.x
)+0.5f, cast(int)drawY
+0.5, cast(int)w
.fullwidth
, cast(int)ln
.h
);
160 //vg.rect(startx+w.x+0.5f, drawY+0.5, w.fullwidth, ln.h);
167 if (lay
.isMarkedWord(w
.wordNum
)) {
169 scope(exit
) vg
.restore();
171 vg
.fillColor(nvgRGB(0, 0, 255));
172 vg
.rect(cast(int)(startx
+w
.x
)+0.5f, cast(int)drawY
+0.5,
173 (lay
.isMarkedWord(w
.wordNum
+1) ?
cast(int)w
.fullwidth
: cast(int)w
.width
),
175 //vg.rect(startx+w.x+0.5f, drawY+0.5, w.fullwidth, ln.h);
180 auto oid
= w
.objectIdx
;
185 scope(exit
) vg
.restore();
187 lay
.objectAtIndex(oid
).draw(vg
, startx
+w
.x
, drawY
+ln
.h
+ln
.desc
);
190 } else if (!w
.expander
) {
191 vg
.text(startx
+w
.x
, drawY
+ln
.h
+ln
.desc
, lay
.wordText(w
));
193 //TODO: draw lines over whitespace
194 bool doStroke
= false;
195 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); }
196 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); }
197 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); }