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/>.
18 module iv
.glkgi
/*is aliced*/;
22 import std
.concurrency
;
24 public import arsd
.simpledisplay
;
25 //public import arsd.color;
26 //public import arsd.image;
29 public import iv
.cmdcongl
;
32 //version=glkgi_rgba; // default, has priority
35 version(BigEndian
) static assert(0, "sorry, big-endian platforms aren't supported yet");
38 public enum KGIRGBA
= true;
39 } else version(glkgi_bgra
) {
40 public enum KGIRGBA
= false;
42 public enum KGIRGBA
= true;
46 // ////////////////////////////////////////////////////////////////////////// //
47 public enum kgiMaxCurW
= 64;
48 public enum kgiMaxCurH
= 64;
51 // ////////////////////////////////////////////////////////////////////////// //
52 // 0:b; 1:g; 2:r; 3: nothing
53 private __gshared
int vbufW
= 800, vbufH
= 600;
54 __gshared
uint* vbuf
; // see KGIRGBA
55 __gshared
uint* vbufsaved
; // saved before updating texture
56 private __gshared
uint* vcurbuf
;
57 private __gshared
bool blit2x
= false;
58 //private enum BlitType { normal, bw, green, red }
59 //private __gshared BlitType blitType = BlitType.normal;
60 private __gshared
bool scanlines
= false;
61 private __gshared SimpleWindow vbwin
;
62 private __gshared
uint vbTexId
= 0;
63 private __gshared
uint vbCurTexId
= 0;
64 private __gshared
uint sdrScanlineId
= 0;
65 private __gshared
int shaderVersionOk
= -1; // <0: not checked; 0: fail; >0: ok
66 private __gshared string kgiTitle
= "KGI Graphics";
67 private __gshared
uint vupcounter
= 0;
68 private __gshared
uint vupcounterlast
= 0;
69 private shared bool updateTexture
= true;
70 private shared bool updateCurTexture
= true;
71 private __gshared
uint fps
= 35; // average FPS
72 private __gshared
bool showShaderWarnings
= false;
74 private __gshared
bool oldogl
= false;
76 private __gshared
int mcurX
= 0, mcurY
= 0;
77 private __gshared
int mhotX
= 0, mhotY
= 0;
78 private __gshared
int mcurHidden
= 1;
80 private shared bool vWantMotionEvents
= false;
81 private shared bool vWantCharEvents
= false;
84 public @property bool kgiMotionEvents () nothrow @trusted @nogc { pragma(inline
, true); return atomicLoad(vWantMotionEvents
); } ///
85 public @property bool kgiCharEvents () nothrow @trusted @nogc { pragma(inline
, true); return atomicLoad(vWantCharEvents
); } ///
87 public @property void kgiMotionEvents (bool v
) nothrow @trusted @nogc { pragma(inline
, true); atomicStore(vWantMotionEvents
, v
); } ///
88 public @property void kgiCharEvents (bool v
) nothrow @trusted @nogc { pragma(inline
, true); atomicStore(vWantCharEvents
, v
); } ///
90 public @property int kgiWidth () nothrow @trusted @nogc { pragma(inline
, true); return vbufW
; }
91 public @property int kgiHeight () nothrow @trusted @nogc { pragma(inline
, true); return vbufH
; }
94 //FIXME! turn this to proper setter
95 public __gshared
bool delegate () onKGICloseRequest
;
98 shared static this () {
99 conRegVar
!blit2x("v_scale2x", "video window scale");
100 conRegVar
!scanlines("v_scanlines", "emulate old CRT scanline effect");
101 conRegVar
!vbufW(64, 4096, "v_width", "video window width");
102 conRegVar
!vbufH(64, 4096, "v_height", "video window height");
103 conRegVar
!fps(1, 60, "v_fps", "video update rate");
104 conRegVar
!kgiTitle("v_title", "video window title");
105 conRegVar
!showShaderWarnings("v_shader_warnings", "show warnings from shader compilation");
106 conRegVar
!oldogl("v_legacygl", "set to true to use legacy OpenGL");
110 private void setUpdateTextureFlag () {
111 pragma(inline
, true);
115 if (vupcounterlast
!= c
) {
117 vbufsaved
[0..vbufW
*vbufH
] = vbuf
[0..vbufW
*vbufH
];
119 atomicStore(updateTexture
, true);
125 public void kgiHideCursor () {
129 scope(exit
) consoleUnlock();
131 csc
= (vbwin
!is null && (mcurHidden
== -1 || mcurHidden
== 1));
133 if (csc
) vbwin
.showCursor();
138 public void kgiShowCursor () {
142 scope(exit
) consoleUnlock();
144 csc
= (vbwin
!is null && mcurHidden
== 0);
146 if (csc
) vbwin
.hideCursor();
151 public void kgiSetCursor (int wdt
, int hgt
, const(VColor
)[] img
, int hotx
=0, int hoty
=0) nothrow @trusted @nogc {
153 scope(exit
) consoleUnlock();
156 if (vcurbuf
is null) return;
157 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
158 if (wdt
< 1 || hgt
< 1) return;
159 foreach (immutable dy
; 0..64) {
160 if (dy
>= hgt
) break;
161 foreach (immutable dx
; 0..64) {
162 if (dx
>= wdt
) break;
164 if (sp
>= img
.length
) break;
165 vcurbuf
[dy
*kgiMaxCurW
+dx
] = img
.ptr
[sp
];
168 atomicStore(updateCurTexture
, true);
172 private void unpackDefaultCursor () nothrow @trusted @nogc {
175 if (vcurbuf
is null) return;
176 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
177 foreach (immutable dy
; 0..defaultCurHeight
) {
178 foreach (immutable dx
; 0..defaultCurWidth
) {
179 uint sp
= dy
*defaultCurWidth
+dx
;
180 vcurbuf
[dy
*kgiMaxCurW
+dx
] = defaultCurPal
.ptr
[defaultCurImg
.ptr
[sp
]];
187 public void kgiSetDefaultCursor () nothrow @trusted @nogc {
189 scope(exit
) consoleUnlock();
190 unpackDefaultCursor();
191 atomicStore(updateCurTexture
, true);
195 public void kgiSetBlankCursor () nothrow @trusted @nogc {
197 scope(exit
) consoleUnlock();
199 if (vcurbuf
is null) return;
200 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
201 atomicStore(updateCurTexture
, true);
205 // ////////////////////////////////////////////////////////////////////////// //
207 public struct KGIEvent
{
208 enum Type
{ None
, Key
, Mouse
, Char
, Close
}
209 Type type
= Type
.None
;
215 static createClose () pure nothrow @trusted @nogc {
217 ev
.type
= KGIEvent
.Type
.Close
;
220 @property const pure nothrow @trusted @nogc:
221 bool isMouse () { pragma(inline
, true); return (type
== Type
.Mouse
); }
222 bool isKey () { pragma(inline
, true); return (type
== Type
.Key
); }
223 bool isChar () { pragma(inline
, true); return (type
== Type
.Char
); }
224 bool isNone () { pragma(inline
, true); return (type
== Type
.None
); }
225 bool isClose () { pragma(inline
, true); return (type
== Type
.Close
); }
229 private __gshared KGIEvent
[] evbuf
;
230 private __gshared
uint evbufused
;
234 public bool kgiHasEvent () {
236 scope(exit
) consoleUnlock();
237 version(LDC
) {} else atomicFence();
238 if (vupcounter
) setUpdateTextureFlag(); // just in case
239 return (evbufused
> 0 || vbwin
is null); // no vbwin --> always has Quit
244 public KGIEvent
kgiPeekEvent () {
246 scope(exit
) consoleUnlock();
247 version(LDC
) {} else atomicFence();
248 if (!atomicLoad(kgiThreadStarted
)) return KGIEvent
.createClose();
249 if (vupcounter
) setUpdateTextureFlag(); // just in case
250 if (evbufused
> 0) return evbuf
[0];
251 if (vbwin
is null) return KGIEvent(KGIEvent
.Type
.Close
);
257 public KGIEvent
kgiGetEvent () {
260 version(LDC
) {} else atomicFence();
261 if (vupcounter
) setUpdateTextureFlag(); // just in case
265 scope(exit
) consoleUnlock();
266 if (!atomicLoad(kgiThreadStarted
)) return KGIEvent
.createClose();
270 import core
.stdc
.string
: memmove
;
271 memmove(evbuf
.ptr
, evbuf
.ptr
+1, KGIEvent
.sizeof
*(evbufused
-1));
274 evbuf
[evbufused
].type
= KGIEvent
.Type
.None
;
276 } else if (vbwin
is null) {
277 return KGIEvent(KGIEvent
.Type
.Close
);
280 Thread
.sleep(10.msecs
); //FIXME
285 private void pushEventIntr (ref KGIEvent ev
) {
286 if (evbufused
>= evbuf
.length
) evbuf
.length
+= 256;
287 evbuf
[evbufused
++] = ev
;
292 public void kgiPushEvent (KeyEvent e
) {
294 ev
.type
= KGIEvent
.Type
.Key
;
297 scope(exit
) consoleUnlock();
302 public void kgiPushEvent (MouseEvent e
) {
304 ev
.type
= KGIEvent
.Type
.Mouse
;
307 scope(exit
) consoleUnlock();
312 public void kgiPushEvent (dchar ch
) {
314 ev
.type
= KGIEvent
.Type
.Char
;
317 scope(exit
) consoleUnlock();
322 public void kgiPushCloseEvent(bool clearQueue
=true) () {
324 ev
.type
= KGIEvent
.Type
.Close
;
326 scope(exit
) consoleUnlock();
327 static if (clearQueue
) evbufused
= 0;
332 /// remove all keypresses from input queue
333 public void kgiKeyFlush () {
334 uint sidx
= 0, didx
= 0;
336 scope(exit
) consoleUnlock();
337 if (!atomicLoad(kgiThreadStarted
)) return;
338 while (sidx
< evbufused
) {
339 if (!evbuf
[sidx
].isKey
) {
340 if (sidx
!= didx
) evbuf
[didx
] = evbuf
[sidx
];
349 /// wait for keypress (and eat it)
350 public KGIEvent
kgiWaitKey () {
352 auto ev
= kgiGetEvent();
355 scope(exit
) consoleUnlock();
360 if (!ev
.isKey
) continue;
361 if (!ev
.k
.pressed
) continue;
367 /// flush drawing buffer (copy it to actual screen)
368 public void kgiFlush () {
369 setUpdateTextureFlag();
370 while (atomicLoad(updateTexture
)) {
373 if (!atomicLoad(kgiThreadStarted
)) return;
374 Thread
.sleep(1.msecs
);
379 // ////////////////////////////////////////////////////////////////////////// //
381 public void kgiDeinit () {
386 private void kgiThread (Tid starterTid
) {
388 vbwin
= new SimpleWindow(vbufW
*(blit2x ?
2 : 1), vbufH
*(blit2x ?
2 : 1), kgiTitle
, OpenGlOptions
.yes
, Resizability
.fixedSize
);
389 if (mcurHidden
== 0) vbwin
.hideCursor();
391 static if (is(typeof(openGLContextFallbackActivated
))) {
392 if (openGLContextFallbackActivated
) oldogl
= true;
395 vbwin
.redrawOpenGlScene
= delegate () {
403 vbwin
.closeQuery
= delegate () {
404 if (onKGICloseRequest
!is null) try { if (!onKGICloseRequest()) return; } catch (Throwable e
) {}
409 vbwin
.visibleForTheFirstTime
= delegate () {
410 vbwin
.setAsCurrentOpenGlContext();
413 import core.stdc.stdio;
414 printf("GL version: %s\n", glGetString(GL_VERSION));
416 glGetIntegerv(GL_MAJOR_VERSION, &h);
417 glGetIntegerv(GL_MINOR_VERSION, &l);
418 printf("version: %d.%d\n", h, l);
419 printf("shader version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
421 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &svcount);
423 printf("%d shader versions supported:\n", svcount);
424 foreach (GLuint n; 0..svcount) printf(" %d: %s\n", n, glGetStringi(GL_SHADING_LANGUAGE_VERSION, n));
428 glGetIntegerv(GL_NUM_EXTENSIONS, &ecount);
430 printf("%d extensions supported:\n", ecount);
431 foreach (GLuint n; 0..ecount) printf(" %d: %s\n", n, glGetStringi(GL_EXTENSIONS, n));
437 glconInit(vbufW
, vbufH
, (blit2x ?
2 : 1));
438 glgfxUpdateTexture();
439 vbwin
.redrawOpenGlSceneNow();
441 send(starterTid
, 42);
444 bool receiveMessages () {
447 import core
.time
: Duration
;
448 auto got
= receiveTimeout(
449 Duration
.zero
, // don't wait
450 (OwnerTerminated e
) {
451 //conwriteln("OWNER IS TERMINATED!");
455 conwriteln("WARNING: unknown thread message received and ignored: ", v
.toString
);
458 if (!got
) break; // no more messages
463 bool processConsoleCommands () {
465 scope(exit
) consoleUnlock();
466 auto ccwasempty
= conQueueEmpty();
468 return (!ccwasempty
&& conQueueEmpty());
471 bool lastConVisible
= isConsoleVisible
;
473 //FIXME: FPS time calculations are totally broken
475 uint rfps
= (fps
< 0 ?
1 : fps
> 120 ?
120 : fps
);
476 uint msfull
= 1000/fps
;
477 auto lastFrameTime
= MonoTime
.currTime
;
478 auto lastCursorTime
= MonoTime
.currTime
;
481 // windoze eats shit! if we won't awake event loop here, it will fuck itself.
482 import core
.sys
.windows
.winuser
;
483 PostMessage(null, WM_USER
, 0, 0);
488 //version(Windows) { {import core.stdc.stdio : printf; printf("xxx\n"); } }
489 if (vbwin
.closed
) return;
490 if (isQuitRequested
) { kgiPushCloseEvent(); vbwin
.close(); return; }
491 if (receiveMessages()) { kgiPushCloseEvent(); vbwin
.close(); return; }
492 auto conexeced
= processConsoleCommands();
493 bool convis
= isConsoleVisible
;
494 if (lastConVisible
!= convis || conexeced
) {
495 lastConVisible
= isConsoleVisible
;
496 setUpdateTextureFlag();
498 scope(exit
) consoleUnlock();
499 if (evbufused
== 0) {
504 bool newFrame
= false;
505 auto ctt
= MonoTime
.currTime
;
506 if (lastConVisible
!= convis || conexeced
) {
509 // visible console should be updated at least 35 times per second
510 newFrame
= ((ctt
-lastFrameTime
).total
!"msecs" >= 28);
513 if ((ctt
-lastFrameTime
).total
!"msecs" >= msfull
) newFrame
= true;
515 //if (newFrame) atomicStore(updateTexture, true);
516 if (newFrame ||
atomicLoad(updateTexture
)) {
518 lastCursorTime
= ctt
;
519 glgfxUpdateTexture();
520 //version(Windows) { {import core.stdc.stdio : printf; printf("000\n"); } }
521 vbwin
.redrawOpenGlSceneNow();
522 } else if (mcurHidden
== 0) {
523 // ~60 FPS for mouse cursor
524 if ((ctt
-lastCursorTime
).total
!"msecs" >= 16) {
525 lastCursorTime
= ctt
;
526 glgfxUpdateCurTexture();
527 //version(Windows) { {import core.stdc.stdio : printf; printf("001\n"); } }
528 vbwin
.redrawOpenGlSceneNow();
532 delegate (KeyEvent event
) {
533 if (vbwin
.closed
) return;
534 if (isQuitRequested
) { kgiPushCloseEvent(); vbwin
.close(); return; }
535 if (glconKeyEvent(event
)) return;
536 //if (event.pressed && event.key == Key.Escape) { concmd("quit"); return; }
539 delegate (MouseEvent event
) {
540 if (vbwin
.closed
) return;
541 mcurX
= event
.x
/(blit2x ?
2 : 1);
542 mcurY
= event
.y
/(blit2x ?
2 : 1);
543 if (event
.type
== MouseEventType
.motion
&& !kgiMotionEvents
) return;
544 if (blit2x
) { event
.x
/= 2; event
.y
/= 2; }
547 delegate (dchar ch
) {
548 if (vbwin
.closed
) return;
549 if (glconCharEvent(ch
)) return;
550 if (ch
== '`') concmd("r_console tan");
551 if (!kgiCharEvents
) return;
555 } catch (Throwable e
) {
556 // here, we are dead and fucked (the exact order doesn't matter)
557 import core
.stdc
.stdlib
: abort
;
558 import core
.stdc
.stdio
: fprintf
, stderr
;
559 import core
.memory
: GC
;
561 GC
.disable(); // yeah
562 thread_suspendAll(); // stop right here, you criminal scum!
563 auto s
= e
.toString();
564 fprintf(stderr
, "\n=== FATAL ===\n%.*s\n", cast(uint)s
.length
, s
.ptr
);
565 abort(); // die, you bitch!
571 import core.stdc.stdlib : exit;
576 atomicStore(kgiThreadStarted
, false);
580 // ////////////////////////////////////////////////////////////////////////// //
581 private __gshared Tid kgiTid
;
582 private shared bool kgiThreadStarted
= false;
585 private void startKGIThread () {
586 //if (!cas(&kgiThreadStarted, false, true)) assert(0, "render thread already started!");
587 kgiTid
= spawn(&kgiThread
, thisTid
);
588 setMaxMailboxSize(kgiTid
, 1024, OnCrowding
.throwException
); //FIXME
589 // wait for "i'm ready" signal
592 if (ok
!= 42) assert(0, "wtf?!");
595 //conwriteln("rendering thread started");
600 public bool kgiInitEx (int awdt
, int ahgt
, string title
, bool a2x
, uint afps
) {
601 import core
.stdc
.stdlib
: malloc
;
602 import arsd
.simpledisplay
;
604 if (awdt
< 1 || ahgt
< 1 || awdt
> 4096 || ahgt
> 4096) {
606 //assert(0, "invalid dimensions");
609 if (!cas(&kgiThreadStarted
, false, true)) return false;
611 if (vbwin
!is null) assert(0, "double initialization");
613 if (afps
< 1) afps
= 1; else if (afps
> 60) afps
= 60;
615 conSealVar("v_scale2x");
616 conSealVar("v_width");
617 conSealVar("v_height");
618 conSealVar("v_title");
621 vbuf
= cast(typeof(vbuf
))malloc(vbuf
[0].sizeof
*awdt
*ahgt
);
622 if (vbuf
is null) assert(0, "KGI: out of memory");
623 vbuf
[0..awdt
*ahgt
] = 0;
625 vbufsaved
= cast(typeof(vbuf
))malloc(vbufsaved
[0].sizeof
*awdt
*ahgt
);
626 if (vbufsaved
is null) assert(0, "KGI: out of memory");
627 vbufsaved
[0..awdt
*ahgt
] = vbuf
[0..awdt
*ahgt
];
629 vcurbuf
= cast(typeof(vcurbuf
))malloc(vcurbuf
[0].sizeof
*kgiMaxCurW
*kgiMaxCurH
);
630 if (vbuf
is null) assert(0, "KGI: out of memory");
631 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
632 unpackDefaultCursor();
641 setOpenGLContextVersion(3, 2); // up to GLSL 150
642 //openGLContextCompatible = false;
643 static if (is(typeof(openGLContextAllowFallback
))) {
644 openGLContextAllowFallback
= true;
654 public bool kgiInit () { return kgiInitEx(vbufW
, vbufH
, kgiTitle
, blit2x
, fps
); }
655 public bool kgiInit (int awdt
, int ahgt
) { return kgiInitEx(awdt
, ahgt
, kgiTitle
, blit2x
, fps
); }
656 public bool kgiInit (int awdt
, int ahgt
, string title
) { return kgiInitEx(awdt
, ahgt
, title
, blit2x
, fps
); }
657 public bool kgiInit (int awdt
, int ahgt
, string title
, bool a2x
) { return kgiInitEx(awdt
, ahgt
, title
, a2x
, fps
); }
658 public bool kgiInit (int awdt
, int ahgt
, string title
, bool a2x
, uint afps
) { return kgiInitEx(awdt
, ahgt
, title
, a2x
, afps
); }
661 // ////////////////////////////////////////////////////////////////////////// //
662 private uint glgfxCompileShader (const(char)[] src
) nothrow @trusted {
665 if (shaderVersionOk
< 0) {
666 // check if we have sufficient shader version here
670 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS
, &svcount
);
672 foreach (GLuint n
; 0..svcount
) {
673 import core
.stdc
.string
: strncmp
;
674 auto v
= glGetStringi(GL_SHADING_LANGUAGE_VERSION
, n
);
675 if (v
is null) continue;
676 //if (strncmp(v, "130", 3) != 0) continue;
677 if (strncmp(cast(char*)v
, "150".ptr
, 3) != 0) continue;
678 if (v
[3] > ' ') continue;
683 if (!found
) return 0; //assert(0, "can't find OpenGL GLSL 150");
686 auto adr = glGetProcAddress("glTexParameterf");
687 if (adr is null) return 0;
692 if (shaderVersionOk
== 0) return 0;
693 return compileShaders(src
);
697 private void glgfxInitTexture () nothrow @trusted {
700 //if (vbTexId) { glDeleteTextures(1, &vbTexId); vbTexId = 0; }
702 enum wrapOpt
= GL_REPEAT
;
703 enum filterOpt
= GL_NEAREST
; //GL_LINEAR;
704 enum ttype
= GL_UNSIGNED_BYTE
;
706 glGenTextures(1, &vbTexId
);
707 if (vbTexId
== 0) assert(0, "can't create kgi texture");
709 glGenTextures(1, &vbCurTexId
);
710 if (vbTexId
== 0) assert(0, "can't create kgicursor texture");
713 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &gltextbinding
);
714 scope(exit
) glBindTexture(GL_TEXTURE_2D
, gltextbinding
);
716 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
717 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapOpt
);
718 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapOpt
);
719 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filterOpt
);
720 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filterOpt
);
721 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
722 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
724 GLfloat
[4] bclr
= 0.0;
725 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, bclr
.ptr
);
727 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
728 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, vbufW
, vbufH
, 0, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
731 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
732 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapOpt
);
733 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapOpt
);
734 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filterOpt
);
735 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filterOpt
);
736 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
737 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
739 //GLfloat[4] bclr = 0.0;
740 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, bclr
.ptr
);
742 //static if (KGIRGBA) enum TexType = GL_RGBA; else enum TexType = GL_BGRA;
743 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, kgiMaxCurW
, kgiMaxCurH
, 0, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
747 private void glgfxUpdateTexture () nothrow @trusted {
751 scope(exit
) consoleUnlock();
753 version(LDC
) {} else atomicFence();
756 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
758 glTextureSubImage2D(vbTexId
, 0, 0/*x*/, 0/*y*/, vbufW
, vbufH
, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
760 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
761 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, vbufW
, vbufH
, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
762 glBindTexture(GL_TEXTURE_2D
, 0);
764 atomicStore(updateTexture
, false);
765 vupcounterlast
= vupcounterlast
.max
;
767 if (atomicLoad(updateCurTexture
)) {
769 glTextureSubImage2D(vbCurTexId
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
771 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
772 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
773 glBindTexture(GL_TEXTURE_2D
, 0);
775 atomicStore(updateCurTexture
, false);
780 private void glgfxUpdateCurTexture () nothrow @trusted {
783 if (atomicLoad(updateCurTexture
)) {
785 scope(exit
) consoleUnlock();
787 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
789 glTextureSubImage2D(vbCurTexId
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
791 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
792 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
793 glBindTexture(GL_TEXTURE_2D
, 0);
796 atomicStore(updateCurTexture
, false);
801 private void glgfxBlit () nothrow @trusted {
805 scope(exit
) consoleUnlock();
807 //if (vbwin is null || vbwin.closed || vbTexId == 0) return;
813 GLint oldfbr, oldfbw;
815 glGetIntegerv(GL_MATRIX_MODE, &glmatmode);
816 glGetIntegerv(GL_TEXTURE_BINDING_2D, &gltextbinding);
817 glGetIntegerv(GL_VIEWPORT, glviewport.ptr);
818 glGetIntegerv(GL_CURRENT_PROGRAM, &oldprg);
819 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldfbr);
820 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfbw);
821 glMatrixMode(GL_PROJECTION); glPushMatrix();
822 glMatrixMode(GL_MODELVIEW); glPushMatrix();
823 glMatrixMode(GL_TEXTURE); glPushMatrix();
824 glMatrixMode(GL_COLOR); glPushMatrix();
825 glPushAttrib(/*GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_CURRENT_BIT*/GL_ALL_ATTRIB_BITS); // let's play safe
828 glPopAttrib(/*GL_ENABLE_BIT*/);
829 glMatrixMode(GL_PROJECTION); glPopMatrix();
830 glMatrixMode(GL_MODELVIEW); glPopMatrix();
831 glMatrixMode(GL_TEXTURE); glPopMatrix();
832 glMatrixMode(GL_COLOR); glPopMatrix();
833 glMatrixMode(glmatmode);
834 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oldfbr);
835 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, oldfbw);
836 glBindTexture(GL_TEXTURE_2D, gltextbinding);
837 glUseProgram(oldprg);
838 glViewport(glviewport.ptr[0], glviewport.ptr[1], glviewport.ptr[2], glviewport.ptr[3]);
848 glBindTexture(GL_TEXTURE_CUBE_MAP
, 0);
849 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
851 if (scanlines
&& shaderVersionOk
< 0) sdrScanlineId
= glgfxCompileShader(sdrScanlineSrc
);
852 glUseProgram(scanlines ? sdrScanlineId
: 0);
855 glMatrixMode(GL_PROJECTION
); // for ortho camera
857 // left, right, bottom, top, near, far
858 glViewport(0, 0, w
*(blit2x ?
2 : 1), h
*(blit2x ?
2 : 1));
859 glOrtho(0, w
, h
, 0, -1, 1); // top-to-bottom
860 glMatrixMode(GL_MODELVIEW
);
863 glEnable(GL_TEXTURE_2D
);
864 glDisable(GL_LIGHTING
);
865 glDisable(GL_DITHER
);
866 //glDisable(GL_BLEND);
867 glDisable(GL_DEPTH_TEST
);
868 //glEnable(GL_BLEND);
869 //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
870 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
872 glDisable(GL_STENCIL_TEST
);
874 glColor4f(1, 1, 1, 1);
875 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
876 //scope(exit) glBindTexture(GL_TEXTURE_2D, 0);
878 glTexCoord2f(0.0f, 0.0f); glVertex2i(x
, y
); // top-left
879 glTexCoord2f(1.0f, 0.0f); glVertex2i(w
, y
); // top-right
880 glTexCoord2f(1.0f, 1.0f); glVertex2i(w
, h
); // bottom-right
881 glTexCoord2f(0.0f, 1.0f); glVertex2i(x
, h
); // bottom-left
884 if (mcurHidden
== 0) {
886 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
887 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
889 int cx0
= mcurX
-mhotX
;
890 int cy0
= mcurY
-mhotY
;
893 glTexCoord2f(0.0f, 0.0f); glVertex2i(cx0
, cy0
); // top-left
894 glTexCoord2f(1.0f, 0.0f); glVertex2i(cx0
+kgiMaxCurW
, cy0
); // top-right
895 glTexCoord2f(1.0f, 1.0f); glVertex2i(cx0
+kgiMaxCurW
, cy0
+kgiMaxCurH
); // bottom-right
896 glTexCoord2f(0.0f, 1.0f); glVertex2i(cx0
, cy0
+kgiMaxCurH
); // bottom-left
904 // ////////////////////////////////////////////////////////////////////////// //
907 /// vlRGBA struct to ease color components extraction/replacing
908 align(1) struct vlRGBA
{
910 static if (KGIRGBA
) {
916 static assert(vlRGBA
.sizeof
== VColor
.sizeof
);
919 static if (KGIRGBA
) {
934 static assert(vlAShift
== 24, "invalid A position in color"); // alas
938 vlAMask
= 0xffu
<<vlAShift
,
939 vlRMask
= 0xffu
<<vlRShift
,
940 vlGMask
= 0xffu
<<vlGShift
,
941 vlBMask
= 0xffu
<<vlBShift
,
942 vlColorMask
= vlRMask|vlGMask|vlBMask
,
946 enum VColor Transparent
= vlAMask
; /// completely transparent pixel color
949 bool isTransparent(T
: VColor
) (T col
) pure nothrow @safe @nogc {
950 pragma(inline
, true);
951 return ((col
&vlAMask
) == vlAMask
);
954 bool isOpaque(T
: VColor
) (T col
) pure nothrow @safe @nogc {
955 pragma(inline
, true);
956 return ((col
&vlAMask
) == 0);
960 VColor
rgbcol(TR
, TG
, TB
, TA
=ubyte) (TR r
, TG g
, TB b
, TA a
=0) pure nothrow @safe @nogc
961 if (__traits(isIntegral
, TR
) && __traits(isIntegral
, TG
) && __traits(isIntegral
, TB
) && __traits(isIntegral
, TA
)) {
962 pragma(inline
, true);
964 (clampToByte(a
)<<vlAShift
)|
965 (clampToByte(r
)<<vlRShift
)|
966 (clampToByte(g
)<<vlGShift
)|
967 (clampToByte(b
)<<vlBShift
);
970 alias rgbacol
= rgbcol
;
973 // generate some templates (rgbRed, rgbSetRed, etc.)
974 private enum genRGBGetSet(string cname
) =
975 "ubyte rgb"~cname
~"() (VColor clr) pure nothrow @safe @nogc {\n"~
976 " pragma(inline, true);\n"~
977 " return ((clr>>vl"~cname
[0]~"Shift)&0xff);\n"~
979 "VColor rgbSet"~cname
~"(T) (VColor clr, T v) pure nothrow @safe @nogc if (__traits(isIntegral, T)) {\n"~
980 " pragma(inline, true);\n"~
981 " return (clr&~vl"~cname
[0]~"Mask)|(clampToByte(v)<<vl"~cname
[0]~"Shift);\n"~
984 mixin(genRGBGetSet
!"Alpha");
985 mixin(genRGBGetSet
!"Red");
986 mixin(genRGBGetSet
!"Green");
987 mixin(genRGBGetSet
!"Blue");
990 // ////////////////////////////////////////////////////////////////////////// //
991 nothrow @trusted @nogc {
993 private void putPixelIntrNoCheck (in int xx
, in int yy
, in VColor col
) {
994 pragma(inline
, true);
995 uint* da = vbuf
+yy
*vbufW
+xx
;
997 immutable uint a
= 256-(col
>>24); // to not loose bits
998 immutable uint dc
= (*da)&0xffffff;
999 immutable uint srb
= (col
&0xff00ff);
1000 immutable uint sg
= (col
&0x00ff00);
1001 immutable uint drb
= (dc
&0xff00ff);
1002 immutable uint dg
= (dc
&0x00ff00);
1003 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1004 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1011 private void putPixelIntr (int xx
, int yy
, VColor col
) {
1012 pragma(inline
, true);
1013 if ((col
&vlAMask
) != vlAMask
&& xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1014 uint* da = vbuf
+yy
*vbufW
+xx
;
1016 immutable uint a
= 256-(col
>>24); // to not loose bits
1017 immutable uint dc
= (*da)&0xffffff;
1018 immutable uint srb
= (col
&0xff00ff);
1019 immutable uint sg
= (col
&0x00ff00);
1020 immutable uint drb
= (dc
&0xff00ff);
1021 immutable uint dg
= (dc
&0x00ff00);
1022 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1023 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1031 void putPixel (int xx
, int yy
, VColor col
) {
1032 pragma(inline
, true);
1033 if ((col
&vlAMask
) != vlAMask
&& xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1034 uint* da = vbuf
+yy
*vbufW
+xx
;
1036 immutable uint a
= 256-(col
>>24); // to not loose bits
1037 immutable uint dc
= (*da)&0xffffff;
1038 immutable uint srb
= (col
&0xff00ff);
1039 immutable uint sg
= (col
&0x00ff00);
1040 immutable uint drb
= (dc
&0xff00ff);
1041 immutable uint dg
= (dc
&0x00ff00);
1042 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1043 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1048 version(LDC
) {} else atomicFence();
1053 private void setPixelIntr (int xx
, int yy
, VColor col
) {
1054 pragma(inline
, true);
1055 if (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1056 uint* da = vbuf
+yy
*vbufW
+xx
;
1061 void setPixel (int xx
, int yy
, VColor col
) {
1062 pragma(inline
, true);
1063 if (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1064 uint* da = vbuf
+yy
*vbufW
+xx
;
1066 version(LDC
) {} else atomicFence();
1072 VColor
getPixel (int xx
, int yy
) {
1073 pragma(inline
, true);
1074 return (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH ? vbuf
[yy
*vbufW
+xx
]&vlColorMask
: Transparent
);
1078 // ////////////////////////////////////////////////////////////////////////// //
1079 void cls (VColor col
) {
1080 vbuf
[0..vbufW
*vbufH
] = col
;
1081 version(LDC
) {} else atomicFence();
1086 // ////////////////////////////////////////////////////////////////////////// //
1087 void drawRect (int x
, int y
, int w
, int h
, immutable VColor col
) {
1088 if (w
< 1 || h
< 1) return;
1089 if (x
<= -w || y
<= -h || x
>= vbufW || y
>= vbufH ||
isTransparent(col
)) return;
1090 if (x
< 0) { w
+= x
; x
= 0; }
1091 if (y
< 0) { h
+= y
; h
= 0; }
1092 if (x
+w
>= vbufW
) w
= vbufW
-x
;
1093 if (y
+h
>= vbufH
) h
= vbufH
-y
;
1094 assert(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
&& w
> 0 && h
> 0 && x
+w
<= vbufW
&& y
+h
<= vbufH
);
1095 if (isOpaque(col
)) {
1099 foreach (immutable yy
; y
+1..y
+h
-1) {
1104 if (h
> 1) vbuf
[d
..d
+w
] = col
;
1106 foreach (immutable yy
; y
..y
+h
) {
1107 putPixelIntr(x
, yy
, col
);
1108 putPixelIntr(x
+w
-1, yy
, col
);
1110 foreach (immutable xx
; x
+1..x
+w
-1) {
1111 putPixelIntr(xx
, y
, col
);
1112 if (h
> 1) putPixelIntr(xx
, y
+h
-1, col
);
1115 version(LDC
) {} else atomicFence();
1119 void fillRect (int x
, int y
, int w
, int h
, immutable VColor col
) {
1120 if (w
< 1 || h
< 1) return;
1121 if (x
<= -w || y
<= -h || x
>= vbufW || y
>= vbufH ||
isTransparent(col
)) return;
1122 if (x
< 0) { w
+= x
; x
= 0; }
1123 if (y
< 0) { h
+= y
; h
= 0; }
1124 if (x
+w
>= vbufW
) w
= vbufW
-x
;
1125 if (y
+h
>= vbufH
) h
= vbufH
-y
;
1126 assert(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
&& w
> 0 && h
> 0 && x
+w
<= vbufW
&& y
+h
<= vbufH
);
1127 if (isOpaque(col
)) {
1129 foreach (immutable yy
; y
..y
+h
) {
1134 foreach (immutable yy
; y
..y
+h
) {
1135 foreach (immutable xx
; x
..x
+w
) {
1136 putPixelIntr(xx
, yy
, col
);
1140 version(LDC
) {} else atomicFence();
1144 void hline (int x
, int y
, int len
, immutable VColor col
) { drawRect(x
, y
, len
, 1, col
); }
1145 void vline (int x
, int y
, int len
, immutable VColor col
) { drawRect(x
, y
, 1, len
, col
); }
1148 // ////////////////////////////////////////////////////////////////////////// //
1149 void drawLine(bool lastPoint
=true) (int x0
, int y0
, int x1
, int y1
, immutable VColor col
) {
1150 enum swap(string a
, string b
) = "{int tmp_="~a
~";"~a
~"="~b
~";"~b
~"=tmp_;}";
1152 if ((col
&vlAMask
) == vlAMask
) return;
1154 if (x0
== x1
&& y0
== y1
) {
1155 static if (lastPoint
) putPixel(x0
, y0
, col
);
1160 int wx0
= 0, wy0
= 0, wx1
= vbufW
-1, wy1
= vbufH
-1;
1162 int stx
, sty
; // "steps" for x and y axes
1163 int dsx
, dsy
; // "lengthes" for x and y axes
1164 int dx2
, dy2
; // "double lengthes" for x and y axes
1165 int xd
, yd
; // current coord
1166 int e
; // "error" (as in bresenham algo)
1172 // from left to right
1173 if (x0
> wx1 || x1
< wx0
) return; // out of screen
1174 stx
= 1; // going right
1176 // from right to left
1177 if (x1
> wx1 || x0
< wx0
) return; // out of screen
1178 stx
= -1; // going left
1183 mixin(swap
!("wx0", "wx1"));
1187 // from top to bottom
1188 if (y0
> wy1 || y1
< wy0
) return; // out of screen
1189 sty
= 1; // going down
1191 // from bottom to top
1192 if (y1
> wy1 || y0
< wy0
) return; // out of screen
1193 sty
= -1; // going up
1198 mixin(swap
!("wy0", "wy1"));
1205 mixin(swap
!("x0", "y0"));
1206 mixin(swap
!("x1", "y1"));
1207 mixin(swap
!("dsx", "dsy"));
1208 mixin(swap
!("wx0", "wy0"));
1209 mixin(swap
!("wx1", "wy1"));
1210 mixin(swap
!("stx", "sty"));
1221 bool xfixed
= false;
1224 int temp
= dx2
*(wy0
-y0
)-dsx
;
1227 if (xd
> wx1
) return; // x is moved out of clipping rect, nothing to do
1231 if (rem
> 0) { ++xd
; e
+= dy2
; }
1235 if (!xfixed
&& x0
< wx0
) {
1237 int temp
= dy2
*(wx0
-x0
);
1240 if (yd
> wy1 || yd
== wy1
&& rem
>= dsx
) return;
1243 if (rem
>= dsx
) { ++yd
; e
-= dx2
; }
1247 int temp
= dx2
*(wy1
-y0
)+dsx
;
1250 if (rem
== 0) --term
;
1252 if (term
> wx1
) term
= wx1
; // clip at right
1253 static if (lastPoint
) {
1257 if (term
== xd
) return; // this is the only point, get out of here
1259 if (sty
== -1) yd
= -yd
;
1260 if (stx
== -1) { xd
= -xd
; term
= -term
; }
1262 // draw it; `putPixel()` can omit checks
1263 while (xd
!= term
) {
1264 putPixelIntrNoCheck(*d0
, *d1
, col
);
1265 // done drawing, move coords
1274 version(LDC
) {} else atomicFence();
1279 // ////////////////////////////////////////////////////////////////////////// //
1280 private void plot4points() (int cx
, int cy
, int x
, int y
, VColor clr
) @trusted {
1281 putPixelIntr(cx
+x
, cy
+y
, clr
);
1282 if (x
!= 0) putPixelIntr(cx
-x
, cy
+y
, clr
);
1283 if (y
!= 0) putPixelIntr(cx
+x
, cy
-y
, clr
);
1284 putPixelIntr(cx
-x
, cy
-y
, clr
);
1288 void drawCircle (int cx
, int cy
, int radius
, VColor clr
) @trusted {
1289 if (radius
> 0 && !isTransparent(clr
)) {
1290 int error
= -radius
, x
= radius
, y
= 0;
1291 if (radius
== 1) { putPixelIntr(cx
, cy
, clr
); return; }
1293 plot4points(cx
, cy
, x
, y
, clr
);
1294 plot4points(cx
, cy
, y
, x
, clr
);
1297 if (error
>= 0) { --x
; error
-= x
*2; }
1299 plot4points(cx
, cy
, x
, y
, clr
);
1300 version(LDC
) {} else atomicFence();
1305 void fillCircle (int cx
, int cy
, int radius
, VColor clr
) @trusted {
1306 if (radius
> 0 && !isTransparent(clr
)) {
1307 int error
= -radius
, x
= radius
, y
= 0;
1308 if (radius
== 1) { putPixelIntr(cx
, cy
, clr
); return; }
1314 hline(cx
-x
, cy
+last_y
, 2*x
+1, clr
);
1315 if (x
!= 0 && last_y
!= 0) hline(cx
-x
, cy
-last_y
, 2*x
+1, clr
);
1318 hline(cx
-last_y
, cy
+x
, 2*last_y
+1, clr
);
1319 if (last_y
!= 0 && x
!= 0) hline(cx
-last_y
, cy
-x
, 2*last_y
+1, clr
);
1326 version(LDC
) {} else atomicFence();
1332 void drawEllipse (int x0
, int y0
, int w
, int h
, VColor clr
) @trusted {
1333 import std
.math
: abs
;
1334 if (w
== 0 && h
== 0) return;
1335 if (w
== 1) { vline(x0
, y0
, h
, clr
); return; }
1336 if (h
== 1) { hline(x0
, y0
, w
, clr
); return; }
1339 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; // values of diameter
1340 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; // error increment
1341 long err
= dx
+dy
+b1
*a
*a
; // error of 1.step
1342 if (x0
> x1
) { x0
= x1
; x1
+= a
; } // if called with swapped points...
1343 if (y0
> y1
) y0
= y1
; // ...exchange them
1344 y0
+= (b
+1)/2; y1
= y0
-b1
; // starting pixel
1345 a
*= 8*a
; b1
= 8*b
*b
;
1348 putPixelIntr(x1
, y0
, clr
); // I. Quadrant
1349 putPixelIntr(x0
, y0
, clr
); // II. Quadrant
1350 putPixelIntr(x0
, y1
, clr
); // III. Quadrant
1351 putPixelIntr(x1
, y1
, clr
); // IV. Quadrant
1353 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } // x step
1354 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } // y step
1357 // too early stop of flat ellipses a=1
1358 putPixelIntr(x0
-1, ++y0
, clr
); // complete tip of ellipse
1359 putPixelIntr(x0
-1, --y1
, clr
);
1361 version(LDC
) {} else atomicFence();
1365 void fillEllipse (int x0
, int y0
, int w
, int h
, VColor clr
) @trusted {
1366 import std
.math
: abs
;
1367 if (w
== 0 && h
== 0) return;
1368 if (w
== 1) { vline(x0
, y0
, h
, clr
); return; }
1369 if (h
== 1) { hline(x0
, y0
, w
, clr
); return; }
1372 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; // values of diameter
1373 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; // error increment
1374 long err
= dx
+dy
+b1
*a
*a
; // error of 1.step
1375 int prev_y0
= -1, prev_y1
= -1;
1376 if (x0
> x1
) { x0
= x1
; x1
+= a
; } // if called with swapped points...
1377 if (y0
> y1
) y0
= y1
; // ...exchange them
1378 y0
+= (b
+1)/2; y1
= y0
-b1
; // starting pixel
1379 a
*= 8*a
; b1
= 8*b
*b
;
1382 if (y0
!= prev_y0
) { hline(x0
, y0
, x1
-x0
+1, clr
); prev_y0
= y0
; }
1383 if (y1
!= y0
&& y1
!= prev_y1
) { hline(x0
, y1
, x1
-x0
+1, clr
); prev_y1
= y1
; }
1385 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } // x step
1386 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } // y step
1389 // too early stop of flat ellipses a=1
1390 putPixelIntr(x0
-1, ++y0
, clr
); // complete tip of ellipse
1391 putPixelIntr(x0
-1, --y1
, clr
);
1393 version(LDC
) {} else atomicFence();
1398 // //////////////////////////////////////////////////////////////////////// //
1399 int charWidth(string type
="msx") () {
1400 static if (type
== "msx") return 6;
1401 else static if (type
== "dos") return 8;
1402 else static if (type
== "d10") return 10;
1403 else static assert(0, "invalid font type");
1406 int charHeight(string type
="msx") () {
1407 static if (type
== "msx") return 8;
1408 else static if (type
== "dos") return 8;
1409 else static if (type
== "d10") return 10;
1410 else static assert(0, "invalid font type");
1413 void drawCharWdt(string type
="msx") (int x
, int y
, int wdt
, int shift
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1414 static if (type
== "msx") { alias fontb8
= kgiFont6
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1415 else static if (type
== "dos") { alias fontb8
= kgiFont8
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1416 else static if (type
== "d10") { alias fontb8
= kgiFont10
; enum fwdt
= 10; enum fhgt
= 10; enum fmask
= 0x8000; }
1417 else static assert(0, "invalid font type");
1418 usize pos
= ch
*fhgt
;
1419 if (wdt
< 1 || shift
>= fwdt
) return;
1420 if (fgcol
== Transparent
&& bgcol
== Transparent
) return;
1421 if (wdt
> fwdt
) wdt
= fwdt
;
1422 if (shift
< 0) shift
= 0;
1423 foreach (immutable int dy
; 0..fhgt
) {
1424 ushort b
= cast(ushort)(fontb8
.ptr
[pos
++]<<shift
);
1425 foreach (immutable int dx
; 0..wdt
) {
1426 VColor c
= (b
&fmask ? fgcol
: bgcol
);
1427 putPixelIntr(x
+dx
, y
+dy
, c
);
1431 version(LDC
) {} else atomicFence();
1441 OutLU
= 0x10, // left-up
1442 OutRU
= 0x20, // right-up
1443 OutLD
= 0x40, // left-down
1444 OutRD
= 0x80, // right-down
1448 void drawCharWdtOut(string type
="msx") (int x
, int y
, int wdt
, int shift
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=0) @trusted {
1449 static if (type
== "msx") { alias fontb8
= kgiFont6
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1450 else static if (type
== "dos") { alias fontb8
= kgiFont8
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1451 else static if (type
== "d10") { alias fontb8
= kgiFont10
; enum fwdt
= 10; enum fhgt
= 10; enum fmask
= 0x8000; }
1452 else static assert(0, "invalid font type");
1453 if (fgcol
== Transparent
&& outcol
== Transparent
) return;
1454 if (ot
== 0 || outcol
== Transparent
) {
1455 // no outline? simple draw
1456 drawCharWdt(x
, y
, wdt
, shift
, ch
, fgcol
, Transparent
);
1459 usize pos
= ch
*fhgt
;
1460 if (wdt
< 1 || shift
>= fwdt
) return;
1461 if (wdt
> 8) wdt
= fwdt
;
1462 if (shift
< 0) shift
= 0;
1463 ubyte[fhgt
+2][fwdt
+2] bmp
= 0; // char bitmap; 0: empty; 1: char; 2: outline
1464 foreach (immutable dy
; 1..fhgt
+1) {
1465 ushort b
= cast(ushort)(fontb8
.ptr
[pos
++]<<shift
);
1466 foreach (immutable dx
; 1..wdt
+1) {
1471 if ((ot
&OutUp
) && bmp
[dy
-1][dx
] == 0) bmp
[dy
-1][dx
] = 2;
1472 if ((ot
&OutDown
) && bmp
[dy
+1][dx
] == 0) bmp
[dy
+1][dx
] = 2;
1473 if ((ot
&OutLeft
) && bmp
[dy
][dx
-1] == 0) bmp
[dy
][dx
-1] = 2;
1474 if ((ot
&OutRight
) && bmp
[dy
][dx
+1] == 0) bmp
[dy
][dx
+1] = 2;
1475 if ((ot
&OutLU
) && bmp
[dy
-1][dx
-1] == 0) bmp
[dy
-1][dx
-1] = 2;
1476 if ((ot
&OutRU
) && bmp
[dy
-1][dx
+1] == 0) bmp
[dy
-1][dx
+1] = 2;
1477 if ((ot
&OutLD
) && bmp
[dy
+1][dx
-1] == 0) bmp
[dy
+1][dx
-1] = 2;
1478 if ((ot
&OutRD
) && bmp
[dy
+1][dx
+1] == 0) bmp
[dy
+1][dx
+1] = 2;
1486 foreach (immutable int dy
; 0..fhgt
+2) {
1487 foreach (immutable int dx
; 0..fwdt
+2) {
1488 if (auto t
= bmp
[dy
][dx
]) putPixelIntr(x
+dx
, y
+dy
, (t
== 1 ? fgcol
: outcol
));
1491 version(LDC
) {} else atomicFence();
1495 void drawChar(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1496 drawCharWdt
!type(x
, y
, charWidth
!type
, 0, ch
, fgcol
, bgcol
);
1499 void drawCharOut(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1500 drawCharWdtOut
!type(x
, y
, charWidth
!type
, 0, ch
, fgcol
, outcol
, ot
);
1503 void drawStr(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1504 foreach (immutable char ch
; str) {
1505 drawChar
!type(x
, y
, ch
, fgcol
, bgcol
);
1506 x
+= charWidth
!type
;
1510 void drawStrOut(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1511 foreach (immutable char ch
; str) {
1512 drawCharOut
!type(x
, y
, ch
, fgcol
, outcol
, ot
);
1513 x
+= charWidth
!type
;
1517 int strWidth(string type
="msx") (const(char)[] str) {
1518 return cast(int)str.length
*charWidth
!type
;
1521 int charWidthProp(string type
="msx") (char ch
) @trusted pure {
1522 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1523 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1524 else static assert(0, "invalid font type");
1525 return (fontw8
.ptr
[ch
]&0x0f);
1528 int strWidthProp(string type
="msx") (const(char)[] str) @trusted pure {
1529 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1530 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1531 else static assert(0, "invalid font type");
1533 foreach (immutable char ch
; str) wdt
+= (fontw8
[ch
]&0x0f)+1;
1534 if (wdt
> 0) --wdt
; // don't count last empty pixel
1538 int drawCharProp(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1539 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1540 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1541 else static assert(0, "invalid font type");
1542 immutable int wdt
= (fontw8
[ch
]&0x0f);
1543 drawCharWdt
!type(x
, y
, wdt
, fontw8
[ch
]>>4, ch
, fgcol
, bgcol
);
1547 int drawCharPropOut(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1548 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1549 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1550 else static assert(0, "invalid font type");
1551 immutable int wdt
= (fontw8
[ch
]&0x0f);
1552 drawCharWdtOut
!type(x
, y
, wdt
, fontw8
[ch
]>>4, ch
, fgcol
, outcol
, ot
);
1556 int drawStrProp(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1559 foreach (immutable char ch
; str) {
1561 if (!isTransparent(bgcol
)) {
1562 foreach (int dy
; 0..8) putPixelIntr(x
, y
+dy
, bgcol
);
1563 // no need to advance vupcounter, 'cause `drawCharProp` will do it
1564 //version(LDC) {} else atomicFence();
1570 x
+= drawCharProp
!type(x
, y
, ch
, fgcol
, bgcol
);
1575 int drawStrPropOut(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1577 foreach (immutable char ch
; str) {
1578 x
+= drawCharPropOut
!type(x
, y
, ch
, fgcol
, outcol
, ot
)+1;
1580 if (x
> sx
) --x
; // don't count last empty pixel
1585 // ////////////////////////////////////////////////////////////////////////// //
1586 /** floodfill area; based on Tarry's maze algorithm.
1588 * fill area with color/pattern. trades memory for speed: doesn't recurse, doesn't allocate.
1589 * will use "transparency" byte as temporary, and will leave it dirty.
1592 * neither `isBorder` nor `patColor` will be called with out-of-range coordinates.
1594 void floodFillEx (int x
, int y
, scope bool delegate (int x
, int y
) nothrow @nogc isBorder
, scope VColor
delegate (int x
, int y
) nothrow @nogc patColor
) nothrow @trusted @nogc {
1601 static ubyte getmark (int x
, int y
) nothrow @trusted @nogc {
1602 pragma(inline
, true);
1603 return cast(ubyte)(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH ? vbuf
[y
*vbufW
+x
]>>vlAShift
: Scanned
);
1606 static void setmark (int x
, int y
, ubyte mark
) nothrow @trusted @nogc {
1607 pragma(inline
, true);
1608 if (x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
) vbuf
[y
*vbufW
+x
] = (vbuf
[y
*vbufW
+x
]&vlColorMask
)|
(mark
<<vlAShift
);
1611 if (x
< 0 || y
< 0 || x
>= vbufW || y
>= vbufH
) return; // nothing to do
1612 if (isBorder(x
, y
)) return; // nothing to do
1614 //setPixel(x, y, getPixel(x, y)); // set update flag
1616 // one can mark bounding rectangle with Scanned
1619 foreach (immutable dy
; 0..vbufH
) {
1620 foreach (immutable dx
; 0..vbufW
) {
1621 *p
&= vlColorMask
; // "not visited" mark
1626 //setmark(x, y, Scanned|Fill|Seed);
1627 VColor pc
= patColor(x
, y
);
1629 vbuf
[y
*vbufW
+x
] = (pc
&vlColorMask
)|
((Scanned|Seed
)<<vlAShift
);
1632 putPixelIntrNoCheck(x
, y
, pc
);
1633 setmark(x
, y
, Scanned|Seed
);
1636 ubyte dir
= 0; // direction: right, left, up, down
1638 x
+= (dir
== 0 ?
1 : dir
== 1 ?
-1 : 0);
1639 y
+= (dir
== 3 ?
1 : dir
== 2 ?
-1 : 0);
1640 auto mk
= getmark(x
, y
);
1642 // not yet visited, check for border
1643 if (isBorder(x
, y
)) {
1645 setmark(x
, y
, Scanned
);
1648 if ((mk
&Scanned
) == 0) {
1650 //setmark(x, y, Scanned|Fill|dir);
1651 pc
= patColor(x
, y
);
1653 vbuf
[y
*vbufW
+x
] = (pc
&vlColorMask
)|
((Scanned|dir
)<<vlAShift
);
1656 putPixelIntrNoCheck(x
, y
, pc
);
1657 setmark(x
, y
, Scanned|dir
);
1659 if (dir
!= 1) dir
= 0; // make exit direction
1663 x
-= (dir
== 0 ?
1 : dir
== 1 ?
-1 : 0);
1664 y
-= (dir
== 3 ?
1 : dir
== 2 ?
-1 : 0);
1667 // done, fill pixels (you can set Fill flag and check all pixels here)
1668 if ((mk
&DirMask
) == 3) {
1670 version(LDC
) {} else atomicFence();
1678 break; // next pixel
1681 if ((mk
&DirMask
) == (dir^
1)) ++dir
; // skip entry-direction
1682 if (dir
<= 3) break; // next pixel
1691 // ////////////////////////////////////////////////////////////////////////// //
1693 static public immutable ubyte[256*8] kgiFont6
= [
1694 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0xa5,0x81,0xa5,0x99,0x42,0x3c,0x3c,0x7e,0xdb,0xff,0xff,0xdb,0x66,0x3c,0x6c,0xfe,
1695 0xfe,0xfe,0x7c,0x38,0x10,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x10,0x38,0x54,0xfe,0x54,0x10,0x38,0x00,0x10,0x38,0x7c,0xfe,
1696 0xfe,0x10,0x38,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0xff,0xff,0xff,0xe7,0xe7,0xff,0xff,0xff,0x38,0x44,0x82,0x82,0x82,0x44,
1697 0x38,0x00,0xc7,0xbb,0x7d,0x7d,0x7d,0xbb,0xc7,0xff,0x0f,0x03,0x05,0x79,0x88,0x88,0x88,0x70,0x38,0x44,0x44,0x44,0x38,0x10,0x7c,0x10,
1698 0x30,0x28,0x24,0x24,0x28,0x20,0xe0,0xc0,0x3c,0x24,0x3c,0x24,0x24,0xe4,0xdc,0x18,0x10,0x54,0x38,0xee,0x38,0x54,0x10,0x00,0x10,0x10,
1699 0x10,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xf0,
1700 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1f,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xff,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
1701 0x10,0x10,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0xf0,0x10,0x10,0x10,0x10,
1702 0x10,0x10,0x10,0x1f,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xf0,0x00,0x00,0x00,0x00,0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81,0x01,0x02,
1703 0x04,0x08,0x10,0x20,0x40,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01,0x00,0x10,0x10,0xff,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
1704 0x00,0x00,0x00,0x00,0x20,0x20,0x20,0x20,0x00,0x00,0x20,0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,
1705 0x50,0x00,0x20,0x78,0xa0,0x70,0x28,0xf0,0x20,0x00,0xc0,0xc8,0x10,0x20,0x40,0x98,0x18,0x00,0x40,0xa0,0x40,0xa8,0x90,0x98,0x60,0x00,
1706 0x10,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00,0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00,0x88,0x50,
1707 0x20,0xf8,0x20,0x50,0x88,0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00,0x00,0x00,0x78,
1708 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x70,0x88,0x98,0xa8,0xc8,0x88,
1709 0x70,0x00,0x20,0x60,0xa0,0x20,0x20,0x20,0xf8,0x00,0x70,0x88,0x08,0x10,0x60,0x80,0xf8,0x00,0x70,0x88,0x08,0x30,0x08,0x88,0x70,0x00,
1710 0x10,0x30,0x50,0x90,0xf8,0x10,0x10,0x00,0xf8,0x80,0xe0,0x10,0x08,0x10,0xe0,0x00,0x30,0x40,0x80,0xf0,0x88,0x88,0x70,0x00,0xf8,0x88,
1711 0x10,0x20,0x20,0x20,0x20,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00,0x70,0x88,0x88,0x78,0x08,0x10,0x60,0x00,0x00,0x00,0x20,0x00,
1712 0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,
1713 0x00,0x00,0xc0,0x60,0x30,0x18,0x30,0x60,0xc0,0x00,0x70,0x88,0x08,0x10,0x20,0x00,0x20,0x00,0x70,0x88,0x08,0x68,0xa8,0xa8,0x70,0x00,
1714 0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00,0xf0,0x48,0x48,0x70,0x48,0x48,0xf0,0x00,0x30,0x48,0x80,0x80,0x80,0x48,0x30,0x00,0xe0,0x50,
1715 0x48,0x48,0x48,0x50,0xe0,0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00,0x70,0x88,0x80,0xb8,
1716 0x88,0x88,0x70,0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x38,0x10,0x10,0x10,0x90,0x90,
1717 0x60,0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x88,0xd8,0xa8,0xa8,0x88,0x88,0x88,0x00,
1718 0x88,0xc8,0xc8,0xa8,0x98,0x98,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00,0x70,0x88,
1719 0x88,0x88,0xa8,0x90,0x68,0x00,0xf0,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0xf8,0x20,0x20,0x20,
1720 0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x88,0x88,0x88,0x88,0x50,0x50,0x20,0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,
1721 0x88,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x88,0x88,0x88,0x70,0x20,0x20,0x20,0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,
1722 0x70,0x40,0x40,0x40,0x40,0x40,0x70,0x00,0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x70,0x00,0x20,0x50,
1723 0x88,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00,0x40,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x08,
1724 0x78,0x88,0x78,0x00,0x80,0x80,0xb0,0xc8,0x88,0xc8,0xb0,0x00,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00,0x08,0x08,0x68,0x98,0x88,0x98,
1725 0x68,0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x70,0x00,0x10,0x28,0x20,0xf8,0x20,0x20,0x20,0x00,0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x70,
1726 0x80,0x80,0xf0,0x88,0x88,0x88,0x88,0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x90,0x60,0x40,0x40,
1727 0x48,0x50,0x60,0x50,0x48,0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0xa8,0x00,0x00,0x00,0xb0,0xc8,
1728 0x88,0x88,0x88,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,0x00,0x00,0xb0,0xc8,0xc8,0xb0,0x80,0x80,0x00,0x00,0x68,0x98,0x98,0x68,
1729 0x08,0x08,0x00,0x00,0xb0,0xc8,0x80,0x80,0x80,0x00,0x00,0x00,0x78,0x80,0xf0,0x08,0xf0,0x00,0x40,0x40,0xf0,0x40,0x40,0x48,0x30,0x00,
1730 0x00,0x00,0x90,0x90,0x90,0x90,0x68,0x00,0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00,0x00,0x00,0x88,0xa8,0xa8,0xa8,0x50,0x00,0x00,0x00,
1731 0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00,0x88,0x88,0x98,0x68,0x08,0x70,0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00,0x18,0x20,0x20,0x40,
1732 0x20,0x20,0x18,0x00,0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00,0xc0,0x20,0x20,0x10,0x20,0x20,0xc0,0x00,0x40,0xa8,0x10,0x00,0x00,0x00,
1733 0x00,0x00,0x00,0x00,0x20,0x50,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,
1734 0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x00,0x00,0x00,0xff,0xff,
1735 0xff,0xff,0xff,0xff,0x00,0x00,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xfc,0xfc,0xfc,0xfc,
1736 0xfc,0xfc,0xfc,0xfc,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x11,0x22,0x44,0x88,0x11,0x22,
1737 0x44,0x88,0x88,0x44,0x22,0x11,0x88,0x44,0x22,0x11,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,
1738 0x80,0xc0,0xe0,0xf0,0xe0,0xc0,0x80,0x00,0x01,0x03,0x07,0x0f,0x07,0x03,0x01,0x00,0xff,0x7e,0x3c,0x18,0x18,0x3c,0x7e,0xff,0x81,0xc3,
1739 0xe7,0xff,0xff,0xe7,0xc3,0x81,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
1740 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x33,0x33,0xcc,0xcc,0x33,0x33,0xcc,0xcc,0x00,0x20,0x20,0x50,0x50,0x88,
1741 0xf8,0x00,0x20,0x20,0x70,0x20,0x70,0x20,0x20,0x00,0x00,0x00,0x00,0x50,0x88,0xa8,0x50,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1742 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,
1743 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x68,0x90,0x90,0x90,0x68,0x00,0x30,0x48,0x48,0x70,0x48,0x48,0x70,0xc0,0xf8,0x88,0x80,0x80,
1744 0x80,0x80,0x80,0x00,0x00,0x50,0x70,0x88,0xf8,0x80,0x70,0x00,0x00,0x00,0x78,0x80,0xf0,0x80,0x78,0x00,0x00,0x00,0x78,0x90,0x90,0x90,
1745 0x60,0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x50,0x00,0x70,0x20,0x20,0x20,0x70,0x00,0xf8,0x20,0x70,0xa8,0xa8,0x70,0x20,0xf8,
1746 0x20,0x50,0x88,0xf8,0x88,0x50,0x20,0x00,0x70,0x88,0x88,0x88,0x50,0x50,0xd8,0x00,0x30,0x40,0x40,0x20,0x50,0x50,0x50,0x20,0x00,0x00,
1747 0x00,0x50,0xa8,0xa8,0x50,0x00,0x08,0x70,0xa8,0xa8,0xa8,0x70,0x80,0x00,0x38,0x40,0x80,0xf8,0x80,0x40,0x38,0x00,0x70,0x88,0x88,0x88,
1748 0x88,0x88,0x88,0x00,0x00,0xf8,0x00,0xf8,0x00,0xf8,0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0xf8,0x00,0xc0,0x30,0x08,0x30,0xc0,0x00,
1749 0xf8,0x00,0x50,0xf8,0x80,0xf0,0x80,0x80,0xf8,0x00,0x78,0x80,0x80,0xf0,0x80,0x80,0x78,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0xa0,0x40,
1750 0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x50,0x70,0x20,0x20,0x20,0x20,0x70,0x00,0x00,0x18,0x24,0x24,0x18,0x00,0x00,0x00,0x00,0x30,
1751 0x78,0x78,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x20,0x20,0x20,0xa0,0x60,0x20,0x00,0xa0,0x50,0x50,0x50,
1752 0x00,0x00,0x00,0x00,0x40,0xa0,0x20,0x40,0xe0,0x00,0x00,0x00,0x00,0x38,0x38,0x38,0x38,0x38,0x38,0x00,0x3c,0x42,0x99,0xa1,0xa1,0x99,
1753 0x42,0x3c,0x00,0x00,0x90,0xa8,0xe8,0xa8,0x90,0x00,0x00,0x00,0x60,0x10,0x70,0x90,0x68,0x00,0x00,0x00,0xf0,0x80,0xf0,0x88,0xf0,0x00,
1754 0x00,0x00,0x90,0x90,0x90,0xf8,0x08,0x00,0x00,0x00,0x30,0x50,0x50,0x70,0x88,0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x70,0x00,0x00,0x20,
1755 0x70,0xa8,0xa8,0x70,0x20,0x00,0x00,0x00,0x78,0x48,0x40,0x40,0x40,0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00,0x00,0x88,0x98,
1756 0xa8,0xc8,0x88,0x00,0x00,0x50,0x20,0x00,0x98,0xa8,0xc8,0x00,0x00,0x00,0x90,0xa0,0xc0,0xa0,0x90,0x00,0x00,0x00,0x38,0x28,0x28,0x48,
1757 0x88,0x00,0x00,0x00,0x88,0xd8,0xa8,0x88,0x88,0x00,0x00,0x00,0x88,0x88,0xf8,0x88,0x88,0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,
1758 0x00,0x00,0x78,0x48,0x48,0x48,0x48,0x00,0x00,0x00,0x78,0x88,0x78,0x28,0x48,0x00,0x00,0x00,0xf0,0x88,0xf0,0x80,0x80,0x00,0x00,0x00,
1759 0x78,0x80,0x80,0x80,0x78,0x00,0x00,0x00,0xf8,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x88,0x50,0x20,0x40,0x80,0x00,0x00,0x00,0xa8,0x70,
1760 0x20,0x70,0xa8,0x00,0x00,0x00,0xf0,0x48,0x70,0x48,0xf0,0x00,0x00,0x00,0x40,0x40,0x70,0x48,0x70,0x00,0x00,0x00,0x88,0x88,0xc8,0xa8,
1761 0xc8,0x00,0x00,0x00,0xf0,0x08,0x70,0x08,0xf0,0x00,0x00,0x00,0xa8,0xa8,0xa8,0xa8,0xf8,0x00,0x00,0x00,0x70,0x88,0x38,0x88,0x70,0x00,
1762 0x00,0x00,0xa8,0xa8,0xa8,0xf8,0x08,0x00,0x00,0x00,0x48,0x48,0x78,0x08,0x08,0x00,0x00,0x00,0xc0,0x40,0x70,0x48,0x70,0x00,0x90,0xa8,
1763 0xa8,0xe8,0xa8,0xa8,0x90,0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00,0xf8,0x88,0x80,0xf0,0x88,0x88,0xf0,0x00,0x90,0x90,0x90,0x90,
1764 0x90,0xf8,0x08,0x00,0x38,0x28,0x28,0x48,0x48,0xf8,0x88,0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0x20,0x70,0xa8,0xa8,0xa8,0x70,
1765 0x20,0x00,0xf8,0x88,0x88,0x80,0x80,0x80,0x80,0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x88,0x88,0x98,0xa8,0xc8,0x88,0x88,0x00,
1766 0x50,0x20,0x88,0x98,0xa8,0xc8,0x88,0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00,0x18,0x28,0x48,0x48,0x48,0x48,0x88,0x00,0x88,0xd8,
1767 0xa8,0xa8,0x88,0x88,0x88,0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0xf8,0x88,0x88,0x88,
1768 0x88,0x88,0x88,0x00,0x78,0x88,0x88,0x78,0x28,0x48,0x88,0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00,0x70,0x88,0x80,0x80,0x80,0x88,
1769 0x70,0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x88,0x88,0x88,0x50,0x20,0x40,0x80,0x00,0xa8,0xa8,0x70,0x20,0x70,0xa8,0xa8,0x00,
1770 0xf0,0x48,0x48,0x70,0x48,0x48,0xf0,0x00,0x80,0x80,0x80,0xf0,0x88,0x88,0xf0,0x00,0x88,0x88,0x88,0xc8,0xa8,0xa8,0xc8,0x00,0xf0,0x08,
1771 0x08,0x30,0x08,0x08,0xf0,0x00,0xa8,0xa8,0xa8,0xa8,0xa8,0xa8,0xf8,0x00,0x70,0x88,0x08,0x78,0x08,0x88,0x70,0x00,0xa8,0xa8,0xa8,0xa8,
1772 0xa8,0xf8,0x08,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0x00,0xc0,0x40,0x40,0x70,0x48,0x48,0x70,0x00,
1775 static public immutable ubyte[256*8] kgiFont8
= [
1776 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x6c,0xfe,
1777 0xfe,0xfe,0x7c,0x38,0x10,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x38,0x7c,0x38,0xfe,0xfe,0xd6,0x10,0x38,0x10,0x10,0x38,0x7c,
1778 0xfe,0x7c,0x10,0x38,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,
1779 0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0x0f,0x07,0x0f,0x7d,0xcc,0xcc,0xcc,0x78,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,
1780 0x3f,0x33,0x3f,0x30,0x30,0x70,0xf0,0xe0,0x7f,0x63,0x7f,0x63,0x63,0x67,0xe6,0xc0,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x80,0xe0,
1781 0xf8,0xfe,0xf8,0xe0,0x80,0x00,0x02,0x0e,0x3e,0xfe,0x3e,0x0e,0x02,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,
1782 0x66,0x00,0x66,0x00,0x7f,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x00,0x7e,0xc3,0x78,0xcc,0xcc,0x78,0x8c,0xf8,0x00,0x00,0x00,0x00,0x7e,0x7e,
1783 0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,
1784 0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x24,
1785 0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
1786 0x00,0x00,0x00,0x00,0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,
1787 0x6c,0x00,0x30,0x7c,0xc0,0x78,0x0c,0xf8,0x30,0x00,0x00,0xc6,0xcc,0x18,0x30,0x66,0xc6,0x00,0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00,
1788 0x60,0x60,0xc0,0x00,0x00,0x00,0x00,0x00,0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00,0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00,0x00,0x66,
1789 0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x30,0x60,0x00,0x00,0x00,0xfc,
1790 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x78,0xcc,0xdc,0xfc,0xec,0xcc,
1791 0x78,0x00,0x30,0xf0,0x30,0x30,0x30,0x30,0xfc,0x00,0x78,0xcc,0x0c,0x38,0x60,0xcc,0xfc,0x00,0x78,0xcc,0x0c,0x38,0x0c,0xcc,0x78,0x00,
1792 0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x00,0xfc,0xc0,0xf8,0x0c,0x0c,0xcc,0x78,0x00,0x38,0x60,0xc0,0xf8,0xcc,0xcc,0x78,0x00,0xfc,0xcc,
1793 0x0c,0x18,0x30,0x60,0x60,0x00,0x78,0xcc,0xcc,0x78,0xcc,0xcc,0x78,0x00,0x78,0xcc,0xcc,0x7c,0x0c,0x18,0x70,0x00,0x00,0x00,0x30,0x30,
1794 0x00,0x30,0x30,0x00,0x00,0x00,0x30,0x30,0x00,0x70,0x30,0x60,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x00,0x00,0x00,0xfc,0x00,0xfc,0x00,
1795 0x00,0x00,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0x78,0xcc,0x0c,0x18,0x30,0x00,0x30,0x00,0x7c,0xc6,0xde,0xde,0xde,0xc0,0x78,0x00,
1796 0x30,0x78,0xcc,0xcc,0xfc,0xcc,0xcc,0x00,0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00,0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00,0xfc,0x6c,
1797 0x66,0x66,0x66,0x6c,0xfc,0x00,0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00,0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00,0x3c,0x66,0xc0,0xc0,
1798 0xce,0x66,0x3e,0x00,0xcc,0xcc,0xcc,0xfc,0xcc,0xcc,0xcc,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,
1799 0x78,0x00,0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00,0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0xc6,0xee,0xfe,0xd6,0xc6,0xc6,0xc6,0x00,
1800 0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x38,0x00,0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00,0x78,0xcc,
1801 0xcc,0xcc,0xdc,0x78,0x1c,0x00,0xfc,0x66,0x66,0x7c,0x78,0x6c,0xe6,0x00,0x78,0xcc,0xe0,0x38,0x1c,0xcc,0x78,0x00,0xfc,0xb4,0x30,0x30,
1802 0x30,0x30,0x78,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xfc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x00,0xc6,0xc6,0xc6,0xd6,0xfe,0xee,
1803 0xc6,0x00,0xc6,0xc6,0x6c,0x38,0x6c,0xc6,0xc6,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x78,0x00,0xfe,0xcc,0x98,0x30,0x62,0xc6,0xfe,0x00,
1804 0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00,0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00,0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00,0x10,0x38,
1805 0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0c,
1806 0x7c,0xcc,0x76,0x00,0xe0,0x60,0x7c,0x66,0x66,0x66,0xbc,0x00,0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00,0x1c,0x0c,0x0c,0x7c,0xcc,0xcc,
1807 0x76,0x00,0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00,0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8,
1808 0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00,0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00,0x18,0x00,0x78,0x18,0x18,0x18,0xd8,0x70,0xe0,0x60,
1809 0x66,0x6c,0x78,0x6c,0xe6,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0xec,0xfe,0xd6,0xc6,0xc6,0x00,0x00,0x00,0xf8,0xcc,
1810 0xcc,0xcc,0xcc,0x00,0x00,0x00,0x78,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0,0x00,0x00,0x76,0xcc,0xcc,0x7c,
1811 0x0c,0x1e,0x00,0x00,0xd8,0x6c,0x6c,0x60,0xf0,0x00,0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00,0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00,
1812 0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0xcc,0xcc,0xcc,0x78,0x30,0x00,0x00,0x00,0xc6,0xc6,0xd6,0xfe,0x6c,0x00,0x00,0x00,
1813 0xc6,0x6c,0x38,0x6c,0xc6,0x00,0x00,0x00,0xcc,0xcc,0xcc,0x7c,0x0c,0xf8,0x00,0x00,0xfc,0x98,0x30,0x64,0xfc,0x00,0x1c,0x30,0x30,0xe0,
1814 0x30,0x30,0x1c,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0xe0,0x30,0x30,0x1c,0x30,0x30,0xe0,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,
1815 0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x18,0x0c,0x78,0x00,0xcc,0x00,0xcc,0xcc,0xcc,0x7e,0x00,
1816 0x1c,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,0x7e,0xc3,0x3c,0x06,0x3e,0x66,0x3f,0x00,0xcc,0x00,0x78,0x0c,0x7c,0xcc,0x7e,0x00,0xe0,0x00,
1817 0x78,0x0c,0x7c,0xcc,0x7e,0x00,0x30,0x30,0x78,0x0c,0x7c,0xcc,0x7e,0x00,0x00,0x00,0x7c,0xc0,0xc0,0x7c,0x06,0x3c,0x7e,0xc3,0x3c,0x66,
1818 0x7e,0x60,0x3c,0x00,0xcc,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,0xe0,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00,0xcc,0x00,0x70,0x30,0x30,0x30,
1819 0x78,0x00,0x7c,0xc6,0x38,0x18,0x18,0x18,0x3c,0x00,0xe0,0x00,0x70,0x30,0x30,0x30,0x78,0x00,0xcc,0x30,0x78,0xcc,0xcc,0xfc,0xcc,0x00,
1820 0x30,0x30,0x00,0x78,0xcc,0xfc,0xcc,0x00,0x1c,0x00,0xfc,0x60,0x78,0x60,0xfc,0x00,0x00,0x00,0x7f,0x0c,0x7f,0xcc,0x7f,0x00,0x3e,0x6c,
1821 0xcc,0xfe,0xcc,0xcc,0xce,0x00,0x78,0xcc,0x00,0x78,0xcc,0xcc,0x78,0x00,0x00,0xcc,0x00,0x78,0xcc,0xcc,0x78,0x00,0x00,0xe0,0x00,0x78,
1822 0xcc,0xcc,0x78,0x00,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0x7e,0x00,0x00,0xe0,0x00,0xcc,0xcc,0xcc,0x7e,0x00,0x00,0xcc,0x00,0xcc,0xcc,0xfc,
1823 0x0c,0xf8,0xc6,0x38,0x7c,0xc6,0xc6,0x7c,0x38,0x00,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x18,0x18,0x7e,0xc0,0xc0,0x7e,0x18,0x18,
1824 0x38,0x6c,0x64,0xf0,0x60,0xe6,0xfc,0x00,0xcc,0xcc,0x78,0xfc,0x30,0xfc,0x30,0x00,0xf0,0xd8,0xd8,0xf4,0xcc,0xde,0xcc,0x0e,0x0e,0x1b,
1825 0x18,0x7e,0x18,0x18,0xd8,0x70,0x1c,0x00,0x78,0x0c,0x7c,0xcc,0x7e,0x00,0x38,0x00,0x70,0x30,0x30,0x30,0x78,0x00,0x00,0x1c,0x00,0x78,
1826 0xcc,0xcc,0x78,0x00,0x00,0x1c,0x00,0xcc,0xcc,0xcc,0x7e,0x00,0x00,0xf8,0x00,0xf8,0xcc,0xcc,0xcc,0x00,0xfc,0x00,0xcc,0xec,0xfc,0xdc,
1827 0xcc,0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x3c,0x66,0x66,0x3c,0x00,0x7e,0x00,0x00,0x30,0x00,0x30,0x60,0xc0,0xcc,0x78,0x00,
1828 0x00,0x00,0x00,0xfc,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0x0c,0x00,0x00,0xc6,0xcc,0xd8,0x3e,0x63,0xce,0x98,0x1f,0xc6,0xcc,
1829 0xd8,0xf3,0x67,0xcf,0x9f,0x03,0x00,0x18,0x00,0x18,0x18,0x3c,0x3c,0x18,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x00,0xcc,0x66,0x33,
1830 0x66,0xcc,0x00,0x00,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0xdc,0x76,0xdc,0x76,0xdc,0x76,
1831 0xdc,0x76,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,
1832 0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x36,0x36,
1833 0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0xf6,0x06,
1834 0xfe,0x00,0x00,0x00,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,
1835 0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,
1836 0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,
1837 0x1f,0x18,0x1f,0x18,0x18,0x18,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,
1838 0x37,0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,
1839 0x36,0x36,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,
1840 0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,
1841 0x36,0x36,0x3f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x00,0x00,0x00,0x00,
1842 0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf7,0x36,0x36,0x36,0x18,0x18,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,
1843 0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
1844 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,
1845 0x76,0xdc,0xc8,0xdc,0x76,0x00,0x00,0x78,0xcc,0xf8,0xcc,0xf8,0xc0,0xc0,0x00,0xfe,0xc6,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0xfe,0x6c,0x6c,
1846 0x6c,0x6c,0x6c,0x00,0xfe,0x66,0x30,0x18,0x30,0x66,0xfe,0x00,0x00,0x00,0x7e,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x66,0x66,0x66,0x66,0x7c,
1847 0x60,0xc0,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x00,0xfc,0x30,0x78,0xcc,0xcc,0x78,0x30,0xfc,0x38,0x6c,0xc6,0xfe,0xc6,0x6c,0x38,0x00,
1848 0x38,0x6c,0xc6,0xc6,0x6c,0x6c,0xee,0x00,0x1c,0x30,0x18,0x7c,0xcc,0xcc,0x78,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x06,0x0c,
1849 0x7e,0xdb,0xdb,0x7e,0x60,0xc0,0x3c,0x60,0xc0,0xfc,0xc0,0x60,0x3c,0x00,0x78,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0x00,0xfc,0x00,0xfc,
1850 0x00,0xfc,0x00,0x00,0x30,0x30,0xfc,0x30,0x30,0x00,0xfc,0x00,0x60,0x30,0x18,0x30,0x60,0x00,0xfc,0x00,0x18,0x30,0x60,0x30,0x18,0x00,
1851 0xfc,0x00,0x0e,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0x70,0x30,0x30,0x00,0xfc,0x00,0x30,0x30,0x00,
1852 0x00,0x72,0x9c,0x00,0x72,0x9c,0x00,0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,
1853 0x00,0x00,0x18,0x00,0x00,0x00,0x0f,0x0c,0x0c,0x0c,0xec,0x6c,0x3c,0x1c,0x78,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x78,0x0c,0x38,0x60,
1854 0x7c,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1857 static public immutable ushort[256*10] kgiFont10
= [
1858 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x4080,0x5280,0x4080,0x5e80,0x4c80,0x2100,0x1e00,
1859 0x0000,0x0000,0x3f00,0x7f80,0x6d80,0x7f80,0x6180,0x7380,0x3f00,0x1e00,0x0000,0x0000,0x3b80,0x7fc0,0x7fc0,0x7fc0,0x3f80,0x1f00,0x0e00,
1860 0x0400,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0e00,0x1f00,0x0e00,0x3f80,0x7fc0,0x3580,
1861 0x0400,0x0e00,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x7fc0,0x3580,0x0400,0x0e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,
1862 0x0c00,0x0000,0x0000,0x0000,0xffc0,0xffc0,0xffc0,0xf3c0,0xe1c0,0xe1c0,0xf3c0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x1e00,0x3300,0x2100,
1863 0x2100,0x3300,0x1e00,0x0000,0x0000,0xffc0,0xffc0,0xe1c0,0xccc0,0xdec0,0xdec0,0xccc0,0xe1c0,0xffc0,0xffc0,0x0000,0x0780,0x0380,0x0780,
1864 0x3e80,0x6600,0x6600,0x6600,0x3c00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3300,0x1e00,0x0c00,0x3f00,0x0c00,0x0000,0x0400,0x0600,0x0700,
1865 0x0500,0x0500,0x0400,0x1c00,0x3c00,0x1800,0x0000,0x0000,0x1f80,0x1f80,0x1080,0x1080,0x1180,0x3380,0x7100,0x2000,0x0000,0x0000,0x0c00,
1866 0x6d80,0x1e00,0x7380,0x7380,0x1e00,0x6d80,0x0c00,0x0000,0x1000,0x1800,0x1c00,0x1e00,0x1f00,0x1e00,0x1c00,0x1800,0x1000,0x0000,0x0100,
1867 0x0300,0x0700,0x0f00,0x1f00,0x0f00,0x0700,0x0300,0x0100,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,
1868 0x0000,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x3300,0x0000,0x0000,0x0000,0x3f80,0x6d80,0x6d80,0x3d80,0x0d80,0x0d80,0x0d80,0x0000,
1869 0x0000,0x0000,0x1f00,0x3000,0x1f00,0x3180,0x1f00,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x7f80,0x7f80,
1870 0x0000,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0xffc0,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x0c00,
1871 0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0600,0x0300,0x7f80,0x0300,
1872 0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x3000,0x7f80,0x3000,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,
1873 0x6000,0x6000,0x7f80,0x0000,0x0000,0x0000,0x0000,0x1100,0x3180,0x7fc0,0x3180,0x1100,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1874 0x1f00,0x3f80,0x7fc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1875 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,0x0c00,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x0000,0x1b00,
1876 0x1b00,0x1b00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1b00,0x1b00,0x7fc0,0x1b00,0x7fc0,0x1b00,0x1b00,0x0000,0x0000,0x0400,
1877 0x1f00,0x3580,0x3400,0x1f00,0x0580,0x3580,0x1f00,0x0400,0x0000,0x0000,0x3180,0x3300,0x0600,0x0c00,0x1980,0x3180,0x0000,0x0000,0x0000,
1878 0x0000,0x1c00,0x3300,0x3300,0x1f80,0x3300,0x3300,0x1d80,0x0000,0x0000,0x0000,0x0e00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,
1879 0x0000,0x0000,0x0600,0x0c00,0x1800,0x1800,0x1800,0x0c00,0x0600,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0600,0x0600,0x0c00,0x1800,
1880 0x0000,0x0000,0x0000,0x0000,0x3300,0x1e00,0x7f80,0x1e00,0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x3f00,0x0c00,0x0c00,
1881 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,
1882 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0180,0x0300,0x0600,0x0c00,
1883 0x1800,0x3000,0x6000,0x0000,0x0000,0x0000,0x1f00,0x3380,0x3780,0x3f80,0x3d80,0x3980,0x1f00,0x0000,0x0000,0x0000,0x0c00,0x1c00,0x0c00,
1884 0x0c00,0x0c00,0x0c00,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x0180,0x0f00,0x1800,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,
1885 0x0180,0x0700,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0700,0x0f00,0x1b00,0x3300,0x3f80,0x0300,0x0780,0x0000,0x0000,0x0000,0x3f80,
1886 0x3000,0x3000,0x3f00,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x3000,0x3f00,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1887 0x3f80,0x3180,0x0180,0x0300,0x0600,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x1f00,0x3180,0x3180,0x1f00,0x0000,0x0000,
1888 0x0000,0x1f00,0x3180,0x3180,0x1f80,0x0180,0x0300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0000,
1889 0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0300,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0300,
1890 0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0300,0x0600,0x0c00,
1891 0x1800,0x0000,0x0000,0x0000,0x1e00,0x3300,0x0300,0x0300,0x0600,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x3f00,0x6180,0x6780,0x6d80,0x6780,
1892 0x6000,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,
1893 0x3180,0x3180,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3e00,0x3300,0x3180,
1894 0x3180,0x3180,0x3300,0x3e00,0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3f00,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x3f80,0x3000,
1895 0x3000,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3380,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,
1896 0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,
1897 0x0700,0x0300,0x0300,0x0300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3300,0x3e00,0x3300,0x3180,0x3180,0x0000,0x0000,
1898 0x0000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x6180,0x7380,0x7f80,0x6d80,0x6180,0x6180,0x6180,0x0000,
1899 0x0000,0x0000,0x3180,0x3980,0x3d80,0x3780,0x3380,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3180,0x1f00,
1900 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3380,
1901 0x1f00,0x0380,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3300,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x1f00,0x0180,
1902 0x3180,0x1f00,0x0000,0x0000,0x0000,0x7f80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,
1903 0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x6180,0x6180,0x6180,
1904 0x6d80,0x7f80,0x7380,0x6180,0x0000,0x0000,0x0000,0x6180,0x3300,0x1e00,0x0c00,0x1e00,0x3300,0x6180,0x0000,0x0000,0x0000,0x6180,0x6180,
1905 0x3300,0x1e00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3f80,0x0300,0x0600,0x0c00,0x1800,0x3000,0x3f80,0x0000,0x0000,0x0000,0x1e00,
1906 0x1800,0x1800,0x1800,0x1800,0x1800,0x1e00,0x0000,0x0000,0x0000,0x6000,0x3000,0x1800,0x0c00,0x0600,0x0300,0x0000,0x0000,0x0000,0x0000,
1907 0x1e00,0x0600,0x0600,0x0600,0x0600,0x0600,0x1e00,0x0000,0x0000,0x0000,0x0400,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,
1908 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0x0000,0x0000,0x1c00,0x0c00,0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,
1909 0x0000,0x0000,0x0000,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x3000,0x3000,0x3f00,0x3180,0x3180,0x3180,0x3f00,
1910 0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0180,0x0180,0x1f80,0x3180,0x3180,0x3180,
1911 0x1f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x1800,0x3e00,0x1800,
1912 0x1800,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x3000,0x3000,0x3f00,0x3180,
1913 0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x0600,0x0000,0x0e00,
1914 0x0600,0x0600,0x0600,0x0600,0x0600,0x1c00,0x0000,0x3000,0x3000,0x3180,0x3300,0x3e00,0x3300,0x3180,0x0000,0x0000,0x0000,0x1c00,0x0c00,
1915 0x0c00,0x0c00,0x0c00,0x0c00,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x3300,0x7f80,0x6d80,0x6d80,0x6180,0x0000,0x0000,0x0000,0x0000,
1916 0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1917 0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x1f80,0x0180,0x01c0,0x0000,
1918 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3000,0x1f00,0x0180,0x3f00,0x0000,
1919 0x0000,0x0000,0x1800,0x1800,0x3e00,0x1800,0x1800,0x1800,0x0f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,
1920 0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x6180,0x6d80,0x6d80,0x7f80,
1921 0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x1b00,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,
1922 0x1f80,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0600,0x0c00,0x1800,0x3f00,0x0000,0x0000,0x0000,0x0e00,0x1800,0x1800,0x3000,
1923 0x1800,0x1800,0x0e00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x1c00,0x0600,0x0600,
1924 0x0300,0x0600,0x0600,0x1c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1925 0x1b00,0x3180,0x3180,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0000,0x1b00,
1926 0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0e00,
1927 0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,
1928 0x0c00,0x0600,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,
1929 0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,
1930 0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3f80,0x3000,
1931 0x1f00,0x0000,0x0000,0x0000,0x3600,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x1c00,0x3600,0x0000,0x1c00,0x0c00,0x0c00,
1932 0x0c00,0x1e00,0x0000,0x0000,0x1800,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,
1933 0x3f80,0x3180,0x3180,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x3180,0x3f80,0x3180,0x3180,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3f80,
1934 0x3000,0x3f00,0x3000,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x0ec0,0x3fc0,0x6e00,0x3b80,0x0000,0x0000,0x0000,0x1f80,0x3600,
1935 0x6600,0x7f80,0x6600,0x6600,0x6780,0x0000,0x0000,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x1b00,
1936 0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0e00,
1937 0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x0600,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,
1938 0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,
1939 0x0000,0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0000,0x0000,0x0400,0x1f00,0x3580,0x3400,0x3580,0x1f00,
1940 0x0400,0x0000,0x0000,0x0f00,0x1980,0x1800,0x3e00,0x1800,0x1800,0x3000,0x3f80,0x0000,0x0000,0x6180,0x6180,0x3300,0x1e00,0x3f00,0x0c00,
1941 0x3f00,0x0c00,0x0000,0x0000,0x7f00,0x6180,0x6d80,0x6d80,0x7f00,0x6c00,0x6c00,0x6700,0x0000,0x0000,0x0700,0x0c00,0x0c00,0x1e00,0x0c00,
1942 0x0c00,0x0c00,0x3800,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x1800,0x0000,0x1c00,0x0c00,
1943 0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3180,
1944 0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x1d80,0x3700,0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x1d80,0x3700,0x0000,
1945 0x3980,0x3d80,0x3780,0x3380,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0300,0x1f00,0x3300,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,
1946 0x3300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0c00,0x1800,0x3000,0x3000,0x3300,0x1e00,0x0000,0x0000,
1947 0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f80,0x0180,0x0180,0x0180,0x0000,0x0000,
1948 0x0000,0x2080,0x2100,0x2200,0x2400,0x0b00,0x1180,0x2300,0x4380,0x0000,0x0000,0x2080,0x2100,0x2200,0x2400,0x0a80,0x1280,0x2380,0x4080,
1949 0x0000,0x0000,0x0c00,0x0000,0x0c00,0x0c00,0x1e00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x1980,0x3300,0x6600,0x3300,0x1980,0x0000,
1950 0x0000,0x0000,0x0000,0x0000,0x6600,0x3300,0x1980,0x3300,0x6600,0x0000,0x0000,0x0000,0x2200,0x8880,0x2200,0x8880,0x2200,0x8880,0x2200,
1951 0x8880,0x2200,0x8880,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0xbb80,0xeec0,0xbb80,0xeec0,0xbb80,0xeec0,
1952 0xbb80,0xeec0,0xbb80,0xeec0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,
1953 0xfc00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,
1954 0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0x0000,0x0000,0xff00,0xff00,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xfc00,
1955 0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0xf300,0xf300,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,
1956 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xff00,0xff00,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,
1957 0x3300,0xf300,0xf300,0x0300,0x0300,0xff00,0xff00,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xff00,0xff00,0x0000,0x0000,0x0000,0x0000,
1958 0x1800,0x1800,0xf800,0xf800,0x1800,0x1800,0xf800,0xf800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfc00,0xfc00,0x0c00,0x0c00,0x0c00,
1959 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1960 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,
1961 0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,
1962 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,0x33c0,
1963 0x33c0,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,
1964 0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0xffc0,
1965 0xffc0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x0000,0x0000,
1966 0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x0c00,
1967 0x0c00,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1968 0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x3300,0x3300,0x3300,
1969 0x3300,0x3300,0x3300,0x3300,0x3300,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,
1970 0x0000,0x0000,0x0000,0x0000,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,0x3300,
1971 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1972 0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0fc0,
1973 0x0fc0,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1974 0x0000,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0x07c0,0x07c0,0x07c0,
1975 0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1976 0x0000,0x1d80,0x3700,0x3200,0x3700,0x1d80,0x0000,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3600,0x3300,0x3180,0x3700,0x3000,0x0000,0x0000,
1977 0x3f80,0x3180,0x3000,0x3000,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,
1978 0x0000,0x3f80,0x1800,0x0c00,0x0600,0x0c00,0x1800,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3600,0x3300,0x3300,0x1e00,0x0000,
1979 0x0000,0x0000,0x0000,0x0000,0x6300,0x6300,0x6700,0x7d80,0x6000,0x6000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0c00,0x0c00,0x0c00,0x0600,
1980 0x0000,0x0000,0x0000,0x1e00,0x0c00,0x3f00,0x6d80,0x6d80,0x3f00,0x0c00,0x1e00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3f00,0x3300,0x3300,
1981 0x1e00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x1b00,0x3b80,0x0000,0x0000,0x0000,0x1f00,0x0c00,0x0600,0x1f00,0x3180,
1982 0x3180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x66c0,0x64c0,0x6cc0,0x3b80,0x0000,0x0000,0x0000,0x0000,0x0180,0x3f00,0x6780,
1983 0x6d80,0x7980,0x3f00,0x6000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3000,0x1e00,0x3000,0x1f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,
1984 0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,
1985 0x3f00,0x0c00,0x0c00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0000,0x3f00,0x0000,0x0000,0x0000,0x1800,
1986 0x0c00,0x0600,0x0c00,0x1800,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0700,0x0d80,0x0d80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,
1987 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x6c00,0x6c00,0x3800,0x0000,0x0000,0x0000,0x0c00,0x0000,0x3f00,0x0000,0x0c00,0x0000,0x0000,0x0000,
1988 0x0000,0x3800,0x6d80,0x0700,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0e00,0x1b00,0x1b00,0x0e00,0x0000,0x0000,0x0000,0x0000,
1989 0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0000,0x0000,
1990 0x0000,0x0000,0x0000,0x07c0,0x0600,0x0600,0x6600,0x3600,0x1e00,0x0e00,0x0600,0x0200,0x0000,0x3e00,0x3300,0x3300,0x3300,0x3300,0x0000,
1991 0x0000,0x0000,0x0000,0x0000,0x1e00,0x0300,0x0e00,0x1800,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,0x1e00,0x1e00,
1992 0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1996 // bits 4..7: lshift
1997 public immutable ubyte[256] kgiFont6PropWidth
= () {
1999 foreach (immutable cnum
; 0..256) {
2000 import core
.bitop
: bsf, bsr;
2002 (cnum
>= 32 && cnum
<= 127) ||
2003 (cnum
>= 143 && cnum
<= 144) ||
2004 (cnum
>= 166 && cnum
<= 167) ||
2005 (cnum
>= 192 && cnum
<= 255);
2009 foreach (immutable dy
; 0..8) {
2010 immutable b
= kgiFont6
[cnum
*8+dy
];
2012 immutable mn
= 7-bsr(b
);
2013 if (mn
< shift
) shift
= mn
;
2018 foreach (immutable dy
; 0..8) {
2019 immutable b
= (kgiFont6
[cnum
*8+dy
]<<shift
);
2020 immutable cwdt
= (b ?
8-bsf(b
) : 0);
2021 if (cwdt
> wdt
) wdt
= cast(ubyte)cwdt
;
2024 case 0: wdt
= 8; break; // 8px space
2025 case 32: wdt
= 5; break; // 5px space
2026 case 17: .. case 27: wdt
= 8; break; // single frames
2027 case 48: .. case 57: wdt
= 5; break; // digits are monospaced
2028 case 127: .. case 142: wdt
= 8; break; // filled frames
2029 case 145: .. case 151: wdt
= 8; break; // filled frames
2030 case 155: .. case 159: wdt
= 8; break; // filled frames
2033 res
[cnum
] = (wdt
&0x0f)|
((shift
<<4)&0xf0);
2039 // bits 4..7: lshift
2040 public immutable ubyte[256] kgiFont8PropWidth
= () {
2042 foreach (immutable cnum
; 0..256) {
2043 import core
.bitop
: bsf, bsr;
2045 (cnum
>= 32 && cnum
<= 127) ||
2046 (cnum
>= 143 && cnum
<= 144) ||
2047 (cnum
>= 166 && cnum
<= 167) ||
2048 (cnum
>= 192 && cnum
<= 255);
2052 foreach (immutable dy
; 0..8) {
2053 immutable b
= kgiFont8
[cnum
*8+dy
];
2055 immutable mn
= 7-bsr(b
);
2056 if (mn
< shift
) shift
= mn
;
2061 foreach (immutable dy
; 0..8) {
2062 immutable b
= (kgiFont8
[cnum
*8+dy
]<<shift
);
2063 immutable cwdt
= (b ?
8-bsf(b
) : 0);
2064 if (cwdt
> wdt
) wdt
= cast(ubyte)cwdt
;
2067 case 0: wdt
= 8; break; // 8px space
2068 case 32: wdt
= 5; break; // 5px space
2069 case 48: .. case 57: wdt
= 5; break; // digits are monospaced
2070 case 176: .. case 223: wdt
= 8; break; // pseudographics (frames, etc)
2073 res
[cnum
] = (wdt
&0x0f)|
((shift
<<4)&0xf0);
2079 // ////////////////////////////////////////////////////////////////////////// //
2082 const(char)[] sdrGetPart(string typepfx
) (const(char)[] s
) nothrow @trusted @nogc {
2083 // skips prefix "---"
2084 static usize
findMark(string at
) (const(char)[] s
, uint idx
=0) nothrow @trusted @nogc {
2085 while (idx
< s
.length
) {
2086 if (idx
== 0 || s
.ptr
[idx
-1] == '\n') {
2087 while (idx
< s
.length
&& (s
.ptr
[idx
] == ' ' || s
.ptr
[idx
] == '\t')) ++idx
;
2088 if (s
.length
-idx
>= 3 && s
.ptr
[idx
] == '-' && s
.ptr
[idx
+1] == '-' && s
.ptr
[idx
+2] == '-') {
2089 static if (at
== "start") {
2090 while (idx
> 0 && s
.ptr
[idx
-1] != '\n') --idx
;
2091 } else static if (at
== "end") {
2093 while (idx
< s
.length
&& s
.ptr
[idx
] == '-') ++idx
;
2094 while (idx
< s
.length
&& (s
.ptr
[idx
] == ' ' || s
.ptr
[idx
] == '\t')) ++idx
;
2096 static assert(0, "wtf?!");
2106 usize idx
= findMark
!"end"(s
);
2107 while (idx
< s
.length
) {
2108 if (s
.length
-idx
>= typepfx
.length
&& s
[idx
..idx
+typepfx
.length
] == typepfx
) {
2109 while (idx
< s
.length
&& s
.ptr
[idx
] != '\n') ++idx
;
2110 while (idx
< s
.length
&& s
.ptr
[idx
] <= ' ') ++idx
;
2111 if (idx
>= s
.length
) return null;
2112 auto eidx
= findMark
!"start"(s
, idx
);
2113 if (eidx
> s
.length
) eidx
= s
.length
;
2114 while (eidx
> idx
&& s
.ptr
[eidx
-1] <= ' ') --eidx
;
2115 return (eidx
> idx ? s
[idx
..eidx
] : null);
2117 while (idx
< s
.length
&& s
.ptr
[idx
] != '\n') ++idx
;
2118 idx
= findMark
!"end"(s
, idx
);
2125 // find var id: glGetUniformLocation(prg, bufasciiz.ptr)
2126 // set var: glUniformXXX()
2128 // returns 0 or programid
2129 uint compileShaders (const(char)[] src
) nothrow @trusted {
2133 GLuint fsid
= 0, vsid
= 0;
2135 auto fragsrc
= sdrGetPart
!"frag"(src
);
2136 auto vertsrc
= sdrGetPart
!"vert"(src
);
2138 if (fragsrc
.length
== 0 && vertsrc
.length
== 0) return 0;
2140 if (fragsrc
.length
) {
2141 fsid
= createShader
!GL_FRAGMENT_SHADER(fragsrc
);
2142 if (fsid
== 0) return 0;
2145 if (vertsrc
.length
) {
2146 vsid
= createShader
!GL_VERTEX_SHADER(vertsrc
);
2148 if (fsid
!= 0) glDeleteShader(fsid
);
2153 prg
= glCreateProgram();
2155 if (fsid
!= 0) glDeleteShader(fsid
);
2156 if (vsid
!= 0) glDeleteShader(vsid
);
2157 conwriteln("GLKGI ERROR: can't create shader program.");
2161 if (fsid
) glAttachShader(prg
, fsid
);
2162 if (vsid
) glAttachShader(prg
, vsid
);
2166 glGetProgramiv(prg
, GL_LINK_STATUS
, &lres
);
2167 if (lres
!= GL_TRUE
) {
2168 glDeleteProgram(prg
);
2169 if (fsid
!= 0) glDeleteShader(fsid
);
2170 if (vsid
!= 0) glDeleteShader(vsid
);
2171 conwriteln("GLKGI ERROR: can't link shader program.");
2179 // returns 0 or shaderid
2180 uint createShader(uint type
) (const(char)[] src
) nothrow @trusted {
2183 auto shaderId
= glCreateShader(type
);
2185 conwriteln("GLKGI ERROR: can't create shader.");
2188 auto sptr
= src
.ptr
;
2189 GLint slen
= cast(int)src
.length
;
2190 glShaderSource(shaderId
, 1, &sptr
, &slen
);
2191 glCompileShader(shaderId
);
2193 glGetShaderiv(shaderId
, GL_COMPILE_STATUS
, &success
);
2194 if (!success || showShaderWarnings
) {
2195 import core
.stdc
.stdlib
: malloc
, free
;
2197 glGetShaderiv(shaderId
, GL_INFO_LOG_LENGTH
, &logSize
);
2199 auto logStrZ
= cast(GLchar
*)malloc(logSize
);
2200 if (logStrZ
!is null) {
2201 //import core.stdc.stdio : printf;
2202 scope(exit
) free(logStrZ
);
2203 glGetShaderInfoLog(shaderId
, logSize
, null, logStrZ
);
2204 if (logSize
> 0 && logStrZ
[logSize
-1] == 0) --logSize
;
2205 //printf("shader '%.*s' compilation messages:\n%s\n", cast(uint)ashaderName.length, ashaderName.ptr, logStrZ);
2206 conwriteln("GLKGI: shader compilation messages:\n", logStrZ
[0..logSize
]);
2211 glDeleteShader(shaderId
);
2212 conwriteln("GLKGI ERROR: can't compile shader.");
2219 // ////////////////////////////////////////////////////////////////////////// //
2221 static string sdrScanlineSrc
= q
{
2225 uniform sampler2D tex
;
2228 vec4 color
= texture2D(tex
, gl_TexCoord
[0].xy
);
2229 if (mod(floor(gl_FragCoord
.y
), 2) == 1) { color
.x
*= 0.75; color
.y
*= 0.75; color
.z
*= 0.75; }
2230 gl_FragColor
= color
;
2237 gl_TexCoord
[0] = gl_MultiTexCoord0
;
2238 //gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;
2239 gl_Position
= gl_ProjectionMatrix
*gl_Vertex
;
2244 // ////////////////////////////////////////////////////////////////////////// //
2245 // default cursor (hi, Death Track!)
2246 private enum defaultCurWidth
= 17;
2247 private enum defaultCurHeight
= 23;
2248 private static immutable ubyte[defaultCurWidth
*defaultCurHeight
] defaultCurImg
= [
2249 0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2250 0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
2251 1,0,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
2252 1,1,3,3,2,2,0,0,0,0,0,0,0,0,0,0,0,
2253 1,1,3,3,4,2,2,0,0,0,0,0,0,0,0,0,0,
2254 1,1,3,3,4,4,2,2,0,0,0,0,0,0,0,0,0,
2255 1,1,3,3,4,4,4,2,2,0,0,0,0,0,0,0,0,
2256 1,1,3,3,4,4,4,4,2,2,0,0,0,0,0,0,0,
2257 1,1,3,3,4,4,4,5,6,2,2,0,0,0,0,0,0,
2258 1,1,3,3,4,4,5,6,7,5,2,2,0,0,0,0,0,
2259 1,1,3,3,4,5,6,7,5,4,5,2,2,0,0,0,0,
2260 1,1,3,3,5,6,7,5,4,5,6,7,2,2,0,0,0,
2261 1,1,3,3,6,7,5,4,5,6,7,7,7,2,2,0,0,
2262 1,1,3,3,7,5,4,5,6,7,7,7,7,7,2,2,0,
2263 1,1,3,3,5,4,5,6,8,8,8,8,8,8,8,8,2,
2264 1,1,3,3,4,5,6,3,8,8,8,8,8,8,8,8,8,
2265 1,1,3,3,5,6,3,3,1,1,1,1,1,1,1,0,0,
2266 1,1,3,3,6,3,3,1,1,1,1,1,1,1,1,0,0,
2267 1,1,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,
2268 1,1,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
2269 1,1,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
2270 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2271 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2273 private static immutable VColor
[9] defaultCurPal
= [
2274 rgbacol( 0, 0, 0, 0),
2275 rgbacol( 0, 0, 0,127),
2276 rgbacol( 85,255,255,255),
2277 rgbacol( 85, 85,255,255),
2278 rgbacol(255, 85, 85,255),
2279 rgbacol(170, 0,170,255),
2280 rgbacol( 85, 85, 85,255),
2281 rgbacol( 0, 0, 0,255),
2282 rgbacol( 0, 0,170,255),