xref: /petsc/src/sys/classes/draw/impls/tikz/tikz.c (revision 2b8d69ca7ea5fe9190df62c1dce3bbd66fce84dd)
1 /*
2     Defines the operations for the X 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",
59                                     "violet", "brown", "pink", 0,       "yellow", 0};
60 
61 PETSC_STATIC_INLINE const char *TikZColorMap(int cl)
62 {
63   return((cl < 16) ? (TikZColors[cl] ? TikZColors[cl] : "black") : "black");
64 }
65 
66 /*
67      These macros transform from the users coordinates to the (0,0) -> (1,1) coordinate system
68 */
69 #define XTRANS(draw,x)  (double)(((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl))))
70 #define YTRANS(draw,y)  (double)(((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl))))
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "PetscDrawClear_TikZ"
74 static PetscErrorCode PetscDrawClear_TikZ(PetscDraw draw)
75 {
76   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
77   PetscBool      written;
78   PetscErrorCode ierr;
79 
80   PetscFunctionBegin;
81   /* often PETSc generates unneeded clears, we want avoid creating empy pictures for them */
82   ierr = MPI_Allreduce(&win->written,&written,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)(draw)));CHKERRQ(ierr);
83   if (!written) PetscFunctionReturn(0);
84   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_END_FRAME);CHKERRQ(ierr);
85   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
86   win->written = PETSC_FALSE;
87   PetscFunctionReturn(0);
88 }
89 
90 #undef __FUNCT__
91 #define __FUNCT__ "PetscDrawLine_TikZ"
92 static PetscErrorCode PetscDrawLine_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
93 {
94   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
95   PetscErrorCode ierr;
96 
97   PetscFunctionBegin;
98   win->written = PETSC_TRUE;
99   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);
100   PetscFunctionReturn(0);
101 }
102 
103 #undef __FUNCT__
104 #define __FUNCT__ "PetscDrawString_TikZ"
105 static PetscErrorCode PetscDrawString_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
106 {
107   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
108   PetscErrorCode ierr;
109 
110   PetscFunctionBegin;
111   win->written = PETSC_TRUE;
112   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);
113   PetscFunctionReturn(0);
114 }
115 
116 #undef __FUNCT__
117 #define __FUNCT__ "PetscDrawStringVertical_TikZ"
118 static PetscErrorCode PetscDrawStringVertical_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,const char text[])
119 {
120   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
121   PetscErrorCode ierr;
122   size_t         len;
123   PetscReal      width;
124 
125   PetscFunctionBegin;
126   win->written = PETSC_TRUE;
127   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
128   ierr = PetscDrawStringGetSize(draw,&width,NULL);CHKERRQ(ierr);
129   yl   = yl - len*width*(draw->coor_yr - draw->coor_yl)/(draw->coor_xr - draw->coor_xl);
130   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);
131   PetscFunctionReturn(0);
132 }
133 
134 #undef __FUNCT__
135 #define __FUNCT__ "PetscDrawStringBoxed_TikZ"
136 /*
137     Does not handle multiline strings correctly
138 */
139 static PetscErrorCode PetscDrawStringBoxed_TikZ(PetscDraw draw,PetscReal xl,PetscReal yl,int cl,int ct,const char text[],PetscReal *w,PetscReal *h)
140 {
141   PetscDraw_TikZ *win = (PetscDraw_TikZ*)draw->data;
142   PetscErrorCode ierr;
143   size_t         len;
144 
145   PetscFunctionBegin;
146   win->written = PETSC_TRUE;
147   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);
148 
149   /* make up totally bogus height and width of box */
150   ierr = PetscStrlen(text,&len);CHKERRQ(ierr);
151   if (w) *w = .07*len;
152   if (h) *h = .07;
153   PetscFunctionReturn(0);
154 }
155 
156 #undef __FUNCT__
157 #define __FUNCT__ "PetscDrawStringGetSize_TikZ"
158 static PetscErrorCode PetscDrawStringGetSize_TikZ(PetscDraw draw,PetscReal *x,PetscReal  *y)
159 {
160   PetscFunctionBegin;
161   if (x) *x = .014*(draw->coor_xr - draw->coor_xl)/((draw->port_xr - draw->port_xl));
162   if (y) *y = .05*(draw->coor_yr - draw->coor_yl)/((draw->port_yr - draw->port_yl));
163   PetscFunctionReturn(0);
164 }
165 
166 static struct _PetscDrawOps DvOps = { 0,
167                                       0,
168                                       PetscDrawLine_TikZ,
169                                       0,
170                                       0,
171                                       0,
172                                       0,
173                                       PetscDrawString_TikZ,
174                                       PetscDrawStringVertical_TikZ,
175                                       0,
176                                       PetscDrawStringGetSize_TikZ,
177                                       0,
178                                       PetscDrawClear_TikZ,
179                                       0,
180                                       0,
181                                       0,
182                                       0,
183                                       0,
184                                       0,
185                                       0,
186                                       0,
187                                       0,
188                                       0,
189                                       0,
190                                       PetscDrawDestroy_TikZ,
191                                       0,
192                                       0,
193                                       0,
194                                       0,
195                                       0,
196                                       0,
197                                       0,
198                                       0,
199                                       0,
200                                       0,
201                                       PetscDrawStringBoxed_TikZ};
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "PetscDrawCreate_TikZ"
205 PETSC_EXTERN PetscErrorCode PetscDrawCreate_TikZ(PetscDraw draw)
206 {
207   PetscDraw_TikZ *win;
208   PetscErrorCode ierr;
209 
210   PetscFunctionBegin;
211   ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
212   ierr = PetscNew(&win);CHKERRQ(ierr);
213   ierr = PetscLogObjectMemory((PetscObject)draw,sizeof(PetscDraw_TikZ));CHKERRQ(ierr);
214 
215   draw->data = (void*) win;
216 
217   if (draw->title) {
218     ierr = PetscStrallocpy(draw->title,&win->filename);CHKERRQ(ierr);
219   } else {
220     const char *fname;
221     ierr = PetscObjectGetName((PetscObject)draw,&fname);CHKERRQ(ierr);
222     ierr = PetscStrallocpy(fname,&win->filename);CHKERRQ(ierr);
223   }
224   ierr = PetscFOpen(PetscObjectComm((PetscObject)draw),win->filename,"w",&win->fd);CHKERRQ(ierr);
225   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_DOCUMENT);CHKERRQ(ierr);
226   ierr = PetscFPrintf(PetscObjectComm((PetscObject)draw),win->fd,TikZ_BEGIN_FRAME);CHKERRQ(ierr);
227 
228   win->written = PETSC_FALSE;
229   PetscFunctionReturn(0);
230 }
231