embed standard resources

This commit is contained in:
Vadim Lopatin 2015-01-22 14:21:18 +03:00
parent 0cac220762
commit 3d8f195e4a
3 changed files with 132 additions and 30 deletions
src/dlangui

View File

@ -31,6 +31,8 @@ version (USE_DEIMAGE) {
version (USE_DLIBIMAGE) { version (USE_DLIBIMAGE) {
import dlib.image.io.io; import dlib.image.io.io;
import dlib.image.image; import dlib.image.image;
import dlib.image.io.png;
import dlib.image.io.jpeg;
version = ENABLE_DLIBIMAGE_JPEG; version = ENABLE_DLIBIMAGE_JPEG;
} }
@ -39,10 +41,24 @@ import dlangui.core.types;
import dlangui.graphics.colors; import dlangui.graphics.colors;
import dlangui.graphics.drawbuf; import dlangui.graphics.drawbuf;
import std.stream; import std.stream;
import std.path;
import std.conv : to; import std.conv : to;
/// 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) {
try {
immutable ubyte[] data = cast(immutable ubyte[])std.file.read(filename);
return loadImage(data, filename);
} catch (Exception e) {
Log.e("exception while loading image from file ", filename);
Log.e(to!string(e));
return null;
}
}
/// load and decode image from input stream to ColorDrawBuf, returns null if loading or decoding is failed
ColorDrawBuf loadImage(immutable ubyte[] data, string filename) {
Log.d("Loading image from file " ~ filename); Log.d("Loading image from file " ~ filename);
version (USE_DEIMAGE) { version (USE_DEIMAGE) {
try { try {
@ -69,6 +85,7 @@ ColorDrawBuf loadImage(string filename) {
} }
} else version (USE_DLIBIMAGE) { } else version (USE_DLIBIMAGE) {
import std.algorithm; import std.algorithm;
static import dlib.core.stream;
try { try {
version (ENABLE_DLIBIMAGE_JPEG) { version (ENABLE_DLIBIMAGE_JPEG) {
} else { } else {
@ -76,19 +93,23 @@ ColorDrawBuf loadImage(string filename) {
if (filename.endsWith(".jpeg") || filename.endsWith(".jpg") || filename.endsWith(".JPG") || filename.endsWith(".JPEG")) if (filename.endsWith(".jpeg") || filename.endsWith(".jpg") || filename.endsWith(".JPG") || filename.endsWith(".JPEG"))
return null; return null;
} }
SuperImage image = dlib.image.io.io.loadImage(filename); SuperImage image = null;
dlib.core.stream.ArrayStream dlibstream = new dlib.core.stream.ArrayStream(cast(ubyte[])data, data.length);
switch(filename.extension)
{
case ".jpg", ".JPG", ".jpeg":
image = dlib.image.io.jpeg.loadJPEG(dlibstream);
break;
case ".png", ".PNG":
image = dlib.image.io.png.loadPNG(dlibstream);
break;
default:
break;
}
//SuperImage image = dlib.image.io.io.loadImage(filename);
if (!image) if (!image)
return null; return null;
int w = image.width; ColorDrawBuf buf = importImage(image);
int h = image.height;
ColorDrawBuf buf = new ColorDrawBuf(w, h);
for (int y = 0; y < h; y++) {
uint * dstLine = buf.scanLine(y);
for (int x = 0; x < w; x++) {
auto pixel = image[x, h - 1 - y].convert(8);
dstLine[x] = makeRGBA(pixel.r, pixel.g, pixel.b, 255 - pixel.a);
}
}
destroy(image); destroy(image);
return buf; return buf;
} catch (Exception e) { } catch (Exception e) {
@ -110,6 +131,22 @@ ColorDrawBuf loadImage(string filename) {
} }
version (USE_DLIBIMAGE) {
ColorDrawBuf importImage(SuperImage image) {
int w = image.width;
int h = image.height;
ColorDrawBuf buf = new ColorDrawBuf(w, h);
for (int y = 0; y < h; y++) {
uint * dstLine = buf.scanLine(y);
for (int x = 0; x < w; x++) {
auto pixel = image[x, h - 1 - y].convert(8);
dstLine[x] = makeRGBA(pixel.r, pixel.g, pixel.b, 255 - pixel.a);
}
}
return buf;
}
}
class ImageDecodingException : Exception { class ImageDecodingException : Exception {
this(string msg) { this(string msg) {
super(msg); super(msg);

View File

@ -37,9 +37,16 @@ import std.conv;
import std.string; import std.string;
import std.path; import std.path;
/// filename prefix for embedded resources
immutable string EMBEDDED_RESOURCE_PREFIX = "@embedded@/";
struct EmbeddedResource { struct EmbeddedResource {
string name; immutable string name;
ubyte[] data; immutable ubyte[] data;
this(immutable string name, immutable ubyte[] data) {
this.name = name;
this.data = data;
}
} }
struct EmbeddedResourceList { struct EmbeddedResourceList {
@ -47,14 +54,41 @@ struct EmbeddedResourceList {
void addResources(EmbeddedResource[] resources) { void addResources(EmbeddedResource[] resources) {
list ~= resources; list ~= resources;
} }
/// find by exact file name
EmbeddedResource * find(string name) {
for(int i = 0; i < list.length; i++)
if (name.equal(list[i].name))
return &list[i];
return null;
}
/// find by name w/o extension
EmbeddedResource * findAutoExtension(string name) {
string xmlname = name ~ ".xml";
string pngname = name ~ ".png";
string png9name = name ~ ".9.png";
string jpgname = name ~ ".jpg";
string jpegname = name ~ ".jpeg";
for(int i = 0; i < list.length; i++) {
string s = list[i].name;
if (s.equal(xmlname) || s.equal(pngname) || s.equal(png9name)
|| s.equal(jpgname) || s.equal(jpegname))
return &list[i];
}
return null;
}
} }
__gshared EmbeddedResourceList embeddedResourceList; __gshared EmbeddedResourceList embeddedResourceList;
EmbeddedResource[] embedResource(string resourceName)() { EmbeddedResource[] embedResource(string resourceName)() {
static if ((baseName(resourceName)).length > 0) immutable string name = baseName(resourceName);
return [EmbeddedResource(resourceName, cast(ubyte[])import(baseName(resourceName)))]; static if (name.length > 0) {
else immutable ubyte[] data = cast(immutable ubyte[])import(name);
static if (data.length > 0)
return [EmbeddedResource(name, data)];
else
return [];
} else
return []; return [];
} }
@ -62,8 +96,10 @@ EmbeddedResource[] embedResource(string resourceName)() {
EmbeddedResource[] embedResources(string[] resourceNames)() { EmbeddedResource[] embedResources(string[] resourceNames)() {
static if (resourceNames.length == 0) static if (resourceNames.length == 0)
return []; return [];
static if (resourceNames.length == 1)
return embedResource!(resourceNames[0])();
else else
return embedResource!(resourceNames[0])() ~ embedResources!(resourceNames[1..$])(); return embedResources!(resourceNames[0 .. $/2])() ~ embedResources!(resourceNames[$/2 .. $])();
} }
/// embed all resources from list /// embed all resources from list
@ -78,6 +114,24 @@ __gshared static this() {
} }
} }
/// load resource bytes from embedded resource or file
immutable(ubyte[]) loadResourceBytes(string filename) {
if (filename.startsWith(EMBEDDED_RESOURCE_PREFIX)) {
EmbeddedResource * embedded = embeddedResourceList.find(filename[EMBEDDED_RESOURCE_PREFIX.length .. $]);
if (embedded)
return embedded.data;
return null;
} else {
try {
immutable ubyte[] data = cast(immutable ubyte[])std.file.read(filename);
return data;
} catch (Exception e) {
Log.e("exception while loading file ", filename);
return null;
}
}
}
class Drawable : RefCountedObject { class Drawable : RefCountedObject {
//private static int _instanceCount; //private static int _instanceCount;
this() { this() {
@ -538,7 +592,11 @@ class StateDrawable : Drawable {
import std.string; import std.string;
try { try {
string s = cast(string)std.file.read(filename); string s = cast(string)loadResourceBytes(filename);
if (!s) {
Log.e("Cannot read drawable resource from file ", filename);
return false;
}
// Check for well-formedness // Check for well-formedness
//check(s); //check(s);
@ -550,9 +608,6 @@ class StateDrawable : Drawable {
} catch (CheckException e) { } catch (CheckException e) {
Log.e("Invalid XML file ", filename); Log.e("Invalid XML file ", filename);
return false; return false;
} catch (Throwable e) {
Log.e("Cannot read drawable resource from file ", filename);
return false;
} }
} }
@ -602,10 +657,13 @@ class ImageCache {
_used = true; _used = true;
return _drawbuf; return _drawbuf;
} }
_drawbuf = loadImage(_filename); immutable ubyte[] data = loadResourceBytes(_filename);
if (_filename.endsWith(".9.png")) if (data) {
_drawbuf.detectNinePatch(); _drawbuf = loadImage(data, _filename);
_used = true; if (_filename.endsWith(".9.png"))
_drawbuf.detectNinePatch();
_used = true;
}
if (_drawbuf.isNull) if (_drawbuf.isNull)
_error = true; _error = true;
return _drawbuf; return _drawbuf;
@ -917,6 +975,12 @@ class DrawableCache {
return id; // it's not a file name, just a color #AARRGGBB return id; // it's not a file name, just a color #AARRGGBB
if (id in _idToFileMap) if (id in _idToFileMap)
return _idToFileMap[id]; return _idToFileMap[id];
EmbeddedResource * embedded = embeddedResourceList.findAutoExtension(id);
if (embedded) {
string fn = EMBEDDED_RESOURCE_PREFIX ~ embedded.name;
_idToFileMap[id] = fn;
return fn;
}
foreach(string path; _resourcePaths) { foreach(string path; _resourcePaths) {
string fn; string fn;
fn = checkFileName(path, id, ".xml"); fn = checkFileName(path, id, ".xml");

View File

@ -1278,7 +1278,11 @@ bool loadTheme(Theme theme, string resourceId, int level = 0) {
filename = drawableCache.findResource(resourceId); filename = drawableCache.findResource(resourceId);
if (!filename || !filename.endsWith(".xml")) if (!filename || !filename.endsWith(".xml"))
return false; return false;
string s = cast(string)std.file.read(filename); string s = cast(string)loadResourceBytes(filename);
if (!s) {
Log.e("Cannot read XML resource ", resourceId, " from file ", filename);
return false;
}
// Check for well-formedness // Check for well-formedness
//check(s); //check(s);
@ -1290,9 +1294,6 @@ bool loadTheme(Theme theme, string resourceId, int level = 0) {
} catch (CheckException e) { } catch (CheckException e) {
Log.e("Invalid XML resource ", resourceId); Log.e("Invalid XML resource ", resourceId);
return false; return false;
} catch (Throwable e) {
Log.e("Cannot read XML resource ", resourceId, " from file ", filename, " exception: ", e);
return false;
} }
} }