#ifndef XRND_RENDER_H
#define XRND_RENDER_H

#include <librnd/core/color_cache.h>
#include <librnd/hid/hid.h>
#include <librnd/hid/pixmap.h>

/* for Pixel */
#include <X11/Intrinsic.h>

#ifdef RND_HAVE_XRENDER
#include <X11/extensions/Xrender.h>
#endif /* RND_HAVE_XRENDER */

#ifdef RND_HAVE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif /* RND_HAVE_XINERAMA */

/* change states of the main drawing area scrollbar widget; if horiz is
   1 change the horizontal scrollbar, otherwise the vertical scrollbar */
typedef void (*xrnd_set_main_scroll_t)(int horiz, int pos, int view, int min, int max, unsigned int slider_size);

typedef void (*xrnd_need_idle_proc_t)(void);

typedef struct xrnd_ctx_s {
	/*** rnd and HID side (configured by the called HID) ***/
	rnd_design_t *dsg;
	rnd_hid_t *hid;
	xrnd_set_main_scroll_t set_mscroll;
	xrnd_need_idle_proc_t need_idle_proc;

	/*** x-side ***/
	Window window; /* main drawing area X window */
	Display *display;
	int screen;
	Colormap colormap;

	/*** internals ***/
	Pixmap pixmap;          /* Current pixmap we are drawing to (either main_pixmap in direct mode or mask_pixmap when drawing the sketch) */
	Pixmap main_pixmap;     /* 'Base pixmap', the final output all sketches are composed onto (then drawn) */
	Pixmap mask_pixmap;     /* 'Sketch pixmap' for compositing: color array */
	Pixmap mask_bitmap;     /* 'Sketch transparency bitmap' for compositing: tells which pixels shall be copied and which one are transparent/erased */
	int use_xrender;
	int pixmap_w, pixmap_h;
	GC my_gc, mask_gc;      /* generic drawing GCs */
	GC bg_gc;               /* used for drawing the background */
	GC clip_gc, pxm_clip_gc, bset_gc, bclear_gc; /* used for compositing */


	rnd_clrcache_t ccache;
	int ccache_inited;
	Pixel bgcolor, offlimit_color, grid_color;
	int bgred, bggreen, bgblue;

	int view_width, view_height;         /* This is the size, in pixels, of the viewport. */
	rnd_coord_t view_left_x, view_top_y; /* This is the PCB location represented by the upper left corner of the viewport.  Note that PCB coordinates put 0,0 in the upper left, much like X does. */
	double view_zoom;                    /* Denotes PCB units per screen pixel.  Larger numbers mean zooming out - the largest value means you are looking at the whole design.  */

	rnd_coord_t crosshair_x, crosshair_y;
	rnd_bool crosshair_on;
	int crosshair_in_window;
	int panning;
	rnd_composite_op_t drawing_mode;
	rnd_pixmap_t bg_img;
	unsigned direct:1;

	unsigned view_inited:1;
	unsigned need_redraw:1;


#ifdef RND_HAVE_XRENDER
	Picture main_picture;
	Picture mask_picture;
	Pixmap pale_pixmap;
	Picture pale_picture;
#endif /* RND_HAVE_XRENDER */
} xrnd_ctx_t;

extern xrnd_ctx_t xrnd;

void xrnd_init(Display *display, int screen, rnd_hid_t *myhid, xrnd_set_main_scroll_t set_mscroll, xrnd_need_idle_proc_t need_idle_proc);

/* Call this on first expose of the main drawing window drawing area */
void xrnd_work_area_first_expose(Window win, int width, int height, Pixel bgcolor);

/* Call these on subsequent expsoe/resize events of the main window drawing area */
void xrnd_work_area_expose(int x, int y, int width, int height);
void xrnd_work_area_resize(int width, int height, Pixel bgcolor);


/* v_widht, v_height: dimensions of the widget in pixels */
/* zoom: PCB units per screen pixel */
void xrnd_render_preview(rnd_hid_t *hid, Display *display, Window window, int clrdepth, GC gc, int v_width, int v_height, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2, double zoom, rnd_hid_expose_ctx_t *expctx, rnd_bool_t flip_local, rnd_bool_t flip_global, rnd_bool_t flip_localx, rnd_bool_t flip_localy);


void xrnd_show_crosshair(int);

/* Call this when mouse cursor moves within the main window; pos_x and pos_y
   are drawing area widget relative */
void xrnd_crosshair_move_to(int pos_x, int pos_y);

/* Call this when mouse cursor enter or leaves the main window; ex and ey are
   drawing area widget relative coords where the cursor enters the widget */
void xrnd_crosshair_enter(int ex, int ey);
void xrnd_crosshair_leave(void);


/* Convert pixel coords to design coords (in main window) */
void xrnd_coords_to_design(int vx, int vy, rnd_coord_t *px, rnd_coord_t *py);

/* Call app's draw_marks on the main window */
void xrnd_draw_marks(void);

/* Redraw the main drawing */
void xrnd_redraw_main(rnd_hid_t *hid);

/* To be called from the HID implementation to scroll to already V-transformed x;y */
void xrnd_pan_direct(rnd_bool mode, rnd_coord_t x, rnd_coord_t y);

/* Make sure the main window view is panned within bounds and update scrollbars */
void xrnd_pan_fixup(void);

/* Zoom main window out to extent */
void xrnd_zoom_max(void);

/* Main window pixel-to-coord conversion in the mian window */
rnd_coord_t xrnd_px(int x);
rnd_coord_t xrnd_py(int y);

void xrnd_load_old_bgimage(const char *fn);


/* librnd HID API functions */
rnd_hid_gc_t xrnd_make_gc(rnd_hid_t *hid);
void xrnd_destroy_gc(rnd_hid_gc_t gc);
void xrnd_render_burst(rnd_hid_t *hid, rnd_burst_op_t op, const rnd_box_t *screen);
void xrnd_set_drawing_mode(rnd_hid_t *hid, rnd_composite_op_t op, rnd_bool direct, const rnd_box_t *drw_screen);
void xrnd_set_color(rnd_hid_gc_t gc, const rnd_color_t *pcolor);
void xrnd_set_line_cap(rnd_hid_gc_t gc, rnd_cap_style_t style);
void xrnd_set_line_width(rnd_hid_gc_t gc, rnd_coord_t width);
void xrnd_set_draw_xor(rnd_hid_gc_t gc, int xor_set);
void xrnd_draw_line(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2);
void xrnd_draw_arc(rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t width, rnd_coord_t height, rnd_angle_t start_angle, rnd_angle_t delta_angle);
void xrnd_draw_rect(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2);
void xrnd_fill_circle(rnd_hid_gc_t gc, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t radius);
void xrnd_fill_polygon(rnd_hid_gc_t gc, int n_coords, rnd_coord_t * x, rnd_coord_t * y);
void xrnd_fill_polygon_offs(rnd_hid_gc_t gc, int n_coords, rnd_coord_t *x, rnd_coord_t *y, rnd_coord_t dx, rnd_coord_t dy);
void xrnd_fill_rect(rnd_hid_gc_t gc, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2);
void xrnd_draw_pixmap(rnd_hid_t *hid, rnd_coord_t cx, rnd_coord_t cy, rnd_coord_t sx, rnd_coord_t sy, rnd_pixmap_t *pixmap);
void xrnd_uninit_pixmap(rnd_hid_t *hid, rnd_pixmap_t *pixmap);
void xrnd_zoom_win(rnd_hid_t *hid, rnd_coord_t x1, rnd_coord_t y1, rnd_coord_t x2, rnd_coord_t y2, rnd_bool set_crosshair);
void xrnd_zoom(rnd_hid_t *hid, rnd_coord_t center_x, rnd_coord_t center_y, double factor, int relative);
void xrnd_pan(rnd_hid_t *hid, rnd_coord_t x, rnd_coord_t y, int relative);
void xrnd_pan_mode(rnd_hid_t *hid, rnd_coord_t x, rnd_coord_t y, rnd_bool mode);
void xrnd_view_get(rnd_hid_t *hid, rnd_box_t *viewbox);
double xrnd_benchmark(rnd_hid_t *hid);
void xrnd_notify_crosshair_change(rnd_hid_t *hid, rnd_bool changes_complete);
void xrnd_notify_mark_change(rnd_hid_t *hid, rnd_bool changes_complete);

/* almost direct HID API functions (need to be wrapped) */
void xrnd_set_crosshair(rnd_coord_t x, rnd_coord_t y, rnd_set_crosshair_t action, int update_pan, int *in_move_event);


#endif
