1 /* coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv
.glkgi
/*is aliced*/;
21 import std
.concurrency
;
23 public import arsd
.simpledisplay
;
24 //public import arsd.color;
25 //public import arsd.image;
28 public import iv
.cmdcongl
;
31 //version=glkgi_rgba; // default, has priority
34 version(BigEndian
) static assert(0, "sorry, big-endian platforms aren't supported yet");
37 public enum KGIRGBA
= true;
38 } else version(glkgi_bgra
) {
39 public enum KGIRGBA
= false;
41 public enum KGIRGBA
= true;
45 // ////////////////////////////////////////////////////////////////////////// //
46 public enum kgiMaxCurW
= 64;
47 public enum kgiMaxCurH
= 64;
50 // ////////////////////////////////////////////////////////////////////////// //
51 // 0:b; 1:g; 2:r; 3: nothing
52 private __gshared
int vbufW
= 800, vbufH
= 600;
53 __gshared
uint* vbuf
; // see KGIRGBA
54 __gshared
uint* vbufsaved
; // saved before updating texture
55 private __gshared
uint* vcurbuf
;
56 private __gshared
bool blit2x
= false;
57 //private enum BlitType { normal, bw, green, red }
58 //private __gshared BlitType blitType = BlitType.normal;
59 private __gshared
bool scanlines
= false;
60 private __gshared SimpleWindow vbwin
;
61 private __gshared
uint vbTexId
= 0;
62 private __gshared
uint vbCurTexId
= 0;
63 private __gshared
uint sdrScanlineId
= 0;
64 private __gshared
int shaderVersionOk
= -1; // <0: not checked; 0: fail; >0: ok
65 private __gshared string kgiTitle
= "KGI Graphics";
66 private __gshared
uint vupcounter
= 0;
67 private __gshared
uint vupcounterlast
= 0;
68 private shared bool updateTexture
= true;
69 private shared bool updateCurTexture
= true;
70 private __gshared
uint fps
= 35; // average FPS
71 private __gshared
bool showShaderWarnings
= false;
73 private __gshared
bool oldogl
= false;
75 private __gshared
int mcurX
= 0, mcurY
= 0;
76 private __gshared
int mhotX
= 0, mhotY
= 0;
77 private __gshared
int mcurHidden
= 1;
79 private shared bool vWantMotionEvents
= false;
80 private shared bool vWantCharEvents
= false;
83 public @property bool kgiMotionEvents () nothrow @trusted @nogc { pragma(inline
, true); return atomicLoad(vWantMotionEvents
); } ///
84 public @property bool kgiCharEvents () nothrow @trusted @nogc { pragma(inline
, true); return atomicLoad(vWantCharEvents
); } ///
86 public @property void kgiMotionEvents (bool v
) nothrow @trusted @nogc { pragma(inline
, true); atomicStore(vWantMotionEvents
, v
); } ///
87 public @property void kgiCharEvents (bool v
) nothrow @trusted @nogc { pragma(inline
, true); atomicStore(vWantCharEvents
, v
); } ///
89 public @property int kgiWidth () nothrow @trusted @nogc { pragma(inline
, true); return vbufW
; }
90 public @property int kgiHeight () nothrow @trusted @nogc { pragma(inline
, true); return vbufH
; }
93 //FIXME! turn this to proper setter
94 public __gshared
bool delegate () onKGICloseRequest
;
97 shared static this () {
98 conRegVar
!blit2x("v_scale2x", "video window scale");
99 conRegVar
!scanlines("v_scanlines", "emulate old CRT scanline effect");
100 conRegVar
!vbufW(64, 4096, "v_width", "video window width");
101 conRegVar
!vbufH(64, 4096, "v_height", "video window height");
102 conRegVar
!fps(1, 60, "v_fps", "video update rate");
103 conRegVar
!kgiTitle("v_title", "video window title");
104 conRegVar
!showShaderWarnings("v_shader_warnings", "show warnings from shader compilation");
105 conRegVar
!oldogl("v_legacygl", "set to true to use legacy OpenGL");
109 private void setUpdateTextureFlag () {
110 pragma(inline
, true);
114 if (vupcounterlast
!= c
) {
116 vbufsaved
[0..vbufW
*vbufH
] = vbuf
[0..vbufW
*vbufH
];
118 atomicStore(updateTexture
, true);
124 public void kgiHideCursor () {
128 scope(exit
) consoleUnlock();
130 csc
= (vbwin
!is null && (mcurHidden
== -1 || mcurHidden
== 1));
132 if (csc
) vbwin
.showCursor();
137 public void kgiShowCursor () {
141 scope(exit
) consoleUnlock();
143 csc
= (vbwin
!is null && mcurHidden
== 0);
145 if (csc
) vbwin
.hideCursor();
150 public void kgiSetCursor (int wdt
, int hgt
, const(VColor
)[] img
, int hotx
=0, int hoty
=0) nothrow @trusted @nogc {
152 scope(exit
) consoleUnlock();
155 if (vcurbuf
is null) return;
156 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
157 if (wdt
< 1 || hgt
< 1) return;
158 foreach (immutable dy
; 0..64) {
159 if (dy
>= hgt
) break;
160 foreach (immutable dx
; 0..64) {
161 if (dx
>= wdt
) break;
163 if (sp
>= img
.length
) break;
164 vcurbuf
[dy
*kgiMaxCurW
+dx
] = img
.ptr
[sp
];
167 atomicStore(updateCurTexture
, true);
171 private void unpackDefaultCursor () nothrow @trusted @nogc {
174 if (vcurbuf
is null) return;
175 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
176 foreach (immutable dy
; 0..defaultCurHeight
) {
177 foreach (immutable dx
; 0..defaultCurWidth
) {
178 uint sp
= dy
*defaultCurWidth
+dx
;
179 vcurbuf
[dy
*kgiMaxCurW
+dx
] = defaultCurPal
.ptr
[defaultCurImg
.ptr
[sp
]];
186 public void kgiSetDefaultCursor () nothrow @trusted @nogc {
188 scope(exit
) consoleUnlock();
189 unpackDefaultCursor();
190 atomicStore(updateCurTexture
, true);
194 public void kgiSetBlankCursor () nothrow @trusted @nogc {
196 scope(exit
) consoleUnlock();
198 if (vcurbuf
is null) return;
199 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
200 atomicStore(updateCurTexture
, true);
204 // ////////////////////////////////////////////////////////////////////////// //
206 public struct KGIEvent
{
207 enum Type
{ None
, Key
, Mouse
, Char
, Close
}
208 Type type
= Type
.None
;
214 static createClose () pure nothrow @trusted @nogc {
216 ev
.type
= KGIEvent
.Type
.Close
;
219 @property const pure nothrow @trusted @nogc:
220 bool isMouse () { pragma(inline
, true); return (type
== Type
.Mouse
); }
221 bool isKey () { pragma(inline
, true); return (type
== Type
.Key
); }
222 bool isChar () { pragma(inline
, true); return (type
== Type
.Char
); }
223 bool isNone () { pragma(inline
, true); return (type
== Type
.None
); }
224 bool isClose () { pragma(inline
, true); return (type
== Type
.Close
); }
228 private __gshared KGIEvent
[] evbuf
;
229 private __gshared
uint evbufused
;
233 public bool kgiHasEvent () {
235 scope(exit
) consoleUnlock();
236 version(LDC
) {} else atomicFence();
237 if (vupcounter
) setUpdateTextureFlag(); // just in case
238 return (evbufused
> 0 || vbwin
is null); // no vbwin --> always has Quit
243 public KGIEvent
kgiPeekEvent () {
245 scope(exit
) consoleUnlock();
246 version(LDC
) {} else atomicFence();
247 if (!atomicLoad(kgiThreadStarted
)) return KGIEvent
.createClose();
248 if (vupcounter
) setUpdateTextureFlag(); // just in case
249 if (evbufused
> 0) return evbuf
[0];
250 if (vbwin
is null) return KGIEvent(KGIEvent
.Type
.Close
);
256 public KGIEvent
kgiGetEvent () {
259 version(LDC
) {} else atomicFence();
260 if (vupcounter
) setUpdateTextureFlag(); // just in case
264 scope(exit
) consoleUnlock();
265 if (!atomicLoad(kgiThreadStarted
)) return KGIEvent
.createClose();
269 import core
.stdc
.string
: memmove
;
270 memmove(evbuf
.ptr
, evbuf
.ptr
+1, KGIEvent
.sizeof
*(evbufused
-1));
273 evbuf
[evbufused
].type
= KGIEvent
.Type
.None
;
275 } else if (vbwin
is null) {
276 return KGIEvent(KGIEvent
.Type
.Close
);
279 Thread
.sleep(10.msecs
); //FIXME
284 private void pushEventIntr (ref KGIEvent ev
) {
285 if (evbufused
>= evbuf
.length
) evbuf
.length
+= 256;
286 evbuf
[evbufused
++] = ev
;
291 public void kgiPushEvent (KeyEvent e
) {
293 ev
.type
= KGIEvent
.Type
.Key
;
296 scope(exit
) consoleUnlock();
301 public void kgiPushEvent (MouseEvent e
) {
303 ev
.type
= KGIEvent
.Type
.Mouse
;
306 scope(exit
) consoleUnlock();
311 public void kgiPushEvent (dchar ch
) {
313 ev
.type
= KGIEvent
.Type
.Char
;
316 scope(exit
) consoleUnlock();
321 public void kgiPushCloseEvent(bool clearQueue
=true) () {
323 ev
.type
= KGIEvent
.Type
.Close
;
325 scope(exit
) consoleUnlock();
326 static if (clearQueue
) evbufused
= 0;
331 /// remove all keypresses from input queue
332 public void kgiKeyFlush () {
333 uint sidx
= 0, didx
= 0;
335 scope(exit
) consoleUnlock();
336 if (!atomicLoad(kgiThreadStarted
)) return;
337 while (sidx
< evbufused
) {
338 if (!evbuf
[sidx
].isKey
) {
339 if (sidx
!= didx
) evbuf
[didx
] = evbuf
[sidx
];
348 /// wait for keypress (and eat it)
349 public KGIEvent
kgiWaitKey () {
351 auto ev
= kgiGetEvent();
354 scope(exit
) consoleUnlock();
359 if (!ev
.isKey
) continue;
360 if (!ev
.k
.pressed
) continue;
366 /// flush drawing buffer (copy it to actual screen)
367 public void kgiFlush () {
368 setUpdateTextureFlag();
369 while (atomicLoad(updateTexture
)) {
372 if (!atomicLoad(kgiThreadStarted
)) return;
373 Thread
.sleep(1.msecs
);
378 // ////////////////////////////////////////////////////////////////////////// //
380 public void kgiDeinit () {
385 private void kgiThread (Tid starterTid
) {
387 vbwin
= new SimpleWindow(vbufW
*(blit2x ?
2 : 1), vbufH
*(blit2x ?
2 : 1), kgiTitle
, OpenGlOptions
.yes
, Resizability
.fixedSize
);
388 if (mcurHidden
== 0) vbwin
.hideCursor();
390 static if (is(typeof(openGLContextFallbackActivated
))) {
391 if (openGLContextFallbackActivated
) oldogl
= true;
394 vbwin
.redrawOpenGlScene
= delegate () {
402 vbwin
.closeQuery
= delegate () {
403 if (onKGICloseRequest
!is null) try { if (!onKGICloseRequest()) return; } catch (Throwable e
) {}
408 vbwin
.visibleForTheFirstTime
= delegate () {
409 vbwin
.setAsCurrentOpenGlContext();
412 import core.stdc.stdio;
413 printf("GL version: %s\n", glGetString(GL_VERSION));
415 glGetIntegerv(GL_MAJOR_VERSION, &h);
416 glGetIntegerv(GL_MINOR_VERSION, &l);
417 printf("version: %d.%d\n", h, l);
418 printf("shader version: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
420 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &svcount);
422 printf("%d shader versions supported:\n", svcount);
423 foreach (GLuint n; 0..svcount) printf(" %d: %s\n", n, glGetStringi(GL_SHADING_LANGUAGE_VERSION, n));
427 glGetIntegerv(GL_NUM_EXTENSIONS, &ecount);
429 printf("%d extensions supported:\n", ecount);
430 foreach (GLuint n; 0..ecount) printf(" %d: %s\n", n, glGetStringi(GL_EXTENSIONS, n));
436 glconInit(vbufW
, vbufH
, (blit2x ?
2 : 1));
437 glgfxUpdateTexture();
438 vbwin
.redrawOpenGlSceneNow();
440 send(starterTid
, 42);
443 bool receiveMessages () {
446 import core
.time
: Duration
;
447 auto got
= receiveTimeout(
448 Duration
.zero
, // don't wait
449 (OwnerTerminated e
) {
450 //conwriteln("OWNER IS TERMINATED!");
454 conwriteln("WARNING: unknown thread message received and ignored: ", v
.toString
);
457 if (!got
) break; // no more messages
462 bool processConsoleCommands () {
464 scope(exit
) consoleUnlock();
465 auto ccwasempty
= conQueueEmpty();
467 return (!ccwasempty
&& conQueueEmpty());
470 bool lastConVisible
= isConsoleVisible
;
472 //FIXME: FPS time calculations are totally broken
474 uint rfps
= (fps
< 0 ?
1 : fps
> 120 ?
120 : fps
);
475 uint msfull
= 1000/fps
;
476 auto lastFrameTime
= MonoTime
.currTime
;
477 auto lastCursorTime
= MonoTime
.currTime
;
480 // windoze eats shit! if we won't awake event loop here, it will fuck itself.
481 import core
.sys
.windows
.winuser
;
482 PostMessage(null, WM_USER
, 0, 0);
487 //version(Windows) { {import core.stdc.stdio : printf; printf("xxx\n"); } }
488 if (vbwin
.closed
) return;
489 if (isQuitRequested
) { kgiPushCloseEvent(); vbwin
.close(); return; }
490 if (receiveMessages()) { kgiPushCloseEvent(); vbwin
.close(); return; }
491 auto conexeced
= processConsoleCommands();
492 bool convis
= isConsoleVisible
;
493 if (lastConVisible
!= convis || conexeced
) {
494 lastConVisible
= isConsoleVisible
;
495 setUpdateTextureFlag();
497 scope(exit
) consoleUnlock();
498 if (evbufused
== 0) {
503 bool newFrame
= false;
504 auto ctt
= MonoTime
.currTime
;
505 if (lastConVisible
!= convis || conexeced
) {
508 // visible console should be updated at least 35 times per second
509 newFrame
= ((ctt
-lastFrameTime
).total
!"msecs" >= 28);
512 if ((ctt
-lastFrameTime
).total
!"msecs" >= msfull
) newFrame
= true;
514 //if (newFrame) atomicStore(updateTexture, true);
515 if (newFrame ||
atomicLoad(updateTexture
)) {
517 lastCursorTime
= ctt
;
518 glgfxUpdateTexture();
519 //version(Windows) { {import core.stdc.stdio : printf; printf("000\n"); } }
520 vbwin
.redrawOpenGlSceneNow();
521 } else if (mcurHidden
== 0) {
522 // ~60 FPS for mouse cursor
523 if ((ctt
-lastCursorTime
).total
!"msecs" >= 16) {
524 lastCursorTime
= ctt
;
525 glgfxUpdateCurTexture();
526 //version(Windows) { {import core.stdc.stdio : printf; printf("001\n"); } }
527 vbwin
.redrawOpenGlSceneNow();
531 delegate (KeyEvent event
) {
532 if (vbwin
.closed
) return;
533 if (isQuitRequested
) { kgiPushCloseEvent(); vbwin
.close(); return; }
534 if (glconKeyEvent(event
)) return;
535 //if (event.pressed && event.key == Key.Escape) { concmd("quit"); return; }
538 delegate (MouseEvent event
) {
539 if (vbwin
.closed
) return;
540 mcurX
= event
.x
/(blit2x ?
2 : 1);
541 mcurY
= event
.y
/(blit2x ?
2 : 1);
542 if (event
.type
== MouseEventType
.motion
&& !kgiMotionEvents
) return;
543 if (blit2x
) { event
.x
/= 2; event
.y
/= 2; }
546 delegate (dchar ch
) {
547 if (vbwin
.closed
) return;
548 if (glconCharEvent(ch
)) return;
549 if (ch
== '`') concmd("r_console tan");
550 if (!kgiCharEvents
) return;
554 } catch (Throwable e
) {
555 // here, we are dead and fucked (the exact order doesn't matter)
556 import core
.stdc
.stdlib
: abort
;
557 import core
.stdc
.stdio
: fprintf
, stderr
;
558 import core
.memory
: GC
;
560 GC
.disable(); // yeah
561 thread_suspendAll(); // stop right here, you criminal scum!
562 auto s
= e
.toString();
563 fprintf(stderr
, "\n=== FATAL ===\n%.*s\n", cast(uint)s
.length
, s
.ptr
);
564 abort(); // die, you bitch!
570 import core.stdc.stdlib : exit;
575 atomicStore(kgiThreadStarted
, false);
579 // ////////////////////////////////////////////////////////////////////////// //
580 private __gshared Tid kgiTid
;
581 private shared bool kgiThreadStarted
= false;
584 private void startKGIThread () {
585 //if (!cas(&kgiThreadStarted, false, true)) assert(0, "render thread already started!");
586 kgiTid
= spawn(&kgiThread
, thisTid
);
587 setMaxMailboxSize(kgiTid
, 1024, OnCrowding
.throwException
); //FIXME
588 // wait for "i'm ready" signal
591 if (ok
!= 42) assert(0, "wtf?!");
594 //conwriteln("rendering thread started");
599 public bool kgiInitEx (int awdt
, int ahgt
, string title
, bool a2x
, uint afps
) {
600 import core
.stdc
.stdlib
: malloc
;
601 import arsd
.simpledisplay
;
603 if (awdt
< 1 || ahgt
< 1 || awdt
> 4096 || ahgt
> 4096) {
605 //assert(0, "invalid dimensions");
608 if (!cas(&kgiThreadStarted
, false, true)) return false;
610 if (vbwin
!is null) assert(0, "double initialization");
612 if (afps
< 1) afps
= 1; else if (afps
> 60) afps
= 60;
614 conSealVar("v_scale2x");
615 conSealVar("v_width");
616 conSealVar("v_height");
617 conSealVar("v_title");
620 vbuf
= cast(typeof(vbuf
))malloc(vbuf
[0].sizeof
*awdt
*ahgt
);
621 if (vbuf
is null) assert(0, "KGI: out of memory");
622 vbuf
[0..awdt
*ahgt
] = 0;
624 vbufsaved
= cast(typeof(vbuf
))malloc(vbufsaved
[0].sizeof
*awdt
*ahgt
);
625 if (vbufsaved
is null) assert(0, "KGI: out of memory");
626 vbufsaved
[0..awdt
*ahgt
] = vbuf
[0..awdt
*ahgt
];
628 vcurbuf
= cast(typeof(vcurbuf
))malloc(vcurbuf
[0].sizeof
*kgiMaxCurW
*kgiMaxCurH
);
629 if (vbuf
is null) assert(0, "KGI: out of memory");
630 vcurbuf
[0..kgiMaxCurW
*kgiMaxCurH
] = 0;
631 unpackDefaultCursor();
640 setOpenGLContextVersion(3, 2); // up to GLSL 150
641 //openGLContextCompatible = false;
642 static if (is(typeof(openGLContextAllowFallback
))) {
643 openGLContextAllowFallback
= true;
653 public bool kgiInit () { return kgiInitEx(vbufW
, vbufH
, kgiTitle
, blit2x
, fps
); }
654 public bool kgiInit (int awdt
, int ahgt
) { return kgiInitEx(awdt
, ahgt
, kgiTitle
, blit2x
, fps
); }
655 public bool kgiInit (int awdt
, int ahgt
, string title
) { return kgiInitEx(awdt
, ahgt
, title
, blit2x
, fps
); }
656 public bool kgiInit (int awdt
, int ahgt
, string title
, bool a2x
) { return kgiInitEx(awdt
, ahgt
, title
, a2x
, fps
); }
657 public bool kgiInit (int awdt
, int ahgt
, string title
, bool a2x
, uint afps
) { return kgiInitEx(awdt
, ahgt
, title
, a2x
, afps
); }
660 // ////////////////////////////////////////////////////////////////////////// //
661 private uint glgfxCompileShader (const(char)[] src
) nothrow @trusted {
664 if (shaderVersionOk
< 0) {
665 // check if we have sufficient shader version here
669 glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS
, &svcount
);
671 foreach (GLuint n
; 0..svcount
) {
672 import core
.stdc
.string
: strncmp
;
673 auto v
= glGetStringi(GL_SHADING_LANGUAGE_VERSION
, n
);
674 if (v
is null) continue;
675 //if (strncmp(v, "130", 3) != 0) continue;
676 if (strncmp(cast(char*)v
, "150".ptr
, 3) != 0) continue;
677 if (v
[3] > ' ') continue;
682 if (!found
) return 0; //assert(0, "can't find OpenGL GLSL 150");
685 auto adr = glGetProcAddress("glTexParameterf");
686 if (adr is null) return 0;
691 if (shaderVersionOk
== 0) return 0;
692 return compileShaders(src
);
696 private void glgfxInitTexture () nothrow @trusted {
699 //if (vbTexId) { glDeleteTextures(1, &vbTexId); vbTexId = 0; }
701 enum wrapOpt
= GL_REPEAT
;
702 enum filterOpt
= GL_NEAREST
; //GL_LINEAR;
703 enum ttype
= GL_UNSIGNED_BYTE
;
705 glGenTextures(1, &vbTexId
);
706 if (vbTexId
== 0) assert(0, "can't create kgi texture");
708 glGenTextures(1, &vbCurTexId
);
709 if (vbTexId
== 0) assert(0, "can't create kgicursor texture");
712 glGetIntegerv(GL_TEXTURE_BINDING_2D
, &gltextbinding
);
713 scope(exit
) glBindTexture(GL_TEXTURE_2D
, gltextbinding
);
715 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
716 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapOpt
);
717 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapOpt
);
718 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filterOpt
);
719 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filterOpt
);
720 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
721 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
723 GLfloat
[4] bclr
= 0.0;
724 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, bclr
.ptr
);
726 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
727 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, vbufW
, vbufH
, 0, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
730 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
731 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, wrapOpt
);
732 glTexParameterf(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, wrapOpt
);
733 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, filterOpt
);
734 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, filterOpt
);
735 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
736 //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
738 //GLfloat[4] bclr = 0.0;
739 glTexParameterfv(GL_TEXTURE_2D
, GL_TEXTURE_BORDER_COLOR
, bclr
.ptr
);
741 //static if (KGIRGBA) enum TexType = GL_RGBA; else enum TexType = GL_BGRA;
742 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, kgiMaxCurW
, kgiMaxCurH
, 0, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
746 private void glgfxUpdateTexture () nothrow @trusted {
750 scope(exit
) consoleUnlock();
752 version(LDC
) {} else atomicFence();
755 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
757 glTextureSubImage2D(vbTexId
, 0, 0/*x*/, 0/*y*/, vbufW
, vbufH
, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
759 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
760 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, vbufW
, vbufH
, TexType
, GL_UNSIGNED_BYTE
, vbufsaved
);
761 glBindTexture(GL_TEXTURE_2D
, 0);
763 atomicStore(updateTexture
, false);
764 vupcounterlast
= vupcounterlast
.max
;
766 if (atomicLoad(updateCurTexture
)) {
768 glTextureSubImage2D(vbCurTexId
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
770 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
771 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
772 glBindTexture(GL_TEXTURE_2D
, 0);
774 atomicStore(updateCurTexture
, false);
779 private void glgfxUpdateCurTexture () nothrow @trusted {
782 if (atomicLoad(updateCurTexture
)) {
784 scope(exit
) consoleUnlock();
786 static if (KGIRGBA
) enum TexType
= GL_RGBA
; else enum TexType
= GL_BGRA
;
788 glTextureSubImage2D(vbCurTexId
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
790 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
791 glTexSubImage2D(GL_TEXTURE_2D
, 0, 0/*x*/, 0/*y*/, kgiMaxCurW
, kgiMaxCurH
, TexType
, GL_UNSIGNED_BYTE
, vcurbuf
);
792 glBindTexture(GL_TEXTURE_2D
, 0);
795 atomicStore(updateCurTexture
, false);
800 private void glgfxBlit () nothrow @trusted {
804 scope(exit
) consoleUnlock();
806 //if (vbwin is null || vbwin.closed || vbTexId == 0) return;
812 GLint oldfbr, oldfbw;
814 glGetIntegerv(GL_MATRIX_MODE, &glmatmode);
815 glGetIntegerv(GL_TEXTURE_BINDING_2D, &gltextbinding);
816 glGetIntegerv(GL_VIEWPORT, glviewport.ptr);
817 glGetIntegerv(GL_CURRENT_PROGRAM, &oldprg);
818 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &oldfbr);
819 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &oldfbw);
820 glMatrixMode(GL_PROJECTION); glPushMatrix();
821 glMatrixMode(GL_MODELVIEW); glPushMatrix();
822 glMatrixMode(GL_TEXTURE); glPushMatrix();
823 glMatrixMode(GL_COLOR); glPushMatrix();
824 glPushAttrib(/*GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_CURRENT_BIT*/GL_ALL_ATTRIB_BITS); // let's play safe
827 glPopAttrib(/*GL_ENABLE_BIT*/);
828 glMatrixMode(GL_PROJECTION); glPopMatrix();
829 glMatrixMode(GL_MODELVIEW); glPopMatrix();
830 glMatrixMode(GL_TEXTURE); glPopMatrix();
831 glMatrixMode(GL_COLOR); glPopMatrix();
832 glMatrixMode(glmatmode);
833 glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oldfbr);
834 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, oldfbw);
835 glBindTexture(GL_TEXTURE_2D, gltextbinding);
836 glUseProgram(oldprg);
837 glViewport(glviewport.ptr[0], glviewport.ptr[1], glviewport.ptr[2], glviewport.ptr[3]);
847 glBindTexture(GL_TEXTURE_CUBE_MAP
, 0);
848 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, 0);
850 if (scanlines
&& shaderVersionOk
< 0) sdrScanlineId
= glgfxCompileShader(sdrScanlineSrc
);
851 glUseProgram(scanlines ? sdrScanlineId
: 0);
854 glMatrixMode(GL_PROJECTION
); // for ortho camera
856 // left, right, bottom, top, near, far
857 glViewport(0, 0, w
*(blit2x ?
2 : 1), h
*(blit2x ?
2 : 1));
858 glOrtho(0, w
, h
, 0, -1, 1); // top-to-bottom
859 glMatrixMode(GL_MODELVIEW
);
862 glEnable(GL_TEXTURE_2D
);
863 glDisable(GL_LIGHTING
);
864 glDisable(GL_DITHER
);
865 //glDisable(GL_BLEND);
866 glDisable(GL_DEPTH_TEST
);
867 //glEnable(GL_BLEND);
868 //glBlendFunc(GL_SRC_ALPHA, GL_ONE);
869 //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
871 glDisable(GL_STENCIL_TEST
);
873 glColor4f(1, 1, 1, 1);
874 glBindTexture(GL_TEXTURE_2D
, vbTexId
);
875 //scope(exit) glBindTexture(GL_TEXTURE_2D, 0);
877 glTexCoord2f(0.0f, 0.0f); glVertex2i(x
, y
); // top-left
878 glTexCoord2f(1.0f, 0.0f); glVertex2i(w
, y
); // top-right
879 glTexCoord2f(1.0f, 1.0f); glVertex2i(w
, h
); // bottom-right
880 glTexCoord2f(0.0f, 1.0f); glVertex2i(x
, h
); // bottom-left
883 if (mcurHidden
== 0) {
885 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
886 glBindTexture(GL_TEXTURE_2D
, vbCurTexId
);
888 int cx0
= mcurX
-mhotX
;
889 int cy0
= mcurY
-mhotY
;
892 glTexCoord2f(0.0f, 0.0f); glVertex2i(cx0
, cy0
); // top-left
893 glTexCoord2f(1.0f, 0.0f); glVertex2i(cx0
+kgiMaxCurW
, cy0
); // top-right
894 glTexCoord2f(1.0f, 1.0f); glVertex2i(cx0
+kgiMaxCurW
, cy0
+kgiMaxCurH
); // bottom-right
895 glTexCoord2f(0.0f, 1.0f); glVertex2i(cx0
, cy0
+kgiMaxCurH
); // bottom-left
903 // ////////////////////////////////////////////////////////////////////////// //
906 /// vlRGBA struct to ease color components extraction/replacing
907 align(1) struct vlRGBA
{
909 static if (KGIRGBA
) {
915 static assert(vlRGBA
.sizeof
== VColor
.sizeof
);
918 static if (KGIRGBA
) {
933 static assert(vlAShift
== 24, "invalid A position in color"); // alas
937 vlAMask
= 0xffu
<<vlAShift
,
938 vlRMask
= 0xffu
<<vlRShift
,
939 vlGMask
= 0xffu
<<vlGShift
,
940 vlBMask
= 0xffu
<<vlBShift
,
941 vlColorMask
= vlRMask|vlGMask|vlBMask
,
945 enum VColor Transparent
= vlAMask
; /// completely transparent pixel color
948 bool isTransparent(T
: VColor
) (T col
) pure nothrow @safe @nogc {
949 pragma(inline
, true);
950 return ((col
&vlAMask
) == vlAMask
);
953 bool isOpaque(T
: VColor
) (T col
) pure nothrow @safe @nogc {
954 pragma(inline
, true);
955 return ((col
&vlAMask
) == 0);
959 VColor
rgbcol(TR
, TG
, TB
, TA
=ubyte) (TR r
, TG g
, TB b
, TA a
=0) pure nothrow @safe @nogc
960 if (__traits(isIntegral
, TR
) && __traits(isIntegral
, TG
) && __traits(isIntegral
, TB
) && __traits(isIntegral
, TA
)) {
961 pragma(inline
, true);
963 (clampToByte(a
)<<vlAShift
)|
964 (clampToByte(r
)<<vlRShift
)|
965 (clampToByte(g
)<<vlGShift
)|
966 (clampToByte(b
)<<vlBShift
);
969 alias rgbacol
= rgbcol
;
972 // generate some templates (rgbRed, rgbSetRed, etc.)
973 private enum genRGBGetSet(string cname
) =
974 "ubyte rgb"~cname
~"() (VColor clr) pure nothrow @safe @nogc {\n"~
975 " pragma(inline, true);\n"~
976 " return ((clr>>vl"~cname
[0]~"Shift)&0xff);\n"~
978 "VColor rgbSet"~cname
~"(T) (VColor clr, T v) pure nothrow @safe @nogc if (__traits(isIntegral, T)) {\n"~
979 " pragma(inline, true);\n"~
980 " return (clr&~vl"~cname
[0]~"Mask)|(clampToByte(v)<<vl"~cname
[0]~"Shift);\n"~
983 mixin(genRGBGetSet
!"Alpha");
984 mixin(genRGBGetSet
!"Red");
985 mixin(genRGBGetSet
!"Green");
986 mixin(genRGBGetSet
!"Blue");
989 // ////////////////////////////////////////////////////////////////////////// //
990 nothrow @trusted @nogc {
992 private void putPixelIntrNoCheck (in int xx
, in int yy
, in VColor col
) {
993 pragma(inline
, true);
994 uint* da = vbuf
+yy
*vbufW
+xx
;
996 immutable uint a
= 256-(col
>>24); // to not loose bits
997 immutable uint dc
= (*da)&0xffffff;
998 immutable uint srb
= (col
&0xff00ff);
999 immutable uint sg
= (col
&0x00ff00);
1000 immutable uint drb
= (dc
&0xff00ff);
1001 immutable uint dg
= (dc
&0x00ff00);
1002 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1003 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1010 private void putPixelIntr (int xx
, int yy
, VColor col
) {
1011 pragma(inline
, true);
1012 if ((col
&vlAMask
) != vlAMask
&& xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1013 uint* da = vbuf
+yy
*vbufW
+xx
;
1015 immutable uint a
= 256-(col
>>24); // to not loose bits
1016 immutable uint dc
= (*da)&0xffffff;
1017 immutable uint srb
= (col
&0xff00ff);
1018 immutable uint sg
= (col
&0x00ff00);
1019 immutable uint drb
= (dc
&0xff00ff);
1020 immutable uint dg
= (dc
&0x00ff00);
1021 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1022 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1030 void putPixel (int xx
, int yy
, VColor col
) {
1031 pragma(inline
, true);
1032 if ((col
&vlAMask
) != vlAMask
&& xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1033 uint* da = vbuf
+yy
*vbufW
+xx
;
1035 immutable uint a
= 256-(col
>>24); // to not loose bits
1036 immutable uint dc
= (*da)&0xffffff;
1037 immutable uint srb
= (col
&0xff00ff);
1038 immutable uint sg
= (col
&0x00ff00);
1039 immutable uint drb
= (dc
&0xff00ff);
1040 immutable uint dg
= (dc
&0x00ff00);
1041 immutable uint orb
= (drb
+(((srb
-drb
)*a
+0x800080)>>8))&0xff00ff;
1042 immutable uint og
= (dg
+(((sg
-dg
)*a
+0x008000)>>8))&0x00ff00;
1047 version(LDC
) {} else atomicFence();
1052 private void setPixelIntr (int xx
, int yy
, VColor col
) {
1053 pragma(inline
, true);
1054 if (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1055 uint* da = vbuf
+yy
*vbufW
+xx
;
1060 void setPixel (int xx
, int yy
, VColor col
) {
1061 pragma(inline
, true);
1062 if (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH
) {
1063 uint* da = vbuf
+yy
*vbufW
+xx
;
1065 version(LDC
) {} else atomicFence();
1071 VColor
getPixel (int xx
, int yy
) {
1072 pragma(inline
, true);
1073 return (xx
>= 0 && yy
>= 0 && xx
< vbufW
&& yy
< vbufH ? vbuf
[yy
*vbufW
+xx
]&vlColorMask
: Transparent
);
1077 // ////////////////////////////////////////////////////////////////////////// //
1078 void cls (VColor col
) {
1079 vbuf
[0..vbufW
*vbufH
] = col
;
1080 version(LDC
) {} else atomicFence();
1085 // ////////////////////////////////////////////////////////////////////////// //
1086 void drawRect (int x
, int y
, int w
, int h
, immutable VColor col
) {
1087 if (w
< 1 || h
< 1) return;
1088 if (x
<= -w || y
<= -h || x
>= vbufW || y
>= vbufH ||
isTransparent(col
)) return;
1089 if (x
< 0) { w
+= x
; x
= 0; }
1090 if (y
< 0) { h
+= y
; h
= 0; }
1091 if (x
+w
>= vbufW
) w
= vbufW
-x
;
1092 if (y
+h
>= vbufH
) h
= vbufH
-y
;
1093 assert(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
&& w
> 0 && h
> 0 && x
+w
<= vbufW
&& y
+h
<= vbufH
);
1094 if (isOpaque(col
)) {
1098 foreach (immutable yy
; y
+1..y
+h
-1) {
1103 if (h
> 1) vbuf
[d
..d
+w
] = col
;
1105 foreach (immutable yy
; y
..y
+h
) {
1106 putPixelIntr(x
, yy
, col
);
1107 putPixelIntr(x
+w
-1, yy
, col
);
1109 foreach (immutable xx
; x
+1..x
+w
-1) {
1110 putPixelIntr(xx
, y
, col
);
1111 if (h
> 1) putPixelIntr(xx
, y
+h
-1, col
);
1114 version(LDC
) {} else atomicFence();
1118 void fillRect (int x
, int y
, int w
, int h
, immutable VColor col
) {
1119 if (w
< 1 || h
< 1) return;
1120 if (x
<= -w || y
<= -h || x
>= vbufW || y
>= vbufH ||
isTransparent(col
)) return;
1121 if (x
< 0) { w
+= x
; x
= 0; }
1122 if (y
< 0) { h
+= y
; h
= 0; }
1123 if (x
+w
>= vbufW
) w
= vbufW
-x
;
1124 if (y
+h
>= vbufH
) h
= vbufH
-y
;
1125 assert(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
&& w
> 0 && h
> 0 && x
+w
<= vbufW
&& y
+h
<= vbufH
);
1126 if (isOpaque(col
)) {
1128 foreach (immutable yy
; y
..y
+h
) {
1133 foreach (immutable yy
; y
..y
+h
) {
1134 foreach (immutable xx
; x
..x
+w
) {
1135 putPixelIntr(xx
, yy
, col
);
1139 version(LDC
) {} else atomicFence();
1143 void hline (int x
, int y
, int len
, immutable VColor col
) { drawRect(x
, y
, len
, 1, col
); }
1144 void vline (int x
, int y
, int len
, immutable VColor col
) { drawRect(x
, y
, 1, len
, col
); }
1147 // ////////////////////////////////////////////////////////////////////////// //
1148 void drawLine(bool lastPoint
=true) (int x0
, int y0
, int x1
, int y1
, immutable VColor col
) {
1149 enum swap(string a
, string b
) = "{int tmp_="~a
~";"~a
~"="~b
~";"~b
~"=tmp_;}";
1151 if ((col
&vlAMask
) == vlAMask
) return;
1153 if (x0
== x1
&& y0
== y1
) {
1154 static if (lastPoint
) putPixel(x0
, y0
, col
);
1159 int wx0
= 0, wy0
= 0, wx1
= vbufW
-1, wy1
= vbufH
-1;
1161 int stx
, sty
; // "steps" for x and y axes
1162 int dsx
, dsy
; // "lengthes" for x and y axes
1163 int dx2
, dy2
; // "double lengthes" for x and y axes
1164 int xd
, yd
; // current coord
1165 int e
; // "error" (as in bresenham algo)
1171 // from left to right
1172 if (x0
> wx1 || x1
< wx0
) return; // out of screen
1173 stx
= 1; // going right
1175 // from right to left
1176 if (x1
> wx1 || x0
< wx0
) return; // out of screen
1177 stx
= -1; // going left
1182 mixin(swap
!("wx0", "wx1"));
1186 // from top to bottom
1187 if (y0
> wy1 || y1
< wy0
) return; // out of screen
1188 sty
= 1; // going down
1190 // from bottom to top
1191 if (y1
> wy1 || y0
< wy0
) return; // out of screen
1192 sty
= -1; // going up
1197 mixin(swap
!("wy0", "wy1"));
1204 mixin(swap
!("x0", "y0"));
1205 mixin(swap
!("x1", "y1"));
1206 mixin(swap
!("dsx", "dsy"));
1207 mixin(swap
!("wx0", "wy0"));
1208 mixin(swap
!("wx1", "wy1"));
1209 mixin(swap
!("stx", "sty"));
1220 bool xfixed
= false;
1223 int temp
= dx2
*(wy0
-y0
)-dsx
;
1226 if (xd
> wx1
) return; // x is moved out of clipping rect, nothing to do
1230 if (rem
> 0) { ++xd
; e
+= dy2
; }
1234 if (!xfixed
&& x0
< wx0
) {
1236 int temp
= dy2
*(wx0
-x0
);
1239 if (yd
> wy1 || yd
== wy1
&& rem
>= dsx
) return;
1242 if (rem
>= dsx
) { ++yd
; e
-= dx2
; }
1246 int temp
= dx2
*(wy1
-y0
)+dsx
;
1249 if (rem
== 0) --term
;
1251 if (term
> wx1
) term
= wx1
; // clip at right
1252 static if (lastPoint
) {
1256 if (term
== xd
) return; // this is the only point, get out of here
1258 if (sty
== -1) yd
= -yd
;
1259 if (stx
== -1) { xd
= -xd
; term
= -term
; }
1261 // draw it; `putPixel()` can omit checks
1262 while (xd
!= term
) {
1263 putPixelIntrNoCheck(*d0
, *d1
, col
);
1264 // done drawing, move coords
1273 version(LDC
) {} else atomicFence();
1278 // ////////////////////////////////////////////////////////////////////////// //
1279 private void plot4points() (int cx
, int cy
, int x
, int y
, VColor clr
) @trusted {
1280 putPixelIntr(cx
+x
, cy
+y
, clr
);
1281 if (x
!= 0) putPixelIntr(cx
-x
, cy
+y
, clr
);
1282 if (y
!= 0) putPixelIntr(cx
+x
, cy
-y
, clr
);
1283 putPixelIntr(cx
-x
, cy
-y
, clr
);
1287 void drawCircle (int cx
, int cy
, int radius
, VColor clr
) @trusted {
1288 if (radius
> 0 && !isTransparent(clr
)) {
1289 int error
= -radius
, x
= radius
, y
= 0;
1290 if (radius
== 1) { putPixelIntr(cx
, cy
, clr
); return; }
1292 plot4points(cx
, cy
, x
, y
, clr
);
1293 plot4points(cx
, cy
, y
, x
, clr
);
1296 if (error
>= 0) { --x
; error
-= x
*2; }
1298 plot4points(cx
, cy
, x
, y
, clr
);
1299 version(LDC
) {} else atomicFence();
1304 void fillCircle (int cx
, int cy
, int radius
, VColor clr
) @trusted {
1305 if (radius
> 0 && !isTransparent(clr
)) {
1306 int error
= -radius
, x
= radius
, y
= 0;
1307 if (radius
== 1) { putPixelIntr(cx
, cy
, clr
); return; }
1313 hline(cx
-x
, cy
+last_y
, 2*x
+1, clr
);
1314 if (x
!= 0 && last_y
!= 0) hline(cx
-x
, cy
-last_y
, 2*x
+1, clr
);
1317 hline(cx
-last_y
, cy
+x
, 2*last_y
+1, clr
);
1318 if (last_y
!= 0 && x
!= 0) hline(cx
-last_y
, cy
-x
, 2*last_y
+1, clr
);
1325 version(LDC
) {} else atomicFence();
1331 void drawEllipse (int x0
, int y0
, int w
, int h
, VColor clr
) @trusted {
1332 import std
.math
: abs
;
1333 if (w
== 0 && h
== 0) return;
1334 if (w
== 1) { vline(x0
, y0
, h
, clr
); return; }
1335 if (h
== 1) { hline(x0
, y0
, w
, clr
); return; }
1338 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; // values of diameter
1339 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; // error increment
1340 long err
= dx
+dy
+b1
*a
*a
; // error of 1.step
1341 if (x0
> x1
) { x0
= x1
; x1
+= a
; } // if called with swapped points...
1342 if (y0
> y1
) y0
= y1
; // ...exchange them
1343 y0
+= (b
+1)/2; y1
= y0
-b1
; // starting pixel
1344 a
*= 8*a
; b1
= 8*b
*b
;
1347 putPixelIntr(x1
, y0
, clr
); // I. Quadrant
1348 putPixelIntr(x0
, y0
, clr
); // II. Quadrant
1349 putPixelIntr(x0
, y1
, clr
); // III. Quadrant
1350 putPixelIntr(x1
, y1
, clr
); // IV. Quadrant
1352 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } // x step
1353 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } // y step
1356 // too early stop of flat ellipses a=1
1357 putPixelIntr(x0
-1, ++y0
, clr
); // complete tip of ellipse
1358 putPixelIntr(x0
-1, --y1
, clr
);
1360 version(LDC
) {} else atomicFence();
1364 void fillEllipse (int x0
, int y0
, int w
, int h
, VColor clr
) @trusted {
1365 import std
.math
: abs
;
1366 if (w
== 0 && h
== 0) return;
1367 if (w
== 1) { vline(x0
, y0
, h
, clr
); return; }
1368 if (h
== 1) { hline(x0
, y0
, w
, clr
); return; }
1371 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; // values of diameter
1372 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; // error increment
1373 long err
= dx
+dy
+b1
*a
*a
; // error of 1.step
1374 int prev_y0
= -1, prev_y1
= -1;
1375 if (x0
> x1
) { x0
= x1
; x1
+= a
; } // if called with swapped points...
1376 if (y0
> y1
) y0
= y1
; // ...exchange them
1377 y0
+= (b
+1)/2; y1
= y0
-b1
; // starting pixel
1378 a
*= 8*a
; b1
= 8*b
*b
;
1381 if (y0
!= prev_y0
) { hline(x0
, y0
, x1
-x0
+1, clr
); prev_y0
= y0
; }
1382 if (y1
!= y0
&& y1
!= prev_y1
) { hline(x0
, y1
, x1
-x0
+1, clr
); prev_y1
= y1
; }
1384 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } // x step
1385 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } // y step
1388 // too early stop of flat ellipses a=1
1389 putPixelIntr(x0
-1, ++y0
, clr
); // complete tip of ellipse
1390 putPixelIntr(x0
-1, --y1
, clr
);
1392 version(LDC
) {} else atomicFence();
1397 // //////////////////////////////////////////////////////////////////////// //
1398 int charWidth(string type
="msx") () {
1399 static if (type
== "msx") return 6;
1400 else static if (type
== "dos") return 8;
1401 else static if (type
== "d10") return 10;
1402 else static assert(0, "invalid font type");
1405 int charHeight(string type
="msx") () {
1406 static if (type
== "msx") return 8;
1407 else static if (type
== "dos") return 8;
1408 else static if (type
== "d10") return 10;
1409 else static assert(0, "invalid font type");
1412 void drawCharWdt(string type
="msx") (int x
, int y
, int wdt
, int shift
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1413 static if (type
== "msx") { alias fontb8
= kgiFont6
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1414 else static if (type
== "dos") { alias fontb8
= kgiFont8
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1415 else static if (type
== "d10") { alias fontb8
= kgiFont10
; enum fwdt
= 10; enum fhgt
= 10; enum fmask
= 0x8000; }
1416 else static assert(0, "invalid font type");
1417 usize pos
= ch
*fhgt
;
1418 if (wdt
< 1 || shift
>= fwdt
) return;
1419 if (fgcol
== Transparent
&& bgcol
== Transparent
) return;
1420 if (wdt
> fwdt
) wdt
= fwdt
;
1421 if (shift
< 0) shift
= 0;
1422 foreach (immutable int dy
; 0..fhgt
) {
1423 ushort b
= cast(ushort)(fontb8
.ptr
[pos
++]<<shift
);
1424 foreach (immutable int dx
; 0..wdt
) {
1425 VColor c
= (b
&fmask ? fgcol
: bgcol
);
1426 putPixelIntr(x
+dx
, y
+dy
, c
);
1430 version(LDC
) {} else atomicFence();
1440 OutLU
= 0x10, // left-up
1441 OutRU
= 0x20, // right-up
1442 OutLD
= 0x40, // left-down
1443 OutRD
= 0x80, // right-down
1447 void drawCharWdtOut(string type
="msx") (int x
, int y
, int wdt
, int shift
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=0) @trusted {
1448 static if (type
== "msx") { alias fontb8
= kgiFont6
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1449 else static if (type
== "dos") { alias fontb8
= kgiFont8
; enum fwdt
= 8; enum fhgt
= 8; enum fmask
= 0x80; }
1450 else static if (type
== "d10") { alias fontb8
= kgiFont10
; enum fwdt
= 10; enum fhgt
= 10; enum fmask
= 0x8000; }
1451 else static assert(0, "invalid font type");
1452 if (fgcol
== Transparent
&& outcol
== Transparent
) return;
1453 if (ot
== 0 || outcol
== Transparent
) {
1454 // no outline? simple draw
1455 drawCharWdt(x
, y
, wdt
, shift
, ch
, fgcol
, Transparent
);
1458 usize pos
= ch
*fhgt
;
1459 if (wdt
< 1 || shift
>= fwdt
) return;
1460 if (wdt
> 8) wdt
= fwdt
;
1461 if (shift
< 0) shift
= 0;
1462 ubyte[fhgt
+2][fwdt
+2] bmp
= 0; // char bitmap; 0: empty; 1: char; 2: outline
1463 foreach (immutable dy
; 1..fhgt
+1) {
1464 ushort b
= cast(ushort)(fontb8
.ptr
[pos
++]<<shift
);
1465 foreach (immutable dx
; 1..wdt
+1) {
1470 if ((ot
&OutUp
) && bmp
[dy
-1][dx
] == 0) bmp
[dy
-1][dx
] = 2;
1471 if ((ot
&OutDown
) && bmp
[dy
+1][dx
] == 0) bmp
[dy
+1][dx
] = 2;
1472 if ((ot
&OutLeft
) && bmp
[dy
][dx
-1] == 0) bmp
[dy
][dx
-1] = 2;
1473 if ((ot
&OutRight
) && bmp
[dy
][dx
+1] == 0) bmp
[dy
][dx
+1] = 2;
1474 if ((ot
&OutLU
) && bmp
[dy
-1][dx
-1] == 0) bmp
[dy
-1][dx
-1] = 2;
1475 if ((ot
&OutRU
) && bmp
[dy
-1][dx
+1] == 0) bmp
[dy
-1][dx
+1] = 2;
1476 if ((ot
&OutLD
) && bmp
[dy
+1][dx
-1] == 0) bmp
[dy
+1][dx
-1] = 2;
1477 if ((ot
&OutRD
) && bmp
[dy
+1][dx
+1] == 0) bmp
[dy
+1][dx
+1] = 2;
1485 foreach (immutable int dy
; 0..fhgt
+2) {
1486 foreach (immutable int dx
; 0..fwdt
+2) {
1487 if (auto t
= bmp
[dy
][dx
]) putPixelIntr(x
+dx
, y
+dy
, (t
== 1 ? fgcol
: outcol
));
1490 version(LDC
) {} else atomicFence();
1494 void drawChar(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1495 drawCharWdt
!type(x
, y
, charWidth
!type
, 0, ch
, fgcol
, bgcol
);
1498 void drawCharOut(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1499 drawCharWdtOut
!type(x
, y
, charWidth
!type
, 0, ch
, fgcol
, outcol
, ot
);
1502 void drawStr(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1503 foreach (immutable char ch
; str) {
1504 drawChar
!type(x
, y
, ch
, fgcol
, bgcol
);
1505 x
+= charWidth
!type
;
1509 void drawStrOut(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1510 foreach (immutable char ch
; str) {
1511 drawCharOut
!type(x
, y
, ch
, fgcol
, outcol
, ot
);
1512 x
+= charWidth
!type
;
1516 int strWidth(string type
="msx") (const(char)[] str) {
1517 return cast(int)str.length
*charWidth
!type
;
1520 int charWidthProp(string type
="msx") (char ch
) @trusted pure {
1521 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1522 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1523 else static assert(0, "invalid font type");
1524 return (fontw8
.ptr
[ch
]&0x0f);
1527 int strWidthProp(string type
="msx") (const(char)[] str) @trusted pure {
1528 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1529 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1530 else static assert(0, "invalid font type");
1532 foreach (immutable char ch
; str) wdt
+= (fontw8
[ch
]&0x0f)+1;
1533 if (wdt
> 0) --wdt
; // don't count last empty pixel
1537 int drawCharProp(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1538 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1539 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1540 else static assert(0, "invalid font type");
1541 immutable int wdt
= (fontw8
[ch
]&0x0f);
1542 drawCharWdt
!type(x
, y
, wdt
, fontw8
[ch
]>>4, ch
, fgcol
, bgcol
);
1546 int drawCharPropOut(string type
="msx") (int x
, int y
, char ch
, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1547 static if (type
== "msx") { alias fontw8
= kgiFont6PropWidth
; }
1548 else static if (type
== "dos") { alias fontw8
= kgiFont8PropWidth
; }
1549 else static assert(0, "invalid font type");
1550 immutable int wdt
= (fontw8
[ch
]&0x0f);
1551 drawCharWdtOut
!type(x
, y
, wdt
, fontw8
[ch
]>>4, ch
, fgcol
, outcol
, ot
);
1555 int drawStrProp(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor bgcol
=Transparent
) @trusted {
1558 foreach (immutable char ch
; str) {
1560 if (!isTransparent(bgcol
)) {
1561 foreach (int dy
; 0..8) putPixelIntr(x
, y
+dy
, bgcol
);
1562 // no need to advance vupcounter, 'cause `drawCharProp` will do it
1563 //version(LDC) {} else atomicFence();
1569 x
+= drawCharProp
!type(x
, y
, ch
, fgcol
, bgcol
);
1574 int drawStrPropOut(string type
="msx") (int x
, int y
, const(char)[] str, VColor fgcol
, VColor outcol
=Transparent
, ubyte ot
=OutAll
) @trusted {
1576 foreach (immutable char ch
; str) {
1577 x
+= drawCharPropOut
!type(x
, y
, ch
, fgcol
, outcol
, ot
)+1;
1579 if (x
> sx
) --x
; // don't count last empty pixel
1584 // ////////////////////////////////////////////////////////////////////////// //
1585 /** floodfill area; based on Tarry's maze algorithm.
1587 * fill area with color/pattern. trades memory for speed: doesn't recurse, doesn't allocate.
1588 * will use "transparency" byte as temporary, and will leave it dirty.
1591 * neither `isBorder` nor `patColor` will be called with out-of-range coordinates.
1593 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 {
1600 static ubyte getmark (int x
, int y
) nothrow @trusted @nogc {
1601 pragma(inline
, true);
1602 return cast(ubyte)(x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH ? vbuf
[y
*vbufW
+x
]>>vlAShift
: Scanned
);
1605 static void setmark (int x
, int y
, ubyte mark
) nothrow @trusted @nogc {
1606 pragma(inline
, true);
1607 if (x
>= 0 && y
>= 0 && x
< vbufW
&& y
< vbufH
) vbuf
[y
*vbufW
+x
] = (vbuf
[y
*vbufW
+x
]&vlColorMask
)|
(mark
<<vlAShift
);
1610 if (x
< 0 || y
< 0 || x
>= vbufW || y
>= vbufH
) return; // nothing to do
1611 if (isBorder(x
, y
)) return; // nothing to do
1613 //setPixel(x, y, getPixel(x, y)); // set update flag
1615 // one can mark bounding rectangle with Scanned
1618 foreach (immutable dy
; 0..vbufH
) {
1619 foreach (immutable dx
; 0..vbufW
) {
1620 *p
&= vlColorMask
; // "not visited" mark
1625 //setmark(x, y, Scanned|Fill|Seed);
1626 VColor pc
= patColor(x
, y
);
1628 vbuf
[y
*vbufW
+x
] = (pc
&vlColorMask
)|
((Scanned|Seed
)<<vlAShift
);
1631 putPixelIntrNoCheck(x
, y
, pc
);
1632 setmark(x
, y
, Scanned|Seed
);
1635 ubyte dir
= 0; // direction: right, left, up, down
1637 x
+= (dir
== 0 ?
1 : dir
== 1 ?
-1 : 0);
1638 y
+= (dir
== 3 ?
1 : dir
== 2 ?
-1 : 0);
1639 auto mk
= getmark(x
, y
);
1641 // not yet visited, check for border
1642 if (isBorder(x
, y
)) {
1644 setmark(x
, y
, Scanned
);
1647 if ((mk
&Scanned
) == 0) {
1649 //setmark(x, y, Scanned|Fill|dir);
1650 pc
= patColor(x
, y
);
1652 vbuf
[y
*vbufW
+x
] = (pc
&vlColorMask
)|
((Scanned|dir
)<<vlAShift
);
1655 putPixelIntrNoCheck(x
, y
, pc
);
1656 setmark(x
, y
, Scanned|dir
);
1658 if (dir
!= 1) dir
= 0; // make exit direction
1662 x
-= (dir
== 0 ?
1 : dir
== 1 ?
-1 : 0);
1663 y
-= (dir
== 3 ?
1 : dir
== 2 ?
-1 : 0);
1666 // done, fill pixels (you can set Fill flag and check all pixels here)
1667 if ((mk
&DirMask
) == 3) {
1669 version(LDC
) {} else atomicFence();
1677 break; // next pixel
1680 if ((mk
&DirMask
) == (dir^
1)) ++dir
; // skip entry-direction
1681 if (dir
<= 3) break; // next pixel
1690 // ////////////////////////////////////////////////////////////////////////// //
1692 static public immutable ubyte[256*8] kgiFont6
= [
1693 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,
1694 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,
1695 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,
1696 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,
1697 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,
1698 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,
1699 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,
1700 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,
1701 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,
1702 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,
1703 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,
1704 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,
1705 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,
1706 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,
1707 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,
1708 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,
1709 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,
1710 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,
1711 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,
1712 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,
1713 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,
1714 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,
1715 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,
1716 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,
1717 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,
1718 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,
1719 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,
1720 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,
1721 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,
1722 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,
1723 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,
1724 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,
1725 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,
1726 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,
1727 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,
1728 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,
1729 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,
1730 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,
1731 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,
1732 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,
1733 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,
1734 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,
1735 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,
1736 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,
1737 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,
1738 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,
1739 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,
1740 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,
1741 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,
1742 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,
1743 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,
1744 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,
1745 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,
1746 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,
1747 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,
1748 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,
1749 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,
1750 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,
1751 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,
1752 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,
1753 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,
1754 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,
1755 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,
1756 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,
1757 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,
1758 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,
1759 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,
1760 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,
1761 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,
1762 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,
1763 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,
1764 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,
1765 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,
1766 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,
1767 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,
1768 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,
1769 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,
1770 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,
1771 0xa8,0xf8,0x08,0x00,0x88,0x88,0x88,0x88,0x78,0x08,0x08,0x00,0xc0,0x40,0x40,0x70,0x48,0x48,0x70,0x00,
1774 static public immutable ubyte[256*8] kgiFont8
= [
1775 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,
1776 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,
1777 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,
1778 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,
1779 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,
1780 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,
1781 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,
1782 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,
1783 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,
1784 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,
1785 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,
1786 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,
1787 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,
1788 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,
1789 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,
1790 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,
1791 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,
1792 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,
1793 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,
1794 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,
1795 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,
1796 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,
1797 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,
1798 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,
1799 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,
1800 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,
1801 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,
1802 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,
1803 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,
1804 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,
1805 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,
1806 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,
1807 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,
1808 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,
1809 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,
1810 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,
1811 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,
1812 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,
1813 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,
1814 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,
1815 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,
1816 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,
1817 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,
1818 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,
1819 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,
1820 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,
1821 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,
1822 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,
1823 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,
1824 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,
1825 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,
1826 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,
1827 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,
1828 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,
1829 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,
1830 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,
1831 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,
1832 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,
1833 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,
1834 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,
1835 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,
1836 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,
1837 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,
1838 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,
1839 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,
1840 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,
1841 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,
1842 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,
1843 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,
1844 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,
1845 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,
1846 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,
1847 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,
1848 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,
1849 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,
1850 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,
1851 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,
1852 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,
1853 0x7c,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1856 static public immutable ushort[256*10] kgiFont10
= [
1857 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x4080,0x5280,0x4080,0x5e80,0x4c80,0x2100,0x1e00,
1858 0x0000,0x0000,0x3f00,0x7f80,0x6d80,0x7f80,0x6180,0x7380,0x3f00,0x1e00,0x0000,0x0000,0x3b80,0x7fc0,0x7fc0,0x7fc0,0x3f80,0x1f00,0x0e00,
1859 0x0400,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0e00,0x1f00,0x0e00,0x3f80,0x7fc0,0x3580,
1860 0x0400,0x0e00,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x7fc0,0x3580,0x0400,0x0e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,
1861 0x0c00,0x0000,0x0000,0x0000,0xffc0,0xffc0,0xffc0,0xf3c0,0xe1c0,0xe1c0,0xf3c0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x1e00,0x3300,0x2100,
1862 0x2100,0x3300,0x1e00,0x0000,0x0000,0xffc0,0xffc0,0xe1c0,0xccc0,0xdec0,0xdec0,0xccc0,0xe1c0,0xffc0,0xffc0,0x0000,0x0780,0x0380,0x0780,
1863 0x3e80,0x6600,0x6600,0x6600,0x3c00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3300,0x1e00,0x0c00,0x3f00,0x0c00,0x0000,0x0400,0x0600,0x0700,
1864 0x0500,0x0500,0x0400,0x1c00,0x3c00,0x1800,0x0000,0x0000,0x1f80,0x1f80,0x1080,0x1080,0x1180,0x3380,0x7100,0x2000,0x0000,0x0000,0x0c00,
1865 0x6d80,0x1e00,0x7380,0x7380,0x1e00,0x6d80,0x0c00,0x0000,0x1000,0x1800,0x1c00,0x1e00,0x1f00,0x1e00,0x1c00,0x1800,0x1000,0x0000,0x0100,
1866 0x0300,0x0700,0x0f00,0x1f00,0x0f00,0x0700,0x0300,0x0100,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,
1867 0x0000,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x3300,0x0000,0x0000,0x0000,0x3f80,0x6d80,0x6d80,0x3d80,0x0d80,0x0d80,0x0d80,0x0000,
1868 0x0000,0x0000,0x1f00,0x3000,0x1f00,0x3180,0x1f00,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x7f80,0x7f80,
1869 0x0000,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0xffc0,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x0c00,
1870 0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0600,0x0300,0x7f80,0x0300,
1871 0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x3000,0x7f80,0x3000,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,
1872 0x6000,0x6000,0x7f80,0x0000,0x0000,0x0000,0x0000,0x1100,0x3180,0x7fc0,0x3180,0x1100,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1873 0x1f00,0x3f80,0x7fc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1874 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,0x0c00,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x0000,0x1b00,
1875 0x1b00,0x1b00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1b00,0x1b00,0x7fc0,0x1b00,0x7fc0,0x1b00,0x1b00,0x0000,0x0000,0x0400,
1876 0x1f00,0x3580,0x3400,0x1f00,0x0580,0x3580,0x1f00,0x0400,0x0000,0x0000,0x3180,0x3300,0x0600,0x0c00,0x1980,0x3180,0x0000,0x0000,0x0000,
1877 0x0000,0x1c00,0x3300,0x3300,0x1f80,0x3300,0x3300,0x1d80,0x0000,0x0000,0x0000,0x0e00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,
1878 0x0000,0x0000,0x0600,0x0c00,0x1800,0x1800,0x1800,0x0c00,0x0600,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0600,0x0600,0x0c00,0x1800,
1879 0x0000,0x0000,0x0000,0x0000,0x3300,0x1e00,0x7f80,0x1e00,0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x3f00,0x0c00,0x0c00,
1880 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,
1881 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0180,0x0300,0x0600,0x0c00,
1882 0x1800,0x3000,0x6000,0x0000,0x0000,0x0000,0x1f00,0x3380,0x3780,0x3f80,0x3d80,0x3980,0x1f00,0x0000,0x0000,0x0000,0x0c00,0x1c00,0x0c00,
1883 0x0c00,0x0c00,0x0c00,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x0180,0x0f00,0x1800,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,
1884 0x0180,0x0700,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0700,0x0f00,0x1b00,0x3300,0x3f80,0x0300,0x0780,0x0000,0x0000,0x0000,0x3f80,
1885 0x3000,0x3000,0x3f00,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x3000,0x3f00,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1886 0x3f80,0x3180,0x0180,0x0300,0x0600,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x1f00,0x3180,0x3180,0x1f00,0x0000,0x0000,
1887 0x0000,0x1f00,0x3180,0x3180,0x1f80,0x0180,0x0300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0000,
1888 0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0300,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0300,
1889 0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0300,0x0600,0x0c00,
1890 0x1800,0x0000,0x0000,0x0000,0x1e00,0x3300,0x0300,0x0300,0x0600,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x3f00,0x6180,0x6780,0x6d80,0x6780,
1891 0x6000,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,
1892 0x3180,0x3180,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3e00,0x3300,0x3180,
1893 0x3180,0x3180,0x3300,0x3e00,0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3f00,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x3f80,0x3000,
1894 0x3000,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3380,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,
1895 0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,
1896 0x0700,0x0300,0x0300,0x0300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3300,0x3e00,0x3300,0x3180,0x3180,0x0000,0x0000,
1897 0x0000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x6180,0x7380,0x7f80,0x6d80,0x6180,0x6180,0x6180,0x0000,
1898 0x0000,0x0000,0x3180,0x3980,0x3d80,0x3780,0x3380,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3180,0x1f00,
1899 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3380,
1900 0x1f00,0x0380,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3300,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x1f00,0x0180,
1901 0x3180,0x1f00,0x0000,0x0000,0x0000,0x7f80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,
1902 0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x6180,0x6180,0x6180,
1903 0x6d80,0x7f80,0x7380,0x6180,0x0000,0x0000,0x0000,0x6180,0x3300,0x1e00,0x0c00,0x1e00,0x3300,0x6180,0x0000,0x0000,0x0000,0x6180,0x6180,
1904 0x3300,0x1e00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3f80,0x0300,0x0600,0x0c00,0x1800,0x3000,0x3f80,0x0000,0x0000,0x0000,0x1e00,
1905 0x1800,0x1800,0x1800,0x1800,0x1800,0x1e00,0x0000,0x0000,0x0000,0x6000,0x3000,0x1800,0x0c00,0x0600,0x0300,0x0000,0x0000,0x0000,0x0000,
1906 0x1e00,0x0600,0x0600,0x0600,0x0600,0x0600,0x1e00,0x0000,0x0000,0x0000,0x0400,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,
1907 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0x0000,0x0000,0x1c00,0x0c00,0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,
1908 0x0000,0x0000,0x0000,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x3000,0x3000,0x3f00,0x3180,0x3180,0x3180,0x3f00,
1909 0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0180,0x0180,0x1f80,0x3180,0x3180,0x3180,
1910 0x1f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x1800,0x3e00,0x1800,
1911 0x1800,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x3000,0x3000,0x3f00,0x3180,
1912 0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x0600,0x0000,0x0e00,
1913 0x0600,0x0600,0x0600,0x0600,0x0600,0x1c00,0x0000,0x3000,0x3000,0x3180,0x3300,0x3e00,0x3300,0x3180,0x0000,0x0000,0x0000,0x1c00,0x0c00,
1914 0x0c00,0x0c00,0x0c00,0x0c00,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x3300,0x7f80,0x6d80,0x6d80,0x6180,0x0000,0x0000,0x0000,0x0000,
1915 0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1916 0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x1f80,0x0180,0x01c0,0x0000,
1917 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3000,0x1f00,0x0180,0x3f00,0x0000,
1918 0x0000,0x0000,0x1800,0x1800,0x3e00,0x1800,0x1800,0x1800,0x0f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,
1919 0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x6180,0x6d80,0x6d80,0x7f80,
1920 0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x1b00,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,
1921 0x1f80,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0600,0x0c00,0x1800,0x3f00,0x0000,0x0000,0x0000,0x0e00,0x1800,0x1800,0x3000,
1922 0x1800,0x1800,0x0e00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x1c00,0x0600,0x0600,
1923 0x0300,0x0600,0x0600,0x1c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1924 0x1b00,0x3180,0x3180,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0000,0x1b00,
1925 0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0e00,
1926 0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,
1927 0x0c00,0x0600,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,
1928 0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,
1929 0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3f80,0x3000,
1930 0x1f00,0x0000,0x0000,0x0000,0x3600,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x1c00,0x3600,0x0000,0x1c00,0x0c00,0x0c00,
1931 0x0c00,0x1e00,0x0000,0x0000,0x1800,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,
1932 0x3f80,0x3180,0x3180,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x3180,0x3f80,0x3180,0x3180,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3f80,
1933 0x3000,0x3f00,0x3000,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x0ec0,0x3fc0,0x6e00,0x3b80,0x0000,0x0000,0x0000,0x1f80,0x3600,
1934 0x6600,0x7f80,0x6600,0x6600,0x6780,0x0000,0x0000,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x1b00,
1935 0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0e00,
1936 0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x0600,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,
1937 0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,
1938 0x0000,0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0000,0x0000,0x0400,0x1f00,0x3580,0x3400,0x3580,0x1f00,
1939 0x0400,0x0000,0x0000,0x0f00,0x1980,0x1800,0x3e00,0x1800,0x1800,0x3000,0x3f80,0x0000,0x0000,0x6180,0x6180,0x3300,0x1e00,0x3f00,0x0c00,
1940 0x3f00,0x0c00,0x0000,0x0000,0x7f00,0x6180,0x6d80,0x6d80,0x7f00,0x6c00,0x6c00,0x6700,0x0000,0x0000,0x0700,0x0c00,0x0c00,0x1e00,0x0c00,
1941 0x0c00,0x0c00,0x3800,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x1800,0x0000,0x1c00,0x0c00,
1942 0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3180,
1943 0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x1d80,0x3700,0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x1d80,0x3700,0x0000,
1944 0x3980,0x3d80,0x3780,0x3380,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0300,0x1f00,0x3300,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,
1945 0x3300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0c00,0x1800,0x3000,0x3000,0x3300,0x1e00,0x0000,0x0000,
1946 0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f80,0x0180,0x0180,0x0180,0x0000,0x0000,
1947 0x0000,0x2080,0x2100,0x2200,0x2400,0x0b00,0x1180,0x2300,0x4380,0x0000,0x0000,0x2080,0x2100,0x2200,0x2400,0x0a80,0x1280,0x2380,0x4080,
1948 0x0000,0x0000,0x0c00,0x0000,0x0c00,0x0c00,0x1e00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x1980,0x3300,0x6600,0x3300,0x1980,0x0000,
1949 0x0000,0x0000,0x0000,0x0000,0x6600,0x3300,0x1980,0x3300,0x6600,0x0000,0x0000,0x0000,0x2200,0x8880,0x2200,0x8880,0x2200,0x8880,0x2200,
1950 0x8880,0x2200,0x8880,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0xbb80,0xeec0,0xbb80,0xeec0,0xbb80,0xeec0,
1951 0xbb80,0xeec0,0xbb80,0xeec0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,
1952 0xfc00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,
1953 0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0x0000,0x0000,0xff00,0xff00,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xfc00,
1954 0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0xf300,0xf300,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,
1955 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xff00,0xff00,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,
1956 0x3300,0xf300,0xf300,0x0300,0x0300,0xff00,0xff00,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xff00,0xff00,0x0000,0x0000,0x0000,0x0000,
1957 0x1800,0x1800,0xf800,0xf800,0x1800,0x1800,0xf800,0xf800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfc00,0xfc00,0x0c00,0x0c00,0x0c00,
1958 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1959 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,
1960 0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,
1961 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,0x33c0,
1962 0x33c0,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,
1963 0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0xffc0,
1964 0xffc0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x0000,0x0000,
1965 0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x0c00,
1966 0x0c00,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1967 0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x3300,0x3300,0x3300,
1968 0x3300,0x3300,0x3300,0x3300,0x3300,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,
1969 0x0000,0x0000,0x0000,0x0000,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,0x3300,
1970 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1971 0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0fc0,
1972 0x0fc0,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1973 0x0000,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0x07c0,0x07c0,0x07c0,
1974 0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1975 0x0000,0x1d80,0x3700,0x3200,0x3700,0x1d80,0x0000,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3600,0x3300,0x3180,0x3700,0x3000,0x0000,0x0000,
1976 0x3f80,0x3180,0x3000,0x3000,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,
1977 0x0000,0x3f80,0x1800,0x0c00,0x0600,0x0c00,0x1800,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3600,0x3300,0x3300,0x1e00,0x0000,
1978 0x0000,0x0000,0x0000,0x0000,0x6300,0x6300,0x6700,0x7d80,0x6000,0x6000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0c00,0x0c00,0x0c00,0x0600,
1979 0x0000,0x0000,0x0000,0x1e00,0x0c00,0x3f00,0x6d80,0x6d80,0x3f00,0x0c00,0x1e00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3f00,0x3300,0x3300,
1980 0x1e00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x1b00,0x3b80,0x0000,0x0000,0x0000,0x1f00,0x0c00,0x0600,0x1f00,0x3180,
1981 0x3180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x66c0,0x64c0,0x6cc0,0x3b80,0x0000,0x0000,0x0000,0x0000,0x0180,0x3f00,0x6780,
1982 0x6d80,0x7980,0x3f00,0x6000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3000,0x1e00,0x3000,0x1f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,
1983 0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,
1984 0x3f00,0x0c00,0x0c00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0000,0x3f00,0x0000,0x0000,0x0000,0x1800,
1985 0x0c00,0x0600,0x0c00,0x1800,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0700,0x0d80,0x0d80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,
1986 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x6c00,0x6c00,0x3800,0x0000,0x0000,0x0000,0x0c00,0x0000,0x3f00,0x0000,0x0c00,0x0000,0x0000,0x0000,
1987 0x0000,0x3800,0x6d80,0x0700,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0e00,0x1b00,0x1b00,0x0e00,0x0000,0x0000,0x0000,0x0000,
1988 0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0000,0x0000,
1989 0x0000,0x0000,0x0000,0x07c0,0x0600,0x0600,0x6600,0x3600,0x1e00,0x0e00,0x0600,0x0200,0x0000,0x3e00,0x3300,0x3300,0x3300,0x3300,0x0000,
1990 0x0000,0x0000,0x0000,0x0000,0x1e00,0x0300,0x0e00,0x1800,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,0x1e00,0x1e00,
1991 0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1995 // bits 4..7: lshift
1996 public immutable ubyte[256] kgiFont6PropWidth
= () {
1998 foreach (immutable cnum
; 0..256) {
1999 import core
.bitop
: bsf, bsr;
2001 (cnum
>= 32 && cnum
<= 127) ||
2002 (cnum
>= 143 && cnum
<= 144) ||
2003 (cnum
>= 166 && cnum
<= 167) ||
2004 (cnum
>= 192 && cnum
<= 255);
2008 foreach (immutable dy
; 0..8) {
2009 immutable b
= kgiFont6
[cnum
*8+dy
];
2011 immutable mn
= 7-bsr(b
);
2012 if (mn
< shift
) shift
= mn
;
2017 foreach (immutable dy
; 0..8) {
2018 immutable b
= (kgiFont6
[cnum
*8+dy
]<<shift
);
2019 immutable cwdt
= (b ?
8-bsf(b
) : 0);
2020 if (cwdt
> wdt
) wdt
= cast(ubyte)cwdt
;
2023 case 0: wdt
= 8; break; // 8px space
2024 case 32: wdt
= 5; break; // 5px space
2025 case 17: .. case 27: wdt
= 8; break; // single frames
2026 case 48: .. case 57: wdt
= 5; break; // digits are monospaced
2027 case 127: .. case 142: wdt
= 8; break; // filled frames
2028 case 145: .. case 151: wdt
= 8; break; // filled frames
2029 case 155: .. case 159: wdt
= 8; break; // filled frames
2032 res
[cnum
] = (wdt
&0x0f)|
((shift
<<4)&0xf0);
2038 // bits 4..7: lshift
2039 public immutable ubyte[256] kgiFont8PropWidth
= () {
2041 foreach (immutable cnum
; 0..256) {
2042 import core
.bitop
: bsf, bsr;
2044 (cnum
>= 32 && cnum
<= 127) ||
2045 (cnum
>= 143 && cnum
<= 144) ||
2046 (cnum
>= 166 && cnum
<= 167) ||
2047 (cnum
>= 192 && cnum
<= 255);
2051 foreach (immutable dy
; 0..8) {
2052 immutable b
= kgiFont8
[cnum
*8+dy
];
2054 immutable mn
= 7-bsr(b
);
2055 if (mn
< shift
) shift
= mn
;
2060 foreach (immutable dy
; 0..8) {
2061 immutable b
= (kgiFont8
[cnum
*8+dy
]<<shift
);
2062 immutable cwdt
= (b ?
8-bsf(b
) : 0);
2063 if (cwdt
> wdt
) wdt
= cast(ubyte)cwdt
;
2066 case 0: wdt
= 8; break; // 8px space
2067 case 32: wdt
= 5; break; // 5px space
2068 case 48: .. case 57: wdt
= 5; break; // digits are monospaced
2069 case 176: .. case 223: wdt
= 8; break; // pseudographics (frames, etc)
2072 res
[cnum
] = (wdt
&0x0f)|
((shift
<<4)&0xf0);
2078 // ////////////////////////////////////////////////////////////////////////// //
2081 const(char)[] sdrGetPart(string typepfx
) (const(char)[] s
) nothrow @trusted @nogc {
2082 // skips prefix "---"
2083 static usize
findMark(string at
) (const(char)[] s
, uint idx
=0) nothrow @trusted @nogc {
2084 while (idx
< s
.length
) {
2085 if (idx
== 0 || s
.ptr
[idx
-1] == '\n') {
2086 while (idx
< s
.length
&& (s
.ptr
[idx
] == ' ' || s
.ptr
[idx
] == '\t')) ++idx
;
2087 if (s
.length
-idx
>= 3 && s
.ptr
[idx
] == '-' && s
.ptr
[idx
+1] == '-' && s
.ptr
[idx
+2] == '-') {
2088 static if (at
== "start") {
2089 while (idx
> 0 && s
.ptr
[idx
-1] != '\n') --idx
;
2090 } else static if (at
== "end") {
2092 while (idx
< s
.length
&& s
.ptr
[idx
] == '-') ++idx
;
2093 while (idx
< s
.length
&& (s
.ptr
[idx
] == ' ' || s
.ptr
[idx
] == '\t')) ++idx
;
2095 static assert(0, "wtf?!");
2105 usize idx
= findMark
!"end"(s
);
2106 while (idx
< s
.length
) {
2107 if (s
.length
-idx
>= typepfx
.length
&& s
[idx
..idx
+typepfx
.length
] == typepfx
) {
2108 while (idx
< s
.length
&& s
.ptr
[idx
] != '\n') ++idx
;
2109 while (idx
< s
.length
&& s
.ptr
[idx
] <= ' ') ++idx
;
2110 if (idx
>= s
.length
) return null;
2111 auto eidx
= findMark
!"start"(s
, idx
);
2112 if (eidx
> s
.length
) eidx
= s
.length
;
2113 while (eidx
> idx
&& s
.ptr
[eidx
-1] <= ' ') --eidx
;
2114 return (eidx
> idx ? s
[idx
..eidx
] : null);
2116 while (idx
< s
.length
&& s
.ptr
[idx
] != '\n') ++idx
;
2117 idx
= findMark
!"end"(s
, idx
);
2124 // find var id: glGetUniformLocation(prg, bufasciiz.ptr)
2125 // set var: glUniformXXX()
2127 // returns 0 or programid
2128 uint compileShaders (const(char)[] src
) nothrow @trusted {
2132 GLuint fsid
= 0, vsid
= 0;
2134 auto fragsrc
= sdrGetPart
!"frag"(src
);
2135 auto vertsrc
= sdrGetPart
!"vert"(src
);
2137 if (fragsrc
.length
== 0 && vertsrc
.length
== 0) return 0;
2139 if (fragsrc
.length
) {
2140 fsid
= createShader
!GL_FRAGMENT_SHADER(fragsrc
);
2141 if (fsid
== 0) return 0;
2144 if (vertsrc
.length
) {
2145 vsid
= createShader
!GL_VERTEX_SHADER(vertsrc
);
2147 if (fsid
!= 0) glDeleteShader(fsid
);
2152 prg
= glCreateProgram();
2154 if (fsid
!= 0) glDeleteShader(fsid
);
2155 if (vsid
!= 0) glDeleteShader(vsid
);
2156 conwriteln("GLKGI ERROR: can't create shader program.");
2160 if (fsid
) glAttachShader(prg
, fsid
);
2161 if (vsid
) glAttachShader(prg
, vsid
);
2165 glGetProgramiv(prg
, GL_LINK_STATUS
, &lres
);
2166 if (lres
!= GL_TRUE
) {
2167 glDeleteProgram(prg
);
2168 if (fsid
!= 0) glDeleteShader(fsid
);
2169 if (vsid
!= 0) glDeleteShader(vsid
);
2170 conwriteln("GLKGI ERROR: can't link shader program.");
2178 // returns 0 or shaderid
2179 uint createShader(uint type
) (const(char)[] src
) nothrow @trusted {
2182 auto shaderId
= glCreateShader(type
);
2184 conwriteln("GLKGI ERROR: can't create shader.");
2187 auto sptr
= src
.ptr
;
2188 GLint slen
= cast(int)src
.length
;
2189 glShaderSource(shaderId
, 1, &sptr
, &slen
);
2190 glCompileShader(shaderId
);
2192 glGetShaderiv(shaderId
, GL_COMPILE_STATUS
, &success
);
2193 if (!success || showShaderWarnings
) {
2194 import core
.stdc
.stdlib
: malloc
, free
;
2196 glGetShaderiv(shaderId
, GL_INFO_LOG_LENGTH
, &logSize
);
2198 auto logStrZ
= cast(GLchar
*)malloc(logSize
);
2199 if (logStrZ
!is null) {
2200 //import core.stdc.stdio : printf;
2201 scope(exit
) free(logStrZ
);
2202 glGetShaderInfoLog(shaderId
, logSize
, null, logStrZ
);
2203 if (logSize
> 0 && logStrZ
[logSize
-1] == 0) --logSize
;
2204 //printf("shader '%.*s' compilation messages:\n%s\n", cast(uint)ashaderName.length, ashaderName.ptr, logStrZ);
2205 conwriteln("GLKGI: shader compilation messages:\n", logStrZ
[0..logSize
]);
2210 glDeleteShader(shaderId
);
2211 conwriteln("GLKGI ERROR: can't compile shader.");
2218 // ////////////////////////////////////////////////////////////////////////// //
2220 static string sdrScanlineSrc
= q
{
2224 uniform sampler2D tex
;
2227 vec4 color
= texture2D(tex
, gl_TexCoord
[0].xy
);
2228 if (mod(floor(gl_FragCoord
.y
), 2) == 1) { color
.x
*= 0.75; color
.y
*= 0.75; color
.z
*= 0.75; }
2229 gl_FragColor
= color
;
2236 gl_TexCoord
[0] = gl_MultiTexCoord0
;
2237 //gl_Position = gl_ProjectionMatrix*gl_ModelViewMatrix*gl_Vertex;
2238 gl_Position
= gl_ProjectionMatrix
*gl_Vertex
;
2243 // ////////////////////////////////////////////////////////////////////////// //
2244 // default cursor (hi, Death Track!)
2245 private enum defaultCurWidth
= 17;
2246 private enum defaultCurHeight
= 23;
2247 private static immutable ubyte[defaultCurWidth
*defaultCurHeight
] defaultCurImg
= [
2248 0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2249 0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
2250 1,0,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
2251 1,1,3,3,2,2,0,0,0,0,0,0,0,0,0,0,0,
2252 1,1,3,3,4,2,2,0,0,0,0,0,0,0,0,0,0,
2253 1,1,3,3,4,4,2,2,0,0,0,0,0,0,0,0,0,
2254 1,1,3,3,4,4,4,2,2,0,0,0,0,0,0,0,0,
2255 1,1,3,3,4,4,4,4,2,2,0,0,0,0,0,0,0,
2256 1,1,3,3,4,4,4,5,6,2,2,0,0,0,0,0,0,
2257 1,1,3,3,4,4,5,6,7,5,2,2,0,0,0,0,0,
2258 1,1,3,3,4,5,6,7,5,4,5,2,2,0,0,0,0,
2259 1,1,3,3,5,6,7,5,4,5,6,7,2,2,0,0,0,
2260 1,1,3,3,6,7,5,4,5,6,7,7,7,2,2,0,0,
2261 1,1,3,3,7,5,4,5,6,7,7,7,7,7,2,2,0,
2262 1,1,3,3,5,4,5,6,8,8,8,8,8,8,8,8,2,
2263 1,1,3,3,4,5,6,3,8,8,8,8,8,8,8,8,8,
2264 1,1,3,3,5,6,3,3,1,1,1,1,1,1,1,0,0,
2265 1,1,3,3,6,3,3,1,1,1,1,1,1,1,1,0,0,
2266 1,1,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,
2267 1,1,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
2268 1,1,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
2269 1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2270 1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2272 private static immutable VColor
[9] defaultCurPal
= [
2273 rgbacol( 0, 0, 0, 0),
2274 rgbacol( 0, 0, 0,127),
2275 rgbacol( 85,255,255,255),
2276 rgbacol( 85, 85,255,255),
2277 rgbacol(255, 85, 85,255),
2278 rgbacol(170, 0,170,255),
2279 rgbacol( 85, 85, 85,255),
2280 rgbacol( 0, 0, 0,255),
2281 rgbacol( 0, 0,170,255),