diff options
-rw-r--r-- | generic/tkZinc.c | 542 |
1 files changed, 401 insertions, 141 deletions
diff --git a/generic/tkZinc.c b/generic/tkZinc.c index 1a5784a..d737cfb 100644 --- a/generic/tkZinc.c +++ b/generic/tkZinc.c @@ -30,6 +30,9 @@ static const char compile_id[]="$Compile: " __FILE__ " " __DATE__ " " __TIME__ " static const char * const zinc_version = "zinc-version-" PACKAGE_VERSION; +#define GLEW_STATIC +#include <GL/glew.h> + #include "Types.h" #include "Geo.h" #include "Item.h" @@ -166,6 +169,9 @@ static int ZnGLAttribs[] = { ZnTess ZnTesselator; +#if defined(GL) && defined(ROTATION) +static void TransformEvent _ANSI_ARGS_((ZnWInfo *wi, XEvent *event)); +#endif static void PickCurrentItem _ANSI_ARGS_((ZnWInfo *wi, XEvent *event)); #ifdef PTK_800 static int ZnReliefParse _ANSI_ARGS_((ClientData client_data, Tcl_Interp *interp, @@ -246,44 +252,54 @@ static Tk_ObjCustomOption gradientOption = { #ifdef PTK_800 #define BORDER_WIDTH_SPEC 0 -#define BACK_COLOR_SPEC 1 -#define CONFINE_SPEC 2 -#define CURSOR_SPEC 3 -#define FONT_SPEC 4 -#define FORE_COLOR_SPEC 5 -#define FULL_RESHAPE_SPEC 6 -#define HEIGHT_SPEC 7 -#define HIGHLIGHT_BACK_COLOR_SPEC 8 -#define HIGHLIGHT_COLOR_SPEC 9 -#define HIGHLIGHT_THICKNESS_SPEC 10 -#define INSERT_COLOR_SPEC 11 -#define INSERT_OFF_TIME_SPEC 12 -#define INSERT_ON_TIME_SPEC 13 -#define INSERT_WIDTH_SPEC 14 -#define MAP_DISTANCE_SYMBOL_SPEC 15 -#define MAP_TEXT_FONT_SPEC 16 -#define OVERLAP_MANAGER_SPEC 17 -#define PICK_APERTURE_SPEC 18 -#define RELIEF_SPEC 19 -#define RENDER_SPEC 20 -#define RESHAPE_SPEC 21 -#define SCROLL_REGION_SPEC 22 -#define SELECT_COLOR_SPEC 23 -#define SPEED_VECTOR_LENGTH_SPEC 24 -#define TAKE_FOCUS_SPEC 25 -#define TILE_SPEC 26 -#define VISIBLE_HISTORY_SIZE_SPEC 27 -#define MANAGED_HISTORY_SIZE_SPEC 28 -#define TRACK_SYMBOL_SPEC 29 -#define WIDTH_SPEC 30 -#define X_SCROLL_CMD_SPEC 31 -#define X_SCROLL_INCREMENT_SPEC 32 -#define Y_SCROLL_CMD_SPEC 33 -#define Y_SCROLL_INCREMENT_SPEC 34 -#define BBOXES_SPEC 35 -#define BBOXES_COLOR_SPEC 36 -#define LIGHT_ANGLE_SPEC 37 -#define FOLLOW_POINTER_SPEC 38 +#define BACK_COLOR_SPEC (BORDER_WIDTH_SPEC + 1) +#define CONFINE_SPEC (BACK_COLOR_SPEC + 1) +#define CURSOR_SPEC (CONFINE_SPEC + 1) +#define FONT_SPEC (CURSOR_SPEC + 1) +#define FORE_COLOR_SPEC (FONT_SPEC + 1) +#define FULL_RESHAPE_SPEC (FORE_COLOR_SPEC + 1) +#define HEIGHT_SPEC (FULL_RESHAPE_SPEC + 1) +#define HIGHLIGHT_BACK_COLOR_SPEC (HEIGHT_SPEC + 1) +#define HIGHLIGHT_COLOR_SPEC (HIGHLIGHT_BACK_COLOR_SPEC + 1) +#define HIGHLIGHT_THICKNESS_SPEC (HIGHLIGHT_COLOR_SPEC + 1) +#define INSERT_COLOR_SPEC (HIGHLIGHT_THICKNESS_SPEC + 1) +#define INSERT_OFF_TIME_SPEC (INSERT_COLOR_SPEC + 1) +#define INSERT_ON_TIME_SPEC (INSERT_OFF_TIME_SPEC + 1) +#define INSERT_WIDTH_SPEC (INSERT_ON_TIME_SPEC + 1) +#define PICK_APERTURE_SPEC (INSERT_WIDTH_SPEC + 1) +#define RELIEF_SPEC (PICK_APERTURE_SPEC + 1) +#define RENDER_SPEC (RELIEF_SPEC + 1) +#define RESHAPE_SPEC (RENDER_SPEC + 1) +#define SCROLL_REGION_SPEC (RESHAPE_SPEC + 1) +#define SELECT_COLOR_SPEC (SCROLL_REGION_SPEC + 1) +#define TAKE_FOCUS_SPEC (SELECT_COLOR_SPEC + 1) +#define TILE_SPEC (TAKE_FOCUS_SPEC + 1) +#define WIDTH_SPEC (TILE_SPEC + 1) +#define X_SCROLL_CMD_SPEC (WIDTH_SPEC + 1) +#define X_SCROLL_INCREMENT_SPEC (X_SCROLL_CMD_SPEC + 1) +#define Y_SCROLL_CMD_SPEC (X_SCROLL_INCREMENT_SPEC + 1) +#define Y_SCROLL_INCREMENT_SPEC (Y_SCROLL_CMD_SPEC + 1) +#define BBOXES_SPEC (Y_SCROLL_INCREMENT_SPEC + 1) +#define BBOXES_COLOR_SPEC (BBOXES_SPEC + 1) +#define LIGHT_ANGLE_SPEC (BBOXES_COLOR_SPEC + 1) +#define FOLLOW_POINTER_SPEC (LIGHT_ANGLE_SPEC + 1) +#ifdef ATC +#define MAP_DISTANCE_SYMBOL_SPEC (FOLLOW_POINTER_SPEC + 1) +#define MAP_TEXT_FONT_SPEC (MAP_DISTANCE_SYMBOL_SPEC + 1) +#define OVERLAP_MANAGER_SPEC (MAP_TEXT_FONT_SPEC + 1) +#define SPEED_VECTOR_LENGTH_SPEC (OVERLAP_MANAGER_SPEC + 1) +#define VISIBLE_HISTORY_SIZE_SPEC (SPEED_VECTOR_LENGTH_SPEC + 1) +#define MANAGED_HISTORY_SIZE_SPEC (VISIBLE_HISTORY_SIZE_SPEC + 1) +#define TRACK_SYMBOL_SPEC (MANAGED_HISTORY_SIZE_SPEC + 1) +#endif +#if defined(GL) && defined(ROTATION) +#ifdef ATC +#define SCREEN_ROTATION_SPEC (TRACK_SYMBOL_SPEC + 1) +#else +#define SCREEN_ROTATION_SPEC (FOLLOW_POINTER_SPEC + 1) +#endif +#define ENABLE_ROTATION_SPEC (SCREEN_ROTATION_SPEC + 1) +#endif #else #define CONFIG_FONT 1<<0 #define CONFIG_MAP_FONT 1<<1 @@ -303,7 +319,11 @@ static Tk_ObjCustomOption gradientOption = { #define CONFIG_MAP_SYMBOL 1<<15 #define CONFIG_TRACK_SYMBOL 1<<16 #define CONFIG_TILE 1<<17 -#define CONFIG_DEBUG 1<<18 +#define CONFIG_DEBUG 1<<18 +#if defined(GL) && defined(ROTATION) +#define CONFIG_ROTATION 1<<19 +#define CONFIG_ENABLE_ROTATION 1<<20 +#endif #endif /* @@ -342,16 +362,6 @@ static Tk_ConfigSpec config_specs[] = { "600", Tk_Offset(ZnWInfo, insert_on_time), 0, NULL}, {TK_CONFIG_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", "2", Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL}, -#ifdef ATC - {TK_CONFIG_CUSTOM, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", - "AtcSymbol19", Tk_Offset(ZnWInfo, map_distance_symbol), - TK_CONFIG_NULL_OK, &bitmapOption}, - {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - Tk_Offset(ZnWInfo, map_text_font), 0, NULL}, - {TK_CONFIG_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", - Tk_Offset(ZnWInfo, om_group_id), 0, NULL}, -#endif {TK_CONFIG_INT, "-pickaperture", "pickAperture", "PickAperture", "1", Tk_Offset(ZnWInfo, pick_aperture), 0, NULL}, {TK_CONFIG_CUSTOM, "-relief", "relief", "Relief", @@ -364,22 +374,10 @@ static Tk_ConfigSpec config_specs[] = { "", Tk_Offset(ZnWInfo, region), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-selectbackground", "selectBackground", "Foreground", "#a0a0a0", Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption}, -#ifdef ATC - {TK_CONFIG_DOUBLE, "-speedvectorlength", "speedVectorLength", - "SpeedVectorLength", "3", Tk_Offset(ZnWInfo, speed_vector_length), 0, NULL}, -#endif {TK_CONFIG_STRING, "-takefocus", "takeFocus", "TakeFocus", NULL, Tk_Offset(ZnWInfo, take_focus), TK_CONFIG_NULL_OK, NULL}, {TK_CONFIG_CUSTOM, "-tile", "tile", "Tile", "", Tk_Offset(ZnWInfo, tile), 0, &imageOption}, -#ifdef ATC - {TK_CONFIG_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", - "6", Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL}, - {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", - "TrackManagedHistorySize", "6", Tk_Offset(ZnWInfo, track_managed_history_size), 0, NULL}, - {TK_CONFIG_CUSTOM, "-tracksymbol", "trackSymbol", "TrackSymbol", - "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol), TK_CONFIG_NULL_OK, &bitmapOption}, -#endif {TK_CONFIG_PIXELS, "-width", "width", "Width", "10c", Tk_Offset(ZnWInfo, opt_width), 0, NULL}, {TK_CONFIG_CALLBACK, "-xscrollcommand", "xScrollCommand", "ScrollCommand", @@ -401,6 +399,30 @@ static Tk_ConfigSpec config_specs[] = { "120", Tk_Offset(ZnWInfo, light_angle), 0, NULL}, {TK_CONFIG_BOOLEAN, "-followpointer", "followPointer", "FollowPointer", "1", Tk_Offset(ZnWInfo, follow_pointer), 0, NULL}, +#ifdef ATC + {TK_CONFIG_CUSTOM, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", + "AtcSymbol19", Tk_Offset(ZnWInfo, map_distance_symbol), + TK_CONFIG_NULL_OK, &bitmapOption}, + {TK_CONFIG_FONT, "-maptextfont", "mapTextFont", "MapTextFont", + "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", + Tk_Offset(ZnWInfo, map_text_font), 0, NULL}, + {TK_CONFIG_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", + Tk_Offset(ZnWInfo, om_group_id), 0, NULL}, + {TK_CONFIG_DOUBLE, "-speedvectorlength", "speedVectorLength", + "SpeedVectorLength", "3", Tk_Offset(ZnWInfo, speed_vector_length), 0, NULL}, + {TK_CONFIG_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", + "6", Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL}, + {TK_CONFIG_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", + "TrackManagedHistorySize", "6", Tk_Offset(ZnWInfo, track_managed_history_size), 0, NULL}, + {TK_CONFIG_CUSTOM, "-tracksymbol", "trackSymbol", "TrackSymbol", + "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol), TK_CONFIG_NULL_OK, &bitmapOption}, +#endif +#if defined(GL) && defined(ROTATION) + {TK_CONFIG_BOOLEAN, "-enablerotation", "enableRotation", "EnableRotation", + "0", Tk_Offset(ZnWInfo, enable_rotation), 0, NULL}, + {TK_CONFIG_DOUBLE, "-screenrotation", "screenRotation", "ScreenRotation", + "0", Tk_Offset(ZnWInfo, screen_rotation), 0, NULL}, +#endif {TK_CONFIG_END, NULL, NULL, NULL, NULL, 0, 0, NULL} }; @@ -441,16 +463,6 @@ static Tk_OptionSpec option_specs[] = { "600", -1, Tk_Offset(ZnWInfo, insert_on_time), 0, NULL, CONFIG_FOCUS}, {TK_OPTION_PIXELS, "-insertwidth", "insertWidth", "InsertWidth", "2", -1, Tk_Offset(ZnWInfo, text_info.insert_width), 0, NULL, CONFIG_FOCUS_ITEM}, -#ifdef ATC - {TK_OPTION_STRING, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", - "AtcSymbol19", Tk_Offset(ZnWInfo, map_symbol_obj), -1, - TK_OPTION_NULL_OK, NULL, CONFIG_MAP_SYMBOL|CONFIG_INVALIDATE_MAPS}, - {TK_OPTION_FONT, "-maptextfont", "mapTextFont", "MapTextFont", - "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", - -1, Tk_Offset(ZnWInfo, map_text_font), 0, NULL, CONFIG_MAP_FONT}, - {TK_OPTION_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", - -1, Tk_Offset(ZnWInfo, om_group_id), 0, NULL, CONFIG_OM}, -#endif {TK_OPTION_INT, "-pickaperture", "pickAperture", "PickAperture", "1", -1, Tk_Offset(ZnWInfo, pick_aperture), 0, NULL, 0}, {TK_OPTION_CUSTOM, "-relief", "relief", "Relief", @@ -464,25 +476,10 @@ static Tk_OptionSpec option_specs[] = { TK_OPTION_NULL_OK, NULL, CONFIG_SET_ORIGIN|CONFIG_SCROLL_REGION}, {TK_OPTION_CUSTOM, "-selectbackground", "selectBackground", "Foreground", "#a0a0a0", -1, Tk_Offset(ZnWInfo, text_info.sel_color), 0, &gradientOption, 0}, -#ifdef ATC - {TK_OPTION_DOUBLE, "-speedvectorlength", "speedVectorLength", - "SpeedVectorLength", "3", -1, Tk_Offset(ZnWInfo, speed_vector_length), - 0, NULL, CONFIG_INVALIDATE_TRACKS}, -#endif {TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus", NULL, Tk_Offset(ZnWInfo, take_focus), -1, TK_OPTION_NULL_OK, NULL, 0}, {TK_OPTION_STRING, "-tile", "tile", "Tile", "", Tk_Offset(ZnWInfo, tile_obj), -1, TK_OPTION_NULL_OK, NULL, CONFIG_TILE|CONFIG_DAMAGE_ALL}, -#ifdef ATC - {TK_OPTION_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", - "6", -1, Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL, CONFIG_INVALIDATE_TRACKS}, - {TK_OPTION_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", - "TrackManagedHistorySize", "6", -1, Tk_Offset(ZnWInfo, track_managed_history_size), - 0, NULL, CONFIG_INVALIDATE_TRACKS}, - {TK_OPTION_STRING, "-tracksymbol", "trackSymbol", "TrackSymbol", - "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol_obj), -1, - 0, NULL, CONFIG_TRACK_SYMBOL|CONFIG_INVALIDATE_TRACKS|CONFIG_INVALIDATE_WPS}, -#endif {TK_OPTION_PIXELS, "-width", "width", "Width", "10c", -1, Tk_Offset(ZnWInfo, opt_width), 0, NULL, CONFIG_DAMAGE_ALL|CONFIG_REQUEST_GEOM}, #ifdef PTK @@ -514,6 +511,33 @@ static Tk_OptionSpec option_specs[] = { "120", -1, Tk_Offset(ZnWInfo, light_angle), 0, NULL, CONFIG_DAMAGE_ALL}, {TK_OPTION_BOOLEAN, "-followpointer", "followPointer", "FollowPointer", "1", -1, Tk_Offset(ZnWInfo, follow_pointer), 0, NULL, CONFIG_FOLLOW_POINTER}, +#ifdef ATC + {TK_OPTION_STRING, "-mapdistancesymbol", "mapDistanceSymbol", "MapDistanceSymbol", + "AtcSymbol19", Tk_Offset(ZnWInfo, map_symbol_obj), -1, + TK_OPTION_NULL_OK, NULL, CONFIG_MAP_SYMBOL|CONFIG_INVALIDATE_MAPS}, + {TK_OPTION_FONT, "-maptextfont", "mapTextFont", "MapTextFont", + "-adobe-helvetica-bold-r-normal--*-120-*-*-*-*-*-*", + -1, Tk_Offset(ZnWInfo, map_text_font), 0, NULL, CONFIG_MAP_FONT}, + {TK_OPTION_INT, "-overlapmanager", "overlapManager", "OverlapManager", "1", + -1, Tk_Offset(ZnWInfo, om_group_id), 0, NULL, CONFIG_OM}, + {TK_OPTION_DOUBLE, "-speedvectorlength", "speedVectorLength", + "SpeedVectorLength", "3", -1, Tk_Offset(ZnWInfo, speed_vector_length), + 0, NULL, CONFIG_INVALIDATE_TRACKS}, + {TK_OPTION_INT, "-trackvisiblehistorysize", "trackVisibleHistorySize", "TrackVisibleHistorySize", + "6", -1, Tk_Offset(ZnWInfo, track_visible_history_size), 0, NULL, CONFIG_INVALIDATE_TRACKS}, + {TK_OPTION_INT, "-trackmanagedhistorysize", "trackManagedHistorySize", + "TrackManagedHistorySize", "6", -1, Tk_Offset(ZnWInfo, track_managed_history_size), + 0, NULL, CONFIG_INVALIDATE_TRACKS}, + {TK_OPTION_STRING, "-tracksymbol", "trackSymbol", "TrackSymbol", + "AtcSymbol15", Tk_Offset(ZnWInfo, track_symbol_obj), -1, + 0, NULL, CONFIG_TRACK_SYMBOL|CONFIG_INVALIDATE_TRACKS|CONFIG_INVALIDATE_WPS}, +#endif +#if defined(GL) && defined(ROTATION) + {TK_OPTION_BOOLEAN, "-enablerotation", "enableRotation", "EnableRotation", + "0", -1, Tk_Offset(ZnWInfo, enable_rotation), 0, NULL, CONFIG_ENABLE_ROTATION}, + {TK_OPTION_DOUBLE, "-screenrotation", "screenRotation", "ScreenRotation", + "0", -1, Tk_Offset(ZnWInfo, screen_rotation), 0, NULL, CONFIG_ROTATION}, +#endif {TK_OPTION_END, NULL, NULL, NULL, NULL, 0, 0, 0, NULL, 0} }; @@ -1140,6 +1164,8 @@ static void InitRendering2(ZnWInfo *wi, Tk_Window top_level) { + static int glew_inited = 0; + GLenum err; ZnGLContextEntry *ce; ZnGLContext gl_context; GLfloat r[2]; /* Min, Max */ @@ -1278,6 +1304,14 @@ InitRendering2(ZnWInfo *wi, fprintf(stderr, "Max texture size: %d\n", ce->max_tex_size); } + + if (!glew_inited) { + glew_inited = 1; + err = glewInit(); + if (err != GLEW_OK) { + fprintf(stderr, "GLEW: %s\n", glewGetErrorString(err)); + } + } #if defined(MAC_OSX_TK) UpdateBufferRect(ce, wi->win); @@ -1389,6 +1423,10 @@ ZincObjCmd(ClientData client_data, /* Main window associated with wi->flags = 0; wi->render = -1; wi->real_top = None; +#if defined(GL) && defined(ROTATION) + wi->screen_rotation = 0; + wi->enable_rotation = 0; +#endif ASSIGN(wi->flags, ZN_HAS_GL, has_gl); #if defined(SHAPE) @@ -1531,7 +1569,8 @@ ZincObjCmd(ClientData client_data, /* Main window associated with Event, (ClientData) wi); Tk_CreateEventHandler(tkwin, KeyPressMask|KeyReleaseMask| ButtonPressMask|ButtonReleaseMask|EnterWindowMask| - LeaveWindowMask|PointerMotionMask|VirtualEventMask, + LeaveWindowMask|PointerMotionMask|VirtualEventMask| + MouseWheelMask, Bind, (ClientData) wi); Tk_CreateSelHandler(tkwin, XA_PRIMARY, XA_STRING, FetchSelection, (ClientData) wi, XA_STRING); @@ -1562,11 +1601,16 @@ ZincObjCmd(ClientData client_data, /* Main window associated with * Allocate double buffer pixmap/image. */ wi->draw_buffer = Tk_GetPixmap(wi->dpy, RootWindowOfScreen(wi->screen), - wi->width, wi->height, Tk_Depth(wi->win)); + wi->opt_width, wi->opt_height, Tk_Depth(wi->win)); } -#ifdef GL + +#if defined(GL) && defined(ROTATION) else { InitRendering1(wi); + wi->canvastex = 0; + wi->fbo = 0; + wi->depthstencil = 0; + SET(wi->flags, ZN_UPDATE_CANVASTEX); } #endif @@ -4559,12 +4603,13 @@ WidgetObjCmd(ClientData client_data, /* Information about the widget. ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask | - PointerMotionMask | VirtualEventMask)) { + PointerMotionMask | VirtualEventMask | + MouseWheelMask)) { Tk_DeleteBinding(interp, wi->binding_table, elem, Tcl_GetString(args[3])); Tcl_ResetResult(interp); Tcl_AppendResult(interp, "requested illegal events; ", "only key, button, motion, enter, leave ", - "and virtual events may be used", NULL); + "mousewheel and virtual events may be used", NULL); goto error; } } @@ -6731,6 +6776,21 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ #endif #endif +#if defined(GL) && defined(ROTATION) + // + // No rotation correction if no GL rendering + if (CONFIG_PROBE(SCREEN_ROTATION_SPEC) || CONFIG_PROBE(ENABLE_ROTATION_SPEC)) { + if (!wi->render) { + wi->screen_rotation = 0; + wi->enable_rotation = 0; + } + else { + SET(wi->flags, ZN_UPDATE_CANVASTEX); + ZnNeedRedisplay(wi); + } + } +#endif + /* * Maintain the pick aperture within meaningful bounds. */ @@ -6967,6 +7027,19 @@ Configure(Tcl_Interp *interp,/* Used for error reporting. */ wi->render = 0; } +#if defined(GL) && defined(ROTATION) + if ((mask & CONFIG_ROTATION) || (mask & CONFIG_ENABLE_ROTATION) || init) { + if (!wi->render) { + wi->screen_rotation = 0; + wi->enable_rotation = 0; + } + else { + SET(wi->flags, ZN_UPDATE_CANVASTEX); + ZnNeedRedisplay(wi); + } + } +#endif + if ((mask & CONFIG_SCROLL_REGION) || init) { /* * Compute the scroll region @@ -7357,10 +7430,12 @@ Event(ClientData client_data, /* Information about widget. */ if (event->type == MapNotify) { SET(wi->flags, ZN_CONFIGURE_EVENT); FinishSetup(wi); + wi->width = wi->opt_width; + wi->height = wi->opt_height; ZnNeedRedisplay(wi); } else if (event->type == Expose) { - ZnDim width, height; + ZnDim width, height; SET(wi->flags, ZN_CONFIGURE_EVENT); FinishSetup(wi); @@ -7376,8 +7451,8 @@ Event(ClientData client_data, /* Information about widget. */ height += bbox.orig.y; bbox.orig.y = 0; } - bbox.corner.x = MIN(wi->width, bbox.orig.x + width); - bbox.corner.y = MIN(wi->height, bbox.orig.y + height); + bbox.corner.x = MIN(wi->opt_width, bbox.orig.x + width); + bbox.corner.y = MIN(wi->opt_height, bbox.orig.y + height); //printf("expose %d %d %d %d\n", // ((XExposeEvent*) event)->x, ((XExposeEvent*) event)->y, @@ -7408,10 +7483,10 @@ Event(ClientData client_data, /* Information about widget. */ int_width = Tk_Width(wi->win); int_height = Tk_Height(wi->win); - if ((wi->width != int_width) || (wi->height != int_height)) { + if ((wi->opt_width != int_width) || (wi->opt_height != int_height)) { bbox.orig.x = bbox.orig.y = 0; - bbox.corner.x = MAX(wi->width, int_width); - bbox.corner.y = MAX(wi->height, int_height); + bbox.corner.x = MAX(wi->opt_width, int_width); + bbox.corner.y = MAX(wi->opt_height, int_height); wi->opt_width = wi->width = int_width; wi->opt_height = wi->height = int_height; @@ -7440,14 +7515,16 @@ Event(ClientData client_data, /* Information about widget. */ int_width, int_height, DefaultDepthOfScreen(wi->screen)); } -#if defined(MAC_OSX_TK) && defined(GL) else { +#if defined(GL) +#if defined(MAC_OSX_TK) ZnGLContextEntry *ce = ZnGLMakeCurrent(wi->dpy, wi); UpdateBufferRect(ce, wi->win); aglUpdateContext(ce->context); +#endif + SET(wi->flags, ZN_UPDATE_CANVASTEX); +#endif } -#endif - } else { /* @@ -7913,6 +7990,11 @@ Bind(ClientData client_data, /* Information about widget. */ if ((event->type == ButtonPress) || (event->type == ButtonRelease)) { int mask; +#if defined(GL) && defined(ROTATION) + if (wi->enable_rotation) { + TransformEvent(wi, event); + } +#endif switch (event->xbutton.button) { case Button1: mask = Button1Mask; @@ -7971,12 +8053,22 @@ Bind(ClientData client_data, /* Information about widget. */ } else if ((event->type == EnterNotify) || (event->type == LeaveNotify)) { +#if defined(GL) && defined(ROTATION) + if (wi->enable_rotation) { + TransformEvent(wi, event); + } +#endif wi->state = event->xcrossing.state; PickCurrentItem(wi, event); goto done; } else if (event->type == MotionNotify) { +#if defined(GL) && defined(ROTATION) + if (wi->enable_rotation) { + TransformEvent(wi, event); + } +#endif wi->state = event->xmotion.state; if (wi->follow_pointer) { PickCurrentItem(wi, event); @@ -8322,6 +8414,14 @@ Destroy(ZnWInfo *wi) wi->map_font_tfi = NULL; } #endif +#ifdef ROTATION + if (wi->canvastex) { + glDeleteFramebuffersEXT(1, &wi->fbo); + glDeleteRenderbuffersEXT(1, &wi->depthstencil); + glDeleteTextures(1, &wi->canvastex); + wi->canvastex = 0; + } +#endif /* * Remove the widget from the context list and * free the context if no more widgets are active. @@ -8513,6 +8613,154 @@ Update(ZnWInfo *wi) } } +#if defined(GL) && defined(ROTATION) +static void +TransformEvent(ZnWInfo *wi, + XEvent *event) +{ + ZnPoint p, xp; + + p.x = event->xmotion.x; + p.y = event->xmotion.y; + ZnTransformPoint(&wi->rotation_transfo, &p, &xp); + event->xmotion.x = ZnNearestInt(xp.x); + event->xmotion.y = ZnNearestInt(xp.y); +} + +static void +SetupRotationTexture(ZnWInfo *wi) +{ + ZnReal offsetX, offsetY; + ZnReal tex_width, tex_height; + int i; + GLenum status; + + // + // Create the canvas buffer if needed (rotation) + if (ISSET(wi->flags, ZN_UPDATE_CANVASTEX)) { + CLEAR(wi->flags, ZN_UPDATE_CANVASTEX); + // + // Free the canvas texture it'll be recreated + // automatically with the correct size. + if (wi->canvastex) { + glDeleteTextures(1, &wi->canvastex); + wi->canvastex = 0; + } + if (wi->depthstencil) { + glDeleteRenderbuffersEXT(1, &wi->depthstencil); + wi->depthstencil = 0; + } + // + // Compute the intermediate canvas size + wi->width = wi->height = hypot(wi->opt_width, wi->opt_height); + tex_width = To2Power(wi->width); + tex_height = To2Power(wi->height); + // + // Transform the window rectangle around the origin and + // compute window coordinates in texture space (center of window + // on texture center) + ZnTransfoSetIdentity(&wi->rotation_transfo); + offsetX = ZnNearestInt(wi->opt_width/2.0); + offsetY = ZnNearestInt(wi->opt_height/2.0); + ZnTranslate(&wi->rotation_transfo, -offsetX, -offsetY, 0); + ZnRotateDeg(&wi->rotation_transfo, -wi->screen_rotation); + //printf("taille: %d %d, rotation: %d, centre: %g %g\n", + // wi->opt_width, wi->opt_height, wi->screen_rotation, offsetX, offsetY); + wi->texcoords[0].x = wi->texcoords[0].y = 0; + wi->texcoords[1].x = 0; wi->texcoords[1].y = wi->opt_height; + wi->texcoords[2].x = wi->opt_width; wi->texcoords[2].y = wi->opt_height; + wi->texcoords[3].x = wi->opt_width; wi->texcoords[3].y = 0; + ZnTranslate(&wi->rotation_transfo, wi->width / 2, wi->height / 2, 0); + ZnScale(&wi->rotation_transfo, 1.0/tex_width, 1.0/tex_height); + ZnTransformPoints(&wi->rotation_transfo, wi->texcoords, wi->texcoords, 4); + // + // Compute event transformation to map incoming mouse event. + ZnTransfoSetIdentity(&wi->rotation_transfo); + ZnTranslate(&wi->rotation_transfo, -offsetX, -offsetY, 0); + ZnRotateDeg(&wi->rotation_transfo, wi->screen_rotation); + ZnTranslate(&wi->rotation_transfo, wi->width / 2, wi->height / 2, 0); + // + // Create a FBO if needed. + if (wi->fbo == 0) { + glGenFramebuffersEXT(1, &wi->fbo); + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wi->fbo); + // + // Create a depth/stencil buffer combo. + glGenRenderbuffersEXT(1, &wi->depthstencil); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, wi->depthstencil); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, + tex_width, tex_height); + // + // Create a texture for rendering. + glGenTextures(1, &wi->canvastex); + glBindTexture(GL_TEXTURE_2D, wi->canvastex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glGetError(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, + 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (glGetError() != GL_NO_ERROR) { + ZnWarning("Can't allocate a texture for the intermediate canvas\n"); + } + // + // Attach a depth/stencil combo to the fbo. + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, wi->depthstencil); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, wi->depthstencil); + // + // Attach the texture to the fbo. + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, wi->canvastex, 0); + status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { + ZnWarning("Frame buffer installation is not complete\n"); + } + } + // + // Redirect all GL primitives to the FBO. + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, wi->fbo); +} + +static void +FinalizeRotation(ZnWInfo *wi) +{ + // + // Ok we have the intermediate texture ready we'll cast it + // to the window now. We use a quad the size of the window + // + // First stop redirecting primitives to the fbo. + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + glViewport(0, 0, wi->opt_width, wi->opt_height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0, wi->opt_width, 0.0, wi->opt_height, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + //glDisable(GL_BLEND); + glColor4us(65535, 65535, 65535, 65535); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, wi->canvastex); + glBegin(GL_QUADS); + glTexCoord2d(wi->texcoords[0].x, wi->texcoords[0].y); + glVertex2i(0, 0); + glTexCoord2d(wi->texcoords[1].x, wi->texcoords[1].y); + glVertex2i(0, wi->opt_height); + glTexCoord2d(wi->texcoords[2].x, wi->texcoords[2].y); + glVertex2i(wi->opt_width, wi->opt_height); + glTexCoord2d(wi->texcoords[3].x, wi->texcoords[3].y); + glVertex2i(wi->opt_width, 0); + glEnd(); + glDisable(GL_TEXTURE_2D); +} +#endif /* ********************************************************************************** @@ -8542,8 +8790,6 @@ Repair(ZnWInfo *wi) int darea_x1, darea_x2, darea_y1, darea_y2; ZnGLContextEntry *ce; #endif - int int_width = Tk_Width(wi->win); - int int_height = Tk_Height(wi->win); //LARGE_INTEGER start, stop, sw_freq; //QueryPerformanceFrequency(&sw_freq); @@ -8572,6 +8818,16 @@ Repair(ZnWInfo *wi) //printf("Repair, scissors: %d\n", ISCLEAR(wi->flags, ZN_CONFIGURE_EVENT)); ce = ZnGLMakeCurrent(wi->dpy, wi); + glDrawBuffer(GL_BACK); + +#if defined(GL) && defined(ROTATION) + // + // Setup for rotation and select the rendering fbo. + if (wi->enable_rotation) { + SetupRotationTexture(wi); + } +#endif + glEnable(GL_POINT_SMOOTH); glEnable(GL_LINE_SMOOTH); #if 0 @@ -8586,7 +8842,6 @@ Repair(ZnWInfo *wi) color = ZnGetGradientColor(wi->back_color, 0.0, NULL); glClearColor((GLfloat) color->red/65536, (GLfloat) color->green/65536, (GLfloat) color->blue/65536, 0.0); - glDrawBuffer(GL_BACK); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -8607,26 +8862,25 @@ Repair(ZnWInfo *wi) } else { darea_x1 = darea_y1 = wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0; - darea_x2 = wi->damaged_area.corner.x = int_width; - darea_y2 = wi->damaged_area.corner.y = int_height; + darea_x2 = wi->damaged_area.corner.x = wi->width; + darea_y2 = wi->damaged_area.corner.y = wi->height; } #else /* * We do not use the damaged area set it to the whole area. */ darea_x1 = darea_y1 = wi->damaged_area.orig.x = wi->damaged_area.orig.y = 0; - darea_x2 = wi->damaged_area.corner.x = int_width; - darea_y2 = wi->damaged_area.corner.y = int_height; + darea_x2 = wi->damaged_area.corner.x = wi->width; + darea_y2 = wi->damaged_area.corner.y = wi->height; #endif // // glViewport and glOrtho must always be used together with // matching parameters to keep the mapping straight (no distorsion). - glViewport(darea_x1, int_height - darea_y2, darea_x2 - darea_x1, darea_y2 - darea_y1); + glViewport(darea_x1, wi->height - darea_y2, darea_x2 - darea_x1, darea_y2 - darea_y1); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(darea_x1, darea_x2, darea_y2, darea_y1, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); - /* * Clear the GL buffers. */ @@ -8639,8 +8893,8 @@ Repair(ZnWInfo *wi) ZnBBox bbox; bbox.orig.x = bbox.orig.y = 0.0; - bbox.corner.x = int_width; - bbox.corner.y = int_height; + bbox.corner.x = wi->width; + bbox.corner.y = wi->height; ZnRenderTile(wi, wi->tile, NULL, NULL, NULL, (ZnPoint *) &bbox); } else { @@ -8656,14 +8910,20 @@ Repair(ZnWInfo *wi) wi->top_group->class->Render(wi->top_group); +#if defined(GL) && defined(ROTATION) + if (wi->enable_rotation) { + FinalizeRotation(wi); + } +#endif + if ((wi->border_width > 0) || (wi->highlight_width > 0)) { unsigned short alpha; #ifdef GL_DAMAGE - glViewport(0, 0, int_width, int_height); + glViewport(0, 0, wi->opt_width, wi->opt_height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); - glOrtho(0.0, int_width, int_height, 0.0, -1.0, 1.0); + glOrtho(0.0, wi->opt_width, wi->opt_height, 0.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); #endif if (wi->highlight_width > 0) { @@ -8675,12 +8935,12 @@ Repair(ZnWInfo *wi) glBegin(GL_QUAD_STRIP); glVertex2d(0.0, 0.0); glVertex2i(wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, 0); - glVertex2i(int_width - wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, int_height); - glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, int_height); - glVertex2i(wi->highlight_width, int_height - wi->highlight_width); + glVertex2i(wi->opt_width, 0); + glVertex2i(wi->opt_width - wi->highlight_width, wi->highlight_width); + glVertex2i(wi->opt_width, wi->opt_height); + glVertex2i(wi->opt_width - wi->highlight_width, wi->opt_height - wi->highlight_width); + glVertex2i(0, wi->opt_height); + glVertex2i(wi->highlight_width, wi->opt_height - wi->highlight_width); glVertex2i(0, 0); glVertex2i(wi->highlight_width, wi->highlight_width); glEnd(); @@ -8689,8 +8949,8 @@ Repair(ZnWInfo *wi) if (wi->relief != ZN_RELIEF_FLAT) { p[4].x = p[4].y = p[3].y = p[1].x = wi->highlight_width; p[0] = p[4]; - p[3].x = p[2].x = int_width - wi->highlight_width; - p[2].y = p[1].y = int_height - wi->highlight_width; + p[3].x = p[2].x = wi->opt_width - wi->highlight_width; + p[2].y = p[1].y = wi->opt_height - wi->highlight_width; ZnRenderPolygonRelief(wi, wi->relief, wi->relief_grad, False, p, 5, (ZnReal) wi->border_width); } @@ -8702,12 +8962,12 @@ Repair(ZnWInfo *wi) glBegin(GL_QUAD_STRIP); glVertex2d(0.0, 0.0); glVertex2i(wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, 0); - glVertex2i(int_width - wi->highlight_width, wi->highlight_width); - glVertex2i(int_width, int_height); - glVertex2i(int_width - wi->highlight_width, int_height - wi->highlight_width); - glVertex2i(0, int_height); - glVertex2i(wi->highlight_width, int_height - wi->highlight_width); + glVertex2i(wi->opt_width, 0); + glVertex2i(wi->opt_width - wi->highlight_width, wi->highlight_width); + glVertex2i(wi->opt_width, wi->opt_height); + glVertex2i(wi->opt_width - wi->highlight_width, wi->opt_height - wi->highlight_width); + glVertex2i(0, wi->opt_height); + glVertex2i(wi->highlight_width, wi->opt_height - wi->highlight_width); glVertex2i(0, 0); glVertex2i(wi->highlight_width, wi->highlight_width); glEnd(); @@ -8794,8 +9054,8 @@ m * Merge the damaged area with the exposed area. */ merge.orig.x = MAX(merge.orig.x, wi->inset); merge.orig.y = MAX(merge.orig.y, wi->inset); - merge.corner.x = MIN(merge.corner.x, int_width-wi->inset); - merge.corner.y = MIN(merge.corner.y, int_height-wi->inset); + merge.corner.x = MIN(merge.corner.x, wi->opt_width-wi->inset); + merge.corner.y = MIN(merge.corner.y, wi->opt_height-wi->inset); ZnBBox2XRect(&merge, &r); XCopyArea(wi->dpy, wi->draw_buffer, Tk_WindowId(wi->win), wi->gc, @@ -8812,8 +9072,8 @@ m * Merge the damaged area with the exposed area. wi->draw_buffer = Tk_WindowId(wi->win); if (wi->relief_grad != ZN_RELIEF_FLAT) { r.x = r.y = wi->highlight_width; - r.width = int_width - 2*wi->highlight_width; - r.height = int_height - 2*wi->highlight_width; + r.width = wi->opt_width - 2*wi->highlight_width; + r.height = wi->opt_height - 2*wi->highlight_width; ZnDrawRectangleRelief(wi, wi->relief, wi->relief_grad, &r, (ZnDim) wi->border_width); } @@ -8821,14 +9081,14 @@ m * Merge the damaged area with the exposed area. XSetForeground(wi->dpy, wi->gc, ZnGetGradientPixel(wi->back_color, 0.0)); XSetFillStyle(wi->dpy, wi->gc, FillSolid); rs[0].x = rs[0].y = wi->highlight_width; - rs[0].width = int_width - 2*wi->highlight_width; + rs[0].width = wi->opt_width - 2*wi->highlight_width; rs[0].height = wi->border_width; - rs[1].x = int_width - wi->highlight_width - wi->border_width; + rs[1].x = wi->opt_width - wi->highlight_width - wi->border_width; rs[1].y = 0; rs[1].width = wi->border_width; - rs[1].height = int_height - 2*wi->highlight_width; + rs[1].height = wi->opt_height - 2*wi->highlight_width; rs[2].x = 0; - rs[2].y = int_height - wi->highlight_width - wi->border_width; + rs[2].y = wi->opt_height - wi->highlight_width - wi->border_width; rs[2].width = rs[0].width; rs[2].height = wi->border_width; rs[3].x = rs[3].y = wi->highlight_width; @@ -8844,19 +9104,19 @@ m * Merge the damaged area with the exposed area. wi->highlight_bg_color, 0.0)); XSetFillStyle(wi->dpy, wi->gc, FillSolid); rs[0].x = rs[0].y = 0; - rs[0].width = int_width; + rs[0].width = wi->opt_width; rs[0].height = wi->highlight_width; - rs[1].x = int_width - wi->highlight_width; + rs[1].x = wi->opt_width - wi->highlight_width; rs[1].y = 0; rs[1].width = wi->highlight_width; - rs[1].height = int_height; + rs[1].height = wi->opt_height; rs[2].x = 0; - rs[2].y = int_height - wi->highlight_width; - rs[2].width = int_width; + rs[2].y = wi->opt_height - wi->highlight_width; + rs[2].width = wi->opt_width; rs[2].height = wi->highlight_width; rs[3].x = rs[3].y = 0; rs[3].width = wi->highlight_width; - rs[3].height = int_height; + rs[3].height = wi->opt_height; XFillRectangles(wi->dpy, Tk_WindowId(wi->win), wi->gc, rs, 4); } //STOP_PRINT("Total GDI"); |