diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/Pcrgraph.cpp FreeFem-sources-4.11/src/Graphics/Pcrgraph.cpp *** FreeFem-sources-4.11.orig/src/Graphics/Pcrgraph.cpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/Pcrgraph.cpp Sat Apr 23 09:39:46 2022 *************** *** 69,74 **** --- 69,77 ---- #include "rgraph.hpp" + #include // add by fujiwara + #include "pdf.h" // add by fujiwara + //char *Version = "1.2.7"; void out_of_memory (); void NEW_HANDLER (void); *************** *** 122,127 **** --- 125,141 ---- static FILE *psfile = 0; static FILE *psfile_save = 0; + static bool pdffile = false; // add by fujiwara + static char *pdffile_name = nullptr; // add by fujiwara + static float pdf_s = 1; // add by fujiwara + static std::stringstream pdffile_content; // add by fujiwara + static FILE *svgfile = 0; // add by fujiwara + static FILE *svgfile_save = 0; // add by fujiwara + static float svg_s = 1; // add by fujiwara + static int svg_r = 0; // add by fujiwara + static int svg_g = 0; // add by fujiwara + static int svg_b = 0; // add by fujiwara + static int svg_lw = 1; // add by fujiwara static float aspx, aspy, echx,echy,ech,rxmin,rxmax,rymin,rymax; static int currx, curry; static int carre; *************** *** 194,199 **** --- 208,231 ---- fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1])); fprintf(psfile,"eF\n"); } + // add by fujiwara + if ( pdffile ) { + + i=0; + pdffile_content << scalx(poly[2*i])*pdf_s << ' ' << (height-scaly( poly[2*i+1]))*pdf_s << " m "; + for (i=1;i\n", + svg_r,svg_g,svg_b, svg_lw, svg_r,svg_g,svg_b); + } + } void out_of_memory () *************** *** 224,229 **** --- 256,268 ---- void penthickness(int pepais){ if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais); + // add by fujiwara + if ( pdffile ){ + pdffile_content << pepais << " w" << std::endl; + } + if ( svgfile ){ + svg_lw = pepais; + } } void showgraphic(){ShowWindow(hWnd, SW_SHOW ); } // UpdateWindow(hWnd);} *************** *** 244,249 **** --- 283,297 ---- fprintf(psfile,"%d %d M\n", currx,height-curry); fprintf(psfile,"(%s) S\n",s); } + // add by fujiwara + if( pdffile ){ + pdffile_content << "BT /F1 " << 9 << " Tf" << std::endl; // 9*pdf_s : text font size + pdffile_content << "1 0 0 1 " << currx*pdf_s << ' ' << (height-curry)*pdf_s << " Tm" << std::endl; + pdffile_content << "(" << string << ") Tj ET" << std::endl; + } + if( svgfile ){ + fprintf(svgfile,"%s\n",currx*svg_s,curry*svg_s,string); + } } void rmoveto(float x, float y) *************** *** 262,267 **** --- 310,324 ---- fprintf(psfile,"%d %d M\n", currx,height-curry); fprintf(psfile,"%d %d L\n", newx,height-newy); } + // add by fujiwara + if ( pdffile ){ + pdffile_content << currx*pdf_s << ' ' << (height-curry)*pdf_s << " m " + << newx*pdf_s << ' ' << (height-newy)*pdf_s << " l S" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, newx*svg_s, newy*svg_s, svg_r, svg_g, svg_b, svg_lw); + } currx = newx; curry = newy; } *************** *** 532,538 **** --- 589,606 ---- r=g=b=0; fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b); + } + // add by fujiwara + if( pdffile ){ + pdffile_content << r << ' ' << g << ' ' << b << " RG" << std::endl; + pdffile_content << r << ' ' << g << ' ' << b << " rg" << std::endl; + } + if( svgfile ){ + svg_r = static_cast(r*256); + svg_g = static_cast(g*256); + svg_b = static_cast(b*256); + } } int LaCouleur(){return cstatic;} *************** *** 750,760 **** --- 818,945 ---- } + //---------------------------------------------------------------------- + // add by fujiwara + //---------------------------------------------------------------------- + void openPDF(const char *filename ) + { + if(pdffile) closePDF(); + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + pdffile_name = new char [ strlen(filename)+1 ]; + strcpy( pdffile_name, filename ); + + pdffile_content.str(""); // clear + pdffile_content.clear( std::stringstream::goodbit ); + + pdffile_content.setf( std::ios::fixed ); + pdffile_content.precision( 3 ); + + const int widthA4PDF = 596; + pdf_s = static_cast(widthA4PDF) / width; + + pdffile = true; + pdffile_content << "q" << std::endl; // gsave + + return; + } + void closePDF(void) + { + if(pdffile) { + + std::string PDFTitle = "plot() by FreeFem++"; + std::string AppName = "FreeFem++ v" + StrVersionNumber(); + + SimplePDF_FF pdf( pdffile_name, PDFTitle.c_str(), AppName.c_str() ); + + const int widthPDF = static_cast( width * pdf_s ); + const int heightPDF = static_cast( height * pdf_s ); + + pdffile_content << "Q" << std::endl; + + pdf.addPage( pdffile_content, widthPDF, heightPDF ); + + pdffile = false; + } + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + return; + } + void openSVG(const char *filename ) + { + if(svgfile_save) closeSVG(); + + const int widthA4PS = 596; + //const int heightA4PS = 842; + svg_s = static_cast(widthA4PS)/width; + + char ffff[32]; + int count = 0; + if(!filename){ + bool notfound; + do { + struct stat buf; + sprintf(ffff,"rgraph_%.3d.svg",count++); + volatile int r = stat(ffff,&buf) ; + notfound = (r != 0); + if( count > 1000 ) break; + } while ( !notfound ); + } + + const char *fsvg (filename?filename:ffff); + + svgfile=fopen(fsvg,"w"); + + if(svgfile) { + svgfile_save=svgfile; + fprintf(svgfile,"\n\n"); + fprintf(svgfile,"\n\n", StrVersionNumber().c_str()); + fprintf(svgfile,"\n", + static_cast(width*svg_s), static_cast(height*svg_s)); + } + else + { + cerr << " Err openning SVG file " << fsvg << endl; + } + return; + } + void closeSVG(void) + { + if(svgfile_save) { + fprintf(svgfile_save,"\n"); + fclose(svgfile_save); + } + svgfile_save=0; + svgfile=0; + + return; + } + //---------------------------------------------------------------------- + // add by fujiwara end + //---------------------------------------------------------------------- + void Commentaire(const char * c) { if(psfile) { fprintf(psfile,"%% %s\n",c); } + // add by fujiwara + if( pdffile ) { + //fprintf(pdffile,"%% %s\n",c); + } + if( svgfile ) { + fprintf(svgfile,"%% %s\n",c); + } }; void NoirEtBlanc(int NB) { *************** *** 767,772 **** --- 952,968 ---- if(in) psfile=psfile_save; else psfile=0; } + // add by fujiwara + void MettreDansPDF(int in) // put into PDF + { + if(in) pdffile=true; + else pdffile=false; + } + void MettreDansSVG(int in) // put into SVG + { + if(in) svgfile=svgfile_save; + else svgfile=0; + } // Various works when the program will end void myexit(int err) *************** *** 1344,1355 **** --- 1540,1555 ---- { if(k) { MettreDansPostScript(0); + MettreDansPDF(0); // add by fujiwara + MettreDansSVG(0); // add by fujiwara couleur(1); float xmin,xmax,ymin,ymax; getcadre(xmin,xmax,ymin,ymax); rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); plotstring(s); MettreDansPostScript(1); + MettreDansPDF(1); // add by fujiwara + MettreDansSVG(1); // add by fujiwara // couleur(1); } } diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/Xrgraph.cpp FreeFem-sources-4.11/src/Graphics/Xrgraph.cpp *** FreeFem-sources-4.11.orig/src/Graphics/Xrgraph.cpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/Xrgraph.cpp Sat Apr 23 09:39:46 2022 *************** *** 66,71 **** --- 66,74 ---- #undef index #include "rgraph.hpp" + #include // add by fujiwara + #include "pdf.h" // add by fujiwara + #ifdef macintoshxx #include #include *************** *** 83,88 **** --- 86,102 ---- static FILE *psfile = 0; static FILE *psfile_save = 0; + static bool pdffile = false; // add by fujiwara + static char *pdffile_name = nullptr; // add by fujiwara + static float pdf_s = 1; // add by fujiwara + static std::stringstream pdffile_content; // add by fujiwara + static FILE *svgfile = 0; // add by fujiwara + static FILE *svgfile_save = 0; // add by fujiwara + static float svg_s = 1; // add by fujiwara + static int svg_r = 0; // add by fujiwara + static int svg_g = 0; // add by fujiwara + static int svg_b = 0; // add by fujiwara + static int svg_lw = 1; // add by fujiwara static bool grey=false; static int LastColor=2; // pour est en couleur par defaut *************** *** 247,252 **** --- 261,276 ---- fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b); } + // add by fujiwara + if( pdffile ){ + pdffile_content << r << ' ' << g << ' ' << b << " RG" << std::endl; + pdffile_content << r << ' ' << g << ' ' << b << " rg" << std::endl; + } + if( svgfile ){ + svg_r = static_cast(r*256); + svg_g = static_cast(g*256); + svg_b = static_cast(b*256); + } } *************** *** 621,626 **** --- 645,659 ---- XDrawLine(display, win, gc, currx, curry, newx, newy); if (psfile) fprintf(psfile,"%d %d %d %d L\n",currx, height-curry, newx, height-newy); + // add by fujiwara + if ( pdffile ){ + pdffile_content << currx*pdf_s << ' ' << (height-curry)*pdf_s << " m " + << newx*pdf_s << ' ' << (height-newy)*pdf_s << " l S" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, newx*svg_s, newy*svg_s, svg_r, svg_g, svg_b, svg_lw); + } currx = newx; curry = newy; /* XFlush(display); */ } *************** *** 652,657 **** --- 685,699 ---- XDrawString(display, win, gc, currx, curry , string, l); lx = XTextWidth( font_info,string,l); if(psfile) fprintf(psfile,"(%s) %d %d S\n",string,currx,height-curry); + // add by fujiwara + if( pdffile ){ + pdffile_content << "BT /F1 " << 9 << " Tf" << std::endl; // 9*pdf_s : text font size + pdffile_content << "1 0 0 1 " << currx*pdf_s << ' ' << (height-curry)*pdf_s << " Tm" << std::endl; + pdffile_content << "(" << string << ") Tj ET" << std::endl; + } + if( svgfile ){ + fprintf(svgfile,"%s\n",currx*svg_s,curry*svg_s,string); + } currx += lx; } *************** *** 679,685 **** case 1 : {fprintf(psfile,"[3] setdash\n");break;} default : {fprintf(psfile,"[4 1] setdash\n");break;} } ! } void penthickness(int pepais) --- 721,733 ---- case 1 : {fprintf(psfile,"[3] setdash\n");break;} default : {fprintf(psfile,"[4 1] setdash\n");break;} } ! // add by fujiwara ! if ( pdffile ){ ! // should be added ! } ! if ( svgfile ){ ! // should be added ! } } void penthickness(int pepais) *************** *** 688,693 **** --- 736,749 ---- gcvalues.line_width = pepais; XChangeGC(display, gc, GCLineWidth, &gcvalues); if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais); + // add by fujiwara + if ( pdffile ){ + pdffile_content << pepais << " w" << std::endl; + } + if ( svgfile ){ + svg_lw = pepais; + } + } *************** *** 747,752 **** --- 803,826 ---- fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1])); fprintf(psfile,"eF\n"); } + // add by fujiwara + if ( pdffile ) { + + i=0; + pdffile_content << scalx(poly[2*i])*pdf_s << ' ' << (height-scaly( poly[2*i+1]))*pdf_s << " m "; + for (i=1;i\n", + svg_r,svg_g,svg_b, svg_lw, svg_r,svg_g,svg_b); + } + } #include "getprog-unix.hpp" *************** *** 1126,1131 **** --- 1200,1315 ---- psfile=0; } + //---------------------------------------------------------------------- + // add by fujiwara + //---------------------------------------------------------------------- + void openPDF(const char *filename ) + { + if(pdffile) closePDF(); + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + pdffile_name = new char [ strlen(filename)+1 ]; + strcpy( pdffile_name, filename ); + + pdffile_content.str(""); // clear + pdffile_content.clear( std::stringstream::goodbit ); + + pdffile_content.setf( std::ios::fixed ); + pdffile_content.precision( 3 ); + + const int widthA4PDF = 596; + pdf_s = static_cast(widthA4PDF) / width; + + pdffile = true; + pdffile_content << "q" << std::endl; // gsave + + return; + } + void closePDF(void) + { + if(pdffile) { + + std::string PDFTitle = "plot() by FreeFem++"; + std::string AppName = "FreeFem++ v" + StrVersionNumber(); + + SimplePDF_FF pdf( pdffile_name, PDFTitle.c_str(), AppName.c_str() ); + + const int widthPDF = static_cast( width * pdf_s ); + const int heightPDF = static_cast( height * pdf_s ); + + pdffile_content << "Q" << std::endl; + + pdf.addPage( pdffile_content, widthPDF, heightPDF ); + + pdffile = false; + } + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + return; + } + void openSVG(const char *filename ) + { + if(svgfile_save) closeSVG(); + + const int widthA4PS = 596; + //const int heightA4PS = 842; + svg_s = static_cast(widthA4PS)/width; + + char ffff[32]; + int count = 0; + if(!filename){ + bool notfound; + do { + struct stat buf; + sprintf(ffff,"rgraph_%.3d.svg",count++); + volatile int r = stat(ffff,&buf) ; + notfound = (r != 0); + if( count > 1000 ) break; + } while ( !notfound ); + } + + const char *fsvg (filename?filename:ffff); + + svgfile=fopen(fsvg,"w"); + + if(svgfile) { + svgfile_save=svgfile; + fprintf(svgfile,"\n\n"); + fprintf(svgfile,"\n\n", StrVersionNumber().c_str()); + fprintf(svgfile,"\n", + static_cast(width*svg_s), static_cast(height*svg_s)); + } + else + { + cerr << " Err openning SVG file " << fsvg << endl; + } + return; + } + void closeSVG(void) + { + if(svgfile_save) { + fprintf(svgfile_save,"\n"); + fclose(svgfile_save); + } + svgfile_save=0; + svgfile=0; + + return; + } + //---------------------------------------------------------------------- + // add by fujiwara end + //---------------------------------------------------------------------- + void coutmode(short i) {} // bof bof --- float GetHeigthFont() *************** *** 1141,1146 **** --- 1325,1337 ---- if(psfile) { fprintf(psfile,"%% %s\n",c); } + // add by fujiwara + if( pdffile ) { + //fprintf(pdffile,"%% %s\n",c); + } + if( svgfile ) { + fprintf(svgfile,"%% %s\n",c); + } }; void NoirEtBlanc(int NB) { *************** *** 1153,1158 **** --- 1344,1360 ---- if(in) psfile=psfile_save; else psfile=0; } + // add by fujiwara + void MettreDansPDF(int in) // put into PDF + { + if(in) pdffile=true; + else pdffile=false; + } + void MettreDansSVG(int in) // put into SVG + { + if(in) svgfile=svgfile_save; + else svgfile=0; + } static void FillRect(float x0,float y0, float x1, float y1) { *************** *** 1188,1199 **** --- 1390,1405 ---- { if(k) { MettreDansPostScript(0); + MettreDansPDF(0); // add by fujiwara + MettreDansSVG(0); // add by fujiwara couleur(1); float xmin,xmax,ymin,ymax; getcadre(xmin,xmax,ymin,ymax); rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); plotstring(s); MettreDansPostScript(1); + MettreDansPDF(1); // add by fujiwara + MettreDansSVG(1); // add by fujiwara // couleur(1); } } diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/glrgraph.hpp FreeFem-sources-4.11/src/Graphics/glrgraph.hpp *** FreeFem-sources-4.11.orig/src/Graphics/glrgraph.hpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/glrgraph.hpp Sat Apr 23 09:39:46 2022 *************** *** 71,76 **** --- 71,78 ---- #include #include #include "rgraph.hpp" + #include // add by fujiwara + #include "pdf.h" // add by fujiwara #include #include #include *************** *** 78,83 **** --- 80,96 ---- int currx=0,curry=0; static FILE *psfile = 0; static FILE *psfile_save = 0; + static bool pdffile = false; // add by fujiwara + static char *pdffile_name = nullptr; // add by fujiwara + static float pdf_s = 1; // add by fujiwara + static std::stringstream pdffile_content; // add by fujiwara + static FILE *svgfile = 0; // add by fujiwara + static FILE *svgfile_save = 0; // add by fujiwara + static float svg_s = 1; // add by fujiwara + static int svg_r = 0; // add by fujiwara + static int svg_g = 0; // add by fujiwara + static int svg_b = 0; // add by fujiwara + static int svg_lw = 1; // add by fujiwara #ifdef AGL static AGLPixelFormat fmt; *************** *** 826,831 **** --- 839,853 ---- lx = XTextWidth( font_info,s,l); #endif if(psfile) fprintf(psfile,"(%s) S\n",s); + // add by fujiwara + if( pdffile ){ + pdffile_content << "BT /F1 " << 9 << " Tf" << std::endl; // 9*pdf_s : text font size + pdffile_content << "1 0 0 1 " << currx*pdf_s << ' ' << (height-curry)*pdf_s << " Tm" << std::endl; + pdffile_content << "(" << string << ") Tj ET" << std::endl; + } + if( svgfile ){ + fprintf(svgfile,"%s\n",currx*svg_s,curry*svg_s,string); + } currx += lx; } *************** *** 849,854 **** --- 871,886 ---- glColor4f (r,g,b,1.); if (psfile) fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b); + // add by fujiwara + if( pdffile ){ + pdffile_content << r << ' ' << g << ' ' << b << " RG" << std::endl; + pdffile_content << r << ' ' << g << ' ' << b << " rg" << std::endl; + } + if( svgfile ){ + svg_r = static_cast(r*256); + svg_g = static_cast(g*256); + svg_b = static_cast(b*256); + } } *************** *** 868,873 **** --- 900,912 ---- // PenSize(pepais,pepais); glLineWidth(pepais); if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais); + // add by fujiwara + if ( pdffile ){ + pdffile_content << pepais << " w" << std::endl; + } + if ( svgfile ){ + svg_lw = pepais; + } } void cadre(float xmin,float xmax,float ymin,float ymax) { *************** *** 939,944 **** --- 978,992 ---- putpixel(newx, newy, lacouleur); if (psfile) fprintf(psfile,"%d %d P\n", newx, height-newy); + // add by fujiwara + if ( pdffile ){ + pdffile_content << newx*pdf_s << ' ' << (height-newy)*pdf_s << ' ' + << pdf_s << ' ' << pdf_s << " re f" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, svg_s, svg_s, svg_r, svg_g, svg_b, 1); + } } *************** *** 948,953 **** --- 996,1008 ---- // MoveTo(newx,newy); if (psfile) fprintf(psfile,"%d %d M\n", newx, height-newy); + // add by fujiwara + if ( pdffile ){ + // should be added + } + if ( svgfile ){ + // should be added + } currx = newx; curry = newy; } *************** *** 961,966 **** --- 1016,1030 ---- glEnd(); if (psfile) fprintf(psfile,"%d %d L\n", newx,height-newy); + // add by fujiwara + if ( pdffile ){ + pdffile_content << currx*pdf_s << ' ' << (height-curry)*pdf_s << " m " + << newx*pdf_s << ' ' << (height-newy)*pdf_s << " l S" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, newx*svg_s, newy*svg_s, svg_r, svg_g, svg_b, svg_lw); + } currx = newx; curry = newy; } *************** *** 979,984 **** --- 1043,1065 ---- fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1])); fprintf(psfile,"eF\n"); } + // add by fujiwara + if ( pdffile ) { + + i=0; + pdffile_content << scalx(poly[2*i])*pdf_s << ' ' << (height-scaly( poly[2*i+1]))*pdf_s << " m "; + for (i=1;i\n", + svg_r,svg_g,svg_b, svg_lw, svg_r,svg_g,svg_b); + } } *************** *** 1546,1556 **** --- 1627,1754 ---- } + //---------------------------------------------------------------------- + // add by fujiwara + //---------------------------------------------------------------------- + void openPDF(const char *filename ) + { + if(pdffile) closePDF(); + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + pdffile_name = new char [ strlen(filename)+1 ]; + strcpy( pdffile_name, filename ); + + pdffile_content.str(""); // clear + pdffile_content.clear( std::stringstream::goodbit ); + + pdffile_content.setf( std::ios::fixed ); + pdffile_content.precision( 3 ); + + const int widthA4PDF = 596; + pdf_s = static_cast(widthA4PDF) / width; + + pdffile = true; + pdffile_content << "q" << std::endl; // gsave + + return; + } + void closePDF(void) + { + if(pdffile) { + + std::string PDFTitle = "plot() by FreeFem++"; + std::string AppName = "FreeFem++ v" + StrVersionNumber(); + + SimplePDF_FF pdf( pdffile_name, PDFTitle.c_str(), AppName.c_str() ); + + const int widthPDF = static_cast( width * pdf_s ); + const int heightPDF = static_cast( height * pdf_s ); + + pdffile_content << "Q" << std::endl; + + pdf.addPage( pdffile_content, widthPDF, heightPDF ); + + pdffile = false; + } + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + return; + } + void openSVG(const char *filename ) + { + if(svgfile_save) closeSVG(); + + const int widthA4PS = 596; + //const int heightA4PS = 842; + svg_s = static_cast(widthA4PS)/width; + + char ffff[32]; + int count = 0; + if(!filename){ + bool notfound; + do { + struct stat buf; + sprintf(ffff,"rgraph_%.3d.svg",count++); + volatile int r = stat(ffff,&buf) ; + notfound = (r != 0); + if( count > 1000 ) break; + } while ( !notfound ); + } + + const char *fsvg (filename?filename:ffff); + + svgfile=fopen(fsvg,"w"); + + if(svgfile) { + svgfile_save=svgfile; + fprintf(svgfile,"\n\n"); + fprintf(svgfile,"\n\n", StrVersionNumber().c_str()); + fprintf(svgfile,"\n", + static_cast(width*svg_s), static_cast(height*svg_s)); + } + else + { + cerr << " Err openning SVG file " << fsvg << endl; + } + return; + } + void closeSVG(void) + { + if(svgfile_save) { + fprintf(svgfile_save,"\n"); + fclose(svgfile_save); + } + svgfile_save=0; + svgfile=0; + + return; + } + //---------------------------------------------------------------------- + // add by fujiwara end + //---------------------------------------------------------------------- + void Commentaire(const char * c) { if(psfile) { fprintf(psfile,"%% %s\n",c); } + // add by fujiwara + if( pdffile ) { + //fprintf(pdffile,"%% %s\n",c); + } + if( svgfile ) { + fprintf(svgfile,"%% %s\n",c); + } }; void NoirEtBlanc(int NB) { *************** *** 1563,1568 **** --- 1761,1777 ---- if(in) psfile=psfile_save; else psfile=0; } + // add by fujiwara + void MettreDansPDF(int in) // put into PDF + { + if(in) pdffile=true; + else pdffile=false; + } + void MettreDansSVG(int in) // put into SVG + { + if(in) svgfile=svgfile_save; + else svgfile=0; + } static void FillRect(float x0,float y0, float x1, float y1) { *************** *** 1617,1628 **** --- 1826,1841 ---- { if(k) { MettreDansPostScript(0); + MettreDansPDF(0); // add by fujiwara + MettreDansSVG(0); // add by fujiwara couleur(1); float xmin,xmax,ymin,ymax; getcadre(xmin,xmax,ymin,ymax); rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); plotstring(s); MettreDansPostScript(1); + MettreDansPDF(1); // add by fujiwara + MettreDansSVG(1); // add by fujiwara // couleur(1); } } diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/macrgraf.cpp FreeFem-sources-4.11/src/Graphics/macrgraf.cpp *** FreeFem-sources-4.11.orig/src/Graphics/macrgraf.cpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/macrgraf.cpp Sat Apr 23 09:39:46 2022 *************** *** 80,85 **** --- 80,88 ---- #include #define fill thequikdrawfill #include "rgraph.hpp" + #include // add by fujiwara + #include "pdf.h" // add by fujiwara + #include #include #include *************** *** 95,100 **** --- 98,114 ---- static FILE *psfile = 0; static FILE *psfile_save = 0; + static bool pdffile = false; // add by fujiwara + static char *pdffile_name = nullptr; // add by fujiwara + static float pdf_s = 1; // add by fujiwara + static std::stringstream pdffile_content; // add by fujiwara + static FILE *svgfile = 0; // add by fujiwara + static FILE *svgfile_save = 0; // add by fujiwara + static float svg_s = 1; // add by fujiwara + static int svg_r = 0; // add by fujiwara + static int svg_g = 0; // add by fujiwara + static int svg_b = 0; // add by fujiwara + static int svg_lw = 1; // add by fujiwara static bool grey=false; int pStrCopy (StringPtr p1, char * p2); *************** *** 661,666 **** --- 675,689 ---- void plotstring(const char *s) { DrawText(s,0,strlen(s)); if(psfile) fprintf(psfile,"(%s) S\n",s); + // add by fujiwara + if( pdffile ){ + pdffile_content << "BT /F1 " << 9 << " Tf" << std::endl; // 9*pdf_s : text font size + pdffile_content << "1 0 0 1 " << currx*pdf_s << ' ' << (height-curry)*pdf_s << " Tm" << std::endl; + pdffile_content << "(" << string << ") Tj ET" << std::endl; + } + if( svgfile ){ + fprintf(svgfile,"%s\n",currx*svg_s,curry*svg_s,string); + } } int LaCouleur(){return lacouleur;} *************** *** 693,698 **** --- 716,731 ---- fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b); } + // add by fujiwara + if( pdffile ){ + pdffile_content << r << ' ' << g << ' ' << b << " RG" << std::endl; + pdffile_content << r << ' ' << g << ' ' << b << " rg" << std::endl; + } + if( svgfile ){ + svg_r = static_cast(r*256); + svg_g = static_cast(g*256); + svg_b = static_cast(b*256); + } } *************** *** 711,716 **** --- 744,756 ---- { PenSize(pepais,pepais); if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais); + // add by fujiwara + if ( pdffile ){ + pdffile_content << pepais << " w" << std::endl; + } + if ( svgfile ){ + svg_lw = pepais; + } } void cadre(float xmin,float xmax,float ymin,float ymax) { *************** *** 781,787 **** putpixel(newx, newy, lacouleur); if (psfile) fprintf(psfile,"%d %d P\n", newx, height-newy); ! } void rmoveto(float x, float y) --- 821,835 ---- putpixel(newx, newy, lacouleur); if (psfile) fprintf(psfile,"%d %d P\n", newx, height-newy); ! // add by fujiwara ! if ( pdffile ){ ! pdffile_content << newx*pdf_s << ' ' << (height-newy)*pdf_s << ' ' ! << pdf_s << ' ' << pdf_s << " re f" << std::endl; ! } ! if ( svgfile ){ ! fprintf(svgfile,"\n", ! currx*svg_s, curry*svg_s, svg_s, svg_s, svg_r, svg_g, svg_b, 1); ! } } void rmoveto(float x, float y) *************** *** 790,796 **** MoveTo(newx,newy); if (psfile) fprintf(psfile,"%d %d M\n", newx, height-newy); ! } void rlineto(float x, float y) --- 838,850 ---- MoveTo(newx,newy); if (psfile) fprintf(psfile,"%d %d M\n", newx, height-newy); ! // add by fujiwara ! if ( pdffile ){ ! // should be added ! } ! if ( svgfile ){ ! // should be added ! } } void rlineto(float x, float y) *************** *** 799,804 **** --- 853,867 ---- LineTo(newx,newy); if (psfile) fprintf(psfile,"%d %d L\n", newx,height-newy); + // add by fujiwara + if ( pdffile ){ + pdffile_content << currx*pdf_s << ' ' << (height-curry)*pdf_s << " m " + << newx*pdf_s << ' ' << (height-newy)*pdf_s << " l S" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, newx*svg_s, newy*svg_s, svg_r, svg_g, svg_b, svg_lw); + } } *************** *** 834,839 **** --- 897,919 ---- fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1])); fprintf(psfile,"eF\n"); } + // add by fujiwara + if ( pdffile ) { + + i=0; + pdffile_content << scalx(poly[2*i])*pdf_s << ' ' << (height-scaly( poly[2*i+1]))*pdf_s << " m "; + for (i=1;i\n", + svg_r,svg_g,svg_b, svg_lw, svg_r,svg_g,svg_b); + } } int pStrCopy (StringPtr p1, char * p2) *************** *** 1097,1108 **** --- 1177,1304 ---- psfile_save=0; } + //---------------------------------------------------------------------- + // add by fujiwara + //---------------------------------------------------------------------- + void openPDF(const char *filename ) + { + if(pdffile) closePDF(); + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + pdffile_name = new char [ strlen(filename)+1 ]; + strcpy( pdffile_name, filename ); + + pdffile_content.str(""); // clear + pdffile_content.clear( std::stringstream::goodbit ); + + pdffile_content.setf( std::ios::fixed ); + pdffile_content.precision( 3 ); + + const int widthA4PDF = 596; + pdf_s = static_cast(widthA4PDF) / width; + + pdffile = true; + pdffile_content << "q" << std::endl; // gsave + + return; + } + void closePDF(void) + { + if(pdffile) { + + std::string PDFTitle = "plot() by FreeFem++"; + std::string AppName = "FreeFem++ v" + StrVersionNumber(); + + SimplePDF_FF pdf( pdffile_name, PDFTitle.c_str(), AppName.c_str() ); + + const int widthPDF = static_cast( width * pdf_s ); + const int heightPDF = static_cast( height * pdf_s ); + + pdffile_content << "Q" << std::endl; + + pdf.addPage( pdffile_content, widthPDF, heightPDF ); + + pdffile = false; + } + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + return; + } + void openSVG(const char *filename ) + { + if(svgfile_save) closeSVG(); + + const int widthA4PS = 596; + //const int heightA4PS = 842; + svg_s = static_cast(widthA4PS)/width; + + char ffff[32]; + int count = 0; + if(!filename){ + bool notfound; + do { + struct stat buf; + sprintf(ffff,"rgraph_%.3d.svg",count++); + volatile int r = stat(ffff,&buf) ; + notfound = (r != 0); + if( count > 1000 ) break; + } while ( !notfound ); + } + + const char *fsvg (filename?filename:ffff); + + svgfile=fopen(fsvg,"w"); + + if(svgfile) { + svgfile_save=svgfile; + fprintf(svgfile,"\n\n"); + fprintf(svgfile,"\n\n", StrVersionNumber().c_str()); + fprintf(svgfile,"\n", + static_cast(width*svg_s), static_cast(height*svg_s)); + } + else + { + cerr << " Err openning SVG file " << fsvg << endl; + } + return; + } + void closeSVG(void) + { + if(svgfile_save) { + fprintf(svgfile_save,"\n"); + fclose(svgfile_save); + } + svgfile_save=0; + svgfile=0; + + return; + } + //---------------------------------------------------------------------- + // add by fujiwara end + //---------------------------------------------------------------------- void Commentaire(const char * c) { if(psfile) { fprintf(psfile,"%% %s\n",c); } + // add by fujiwara + if( pdffile ) { + //fprintf(pdffile,"%% %s\n",c); + } + if( svgfile ) { + fprintf(svgfile,"%% %s\n",c); + } }; void NoirEtBlanc(int NB) { *************** *** 1115,1120 **** --- 1311,1327 ---- if(in) psfile=psfile_save; else psfile=0; } + // add by fujiwara + void MettreDansPDF(int in) // put into PDF + { + if(in) pdffile=true; + else pdffile=false; + } + void MettreDansSVG(int in) // put into SVG + { + if(in) svgfile=svgfile_save; + else svgfile=0; + } static void FillRect(float x0,float y0, float x1, float y1) { *************** *** 1160,1171 **** --- 1367,1382 ---- { if(k) { MettreDansPostScript(0); + MettreDansPDF(0); // add by fujiwara + MettreDansSVG(0); // add by fujiwara couleur(1); float xmin,xmax,ymin,ymax; getcadre(xmin,xmax,ymin,ymax); rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); plotstring(s); MettreDansPostScript(1); + MettreDansPDF(1); // add by fujiwara + MettreDansSVG(1); // add by fujiwara // couleur(1); } } diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/pdf.h FreeFem-sources-4.11/src/Graphics/pdf.h *** FreeFem-sources-4.11.orig/src/Graphics/pdf.h Thu Jan 1 09:00:00 1970 --- FreeFem-sources-4.11/src/Graphics/pdf.h Sat Apr 23 09:39:46 2022 *************** *** 0 **** --- 1,492 ---- + // -*- C++ -*- + // Time-stamp: "2019-12-29 10:38:37 fujiwara" + // + // SUMMARY : Class in order to generate Portable Document Format + // ORG : Graduate School of Informatics, Kyoto University, Japan + // AUTHOR : Hiroshi Fujiwara + // E-MAIL : fujiwara@acs.i.kyoto-u.ac.jp + // + // The newest version is avalilable at: + // http://www-an.acs.i.kyoto-u.ac.jp/~fujiwara/ff++-programs + // + //---------------------------------------------------------------------- + #ifndef PDF_H + #define PDF_H + + #include + #include + #include + #include + #include + #include + #include + #include // strlen + #include // exit + + //#define HAVE_ZLIB // need zlib : CC ***.cpp -lz + //#undef HAVE_ZLIB + + //---------------------------------------------------------------------- + // Simple PDF class + //---------------------------------------------------------------------- + #include + #include + #include + #include + #include // strlen + #include // exit + + class SimplePDF_FF + { + int byte_offset; + std::list xref; + + struct OutlineItem { + int headPageObjectNumber; + char *label; + }; + std::list outline; + + const std::string filename; + const std::string DocumentTitle; + int page_obj_offset, page; + + std::string get_datetime() const + { + std::time_t now = std::time( NULL ); + const std::tm* lt = std::localtime(&now); + + std::stringstream s; + + s << std::setfill('0') << std::right // valid for all operations << + << "20" << std::setw(2) << lt->tm_year-100 + << std::setw(2) << lt->tm_mon+1 // setw() is reset at each ops << + << std::setw(2) << lt->tm_mday + << std::setw(2) << lt->tm_hour + << std::setw(2) << lt->tm_min + << std::setw(2) << lt->tm_sec; + + return s.str(); + } + + #ifdef HAVE_ZLIB + int deflate_compress( char* &buf, const std::string &Stream ) const; + #endif + + public: + + SimplePDF_FF( const char *const filename, const char *const title = "", + const char *const AppName = "" ); + + ~SimplePDF_FF(); + + void addPage( const std::stringstream &ContentStream, const int WIDTH, const int HEIGHT ); + + void addBookmark( const char *const BookmarkLabel ); + }; + + SimplePDF_FF::SimplePDF_FF( const char *const PDFfilename, const char *const title, + const char *const AppName ) : filename( PDFfilename ), DocumentTitle( title ), page(0) + { + std::ofstream fout( filename.c_str(), std::ios::binary ); + + if( !fout ){ + std::cerr << "Cannot open the file: " << filename << std::endl; + return; + } + + //-------------------------------------------------- + // Header Section + //-------------------------------------------------- + std::stringstream header; + #if 1 + // match to pdflatex & dvipdfmx in texlive 2019 + header << "%PDF-1.5\n" + << '%' << char(0xd0) << char(0xd4) << char(0xc5) << char(0xd8) << '\n'; + #else + header << "%PDF-1.7\n" + << '%' << char(0xe2) << char(0xe3) << char(0xcf) << char(0xd3) << '\n'; + #endif + + fout << header.str(); + byte_offset = header.str().length(); + + fout.close(); + + //-------------------------------------------------- + // Body Section : Objects + //-------------------------------------------------- + std::list obj; + + std::stringstream strDocumentInfo; + strDocumentInfo << "1 0 obj\n" + << "<<\n"; + + if( strlen( DocumentTitle.c_str() ) > 0 ) + strDocumentInfo << " /Title (" << DocumentTitle << ")\n"; + + strDocumentInfo << " /Creator (" << AppName << ")\n" + << " /CreationDate (D:" << get_datetime() << ")\n" + << ">>\n" + << "endobj\n"; + const std::string DocumentInfo = strDocumentInfo.str(); + + // /PageLayout \in { /SinglePage (default), /OneColumn, + // /TwoColumnLeft, /TwoColumnRight, /TwoPageLeft, /TwoPageRight } + // /PageMode \in { /UseNone (default), /UseOutlines, /UseThumbs, /FullScreen, /UseOC, /UseAttachements } + const std::string DocumentCatalog = + "2 0 obj\n" + "<<\n" + " /Pages 3 0 R\n" + " /Type /Catalog\n" + " /PageLayout /SinglePage\n" + " /PageMode 4 0 R\n" + " /Outlines 5 0 R\n" + ">>\n" + "endobj\n"; + + //-------------------------------------------------- + // Object 3 is reserved for PageTree + // Object 4 is reserved for PageMode + // Object 5 is reserved for Outlines + // Object 6 is reserved for Outlines (document title) + //-------------------------------------------------- + + //-------------------------------------------------- + // Roman Fonts + //-------------------------------------------------- + const std::string FontEH = + "7 0 obj\n" + "<<\n" + " /BaseFont /Helvetica\n" + " /Subtype /Type1\n" + " /Type /Font\n" + ">>\n" + "endobj\n"; + + fout.open( filename.c_str(), std::ios::app ); + + obj.push_back( &DocumentInfo ); + obj.push_back( &DocumentCatalog ); + obj.push_back( &FontEH ); + + for(std::list::const_iterator itr = obj.begin(); itr != obj.end(); itr++){ + fout << **itr; + xref.push_back( byte_offset ); + byte_offset += (*itr)->length(); + } + + fout.close(); + + page_obj_offset = obj.size()+5; + + return; + } + + SimplePDF_FF::~SimplePDF_FF() + { + std::ofstream fout( filename.c_str(), std::ios::app ); + + //---------------------------------------- + // PageTree + //---------------------------------------- + std::stringstream strPageTree; + strPageTree << "3 0 obj\n" + << "<<\n" + << " /Kids ["; + + for(int i = 0; i < page; i++) + strPageTree << ((i == 0)? "": " ") << page_obj_offset+i*2 << " 0 R"; + + strPageTree << "]\n" + << " /Type /Pages\n" + << " /Count " << page << "\n" + << ">>\n" + << "endobj\n"; + + fout << strPageTree.str(); + + std::list::iterator itr = xref.begin(); // obj 1 (DocumentInfo) + itr++; // obj 2 (DocumentCatalog) + itr++; // obj 3 (FontEH at present) + itr = xref.insert( itr, byte_offset ); // byte_offset is inserted before itr (FontEH) + // and itr indicates byte_offset + + byte_offset += strPageTree.str().length(); + + //---------------------------------------- + // /PageMode \in { /UseNone (default), /UseOutlines, /UseThumbs, /FullScreen, /UseOC, /UseAttachements } + //---------------------------------------- + std::stringstream strPageMode; + strPageMode << "4 0 obj\n" + << " " << (outline.empty()? "/UseNone\n": "/UseOutlines\n") + << "endobj\n"; + + fout << strPageMode.str(); + + itr++; // obj 3 (FontEH at present) + itr = xref.insert( itr, byte_offset ); // byte_offset is inserted before itr (FontEH) + // and itr indicates byte_offset + byte_offset += strPageMode.str().length(); + + //---------------------------------------- + // Outlines + //---------------------------------------- + std::stringstream strOutlines; + strOutlines << "5 0 obj\n" + << "<<\n" + << " /Type /Outlines\n" + << " /Count " << 1+outline.size() << "\n" // 1 : Document Title + << " /First 6 0 R\n" + << " /Last 6 0 R\n" + << ">>\n" + << "endobj\n"; + + fout << strOutlines.str(); + + itr++; // obj 3 (FontEH at present) + itr = xref.insert( itr, byte_offset ); // byte_offset is inserted before itr (FontEH) + // and itr indicates byte_offset + byte_offset += strOutlines.str().length(); + + //---------------------------------------- + // the top of outline + //---------------------------------------- + strOutlines.str(""); // clear string buffer + strOutlines.clear( std::stringstream::goodbit ); // clear status + + strOutlines << "6 0 obj\n" + << "<<\n" + << " /Title (" << DocumentTitle << ")\n" + << " /Parent 5 0 R\n" + << " /Count " << outline.size() << "\n"; + + if( !outline.empty() ){ + + const int OutlineItemIdFirst = xref.size()+2; + const int OutlineItemIdLast = xref.size()+outline.size()+1; + + strOutlines << " /First " << OutlineItemIdFirst << " 0 R\n" + << " /Last " << OutlineItemIdLast << " 0 R\n"; + } + + strOutlines << " /Dest [" << outline.front().headPageObjectNumber << " 0 R /Fit]\n" + << ">>\n" + << "endobj\n"; + + fout << strOutlines.str(); + + itr++; // obj 3 (FontEH at present) + itr = xref.insert( itr, byte_offset ); // byte_offset is inserted before itr (FontEH) + // and itr indicates byte_offset + byte_offset += strOutlines.str().length(); + + //---------------------------------------- + // outline items + //---------------------------------------- + for(std::list::iterator itr = outline.begin(); itr != outline.end(); itr++){ + + std::stringstream strOutlineItem; + + const int object_id = xref.size()+1; + + strOutlineItem << object_id << " 0 obj\n" + << "<<\n" + << " /Title (" << itr->label << ")\n" + << " /Parent 6 0 R\n"; + + if( itr != outline.begin() ) + strOutlineItem << " /Prev " << object_id-1 << " 0 R\n"; + + std::list::const_iterator succ = itr; + succ++; + if( succ != outline.end() ) + strOutlineItem << " /Next " << object_id+1 << " 0 R\n"; + + strOutlineItem << " /Count 0\n" + << " /Dest [" << itr->headPageObjectNumber << " 0 R /Fit]\n" + << ">>\n" + << "endobj\n"; + + fout << strOutlineItem.str(); + + delete [] itr->label; + + xref.push_back( byte_offset ); + byte_offset += strOutlineItem.str().length(); + } + + //---------------------------------------- + // Corss-reference Table Section + //---------------------------------------- + const int nobjs = xref.size()+1; // including 0th object (0 0 obj) + + fout << "xref\n"; + fout << "0 " << nobjs << std::endl; + fout << "0000000000 65535 f \n"; // 0 0 obj + + for(std::list::const_iterator itr = xref.begin(); itr != xref.end(); itr++) + fout << std::setw(10) << std::setfill('0') << *itr << " 00000 n \n"; + + //---------------------------------------- + // Trailer Section + //---------------------------------------- + fout << "trailer\n" + << "<<\n" + << " /Info 1 0 R\n" + << " /Root 2 0 R\n" + << " /Size " << nobjs << "\n" + << ">>\n" + << "startxref\n" + << byte_offset << std::endl // starting position of 'xref' + << "%%EOF\n"; + + fout.close(); + + return; + } + // + + #ifdef HAVE_ZLIB + + #include + + int SimplePDF_FF::deflate_compress( char* &outbuf, const std::string &Stream ) const + { + char *inbuf = new char [ Stream.length()+1 ]; + + for(size_t i = 0; i < Stream.length(); i++) // strcpy or strncpy + inbuf[i] = Stream[i]; + inbuf[ Stream.length() ] = '\0'; + + z_stream z; + z.zalloc = Z_NULL; + z.zfree = Z_NULL; + z.opaque = Z_NULL; + + if( deflateInit(&z, Z_DEFAULT_COMPRESSION) != Z_OK ) { + std::cerr << "zlib: deflateInit(): " << ((z.msg)? z.msg: "Error") << std::endl; + std::exit(1); + } + + outbuf = new char [ Stream.length()+1 ]; + + z.next_in = reinterpret_cast(inbuf); + z.avail_in = Stream.length(); + z.next_out = reinterpret_cast(outbuf); + z.avail_out = Stream.length(); + + if( deflate(&z, Z_FINISH) != Z_STREAM_END ){ + std::cerr << "zlib: deflate(): " << ((z.msg)? z.msg: "Error") << std::endl; + std::exit(1); + } + + if( deflateEnd(&z) != Z_OK ){ + std::cerr << "zlib: deflateEnd(): " << ((z.msg)? z.msg: "Error") << std::endl; + std::exit(1); + } + + delete [] inbuf; + + const int compressed_buf_length = Stream.length() - z.avail_out; + + outbuf[compressed_buf_length] = '\n'; + + return compressed_buf_length+1; + } + + #endif + + void SimplePDF_FF::addPage( const std::stringstream &ContentStream, + const int WIDTH, const int HEIGHT ) + { + //---------------------------------------- + // PageObject + //---------------------------------------- + std::stringstream strPageObject; + + strPageObject << page_obj_offset+2*page << " 0 obj\n" + << "<<\n" + << " /Type /Page\n" + << " /Parent 3 0 R\n" + << " /Resources << /Font << /F1 7 0 R >> >>\n" + << " /MediaBox [0 0 " << WIDTH << ' ' << HEIGHT << "]\n" + << " /Contents " << page_obj_offset+2*page+1 << " 0 R\n" + << ">>\n" + << "endobj\n"; + + const std::string PageObject = strPageObject.str(); + + //---------------------------------------- + // pageContent (stream) + //---------------------------------------- + #ifdef HAVE_ZLIB + char *buf; + const int compressed_buf_length = deflate_compress( buf, ContentStream.str() ); + #endif + + //---------------------------------------- + // pageContent (object) + //---------------------------------------- + std::stringstream strContent; + strContent << page_obj_offset+2*page+1 << " 0 obj\n" + << "<< /Length "; + #ifdef HAVE_ZLIB + strContent << compressed_buf_length << " /Filter /FlateDecode"; + #else + strContent << ContentStream.str().length(); + #endif + strContent << " >>\n" + << "stream\n"; + + #ifdef HAVE_ZLIB + // Following works well even if buf[] has '\0' + strContent << std::string( buf+0, buf+compressed_buf_length ); + delete [] buf; + #else + strContent << ContentStream.str(); + #endif + + strContent << "endstream\n" + << "endobj\n"; + + const std::string Content = strContent.str(); + + //---------------------------------------- + // Add Page Objects + //---------------------------------------- + std::ofstream fout( filename.c_str(), std::ios::app ); + + const std::string*const PageObj[2] = { &PageObject, &Content }; + + for(int i = 0; i < 2; i++){ + xref.push_back( byte_offset ); + fout << *PageObj[i]; + byte_offset += PageObj[i]->length(); + } + + fout.close(); + page++; + + return; + } + + void SimplePDF_FF::addBookmark( const char *const BookmarkLabel ) + { + OutlineItem item; + + item.headPageObjectNumber = page_obj_offset+2*page; + + item.label = new char [ strlen(BookmarkLabel)+1 ]; + strcpy( item.label, BookmarkLabel ); + + outline.push_back( item ); + + return; + } + + #endif // PDF_H + + //---------------------------------------------------------------------- + // End of file + //---------------------------------------------------------------------- diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/rgraph.hpp FreeFem-sources-4.11/src/Graphics/rgraph.hpp *** FreeFem-sources-4.11.orig/src/Graphics/rgraph.hpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/rgraph.hpp Sat Apr 23 09:39:46 2022 *************** *** 90,101 **** --- 90,107 ---- EXTERNFF( void ,openPS,(const char * )) ; EXTERNFF( void ,closePS,(void)) ; + EXTERNFF( void ,openPDF,(const char * )) ; // add by fujiwara + EXTERNFF( void ,closePDF,(void)) ; // add by fujiwara + EXTERNFF( void ,openSVG,(const char * )) ; // add by fujiwara + EXTERNFF( void ,closeSVG,(void)) ; // add by fujiwara EXTERNFF( void ,coutmode,(short i)) ; EXTERNFF( void ,myexit,(int err)) ; // err=0 ?? EXTERNFF( void ,viderbuff,()) ; EXTERNFF( void ,Commentaire,(const char *)) ; EXTERNFF( void ,NoirEtBlanc,(int NB)) ; EXTERNFF( void ,MettreDansPostScript,(int in)) ;// oui=1 ou non=0 + EXTERNFF( void ,MettreDansPDF,(int in)) ;// oui=1 ou non=0 // add by fujiwara + EXTERNFF( void ,MettreDansSVG,(int in)) ;// oui=1 ou non=0 // add by fujiwara EXTERNFF( int ,getprog,(char* fn,int , char** argvptr)) ; EXTERNFF( void ,setgrey,(bool )) ; EXTERNFF( int ,getgrey,( )) ; *************** *** 135,146 **** --- 141,158 ---- //compileString=compileString_; openPS=openPS_; closePS=closePS_; + openPDF=openPDF_; // add by fujiwara + closePDF=closePDF_; // add by fujiwara + openSVG=openSVG_; // add by fujiwara + closeSVG=closeSVG_; // add by fujiwara coutmode=coutmode_; myexit=myexit_; viderbuff=viderbuff_; Commentaire=Commentaire_; NoirEtBlanc=NoirEtBlanc_; MettreDansPostScript=MettreDansPostScript_; + MettreDansPDF=MettreDansPDF_; // add by fujiwara + MettreDansSVG=MettreDansSVG_; // add by fujiwara getprog=getprog_; setgrey=setgrey_; getgrey=getgrey_; *************** *** 179,190 **** --- 191,208 ---- //#define compileString compileString_ #define openPS openPS_ #define closePS closePS_ + #define openPDF openPDF_ // add by fujiwara + #define closePDF closePDF_ // add by fujiwara + #define openSVG openSVG_ // add by fujiwara + #define closeSVG closeSVG_ // add by fujiwara #define coutmode coutmode_ #define myexit myexit_ #define viderbuff viderbuff_ #define Commentaire Commentaire_ #define NoirEtBlanc NoirEtBlanc_ #define MettreDansPostScript MettreDansPostScript_ + #define MettreDansPDF MettreDansPDF_ // add by fujiwara + #define MettreDansSVG MettreDansSVG_ // add by fujiwara #define getprog getprog_ #define setgrey setgrey_ #define getgrey getgrey_ diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/Graphics/sansrgraph.cpp FreeFem-sources-4.11/src/Graphics/sansrgraph.cpp *** FreeFem-sources-4.11.orig/src/Graphics/sansrgraph.cpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/Graphics/sansrgraph.cpp Sat Apr 23 09:39:46 2022 *************** *** 43,48 **** --- 43,51 ---- using namespace std; #include "rgraph.hpp" + #include // add by fujiwara + #include "pdf.h" // add by fujiwara + #include "error.hpp" #ifdef macintoshxx #include *************** *** 127,132 **** --- 130,146 ---- static bool grey=false; static FILE *psfile = 0; static FILE *psfile_save = 0; + static bool pdffile = false; // add by fujiwara + static char *pdffile_name = nullptr; // add by fujiwara + static float pdf_s = 1; // add by fujiwara + static std::stringstream pdffile_content; // add by fujiwara + static FILE *svgfile = 0; // add by fujiwara + static FILE *svgfile_save = 0; // add by fujiwara + static float svg_s = 1; // add by fujiwara + static int svg_r = 0; // add by fujiwara + static int svg_g = 0; // add by fujiwara + static int svg_b = 0; // add by fujiwara + static int svg_lw = 1; // add by fujiwara static int LastColor=2; // pour est en couleur par defaut const float fMinPixel = -32000; *************** *** 278,283 **** --- 292,308 ---- if(psfile) fprintf(psfile,"%.3f %.3f %.3f C\n",r,g,b); + // add by fujiwara + if( pdffile ){ + pdffile_content << r << ' ' << g << ' ' << b << " RG" << std::endl; + pdffile_content << r << ' ' << g << ' ' << b << " rg" << std::endl; + } + if( svgfile ){ + svg_r = static_cast(r*256); + svg_g = static_cast(g*256); + svg_b = static_cast(b*256); + } + #ifdef FFJS_GRAPH // ALH - <> javascript graph [[file:~/ffjs/main.js::ffjs_couleur]] EM_ASM_DOUBLE({ffjs_couleur($0,$1,$2)},r,g,b); *************** *** 488,493 **** --- 513,528 ---- int newx = scalx(x), newy = scaly(y); if (psfile) fprintf(psfile,"%d %d %d %d L\n",currx, height-curry, newx, height-newy); + // add by fujiwara + if ( pdffile ){ + pdffile_content << currx*pdf_s << ' ' << (height-curry)*pdf_s << " m " + << newx*pdf_s << ' ' << (height-newy)*pdf_s << " l S" << std::endl; + } + if ( svgfile ){ + fprintf(svgfile,"\n", + currx*svg_s, curry*svg_s, newx*svg_s, newy*svg_s, svg_r, svg_g, svg_b, svg_lw); + } + // add by fujiwara currx = newx; curry = newy; #ifdef FFJS_GRAPH *************** *** 521,526 **** --- 556,572 ---- { //int l = strlen(string); if(psfile) fprintf(psfile,"(%s) %d %d S\n",string,currx,height-curry); + // add by fujiwara + if( pdffile ){ + pdffile_content << "BT /F1 " << 9 << " Tf" << std::endl; // 9*pdf_s : text font size + pdffile_content << "1 0 0 1 " << currx*pdf_s << ' ' << (height-curry)*pdf_s << " Tm" << std::endl; + pdffile_content << "(" << string << ") Tj ET" << std::endl; + } + if( svgfile ){ + fprintf(svgfile,"%s\n",currx*svg_s,curry*svg_s,string); + } + // add by fujiwara + #ifdef FFJS_GRAPH // ALH - <> javascript graph - Send the string character by character to // [[file:~/ffjs/main.js::ffjs_plotstring]] because there is no string parameter at the moment *************** *** 538,543 **** --- 584,597 ---- void penthickness(int pepais) { if (psfile) fprintf(psfile,"%d setlinewidth\n",pepais*2); + // add by fujiwara + if ( pdffile ){ + pdffile_content << pepais << " w" << std::endl; + } + if ( svgfile ){ + svg_lw = pepais; + } + // add bu fujiwara #ifdef FFJS_GRAPH // ALH - <> javascript graph [[file:~/ffjs/main.js::ffjs_penthickness]] *************** *** 579,584 **** --- 633,656 ---- fprintf(psfile,"%d %d ", scalx(poly[2*i]),height-scaly( poly[2*i+1])); fprintf(psfile,"eF\n"); } + // add by fujiwara + if ( pdffile ) { + + i=0; + pdffile_content << scalx(poly[2*i])*pdf_s << ' ' << (height-scaly( poly[2*i+1]))*pdf_s << " m "; + for (i=1;i\n", + svg_r,svg_g,svg_b, svg_lw, svg_r,svg_g,svg_b); + } + // add by fujiwara #ifdef FFJS_GRAPH // ALH - <> javascript graph [[file:~/ffjs/main.js::ffjs_fillpoly]] *************** *** 588,593 **** --- 660,775 ---- #endif } + //---------------------------------------------------------------------- + // add by fujiwara + //---------------------------------------------------------------------- + void openPDF(const char *filename ) + { + if(pdffile) closePDF(); + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + pdffile_name = new char [ strlen(filename)+1 ]; + strcpy( pdffile_name, filename ); + + pdffile_content.str(""); // clear + pdffile_content.clear( std::stringstream::goodbit ); + + pdffile_content.setf( std::ios::fixed ); + pdffile_content.precision( 3 ); + + const int widthA4PDF = 596; + pdf_s = static_cast(widthA4PDF) / width; + + pdffile = true; + pdffile_content << "q" << std::endl; // gsave + + return; + } + void closePDF(void) + { + if(pdffile) { + + std::string PDFTitle = "plot() by FreeFem++"; + std::string AppName = "FreeFem++ v" + StrVersionNumber(); + + SimplePDF_FF pdf( pdffile_name, PDFTitle.c_str(), AppName.c_str() ); + + const int widthPDF = static_cast( width * pdf_s ); + const int heightPDF = static_cast( height * pdf_s ); + + pdffile_content << "Q" << std::endl; + + pdf.addPage( pdffile_content, widthPDF, heightPDF ); + + pdffile = false; + } + + if( pdffile_name != nullptr ){ + delete [] pdffile_name; + pdffile_name = nullptr; + } + + return; + } + void openSVG(const char *filename ) + { + if(svgfile_save) closeSVG(); + + const int widthA4PS = 596; + //const int heightA4PS = 842; + svg_s = static_cast(widthA4PS)/width; + + char ffff[32]; + int count = 0; + if(!filename){ + bool notfound; + do { + struct stat buf; + sprintf(ffff,"rgraph_%.3d.svg",count++); + volatile int r = stat(ffff,&buf) ; + notfound = (r != 0); + if( count > 1000 ) break; + } while ( !notfound ); + } + + const char *fsvg (filename?filename:ffff); + + svgfile=fopen(fsvg,"w"); + + if(svgfile) { + svgfile_save=svgfile; + fprintf(svgfile,"\n\n"); + fprintf(svgfile,"\n\n", StrVersionNumber().c_str()); + fprintf(svgfile,"\n", + static_cast(width*svg_s), static_cast(height*svg_s)); + } + else + { + cerr << " Err openning SVG file " << fsvg << endl; + } + return; + } + void closeSVG(void) + { + if(svgfile_save) { + fprintf(svgfile_save,"\n"); + fclose(svgfile_save); + } + svgfile_save=0; + svgfile=0; + + return; + } + //---------------------------------------------------------------------- + // add by fujiwara end + //---------------------------------------------------------------------- + int execute (const char * str) { *************** *** 720,725 **** --- 902,915 ---- if(psfile) { fprintf(psfile,"%% %s\n",c); } + // add by fujiwara + if( pdffile ) { + //fprintf(pdffile,"%% %s\n",c); + } + if( svgfile ) { + fprintf(svgfile,"%% %s\n",c); + } + // add by fujiwara } void NoirEtBlanc(int NB) { *************** *** 732,737 **** --- 922,939 ---- if(in) psfile=psfile_save; else psfile=0; } + // add by fujiwara + void MettreDansPDF(int in) // put into PDF + { + if(in) pdffile=true; + else pdffile=false; + } + void MettreDansSVG(int in) // put into SVG + { + if(in) svgfile=svgfile_save; + else svgfile=0; + } + // add by fujiwara static void FillRect(float x0,float y0, float x1, float y1) { *************** *** 767,778 **** --- 969,984 ---- { if(k) { MettreDansPostScript(0); + MettreDansPDF(0); // add by fujiwara + MettreDansSVG(0); // add by fujiwara couleur(1); float xmin,xmax,ymin,ymax; getcadre(xmin,xmax,ymin,ymax); rmoveto(xmin+(xmax-xmin)/100,ymax-(k)*(ymax-ymin)/30); plotstring(s); MettreDansPostScript(1); + MettreDansPDF(1); // add by fujiwara + MettreDansSVG(1); // add by fujiwara // couleur(1); } } diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/fflib/lgfem.cpp FreeFem-sources-4.11/src/fflib/lgfem.cpp *** FreeFem-sources-4.11.orig/src/fflib/lgfem.cpp Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/fflib/lgfem.cpp Sat Apr 23 09:46:18 2022 *************** *** 2794,2800 **** /// <> FFCS: added new parameters for VTK graphics. /// See /// [[Plot_name_param]] for new parameter names ! static const int n_name_param = 44; Expression bb[4]; --- 2794,2800 ---- /// <> FFCS: added new parameters for VTK graphics. /// See /// [[Plot_name_param]] for new parameter names ! static const int n_name_param = 46; // modified by fujiwara Expression bb[4]; *************** *** 3049,3054 **** --- 3049,3056 ---- {"add", &typeid(bool)}, // add to previous plot {"prev", &typeid(bool)}, // keep previou view point {"ech", &typeid(double)}, // keep previou view point + {"pdf", &typeid(string*)}, // 21, add by fujiwara + {"svg", &typeid(string*)}, // 22, add by fujiwara // FFCS: more options for VTK graphics (numbers are required for processing) *************** *** 4317,4323 **** // [[file:../ffcs/src/plot.cpp::Plotparam_listvalues]] and read the parameter value from the // pipe at [[file:../ffcs/src/visudata.cpp::receiving_plot_parameters]]. ! #define VTK_START 20 #define SEND_VTK_PARAM(index, type) \ if (nargs[VTK_START + index]) \ (theplot << (long)(VTK_START + index)) <= GetAny< type >((*nargs[VTK_START + index])(s)); --- 4319,4325 ---- // [[file:../ffcs/src/plot.cpp::Plotparam_listvalues]] and read the parameter value from the // pipe at [[file:../ffcs/src/visudata.cpp::receiving_plot_parameters]]. ! #define VTK_START 22 // modified by fujiwara #define SEND_VTK_PARAM(index, type) \ if (nargs[VTK_START + index]) \ (theplot << (long)(VTK_START + index)) <= GetAny< type >((*nargs[VTK_START + index])(s)); *************** *** 4561,4566 **** --- 4563,4570 ---- bool bw = false; string *psfile = 0; + string * pdffile=0; // add by fujiwara + string * svgfile=0; // add by fujiwara string *cm = 0; pferbase fe = 0, fe1 = 0; int cmp0, cmp1; *************** *** 4570,4575 **** --- 4574,4581 ---- if (nargs[0]) coeff = GetAny< double >((*nargs[0])(s)); if (nargs[1]) cm = GetAny< string * >((*nargs[1])(s)); if (nargs[2]) psfile = GetAny< string * >((*nargs[2])(s)); + if (nargs[21]) pdffile= GetAny((*nargs[21])(s)); // add by fujiwara + if (nargs[22]) svgfile= GetAny((*nargs[22])(s)); // add by fujiwara if (nargs[3]) wait = GetAny< bool >((*nargs[3])(s)); if (nargs[4]) fill = GetAny< bool >((*nargs[4])(s)); if (nargs[5]) value = GetAny< bool >((*nargs[5])(s)); *************** *** 4624,4629 **** --- 4630,4637 ---- const Mesh *cTh = 0; bool vecvalue = false, isovalue = false; bool ops = psfile; + bool opdf=pdffile; // add by fujiwara + bool osvg=svgfile; // add by fujiwara bool drawmeshes = false; if (clean) { // ALH - 28/3/15 - Open PS file before blanking the current picture because Javascript needs to *************** *** 4634,4639 **** --- 4642,4655 ---- openPS(psfile->c_str( )); } + // add by fujiwara + if( pdffile ) { + openPDF(pdffile->c_str()); + } + // add by fujiwara + if( svgfile ) { + openSVG(svgfile->c_str()); + } reffecran( ); if (bw) NoirEtBlanc(1); *************** *** 4846,4851 **** --- 4862,4877 ---- ops = false; closePS( ); } + // add by fujiwara + if ( opdf ) { + opdf = false; + closePDF(); + } + // add by fujiwara + if ( osvg ) { + osvg = false; + closeSVG(); + } if (wait && !NoWait) { next: float x, y, x0, y0, x1, y1, dx, dy, coef = 1.5; diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/mpi/Makefile.am FreeFem-sources-4.11/src/mpi/Makefile.am *** FreeFem-sources-4.11.orig/src/mpi/Makefile.am Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/mpi/Makefile.am Sat Apr 23 09:39:46 2022 *************** *** 43,51 **** ../lglib/lg.tab.cpp \ parallelempi.cpp FreeFem___mpi_DEPENDENCIES = ../fflib/libff.a ! LDADD = ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLACSLIBS@ @MPI_LIB@ @FF_LIBS@ ! AM_CXXFLAGS = -DPARALLELE AM_CPPFLAGS = -I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../femlib @MPI_INCLUDE@ $(HDF5_CPPFLAGS) $(UMFPACK_CPPFLAGS) ff-mpirun: ff-mpirun.in Makefile ../../config.status --file=ff-mpirun:ff-mpirun.in --- 43,51 ---- ../lglib/lg.tab.cpp \ parallelempi.cpp FreeFem___mpi_DEPENDENCIES = ../fflib/libff.a ! LDADD = ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLACSLIBS@ @MPI_LIB@ @FF_LIBS@ -lz ! AM_CXXFLAGS = -DPARALLELE -DHAVE_ZLIB AM_CPPFLAGS = -I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../femlib @MPI_INCLUDE@ $(HDF5_CPPFLAGS) $(UMFPACK_CPPFLAGS) ff-mpirun: ff-mpirun.in Makefile ../../config.status --file=ff-mpirun:ff-mpirun.in diff '--color=auto' -Ncr FreeFem-sources-4.11.orig/src/nw/Makefile.am FreeFem-sources-4.11/src/nw/Makefile.am *** FreeFem-sources-4.11.orig/src/nw/Makefile.am Wed Apr 6 03:42:53 2022 --- FreeFem-sources-4.11/src/nw/Makefile.am Sat Apr 23 09:39:46 2022 *************** *** 48,58 **** FreeFem___nw_SOURCES = ../Graphics/sansrgraph.cpp ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp FreeFem___SOURCES = ../Graphics/sansrgraph.cpp ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp ! FreeFem___LDADD = ../lglib/liblg.a ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@ @FF_LIBS@ ! FreeFem___nw_LDADD = ../lglib/liblg.a ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@ @FF_LIBS@ FreeFem___nw_DEPENDENCIES = ../fflib/libff.a ../lglib/liblg.a FreeFem___DEPENDENCIES = ../fflib/libff.a ../lglib/liblg.a #LDADD = ../lglib/liblg.a ../fflib/libff.a ! AM_CPPFLAGS = -I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../.. -I$(srcdir)/../femlib --- 48,58 ---- FreeFem___nw_SOURCES = ../Graphics/sansrgraph.cpp ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp FreeFem___SOURCES = ../Graphics/sansrgraph.cpp ../mpi/parallelempi-empty.cpp ../fflib/ffapi.cpp ! FreeFem___LDADD = ../lglib/liblg.a ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@ @FF_LIBS@ -lz ! FreeFem___nw_LDADD = ../lglib/liblg.a ../fflib/libff.a @UMFPACKLIBS@ @ARPACKLIBS@ @BLASLIBS@ @FF_LIBS@ -lz FreeFem___nw_DEPENDENCIES = ../fflib/libff.a ../lglib/liblg.a FreeFem___DEPENDENCIES = ../fflib/libff.a ../lglib/liblg.a #LDADD = ../lglib/liblg.a ../fflib/libff.a ! AM_CPPFLAGS = -I$(srcdir)/../fflib -I$(srcdir)/../Graphics -I$(srcdir)/../.. -I$(srcdir)/../femlib -DHAVE_ZLIB