2 * Pixel Graphics Library
3 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
4 * Understanding is not required. Only obedience.
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, version 3 of the License ONLY.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module iv
.sdpy
.bgichr
/*is aliced*/;
22 import iv
.sdpy
.gfxbuf
;
27 // ////////////////////////////////////////////////////////////////////////// //
37 static struct Stroke
{
50 int[256] ffirstStroke
;
52 ushort fver
, dver
; // font and driver versions
55 this (const(char)[] fname
) {
56 import std
.stdio
: File
;
57 load(File(fname
.idup
)); // fixme
60 this(ST
) (auto ref ST st
) if (isReadableStream
!ST
) {
64 @property const pure nothrow @safe @nogc {
65 int height () { return fascent
-fdescent
; }
66 int ascent () { return fascent
; }
67 int descent () { return fdescent
; }
68 int baseline () { return fbase
; }
71 const pure nothrow @safe @nogc {
72 int charWidth (char ch
, in float scale
=1.0f) { return cast(int)(scale
*wdt
[cast(ubyte)ch
]); }
73 int textWidth (const(char)[] str, in float scale
=1.0f) {
75 foreach (immutable ch
; str) w
+= scale
*wdt
[cast(ubyte)ch
];
80 int drawChar() (auto ref GfxBuf gb
, int x
, int y
, char ch
, VColor clr
, in float scale
=1.0f) {
81 int sn
= ffirstStroke
[cast(ubyte)ch
];
83 float ox
= 0.0f, oy
= 0.0f;
84 for (; sn
< stk
.length
&& stk
[sn
].opcode
!= OpEnd
; ++sn
) {
85 immutable float nx
= scale
*stk
[sn
].x
;
86 immutable float ny
= scale
*stk
[sn
].y
;
87 if (stk
[sn
].opcode
== OpDraw
) {
88 immutable bool lastPoint
= (sn
+1 >= stk
.length || stk
[sn
+1].opcode
!= OpDraw
);
89 gb
.line(cast(int)(x
+ox
), cast(int)(y
-oy
), cast(int)(x
+nx
), cast(int)(y
-ny
), clr
, lastPoint
);
94 return cast(int)(scale
*wdt
[ch
]);
97 int drawText() (auto ref GfxBuf gb
, int x
, int y
, const(char)[] str, VColor clr
, in float scale
=1.0f) {
99 foreach (immutable ch
; str) {
100 int d
= drawChar(gb
, x
, y
, ch
, clr
, scale
);
108 void load(ST
) (auto ref ST st
) if (isReadableStream
!ST
) {
110 int dataSize
, charCount
, stkOfs
, dataOfs
;
113 st
.rawReadExact(sign
[0..4]);
114 if (sign
!= "PK\x08\x08") throw new Exception("invalid CHR signature");
115 // font type ("BGI ", "LCD ")
116 st
.rawReadExact(type
[0..4]);
118 btcount
= 8; // temp counter
120 ubyte b
= st
.readNum
!ubyte();
123 if (btcount
> 65535) throw new Exception("CHR description too long");
126 dataOfs
= st
.readNum
!ushort();
129 st
.rawReadExact(name
[0..4]);
132 dataSize
= st
.readNum
!ushort();
134 if (dataSize
< 2) throw new Exception("invalid CHR data size");
136 fver
= cast(ushort)(st
.readNum
!ubyte()<<8);
137 fver |
= st
.readNum
!ubyte();
138 dver
= cast(ushort)(st
.readNum
!ubyte()<<8);
139 dver |
= st
.readNum
!ubyte();
141 // skip other header bytes
142 if (dataOfs
< btcount
) throw new Exception("invalid CHR data offset");
143 while (btcount
< dataOfs
) { st
.readNum
!ubyte(); ++btcount
; }
146 //debug { import std.stdio; writefln("ofs=0x%08x", st.tell); }
147 if (st
.readNum
!ubyte() != '+') throw new Exception("invalid CHR data signature");
150 charCount
= st
.readNum
!ushort();
152 if (charCount
< 1 || charCount
> 255) throw new Exception("invalid CHR character count");
157 ffirstChar
= st
.readNum
!ubyte();
159 // offset to stroke data (from the start of this header)
160 stkOfs
= st
.readNum
!ushort();
166 fascent
= st
.readNum
!byte();
169 fbase
= st
.readNum
!byte();
172 fdescent
= st
.readNum
!byte();
174 // internal font name
175 st
.rawReadExact(sign
[0..4]);
180 // stroke offsets in stroke data
183 //debug { import std.stdio; writefln("stofs=0x%08x", st.tell); }
184 foreach (int cn
; ffirstChar
..ffirstChar
+charCount
) {
185 auto fs
= st
.readNum
!ushort();
187 if (fs
< 0 || fs
%2) throw new Exception("invalid CHR stroke offset");
188 if (cn
< 256) ffirstStroke
[cn
] = fs
/2;
190 //debug { import std.stdio; writefln("wdtofs=0x%08x", st.tell); }
192 foreach (int cn
; ffirstChar
..ffirstChar
+charCount
) {
193 auto w
= st
.readNum
!ubyte();
195 if (cn
< 256) wdt
[cn
] = w
;
197 // move to stroke data
198 if (btcount
> stkOfs
) throw new Exception("invalid CHR stroke data offset");
199 while (btcount
< stkOfs
) { st
.readNum
!ubyte(); ++btcount
; }
201 //debug { import std.stdio; writefln("sdofs=0x%08x", st.tell); }
202 if ((dataSize
-= btcount
) < 2) throw new Exception("invalid CHR no stroke data");
203 stk
.length
= dataSize
/2;
204 foreach (ref s
; stk
) {
210 x
= st
.readNum
!ubyte();
211 y
= st
.readNum
!ubyte();
213 op
= (x
>>7)|
((y
>>6)&0x02);
214 if ((x
&= 0x7f) > 63) x
-= 128;
215 if ((y
&= 0x7f) > 63) y
-= 128;
216 s
.opcode
= cast(ubyte)op
;
220 flastChar
= ffirstChar
+charCount
-1;
221 if (flastChar
> 255) flastChar
= 255;