/*************************************************************************** * export_2d.cpp is part of Math Graphic Library * Copyright (C) 2007-2016 Alexey Balakin * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "mgl2/canvas.h" #include "mgl2/canvas_cf.h" #include "mgl2/font.h" #include #include #include #undef _GR_ #define _GR_ ((mglCanvas *)(*gr)) #define _Gr_ ((mglCanvas *)(gr)) void mgl_printf(void *fp, bool gz, const char *str, ...); //----------------------------------------------------------------------------- static const char *mgl_get_dash(unsigned short d, mreal w,char dlm) { static std::string s; if(d==0xffff) return ""; int f=0, p=d&1, n=p?0:1; s = p ? "" : "0"; for(int i=0;i<16;i++) { int j = i;//15-i; if(((d>>j)&1) == p) f++; else { s += mgl_str_num(f*w)+dlm; p = (d>>j)&1; f = 1; n++; } } s += mgl_str_num(f*w) + ((n%2) ? "" : " 0"); return s.c_str(); } //----------------------------------------------------------------------------- bool MGL_LOCAL_PURE mgl_is_same(HMGL gr, long i, mreal wp,uint32_t cp, int st) { const mglPrim &pr=_Gr_->GetPrm(i); if(abs(pr.type)!=1) return false; if(pr.w>=1 && wp!=pr.w) return false; if(pr.w<1 && wp!=1) return false; if(st!=pr.n3) return false; return (cp==_Gr_->GetPrmCol(i)); } //----------------------------------------------------------------------------- std::vector static put_line(HMGL gr, long i, mreal wp, uint32_t cp,int st) { std::vector ids; long n1=gr->GetPrm(i).n1, n2=gr->GetPrm(i).n2; if(n1>n2) { n1=gr->GetPrm(i).n2; n2=gr->GetPrm(i).n1; } if(n1<0 || n2<0) return ids; const mglPnt &pp1 = gr->GetPnt(n1), &pp2 = gr->GetPnt(n2); mreal x0=pp1.x, y0=pp1.y; bool ok=true; long j; // first point while(ok) // try to find starting point { for(ok=false,j=i+1;jGetPrmNum();j++) { mglPrim &q = gr->GetPrm(j); if(q.type>1) break; if(mgl_is_same(gr, j, wp,cp,st) && q.type==1 && q.n1>=0 && q.n2>=0) // previous point { const mglPnt &p1 = gr->GetPnt(q.n1); const mglPnt &p2 = gr->GetPnt(q.n2); if(p2.x==x0 && p2.y==y0) { ok = true; ids.push_back(q.n1); x0 = p1.x; y0 = p1.y; q.type = -1; } else if(p1.x==x0 && p1.y==y0) { ok = true; ids.push_back(q.n2); x0 = p2.x; y0 = p2.y; q.type = -1; } } } } std::reverse(ids.begin(),ids.end()); ids.push_back(n1); ids.push_back(n2); x0 = pp2.x; y0 = pp2.y; ok = true; while(ok) // try to find starting point { for(ok=false,j=i+1;jGetPrmNum();j++) { mglPrim &q = gr->GetPrm(j); if(q.type>1) break; if(mgl_is_same(gr, j,wp,cp,st) && q.type==1 && q.n1>=0 && q.n2>=0) // next point { const mglPnt &p1 = gr->GetPnt(q.n1); const mglPnt &p2 = gr->GetPnt(q.n2); if(p2.x==x0 && p2.y==y0) { ok = true; ids.push_back(q.n1); x0 = p1.x; y0 = p1.y; q.type = -1; } else if(p1.x==x0 && p1.y==y0) { ok = true; ids.push_back(q.n2); x0 = p2.x; y0 = p2.y; q.type = -1; } } } } return ids; } //----------------------------------------------------------------------------- //put_desc(fp,"%c%c%c_%04x {", "np %d %d mt %d %d ll %d %d ll cp fill\n", //"np %d %d mt ", "%d %d ll ", "cp dr\n", "} def") void static put_desc(HMGL gr, void *fp, bool gz, const char *pre, const char *ln1, const char *ln2, const char *ln3, const char *suf) { long n=0; for(long i=0;iGetPrmNum();i++) if(gr->GetPrm(i).type==4) n++; if(n==0) return; // no glyphs wchar_t *g = new wchar_t[n]; int *s = new int[n]; n=0; for(long i=0;iGetPrmNum();i++) { const mglPrim &q = gr->GetPrm(i); if(q.type!=4 || (q.n3&8)) continue; // not a glyph bool is=false; for(long j=0;jGetGlf(q.n4); int nl=g.nl; const short *ln=g.line; bool np=true; if(ln && nl>0) for(long ik=0;ik> pat\n"); } else { mgl_printf(fp, gz, "/PaintProc { gsave %d rotate\n",-ang); for(int i=-4;i<4;i++) for(int j=-4;j<4;j++) { int ii = (8+i)&7, jj = (8+j)&7; if(pd & (1L<<(ii+8*jj))) mgl_printf(fp, gz, "%g %g %g %g rf\n",i*pw,j*pw,pw,pw); } mgl_printf(fp, gz, "grestore}\n>> pat\n"); } return true; } //----------------------------------------------------------------------------- void MGL_EXPORT mgl_write_eps(HMGL gr, const char *fname,const char *descr) { if(!fname || *fname==0) return; if(gr->GetPrmNum()<1) return; _Gr_->clr(MGL_FINISHED); _Gr_->PreparePrim(1); time_t now; time(&now); bool gz = fname[strlen(fname)-1]=='z'; void *fp; if(!strcmp(fname,"-")) fp = stdout; // allow to write in stdout else fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt"); if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; } int w = _Gr_->GetWidth(), h = _Gr_->GetHeight(); int x1=gr->BBoxX1, x2=gr->BBoxX2<0?w:gr->BBoxX2, y1=gr->BBoxY1, y2=gr->BBoxY2<0?h:gr->BBoxY2; if(x2>w) x2=w; if(y2>h) y2=h; if(x1<0 || x1>=x2) { x1=0; x2=w; } if(y1<0 || y1>=y2) { y1=0; y2=h; } if(gz) { unsigned len = strlen(fname), pos=0; char *buf = new char[len+4]; memcpy(buf,fname,len); if(buf[len-3]=='.') pos = len-2; else if(buf[len-2]=='.') pos = len-1; else { buf[len-1]='.'; pos = len; } if(pos) { buf[pos]=buf[pos+1]='b'; buf[pos+2]=0; } FILE *fb = fopen(buf,"w"); fprintf(fb, "%%%%BoundingBox: %d %d %d %d\n", x1, h-y2, x2, h-y1); fclose(fb); delete []buf; } const std::string loc = setlocale(LC_NUMERIC, "C"); mgl_printf(fp, gz, "%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: %d %d %d %d\n", x1, h-y2, x2, h-y1); mgl_printf(fp, gz, "%%%%Created by MathGL library\n%%%%Title: %s\n",descr ? descr : fname); mgl_printf(fp, gz, "%%%%CreationDate: %s\n",ctime(&now)); mgl_printf(fp, gz, "%%%%LanguageLevel: 2\n50 dict begin"); mgl_printf(fp, gz, "/lw {setlinewidth} def\n/rgb {setrgbcolor} def\n"); mgl_printf(fp, gz, "/np {newpath} def\n/cp {closepath} def\n"); mgl_printf(fp, gz, "/ll {lineto} def\n/mt {moveto} def\n"); mgl_printf(fp, gz, "/rl {rlineto} def\n/rm {rmoveto} def\n/dr {stroke} def\n"); mgl_printf(fp, gz, "/ss {%g} def\n",0.35*gr->mark_size()); mgl_printf(fp, gz, "/s2 {%g} def\n",0.7*gr->mark_size()); mgl_printf(fp, gz, "/sm {-%g} def\n",0.35*gr->mark_size()); mgl_printf(fp, gz, "/m_c {ss 0.3 mul 0 360 arc} def\n"); mgl_printf(fp, gz, "/d0 {[] 0 setdash} def\n/sd {setdash} def\n"); mgl_printf(fp, gz, "/pat {[1 0 0 1 0 0] makepattern /Mask exch def [/Pattern /DeviceRGB] setcolorspace} def\n"); mgl_printf(fp, gz, "/mask {Mask setpattern} def\n/rf {rectfill} def\n"); bool m_p=false,m_x=false,m_d=false,m_v=false,m_t=false, m_s=false,m_a=false,m_o=false,m_T=false, m_V=false,m_S=false,m_D=false,m_Y=false,m_l=false, m_L=false,m_r=false,m_R=false,m_X=false,m_P=false; // add mark definition if present for(long i=0;iGetPrmNum();i++) { const mglPrim &q = gr->GetPrm(i); if(q.type>0) continue; if(q.n4=='+') m_p = true; if(q.n4=='x') m_x = true; if(q.n4=='s') m_s = true; if(q.n4=='d') m_d = true; if(q.n4=='v') m_v = true; if(q.n4=='^') m_t = true; if(q.n4=='*') m_a = true; if(q.n4=='o' || q.n4=='O' || q.n4=='C') m_o = true; if(q.n4=='S') m_S = true; if(q.n4=='D') m_D = true; if(q.n4=='V') m_V = true; if(q.n4=='T') m_T = true; if(q.n4=='<') m_l = true; if(q.n4=='L') m_L = true; if(q.n4=='>') m_r = true; if(q.n4=='R') m_R = true; if(q.n4=='Y') m_Y = true; if(q.n4=='P') m_P = true; if(q.n4=='X') m_X = true; } if(m_P) { m_p=true; m_s=true; } if(m_X) { m_x=true; m_s=true; } if(m_p) mgl_printf(fp, gz, "/m_p {sm 0 rm s2 0 rl sm sm rm 0 s2 rl d0} def\n"); if(m_x) mgl_printf(fp, gz, "/m_x {sm sm rm s2 s2 rl 0 sm 2 mul rm sm 2 mul s2 rl d0} def\n"); if(m_s) mgl_printf(fp, gz, "/m_s {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp d0} def\n"); if(m_d) mgl_printf(fp, gz, "/m_d {sm 0 rm ss ss rl ss sm rl sm sm rl cp d0} def\n"); if(m_v) mgl_printf(fp, gz, "/m_v {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl d0 cp} def\n"); if(m_t) mgl_printf(fp, gz, "/m_t {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl d0 cp} def\n"); if(m_a) mgl_printf(fp, gz, "/m_a {sm 0 rm s2 0 rl sm 1.6 mul sm 0.8 mul rm ss 1.2 mul ss 1.6 mul rl 0 sm 1.6 mul rm sm 1.2 mul ss 1.6 mul rl d0} def\n"); if(m_o) mgl_printf(fp, gz, "/m_o {ss 0 360 d0 arc} def\n"); if(m_S) mgl_printf(fp, gz, "/m_S {sm sm rm 0 s2 rl s2 0 rl 0 sm 2 mul rl cp} def\n"); if(m_D) mgl_printf(fp, gz, "/m_D {sm 0 rm ss ss rl ss sm rl sm sm rl cp} def\n"); if(m_V) mgl_printf(fp, gz, "/m_V {sm ss 2 div rm s2 0 rl sm sm 1.5 mul rl cp} def\n"); if(m_T) mgl_printf(fp, gz, "/m_T {sm sm 2 div rm s2 0 rl sm ss 1.5 mul rl cp} def\n"); if(m_Y) mgl_printf(fp, gz, "/m_Y {0 sm rm 0 ss rl sm ss rl s2 0 rm sm sm rl d0} def\n"); if(m_r) mgl_printf(fp, gz, "/m_r {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl d0 cp} def\n"); if(m_l) mgl_printf(fp, gz, "/m_l {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl d0 cp} def\n"); if(m_R) mgl_printf(fp, gz, "/m_R {sm 2 div sm rm 0 s2 rl ss 1.5 mul sm rl cp} def\n"); if(m_L) mgl_printf(fp, gz, "/m_L {ss 2 div sm rm 0 s2 rl sm 1.5 mul sm rl cp} def\n"); if(m_P) mgl_printf(fp, gz, "/m_P {m_p 0 sm rm m_s} def\n"); if(m_X) mgl_printf(fp, gz, "/m_X {m_x ss sm rm m_s} def\n"); // if(m_C) mgl_printf(fp, gz, "/m_C {m_c m_o} def\n"); mgl_printf(fp, gz, "0 setlinecap\n1 setlinejoin\n\n"); // manual setting round line cap // Write background image first const unsigned char *img = mgl_get_background(gr); bool same = true; unsigned char white[3]={255,255,255}; #pragma omp parallel for for(long i=0;i=y1;j--) for(long i=x1;i0) mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "%02x%02x%02x",img[4*(i+w*j)],img[4*(i+w*j)+1],img[4*(i+w*j)+2]); } mgl_printf(fp, gz, "\n>} false 3 colorimage\ngrestore\n\n"); } else if(memcmp(img,white,3)) mgl_printf(fp, gz, "np 0 0 mt 0 %d ll %d %d ll %d 0 ll cp %g %g %g rgb fill\n", y2-y1, x2-x1, y2-y1, x2-x1, img[0]/255., img[1]/255., img[2]/255.); // write definition for all glyphs put_desc(gr,fp,gz,"/%c%c_%04x { np\n", "\t%d %d mt ", "%d %d ll ", "cp\n", "} def\n"); // write primitives mreal wp=-1; float qs_old=gr->mark_size()/gr->FontFactor(); mglRGBA cp; int st=0; char str[256]="", msk[256]=""; for(long i=0;iGetPrmNum();i++) { const mglPrim &q = gr->GetPrm(i); if(q.type<0) continue; // q.n1>=0 always cp.c = _Gr_->GetPrmCol(i); const mglPnt &p1 = gr->GetPnt(q.n1); if(q.type>1) { snprintf(str,256,"%.2g %.2g %.2g rgb ", cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); str[255]=0; snprintf(msk,256,"%.2g %.2g %.2g mask ", cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); msk[255]=0; } if(q.type==0) // mark { mreal x0 = p1.x,y0 = p1.y; // snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", 50*q.s*q.w>1?50*q.s*q.w:1, cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1?q.w:1, cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); str[255]=0; wp=1; // NOTE: this may renew line style if a mark inside! if(q.s!=qs_old) { mgl_printf(fp, gz, "/ss {%g} def\n",q.s); mgl_printf(fp, gz, "/s2 {%g} def\n",q.s*2); mgl_printf(fp, gz, "/sm {-%g} def\n",q.s); qs_old = q.s; } switch(q.n4) { case '+': mgl_printf(fp, gz, "np %g %g mt m_p %sdr\n",x0,y0,str); break; case 'x': mgl_printf(fp, gz, "np %g %g mt m_x %sdr\n",x0,y0,str); break; case 's': mgl_printf(fp, gz, "np %g %g mt m_s %sdr\n",x0,y0,str); break; case 'd': mgl_printf(fp, gz, "np %g %g mt m_d %sdr\n",x0,y0,str); break; case '*': mgl_printf(fp, gz, "np %g %g mt m_a %sdr\n",x0,y0,str); break; case 'v': mgl_printf(fp, gz, "np %g %g mt m_v %sdr\n",x0,y0,str); break; case '^': mgl_printf(fp, gz, "np %g %g mt m_t %sdr\n",x0,y0,str); break; case 'S': mgl_printf(fp, gz, "np %g %g mt m_S %sfill\n",x0,y0,str); break; case 'D': mgl_printf(fp, gz, "np %g %g mt m_D %sfill\n",x0,y0,str); break; case 'V': mgl_printf(fp, gz, "np %g %g mt m_V %sfill\n",x0,y0,str); break; case 'T': mgl_printf(fp, gz, "np %g %g mt m_T %sfill\n",x0,y0,str); break; case 'o': mgl_printf(fp, gz, "%g %g m_o %sdr\n",x0,y0,str);break; case 'O': mgl_printf(fp, gz, "%g %g m_o %sfill\n",x0,y0,str);break; case 'Y': mgl_printf(fp, gz, "np %g %g mt m_Y %sdr\n",x0,y0,str); break; case '<': mgl_printf(fp, gz, "np %g %g mt m_l %sdr\n",x0,y0,str); break; case '>': mgl_printf(fp, gz, "np %g %g mt m_r %sdr\n",x0,y0,str); break; case 'L': mgl_printf(fp, gz, "np %g %g mt m_L %sfill\n",x0,y0,str); break; case 'R': mgl_printf(fp, gz, "np %g %g mt m_R %sfill\n",x0,y0,str); break; case 'P': mgl_printf(fp, gz, "np %g %g mt m_P %sdr\n",x0,y0,str); break; case 'X': mgl_printf(fp, gz, "np %g %g mt m_X %sdr\n",x0,y0,str); break; case 'C': mgl_printf(fp, gz, "%g %g m_o %g %g m_c %sdr\n",x0,y0,x0,y0,str); break; case '.': mgl_printf(fp, gz, "%g %g m_c %sfill\n",x0,y0,str); } } else if(q.type==3) // quad { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4); if(cp.r[3]) // TODO && gr->quad_vis(p1,p2,p3,p4)) { bool mask = mgl_eps_pattern(fp,gz,q); mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp %sfill\n", p1.x, p1.y, p2.x, p2.y, p4.x, p4.y, p3.x, p3.y, mask?msk:str); } } else if(q.type==2) // trig { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3); if(cp.r[3]) // TODO && gr->trig_vis(p1,p2,p3)) { bool mask = mgl_eps_pattern(fp,gz,q); mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll cp %sfill\n", p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, mask?msk:str); } } else if(q.type==1) // line { snprintf(str,256,"%.2g lw %.2g %.2g %.2g rgb ", q.w>1 ? q.w:1., cp.r[0]/255.,cp.r[1]/255.,cp.r[2]/255.); str[255]=0; wp = q.w>1 ? q.w:1; st = q.n3; std::vector ids = put_line(gr,i,wp,cp.c,st); for(size_t j=0;jGetPnt(ids[j]); float x0 = p.x, y0 = p.y; mgl_printf(fp, gz, j==0?"np %g %g mt ":"%g %g ll ",x0,y0); } const char *sd = mgl_get_dash(q.n3,q.w,' '); if(sd && sd[0]) mgl_printf(fp, gz, "%s [%s] %g sd dr\n",str,sd,q.w*q.s); else mgl_printf(fp, gz, "%s d0 dr\n",str); } else if(q.type==4) // glyph { float phi = gr->GetGlyphPhi(gr->GetPnt(q.n2),q.w); if(mgl_isnan(phi)) continue; mreal ss = q.s/2, xx = p1.u, yy = p1.v, zz = q.p; mgl_printf(fp, gz, "gsave\t%g %g translate %g %g scale %g rotate %s\n", p1.x, p1.y, ss, ss, -phi, str); if(q.n3&8) // this is "line" { mreal dy = 0.004,f=fabs(zz); mgl_printf(fp, gz, "np %g %g mt %g %g ll %g %g ll %g %g ll cp ", xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy); } else mgl_printf(fp, gz, "%.3g %.3g translate %g %g scale %c%c_%04x ", xx, yy, zz, zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4); if(q.n3&4) mgl_printf(fp, gz, "dr"); else mgl_printf(fp, gz, "eofill"); mgl_printf(fp, gz, " grestore\n"); } } for(long i=0;iGetPrmNum();i++) { mglPrim &q = gr->GetPrm(i); if(q.type==-1) q.type = 1; } mgl_printf(fp, gz, "\nshowpage\n%%%%EOF\n"); if(strcmp(fname,"-")) { if(gz) gzclose((gzFile)fp); else fclose((FILE *)fp); } setlocale(LC_NUMERIC, loc.c_str()); } void MGL_EXPORT mgl_write_eps_(uintptr_t *gr, const char *fname,const char *descr,int l,int n) { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0; char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0; mgl_write_eps(_GR_,s,d); delete []s; delete []d; } //----------------------------------------------------------------------------- void MGL_EXPORT mgl_write_svg(HMGL gr, const char *fname,const char *descr) { if(!fname || *fname==0) return; if(gr->GetPrmNum()<1) return; _Gr_->clr(MGL_FINISHED); _Gr_->PreparePrim(1); time_t now; time(&now); bool gz = fname[strlen(fname)-1]=='z'; long hh = _Gr_->GetHeight(), ww = _Gr_->GetWidth(); void *fp = stdout; // allow to write in stdout bool head = true; if(strcmp(fname,"-")) fp = gz ? (void*)gzopen(fname,"wt") : (void*)fopen(fname,"wt"); else head = false; if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; } int x1=gr->BBoxX1, x2=gr->BBoxX2<0?ww:gr->BBoxX2, y1=gr->BBoxY1, y2=gr->BBoxY2<0?hh:gr->BBoxY2; if(x2>ww) x2=ww; if(y2>hh) y2=hh; if(x1<0 || x1>=x2) { x1=0; x2=ww; } if(y1<0 || y1>=y2) { y1=0; y2=hh; } ww = x2-x1; hh = y2-y1; const std::string loc = setlocale(LC_NUMERIC, "C"); if(head) { mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "\n", ww, hh); mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "\n\n\n",descr?descr:fname,ctime(&now)); } else { mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "\n", ww, hh); } // write definition for all glyphs put_desc(gr,fp,gz,"\n"); // Write background image first const unsigned char *img = mgl_get_background(gr); bool same = true; unsigned char white[3]={255,255,255}; #pragma omp parallel for for(long i=0;i /* mgl_printf(fp, gz, "%d %d 8 [1 0 0 1 0 0] {<", ww,hh,1+ww*hh/40); for(long j=hh-1;j>=0;j--) for(long i=0;i0) mgl_printf(fp, gz, "\n"); mgl_printf(fp, gz, "%02x%02x%02x",img[4*(i+ww*j)],img[4*(i+ww*j)+1],img[4*(i+ww*j)+2]); } mgl_printf(fp, gz, "\n>} false 3 colorimage\n\n");*/ } else if(memcmp(img,white,3)) { mgl_printf(fp, gz, "\n", img[0], img[1], img[2], img[3]/255.); mgl_printf(fp, gz, " \n", hh, ww, hh, ww); } // currentColor -> inherit ??? mgl_printf(fp, gz, "\n"); // write primitives mreal wp=-1; int st=0; mglRGBA cp; // hh += (y2+y1)/2; for(long i=0;iGetPrmNum();i++) { const mglPrim &q = gr->GetPrm(i); if(q.type<0) continue; // q.n1>=0 always cp.c = _Gr_->GetPrmCol(i); const mglPnt &p1=gr->GetPnt(q.n1); if(q.type==0) { mreal x=p1.x-x1,y=hh-p1.y,s=q.s; if(!strchr("xsSoO",q.n4)) s *= 1.1; wp = 1; if(strchr("SDVTLR",q.n4)) mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2])); else mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]), q.w>1?q.w:1); // mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]), 50*q.s*q.w>1?50*q.s*q.w:1); switch(q.n4) { case 'P': mgl_printf(fp, gz, "\n", x-s,y,x+s,y,x,y-s,x,y+s, x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s,x-s,y-s); break; case '+': mgl_printf(fp, gz, "\n", x-s,y,x+s,y,x,y-s,x,y+s); break; case 'X': mgl_printf(fp, gz, "\n", x-s,y-s,x+s,y+s,x+s,y-s,x-s,y+s, x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s,x-s,y-s); break; case 'x': mgl_printf(fp, gz, "\n", x-s,y-s,x+s,y+s,x+s,y-s,x-s,y+s); break; case 's': case 'S': mgl_printf(fp, gz, "\n", x-s,y-s,x+s,y-s,x+s,y+s,x-s,y+s); break; case 'd': case 'D': mgl_printf(fp, gz, "\n", x-s,y,x,y-s,x+s,y,x,y+s); break; case 'v': case 'V': mgl_printf(fp, gz, "\n", x-s,y-s/2,x+s,y-s/2,x,y+s); break; case '^': case 'T': mgl_printf(fp, gz, "\n", x-s,y+s/2,x+s,y+s/2,x,y-s); break; case '<': case 'L': mgl_printf(fp, gz, "\n", x+s/2,y+s,x+s/2,y-s,x-s,y); break; case '>': case 'R': mgl_printf(fp, gz, "\n", x-s/2,y+s,x-s/2,y-s,x+s,y); break; case 'Y': mgl_printf(fp, gz, "\n", x,y-s, x,y, x+s,y+s, x,y, x-s,y+s); break; case 'C': mgl_printf(fp, gz, "\n\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y,x,y,s); break; case 'o': mgl_printf(fp, gz, "\n", x,y,s); break; case 'O': mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y,s); break; case '*': mgl_printf(fp, gz, "\n", x-s,y,x+s,y,x-0.6*s,y-0.8*s,x+0.6*s,y+0.8*s,x+0.6*s,y-0.8*s,x-0.6*s,y+0.8*s); break; case '.': mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),x,y); break; } mgl_printf(fp, gz, "\n"); } else if(q.type==1) { mgl_printf(fp,gz,"1) mgl_printf(fp, gz, " stroke-width=\"%g\"", q.w); wp = q.w>1 ? q.w:1; st = q.n3; std::vector ids = put_line(gr,i,wp,cp.c,st); for(size_t j=0;jGetPnt(ids[j]); mgl_printf(fp, gz, j==0?"> \n"); } else if(q.type==2 && cp.r[3]) { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3); mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.); mgl_printf(fp, gz, " \n", p1.x-x1, hh-p1.y, p2.x-x1, hh-p2.y, p3.x-x1, hh-p3.y); } else if(q.type==3 && cp.r[3]) { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4); mgl_printf(fp, gz, "\n", int(cp.r[0]),int(cp.r[1]),int(cp.r[2]),cp.r[3]/255.); mgl_printf(fp, gz, " \n", p1.x-x1, hh-p1.y, p2.x-x1, hh-p2.y, p4.x-x1, hh-p4.y, p3.x-x1, hh-p3.y); } else if(q.type==4) { float phi = gr->GetGlyphPhi(gr->GetPnt(q.n2),q.w); if(mgl_isnan(phi)) continue; mreal ss = q.s/2, xx = p1.u, yy = p1.v, zz = q.p; if(q.n3&8) // this is "line" { mgl_printf(fp, gz, "", int(cp.r[0]),int(cp.r[1]),int(cp.r[2])); else mgl_printf(fp, gz, " fill=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2])); mreal dy = 0.004,f=fabs(zz); mgl_printf(fp, gz, "\n", xx,yy+dy, xx+f,yy+dy, xx+f,yy-dy, xx,yy-dy); } else { ss *= zz; mgl_printf(fp, gz, "", int(cp.r[0]),int(cp.r[1]),int(cp.r[2])); else mgl_printf(fp, gz, " fill=\"#%02x%02x%02x\">", int(cp.r[0]),int(cp.r[1]),int(cp.r[2])); mgl_printf(fp, gz, "\n", xx/zz, yy/zz, q.n3&1?'b':'n', q.n3&2?'i':'n', q.n4); } } } for(long i=0;iGetPrmNum();i++) { mglPrim &q=gr->GetPrm(i); if(q.type==-1) q.type = 1; } mgl_printf(fp, gz, ""); if(strcmp(fname,"-")) { if(gz) gzclose((gzFile)fp); else fclose((FILE *)fp); } setlocale(LC_NUMERIC, loc.c_str()); } void MGL_EXPORT mgl_write_svg_(uintptr_t *gr, const char *fname,const char *descr,int l,int n) { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0; char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0; mgl_write_svg(_GR_,s,d); delete []s; delete []d; } //----------------------------------------------------------------------------- void MGL_EXPORT mgl_write_tex(HMGL gr, const char *fname,const char *descr) { if(gr->GetPrmNum()<1) return; _Gr_->clr(MGL_FINISHED); _Gr_->PreparePrim(1); FILE *fp = fopen(fname,"w"); if(!fp) { gr->SetWarn(mglWarnOpen,fname); return; } const std::string loc = setlocale(LC_NUMERIC, "C"); fwide(fp,1); fwprintf(fp, L"%% Created by MathGL library\n%% Title: %s\n\n",descr?descr:fname); // provide marks fwprintf(fp, L"\\providecommand{\\mglp}[4]{\\draw[#3] (#1-#4, #2) -- (#1+#4,#2) (#1,#2-#4) -- (#1,#2+#4);}\n"); fwprintf(fp, L"\\providecommand{\\mglx}[4]{\\draw[#3] (#1-#4, #2-#4) -- (#1+#4,#2+#4) (#1+#4,#2-#4) -- (#1-#4,#2+#4);}\n"); fwprintf(fp, L"\\providecommand{\\mgls}[4]{\\draw[#3] (#1-#4, #2-#4) -- (#1+#4,#2-#4) -- (#1+#4,#2+#4) -- (#1-#4,#2+#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglS}[4]{\\fill[#3] (#1-#4, #2-#4) -- (#1+#4,#2-#4) -- (#1+#4,#2+#4) -- (#1-#4,#2+#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mgld}[4]{\\draw[#3] (#1, #2-#4) -- (#1+#4,#2) -- (#1,#2+#4) -- (#1-#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglD}[4]{\\fill[#3] (#1, #2-#4) -- (#1+#4,#2) -- (#1,#2+#4) -- (#1-#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglv}[4]{\\draw[#3] (#1-#4, #2+#4/2) -- (#1+#4,#2+#4/2) -- (#1,#2-#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglV}[4]{\\fill[#3] (#1-#4, #2+#4/2) -- (#1+#4,#2+#4/2) -- (#1,#2-#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglt}[4]{\\draw[#3] (#1-#4, #2-#4/2) -- (#1+#4,#2-#4/2) -- (#1,#2+#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglT}[4]{\\fill[#3] (#1-#4, #2-#4/2) -- (#1+#4,#2-#4/2) -- (#1,#2+#4) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mgll}[4]{\\draw[#3] (#1+#4/2, #2-#4) -- (#1+#4/2,#2+#4) -- (#1-#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglL}[4]{\\fill[#3] (#1+#4/2, #2-#4) -- (#1+#4/2,#2+#4) -- (#1-#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglr}[4]{\\draw[#3] (#1-#4/2, #2-#4) -- (#1-#4/2,#2+#4) -- (#1+#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglR}[4]{\\fill[#3] (#1-#4/2, #2-#4) -- (#1-#4/2,#2+#4) -- (#1+#4,#2) -- cycle;}\n"); fwprintf(fp, L"\\providecommand{\\mglR}[4]{\\draw[#3] (#1, #2-#4) -- (#1,#2) -- (#1-#4,#2+#4) (#1,#2) -- (#1+#4,#2+#4);}\n"); fwprintf(fp, L"\\providecommand{\\mgla}[4]{\\draw[#3] (#1-#4, #2) -- (#1+#4,#2) (#1-0.6*#4,#2-0.8*#4) -- (#1+0.6*#4,#2+0.8*#4) (#1-0.6*#4,#2+0.8*#4) -- (#1+0.6*#4,#2-0.8*#4);}\n"); fwprintf(fp, L"\\providecommand{\\mglY}[4]{\\draw[#3] (#1, #2-#4) -- (#1,#2) (#1-#4,#2+#4) -- (#1,#2) (#1+#4,#2+#4) -- (#1,#2);}\n"); fwprintf(fp, L"\\providecommand{\\mglo}[4]{\\draw[#3] (#1, #2) circle (#4);}\n"); fwprintf(fp, L"\\providecommand{\\mglO}[4]{\\fill[#3] (#1, #2) circle (#4);}\n"); fwprintf(fp, L"\\providecommand{\\mglc}[3]{\\draw[#3] (#1, #2) circle (%g);}\n\n", 4e-4*gr->mark_size()); fwprintf(fp, L"\\begin{tikzpicture}\n"); // write primitives first mreal wp=-1; int st=0; mglRGBA cp; char cname[128]; for(long i=0;iGetPrmNum();i++) { const mglPrim &q = gr->GetPrm(i); if(q.type<0) continue; // q.n1>=0 always cp.c = _Gr_->GetPrmCol(i); snprintf(cname,128,"color={rgb,255:red,%d;green,%d;blue,%d}",cp.r[0],cp.r[1],cp.r[2]); cname[127]=0; const mglPnt &p1=gr->GetPnt(q.n1); mreal x=p1.x/100,y=p1.y/100,s=q.s/100; if(q.type==0) { if(!strchr("xsSoO",q.n4)) s *= 1.1; wp = 1; switch(q.n4) // NOTE: no thickness for marks in TeX { case 'P': fwprintf(fp, L"\\mglp{%.4g}{%.4g}{%s}{%.4g} \\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s); break; case 'X': fwprintf(fp, L"\\mglx{%.4g}{%.4g}{%s}{%.4g} \\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s); break; case 'C': fwprintf(fp, L"\\mglc{%.4g}{%.4g}{%s}{%.4g} \\mglo{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s,x,y,cname,s); break; case '+': fwprintf(fp, L"\\mglp{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'x': fwprintf(fp, L"\\mglx{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 's': fwprintf(fp, L"\\mgls{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'S': fwprintf(fp, L"\\mglS{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'd': fwprintf(fp, L"\\mgld{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'D': fwprintf(fp, L"\\mglD{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case '^': fwprintf(fp, L"\\mglt{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'T': fwprintf(fp, L"\\mglT{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'v': fwprintf(fp, L"\\mglv{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'V': fwprintf(fp, L"\\mglV{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case '<': fwprintf(fp, L"\\mgll{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'L': fwprintf(fp, L"\\mglL{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case '>': fwprintf(fp, L"\\mglr{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'R': fwprintf(fp, L"\\mglR{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'Y': fwprintf(fp, L"\\mglY{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'o': fwprintf(fp, L"\\mglo{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case 'O': fwprintf(fp, L"\\mglO{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; case '*': fwprintf(fp, L"\\mgla{%.4g}{%.4g}{%s}{%.4g}\n", x,y,cname,s); break; default: fwprintf(fp, L"\\mglc{%.4g}{%.4g}{%s}\n", x,y,cname); break; } } else if(q.type==2 && cp.r[3]) { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3); if(cp.r[3]<255) fwprintf(fp, L"\\fill[%s, fill opacity=%.4g] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname,cp.r[3]/255., x,y, p2.x/100,p2.y/100, p3.x/100,p3.y/100); else fwprintf(fp, L"\\fill[%s, fill] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname, x,y, p2.x/100,p2.y/100, p3.x/100,p3.y/100); } else if(q.type==3 && cp.r[3]) { const mglPnt &p2=gr->GetPnt(q.n2), &p3=gr->GetPnt(q.n3), &p4=gr->GetPnt(q.n4); if(cp.r[3]<255) fwprintf(fp, L"\\fill[%s, fill opacity=%.4g] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname,cp.r[3]/255., x,y, p2.x/100,p2.y/100, p4.x/100,p4.y/100, p3.x/100,p3.y/100); else fwprintf(fp, L"\\fill[%s, fill] (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- (%.4g,%.4g) -- cycle;\n", cname, x,y, p2.x/100,p2.y/100, p4.x/100,p4.y/100, p3.x/100,p3.y/100); } else if(q.type==1) // lines { //const char *dash[]={"", "8 8","4 4","1 3","7 4 1 4","3 2 1 2"}; const char *w[]={"semithick","thick","very thick","ultra thick"}; int iw=int(q.w-0.5); if(iw>3) iw=3; if(iw<0) fwprintf(fp,L"\\draw[%s] ",cname); else fwprintf(fp,L"\\draw[%s,%s] ",cname,w[iw]); // TODO: add line dashing wp = q.w>1 ? q.w:1; st = q.n3; std::vector ids = put_line(gr,i,wp,cp.c,st); for(size_t j=0;jGetPnt(ids[j]); float x0 = p.x, y0 = p.y; fwprintf(fp, j==0?L"(%.4g,%.4g)":L" -- (%.4g,%.4g)",0.01*x0,y0*0.01); } fwprintf(fp, L";\n"); } else if(q.type==6 && mgl_isnum(q.p)) // text { const mglText &t = gr->GetPtx(q.n3); mreal dy = q.w*cos(q.p*M_PI/180)/100, dx = q.w*sin(q.p*M_PI/180)/100; int f,a; mglGetStyle(t.stl.c_str(), &f, &a); std::string ss=cname; if((a&3)==0) ss.append(",anchor=base west"); if((a&3)==1) ss.append(",anchor=base"); if((a&3)==2) ss.append(",anchor=base east"); // if(f&MGL_FONT_ITAL) ss.append(",font=\\itshape"); // if(f&MGL_FONT_BOLD) ss.append(",font=\\bfshape"); if(t.text.find('\\')!=std::string::npos || t.text.find('{')!=std::string::npos || t.text.find('_')!=std::string::npos || t.text.find('^')!=std::string::npos) fwprintf(fp,L"\\draw[%s] (%.4g,%.4g) node[rotate=%.2g]{$%ls$};\n", ss.c_str(),x-dx,y-dy, -q.p, t.text.c_str()); else fwprintf(fp,L"\\draw[%s] (%.4g,%.4g) node[rotate=%.2g]{%ls};\n", ss.c_str(),x-dx,y-dy, -q.p, t.text.c_str()); } } fwprintf(fp, L"\\end{tikzpicture}\n"); for(long i=0;iGetPrmNum();i++) { mglPrim &q=gr->GetPrm(i); if(q.type==-1) q.type = 1; } fclose(fp); setlocale(LC_NUMERIC, loc.c_str()); // provide main file for viewing figure fp=fopen("mglmain.tex","wt"); if(fp) { fprintf(fp, "%% this file just show figure\n"); fprintf(fp, "\\documentclass{article}\n\\usepackage{tikz}\n"); fprintf(fp, "\\usepackage[T2A]{fontenc}\n\\usepackage[utf8]{inputenc}\n"); fprintf(fp, "\\begin{document}\n\\input{%s}\n\\end{document}\n",fname); fclose(fp); } } void MGL_EXPORT mgl_write_tex_(uintptr_t *gr, const char *fname,const char *descr,int l,int n) { char *s=new char[l+1]; memcpy(s,fname,l); s[l]=0; char *d=new char[n+1]; memcpy(d,descr,n); d[n]=0; mgl_write_tex(_GR_,s,d); delete []s; delete []d; } //-----------------------------------------------------------------------------