This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via 5381c2dcc328739b9d82e462da5e2135a8d23c2a (commit)
from cf7258563111632ca23dbf29221e16402dc50b24 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/5381c2dcc328739b9d82e462da5e2135a8d2…
commit 5381c2dcc328739b9d82e462da5e2135a8d23c2a
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Sat Jun 29 00:03:11 2013 +0200
loaders: TIFF: A few fixes.
Enable 1bpp
Fix MINISWHITE
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/libs/loaders/GP_TIFF.c b/libs/loaders/GP_TIFF.c
index 6d12b2f..ac49d06 100644
--- a/libs/loaders/GP_TIFF.c
+++ b/libs/loaders/GP_TIFF.c
@@ -101,6 +101,38 @@ static const char *compression_name(uint16_t compression)
return "Unknown";
}
+static const char *photometric_name(uint16_t photometric)
+{
+ switch (photometric) {
+ case PHOTOMETRIC_MINISWHITE:
+ return "Min is White";
+ case PHOTOMETRIC_MINISBLACK:
+ return "Min is black";
+ case PHOTOMETRIC_RGB:
+ return "RGB";
+ case PHOTOMETRIC_PALETTE:
+ return "Palette";
+ case PHOTOMETRIC_MASK:
+ return "Mask";
+ case PHOTOMETRIC_SEPARATED:
+ return "Separated";
+ case PHOTOMETRIC_YCBCR:
+ return "YCBCR";
+ case PHOTOMETRIC_CIELAB:
+ return "CIELAB";
+ case PHOTOMETRIC_ICCLAB:
+ return "ICCLAB";
+ case PHOTOMETRIC_ITULAB:
+ return "ITULAB";
+ case PHOTOMETRIC_LOGL:
+ return "LOGL";
+ case PHOTOMETRIC_LOGLUV:
+ return "LOGLUV";
+ default:
+ return "Unknown";
+ }
+}
+
struct tiff_header {
/* compulsory tiff data */
uint32_t w, h;
@@ -174,6 +206,9 @@ static GP_PixelType match_grayscale_pixel_type(TIFF *tiff,
}
switch (header->bits_per_sample) {
+ case 1:
+ GP_DEBUG(1, "Have 1bit Bitmap");
+ return GP_PIXEL_G1;
case 2:
GP_DEBUG(1, "Have 2bit Grayscale");
return GP_PIXEL_G2;
@@ -220,21 +255,19 @@ static GP_PixelType match_pixel_type(TIFF *tiff, struct tiff_header *header)
if (!TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &header->photometric))
return GP_PIXEL_UNKNOWN;
+ GP_DEBUG(1, "Have photometric %s",
+ photometric_name(header->photometric));
+
switch (header->photometric) {
/* 1-bit or 4, 8-bit grayscale */
- case 0:
- case 1:
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
return match_grayscale_pixel_type(tiff, header);
- break;
- /* RGB */
- case 2:
+ case PHOTOMETRIC_RGB:
return match_rgb_pixel_type(tiff, header);
- break;
- /* Palette */
- case 3:
- /* The palete is RGB161616 map it to BGR888 for now */
+ /* The palete is RGB161616 map it to BGR888 for now */
+ case PHOTOMETRIC_PALETTE:
return GP_PIXEL_RGB888;
- break;
default:
GP_DEBUG(1, "Unimplemented photometric interpretation %u",
(unsigned) header->photometric);
@@ -335,7 +368,7 @@ int tiff_read_palette(TIFF *tiff, GP_Context *res, struct tiff_header *header,
int tiff_read(TIFF *tiff, GP_Context *res, struct tiff_header *header,
GP_ProgressCallback *callback)
{
- uint32_t y;
+ uint32_t i, y;
uint16_t planar_config, samples, s;
GP_DEBUG(1, "Reading tiff data");
@@ -395,6 +428,11 @@ int tiff_read(TIFF *tiff, GP_Context *res, struct tiff_header *header,
default:
break;
}
+
+ /* We need to negate the values when Min is White */
+ if (header->photometric == PHOTOMETRIC_MINISWHITE)
+ for (i = 0; i < res->bytes_per_row; i++)
+ addr[i] = ~addr[i];
}
if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) {
@@ -433,8 +471,7 @@ GP_Context *GP_ReadTIFF(void *t, GP_ProgressCallback *callback)
}
switch (header.photometric) {
- /* Palette */
- case 3:
+ case PHOTOMETRIC_PALETTE:
err = tiff_read_palette(t, res, &header, callback);
break;
default:
-----------------------------------------------------------------------
Summary of changes:
libs/loaders/GP_TIFF.c | 63 ++++++++++++++++++++++++++++++++++++++----------
1 files changed, 50 insertions(+), 13 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via 7b45cc14bb03dac82ca26db54905482a3f809992 (commit)
via bd7e97d26552c0e97f36592f7270fe897951026b (commit)
via 5bc943fc5a47fa622d3083545c7141975d958b3d (commit)
via ccba73cabc5a6e324c97f61a557996fbc8f4b60b (commit)
via 541f03f55268a31766b13942a28e54c5fbf35dcb (commit)
via 1b859e4a9f90d27a0e64106c3e6188d6644db3e5 (commit)
via 824ecde7b09c940b797d014492e20a4b179fe030 (commit)
from 7cd59d01dfdab87e6047ba1ad04ad4351a685b44 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/7b45cc14bb03dac82ca26db54905482a3f80…
commit 7b45cc14bb03dac82ca26db54905482a3f809992
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 17:18:27 2013 +0200
loaders: TIFF: Write loader for basic types.
This adds loader support for most common tiff images.
So far we do not support tiled images, images with planar > 1
obscure and too big bits_per_samples.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/libs/loaders/GP_TIFF.c b/libs/loaders/GP_TIFF.c
index 3f4a4e9..89e936e 100644
--- a/libs/loaders/GP_TIFF.c
+++ b/libs/loaders/GP_TIFF.c
@@ -33,6 +33,9 @@
#include <string.h>
#include "../../config.h"
+
+#include "core/GP_Pixel.h"
+#include "core/GP_GetPutPixel.h"
#include "core/GP_Debug.h"
#include "GP_TIFF.h"
@@ -98,79 +101,357 @@ static const char *compression_name(uint16_t compression)
return "Unknown";
}
-GP_Context *GP_ReadTIFF(void *t, GP_ProgressCallback *callback)
-{
- uint32_t w, h, y, tile_w, tile_h, rows_per_strip;
- uint16_t compression, bpp;
- TIFF *tiff = t;
- TIFFRGBAImage img;
- GP_Context *res;
- int err;
+struct tiff_header {
+ /* compulsory tiff data */
+ uint32_t w, h;
+ uint16_t compress;
+ uint16_t bits_per_sample;
+
+ /* either strips or tiles should be set */
+ uint32_t rows_per_strip;
+
+ uint32_t tile_w;
+ uint32_t tile_h;
+ /* pixel type related values */
+ uint16_t photometric;
+};
+
+static int read_header(TIFF *tiff, struct tiff_header *header)
+{
/* all these fields are compulsory in tiff image */
- TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
- TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
- TIFFGetField(tiff, TIFFTAG_COMPRESSION, &compression);
- TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bpp);
+ if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &header->w)) {
+ GP_DEBUG(1, "Failed to read Width");
+ return EIO;
+ }
+
+ if (!TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &header->h)) {
+ GP_DEBUG(1, "Failed to read Height");
+ return EIO;
+ }
+
+ if (!TIFFGetField(tiff, TIFFTAG_COMPRESSION, &header->compress)) {
+ GP_DEBUG(1, "Failed to read Compression Type");
+ return EIO;
+ }
- GP_DEBUG(1, "TIFF image %ux%u compression: %s, bpp: %u",
- w, h, compression_name(compression), bpp);
+ if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE,
+ &header->bits_per_sample)) {
+ GP_DEBUG(1, "Failed to read Bits Per Sample");
+ return EIO;
+ }
+
+ GP_DEBUG(1, "TIFF image %ux%u Compression: %s, Bits Per Sample: %u",
+ header->w, header->h,
+ compression_name(header->compress), header->bits_per_sample);
/* If set tiff is saved in tiles */
- if (TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &tile_w) &&
- TIFFGetField(tiff, TIFFTAG_TILELENGTH, &tile_h)) {
- GP_DEBUG(1, "TIFF is tiled in %ux%u", tile_w, tile_h);
- err = ENOSYS;
- goto err1;
+ if (TIFFGetField(tiff, TIFFTAG_TILEWIDTH, &header->tile_w) &&
+ TIFFGetField(tiff, TIFFTAG_TILELENGTH, &header->tile_h)) {
+ GP_DEBUG(1, "TIFF is tiled in %ux%u",
+ header->tile_w, header->tile_h);
+ header->rows_per_strip = 0;
+ return 0;
}
- if (!TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &rows_per_strip)) {
- GP_DEBUG(1, "TIFF is not stored in strips");
- err = ENOSYS;
- goto err1;
- } else {
- GP_DEBUG(1, "TIFF rows_per_strip = %u", rows_per_strip);
+ if (!TIFFGetField(tiff, TIFFTAG_ROWSPERSTRIP, &header->rows_per_strip)) {
+ GP_DEBUG(1, "TIFF not saved in tiles nor strips");
+ return ENOSYS;
}
- res = GP_ContextAlloc(w, h, GP_PIXEL_xRGB8888);
+ GP_DEBUG(1, "TIFF is saved in strips");
- if (res == NULL) {
- err = errno;
- GP_WARN("Malloc failed");
- goto err1;
+ return 0;
+}
+
+static GP_PixelType match_grayscale_pixel_type(TIFF *tiff,
+ struct tiff_header *header)
+{
+ if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE,
+ &header->bits_per_sample)) {
+ GP_DEBUG(1, "Have 1bit Bitmap");
+ return GP_PIXEL_G1;
+ }
+
+ switch (header->bits_per_sample) {
+ case 2:
+ GP_DEBUG(1, "Have 2bit Grayscale");
+ return GP_PIXEL_G2;
+ case 4:
+ GP_DEBUG(1, "Have 4bit Grayscale");
+ return GP_PIXEL_G4;
+ case 8:
+ GP_DEBUG(1, "Have 8bit Grayscale");
+ return GP_PIXEL_G8;
+ case 16:
+ GP_DEBUG(1, "Have 16bit Grayscale");
+ return GP_PIXEL_G16;
+ default:
+ GP_DEBUG(1, "Unimplemented bits per sample %u",
+ (unsigned) header->bits_per_sample);
+ return GP_PIXEL_UNKNOWN;
+ }
+}
+
+static GP_PixelType match_rgb_pixel_type(TIFF *tiff, struct tiff_header *header)
+{
+ uint16_t samples;
+
+ if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples)) {
+ GP_DEBUG(1, "Failed to get Samples Per Pixel");
+ return EINVAL;
+ }
+
+ GP_DEBUG(1, "Have %u samples per pixel", (unsigned) samples);
+
+ uint16_t bps = header->bits_per_sample;
+
+ /* Mach RGB pixel type with given pixel sizes */
+ if (samples == 3)
+ return GP_PixelRGBLookup(bps, 0, bps, bps,
+ bps, 2*bps, 0, 0, 3*bps);
+
+ GP_DEBUG(1, "Unsupported");
+ return GP_PIXEL_UNKNOWN;
+}
+
+static GP_PixelType match_palette_pixel_type(TIFF *tiff, struct tiff_header *header)
+{
+ /* The palete is RGB161616 map it to BGR888 for now */
+ return GP_PIXEL_RGB888;
+}
+
+static GP_PixelType match_pixel_type(TIFF *tiff, struct tiff_header *header)
+{
+ if (!TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &header->photometric))
+ return GP_PIXEL_UNKNOWN;
+
+ switch (header->photometric) {
+ /* 1-bit or 4, 8-bit grayscale */
+ case 0:
+ case 1:
+ return match_grayscale_pixel_type(tiff, header);
+ break;
+ /* RGB */
+ case 2:
+ return match_rgb_pixel_type(tiff, header);
+ break;
+ /* Palette */
+ case 3:
+ return match_palette_pixel_type(tiff, header);
+ break;
+ default:
+ GP_DEBUG(1, "Unimplemented photometric interpretation %u",
+ (unsigned) header->photometric);
+ return GP_PIXEL_UNKNOWN;
+ }
+}
+
+uint16_t get_idx(uint8_t *row, uint32_t x, uint16_t bps)
+{
+ switch (bps) {
+ case 1:
+ return !!(row[x/8] & (1<<(7 - x%8)));
+ case 2:
+ return (row[x/4] >> (2*(3 - x%4))) & 0x03;
+ case 4:
+ return (row[x/2] >> (4*(!(x%2)))) & 0x0f;
+ case 8:
+ return row[x];
+ case 16:
+ return ((uint16_t*)row)[x];
+ }
+
+ GP_DEBUG(1, "Unsupported bits per sample %u", (unsigned) bps);
+ return 0;
+}
+
+int tiff_read_palette(TIFF *tiff, GP_Context *res, struct tiff_header *header,
+ GP_ProgressCallback *callback)
+{
+ if (TIFFIsTiled(tiff)) {
+ //TODO
+ return ENOSYS;
+ }
+
+ if (header->bits_per_sample > 48) {
+ GP_DEBUG(1, "Bits per sample too big %u",
+ (unsigned)header->bits_per_sample);
+ return EINVAL;
}
- char emsg[1024];
+ unsigned int palette_size = (1<<header->bits_per_sample);
+ uint16_t *palette_r, *palette_g, *palette_b;
+ uint32_t x, y, scanline_size;
+
+ GP_DEBUG(1, "Pallete size %u", palette_size);
- if (TIFFRGBAImageBegin(&img, tiff, 0, emsg) != 1) {
- GP_DEBUG(1, "TIFFRGBAImageBegin failed: %s", emsg);
- err = EINVAL;
- goto err2;
+ if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &palette_r, &palette_g, &palette_b)) {
+ GP_DEBUG(1, "Failed to read palette");
+ return EIO;
}
- for (y = 0; y < h; y += rows_per_strip) {
- void *row = GP_PIXEL_ADDR(res, 0, y);
+ scanline_size = TIFFScanlineSize(tiff);
+
+ GP_DEBUG(1, "Scanline size %u", (unsigned) scanline_size);
+
+ uint8_t buf[scanline_size];
+
+ /* Read image strips scanline by scanline */
+ for (y = 0; y < header->h; y++) {
+ if (TIFFReadScanline(tiff, buf, y, 0) != 1) {
+ //TODO: Make use of TIFF ERROR
+ GP_DEBUG(1, "Error reading scanline");
+ return EIO;
+ }
+
+ for (x = 0; x < header->w; x++) {
+ uint16_t i = get_idx(buf, x, header->bits_per_sample);
- if (TIFFReadRGBAStrip(tiff, y, row) != 1) {
- err = EINVAL;
- goto err2;
+ if (i >= palette_size) {
+ GP_WARN("Invalid palette index %u",
+ (unsigned) i);
+ i = 0;
+ }
+
+ GP_Pixel p = GP_Pixel_CREATE_RGB888(palette_r[i]>>8,
+ palette_g[i]>>8,
+ palette_b[i]>>8);
+
+ GP_PutPixel_Raw_24BPP(res, x, y, p);
}
- if (GP_ProgressCallbackReport(callback, y, h, w)) {
+ if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) {
GP_DEBUG(1, "Operation aborted");
- err = ECANCELED;
- goto err2;
+ return ECANCELED;
+ }
+ }
+
+ GP_ProgressCallbackDone(callback);
+ return 0;
+}
+
+//Temporary, the bitendians strikes again
+#include "core/GP_BitSwap.h"
+
+/*
+ * Direct read -> data in image are in right format.
+ */
+int tiff_read(TIFF *tiff, GP_Context *res, struct tiff_header *header,
+ GP_ProgressCallback *callback)
+{
+ uint32_t y;
+ uint16_t planar_config, samples, s;
+
+ GP_DEBUG(1, "Reading tiff data");
+
+ if (TIFFIsTiled(tiff)) {
+ //TODO
+ return ENOSYS;
+ }
+
+ //ASSERT ScanlineSize == w!
+
+ /* Figure out number of planes */
+ if (!TIFFGetField(tiff, TIFFTAG_PLANARCONFIG, &planar_config))
+ planar_config = 1;
+
+ switch (planar_config) {
+ case 1:
+ GP_DEBUG(1, "Planar config = 1, all samples are in one plane");
+ samples = 1;
+ break;
+ case 2:
+ if (!TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samples)) {
+ GP_DEBUG(1, "Planar config = 2, samples per pixel undefined");
+ return EINVAL;
}
+ GP_DEBUG(1, "Have %u samples per pixel", (unsigned)samples);
+ break;
+ default:
+ GP_DEBUG(1, "Unimplemented planar config = %u",
+ (unsigned)planar_config);
+ return EINVAL;
}
- TIFFRGBAImageEnd(&img);
+ /* Read image strips scanline by scanline */
+ for (y = 0; y < header->h; y++) {
+ uint8_t *addr = GP_PIXEL_ADDR(res, 0, y);
+
+ //TODO: Does not work with RowsPerStrip > 1 -> needs StripOrientedIO
+ for (s = 0; s < samples; s++) {
+ if (TIFFReadScanline(tiff, addr, y, s) != 1) {
+ //TODO: Make use of TIFF ERROR
+ GP_DEBUG(1, "Error reading scanline");
+ return EIO;
+ }
+
+ //Temporary, till bitendians are fixed
+ switch (res->pixel_type) {
+ case GP_PIXEL_G1:
+ GP_BitSwapRow_B1(addr, res->bytes_per_row);
+ break;
+ case GP_PIXEL_G2:
+ GP_BitSwapRow_B2(addr, res->bytes_per_row);
+ break;
+ case GP_PIXEL_G4:
+ GP_BitSwapRow_B4(addr, res->bytes_per_row);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (GP_ProgressCallbackReport(callback, y, res->h, res->w)) {
+ GP_DEBUG(1, "Operation aborted");
+ return ECANCELED;
+ }
+ }
GP_ProgressCallbackDone(callback);
- return res;
+ return 0;
+}
-err2:
- GP_ContextFree(res);
+GP_Context *GP_ReadTIFF(void *t, GP_ProgressCallback *callback)
+{
+ struct tiff_header header;
+ GP_Context *res = NULL;
+ GP_PixelType pixel_type;
+ int err;
+
+ if ((err = read_header(t, &header)))
+ goto err1;
+
+ pixel_type = match_pixel_type(t, &header);
+
+ if (pixel_type == GP_PIXEL_UNKNOWN) {
+ err = ENOSYS;
+ goto err1;
+ }
+
+ res = GP_ContextAlloc(header.w, header.h, pixel_type);
+
+ if (res == NULL) {
+ err = errno;
+ GP_DEBUG(1, "Malloc failed");
+ goto err1;
+ }
+
+ switch (header.photometric) {
+ /* Palette */
+ case 3:
+ err = tiff_read_palette(t, res, &header, callback);
+ break;
+ default:
+ err = tiff_read(t, res, &header, callback);
+ }
+
+ if (err)
+ goto err1;
+
+ return res;
err1:
+ GP_ContextFree(res);
errno = err;
return NULL;
}
http://repo.or.cz/w/gfxprim.git/commit/bd7e97d26552c0e97f36592f7270fe897951…
commit bd7e97d26552c0e97f36592f7270fe897951026b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 15:43:30 2013 +0200
backends: X11: Hotfix for Wait().
Hold the display lock only when processing events.
This fixes lock when main thread sleeps in backend->Wait() and some
other thread calls backend function that works with X11 connection.
The correct fix will be single backend Wait() with poll for all
backends that have filedescriptor to wait on.
Also add XFlush() after update_rect() (it was previously flushed
automatically by the XNextEvent() call).
Lastly but not least remove the WARNING from docs.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/doc/backends.txt b/doc/backends.txt
index 10127e6..7130b29 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -368,14 +368,6 @@ Blocks until backend event arrives.
Events received by backend are not necessarily translated into the input
events.
-[WARNING]
-Using GP_BackendWait() in multi-threaded program will most likely cause
-deadlocks. As the backend data structures and connection is guarded by a lock
-any other backend function (called from different thread while
-GP_BackendWait() is blocking) will lock until GP_BackendWait() returns (i.e.
-event was received).
-
-
GP_BackendWaitEvent
^^^^^^^^^^^^^^^^^^^
diff --git a/libs/backends/GP_X11.c b/libs/backends/GP_X11.c
index 7392202..8505edc 100644
--- a/libs/backends/GP_X11.c
+++ b/libs/backends/GP_X11.c
@@ -79,6 +79,8 @@ static void x11_update_rect(GP_Backend *self, GP_Coord x0, GP_Coord y0,
putimage(win, x0, y0, x1, y1);
+ XFlush(win->dpy);
+
XUnlockDisplay(win->dpy);
}
@@ -185,17 +187,13 @@ static void x11_poll(GP_Backend *self)
XUnlockDisplay(win->dpy);
}
+#include <poll.h>
+
static void x11_wait(GP_Backend *self)
{
- struct x11_win *win = GP_BACKEND_PRIV(self);
- XEvent ev;
-
- XLockDisplay(win->dpy);
-
- XNextEvent(win->dpy, &ev);
- x11_ev(&ev);
-
- XUnlockDisplay(win->dpy);
+ struct pollfd fd = {.fd = self->fd, .events = POLLIN, .revents = 0};
+ poll(&fd, 1, -1);
+ x11_poll(self);
}
static int resize_buffer(struct GP_Backend *self, uint32_t w, uint32_t h)
http://repo.or.cz/w/gfxprim.git/commit/5bc943fc5a47fa622d3083545c7141975d95…
commit 5bc943fc5a47fa622d3083545c7141975d958b3d
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 14:31:35 2013 +0200
spiv: Initialize sleep_ms correctly.
So that no timers are scheduled if -s param is not set.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c
index 9b34c35..287cc12 100644
--- a/demos/spiv/spiv.c
+++ b/demos/spiv/spiv.c
@@ -669,7 +669,7 @@ int main(int argc, char *argv[])
{
GP_Context *context = NULL;
const char *backend_opts = "X11";
- int sleep_ms = -1;
+ int sleep_ms = 0;
int opt;
int shift_flag;
GP_PixelType emul_type = GP_PIXEL_UNKNOWN;
http://repo.or.cz/w/gfxprim.git/commit/ccba73cabc5a6e324c97f61a557996fbc8f4…
commit ccba73cabc5a6e324c97f61a557996fbc8f4b60b
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 14:29:15 2013 +0200
libs: backends: BackendWait() fix.
Get the TimeStamp only when there are timers in timer queue.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/libs/backends/GP_Backend.c b/libs/backends/GP_Backend.c
index bcc7ac3..9bf2f7e 100644
--- a/libs/backends/GP_Backend.c
+++ b/libs/backends/GP_Backend.c
@@ -177,9 +177,9 @@ static void wait_timers_poll(GP_Backend *self)
void GP_BackendWait(GP_Backend *self)
{
- uint64_t now = GP_GetTimeStamp();
-
if (self->timers) {
+ uint64_t now = GP_GetTimeStamp();
+
/* Get rid of possibly expired timers */
if (GP_TimerQueueProcess(&self->timers, now))
return;
http://repo.or.cz/w/gfxprim.git/commit/541f03f55268a31766b13942a28e54c5fbf3…
commit 541f03f55268a31766b13942a28e54c5fbf35dcb
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 13:20:58 2013 +0200
backends: Add GP_BackendTimersInQueue() + docs.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/doc/backends.txt b/doc/backends.txt
index 874ba52..10127e6 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -432,6 +432,20 @@ backend 'Poll' or 'Wait' functions.
If timer callback is set to 'NULL' a timer event is pushed to the backend
input queue once timer has expired otherwise timer callback is called.
+GP_BackendTimersInQueue
+^^^^^^^^^^^^^^^^^^^^^^^
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <backends/GP_Backend.h>
+/* or */
+#include <GP.h>
+
+void GP_BackendTimersInQueue(GP_Backend *self);
+-------------------------------------------------------------------------------
+
+Returns number of timers scheduled in backend timer queue.
+
GP_BackendEventsQueued
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/include/backends/GP_Backend.h b/include/backends/GP_Backend.h
index f94252c..ec4af3b 100644
--- a/include/backends/GP_Backend.h
+++ b/include/backends/GP_Backend.h
@@ -212,6 +212,14 @@ int GP_BackendWaitEvent(GP_Backend *self, GP_Event *ev);
void GP_BackendAddTimer(GP_Backend *self, GP_Timer *timer);
/*
+ * Returns number of timers scheduled in backend.
+ */
+static inline unsigned int GP_BackendTimersInQueue(GP_Backend *self)
+{
+ return GP_TimerQueueSize(self->timers);
+}
+
+/*
* Sets backend caption, if supported.
*
* When setting caption is not possible/implemented non zero is returned.
http://repo.or.cz/w/gfxprim.git/commit/1b859e4a9f90d27a0e64106c3e6188d6644d…
commit 1b859e4a9f90d27a0e64106c3e6188d6644db3e5
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 12:59:37 2013 +0200
input: timers: Implement remove + docs.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/build/syms/Input_symbols.txt b/build/syms/Input_symbols.txt
index 700dedc..e6742b7 100644
--- a/build/syms/Input_symbols.txt
+++ b/build/syms/Input_symbols.txt
@@ -28,5 +28,6 @@ GP_EventQueuePushResize
GP_TimerQueueDump
GP_TimerQueueProcess
GP_TimerQueueInsert
+GP_TimerQueueRemove
GP_GetTimeStamp
diff --git a/demos/c_simple/timers.c b/demos/c_simple/timers.c
index 4e863c9..b914fe4 100644
--- a/demos/c_simple/timers.c
+++ b/demos/c_simple/timers.c
@@ -67,6 +67,10 @@ int main(void)
GP_TimerQueueDump(queue);
+ GP_TimerQueueRemove(&queue, &timers[MAX-1]);
+
+ GP_TimerQueueDump(queue);
+
for (now = 0; now < 100; now += 3) {
printf("NOW %un", (unsigned int) now);
printf("-------------------------------------n");
diff --git a/doc/input.txt b/doc/input.txt
index e92c5a5..aa69595 100644
--- a/doc/input.txt
+++ b/doc/input.txt
@@ -275,7 +275,7 @@ typedef struct GP_Timer {
Timers are implemented as a simple structure with a callback, expiration, id
string and internal heap pointers. The priority queue is described simply by
-the pointer to the top timer (soonest time to expire).
+the pointer to the top timer (soonest to expire).
The 'priv' pointer is used to pass a user pointer to the callback function.
@@ -315,6 +315,21 @@ at `now + timer->expire`.
/* or */
#include <input/GP_Timer.h>
+void GP_TimerQueueRemove(GP_Timer **queue, GP_Timer *timer);
+-------------------------------------------------------------------------------
+
+Removes timer from the queue.
+
+If timer is not found in the queue nothing is done but warning is printed.
+
+Runs in 'O(n)' time (the insert and process runs in 'O(nlog(n))').
+
+[source,c]
+-------------------------------------------------------------------------------
+#include <GP.h>
+/* or */
+#include <input/GP_Timer.h>
+
int GP_TimerQueueProcess(GP_Timer **queue, uint64_t now);
-------------------------------------------------------------------------------
@@ -325,6 +340,17 @@ into the queue with new expiration time.
Returns number of timers processed.
+[source,c]
+-------------------------------------------------------------------------------
+#include <GP.h>
+/* or */
+#include <input/GP_Timer.h>
+
+unsigned int GP_TimerQueueSize(GP_Timer *queue);
+-------------------------------------------------------------------------------
+
+Returns number of timers in the queue.
+
[[TimeStamp]]
TimerStamp
~~~~~~~~~~
diff --git a/include/input/GP_Timer.h b/include/input/GP_Timer.h
index 1debab2..9d6c8ed 100644
--- a/include/input/GP_Timer.h
+++ b/include/input/GP_Timer.h
@@ -78,10 +78,11 @@ void GP_TimerQueueDump(GP_Timer *queue);
void GP_TimerQueueInsert(GP_Timer **queue, uint64_t now, GP_Timer *timer);
/*
- * Removes timer from timer queue. Returns NULL if id was not found.
+ * Removes timer from timer queue.
+ *
+ * This operation (in contrast with insert and process) runs in O(n) time.
*/
-GP_Timer GP_TimerQueueRemove(GP_Timer *queue, GP_Timer *timer);
-GP_Timer GP_TimerQueueRemoveById(GP_Timer *queue, const char *id);
+void GP_TimerQueueRemove(GP_Timer **queue, GP_Timer *timer);
/*
* Processes queue, all timers with expires <= now are processed.
@@ -90,4 +91,12 @@ GP_Timer GP_TimerQueueRemoveById(GP_Timer *queue, const char *id);
*/
int GP_TimerQueueProcess(GP_Timer **queue, uint64_t now);
+/*
+ * Returns size of the queue, i.e. number of timers.
+ */
+static inline unsigned int GP_TimerQueueSize(GP_Timer *queue)
+{
+ return queue ? queue->sons + 1 : 0;
+}
+
#endif /* INPUT_GP_TIMER_H */
diff --git a/libs/input/GP_Timer.c b/libs/input/GP_Timer.c
index 3f4adfe..4ee1c10 100644
--- a/libs/input/GP_Timer.c
+++ b/libs/input/GP_Timer.c
@@ -198,6 +198,73 @@ void GP_TimerQueueInsert(GP_Timer **heap, uint64_t now, GP_Timer *timer)
*heap = insert(*heap, timer);
}
+static GP_Timer *rem(GP_Timer *heap, GP_Timer *timer, GP_Timer *last, int *flag)
+{
+ if (heap == NULL)
+ return NULL;
+
+ /* Found -> remove */
+ if (heap == timer) {
+ GP_DEBUG(3, "Timer found -> removing");
+
+ *flag = 1;
+
+ last->left = heap->left;
+ last->right = heap->right;
+ last->sons = heap->sons;
+
+ return bubble_down(last);
+ }
+
+ heap->left = rem(heap->left, timer, last, flag);
+ heap->right = rem(heap->right, timer, last, flag);
+
+ return heap;
+}
+
+static GP_Timer *pre_rem(GP_Timer *heap, GP_Timer *timer)
+{
+ GP_Timer *last;
+ int flag = 0;
+
+ if (!heap) {
+ GP_WARN("Attempt to remove timer %s from empty queue",
+ timer->id);
+ return NULL;
+ }
+
+ /*
+ * Remove last timer from the heap prior the removal,
+ * we will use it in place of the removed timer later.
+ */
+ heap = rem_last(heap, &last);
+
+ if (!heap) {
+ if (timer == last)
+ return NULL;
+
+ GP_WARN("Timer %s not found (queue has one timer)", timer->id);
+ return last;
+ }
+
+ heap = rem(heap, timer, last, &flag);
+
+ if (!flag) {
+ GP_WARN("Timer %s not found", timer->id);
+ /* reinsert the last element */
+ return insert(heap, last);
+ }
+
+ return heap;
+}
+
+void GP_TimerQueueRemove(GP_Timer **queue, GP_Timer *timer)
+{
+ GP_DEBUG(3, "Removing timer %s from queue", timer->id);
+
+ *queue = pre_rem(*queue, timer);
+}
+
static GP_Timer *process_top(GP_Timer *heap, uint64_t now)
{
GP_Timer *timer = heap;
http://repo.or.cz/w/gfxprim.git/commit/824ecde7b09c940b797d014492e20a4b179f…
commit 824ecde7b09c940b797d014492e20a4b179fe030
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Fri Jun 28 11:18:36 2013 +0200
doc: Remove trailing whitespaces.
This should be the last one.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/doc/api.txt b/doc/api.txt
index f005a82..709bb92 100644
--- a/doc/api.txt
+++ b/doc/api.txt
@@ -12,7 +12,7 @@ GFXprim API
+
. link:core.html[Library Core overview]
+
- Describes functions and macros in library core.
+ Describes functions and macros in library core.
+
. link:pixels.html[Pixel Types]
+
diff --git a/doc/backends.txt b/doc/backends.txt
index 151e654..874ba52 100644
--- a/doc/backends.txt
+++ b/doc/backends.txt
@@ -4,7 +4,7 @@ Drawing Backends
Drawing backends provide means to draw into computer screen or into a window
inside of running operating system. Instead of having one unified
initialization interface each backend has it's specific function and semantics
-but once backend is initialized the backend structure provides unified API for
+but once backend is initialized the backend structure provides unified API for
controlling the drawing.
So far there are backends for Linux mmaped 'frame-buffer', 'libSDL' and
@@ -92,7 +92,7 @@ X Server
enum GP_BackendX11Flags {
/* When set, w and h is ignored and root window is used */
GP_X11_USE_ROOT_WIN = 0x01,
-
+
/* Create new borderless window above the root window */
GP_X11_CREATE_ROOT_WIN = 0x02,
@@ -151,7 +151,7 @@ GP_BackendX11RequestFullscreen
/*
* Changes full screen mode.
- *
+ *
* 0 = off
* 1 = on
* 2 = toggle
@@ -206,15 +206,15 @@ typdef struct GP_Backend {
*/
const char *name;
- /*
+ /*
* Pointer to context APP should draw to.
*/
GP_Context *context;
...
- /*
- * Connection fd. Set to -1 if not available
+ /*
+ * Connection fd. Set to -1 if not available
*/
int fd;
};
@@ -293,7 +293,7 @@ GP_BackendPoll
void GP_BackendPoll(GP_Backend *backend);
-------------------------------------------------------------------------------
-Polls for backend events.
+Polls for backend events.
The poll only reads events from event source (i.e. X11 socket, Linux evdev
file descriptor), process them and may place new event into the backend event
@@ -345,7 +345,7 @@ otherwise.
while (GP_BackendPollEvent(backend, &ev) {
/* process events */
-
+
}
-------------------------------------------------------------------------------
diff --git a/doc/backends_python.txt b/doc/backends_python.txt
index 48f5e01..65ff893 100644
--- a/doc/backends_python.txt
+++ b/doc/backends_python.txt
@@ -23,7 +23,7 @@ import gfxprim.backends as backends
# Create 100x100 X11 window
bk = backends.BackendX11Init(None, x, y, w, h, "Window title", 0)
-
+
# Assert that inicialization was successful
assert(bk)
@@ -58,7 +58,7 @@ import gfxprim.backends as backends
# Initialize backend by init string
bk = backends.BackendInit(backend_string, "Window title", stderr)
-
+
# Assert that inicialization was successful
assert(bk)
@@ -83,7 +83,7 @@ import gfxprim.backends as backends
# Initialize backend
bk = backends.BackendInit("X11:100x100", "Window title", stderr)
-
+
# Assert that inicialization was successful
assert(bk)
@@ -106,11 +106,11 @@ movements.
import gfxprim.core as core
import gfxprim.input as input
import gfxprim.backends as backends
-
-
+
+
# Initialize backend
bk = backends.BackendInit("X11:100x100", "Window title", stderr)
-
+
# Assert that inicialization was successful
assert(bk)
diff --git a/doc/context.txt b/doc/context.txt
index df6ff47..ea7d5ba 100644
--- a/doc/context.txt
+++ b/doc/context.txt
@@ -15,7 +15,7 @@ typedef struct GP_Context {
uint32_t bytes_per_row;
uint32_t w; /* width in pixels */
uint32_t h; /* height in pixels */
- /*
+ /*
* Row bit offset. The offset is ignored for byte aligned pixels.
* Basically it's used for non aligned pixels with combination
* with subcontextes.
@@ -81,7 +81,7 @@ GP_TRANSFORM_POINT(context, x, y)
GP_TRANSFORM_RECT(context, x, y, w, h)
/* Inverse transformation, bitmap coordinates to user coordinates */
-GP_RETRANSFORM_POINT(context, x, y)
+GP_RETRANSFORM_POINT(context, x, y)
-------------------------------------------------------------------------------
[source,c]
@@ -91,7 +91,7 @@ GP_RETRANSFORM_POINT(context, x, y)
#include <GP.h>
/*
- * Rotate context flags clock wise.
+ * Rotate context flags clock wise.
*/
void GP_ContextRotateCW(GP_Context *context);
@@ -170,11 +170,11 @@ appropriate size; the initial contents of the bitmap are undefined.
#include <GP.h>
enum GP_ContextCopyFlags {
- /*
+ /*
* Copy bitmap pixels too. If not set pixels are uninitialized.
*/
GP_COPY_WITH_PIXELS = 0x01,
- /*
+ /*
* Copy image rotation flags. If not set flags are set to (0, 0, 0).
*/
GP_COPY_WITH_ROTATION = 0x02,
@@ -266,7 +266,7 @@ Conversions
#include <GP.h>
GP_Context *GP_ContextConvertAlloc(const GP_Context *src,
- GP_PixelType dst_pixel_type);
+ GP_PixelType dst_pixel_type);
GP_Context *GP_ContextConvert(const GP_Context *src, GP_Context *dst);
diff --git a/doc/core.txt b/doc/core.txt
index ec172a2..c7148fa 100644
--- a/doc/core.txt
+++ b/doc/core.txt
@@ -34,7 +34,7 @@ GP_CONTAINER_OF(ptr, structure, member);
These common macros implements basic functions such as minimum, maximum,
absolute value, swap and sign.
-All macros use 'typeof()' in order to evaluate their arguments exactly once.
+All macros use 'typeof()' in order to evaluate their arguments exactly once.
The 'GP_ARRAY_SIZE()' macro computes size of statically defined array (i.e.
returns +sizeof(array) / sizeof(elem)+).
diff --git a/doc/core_python.txt b/doc/core_python.txt
index 3e7256f..cd60469 100644
--- a/doc/core_python.txt
+++ b/doc/core_python.txt
@@ -27,7 +27,7 @@ import gfxprim.core as core
Creates a context of a particular size and pixel type.
First two parameters are 'width' and 'height' third is pixel type which is an
-enumeration
+enumeration
May raise 'OSError' with 'ENOMEM' errno if allocation has failed.
@@ -78,7 +78,7 @@ import gfxprim.core as core
# sx and sy in the source context
# tx and ty in in the target
context.Blit(sx, sy, target, tx, ty, w, h)
-
+
# Alternatively the size can be described by
# coordinates in the source or target
context.Blit(sx, sy, target, tx, ty, sx2=, sy2=)
@@ -100,7 +100,7 @@ Colors and Pixels
~~~~~~~~~~~~~~~~~
Pixel in gfxprim is a number large enough to store a pixel value. Pixel is
-passed as a parameter to all drawing functions.
+passed as a parameter to all drawing functions.
Color is a more abstract representation for example RGB triplet.
@@ -133,7 +133,7 @@ import gfxprim.core as core
-------------------------------------------------------------------------------
-The PixelTypes array stores all supported pixel types
+The PixelTypes array stores all supported pixel types
Debug Functions
~~~~~~~~~~~~~~~
diff --git a/doc/debug.txt b/doc/debug.txt
index cdc3d4b..aedef2a 100644
--- a/doc/debug.txt
+++ b/doc/debug.txt
@@ -3,7 +3,7 @@ Debug Messages
The GFXprim library includes a debug message infrastructure in order to ease
the debugging.
-
+
Many places of the library uses debug messages to report warnings, bugs, or
generally important events (i.e. context has been allocated, filter function
has been called).
diff --git a/doc/filter_additive_gaussian_noise.txt b/doc/filter_additive_gaussian_noise.txt
index c64de38..8acba98 100644
--- a/doc/filter_additive_gaussian_noise.txt
+++ b/doc/filter_additive_gaussian_noise.txt
@@ -40,27 +40,27 @@ TIP: See the link:example_gaussian_noise.html[source code] used to generate
.Original Image; Gaussian Additive Noise s=0.01, s=0.02, s=0.05, s=0.7, s=0.1, s=0.05 m=0.1, s=0.05 m=-0.1
image:images/dither/lenna_small.png[
- "Original Image",
+ "Original Image",
link="images/dither/lenna.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_01_m_0.png[
- "Additive Noise sigma = 0.01 mu = 0.0",
+ "Additive Noise sigma = 0.01 mu = 0.0",
link="images/gaussian_noise/lenna_noise_s_0_01_m_0.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_02_m_0.png[
- "Additive Noise sigma = 0.02 mu = 0.0",
+ "Additive Noise sigma = 0.02 mu = 0.0",
link="images/gaussian_noise/lenna_noise_s_0_02_m_0.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_05_m_0.png[
- "Additive Noise sigma = 0.05 mu = 0.0",
+ "Additive Noise sigma = 0.05 mu = 0.0",
link="images/gaussian_noise/lenna_noise_s_0_05_m_0.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_07_m_0.png[
- "Additive Noise sigma = 0.07 mu = 0.0",
+ "Additive Noise sigma = 0.07 mu = 0.0",
link="images/gaussian_noise/lenna_noise_s_0_07_m_0.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_1_m_0.png[
- "Additive Noise sigma = 0.1 mu = 0.0",
+ "Additive Noise sigma = 0.1 mu = 0.0",
link="images/gaussian_noise/lenna_noise_s_0_1_m_0.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_05_m_0_1.png[
- "Additive Noise sigma = 0.1 mu = 0.1",
+ "Additive Noise sigma = 0.1 mu = 0.1",
link="images/gaussian_noise/lenna_noise_s_0_05_m_0_1.png"]
image:images/gaussian_noise/lenna_small_noise_s_0_05_m_-0_1.png[
- "Additive Noise sigma = 0.1 mu = -0.1",
+ "Additive Noise sigma = 0.1 mu = -0.1",
link="images/gaussian_noise/lenna_noise_s_0_05_m_-0_1.png"]
diff --git a/doc/filters.txt b/doc/filters.txt
index c4f2049..106be48 100644
--- a/doc/filters.txt
+++ b/doc/filters.txt
@@ -236,7 +236,7 @@ Brightness filter, increments all pixel channels by a fixed value.
-------------------------------------------------------------------------------
#include <GP_Filters.h>
-GP_Context *GP_FilterContrast(const GP_Context *src, GP_Context *dst,
+GP_Context *GP_FilterContrast(const GP_Context *src, GP_Context *dst,
float mul, GP_ProgressCallback *callback);
-------------------------------------------------------------------------------
@@ -537,7 +537,7 @@ filter operates on.
The dst coordinates defines offset into the dst context.
The kernel is two-dimensional array of a size kw * kh indexed as
-kernel[x + y*kw].
+kernel[x + y*kw].
The kern_div is a coefficient that is used to divide the resulting values often
used to normalize the result.
@@ -613,7 +613,7 @@ The dst coordinates are offset into the dst.
The kernel is one-dimensional array of floats of size kw or kh.
-The kern_div is a coefficient that is used to divide the resulting values.
+The kern_div is a coefficient that is used to divide the resulting values.
The last function does both vertical and horizontal convolution and takes care
of correct progress callback.
@@ -660,7 +660,7 @@ NOTE: The number of kernel rows and columns is expected to be odd number.
NOTE: The linear convolutions are internally implemented using integer
arithmetics, which works fine, but you need to take a care not to
overflow 32bit signed integer. If the pixel channel size is 8bit
- long and 10bits are used for the fixed point part of the number
+ long and 10bits are used for the fixed point part of the number
the rest must fit into about 10 bits to be safe.
[source,c]
@@ -775,7 +775,7 @@ The convolution kernel is defined as:
begin{bmatrix}
0 & 0 & 0 \
1 & -2 & 1 \
-0 & 0 & 0
+0 & 0 & 0
end{bmatrix}
=
begin{bmatrix}
@@ -817,16 +817,16 @@ O(x,y) = I(x,y) - w * I''(x,y)
.Original Image; Edge Sharpening w=0.1, w=0.3, w=0.5
image:images/dither/lenna_small.png[
- "Original Image",
+ "Original Image",
link="images/dither/lenna.png"]
image:images/edge_sharpening/lenna_small_w_0_1.png[
- "Edge Sharpening w=0.1",
+ "Edge Sharpening w=0.1",
link="images/edge_sharpening/lenna_w_0_1.png"]
image:images/edge_sharpening/lenna_small_w_0_3.png[
- "Edge Sharpening w=0.5",
+ "Edge Sharpening w=0.5",
link="images/edge_sharpening/lenna_w_0_3.png"]
image:images/edge_sharpening/lenna_small_w_0_5.png[
- "Edge Sharpening w=0.5",
+ "Edge Sharpening w=0.5",
link="images/edge_sharpening/lenna_w_0_5.png"]
Gaussian Blur
@@ -962,7 +962,7 @@ int GP_FilterFloydSteinberg_RGB888(const GP_Context *src,
-------------------------------------------------------------------------------
Renders Floyd Steinberg dithering directly into passed context. The
-destination must be at least as large as source.
+destination must be at least as large as source.
If operation was aborted by a callback, non-zero is returned.
@@ -984,7 +984,7 @@ Hilbert-Peano
^^^^^^^^^^^^^
Hilbert-Peano space filling curve based dithering.
-
+
The error value is distributed around the Hilbert curve.
The result is a little more noisy, but doesn't create repeating patterns like
@@ -1001,7 +1001,7 @@ int GP_FilterHilbertPeano_RGB888(const GP_Context *src,
-------------------------------------------------------------------------------
Renders Hilbert Peano dithering directly into passed context. The
-destination must be at least as large as source.
+destination must be at least as large as source.
If operation was aborted by a callback, non-zero is returned.
@@ -1026,7 +1026,7 @@ All following images were generated using 'grinder'.
.Original Image; Floyd-Steinberg, Hilbert-Peano: 1-bit, 2-bit, 4-bit, 8-bit Grayscale; 1-bit, 2-bit, 3-bit (per channel) RGB
image:images/dither/lenna_small.png[
- "Original Image",
+ "Original Image",
link="images/dither/lenna.png"]
image:images/dither/lenna_G1_FS_small.png[
"1-bit Grayscale Floyd-Steinberg",
@@ -1113,7 +1113,7 @@ rectangle of 2 * xmed + 1 x 2 * ymed + 1 pixels.
.Original Image; Median 3x3, 5x5, 7x7, 9x9
image:images/dither/lenna_small.png[
- "Original Image",
+ "Original Image",
link="images/dither/lenna.png"]
image:images/median/lenna_small_med_3_3.png[
"Median 3x3",
diff --git a/doc/gamma.txt b/doc/gamma.txt
index f15f072..317900a 100644
--- a/doc/gamma.txt
+++ b/doc/gamma.txt
@@ -48,8 +48,8 @@ order not to loose precision.
The pointers to gamma tables are storied in 'GP_Gamma' structure and are
organized in the same order as channels. First N tables for each channel and
-gamma value gamma, then N tables for inverse 1/gamma function.
-
+gamma value gamma, then N tables for inverse 1/gamma function.
+
So when we have RGB888 pixel and gamma 2.2 there are two tables in the memory,
one for gamma 2.2 input 8bit output 10bit and it's inverse input 10bit output
8bit. The 'GP_Gamma' contains six pointers. First three points to the gamma
@@ -81,7 +81,7 @@ gamma->tables[chan_count + chan_number].u8[chan_val]
gamma->tables[chan_count + chan_number].u16[chan_val]
-/*
+/*
* When doing more than one conversion it's better to save pointers to
* individual table (example for RGB888):
*/
diff --git a/doc/gen.txt b/doc/gen.txt
index 3f3c0d8..23edf2b 100644
--- a/doc/gen.txt
+++ b/doc/gen.txt
@@ -28,7 +28,7 @@ class PixelSize(object):
def needs_bit_endian(self):
...
-
+
...
-------------------------------------------------------------------------------
@@ -74,7 +74,7 @@ BE
["graphviz", "bit-endian-be-1bit.png"]
------------------------------------------------------------------------------
digraph bit_endian {
- graph [ dpi = 70 ];
+ graph [ dpi = 70 ];
node [shape = record];
rankdir = LR;
@@ -94,7 +94,7 @@ digraph bit_endian {
["graphviz", "bit-endian-be-2bits.png"]
------------------------------------------------------------------------------
digraph bit_endian {
- graph [ dpi = 70 ];
+ graph [ dpi = 70 ];
node [shape = record];
rankdir = LR;
@@ -117,7 +117,7 @@ LE
["graphviz", "bit-endian-le-1bit.png"]
------------------------------------------------------------------------------
digraph bit_endian {
- graph [ dpi = 70 ];
+ graph [ dpi = 70 ];
node [shape = record];
rankdir = LR;
@@ -137,7 +137,7 @@ digraph bit_endian {
["graphviz", "bit-endian-le-2bits.png"]
------------------------------------------------------------------------------
digraph bit_endian {
- graph [ dpi = 70 ];
+ graph [ dpi = 70 ];
node [shape = record];
rankdir = LR;
diff --git a/doc/grabbers.txt b/doc/grabbers.txt
index ce71654..65dd71d 100644
--- a/doc/grabbers.txt
+++ b/doc/grabbers.txt
@@ -27,8 +27,8 @@ typdef struct GP_Grabber {
* Currently loaded frame.
*/
GP_Context *frame;
-
- /*
+
+ /*
* Connection fd usable for select() or poll().
*
* Set to -1 if not available.
diff --git a/doc/input.txt b/doc/input.txt
index 5db6158..e92c5a5 100644
--- a/doc/input.txt
+++ b/doc/input.txt
@@ -35,18 +35,18 @@ typedef struct GP_Event {
/* input device id */
uint32_t dev_id;
-
+
/* event timestamp */
struct timeval time;
- /*
+ /*
* Cursor position, position on screen accumulated
* from all pointer devices
*/
uint32_t cursor_x;
uint32_t cursor_y;
- /*
+ /*
* Bitmap of pressed keys including mouse buttons
* accumulated for all input devices.
*/
@@ -145,7 +145,7 @@ struct GP_EventSys {
The event 'value' is a union that could hold different information. The right
format of the data is known from the 'type' and 'code'. Some types of the
events has no value at all.
-
+
* The relative coordinates are used for 'GP_EV_REL_POS' and absolute coordinates
for 'GP_EV_ABS_POS'.
@@ -157,7 +157,7 @@ events has no value at all.
This image shows GFXprim key names without the 'GP_KEY_' prefix (Click for a
higher resolution). So for example 'LEFTSHIFT' on the image is
'GP_KEY_LEFT_SHIFT'.
-+
++
[[Keyboard Layout]]
.GFXprim key names without the 'GP_KEY_' prefix.
image::keyboard.svg["Keyboard Layout",width=800,link="keyboard.svg"]
@@ -259,8 +259,8 @@ typedef struct GP_Timer {
/* Timer id, showed in debug messages */
char id[10];
- /*
- * Timer Callback
+ /*
+ * Timer Callback
*
* If non-zero is returned, the timer is rescheduled to expire
* return value from now.
@@ -277,7 +277,7 @@ Timers are implemented as a simple structure with a callback, expiration, id
string and internal heap pointers. The priority queue is described simply by
the pointer to the top timer (soonest time to expire).
-The 'priv' pointer is used to pass a user pointer to the callback function.
+The 'priv' pointer is used to pass a user pointer to the callback function.
The number of timers in the queue is the number of sons of the top timer plus
one.
@@ -294,7 +294,7 @@ variables corresponds to the structure members.
void GP_TimerQueueDump(GP_Timer *queue);
-------------------------------------------------------------------------------
-
+
Prints the structure of binary heap into stdout, only for debugging.
[source,c]
diff --git a/doc/loaders.txt b/doc/loaders.txt
index 95eb780..fd10817 100644
--- a/doc/loaders.txt
+++ b/doc/loaders.txt
@@ -16,7 +16,7 @@ All saving functions returns zero on success and non-zero on failure. If
image saving is aborted by a callback, the opened file is closed and removed
from a filesystem before the call returns.
-In case of a failure 'errno' is set.
+In case of a failure 'errno' is set.
The signature matching functions takes a 32 bytes long buffer and looks for a
valid image signature. If signature is found 1 is returned.
@@ -48,7 +48,7 @@ Image Loader
GP_Context *GP_LoadImage(const char *src_path, GP_ProgressCallback *callback);
-------------------------------------------------------------------------------
-Loads image from a file.
+Loads image from a file.
The image format is first guessed by the file extension. If loader for the
file extension is found it's called and if it succedes the image data is
@@ -88,7 +88,7 @@ Advanced usage
[source,c]
-------------------------------------------------------------------------------
typedef struct GP_Loader {
- /*
+ /*
* Loads an image.
*
* Returns allocated and initialized bitmap on success, NULL on failure
@@ -96,13 +96,13 @@ typedef struct GP_Loader {
*/
GP_Context *(*Load)(const char *src_path, GP_ProgressCallback *callback);
- /*
+ /*
* Save an image.
*
* Returns zero on succes, non-zero on failure and errno must be set.
*/
int (*Save)(const GP_Context *src, const char *dst_path,
- GP_ProgressCallback *callback);
+ GP_ProgressCallback *callback);
/*
* The buffer is filled with 32 bytes from an image start, returns 1 if
@@ -117,7 +117,7 @@ typedef struct GP_Loader {
/* don't touch */
struct GP_Loader *next;
-
+
/*
* NULL terminated array of file extensions.
*/
@@ -143,7 +143,7 @@ void GP_LoaderUnregister(GP_Loader *self);
The 'GP_Loader' structure describes an image loader.
The 'Load', 'Save' and 'Match' functions could be 'NULL' if the particular
-functionality is not implemented.
+functionality is not implemented.
The 'fmt_name' is a short string that describes the format. For example:
'Netbpm portable pixmap'.
@@ -248,7 +248,7 @@ int GP_SavePNG(const GP_Context *src, const char *dst_path,
Currently only 'RGB888' format is supported, you should convert the
'GP_Context' to 'RGB888' before calling this function otherwise non-zero is
-returned and 'errno' is set to 'ENOSYS'.
+returned and 'errno' is set to 'ENOSYS'.
[source,c]
-------------------------------------------------------------------------------
diff --git a/doc/loaders_python.txt b/doc/loaders_python.txt
index 992cd07..8fa511a 100644
--- a/doc/loaders_python.txt
+++ b/doc/loaders_python.txt
@@ -43,7 +43,7 @@ import gfxprim.loaders as loaders
img.loaders.SavePNG(path, callback=None)
img.loaders.SaveJPG(path, callback=None)
-
+
img.loaders.SaveBMP(path, callback=None)
-------------------------------------------------------------------------------
diff --git a/doc/pixel_types.txt b/doc/pixel_types.txt
index b54ad7a..ee0111c 100644
--- a/doc/pixel_types.txt
+++ b/doc/pixel_types.txt
@@ -12,7 +12,7 @@ Pixel sizes 1, 2 and 4 depend on bit-endian setting and are supported on all sys
Subcontext operations and blits may be slower in case of a different subpixel alignment.
Pixel sizes not divisible by 8 and between 9 and 23 depend on the bit endian -
-the endianity of the system must match the bit-endianity. The other combination
+the endianity of the system must match the bit-endianity. The other combination
is not supported at all - it would be too complicated and probably very inefficient
to decode/encode.
@@ -44,7 +44,7 @@ format, as long as it is not used (compile-time warning is generated).
Bit-endianity
-------------
-With 1, 2 and 4 bpp formats, there are two possible orders of pixels within a byte,
+With 1, 2 and 4 bpp formats, there are two possible orders of pixels within a byte,
both seen in the wild. The two are enumerated in `GP_BIT_ENDIAN`:
`GP_BIT_ENDIAN_LE`::
-----------------------------------------------------------------------
Summary of changes:
build/syms/Input_symbols.txt | 1 +
demos/c_simple/timers.c | 4 +
demos/spiv/spiv.c | 2 +-
doc/api.txt | 2 +-
doc/backends.txt | 38 ++--
doc/backends_python.txt | 12 +-
doc/context.txt | 12 +-
doc/core.txt | 2 +-
doc/core_python.txt | 8 +-
doc/debug.txt | 2 +-
doc/filter_additive_gaussian_noise.txt | 16 +-
doc/filters.txt | 28 ++--
doc/gamma.txt | 6 +-
doc/gen.txt | 10 +-
doc/grabbers.txt | 4 +-
doc/input.txt | 46 +++-
doc/loaders.txt | 16 +-
doc/loaders_python.txt | 2 +-
doc/pixel_types.txt | 4 +-
include/backends/GP_Backend.h | 8 +
include/input/GP_Timer.h | 15 +-
libs/backends/GP_Backend.c | 4 +-
libs/backends/GP_X11.c | 16 +-
libs/input/GP_Timer.c | 67 ++++++
libs/loaders/GP_TIFF.c | 375 ++++++++++++++++++++++++++++----
25 files changed, 550 insertions(+), 150 deletions(-)
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project gfxprim.git.
The branch, master has been updated
via 88500942a4e2dda6951c5abaf6bc05e4bb5d6efc (commit)
via d6f1b011de7a541ecd56b6479d649bb8d6a26109 (commit)
via a45c066497e510b339d3b9280859530ecf6e5b0c (commit)
from b287df058124c3d9039a8bfe5475927a1d5fc68e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/gfxprim.git/commit/88500942a4e2dda6951c5abaf6bc05e4bb5d…
commit 88500942a4e2dda6951c5abaf6bc05e4bb5d6efc
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Jun 27 20:26:39 2013 +0200
tests: runtest.py: Print name of tests directory.
Prints name of tests directory we are about to run testsuite from.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/tests/runtests.py b/tests/runtests.py
index d6619a5..8cd1477 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -98,10 +98,11 @@ def run_tests(resdir, testsdir):
runtest = path + '/test_list.txt'
if (os.access(runtest, os.R_OK)):
- # Create result directory
+ # Create result directory
curresdir = resdir + '/' + name
os.mkdir(curresdir)
# Run tests
+ print("n========= Running " + name + " testsuites =========n")
run_test(curresdir, path, runtest)
def main():
http://repo.or.cz/w/gfxprim.git/commit/d6f1b011de7a541ecd56b6479d649bb8d6a2…
commit d6f1b011de7a541ecd56b6479d649bb8d6a26109
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Jun 27 20:22:20 2013 +0200
tests: input: Simple test for TimeStamp.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/tests/input/Makefile b/tests/input/Makefile
index e5e49bc..7f8726c 100644
--- a/tests/input/Makefile
+++ b/tests/input/Makefile
@@ -2,9 +2,9 @@ TOPDIR=../..
include $(TOPDIR)/pre.mk
-CSOURCES=Timer.c
+CSOURCES=Timer.c TimeStamp.c
-APPS=Timer
+APPS=Timer TimeStamp
include ../tests.mk
diff --git a/tests/input/TimeStamp.c b/tests/input/TimeStamp.c
new file mode 100644
index 0000000..5ab2dc2
--- /dev/null
+++ b/tests/input/TimeStamp.c
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * This file is part of gfxprim library. *
+ * *
+ * Gfxprim is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2.1 of the License, or (at your option) any later version. *
+ * *
+ * Gfxprim is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with gfxprim; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301 USA *
+ * *
+ * Copyright (C) 2009-2013 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+/*
+
+ Test for TimeStamp monotonicity.
+
+ */
+
+#include <stdlib.h>
+#include <input/GP_TimeStamp.h>
+
+#include "tst_test.h"
+
+#define MAX 2048
+
+static int time_stamp_monotonicity(void)
+{
+ uint64_t ts = 0, nts;
+ int i, fail = 0;
+
+ for (i = 0; i < MAX; i++) {
+ nts = GP_GetTimeStamp();
+ if (nts < ts) {
+ tst_msg("TimeStamp failed at %i %llu < %llu", i,
+ (long long unsigned)nts,
+ (long long unsigned) ts);
+ fail++;
+ }
+ }
+
+ if (fail)
+ return TST_FAILED;
+
+ return TST_SUCCESS;
+}
+
+const struct tst_suite tst_suite = {
+ .suite_name = "TimeStamp Testsuite",
+ .tests = {
+ {.name = "TimeStamp monotonicity",
+ .tst_fn = time_stamp_monotonicity},
+ {.name = NULL},
+ }
+};
http://repo.or.cz/w/gfxprim.git/commit/a45c066497e510b339d3b9280859530ecf6e…
commit a45c066497e510b339d3b9280859530ecf6e5b0c
Author: Cyril Hrubis <metan(a)ucw.cz>
Date: Thu Jun 27 20:16:57 2013 +0200
tests: input: Add timers testsuite.
Signed-off-by: Cyril Hrubis <metan(a)ucw.cz>
diff --git a/tests/Makefile b/tests/Makefile
index 6eb167d..56d5c28 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,7 +1,7 @@
TOPDIR=..
include $(TOPDIR)/pre.mk
-SUBDIRS=core framework loaders gfx filters
+SUBDIRS=core framework loaders gfx filters input
loaders: framework
gfx: framework
diff --git a/tests/input/Makefile b/tests/input/Makefile
new file mode 100644
index 0000000..e5e49bc
--- /dev/null
+++ b/tests/input/Makefile
@@ -0,0 +1,12 @@
+TOPDIR=../..
+
+include $(TOPDIR)/pre.mk
+
+CSOURCES=Timer.c
+
+APPS=Timer
+
+include ../tests.mk
+
+include $(TOPDIR)/app.mk
+include $(TOPDIR)/post.mk
diff --git a/tests/input/Timer.c b/tests/input/Timer.c
new file mode 100644
index 0000000..34ce1eb
--- /dev/null
+++ b/tests/input/Timer.c
@@ -0,0 +1,207 @@
+/*****************************************************************************
+ * This file is part of gfxprim library. *
+ * *
+ * Gfxprim is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2.1 of the License, or (at your option) any later version. *
+ * *
+ * Gfxprim is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with gfxprim; if not, write to the Free Software *
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
+ * Boston, MA 02110-1301 USA *
+ * *
+ * Copyright (C) 2009-2013 Cyril Hrubis <metan(a)ucw.cz> *
+ * *
+ *****************************************************************************/
+
+/*
+
+ Test for Timers code.
+
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <input/GP_Timer.h>
+
+#include "tst_test.h"
+
+static uint32_t callback_set_priv(GP_Timer *self)
+{
+ self->priv = (void*)1;
+
+ return 0;
+}
+
+static int callback_is_called(void)
+{
+ GP_TIMER_DECLARE(timer, 10, 0, "Timer", callback_set_priv, NULL);
+ GP_Timer *head = NULL;
+ int fail = 0;
+
+ GP_TimerQueueInsert(&head, 10, &timer);
+
+ /* Now call process before the timer expiration */
+ if (GP_TimerQueueProcess(&head, 10)) {
+ tst_msg("GP_TimerQueueProcess() reported non-zero");
+ fail++;
+ }
+
+ if (timer.priv) {
+ tst_msg("Callback was called");
+ fail++;
+ }
+
+ /* Now call process after the expiration time */
+ if (GP_TimerQueueProcess(&head, 30) != 1) {
+ tst_msg("GP_TimerQueueProcess() reported wrong number");
+ fail++;
+ }
+
+ if (!timer.priv) {
+ tst_msg("Callback was not called");
+ fail++;
+ }
+
+ if (fail)
+ return TST_FAILED;
+
+ return TST_SUCCESS;
+}
+
+#define MAX 2048
+
+static int monotonicity_failed = 0;
+static uint64_t prev_expires;
+
+static uint32_t callback_check_monotonicity(GP_Timer *self)
+{
+ if (self->expires < prev_expires) {
+ monotonicity_failed = 1;
+ tst_msg("Wrong order of expirations detected");
+ }
+
+ prev_expires = self->expires;
+
+ return 0;
+}
+
+static int expirations_sorted(void)
+{
+ GP_Timer *head = NULL;
+ GP_Timer timers[MAX];
+ int i;
+ uint64_t expires;
+
+ for (i = 0; i < MAX; i++) {
+ timers[i].expires = random();
+ timers[i].period = 0;
+ timers[i].Callback = callback_check_monotonicity;
+ timers[i].priv = &expires;
+ strcpy(timers[i].id, "Timer");
+ GP_TimerQueueInsert(&head, 0, &timers[i]);
+ }
+
+ prev_expires = head->expires;
+
+ for (i = 0; i < MAX; i++)
+ GP_TimerQueueProcess(&head, head ? head->expires : 0);
+
+ if (monotonicity_failed)
+ return TST_FAILED;
+
+ return TST_SUCCESS;
+}
+
+static int process_with_NULL_head(void)
+{
+ GP_Timer *head = NULL;
+
+ if (GP_TimerQueueProcess(&head, 1024)) {
+ tst_msg("GP_TimerQueueProcess returned non-zero");
+ return TST_FAILED;
+ }
+
+ return TST_SUCCESS;
+}
+
+/*
+ * Test that periodic timers are rescheduled
+ */
+static int periodic_timers(void)
+{
+ GP_TIMER_DECLARE(timer1, 0, 10, "Timer1", callback_set_priv, NULL);
+ GP_TIMER_DECLARE(timer2, 0, 20, "Timer2", callback_set_priv, NULL);
+ GP_Timer *head = NULL;
+ int fail = 0;
+
+ GP_TimerQueueInsert(&head, 10, &timer1);
+ GP_TimerQueueInsert(&head, 10, &timer2);
+
+ /* Make timer1 expire */
+ if (GP_TimerQueueProcess(&head, 20) != 1) {
+ tst_msg("GP_TimerQueueProcess() reported wrong number");
+ fail++;
+ }
+
+ if (!timer1.priv) {
+ tst_msg("Timer1 callback was not called");
+ fail++;
+ }
+
+ /* check that there are two timers in the queue */
+ if (head->sons != 1) {
+ tst_msg("Queue head has wrong number of sons %u", head->sons);
+ fail++;
+ }
+
+ timer1.priv = NULL;
+
+ /* Make both timers expire */
+ if (GP_TimerQueueProcess(&head, 30) != 2) {
+ tst_msg("GP_TimerQueueProcess() reported wrong number");
+ fail++;
+ }
+
+ if (!timer1.priv) {
+ tst_msg("Timer1 callback was not called");
+ fail++;
+ }
+
+ if (!timer2.priv) {
+ tst_msg("Timer2 callback was not called");
+ fail++;
+ }
+
+ /* check that there are two timers in the queue */
+ if (head->sons != 1) {
+ tst_msg("Queue head has wrong number of sons %u", head->sons);
+ fail++;
+ }
+
+ if (fail)
+ return TST_FAILED;
+
+ return TST_SUCCESS;
+}
+
+const struct tst_suite tst_suite = {
+ .suite_name = "Timer Testsuite",
+ .tests = {
+ {.name = "Callback is called",
+ .tst_fn = callback_is_called},
+ {.name = "Call process with NULL head",
+ .tst_fn = process_with_NULL_head},
+ {.name = "Expirations are sorted",
+ .tst_fn = expirations_sorted},
+ {.name = "Periodic timers",
+ .tst_fn = periodic_timers},
+ {.name = NULL},
+ }
+};
diff --git a/tests/input/runtest.sh b/tests/input/runtest.sh
new file mode 100755
index 0000000..b3039a3
--- /dev/null
+++ b/tests/input/runtest.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+#
+# By default the glibc __libc_message() writes to /dev/tty before calling
+# the abort(). Exporting this macro makes it to use stderr instead.
+#
+# The main usage of the function are malloc assertions, so this makes us catch
+# the malloc error message by catching stderr output.
+#
+export LIBC_FATAL_STDERR_=1
+
+TEST="$1"
+shift
+
+LD_PRELOAD=`pwd`/../framework/libtst_preload.so LD_LIBRARY_PATH=../../build/ "./$TEST" "$@"
diff --git a/tests/input/test_list.txt b/tests/input/test_list.txt
new file mode 100644
index 0000000..777c39b
--- /dev/null
+++ b/tests/input/test_list.txt
@@ -0,0 +1,3 @@
+# Input test list
+
+Timer
-----------------------------------------------------------------------
Summary of changes:
tests/Makefile | 2 +-
tests/{loaders => input}/Makefile | 5 +-
tests/{core/Pixel.c => input/TimeStamp.c} | 46 +++----
tests/input/Timer.c | 207 +++++++++++++++++++++++++++++
tests/{core => input}/runtest.sh | 0
tests/input/test_list.txt | 3 +
tests/runtests.py | 3 +-
7 files changed, 235 insertions(+), 31 deletions(-)
copy tests/{loaders => input}/Makefile (64%)
copy tests/{core/Pixel.c => input/TimeStamp.c} (72%)
create mode 100644 tests/input/Timer.c
copy tests/{core => input}/runtest.sh (100%)
create mode 100644 tests/input/test_list.txt
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos(a)gmail.com
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
gfxprim.git ("A simple 2D graphics library with emphasis on correctness and well-defined operation.")