4 import arsd
.simpledisplay
;
14 import egfx
.backx
: XlibTCImage
;
19 // ////////////////////////////////////////////////////////////////////////// //
20 // "simple" XImage methods
22 import core
.stdc
.config
: c_long
, c_ulong
;
24 XImage
* xxsimple_create_image (XDisplay
* display
, Visual
* visual
, uint depth
, int format
, int offset
, ubyte* data
, uint width
, uint height
, int bitmap_pad
, int bytes_per_line
) {
25 return XCreateImage(display
, visual
, depth
, format
, offset
, data
, width
, height
, bitmap_pad
, bytes_per_line
);
28 int xxsimple_destroy_image (XImage
* ximg
) {
29 if (ximg
.data
!is null) {
30 import core
.stdc
.stdlib
: free
;
34 ximg
.width
= ximg
.height
= 0;
38 c_ulong
xxsimple_get_pixel (XImage
* ximg
, int x
, int y
) {
39 if (ximg
.data
is null) return 0;
40 if (x
< 0 || y
< 0 || x
>= ximg
.width || y
>= ximg
.height
) return 0;
41 auto buf
= cast(const(uint)*)ximg
.data
;
42 return buf
[y
*ximg
.width
+x
];
45 int xxsimple_put_pixel (XImage
* ximg
, int x
, int y
, c_ulong clr
) {
46 if (ximg
.data
is null) return 0;
47 if (x
< 0 || y
< 0 || x
>= ximg
.width || y
>= ximg
.height
) return 0;
48 auto buf
= cast(uint*)ximg
.data
;
49 buf
[y
*ximg
.width
+x
] = cast(uint)clr
;
53 XImage
* xxsimple_sub_image (XImage
* ximg
, int x
, int y
, uint wdt
, uint hgt
) {
54 import core
.stdc
.stdlib
: malloc
, free
;
55 import core
.stdc
.string
: memset
;
56 if (wdt
< 1 || hgt
< 1) return null;
57 XImage
* res
= cast(XImage
*)malloc(XImage
.sizeof
);
58 if (res
is null) return null;
59 memset(res
, 0, XImage
.sizeof
);
60 ximageCreateSimple(*res
, wdt
, hgt
);
61 foreach (immutable int dy
; y
..y
+hgt
) {
62 foreach (immutable int dx
; x
..x
+wdt
) {
64 if (dx
>= 0 && dy
>= 0 && dx
< ximg
.width
&& dy
< ximg
.height
) clr
= cast(uint)ximg
.f
.get_pixel(ximg
, dx
, dy
);
65 res
.f
.put_pixel(res
, dx
-x
, dy
-y
, clr
);
71 int xxsimple_add_pixel (XImage
* ximg
, c_long clr
) {
72 if (ximg
.data
is null) return 0;
73 auto buf
= cast(uint*)ximg
.data
;
74 foreach (ref uint v
; buf
[0..ximg
.width
*ximg
.height
]) v
+= cast(uint)clr
;
80 // ////////////////////////////////////////////////////////////////////////// //
81 // create "simple" XImage with allocated buffer
82 private void ximageCreateSimple (ref XImage handle
, int width
, int height
) {
83 import core
.stdc
.stdlib
: malloc
;
85 if (width
< 1) width
= 1;
86 if (height
< 1) height
= 1;
88 auto data
= malloc(width
*height
*4);
89 if (data
is null) assert(0, "out of memory");
92 handle
.height
= height
;
94 handle
.format
= ImageFormat
.ZPixmap
;
96 handle
.byte_order
= 0;
97 handle
.bitmap_unit
= 0;
98 handle
.bitmap_bit_order
= 0;
99 handle
.bitmap_pad
= 0;
101 handle
.bytes_per_line
= 0;
102 handle
.bits_per_pixel
= 0; // THIS MATTERS!
104 handle
.green_mask
= 0;
105 handle
.blue_mask
= 0;
107 handle
.obdata
= null;
108 handle
.f
.create_image
= &xxsimple_create_image
;
109 handle
.f
.destroy_image
= &xxsimple_destroy_image
;
110 handle
.f
.get_pixel
= &xxsimple_get_pixel
;
111 handle
.f
.put_pixel
= &xxsimple_put_pixel
;
112 handle
.f
.sub_image
= &xxsimple_sub_image
;
113 handle
.f
.add_pixel
= &xxsimple_add_pixel
;
117 // ////////////////////////////////////////////////////////////////////////// //
118 public struct XlibImage
{
121 @disable this (this);
123 this (MemoryImage aimg
) {
124 if (aimg
is null || aimg
.width
< 1 || aimg
.height
< 1) throw new Exception("can't create xlib image from empty MemoryImage");
128 this (int wdt
, int hgt
) {
129 if (wdt
< 1 || hgt
< 1) throw new Exception("invalid xlib image");
130 create(new TrueColorImage(wdt
, hgt
));
133 ~this () { dispose(); }
135 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline
, true); return (handle
.obdata
!is null); }
137 @property int width () const pure nothrow @trusted @nogc { pragma(inline
, true); return handle
.width
; }
138 @property int height () const pure nothrow @trusted @nogc { pragma(inline
, true); return handle
.height
; }
140 void setup (MemoryImage aimg
) {
142 if (aimg
is null || aimg
.width
< 1 || aimg
.height
< 1) throw new Exception("can't create xlib image from empty MemoryImage");
146 private void create (MemoryImage ximg
) {
147 handle
.width
= ximg
.width
;
148 handle
.height
= ximg
.height
;
150 handle
.format
= ImageFormat
.ZPixmap
;
152 handle
.byte_order
= 0;
153 handle
.bitmap_unit
= 0;
154 handle
.bitmap_bit_order
= 0;
155 handle
.bitmap_pad
= 0;
157 handle
.bytes_per_line
= 0;
158 handle
.bits_per_pixel
= 0; // THIS MATTERS!
160 handle
.green_mask
= 0;
161 handle
.blue_mask
= 0;
163 handle
.obdata
= *cast(void**)&ximg
;
164 handle
.f
.create_image
= &xx_create_image
;
165 handle
.f
.destroy_image
= &xx_destroy_image
;
166 handle
.f
.get_pixel
= &xx_get_pixel
;
167 handle
.f
.put_pixel
= &xx_put_pixel
;
168 handle
.f
.sub_image
= &xx_sub_image
;
169 handle
.f
.add_pixel
= &xx_add_pixel
;
173 // note: this calls free(rawData) for us
174 if (handle
.obdata
!is null) {
175 XDestroyImage(&handle
);
176 handle
.obdata
= null;
180 // blit to window buffer
181 final void blitAt (SimpleWindow w
, int destx
, int desty
) {
182 blitRect(w
, destx
, desty
, GxRect(0, 0, width
, height
));
185 // blit to window buffer
186 final void blitRect (SimpleWindow w
, int destx
, int desty
, GxRect srect
) {
187 if (w
is null || handle
.obdata
is null || w
.closed
) return;
188 XPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.buffer
, w
.impl
.gc
, &handle
, srect
.x0
, srect
.y0
, destx
, desty
, srect
.width
, srect
.height
);
192 final void blitAtWin (SimpleWindow w
, int destx
, int desty
) {
193 blitRectWin(w
, destx
, desty
, GxRect(0, 0, width
, height
));
197 final void blitRectWin (SimpleWindow w
, int destx
, int desty
, GxRect srect
) {
198 if (w
is null || handle
.obdata
is null || w
.closed
) return;
199 XPutImage(w
.impl
.display
, cast(Drawable
)w
.impl
.window
, w
.impl
.gc
, &handle
, srect
.x0
, srect
.y0
, destx
, desty
, srect
.width
, srect
.height
);
202 static private extern(C
):
203 import core
.stdc
.config
: c_long
, c_ulong
;
205 XImage
* xx_create_image (XDisplay
* display
, Visual
* visual
, uint depth
, int format
, int offset
, ubyte* data
, uint width
, uint height
, int bitmap_pad
, int bytes_per_line
) {
206 return XCreateImage(display
, visual
, depth
, format
, offset
, data
, width
, height
, bitmap_pad
, bytes_per_line
);
209 int xx_destroy_image (XImage
* ximg
) {
210 MemoryImage img
= *cast(MemoryImage
*)&ximg
.obdata
;
211 if (img
!is null) ximg
.obdata
= null;
212 ximg
.width
= ximg
.height
= 0;
216 c_ulong
xx_get_pixel (XImage
* ximg
, int x
, int y
) {
217 MemoryImage img
= *cast(MemoryImage
*)&ximg
.obdata
;
218 if (img
is null) return 0;
219 return img
.getPixel(x
, y
).c2img
;
222 int xx_put_pixel (XImage
* ximg
, int x
, int y
, c_ulong clr
) {
223 MemoryImage img
= *cast(MemoryImage
*)&ximg
.obdata
;
224 if (img
!is null && x
>= 0 && y
>= 0 && x
< img
.width
&& y
< img
.height
) img
.setPixel(x
, y
, img2c(cast(uint)clr
));
228 XImage
* xx_sub_image (XImage
* ximg
, int x
, int y
, uint wdt
, uint hgt
) {
229 return xxsimple_sub_image(ximg
, x
, y
, wdt
, hgt
);
232 int xx_add_pixel (XImage
* ximg
, c_long clr
) {
233 //assert(0, "xx_add_pixel: alas!");
239 // ////////////////////////////////////////////////////////////////////////// //
240 version(custom_img
) {
241 __gshared XlibImage xlimg
;
243 __gshared XlibTCImage xlimg
;
247 // ////////////////////////////////////////////////////////////////////////// //
249 public struct EPixmapImpl {
251 private int mWidth, mHeight;
253 this (int wdt, int hgt) {
254 //if (width < 1 || height < 1) throw new Exception("invalid pixmap dimensions");
255 if (wdt < 1) wdt = 1;
256 if (hgt < 1) hgt = 1;
257 if (wdt > 1024) wdt = 1024;
258 if (hgt > 1024) hgt = 1024;
259 xpm = XCreatePixmap(glconCtlWindow.impl.display, cast(Drawable)glconCtlWindow.impl.window, wdt, hgt, 24);
264 this (ref XlibTCImage xtc) {
265 if (!xtc.valid) throw new Exception("can't create pixmap from empty xlib image");
267 int hgt = xtc.height;
268 if (wdt < 1) wdt = 1;
269 if (hgt < 1) hgt = 1;
270 if (wdt > 1024) wdt = 1024;
271 if (hgt > 1024) hgt = 1024;
272 xpm = XCreatePixmap(glconCtlWindow.impl.display, cast(Drawable)glconCtlWindow.impl.window, wdt, hgt, 24);
273 // source x, source y
274 XPutImage(glconCtlWindow.impl.display, cast(Drawable)xpm, glconCtlWindow.impl.gc, xtc.handle, 0, 0, 0, 0, wdt, hgt);
279 @disable this (this);
282 if (glconCtlWindow is null || glconCtlWindow.closed) { xpm = 0; return; }
284 XFreePixmap(glconCtlWindow.impl.display, xpm);
289 @property bool valid () const pure nothrow @trusted @nogc { pragma(inline, true); return (xpm != 0); }
291 @property int width () const pure nothrow @trusted @nogc { pragma(inline, true); return mWidth; }
292 @property int height () const pure nothrow @trusted @nogc { pragma(inline, true); return mHeight; }
294 // blit to window buffer
295 final void blitAt (SimpleWindow w, int x, int y) {
296 blitRect(w, x, y, GxRect(0, 0, width, height));
299 // blit to window buffer
300 final void blitRect (SimpleWindow w, int destx, int desty, GxRect srect) {
301 if (w is null || !xpm || w.closed) return;
302 XCopyArea(w.impl.display, cast(Drawable)xpm, cast(Drawable)w.impl.buffer, w.impl.gc, srect.x0, srect.y0, srect.width, srect.height, destx, desty);
307 public alias EPixmap = KRC!EPixmapImpl;
311 // ////////////////////////////////////////////////////////////////////////// //
312 public class BmpWindow
: SimpleWindow
{
314 sdpyWindowClass
= "BMPVIEW_WINDOW";
315 super(800, 600, "Bitmap Viewer", OpenGlOptions
.no
, Resizability
.allowResizing
);
318 glconCtlWindow
= this;
319 //glconResize(img.width, img.height);
320 glconCtlWindow
.addEventListener((GLConScreenRepaintEvent evt
) { redraw(true); });
321 glconCtlWindow
.addEventListener((GLConDoConsoleCommandsEvent evt
) {
322 scope(exit
) if (!conQueueEmpty()) glconPostDoConCommands();
323 glconProcessEventMessage();
324 if (isQuitRequested
) { glconCtlWindow
.close(); return; }
328 void redraw (bool forceredraw
) {
330 //xlimg.blitAtWin(this, 5, 8);
331 xlimg
.blitAt(this, 5, 8);
332 glconDrawWindow
= this;
333 glconDrawDirect
= false;
335 XCopyArea(this.impl
.display
, cast(Drawable
)this.impl
.buffer
, cast(Drawable
)this.impl
.window
, this.impl
.gc
, 0, 0, this.width
, this.height
, 0, 0);
339 protected void setupHandlers () {
340 handleExpose
= delegate (int x
, int y
, int wdt
, int hgt
, int eventsLeft
) {
341 if (eventsLeft
== 0) redraw(false);
344 visibilityChanged
= delegate (bool visible
) {
345 //if (visible) createPixmap(); else freePixmap();
347 handleKeyEvent
= delegate (KeyEvent event
) {
348 scope(exit
) if (!conQueueEmpty()) glconPostDoConCommands();
349 if (glconKeyEvent(event
)) { glconPostScreenRepaint(); return; }
350 if (isQuitRequested
) { close(); return; }
351 if ((event
.modifierState
&ModifierState
.numLock
) == 0) {
353 case Key
.Pad0
: event
.key
= Key
.Insert
; break;
354 case Key
.Pad1
: event
.key
= Key
.End
; break;
355 case Key
.Pad2
: event
.key
= Key
.Down
; break;
356 case Key
.Pad3
: event
.key
= Key
.PageDown
; break;
357 case Key
.Pad4
: event
.key
= Key
.Left
; break;
358 //case Key.Pad5: event.key = Key.Insert; break;
359 case Key
.Pad6
: event
.key
= Key
.Right
; break;
360 case Key
.Pad7
: event
.key
= Key
.Home
; break;
361 case Key
.Pad8
: event
.key
= Key
.Up
; break;
362 case Key
.Pad9
: event
.key
= Key
.PageUp
; break;
363 case Key
.PadEnter
: event
.key
= Key
.Enter
; break;
364 case Key
.PadDot
: event
.key
= Key
.Delete
; break;
368 if (event
.key
== Key
.PadEnter
) event
.key
= Key
.Enter
;
371 //conwriteln(event.toStr);
372 if (event
== "C-Q") { close(); return; }
373 if (event
== "Escape") { close(); return; }
377 handleMouseEvent
= delegate (MouseEvent event
) {
378 scope(exit
) if (!conQueueEmpty()) glconPostDoConCommands();
379 if (isQuitRequested
) { close(); return; }
382 handleCharEvent
= delegate (dchar ch
) {
383 scope(exit
) if (!conQueueEmpty()) glconPostDoConCommands();
384 if (glconCharEvent(ch
)) { glconPostScreenRepaint(); return; }
385 if (isQuitRequested
) { close(); return; }
388 windowResized
= delegate (int wdt
, int hgt
) {
389 scope(exit
) if (!conQueueEmpty()) glconPostDoConCommands();
390 if (isQuitRequested
) { close(); return; }
391 if (wdt
< 1) wdt
= 1;
392 if (hgt
< 1) hgt
= 1;
393 glconResize(wdt
, hgt
);
395 if (backbuf.width != wdt || backbuf.height != hgt) {
397 //backbuf = new Image(wdt, hgt);
398 //glconBackBuffer = this.backbuf;
404 onFocusChange
= delegate (bool focused
) {};
409 void main (string
[] args
) {
411 import core
.stdc
.stdio
;
413 printf("%u\n", XImage
.sizeof
);
415 printf("width: %u\n", XImage
.width
.offsetof
);
416 printf("height: %u\n", XImage
.height
.offsetof
);
417 printf("xoffset: %u\n", XImage
.xoffset
.offsetof
);
418 printf("format: %u\n", XImage
.format
.offsetof
);
419 printf("data: %u\n", XImage
.data
.offsetof
);
420 printf("byte_order: %u\n", XImage
.byte_order
.offsetof
);
421 printf("bitmap_unit: %u\n", XImage
.bitmap_unit
.offsetof
);
422 printf("bitmap_bit_order: %u\n", XImage
.bitmap_bit_order
.offsetof
);
423 printf("bitmap_pad: %u\n", XImage
.bitmap_pad
.offsetof
);
424 printf("depth: %u\n", XImage
.depth
.offsetof
);
425 printf("bytes_per_line: %u\n", XImage
.bytes_per_line
.offsetof
);
426 printf("bits_per_pixel: %u\n", XImage
.bits_per_pixel
.offsetof
);
427 printf("red_mask: %u\n", XImage
.red_mask
.offsetof
);
428 printf("green_mask: %u\n", XImage
.green_mask
.offsetof
);
429 printf("blue_mask: %u\n", XImage
.blue_mask
.offsetof
);
430 printf("obdata: %u\n", XImage
.obdata
.offsetof
);
431 printf("f: %u\n", XImage
.f
.offsetof
);
432 printf("f.create_image: %u\n", XImage
.f
.offsetof
+XImage
.f
.create_image
.offsetof
);
433 printf("f.destroy_image: %u\n", XImage
.f
.offsetof
+XImage
.f
.destroy_image
.offsetof
);
434 printf("f.get_pixel: %u\n", XImage
.f
.offsetof
+XImage
.f
.get_pixel
.offsetof
);
435 printf("f.put_pixel: %u\n", XImage
.f
.offsetof
+XImage
.f
.put_pixel
.offsetof
);
436 printf("f.sub_image: %u\n", XImage
.f
.offsetof
+XImage
.f
.sub_image
.offsetof
);
437 printf("f.add_pixel: %u\n", XImage
.f
.offsetof
+XImage
.f
.add_pixel
.offsetof
);
440 glconAllowOpenGLRender
= false;
441 if (args
.length
== 1) args
~= "EQMAIN.BMP";
443 concmd("r_console tan");
445 conProcessArgs
!true(args
);
446 conProcessQueue(int.max
/4);
448 auto bmp
= loadImageFromFile(VFile(args
[1]));
449 auto win
= new BmpWindow();
450 //glconCtlWindow = win;
454 conwriteln("size: ", xlimg
.width
, "x", xlimg
.height
);
459 auto xi = XlibTCImage(bmp);
460 conwriteln("size: ", xi.handle.width, "x", xi.handle.height);
461 conwriteln("xoffset: ", xi.handle.xoffset);
462 conwriteln("format: ", xi.handle.format);
463 conwriteln("byte_order: ", xi.handle.byte_order);
464 conwriteln("bitmap_unit: ", xi.handle.bitmap_unit);
465 conwriteln("bitmap_bit_order: ", xi.handle.bitmap_bit_order);
466 conwriteln("bitmap_pad: ", xi.handle.bitmap_pad);
467 conwriteln("depth: ", xi.handle.depth);
468 conwriteln("bytes_per_line: ", xi.handle.bytes_per_line);
469 conwriteln("bits_per_pixel: ", xi.handle.bits_per_pixel);
470 conwritefln!"red_mask: 0x%08x"(xi.handle.red_mask);
471 conwritefln!"green_mask: 0x%08x"(xi.handle.green_mask);
472 conwritefln!"blue_mask: 0x%08x"(xi.handle.blue_mask);
480 conProcessQueue(int.max
/4);