1 module x11gfx
is aliced
;
3 import arsd
.simpledisplay
;
7 // ////////////////////////////////////////////////////////////////////////// //
8 // 0:b; 1:g; 2:r; 3: nothing
9 __gshared
int vbufW
= 256, vbufH
= 192;
10 __gshared
uint[] vbuf
;
11 __gshared
bool blit2x
= true;
12 enum BlitType
{ Normal
, BlackWhite
, Green
}
13 __gshared
int blitType
= BlitType
.Normal
;
14 __gshared Image vbimg
;
15 __gshared SimpleWindow vbwin
;
18 // ////////////////////////////////////////////////////////////////////////// //
19 void x11gfxDeinit () {
21 if (vbimg
!is null) delete vbimg
;
22 if (vbwin
!is null) { if (!vbwin
.closed
) vbwin
.close(); delete vbwin
; }
23 if (vbuf
!is null) delete vbuf
;
31 SimpleWindow
x11gfxInit (string title
) {
32 if (vbufW
< 1 || vbufH
< 1 || vbufW
> 4096 || vbufH
> 4096) assert(0, "invalid dimensions");
34 vbwin
= new SimpleWindow(vbufW
*(blit2x ?
2 : 1), vbufH
*(blit2x ?
2 : 1), title
, OpenGlOptions
.no
, Resizablity
.fixedSize
);
35 vbimg
= new Image(vbufW
*(blit2x ?
2 : 1), vbufH
*(blit2x ?
2 : 1));
41 if (vbwin
is null || vbwin
.closed
) return;
42 auto painter
= vbwin
.draw();
43 painter
.drawImage(Point(0, 0), vbimg
);
47 // ////////////////////////////////////////////////////////////////////////// //
48 final class X11Image
{
53 assert(w
> 0 && w
<= 4096);
54 assert(h
> 0 && h
<= 4096);
61 VColor
getPixel (int x
, int y
) const {
62 return (x
>= 0 && y
>= 0 && x
< width
&& y
< height ? data
[y
*width
+x
] : Transparent
);
65 void setPixel (int x
, int y
, VColor c
) {
66 if (x
>= 0 && y
>= 0 && x
< width
&& y
< height
) data
[y
*width
+x
] = c
;
69 void blitFast (int x
, int y
) const {
70 if (width
< 1 || height
< 1) return;
71 if (x
<= -width || y
<= -height
) return;
72 if (x
>= vbufW || y
>= vbufH
) return;
73 auto src
= cast(const(VColor
)*)data
.ptr
;
74 if (x
>= 0 && y
>= 0 && x
+width
< vbufW
&& y
+height
< vbufH
) {
75 auto d
= cast(uint*)vbuf
.ptr
;
77 foreach (int dy
; 0..height
) {
78 d
[0..width
] = src
[0..width
];
83 foreach (int dy
; 0..height
) {
84 foreach (int dx
; 0..width
) {
85 .setPixel(x
+dx
, y
+dy
, *src
++);
91 void blit (int x
, int y
) const {
92 if (width
< 1 || height
< 1) return;
93 if (x
<= -width || y
<= -height
) return;
94 if (x
>= vbufW || y
>= vbufH
) return;
95 auto src
= cast(const(VColor
)*)data
.ptr
;
96 foreach (int dy
; 0..height
) {
97 foreach (int dx
; 0..width
) {
98 putPixel(x
+dx
, y
+dy
, *src
++);
103 void blit2x (int x
, int y
) const {
104 if (width
< 1 || height
< 1) return;
105 if (x
<= -width || y
<= -height
) return;
106 if (x
>= vbufW || y
>= vbufH
) return;
107 auto src
= cast(const(VColor
)*)data
.ptr
;
108 foreach (immutable int dy
; 0..height
) {
109 foreach (immutable int dx
; 0..width
) {
110 putPixel(x
+dx
*2+0, y
+dy
*2+0, *src
);
111 putPixel(x
+dx
*2+1, y
+dy
*2+0, *src
);
112 putPixel(x
+dx
*2+0, y
+dy
*2+1, *src
);
113 putPixel(x
+dx
*2+1, y
+dy
*2+1, *src
);
119 private void blit2xImpl(string op
) (int x
, int y
) nothrow @trusted @nogc {
120 if (width
< 1 || height
< 1) return;
121 if (x
<= -width || y
<= -height
) return;
122 if (x
>= vbufW || y
>= vbufH
) return;
123 auto s
= cast(const(ubyte)*)data
.ptr
;
124 //auto d = cast(uint*)vscr2x;
125 foreach (immutable int dy
; 0..height
) {
126 foreach (immutable int dx
; 0..width
) {
127 static if (op
.length
) mixin(op
);
128 immutable uint c1
= ((((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff)|
(((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
129 putPixel(x
+dx
*2+0, y
+dy
*2+0, c0
);
130 putPixel(x
+dx
*2+1, y
+dy
*2+0, c0
);
131 putPixel(x
+dx
*2+0, y
+dy
*2+1, c1
);
132 putPixel(x
+dx
*2+1, y
+dy
*2+1, c1
);
138 alias blit2xTV
= blit2xImpl
!"immutable uint c0 = (cast(immutable(uint)*)s)[0];";
139 alias blit2xTVBW
= blit2xImpl
!"immutable ubyte i = cast(ubyte)((s[0]*28+s[1]*151+s[2]*77)/256); immutable uint c0 = (i<<16)|(i<<8)|i;";
140 alias blit2xTVGreen
= blit2xImpl
!"immutable ubyte i = cast(ubyte)((s[0]*28+s[1]*151+s[2]*77)/256); immutable uint c0 = i<<8;";
144 private void initVBuf () {
145 vbuf
.length
= vbufW
*vbufH
;
151 void blit2xImpl(string op
, bool scanlines
=true) (Image img
) {
152 static if (UsingSimpledisplayX11
) {
153 auto s
= cast(const(ubyte)*)vbuf
.ptr
;
154 immutable iw
= img
.width
;
155 auto dd = cast(uint*)img
.getDataPointer
;
156 foreach (immutable int dy
; 0..vbufH
) {
157 if (dy
*2+1 >= img
.height
) return;
158 auto d
= dd+iw
*(dy
*2);
159 foreach (immutable int dx
; 0..vbufW
) {
161 static if (op
.length
) mixin(op
);
162 static if (scanlines
) {
163 immutable uint c1
= ((((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff)|
(((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
168 d
[iw
+0] = d
[iw
+1] = c1
;
176 immutable bpp
= img
.bytesPerPixel();
177 immutable rofs
= img
.redByteOffset
;
178 immutable gofs
= img
.greenByteOffset
;
179 immutable bofs
= img
.blueByteOffset
;
180 immutable nlo
= img
.adjustmentForNextLine
;
181 auto s
= cast(const(ubyte)*)vbuf
.ptr
;
182 immutable iw
= img
.width
;
183 auto dd = cast(ubyte*)img
.getDataPointer
;
184 foreach (immutable int dy
; 0..vbufH
) {
185 if (dy
*2+1 >= img
.height
) return;
186 auto d
= dd+img
.offsetForPixel(0, dy
*2);
187 foreach (immutable int dx
; 0..vbufW
) {
189 static if (op
.length
) mixin(op
);
190 static if (scanlines
) {
191 immutable uint c1
= ((((c0
&0x00ff00ff)*6)>>3)&0x00ff00ff)|
(((c0
&0x0000ff00)*6)>>3)&0x0000ff00;
195 d
[bofs
] = d
[bofs
+bpp
] = c0
&0xff;
196 d
[gofs
] = d
[gofs
+bpp
] = (c0
>>8)&0xff;
197 d
[rofs
] = d
[rofs
+bpp
] = (c0
>>16)&0xff;
198 d
[bofs
+nlo
] = d
[bofs
+nlo
+bpp
] = c0
&0xff;
199 d
[gofs
+nlo
] = d
[gofs
+nlo
+bpp
] = (c0
>>8)&0xff;
200 d
[rofs
+nlo
] = d
[rofs
+nlo
+bpp
] = (c0
>>16)&0xff;
209 alias blit2xTV
= blit2xImpl
!"immutable uint c0 = (cast(immutable(uint)*)s)[0];";
210 alias blit2xTVBW
= blit2xImpl
!"immutable ubyte i = cast(ubyte)((s[0]*28+s[1]*151+s[2]*77)/256); immutable uint c0 = (i<<16)|(i<<8)|i;";
211 alias blit2xTVGreen
= blit2xImpl
!"immutable ubyte i = cast(ubyte)((s[0]*28+s[1]*151+s[2]*77)/256); immutable uint c0 = i<<8;";
215 void realizeVBuf (/*Image img*/) {
216 if (vbimg
is null) return;
220 auto dp = cast(uint*)img.getDataPointer;
221 import core.stdc.string : memcpy;
222 memcpy(dp, sp, vbufW*vbufH*4);
225 if (img
.width
< vbufW
*2 || img
.height
< vbufH
*2) return;
227 case BlitType
.BlackWhite
: blit2xTVBW(img
); break;
228 case BlitType
.Green
: blit2xTVGreen(img
); break;
229 default: blit2xTV(img
); break;
232 if (img
.width
< vbufW || img
.height
< vbufH
) return;
233 static if (UsingSimpledisplayX11
) {
234 auto dp
= cast(uint*)img
.getDataPointer
;
235 dp
[0..vbufW
*vbufH
] = vbuf
.ptr
[0..vbufW
*vbufH
];
238 auto sp
= cast(ubyte*)vbuf
.ptr
;
239 auto dp
= cast(ubyte*)img
.getDataPointer
;
240 immutable bpp
= img
.bytesPerPixel();
241 immutable rofs
= img
.redByteOffset
;
242 immutable gofs
= img
.greenByteOffset
;
243 immutable bofs
= img
.blueByteOffset
;
244 foreach (immutable y
; 0..vbufH
) {
245 auto d
= dp
+img
.offsetForTopLeftPixel
;
246 foreach (immutable x
; 0..vbufW
) {
259 // ////////////////////////////////////////////////////////////////////////// //
260 ubyte clampToByte(T
) (T n
) @safe pure nothrow @nogc
261 if (__traits(isIntegral
, T
) && (T
.sizeof
== 2 || T
.sizeof
== 4))
263 static if (__VERSION__
> 2067) pragma(inline
, true);
264 n
&= -cast(int)(n
>= 0);
265 return cast(ubyte)(n|
((255-cast(int)n
)>>31));
268 ubyte clampToByte(T
) (T n
) @safe pure nothrow @nogc
269 if (__traits(isIntegral
, T
) && T
.sizeof
== 1)
271 static if (__VERSION__
> 2067) pragma(inline
, true);
276 // ////////////////////////////////////////////////////////////////////////// //
279 /// vlRGBA struct to ease color components extraction/replacing
280 align(1) struct vlRGBA
{
284 static assert(vlRGBA
.sizeof
== VColor
.sizeof
);
288 vlAMask
= 0xff000000u
,
289 vlRMask
= 0x00ff0000u
,
290 vlGMask
= 0x0000ff00u
,
291 vlBMask
= 0x000000ffu
302 enum VColor Transparent
= vlAMask
; /// completely transparent pixel color
305 bool isTransparent(T
: VColor
) (T col
) @safe pure nothrow @nogc {
306 static if (__VERSION__
> 2067) pragma(inline
, true);
307 return ((col
&vlAMask
) == vlAMask
);
310 bool isOpaque(T
: VColor
) (T col
) @safe pure nothrow @nogc {
311 static if (__VERSION__
> 2067) pragma(inline
, true);
312 return ((col
&vlAMask
) == 0);
316 VColor
rgbcol(TR
, TG
, TB
, TA
=ubyte) (TR r
, TG g
, TB b
, TA a
=0) @safe pure nothrow @nogc
317 if (__traits(isIntegral
, TR
) && __traits(isIntegral
, TG
) && __traits(isIntegral
, TB
) && __traits(isIntegral
, TA
)) {
318 static if (__VERSION__
> 2067) pragma(inline
, true);
320 (clampToByte(a
)<<vlAShift
)|
321 (clampToByte(r
)<<vlRShift
)|
322 (clampToByte(g
)<<vlGShift
)|
323 (clampToByte(b
)<<vlBShift
);
326 alias rgbacol
= rgbcol
;
329 // generate some templates
330 private enum genRGBGetSet(string cname
) =
331 "ubyte rgb"~cname
~"() (VColor clr) @safe pure nothrow @nogc {\n"~
332 " static if (__VERSION__ > 2067) pragma(inline, true);\n"~
333 " return ((clr>>vl"~cname
[0]~"Shift)&0xff);\n"~
335 "VColor rgbSet"~cname
~"(T) (VColor clr, T v) @safe pure nothrow @nogc if (__traits(isIntegral, T)) {\n"~
336 " static if (__VERSION__ > 2067) pragma(inline, true);\n"~
337 " return (clr&~vl"~cname
[0]~"Mask)|(clampToByte(v)<<vl"~cname
[0]~"Shift);\n"~
340 mixin(genRGBGetSet
!"Alpha");
341 mixin(genRGBGetSet
!"Red");
342 mixin(genRGBGetSet
!"Green");
343 mixin(genRGBGetSet
!"Blue");
346 void putPixel(TX
, TY
) (TX x
, TY y
, VColor col
) @trusted
347 if (__traits(isIntegral
, TX
) && __traits(isIntegral
, TY
))
349 static if (__VERSION__
> 2067) pragma(inline
, true);
350 immutable long xx
= cast(long)x
;
351 immutable long yy
= cast(long)y
;
352 if ((col
&vlAMask
) != vlAMask
&& xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
353 uint* da = vbuf
.ptr
+yy
*vbufW
+xx
;
355 immutable uint a
= 256-(col
>>24); // to not loose bits
356 immutable uint dc
= (*da)&0xffffff;
357 immutable uint srb
= (col
&0xff00ff);
358 immutable uint sg
= (col
&0x00ff00);
359 immutable uint drb
= (dc
&0xff00ff);
360 immutable uint dg
= (dc
&0x00ff00);
361 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
362 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
370 void setPixel(TX
, TY
) (TX x
, TY y
, VColor col
) @trusted
371 if (__traits(isIntegral
, TX
) && __traits(isIntegral
, TY
))
373 static if (__VERSION__
> 2067) pragma(inline
, true);
374 immutable long xx
= cast(long)x
;
375 immutable long yy
= cast(long)y
;
376 if (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
377 uint* da = vbuf
.ptr
+yy
*vbufW
+xx
;
383 void drawLine(bool lastPoint
=true) (int x0
, int y0
, int x1
, int y1
, immutable VColor col
) {
384 enum swap(string a
, string b
) = "{int tmp_="~a
~";"~a
~"="~b
~";"~b
~"=tmp_;}";
386 if ((col
&vlAMask
) == vlAMask
) return;
388 if (x0
== x1
&& y0
== y1
) {
389 static if (lastPoint
) putPixel(x0
, y0
, col
);
394 int wx0
= 0, wy0
= 0, wx1
= vbufW
-1, wy1
= vbufH
-1;
396 int stx
, sty
; // "steps" for x and y axes
397 int dsx
, dsy
; // "lengthes" for x and y axes
398 int dx2
, dy2
; // "double lengthes" for x and y axes
399 int xd
, yd
; // current coord
400 int e
; // "error" (as in bresenham algo)
406 // from left to right
407 if (x0
> wx1 || x1
< wx0
) return; // out of screen
408 stx
= 1; // going right
410 // from right to left
411 if (x1
> wx1 || x0
< wx0
) return; // out of screen
412 stx
= -1; // going left
417 mixin(swap
!("wx0", "wx1"));
421 // from top to bottom
422 if (y0
> wy1 || y1
< wy0
) return; // out of screen
423 sty
= 1; // going down
425 // from bottom to top
426 if (y1
> wy1 || y0
< wy0
) return; // out of screen
427 sty
= -1; // going up
432 mixin(swap
!("wy0", "wy1"));
439 mixin(swap
!("x0", "y0"));
440 mixin(swap
!("x1", "y1"));
441 mixin(swap
!("dsx", "dsy"));
442 mixin(swap
!("wx0", "wy0"));
443 mixin(swap
!("wx1", "wy1"));
444 mixin(swap
!("stx", "sty"));
458 int temp
= dx2
*(wy0
-y0
)-dsx
;
461 if (xd
> wx1
) return; // x is moved out of clipping rect, nothing to do
465 if (rem
> 0) { ++xd
; e
+= dy2
; }
469 if (!xfixed
&& x0
< wx0
) {
471 int temp
= dy2
*(wx0
-x0
);
474 if (yd
> wy1 || yd
== wy1
&& rem
>= dsx
) return;
477 if (rem
>= dsx
) { ++yd
; e
-= dx2
; }
481 int temp
= dx2
*(wy1
-y0
)+dsx
;
484 if (rem
== 0) --term
;
486 if (term
> wx1
) term
= wx1
; // clip at right
487 static if (lastPoint
) {
491 if (term
== xd
) return; // this is the only point, get out of here
493 if (sty
== -1) yd
= -yd
;
494 if (stx
== -1) { xd
= -xd
; term
= -term
; }
496 // draw it; `putPixel()` can omit checks
498 // inlined `putPixel(*d0, *d1, col)`
499 // this can be made even faster by precalculating `da` and making
500 // separate code branches for mixing and non-mixing drawing, but...
502 uint* da = vbuf
.ptr
+(*d1
)*vbufW
+(*d0
);
504 immutable uint a
= 256-(col
>>24); // to not loose bits
505 immutable uint dc
= (*da)&0xffffff;
506 immutable uint srb
= (col
&0xff00ff);
507 immutable uint sg
= (col
&0x00ff00);
508 immutable uint drb
= (dc
&0xff00ff);
509 immutable uint dg
= (dc
&0x00ff00);
510 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
511 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
516 // done drawing, move coords
528 // //////////////////////////////////////////////////////////////////////// //
530 * Draw character onto virtual screen in KOI8 encoding.
538 * col = foreground color
539 * bkcol = background color
544 void drawCharWdt (int x
, int y
, int wdt
, int shift
, char ch
, VColor col
, VColor bkcol
=Transparent
) @trusted {
546 if (wdt
< 1 || shift
>= 8) return;
547 if (col
== Transparent
&& bkcol
== Transparent
) return;
548 if (wdt
> 8) wdt
= 8;
549 if (shift
< 0) shift
= 0;
550 foreach (immutable int dy
; 0..8) {
551 ubyte b
= cast(ubyte)(vlFont6
[pos
++]<<shift
);
552 foreach (immutable int dx
; 0..wdt
) {
553 VColor c
= (b
&0x80 ? col
: bkcol
);
554 if (!isTransparent(c
)) putPixel(x
+dx
, y
+dy
, c
);
566 OutLU
= 0x10, // left-up
567 OutRU
= 0x20, // right-up
568 OutLD
= 0x40, // left-down
569 OutRD
= 0x80, // right-down
574 * Draw outlined character onto virtual screen in KOI8 encoding.
582 * col = foreground color
583 * outcol = outline color
584 * ot = outline type, OutXXX, ored
589 void drawCharWdtOut (int x
, int y
, int wdt
, int shift
, char ch
, VColor col
, VColor outcol
=Transparent
, ubyte ot
=0) @trusted {
590 if (col
== Transparent
&& outcol
== Transparent
) return;
591 if (ot
== 0 || outcol
== Transparent
) {
592 // no outline? simple draw
593 drawCharWdt(x
, y
, wdt
, shift
, ch
, col
, Transparent
);
597 if (wdt
< 1 || shift
>= 8) return;
598 if (wdt
> 8) wdt
= 8;
599 if (shift
< 0) shift
= 0;
600 ubyte[8+2][8+2] bmp
= 0; // char bitmap; 0: empty; 1: char; 2: outline
601 foreach (immutable dy
; 1..9) {
602 ubyte b
= cast(ubyte)(vlFont6
[pos
++]<<shift
);
603 foreach (immutable dx
; 1..wdt
+1) {
608 if ((ot
&OutUp
) && bmp
[dy
-1][dx
] == 0) bmp
[dy
-1][dx
] = 2;
609 if ((ot
&OutDown
) && bmp
[dy
+1][dx
] == 0) bmp
[dy
+1][dx
] = 2;
610 if ((ot
&OutLeft
) && bmp
[dy
][dx
-1] == 0) bmp
[dy
][dx
-1] = 2;
611 if ((ot
&OutRight
) && bmp
[dy
][dx
+1] == 0) bmp
[dy
][dx
+1] = 2;
612 if ((ot
&OutLU
) && bmp
[dy
-1][dx
-1] == 0) bmp
[dy
-1][dx
-1] = 2;
613 if ((ot
&OutRU
) && bmp
[dy
-1][dx
+1] == 0) bmp
[dy
-1][dx
+1] = 2;
614 if ((ot
&OutLD
) && bmp
[dy
+1][dx
-1] == 0) bmp
[dy
+1][dx
-1] = 2;
615 if ((ot
&OutRD
) && bmp
[dy
+1][dx
+1] == 0) bmp
[dy
+1][dx
+1] = 2;
623 foreach (immutable int dy
; 0..10) {
624 foreach (immutable int dx
; 0..10) {
625 if (auto t
= bmp
[dy
][dx
]) putPixel(x
+dx
, y
+dy
, (t
== 1 ? col
: outcol
));
631 * Draw 6x8 character onto virtual screen in KOI8 encoding.
637 * col = foreground color
638 * bkcol = background color
643 void drawChar (int x
, int y
, char ch
, VColor col
, VColor bkcol
=Transparent
) @trusted {
644 drawCharWdt(x
, y
, 6, 0, ch
, col
, bkcol
);
647 void drawCharOut (int x
, int y
, char ch
, VColor col
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
648 drawCharWdtOut(x
, y
, 6, 0, ch
, col
, outcol
, ot
);
651 void drawStr (int x
, int y
, string
str, VColor col
, VColor bkcol
=Transparent
) @trusted {
652 foreach (immutable char ch
; str) {
653 drawChar(x
, y
, ch
, col
, bkcol
);
658 void drawStrOut (int x
, int y
, string
str, VColor col
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
659 foreach (immutable char ch
; str) {
660 drawCharOut(x
, y
, ch
, col
, outcol
, ot
);
665 static int charWidthProp (char ch
) @trusted pure { return (vlFontPropWidth
[ch
]&0x0f); }
667 int strWidthProp (string
str) @trusted pure {
669 foreach (immutable char ch
; str) wdt
+= (vlFontPropWidth
[ch
]&0x0f)+1;
670 if (wdt
> 0) --wdt
; // don't count last empty pixel
674 int drawCharProp (int x
, int y
, char ch
, VColor col
, VColor bkcol
=Transparent
) @trusted {
675 immutable int wdt
= (vlFontPropWidth
[ch
]&0x0f);
676 drawCharWdt(x
, y
, wdt
, vlFontPropWidth
[ch
]>>4, ch
, col
, bkcol
);
680 int drawCharPropOut (int x
, int y
, char ch
, VColor col
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
681 immutable int wdt
= (vlFontPropWidth
[ch
]&0x0f);
682 drawCharWdtOut(x
, y
, wdt
, vlFontPropWidth
[ch
]>>4, ch
, col
, outcol
, ot
);
686 int drawStrProp (int x
, int y
, string
str, VColor col
, VColor bkcol
=Transparent
) @trusted {
689 foreach (immutable char ch
; str) {
691 if (!isTransparent(bkcol
)) foreach (int dy
; 0..8) putPixel(x
, y
+dy
, bkcol
);
695 x
+= drawCharProp(x
, y
, ch
, col
, bkcol
);
700 int drawStrPropOut (int x
, int y
, string
str, VColor col
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
702 foreach (immutable char ch
; str) {
703 x
+= drawCharPropOut(x
, y
, ch
, col
, outcol
, ot
)+1;
705 if (x
> sx
) --x
; // don't count last empty pixel
709 // ////////////////////////////////////////////////////////////////////////// //
710 void clear (VColor col
) @trusted {
711 vbuf
.ptr
[0..vbufW
*vbufH
] = col
;
715 // ////////////////////////////////////////////////////////////////////////// //
716 public immutable ubyte[256*8] vlFont6
= [
3025 // bits 4..7: lshift
3026 public immutable ubyte[256] vlFontPropWidth
= () {
3028 foreach (immutable cnum
; 0..256) {
3029 import core
.bitop
: bsf, bsr;
3031 (cnum
>= 32 && cnum
<= 127) ||
3032 (cnum
>= 143 && cnum
<= 144) ||
3033 (cnum
>= 166 && cnum
<= 167) ||
3034 (cnum
>= 192 && cnum
<= 255);
3038 foreach (immutable dy
; 0..8) {
3039 immutable b
= vlFont6
[cnum
*8+dy
];
3041 immutable mn
= 7-bsr(b
);
3042 if (mn
< shift
) shift
= mn
;
3047 foreach (immutable dy
; 0..8) {
3048 immutable b
= (vlFont6
[cnum
*8+dy
]<<shift
);
3049 immutable cwdt
= (b ?
8-bsf(b
) : 0);
3050 if (cwdt
> wdt
) wdt
= cast(ubyte)cwdt
;
3053 case 0: wdt
= 8; break; // 8px space
3054 case 32: wdt
= 5; break; // 5px space
3055 case 17: .. case 27: wdt
= 8; break; // single frames
3056 case 48: .. case 57: wdt
= 5; break; // digits are monospaced
3057 case 127: .. case 142: wdt
= 8; break; // filled frames
3058 case 145: .. case 151: wdt
= 8; break; // filled frames
3059 case 155: .. case 159: wdt
= 8; break; // filled frames
3062 res
[cnum
] = (wdt
&0x0f)|
((shift
<<4)&0xf0);