// Gmsh - Copyright (C) 1997-2009 C. Geuzaine, J.-F. Remacle // // See the LICENSE.txt file for license information. Please report all // bugs and problems to <gmsh@geuz.org>. #include <string.h> #include "GmshConfig.h" #include "GmshMessage.h" #include "GModel.h" #include "GmshDefines.h" #include "StringUtils.h" #include "Context.h" #include "Options.h" #if defined(HAVE_FLTK) #include <FL/gl.h> #include "gl2ps.h" #include "gl2gif.h" #include "gl2jpeg.h" #include "gl2png.h" #include "gl2ppm.h" #include "gl2yuv.h" #endif int GuessFileFormatFromFileName(std::string fileName) { int len; char ext[256]; const char *name = fileName.c_str(); for(len = strlen(name) - 1; len >= 0; len--) { if(name[len] == '.') { strcpy(ext, &name[len]); break; } } if(len <= 0) strcpy(ext, ""); if (!strcmp(ext, ".geo")) return FORMAT_GEO; else if(!strcmp(ext, ".msh")) return FORMAT_MSH; else if(!strcmp(ext, ".pos")) return FORMAT_POS; else if(!strcmp(ext, ".opt")) return FORMAT_OPT; else if(!strcmp(ext, ".unv")) return FORMAT_UNV; else if(!strcmp(ext, ".vtk")) return FORMAT_VTK; else if(!strcmp(ext, ".stl")) return FORMAT_STL; else if(!strcmp(ext, ".cgns")) return FORMAT_CGNS; else if(!strcmp(ext, ".med")) return FORMAT_MED; else if(!strcmp(ext, ".mesh")) return FORMAT_MESH; else if(!strcmp(ext, ".bdf")) return FORMAT_BDF; else if(!strcmp(ext, ".diff")) return FORMAT_DIFF; else if(!strcmp(ext, ".nas")) return FORMAT_BDF; else if(!strcmp(ext, ".p3d")) return FORMAT_P3D; else if(!strcmp(ext, ".wrl")) return FORMAT_VRML; else if(!strcmp(ext, ".vrml")) return FORMAT_VRML; else if(!strcmp(ext, ".gif")) return FORMAT_GIF; else if(!strcmp(ext, ".jpg")) return FORMAT_JPEG; else if(!strcmp(ext, ".jpeg")) return FORMAT_JPEG; else if(!strcmp(ext, ".png")) return FORMAT_PNG; else if(!strcmp(ext, ".ps")) return FORMAT_PS; else if(!strcmp(ext, ".eps")) return FORMAT_EPS; else if(!strcmp(ext, ".pdf")) return FORMAT_PDF; else if(!strcmp(ext, ".tex")) return FORMAT_TEX; else if(!strcmp(ext, ".svg")) return FORMAT_SVG; else if(!strcmp(ext, ".ppm")) return FORMAT_PPM; else if(!strcmp(ext, ".yuv")) return FORMAT_YUV; else return -1; } std::string GetDefaultFileName(int format) { char no_ext[256], ext[256], base[256]; SplitFileName(GModel::current()->getFileName().c_str(), no_ext, ext, base); std::string name(no_ext); switch(format){ case FORMAT_GEO: name += ".geo_unrolled"; break; case FORMAT_MSH: name += ".msh"; break; case FORMAT_POS: name += ".pos"; break; case FORMAT_OPT: name += ".opt"; break; case FORMAT_UNV: name += ".unv"; break; case FORMAT_VTK: name += ".vtk"; break; case FORMAT_STL: name += ".stl"; break; case FORMAT_CGNS: name += ".cgns"; break; case FORMAT_MED: name += ".med"; break; case FORMAT_MESH: name += ".mesh"; break; case FORMAT_BDF: name += ".bdf"; break; case FORMAT_DIFF: name += ".diff"; break; case FORMAT_P3D: name += ".p3d"; break; case FORMAT_VRML: name += ".wrl"; break; case FORMAT_GIF: name += ".gif"; break; case FORMAT_JPEG: name += ".jpg"; break; case FORMAT_PNG: name += ".png"; break; case FORMAT_PS: name += ".ps"; break; case FORMAT_EPS: name += ".eps"; break; case FORMAT_PDF: name += ".pdf"; break; case FORMAT_TEX: name += ".tex"; break; case FORMAT_SVG: name += ".svg"; break; case FORMAT_PPM: name += ".ppm"; break; case FORMAT_YUV: name += ".yuv"; break; default: break; } return name; } void CreateOutputFile(std::string fileName, int format) { if(fileName.empty()) fileName = GetDefaultFileName(format); char no_ext[256], ext[256], base[256]; SplitFileName(fileName.c_str(), no_ext, ext, base); int oldformat = CTX::instance()->print.format; CTX::instance()->print.format = format; CTX::instance()->printing = 1; #if defined(HAVE_FLTK) int vp[4]; GetCurrentOpenglWindowViewport(vp); GLint viewport[4]; for(int i = 0; i < 4; i++) viewport[i] = vp[i]; GLint width = viewport[2] - viewport[0]; GLint height = viewport[3] - viewport[1]; #endif bool printEndMessage = true; if(format != FORMAT_AUTO) Msg::StatusBar(2, true, "Writing '%s'", fileName.c_str()); switch (format) { case FORMAT_AUTO: CreateOutputFile(fileName, GuessFileFormatFromFileName(fileName)); printEndMessage = false; break; case FORMAT_OPT: Print_Options(0, GMSH_FULLRC, 1, 1, fileName.c_str()); break; case FORMAT_MSH: GModel::current()->writeMSH (fileName, CTX::instance()->mesh.msh_file_version, CTX::instance()->mesh.binary, CTX::instance()->mesh.save_all, CTX::instance()->mesh.save_parametric, CTX::instance()->mesh.scaling_factor); break; case FORMAT_STL: GModel::current()->writeSTL (fileName, CTX::instance()->mesh.binary, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_VRML: GModel::current()->writeVRML (fileName, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_UNV: GModel::current()->writeUNV (fileName, CTX::instance()->mesh.save_all, CTX::instance()->mesh.save_groups_of_nodes, CTX::instance()->mesh.scaling_factor); break; case FORMAT_VTK: GModel::current()->writeVTK (fileName, CTX::instance()->mesh.binary, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor, CTX::instance()->big_endian); break; case FORMAT_MESH: GModel::current()->writeMESH (fileName, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_BDF: GModel::current()->writeBDF (fileName, CTX::instance()->mesh.bdf_field_format, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_DIFF: GModel::current()->writeDIFF (fileName, CTX::instance()->mesh.binary, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_P3D: GModel::current()->writeP3D (fileName, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_CGNS: GModel::current()->writeCGNS (fileName, CTX::instance()->mesh.zone_definition, CTX::instance()->mesh.cgns_options, CTX::instance()->mesh.scaling_factor); break; case FORMAT_MED: GModel::current()->writeMED (fileName, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_POS: GModel::current()->writePOS (fileName, CTX::instance()->print.pos_elementary, CTX::instance()->print.pos_element, CTX::instance()->print.pos_gamma, CTX::instance()->print.pos_eta, CTX::instance()->print.pos_rho, CTX::instance()->print.pos_disto, CTX::instance()->mesh.save_all, CTX::instance()->mesh.scaling_factor); break; case FORMAT_GEO: GModel::current()->writeGEO(fileName, CTX::instance()->print.geo_labels); break; #if defined(HAVE_FLTK) case FORMAT_PPM: case FORMAT_YUV: case FORMAT_GIF: case FORMAT_JPEG: case FORMAT_PNG: { FILE *fp; if(!(fp = fopen(fileName.c_str(), "wb"))) { Msg::Error("Unable to open file '%s'", fileName.c_str()); break; } PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE); int old_bg_gradient = CTX::instance()->bg_gradient; if(format == FORMAT_GIF && CTX::instance()->print.gif_transparent) CTX::instance()->bg_gradient = 0; buffer.Fill(CTX::instance()->batch); CTX::instance()->bg_gradient = old_bg_gradient; if(format == FORMAT_PPM){ create_ppm(fp, &buffer); } else if(format == FORMAT_YUV){ create_yuv(fp, &buffer); } else if(format == FORMAT_GIF){ create_gif(fp, &buffer, CTX::instance()->print.gif_dither, CTX::instance()->print.gif_sort, CTX::instance()->print.gif_interlace, CTX::instance()->print.gif_transparent, CTX::instance()->unpack_red(CTX::instance()->color.bg), CTX::instance()->unpack_green(CTX::instance()->color.bg), CTX::instance()->unpack_blue(CTX::instance()->color.bg)); } else if(format == FORMAT_JPEG){ create_jpeg(fp, &buffer, CTX::instance()->print.jpeg_quality, CTX::instance()->print.jpeg_smoothing); } else{ create_png(fp, &buffer, 100); } fclose(fp); } break; case FORMAT_PS: case FORMAT_EPS: case FORMAT_PDF: case FORMAT_SVG: { FILE *fp; if(!(fp = fopen(fileName.c_str(), "wb"))) { Msg::Error("Unable to open file '%s'", fileName.c_str()); break; } int psformat; switch(format){ case FORMAT_PDF: psformat = GL2PS_PDF; break; case FORMAT_PS: psformat = GL2PS_PS; break; case FORMAT_SVG: psformat = GL2PS_SVG; break; default: psformat = GL2PS_EPS; break; } int old_bg_gradient = CTX::instance()->bg_gradient; if(!CTX::instance()->print.eps_background) CTX::instance()->bg_gradient = 0; PixelBuffer buffer(width, height, GL_RGB, GL_FLOAT); if(CTX::instance()->print.eps_quality == 0) buffer.Fill(CTX::instance()->batch); int pssort = (CTX::instance()->print.eps_quality == 3) ? GL2PS_NO_SORT : (CTX::instance()->print.eps_quality == 2) ? GL2PS_BSP_SORT : GL2PS_SIMPLE_SORT; int psoptions = GL2PS_SIMPLE_LINE_OFFSET | GL2PS_SILENT | (CTX::instance()->print.eps_occlusion_culling ? GL2PS_OCCLUSION_CULL : 0) | (CTX::instance()->print.eps_best_root ? GL2PS_BEST_ROOT : 0) | (CTX::instance()->print.eps_background ? GL2PS_DRAW_BACKGROUND : 0) | (CTX::instance()->print.eps_compress ? GL2PS_COMPRESS : 0) | (CTX::instance()->print.eps_ps3shading ? 0 : GL2PS_NO_PS3_SHADING); GLint buffsize = 0; int res = GL2PS_OVERFLOW; while(res == GL2PS_OVERFLOW) { buffsize += 2048 * 2048; gl2psBeginPage(base, "Gmsh", viewport, psformat, pssort, psoptions, GL_RGBA, 0, NULL, 15, 20, 10, buffsize, fp, base); if(CTX::instance()->print.eps_quality == 0){ double modelview[16], projection[16]; glGetDoublev(GL_PROJECTION_MATRIX, projection); glGetDoublev(GL_MODELVIEW_MATRIX, modelview); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho((double)viewport[0], (double)viewport[2], (double)viewport[1], (double)viewport[3], -1., 1.); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRasterPos2d(0, 0); gl2psDrawPixels(width, height, 0, 0, GL_RGB, GL_FLOAT, buffer.GetPixels()); glMatrixMode(GL_PROJECTION); glLoadMatrixd(projection); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(modelview); } else{ buffer.Fill(CTX::instance()->batch); } res = gl2psEndPage(); } CTX::instance()->bg_gradient = old_bg_gradient; fclose(fp); } break; case FORMAT_TEX: { FILE *fp; if(!(fp = fopen(fileName.c_str(), "w"))) { Msg::Error("Unable to open file '%s'", fileName.c_str()); break; } GLint buffsize = 0; int res = GL2PS_OVERFLOW; while(res == GL2PS_OVERFLOW) { buffsize += 2048 * 2048; gl2psBeginPage(base, "Gmsh", viewport, GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL, 0, 0, 0, buffsize, fp, base); PixelBuffer buffer(width, height, GL_RGB, GL_UNSIGNED_BYTE); int oldtext = CTX::instance()->print.text; CTX::instance()->print.text = 1; buffer.Fill(CTX::instance()->batch); CTX::instance()->print.text = oldtext; res = gl2psEndPage(); } fclose(fp); } break; #endif default: Msg::Error("Unknown output file format"); printEndMessage = false; break; } if(printEndMessage) Msg::StatusBar(2, true, "Wrote '%s'", fileName.c_str()); CTX::instance()->print.format = oldformat; CTX::instance()->printing = 0; #if defined(HAVE_FLTK) Draw(); #endif }