fix pixmap leak

git-svn-id: http://svn2.nishi.boats/svn/milsko/trunk@82 b9cfdab3-6d41-4d17-bbe4-086880011989
This commit is contained in:
Nishi 2025-09-30 17:47:03 +00:00
commit 8ea2d4a50a
15 changed files with 9440 additions and 1337 deletions

View file

@ -7,7 +7,7 @@ CFLAGS = -Wall -Wextra -Iinclude
LDFLAGS = LDFLAGS =
LIBS = LIBS =
L_CFLAGS = $(CFLAGS) -fPIC -D_MILSKO L_CFLAGS = $(CFLAGS) -fPIC -D_MILSKO -DHAVE_CONFIG_H
L_LDFLAGS = $(LDFLAGS) L_LDFLAGS = $(LDFLAGS)
L_LIBS = $(LIBS) L_LIBS = $(LIBS)
@ -15,7 +15,7 @@ E_CFLAGS = $(CFLAGS)
E_LDFLAGS = $(LDFLAGS) -Lsrc E_LDFLAGS = $(LDFLAGS) -Lsrc
E_LIBS = $(LIBS) -lMw E_LIBS = $(LIBS) -lMw
L_OBJS = src/ds.o src/core.o src/default.o src/draw.o src/lowlevel.o src/font.o L_OBJS = src/ds.o src/core.o src/default.o src/draw.o src/lowlevel.o src/font.o src/image.o
L_OBJS += src/window.o src/button.o src/opengl.o src/frame.o L_OBJS += src/window.o src/button.o src/opengl.o src/frame.o
ifeq ($(TARGET),NetBSD) ifeq ($(TARGET),NetBSD)
@ -53,7 +53,7 @@ SO = .dll
EXEC = .exe EXEC = .exe
endif endif
EXAMPLES = examples/example$(EXEC) examples/rotate$(EXEC) examples/opengl$(EXEC) EXAMPLES = examples/example$(EXEC) examples/rotate$(EXEC) examples/opengl$(EXEC) examples/image$(EXEC)
.PHONY: all format clean lib examples .PHONY: all format clean lib examples
@ -62,8 +62,8 @@ lib: src/libMw$(SO)
examples: $(EXAMPLES) examples: $(EXAMPLES)
format: format:
clang-format --verbose -i $(shell find src include examples tools -name "*.c" -or -name "*.h") clang-format --verbose -i `find src include examples tools "(" -name "*.c" -or -name "*.h" ")" -and -not -name "stb_*.h"`
perltidy -b -bext='/' --paren-tightness=2 $(shell find tools -name "*.pl") perltidy -b -bext='/' --paren-tightness=2 `find tools -name "*.pl"`
src/libMw$(SO): $(L_OBJS) src/libMw$(SO): $(L_OBJS)
$(CC) $(L_LDFLAGS) -shared -o $@ $^ $(L_LIBS) $(CC) $(L_LDFLAGS) -shared -o $@ $^ $(L_LIBS)
@ -81,4 +81,4 @@ examples/%.o: examples/%.c
$(CC) $(E_CFLAGS) -c -o $@ $< $(CC) $(E_CFLAGS) -c -o $@ $<
clean: clean:
rm -f src/*.dll src/*.so src/*.a src/*.lib */*.o examples/*.exe $(EXAMPLES) rm -f src/*.dll src/*.so src/*.a src/*.lib */*.o */*/*.o examples/*.exe $(EXAMPLES)

16
examples/image.c Normal file
View file

@ -0,0 +1,16 @@
/* $Id$ */
#include <Mw/Milsko.h>
int main() {
MwWidget window = MwVaCreateWidget(MwWindowClass, "window", NULL, 0, 0, 500, 500,
MwNtitle, "image button",
NULL);
MwWidget button = MwCreateWidget(MwButtonClass, "button", window, 50, 50, 400, 400);
MwLLPixmap px = MwLoadImage(button, "examples/picture.png");
MwVaApply(button,
MwNpixmap, px,
NULL);
MwLoop(window);
}

BIN
examples/picture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -106,6 +106,14 @@ MWDECL void MwSetInteger(MwWidget handle, const char* key, int n);
*/ */
MWDECL void MwSetText(MwWidget handle, const char* key, const char* value); MWDECL void MwSetText(MwWidget handle, const char* key, const char* value);
/*!
* %brief Sets a void pointer property
* %param handle Widget
* %param key Key
* %param value Value
*/
MWDECL void MwSetVoid(MwWidget handle, const char* key, void* value);
/*! /*!
* %brief Gets the integer property * %brief Gets the integer property
* %param handle Widget * %param handle Widget
@ -122,6 +130,14 @@ MWDECL int MwGetInteger(MwWidget handle, const char* key);
*/ */
MWDECL const char* MwGetText(MwWidget handle, const char* key); MWDECL const char* MwGetText(MwWidget handle, const char* key);
/*!
* %brief Gets the void pointer property
* %param handle Widget
* %param key Key
* %return Value
*/
MWDECL void* MwGetVoid(MwWidget handle, const char* key);
/*! /*!
* %brief Sets the default property * %brief Sets the default property
* %param handle Widget * %param handle Widget

View file

@ -60,6 +60,14 @@ MWDECL void MwDrawFrameEx(MwWidget handle, MwRect* rect, MwLLColor color, int in
*/ */
MWDECL void MwDrawText(MwWidget handle, MwPoint* point, const char* text, MwLLColor color); MWDECL void MwDrawText(MwWidget handle, MwPoint* point, const char* text, MwLLColor color);
/*!
* %brief Creates a pixmap from image
* %param handle Widget
* %param path Path
* %return Pixmap
*/
MWDECL MwLLPixmap MwLoadImage(MwWidget handle, const char* path);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -16,6 +16,8 @@
#define MwNbackground "Sbackground" #define MwNbackground "Sbackground"
#define MwNforeground "Sforeground" #define MwNforeground "Sforeground"
#define MwNpixmap "Vpixmap"
#define MwNactivateHandler "Cactivate" #define MwNactivateHandler "Cactivate"
#define MwNresizeHandler "Cresize" #define MwNresizeHandler "Cresize"
#define MwNtickHandler "Ctick" #define MwNtickHandler "Ctick"

View file

@ -14,6 +14,7 @@ typedef struct _MwRect MwRect;
typedef struct _MwIntegerKeyValue MwIntegerKeyValue; typedef struct _MwIntegerKeyValue MwIntegerKeyValue;
typedef struct _MwTextKeyValue MwTextKeyValue; typedef struct _MwTextKeyValue MwTextKeyValue;
typedef struct _MwUserHandlerKeyValue MwUserHandlerKeyValue; typedef struct _MwUserHandlerKeyValue MwUserHandlerKeyValue;
typedef struct _MwVoidKeyValue MwVoidKeyValue;
typedef struct _MwFont MwFont; typedef struct _MwFont MwFont;
#ifdef _MILSKO #ifdef _MILSKO
typedef struct _MwWidget *MwWidget, MwWidgetRec; typedef struct _MwWidget *MwWidget, MwWidgetRec;
@ -56,6 +57,11 @@ struct _MwUserHandlerKeyValue {
MwUserHandler value; MwUserHandler value;
}; };
struct _MwVoidKeyValue {
char* key;
void* value;
};
#ifdef _MILSKO #ifdef _MILSKO
struct _MwWidget { struct _MwWidget {
char* name; char* name;
@ -74,6 +80,7 @@ struct _MwWidget {
MwIntegerKeyValue* integer; MwIntegerKeyValue* integer;
MwTextKeyValue* text; MwTextKeyValue* text;
MwUserHandlerKeyValue* handler; MwUserHandlerKeyValue* handler;
MwVoidKeyValue* data;
}; };
#endif #endif

View file

@ -19,11 +19,15 @@
struct _MwLL { struct _MwLL {
Display* display; Display* display;
Window window; Window window;
Pixmap pixmap;
GC gc; GC gc;
Colormap colormap; Colormap colormap;
void* user; void* user;
Atom wm_delete; Atom wm_delete;
unsigned int width;
unsigned int height;
MwLLHandler handler; MwLLHandler handler;
}; };

View file

@ -11,6 +11,7 @@ static void draw(MwWidget handle) {
MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground)); MwLLColor base = MwParseColor(handle, MwGetText(handle, MwNbackground));
MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground)); MwLLColor text = MwParseColor(handle, MwGetText(handle, MwNforeground));
const char* str = MwGetText(handle, MwNtext); const char* str = MwGetText(handle, MwNtext);
MwLLPixmap px = MwGetVoid(handle, MwNpixmap);
if(str == NULL) str = ""; if(str == NULL) str = "";
@ -22,10 +23,33 @@ static void draw(MwWidget handle) {
MwDrawFrame(handle, &r, base, handle->pressed); MwDrawFrame(handle, &r, base, handle->pressed);
MwDrawRect(handle, &r, base); MwDrawRect(handle, &r, base);
if(px != NULL) {
int ow = r.width;
int oh = r.height;
double sw = (double)ow / px->width;
double sh = (double)oh / px->height;
if(sw < sh) {
r.width = px->width * sw;
r.height = px->height * sw;
} else {
r.width = px->width * sh;
r.height = px->height * sh;
}
r.width -= 10;
r.height -= 10;
r.x += (double)(ow - r.width) / 2;
r.y += (double)(oh - r.height) / 2;
MwLLDrawPixmap(handle->lowlevel, &r, px);
} else {
point.x = r.x + r.width / 2; point.x = r.x + r.width / 2;
point.y = r.x + r.height / 2; point.y = r.x + r.height / 2;
MwDrawText(handle, &point, str, text); MwDrawText(handle, &point, str, text);
}
MwLLFreeColor(text); MwLLFreeColor(text);
MwLLFreeColor(base); MwLLFreeColor(base);

View file

@ -57,10 +57,12 @@ MwWidget MwCreateWidget(MwClass widget_class, const char* name, MwWidget parent,
sh_new_strdup(h->text); sh_new_strdup(h->text);
sh_new_strdup(h->integer); sh_new_strdup(h->integer);
sh_new_strdup(h->handler); sh_new_strdup(h->handler);
sh_new_strdup(h->data);
shdefault(h->integer, -1); shdefault(h->integer, -1);
shdefault(h->text, NULL); shdefault(h->text, NULL);
shdefault(h->handler, NULL); shdefault(h->handler, NULL);
shdefault(h->data, NULL);
MwDispatch(h, create); MwDispatch(h, create);
@ -122,6 +124,7 @@ void MwDestroyWidget(MwWidget handle) {
} }
shfree(handle->text); shfree(handle->text);
shfree(handle->handler); shfree(handle->handler);
shfree(handle->data);
free(handle); free(handle);
} }
@ -182,6 +185,10 @@ void MwSetText(MwWidget handle, const char* key, const char* value) {
} }
} }
void MwSetVoid(MwWidget handle, const char* key, void* value) {
shput(handle->data, key, value);
}
int MwGetInteger(MwWidget handle, const char* key) { int MwGetInteger(MwWidget handle, const char* key) {
if(strcmp(key, MwNx) == 0 || strcmp(key, MwNy) == 0 || strcmp(key, MwNwidth) == 0 || strcmp(key, MwNheight) == 0) { if(strcmp(key, MwNx) == 0 || strcmp(key, MwNy) == 0 || strcmp(key, MwNwidth) == 0 || strcmp(key, MwNheight) == 0) {
int x, y; int x, y;
@ -203,6 +210,10 @@ const char* MwGetText(MwWidget handle, const char* key) {
return shget(handle->text, key); return shget(handle->text, key);
} }
void* MwGetVoid(MwWidget handle, const char* key) {
return shget(handle->data, key);
}
void MwVaApply(MwWidget handle, ...) { void MwVaApply(MwWidget handle, ...) {
va_list va; va_list va;
@ -228,6 +239,9 @@ void MwVaListApply(MwWidget handle, va_list va) {
shput(handle->handler, key, h); shput(handle->handler, key, h);
ind = shgeti(handle->handler, key); ind = shgeti(handle->handler, key);
handle->handler[ind].user_data = NULL; handle->handler[ind].user_data = NULL;
} else if(key[0] == 'V') {
void* v = va_arg(va, void*);
MwSetVoid(handle, key, v);
} }
} }
} }

View file

@ -1,6 +1,8 @@
/* $Id$ */ /* $Id$ */
#include <Mw/Milsko.h> #include <Mw/Milsko.h>
#include <stb_image.h>
static int hex(const char* txt, int len) { static int hex(const char* txt, int len) {
int i; int i;
int r = 0; int r = 0;
@ -145,3 +147,17 @@ void MwDrawText(MwWidget handle, MwPoint* point, const char* text, MwLLColor col
sx += fw * sc; sx += fw * sc;
} }
} }
MwLLPixmap MwLoadImage(MwWidget handle, const char* path) {
int width, height, ch;
unsigned char* rgb = stbi_load(path, &width, &height, &ch, 3);
MwLLPixmap px;
if(rgb == NULL) return NULL;
px = MwLLCreatePixmap(handle->lowlevel, rgb, width, height);
free(rgb);
return px;
}

3
src/image.c Normal file
View file

@ -0,0 +1,3 @@
/* $Id$ */
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

239
src/stb_ds.h generated
View file

@ -556,8 +556,7 @@ extern void* stbds_shmode_func(size_t elemsize, int mode);
#define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v)) #define stbds_arrins(a,i,v) (stbds_arrinsn((a),(i),1), (a)[i]=(v))
#define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \ #define stbds_arrmaybegrow(a,n) ((!(a) || stbds_header(a)->length + (n) > stbds_header(a)->capacity) \
? (stbds_arrgrow(a, n, 0), 0) \ ? (stbds_arrgrow(a,n,0),0) : 0)
: 0)
#define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c))) #define stbds_arrgrow(a,b,c) ((a) = stbds_arrgrowf_wrapper((a), sizeof *(a), (b), (c)))
@ -663,12 +662,14 @@ typedef struct
ptrdiff_t temp; ptrdiff_t temp;
} stbds_array_header; } stbds_array_header;
typedef struct stbds_string_block { typedef struct stbds_string_block
{
struct stbds_string_block *next; struct stbds_string_block *next;
char storage[8]; char storage[8];
} stbds_string_block; } stbds_string_block;
struct stbds_string_arena { struct stbds_string_arena
{
stbds_string_block *storage; stbds_string_block *storage;
size_t remaining; size_t remaining;
unsigned char block; unsigned char block;
@ -678,7 +679,8 @@ struct stbds_string_arena {
#define STBDS_HM_BINARY 0 #define STBDS_HM_BINARY 0
#define STBDS_HM_STRING 1 #define STBDS_HM_STRING 1
enum { enum
{
STBDS_SH_NONE, STBDS_SH_NONE,
STBDS_SH_DEFAULT, STBDS_SH_DEFAULT,
STBDS_SH_STRDUP, STBDS_SH_STRDUP,
@ -688,32 +690,25 @@ enum {
#ifdef __cplusplus #ifdef __cplusplus
// in C we use implicit assignment from these void*-returning functions to T*. // in C we use implicit assignment from these void*-returning functions to T*.
// in C++ these templates make the same code work // in C++ these templates make the same code work
template <class T> template<class T> static T * stbds_arrgrowf_wrapper(T *a, size_t elemsize, size_t addlen, size_t min_cap) {
static T* stbds_arrgrowf_wrapper(T* a, size_t elemsize, size_t addlen, size_t min_cap) {
return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap); return (T*)stbds_arrgrowf((void *)a, elemsize, addlen, min_cap);
} }
template <class T> template<class T> static T * stbds_hmget_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) {
static T* stbds_hmget_key_wrapper(T* a, size_t elemsize, void* key, size_t keysize, int mode) {
return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode); return (T*)stbds_hmget_key((void*)a, elemsize, key, keysize, mode);
} }
template <class T> template<class T> static T * stbds_hmget_key_ts_wrapper(T *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode) {
static T* stbds_hmget_key_ts_wrapper(T* a, size_t elemsize, void* key, size_t keysize, ptrdiff_t* temp, int mode) {
return (T*)stbds_hmget_key_ts((void*)a, elemsize, key, keysize, temp, mode); return (T*)stbds_hmget_key_ts((void*)a, elemsize, key, keysize, temp, mode);
} }
template <class T> template<class T> static T * stbds_hmput_default_wrapper(T *a, size_t elemsize) {
static T* stbds_hmput_default_wrapper(T* a, size_t elemsize) {
return (T*)stbds_hmput_default((void *)a, elemsize); return (T*)stbds_hmput_default((void *)a, elemsize);
} }
template <class T> template<class T> static T * stbds_hmput_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, int mode) {
static T* stbds_hmput_key_wrapper(T* a, size_t elemsize, void* key, size_t keysize, int mode) {
return (T*)stbds_hmput_key((void*)a, elemsize, key, keysize, mode); return (T*)stbds_hmput_key((void*)a, elemsize, key, keysize, mode);
} }
template <class T> template<class T> static T * stbds_hmdel_key_wrapper(T *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode){
static T* stbds_hmdel_key_wrapper(T* a, size_t elemsize, void* key, size_t keysize, size_t keyoffset, int mode) {
return (T*)stbds_hmdel_key((void*)a, elemsize, key, keysize, keyoffset, mode); return (T*)stbds_hmdel_key((void*)a, elemsize, key, keysize, keyoffset, mode);
} }
template <class T> template<class T> static T * stbds_shmode_func_wrapper(T *, size_t elemsize, int mode) {
static T* stbds_shmode_func_wrapper(T*, size_t elemsize, int mode) {
return (T*)stbds_shmode_func(elemsize, mode); return (T*)stbds_shmode_func(elemsize, mode);
} }
#else #else
@ -728,6 +723,7 @@ static T* stbds_shmode_func_wrapper(T*, size_t elemsize, int mode) {
#endif // INCLUDE_STB_DS_H #endif // INCLUDE_STB_DS_H
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// //
// IMPLEMENTATION // IMPLEMENTATION
@ -763,7 +759,8 @@ size_t stbds_rehash_items;
//int *prev_allocs[65536]; //int *prev_allocs[65536];
//int num_prev; //int num_prev;
void* stbds_arrgrowf(void* a, size_t elemsize, size_t addlen, size_t min_cap) { void *stbds_arrgrowf(void *a, size_t elemsize, size_t addlen, size_t min_cap)
{
stbds_array_header temp={0}; // force debugging stbds_array_header temp={0}; // force debugging
void *b; void *b;
size_t min_len = stbds_arrlen(a) + addlen; size_t min_len = stbds_arrlen(a) + addlen;
@ -800,7 +797,8 @@ void* stbds_arrgrowf(void* a, size_t elemsize, size_t addlen, size_t min_cap) {
return b; return b;
} }
void stbds_arrfreef(void* a) { void stbds_arrfreef(void *a)
{
STBDS_FREE(NULL, stbds_header(a)); STBDS_FREE(NULL, stbds_header(a));
} }
@ -850,7 +848,8 @@ typedef struct
static size_t stbds_hash_seed=0x31415926; static size_t stbds_hash_seed=0x31415926;
void stbds_rand_seed(size_t seed) { void stbds_rand_seed(size_t seed)
{
stbds_hash_seed = seed; stbds_hash_seed = seed;
} }
@ -861,7 +860,8 @@ void stbds_rand_seed(size_t seed) {
#define STBDS_SIZE_T_BITS ((sizeof (size_t)) * 8) #define STBDS_SIZE_T_BITS ((sizeof (size_t)) * 8)
static size_t stbds_probe_position(size_t hash, size_t slot_count, size_t slot_log2) { static size_t stbds_probe_position(size_t hash, size_t slot_count, size_t slot_log2)
{
size_t pos; size_t pos;
STBDS_NOTUSED(slot_log2); STBDS_NOTUSED(slot_log2);
pos = hash & (slot_count-1); pos = hash & (slot_count-1);
@ -871,7 +871,8 @@ static size_t stbds_probe_position(size_t hash, size_t slot_count, size_t slot_l
return pos; return pos;
} }
static size_t stbds_log2(size_t slot_count) { static size_t stbds_log2(size_t slot_count)
{
size_t n=0; size_t n=0;
while (slot_count > 1) { while (slot_count > 1) {
slot_count >>= 1; slot_count >>= 1;
@ -880,7 +881,8 @@ static size_t stbds_log2(size_t slot_count) {
return n; return n;
} }
static stbds_hash_index* stbds_make_hash_index(size_t slot_count, stbds_hash_index* ot) { static stbds_hash_index *stbds_make_hash_index(size_t slot_count, stbds_hash_index *ot)
{
stbds_hash_index *t; stbds_hash_index *t;
t = (stbds_hash_index *) STBDS_REALLOC(NULL,0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1); t = (stbds_hash_index *) STBDS_REALLOC(NULL,0,(slot_count >> STBDS_BUCKET_SHIFT) * sizeof(stbds_hash_bucket) + sizeof(stbds_hash_index) + STBDS_CACHE_LINE_SIZE-1);
t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE); t->storage = (stbds_hash_bucket *) STBDS_ALIGN_FWD((size_t) (t+1), STBDS_CACHE_LINE_SIZE);
@ -999,7 +1001,8 @@ static stbds_hash_index* stbds_make_hash_index(size_t slot_count, stbds_hash_ind
pos &= (t->slot_count-1); pos &= (t->slot_count-1);
} }
} }
done:; done:
;
} }
} }
} }
@ -1010,7 +1013,8 @@ static stbds_hash_index* stbds_make_hash_index(size_t slot_count, stbds_hash_ind
#define STBDS_ROTATE_LEFT(val, n) (((val) << (n)) | ((val) >> (STBDS_SIZE_T_BITS - (n)))) #define STBDS_ROTATE_LEFT(val, n) (((val) << (n)) | ((val) >> (STBDS_SIZE_T_BITS - (n))))
#define STBDS_ROTATE_RIGHT(val, n) (((val) >> (n)) | ((val) << (STBDS_SIZE_T_BITS - (n)))) #define STBDS_ROTATE_RIGHT(val, n) (((val) >> (n)) | ((val) << (STBDS_SIZE_T_BITS - (n))))
size_t stbds_hash_string(char* str, size_t seed) { size_t stbds_hash_string(char *str, size_t seed)
{
size_t hash = seed; size_t hash = seed;
while (*str) while (*str)
hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++; hash = STBDS_ROTATE_LEFT(hash, 9) + (unsigned char) *str++;
@ -1044,7 +1048,8 @@ typedef int STBDS_SIPHASH_2_4_can_only_be_used_in_64_bit_builds[sizeof(size_t) =
#pragma warning(disable:4127) // conditional expression is constant, for do..while(0) and sizeof()== #pragma warning(disable:4127) // conditional expression is constant, for do..while(0) and sizeof()==
#endif #endif
static size_t stbds_siphash_bytes(void* p, size_t len, size_t seed) { static size_t stbds_siphash_bytes(void *p, size_t len, size_t seed)
{
unsigned char *d = (unsigned char *) p; unsigned char *d = (unsigned char *) p;
size_t i,j; size_t i,j;
size_t v0,v1,v2,v3, data; size_t v0,v1,v2,v3, data;
@ -1067,20 +1072,10 @@ static size_t stbds_siphash_bytes(void* p, size_t len, size_t seed) {
#define STBDS_SIPROUND() \ #define STBDS_SIPROUND() \
do { \ do { \
v0 += v1; \ v0 += v1; v1 = STBDS_ROTATE_LEFT(v1, 13); v1 ^= v0; v0 = STBDS_ROTATE_LEFT(v0,STBDS_SIZE_T_BITS/2); \
v1 = STBDS_ROTATE_LEFT(v1, 13); \ v2 += v3; v3 = STBDS_ROTATE_LEFT(v3, 16); v3 ^= v2; \
v1 ^= v0; \ v2 += v1; v1 = STBDS_ROTATE_LEFT(v1, 17); v1 ^= v2; v2 = STBDS_ROTATE_LEFT(v2,STBDS_SIZE_T_BITS/2); \
v0 = STBDS_ROTATE_LEFT(v0, STBDS_SIZE_T_BITS / 2); \ v0 += v3; v3 = STBDS_ROTATE_LEFT(v3, 21); v3 ^= v0; \
v2 += v3; \
v3 = STBDS_ROTATE_LEFT(v3, 16); \
v3 ^= v2; \
v2 += v1; \
v1 = STBDS_ROTATE_LEFT(v1, 17); \
v1 ^= v2; \
v2 = STBDS_ROTATE_LEFT(v2, STBDS_SIZE_T_BITS / 2); \
v0 += v3; \
v3 = STBDS_ROTATE_LEFT(v3, 21); \
v3 ^= v0; \
} while (0) } while (0)
for (i=0; i+sizeof(size_t) <= len; i += sizeof(size_t), d += sizeof(size_t)) { for (i=0; i+sizeof(size_t) <= len; i += sizeof(size_t), d += sizeof(size_t)) {
@ -1094,22 +1089,14 @@ static size_t stbds_siphash_bytes(void* p, size_t len, size_t seed) {
} }
data = len << (STBDS_SIZE_T_BITS-8); data = len << (STBDS_SIZE_T_BITS-8);
switch (len - i) { switch (len - i) {
case 7: case 7: data |= ((size_t) d[6] << 24) << 24; // fall through
data |= ((size_t)d[6] << 24) << 24; // fall through case 6: data |= ((size_t) d[5] << 20) << 20; // fall through
case 6: case 5: data |= ((size_t) d[4] << 16) << 16; // fall through
data |= ((size_t)d[5] << 20) << 20; // fall through case 4: data |= (d[3] << 24); // fall through
case 5: case 3: data |= (d[2] << 16); // fall through
data |= ((size_t)d[4] << 16) << 16; // fall through case 2: data |= (d[1] << 8); // fall through
case 4: case 1: data |= d[0]; // fall through
data |= (d[3] << 24); // fall through case 0: break;
case 3:
data |= (d[2] << 16); // fall through
case 2:
data |= (d[1] << 8); // fall through
case 1:
data |= d[0]; // fall through
case 0:
break;
} }
v3 ^= data; v3 ^= data;
for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j) for (j=0; j < STBDS_SIPHASH_C_ROUNDS; ++j)
@ -1126,7 +1113,8 @@ static size_t stbds_siphash_bytes(void* p, size_t len, size_t seed) {
#endif #endif
} }
size_t stbds_hash_bytes(void* p, size_t len, size_t seed) { size_t stbds_hash_bytes(void *p, size_t len, size_t seed)
{
#ifdef STBDS_SIPHASH_2_4 #ifdef STBDS_SIPHASH_2_4
return stbds_siphash_bytes(p,len,seed); return stbds_siphash_bytes(p,len,seed);
#else #else
@ -1211,7 +1199,9 @@ size_t stbds_hash_bytes(void* p, size_t len, size_t seed) {
#pragma warning(pop) #pragma warning(pop)
#endif #endif
static int stbds_is_key_equal(void* a, size_t elemsize, void* key, size_t keysize, size_t keyoffset, int mode, size_t i) {
static int stbds_is_key_equal(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode, size_t i)
{
if (mode >= STBDS_HM_STRING) if (mode >= STBDS_HM_STRING)
return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset)); return 0==strcmp((char *) key, * (char **) ((char *) a + elemsize*i + keyoffset));
else else
@ -1223,7 +1213,8 @@ static int stbds_is_key_equal(void* a, size_t elemsize, void* key, size_t keysiz
#define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table) #define stbds_hash_table(a) ((stbds_hash_index *) stbds_header(a)->hash_table)
void stbds_hmfree_func(void* a, size_t elemsize) { void stbds_hmfree_func(void *a, size_t elemsize)
{
if (a == NULL) return; if (a == NULL) return;
if (stbds_hash_table(a) != NULL) { if (stbds_hash_table(a) != NULL) {
if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) { if (stbds_hash_table(a)->string.mode == STBDS_SH_STRDUP) {
@ -1238,7 +1229,8 @@ void stbds_hmfree_func(void* a, size_t elemsize) {
STBDS_FREE(NULL, stbds_header(a)); STBDS_FREE(NULL, stbds_header(a));
} }
static ptrdiff_t stbds_hm_find_slot(void* a, size_t elemsize, void* key, size_t keysize, size_t keyoffset, int mode) { static ptrdiff_t stbds_hm_find_slot(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode)
{
void *raw_a = STBDS_HASH_TO_ARR(a,elemsize); void *raw_a = STBDS_HASH_TO_ARR(a,elemsize);
stbds_hash_index *table = stbds_hash_table(raw_a); stbds_hash_index *table = stbds_hash_table(raw_a);
size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed); size_t hash = mode >= STBDS_HM_STRING ? stbds_hash_string((char*)key,table->seed) : stbds_hash_bytes(key, keysize,table->seed);
@ -1286,7 +1278,8 @@ static ptrdiff_t stbds_hm_find_slot(void* a, size_t elemsize, void* key, size_t
/* NOTREACHED */ /* NOTREACHED */
} }
void* stbds_hmget_key_ts(void* a, size_t elemsize, void* key, size_t keysize, ptrdiff_t* temp, int mode) { void * stbds_hmget_key_ts(void *a, size_t elemsize, void *key, size_t keysize, ptrdiff_t *temp, int mode)
{
size_t keyoffset = 0; size_t keyoffset = 0;
if (a == NULL) { if (a == NULL) {
// make it non-empty so we can return a temp // make it non-empty so we can return a temp
@ -1316,14 +1309,16 @@ void* stbds_hmget_key_ts(void* a, size_t elemsize, void* key, size_t keysize, pt
} }
} }
void* stbds_hmget_key(void* a, size_t elemsize, void* key, size_t keysize, int mode) { void * stbds_hmget_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
{
ptrdiff_t temp; ptrdiff_t temp;
void *p = stbds_hmget_key_ts(a, elemsize, key, keysize, &temp, mode); void *p = stbds_hmget_key_ts(a, elemsize, key, keysize, &temp, mode);
stbds_temp(STBDS_HASH_TO_ARR(p,elemsize)) = temp; stbds_temp(STBDS_HASH_TO_ARR(p,elemsize)) = temp;
return p; return p;
} }
void* stbds_hmput_default(void* a, size_t elemsize) { void * stbds_hmput_default(void *a, size_t elemsize)
{
// three cases: // three cases:
// a is NULL <- allocate // a is NULL <- allocate
// a has a hash table but no entries, because of shmode <- grow // a has a hash table but no entries, because of shmode <- grow
@ -1339,7 +1334,8 @@ void* stbds_hmput_default(void* a, size_t elemsize) {
static char *stbds_strdup(char *str); static char *stbds_strdup(char *str);
void* stbds_hmput_key(void* a, size_t elemsize, void* key, size_t keysize, int mode) { void *stbds_hmput_key(void *a, size_t elemsize, void *key, size_t keysize, int mode)
{
size_t keyoffset=0; size_t keyoffset=0;
void *raw_a; void *raw_a;
stbds_hash_index *table; stbds_hash_index *table;
@ -1452,25 +1448,18 @@ void* stbds_hmput_key(void* a, size_t elemsize, void* key, size_t keysize, int m
stbds_temp(a) = i-1; stbds_temp(a) = i-1;
switch (table->string.mode) { switch (table->string.mode) {
case STBDS_SH_STRDUP: case STBDS_SH_STRDUP: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_strdup((char*) key); break;
stbds_temp_key(a) = *(char**)((char*)a + elemsize * i) = stbds_strdup((char*)key); case STBDS_SH_ARENA: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = stbds_stralloc(&table->string, (char*)key); break;
break; case STBDS_SH_DEFAULT: stbds_temp_key(a) = *(char **) ((char *) a + elemsize*i) = (char *) key; break;
case STBDS_SH_ARENA: default: memcpy((char *) a + elemsize*i, key, keysize); break;
stbds_temp_key(a) = *(char**)((char*)a + elemsize * i) = stbds_stralloc(&table->string, (char*)key);
break;
case STBDS_SH_DEFAULT:
stbds_temp_key(a) = *(char**)((char*)a + elemsize * i) = (char*)key;
break;
default:
memcpy((char*)a + elemsize * i, key, keysize);
break;
} }
} }
return STBDS_ARR_TO_HASH(a,elemsize); return STBDS_ARR_TO_HASH(a,elemsize);
} }
} }
void* stbds_shmode_func(size_t elemsize, int mode) { void * stbds_shmode_func(size_t elemsize, int mode)
{
void *a = stbds_arrgrowf(0, elemsize, 0, 1); void *a = stbds_arrgrowf(0, elemsize, 0, 1);
stbds_hash_index *h; stbds_hash_index *h;
memset(a, 0, elemsize); memset(a, 0, elemsize);
@ -1480,7 +1469,8 @@ void* stbds_shmode_func(size_t elemsize, int mode) {
return STBDS_ARR_TO_HASH(a,elemsize); return STBDS_ARR_TO_HASH(a,elemsize);
} }
void* stbds_hmdel_key(void* a, size_t elemsize, void* key, size_t keysize, size_t keyoffset, int mode) { void * stbds_hmdel_key(void *a, size_t elemsize, void *key, size_t keysize, size_t keyoffset, int mode)
{
if (a == NULL) { if (a == NULL) {
return 0; return 0;
} else { } else {
@ -1547,7 +1537,8 @@ void* stbds_hmdel_key(void* a, size_t elemsize, void* key, size_t keysize, size_
/* NOTREACHED */ /* NOTREACHED */
} }
static char* stbds_strdup(char* str) { static char *stbds_strdup(char *str)
{
// to keep replaceable allocator simple, we don't want to use strdup. // to keep replaceable allocator simple, we don't want to use strdup.
// rolling our own also avoids problem of strdup vs _strdup // rolling our own also avoids problem of strdup vs _strdup
size_t len = strlen(str)+1; size_t len = strlen(str)+1;
@ -1563,7 +1554,8 @@ static char* stbds_strdup(char* str) {
#define STBDS_STRING_ARENA_BLOCKSIZE_MAX (1u<<20) #define STBDS_STRING_ARENA_BLOCKSIZE_MAX (1u<<20)
#endif #endif
char* stbds_stralloc(stbds_string_arena* a, char* str) { char *stbds_stralloc(stbds_string_arena *a, char *str)
{
char *p; char *p;
size_t len = strlen(str)+1; size_t len = strlen(str)+1;
if (len > a->remaining) { if (len > a->remaining) {
@ -1610,7 +1602,8 @@ char* stbds_stralloc(stbds_string_arena* a, char* str) {
return p; return p;
} }
void stbds_strreset(stbds_string_arena* a) { void stbds_strreset(stbds_string_arena *a)
{
stbds_string_block *x,*y; stbds_string_block *x,*y;
x = a->storage; x = a->storage;
while (x) { while (x) {
@ -1638,15 +1631,12 @@ void stbds_strreset(stbds_string_arena* a) {
#include <assert.h> #include <assert.h>
#endif #endif
typedef struct { typedef struct { int key,b,c,d; } stbds_struct;
int key, b, c, d; typedef struct { int key[2],b,c,d; } stbds_struct2;
} stbds_struct;
typedef struct {
int key[2], b, c, d;
} stbds_struct2;
static char buffer[256]; static char buffer[256];
char* strkey(int n) { char *strkey(int n)
{
#if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__) #if defined(_WIN32) && defined(__STDC_WANT_SECURE_LIB__)
sprintf_s(buffer, sizeof(buffer), "test_%d", n); sprintf_s(buffer, sizeof(buffer), "test_%d", n);
#else #else
@ -1655,7 +1645,8 @@ char* strkey(int n) {
return buffer; return buffer;
} }
void stbds_unit_tests(void) { void stbds_unit_tests(void)
{
#if defined(_MSC_VER) && _MSC_VER <= 1200 && defined(__cplusplus) #if defined(_MSC_VER) && _MSC_VER <= 1200 && defined(__cplusplus)
// VC6 C++ doesn't like the template<> trick on unnamed structures, so do nothing! // VC6 C++ doesn't like the template<> trick on unnamed structures, so do nothing!
STBDS_ASSERT(0); STBDS_ASSERT(0);
@ -1663,18 +1654,9 @@ void stbds_unit_tests(void) {
const int testsize = 100000; const int testsize = 100000;
const int testsize2 = testsize/20; const int testsize2 = testsize/20;
int *arr=NULL; int *arr=NULL;
struct { struct { int key; int value; } *intmap = NULL;
int key; struct { char *key; int value; } *strmap = NULL, s;
int value; struct { stbds_struct key; int value; } *map = NULL;
}* intmap = NULL;
struct {
char* key;
int value;
} *strmap = NULL, s;
struct {
stbds_struct key;
int value;
}* map = NULL;
stbds_struct *map2 = NULL; stbds_struct *map2 = NULL;
stbds_struct2 *map3 = NULL; stbds_struct2 *map3 = NULL;
stbds_string_arena sa = { 0 }; stbds_string_arena sa = { 0 };
@ -1691,25 +1673,16 @@ void stbds_unit_tests(void) {
} }
for (i=0; i < 4; ++i) { for (i=0; i < 4; ++i) {
arrpush(arr, 1); arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
arrpush(arr, 2);
arrpush(arr, 3);
arrpush(arr, 4);
arrdel(arr,i); arrdel(arr,i);
arrfree(arr); arrfree(arr);
arrpush(arr, 1); arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
arrpush(arr, 2);
arrpush(arr, 3);
arrpush(arr, 4);
arrdelswap(arr,i); arrdelswap(arr,i);
arrfree(arr); arrfree(arr);
} }
for (i=0; i < 5; ++i) { for (i=0; i < 5; ++i) {
arrpush(arr, 1); arrpush(arr,1); arrpush(arr,2); arrpush(arr,3); arrpush(arr,4);
arrpush(arr, 2);
arrpush(arr, 3);
arrpush(arr, 4);
stbds_arrins(arr,i,5); stbds_arrins(arr,i,5);
STBDS_ASSERT(arr[i] == 5); STBDS_ASSERT(arr[i] == 5);
if (i < 4) if (i < 4)
@ -1726,24 +1699,20 @@ void stbds_unit_tests(void) {
hmput(intmap, i, i*5); hmput(intmap, i, i*5);
for (i=0; i < testsize; i+=1) { for (i=0; i < testsize; i+=1) {
if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
else else STBDS_ASSERT(hmget(intmap, i) == i*5);
STBDS_ASSERT(hmget(intmap, i) == i * 5);
if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 ); if (i & 1) STBDS_ASSERT(hmget_ts(intmap, i, temp) == -2 );
else else STBDS_ASSERT(hmget_ts(intmap, i, temp) == i*5);
STBDS_ASSERT(hmget_ts(intmap, i, temp) == i * 5);
} }
for (i=0; i < testsize; i+=2) for (i=0; i < testsize; i+=2)
hmput(intmap, i, i*3); hmput(intmap, i, i*3);
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 ); if (i & 1) STBDS_ASSERT(hmget(intmap, i) == -2 );
else else STBDS_ASSERT(hmget(intmap, i) == i*3);
STBDS_ASSERT(hmget(intmap, i) == i * 3);
for (i=2; i < testsize; i+=4) for (i=2; i < testsize; i+=4)
hmdel(intmap, i); // delete half the entries hmdel(intmap, i); // delete half the entries
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 ); if (i & 3) STBDS_ASSERT(hmget(intmap, i) == -2 );
else else STBDS_ASSERT(hmget(intmap, i) == i*3);
STBDS_ASSERT(hmget(intmap, i) == i * 3);
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
hmdel(intmap, i); // delete the rest of the entries hmdel(intmap, i); // delete the rest of the entries
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
@ -1811,14 +1780,12 @@ void stbds_unit_tests(void) {
shput(strmap, strkey(i), i*3); shput(strmap, strkey(i), i*3);
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); if (i & 1) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
else else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
STBDS_ASSERT(shget(strmap, strkey(i)) == i * 3);
for (i=2; i < testsize; i+=4) for (i=2; i < testsize; i+=4)
shdel(strmap, strkey(i)); // delete half the entries shdel(strmap, strkey(i)); // delete half the entries
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 ); if (i & 3) STBDS_ASSERT(shget(strmap, strkey(i)) == -2 );
else else STBDS_ASSERT(shget(strmap, strkey(i)) == i*3);
STBDS_ASSERT(shget(strmap, strkey(i)) == i * 3);
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
shdel(strmap, strkey(i)); // delete the rest of the entries shdel(strmap, strkey(i)); // delete the rest of the entries
for (i=0; i < testsize; i+=1) for (i=0; i < testsize; i+=1)
@ -1827,10 +1794,7 @@ void stbds_unit_tests(void) {
} }
{ {
struct { struct { char *key; char value; } *hash = NULL;
char* key;
char value;
}* hash = NULL;
char name[4] = "jen"; char name[4] = "jen";
shput(hash, "bob" , 'h'); shput(hash, "bob" , 'h');
shput(hash, "sally" , 'e'); shput(hash, "sally" , 'e');
@ -1851,11 +1815,9 @@ void stbds_unit_tests(void) {
stbds_struct s = { i,i*2,i*3 ,i*4 }; stbds_struct s = { i,i*2,i*3 ,i*4 };
stbds_struct t = { i,i*2,i*3+1,i*4 }; stbds_struct t = { i,i*2,i*3+1,i*4 };
if (i & 1) STBDS_ASSERT(hmget(map, s) == 0); if (i & 1) STBDS_ASSERT(hmget(map, s) == 0);
else else STBDS_ASSERT(hmget(map, s) == i*5);
STBDS_ASSERT(hmget(map, s) == i * 5);
if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0); if (i & 1) STBDS_ASSERT(hmget_ts(map, s, temp) == 0);
else else STBDS_ASSERT(hmget_ts(map, s, temp) == i*5);
STBDS_ASSERT(hmget_ts(map, s, temp) == i * 5);
//STBDS_ASSERT(hmget(map, t.key) == 0); //STBDS_ASSERT(hmget(map, t.key) == 0);
} }
@ -1869,8 +1831,7 @@ void stbds_unit_tests(void) {
stbds_struct s = { i,i*2,i*3,i*4 }; stbds_struct s = { i,i*2,i*3,i*4 };
stbds_struct t = { i,i*2,i*3+1,i*4 }; stbds_struct t = { i,i*2,i*3+1,i*4 };
if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0); if (i & 1) STBDS_ASSERT(hmgets(map2, s.key).d == 0);
else else STBDS_ASSERT(hmgets(map2, s.key).d == i*4);
STBDS_ASSERT(hmgets(map2, s.key).d == i * 4);
//STBDS_ASSERT(hmgetp(map2, t.key) == 0); //STBDS_ASSERT(hmgetp(map2, t.key) == 0);
} }
hmfree(map2); hmfree(map2);
@ -1883,14 +1844,14 @@ void stbds_unit_tests(void) {
stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 }; stbds_struct2 s = { { i,i*2}, i*3, i*4, i*5 };
stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 }; stbds_struct2 t = { { i,i*2}, i*3+1, i*4, i*5 };
if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0); if (i & 1) STBDS_ASSERT(hmgets(map3, s.key).d == 0);
else else STBDS_ASSERT(hmgets(map3, s.key).d == i*5);
STBDS_ASSERT(hmgets(map3, s.key).d == i * 5);
//STBDS_ASSERT(hmgetp(map3, t.key) == 0); //STBDS_ASSERT(hmgetp(map3, t.key) == 0);
} }
#endif #endif
} }
#endif #endif
/* /*
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
This software is available under 2 licenses -- choose whichever you prefer. This software is available under 2 licenses -- choose whichever you prefer.

7988
src/stb_image.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,22 @@
static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask; static unsigned long mask = ExposureMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask;
static void create_pixmap(MwLL handle) {
XWindowAttributes attr;
int x, y;
unsigned int w, h;
MwLLGetXYWH(handle, &x, &y, &w, &h);
XGetWindowAttributes(handle->display, handle->window, &attr);
handle->pixmap = XCreatePixmap(handle->display, handle->window, w, h, attr.depth);
}
static void destroy_pixmap(MwLL handle) {
XFreePixmap(handle->display, handle->pixmap);
}
MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) { MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) {
MwLL r; MwLL r;
Window p; Window p;
@ -19,12 +35,18 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) {
p = parent->window; p = parent->window;
} }
r->window = XCreateSimpleWindow(r->display, p, x, y, width, height, 0, 0, WhitePixel(r->display, XDefaultScreen(r->display))); r->window = XCreateSimpleWindow(r->display, p, x, y, width, height, 0, 0, WhitePixel(r->display, XDefaultScreen(r->display)));
r->width = width;
r->height = height;
r->colormap = DefaultColormap(r->display, XDefaultScreen(r->display)); r->colormap = DefaultColormap(r->display, XDefaultScreen(r->display));
r->wm_delete = XInternAtom(r->display, "WM_DELETE_WINDOW", False); r->wm_delete = XInternAtom(r->display, "WM_DELETE_WINDOW", False);
XSetWMProtocols(r->display, r->window, &r->wm_delete, 1); XSetWMProtocols(r->display, r->window, &r->wm_delete, 1);
r->gc = XCreateGC(r->display, r->window, 0, 0); r->gc = XCreateGC(r->display, r->window, 0, 0);
create_pixmap(r);
XSetGraphicsExposures(r->display, r->gc, False); XSetGraphicsExposures(r->display, r->gc, False);
XSelectInput(r->display, r->window, mask); XSelectInput(r->display, r->window, mask);
@ -36,6 +58,7 @@ MwLL MwLLCreate(MwLL parent, int x, int y, int width, int height) {
void MwLLDestroy(MwLL handle) { void MwLLDestroy(MwLL handle) {
MwLLDestroyCommon(handle); MwLLDestroyCommon(handle);
destroy_pixmap(handle);
XFreeGC(handle->display, handle->gc); XFreeGC(handle->display, handle->gc);
XDestroyWindow(handle->display, handle->window); XDestroyWindow(handle->display, handle->window);
free(handle); free(handle);
@ -51,7 +74,7 @@ void MwLLPolygon(MwLL handle, MwPoint* points, int points_count, MwLLColor color
p[i].x = points[i].x; p[i].x = points[i].x;
p[i].y = points[i].y; p[i].y = points[i].y;
} }
XFillPolygon(handle->display, handle->window, handle->gc, p, points_count, Convex, CoordModeOrigin); XFillPolygon(handle->display, handle->pixmap, handle->gc, p, points_count, Convex, CoordModeOrigin);
free(p); free(p);
} }
@ -110,25 +133,43 @@ int MwLLPending(MwLL handle) {
void MwLLNextEvent(MwLL handle) { void MwLLNextEvent(MwLL handle) {
XEvent ev; XEvent ev;
while(XCheckTypedWindowEvent(handle->display, handle->window, ClientMessage, &ev) || XCheckWindowEvent(handle->display, handle->window, mask, &ev)) { while(XCheckTypedWindowEvent(handle->display, handle->window, ClientMessage, &ev) || XCheckWindowEvent(handle->display, handle->window, mask, &ev)) {
int render = 0;
if(ev.type == Expose) { if(ev.type == Expose) {
MwLLDispatch(handle, draw); render = 1;
} else if(ev.type == ButtonPress) { } else if(ev.type == ButtonPress) {
if(ev.xbutton.button == Button1) { if(ev.xbutton.button == Button1) {
MwLLDispatch(handle, down); MwLLDispatch(handle, down);
MwLLDispatch(handle, draw); render = 1;
} }
} else if(ev.type == ButtonRelease) { } else if(ev.type == ButtonRelease) {
if(ev.xbutton.button == Button1) { if(ev.xbutton.button == Button1) {
MwLLDispatch(handle, up); MwLLDispatch(handle, up);
MwLLDispatch(handle, draw); render = 1;
} }
} else if(ev.type == ConfigureNotify) { } else if(ev.type == ConfigureNotify) {
MwLLDispatch(handle, resize); MwLLDispatch(handle, resize);
if(handle->width != (unsigned int)ev.xconfigure.width || handle->height != (unsigned int)ev.xconfigure.height) {
destroy_pixmap(handle);
create_pixmap(handle);
render = 1;
}
handle->width = ev.xconfigure.width;
handle->height = ev.xconfigure.height;
} else if(ev.type == ClientMessage) { } else if(ev.type == ClientMessage) {
if(ev.xclient.data.l[0] == (long)handle->wm_delete) { if(ev.xclient.data.l[0] == (long)handle->wm_delete) {
MwLLDispatch(handle, close); MwLLDispatch(handle, close);
} }
} }
if(render) {
int x, y;
unsigned int w, h;
MwLLGetXYWH(handle, &x, &y, &w, &h);
MwLLDispatch(handle, draw);
XCopyArea(handle->display, handle->pixmap, handle->window, handle->gc, 0, 0, w, h, 0, 0);
}
} }
} }
@ -232,11 +273,14 @@ void MwLLDrawPixmap(MwLL handle, MwRect* rect, MwLLPixmap pixmap) {
} }
src = XRenderCreatePicture(handle->display, px, format, 0, &attr); src = XRenderCreatePicture(handle->display, px, format, 0, &attr);
dest = XRenderCreatePicture(handle->display, handle->window, format, 0, &attr); dest = XRenderCreatePicture(handle->display, handle->pixmap, format, 0, &attr);
XRenderSetPictureTransform(handle->display, src, &m); XRenderSetPictureTransform(handle->display, src, &m);
XRenderComposite(handle->display, PictOpSrc, src, 0, dest, 0, 0, 0, 0, rect->x, rect->y, rect->width, rect->height); XRenderComposite(handle->display, PictOpSrc, src, 0, dest, 0, 0, 0, 0, rect->x, rect->y, rect->width, rect->height);
XRenderFreePicture(handle->display, src);
XRenderFreePicture(handle->display, dest);
XFreePixmap(handle->display, px); XFreePixmap(handle->display, px);
} }
} }