Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.Problems.GaussianProcessTuning/ILNumerics.2.14.4735.573/Drawing/Labeling/ILSimpleTexInterpreter.cs @ 9426

Last change on this file since 9426 was 9102, checked in by gkronber, 12 years ago

#1967: ILNumerics source for experimentation

File size: 26.4 KB
Line 
1///
2///    This file is part of ILNumerics Community Edition.
3///
4///    ILNumerics Community Edition - high performance computing for applications.
5///    Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net
6///
7///    ILNumerics Community Edition is free software: you can redistribute it and/or modify
8///    it under the terms of the GNU General Public License version 3 as published by
9///    the Free Software Foundation.
10///
11///    ILNumerics Community Edition is distributed in the hope that it will be useful,
12///    but WITHOUT ANY WARRANTY; without even the implied warranty of
13///    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14///    GNU General Public License for more details.
15///
16///    You should have received a copy of the GNU General Public License
17///    along with ILNumerics Community Edition. See the file License.txt in the root
18///    of your distribution package. If not, see <http://www.gnu.org/licenses/>.
19///
20///    In addition this software uses the following components and/or licenses:
21///
22///    =================================================================================
23///    The Open Toolkit Library License
24///   
25///    Copyright (c) 2006 - 2009 the Open Toolkit library.
26///   
27///    Permission is hereby granted, free of charge, to any person obtaining a copy
28///    of this software and associated documentation files (the "Software"), to deal
29///    in the Software without restriction, including without limitation the rights to
30///    use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
31///    the Software, and to permit persons to whom the Software is furnished to do
32///    so, subject to the following conditions:
33///
34///    The above copyright notice and this permission notice shall be included in all
35///    copies or substantial portions of the Software.
36///
37///    =================================================================================
38///   
39
40using System;
41using System.Text;
42using System.Drawing;
43using System.Collections.Generic;
44using ILNumerics.Drawing;
45using ILNumerics.Drawing.Interfaces;
46
47namespace ILNumerics.Drawing.Labeling {
48    /// <summary>
49    /// Simple, (partial) tex symbol interpreter
50    /// </summary>
51    /// <remarks>this is the default interpreter for all ILLabelingElements</remarks>
52    public class ILSimpleTexInterpreter : ILSimpleInterpreter {
53
54#region attributes
55        public static readonly ILKeywords Keywords = new ILKeywords();
56#endregion
57
58#region constructor
59       
60        /// <summary>
61        /// create a new instance of a simple text interpreter
62        /// </summary>
63        public ILSimpleTexInterpreter () : base () { }
64
65#endregion
66
67#region helper functions
68
69        protected override void parseString (string expression, Font font, Point offset, Color color,
70                                    IILTextRenderer renderer, ref Size size,
71                                    ref List<ILRenderQueueItem> queue) {
72            int pos = 0;
73            string key, itemText;
74            RectangleF bmpSize = new RectangleF();
75            int curHeigth = 0, curWidth = 0;
76            Bitmap itemBMP = null;
77            int lineHeight = 0, lineWidth = 0;
78            Size itemSize = Size.Empty;
79            while (pos < expression.Length) {
80                itemText = expression.Substring(pos++,1);
81                #region special position control sequences
82                if (itemText == "\r") {
83                    queue.Add(new ILRenderQueueItem(itemText,0,0, color));
84                    if (curWidth < lineWidth)
85                        curWidth = lineWidth;
86                    lineWidth = 0;
87                    continue;
88                } else if (itemText == "\n") {
89                    queue.Add(new ILRenderQueueItem(itemText,0,0, color));
90                    curHeigth += lineHeight;
91                    lineHeight = 0;
92                    if (curWidth < lineWidth)
93                        curWidth = lineWidth;
94                    lineWidth = 0;
95                    continue;
96                #endregion
97                } else if (itemText == "\\") {   
98                    #region font control
99                    if (pos < expression.Length - 2) {
100                        #region test for font control sequences: \it,\bf,\rm
101                        if (expression[pos] == 'i' && expression[pos+1] == 't') {
102                            font = new Font(font,font.Style | FontStyle.Italic);
103                            pos += 2; continue;
104                        } else if (expression[pos] == 'b' && expression[pos+1] == 'f') {
105                            font = new Font(font,font.Style | FontStyle.Bold);
106                            pos += 2; continue;
107                        } else if (expression[pos] == 'r' && expression[pos+1] == 'm') {
108                            font = new Font(font,FontStyle.Regular);
109                            pos += 2; continue;
110                        }
111                        #endregion
112                        #region fontname,-size,-color
113                        if (parseKeyword(expression,ref pos,Keywords.Reset)) {
114                            color = Color.Empty;
115                            font = m_normalFont;
116                            offset = new Point(0,0);
117                            continue;
118                        }
119                        string parameter = "";
120                        if (parseKeywordArgumented(expression,ref pos,Keywords.Fontname,ref parameter)) {
121                            font = new Font(parameter,font.Size,font.Style,font.Unit);
122                            continue;
123                        }
124                        if (parseKeywordArgumented(expression,ref pos,Keywords.Fontsize,ref parameter)) {
125                            int newSize;
126                            if (!int.TryParse(parameter,out newSize))
127                                continue;
128                            if (parameter.StartsWith("+") && newSize > 0 ) {
129                                newSize += (int)font.Size;
130                                if (newSize > 40) newSize = 40;   
131                            } else if (parameter.StartsWith("-") && -newSize < font.Size) {
132                                newSize = (int)font.Size + newSize;
133                            }
134                            if (newSize > 0 && newSize < 40) {
135                                offset.Y += (int)Math.Round(font.Size - newSize); 
136                                font = new Font(font.Name,newSize,font.Style,font.Unit);
137                            }
138                            continue;
139                        }
140                        if (parseKeywordArgumented(expression,ref pos,Keywords.Color,ref parameter)) {
141                            parseColor(parameter, ref color);   
142                            continue;
143                        }
144                        #endregion
145                    }
146                    #endregion
147                    //if (pos < expression.Length - "size".Length)
148                    #region handle predefined symbols
149                    TextSymbols symbol = matchSymbol(expression,ref pos);
150                    if (symbol != TextSymbols.nothing) {
151                        itemText = TranslateSymbol(symbol);
152                        if (String.IsNullOrEmpty (itemText)) continue;
153                    }
154                    #endregion
155                    #region lower- upper indices
156                } else if (pos < expression.Length && itemText == "_") {
157                    int end;
158                    if (pos < expression.Length-1 && expression[pos] == '{') {
159                        pos ++;
160                        // find end brace & remove
161                        end = expression.IndexOf('}',pos)-1;
162                        if (end > 0 && end < expression.Length) {
163                            parseString(
164                                expression.Substring(pos,end-pos+1),
165                                new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
166                                new Point(offset.X,offset.Y + (int)(0.3f * font.Height)),
167                                color, renderer, ref size, ref queue);
168                            pos = end+2;
169                            continue;
170                        }
171                    }
172                    // cache next char only
173                    parseString(
174                        expression.Substring(pos++,1),
175                        new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
176                        new Point(offset.X,offset.Y + (int)(0.3f * font.Height)),
177                        color, renderer, ref size, ref queue);
178                    continue;
179                } else if (pos < expression.Length && itemText == "^") {
180                    int end;
181                    //offset.Y += 0.8f * font.Height;
182                    if (pos < expression.Length-1 && expression[pos] == '{') {
183                        pos ++;
184                        // find end brace & remove
185                        end = expression.IndexOf('}',pos)-1;
186                        if (end > 0 && end < expression.Length) {
187                            parseString(
188                                expression.Substring(pos,end-pos+1),
189                                new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
190                                new Point(offset.X,offset.Y - (int)(0.2f * font.Height)),
191                                color, renderer, ref size, ref queue);
192                            pos = end+2;
193                            continue;
194                        }
195                    }
196                    // cache next char only
197                    parseString(
198                        expression.Substring(pos++,1),
199                        new Font(font.Name,font.Size * 0.7f,font.Style,font.Unit),
200                        new Point(offset.X,offset.Y - (int)(0.2f * font.Height))
201                        ,color, renderer, ref size, ref queue);
202                    continue;
203                    #endregion
204                }
205                key = ILHashCreator.Hash(font,itemText);
206               
207                if (renderer.TryGetSize(key, ref itemSize)) {
208                    queue.Add(new ILRenderQueueItem(key,offset,color));
209                    if (itemSize.Height > lineHeight) lineHeight = itemSize.Height;
210                    lineWidth += (int)itemSize.Width;
211                } else {
212                    lock (this) {
213                        itemBMP = transformItem(itemText,font,out bmpSize);
214                        renderer.Cache(key,itemBMP,bmpSize);
215                        queue.Add(new ILRenderQueueItem(key,offset,color));
216                        // update size
217                        if (bmpSize.Height > lineHeight)
218                            lineHeight = (int)bmpSize.Height;
219                        lineWidth += (int)bmpSize.Width;
220                    }
221                }
222            }
223            size.Width += ((curWidth>lineWidth)?curWidth:lineWidth);
224            size.Height = curHeigth + lineHeight;
225        }
226
227        private bool parseKeyword(string text, ref int pos, string keyword) {
228            if (pos < text.Length - keyword.Length                 
229                && text.Substring(pos,keyword.Length) == keyword) {
230                pos += keyword.Length;
231                return true;
232            }
233            return false;
234        }
235
236        private void parseColor(string parameter, ref Color color) {
237            if (!String.IsNullOrEmpty(parameter) && parameter[0] == '#') {
238                // try to parse for rgb value. Format: #D2E540
239                if (parameter.Length == 7) {
240                    IFormatProvider format = System.Threading.Thread.CurrentThread.CurrentCulture;
241                    byte r,g,b;
242                    // R - value
243                    if (!byte.TryParse(parameter.Substring(1,2),
244                                      System.Globalization.NumberStyles.HexNumber,
245                                      format,out r)) return;
246                    // G - value
247                    if (!byte.TryParse(parameter.Substring(3,2),
248                                      System.Globalization.NumberStyles.HexNumber,
249                                      format,out g)) return;
250                    // B - value
251                    if (!byte.TryParse(parameter.Substring(5,2),
252                                      System.Globalization.NumberStyles.HexNumber,
253                                      format,out b)) return;
254                    color = Color.FromArgb(r,g,b);
255                }
256            } else {
257                // try to parse for known color name
258                try {
259                    color = Color.FromName(parameter);
260                } catch {}
261            }
262        }
263        private bool parseKeywordArgumented(string text, ref int pos, string keyword, ref string parameter) {
264            int tmpPos = pos;
265            if (pos < text.Length - keyword.Length                 
266                && text.Substring(pos,keyword.Length) == keyword) {
267                tmpPos = pos+keyword.Length;
268                if (text[tmpPos] != '{'
269                    || tmpPos == text.Length-1) return false;
270                int end = text.IndexOf('}',++tmpPos);
271                if (end < tmpPos) return false;
272                parameter = text.Substring(tmpPos,end-tmpPos).Trim();
273                pos = end + 1;
274                return true;
275            }
276            return false;
277        }
278        /// <summary>
279        /// extract TextSymbol from text
280        /// </summary>
281        /// <param name="text">text to extract symbol from</param>
282        /// <param name="pos">current text character position</param>
283        /// <returns>one of TextSymbol enumeration values</returns>
284        /// <remarks>if one symbol was found, its enum representation is
285        /// returned and pos is increased by the corresponding number of
286        /// characters. If no matching symbol was found, pos is not altered
287        /// and TextSymbols.nothing will be returned.</remarks>
288        internal static TextSymbols matchSymbol (string text, ref int pos) {
289            foreach (string sym in Enum.GetNames(typeof(TextSymbols))) {
290                if (pos <= text.Length - sym.Length) {
291                    if (text.Substring(pos,sym.Length) != sym) {
292                        continue;
293                    }
294                    if (sym == "nothing") continue;
295                    pos += sym.Length;
296                    return (TextSymbols)Enum.Parse(typeof(TextSymbols),sym);
297                }
298            }
299            return TextSymbols.nothing;
300        }
301        /// <summary>
302        ///  translates TextSymbol enum value to unicode character
303        /// </summary>
304        /// <param name="symbol">enum representation</param>
305        /// <returns>unicode character</returns>
306        /// <remarks>refers to: http://www.decodeunicode.org/ (e.g.)</remarks>
307        public static string TranslateSymbol (TextSymbols symbol) {
308            #region symbol matching
309            switch (symbol) {
310                case TextSymbols.alpha:
311                    return "α";
312                case TextSymbols.beta:
313                    return "β";
314                case TextSymbols.gamma:
315                    return "γ";
316                case TextSymbols.delta:
317                    return "ÎŽ";
318                case TextSymbols.epsilon:
319                    return "ε";
320                case TextSymbols.zeta:
321                    return "ζ";
322                case TextSymbols.eta:
323                    return "η";
324                case TextSymbols.theta:
325                    return "Ξ";
326                case TextSymbols.vartheta:
327                    return "\u03d1";
328                case TextSymbols.iota:
329                    return "ι";
330                case TextSymbols.kappa:
331                    return "κ";
332                case TextSymbols.lambda:
333                    return "λ";
334                case TextSymbols.mu:
335                    return "ÎŒ";
336                case TextSymbols.nu:
337                    return "Îœ";
338                case TextSymbols.xi:
339                    return "Ο";
340                case TextSymbols.pi:
341                    return "π";
342                case TextSymbols.rho:
343                    return "ρ";
344                case TextSymbols.sigma:
345                    return "σ";
346                case TextSymbols.varsigma:
347                    return "ς";
348                case TextSymbols.tau:
349                    return "τ";
350                case TextSymbols.upsilon:
351                    return "υ";
352                case TextSymbols.phi:
353                    return "φ";
354                case TextSymbols.chi:
355                    return "χ";
356                case TextSymbols.psi:
357                    return "ψ";
358                case TextSymbols.omega:
359                    return "ω";
360                case TextSymbols.Gamma:
361                    return "Γ";
362                case TextSymbols.Delta:
363                    return "Δ";
364                case TextSymbols.Theta:
365                    return "Θ";
366                case TextSymbols.Lambda:
367                    return "Λ";
368                case TextSymbols.Xi:
369                    return "Ξ";
370                case TextSymbols.Pi:
371                    return "\u03a0"; //"Π";
372                case TextSymbols.Sigma:
373                    return "Σ";
374                case TextSymbols.Upsilon:
375                    return "Î¥";
376                case TextSymbols.Phi:
377                    return "Ί";
378                case TextSymbols.Psi:
379                    return "Κ";
380                case TextSymbols.Omega:
381                    return "Ω";
382                case TextSymbols.forall:
383                    return "\u2200";
384                case TextSymbols.exists:
385                    return "\u2203"; 
386                case TextSymbols.ni:
387                    return "\u220b";
388                case TextSymbols.cong:
389                    return "\u2205";
390                case TextSymbols.neq:
391                    return "\u2260";
392                case TextSymbols.equiv:
393                    return "\u2261";
394                case TextSymbols.approx:
395                    return "\u2240";
396                case TextSymbols.aleph:
397                    return "\u2235";
398                case TextSymbols.Im:
399                    return "\u2111";
400                case TextSymbols.Re:
401                    return "\u211b";
402                case TextSymbols.wp:
403                    return "\u2118";
404                case TextSymbols.otimes:
405                    return "\u2297";
406                case TextSymbols.oplus:
407                    return "\u2295";
408                case TextSymbols.oslash:
409                    return "\u2205";
410                case TextSymbols.cap:
411                    return "\u22c2";
412                case TextSymbols.cup:
413                    return "\u22c3";
414                case TextSymbols.supseteq:
415                    return "\u2287";
416                case TextSymbols.supset:
417                    return "\u2283";
418                case TextSymbols.subseteq:
419                    return "\u2286";
420                case TextSymbols.subset:
421                    return "\u2282";
422                case TextSymbols.int_:
423                    return "\u222b";
424                case TextSymbols.in_:
425                    return "\u2208";
426                case TextSymbols.o:
427                    return "\u25cb";
428                case TextSymbols.rfloor:
429                    return "\u230b";
430                case TextSymbols.lceil:
431                    return "\u2308";
432                case TextSymbols.nabla:
433                    return "\u2207";
434                case TextSymbols.lfloor:
435                    return "\u230a";
436                case TextSymbols.cdot:
437                    return "\u2219";
438                case TextSymbols.ldots:
439                    return "\u2026";
440                case TextSymbols.cdots:
441                    return "\u220f";
442                case TextSymbols.perp:
443                    return "\u22a5";
444                case TextSymbols.neg:
445                    return "\u2511";
446                case TextSymbols.prime:
447                    return "\u2032";
448                case TextSymbols.wedge:
449                    return "\u22c0";
450                case TextSymbols.times:
451                    return "\u2a09";
452                case TextSymbols.Null:
453                    return "\u2205";
454                case TextSymbols.rceil:
455                    return "\u2309";
456                case TextSymbols.surd:
457                    return "\u221a";
458                case TextSymbols.mid:
459                    return "|";
460                case TextSymbols.vee:
461                    return "\u22c1";
462                case TextSymbols.varpi:
463                    return "\u03d6";
464                case TextSymbols.copyright:
465                    return "\u00a9";
466                case TextSymbols.langle:
467                    return "\u2329";
468                case TextSymbols.rangle:
469                    return "\u232a";
470                case TextSymbols.sim:
471                    return "\u223c";
472                case TextSymbols.leq:
473                    return "\u2264";
474                case TextSymbols.infty:
475                    return "\u221e";
476                case TextSymbols.leftrightarrow:
477                    return "\u21d4";
478                case TextSymbols.leftarrow:
479                    return "\u21d0";
480                case TextSymbols.uparrow:
481                    return "\u21d1";
482                case TextSymbols.rightarrow:
483                    return "\u21d2";
484                case TextSymbols.downarrow:         
485                    return "\u21d3";
486                case TextSymbols.circ:
487                    return "\u25cc";
488                case TextSymbols.pm:
489                    return "\u00b1";
490                case TextSymbols.geq:
491                    return "\u2265";
492                case TextSymbols.propto:
493                    return "\u221d";
494                case TextSymbols.partial:
495                    return "\u2202";
496                case TextSymbols.div:
497                    return "\u00f7";
498                default:
499                    break;
500            }
501            return "";
502            #endregion
503        }
504
505#endregion
506
507#region symbol definitions
508
509        /// <summary>
510        /// available keywords, interpretable by this IILInterpreter
511        /// </summary>
512        /// <remarks><para>The static instance ILSimpleTexInterpreter.Keywords can be
513        /// used to alter the keywords used to switch to different font styles etc.</para></remarks>
514        public class ILKeywords {
515            private string m_fontname = "fontname";
516            /// <summary>
517            /// placeholder for font name control sequence
518            /// </summary>
519            public string Fontname {
520                get { return m_fontname; }
521                set { if (!string.IsNullOrEmpty(value)) m_fontname = value; }
522            }     
523            private string m_fontsize = "fontsize";
524            /// <summary>
525            /// placeholder for font size control sequence
526            /// </summary>
527            public string Fontsize {
528                get { return m_fontsize; }
529                set { if (!string.IsNullOrEmpty(value)) m_fontsize = value; }
530            }     
531            private string m_italic = "it";
532            /// <summary>
533            /// placeholder for italic font control sequence
534            /// </summary>
535            public string Italic {
536                get { return m_italic; }
537                set { if (!string.IsNullOrEmpty(value)) m_italic = value; }
538            }     
539            private string m_bold = "bf";
540            /// <summary>
541            /// placeholder for bold font control sequence
542            /// </summary>
543            public string Bold {
544                get { return m_bold; }
545                set { if (!string.IsNullOrEmpty(value)) m_bold = value; }
546            }     
547            private string m_color = "color";
548            /// <summary>
549            /// placeholder for font color control sequence
550            /// </summary>
551            public string Color {
552                get { return m_color; }
553                set { if (!string.IsNullOrEmpty(value)) m_color = value; }
554            }     
555            private string m_reset = "reset";
556            /// <summary>
557            /// placeholder for text control sequence 'reset to initial value'
558            /// </summary>
559            public string Reset {
560                get { return m_reset; }
561                set { if (!string.IsNullOrEmpty(value)) m_reset = value; }
562            }     
563        }
564#pragma warning disable 1591
565        /// <summary>
566        /// all available TextSymbols (like \\Alpha etc.) this IILTextInterpreter understands
567        /// </summary>
568        public enum TextSymbols {
569            alpha,
570            beta,
571            gamma,
572            delta,
573            epsilon,
574            zeta,
575            eta,
576            theta,
577            vartheta,
578            iota,
579            kappa,
580            lambda,
581            mu,
582            nu,
583            xi,
584            pi,
585            rho,
586            sigma,
587            varsigma,
588            tau,
589            upsilon,
590            phi,
591            chi,
592            psi,
593            omega,
594            Gamma,
595            Delta,
596            Theta,
597            Lambda,
598            Xi,
599            Pi,
600            Sigma,
601            Upsilon,
602            Phi,
603            Psi,
604            Omega,
605            forall,
606            exists,
607            ni,
608            cong,
609            neq,
610            equiv,
611            approx,
612            aleph,
613            Im,
614            Re,
615            wp,
616            otimes,
617            oplus,
618            oslash,
619            cap,
620            cup,
621            supseteq,
622            supset,
623            subseteq,
624            subset,
625            int_,
626            in_,
627            o,
628            rfloor,
629            lceil,
630            nabla,
631            lfloor,
632            cdot,
633            ldots,
634            perp,
635            neg,
636            prime,
637            wedge,
638            times,
639            Null,
640            rceil,
641            surd,
642            mid,
643            vee,
644            varpi,
645            copyright,
646            langle,
647            rangle,
648            nothing,
649            sim,
650            leq,
651            infty,
652            clubsuit,
653            diamondsuit,
654            heartsuit,
655            spadesuit,
656            leftrightarrow,
657            leftarrow,
658            uparrow,
659            rightarrow,
660            downarrow,
661            circ,
662            pm,
663            geq,
664            propto,
665            partial,
666            div,
667            cdots
668        }
669#pragma warning restore 1591
670
671#endregion
672
673    }
674}
Note: See TracBrowser for help on using the repository browser.