xref: /petsc/src/sys/classes/draw/impls/tikz/tikz.c (revision 4fc747eaadbeca11629f314a99edccbc2ed7b3d3)
1 /*
2     Defines the operations for the TikZ PetscDraw implementation.
3 */
4 
5 #include <petsc/private/drawimpl.h>         /*I  "petscsys.h" I*/
6 
7 typedef struct {
8   char      *filename;
9   FILE      *fd;
10   PetscBool written;  /* something has been written to the current frame */
11 } PetscDraw_TikZ;
12 
13 #define TikZ_BEGIN_DOCUMENT  "\\documentclass{beamer}\n\n\
14 \\usepackage{tikz}\n\
15 \\usepackage{pgflibraryshapes}\n\
16 \\usetikzlibrary{backgrounds}\n\
17 \\usetikzlibrary{arrows}\n\
18 \\newenvironment{changemargin}[2]{%%\n\
19   \\begin{list}{}{%%\n\
20     \\setlength{\\topsep}{0pt}%%\n\
21     \\setlength{\\leftmargin}{#1}%%\n\
22     \\setlength{\\rightmargin}{#2}%%\n\
23     \\setlength{\\listparindent}{\\parindent}%%\n\
24     \\setlength{\\itemindent}{\\parindent}%%\n\
25     \\setlength{\\parsep}{\\parskip}%%\n\
26   }%%\n\
27   \\item[]}{\\end{list}}\n\n\
28 \\begin{document}\n"
29 
30 #define TikZ_BEGIN_FRAME "\\begin{frame}{}\n\
31 \\begin{changemargin}{-1cm}{0cm}\n\
32 \\begin{center}\n\
33 \\begin{tikzpicture}[scale = 10.00,font=\\fontsize{8}{8}\\selectfont]\n"
34 
35 #define TikZ_END_FRAME "\\end{tikzpicture}\n\
36 \\end{center}\n\
37 \\end{changemargin}\n\
38 \\end{frame}\n"
39 
40 #define TikZ_END_DOCUMENT  "\\end{document}\n"
41 
42 #undef __FUNCT__
43 #define __FUNCT__ "PetscDrawDestroy_TikZ"
44 static PetscErrorCode  PetscDrawDestroy_TikZ(PetscDraw draw)
45 {
46   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
47   PetscErrorCode ierr;
48 
49   PetscFunctionBegin;
50   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME);CHKERRQ(ierr);
51   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_DOCUMENT);CHKERRQ(ierr);
52   ierr = PetscFClose(PetscObjectComm((PetscObject)draw),win->fd);CHKERRQ(ierr);
53   ierr = PetscFree(win->filename);CHKERRQ(ierr);
54   ierr = PetscFree(draw->data);CHKERRQ(ierr);
55   PetscFunctionReturn(0);
56 }
57 
58 static const char *TikZColors[] = {"white","black","red","green","cyan","blue","magenta",0,0,"orange","violet","brown","pink",0,"yellow",0};
59 
60 PETSC_STATIC_INLINE const char *TikZColorMap(int cl)
61 {
62   return((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
63 }
64 
65 /*
66      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
67 */
68 #define XTRANS(draw,x)  (double)(((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
69 #define YTRANS(draw,y)  (double)(((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
70 
71 #undef __FUNCT__
72 #define __FUNCT__ "PetscDrawClear_TikZ"
73 static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
74 {
75   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
76   PetscBool      written;
77   PetscErrorCode ierr;
78 
79   PetscFunctionBegin;
80   /* often PETSc generates unneeded clears, we want avoid creating empy pictures for them */
81   ierr = MPI_Allreduce(&win->written,&written,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)(draw)));CHKERRQ(ierr);
82   if (!written) PetscFunctionReturn(0);
83   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME);CHKERRQ(ierr);
84   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
85   win->written = PETSC_FALSE;
86   PetscFunctionReturn(0);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "PetscDrawLine_TikZ"
91 static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
92 {
93   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
94   PetscErrorCode ierr;
95 
96   PetscFunctionBegin;
97   win->written = PETSC_TRUE;
98   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\draw [%s] (%g,%g) --(%g,%g);\n",TikZColorMap(cl),XTRANS(draw,xl),YTRANS(draw,yl),XTRANS(draw,xr),YTRANS(draw,yr));CHKERRQ(ierr);
99   PetscFunctionReturn(0);
100 }
101 
102 #undef __FUNCT__
103 #define __FUNCT__ "PetscDrawString_TikZ"
104 static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
105 {
106   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
107   PetscErrorCode ierr;
108 
109   PetscFunctionBegin;
110   win->written = PETSC_TRUE;
111   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\node [above right, %s] at (%g,%g) {%s};\n",TikZColorMap(cl),XTRANS(draw,xl),YTRANS(draw,yl),text);CHKERRQ(ierr);
112   PetscFunctionReturn(0);
113 }
114 
115 #undef __FUNCT__
116 #define __FUNCT__ "PetscDrawStringVertical_TikZ"
117 static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
118 {
119   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
120   PetscErrorCode ierr;
121   size_t         len;
122   PetscReal      width;
123 
124   PetscFunctionBegin;
125   win->written = PETSC_TRUE;
126   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
127   ierr = PetscDrawStringGetSize(draw,&width,NULL);CHKERRQ(ierr);
128   yl   = yl - len*width*(draw->coor_yr - draw->coor_yl)/(draw->coor_xr - draw->coor_xl);
129   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\node [rotate=90, %s] at (%g,%g) {%s};\n",TikZColorMap(cl),XTRANS(draw,xl),YTRANS(draw,yl),text);CHKERRQ(ierr);
130   PetscFunctionReturn(0);
131 }
132 
133 #undef __FUNCT__
134 #define __FUNCT__ "PetscDrawStringBoxed_TikZ"
135 /*
136     Does not handle multiline strings correctly
137 */
138 static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,int ct,const char text[],PetscReal *w,PetscReal *h)
139 {
140   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
141   PetscErrorCode ierr;
142   size_t         len;
143 
144   PetscFunctionBegin;
145   win->written = PETSC_TRUE;
146   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,"\\draw (%g,%g) node [rectangle, draw, align=center, inner sep=1ex] {%s};\n",XTRANS(draw,xl),YTRANS(draw,yl),text);CHKERRQ(ierr);
147 
148   /* make up totally bogus height and width of box */
149   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
150   if (w) *w = .07*len;
151   if (h) *h = .07;
152   PetscFunctionReturn(0);
153 }
154 
155 #undef __FUNCT__
156 #define __FUNCT__ "PetscDrawStringGetSize_TikZ"
157 static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw,PetscReal *x,PetscReal  *y)
158 {
159   PetscFunctionBegin;
160   if (x) *x = .014*(draw->coor_xr - draw->coor_xl)/((draw->port_xr - draw->port_xl));
161   if (y) *y = .05*(draw->coor_yr - draw->coor_yl)/((draw->port_yr - draw->port_yl));
162   PetscFunctionReturn(0);
163 }
164 
165 static struct _PetscDrawOps DvOps = { 0,
166                                       0,
167                                       PetscDrawLine_TikZ,
168                                       0,
169                                       0,
170                                       0,
171                                       0,
172                                       PetscDrawString_TikZ,
173                                       PetscDrawStringVertical_TikZ,
174                                       0,
175                                       PetscDrawStringGetSize_TikZ,
176                                       0,
177                                       PetscDrawClear_TikZ,
178                                       0,
179                                       0,
180                                       0,
181                                       0,
182                                       0,
183                                       0,
184                                       0,
185                                       0,
186                                       0,
187                                       0,
188                                       0,
189                                       PetscDrawDestroy_TikZ,
190                                       0,
191                                       0,
192                                       0,
193                                       0,
194                                       0,
195                                       0,
196                                       0,
197                                       0,
198                                       0,
199                                       0,
200                                       PetscDrawStringBoxed_TikZ};
201 
202 #undef __FUNCT__
203 #define __FUNCT__ "PetscDrawCreate_TikZ"
204 PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
205 {
206   PetscDraw_TikZ *win;
207   PetscErrorCode ierr;
208 
209   PetscFunctionBegin;
210   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
211   ierr = PetscNew(&win);CHKERRQ(ierr);
212   ierr = PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_TikZ));CHKERRQ(ierr);
213 
214   draw->data = (void*) win;
215 
216   if (draw->title) {
217     ierr = PetscStrallocpy(draw->title,&win->filename);CHKERRQ(ierr);
218   } else {
219     const char *fname;
220     ierr = PetscObjectGetName((PetscObject)draw,&fname);CHKERRQ(ierr);
221     ierr = PetscStrallocpy(fname,&win->filename);CHKERRQ(ierr);
222   }
223   ierr = PetscFOpen(PetscObjectComm((PetscObject)draw),win->filename,"w",&win->fd);CHKERRQ(ierr);
224   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_DOCUMENT);CHKERRQ(ierr);
225   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
226 
227   win->written = PETSC_FALSE;
228   PetscFunctionReturn(0);
229 }
230