shithub: view

ref: ac1a4e7dbe0b0c96054aee63bdd167636e857b85
dir: view/io.c

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include "a.h"

#define NULL nil
#define STBI_NO_STDIO
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define NANOSVG_ALL_COLOR_KEYWORDS
#define NANOSVG_IMPLEMENTATION
#include "nanosvg.h"
#define NANOSVGRAST_IMPLEMENTATION
#include "nanosvgrast.h"

Image*
load9(char *filename)
{
	Image *i;
	int fd;

	fd = open(filename, OREAD);
	if(fd < 0)
		sysfatal("open: %r");
	i = readimage(display, fd, 1);
	if(i == nil)
		sysfatal("readimage: %r");
	close(fd);
	return i;
}

Image*
loadany(char *filename)
{
	Image *i;
	uchar *buf, *out;
	int n, w, h, c;
	ulong chan;

	buf = readfile(filename, &n);
	if(buf == nil)
		sysfatal("readfile: %r");
	out = stbi_load_from_memory(buf, n, &w, &h, &c, 4);
	free(buf);
	if(out==nil)
		sysfatal("stbi_load_from_memory: %r");
	chan = c==3 ? XBGR32 : ABGR32;
	lockdisplay(display);
	i = eallocimage(w, h, chan, 0, DNofill);
	if(loadimage(i, i->r, out, 4*w*h)<0)
		sysfatal("loadimage: %r");
	unlockdisplay(display);
	return i;
}

Image*
loadsvg(char *filename)
{
	Image *i;
	NSVGimage *image;
	NSVGrasterizer *rast;
	uchar *data;
	int w, h, sz;

	image = nsvgParseFromFile(filename, "px", 96);
	if(image==nil)
		sysfatal("svg parse: %r");
	w = image->width;
	h = image->height;
	rast = nsvgCreateRasterizer();
	if(rast==nil)
		sysfatal("create rasterizer: %r");
	sz = w*h*4;
	data = malloc(sz);
	if(data==nil)
		sysfatal("malloc: %r");
	nsvgRasterize(rast, image, 0, 0, 1.0, data, w, h, w*4);
	nsvgDelete(image);
	nsvgDeleteRasterizer(rast);
	lockdisplay(display);
	i = eallocimage(w, h, ABGR32, 0, DNofill);
	if(loadimage(i, i->r, data, sz)<sz)
		sysfatal("loadimage: %r");
	unlockdisplay(display);
	return i;
}

Image*
load(char *filename)
{
	Image *i;
	int f;

	i = nil;
	f = fileformat(filename);
	if(f < 0)
		sysfatal("load: %r");
	switch(f){
	case SVG:
		i = loadsvg(filename);
		break;		
	case NINE:
		i = load9(filename);
		break;
	case GIF:
	case JPEG:
	case PNG:
	case BMP:
		i = loadany(filename);
		break;
	}
	return i;
}

int
save(Image *i, char *f)
{
	int fd, r;

	if(access(f, 0) < 0)
		fd = create(f, OWRITE, 0644);
	else
		fd = open(f, OWRITE|OTRUNC);
	if(fd < 0)
		return -1;
	r = writeimage(fd, i, 1);
	close(fd);
	return r;
}

int
export(Image *i, char *f)
{
	int fd, pfd[2], r;
	Waitmsg *m;

	r = -1;
	if(access(f, 0) < 0)
		fd = create(f, OWRITE, 0644);
	else
		fd = open(f, OWRITE|OTRUNC);
	if(fd < 0)
		return -1;
	if(pipe(pfd) < 0){
		close(fd);
		return -1;
	}
	switch(rfork(RFFDG|RFPROC)){
	case -1:
		goto Err;
	case 0:
		dup(pfd[1], 0);
		dup(fd, 1);
		close(pfd[1]);
		close(pfd[0]);
		execl("/bin/rc", "rc", "-c", "topng", nil);
		_exits("exec");
	}
	if(writeimage(pfd[0], i, 1) < 0)
		goto Err;
	m = wait();
	if(m->msg[0] == 0)
		r = 0;
Err:
	close(fd);
	close(pfd[1]);
	close(pfd[0]);
	return r;
}