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