1 // showmathdemo.cpp Copyright (C) Codemist 2013-2020
2
3 // Demonstrate display of mathematical formulae...
4
5 /**************************************************************************
6 * Copyright (C) 2020, Codemist. A C Norman *
7 * *
8 * Redistribution and use in source and binary forms, with or without *
9 * modification, are permitted provided that the following conditions are *
10 * met: *
11 * *
12 * * Redistributions of source code must retain the relevant *
13 * copyright notice, this list of conditions and the following *
14 * disclaimer. *
15 * * Redistributions in binary form must reproduce the above *
16 * copyright notice, this list of conditions and the following *
17 * disclaimer in the documentation and/or other materials provided *
18 * with the distribution. *
19 * *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
24 * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
29 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
31 * DAMAGE. *
32 *************************************************************************/
33
34
35 /* $Id: showmathdemo.cpp 5433 2020-10-15 21:09:02Z arthurcnorman $ */
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #else
40 #define HAVE_LIBFOX 1
41 #endif
42
43 #ifndef HAVE_LIBFOX
44
45 #include <cstdio>
46
main(int argc,char * argv[])47 int main(int argc, char *argv[])
48 { std::printf("FOX library not detected and so this demo is unavailable\n");
49 return 0;
50 }
51
52 #else
53
54 #include <cctype>
55 #include <cstring>
56 #include <cstdio>
57
58 #ifndef WIN32
59 #ifdef HAVE_LIBXFT
60 #include <X11/Xft/Xft.h>
61 #else
62 #error The code needs Xft on non-Windows platforms
63 #endif
64 #endif
65
66 #include "fx.h"
67 #include "fwin.h"
68
69 #include "FXShowMath.h"
70
71 extern int main(int argc,char *argv[]);
72
73 #ifdef HAVE_LIBXFT
74
75 namespace FX
76 {
77 extern XftDraw *ftDraw;
78 extern XftColor ftBlack;
79 extern XftFont *ftFont;
80 }
81
82 extern Display *dpy;
83 extern int screen;
84 extern XftDraw *FX::ftDraw;
85 extern Visual *ftVisual;
86 extern Colormap ftColormap;
87 extern XftColor FX::ftBlack;
88 extern FcConfig *config;
89 extern XftFont *FX::ftFont;
90
91 #endif
92
93 using namespace FX;
94
95 // At least for testing purposes I will extract the LaTeX-like stuff
96 // from a string...
97
98 static const char *TeXInput;
99
nextChar()100 static int nextChar()
101 { return *TeXInput++;
102 }
103
104
105 ///////////////////////////////////////////////////////////////////////////
106
107 // Now a small framework that displays a window and paints a box structure
108 // in it.
109
110 class MathWindow : public FXMainWindow
111 {
112
113 FXDECLARE(MathWindow)
114
115 private:
116 FXApp *app;
117
118 protected:
MathWindow()119 MathWindow() {}
120 ~MathWindow();
121
122 public:
123 FXCanvas *canvas;
124 long onPaint(FXObject *, FXSelector, void *);
125 MathWindow(FXApp* a);
126 virtual void create();
127 enum
128 { ID_CANVAS = FXMainWindow::ID_LAST,
129 ID_LAST
130 };
131 };
132
133
134
135 FXDEFMAP(MathWindow) MathWindowMap[] =
136 { FXMAPFUNC(SEL_PAINT, MathWindow::ID_CANVAS, MathWindow::onPaint),
137 };
138
FXIMPLEMENT(MathWindow,FXMainWindow,MathWindowMap,ARRAYNUMBER (MathWindowMap))139 FXIMPLEMENT(MathWindow,FXMainWindow,MathWindowMap,
140 ARRAYNUMBER(MathWindowMap))
141
142
143 MathWindow::MathWindow(FXApp *a)
144 :FXMainWindow(a,"ShowMathDemo",nullptr,nullptr,DECOR_ALL,100,100,550,
145 600)
146 { canvas=new FXCanvas(this,this,ID_CANVAS,
147 FRAME_SUNKEN|FRAME_THICK|LAYOUT_FILL_X|LAYOUT_FILL_Y|
148 LAYOUT_FILL_ROW|LAYOUT_FILL_COLUMN);
149 app = a;
150 }
151
~MathWindow()152 MathWindow::~MathWindow()
153 { closeShowMath(app);
154 }
155
create()156 void MathWindow::create()
157 { FXMainWindow::create();
158 show(PLACEMENT_SCREEN);
159 }
160
161 static Box *topBox = nullptr;
162
163 static int fontFace = 2;
164
onPaint(FXObject *,FXSelector,void * ptr)165 long MathWindow::onPaint(FXObject *, FXSelector, void *ptr)
166 { FXEvent *ev = (FXEvent*)ptr;
167 FXDCWindow dc(canvas, ev);
168 dc.setForeground(canvas->getBackColor());
169 dc.fillRectangle(ev->rect.x, ev->rect.y, ev->rect.w, ev->rect.h);
170 dc.setForeground(FXRGB(80, 20, 0));
171
172 #ifndef WIN32
173 ftFont = (XftFont *)mathFont[fontFace];
174 #endif
175 dc.setFont((FXFont *)mathFont[fontFace]);
176 int i, j;
177 for (i=0; i<256; i+=16)
178 { for (j=0; j<16; j++)
179 {
180 #ifdef WIN32
181 char bb[4];
182 bb[0] = i+j;
183 dc.drawText(32*j+25, (71*i)/50+220, bb, 1);
184 #else
185 FT_UInt bbb[1];
186 bbb[0] = i+j+1;
187 XftDrawGlyphs(ftDraw, &ftBlack, ftFont,
188 32*j+25, (71*i)/50+220, bbb, 1);
189 #endif
190 }
191 }
192 paintBox(&dc, topBox,
193 (550 - topBox->text.width)/2,
194 topBox->text.height + 10);
195 return 1;
196 }
197
198
199 ///////////////////////////////////////////////////////////////////////////
200
201
202 // The main program just sets things up and runs the demo.
203
204 // Some test data.
205
206 static const char *testData[] =
207 { "\\begin{center}$\\displaystyle x \\not \\equiv y $\\end{center}",
208
209 "\\begin{center}$\\displaystyle x_2$\\end{center}",
210
211 "\\begin{center}$\\displaystyle x+\\mathrm{100}$\\end{center}",
212
213 "\\begin{center}$\\displaystyle x^4-\\mathrm{12}\\*x^3+\\mathrm{54}\\*x^2"
214 "-\\mathrm{108}\\*x+\\mathrm{81}$\\end{center}",
215
216 "\\begin{center}$\\displaystyle x^{\\mathrm{30}}+\\mathrm{30}\\*x^{"
217 "\\mathrm{29}}+\\mathrm{435}\\*x^{\\mathrm{28}}+\\mathrm{4060}\\*x^{\\mathrm{27}}+"
218 "\\mathrm{27405}\\*x^{\\mathrm{26}}+\\mathrm{142506}\\*x^{\\mathrm{25}}+\\mathrm{593775}"
219 "\\*x^{\\mathrm{24}}+\\mathrm{2035800}\\*x^{\\mathrm{23}}+\\mathrm{5852925}\\*x^{"
220 "\\mathrm{22}}+$\\end{center}",
221
222 "\\begin{center}$\\displaystyle \\mathrm{14307150}\\*x^{\\mathrm{21}}+"
223 "\\mathrm{30045015}\\*x^{\\mathrm{20}}+\\mathrm{54627300}\\*x^{\\mathrm{19}}+\\mathrm{86"
224 "493225}\\*x^{\\mathrm{18}}+\\mathrm{119759850}\\*x^{\\mathrm{17}}+\\mathrm{145422675}"
225 "\\*x^{\\mathrm{16}}+$\\end{center}",
226
227 "\\begin{center}$\\displaystyle \\sin\\left(y\\right)$\\end{center}",
228
229 "\\begin{center}$\\displaystyle \\sqrt{-x+1}$\\end{center}",
230
231 "\\begin{center}$\\displaystyle \\left(\\frac{x+1}{x-1}\\right)$\\end{center}",
232
233 "\\begin{center}$\\displaystyle \\pi$\\end{center}",
234
235 "\\begin{center}$\\displaystyle e^z$\\end{center}",
236
237 "\\begin{center}$\\displaystyle e^{i\\*\\theta}$\\end{center}",
238
239 "\\begin{center}$\\displaystyle \\left(\\begin{matrix} \\sin \\left(1\\right) & x_2+\\Theta^2 \\\\"
240 "\\frac{\\exists x : x < 2}{3-z_2} & \\gamma"
241 "\\end{matrix}\\right\\}$\\end{center}",
242
243 "\\begin{center}$\\displaystyle \\int 2^{e^{e^x}}\\,d\\,x$\\end{center}",
244
245 "\\begin{center}$\\displaystyle b!$\\end{center}",
246
247 "\\begin{center}$\\displaystyle a \\not\\equiv b$\\end{center}",
248
249 nullptr
250 };
251
252
main(int argc,char * argv[])253 int main(int argc,char *argv[])
254 { int example = 0;
255 int fontSize = 160;
256 fontFace = 2;
257
258 FXApp application("ShowMath", "Test");
259 application.init(argc, argv);
260
261 find_program_directory(argv[0]);
262
263 int whichArg = 0;
264 argv++;
265
266 while (argc-- > 1)
267 { const char *a = *argv++;
268 unsigned int n = std::atoi(a);
269 switch (whichArg++)
270 { case 0:
271 if (n < sizeof(testData)/sizeof(testData[0])) example = n;
272 break;
273 case 1:
274 if (n == 0) n = 280;
275 while (n < 50) n = n*10;
276 while (n >= 500) n = n/10;
277 fontSize = n;
278 break;
279 case 2:
280 if (n<12) fontFace = n;
281 else fontFace = 2;
282 break;
283 default:
284 break;
285 }
286 }
287
288 int mainSize = fontSize;
289 MathWindow *w = new MathWindow(&application);
290
291 application.create();
292
293 setupShowMath(&application, mainSize, w->canvas);
294
295 TeXInput = testData[example];
296
297 topBox = parseTeX(nextChar, 0);
298
299 if (topBox == nullptr)
300 { std::printf("Failed to parse this example\n");
301 std::exit(1);
302 }
303
304 measureBox(topBox);
305
306 return application.run();
307 }
308
309 #endif /* HAVE_LIBFOX */
310
311 // end of showmathdemo.cpp
312