From 79a18449cd56234f2a3c9644cea3ef46ac3d0226 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Wed, 5 Mar 2014 14:52:50 +0400 Subject: [PATCH] loading and drawing of PNGs is working --- examples/example1/example1.visualdproj | 4 +- examples/example1/res/exit.png | Bin 0 -> 1915 bytes examples/example1/res/fileclose.png | Bin 0 -> 1594 bytes examples/example1/res/fileopen.png | Bin 0 -> 2232 bytes examples/example1/winmain.d | 17 ++++- src/dlangui/core/types.d | 42 ++++++++++--- src/dlangui/graphics/drawbuf.d | 70 ++++++++++++++++++++- src/dlangui/graphics/images.d | 14 ++++- src/dlangui/platforms/windows/win32fonts.d | 17 ++--- src/dlangui/platforms/windows/winapp.d | 57 ++++++++++++++--- 10 files changed, 185 insertions(+), 36 deletions(-) create mode 100644 examples/example1/res/exit.png create mode 100644 examples/example1/res/fileclose.png create mode 100644 examples/example1/res/fileopen.png diff --git a/examples/example1/example1.visualdproj b/examples/example1/example1.visualdproj index 6a6bd692..bfd6808a 100644 --- a/examples/example1/example1.visualdproj +++ b/examples/example1/example1.visualdproj @@ -47,7 +47,7 @@ 0 0 $(DMDInstallDir)windows\bin\dmd.exe - ../../src ../../3rdparty + $(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/3rdparty/libpng/source $(ConfigurationName) $(OutDir) @@ -84,7 +84,7 @@ phobos.lib ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib dlangui.lib - ../../Debug ../../3rdparty/win32/lib + ../../Debug ../../3rdparty/libpng/lib $(OutDir)\$(ProjectName).exe diff --git a/examples/example1/res/exit.png b/examples/example1/res/exit.png new file mode 100644 index 0000000000000000000000000000000000000000..7445887949c3b817d3fd5a223747264e7a5d2ac9 GIT binary patch literal 1915 zcmV->2ZZ>EP)7r0xWIucLV^Pql7VD02xVgt4ki;@N<7Yj+ga>(r@P%<)!ntsp{lDFTXT!%lS*GL zuipP(|M$N4y%N`TIViFhm;lCsF!y&#Qq9A|B__p&?w?(uf2vIkFUmVa1!e3BHZ0gD3L(x>cX;Z z%uEI;6wp>ya8_0VwWM_pg@`}#1o_LCS?A$|bpY3OsoFNKZDaWkTEXKZBP4h2LXX8( z5$x>mugADpnDGC4`RQgv_<#Borq1RVduE*8NjAV7S0nEw6y2{nYpv2B*-=eaXC$KAO( z+9DAWLql{A57Rv`fbs!1J@N>}&6~OQ)mQXaDggo4aZpMHm>vPg0ic@CBcTvV1U(*K z1%B{p^FVt$9e`_^xQ2mi z7(^_KWT}Mp#TQ)v@=L1avPUA3VEuE?k;`VmG!fH8L;_6J6oOoir5}EvV`PMN+qVZ_ ze(IA?s9w0hV?8~DEXxBmO(FvWL~9DW$48h>$3m)D>qM^U?djvfJ-GD!yx(Wv-H3527Rx;PGQ$Bj9d=aG@(=i!@xRo zhQiED;OEhoU*_`syr)2e>Z+ClwTjk}N)b*bgM>T&!3XT@FDl+$(FwgrywUb#YeW`<}BIHrj- zRLgKIMy^nR8n|hKY2wV!Q%$D>yXb}uRMTmc2zFx#9LEW2c~=90^wbnxjzcw_##&nP zPO+9}Zqv`2Ba1p^&$>4Fh|5 z8TZ~j++xuKZ5)+K@bywEK|YV0&0<};6qx*J>sB(=DoUv!2Xp}2w$YSAYE{c0B0^l( zgWXI6#J0V!Y#CB6BZg7mko=9R#UU%U?JYw;Hxz*7hd@&bV|qHU-#9)_u|b{2?Y4C& zA5b-biwL2yvA|~W@?{d?FiHfgDFn8S_^Y7UK%jryHVU=;XxZCWDX<2(5I9~z zSs#h4R={?gpwTcI*6#XL3ahVg%?6`YgGSKWq4o8lhK2&0%*;%kKx-0;FK^}gbt>7c z_fXS#{QdVS_&Zo5iAJJ#E?pv`Y0V)}inap>g5A}~W>M)hx>BnPk!9O;=OUz!9u1ri z@7|5EZ(q>;)a**1ea5XHf8^%*^PE3+jFGmsCh+jyz3AiPfuD1S4lx#wd&-Gm`61A2 z3aDCNCqn7;X%8ZzADf*&O+H~D(UN&r? z{lgE5z4<088U>)VxX8~(j_{Xc(gSZHpw~hW4Tqaz?B;UZeeXSbCMIa>=>edB_imh> zJ1JhfM&-&Ct$x zlbxL?*G2r+xh7d{?{oaWBFA-!Dn*-L*~Gsmu3HDJo%{Z5+h%@ok*f;}+%6OVrgUK9 zW`G5bO{};v9J({rdYv=#~002ovPDHLkV1jg; Bou>c* literal 0 HcmV?d00001 diff --git a/examples/example1/res/fileclose.png b/examples/example1/res/fileclose.png new file mode 100644 index 0000000000000000000000000000000000000000..8acc84d11a0411695db414ff2bc3d6dee4f2b442 GIT binary patch literal 1594 zcmV-A2F3Y_P)bAYI2Vqj&3xc%Qhi2mQde*xM5zy<@=9RLb7o;tPW z03ine1Q1>a04){(QuBd00L16w;$)DMlVh;5G6J$W7&J8%!0O(-`N;74^?Qb6$Idfc zy?Tw|>({RgfB*ggNo@e)#M7tOe!%4bfB?ej0HEatKx#cGs6iGR8yhkN20AgQtIOgI zT99MbuRqAJZQCw}&!0bmECNMG;F&Y)E?{#2KmcKN0MzpRKrsOc2?>Ve3W1%-g)*|X~}pgRB{fG`{Y4fgXuzJipL6hl^46oZtM2w5ro z`}dy=%a(0t*t>ThD1Cquso}YE8$KXA03d*{WkXP$D~O4SF(f7iGw|_oGkp2-9T>Ow z8UFnF17_pHpeSHvWd^hV{{6=g5a7t5t*ryHPyuQ-3IGToCM>Bv02JrGzAg+rJe{h)_{cVUUmz2K(an?I#Sjwt5UoN>X42%F0p<0s=f3K7alC1JDDy4BXtD80wgq z7=d!;K$-~@74^s#0t65fav=lC=OEwf=%@iTegk89c?r1XFrcNSz#t+b09W(j!)FE; z7h|~PFd!(%3zmQS^c6TdczF0g!VdcSz6vlk00G2;q}~CdNeGci3CHVjEodRb#)?6%V8ihGZ0MUa>V!V;M@goF8~A(6H*8q1l8xD5CGB0 zSV~HQp|LRyYl2&}Xa`nDI6K>b>lbAF^XE^Xd4Cz84Hqx~2q5GTH~^CT`t=Jir3#_= zytz38tL63e)4_56?b{EAjEn#bM}REdx9=!i?9-=Du;7O`Q~&}99sV|}JK*wf z-n@pjk{XdM1PCCE_JFBr@On_KrLL|CES3e3N<9N$si(rQc<~l+kmCX%buuzy469e~ zLTV+wWw>F zf`Z);=m3-k2|xg0ZIT%q2ZEbqEG(=7dU|@`{7(*e`t$|EnKP$>IqN65Nd~kWqe%u3 zKsXzvAV&b@z>QKB6*XY1MjhT1Cj@@|`VCAw*BP!~zXETRB3q8^0Du6(+blOS3J?Iw zgPY}`oT03&3QXAwz_h`S)#7*WJ_4)fdknX3-2mqKAK*9#HOpbaj?Do80Yp^C1k{Xz zwqzVY>Ot8`L_~}M(KGtT@Z`xOWP`yS6JT~D*f9YJAfg-q1E7`+v@u~1ZDb;s?eMM{ say}>I0Du5u9O&LLKmZMR?-(G!0PRc`sBxJOHUIzs07*qoM6N<$f|Hx8uK)l5 literal 0 HcmV?d00001 diff --git a/examples/example1/res/fileopen.png b/examples/example1/res/fileopen.png new file mode 100644 index 0000000000000000000000000000000000000000..503a0045911aea0af4dfa1562ca1216941935702 GIT binary patch literal 2232 zcmWkwYgAH+7Cv|sFhM9Q!N-83m8D%lZJeo;gOAFl(jK?EWr6vib!*b>p%!rf8`QMa z>Z(1}%9*^YJD7FT$^@m%@_|+s-ZH>^^%4>vAcu1<{n&f2z1Fw({?^*xUVG=qZ&*#9 z{BA_N-5)x3Y{DKK1>E&q0FbwZIi31w&*_I_wjbV{mU=idF(U=w zCa3L5VaEQJC`j3ql9-%*@L9@A03fc7jplC2`rjS|!#FC)K@9BKL*oNfD3B>FDJfYZ z>%DtmYjP_83TAtwzP{@;+6h(hAcRu!gBZBBgBW^rZ2#c!K-0*FYJpm%+BM{vFzh&Y z*wI3%h_IKc(hU6NErV7J2RttrwPue7*WS4eutQXz!x#&J>MNC1M$a;l9mfoteQ(+@ zZ|~Rseoe@b5_>qU#W0%{!|Kyu6rTL_7N(X*V1roOW9NRTI?^2J!4%WDt~ytaP={$1 z>+E2G;{)P=KUKQi)xXPV7`b#$as1kpRQU3JeY>6mz7&#|IcM`IzsYzUjE$hSGQB~I zK}eY-KfgqBCFfsNHTy=&qO7Hs%PZ?9LgTfW_}ZGA08^~o$d~&jD{8i0(u2jekswe- zVWJiS?P&Z|*SQMXvEc+w>%jdRw>7cbx5O8RwfD!K<8F{u=${tBBn+*(XdO{=@PAvl z5bsVPUwxCd(kgZ}N>+iZwg8S)7e5agEduv(kyd;W;~EVds>dKPDm+5=!aqiqmWjUJ zxif&JDG!iNB9@#Lr`{{D=epsWkJCTBOY-%up!aV(@cwIJL;ndU|4H{>`~Zi%-*LkZ zUOGm1r@AXaP;4I0Z(h`VnVWFl78EIQKPOOFs`RX12dbC{t^ zmEPZlQX4J%BIYOy4^6kt!*{_7+MJe7dRF$D_Wx{Sh!Qm!Gh~gRu%nQ)Kd^&TB>FY0 zZb!#~8C#Kw4ub7zd2*QNNMx=dLLa=x#^o?gbOLEBrlzg0lgn2k&#B!RCCyOONp8$V z#@P)bRM1`Dof!YxLMKm*65@aAKaR{cym42%gN{@U4#uv_fHI~Fc&V7G`e=%yts|%8 z-9tXS(UR`JOk-(0V%f8pnHsWMu}04M8nW3*_3dPr<_b2SKJd z{SV0%iiZB+r~ahkG8?erFos1w&&8BFX>=dVBD)b%o~#a1ut)dh1t+iG7ji3Htu&4W zJl>yvff9IXdwC!2%#~vc(Lr4`OnRrdKpQ*Ca3V7I&PBixn3m;Q*mOGgYH;AvUV$#r zrdGDMyOv^LN4SF9<8*iK+`9^{6UDz>I*1|yU9upBN*(5FvSydRf|-GY-XoRNh9d($ zDpOJz%C1G+_~yxBn*TkV1Mw=pI7&Ba*+zPBs*x0tijby%5bmK;_oV2ClW-#yamvOC z`u5$z8P{f>TV-N8hpB-xyS z`TMW7i}e+bTA^I~<-ZRZ?9f$<*$D7=!8M`1M^kEi&m5=f1u`B~AWjVy0;LIYJWP;< zSs1DhBOD0=lNcN<#f%J5R7GhDng}yLGme4^ONPQ8=Obh7UkpCXUeuNVtxRPkG4NEe*Wr%&+FmXx6--Pg+HXMx)Vef zc0N(oRY;s(T+dWiqQETY-Lf*d!eOawJ8|uK1?2oK%#UqXVw>@+l_&c%j>8t>TIab? zfO1VQk@GT@kxWy%?Mn%8Dj;9 zG+NC$l9GJ#mk%61FUrg0HQG=nhl5!e8Eh72Z8u_1DILpYHcnXWgtf(Ztp5np5YUDL zaE@^xvr%XTWq=DCU-=8f1KgOtelC)6RtQUknr?@zJTZPja<1Tlgj~M3kA?-;+OSUJ zq<1{YKgg%0*@%tAF;QHgZxa|bwW#5ixz*xXj-q!^^K>q`)K+<A!GEmkjG01(jAzr;HF3&lb49Z%k8)>dmMd-*e+yf>bHzFcw{RgpMn$aJ zI0Ti`mtc&pCM)8uDyoOxJo*Pr^T2ei&Je(L)59{A;A)89{luVYpB~^&IeouRp1PyM z@xTk;z!Zl9AFmc-DWQfVoJSji74MVG2dBO3!0!XzI_IilLh94AYrY@`3?cTV=jD_u zeI$zsn<-}nsXu4Y%daW4Z^@^vj9SzI0wmXUU61NX&odfH9-D48te~#z{?SttJ!5g9 zT~?kQTg1988D(%pY$4%~8HUo)Y$B`~Bh=n9KQU6a5OK>+%uE&OJCpeTMvqQ9r? zHWNVm4VC=ZU-0^j780wNBu_GVX}d#LB&P5j9aOFf2|Fs2~ z3G?Gh5@r||8_=k4iV8XHeOeQ~Q)FyiY-f0BNU3wGUKwvTy{z>l&dP{?JH7Zk-hGZ; y9fyE`yPi+hMiG$Q8L#T~L@HDW_J _clipRect.left) { + rc2.right -= rc.right - _clipRect.left; + rc.right = _clipRect.right; + } + if (rc.bottom > _clipRect.bottom) { + rc2.bottom -= rc.bottom - _clipRect.bottom; + rc.bottom = _clipRect.bottom; + } + } + if (rc.left < 0) { + rc2.left += -rc.left; + rc.left = 0; + } + if (rc.top < 0) { + rc2.top += -rc.top; + rc.top = 0; + } + if (rc.right > width) { + rc2.right -= rc.right - width; + rc.right = width; + } + if (rc.bottom > height) { + rc2.bottom -= rc.bottom - height; + rc.bottom = height; + } + return !rc.empty() && !rc2.empty(); + } void beforeDrawing() { } void afterDrawing() { } /// returns buffer bits per pixel @@ -55,6 +92,12 @@ class DrawBuf : RefCountedObject { } abstract void fillRect(Rect rc, uint color); abstract void drawGlyph(int x, int y, ubyte[] src, int srcdx, int srcdy, uint color); + /// draw source buffer rectangle contents to destination buffer + abstract void drawFragment(int x, int y, DrawBuf src, Rect srcrect); + /// draw whole unscaled image at specified coordinates + void drawImage(int x, int y, DrawBuf src) { + drawFragment(x, y, src, Rect(0, 0, src.width, src.height)); + } void clear() {} ~this() { clear(); } } @@ -68,6 +111,31 @@ class ColorDrawBufBase : DrawBuf { override @property int bpp() { return 32; } @property override int width() { return _dx; } @property override int height() { return _dy; } + /// draw source buffer rectangle contents to destination buffer + override void drawFragment(int x, int y, DrawBuf src, Rect srcrect) { + Rect dstrect = Rect(x, y, x + srcrect.width, y + srcrect.height); + if (applyClipping(dstrect, srcrect)) { + if (src.applyClipping(srcrect, dstrect)) { + int dx = srcrect.width; + int dy = srcrect.height; + for (int yy = 0; yy < dy; yy++) { + uint * srcrow = src.scanLine(srcrect.top + yy) + srcrect.left; + uint * dstrow = scanLine(dstrect.top + yy) + dstrect.left; + for (int i = 0; i < dx; i++) { + uint pixel = srcrow[i]; + uint alpha = pixel >> 24; + if (!alpha) + dstrow[i] = pixel; + else if (alpha < 255) { + // apply blending + dstrow[i] = blendARGB(dstrow[i], pixel, alpha); + } + } + + } + } + } + } override void fillRect(int left, int top, int right, int bottom, uint color) { fillRect(Rect(left, top, right, bottom), color); } diff --git a/src/dlangui/graphics/images.d b/src/dlangui/graphics/images.d index c4c2e6ca..9e745dae 100644 --- a/src/dlangui/graphics/images.d +++ b/src/dlangui/graphics/images.d @@ -1,5 +1,6 @@ module dlangui.graphics.images; +import dlangui.core.logger; import dlangui.graphics.drawbuf; import std.stream; import libpng.png; @@ -66,6 +67,7 @@ class ImageCache { /// load and decode image from file to ColorDrawBuf, returns null if loading or decoding is failed ColorDrawBuf loadImage(string filename) { + Log.d("Loading image from file " ~ filename); try { std.stream.File f = new std.stream.File(filename); scope(exit) { f.close(); } @@ -89,13 +91,19 @@ class ImageDecodingException : Exception { } } -extern (C) void lvpng_error_func (png_structp png, png_const_charp) +extern (C) void lvpng_error_func (png_structp png, png_const_charp msg) { + string s = fromStringz(msg); + Log.d("Error while reading PNG image: ", s); + // todo: exceptions do not work inside C function throw new ImageDecodingException("Error while decoding PNG image"); } -extern (C) void lvpng_warning_func (png_structp png, png_const_charp) +extern (C) void lvpng_warning_func (png_structp png, png_const_charp msg) { + string s = fromStringz(msg); + Log.d("Warn while reading PNG image: ", s); + // todo: exceptions do not work inside C function throw new ImageDecodingException("Error while decoding PNG image"); } @@ -105,6 +113,8 @@ extern (C) void lvpng_read_func(png_structp png, png_bytep buf, png_size_t len) ubyte[] localbuf = new ubyte[len]; if (stream.read(localbuf) != len) throw new ImageDecodingException("Error while reading PNG image"); + for (uint i = 0; i < len; i++) + buf[i] = localbuf[i]; } /// load and decode PNG image diff --git a/src/dlangui/platforms/windows/win32fonts.d b/src/dlangui/platforms/windows/win32fonts.d index 944e7250..cbf68667 100644 --- a/src/dlangui/platforms/windows/win32fonts.d +++ b/src/dlangui/platforms/windows/win32fonts.d @@ -1,18 +1,18 @@ -module dlangui.platforms.windows.win32fonts; - +module dlangui.platforms.windows.win32fonts; + version (Windows) { - + import win32.windows; import dlangui.graphics.fonts; import dlangui.platforms.windows.win32drawbuf; import std.string; import std.utf; - + //auto toUTF16z(S)(S s) //{ //return toUTFz!(const(wchar)*)(s); //} - + struct FontDef { immutable FontFamily _family; immutable string _face; @@ -429,13 +429,6 @@ class Win32FontManager : FontManager { } } -string fromStringz(const(char[]) s) { - int i = 0; - while(s[i]) - i++; - return cast(string)(s[0..i].dup); -} - FontFamily pitchAndFamilyToFontFamily(ubyte flags) { if ((flags & FF_DECORATIVE) == FF_DECORATIVE) return FontFamily.Fantasy; diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index fc6dbc81..673cb2b4 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -8,6 +8,7 @@ import std.string; import std.utf; import std.stdio; import std.algorithm; +import std.file; import dlangui.platforms.common.platform; import dlangui.platforms.windows.win32fonts; import dlangui.platforms.windows.win32drawbuf; @@ -19,7 +20,7 @@ pragma(lib, "gdi32.lib"); pragma(lib, "user32.lib"); pragma(lib, "libpng15.lib"); -extern (C) int UIAppMain(); +extern (C) int UIAppMain(string[] args); immutable WIN_CLASS_NAME = "DLANGUI_APP"; @@ -112,20 +113,26 @@ class Win32Platform : Platform { } } +/// returns current executable path only, including last path delimiter +string exePath() { + string path = thisExePath(); + int lastSlash = 0; + for (int i = 0; i < path.length; i++) + if (path[i] == '\\') + lastSlash = i; + return path[0 .. lastSlash + 1]; +} + extern(Windows) int DLANGUIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int result; - void exceptionHandler(Throwable e) { - throw e; - } - try { - Runtime.initialize(&exceptionHandler); + Runtime.initialize(); result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); - Runtime.terminate(&exceptionHandler); + Runtime.terminate(); } catch (Throwable e) // catch any uncaught exceptions { @@ -137,11 +144,45 @@ int DLANGUIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, return result; } +string[] splitCmdLine(string line) { + string[] res; + int start = 0; + bool insideQuotes = false; + for (int i = 0; i <= line.length; i++) { + char ch = i < line.length ? line[i] : 0; + if (ch == '\"') { + if (insideQuotes) { + if (i > start) + res ~= line[start .. i]; + start = i + 1; + insideQuotes = false; + } else { + insideQuotes = true; + start = i + 1; + } + } else if (!insideQuotes && (ch == ' ' || ch == '\t' || ch == 0)) { + if (i > start) { + res ~= line[start .. i]; + } + start = i + 1; + } + } + return res; +} + int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow) { setFileLogger(std.stdio.File("ui.log", "w")); setLogLevel(LogLevel.Trace); + string basePath = exePath(); + Log.i("Current executable: ", exePath()); + + string cmdline = fromStringz(lpCmdLine); + Log.i("Command line: ", cmdline); + string[] args = splitCmdLine(cmdline); + Log.i("Command line params: ", args); + _cmdShow = iCmdShow; _hInstance = hInstance; Log.d("Inside myWinMain"); @@ -156,7 +197,7 @@ int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int Platform.setInstance(platform); Win32FontManager fontMan = new Win32FontManager(); FontManager.instance = fontMan; - return UIAppMain(); + return UIAppMain(args); }