00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: cmd_render.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.49 $ $Date: 2020年07月08日 04:19:30 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * text commands for rendering control 00019 ***************************************************************************/ 00020 00021 #include <stdlib.h> 00022 #include <tcl.h> 00023 #include "config.h" 00024 #include "utilities.h" 00025 #include "VMDApp.h" 00026 00027 #define CHECK_RENDER(x) if (!app->filerender_valid(x)) { delete [] extstr; Tcl_AppendResult(interp, "No render method: ", x, NULL); return TCL_ERROR; } 00028 00029 int text_cmd_render(ClientData cd, Tcl_Interp *interp, int argc, 00030 const char *argv[]) { 00031 VMDApp *app = (VMDApp *)cd; 00032 00033 if (argc >= 3) { 00034 char *extstr = NULL; 00035 if (argc > 3) 00036 extstr = combine_arguments(argc, argv, 3); 00037 00038 if (!strupncmp(argv[1], "options", CMDLEN)) { 00039 const char *opt = app->filerender_option(argv[2], NULL); 00040 if (!opt) { 00041 Tcl_AppendResult(interp, "render:\n", 00042 "No rendering method '", argv[2], "' available.", NULL); 00043 return TCL_ERROR; 00044 } 00045 if (extstr == NULL) { //print the option 00046 Tcl_AppendResult(interp, opt, NULL); 00047 } else { 00048 app->filerender_option(argv[2], extstr); 00049 delete [] extstr; 00050 } 00051 return TCL_OK; 00052 00053 } else if (!strupncmp(argv[1], "default", CMDLEN)) { 00054 const char *opt = app->filerender_default_option(argv[2]); 00055 if (!opt) { 00056 Tcl_AppendResult(interp, "render:\n", "No rendering method '", 00057 argv[2], "' available.", NULL); 00058 return TCL_ERROR; 00059 } 00060 Tcl_AppendResult(interp, opt, NULL); 00061 return TCL_OK; 00062 00063 } else if (!strupncmp(argv[1], "hasaa", CMDLEN)) { 00064 CHECK_RENDER(argv[2]) 00065 Tcl_SetObjResult(interp, Tcl_NewIntObj(app->filerender_has_antialiasing(argv[2]))); 00066 return TCL_OK; 00067 00068 } else if (!strupncmp(argv[1], "aasamples", CMDLEN)) { 00069 int aasamples = -1; 00070 if (argc ==4) { 00071 if (Tcl_GetInt(interp, argv[3], &aasamples) != TCL_OK) 00072 return TCL_ERROR; 00073 } 00074 CHECK_RENDER(argv[2]) 00075 Tcl_SetObjResult(interp, Tcl_NewIntObj(app->filerender_aasamples(argv[2], aasamples))); 00076 return TCL_OK; 00077 00078 } else if (!strupncmp(argv[1], "aosamples", CMDLEN)) { 00079 int aosamples = -1; 00080 if (argc ==4) { 00081 if (Tcl_GetInt(interp, argv[3], &aosamples) != TCL_OK) 00082 return TCL_ERROR; 00083 } 00084 CHECK_RENDER(argv[2]) 00085 Tcl_SetObjResult(interp, Tcl_NewIntObj(app->filerender_aosamples(argv[2], aosamples))); 00086 return TCL_OK; 00087 00088 } else if (!strupncmp(argv[1], "imagesize", CMDLEN)) { 00089 int w=0, h=0; 00090 CHECK_RENDER(argv[2]) 00091 if (argc == 4) { 00092 int listn; 00093 const char **listelem; 00094 if (Tcl_SplitList(interp, argv[3], &listn, &listelem) != TCL_OK) { 00095 return TCL_ERROR; 00096 } 00097 if (listn != 2) { 00098 Tcl_SetResult(interp, (char *) "Image size list must have two elements", TCL_STATIC); 00099 Tcl_Free((char *)listelem); 00100 } 00101 if (Tcl_GetInt(interp, listelem[0], &w) != TCL_OK || 00102 Tcl_GetInt(interp, listelem[1], &h) != TCL_OK) { 00103 Tcl_Free((char *)listelem); 00104 return TCL_ERROR; 00105 } 00106 Tcl_Free((char *)listelem); 00107 } else if (argc != 3 && argc > 4) { 00108 Tcl_SetResult(interp, (char *) "Usage: render imagesize <method> {width height}", TCL_STATIC); 00109 return TCL_ERROR; 00110 } 00111 if (!app->filerender_imagesize(argv[2], &w, &h)) { 00112 Tcl_SetResult(interp, (char *) "Unable to set/get image size.", TCL_STATIC); 00113 return TCL_ERROR; 00114 } 00115 char tmpstring[128] = { 0 }; 00116 sprintf(tmpstring, "%d %d", w, h); 00117 Tcl_SetResult(interp, tmpstring, TCL_VOLATILE); 00118 return TCL_OK; 00119 00120 } else if (!strupncmp(argv[1], "hasimagesize", CMDLEN)) { 00121 int rc = app->filerender_has_imagesize(argv[2]); 00122 Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); 00123 return TCL_OK; 00124 00125 } else if (!strupncmp(argv[1], "aspectratio", CMDLEN)) { 00126 CHECK_RENDER(argv[2]) 00127 double daspect = -1; 00128 if (argc == 4) { 00129 if (Tcl_GetDouble(interp, argv[3], &daspect) != TCL_OK) 00130 return TCL_ERROR; 00131 } 00132 float aspect = (float)daspect; 00133 if (!app->filerender_aspectratio(argv[2], &aspect)) { 00134 Tcl_SetResult(interp, (char *) "Unable to get aspect ratio.", TCL_STATIC); 00135 return TCL_ERROR; 00136 } 00137 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(aspect)); 00138 return TCL_OK; 00139 00140 } else if (!strupncmp(argv[1], "formats", CMDLEN)) { 00141 CHECK_RENDER(argv[2]) 00142 int n = app->filerender_numformats(argv[2]); 00143 for (int i=0; i<n; i++) { 00144 Tcl_AppendElement(interp, app->filerender_get_format(argv[2], i)); 00145 } 00146 return TCL_OK; 00147 00148 } else if (!strupncmp(argv[1], "format", CMDLEN)) { 00149 CHECK_RENDER(argv[2]) 00150 if (argc == 3) { 00151 Tcl_AppendElement(interp, app->filerender_cur_format(argv[2])); 00152 return TCL_OK; 00153 } 00154 if (app->filerender_set_format(argv[2], argv[3])) 00155 return TCL_OK; 00156 Tcl_AppendResult(interp, "Unable to set render output format to ", 00157 argv[3], NULL); 00158 return TCL_ERROR; 00159 00160 } else { 00161 app->display_update(); 00162 int retval = app->filerender_render(argv[1], argv[2], extstr); 00163 if(extstr) 00164 delete [] extstr; 00165 return retval ? TCL_OK : TCL_ERROR; 00166 } 00167 } else if (argc == 2) { 00168 for (int i=0; i<app->filerender_num(); i++) 00169 Tcl_AppendElement(interp, app->filerender_name(i)); 00170 return TCL_OK; 00171 } 00172 00173 // if here, something went wrong, so return an error message 00174 Tcl_AppendResult(interp, "render usage:\n", 00175 "render list\n", 00176 "render hasaa <method>\n", 00177 "render aasamples <method> [aasamples]\n", 00178 "render aosamples <method> [aosamples]\n", 00179 // "render hasimagesize <method>\n", 00180 // "render imagesize <method> [{width height}]\n", 00181 "render formats <method>\n", 00182 "render format <method> <format>\n", 00183 "render options <method> <new default exec command>\n", 00184 "render default <method>\n", 00185 "render <method> <filename> [exec command]\n", 00186 NULL); 00187 return TCL_ERROR; 00188 } 00189 00190 00191 // XXX this fails to compile on Windows due to Tk's ridiculous 00192 // insistence of including X11 headers as part of tk.h, we've gotta 00193 // find a better way of coping with this. 00194 #if defined(VMDTK) && !defined(_MSC_VER) 00195 #include <tk.h> 00196 #include "DisplayDevice.h" 00197 int text_cmd_tkrender(ClientData cd, Tcl_Interp *interp, int argc, 00198 const char *argv[]) { 00199 if (!Tcl_PkgPresent(interp, "Tk", TK_VERSION, 0)) { 00200 Tcl_SetResult(interp, (char *) "Tk not available.", TCL_STATIC); 00201 return TCL_ERROR; 00202 } 00203 if (argc != 2) { 00204 Tcl_SetResult(interp, (char *) "tkrender usage:\ntkrender <photo handle>\n", TCL_STATIC); 00205 return TCL_ERROR; 00206 } 00207 Tk_PhotoHandle handle = Tk_FindPhoto(interp, argv[1]); 00208 if (!handle) { 00209 Tcl_AppendResult(interp, "photo handle '", argv[1], "' has not been created.", NULL); 00210 return TCL_ERROR; 00211 } 00212 00213 int xs=0, ys=0; 00214 DisplayDevice *display = ((VMDApp *)cd)->display; 00215 display->update(TRUE); 00216 unsigned char *img = display->readpixels_rgb3u(xs, ys); 00217 display->update(TRUE); 00218 00219 if (!img) { 00220 Tcl_SetResult(interp, (char *) "Error reading pixel data from display device.", TCL_STATIC); 00221 return TCL_ERROR; 00222 } 00223 00224 // OpenGL and Tk use opposite row order for pixel data. 00225 // Here we assume that readpixels returned data in packed RGB format. 00226 Tk_PhotoImageBlock blk = { 00227 img+3*xs*(ys-1), // pixel pointer; points to start of top row on screen. 00228 xs, // width 00229 ys, // height 00230 -3*xs, // address difference between two vertically adjacent pixels 00231 3, // address difference between two horizontally adjacent pixels 00232 {0,1,2,3} // r, g, b, a offsets within each pixel. 00233 }; 00234 00235 // set the size of the photo object to match the screen size. One could 00236 // also create a new photo object with no size information, but that would 00237 // likely to lead to memory leaks in various scripts. There's also currently 00238 // no way to read out the size of the display in VMD (sad, I know), so 00239 // it's just easier to set it here. 00240 Tk_PhotoSetSize(interp, handle, xs, ys); 00241 Tk_PhotoPutBlock(interp, handle, &blk, 0, 0, xs, ys, TK_PHOTO_COMPOSITE_SET); 00242 00243 free(img); 00244 return TCL_OK; 00245 } 00246 00247 #endif 00248 00249