1 /* Written by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
2 * Understanding is not required. Only obedience.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 3 of the License ONLY.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 module iv
.sdpyutil
/*is aliced*/;
19 import arsd
.simpledisplay
;
22 //version = krc_debug;
25 // ////////////////////////////////////////////////////////////////////////// //
26 public bool sdpyHasXShm () {
27 static if (UsingSimpledisplayX11
) {
28 __gshared
int xshmAvailable
= -1;
29 if (xshmAvailable
< 0) {
31 xshmAvailable
= (XQueryExtension(XDisplayConnection
.get(), "MIT-SHM", &i1
, &i2
, &i3
) != 0 ?
1 : 0);
33 return (xshmAvailable
> 0);
40 // ////////////////////////////////////////////////////////////////////////// //
41 /// get desktop number for the given window; -1: unknown
42 public int getWindowDesktop (SimpleWindow sw
) {
43 static if (UsingSimpledisplayX11
) {
44 import core
.stdc
.config
;
45 if (sw
is null || sw
.closed
) return -1;
46 auto dpy
= sw
.impl
.display
;
47 auto xwin
= sw
.impl
.window
;
48 auto atomWTF
= GetAtom
!("_NET_WM_DESKTOP", true)(dpy
);
55 auto status
= XGetWindowProperty(dpy
, xwin
, atomWTF
, 0, 1, /*False*/0, AnyPropertyType
, &aType
, &format
, &itemCount
, &bytesAfter
, &propRes
);
56 if (status
>= Success
) {
57 if (propRes
!is null) {
58 if (itemCount
> 0 && format
== 32) desktop
= *cast(int*)propRes
;
69 // ////////////////////////////////////////////////////////////////////////// //
70 /// switch to desktop with the given window
71 public void switchToWindowDesktop(bool doflush
=true) (SimpleWindow sw
) {
72 static if (UsingSimpledisplayX11
) {
73 if (sw
is null || sw
.closed
) return;
74 auto desktop
= sw
.getWindowDesktop();
75 if (desktop
< 0) return;
76 auto dpy
= sw
.impl
.display
;
78 e
.xclient
.type
= EventType
.ClientMessage
;
80 e
.xclient
.send_event
= 1/*True*/;
81 e
.xclient
.message_type
= GetAtom
!("_NET_CURRENT_DESKTOP", true)(dpy
);
82 e
.xclient
.window
= RootWindow(dpy
, DefaultScreen(dpy
));
83 e
.xclient
.format
= 32;
84 e
.xclient
.data
.l
[0] = desktop
;
85 XSendEvent(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)), false, EventMask
.SubstructureRedirectMask|EventMask
.SubstructureNotifyMask
, &e
);
86 static if (doflush
) flushGui();
91 // ////////////////////////////////////////////////////////////////////////// //
92 /// switch to the given window
93 public void switchToWindow(string src
="normal") (SimpleWindow sw
) if (src
== "normal" || src
== "pager") {
94 static if (UsingSimpledisplayX11
) {
95 if (sw
is null || sw
.closed
) return;
96 switchToWindowDesktop
!false(sw
);
97 auto dpy
= sw
.impl
.display
;
98 auto xwin
= sw
.impl
.window
;
100 e
.xclient
.type
= EventType
.ClientMessage
;
101 e
.xclient
.serial
= 0;
102 e
.xclient
.send_event
= 1/*True*/;
103 e
.xclient
.message_type
= GetAtom
!("_NET_ACTIVE_WINDOW", true)(dpy
);
104 e
.xclient
.window
= xwin
;
105 e
.xclient
.format
= 32;
106 static if (src
== "pager") {
107 e
.xclient
.data
.l
[0] = 2; // pretend to be a pager
109 e
.xclient
.data
.l
[0] = 1; // application request
111 XSendEvent(dpy
, RootWindow(dpy
, DefaultScreen(dpy
)), false, EventMask
.SubstructureRedirectMask|EventMask
.SubstructureNotifyMask
, &e
);
117 // ////////////////////////////////////////////////////////////////////////// //
118 /// Get global window coordinates and size. This can be used to show various notifications.
119 void getWindowRect (SimpleWindow sw
, out int x
, out int y
, out int width
, out int height
) {
120 static if (UsingSimpledisplayX11
) {
121 if (sw
is null || sw
.closed
) { width
= 1; height
= 1; return; } // 1: just in case
123 //XWindowAttributes xwa;
124 //XGetWindowAttributes(dpy, nativeHandle, &xwa);
125 //XTranslateCoordinates(dpy, nativeHandle, RootWindow(dpy, DefaultScreen(dpy)), xwa.x, xwa.y, &x, &y, &dummyw);
126 XTranslateCoordinates(sw
.impl
.display
, sw
.impl
.window
, RootWindow(sw
.impl
.display
, DefaultScreen(sw
.impl
.display
)), x
, y
, &x
, &y
, &dummyw
);
130 assert(0, "iv.sdpyutil: getWindowRect() -- not for windoze yet");
135 // ////////////////////////////////////////////////////////////////////////// //
136 public void getWorkAreaRect (out int x
, out int y
, out int width
, out int height
) {
137 static if (UsingSimpledisplayX11
) {
138 import core
.stdc
.config
;
141 auto dpy
= XDisplayConnection
.get
;
142 if (dpy
is null) return;
143 auto root
= RootWindow(dpy
, DefaultScreen(dpy
));
144 auto atomWTF
= GetAtom
!("_NET_WORKAREA", true)(dpy
);
150 auto status
= XGetWindowProperty(dpy
, root
, atomWTF
, 0, 4, /*False*/0, AnyPropertyType
, &aType
, &format
, &itemCount
, &bytesAfter
, cast(void**)&propRes
);
151 if (status
>= Success
) {
152 if (propRes
!is null) {
167 // ////////////////////////////////////////////////////////////////////////// //
168 enum _NET_WM_MOVERESIZE_SIZE_TOPLEFT
= 0;
169 enum _NET_WM_MOVERESIZE_SIZE_TOP
= 1;
170 enum _NET_WM_MOVERESIZE_SIZE_TOPRIGHT
= 2;
171 enum _NET_WM_MOVERESIZE_SIZE_RIGHT
= 3;
172 enum _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT
= 4;
173 enum _NET_WM_MOVERESIZE_SIZE_BOTTOM
= 5;
174 enum _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT
= 6;
175 enum _NET_WM_MOVERESIZE_SIZE_LEFT
= 7;
176 enum _NET_WM_MOVERESIZE_MOVE
= 8; /* movement only */
177 enum _NET_WM_MOVERESIZE_SIZE_KEYBOARD
= 9; /* size via keyboard */
178 enum _NET_WM_MOVERESIZE_MOVE_KEYBOARD
= 10; /* move via keyboard */
179 enum _NET_WM_MOVERESIZE_CANCEL
= 11; /* cancel operation */
182 public void wmInitiateMoving (SimpleWindow sw
, int localx
, int localy
) {
183 static if (UsingSimpledisplayX11
) {
184 if (sw
is null || sw
.closed || sw
.hidden
) return;
186 auto dpy
= sw
.impl
.display
;
187 auto xwin
= sw
.impl
.window
;
188 auto root
= RootWindow(dpy
, DefaultScreen(dpy
));
189 // convert local to global
190 //{ import core.stdc.stdio; printf("local: %d,%d\n", localx, localy); }
191 XTranslateCoordinates(dpy
, xwin
, root
, localx
, localy
, &localx
, &localy
, &dummyw
);
192 //{ import core.stdc.stdio; printf("global: %d,%d\n", localx, localy); }
195 e
.xclient
.type
= EventType
.ClientMessage
;
196 e
.xclient
.serial
= 0;
197 e
.xclient
.send_event
= 1/*True*/;
198 e
.xclient
.message_type
= GetAtom
!("_NET_WM_MOVERESIZE", true)(dpy
);
199 e
.xclient
.window
= xwin
;
200 e
.xclient
.format
= 32;
201 e
.xclient
.data
.l
[0] = localx
; // root_x
202 e
.xclient
.data
.l
[1] = localy
; // root_y
203 e
.xclient
.data
.l
[2] = _NET_WM_MOVERESIZE_MOVE
;
204 e
.xclient
.data
.l
[3] = 0; // left button
205 e
.xclient
.data
.l
[4] = 1; // application request
206 XSendEvent(dpy
, root
, false, EventMask
.SubstructureRedirectMask|EventMask
.SubstructureNotifyMask
, &e
);
212 public void wmCancelMoving (SimpleWindow sw
, int localx
, int localy
) {
213 static if (UsingSimpledisplayX11
) {
214 if (sw
is null || sw
.closed || sw
.hidden
) return;
216 auto dpy
= sw
.impl
.display
;
217 auto xwin
= sw
.impl
.window
;
218 auto root
= RootWindow(dpy
, DefaultScreen(dpy
));
219 // convert local to global
220 XTranslateCoordinates(dpy
, xwin
, root
, localx
, localy
, &localx
, &localy
, &dummyw
);
223 e
.xclient
.type
= EventType
.ClientMessage
;
224 e
.xclient
.serial
= 0;
225 e
.xclient
.send_event
= 1/*True*/;
226 e
.xclient
.message_type
= GetAtom
!("_NET_WM_MOVERESIZE", true)(dpy
);
227 e
.xclient
.window
= xwin
;
228 e
.xclient
.format
= 32;
229 e
.xclient
.data
.l
[0] = localx
; // root_x
230 e
.xclient
.data
.l
[1] = localy
; // root_y
231 e
.xclient
.data
.l
[2] = _NET_WM_MOVERESIZE_CANCEL
;
232 e
.xclient
.data
.l
[3] = 0; // left button
233 e
.xclient
.data
.l
[4] = 1; // application request
234 XSendEvent(dpy
, root
, false, EventMask
.SubstructureRedirectMask|EventMask
.SubstructureNotifyMask
, &e
);
240 // ////////////////////////////////////////////////////////////////////////// //
241 public struct XRefCounted(T
) if (is(T
== struct)) {
246 static void doIncRef (usize ox
) nothrow @trusted @nogc {
247 pragma(inline
, true);
249 *cast(uint*)(ox
-uint.sizeof
) += 1;
250 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("doIncRef for 0x%08x (%u)\n", cast(uint)ox
, *cast(uint*)(ox
-uint.sizeof
)); }
254 static void doDecRef() (ref usize ox
) {
256 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("doDecRef for 0x%08x (%u)\n", cast(uint)ox
, *cast(uint*)(ox
-uint.sizeof
)); }
257 if ((*cast(uint*)(ox
-uint.sizeof
) -= 1) == 0) {
260 import core
.stdc
.stdlib
: free
;
261 import core
.memory
: GC
;
263 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("CG CLEANUP FOR WRAPPER 0x%08x\n", cast(uint)ox
); }
264 version(krc_debug
) import core
.stdc
.stdio
: printf
;
265 void* mem
= cast(void*)ox
;
266 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("DESTROYING WRAPPER 0x%08x\n", cast(uint)mem
); }
267 enum instSize
= T
.sizeof
;
268 auto pbm
= __traits(getPointerBitmap
, T
);
269 version(krc_debug
) printf("[%.*s]: size=%u (%u) (%u)\n", cast(uint)T
.stringof
.length
, T
.stringof
.ptr
, cast(uint)pbm
[0], cast(uint)instSize
, cast(uint)(pbm
[0]/usize
.sizeof
));
270 immutable(ubyte)* p
= cast(immutable(ubyte)*)(pbm
.ptr
+1);
272 immutable end
= pbm
[0]/usize
.sizeof
;
273 while (bitnum
< end
) {
274 if (p
[bitnum
/8]&(1U<<(bitnum
%8))) {
276 while (bitnum
+len
< end
&& (p
[(bitnum
+len
)/8]&(1U<<((bitnum
+len
)%8))) != 0) ++len
;
277 version(krc_debug
) printf(" #%u (%u)\n", cast(uint)(bitnum
*usize
.sizeof
), cast(uint)len
);
278 GC
.removeRange((cast(usize
*)mem
)+bitnum
);
285 free(cast(void*)(ox
-uint.sizeof
));
288 (*cast(T
*)ox
).destroy
;
294 this(A
...) (auto ref A args
) {
295 intrp__
= newOx
!T(args
);
298 this() (auto ref typeof(this) src
) nothrow @trusted @nogc {
299 intrp__
= src
.intrp__
;
303 ~this () { doDecRef(intrp__
); }
305 this (this) nothrow @trusted @nogc { doIncRef(intrp__
); }
307 void opAssign() (typeof(this) src
) {
308 if (!intrp__
&& !src
.intrp__
) return;
309 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("***OPASSIGN(0x%08x -> 0x%08x)\n", cast(void*)src
.intrp__
, cast(void*)intrp__
); }
311 // assigning to non-empty
313 // both streams are active
314 if (intrp__
== src
.intrp__
) return; // nothing to do
316 auto newo
= src
.intrp__
;
317 // first increase rc for new object
319 // replace object for this
321 // release old object
324 // just close this one
325 scope(exit
) intrp__
= 0;
328 } else if (src
.intrp__
) {
329 // this is empty, but other is not; easy deal
330 intrp__
= src
.intrp__
;
335 usize
toHash () const pure nothrow @safe @nogc { pragma(inline
, true); return intrp__
; } // yeah, so simple
336 bool opEquals() (auto ref typeof(this) s
) const { pragma(inline
, true); return (intrp__
== s
.intrp__
); }
338 @property bool hasObject () const pure nothrow @trusted @nogc { pragma(inline
, true); return (intrp__
!= 0); }
340 @property inout(T
)* intr_ () inout pure nothrow @trusted @nogc { pragma(inline
, true); return cast(typeof(return))intrp__
; }
343 static if (__traits(compiles
, ((){T s
; bool v
= s
.valid
;}))) {
344 @property bool valid () const nothrow @trusted @nogc { pragma(inline
, true); return (intrp__ ? intr_
.valid
: false); }
350 usize
newOx (CT
, A
...) (auto ref A args
) if (is(CT
== struct)) {
351 import core
.exception
: onOutOfMemoryErrorNoGC
;
352 import core
.memory
: GC
;
353 import core
.stdc
.stdlib
: malloc
, free
;
354 import core
.stdc
.string
: memset
;
355 import std
.conv
: emplace
;
356 enum instSize
= CT
.sizeof
;
357 // let's hope that malloc() aligns returned memory right
358 auto memx
= malloc(instSize
+uint.sizeof
);
359 if (memx
is null) onOutOfMemoryErrorNoGC(); // oops
360 scope(failure
) free(memx
);
361 memset(memx
, 0, instSize
+uint.sizeof
);
362 *cast(uint*)memx
= 1;
363 auto mem
= memx
+uint.sizeof
;
364 emplace
!CT(mem
[0..instSize
], args
);
366 version(krc_debug
) import core
.stdc
.stdio
: printf
;
367 auto pbm
= __traits(getPointerBitmap
, CT
);
368 version(krc_debug
) printf("[%.*s]: size=%u (%u) (%u)\n", cast(uint)CT
.stringof
.length
, CT
.stringof
.ptr
, cast(uint)pbm
[0], cast(uint)instSize
, cast(uint)(pbm
[0]/usize
.sizeof
));
369 immutable(ubyte)* p
= cast(immutable(ubyte)*)(pbm
.ptr
+1);
371 immutable end
= pbm
[0]/usize
.sizeof
;
372 while (bitnum
< end
) {
373 if (p
[bitnum
/8]&(1U<<(bitnum
%8))) {
375 while (bitnum
+len
< end
&& (p
[(bitnum
+len
)/8]&(1U<<((bitnum
+len
)%8))) != 0) ++len
;
376 version(krc_debug
) printf(" #%u (%u)\n", cast(uint)(bitnum
*usize
.sizeof
), cast(uint)len
);
377 GC
.addRange((cast(usize
*)mem
)+bitnum
, usize
.sizeof
*len
);
383 version(krc_debug
) { import core
.stdc
.stdio
: printf
; printf("CREATED WRAPPER 0x%08x\n", mem
); }
384 return cast(usize
)mem
;
389 static if (UsingSimpledisplayX11
) {
390 // ////////////////////////////////////////////////////////////////////////// //
391 // for X11 we will keep all XShm-allocated images in this list, so we can free 'em on connection closing.
392 // we'll use glibc malloc()/free(), 'cause `unregisterImage()` can be called from object dtor.
393 private struct XShmSeg
{
395 __gshared usize headp
= 0, tailp
= 0;
397 static @property XShmSeg
* head () nothrow @trusted @nogc { pragma(inline
, true); return cast(XShmSeg
*)headp
; }
398 static @property void head (XShmSeg
* v
) nothrow @trusted @nogc { pragma(inline
, true); headp
= cast(usize
)v
; }
400 static @property XShmSeg
* tail () nothrow @trusted @nogc { pragma(inline
, true); return cast(XShmSeg
*)tailp
; }
401 static @property void tail (XShmSeg
* v
) nothrow @trusted @nogc { pragma(inline
, true); tailp
= cast(usize
)v
; }
404 usize segp
; // XShmSegmentInfo*; hide it from GC
405 usize prevp
; // next link; hide it from GC
406 usize nextp
; // next link; hide it from GC
409 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline
, true); return (segp
!= 0); }
411 @property XShmSeg
* next () pure nothrow @trusted @nogc { pragma(inline
, true); return cast(XShmSeg
*)nextp
; }
412 @property void next (XShmSeg
* v
) pure nothrow @trusted @nogc { pragma(inline
, true); nextp
= cast(usize
)v
; }
414 @property XShmSeg
* prev () pure nothrow @trusted @nogc { pragma(inline
, true); return cast(XShmSeg
*)prevp
; }
415 @property void prev (XShmSeg
* v
) pure nothrow @trusted @nogc { pragma(inline
, true); prevp
= cast(usize
)v
; }
417 @property XShmSegmentInfo
* seg () pure nothrow @trusted @nogc { pragma(inline
, true); return cast(XShmSegmentInfo
*)segp
; }
418 @property void seg (XShmSegmentInfo
* v
) pure nothrow @trusted @nogc { pragma(inline
, true); segp
= cast(usize
)v
; }
421 XShmSeg
* alloc () nothrow @trusted @nogc {
422 import core
.stdc
.stdlib
: malloc
, free
;
423 XShmSeg
* res
= cast(XShmSeg
*)malloc(XShmSeg
.sizeof
);
425 res
.seg
= cast(XShmSegmentInfo
*)malloc(XShmSegmentInfo
.sizeof
);
426 if (res
.seg
is null) { free(res
); return null; }
429 if (tail
!is null) tail
.next
= res
; else { assert(head
is null); head
= res
; }
435 void free (XShmSeg
* seg
, bool unregister
) {
437 //{ import core.stdc.stdio; printf("00: freeing...\n"); }
438 import core
.stdc
.stdlib
: free
;
439 if (seg
.prev
!is null) seg
.prev
.next
= seg
.next
; else { assert(head
is seg
); head
= head
.next
; if (head
!is null) head
.prev
= null; }
440 if (seg
.next
!is null) seg
.next
.prev
= seg
.prev
; else { assert(tail
is seg
); tail
= tail
.prev
; if (tail
!is null) tail
.next
= null; }
443 //{ import core.stdc.stdio; printf("00: freeing-unreg...\n"); }
444 shmdt(seg
.seg
.shmaddr
);
445 shmctl(seg
.seg
.shmid
, IPC_RMID
, null);
454 import core
.stdc
.stdlib
: free
;
455 while (head
!is null) {
456 //{ import core.stdc.stdio; printf("01: freeing...\n"); }
458 //{ import core.stdc.stdio; printf("01: freeing-unreg...\n"); }
459 shmdt(head
.seg
.shmaddr
);
460 shmctl(head
.seg
.shmid
, IPC_RMID
, null);
470 shared static ~this () { freeList(); }
475 // ////////////////////////////////////////////////////////////////////////// //
476 public alias XImageTC
= XRefCounted
!XlibImageTC
;
478 public struct XlibImageTC
{
479 static if (UsingSimpledisplayX11
) {
480 private bool thisIsXShm
;
485 private XShmSeg
* shminfo
;
487 @disable this (this);
489 this (MemoryImage img
, bool xshm
=false) {
490 if (img
is null || img
.width
< 1 || img
.height
< 1) throw new Exception("can't create xlib image from empty MemoryImage");
491 create(img
.width
, img
.height
, img
, xshm
);
494 this (int wdt
, int hgt
, bool xshm
=false) {
495 if (wdt
< 1 || hgt
< 1) throw new Exception("invalid xlib image");
496 create(wdt
, hgt
, null, xshm
);
499 this (int wdt
, int hgt
, MemoryImage aimg
, bool xshm
=false) {
500 if (wdt
< 1 || hgt
< 1) throw new Exception("invalid xlib image");
501 create(wdt
, hgt
, aimg
, xshm
);
504 ~this () { dispose(); }
506 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline
, true); return (thisIsXShm ? handleshm
!is null : handle
.data
!is null); }
507 @property bool xshm () const pure nothrow @trusted @nogc { pragma(inline
, true); return thisIsXShm
; }
509 @property int width () const pure nothrow @trusted @nogc { pragma(inline
, true); return (thisIsXShm ? handleshm
.width
: handle
.width
); }
510 @property int height () const pure nothrow @trusted @nogc { pragma(inline
, true); return (thisIsXShm ? handleshm
.height
: handle
.height
); }
512 inout(uint)* data () inout nothrow @trusted @nogc { pragma(inline
, true); return cast(typeof(return))(thisIsXShm ? handleshm
.data
: handle
.data
); }
514 void setup (MemoryImage aimg
, bool xshm
=false) {
516 if (aimg
is null || aimg
.width
< 1 || aimg
.height
< 1) throw new Exception("can't create xlib image from empty MemoryImage");
517 create(aimg
.width
, aimg
.height
, aimg
, xshm
);
520 void setup (int wdt
, int hgt
, MemoryImage aimg
=null, bool xshm
=false) {
522 if (wdt
< 1 || hgt
< 1) throw new Exception("invalid xlib image");
523 create(wdt
, hgt
, aimg
, xshm
);
526 TrueColorImage
getAsTC () {
527 if (!valid
) return null;
528 auto tc
= new TrueColorImage(width
, height
);
529 scope(failure
) delete tc
;
530 auto sc
= cast(const(uint)*)data
;
531 auto dc
= tc
.imageData
.colors
.ptr
;
532 foreach (immutable dy
; 0..height
) {
533 foreach (immutable dx
; 0..width
) {
534 *dc
++ = img2c(*sc
++);
540 private void create (int width
, int height
, MemoryImage ximg
, bool xshm
) {
541 import core
.stdc
.stdlib
: malloc
, free
;
542 if (xshm
&& !sdpyHasXShm
) xshm
= false;
545 auto dpy
= XDisplayConnection
.get();
546 if (dpy
is null) throw new Exception("can't create XShmImage");
548 shminfo
= XShmSeg
.alloc();
549 if (shminfo
is null) throw new Exception("can't create XShmImage");
550 bool registered
= false;
551 scope(failure
) { XShmSeg
.free(shminfo
, registered
); shminfo
= null; }
553 handleshm
= XShmCreateImage(dpy
, DefaultVisual(dpy
, DefaultScreen(dpy
)), 24, ImageFormat
.ZPixmap
, null, shminfo
.seg
, width
, height
);
554 if (handleshm
is null) throw new Exception("can't create XShmImage");
555 assert(handleshm
.bytes_per_line
== 4*width
);
557 shminfo
.seg
.shmid
= shmget(IPC_PRIVATE
, handleshm
.bytes_per_line
*height
, IPC_CREAT|
511 /* 0777 */);
558 assert(shminfo
.seg
.shmid
>= 0);
560 handleshm
.data
= shminfo
.seg
.shmaddr
= cast(ubyte*)shmat(shminfo
.seg
.shmid
, null, 0);
561 assert(handleshm
.data
!= cast(ubyte*)-1);
563 auto rawData
= cast(uint*)handleshm
.data
;
564 if (ximg
is null || ximg
.width
< width || ximg
.height
< height
) rawData
[0..width
*height
] = 0;
565 if (ximg
!is null && ximg
.width
> 0 && ximg
.height
> 0) {
566 foreach (immutable int y
; 0..height
) {
567 foreach (immutable int x
; 0..width
) {
568 rawData
[y
*width
+x
] = c2img(ximg
.getPixel(x
, y
));
573 shminfo
.seg
.readOnly
= 0;
574 XShmAttach(dpy
, shminfo
.seg
);
576 auto rawData
= cast(uint*)malloc(width
*height
*4);
577 scope(failure
) free(rawData
);
578 if (ximg
is null || ximg
.width
< width || ximg
.height
< height
) rawData
[0..width
*height
] = 0;
579 if (ximg
!is null && ximg
.width
> 0 && ximg
.height
> 0) {
580 foreach (immutable int y
; 0..height
) {
581 foreach (immutable int x
; 0..width
) {
582 rawData
[y
*width
+x
] = c2img(ximg
.getPixel(x
, y
));
586 //handle = XCreateImage(dpy, DefaultVisual(dpy, screen), 24/*bpp*/, ImageFormat.ZPixmap, 0/*offset*/, cast(ubyte*)rawData, width, height, 8/*FIXME*/, 4*width); // padding, bytes per line
587 handle
.width
= width
;
588 handle
.height
= height
;
590 handle
.format
= ImageFormat
.ZPixmap
;
591 handle
.data
= rawData
;
592 handle
.byte_order
= 0;
593 handle
.bitmap_unit
= 32;
594 handle
.bitmap_bit_order
= 0;
595 handle
.bitmap_pad
= 8;
597 handle
.bytes_per_line
= 0;
598 handle
.bits_per_pixel
= 32; // THIS MATTERS!
599 handle
.red_mask
= 0x00ff0000;
600 handle
.green_mask
= 0x0000ff00;
601 handle
.blue_mask
= 0x000000ff;
608 if (auto dpy
= XDisplayConnection
.get()) XShmDetach(dpy
, shminfo
.seg
);
609 XDestroyImage(handleshm
);
610 //shmdt(shminfo.seg.shmaddr);
611 //shmctl(shminfo.seg.shmid, IPC_RMID, null);
612 XShmSeg
.free(shminfo
, true);
616 if (handle
.data
!is null) {
617 import core
.stdc
.stdlib
: free
;
618 if (handle
.data
!is null) free(handle
.data
);
619 handle
= XImage
.init
;
624 void putPixel (int x
, int y
, Color c
) nothrow @trusted @nogc {
625 pragma(inline
, true);
626 if (valid
&& x
>= 0 && y
>= 0 && x
< width
&& y
< height
) {
627 data
[y
*width
+x
] = c2img(c
);
631 Color
getPixel (int x
, int y
, Color c
) nothrow @trusted @nogc {
632 pragma(inline
, true);
633 return (valid
&& x
>= 0 && y
>= 0 && x
< width
&& y
< height ?
img2c(data
[y
*width
+x
]) : Color
.transparent
);
636 uint* row (int y
) nothrow @trusted @nogc {
637 pragma(inline
, true);
638 return (valid
&& y
>= 0 && y
< height ? data
+y
*width
: null);
641 // blit to window buffer
642 void blitAt (SimpleWindow w
, int destx
, int desty
) { blitRect(w
, destx
, desty
, 0, 0, width
, height
); }
644 // blit to window buffer
645 void blitRect (SimpleWindow w
, int destx
, int desty
, int sx0
, int sy0
, int swdt
, int shgt
) {
646 if (w
is null ||
!valid || w
.closed
) return;
648 XShmPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.buffer
, w
.impl
.gc
, handleshm
, sx0
, sy0
, destx
, desty
, swdt
, shgt
, 0);
650 XPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.buffer
, w
.impl
.gc
, &handle
, sx0
, sy0
, destx
, desty
, swdt
, shgt
);
655 void blitAtWin (SimpleWindow w
, int destx
, int desty
) { blitRectWin(w
, destx
, desty
, 0, 0, width
, height
); }
658 void blitRectWin (SimpleWindow w
, int destx
, int desty
, int sx0
, int sy0
, int swdt
, int shgt
) {
659 if (w
is null ||
!valid || w
.closed
) return;
661 XShmPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, w
.impl
.gc
, handleshm
, sx0
, sy0
, destx
, desty
, swdt
, shgt
, 0);
663 XPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, w
.impl
.gc
, &handle
, sx0
, sy0
, destx
, desty
, swdt
, shgt
);
669 public ubyte icR (uint c
) pure nothrow @safe @nogc { pragma(inline
, true); return ((c
>>16)&0xff); }
670 public ubyte icG (uint c
) pure nothrow @safe @nogc { pragma(inline
, true); return ((c
>>8)&0xff); }
671 public ubyte icB (uint c
) pure nothrow @safe @nogc { pragma(inline
, true); return (c
&0xff); }
672 public ubyte icA (uint c
) pure nothrow @safe @nogc { pragma(inline
, true); return ((c
>>24)&0xff); }
674 public uint icRGB (int r
, int g
, int b
) pure nothrow @safe @nogc {
675 pragma(inline
, true);
676 return (Color
.clampToByte(r
)<<16)|
(Color
.clampToByte(g
)<<8)|Color
.clampToByte(b
);
679 public uint icRGBA (int r
, int g
, int b
, int a
) pure nothrow @safe @nogc {
680 pragma(inline
, true);
681 return (Color
.clampToByte(a
)<<24)|
(Color
.clampToByte(r
)<<16)|
(Color
.clampToByte(g
)<<8)|Color
.clampToByte(b
);
684 public uint c2img (in Color c
) pure nothrow @safe @nogc {
685 pragma(inline
, true);
687 ((c
.asUint
&0xff)<<16)|
688 (c
.asUint
&0x00ff00U
)|
689 ((c
.asUint
>>16)&0xff);
692 public uint c2imgA (in Color c
) pure nothrow @safe @nogc {
693 pragma(inline
, true);
695 ((c
.asUint
&0xff)<<16)|
696 (c
.asUint
&0xff_00ff00U)|
697 ((c
.asUint
>>16)&0xff);
700 public uint c2img (uint c
) pure nothrow @safe @nogc {
701 pragma(inline
, true);
708 public uint c2imgA (uint c
) pure nothrow @safe @nogc {
709 pragma(inline
, true);
716 public Color
img2c (uint clr
) pure nothrow @safe @nogc {
717 pragma(inline
, true);
718 return Color((clr
>>16)&0xff, (clr
>>8)&0xff, clr
&0xff);
721 public Color
img2cA (uint clr
) pure nothrow @safe @nogc {
722 pragma(inline
, true);
723 return Color((clr
>>16)&0xff, (clr
>>8)&0xff, clr
&0xff, (clr
>>24)&0xff);
728 // ////////////////////////////////////////////////////////////////////////// //
729 static if (UsingSimpledisplayX11
) {
731 public alias XPixmap
= XRefCounted
!XlibPixmap
;
733 public struct XlibPixmap
{
735 private int mWidth
, mHeight
;
737 this (SimpleWindow w
) {}
739 this (SimpleWindow w
, int wdt
, int hgt
) { setup(w
, wdt
, hgt
); }
740 this (SimpleWindow w
, ref XlibImageTC xtc
) { setup(w
, xtc
); }
741 this (SimpleWindow w
, XImageTC xtc
) { if (!xtc
.hasObject
) throw new Exception("can't create pixmap from empty object"); setup(w
, *xtc
.intr_
); }
743 this (SimpleWindow w
, ref XlibPixmap xpm
) { setup(w
, xpm
); }
744 this (SimpleWindow w
, XPixmap xpm
) { if (!xpm
.hasObject
) throw new Exception("can't create pixmap from empty object"); setup(w
, *xpm
.intr_
); }
746 @disable this (this);
748 ~this () { dispose(); }
750 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline
, true); return (xpm
!= 0); }
752 @property int width () const pure nothrow @trusted @nogc { pragma(inline
, true); return mWidth
; }
753 @property int height () const pure nothrow @trusted @nogc { pragma(inline
, true); return mHeight
; }
755 void copyFromWinBuf (SimpleWindow w
) {
756 if (w
is null || w
.closed
) throw new Exception("can't copy pixmap without window");
757 if (!valid || mWidth
!= w
.width || mHeight
!= w
.height
) {
759 xpm
= XCreatePixmap(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, w
.width
, w
.height
, 24);
763 XCopyArea(w
.impl
.display
, cast(Drawable
)w
.impl
.buffer
, cast(Drawable
)xpm
, w
.impl
.gc
, 0, 0, mWidth
, mHeight
, 0, 0);
766 void copyFrom (SimpleWindow w
, ref XlibPixmap axpm
) {
768 if (!axpm
.valid
) return;
769 if (w
is null || w
.closed
) throw new Exception("can't copy pixmap without window");
770 XCopyArea(w
.impl
.display
, cast(Drawable
)axpm
.xpm
, cast(Drawable
)xpm
, w
.impl
.gc
, 0, 0, axpm
.width
, axpm
.height
, 0, 0);
773 void copyFrom (SimpleWindow w
, XPixmap axpm
) {
774 if (!axpm
.hasObject
) return;
775 copyFrom(w
, *axpm
.intr_
);
778 void setup (SimpleWindow w
, int wdt
, int hgt
) {
780 if (w
is null || w
.closed
) throw new Exception("can't create pixmap without window");
781 if (wdt
< 1) wdt
= 1;
782 if (hgt
< 1) hgt
= 1;
783 if (wdt
> 16384) wdt
= 16384;
784 if (hgt
> 16384) hgt
= 16384;
785 xpm
= XCreatePixmap(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, wdt
, hgt
, 24);
790 void setup (SimpleWindow w
, XPixmap xpm
) {
791 if (!xpm
.hasObject
) throw new Exception("can't create pixmap from empty xlib image");
792 setup(w
, *xpm
.intr_
);
795 void setup (SimpleWindow w
, ref XlibPixmap axpm
) {
796 if (!axpm
.valid
) throw new Exception("can't create pixmap from empty xlib pixmap");
798 if (w
is null || w
.closed
) throw new Exception("can't create pixmap without window");
799 int wdt
= axpm
.width
;
800 int hgt
= axpm
.height
;
801 if (wdt
< 1) wdt
= 1;
802 if (hgt
< 1) hgt
= 1;
803 if (wdt
> 16384) wdt
= 16384;
804 if (hgt
> 16384) hgt
= 16384;
805 xpm
= XCreatePixmap(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, wdt
, hgt
, 24);
806 XCopyArea(w
.impl
.display
, cast(Drawable
)axpm
.xpm
, cast(Drawable
)xpm
, w
.impl
.gc
, 0, 0, wdt
, hgt
, 0, 0);
811 void setup (SimpleWindow w
, XImageTC xtc
) {
812 if (!xtc
.hasObject
) throw new Exception("can't create pixmap from empty xlib image");
813 setup(w
, *xtc
.intr_
);
816 void setup (SimpleWindow w
, ref XlibImageTC xtc
) {
817 if (!xtc
.valid
) throw new Exception("can't create pixmap from empty xlib image");
819 if (w
is null || w
.closed
) throw new Exception("can't create pixmap without window");
821 int hgt
= xtc
.height
;
822 if (wdt
< 1) wdt
= 1;
823 if (hgt
< 1) hgt
= 1;
824 if (wdt
> 16384) wdt
= 16384;
825 if (hgt
> 16384) hgt
= 16384;
826 xpm
= XCreatePixmap(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, wdt
, hgt
, 24);
827 // source x, source y
828 if (xtc
.thisIsXShm
) {
829 XShmPutImage(w
.impl
.display
, cast(Drawable
)xpm
, w
.impl
.gc
, xtc
.handleshm
, 0, 0, 0, 0, wdt
, hgt
, 0);
831 XPutImage(w
.impl
.display
, cast(Drawable
)xpm
, w
.impl
.gc
, &xtc
.handle
, 0, 0, 0, 0, wdt
, hgt
);
839 XFreePixmap(XDisplayConnection
.get(), xpm
);
842 mWidth
= mHeight
= 0;
845 // blit to window buffer
846 void blitAt (SimpleWindow w
, int x
, int y
) {
847 blitRect(w
, x
, y
, 0, 0, width
, height
);
850 // blit to window buffer
851 void blitRect (SimpleWindow w
, int destx
, int desty
, int sx0
, int sy0
, int swdt
, int shgt
) {
852 if (w
is null ||
!xpm || w
.closed
) return;
853 XCopyArea(w
.impl
.display
, cast(Drawable
)xpm
, cast(Drawable
)w
.impl
.buffer
, w
.impl
.gc
, sx0
, sy0
, swdt
, shgt
, destx
, desty
);
856 // blit to window buffer
857 void blitAtWin (SimpleWindow w
, int x
, int y
) {
858 blitRectWin(w
, x
, y
, 0, 0, width
, height
);
861 // blit to window buffer
862 void blitRectWin (SimpleWindow w
, int destx
, int desty
, int sx0
, int sy0
, int swdt
, int shgt
) {
863 if (w
is null ||
!xpm || w
.closed
) return;
864 XCopyArea(w
.impl
.display
, cast(Drawable
)xpm
, cast(Drawable
)w
.impl
.window
, w
.impl
.gc
, sx0
, sy0
, swdt
, shgt
, destx
, desty
);
868 // ////////////////////////////////////////////////////////////////////////// //
872 void sdpyNormalizeArrowKeys(bool domods
=true) (ref KeyEvent event
) {
875 case Key
.Ctrl_r
: event
.key
= Key
.Ctrl
; return;
876 case Key
.Shift_r
: event
.key
= Key
.Shift
; return;
877 case Key
.Alt_r
: event
.key
= Key
.Alt
; return;
878 case Key
.Windows_r
: event
.key
= Key
.Windows
; return;
882 if ((event
.modifierState
&ModifierState
.numLock
) == 0) {
884 case Key
.PadEnter
: event
.key
= Key
.Enter
; return;
885 case Key
.Pad1
: event
.key
= Key
.End
; return;
886 case Key
.Pad2
: event
.key
= Key
.Down
; return;
887 case Key
.Pad3
: event
.key
= Key
.PageDown
; return;
888 case Key
.Pad4
: event
.key
= Key
.Left
; return;
889 //case Key.Pad5: event.key = Key.; return;
890 case Key
.Pad6
: event
.key
= Key
.Right
; return;
891 case Key
.Pad7
: event
.key
= Key
.Home
; return;
892 case Key
.Pad8
: event
.key
= Key
.Up
; return;
893 case Key
.Pad9
: event
.key
= Key
.PageUp
; return;
894 case Key
.Pad0
: event
.key
= Key
.Insert
; return;
902 // ////////////////////////////////////////////////////////////////////////// //
903 // this mixin can be used to alphablend two `uint` colors
904 // `colu32name` is variable that holds color to blend,
905 // `destu32name` is variable that holds "current" color (from surface, for example)
906 // alpha value of `destu32name` doesn't matter
907 // alpha value of `colu32name` means: 255 for replace color, 0 for keep `destu32name` (was reversed)
908 private enum ColorBlendMixinStr(string colu32name, string destu32name) = "{
909 immutable uint a_tmp_ = (256-(255-(("~colu32name~")>>24)))&(-(1-(((255-(("~colu32name~")>>24))+1)>>8))); // to not loose bits, but 255 should become 0
910 immutable uint dc_tmp_ = ("~destu32name~")&0xffffff;
911 immutable uint srb_tmp_ = (("~colu32name~")&0xff00ff);
912 immutable uint sg_tmp_ = (("~colu32name~")&0x00ff00);
913 immutable uint drb_tmp_ = (dc_tmp_&0xff00ff);
914 immutable uint dg_tmp_ = (dc_tmp_&0x00ff00);
915 immutable uint orb_tmp_ = (drb_tmp_+(((srb_tmp_-drb_tmp_)*a_tmp_+0x800080)>>8))&0xff00ff;
916 immutable uint og_tmp_ = (dg_tmp_+(((sg_tmp_-dg_tmp_)*a_tmp_+0x008000)>>8))&0x00ff00;
917 ("~destu32name~") = (orb_tmp_|og_tmp_)|0xff000000; /*&0xffffff;*/
921 Color blend (Color dst, Color src) nothrow @trusted @nogc {
922 pragma(inline, true);
923 mixin(ColorBlendMixinStr!("src.asUint", "dst.asUint"));
928 // the only two requirements: alpha is in high bits, and "0 alpha" means "transparent"
929 uint blendU32 (uint dst, uint src) nothrow @trusted @nogc {
930 pragma(inline, true);
931 mixin(ColorBlendMixinStr!("src", "dst"));
936 Color
blend (Color dst
, Color src
) pure nothrow @trusted @nogc { pragma(inline
, true); return dst
.alphaBlend(src
); }
937 uint blendU32 (uint dst
, uint src
) pure nothrow @trusted @nogc { pragma(inline
, true); mixin(Color
.ColorBlendMixinStr
!("src", "dst")); return dst
; }
940 // ////////////////////////////////////////////////////////////////////////// //
943 // some "fastgfx" backend
946 static T
abs(T
) (T n
) pure nothrow @safe @nogc { pragma(inline
, true); return (n
< 0 ?
-n
: n
); }
949 private static int lrintf (float f
) nothrow @trusted @nogc { pragma(inline
, true); return cast(int)(f
+0.5f); }
950 private static int lrintd (double f
) nothrow @trusted @nogc { pragma(inline
, true); return cast(int)(f
+0.5); }
952 private import core
.stdc
.math
: lrintf
, lrintd
= lrint
;
954 private import core
.stdc
.math
: sqrtf
, sqrtd
= sqrt
;
955 private import core
.stdc
.math
: floorf
, floord
= floor
;
956 private import core
.stdc
.math
: cosf
, sinf
;
962 protected: // low-level methods; will always be called with valid coords
964 abstract Color
getpix (int x
, int y
);
965 abstract void putpix (int x
, int y
, Color c
);
968 void hline (int x
, int y
, int len
, Color c
) {
969 while (len
-- > 0) putpix(x
++, y
, c
);
972 void vline (int x
, int y
, int len
, Color c
) {
973 while (len
-- > 0) putpix(x
, y
++, c
);
976 void fillrc (int x
, int y
, int w
, int h
, Color c
) {
977 while (h
-- > 0) hline(x
, y
++, w
, c
);
981 this (int awdt
, int ahgt
) {
982 if (awdt
< 0) awdt
= 0;
983 if (ahgt
< 0) ahgt
= 0;
984 dim
= GxSize(awdt
, ahgt
);
988 final @property int width () const pure nothrow @safe @nogc { pragma(inline
, true); return dim
.width
; }
989 final @property int height () const pure nothrow @safe @nogc { pragma(inline
, true); return dim
.height
; }
991 void cls (Color clr
=Color
.white
) { fillrc(0, 0, dim
.width
, dim
.height
, clr
); }
993 // can return null, yeah
994 TrueColorImage
getBuffer () { return null; }
997 Color
getPixel (int x
, int y
) {
998 pragma(inline
, true);
999 return (x
>= 0 && y
>= 0 && x
< dim
.width
&& y
< dim
.height
&& clip
.inside(x
, y
) ?
getpix(x
, y
) : Color
.transparent
);
1002 void putPixel (int x
, int y
, Color c
) {
1003 pragma(inline
, true);
1004 if (x
>= 0 && y
>= 0 && x
< dim
.width
&& y
< dim
.height
&& clip
.inside(x
, y
)) putpix(x
, y
, c
);
1007 void drawHLine (int x
, int y
, int len
, Color c
) {
1008 pragma(inline
, true);
1009 if (GxRect(dim
).clipHStripe(x
, y
, len
) && clip
.clipHStripe(x
, y
, len
)) hline(x
, y
, len
, c
);
1012 void drawVLine (int x
, int y
, int len
, Color c
) {
1013 pragma(inline
, true);
1014 if (GxRect(dim
).clipVStripe(x
, y
, len
) && clip
.clipVStripe(x
, y
, len
)) vline(x
, y
, len
, c
);
1017 void fillRect (int x
, int y
, int w
, int h
, Color c
) {
1018 pragma(inline
, true);
1019 if (GxRect(dim
).clipHVStripes(x
, y
, w
, h
) && clip
.clipHVStripes(x
, y
, w
, h
)) fillrc(x
, y
, w
, h
, c
);
1022 void drawRect(bool filled
) (int x
, int y
, int w
, int h
, Color c
) {
1023 pragma(inline
, true);
1024 static if (filled
) {
1025 if (GxRect(dim
).clipHVStripes(x
, y
, w
, h
) && clip
.clipHVStripes(x
, y
, w
, h
)) fillrc(x
, y
, w
, h
, c
);
1028 if (h
> 1) hline(x
, y
+h
-1, w
, c
);
1029 if (h
> 2 && w
> 2) {
1030 vline(x
+1, y
, w
-2, c
);
1031 vline(x
+1, y
+h
-1, w
-2, c
);
1036 void drawEllipse(bool filled
=false) (int x0
, int y0
, int x1
, int y1
, Color col
) {
1037 int a
= abs(x1
-x0
), b
= abs(y1
-y0
), b1
= b
&1; // values of diameter
1038 long dx
= 4*(1-a
)*b
*b
, dy
= 4*(b1
+1)*a
*a
; // error increment
1039 long err
= dx
+dy
+b1
*a
*a
; // error of 1.step
1040 int prev_y0
= -1, prev_y1
= -1;
1041 if (x0
> x1
) { x0
= x1
; x1
+= a
; } // if called with swapped points...
1042 if (y0
> y1
) y0
= y1
; // ...exchange them
1043 y0
+= (b
+1)/2; y1
= y0
-b1
; // starting pixel
1044 a
*= 8*a
; b1
= 8*b
*b
;
1047 if (y0
!= prev_y0
) {
1048 static if (filled
) {
1049 drawHLine(x0
, y0
, x1
-x0
+1, col
);
1051 putPixel(x0
, y0
, col
);
1052 if (x1
!= x0
) putPixel(x1
, y0
, col
);
1056 if (y1
!= y0
&& y1
!= prev_y1
) {
1057 static if (filled
) {
1058 drawHLine(x0
, y1
, x1
-x0
+1, col
);
1060 putPixel(x0
, y1
, col
);
1061 if (x1
!= x0
) putPixel(x1
, y1
, col
);
1066 if (e2
>= dx
) { ++x0
; --x1
; err
+= dx
+= b1
; } // x step
1067 if (e2
<= dy
) { ++y0
; --y1
; err
+= dy
+= a
; } // y step
1070 // too early stop of flat ellipses a=1
1071 putPixel(x0
-1, ++y0
, col
); // complete tip of ellipse
1072 putPixel(x0
-1, --y1
, col
);
1076 void drawCircle(bool filled
=false) (int cx
, int cy
, int radius
, Color col
) {
1077 if (radius
< 1) return;
1078 int error
= -radius
, x
= radius
, y
= 0;
1079 if (radius
== 1) { putPixel(cx
, cy
, col
); return; }
1085 static if (filled
) {
1086 drawHLine(cx
-x
, cy
+last_y
, 2*x
+1, col
);
1088 putPixel(cx
-x
, cy
+last_y
, col
);
1089 if (x
!= 0) putPixel(cx
+x
, cy
+last_y
, col
);
1091 if (x
!= 0 && last_y
!= 0) {
1092 static if (filled
) {
1093 drawHLine(cx
-x
, cy
-last_y
, 2*x
+1, col
);
1095 putPixel(cx
-x
, cy
-last_y
, col
);
1096 putPixel(cx
+x
, cy
-last_y
, col
);
1101 static if (filled
) {
1102 drawHLine(cx
-last_y
, cy
+x
, 2*last_y
+1, col
);
1103 if (last_y
!= 0 && x
!= 0) drawHLine(cx
-last_y
, cy
-x
, 2*last_y
+1, col
);
1105 putPixel(cx
-last_y
, cy
+x
, col
);
1106 if (last_y
!= 0 && x
!= 0) {
1107 putPixel(cx
+last_y
, cy
+x
, col
);
1108 putPixel(cx
-last_y
, cy
-x
, col
);
1109 putPixel(cx
+last_y
, cy
-x
, col
);
1120 void drawLineEx(bool lastPoint
=true) (int x0
, int y0
, int x1
, int y1
, scope void delegate (int x
, int y
) putPixel
) {
1121 enum swap(string a
, string b
) = "{int tmp_="~a
~";"~a
~"="~b
~";"~b
~"=tmp_;}";
1123 if (x0
== x1
&& y0
== y1
) {
1124 static if (lastPoint
) putPixel(x0
, y0
);
1129 int wx0
= clip
.x0
, wy0
= clip
.y0
, wx1
= clip
.x1
, wy1
= clip
.y1
;
1130 if (wx0
< 0) wx0
= 0; else if (wx0
>= dim
.width
) wx0
= dim
.width
-1;
1131 if (wx1
< 0) wx1
= 0; else if (wx1
>= dim
.width
) wx1
= dim
.width
-1;
1132 if (wy0
< 0) wy0
= 0; else if (wy0
>= dim
.height
) wy0
= dim
.height
-1;
1133 if (wy1
< 0) wy1
= 0; else if (wy1
>= dim
.height
) wy1
= dim
.height
-1;
1134 if (wx0
> wx1 || wy0
> wy1
) return;
1136 int stx
, sty
; // "steps" for x and y axes
1137 int dsx
, dsy
; // "lengthes" for x and y axes
1138 int dx2
, dy2
; // "double lengthes" for x and y axes
1139 int xd
, yd
; // current coord
1140 int e
; // "error" (as in bresenham algo)
1146 // from left to right
1147 if (x0
> wx1 || x1
< wx0
) return; // out of screen
1148 stx
= 1; // going right
1150 // from right to left
1151 if (x1
> wx1 || x0
< wx0
) return; // out of screen
1152 stx
= -1; // going left
1157 mixin(swap
!("wx0", "wx1"));
1161 // from top to bottom
1162 if (y0
> wy1 || y1
< wy0
) return; // out of screen
1163 sty
= 1; // going down
1165 // from bottom to top
1166 if (y1
> wy1 || y0
< wy0
) return; // out of screen
1167 sty
= -1; // going up
1172 mixin(swap
!("wy0", "wy1"));
1179 mixin(swap
!("x0", "y0"));
1180 mixin(swap
!("x1", "y1"));
1181 mixin(swap
!("dsx", "dsy"));
1182 mixin(swap
!("wx0", "wy0"));
1183 mixin(swap
!("wx1", "wy1"));
1184 mixin(swap
!("stx", "sty"));
1195 bool xfixed
= false;
1198 int temp
= dx2
*(wy0
-y0
)-dsx
;
1201 if (xd
> wx1
) return; // x is moved out of clipping rect, nothing to do
1205 if (rem
> 0) { ++xd
; e
+= dy2
; }
1209 if (!xfixed
&& x0
< wx0
) {
1211 int temp
= dy2
*(wx0
-x0
);
1214 if (yd
> wy1 || yd
== wy1
&& rem
>= dsx
) return;
1217 if (rem
>= dsx
) { ++yd
; e
-= dx2
; }
1221 int temp
= dx2
*(wy1
-y0
)+dsx
;
1224 if (rem
== 0) --term
;
1226 if (term
> wx1
) term
= wx1
; // clip at right
1227 static if (lastPoint
) {
1231 if (term
== xd
) return; // this is the only point, get out of here
1233 if (sty
== -1) yd
= -yd
;
1234 if (stx
== -1) { xd
= -xd
; term
= -term
; }
1236 // draw it; `putPixel()` can omit checks
1237 while (xd
!= term
) {
1239 // done drawing, move coords
1250 void drawLine(bool lastPoint
=true) (int x0
, int y0
, int x1
, int y1
, Color c
) { drawLineEx
!lastPoint(x0
, y0
, x1
, y1
, (x
, y
) => putPixel(x
, y
, c
)); }
1252 // ////////////////////////////////////////////////////////////////////// //
1253 // plot a limited quadratic Bezier segment
1254 final void drawQuadBezierSeg (int x0
, int y0
, int x1
, int y1
, int x2
, int y2
, Color fc
) {
1255 int sx
= x2
-x1
, sy
= y2
-y1
;
1256 long xx
= x0
-x1
, yy
= y0
-y1
; // relative values for checks
1257 assert(xx
*sx
<= 0 && yy
*sy
<= 0); // sign of gradient must not change
1258 double cur
= xx
*sy
-yy
*sx
; // curvature
1259 // begin with longer part
1260 if (sx
*cast(long)sx
+sy
*cast(long)sy
> xx
*xx
+yy
*yy
) { x2
= x0
; x0
= sx
+x1
; y2
= y0
; y0
= sy
+y1
; cur
= -cur
; } // swap P0 P2
1263 xx
+= sx
; xx
*= (sx
= (x0
< x2 ?
1 : -1)); // x step direction
1264 yy
+= sy
; yy
*= (sy
= (y0
< y2 ?
1 : -1)); // y step direction
1265 // differences 2nd degree
1269 // negated curvature?
1270 if (cur
*sx
*sy
< 0) { xx
= -xx
; yy
= -yy
; xy
= -xy
; cur
= -cur
; }
1271 double dx
= 4.0*sy
*cur
*(x1
-x0
)+xx
-xy
; // differences 1st degree
1272 double dy
= 4.0*sx
*cur
*(y0
-y1
)+yy
-xy
;
1275 double err
= dx
+dy
+xy
; // error 1st step
1277 putPixel(x0
, y0
, fc
); // plot curve
1278 if (x0
== x2
&& y0
== y2
) return; // last pixel -> curve finished
1279 y1
= 2*err
< dx
; // save value for test of y step
1280 if (2*err
> dy
) { x0
+= sx
; dx
-= xy
; err
+= dy
+= yy
; } // x step
1281 if (y1
) { y0
+= sy
; dy
-= xy
; err
+= dx
+= xx
; } // y step
1282 } while (dy
< 0 && dx
> 0); // gradient negates -> algorithm fails
1284 drawLine(x0
, y0
, x2
, y2
, fc
); // plot remaining part to end
1287 // plot any quadratic Bezier curve
1288 final void drawQuadBezier (int x0
, int y0
, int x1
, int y1
, int x2
, int y2
, Color fc
) {
1289 int x
= x0
-x1
, y
= y0
-y1
;
1290 double t
= x0
-2*x1
+x2
;
1291 // horizontal cut at P4?
1292 if (cast(long)x
*(x2
-x1
) > 0) {
1293 // vertical cut at P6 too?
1294 if (cast(long)y
*(y2
-y1
) > 0) {
1296 if (abs((y0
-2*y1
+y2
)/t
*x
) > abs(y
)) { x0
= x2
; x2
= x
+x1
; y0
= y2
; y2
= y
+y1
; } // swap points
1297 // now horizontal cut at P4 comes first
1300 double r
= (1-t
)*((1-t
)*y0
+2.0*t
*y1
)+t
*t
*y2
; // By(t=P4)
1301 t
= (x0
*x2
-x1
*x1
)*t
/(x0
-x1
); // gradient dP4/dx=0
1302 x
= cast(int)lrintd(t
); y
= cast(int)lrintd(r
);
1303 r
= (y1
-y0
)*(t
-x0
)/(x1
-x0
)+y0
; // intersect P3 | P0 P1
1304 drawQuadBezierSeg(x0
, y0
, x
, cast(int)lrintd(r
), x
, y
, fc
);
1305 r
= (y1
-y2
)*(t
-x2
)/(x1
-x2
)+y2
; // intersect P4 | P1 P2
1306 x0
= x1
= x
; y0
= y
; y1
= cast(int)lrintd(r
); // P0 = P4, P1 = P8
1308 // vertical cut at P6?
1309 if (cast(long)(y0
-y1
)*(y2
-y1
) > 0) {
1310 t
= y0
-2*y1
+y2
; t
= (y0
-y1
)/t
;
1311 double r
= (1-t
)*((1-t
)*x0
+2.0*t
*x1
)+t
*t
*x2
; // Bx(t=P6)
1312 t
= (y0
*y2
-y1
*y1
)*t
/(y0
-y1
); // gradient dP6/dy=0
1313 x
= cast(int)lrintd(r
); y
= cast(int)lrintd(t
);
1314 r
= (x1
-x0
)*(t
-y0
)/(y1
-y0
)+x0
; // intersect P6 | P0 P1
1315 drawQuadBezierSeg(x0
, y0
, cast(int)lrintd(r
), y
, x
, y
, fc
);
1316 r
= (x1
-x2
)*(t
-y2
)/(y1
-y2
)+x2
; // intersect P7 | P1 P2
1317 x0
= x
; x1
= cast(int)lrintd(r
); y0
= y1
= y
; // P0 = P6, P1 = P7
1319 drawQuadBezierSeg(x0
, y0
, x1
, y1
, x2
, y2
, fc
); // remaining part
1322 // plot a limited rational Bezier segment, squared weight
1323 final void drawQuadRationalBezierSeg (int x0
, int y0
, int x1
, int y1
, int x2
, int y2
, float w
, Color fc
) {
1324 int sx
= x2
-x1
, sy
= y2
-y1
; // relative values for checks
1325 double dx
= x0
-x2
, dy
= y0
-y2
, xx
= x0
-x1
, yy
= y0
-y1
;
1326 double xy
= xx
*sy
+yy
*sx
, cur
= xx
*sy
-yy
*sx
; // curvature
1327 assert(xx
*sx
<= 0.0 && yy
*sy
<= 0.0); // sign of gradient must not change
1328 if (cur
!= 0.0 && w
> 0.0) { // no straight line
1329 // begin with longer part
1330 if (sx
*cast(long)sx
+sy
*cast(long)sy
> xx
*xx
+yy
*yy
) { x2
= x0
; x0
-= cast(int)dx
; y2
= y0
; y0
-= cast(int)dy
; cur
= -cur
; } // swap P0 P2
1331 xx
= 2.0*(4.0*w
*sx
*xx
+dx
*dx
); // differences 2nd degree
1332 yy
= 2.0*(4.0*w
*sy
*yy
+dy
*dy
);
1333 sx
= (x0
< x2 ?
1 : -1); // x step direction
1334 sy
= (y0
< y2 ?
1 : -1); // y step direction
1335 xy
= -2.0*sx
*sy
*(2.0*w
*xy
+dx
*dy
);
1336 // negated curvature?
1337 if (cur
*sx
*sy
< 0.0) { xx
= -xx
; yy
= -yy
; xy
= -xy
; cur
= -cur
; }
1338 dx
= 4.0*w
*(x1
-x0
)*sy
*cur
+xx
/2.0+xy
; // differences 1st degree
1339 dy
= 4.0*w
*(y0
-y1
)*sx
*cur
+yy
/2.0+xy
;
1340 if (w
< 0.5 && dy
> dx
) {
1341 // flat ellipse, algorithm fails
1342 cur
= (w
+1.0)/2.0; w
= sqrtf(w
); xy
= 1.0/(w
+1.0);
1343 sx
= cast(int)lrintd((x0
+2.0*w
*x1
+x2
)*xy
/2.0); // subdivide curve in half
1344 sy
= cast(int)lrintd((y0
+2.0*w
*y1
+y2
)*xy
/2.0);
1345 dx
= floord((w
*x1
+x0
)*xy
+0.5); dy
= floord((y1
*w
+y0
)*xy
+0.5);
1346 drawQuadRationalBezierSeg(x0
, y0
, cast(int)dx
, cast(int)dy
, sx
, sy
, cur
, fc
);/* plot separately */
1347 dx
= floord((w
*x1
+x2
)*xy
+0.5); dy
= floord((y1
*w
+y2
)*xy
+0.5);
1348 drawQuadRationalBezierSeg(sx
, sy
, cast(int)dx
, cast(int)dy
, x2
, y2
, cur
, fc
);
1351 double err
= dx
+dy
-xy
; // error 1.step
1353 putPixel(x0
, y0
, fc
); // plot curve
1354 if (x0
== x2
&& y0
== y2
) return; // last pixel -> curve finished
1355 x1
= 2*err
> dy
; y1
= 2*(err
+yy
) < -dy
;/* save value for test of x step */
1356 if (2*err
< dx || y1
) { y0
+= sy
; dy
+= xy
; err
+= dx
+= xx
; }/* y step */
1357 if (2*err
> dx || x1
) { x0
+= sx
; dx
+= xy
; err
+= dy
+= yy
; }/* x step */
1358 } while (dy
<= xy
&& dx
>= xy
); // gradient negates -> algorithm fails
1360 drawLine(x0
, y0
, x2
, y2
, fc
); // plot remaining needle to end
1363 // rectangle enclosing the ellipse, integer rotation angle
1364 final void drawRotatedEllipseRect (int x0
, int y0
, int x1
, int y1
, long zd
, Color fc
) {
1365 int xd
= x1
-x0
, yd
= y1
-y0
;
1366 float w
= xd
*cast(long)yd
;
1367 if (zd
== 0) return drawEllipse(x0
, y0
, x1
, y1
, fc
); // looks nicer
1368 if (w
!= 0.0) w
= (w
-zd
)/(w
+w
); // squared weight of P1
1369 assert(w
<= 1.0 && w
>= 0.0); // limit angle to |zd|<=xd*yd
1370 // snap xe,ye to int
1371 xd
= cast(int)lrintf(xd
*w
);
1372 yd
= cast(int)lrintf(yd
*w
);
1373 drawQuadRationalBezierSeg(x0
, y0
+yd
, x0
, y0
, x0
+xd
, y0
, 1.0-w
, fc
);
1374 drawQuadRationalBezierSeg(x0
, y0
+yd
, x0
, y1
, x1
-xd
, y1
, w
, fc
);
1375 drawQuadRationalBezierSeg(x1
, y1
-yd
, x1
, y1
, x1
-xd
, y1
, 1.0-w
, fc
);
1376 drawQuadRationalBezierSeg(x1
, y1
-yd
, x1
, y0
, x0
+xd
, y0
, w
, fc
);
1379 // plot ellipse rotated by angle (radian)
1380 final void drawRotatedEllipse (int x
, int y
, int a
, int b
, float angle
, Color fc
) {
1381 float xd
= cast(long)a
*a
, yd
= cast(long)b
*b
;
1382 float s
= sinf(angle
), zd
= (xd
-yd
)*s
; // ellipse rotation
1383 xd
= sqrtf(xd
-zd
*s
), yd
= sqrtf(yd
+zd
*s
); // surrounding rectangle
1384 a
= cast(int)lrintf(xd
);
1385 b
= cast(int)lrintf(yd
);
1386 zd
= zd
*a
*b
/(xd
*yd
); // scale to integer
1387 drawRotatedEllipseRect(x
-a
, y
-b
, x
+a
, y
+b
, cast(long)(4*zd
*cosf(angle
)), fc
);
1390 // plot limited cubic Bezier segment
1391 final void drawCubicBezierSeg (int x0
, int y0
, float x1
, float y1
, float x2
, float y2
, int x3
, int y3
, Color fc
) {
1392 immutable double EP
= 0.01;
1394 int sx
= (x0
< x3 ?
1 : -1), sy
= (y0
< y3 ?
1 : -1); // step direction
1395 float xc
= -abs(x0
+x1
-x2
-x3
), xa
= xc
-4*sx
*(x1
-x2
), xb
= sx
*(x0
-x1
-x2
+x3
);
1396 float yc
= -abs(y0
+y1
-y2
-y3
), ya
= yc
-4*sy
*(y1
-y2
), yb
= sy
*(y0
-y1
-y2
+y3
);
1397 // check for curve restrains
1398 // slope P0-P1 == P2-P3 and (P0-P3 == P1-P2 or no slope change)
1399 assert((x1
-x0
)*(x2
-x3
) < EP
&& ((x3
-x0
)*(x1
-x2
) < EP || xb
*xb
< xa
*xc
+EP
));
1400 assert((y1
-y0
)*(y2
-y3
) < EP
&& ((y3
-y0
)*(y1
-y2
) < EP || yb
*yb
< ya
*yc
+EP
));
1402 if (xa
== 0 && ya
== 0) {
1404 sx
= cast(int)floorf((3*x1
-x0
+1)/2);
1405 sy
= cast(int)floorf((3*y1
-y0
+1)/2);
1406 return drawQuadBezierSeg(x0
, y0
, sx
, sy
, x3
, y3
, fc
);
1408 x1
= (x1
-x0
)*(x1
-x0
)+(y1
-y0
)*(y1
-y0
)+1; // line lengths
1409 x2
= (x2
-x3
)*(x2
-x3
)+(y2
-y3
)*(y2
-y3
)+1;
1410 // loop over both ends
1412 double ab
= xa
*yb
-xb
*ya
;
1413 double ac
= xa
*yc
-xc
*ya
;
1414 double bc
= xb
*yc
-xc
*yb
;
1415 double ex
= ab
*(ab
+ac
-3*bc
)+ac
*ac
; // P0 part of self-intersection loop?
1416 immutable int f
= cast(int)(ex
> 0 ?
1 : sqrtf(1+1024/x1
)); // calculate resolution
1417 ab
*= f
; ac
*= f
; bc
*= f
; ex
*= f
*f
; // increase resolution
1418 // init differences of 1st degree
1419 double xy
= 9*(ab
+ac
+bc
)/8;
1420 double cb
= 8*(xa
-ya
);
1421 double dx
= 27*(8*ab
*(yb
*yb
-ya
*yc
)+ex
*(ya
+2*yb
+yc
))/64-ya
*ya
*(xy
-ya
);
1422 double dy
= 27*(8*ab
*(xb
*xb
-xa
*xc
)-ex
*(xa
+2*xb
+xc
))/64-xa
*xa
*(xy
+xa
);
1423 // init differences of 2nd degree
1424 double xx
= 3*(3*ab
*(3*yb
*yb
-ya
*ya
-2*ya
*yc
)-ya
*(3*ac
*(ya
+yb
)+ya
*cb
))/4;
1425 double yy
= 3*(3*ab
*(3*xb
*xb
-xa
*xa
-2*xa
*xc
)-xa
*(3*ac
*(xa
+xb
)+xa
*cb
))/4;
1426 xy
= xa
*ya
*(6*ab
+6*ac
-3*bc
+cb
); ac
= ya
*ya
; cb
= xa
*xa
;
1427 xy
= 3*(xy
+9*f
*(cb
*yb
*yc
-xb
*xc
*ac
)-18*xb
*yb
*ab
)/8;
1428 // negate values if inside self-intersection loop
1429 if (ex
< 0) { dx
= -dx
; dy
= -dy
; xx
= -xx
; yy
= -yy
; xy
= -xy
; ac
= -ac
; cb
= -cb
; }
1430 // init differences of 3rd degree
1435 // error of 1st step
1439 const(double)* pxy
= &xy
;
1440 zzloop
: for (int fx
= f
, fy
= f
; x0
!= x3
&& y0
!= y3
; ) {
1441 putPixel(x0
, y0
, fc
); // plot curve
1442 // move sub-steps of one pixel
1444 if (dx
> *pxy || dy
< *pxy
) break zzloop
; // confusing values
1445 y1
= 2*ex
-dy
; // save value for test of y step
1446 if (2*ex
>= dx
) { fx
--; ex
+= dx
+= xx
; dy
+= xy
+= ac
; yy
+= bc
; xx
+= ab
; } // x sub-step
1447 if (y1
<= 0) { fy
--; ex
+= dy
+= yy
; dx
+= xy
+= bc
; xx
+= ac
; yy
+= cb
; } // y sub-step
1448 } while (fx
> 0 && fy
> 0); // pixel complete?
1449 if (2*fx
<= f
) { x0
+= sx
; fx
+= f
; } // x step
1450 if (2*fy
<= f
) { y0
+= sy
; fy
+= f
; } // y step
1451 if (pxy
== &xy
&& dx
< 0 && dy
> 0) pxy
= &EP
; // pixel ahead valid
1454 xx
= x0
; x0
= x3
; x3
= cast(int)xx
; sx
= -sx
; xb
= -xb
;
1455 yy
= y0
; y0
= y3
; y3
= cast(int)yy
; sy
= -sy
; yb
= -yb
; x1
= x2
;
1456 } while (leg
--); // try other end
1457 drawLine(x0
, y0
, x3
, y3
, fc
); // remaining part in case of cusp or crunode
1460 // plot any cubic Bezier curve
1461 final void drawCubicBezier (int x0
, int y0
, int x1
, int y1
, int x2
, int y2
, int x3
, int y3
, Color fc
) {
1463 long xc
= x0
+x1
-x2
-x3
, xa
= xc
-4*(x1
-x2
);
1464 long xb
= x0
-x1
-x2
+x3
, xd
= xb
+4*(x1
+x2
);
1465 long yc
= y0
+y1
-y2
-y3
, ya
= yc
-4*(y1
-y2
);
1466 long yb
= y0
-y1
-y2
+y3
, yd
= yb
+4*(y1
+y2
);
1467 float fx0
= x0
, fy0
= y0
;
1468 double t1
= xb
*xb
-xa
*xc
;
1470 // sub-divide curve at gradient sign changes
1471 if (xa
== 0) { // horizontal
1472 if (abs(xc
) < 2*abs(xb
)) t
.ptr
[n
++] = xc
/(2.0*xb
); // one change
1473 } else if (t1
> 0.0) { // two changes
1474 immutable double t2
= sqrtd(t1
);
1475 t1
= (xb
-t2
)/xa
; if (abs(t1
) < 1.0) t
.ptr
[n
++] = t1
;
1476 t1
= (xb
+t2
)/xa
; if (abs(t1
) < 1.0) t
.ptr
[n
++] = t1
;
1479 if (ya
== 0) { // vertical
1480 if (abs(yc
) < 2*abs(yb
)) t
.ptr
[n
++] = yc
/(2.0*yb
); // one change
1481 } else if (t1
> 0.0) { // two changes
1482 immutable double t2
= sqrtd(t1
);
1483 t1
= (yb
-t2
)/ya
; if (abs(t1
) < 1.0) t
.ptr
[n
++] = t1
;
1484 t1
= (yb
+t2
)/ya
; if (abs(t1
) < 1.0) t
.ptr
[n
++] = t1
;
1486 // bubble sort of 4 points
1487 for (i
= 1; i
< n
; i
++) if ((t1
= t
.ptr
[i
-1]) > t
.ptr
[i
]) { t
.ptr
[i
-1] = t
.ptr
[i
]; t
.ptr
[i
] = t1
; i
= 0; }
1488 t1
= -1.0; t
.ptr
[n
] = 1.0; // begin / end point
1489 for (i
= 0; i
<= n
; i
++) { // plot each segment separately
1490 immutable double t2
= t
.ptr
[i
]; // sub-divide at t[i-1], t[i]
1491 float fx1
= (t1
*(t1
*xb
-2*xc
)-t2
*(t1
*(t1
*xa
-2*xb
)+xc
)+xd
)/8-fx0
;
1492 float fy1
= (t1
*(t1
*yb
-2*yc
)-t2
*(t1
*(t1
*ya
-2*yb
)+yc
)+yd
)/8-fy0
;
1493 float fx2
= (t2
*(t2
*xb
-2*xc
)-t1
*(t2
*(t2
*xa
-2*xb
)+xc
)+xd
)/8-fx0
;
1494 float fy2
= (t2
*(t2
*yb
-2*yc
)-t1
*(t2
*(t2
*ya
-2*yb
)+yc
)+yd
)/8-fy0
;
1495 immutable float fx3
= (t2
*(t2
*(3*xb
-t2
*xa
)-3*xc
)+xd
)/8;
1496 immutable float fy3
= (t2
*(t2
*(3*yb
-t2
*ya
)-3*yc
)+yd
)/8;
1499 // scale bounds to int
1500 x3
= cast(int)lrintf(fx3
);
1501 y3
= cast(int)lrintf(fy3
);
1502 if (fx0
!= 0.0f) { fx1
*= fx0
= (x0
-x3
)/fx0
; fx2
*= fx0
; }
1503 if (fy0
!= 0.0f) { fy1
*= fy0
= (y0
-y3
)/fy0
; fy2
*= fy0
; }
1504 if (x0
!= x3 || y0
!= y3
) drawCubicBezierSeg(x0
, y0
, x0
+fx1
, y0
+fy1
, x0
+fx2
, y0
+fy2
, x3
, y3
, fc
); // segment t1 - t2
1505 x0
= x3
; y0
= y3
; fx0
= fx3
; fy0
= fy3
; t1
= t2
;
1509 // ////////////////////////////////////////////////////////////////////////// //
1510 enum BaphometDims
= 512; // [0..511]
1511 final void renderBaphomet (Color fc
, float ofsx
=0, float ofsy
=0, float scalex
=1, float scaley
=1) {
1512 auto path
= cast(const(ubyte)[])baphometPath
;
1513 immutable plen
= path
.length
;
1517 Bounds
, // always first, has 4 args (x0, y0, x1, y1)
1525 CubicTo
, // cubic bezier
1529 Command
getCommand () nothrow @trusted @nogc {
1530 if (ppos
>= plen
) assert(0, "invalid path");
1531 return cast(Command
)(path
.ptr
[ppos
++]);
1534 float getFloat () nothrow @trusted @nogc {
1535 if (ppos
>= plen || plen
-ppos
< float.sizeof
) assert(0, "invalid path");
1536 version(LittleEndian
) {
1537 float res
= *cast(const(float)*)(&path
.ptr
[ppos
]);
1538 ppos
+= cast(uint)float.sizeof
;
1541 static assert(float.sizeof
== 4);
1542 uint xp
= path
.ptr
[ppos
]|
(path
.ptr
[ppos
+1]<<8)|
(path
.ptr
[ppos
+2]<<16)|
(path
.ptr
[ppos
+3]<<24);
1543 ppos
+= cast(uint)float.sizeof
;
1544 return *cast(const(float)*)(&xp
);
1548 int scaleX (float v
) nothrow @trusted @nogc { pragma(inline
, true); return cast(int)lrintf(ofsx
+v
*scalex
); }
1549 int scaleY (float v
) nothrow @trusted @nogc { pragma(inline
, true); return cast(int)lrintf(ofsy
+v
*scaley
); }
1552 while (ppos
< plen
) {
1553 auto cmd
= getCommand();
1554 final switch (cmd
) {
1555 case Command
.Bounds
: ppos
+= 4*cast(uint)float.sizeof
; break;
1556 case Command
.StrokeMode
: case Command
.FillMode
: case Command
.StrokeFillMode
: break;
1557 case Command
.NormalStroke
: case Command
.ThinStroke
: break;
1558 case Command
.MoveTo
:
1559 cx
= scaleX(getFloat());
1560 cy
= scaleY(getFloat());
1562 case Command
.LineTo
:
1563 immutable int ex
= scaleX(getFloat());
1564 immutable int ey
= scaleY(getFloat());
1565 drawLine(cx
, cy
, ex
, ey
, fc
);
1569 case Command
.CubicTo
: // cubic bezier
1570 immutable int x1
= scaleX(getFloat());
1571 immutable int y1
= scaleY(getFloat());
1572 immutable int x2
= scaleX(getFloat());
1573 immutable int y2
= scaleY(getFloat());
1574 immutable int ex
= scaleX(getFloat());
1575 immutable int ey
= scaleY(getFloat());
1576 drawCubicBezier(cx
, cy
, x1
, y1
, x2
, y2
, ex
, ey
, fc
);
1580 case Command
.EndPath
: // don't close this path
1586 // ////////////////////////////////////////////////////////////////////////// //
1587 enum CharWidth
= 10, CharHeight
= 10;
1589 void drawChar (int x
, int y
, char ch
, Color c
, Color bg
=Color
.transparent
) {
1590 foreach (immutable dy
; 0..10) {
1591 ushort w
= confont10
.ptr
[ch
*10+dy
];
1592 foreach (immutable dx
; 0..10) {
1594 if (c
.a
!= 0) putPixel(x
+dx
, y
+dy
, c
);
1596 if (bg
.a
!= 0) putPixel(x
+dx
, y
+dy
, bg
);
1603 void drawText (int x
, int y
, const(char)[] text
, Color c
, Color bg
=Color
.transparent
) {
1604 foreach (char ch
; text
) {
1605 drawChar(x
, y
, ch
, c
, bg
);
1610 void drawTextShadow (int x
, int y
, const(char)[] text
, Color c
, Color shadc
) {
1611 drawText(x
+1, y
+1, text
, shadc
);
1612 drawText(x
, y
, text
, c
);
1615 // ////////////////////////////////////////////////////////////////////////// //
1616 static public __gshared
immutable ushort[256*10] confont10
= [
1617 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x4080,0x5280,0x4080,0x5e80,0x4c80,0x2100,0x1e00,
1618 0x0000,0x0000,0x3f00,0x7f80,0x6d80,0x7f80,0x6180,0x7380,0x3f00,0x1e00,0x0000,0x0000,0x3b80,0x7fc0,0x7fc0,0x7fc0,0x3f80,0x1f00,0x0e00,
1619 0x0400,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0e00,0x1f00,0x0e00,0x3f80,0x7fc0,0x3580,
1620 0x0400,0x0e00,0x0000,0x0400,0x0e00,0x1f00,0x3f80,0x7fc0,0x7fc0,0x3580,0x0400,0x0e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,
1621 0x0c00,0x0000,0x0000,0x0000,0xffc0,0xffc0,0xffc0,0xf3c0,0xe1c0,0xe1c0,0xf3c0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x1e00,0x3300,0x2100,
1622 0x2100,0x3300,0x1e00,0x0000,0x0000,0xffc0,0xffc0,0xe1c0,0xccc0,0xdec0,0xdec0,0xccc0,0xe1c0,0xffc0,0xffc0,0x0000,0x0780,0x0380,0x0780,
1623 0x3e80,0x6600,0x6600,0x6600,0x3c00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3300,0x1e00,0x0c00,0x3f00,0x0c00,0x0000,0x0400,0x0600,0x0700,
1624 0x0500,0x0500,0x0400,0x1c00,0x3c00,0x1800,0x0000,0x0000,0x1f80,0x1f80,0x1080,0x1080,0x1180,0x3380,0x7100,0x2000,0x0000,0x0000,0x0c00,
1625 0x6d80,0x1e00,0x7380,0x7380,0x1e00,0x6d80,0x0c00,0x0000,0x1000,0x1800,0x1c00,0x1e00,0x1f00,0x1e00,0x1c00,0x1800,0x1000,0x0000,0x0100,
1626 0x0300,0x0700,0x0f00,0x1f00,0x0f00,0x0700,0x0300,0x0100,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,
1627 0x0000,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x3300,0x0000,0x0000,0x0000,0x3f80,0x6d80,0x6d80,0x3d80,0x0d80,0x0d80,0x0d80,0x0000,
1628 0x0000,0x0000,0x1f00,0x3000,0x1f00,0x3180,0x1f00,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x7f80,0x7f80,
1629 0x0000,0x0000,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0xffc0,0x0000,0x0c00,0x1e00,0x3f00,0x0c00,0x0c00,0x0c00,
1630 0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x3f00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0600,0x0300,0x7f80,0x0300,
1631 0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x3000,0x7f80,0x3000,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,
1632 0x6000,0x6000,0x7f80,0x0000,0x0000,0x0000,0x0000,0x1100,0x3180,0x7fc0,0x3180,0x1100,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1633 0x1f00,0x3f80,0x7fc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x7fc0,0x3f80,0x1f00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1634 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x1e00,0x1e00,0x0c00,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x0000,0x1b00,
1635 0x1b00,0x1b00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1b00,0x1b00,0x7fc0,0x1b00,0x7fc0,0x1b00,0x1b00,0x0000,0x0000,0x0400,
1636 0x1f00,0x3580,0x3400,0x1f00,0x0580,0x3580,0x1f00,0x0400,0x0000,0x0000,0x3180,0x3300,0x0600,0x0c00,0x1980,0x3180,0x0000,0x0000,0x0000,
1637 0x0000,0x1c00,0x3300,0x3300,0x1f80,0x3300,0x3300,0x1d80,0x0000,0x0000,0x0000,0x0e00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,
1638 0x0000,0x0000,0x0600,0x0c00,0x1800,0x1800,0x1800,0x0c00,0x0600,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0600,0x0600,0x0c00,0x1800,
1639 0x0000,0x0000,0x0000,0x0000,0x3300,0x1e00,0x7f80,0x1e00,0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x3f00,0x0c00,0x0c00,
1640 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,
1641 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0180,0x0300,0x0600,0x0c00,
1642 0x1800,0x3000,0x6000,0x0000,0x0000,0x0000,0x1f00,0x3380,0x3780,0x3f80,0x3d80,0x3980,0x1f00,0x0000,0x0000,0x0000,0x0c00,0x1c00,0x0c00,
1643 0x0c00,0x0c00,0x0c00,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x0180,0x0f00,0x1800,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,
1644 0x0180,0x0700,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0700,0x0f00,0x1b00,0x3300,0x3f80,0x0300,0x0780,0x0000,0x0000,0x0000,0x3f80,
1645 0x3000,0x3000,0x3f00,0x0180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x3000,0x3f00,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1646 0x3f80,0x3180,0x0180,0x0300,0x0600,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x1f00,0x3180,0x3180,0x1f00,0x0000,0x0000,
1647 0x0000,0x1f00,0x3180,0x3180,0x1f80,0x0180,0x0300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x0000,
1648 0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0c00,0x0c00,0x1800,0x0000,0x0000,0x0300,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0300,
1649 0x0000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1800,0x0c00,0x0600,0x0300,0x0600,0x0c00,
1650 0x1800,0x0000,0x0000,0x0000,0x1e00,0x3300,0x0300,0x0300,0x0600,0x0c00,0x0000,0x0c00,0x0000,0x0000,0x3f00,0x6180,0x6780,0x6d80,0x6780,
1651 0x6000,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,
1652 0x3180,0x3180,0x3f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3e00,0x3300,0x3180,
1653 0x3180,0x3180,0x3300,0x3e00,0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3f00,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x3f80,0x3000,
1654 0x3000,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3380,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,
1655 0x3180,0x3180,0x3f80,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,
1656 0x0700,0x0300,0x0300,0x0300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3300,0x3e00,0x3300,0x3180,0x3180,0x0000,0x0000,
1657 0x0000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3000,0x3f80,0x0000,0x0000,0x0000,0x6180,0x7380,0x7f80,0x6d80,0x6180,0x6180,0x6180,0x0000,
1658 0x0000,0x0000,0x3180,0x3980,0x3d80,0x3780,0x3380,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3180,0x1f00,
1659 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x3380,
1660 0x1f00,0x0380,0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3300,0x3180,0x3180,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x1f00,0x0180,
1661 0x3180,0x1f00,0x0000,0x0000,0x0000,0x7f80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,
1662 0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x6180,0x6180,0x6180,
1663 0x6d80,0x7f80,0x7380,0x6180,0x0000,0x0000,0x0000,0x6180,0x3300,0x1e00,0x0c00,0x1e00,0x3300,0x6180,0x0000,0x0000,0x0000,0x6180,0x6180,
1664 0x3300,0x1e00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x3f80,0x0300,0x0600,0x0c00,0x1800,0x3000,0x3f80,0x0000,0x0000,0x0000,0x1e00,
1665 0x1800,0x1800,0x1800,0x1800,0x1800,0x1e00,0x0000,0x0000,0x0000,0x6000,0x3000,0x1800,0x0c00,0x0600,0x0300,0x0000,0x0000,0x0000,0x0000,
1666 0x1e00,0x0600,0x0600,0x0600,0x0600,0x0600,0x1e00,0x0000,0x0000,0x0000,0x0400,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,
1667 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0x0000,0x0000,0x1c00,0x0c00,0x0600,0x0000,0x0000,0x0000,0x0000,0x0000,
1668 0x0000,0x0000,0x0000,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x3000,0x3000,0x3f00,0x3180,0x3180,0x3180,0x3f00,
1669 0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0000,0x0000,0x0000,0x0180,0x0180,0x1f80,0x3180,0x3180,0x3180,
1670 0x1f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0000,0x0f00,0x1800,0x1800,0x3e00,0x1800,
1671 0x1800,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x3000,0x3000,0x3f00,0x3180,
1672 0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x0600,0x0000,0x0e00,
1673 0x0600,0x0600,0x0600,0x0600,0x0600,0x1c00,0x0000,0x3000,0x3000,0x3180,0x3300,0x3e00,0x3300,0x3180,0x0000,0x0000,0x0000,0x1c00,0x0c00,
1674 0x0c00,0x0c00,0x0c00,0x0c00,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x3300,0x7f80,0x6d80,0x6d80,0x6180,0x0000,0x0000,0x0000,0x0000,
1675 0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,
1676 0x0000,0x0000,0x3f00,0x3180,0x3180,0x3f00,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3180,0x3180,0x1f80,0x0180,0x01c0,0x0000,
1677 0x0000,0x0000,0x0000,0x3f00,0x3180,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3000,0x1f00,0x0180,0x3f00,0x0000,
1678 0x0000,0x0000,0x1800,0x1800,0x3e00,0x1800,0x1800,0x1800,0x0f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,
1679 0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x1b00,0x0e00,0x0400,0x0000,0x0000,0x0000,0x0000,0x0000,0x6180,0x6d80,0x6d80,0x7f80,
1680 0x3300,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x1b00,0x0e00,0x1b00,0x3180,0x0000,0x0000,0x0000,0x0000,0x0000,0x3180,0x3180,0x3180,
1681 0x1f80,0x0180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0600,0x0c00,0x1800,0x3f00,0x0000,0x0000,0x0000,0x0e00,0x1800,0x1800,0x3000,
1682 0x1800,0x1800,0x0e00,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x1c00,0x0600,0x0600,
1683 0x0300,0x0600,0x0600,0x1c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x0400,0x0e00,
1684 0x1b00,0x3180,0x3180,0x3180,0x3f80,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3000,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0000,0x1b00,
1685 0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0e00,
1686 0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,
1687 0x0c00,0x0600,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,
1688 0x0000,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3000,0x3180,0x1f00,0x0c00,0x1800,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,
1689 0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3f80,0x3000,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3f80,0x3000,
1690 0x1f00,0x0000,0x0000,0x0000,0x3600,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x1c00,0x3600,0x0000,0x1c00,0x0c00,0x0c00,
1691 0x0c00,0x1e00,0x0000,0x0000,0x1800,0x0c00,0x0000,0x1c00,0x0c00,0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,
1692 0x3f80,0x3180,0x3180,0x0000,0x0000,0x0e00,0x1b00,0x0e00,0x1f00,0x3180,0x3f80,0x3180,0x3180,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3f80,
1693 0x3000,0x3f00,0x3000,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x0ec0,0x3fc0,0x6e00,0x3b80,0x0000,0x0000,0x0000,0x1f80,0x3600,
1694 0x6600,0x7f80,0x6600,0x6600,0x6780,0x0000,0x0000,0x0e00,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0000,0x1b00,
1695 0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0c00,0x0600,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0e00,
1696 0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x0600,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,
1697 0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x1f80,0x0180,0x1f00,0x0000,0x0000,0x1b00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,
1698 0x0000,0x0000,0x1b00,0x0000,0x3180,0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x0000,0x0000,0x0400,0x1f00,0x3580,0x3400,0x3580,0x1f00,
1699 0x0400,0x0000,0x0000,0x0f00,0x1980,0x1800,0x3e00,0x1800,0x1800,0x3000,0x3f80,0x0000,0x0000,0x6180,0x6180,0x3300,0x1e00,0x3f00,0x0c00,
1700 0x3f00,0x0c00,0x0000,0x0000,0x7f00,0x6180,0x6d80,0x6d80,0x7f00,0x6c00,0x6c00,0x6700,0x0000,0x0000,0x0700,0x0c00,0x0c00,0x1e00,0x0c00,
1701 0x0c00,0x0c00,0x3800,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x0180,0x1f80,0x3180,0x1f80,0x0000,0x0000,0x0c00,0x1800,0x0000,0x1c00,0x0c00,
1702 0x0c00,0x0c00,0x1e00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x1f00,0x3180,0x3180,0x3180,0x1f00,0x0000,0x0000,0x0600,0x0c00,0x0000,0x3180,
1703 0x3180,0x3180,0x3180,0x1f80,0x0000,0x0000,0x1d80,0x3700,0x0000,0x3f00,0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x1d80,0x3700,0x0000,
1704 0x3980,0x3d80,0x3780,0x3380,0x3180,0x0000,0x0000,0x0000,0x1e00,0x0300,0x1f00,0x3300,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,
1705 0x3300,0x3300,0x3300,0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0c00,0x1800,0x3000,0x3000,0x3300,0x1e00,0x0000,0x0000,
1706 0x0000,0x0000,0x0000,0x3f80,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3f80,0x0180,0x0180,0x0180,0x0000,0x0000,
1707 0x0000,0x2080,0x2100,0x2200,0x2400,0x0b00,0x1180,0x2300,0x4380,0x0000,0x0000,0x2080,0x2100,0x2200,0x2400,0x0a80,0x1280,0x2380,0x4080,
1708 0x0000,0x0000,0x0c00,0x0000,0x0c00,0x0c00,0x1e00,0x1e00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x1980,0x3300,0x6600,0x3300,0x1980,0x0000,
1709 0x0000,0x0000,0x0000,0x0000,0x6600,0x3300,0x1980,0x3300,0x6600,0x0000,0x0000,0x0000,0x2200,0x8880,0x2200,0x8880,0x2200,0x8880,0x2200,
1710 0x8880,0x2200,0x8880,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0x5540,0xaa80,0xbb80,0xeec0,0xbb80,0xeec0,0xbb80,0xeec0,
1711 0xbb80,0xeec0,0xbb80,0xeec0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,
1712 0xfc00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,
1713 0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0x0000,0x0000,0xff00,0xff00,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xfc00,
1714 0xfc00,0x0c00,0x0c00,0xfc00,0xfc00,0x0c00,0x0c00,0x3300,0x3300,0xf300,0xf300,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,0x3300,
1715 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,0xff00,0xff00,0x0300,0x0300,0xf300,0xf300,0x3300,0x3300,0x3300,
1716 0x3300,0xf300,0xf300,0x0300,0x0300,0xff00,0xff00,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xff00,0xff00,0x0000,0x0000,0x0000,0x0000,
1717 0x1800,0x1800,0xf800,0xf800,0x1800,0x1800,0xf800,0xf800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xfc00,0xfc00,0x0c00,0x0c00,0x0c00,
1718 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1719 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,
1720 0x0c00,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,
1721 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x3300,0x3300,0x3300,0x3300,0x33c0,
1722 0x33c0,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,
1723 0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0xffc0,
1724 0xffc0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x33c0,0x33c0,0x3000,0x3000,0x33c0,0x33c0,0x3300,0x3300,0x0000,0x0000,
1725 0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0xf3c0,0xf3c0,0x0000,0x0000,0xf3c0,0xf3c0,0x3300,0x3300,0x0c00,
1726 0x0c00,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0x3300,0x3300,0x3300,0x3300,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1727 0x0000,0x0000,0xffc0,0xffc0,0x0000,0x0000,0xffc0,0xffc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0xffc0,0xffc0,0x3300,0x3300,0x3300,
1728 0x3300,0x3300,0x3300,0x3300,0x3300,0x3fc0,0x3fc0,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,
1729 0x0000,0x0000,0x0000,0x0000,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0fc0,0x0fc0,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x3fc0,0x3fc0,0x3300,
1730 0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0x3300,0xf3c0,0xf3c0,0x3300,0x3300,0x3300,0x3300,0x0c00,0x0c00,0xffc0,0xffc0,0x0000,0x0000,
1731 0xffc0,0xffc0,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0xfc00,0xfc00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0fc0,
1732 0x0fc0,0x0c00,0x0c00,0x0c00,0x0c00,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,
1733 0x0000,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0xf800,0x07c0,0x07c0,0x07c0,
1734 0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0x07c0,0xffc0,0xffc0,0xffc0,0xffc0,0xffc0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1735 0x0000,0x1d80,0x3700,0x3200,0x3700,0x1d80,0x0000,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3600,0x3300,0x3180,0x3700,0x3000,0x0000,0x0000,
1736 0x3f80,0x3180,0x3000,0x3000,0x3000,0x3000,0x3000,0x0000,0x0000,0x0000,0x0000,0x7f80,0x3300,0x3300,0x3300,0x3300,0x3300,0x0000,0x0000,
1737 0x0000,0x3f80,0x1800,0x0c00,0x0600,0x0c00,0x1800,0x3f80,0x0000,0x0000,0x0000,0x0000,0x0000,0x1f80,0x3600,0x3300,0x3300,0x1e00,0x0000,
1738 0x0000,0x0000,0x0000,0x0000,0x6300,0x6300,0x6700,0x7d80,0x6000,0x6000,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0c00,0x0c00,0x0c00,0x0600,
1739 0x0000,0x0000,0x0000,0x1e00,0x0c00,0x3f00,0x6d80,0x6d80,0x3f00,0x0c00,0x1e00,0x0000,0x0000,0x1e00,0x3300,0x3300,0x3f00,0x3300,0x3300,
1740 0x1e00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,0x3180,0x3180,0x1b00,0x3b80,0x0000,0x0000,0x0000,0x1f00,0x0c00,0x0600,0x1f00,0x3180,
1741 0x3180,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x3b80,0x66c0,0x64c0,0x6cc0,0x3b80,0x0000,0x0000,0x0000,0x0000,0x0180,0x3f00,0x6780,
1742 0x6d80,0x7980,0x3f00,0x6000,0x0000,0x0000,0x0000,0x0000,0x1f00,0x3000,0x1e00,0x3000,0x1f00,0x0000,0x0000,0x0000,0x1f00,0x3180,0x3180,
1743 0x3180,0x3180,0x3180,0x3180,0x0000,0x0000,0x0000,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,
1744 0x3f00,0x0c00,0x0c00,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0600,0x0c00,0x1800,0x0c00,0x0600,0x0000,0x3f00,0x0000,0x0000,0x0000,0x1800,
1745 0x0c00,0x0600,0x0c00,0x1800,0x0000,0x3f00,0x0000,0x0000,0x0000,0x0700,0x0d80,0x0d80,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,
1746 0x0c00,0x0c00,0x0c00,0x0c00,0x0c00,0x6c00,0x6c00,0x3800,0x0000,0x0000,0x0000,0x0c00,0x0000,0x3f00,0x0000,0x0c00,0x0000,0x0000,0x0000,
1747 0x0000,0x3800,0x6d80,0x0700,0x0000,0x3800,0x6d80,0x0700,0x0000,0x0000,0x0000,0x0e00,0x1b00,0x1b00,0x0e00,0x0000,0x0000,0x0000,0x0000,
1748 0x0000,0x0000,0x0000,0x0000,0x0c00,0x0c00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0c00,0x0000,0x0000,0x0000,
1749 0x0000,0x0000,0x0000,0x07c0,0x0600,0x0600,0x6600,0x3600,0x1e00,0x0e00,0x0600,0x0200,0x0000,0x3e00,0x3300,0x3300,0x3300,0x3300,0x0000,
1750 0x0000,0x0000,0x0000,0x0000,0x1e00,0x0300,0x0e00,0x1800,0x1f00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1e00,0x1e00,0x1e00,
1751 0x1e00,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
1754 private static immutable ubyte[7641] baphometPath
= [
1755 0x01,0x04,0x06,0x30,0x89,0x7f,0x43,0x00,0x80,0xff,0x43,0x08,0xa0,0x1d,0xc6,0x43,0x00,0x80,0xff,0x43,
1756 0x00,0x80,0xff,0x43,0xa2,0x1d,0xc6,0x43,0x00,0x80,0xff,0x43,0x30,0x89,0x7f,0x43,0x08,0x00,0x80,0xff,
1757 0x43,0x7a,0x89,0xe5,0x42,0xa0,0x1d,0xc6,0x43,0x00,0x00,0x00,0x00,0x30,0x89,0x7f,0x43,0x00,0x00,0x00,
1758 0x00,0x08,0x7a,0x89,0xe5,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0x89,0xe5,0x42,0x00,0x00,
1759 0x00,0x00,0x30,0x89,0x7f,0x43,0x08,0x00,0x00,0x00,0x00,0xa2,0x1d,0xc6,0x43,0x7a,0x89,0xe5,0x42,0x00,
1760 0x80,0xff,0x43,0x30,0x89,0x7f,0x43,0x00,0x80,0xff,0x43,0x09,0x06,0x30,0x89,0x7f,0x43,0x72,0x87,0xdd,
1761 0x43,0x08,0x16,0x68,0xb3,0x43,0x72,0x87,0xdd,0x43,0x71,0x87,0xdd,0x43,0x17,0x68,0xb3,0x43,0x71,0x87,
1762 0xdd,0x43,0x30,0x89,0x7f,0x43,0x08,0x71,0x87,0xdd,0x43,0xd2,0x2f,0x18,0x43,0x16,0x68,0xb3,0x43,0x35,
1763 0xe2,0x87,0x42,0x30,0x89,0x7f,0x43,0x35,0xe2,0x87,0x42,0x08,0xd1,0x2f,0x18,0x43,0x35,0xe2,0x87,0x42,
1764 0x35,0xe2,0x87,0x42,0xd2,0x2f,0x18,0x43,0x35,0xe2,0x87,0x42,0x30,0x89,0x7f,0x43,0x08,0x35,0xe2,0x87,
1765 0x42,0x17,0x68,0xb3,0x43,0xd1,0x2f,0x18,0x43,0x72,0x87,0xdd,0x43,0x30,0x89,0x7f,0x43,0x72,0x87,0xdd,
1766 0x43,0x09,0x06,0x79,0xcb,0x11,0x43,0x62,0xbf,0xd7,0x42,0x07,0xa4,0x3f,0x7f,0x43,0x0b,0x86,0xdc,0x43,
1767 0x07,0x6c,0xb9,0xb2,0x43,0xe8,0xd1,0xca,0x42,0x07,0x6e,0x4d,0xa0,0x42,0xa9,0x10,0x9c,0x43,0x07,0xb7,
1768 0x40,0xd7,0x43,0xa9,0x10,0x9c,0x43,0x07,0x79,0xcb,0x11,0x43,0x62,0xbf,0xd7,0x42,0x09,0x06,0x98,0x42,
1769 0x74,0x43,0xb1,0x8d,0x68,0x43,0x08,0xd7,0x24,0x79,0x43,0xba,0x83,0x6e,0x43,0xa9,0x16,0x7c,0x43,0x56,
1770 0xa1,0x76,0x43,0x74,0x2a,0x7d,0x43,0x44,0x73,0x80,0x43,0x08,0x55,0xd1,0x7e,0x43,0xe3,0xea,0x76,0x43,
1771 0xbc,0x18,0x81,0x43,0x7f,0xa8,0x6e,0x43,0x8f,0x0a,0x84,0x43,0x02,0xfc,0x68,0x43,0x09,0x06,0x92,0x29,
1772 0x8d,0x43,0x73,0xc3,0x67,0x43,0x08,0xa4,0xd9,0x8e,0x43,0xf2,0xa6,0x7a,0x43,0x8f,0x22,0x88,0x43,0x75,
1773 0x2a,0x7d,0x43,0x42,0x7f,0x82,0x43,0x08,0xc8,0x88,0x43,0x09,0x06,0xc1,0x79,0x74,0x43,0x50,0x64,0x89,
1774 0x43,0x08,0x68,0x2d,0x72,0x43,0xee,0x21,0x81,0x43,0xcd,0x97,0x55,0x43,0xe6,0xf1,0x7b,0x43,0x91,0xec,
1775 0x5d,0x43,0xa8,0xc7,0x6a,0x43,0x09,0x06,0xfa,0xa5,0x52,0x43,0x60,0x97,0x7c,0x43,0x08,0x19,0xff,0x50,
1776 0x43,0xe9,0x6e,0x8a,0x43,0xb0,0xbd,0x70,0x43,0x4c,0x51,0x82,0x43,0x04,0xeb,0x69,0x43,0x66,0x0f,0x8e,
1777 0x43,0x09,0x06,0x17,0xbf,0x71,0x43,0x2c,0x58,0x94,0x43,0x08,0x1c,0x96,0x6e,0x43,0x61,0x68,0x99,0x43,
1778 0x2d,0x3a,0x6e,0x43,0xc8,0x81,0x9e,0x43,0xb7,0x9b,0x72,0x43,0x61,0xa4,0xa3,0x43,0x09,0x06,0x30,0xdb,
1779 0x82,0x43,0xdb,0xe9,0x93,0x43,0x08,0x11,0x82,0x84,0x43,0x61,0x68,0x99,0x43,0xe8,0x4a,0x84,0x43,0x8e,
1780 0xa6,0x9e,0x43,0x42,0x7f,0x82,0x43,0x61,0xa4,0xa3,0x43,0x09,0x06,0xc4,0x02,0x85,0x43,0xd1,0x0b,0x92,
1781 0x43,0x08,0xd6,0xb2,0x86,0x43,0x34,0x1e,0x92,0x43,0x4f,0x58,0x87,0x43,0xa4,0xf1,0x92,0x43,0x03,0xd9,
1782 0x87,0x43,0x7b,0xc6,0x94,0x43,0x09,0x06,0x87,0x3e,0x64,0x43,0x31,0x3b,0x93,0x43,0x08,0x3b,0xbf,0x64,
1783 0x43,0x6f,0xf9,0x91,0x43,0x96,0x0b,0x67,0x43,0xc5,0x4a,0x91,0x43,0xcf,0xfe,0x6a,0x43,0x31,0x2f,0x91,
1784 0x43,0x09,0x06,0x16,0x74,0xb5,0x43,0x08,0xec,0x8e,0x43,0x08,0x1b,0x4b,0xb2,0x43,0xee,0x5d,0x8b,0x43,
1785 0x48,0x4d,0xad,0x43,0x12,0xa6,0x8a,0x43,0xf3,0xd7,0xa7,0x43,0x74,0xb8,0x8a,0x43,0x08,0x8c,0xb2,0xa0,
1786 0x43,0xcd,0xf8,0x8a,0x43,0x68,0x46,0x9b,0x43,0x79,0x8f,0x87,0x43,0x49,0xc9,0x96,0x43,0xe9,0x3e,0x82,
1787 0x43,0x08,0x60,0x5c,0x97,0x43,0xa1,0xde,0x8b,0x43,0x4e,0xa0,0x93,0x43,0x31,0x3b,0x93,0x43,0x9f,0xea,
1788 0x8d,0x43,0x27,0x8d,0x99,0x43,0x08,0x07,0xe0,0x8c,0x43,0x06,0x34,0x9b,0x43,0x38,0xe9,0x8c,0x43,0x46,
1789 0x0a,0x9e,0x43,0x3d,0xcc,0x8b,0x43,0xb2,0x06,0xa2,0x43,0x08,0xf1,0x40,0x8a,0x43,0xb0,0x12,0xa4,0x43,
1790 0x39,0xd1,0x88,0x43,0x76,0x43,0xa6,0x43,0xfa,0x06,0x88,0x43,0xa4,0x75,0xa9,0x43,0x08,0x19,0x6c,0x88,
1791 0x43,0x9f,0x9e,0xac,0x43,0x66,0xeb,0x87,0x43,0x44,0x76,0xb0,0x43,0x6b,0xce,0x86,0x43,0x3b,0xbc,0xb4,
1792 0x43,0x08,0xa9,0x8c,0x85,0x43,0x06,0xd0,0xb5,0x43,0xfa,0xee,0x83,0x43,0x74,0xa3,0xb6,0x43,0x3d,0x90,
1793 0x81,0x43,0x31,0xf6,0xb6,0x43,0x08,0x9d,0x61,0x7d,0x43,0xee,0x48,0xb7,0x43,0x3b,0x1f,0x75,0x43,0xcf,
1794 0xe3,0xb6,0x43,0xee,0x6f,0x6d,0x43,0x68,0xe2,0xb5,0x43,0x08,0xd4,0xed,0x6b,0x43,0x87,0x2f,0xb2,0x43,
1795 0x0e,0xc9,0x6b,0x43,0xa7,0x7c,0xae,0x43,0x98,0xfa,0x67,0x43,0xab,0x53,0xab,0x43,0x08,0x25,0x2c,0x64,
1796 0x43,0x33,0xa2,0xa8,0x43,0x40,0x96,0x61,0x43,0xc3,0xc2,0xa5,0x43,0x64,0xde,0x60,0x43,0xfa,0xa2,0xa2,
1797 0x43,0x08,0xb0,0x5d,0x60,0x43,0x06,0x4c,0x9f,0x43,0x9a,0xca,0x5f,0x43,0x38,0x3d,0x9b,0x43,0x3b,0x8f,
1798 0x5c,0x43,0x85,0xb0,0x98,0x43,0x08,0x42,0x36,0x51,0x43,0x3d,0xf0,0x91,0x43,0xcd,0x4f,0x49,0x43,0xdb,
1799 0xb9,0x8b,0x43,0xe0,0xdb,0x44,0x43,0x42,0x8b,0x84,0x43,0x08,0x7e,0xc9,0x44,0x43,0x8a,0x57,0x8d,0x43,
1800 0xbc,0x6c,0x0f,0x43,0x23,0x62,0x8e,0x43,0xf5,0x17,0x07,0x43,0xc5,0x3e,0x8f,0x43,0x09,0x06,0xe0,0xea,
1801 0x76,0x43,0xab,0xef,0xc5,0x43,0x08,0x12,0x00,0x79,0x43,0xab,0xcb,0xbf,0x43,0x79,0xb9,0x6d,0x43,0x7e,
1802 0x8d,0xba,0x43,0xee,0x6f,0x6d,0x43,0x98,0xeb,0xb5,0x43,0x08,0xe0,0x02,0x7b,0x43,0x5f,0x1c,0xb8,0x43,
1803 0x85,0x2c,0x82,0x43,0xe9,0x65,0xb8,0x43,0xd6,0xb2,0x86,0x43,0xc6,0x05,0xb5,0x43,0x08,0x03,0xcd,0x85,
1804 0x43,0x5a,0x39,0xb9,0x43,0xe4,0x4f,0x81,0x43,0xdb,0xd4,0xbf,0x43,0xdf,0x6c,0x82,0x43,0xbc,0x93,0xc5,
1805 0x43,0x09,0x06,0xf0,0xd0,0x22,0x43,0x5d,0x19,0x08,0x43,0x08,0xbc,0xab,0x49,0x43,0x4a,0x35,0x29,0x43,
1806 0xcb,0xf7,0x65,0x43,0xce,0x37,0x45,0x43,0x0e,0x99,0x63,0x43,0x67,0xc6,0x5c,0x43,0x09,0x06,0x05,0x94,
1807 0xab,0x43,0xc2,0x13,0x04,0x43,0x08,0x9f,0x26,0x98,0x43,0x11,0x42,0x25,0x43,0x97,0x00,0x8a,0x43,0x32,
1808 0x32,0x41,0x43,0xf5,0x2f,0x8b,0x43,0xc7,0xc0,0x58,0x43,0x09,0x06,0x8f,0x85,0x48,0x43,0xe0,0xa8,0x8c,
1809 0x43,0x08,0x55,0xaa,0x48,0x43,0xe0,0xa8,0x8c,0x43,0x6b,0x3d,0x49,0x43,0xc1,0x43,0x8c,0x43,0x31,0x62,
1810 0x49,0x43,0xc1,0x43,0x8c,0x43,0x08,0x2f,0xe3,0x2f,0x43,0xad,0xe7,0x98,0x43,0xff,0x0d,0x0d,0x43,0xad,
1811 0xf3,0x9a,0x43,0xf0,0xaf,0xcc,0x42,0x74,0x00,0x97,0x43,0x08,0xbb,0xa2,0xf7,0x42,0x93,0x4d,0x93,0x43,
1812 0x5e,0x19,0x08,0x43,0x5a,0x2a,0x87,0x43,0x23,0x6e,0x10,0x43,0x42,0x97,0x86,0x43,0x08,0xca,0xe8,0x33,
1813 0x43,0x1b,0x3c,0x80,0x43,0x80,0xe8,0x4d,0x43,0xda,0xf4,0x70,0x43,0xae,0x0e,0x4f,0x43,0x2b,0x1b,0x65,
1814 0x43,0x08,0x66,0x96,0x54,0x43,0xa3,0xe1,0x3b,0x43,0x4e,0xc4,0x19,0x43,0xa0,0x1a,0x16,0x43,0x10,0xe2,
1815 0x14,0x43,0x26,0x14,0xe0,0x42,0x08,0x5c,0x91,0x1c,0x43,0xcb,0x27,0xee,0x42,0xa9,0x40,0x24,0x43,0x71,
1816 0x3b,0xfc,0x42,0xf3,0xef,0x2b,0x43,0x8b,0x27,0x05,0x43,0x08,0xe2,0x4b,0x2c,0x43,0x48,0x86,0x07,0x43,
1817 0x79,0x62,0x2f,0x43,0x05,0xe5,0x09,0x43,0x55,0x32,0x34,0x43,0xa0,0xd2,0x09,0x43,0x08,0x74,0xa3,0x36,
1818 0x43,0x3a,0xd1,0x08,0x43,0x7e,0x81,0x38,0x43,0x09,0xd4,0x0a,0x43,0x0d,0xba,0x39,0x43,0xa0,0xea,0x0d,
1819 0x43,0x08,0x6f,0xe4,0x3d,0x43,0x43,0xc7,0x0e,0x43,0xd6,0xe5,0x3e,0x43,0xc4,0x4a,0x11,0x43,0x55,0x7a,
1820 0x40,0x43,0x59,0x72,0x13,0x43,0x08,0x55,0x92,0x44,0x43,0xbf,0x73,0x14,0x43,0x23,0x95,0x46,0x43,0xa5,
1821 0x09,0x17,0x43,0xe0,0xf3,0x48,0x43,0xfe,0x55,0x19,0x43,0x08,0xcd,0x4f,0x49,0x43,0xaa,0x10,0x1c,0x43,
1822 0x61,0x77,0x4b,0x43,0xfe,0x6d,0x1d,0x43,0x80,0xe8,0x4d,0x43,0x2b,0x94,0x1e,0x43,0x08,0x58,0xc9,0x51,
1823 0x43,0x41,0x27,0x1f,0x43,0x9b,0x82,0x53,0x43,0x35,0x72,0x20,0x43,0x53,0xf2,0x54,0x43,0x88,0xcf,0x21,
1824 0x43,0x08,0x7b,0x29,0x55,0x43,0xe8,0x0a,0x25,0x43,0xb2,0x2d,0x58,0x43,0xef,0xe8,0x26,0x43,0x9b,0xb2,
1825 0x5b,0x43,0xd0,0x8f,0x28,0x43,0x08,0x5f,0xef,0x5f,0x43,0xeb,0x11,0x2a,0x43,0xfd,0xdc,0x5f,0x43,0x6e,
1826 0x95,0x2c,0x43,0x3b,0xa7,0x60,0x43,0x2b,0xf4,0x2e,0x43,0x08,0x06,0xbb,0x61,0x43,0xfd,0xe5,0x31,0x43,
1827 0xe7,0x61,0x63,0x43,0xef,0x30,0x33,0x43,0x53,0x52,0x65,0x43,0xa3,0xb1,0x33,0x43,0x08,0x12,0xa0,0x68,
1828 0x43,0x7f,0x69,0x34,0x43,0x40,0xc6,0x69,0x43,0x64,0xff,0x36,0x43,0x7e,0x90,0x6a,0x43,0x71,0xcc,0x39,
1829 0x43,0x08,0xbc,0x5a,0x6b,0x43,0x51,0x73,0x3b,0x43,0xc1,0x49,0x6c,0x43,0xa5,0xd0,0x3c,0x43,0xe0,0xba,
1830 0x6e,0x43,0xb8,0x74,0x3c,0x43,0x08,0x6b,0x1c,0x73,0x43,0x13,0xc1,0x3e,0x43,0x40,0xf6,0x71,0x43,0xce,
1831 0x1f,0x41,0x43,0x55,0x89,0x72,0x43,0x8d,0x7e,0x43,0x43,0x08,0x68,0x2d,0x72,0x43,0x89,0xae,0x4b,0x43,
1832 0xc1,0x79,0x74,0x43,0xcb,0x78,0x4c,0x43,0x55,0xa1,0x76,0x43,0x5b,0xb1,0x4d,0x43,0x08,0xa2,0x38,0x7a,
1833 0x43,0xd1,0x56,0x4e,0x43,0x85,0xb6,0x78,0x43,0xb1,0x15,0x54,0x43,0x83,0xc7,0x77,0x43,0x89,0x0e,0x5c,
1834 0x43,0x08,0xcf,0x46,0x77,0x43,0x0f,0x81,0x5f,0x43,0x1a,0xde,0x7a,0x43,0xce,0xc7,0x5d,0x43,0x42,0x73,
1835 0x80,0x43,0x99,0xc3,0x5a,0x43,0x08,0x85,0x2c,0x82,0x43,0xf6,0xe6,0x59,0x43,0x81,0x3d,0x81,0x43,0x16,
1836 0x10,0x50,0x43,0xd6,0x8e,0x80,0x43,0x5b,0x99,0x49,0x43,0x08,0xc4,0xea,0x80,0x43,0x22,0x95,0x46,0x43,
1837 0xfa,0xe2,0x81,0x43,0xda,0xec,0x43,0x43,0x78,0x77,0x83,0x43,0xe4,0xb2,0x41,0x43,0x08,0x8a,0x27,0x85,
1838 0x43,0x86,0x77,0x3e,0x43,0x0c,0x9f,0x85,0x43,0x07,0xf4,0x3b,0x43,0x8f,0x16,0x86,0x43,0xe6,0x82,0x39,
1839 0x43,0x08,0x85,0x44,0x86,0x43,0x37,0xd9,0x35,0x43,0x1e,0x4f,0x87,0x43,0xe1,0x7b,0x34,0x43,0xdf,0x90,
1840 0x88,0x43,0xb6,0x55,0x33,0x43,0x08,0xae,0x93,0x8a,0x43,0xfd,0xe5,0x31,0x43,0xfa,0x12,0x8a,0x43,0xbf,
1841 0x03,0x2d,0x43,0x19,0x78,0x8a,0x43,0x45,0x5e,0x2c,0x43,0x08,0x03,0xf1,0x8b,0x43,0xac,0x47,0x29,0x43,
1842 0x2f,0x17,0x8d,0x43,0x45,0x46,0x28,0x43,0xc8,0x21,0x8e,0x43,0x30,0xb3,0x27,0x43,0x08,0xa9,0xc8,0x8f,
1843 0x43,0xef,0xe8,0x26,0x43,0xbf,0x5b,0x90,0x43,0x5b,0xc1,0x24,0x43,0x10,0xca,0x90,0x43,0xa0,0x62,0x22,
1844 0x43,0x08,0x26,0x5d,0x91,0x43,0xbb,0xcc,0x1f,0x43,0xf0,0x70,0x92,0x43,0x78,0x13,0x1e,0x43,0x77,0xd7,
1845 0x93,0x43,0x73,0x24,0x1d,0x43,0x08,0x65,0x3f,0x96,0x43,0xce,0x58,0x1b,0x43,0xbe,0x7f,0x96,0x43,0xbf,
1846 0x8b,0x18,0x43,0x60,0x5c,0x97,0x43,0xb6,0xad,0x16,0x43,0x08,0xba,0xa8,0x99,0x43,0x78,0xcb,0x11,0x43,
1847 0x49,0xe1,0x9a,0x43,0x78,0xcb,0x11,0x43,0x01,0x51,0x9c,0x43,0x73,0xdc,0x10,0x43,0x08,0x72,0x24,0x9d,
1848 0x43,0xd2,0xff,0x0f,0x43,0x1c,0xd3,0x9d,0x43,0x07,0xec,0x0e,0x43,0xeb,0xc9,0x9d,0x43,0xe8,0x7a,0x0c,
1849 0x43,0x08,0x60,0x80,0x9d,0x43,0xd7,0xbe,0x08,0x43,0x4d,0xe8,0x9f,0x43,0x86,0x50,0x08,0x43,0x25,0xbd,
1850 0xa1,0x43,0x5b,0x2a,0x07,0x43,0x08,0x99,0x7f,0xa3,0x43,0xc9,0xf1,0x05,0x43,0x48,0x1d,0xa5,0x43,0x86,
1851 0x38,0x04,0x43,0x6c,0x71,0xa6,0x43,0x18,0x59,0x01,0x43,0x08,0x32,0x96,0xa6,0x43,0x6e,0x64,0xff,0x42,
1852 0x48,0x29,0xa7,0x43,0xed,0xcf,0xfd,0x42,0x5f,0xbc,0xa7,0x43,0x71,0x3b,0xfc,0x42,0x08,0xf3,0xe3,0xa9,
1853 0x43,0xf7,0x7d,0xf7,0x42,0xd8,0x6d,0xaa,0x43,0x45,0xe5,0xf2,0x42,0x48,0x41,0xab,0x43,0xcb,0x27,0xee,
1854 0x42,0x08,0x24,0xf9,0xab,0x43,0x52,0x6a,0xe9,0x42,0xee,0x0c,0xad,0x43,0x4c,0x8c,0xe7,0x42,0x1b,0x33,
1855 0xae,0x43,0xcc,0xf7,0xe5,0x42,0x08,0xaa,0x6b,0xaf,0x43,0xe8,0x61,0xe3,0x42,0x90,0xf5,0xaf,0x43,0xc9,
1856 0xf0,0xe0,0x42,0xe0,0x63,0xb0,0x43,0xe5,0x5a,0xde,0x42,0x08,0xaa,0x83,0xb3,0x43,0x29,0x2d,0x09,0x43,
1857 0x6a,0xfe,0x8e,0x43,0xb8,0x74,0x3c,0x43,0xd5,0x06,0x95,0x43,0xe6,0x79,0x67,0x43,0x08,0x2f,0x53,0x97,
1858 0x43,0xe9,0xb0,0x74,0x43,0xa8,0x28,0xa0,0x43,0x43,0xfd,0x76,0x43,0x83,0x28,0xad,0x43,0x17,0x59,0x81,
1859 0x43,0x08,0x3d,0xe7,0xbf,0x43,0x4b,0x8d,0x8c,0x43,0xae,0x96,0xba,0x43,0x66,0x27,0x92,0x43,0x15,0xe0,
1860 0xc7,0x43,0x6f,0x11,0x96,0x43,0x08,0x7e,0x5d,0xb2,0x43,0xdb,0x01,0x98,0x43,0x9e,0x56,0xa0,0x43,0x80,
1861 0xc1,0x97,0x43,0x69,0x2e,0x97,0x43,0x31,0x17,0x8d,0x43,0x09,0x06,0xab,0xa7,0x39,0x43,0x67,0x0f,0x0e,
1862 0x43,0x08,0xdb,0xbc,0x3b,0x43,0xe8,0x92,0x10,0x43,0xb5,0x85,0x3b,0x43,0x97,0x3c,0x14,0x43,0xab,0xa7,
1863 0x39,0x43,0x0c,0x0b,0x18,0x43,0x09,0x06,0xca,0x30,0x40,0x43,0x30,0x3b,0x13,0x43,0x08,0x17,0xc8,0x43,
1864 0x43,0xa5,0x09,0x17,0x43,0x7e,0xc9,0x44,0x43,0x1a,0xd8,0x1a,0x43,0x9d,0x22,0x43,0x43,0x8d,0xa6,0x1e,
1865 0x43,0x09,0x06,0xc8,0x78,0x4c,0x43,0xed,0xc9,0x1d,0x43,0x08,0x0b,0x32,0x4e,0x43,0x22,0xce,0x20,0x43,
1866 0x23,0xc5,0x4e,0x43,0x58,0xd2,0x23,0x43,0x0b,0x32,0x4e,0x43,0x2b,0xc4,0x26,0x43,0x09,0x06,0xec,0x08,
1867 0x58,0x43,0xc7,0xb1,0x26,0x43,0x08,0x02,0x9c,0x58,0x43,0xef,0x00,0x2b,0x43,0xd9,0x64,0x58,0x43,0x02,
1868 0xbd,0x2e,0x43,0x10,0x51,0x57,0x43,0x37,0xc1,0x31,0x43,0x09,0x06,0xcb,0xdf,0x61,0x43,0x4a,0x65,0x31,
1869 0x43,0x08,0xbe,0x2a,0x63,0x43,0xbd,0x33,0x35,0x43,0x32,0xe1,0x62,0x43,0x56,0x4a,0x38,0x43,0xde,0x83,
1870 0x61,0x43,0x3c,0xe0,0x3a,0x43,0x09,0x06,0x1c,0x7e,0x6a,0x43,0x5b,0x39,0x39,0x43,0x08,0x31,0x11,0x6b,
1871 0x43,0x0c,0xd2,0x3d,0x43,0x1c,0x7e,0x6a,0x43,0x13,0xd9,0x42,0x43,0xd9,0xc4,0x68,0x43,0xcb,0x60,0x48,
1872 0x43,0x09,0x06,0xe5,0xc1,0x73,0x43,0x16,0xf8,0x4b,0x43,0x08,0xa6,0xf7,0x72,0x43,0xb1,0xfd,0x4f,0x43,
1873 0x3b,0x07,0x71,0x43,0x4a,0x14,0x53,0x43,0xa2,0xf0,0x6d,0x43,0x7c,0x29,0x55,0x43,0x09,0x06,0x00,0x8d,
1874 0xa6,0x43,0xef,0x21,0x01,0x43,0x08,0x52,0xfb,0xa6,0x43,0xce,0xc8,0x02,0x43,0xe6,0x16,0xa7,0x43,0x51,
1875 0x4c,0x05,0x43,0x3b,0x68,0xa6,0x43,0x4c,0x75,0x08,0x43,0x09,0x06,0xde,0x20,0xa1,0x43,0x86,0x50,0x08,
1876 0x43,0x08,0xd4,0x4e,0xa1,0x43,0xd3,0xe7,0x0b,0x43,0xb5,0xe9,0xa0,0x43,0x59,0x5a,0x0f,0x43,0xba,0xcc,
1877 0x9f,0x43,0x54,0x83,0x12,0x43,0x09,0x06,0x77,0xfb,0x99,0x43,0x6c,0x16,0x13,0x43,0x08,0xde,0xfc,0x9a,
1878 0x43,0x4a,0xbd,0x14,0x43,0x06,0x34,0x9b,0x43,0xfe,0x55,0x19,0x43,0x13,0xe9,0x99,0x43,0x41,0x27,0x1f,
1879 0x43,0x09,0x06,0x46,0xce,0x93,0x43,0x26,0xa5,0x1d,0x43,0x08,0xe7,0xaa,0x94,0x43,0xbb,0xcc,0x1f,0x43,
1880 0x18,0xb4,0x94,0x43,0xa8,0x40,0x24,0x43,0xe2,0xbb,0x93,0x43,0x21,0xfe,0x28,0x43,0x09,0x06,0xb1,0x8e,
1881 0x8d,0x43,0xa8,0x58,0x28,0x43,0x08,0x19,0x90,0x8e,0x43,0x54,0x13,0x2b,0x43,0xa4,0xd9,0x8e,0x43,0x84,
1882 0x40,0x31,0x43,0x46,0xaa,0x8d,0x43,0x29,0x24,0x37,0x43,0x09,0x06,0xd6,0xbe,0x88,0x43,0xef,0x30,0x33,
1883 0x43,0x08,0x0c,0xb7,0x89,0x43,0x0e,0xa2,0x35,0x43,0xc0,0x37,0x8a,0x43,0x7a,0xaa,0x3b,0x43,0xbb,0x48,
1884 0x89,0x43,0xbb,0x7b,0x41,0x43,0x09,0x06,0x3a,0xad,0x82,0x43,0xc4,0x59,0x43,0x43,0x08,0xd2,0xb7,0x83,
1885 0x43,0x2b,0x5b,0x44,0x43,0x35,0xd6,0x85,0x43,0x48,0xf5,0x49,0x43,0x42,0x97,0x86,0x43,0xc4,0xa1,0x4f,
1886 0x43,0x09,0x06,0x9c,0xb3,0x80,0x43,0x48,0x55,0x5a,0x43,0x08,0xff,0xc5,0x80,0x43,0x09,0x73,0x55,0x43,
1887 0x93,0xe1,0x80,0x43,0x0f,0x39,0x53,0x43,0xf1,0xbe,0x7e,0x43,0x18,0xe7,0x4c,0x43,0x09,0x06,0xe0,0x02,
1888 0x7b,0x43,0x92,0xec,0x5d,0x43,0x08,0x09,0x3a,0x7b,0x43,0xf0,0xf7,0x58,0x43,0x09,0x3a,0x7b,0x43,0xe6,
1889 0x31,0x5b,0x43,0xe0,0x02,0x7b,0x43,0xa8,0x4f,0x56,0x43,0x09,0x06,0x39,0x4f,0x7d,0x43,0x3e,0x8f,0x5c,
1890 0x43,0x08,0xe9,0xe0,0x7c,0x43,0x03,0x9c,0x58,0x43,0x1e,0x2b,0x81,0x43,0x7f,0x30,0x5a,0x43,0xff,0x73,
1891 0x7d,0x43,0xf6,0xb6,0x51,0x43,0x09,0x06,0x5c,0xb8,0x52,0x43,0x28,0x21,0x87,0x43,0x08,0xae,0x3e,0x57,
1892 0x43,0x12,0x9a,0x88,0x43,0x23,0xf5,0x56,0x43,0x04,0xf1,0x8b,0x43,0x25,0xfc,0x5b,0x43,0x85,0x74,0x8e,
1893 0x43,0x08,0x2f,0xf2,0x61,0x43,0x8e,0x52,0x90,0x43,0xd9,0xdc,0x6c,0x43,0x85,0x74,0x8e,0x43,0xc6,0x20,
1894 0x69,0x43,0x3d,0xd8,0x8d,0x43,0x08,0x6d,0x8c,0x5a,0x43,0xf5,0x3b,0x8d,0x43,0x3d,0x77,0x58,0x43,0xa1,
1895 0xc6,0x87,0x43,0xf8,0xed,0x5e,0x43,0x5e,0x0d,0x86,0x43,0x09,0x06,0xde,0xcc,0x92,0x43,0xf7,0x17,0x87,
1896 0x43,0x08,0xb6,0x89,0x90,0x43,0xae,0x87,0x88,0x43,0x4a,0xa5,0x90,0x43,0xa1,0xde,0x8b,0x43,0xf9,0x2a,
1897 0x8e,0x43,0x23,0x62,0x8e,0x43,0x08,0xf5,0x2f,0x8b,0x43,0x5c,0x49,0x90,0x43,0x35,0xd6,0x85,0x43,0x8e,
1898 0x46,0x8e,0x43,0x3d,0xb4,0x87,0x43,0x47,0xaa,0x8d,0x43,0x08,0x6a,0xfe,0x8e,0x43,0xff,0x0d,0x8d,0x43,
1899 0xbb,0x6c,0x8f,0x43,0xf7,0x17,0x87,0x43,0x5c,0x31,0x8c,0x43,0xb2,0x5e,0x85,0x43,0x09,0x06,0x60,0x38,
1900 0x91,0x43,0x69,0x5d,0x7a,0x43,0x08,0x34,0x1e,0x92,0x43,0x1e,0x5b,0x89,0x43,0x04,0x63,0x7e,0x43,0x5e,
1901 0x01,0x84,0x43,0x59,0x2a,0x87,0x43,0x0d,0xcf,0x8d,0x43,0x09,0x03,0x04,0x06,0x5a,0x18,0x63,0x43,0x82,
1902 0x79,0x8b,0x43,0x08,0x25,0x2c,0x64,0x43,0x82,0x79,0x8b,0x43,0x2a,0x1b,0x65,0x43,0x9d,0xef,0x8a,0x43,
1903 0x2a,0x1b,0x65,0x43,0xc1,0x37,0x8a,0x43,0x08,0x2a,0x1b,0x65,0x43,0x17,0x89,0x89,0x43,0x25,0x2c,0x64,
1904 0x43,0x31,0xff,0x88,0x43,0x5a,0x18,0x63,0x43,0x31,0xff,0x88,0x43,0x08,0xf3,0x16,0x62,0x43,0x31,0xff,
1905 0x88,0x43,0xee,0x27,0x61,0x43,0x17,0x89,0x89,0x43,0xee,0x27,0x61,0x43,0xc1,0x37,0x8a,0x43,0x08,0xee,
1906 0x27,0x61,0x43,0x9d,0xef,0x8a,0x43,0xf3,0x16,0x62,0x43,0x82,0x79,0x8b,0x43,0x5a,0x18,0x63,0x43,0x82,
1907 0x79,0x8b,0x43,0x09,0x06,0x4f,0x64,0x89,0x43,0x82,0x79,0x8b,0x43,0x08,0x34,0xee,0x89,0x43,0x82,0x79,
1908 0x8b,0x43,0x85,0x5c,0x8a,0x43,0x9d,0xef,0x8a,0x43,0x85,0x5c,0x8a,0x43,0xc1,0x37,0x8a,0x43,0x08,0x85,
1909 0x5c,0x8a,0x43,0x17,0x89,0x89,0x43,0x34,0xee,0x89,0x43,0x31,0xff,0x88,0x43,0x4f,0x64,0x89,0x43,0x31,
1910 0xff,0x88,0x43,0x08,0x9c,0xe3,0x88,0x43,0x31,0xff,0x88,0x43,0x19,0x6c,0x88,0x43,0x17,0x89,0x89,0x43,
1911 0x19,0x6c,0x88,0x43,0xc1,0x37,0x8a,0x43,0x08,0x19,0x6c,0x88,0x43,0x9d,0xef,0x8a,0x43,0x9c,0xe3,0x88,
1912 0x43,0x82,0x79,0x8b,0x43,0x4f,0x64,0x89,0x43,0x82,0x79,0x8b,0x43,0x09,0x02,0x04,0x06,0x19,0x60,0x86,
1913 0x43,0xec,0xed,0xa3,0x43,0x08,0x35,0xd6,0x85,0x43,0x76,0x43,0xa6,0x43,0x93,0xe1,0x80,0x43,0x57,0x02,
1914 0xac,0x43,0x61,0xd8,0x80,0x43,0x87,0x17,0xae,0x43,0x08,0xa5,0x85,0x80,0x43,0xc3,0xfe,0xaf,0x43,0xce,
1915 0xbc,0x80,0x43,0x83,0x40,0xb1,0x43,0xa5,0x91,0x82,0x43,0x79,0x6e,0xb1,0x43,0x08,0x23,0x26,0x84,0x43,
1916 0x40,0x93,0xb1,0x43,0x30,0xe7,0x84,0x43,0xbe,0x1b,0xb1,0x43,0x11,0x82,0x84,0x43,0xab,0x6b,0xaf,0x43,
1917 0x08,0xb7,0x41,0x84,0x43,0x3b,0x98,0xae,0x43,0xb7,0x41,0x84,0x43,0xc3,0xf2,0xad,0x43,0xa1,0xae,0x83,
1918 0x43,0x83,0x28,0xad,0x43,0x08,0xb2,0x52,0x83,0x43,0x80,0x39,0xac,0x43,0x81,0x49,0x83,0x43,0xf0,0x00,
1919 0xab,0x43,0xe4,0x67,0x85,0x43,0x76,0x4f,0xa8,0x43,0x08,0x9c,0xd7,0x86,0x43,0xd1,0x83,0xa6,0x43,0xec,
1920 0x45,0x87,0x43,0x01,0x75,0xa2,0x43,0x19,0x60,0x86,0x43,0xec,0xed,0xa3,0x43,0x09,0x06,0xd9,0xdc,0x6c,
1921 0x43,0x14,0x25,0xa4,0x43,0x08,0xa2,0xf0,0x6d,0x43,0x9f,0x7a,0xa6,0x43,0x47,0xec,0x77,0x43,0x80,0x39,
1922 0xac,0x43,0xa9,0xfe,0x77,0x43,0xb0,0x4e,0xae,0x43,0x08,0x23,0xa4,0x78,0x43,0xea,0x35,0xb0,0x43,0xd2,
1923 0x35,0x78,0x43,0xab,0x77,0xb1,0x43,0xc1,0x79,0x74,0x43,0xa2,0xa5,0xb1,0x43,0x08,0xc6,0x50,0x71,0x43,
1924 0x68,0xca,0xb1,0x43,0xab,0xce,0x6f,0x43,0xe7,0x52,0xb1,0x43,0xea,0x98,0x70,0x43,0xd4,0xa2,0xaf,0x43,
1925 0x08,0x9d,0x19,0x71,0x43,0x96,0xd8,0xae,0x43,0x9d,0x19,0x71,0x43,0xec,0x29,0xae,0x43,0xca,0x3f,0x72,
1926 0x43,0xab,0x5f,0xad,0x43,0x08,0xa6,0xf7,0x72,0x43,0xa7,0x70,0xac,0x43,0x09,0x0a,0x73,0x43,0x17,0x38,
1927 0xab,0x43,0x44,0xcd,0x6e,0x43,0x9f,0x86,0xa8,0x43,0x08,0xd4,0xed,0x6b,0x43,0xf8,0xba,0xa6,0x43,0x31,
1928 0x11,0x6b,0x43,0x2a,0xac,0xa2,0x43,0xd9,0xdc,0x6c,0x43,0x14,0x25,0xa4,0x43,0x09,0x01,0x05,0x06,0x66,
1929 0x5d,0x7a,0x43,0x74,0xeb,0xc2,0x43,0x08,0x09,0x22,0x77,0x43,0x50,0xbb,0xc7,0x43,0xe9,0xe0,0x7c,0x43,
1930 0xf5,0x86,0xc9,0x43,0x8f,0x94,0x7a,0x43,0xc5,0x95,0xcd,0x43,0x09,0x06,0x08,0x98,0x80,0x43,0x6b,0x19,
1931 0xc3,0x43,0x08,0xb7,0x35,0x82,0x43,0x79,0xf2,0xc7,0x43,0xf1,0xbe,0x7e,0x43,0x1e,0xbe,0xc9,0x43,0x73,
1932 0x7c,0x80,0x43,0xec,0xcc,0xcd,0x43,0x09,0x06,0x28,0xab,0x7d,0x43,0xae,0xde,0xc6,0x43,0x08,0x1e,0xcd,
1933 0x7b,0x43,0x8a,0xa2,0xc9,0x43,0x30,0x89,0x7f,0x43,0x5c,0x94,0xcc,0x43,0x28,0xab,0x7d,0x43,0x42,0x2a,
1934 0xcf,0x43,0x09,0x01,0x05,0x06,0x24,0x14,0xe0,0x42,0xf5,0x77,0x97,0x43,0x08,0xf7,0x1d,0xe7,0x42,0x74,
1935 0x00,0x97,0x43,0x4d,0x93,0xec,0x42,0xdb,0xf5,0x95,0x43,0x29,0x4b,0xed,0x42,0xcd,0x34,0x95,0x43,0x09,
1936 0x06,0x29,0x7b,0xf5,0x42,0x6f,0x1d,0x98,0x43,0x08,0xe4,0xf1,0xfb,0x42,0x61,0x5c,0x97,0x43,0xdb,0x7d,
1937 0x01,0x43,0xb2,0xbe,0x95,0x43,0x55,0x23,0x02,0x43,0xe7,0xaa,0x94,0x43,0x09,0x06,0x98,0xdc,0x03,0x43,
1938 0xbe,0x8b,0x98,0x43,0x08,0x66,0xdf,0x05,0x43,0x47,0xe6,0x97,0x43,0xae,0x87,0x08,0x43,0x98,0x48,0x96,
1939 0x43,0x61,0x08,0x09,0x43,0xd6,0x06,0x95,0x43,0x09,0x06,0x31,0x0b,0x0b,0x43,0x8e,0x82,0x98,0x43,0x08,
1940 0xdb,0xc5,0x0d,0x43,0x80,0xc1,0x97,0x43,0xd6,0xee,0x10,0x43,0xa9,0xec,0x95,0x43,0x79,0xcb,0x11,0x43,
1941 0x55,0x8f,0x94,0x43,0x09,0x06,0xd1,0x2f,0x18,0x43,0xdb,0x01,0x98,0x43,0x08,0xad,0xe7,0x18,0x43,0x38,
1942 0x25,0x97,0x43,0x8a,0x9f,0x19,0x43,0x80,0xb5,0x95,0x43,0xd6,0x1e,0x19,0x43,0xe0,0xd8,0x94,0x43,0x09,
1943 0x06,0x9a,0x5b,0x1d,0x43,0x58,0x8a,0x97,0x43,0x08,0x01,0x5d,0x1e,0x43,0xf1,0x88,0x96,0x43,0x2f,0x83,
1944 0x1f,0x43,0x19,0xb4,0x94,0x43,0x19,0xf0,0x1e,0x43,0x6f,0x05,0x94,0x43,0x09,0x06,0x0b,0x53,0x24,0x43,
1945 0xae,0xdb,0x96,0x43,0x08,0x25,0xd5,0x25,0x43,0x50,0xac,0x95,0x43,0x53,0xfb,0x26,0x43,0x8a,0x7b,0x93,
1946 0x43,0x76,0x43,0x26,0x43,0xb7,0x95,0x92,0x43,0x09,0x06,0x76,0x5b,0x2a,0x43,0x47,0xda,0x95,0x43,0x08,
1947 0xf3,0xef,0x2b,0x43,0x10,0xe2,0x94,0x43,0x6d,0x95,0x2c,0x43,0xae,0xc3,0x92,0x43,0x68,0xa6,0x2b,0x43,
1948 0x47,0xc2,0x91,0x43,0x09,0x06,0x36,0xc1,0x31,0x43,0x2c,0x58,0x94,0x43,0x08,0x8c,0x1e,0x33,0x43,0x31,
1949 0x3b,0x93,0x43,0x79,0x7a,0x33,0x43,0xff,0x25,0x91,0x43,0xd9,0x9d,0x32,0x43,0xc1,0x5b,0x90,0x43,0x09,
1950 0x06,0x25,0x35,0x36,0x43,0x31,0x3b,0x93,0x43,0x08,0x3f,0xb7,0x37,0x43,0xc1,0x67,0x92,0x43,0xe0,0x93,
1951 0x38,0x43,0xae,0xb7,0x90,0x43,0x7e,0x81,0x38,0x43,0x0d,0xdb,0x8f,0x43,0x09,0x06,0xb5,0x85,0x3b,0x43,
1952 0xe4,0xaf,0x91,0x43,0x08,0xcf,0x07,0x3d,0x43,0x9d,0x13,0x91,0x43,0xbc,0x63,0x3d,0x43,0x47,0xb6,0x8f,
1953 0x43,0xe5,0x9a,0x3d,0x43,0x74,0xd0,0x8e,0x43,0x09,0x06,0xae,0xc6,0x42,0x43,0xa4,0xd9,0x8e,0x43,0x08,
1954 0xca,0x48,0x44,0x43,0xfa,0x2a,0x8e,0x43,0xa2,0x11,0x44,0x43,0x9d,0xfb,0x8c,0x43,0x55,0x92,0x44,0x43,
1955 0x0d,0xc3,0x8b,0x43,0x09,0x06,0x39,0x10,0xc3,0x43,0x34,0x36,0x96,0x43,0x08,0x92,0x44,0xc1,0x43,0xe4,
1956 0xc7,0x95,0x43,0x6f,0xf0,0xbf,0x43,0x4b,0xbd,0x94,0x43,0x47,0xb9,0xbf,0x43,0x0b,0xf3,0x93,0x43,0x09,
1957 0x06,0x8f,0x49,0xbe,0x43,0xb7,0xad,0x96,0x43,0x08,0x11,0xb5,0xbc,0x43,0x77,0xe3,0x95,0x43,0x9c,0xf2,
1958 0xba,0x43,0xfa,0x4e,0x94,0x43,0xae,0x96,0xba,0x43,0x31,0x3b,0x93,0x43,0x09,0x06,0xdb,0xb0,0xb9,0x43,
1959 0x10,0xee,0x96,0x43,0x08,0x42,0xa6,0xb8,0x43,0xc8,0x51,0x96,0x43,0x50,0x5b,0xb7,0x43,0x19,0xb4,0x94,
1960 0x43,0xf7,0x1a,0xb7,0x43,0x58,0x72,0x93,0x43,0x09,0x06,0xf2,0x2b,0xb6,0x43,0x10,0xee,0x96,0x43,0x08,
1961 0x9d,0xce,0xb4,0x43,0x04,0x2d,0x96,0x43,0xed,0x30,0xb3,0x43,0x2c,0x58,0x94,0x43,0xce,0xcb,0xb2,0x43,
1962 0xd6,0xfa,0x92,0x43,0x09,0x06,0x5a,0x09,0xb1,0x43,0x19,0xc0,0x96,0x43,0x08,0x6c,0xad,0xb0,0x43,0x77,
1963 0xe3,0x95,0x43,0x7e,0x51,0xb0,0x43,0xc0,0x73,0x94,0x43,0xd8,0x91,0xb0,0x43,0x1e,0x97,0x93,0x43,0x09,
1964 0x06,0x48,0x4d,0xad,0x43,0xbe,0x7f,0x96,0x43,0x08,0x95,0xcc,0xac,0x43,0x58,0x7e,0x95,0x43,0x4d,0x30,
1965 0xac,0x43,0x80,0xa9,0x93,0x43,0xd8,0x79,0xac,0x43,0xd6,0xfa,0x92,0x43,0x09,0x06,0x90,0xd1,0xa9,0x43,
1966 0x14,0xd1,0x95,0x43,0x08,0x83,0x10,0xa9,0x43,0xb7,0xa1,0x94,0x43,0x3b,0x74,0xa8,0x43,0xf1,0x70,0x92,
1967 0x43,0x29,0xd0,0xa8,0x43,0x1e,0x8b,0x91,0x43,0x09,0x06,0x5a,0xcd,0xa6,0x43,0x8a,0x87,0x95,0x43,0x08,
1968 0x1c,0x03,0xa6,0x43,0x23,0x86,0x94,0x43,0x5f,0xb0,0xa5,0x43,0xc1,0x67,0x92,0x43,0xe1,0x27,0xa6,0x43,
1969 0x8a,0x6f,0x91,0x43,0x09,0x06,0xd4,0x5a,0xa3,0x43,0x2c,0x58,0x94,0x43,0x08,0x29,0xac,0xa2,0x43,0x31,
1970 0x3b,0x93,0x43,0x32,0x7e,0xa2,0x43,0xff,0x25,0x91,0x43,0x83,0xec,0xa2,0x43,0x8e,0x52,0x90,0x43,0x09,
1971 0x06,0xf8,0x96,0xa0,0x43,0x1e,0x97,0x93,0x43,0x08,0xeb,0xd5,0x9f,0x43,0x7b,0xba,0x92,0x43,0x99,0x67,
1972 0x9f,0x43,0x9d,0x13,0x91,0x43,0x99,0x67,0x9f,0x43,0xfa,0x36,0x90,0x43,0x09,0x06,0xeb,0xc9,0x9d,0x43,
1973 0xc8,0x39,0x92,0x43,0x08,0xde,0x08,0x9d,0x43,0xb2,0xa6,0x91,0x43,0xe6,0xda,0x9c,0x43,0x2c,0x40,0x90,
1974 0x43,0x52,0xbf,0x9c,0x43,0x5a,0x5a,0x8f,0x43,0x09,0x06,0x37,0x3d,0x9b,0x43,0x85,0x80,0x90,0x43,0x08,
1975 0x2a,0x7c,0x9a,0x43,0xdb,0xd1,0x8f,0x43,0xf0,0xa0,0x9a,0x43,0x7d,0xa2,0x8e,0x43,0x65,0x57,0x9a,0x43,
1976 0xee,0x69,0x8d,0x43,0x09,0x02,0x04,0x06,0x2a,0xf4,0x2e,0x42,0x04,0x21,0x94,0x43,0x08,0x0d,0x8a,0x31,
1977 0x42,0x9f,0x0e,0x94,0x43,0xf3,0x1f,0x34,0x42,0x3d,0xfc,0x93,0x43,0x63,0xff,0x36,0x42,0xa9,0xe0,0x93,
1978 0x43,0x08,0xb5,0x34,0x5d,0x42,0x0b,0xf3,0x93,0x43,0x6d,0xa4,0x5e,0x42,0x03,0x39,0x98,0x43,0xe7,0x31,
1979 0x5b,0x42,0x93,0x89,0x9d,0x43,0x08,0x02,0x9c,0x58,0x42,0xd4,0x5a,0xa3,0x43,0x38,0x70,0x53,0x42,0x14,
1980 0x49,0xaa,0x43,0xf8,0xed,0x5e,0x42,0x83,0x28,0xad,0x43,0x08,0xea,0x68,0x68,0x42,0x20,0x22,0xaf,0x43,
1981 0x12,0xb8,0x6c,0x42,0xb5,0x49,0xb1,0x43,0x2a,0x4b,0x6d,0x42,0x0d,0x96,0xb3,0x43,0x07,0x2a,0x4b,0x6d,
1982 0x42,0xc6,0x05,0xb5,0x43,0x08,0x87,0x6e,0x6c,0x42,0x68,0xee,0xb7,0x43,0x1c,0x66,0x66,0x42,0x31,0x0e,
1983 0xbb,0x43,0x57,0x11,0x5e,0x42,0x8f,0x49,0xbe,0x43,0x08,0x66,0x96,0x54,0x42,0xb9,0x5c,0xb8,0x43,0x2c,
1984 0x2b,0x3c,0x42,0x68,0xd6,0xb3,0x43,0x2a,0xf4,0x2e,0x42,0x6d,0xad,0xb0,0x43,0x07,0x2a,0xf4,0x2e,0x42,
1985 0x61,0xa4,0xa3,0x43,0x08,0x55,0x1a,0x30,0x42,0xf0,0xd0,0xa2,0x43,0xf8,0xf6,0x30,0x42,0xb2,0x06,0xa2,
1986 0x43,0x98,0xd3,0x31,0x42,0xd6,0x4e,0xa1,0x43,0x08,0x1c,0x6f,0x38,0x42,0x2a,0x94,0x9e,0x43,0xc1,0x22,
1987 0x36,0x42,0xf5,0x9b,0x9d,0x43,0x2a,0xf4,0x2e,0x42,0x6a,0x52,0x9d,0x43,0x07,0x2a,0xf4,0x2e,0x42,0x57,
1988 0xa2,0x9b,0x43,0x08,0xab,0x8f,0x35,0x42,0x8a,0xab,0x9b,0x43,0xe9,0x71,0x3a,0x42,0xb2,0xe2,0x9b,0x43,
1989 0xb7,0x74,0x3c,0x42,0x34,0x5a,0x9c,0x43,0x08,0x23,0x7d,0x42,0x42,0x0b,0x2f,0x9e,0x43,0xe5,0x9a,0x3d,
1990 0x42,0x38,0x6d,0xa3,0x43,0x36,0xd9,0x35,0x42,0xf3,0xd7,0xa7,0x43,0x08,0x12,0x61,0x2e,0x42,0xb0,0x42,
1991 0xac,0x43,0x63,0xff,0x36,0x42,0xdd,0x74,0xaf,0x43,0x1e,0xa6,0x45,0x42,0x44,0x82,0xb2,0x43,0x08,0x74,
1992 0x1b,0x4b,0x42,0x79,0x7a,0xb3,0x43,0x10,0x21,0x4f,0x42,0x2a,0x18,0xb5,0x43,0xdb,0x4c,0x54,0x42,0x91,
1993 0x19,0xb6,0x43,0x08,0xee,0x3f,0x65,0x42,0x5f,0x28,0xba,0x43,0xa7,0xaf,0x66,0x42,0xb9,0x50,0xb6,0x43,
1994 0x14,0x58,0x5c,0x42,0xca,0xdc,0xb1,0x43,0x08,0x2c,0x8b,0x4c,0x42,0x4e,0x30,0xac,0x43,0x19,0xcf,0x48,
1995 0x42,0x2a,0xd0,0xa8,0x43,0xbc,0xab,0x49,0x42,0xa9,0x4c,0xa6,0x43,0x08,0x61,0x5f,0x47,0x42,0xfa,0xa2,
1996 0xa2,0x43,0xa7,0xaf,0x66,0x42,0x85,0x98,0x94,0x43,0x2a,0xf4,0x2e,0x42,0xc3,0x62,0x95,0x43,0x07,0x2a,
1997 0xf4,0x2e,0x42,0x04,0x21,0x94,0x43,0x09,0x06,0xd0,0xfe,0xea,0x41,0x9f,0x0e,0x94,0x43,0x08,0xdc,0xe3,
1998 0xf1,0x41,0xe9,0x9e,0x92,0x43,0xd2,0xe7,0x0b,0x42,0xd6,0x06,0x95,0x43,0x2a,0xf4,0x2e,0x42,0x04,0x21,
1999 0x94,0x43,0x07,0x2a,0xf4,0x2e,0x42,0xc3,0x62,0x95,0x43,0x08,0x87,0x17,0x2e,0x42,0xc3,0x62,0x95,0x43,
2000 0xe7,0x3a,0x2d,0x42,0xf5,0x6b,0x95,0x43,0x44,0x5e,0x2c,0x42,0xf5,0x6b,0x95,0x43,0x08,0xd1,0x47,0x1c,
2001 0x42,0x19,0xc0,0x96,0x43,0x66,0xdf,0x05,0x42,0x38,0x19,0x95,0x43,0x12,0x6a,0x00,0x42,0xb2,0xbe,0x95,
2002 0x43,0x08,0xbb,0x6b,0xea,0x41,0xd6,0x12,0x97,0x43,0x2d,0x82,0xfa,0x41,0x61,0x74,0x9b,0x43,0x7e,0x72,
2003 0x06,0x42,0x8a,0xab,0x9b,0x43,0x08,0xc8,0x39,0x12,0x42,0x4e,0xd0,0x9b,0x43,0x53,0xe3,0x22,0x42,0xc3,
2004 0x86,0x9b,0x43,0x2a,0xf4,0x2e,0x42,0x57,0xa2,0x9b,0x43,0x07,0x2a,0xf4,0x2e,0x42,0x6a,0x52,0x9d,0x43,
2005 0x08,0x01,0xa5,0x2a,0x42,0xa4,0x2d,0x9d,0x43,0x96,0x9c,0x24,0x42,0x06,0x40,0x9d,0x43,0x8a,0xb7,0x1d,
2006 0x42,0x9a,0x5b,0x9d,0x43,0x08,0x6b,0x16,0x13,0x42,0xcd,0x64,0x9d,0x43,0x42,0xc7,0x0e,0x42,0x9a,0x5b,
2007 0x9d,0x43,0x23,0x26,0x04,0x42,0xcd,0x64,0x9d,0x43,0x08,0xe6,0x91,0xeb,0x41,0x38,0x49,0x9d,0x43,0x73,
2008 0x7b,0xdb,0x41,0xf5,0x83,0x99,0x43,0x7f,0x60,0xe2,0x41,0x0b,0x0b,0x98,0x43,0x08,0x7f,0x60,0xe2,0x41,
2009 0xec,0x99,0x95,0x43,0xe3,0x5a,0xde,0x41,0xbe,0x7f,0x96,0x43,0xd0,0xfe,0xea,0x41,0x9f,0x0e,0x94,0x43,
2010 0x07,0xd0,0xfe,0xea,0x41,0x9f,0x0e,0x94,0x43,0x09,0x06,0x2a,0xf4,0x2e,0x42,0x6d,0xad,0xb0,0x43,0x08,
2011 0xd4,0x7e,0x29,0x42,0xab,0x6b,0xaf,0x43,0x4e,0x0c,0x26,0x42,0x44,0x6a,0xae,0x43,0x38,0x79,0x25,0x42,
2012 0xd4,0x96,0xad,0x43,0x08,0x25,0xbd,0x21,0x42,0xe2,0x4b,0xac,0x43,0x49,0x35,0x29,0x42,0x9a,0x97,0xa7,
2013 0x43,0x2a,0xf4,0x2e,0x42,0x61,0xa4,0xa3,0x43,0x07,0x2a,0xf4,0x2e,0x42,0x6d,0xad,0xb0,0x43,0x09,0x06,
2014 0x1d,0xe5,0x7f,0x43,0x87,0x4a,0xe6,0x43,0x08,0x86,0x20,0x80,0x43,0x57,0x41,0xe6,0x43,0x7d,0x4e,0x80,
2015 0x43,0x25,0x38,0xe6,0x43,0xa5,0x85,0x80,0x43,0xf3,0x2e,0xe6,0x43,0x08,0x35,0xca,0x83,0x43,0xd4,0xc9,
2016 0xe5,0x43,0x9c,0xd7,0x86,0x43,0x44,0x91,0xe4,0x43,0xd5,0xca,0x8a,0x43,0x91,0x1c,0xe6,0x43,0x08,0x53,
2017 0x5f,0x8c,0x43,0xf8,0x1d,0xe7,0x43,0x2f,0x17,0x8d,0x43,0x4e,0x7b,0xe8,0x43,0x92,0x29,0x8d,0x43,0x2f,
2018 0x22,0xea,0x43,0x07,0x92,0x29,0x8d,0x43,0x44,0xb5,0xea,0x43,0x08,0xfe,0x0d,0x8d,0x43,0x2a,0x4b,0xed,
2019 0x43,0xe3,0x8b,0x8b,0x43,0x55,0x7d,0xf0,0x43,0xec,0x51,0x89,0x43,0x72,0x0b,0xf4,0x43,0x08,0xcd,0xd4,
2020 0x84,0x43,0x9d,0x55,0xfb,0x43,0xc9,0xe5,0x83,0x43,0x74,0x1e,0xfb,0x43,0x73,0x94,0x84,0x43,0x5a,0x90,
2021 0xf7,0x43,0x08,0xe8,0x62,0x88,0x43,0xfd,0x30,0xee,0x43,0x39,0xc5,0x86,0x43,0xdd,0xbf,0xeb,0x43,0x35,
2022 0xbe,0x81,0x43,0x40,0xde,0xed,0x43,0x08,0x4f,0x34,0x81,0x43,0x36,0x0c,0xee,0x43,0x08,0x98,0x80,0x43,
2023 0xfd,0x30,0xee,0x43,0x1d,0xe5,0x7f,0x43,0x91,0x4c,0xee,0x43,0x07,0x1d,0xe5,0x7f,0x43,0x91,0x40,0xec,
2024 0x43,0x08,0x35,0xbe,0x81,0x43,0x06,0xf7,0xeb,0x43,0x15,0x65,0x83,0x43,0x49,0xa4,0xeb,0x43,0x1e,0x43,
2025 0x85,0x43,0xbe,0x5a,0xeb,0x43,0x08,0xae,0x93,0x8a,0x43,0xfd,0x18,0xea,0x43,0x42,0x97,0x86,0x43,0x5f,
2026 0x67,0xf4,0x43,0xa9,0x98,0x87,0x43,0xd4,0x1d,0xf4,0x43,0x08,0x5c,0x25,0x8a,0x43,0xcf,0x16,0xef,0x43,
2027 0x46,0xaa,0x8d,0x43,0x5a,0x3c,0xe9,0x43,0x19,0x6c,0x88,0x43,0x53,0x5e,0xe7,0x43,0x08,0xc4,0x02,0x85,
2028 0x43,0x96,0x0b,0xe7,0x43,0x85,0x2c,0x82,0x43,0x83,0x67,0xe7,0x43,0x1d,0xe5,0x7f,0x43,0x72,0xc3,0xe7,
2029 0x43,0x07,0x1d,0xe5,0x7f,0x43,0x87,0x4a,0xe6,0x43,0x09,0x06,0xfd,0x24,0x6c,0x43,0xd9,0x94,0xe0,0x43,
2030 0x08,0xfa,0x6c,0x78,0x43,0xd1,0xc2,0xe0,0x43,0x25,0x5c,0x6c,0x43,0x25,0x44,0xe8,0x43,0x1d,0xe5,0x7f,
2031 0x43,0x87,0x4a,0xe6,0x43,0x07,0x1d,0xe5,0x7f,0x43,0x72,0xc3,0xe7,0x43,0x08,0xa6,0x27,0x7b,0x43,0x91,
2032 0x28,0xe8,0x43,0xbc,0xa2,0x77,0x43,0xb0,0x8d,0xe8,0x43,0xc6,0x68,0x75,0x43,0x57,0x4d,0xe8,0x43,0x08,
2033 0xe0,0xd2,0x72,0x43,0xab,0x9e,0xe7,0x43,0x50,0x9a,0x71,0x43,0x2a,0x27,0xe7,0x43,0xea,0x98,0x70,0x43,
2034 0x57,0x35,0xe4,0x43,0x08,0x94,0x3b,0x6f,0x43,0x14,0x7c,0xe2,0x43,0xff,0x13,0x6d,0x43,0x06,0xbb,0xe1,
2035 0x43,0xcf,0xfe,0x6a,0x43,0x06,0xbb,0xe1,0x43,0x08,0x44,0x9d,0x66,0x43,0x77,0x8e,0xe2,0x43,0x3b,0xef,
2036 0x6c,0x43,0x91,0x10,0xe4,0x43,0xfd,0x24,0x6c,0x43,0xb0,0x81,0xe6,0x43,0x08,0x96,0x23,0x6b,0x43,0xee,
2037 0x57,0xe9,0x43,0xca,0x0f,0x6a,0x43,0x5f,0x37,0xec,0x43,0x55,0x71,0x6e,0x43,0x9f,0x01,0xed,0x43,0x08,
2038 0xdb,0xfb,0x75,0x43,0x3b,0xef,0xec,0x43,0x09,0x3a,0x7b,0x43,0xb0,0xa5,0xec,0x43,0x1d,0xe5,0x7f,0x43,
2039 0x91,0x40,0xec,0x43,0x07,0x1d,0xe5,0x7f,0x43,0x91,0x4c,0xee,0x43,0x08,0xa9,0x16,0x7c,0x43,0xb0,0xb1,
2040 0xee,0x43,0x47,0xec,0x77,0x43,0xd9,0xe8,0xee,0x43,0x1e,0x9d,0x73,0x43,0xcf,0x16,0xef,0x43,0x08,0x0e,
2041 0xc9,0x6b,0x43,0xee,0x7b,0xef,0x43,0x7e,0x90,0x6a,0x43,0xfd,0x30,0xee,0x43,0x01,0xfc,0x68,0x43,0x4e,
2042 0x93,0xec,0x43,0x08,0x31,0xf9,0x66,0x43,0x4e,0x87,0xea,0x43,0x31,0x11,0x6b,0x43,0xd4,0xd5,0xe7,0x43,
2043 0xd9,0xc4,0x68,0x43,0xd4,0xc9,0xe5,0x43,0x08,0xe5,0x79,0x67,0x43,0x77,0x9a,0xe4,0x43,0x44,0x9d,0x66,
2044 0x43,0xab,0x86,0xe3,0x43,0x7e,0x78,0x66,0x43,0x0b,0xaa,0xe2,0x43,0x07,0x7e,0x78,0x66,0x43,0x57,0x29,
2045 0xe2,0x43,0x08,0xa7,0xaf,0x66,0x43,0xbe,0x1e,0xe1,0x43,0x87,0x56,0x68,0x43,0x77,0x82,0xe0,0x43,0xfd,
2046 0x24,0x6c,0x43,0xd9,0x94,0xe0,0x43,0x09,0x06,0xc4,0x41,0xbf,0x43,0x85,0xc0,0x72,0x42,0x08,0x73,0xdf,
2047 0xc0,0x43,0xf4,0x76,0x72,0x42,0x97,0x33,0xc2,0x43,0x85,0xc0,0x72,0x42,0xb2,0xb5,0xc3,0x43,0x64,0x56,
2048 0x75,0x42,0x08,0x03,0x24,0xc4,0x43,0x5e,0x7f,0x78,0x42,0xfa,0x51,0xc4,0x43,0x01,0x85,0x7c,0x42,0x5c,
2049 0x64,0xc4,0x43,0xa0,0xb3,0x80,0x42,0x07,0x5c,0x64,0xc4,0x43,0x10,0x93,0x83,0x42,0x08,0xc8,0x48,0xc4,
2050 0x43,0x1c,0x78,0x8a,0x42,0x27,0x6c,0xc3,0x43,0xaf,0xcf,0x94,0x42,0x23,0x7d,0xc2,0x43,0x99,0x9c,0xa4,
2051 0x42,0x08,0x3d,0xe7,0xbf,0x43,0xfb,0xfd,0xb5,0x42,0xb3,0x9d,0xbf,0x43,0x88,0x17,0xae,0x42,0xc4,0x41,
2052 0xbf,0x43,0x69,0x76,0xa3,0x42,0x07,0xc4,0x41,0xbf,0x43,0xac,0xc8,0x8f,0x42,0x08,0x4f,0x8b,0xbf,0x43,
2053 0xed,0x81,0x91,0x42,0xe4,0xa6,0xbf,0x43,0x5d,0x61,0x94,0x42,0xfa,0x39,0xc0,0x43,0x3b,0x49,0x9d,0x42,
2054 0x08,0x2b,0x43,0xc0,0x43,0x28,0xed,0xa9,0x42,0x61,0x3b,0xc1,0x43,0x00,0x9e,0xa5,0x42,0xe4,0xb2,0xc1,
2055 0x43,0x5d,0x91,0x9c,0x42,0x08,0x78,0xce,0xc1,0x43,0xfd,0x36,0x90,0x42,0x22,0x89,0xc4,0x43,0x81,0x72,
2056 0x86,0x42,0xae,0xc6,0xc2,0x43,0xa0,0xb3,0x80,0x42,0x08,0x54,0x86,0xc2,0x43,0x58,0xd1,0x7e,0x42,0x30,
2057 0x32,0xc1,0x43,0xce,0x5e,0x7b,0x42,0xc4,0x41,0xbf,0x43,0xe8,0xf1,0x7b,0x42,0x07,0xc4,0x41,0xbf,0x43,
2058 0x85,0xc0,0x72,0x42,0x09,0x06,0xf6,0x32,0xbb,0x43,0x40,0xa7,0x60,0x42,0x08,0x35,0xfd,0xbb,0x43,0xa4,
2059 0xa1,0x5c,0x42,0x5e,0x34,0xbc,0x43,0x9d,0x2a,0x70,0x42,0x5e,0x40,0xbe,0x43,0x0e,0x0a,0x73,0x42,0x08,
2060 0x4c,0x9c,0xbe,0x43,0x0e,0x0a,0x73,0x42,0x08,0xef,0xbe,0x43,0x0e,0x0a,0x73,0x42,0xc4,0x41,0xbf,0x43,
2061 0x85,0xc0,0x72,0x42,0x07,0xc4,0x41,0xbf,0x43,0xe8,0xf1,0x7b,0x42,0x08,0xcd,0x13,0xbf,0x43,0xe8,0xf1,
2062 0x7b,0x42,0xd6,0xe5,0xbe,0x43,0x71,0x3b,0x7c,0x42,0xdf,0xb7,0xbe,0x43,0x71,0x3b,0x7c,0x42,0x08,0x08,
2063 0xe3,0xbc,0x43,0xa4,0x61,0x7d,0x42,0x28,0x3c,0xbb,0x43,0x91,0x45,0x69,0x42,0x28,0x3c,0xbb,0x43,0x58,
2064 0x71,0x6e,0x42,0x08,0xce,0xfb,0xba,0x43,0xd5,0x35,0x78,0x42,0x59,0x45,0xbb,0x43,0x58,0x23,0x82,0x42,
2065 0xa1,0xe1,0xbb,0x43,0xd7,0xbe,0x88,0x42,0x08,0xc9,0x18,0xbc,0x43,0xaf,0x9f,0x8c,0x42,0x1e,0x76,0xbd,
2066 0x43,0x51,0x7c,0x8d,0x42,0xd6,0xe5,0xbe,0x43,0xf4,0x58,0x8e,0x42,0x08,0x9c,0x0a,0xbf,0x43,0x45,0xc7,
2067 0x8e,0x42,0x30,0x26,0xbf,0x43,0x96,0x35,0x8f,0x42,0xc4,0x41,0xbf,0x43,0xac,0xc8,0x8f,0x42,0x07,0xc4,
2068 0x41,0xbf,0x43,0x69,0x76,0xa3,0x42,0x08,0x08,0xef,0xbe,0x43,0xb1,0xd6,0x99,0x42,0xe8,0x89,0xbe,0x43,
2069 0xde,0xc5,0x8d,0x42,0xc0,0x46,0xbc,0x43,0xc2,0x5b,0x90,0x42,0x08,0x9c,0xf2,0xba,0x43,0x86,0x80,0x90,
2070 0x42,0xf2,0x43,0xba,0x43,0xe8,0x73,0x87,0x42,0x8f,0x31,0xba,0x43,0xb6,0xf4,0x7d,0x42,0x07,0x8f,0x31,
2071 0xba,0x43,0x21,0xc6,0x76,0x42,0x08,0xc0,0x3a,0xba,0x43,0x5f,0x48,0x6b,0x42,0xae,0x96,0xba,0x43,0xe3,
2072 0x83,0x61,0x42,0xf6,0x32,0xbb,0x43,0x40,0xa7,0x60,0x42,0x09,0x06,0xea,0x74,0xea,0x43,0x61,0x44,0x93,
2073 0x43,0x08,0x24,0x5c,0xec,0x43,0x31,0x3b,0x93,0x43,0xfb,0x30,0xee,0x43,0x93,0x4d,0x93,0x43,0x0d,0xe1,
2074 0xef,0x43,0x80,0xa9,0x93,0x43,0x08,0x8f,0x58,0xf0,0x43,0xd1,0x17,0x94,0x43,0xb7,0x8f,0xf0,0x43,0x10,
2075 0xe2,0x94,0x43,0xea,0x98,0xf0,0x43,0xa9,0xec,0x95,0x43,0x07,0xea,0x98,0xf0,0x43,0x38,0x25,0x97,0x43,
2076 0x08,0x23,0x74,0xf0,0x43,0x9f,0x32,0x9a,0x43,0x5a,0x60,0xef,0x43,0x53,0xcb,0x9e,0x43,0x2d,0x3a,0xee,
2077 0x43,0xfd,0x91,0xa3,0x43,0x08,0xa2,0xf0,0xed,0x43,0xdd,0x38,0xa5,0x43,0x17,0xa7,0xed,0x43,0xbe,0xdf,
2078 0xa6,0x43,0x5a,0x54,0xed,0x43,0x9f,0x86,0xa8,0x43,0x08,0xfc,0x24,0xec,0x43,0xca,0xc4,0xad,0x43,0x48,
2079 0xa4,0xeb,0x43,0x40,0x6f,0xab,0x43,0x28,0x3f,0xeb,0x43,0x1c,0x0f,0xa8,0x43,0x08,0x1f,0x6d,0xeb,0x43,
2080 0x72,0x48,0xa3,0x43,0x67,0x09,0xec,0x43,0xd1,0x53,0x9e,0x43,0xea,0x74,0xea,0x43,0x1e,0xc7,0x9b,0x43,
2081 0x07,0xea,0x74,0xea,0x43,0x8a,0x9f,0x99,0x43,0x08,0x7e,0x90,0xea,0x43,0x8a,0x9f,0x99,0x43,0x12,0xac,
2082 0xea,0x43,0xbc,0xa8,0x99,0x43,0xa7,0xc7,0xea,0x43,0xbc,0xa8,0x99,0x43,0x08,0x51,0x76,0xeb,0x43,0x9f,
2083 0x32,0x9a,0x43,0x5e,0x37,0xec,0x43,0x49,0xed,0x9c,0x43,0xb0,0xa5,0xec,0x43,0x2a,0xa0,0xa0,0x43,0x08,
2084 0x09,0xe6,0xec,0x43,0xd1,0x77,0xa4,0x43,0x28,0x4b,0xed,0x43,0x61,0xa4,0xa3,0x43,0xab,0xc2,0xed,0x43,
2085 0x8e,0xb2,0xa0,0x43,0x08,0x70,0xe7,0xed,0x43,0xde,0x08,0x9d,0x43,0x87,0x86,0xf0,0x43,0x2f,0x53,0x97,
2086 0x43,0x87,0x7a,0xee,0x43,0xec,0x99,0x95,0x43,0x08,0xca,0x27,0xee,0x43,0xff,0x3d,0x95,0x43,0x74,0xca,
2087 0xec,0x43,0x55,0x8f,0x94,0x43,0xea,0x74,0xea,0x43,0xe7,0xaa,0x94,0x43,0x07,0xea,0x74,0xea,0x43,0x61,
2088 0x44,0x93,0x43,0x09,0x06,0x05,0xd3,0xe5,0x43,0x19,0x9c,0x90,0x43,0x08,0x09,0xc2,0xe6,0x43,0xd1,0xff,
2089 0x8f,0x43,0x4d,0x6f,0xe6,0x43,0x74,0xe8,0x92,0x43,0x3b,0xd7,0xe8,0x43,0xc3,0x56,0x93,0x43,0x08,0x1f,
2090 0x61,0xe9,0x43,0x93,0x4d,0x93,0x43,0x05,0xeb,0xe9,0x43,0x93,0x4d,0x93,0x43,0xea,0x74,0xea,0x43,0x61,
2091 0x44,0x93,0x43,0x07,0xea,0x74,0xea,0x43,0xe7,0xaa,0x94,0x43,0x08,0x24,0x50,0xea,0x43,0xe7,0xaa,0x94,
2092 0x43,0x2d,0x22,0xea,0x43,0xe7,0xaa,0x94,0x43,0x36,0xf4,0xe9,0x43,0xe7,0xaa,0x94,0x43,0x08,0xa2,0xcc,
2093 0xe7,0x43,0xe0,0xd8,0x94,0x43,0xd4,0xc9,0xe5,0x43,0x19,0xa8,0x92,0x43,0xd4,0xc9,0xe5,0x43,0x27,0x69,
2094 0x93,0x43,0x08,0x17,0x77,0xe5,0x43,0xe0,0xd8,0x94,0x43,0x67,0xe5,0xe5,0x43,0x47,0xda,0x95,0x43,0x43,
2095 0x9d,0xe6,0x43,0xe2,0xd3,0x97,0x43,0x08,0x9d,0xdd,0xe6,0x43,0xad,0xe7,0x98,0x43,0x09,0xce,0xe8,0x43,
2096 0xff,0x55,0x99,0x43,0xea,0x74,0xea,0x43,0x8a,0x9f,0x99,0x43,0x07,0xea,0x74,0xea,0x43,0x1e,0xc7,0x9b,
2097 0x43,0x08,0x71,0xcf,0xe9,0x43,0x53,0xb3,0x9a,0x43,0xa7,0xbb,0xe8,0x43,0xdb,0x0d,0x9a,0x43,0xc6,0x14,
2098 0xe7,0x43,0xdb,0x0d,0x9a,0x43,0x08,0x48,0x80,0xe5,0x43,0xdb,0x0d,0x9a,0x43,0x0a,0xb6,0xe4,0x43,0xc3,
2099 0x6e,0x97,0x43,0x76,0x9a,0xe4,0x43,0x74,0xf4,0x94,0x43,0x07,0x76,0x9a,0xe4,0x43,0x79,0xd7,0x93,0x43,
2100 0x08,0xd8,0xac,0xe4,0x43,0x66,0x27,0x92,0x43,0x29,0x1b,0xe5,0x43,0xe0,0xc0,0x90,0x43,0x05,0xd3,0xe5,
2101 0x43,0x19,0x9c,0x90,0x43,0x09,0x06,0x1b,0x66,0xe6,0x42,0xe3,0xa3,0x8f,0x42,0x08,0x71,0x0b,0xf4,0x42,
2102 0x00,0x0e,0x8d,0x42,0x8c,0x0f,0x01,0x43,0x3e,0xc0,0x89,0x42,0xf3,0x28,0x06,0x43,0x48,0x9e,0x8b,0x42,
2103 0x08,0x15,0x89,0x09,0x43,0x00,0x0e,0x8d,0x42,0xe0,0x9c,0x0a,0x43,0xc1,0x8b,0x98,0x42,0xa6,0xc1,0x0a,
2104 0x43,0x02,0xa5,0xaa,0x42,0x07,0xa6,0xc1,0x0a,0x43,0xf9,0xf6,0xb0,0x42,0x08,0xa6,0xc1,0x0a,0x43,0x47,
2105 0x8e,0xb4,0x42,0x42,0xaf,0x0a,0x43,0x1f,0x6f,0xb8,0x42,0xe0,0x9c,0x0a,0x43,0xba,0x74,0xbc,0x42,0x08,
2106 0xa1,0xd2,0x09,0x43,0x40,0x47,0xd0,0x42,0x0d,0xab,0x07,0x43,0x91,0xb5,0xd0,0x42,0x3b,0xb9,0x04,0x43,
2107 0xec,0x71,0xba,0x42,0x08,0xe5,0x5b,0x03,0x43,0xe3,0x33,0xa8,0x42,0x63,0xd8,0x00,0x43,0xce,0x70,0x9f,
2108 0x42,0x1b,0x66,0xe6,0x42,0xae,0x2f,0xa5,0x42,0x07,0x1b,0x66,0xe6,0x42,0xa2,0x4a,0x9e,0x42,0x08,0xed,
2109 0x6f,0xed,0x42,0x73,0x24,0x9d,0x42,0xd8,0x0c,0xf5,0x42,0x99,0x6c,0x9c,0x42,0x27,0xab,0xfd,0x42,0xea,
2110 0xda,0x9c,0x42,0x08,0x36,0xca,0x03,0x43,0x2b,0x94,0x9e,0x42,0x68,0xc7,0x01,0x43,0x8f,0xbe,0xa2,0x42,
2111 0xfa,0x06,0x08,0x43,0x73,0xb4,0xb5,0x42,0x08,0x8e,0x2e,0x0a,0x43,0x1f,0x6f,0xb8,0x42,0x9d,0xe3,0x08,
2112 0x43,0xd7,0x1e,0x99,0x42,0x28,0x15,0x05,0x43,0x32,0x3b,0x93,0x42,0x08,0x63,0xf0,0x04,0x43,0x70,0xed,
2113 0x8f,0x42,0x71,0x0b,0xf4,0x42,0x32,0x3b,0x93,0x42,0x1b,0x66,0xe6,0x42,0x73,0xf4,0x94,0x42,0x07,0x1b,
2114 0x66,0xe6,0x42,0xe3,0xa3,0x8f,0x42,0x09,0x06,0x5e,0x28,0xba,0x42,0x35,0xe2,0x87,0x42,0x08,0x8e,0x55,
2115 0xc0,0x42,0xb8,0x4d,0x86,0x42,0x60,0xbf,0xd7,0x42,0x3e,0xf0,0x91,0x42,0x63,0xf6,0xe4,0x42,0x70,0xed,
2116 0x8f,0x42,0x08,0x7a,0x89,0xe5,0x42,0xac,0xc8,0x8f,0x42,0xcc,0xf7,0xe5,0x42,0xac,0xc8,0x8f,0x42,0x1b,
2117 0x66,0xe6,0x42,0xe3,0xa3,0x8f,0x42,0x07,0x1b,0x66,0xe6,0x42,0x73,0xf4,0x94,0x42,0x08,0x63,0xf6,0xe4,
2118 0x42,0x3b,0x19,0x95,0x42,0xe6,0x61,0xe3,0x42,0x00,0x3e,0x95,0x42,0xf4,0x16,0xe2,0x42,0xc4,0x62,0x95,
2119 0x42,0x08,0x6e,0x74,0xd6,0x42,0x15,0xd1,0x95,0x42,0x97,0x63,0xca,0x42,0xaf,0xcf,0x94,0x42,0xfb,0x2d,
2120 0xbe,0x42,0x86,0x80,0x90,0x42,0x08,0x97,0x03,0xba,0x42,0xce,0x10,0x8f,0x42,0x5e,0x28,0xba,0x42,0x3e,
2121 0xf0,0x91,0x42,0xf2,0x4f,0xbc,0x42,0x45,0xf7,0x96,0x42,0x08,0x27,0x54,0xbf,0x42,0x73,0x24,0x9d,0x42,
2122 0xa5,0xe8,0xc0,0x42,0x86,0xe0,0xa0,0x42,0xe4,0xca,0xc5,0x42,0xed,0x11,0xaa,0x42,0x08,0x54,0xaa,0xc8,
2123 0x42,0x86,0x40,0xb1,0x42,0x59,0x81,0xc5,0x42,0xa1,0x11,0xc4,0x42,0x3e,0xe7,0xbf,0x42,0xfb,0x8d,0xce,
2124 0x42,0x08,0xb4,0x6d,0xb7,0x42,0x30,0xc2,0xd9,0x42,0x46,0xf5,0xc9,0x42,0xdf,0x53,0xd9,0x42,0x38,0x40,
2125 0xcb,0x42,0x62,0x8f,0xcf,0x42,0x08,0x7d,0xf9,0xcc,0x42,0xec,0xa1,0xc2,0x42,0x07,0x43,0xcd,0x42,0x6c,
2126 0xdd,0xb8,0x42,0x2b,0x8b,0xcc,0x42,0x92,0xf5,0xaf,0x42,0x08,0xf9,0x8d,0xce,0x42,0x41,0x57,0xa7,0x42,
2127 0x5b,0xb8,0xd2,0x42,0xae,0x2f,0xa5,0x42,0x18,0x2f,0xd9,0x42,0x13,0x2a,0xa1,0x42,0x08,0x41,0x7e,0xdd,
2128 0x42,0xe3,0x03,0xa0,0x42,0x2e,0xf2,0xe1,0x42,0x7c,0x02,0x9f,0x42,0x1b,0x66,0xe6,0x42,0xa2,0x4a,0x9e,
2129 0x42,0x07,0x1b,0x66,0xe6,0x42,0xae,0x2f,0xa5,0x42,0x08,0x4d,0x63,0xe4,0x42,0x00,0x9e,0xa5,0x42,0xf4,
2130 0x16,0xe2,0x42,0x15,0x31,0xa6,0x42,0x99,0xca,0xdf,0x42,0x2b,0xc4,0xa6,0x42,0x08,0xc0,0x82,0xc6,0x42,
2131 0xc4,0xc2,0xa5,0x42,0x57,0xe1,0xd5,0x42,0x91,0xb5,0xd0,0x42,0x54,0xda,0xd0,0x42,0x97,0x93,0xd2,0x42,
2132 0x08,0x9c,0x3a,0xc7,0x42,0x17,0x58,0xdc,0x42,0x9c,0x0a,0xbf,0x42,0x6e,0xa4,0xde,0x42,0x90,0x25,0xb8,
2133 0x42,0xdf,0x53,0xd9,0x42,0x08,0x59,0x21,0xb5,0x42,0xf2,0xdf,0xd4,0x42,0x51,0x43,0xb3,0x42,0x91,0xb5,
2134 0xd0,0x42,0xc5,0x29,0xbb,0x42,0x0e,0x1a,0xca,0x42,0x08,0x65,0x36,0xc4,0x42,0xd0,0x07,0xbd,0x42,0x3e,
2135 0xe7,0xbf,0x42,0x37,0x09,0xbe,0x42,0x0c,0xea,0xc1,0x42,0xcd,0xd0,0xaf,0x42,0x08,0x2b,0x5b,0xc4,0x42,
2136 0x18,0x08,0xa3,0x42,0x67,0xa6,0xab,0x42,0x99,0x3c,0x94,0x42,0x5e,0x28,0xba,0x42,0x35,0xe2,0x87,0x42,
2141 // ////////////////////////////////////////////////////////////////////////// //
2142 final class SdpyDrawSdpyImage
: SdpyDrawBase
{
2147 // must be overriden
2148 override Color
getpix (int x
, int y
) {
2149 static if (UsingSimpledisplayX11
) {
2150 pragma(inline
, true);
2151 const(uint)* dp
= (cast(const(uint)*)vbuf
.getDataPointer
)+y
*vbuf
.width
+x
;
2152 return XlibImageTC
.img2c(*dp
);
2154 return vbuf
.getPixel(x
, y
);
2158 override void putpix (int x
, int y
, Color col
) {
2159 static if (UsingSimpledisplayX11
) {
2160 uint* dp
= (cast(uint*)vbuf
.getDataPointer
)+y
*vbuf
.width
+x
;
2161 if (col
.a
== 255) *dp
= XlibImageTC
.c2img(col
)|
0xff_000000; else *dp
= blendU32(*dp
, XlibImageTC
.c2img(col
)|
(col
.a
<<24));
2163 vbuf
.setPixel(x
, y
, col
);
2168 override void hline (int x
, int y
, int len
, Color col
) {
2169 static if (UsingSimpledisplayX11
) {
2170 uint* dp
= (cast(uint*)vbuf
.getDataPointer
)+y
*vbuf
.width
+x
;
2171 uint uc
= XlibImageTC
.c2img(col
);
2174 foreach (immutable _
; 0..len
) *dp
++ = uc
;
2177 foreach (immutable _
; 0..len
) { *dp
= blendU32(*dp
, uc
); ++dp
; }
2180 while (len
-- > 0) vbuf
.setPixel(x
++, y
, col
);
2187 super(img
.width
, img
.height
);
2190 override TrueColorImage
getBuffer () {
2191 auto img
= new TrueColorImage(vbuf
.width
, vbuf
.height
);
2192 static if (UsingSimpledisplayX11
) {
2193 const(uint)* sp
= cast(const(uint)*)vbuf
.getDataPointer
;
2194 auto dp
= img
.imageData
.colors
.ptr
;
2195 foreach (immutable y
; 0..vbuf
.height
) {
2196 foreach (immutable x
; 0..vbuf
.width
) {
2197 *dp
++ = XlibImageTC
.img2c(*sp
++);
2201 foreach (immutable y
; 0..vbuf
.height
) {
2202 foreach (immutable x
; 0..vbuf
.width
) {
2203 img
.setPixel(x
, y
, vbuf
.getPixel(x
, y
));
2210 final @property Image
imagebuf () pure nothrow @safe @nogc { pragma(inline
, true); return vbuf
; }
2214 // ////////////////////////////////////////////////////////////////////////// //
2215 // some "fastgfx" backend
2217 class SdpyAADrawBase(RendT) if (is(RT : Renderer!ST, ST)) {
2219 static T abs(T) (T n) pure nothrow @safe @nogc { pragma(inline, true); return (n < 0 ? -n : n); }
2222 private static int lrintf (float f) nothrow @trusted @nogc { pragma(inline, true); return cast(int)(f+0.5f); }
2223 private static int lrintd (double f) nothrow @trusted @nogc { pragma(inline, true); return cast(int)(f+0.5); }
2225 private import core.stdc.math : lrintf, lrintd = lrint;
2227 private import core.stdc.math : sqrtf, sqrtd = sqrt;
2228 private import core.stdc.math : floorf, floord = floor;
2229 private import core.stdc.math : cosf, sinf;
2236 protected nothrow @trusted @nogc: // low-level methods; will always be called with valid coords
2237 // must be overriden
2239 final void hline (int x, int y, int len, Color c) {
2240 while (len-- > 0) rend.putPixel(x++, y, c);
2243 final void vline (int x, int y, int len, Color c) {
2244 while (len-- > 0) rend.putPixel(x, y++, c);
2247 final void fillrc (int x, int y, int w, int h, Color c) {
2248 while (h-- > 0) hline(x, y++, w, c);
2253 float tessTol = 0.25f;
2254 float angleTol = 0.0f; // 0.0f -- angle tolerance for McSeem Bezier rasterizer
2255 float cuspLimit = 0; // 0 -- cusp limit for McSeem Bezier rasterizer (0: real cusps)
2257 public nothrow @trusted @nogc:
2258 this (int awdt, int ahgt) {
2259 if (awdt < 0) awdt = 0;
2260 if (ahgt < 0) ahgt = 0;
2261 dim = GxSize(awdt, ahgt);
2267 final @property int width () const pure nothrow @safe @nogc { pragma(inline, true); return dim.width; }
2268 final @property int height () const pure nothrow @safe @nogc { pragma(inline, true); return dim.height; }
2270 void cls (Color clr=Color.white) { rend.clear(clr); beginPath(); }
2272 // can return null, yeah
2273 TrueColorImage getBuffer () { return null; }
2276 Color getPixel (int x, int y) {
2277 pragma(inline, true);
2278 return (x >= 0 && y >= 0 && x < dim.width && y < dim.height && clip.inside(x, y) ? rend.getPixel(x, y) : Color.transparent);
2281 void putPixel (int x, int y, Color c) {
2282 pragma(inline, true);
2283 if (x >= 0 && y >= 0 && x < dim.width && y < dim.height && clip.inside(x, y)) rend.putPixel(x, y, c);
2286 // ////////////////////////////////////////////////////////////////////////// //
2287 // based on the ideas and code of Maxim Shemanarev. Rest in Peace, bro!
2288 // see http://www.antigrain.com/research/adaptive_bezier/index.html
2289 private void nvg__tesselateBezierMcSeem (in float x1, in float y1, in float x2, in float y2, in float x3, in float y3, in float x4, in float y4, in int level/*, in int type*/) {
2290 enum CollinearEPS = 0.00000001f; // 0.00001f;
2291 enum AngleTolEPS = 0.01f;
2293 static float distSquared (in float x1, in float y1, in float x2, in float y2) pure nothrow @safe @nogc {
2294 pragma(inline, true);
2295 immutable float dx = x2-x1;
2296 immutable float dy = y2-y1;
2301 rast.lineTo(x1, y1/*, 0*/);
2302 nvg__tesselateBezierMcSeem(ctx, x1, y1, x2, y2, x3, y3, x4, y4, 1/*, type*/);
2303 rast.lineTo(x4, y4/*, type*/);
2307 if (level >= 32) return; // recurse limit; practically, it should be never reached, but...
2309 // calculate all the mid-points of the line segments
2310 immutable float x12 = (x1+x2)*0.5f;
2311 immutable float y12 = (y1+y2)*0.5f;
2312 immutable float x23 = (x2+x3)*0.5f;
2313 immutable float y23 = (y2+y3)*0.5f;
2314 immutable float x34 = (x3+x4)*0.5f;
2315 immutable float y34 = (y3+y4)*0.5f;
2316 immutable float x123 = (x12+x23)*0.5f;
2317 immutable float y123 = (y12+y23)*0.5f;
2318 immutable float x234 = (x23+x34)*0.5f;
2319 immutable float y234 = (y23+y34)*0.5f;
2320 immutable float x1234 = (x123+x234)*0.5f;
2321 immutable float y1234 = (y123+y234)*0.5f;
2323 // try to approximate the full cubic curve by a single straight line
2324 immutable float dx = x4-x1;
2325 immutable float dy = y4-y1;
2327 float d2 = nvg__absf(((x2-x4)*dy-(y2-y4)*dx));
2328 float d3 = nvg__absf(((x3-x4)*dy-(y3-y4)*dx));
2330 final switch ((cast(int)(d2 > CollinearEPS)<<1)+cast(int)(d3 > CollinearEPS)) {
2332 // all collinear or p1 == p4
2333 float k = dx*dx+dy*dy;
2335 d2 = distSquared(x1, y1, x2, y2);
2336 d3 = distSquared(x4, y4, x3, y3);
2341 d2 = k*(da1*dx+da2*dy);
2344 d3 = k*(da1*dx+da2*dy);
2345 if (d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1) {
2346 // Simple collinear case, 1---2---3---4
2347 // We can leave just two endpoints
2350 if (d2 <= 0) d2 = distSquared(x2, y2, x1, y1);
2351 else if (d2 >= 1) d2 = distSquared(x2, y2, x4, y4);
2352 else d2 = distSquared(x2, y2, x1+d2*dx, y1+d2*dy);
2354 if (d3 <= 0) d3 = distSquared(x3, y3, x1, y1);
2355 else if (d3 >= 1) d3 = distSquared(x3, y3, x4, y4);
2356 else d3 = distSquared(x3, y3, x1+d3*dx, y1+d3*dy);
2359 if (d2 < ctx.tessTol) {
2360 rast.lineTo(x2, y2/*, type*/);
2363 } if (d3 < ctx.tessTol) {
2364 rast.lineTo(x3, y3/*, type*/);
2369 // p1,p2,p4 are collinear, p3 is significant
2370 if (d3*d3 <= ctx.tessTol*(dx*dx+dy*dy)) {
2371 if (ctx.angleTol < AngleTolEPS) {
2372 rast.lineTo(x23, y23/*, type*/);
2376 float da1 = nvg__absf(nvg__atan2f(y4-y3, x4-x3)-nvg__atan2f(y3-y2, x3-x2));
2377 if (da1 >= NVG_PI) da1 = 2*NVG_PI-da1;
2378 if (da1 < ctx.angleTol) {
2379 rast.lineTo(x2, y2/*, type*/);
2380 rast.lineTo(x3, y3/*, type*/);
2383 if (ctx.cuspLimit != 0.0) {
2384 if (da1 > ctx.cuspLimit) {
2385 rast.lineTo(x3, y3/*, type*/);
2393 // p1,p3,p4 are collinear, p2 is significant
2394 if (d2*d2 <= ctx.tessTol*(dx*dx+dy*dy)) {
2395 if (ctx.angleTol < AngleTolEPS) {
2396 rast.lineTo(x23, y23/*, type*/);
2400 float da1 = nvg__absf(nvg__atan2f(y3-y2, x3-x2)-nvg__atan2f(y2-y1, x2-x1));
2401 if (da1 >= NVG_PI) da1 = 2*NVG_PI-da1;
2402 if (da1 < ctx.angleTol) {
2403 rast.lineTo(x2, y2/*, type*/);
2404 rast.lineTo(x3, y3/*, type*/);
2407 if (ctx.cuspLimit != 0.0) {
2408 if (da1 > ctx.cuspLimit) {
2409 rast.lineTo(x2, y2/*, type*/);
2418 if ((d2+d3)*(d2+d3) <= ctx.tessTol*(dx*dx+dy*dy)) {
2419 // if the curvature doesn't exceed the distance tolerance value, we tend to finish subdivisions
2420 if (ctx.angleTol < AngleTolEPS) {
2421 rast.lineTo(x23, y23/*, type*/);
2424 // angle and cusp condition
2425 immutable float k = nvg__atan2f(y3-y2, x3-x2);
2426 float da1 = nvg__absf(k-nvg__atan2f(y2-y1, x2-x1));
2427 float da2 = nvg__absf(nvg__atan2f(y4-y3, x4-x3)-k);
2428 if (da1 >= NVG_PI) da1 = 2*NVG_PI-da1;
2429 if (da2 >= NVG_PI) da2 = 2*NVG_PI-da2;
2430 if (da1+da2 < ctx.angleTol) {
2431 // finally we can stop the recursion
2432 rast.lineTo(x23, y23/*, type*/);
2435 if (ctx.cuspLimit != 0.0) {
2436 if (da1 > ctx.cuspLimit) {
2437 rast.lineTo(x2, y2/*, type*/);
2440 if (da2 > ctx.cuspLimit) {
2441 rast.lineTo(x3, y3/*, type*/);
2450 // continue subdivision
2451 nvg__tesselateBezierMcSeem(x1, y1, x12, y12, x123, y123, x1234, y1234, level+1/*, 0*/);
2452 nvg__tesselateBezierMcSeem(x1234, y1234, x234, y234, x34, y34, x4, y4, level+1/*, type*/);
2455 @property float curX () const pure { pragma(inline, true); return rast.curX; }
2456 @property float curY () const pure { pragma(inline, true); return rast.curY; }
2458 void beginPath () { pragma(inline, true); rast.reset(); rast.moveTo(0, 0); }
2460 void moveTo (in float x, in float y) { pragma(inline, true); rast.moveTo(x, y); }
2461 void lineTo (in float x, in float y) { pragma(inline, true); rast.lineTo(x, y); }
2463 void bezierTo (in float x2, in float y2, in float x3, in float y3, in float x4, in float y4) {
2464 pragma(inline, true);
2465 nvg__tesselateBezierMcSeem(curX, curY, x2, y2, x3, y3, x4, y4);
2468 void quadTo (in float cx, in float cy, in float x, in float y) {
2469 immutable float x0 = curX;
2470 immutable float y0 = curY;
2472 x0+2.0f/3.0f*(cx-x0), y0+2.0f/3.0f*(cy-y0),
2473 x+2.0f/3.0f*(cx-x), y+2.0f/3.0f*(cy-y),
2478 void fill (in Color c) {
2479 pragma(inline, true);
2480 rast.render(rend, c);
2483 // ////////////////////////////////////////////////////////////////////////// //
2484 enum BaphometDims = 512; // [0..511]
2485 final void renderBaphomet (in Color fc, float ofsx=0, float ofsy=0, float scalex=1, float scaley=1) {
2486 auto path = cast(const(ubyte)[])baphometPath;
2487 immutable plen = path.length;
2490 void drawLine (float x1, float y1, float x2, float y2, float width=0.2) {
2491 import std.math : sqrt;
2494 immutable float d = sqrtf(dx*dx+dy*dy);
2496 dx = width*(y2-y1)/d;
2497 dy = width*(x2-x1)/d;
2499 rast.moveTo(x1-dx, y1+dy);
2500 rast.lineTo(x2-dx, y2+dy);
2501 rast.lineTo(x2+dx, y2-dy);
2502 rast.lineTo(x1+dx, y1-dy);
2506 Bounds, // always first, has 4 args (x0, y0, x1, y1)
2514 CubicTo, // cubic bezier
2518 Command getCommand () nothrow @trusted @nogc {
2519 if (ppos >= plen) assert(0, "invalid path");
2520 return cast(Command)(path.ptr[ppos++]);
2523 float getFloat () nothrow @trusted @nogc {
2524 if (ppos >= plen || plen-ppos < float.sizeof) assert(0, "invalid path");
2525 version(LittleEndian) {
2526 float res = *cast(const(float)*)(&path.ptr[ppos]);
2527 ppos += cast(uint)float.sizeof;
2530 static assert(float.sizeof == 4);
2531 uint xp = path.ptr[ppos]|(path.ptr[ppos+1]<<8)|(path.ptr[ppos+2]<<16)|(path.ptr[ppos+3]<<24);
2532 ppos += cast(uint)float.sizeof;
2533 return *cast(const(float)*)(&xp);
2537 int scaleX (float v) nothrow @trusted @nogc { pragma(inline, true); return lrintf(ofsx+v*scalex); }
2538 int scaleY (float v) nothrow @trusted @nogc { pragma(inline, true); return lrintf(ofsy+v*scaley); }
2541 bool doStroke = false, doFill = false;
2542 while (ppos < plen) {
2543 auto cmd = getCommand();
2544 final switch (cmd) {
2545 case Command.Bounds: ppos += 4*cast(uint)float.sizeof; break;
2546 case Command.StrokeMode: doStroke = true; doFill = false; break;
2547 case Command.FillMode: doStroke = false; doFill = true;
2548 case Command.StrokeFillMode: break;
2549 case Command.NormalStroke: case Command.ThinStroke: break;
2550 case Command.MoveTo:
2551 cx = scaleX(getFloat());
2552 cy = scaleY(getFloat());
2553 rast.moveTo(cx, cy);
2555 case Command.LineTo:
2556 immutable int ex = scaleX(getFloat());
2557 immutable int ey = scaleY(getFloat());
2558 if (doFill) rast.lineTo(ex, ey); else if (doStroke) drawLine(cx, cy, ex, ey, fc);
2562 case Command.CubicTo: // cubic bezier
2563 immutable int x1 = scaleX(getFloat());
2564 immutable int y1 = scaleY(getFloat());
2565 immutable int x2 = scaleX(getFloat());
2566 immutable int y2 = scaleY(getFloat());
2567 immutable int ex = scaleX(getFloat());
2568 immutable int ey = scaleY(getFloat());
2569 if (doFill) drawCubicBezier(cx, cy, x1, y1, x2, y2, ex, ey, fc);
2573 case Command.EndPath: // don't close this path
2581 // ////////////////////////////////////////////////////////////////////////// //
2583 /* *****************************************************************************
2584 Anti-Grain Geometry - Version 2.1 Lite
2585 Copyright (C) 2002-2003 Maxim Shemanarev (McSeem)
2587 Permission to copy, use, modify, sell and distribute this software
2588 is granted provided this copyright notice appears in all copies.
2589 This software is provided "as is" without express or implied
2590 warranty, and with no claim as to its suitability for any purpose.
2592 The author gratefully acknowleges the support of David Turner,
2593 Robert Wilhelm, and Werner Lemberg - the authors of the FreeType
2594 libray - in producing this work. See http://www.freetype.org for details.
2596 Initially the rendering algorithm was designed by David Turner and the
2597 other authors of the FreeType library - see the above notice. I nearly
2598 created a similar renderer, but still I was far from David's work.
2599 I completely redesigned the original code and adapted it for Anti-Grain
2600 ideas. Two functions - renderLine and renderScanLine are the core of
2601 the algorithm - they calculate the exact coverage of each pixel cell
2602 of the polygon. I left these functions almost as is, because there's
2603 no way to improve the perfection - hats off to David and his group!
2605 All other code is very different from the original.
2606 ***************************************************************************** */
2607 struct RenderingBuffer {
2609 ubyte* mBuf; // Pointer to renrdering buffer
2610 ubyte** mRows; // Pointers to each row of the buffer
2611 uint mWidth; // Width in pixels
2612 uint mHeight; // Height in pixels
2613 int mStride; // Number of bytes per row. Can be < 0
2614 uint mMaxHeight; // Maximal current height
2616 public nothrow @trusted @nogc:
2617 @disable this (this); // no copies
2619 this (ubyte* buf, uint width, uint height, int stride) {
2620 attach(buf, width, height, stride);
2624 import core.stdc.stdlib : free;
2628 void attach (ubyte* buf, uint width, uint height, int stride) {
2629 import core.stdc.stdlib : realloc;
2630 if (width < 1 || height < 1 || width > short.max || height > short.max) assert(0, "invalid rendering buffer dimensions");
2635 if (height > mMaxHeight || mRows is null) {
2636 mRows = cast(ubyte**)realloc(mRows, (ubyte*).sizeof*height);
2637 if (mRows is null) assert(0, "out of memory");
2640 ubyte* rowPtr = mBuf;
2641 if (stride < 0) rowPtr = mBuf-cast(int)(height-1)*stride;
2643 ubyte** rows = mRows;
2650 @property inout(ubyte)* buf () inout pure { pragma(inline, true); return mBuf; }
2651 uint width () const pure { pragma(inline, true); return mWidth; }
2652 uint height () const pure { pragma(inline, true); return mHeight; }
2653 int stride () const pure { pragma(inline, true); return mStride; }
2655 bool inbox (int x, int y) const pure { pragma(inline, true); return (x >= 0 && y >= 0 && x < cast(int)mWidth && y < cast(int)mHeight); }
2657 uint absStride() const pure { pragma(inline, true); return (mStride < 0 ? cast(uint)(-mStride) : cast(uint)mStride); }
2659 inout(ubyte)* row (uint y) inout pure { pragma(inline, true); return (y < mHeight ? mRows[y] : null); }
2661 inout(ubyte)[] opSlice () inout pure { pragma(inline, true); return mBuf[0..mHeight*absStride]; }
2671 int mLastX = 0x7fff;
2672 int mLastY = 0x7fff;
2677 ubyte** mCurStartPtr;
2681 enum { AAShift = 8 }
2683 static struct Iterator {
2685 const(ubyte)* mCovers;
2686 const(ushort)* mCurCount;
2687 const(ubyte*)* mCurStartPtr;
2689 public nothrow @trusted @nogc:
2690 @disable this (this); // no copies
2692 this (in ref ScanLine sl) {
2693 mCovers = sl.mCovers;
2694 mCurCount = sl.mCounts;
2695 mCurStartPtr = sl.mStartPtrs;
2701 return cast(int)(*mCurStartPtr-mCovers);
2704 @property int numPix () const pure { pragma(inline, true); return cast(int)(*mCurCount); }
2705 @property const(ubyte)* covers () const pure { pragma(inline, true); return *mCurStartPtr; }
2708 public nothrow @trusted @nogc:
2709 @disable this (this); // no copies
2712 import core.stdc.stdlib : free;
2718 auto iterator () const { pragma(inline, true); return Iterator(this); }
2720 void reset (int minX, int maxX, int dx=0, int dy=0) {
2721 uint maxLen = maxX-minX+2;
2722 if (maxLen > mMaxLen) {
2723 import core.stdc.stdlib : realloc;
2724 mCovers = cast(ubyte*)realloc(mCovers, maxLen);
2725 if (mCovers is null) assert(0, "out of memory");
2726 mStartPtrs = cast(ubyte**)realloc(mStartPtrs, (ubyte*).sizeof*maxLen);
2727 if (mStartPtrs is null) assert(0, "out of memory");
2728 mCounts = cast(ushort*)realloc(mCounts, ushort.sizeof*maxLen);
2729 if (mCounts is null) assert(0, "out of memory");
2737 mCurCount = mCounts;
2738 mCurStartPtr = mStartPtrs;
2742 void resetSpans () {
2743 pragma(inline, true);
2746 mCurCount = mCounts;
2747 mCurStartPtr = mStartPtrs;
2751 void addSpan (int x, int y, uint num, uint cover) {
2752 import core.stdc.string : memset;
2754 memset(mCovers+x, cover, num);
2755 if (x == mLastX+1) {
2756 (*mCurCount) += cast(ushort)num;
2758 *++mCurCount = cast(ushort)num;
2759 *++mCurStartPtr = mCovers+x;
2766 void addCell (int x, int y, uint cover) {
2768 mCovers[x] = cast(ubyte)cover;
2769 if (x == mLastX+1) {
2773 *++mCurStartPtr = mCovers+x;
2780 @property bool isReady (int y) const pure { pragma(inline, true); return (mNumSpans && (y^mLastY)); }
2781 @property int baseX () const pure { pragma(inline, true); return mMinX+mDX; }
2782 @property int y () const pure { pragma(inline, true); return mLastY+mDY; }
2783 @property uint numSpans () const pure { pragma(inline, true); return mNumSpans; }
2787 public template isGoodSpan(T) {
2788 static if (is(T == struct)) {
2789 enum isGoodSpan = is(typeof((){
2791 span.render(cast(ubyte*)0x29a, cast(int)0x29a, cast(uint)0x29a, cast(const(ubyte)*)0x29a, Color.red);
2792 span.hline(cast(ubyte*)0x29a, cast(int)0x29a, cast(uint)0x29a, Color.red);
2793 Color c = span.get(cast(const(ubyte)*)0x29a, cast(int)0x29a);
2794 // we should be able to copy it
2798 enum isGoodSpan = false;
2802 public struct Renderer(Span) if (isGoodSpan!Span) {
2804 RenderingBuffer mRBuf;
2807 public nothrow @trusted @nogc:
2808 this (ubyte* abuf, uint awidth, uint aheight, int astride) { mRBuf.attach(abuf, awidth, aheight, astride); }
2810 void attach (ubyte* abuf, uint awidth, uint aheight, int astride) { mRBuf.attach(abuf, awidth, aheight, astride); }
2812 void clear (in Color c) {
2813 foreach (immutable uint y; 0..mRBuf.height) {
2814 mSpan.hline(mRBuf.row(y), 0, mRBuf.width, c);
2818 void setPixel (int x, int y, in Color c) {
2819 if (mRBuf.inbox(x, y)) {
2820 mSpan.hline(mRBuf.row(y), x, 1, c);
2824 Color getPixel (int x, int y) const pure { pragma(inline, true); return (mRBuf.inbox(x, y) ? mSpan.get(mRBuf.row(y), x) : Color.transparent); }
2826 @property int width () const pure { pragma(inline, true); return mRBuf.width; }
2827 @property int height () const pure { pragma(inline, true); return mRBuf.height; }
2829 void render (in ref ScanLine sl, in Color c) {
2830 if (sl.y < 0 || sl.y >= cast(int)mRBuf.height) return;
2831 uint numSpans = sl.numSpans;
2832 int baseX = sl.baseX;
2833 ubyte* row = mRBuf.row(sl.y);
2834 auto span = sl.iterator;
2836 int x = span.next+baseX;
2837 const(ubyte)* covers = span.covers;
2838 int numPix = span.numPix;
2841 if (numPix <= 0) continue;
2845 if (x+numPix >= cast(int)mRBuf.width) {
2846 numPix = mRBuf.width-x;
2847 if (numPix <= 0) continue;
2849 mSpan.render(row, x, numPix, covers, c);
2850 } while (--numSpans);
2853 inout(ubyte)[] opSlice () inout pure { pragma(inline, true); return mRBuf[]; }
2857 /* *****************************************************************************
2858 These constants determine the subpixel accuracy, to be more precise,
2859 the number of bits of the fractional part of the coordinates.
2860 The possible coordinate capacity in bits can be calculated by formula:
2861 sizeof(int) * 8 - PolyBaseShift * 2, i.e, for 32-bit integers and
2862 8-bits fractional part the capacity is 16 bits or [-32768...32767].
2863 ***************************************************************************** */
2866 PolyBaseSize = cast(uint)(1<<PolyBaseShift),
2867 PolyBaseMask = cast(uint)(PolyBaseSize-1),
2871 int polyCoord (in double c) pure nothrow @safe @nogc { pragma(inline, true); return cast(int)(c*PolyBaseSize); }
2882 public nothrow @trusted @nogc:
2883 this (int cx, int cy, int c, int a) {
2884 pragma(inline, true);
2887 packedCoord = (cy<<16)+cx;
2892 void setCover (int c, int a) {
2893 pragma(inline, true);
2898 void addCover (int c, int a) {
2899 pragma(inline, true);
2904 void setCoord (int cx, int cy) {
2905 pragma(inline, true);
2908 packedCoord = (cy<<16)+cx;
2911 void set (int cx, int cy, int c, int a) {
2912 pragma(inline, true);
2915 packedCoord = (cy<<16)+cx;
2922 // An internal class that implements the main rasterization algorithm. Used in the rasterizer. Should not be used direcly.
2926 CellBlockShift = 12U,
2927 CellBlockSize = cast(uint)(1<<CellBlockShift),
2928 CellBlockMask = cast(uint)(CellBlockSize-1),
2929 CellBlockPool = 256U,
2930 CellBlockLimit = 1024U,
2933 enum QSortThreshold = 9;
2947 Cell** mSortedCells;
2949 Cell mCurCell = Cell(0x7fff, 0x7fff, 0, 0);
2954 int mMinX = 0x7fffffff;
2955 int mMinY = 0x7fffffff;
2956 int mMaxX = -0x7fffffff;
2957 int mMaxY = -0x7fffffff;
2958 uint mFlags = SortRequired;
2960 public nothrow @trusted @nogc:
2961 @disable this (this); // no copies
2964 import core.stdc.stdlib : free;
2967 Cell** ptr = mCells+mNumBlocks-1;
2968 while (mNumBlocks--) {
2979 mCurCell.set(0x7fff, 0x7fff, 0, 0);
2980 mFlags |= SortRequired;
2981 mFlags &= ~NotClosed;
2984 mMaxX = -0x7fffffff;
2985 mMaxY = -0x7fffffff;
2988 void moveTo (int x, int y) {
2989 if ((mFlags&SortRequired) == 0) reset();
2990 if (mFlags&NotClosed) lineTo(mCloseX, mCloseY);
2991 setCurCell(x>>PolyBaseShift, y>>PolyBaseShift);
2992 mCloseX = mCurX = x;
2993 mCloseY = mCurY = y;
2996 void lineTo (int x, int y) {
2997 if ((mFlags&SortRequired) && ((mCurX^x)|(mCurY^y))) {
2998 int c = mCurX>>PolyBaseShift;
2999 if (c < mMinX) mMinX = c;
3001 if (c > mMaxX) mMaxX = c;
3003 c = x>>PolyBaseShift;
3004 if (c < mMinX) mMinX = c;
3006 if (c > mMaxX) mMaxX = c;
3008 renderLine(mCurX, mCurY, x, y);
3011 mFlags |= NotClosed;
3015 @property double curX () const pure { pragma(inline, true); return cast(double)mCurX/cast(double)PolyBaseSize; }
3016 @property double curY () const pure { pragma(inline, true); return cast(double)mCurY/cast(double)PolyBaseSize; }
3018 @property int minX () const pure { pragma(inline, true); return mMinX; }
3019 @property int minY () const pure { pragma(inline, true); return mMinY; }
3020 @property int maxX () const pure { pragma(inline, true); return mMaxX; }
3021 @property int maxY () const pure { pragma(inline, true); return mMaxY; }
3023 @property uint numCells () const pure { pragma(inline, true); return mNumCells; }
3025 const(Cell)** cells () {
3026 if (mFlags&NotClosed) {
3027 lineTo(mCloseX, mCloseY);
3028 mFlags &= ~NotClosed;
3030 // perform sort only the first time
3031 if (mFlags&SortRequired) {
3033 if (mNumCells == 0) return null;
3035 mFlags &= ~SortRequired;
3037 return cast(const(Cell)**)mSortedCells;
3041 void allocateBlock () {
3042 import core.stdc.stdlib : realloc;
3043 if (mCurBlock >= mNumBlocks) {
3044 import core.stdc.string : memset;
3045 if (mNumBlocks >= mMaxBlocks) {
3046 Cell** newCells = cast(Cell**)realloc(mCells, (mMaxBlocks+CellBlockPool)*(Cell*).sizeof);
3047 if (newCells is null) assert(0, "out of memory");
3049 mMaxBlocks += CellBlockPool;
3051 auto cc = cast(Cell*)realloc(null, Cell.sizeof*CellBlockSize);
3052 if (cc is null) assert(0, "out of memory");
3053 memset(cc, 0, Cell.sizeof*CellBlockSize);
3054 foreach (ref c; cc[0..CellBlockSize]) c = Cell.init;
3055 mCells[mNumBlocks++] = cc;
3057 mCurCellPtr = mCells[mCurBlock++];
3060 void addCurCell () {
3061 if (mCurCell.area|mCurCell.cover) {
3062 if ((mNumCells&CellBlockMask) == 0) {
3063 if (mNumBlocks >= CellBlockLimit) return;
3066 *mCurCellPtr++ = mCurCell;
3071 void setCurCell (int x, int y) {
3072 if (mCurCell.packedCoord != (y<<16)+x) {
3074 mCurCell.set(x, y, 0, 0);
3078 void renderScanLine (int ey, int x1, int y1, int x2, int y2) {
3079 int ex1 = x1>>PolyBaseShift;
3080 int ex2 = x2>>PolyBaseShift;
3081 int fx1 = x1&PolyBaseMask;
3082 int fx2 = x2&PolyBaseMask;
3084 int delta, p, first, dx;
3085 int incr, lift, mod, rem;
3087 // trivial case; happens often
3089 setCurCell(ex2, ey);
3093 // everything is located in a single cell: that is easy!
3096 mCurCell.addCover(delta, (fx1+fx2)*delta);
3100 // ok, we'll have to render a run of adjacent cells on the same scanline...
3101 p = (PolyBaseSize-fx1)*(y2-y1);
3102 first = PolyBaseSize;
3122 mCurCell.addCover(delta, (fx1+first)*delta);
3125 setCurCell(ex1, ey);
3129 p = PolyBaseSize*(y2-y1+delta);
3140 while (ex1 != ex2) {
3147 mCurCell.addCover(delta, PolyBaseSize*delta);
3150 setCurCell(ex1, ey);
3155 mCurCell.addCover(delta, (fx2+PolyBaseSize-first)*delta);
3158 void renderLine (int x1, int y1, int x2, int y2) {
3159 int ey1 = y1>>PolyBaseShift;
3160 int ey2 = y2>>PolyBaseShift;
3161 int fy1 = y1&PolyBaseMask;
3162 int fy2 = y2&PolyBaseMask;
3164 int dx, dy, xFrom, xTo;
3165 int p, rem, mod, lift, delta, first, incr;
3167 if (ey1 < mMinY) mMinY = ey1;
3168 if (ey1+1 > mMaxY) mMaxY = ey1+1;
3169 if (ey2 < mMinY) mMinY = ey2;
3170 if (ey2+1 > mMaxY) mMaxY = ey2+1;
3175 // everything is on a single scanline
3177 renderScanLine(ey1, x1, fy1, x2, fy2);
3181 // vertical line: we have to calculate start and end cells,
3182 // and then the common values of the area and coverage for
3183 // all cells of the line. we know exactly there's only one
3184 // cell, so, we don't have to call renderScanLine().
3187 int ex = x1>>PolyBaseShift;
3188 int twoFx = (x1-(ex<<PolyBaseShift))<<1;
3191 first = PolyBaseSize;
3199 //renderScanLine(ey1, xFrom, fy1, xFrom, first);
3201 mCurCell.addCover(delta, twoFx*delta);
3204 setCurCell(ex, ey1);
3206 delta = first+first-PolyBaseSize;
3208 while (ey1 != ey2) {
3209 //renderScanLine(ey1, xFrom, PolyBaseSize - first, xFrom, first);
3210 mCurCell.setCover(delta, area);
3212 setCurCell(ex, ey1);
3214 //renderScanLine(ey1, xFrom, PolyBaseSize - first, xFrom, fy2);
3215 delta = fy2-PolyBaseSize+first;
3216 mCurCell.addCover(delta, twoFx*delta);
3220 // ok, we have to render several scanlines
3221 p = (PolyBaseSize-fy1)*dx;
3222 first = PolyBaseSize;
3240 renderScanLine(ey1, x1, fy1, xFrom, first);
3243 setCurCell(xFrom>>PolyBaseShift, ey1);
3246 p = PolyBaseSize*dx;
3256 while (ey1 != ey2) {
3265 renderScanLine(ey1, xFrom, PolyBaseSize-first, xTo, first);
3269 setCurCell(xFrom>>PolyBaseShift, ey1);
3273 renderScanLine(ey1, xFrom, PolyBaseSize-first, x2, fy2);
3276 static void qsortCells (Cell** start, uint num) {
3277 static void swapCells (Cell** a, Cell** b) nothrow @trusted @nogc {
3278 pragma(inline, true);
3284 static bool lessThan (Cell** a, Cell** b) nothrow @trusted @nogc { pragma(inline, true); return ((**a).packedCoord < (**b).packedCoord); }
3286 Cell**[80] stack = void;
3296 int len = cast(int)(limit-base);
3302 if (len > QSortThreshold) {
3303 // we use base + len/2 as the pivot
3305 swapCells(base, pivot);
3310 // now ensure that *i <= *base <= *j
3311 if (lessThan(j, i)) swapCells(i, j);
3312 if (lessThan(base, i)) swapCells(base, i);
3313 if (lessThan(j, base)) swapCells(base, j);
3316 do { ++i; } while (lessThan(i, base));
3317 do { --j; } while (lessThan(base, j));
3324 // now, push the largest sub-array
3325 if (j-base > limit-i) {
3336 // the sub-array is small, perform insertion sort
3339 for (; i < limit; j = i, ++i) {
3340 for (; lessThan(j+1, j); --j) {
3342 if (j == base) break;
3345 if (top > stack.ptr) {
3357 if (mNumCells == 0) return;
3359 if (mNumCells > mSortedSize) {
3360 import core.stdc.stdlib: realloc;
3361 mSortedSize = mNumCells;
3362 mSortedCells = cast(Cell**)realloc(mSortedCells, (mNumCells+1)*(Cell*).sizeof);
3365 Cell** sortedPtr = mSortedCells;
3366 Cell** blockPtr = mCells;
3369 uint nb = mNumCells>>CellBlockShift;
3373 cellPtr = *blockPtr++;
3375 while (i--) *sortedPtr++ = cellPtr++;
3378 cellPtr = *blockPtr++;
3379 i = mNumCells&CellBlockMask;
3380 while (i--) *sortedPtr++ = cellPtr++;
3381 mSortedCells[mNumCells] = null;
3382 qsortCells(mSortedCells, mNumCells);
3387 /* *****************************************************************************
3388 Polygon rasterizer that is used to render filled polygons with
3389 high-quality Anti-Aliasing. Internally, by default, the class uses
3390 integer coordinates in format 24.8, i.e. 24 bits for integer part
3391 and 8 bits for fractional - see PolyBaseShift. This class can be
3392 used in the following way:
3394 1. fillRule = FillRule.EvenOdd; // optional
3396 2. gamma() - optional.
3400 4. moveTo(x, y) / lineTo(x, y) - make the polygon. One can create
3401 more than one contour, but each contour must consist of at least 3
3402 vertices, i.e. moveTo(x1, y1); lineTo(x2, y2); lineTo(x3, y3);
3403 is the absolute minimum of vertices that define a triangle.
3404 The algorithm does not check either the number of vertices nor
3405 coincidence of their coordinates, but in the worst case it just
3406 won't draw anything.
3407 The orger of the vertices (clockwise or counterclockwise)
3408 is important when using the non-zero filling rule (FillNonZero).
3409 In this case the vertex order of all the contours must be the same
3410 if you want your intersecting polygons to be without "holes".
3411 You actually can use different vertices order. If the contours do not
3412 intersect each other the order is not important anyway. If they do,
3413 contours with the same vertex order will be rendered without "holes"
3414 while the intersecting contours with different orders will have "holes".
3416 fillRule() and gamma() can be called anytime before "sweeping".
3417 ***************************************************************************** */
3418 public struct Rasterizer {
3421 AAShift = ScanLine.AAShift,
3436 FillRule mFillingRule = FillRule.NonZero;
3437 ubyte[256] mGamma = DefaultGamma[];
3439 public nothrow @trusted @nogc:
3440 void reset () { mOutline.reset(); }
3442 @property FillRule fillRule () const pure { pragma(inline, true); return mFillingRule; }
3443 @property void fillRule (FillRule v) { pragma(inline, true); mFillingRule = v; }
3445 void gamma (in double g) {
3446 foreach (immutable uint i; 0..256) {
3447 import std.math : pow;
3448 mGamma.ptr[i] = cast(ubyte)(pow(cast(double)i/255.0, g)*255.0);
3452 void gamma (const(ubyte)[] g) {
3453 if (g.length != 256) assert(0, "invalid gamma array");
3454 mGamma[] = g[0..256];
3457 void moveTo (int x, int y) { mOutline.moveTo(x, y); }
3458 void lineTo (int x, int y) { mOutline.lineTo(x, y); }
3460 void moveTo (in double x, in double y) { mOutline.moveTo(polyCoord(x), polyCoord(y)); }
3461 void lineTo (in double x, in double y) { mOutline.lineTo(polyCoord(x), polyCoord(y)); }
3463 @property double curX () const pure { pragma(inline, true); return mOutline.curX; }
3464 @property double curY () const pure { pragma(inline, true); return mOutline.curY; }
3466 @property int minX () const pure { pragma(inline, true); return mOutline.minX; }
3467 @property int minY () const pure { pragma(inline, true); return mOutline.minY; }
3468 @property int maxX () const pure { pragma(inline, true); return mOutline.maxX; }
3469 @property int maxY () const pure { pragma(inline, true); return mOutline.maxY; }
3471 uint calculateAlpha (int area) const pure {
3472 int cover = area>>(PolyBaseShift*2+1-AAShift);
3473 if (cover < 0) cover = -cover;
3474 if (mFillingRule == FillRule.EvenOdd) {
3476 if (cover > AANum) cover = AA2Num-cover;
3478 if (cover > AAMask) cover = AAMask;
3482 void render(RT) (ref RT r, in Color c, int dx=0, int dy=0) if (is(RT : Renderer!ST, ST)) {
3483 const(Cell)** cells = mOutline.cells();
3484 if (mOutline.numCells() == 0) return;
3491 mScanline.reset(mOutline.minX(), mOutline.maxX(), dx, dy);
3494 const(Cell)* curCell = *cells++;
3496 const(Cell)* startCell = curCell;
3498 int coord = curCell.packedCoord;
3502 area = startCell.area;
3503 cover += startCell.cover;
3505 // accumulate all start cells
3506 while ((curCell = *cells++) !is null) {
3507 if (curCell.packedCoord != coord) break;
3508 area += curCell.area;
3509 cover += curCell.cover;
3513 alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area);
3515 if (mScanline.isReady(y)) {
3516 r.render(mScanline, c);
3517 mScanline.resetSpans();
3519 mScanline.addCell(x, y, mGamma[alpha]);
3524 if (!curCell) break;
3526 if (curCell.x > x) {
3527 alpha = calculateAlpha(cover<<(PolyBaseShift+1));
3529 if (mScanline.isReady(y)) {
3530 r.render(mScanline, c);
3531 mScanline.resetSpans();
3533 mScanline.addSpan(x, y, curCell.x-x, mGamma[alpha]);
3538 if (mScanline.numSpans) r.render(mScanline, c);
3541 bool hitTest (int tx, int ty) {
3542 const(Cell)** cells = mOutline.cells();
3543 if (mOutline.numCells == 0) return false;
3551 const(Cell)* curCell = *cells++;
3553 const(Cell)* startCell = curCell;
3555 int coord = curCell.packedCoord;
3559 if (y > ty) return false;
3561 area = startCell.area;
3562 cover += startCell.cover;
3564 while ((curCell = *cells++) !is null) {
3565 if (curCell.packedCoord != coord) break;
3566 area += curCell.area;
3567 cover += curCell.cover;
3571 alpha = calculateAlpha((cover<<(PolyBaseShift+1))-area);
3573 if (tx == x && ty == y) return true;
3578 if (!curCell) break;
3580 if (curCell.x > x) {
3581 alpha = calculateAlpha(cover<<(PolyBaseShift+1));
3583 if (ty == y && tx >= x && tx <= curCell.x) return true;
3591 static immutable ubyte[256] DefaultGamma = [
3592 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 7, 7, 8, 8,
3593 9, 10, 10, 11, 11, 12, 13, 13, 14, 14, 15, 16, 16, 17, 18, 18,
3594 19, 19, 20, 21, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 27, 28,
3595 29, 29, 30, 30, 31, 32, 32, 33, 34, 34, 35, 36, 36, 37, 37, 38,
3596 39, 39, 40, 41, 41, 42, 43, 43, 44, 45, 45, 46, 47, 47, 48, 49,
3597 49, 50, 51, 51, 52, 53, 53, 54, 55, 55, 56, 57, 57, 58, 59, 60,
3598 60, 61, 62, 62, 63, 64, 65, 65, 66, 67, 68, 68, 69, 70, 71, 71,
3599 72, 73, 74, 74, 75, 76, 77, 78, 78, 79, 80, 81, 82, 83, 83, 84,
3600 85, 86, 87, 88, 89, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
3601 100,101,101,102,103,104,105,106,107,108,109,110,111,112,114,115,
3602 116,117,118,119,120,121,122,123,124,126,127,128,129,130,131,132,
3603 134,135,136,137,139,140,141,142,144,145,146,147,149,150,151,153,
3604 154,155,157,158,159,161,162,164,165,166,168,169,171,172,174,175,
3605 177,178,180,181,183,184,186,188,189,191,192,194,195,197,199,200,
3606 202,204,205,207,209,210,212,214,215,217,219,220,222,224,225,227,
3607 229,230,232,234,236,237,239,241,242,244,246,248,249,251,253,255
3612 // ////////////////////////////////////////////////////////////////////////// //
3613 // X11 image: "bgra"; TrueColorImage: "rgba"
3614 public struct SimpleSpan(string mode)
3615 if (mode == "bgra" || mode == "rgba" || mode == "x11" || mode == "X11" || mode == "arsd" || mode == "bgr" || mode == "rgb")
3617 static if (mode == "bgra" || mode == "x11" || mode == "X11") {
3619 enum Is32Bit = true;
3620 } else static if (mode == "rgba" || mode == "arsd") {
3621 enum IsBGRA = false;
3622 enum Is32Bit = true;
3623 } else static if (mode == "bgr") {
3625 enum Is32Bit = false;
3626 } else static if (mode == "rgb") {
3627 enum IsBGRA = false;
3628 enum Is32Bit = false;
3630 static assert(0, "invalid mode");
3633 static void render (ubyte* ptr, int x, uint count, const(ubyte)* covers, in Color c) {
3634 static if (Is32Bit) {
3635 ubyte* p = ptr+(x<<2);
3637 ubyte* p = ptr+x+x+x;
3640 int alpha = (*covers++)*c.a;
3641 static if (IsBGRA) {
3645 static if (Is32Bit) int a = p[3];
3646 *p++ = cast(ubyte)((((c.b-b)*alpha)+(b<<16))>>16);
3647 *p++ = cast(ubyte)((((c.g-g)*alpha)+(g<<16))>>16);
3648 *p++ = cast(ubyte)((((c.r-r)*alpha)+(r<<16))>>16);
3649 static if (Is32Bit) *p++ = cast(ubyte)((((c.a-a)*alpha)+(a<<16))>>16);
3654 static if (Is32Bit) int a = p[3];
3655 *p++ = cast(ubyte)((((c.r-r)*alpha)+(r<<16))>>16);
3656 *p++ = cast(ubyte)((((c.g-g)*alpha)+(g<<16))>>16);
3657 *p++ = cast(ubyte)((((c.b-b)*alpha)+(b<<16))>>16);
3658 static if (Is32Bit) *p++ = cast(ubyte)((((c.a-a)*alpha)+(a<<16))>>16);
3663 static void hline (ubyte* ptr, int x, uint count, in Color c) {
3664 static if (!IsBGRA && Is32Bit) {
3666 uint* p = cast(uint*)(ptr+(x<<2));
3667 p[0..count] = c.asUint;
3669 static if (Is32Bit) {
3670 ubyte* p = ptr+(x<<2);
3672 ubyte* p = ptr+x+x+x;
3675 static if (IsBGRA) {
3684 static if (Is32Bit) *p++ = c.a;
3689 static Color get (const(ubyte)* ptr, int x) {
3690 static if (Is32Bit) {
3691 const(ubyte)* p = ptr+(x<<2);
3693 const(ubyte)* p = ptr+x+x+x;
3695 static if (IsBGRA) {
3696 static if (Is32Bit) {
3697 return Color(p[2], p[1], p[0], p[3]);
3699 return Color(p[2], p[1], p[0], 255);
3702 static if (Is32Bit) {
3703 return Color(p[0], p[1], p[2], p[3]);
3705 return Color(p[0], p[1], p[2]);
3713 // ////////////////////////////////////////////////////////////////////////// //
3715 version(linux) final class SdpyDrawVBuf : SdpyDrawBase {
3720 // must be overriden
3721 override Color getpix (int x, int y) {
3722 pragma(inline, true);
3723 return XlibImageTC.img2c(vbuf.data[y*vbuf.width+x]);
3726 override void putpix (int x, int y, Color col) {
3727 uint* dp = vbuf.data+y*vbuf.width+x;
3728 if (col.a == 255) *dp = XlibImageTC.c2img(col)|0xff_000000; else *dp = blendU32(*dp, XlibImageTC.c2img(col)|(col.a<<24));
3732 override void hline (int x, int y, int len, Color col) {
3733 uint* dp = vbuf.data+y*vbuf.width+x;
3734 uint uc = XlibImageTC.c2img(col);
3737 foreach (immutable _; 0..len) *dp++ = uc;
3740 foreach (immutable _; 0..len) { *dp = blendU32(*dp, uc); ++dp; }
3745 this (XImageTC img) {
3747 super(img.width, img.height);
3750 override TrueColorImage getBuffer () {
3751 auto img = new TrueColorImage(vbuf.width, vbuf.height);
3752 const(uint)* sp = cast(const(uint)*)vbuf.data;
3753 auto dp = img.imageData.colors.ptr;
3754 foreach (immutable y; 0..vbuf.height) {
3755 foreach (immutable x; 0..vbuf.width) {
3756 *dp++ = XlibImageTC.img2c(*sp++);
3762 final @property XImageTC imagebuf () pure nothrow @safe @nogc { pragma(inline, true); return vbuf; }
3764 final void cls (Color clr) {
3765 import core.stdc.string : memset;
3766 if (!vbuf.valid) return;
3767 if (clr.r == 0 && clr.g == 0 && clr.b == 0) {
3768 memset(vbuf.data, 0, vbuf.width*vbuf.height*uint.sizeof);
3770 drawRect!true(0, 0, vbuf.width, vbuf.height);
3774 void blitFrom (DFImage src, int x0, int y0, int subalpha=-1, int cx0=0, int cy0=0, int cx1=int.max, int cy1=int.max) {
3775 if (src is null || !src.valid || !vbuf.valid) return;
3776 if (cx1 >= vbuf.width) cx1 = vbuf.width-1;
3777 if (cy1 >= vbuf.height) cy1 = vbuf.height-1;
3778 if (cx0 < 0) cx0 = 0;
3779 if (cy0 < 0) cy0 = 0;
3780 if (cx1 < cx0 || cy1 < cy0 || cx1 < 0 || cy1 < 0 || cx0 >= vbuf.width || cy0 >= vbuf.height) return; // nothing to do here
3782 void doBlit(bool doSrcAlpha, bool doSubAlpha) (int x, int y, int xofs, int yofs, int wdt, int hgt, int subalpha=0) {
3783 auto sc = cast(const(uint)*)src.data.ptr;
3784 auto dc = vbuf.data;
3785 sc += yofs*src.width+xofs;
3786 dc += y*vbuf.width+x;
3787 foreach (immutable dy; 0..hgt) {
3788 static if (!doSubAlpha && !doSrcAlpha) {
3790 import core.stdc.string : memcpy;
3791 memcpy(dc, sc, wdt*uint.sizeof);
3795 foreach (immutable dx; 0..wdt) {
3796 static if (doSubAlpha) {
3797 static assert(!doSrcAlpha);
3798 *dcl = XlibImageTC.icRGB(
3799 XlibImageTC.icR(*dcl)+XlibImageTC.icR(*scl)*(255-subalpha)/255,
3800 XlibImageTC.icG(*dcl)+XlibImageTC.icG(*scl)*(255-subalpha)/255,
3801 XlibImageTC.icB(*dcl)+XlibImageTC.icB(*scl)*(255-subalpha)/255,
3804 static assert(doSrcAlpha);
3805 if (XlibImageTC.icA(*scl) == 255) {
3807 } else if (XlibImageTC.icA(*scl)) {
3808 *dcl = (*dcl).blendU32(*scl);
3820 int swdt = src.width, shgt = src.height, xofs = 0, yofs = 0, x = x0, y = y0;
3821 if (!GxRect(cx0, cy0, cx1-cx0+1, cy1-cy0+1).clipHVStripes(x, y, swdt, shgt, &xofs, &yofs)) return; // nothing to do here
3822 if (!src.hasAlpha && subalpha < 0) {
3823 doBlit!(false, false)(x, y, xofs, yofs, swdt, shgt);
3824 } else if (subalpha >= 0) {
3825 doBlit!(false, true)(x, y, xofs, yofs, swdt, shgt, subalpha);
3826 } else if (src.hasAlpha) {
3827 doBlit!(true, false)(x, y, xofs, yofs, swdt, shgt);
3833 void blendRect (int x0, int y0, int w, int h, Color clr) {
3834 if (clr.a == 0 || !vbuf.valid) return;
3835 if (!GxRect(0, 0, vbuf.width, vbuf.height).clipHVStripes(x0, y0, w, h)) return; // nothing to do here
3836 auto dc = vbuf.data;
3837 dc += y0*vbuf.width+x0;
3839 uint c = XlibImageTC.c2img(clr);
3840 foreach (immutable dy; 0..h) {
3842 foreach (immutable dx; 0..w) *dcl++ = c;
3846 uint c = XlibImageTC.icRGBA(clr.r, clr.g, clr.b, clr.a);
3847 foreach (immutable dy; 0..h) {
3849 foreach (immutable dx; 0..w) {
3850 *dcl = (*dcl).blendU32(c);