loading and drawing of PNGs is working

This commit is contained in:
Vadim Lopatin 2014-03-05 14:52:50 +04:00
parent b506c6f285
commit 79a18449cd
10 changed files with 185 additions and 36 deletions

View File

@ -47,7 +47,7 @@
<compiler>0</compiler> <compiler>0</compiler>
<otherDMD>0</otherDMD> <otherDMD>0</otherDMD>
<program>$(DMDInstallDir)windows\bin\dmd.exe</program> <program>$(DMDInstallDir)windows\bin\dmd.exe</program>
<imppath>../../src ../../3rdparty</imppath> <imppath>$(SolutionDir)/src $(SolutionDir)/3rdparty $(SolutionDir)/3rdparty/libpng/source</imppath>
<fileImppath /> <fileImppath />
<outdir>$(ConfigurationName)</outdir> <outdir>$(ConfigurationName)</outdir>
<objdir>$(OutDir)</objdir> <objdir>$(OutDir)</objdir>
@ -84,7 +84,7 @@
<objfiles /> <objfiles />
<linkswitches /> <linkswitches />
<libfiles>phobos.lib ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib dlangui.lib</libfiles> <libfiles>phobos.lib ole32.lib kernel32.lib user32.lib comctl32.lib comdlg32.lib dlangui.lib</libfiles>
<libpaths>../../Debug ../../3rdparty/win32/lib</libpaths> <libpaths>../../Debug ../../3rdparty/libpng/lib</libpaths>
<deffile /> <deffile />
<resfile /> <resfile />
<exefile>$(OutDir)\$(ProjectName).exe</exefile> <exefile>$(OutDir)\$(ProjectName).exe</exefile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,7 +1,7 @@
module winmain; module winmain;
pragma(lib, "dlangui.lib");
import dlangui.platforms.common.platform; import dlangui.platforms.common.platform;
import dlangui.graphics.images;
import dlangui.widgets.widget; import dlangui.widgets.widget;
import dlangui.core.logger; import dlangui.core.logger;
import dlangui.graphics.fonts; import dlangui.graphics.fonts;
@ -20,6 +20,9 @@ version(Windows) {
} }
} }
ImageCache imageCache;
string resourceDir;
class TestWidget : Widget { class TestWidget : Widget {
public override void onDraw(DrawBuf buf) { public override void onDraw(DrawBuf buf) {
super.onDraw(buf); super.onDraw(buf);
@ -34,10 +37,20 @@ class TestWidget : Widget {
Log.d("Got font, drawing text"); Log.d("Got font, drawing text");
font.drawText(buf, _pos.left + 5, _pos.top + 5, "Text"d, 0x0000FF); font.drawText(buf, _pos.left + 5, _pos.top + 5, "Text"d, 0x0000FF);
Log.d("Text is drawn successfully"); Log.d("Text is drawn successfully");
DrawBufRef img = imageCache.get(resourceDir ~ "exit.png");
if (!img.isNull) {
Log.d("loaded image ", img.width, "x", img.height);
buf.drawImage(200, 200, img);
buf.drawImage(250, 250, img);
}
} }
} }
extern (C) int UIAppMain() { extern (C) int UIAppMain(string[] args) {
imageCache = new ImageCache();
resourceDir = exePath() ~ "..\\res\\";
Log.d("Some debug message"); Log.d("Some debug message");
Log.e("Sample error #", 22); Log.e("Sample error #", 22);

View File

@ -10,22 +10,22 @@ public struct Point {
} }
public struct Rect { public struct Rect {
public int left; int left;
public int top; int top;
public int right; int right;
public int bottom; int bottom;
public @property int width() { return right - left; } @property int width() { return right - left; }
public @property int height() { return bottom - top; } @property int height() { return bottom - top; }
public this(int x0, int y0, int x1, int y1) { this(int x0, int y0, int x1, int y1) {
left = x0; left = x0;
top = y0; top = y0;
right = x1; right = x1;
bottom = y1; bottom = y1;
} }
public bool empty() { @property bool empty() {
return right <= left || bottom <= top; return right <= left || bottom <= top;
} }
public bool intersect(Rect rc) { bool intersect(Rect rc) {
if (left < rc.left) if (left < rc.left)
left = rc.left; left = rc.left;
if (top < rc.top) if (top < rc.top)
@ -109,3 +109,27 @@ public struct Ref(T) { // if (T is RefCountedObject)
_data.releaseRef(); _data.releaseRef();
} }
} }
// some utility functions
string fromStringz(const(char[]) s) {
int i = 0;
while(s[i])
i++;
return cast(string)(s[0..i].dup);
}
string fromStringz(const(char*) s) {
int i = 0;
while(s[i])
i++;
return cast(string)(s[0..i].dup);
}
wstring fromWStringz(const(wchar[]) s) {
int i = 0;
while(s[i])
i++;
return cast(wstring)(s[0..i].dup);
}

View File

@ -29,7 +29,7 @@ class DrawBuf : RefCountedObject {
_clipRect = rect; _clipRect = rect;
_clipRect.intersect(Rect(0, 0, width, height)); _clipRect.intersect(Rect(0, 0, width, height));
} }
protected bool applyClipping(ref Rect rc) { bool applyClipping(ref Rect rc) {
if (!_clipRect.empty()) if (!_clipRect.empty())
rc.intersect(_clipRect); rc.intersect(_clipRect);
if (rc.left < 0) if (rc.left < 0)
@ -42,6 +42,43 @@ class DrawBuf : RefCountedObject {
rc.bottom = height; rc.bottom = height;
return !rc.empty(); return !rc.empty();
} }
bool applyClipping(ref Rect rc, ref Rect rc2) {
if (!_clipRect.empty()) {
if (rc.left < _clipRect.left) {
rc2.left += _clipRect.left - rc.left;
rc.left = _clipRect.left;
}
if (rc.top < _clipRect.top) {
rc2.top += _clipRect.top - rc.top;
rc.top = _clipRect.top;
}
if (rc.right > _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 beforeDrawing() { }
void afterDrawing() { } void afterDrawing() { }
/// returns buffer bits per pixel /// returns buffer bits per pixel
@ -55,6 +92,12 @@ class DrawBuf : RefCountedObject {
} }
abstract void fillRect(Rect rc, uint color); abstract void fillRect(Rect rc, uint color);
abstract void drawGlyph(int x, int y, ubyte[] src, int srcdx, int srcdy, 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() {} void clear() {}
~this() { clear(); } ~this() { clear(); }
} }
@ -68,6 +111,31 @@ class ColorDrawBufBase : DrawBuf {
override @property int bpp() { return 32; } override @property int bpp() { return 32; }
@property override int width() { return _dx; } @property override int width() { return _dx; }
@property override int height() { return _dy; } @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) { override void fillRect(int left, int top, int right, int bottom, uint color) {
fillRect(Rect(left, top, right, bottom), color); fillRect(Rect(left, top, right, bottom), color);
} }

View File

@ -1,5 +1,6 @@
module dlangui.graphics.images; module dlangui.graphics.images;
import dlangui.core.logger;
import dlangui.graphics.drawbuf; import dlangui.graphics.drawbuf;
import std.stream; import std.stream;
import libpng.png; 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 /// load and decode image from file to ColorDrawBuf, returns null if loading or decoding is failed
ColorDrawBuf loadImage(string filename) { ColorDrawBuf loadImage(string filename) {
Log.d("Loading image from file " ~ filename);
try { try {
std.stream.File f = new std.stream.File(filename); std.stream.File f = new std.stream.File(filename);
scope(exit) { f.close(); } 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"); 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"); 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]; ubyte[] localbuf = new ubyte[len];
if (stream.read(localbuf) != len) if (stream.read(localbuf) != len)
throw new ImageDecodingException("Error while reading PNG image"); throw new ImageDecodingException("Error while reading PNG image");
for (uint i = 0; i < len; i++)
buf[i] = localbuf[i];
} }
/// load and decode PNG image /// load and decode PNG image

View File

@ -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) { FontFamily pitchAndFamilyToFontFamily(ubyte flags) {
if ((flags & FF_DECORATIVE) == FF_DECORATIVE) if ((flags & FF_DECORATIVE) == FF_DECORATIVE)
return FontFamily.Fantasy; return FontFamily.Fantasy;

View File

@ -8,6 +8,7 @@ import std.string;
import std.utf; import std.utf;
import std.stdio; import std.stdio;
import std.algorithm; import std.algorithm;
import std.file;
import dlangui.platforms.common.platform; import dlangui.platforms.common.platform;
import dlangui.platforms.windows.win32fonts; import dlangui.platforms.windows.win32fonts;
import dlangui.platforms.windows.win32drawbuf; import dlangui.platforms.windows.win32drawbuf;
@ -19,7 +20,7 @@ pragma(lib, "gdi32.lib");
pragma(lib, "user32.lib"); pragma(lib, "user32.lib");
pragma(lib, "libpng15.lib"); pragma(lib, "libpng15.lib");
extern (C) int UIAppMain(); extern (C) int UIAppMain(string[] args);
immutable WIN_CLASS_NAME = "DLANGUI_APP"; 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) extern(Windows)
int DLANGUIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, int DLANGUIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) { LPSTR lpCmdLine, int nCmdShow) {
int result; int result;
void exceptionHandler(Throwable e) {
throw e;
}
try try
{ {
Runtime.initialize(&exceptionHandler); Runtime.initialize();
result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow); result = myWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
Runtime.terminate(&exceptionHandler); Runtime.terminate();
} }
catch (Throwable e) // catch any uncaught exceptions catch (Throwable e) // catch any uncaught exceptions
{ {
@ -137,11 +144,45 @@ int DLANGUIWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
return result; 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) int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
{ {
setFileLogger(std.stdio.File("ui.log", "w")); setFileLogger(std.stdio.File("ui.log", "w"));
setLogLevel(LogLevel.Trace); 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; _cmdShow = iCmdShow;
_hInstance = hInstance; _hInstance = hInstance;
Log.d("Inside myWinMain"); Log.d("Inside myWinMain");
@ -156,7 +197,7 @@ int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int
Platform.setInstance(platform); Platform.setInstance(platform);
Win32FontManager fontMan = new Win32FontManager(); Win32FontManager fontMan = new Win32FontManager();
FontManager.instance = fontMan; FontManager.instance = fontMan;
return UIAppMain(); return UIAppMain(args);
} }