boxes, attractors and everything

This commit is contained in:
Florian Stecker
2018-08-17 15:41:17 +02:00
parent 09a43c7ac3
commit c3deff6d64
3 changed files with 391 additions and 277 deletions

View File

@@ -12,8 +12,28 @@ static Bool alwaysTruePredicate(Display *display, XEvent *event, XPointer arg)
return true;
}
int initCairo(int screen, int mask, int width, int height, const char *name, GraphicsInfo *info)
void updateDimensions(DrawingContext *ctx)
{
double det = ctx->matrix.xx * ctx->matrix.yy - ctx->matrix.xy * ctx->matrix.yx;
double cx = (double)ctx->width/2;
double cy = (double)ctx->height/2;
double r = 2*sqrt((cx*cx + cy*cy)/det); // this is not safe anymore if we have non-uniform scaling
// don't use cairo_device_to_user() since the matrix might not be our CTM yet
cx -= ctx->matrix.x0;
cy -= ctx->matrix.y0;
ctx->center_x = ( ctx->matrix.yy * cx - ctx->matrix.xy * cy) / det;
ctx->center_y = (- ctx->matrix.yx * cx + ctx->matrix.xx * cy) / det;
ctx->radius = r;
ctx->scalefactor = sqrt(det);
}
GraphicsInfo *initCairo(int screen, int mask, int width, int height, const char *name)
{
GraphicsInfo *info = malloc(sizeof(GraphicsInfo));
DrawingContext *ctx = malloc(sizeof(DrawingContext));
info->context = ctx;
mask |= StructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask;
info->display = XOpenDisplay(NULL);
@@ -34,17 +54,18 @@ int initCairo(int screen, int mask, int width, int height, const char *name, Gra
XMapWindow(info->display, info->win);
info->sfc = cairo_xlib_surface_create(info->display, info->win, visual, width, height);
cairo_xlib_surface_set_size(info->sfc, width, height);
info->ctx = cairo_create(info->sfc);
cairo_matrix_init_identity(&info->matrix);
info->scalefactor = 1.0;
info->surface = cairo_xlib_surface_create(info->display, info->win, visual, width, height);
cairo_xlib_surface_set_size(info->surface, width, height);
info->context->cairo = cairo_create(info->surface);
cairo_matrix_init_identity(&info->context->matrix);
info->context->width = width;
info->context->height = height;
info->wm_delete_window = XInternAtom(info->display, "WM_DELETE_WINDOW", 0);
info->wm_protocols = XInternAtom(info->display, "WM_PROTOCOLS", 0);
XSetWMProtocols(info->display, info->win, &info->wm_delete_window, 1);
return 1;
return info;
}
void destroyCairo(GraphicsInfo *info)
@@ -52,6 +73,8 @@ void destroyCairo(GraphicsInfo *info)
XDestroyWindow(info->display, info->win);
XFreeColormap(info->display, info->cmap);
XCloseDisplay(info->display);
free(info->context);
free(info);
}
void startTimer(GraphicsInfo *info)
@@ -80,7 +103,7 @@ void waitUpdateTimer(GraphicsInfo *info)
info->frames++;
}
int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *, void*), void *data)
int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(DrawingContext *))
{
int state;
static int last_x, last_y;
@@ -88,14 +111,15 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
switch(ev->type) {
case Expose:
draw(info->ctx, data);
draw(info->context);
break;
case ConfigureNotify:
printf("ConfigureNotify Event, new dimensions: %d %d %d %d\n", ev->xconfigure.x, ev->xconfigure.y, ev->xconfigure.width, ev->xconfigure.height);
info->width = ev->xconfigure.width;
info->height = ev->xconfigure.height;
cairo_xlib_surface_set_size(info->sfc, info->width, info->height);
info->context->width = ev->xconfigure.width;
info->context->height = ev->xconfigure.height;
cairo_xlib_surface_set_size(info->surface, ev->xconfigure.width, ev->xconfigure.height);
draw(info->context);
break;
case KeyPress:
@@ -111,20 +135,19 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
cairo_matrix_translate(&transform, ev->xbutton.x, ev->xbutton.y);
cairo_matrix_scale(&transform, 5.0/4.0, 5.0/4.0);
cairo_matrix_translate(&transform, -ev->xbutton.x, -ev->xbutton.y);
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
info->scalefactor *= 5.0/4.0;
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
draw(info->context);
} else if(ev->xbutton.button == 5) {
cairo_matrix_t transform;
cairo_matrix_init_identity(&transform);
cairo_matrix_translate(&transform, ev->xbutton.x, ev->xbutton.y);
cairo_matrix_scale(&transform, 4.0/5.0, 4.0/5.0);
cairo_matrix_translate(&transform, -ev->xbutton.x, -ev->xbutton.y);
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
info->scalefactor *= 4.0/5.0;
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
draw(info->context);
}
last_x = ev->xbutton.x;
last_y = ev->xbutton.y;
draw(info->ctx, data);
break;
case MotionNotify:
@@ -135,26 +158,23 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
cairo_matrix_t transform;
cairo_matrix_init_identity(&transform);
cairo_matrix_translate(&transform, dx, dy);
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
printf("Button1Motion Event, dx: %d, dy: %d\n", dx, dy);
draw(info->ctx, data);
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
draw(info->context);
} else if(ev->xmotion.state & Button1Mask && ev->xmotion.state & ShiftMask) {
double width = (double) cairo_xlib_surface_get_width(info->surface);
double height = (double) cairo_xlib_surface_get_height(info->surface);
double angle =
atan2((double)ev->xmotion.y - (double)info->height/2, (double)ev->xmotion.x - (double)info->width/2)-
atan2((double)last_y - (double)info->height/2, (double)last_x - (double)info->width/2);
atan2((double)ev->xmotion.y - height/2, (double)ev->xmotion.x - width/2)-
atan2((double)last_y - height/2, (double)last_x - width/2);
cairo_matrix_t transform;
cairo_matrix_init_identity(&transform);
cairo_matrix_translate(&transform, (double)info->width/2, (double)info->height/2);
cairo_matrix_translate(&transform, width/2, height/2);
cairo_matrix_rotate(&transform, angle);
cairo_matrix_translate(&transform, -(double)info->width/2, -(double)info->height/2);
cairo_matrix_multiply(&info->matrix, &info->matrix, &transform);
printf("Button1Motion Event, angle: %f\n", angle);
draw(info->ctx, data);
cairo_matrix_translate(&transform, -width/2, -height/2);
cairo_matrix_multiply(&info->context->matrix, &info->context->matrix, &transform);
draw(info->context);
}
last_x = ev->xmotion.x;
last_y = ev->xmotion.y;
@@ -172,7 +192,7 @@ int processStandardEvent(GraphicsInfo *info, XEvent *ev, void (*draw)(cairo_t *,
}
int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*, void*), void (*draw)(cairo_t *, void*), void *data) // get any events from the queue and the server, process them if neccessary, quit if wanted
int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*), void (*draw)(DrawingContext*)) // get any events from the queue and the server, process them if neccessary, quit if wanted
{
XEvent ev;
@@ -193,10 +213,10 @@ int checkEvents(GraphicsInfo *info, int (*process)(GraphicsInfo*, XEvent*, void*
}
} */
if(processStandardEvent(info, &ev, draw, data))
if(processStandardEvent(info, &ev, draw))
return 1;
if(process(info, &ev, data))
if(process(info, &ev))
return 1; // quit event queue and application
return 0;