Beispiel #1
0
        public override Box CreateBox(TexStyle style)
        {
            // Create result box.
            var  resultBox = HorizontalBox.Get();
            Atom curAtom = null, prevAtom = null;
            var  resultPos = 0;

            // Create and add box for each atom in row.
            for (int i = 0; i < Elements.Count; i++)
            {
                curAtom = (Elements[i]);

                // Create and add glue box, unless atom is first of row or previous/current atom is spaces.
                if (prevAtom != null && !(prevAtom is SpaceAtom) && !(curAtom is SpaceAtom))
                {
                    Box spaceBox = SpaceAtom.CreateGlueBox(prevAtom.GetRightType(), curAtom.GetLeftType(), style);
                    if (spaceBox != null)
                    {
                        resultBox.Add(spaceBox);
                        resultPos++;
                    }
                }
                // Create and add box for atom.
                GenerateDelimiterBox(resultBox, ref i, ref resultPos, style);
                //resultBox.Add(curBox);
                prevAtom = curAtom;
            }
            return(resultBox);
        }
        Atom Matrix(string value, ref int position, bool vertical)
        {
            MatrixAtom          matrixAtom = MatrixAtom.Get();
            List <List <Atom> > childs     = matrixAtom.Elements;

            Atom parsedChild = (Parse(ReadGroup(
                                          value, ref position, leftGroupChar, rightGroupChar)).ExtractRoot());

            childs.Add(ListPool <Atom> .Get());
            if (parsedChild == null)
            {
                MatrixAtom.Last(childs).Add(SpaceAtom.Get());
            }
            if (parsedChild is RowAtom)
            {
                List <Atom> el = ((RowAtom)parsedChild).Elements;
                if (vertical)
                {
                    MatrixAtom.ParseMatrixVertical(el, childs);
                }
                else
                {
                    MatrixAtom.ParseMatrix(el, childs);
                }
                el.Clear();
                ObjPool <RowAtom> .Release((RowAtom)parsedChild);
            }
            else
            {
                MatrixAtom.Last(childs).Add(parsedChild);
            }
            matrixAtom.Elements = childs;
            return(matrixAtom);
        }
Beispiel #3
0
        Box CreateBoxDefault(TexStyle style, Box baseBox)
        {
            var factor        = TexUtility.SizeFactor(style);
            var clearance     = TEXConfiguration.main.RootMargin * factor;
            var lineThickness = TEXConfiguration.main.LineThickness * factor;

            // Create box for radical sign.
            var totalHeight    = baseBox.totalHeight;
            var radicalSignBox = DelimiterFactory.CreateBox(rootSymbol, totalHeight + clearance + lineThickness,
                                                            style);

            // Add some clearance to left and right side
            baseBox = HorizontalBox.Get(baseBox, baseBox.width + clearance * 2, TexAlignment.Center);

            // Add half of excess height to clearance.
            lineThickness = Mathf.Max(radicalSignBox.height, lineThickness);
            clearance     = radicalSignBox.totalHeight - totalHeight - lineThickness * 2;

            // Create box for square-root containing base box.
            TexUtility.CentreBox(radicalSignBox, style);
            var overBar = OverBar.Get(baseBox, clearance, lineThickness);

            TexUtility.CentreBox(overBar, style);
            var radicalContainerBox = HorizontalBox.Get(radicalSignBox);

            radicalContainerBox.Add(overBar);

            // If atom is simple radical, just return square-root box.
            if (DegreeAtom == null)
            {
                return(radicalContainerBox);
            }

            // Atom is complex radical (nth-root).

            // Create box for root atom.
            var rootBox     = DegreeAtom.CreateBox(TexUtility.GetRootStyle());
            var bottomShift = scale * (radicalContainerBox.height + radicalContainerBox.depth);

            rootBox.shift = radicalContainerBox.depth - rootBox.depth - bottomShift;

            // Create result box.
            var resultBox = HorizontalBox.Get();

            // Add box for negative kern.
            var negativeKern = SpaceAtom.Get(-((radicalSignBox.width) / 2f), 0, 0).CreateBox(TexStyle.Display);
            var xPos         = rootBox.width + negativeKern.width;

            if (xPos < 0)
            {
                resultBox.Add(StrutBox.Get(-xPos, 0, 0, 0));
            }

            resultBox.Add(rootBox);
            resultBox.Add(negativeKern);
            resultBox.Add(radicalContainerBox);

            return(resultBox);
        }
Beispiel #4
0
        public static AccentedAtom Get(Atom baseAtom, string accentName)
        {
            var atom = ObjPool <AccentedAtom> .Get();

            atom.BaseAtom   = baseAtom ?? SpaceAtom.Get(0, 0, 0);
            atom.AccentAtom = SymbolAtom.GetAtom(accentName);
            return(atom);
        }
Beispiel #5
0
        public static AccentedAtom Get(Atom baseAtom, Atom accent)
        {
            var atom = ObjPool <AccentedAtom> .Get();

            atom.BaseAtom   = baseAtom ?? SpaceAtom.Get(0, 0, 0);
            atom.AccentAtom = accent as SymbolAtom;
            return(atom);
        }
Beispiel #6
0
        // the secret sauce begin here
        public TexFormula Parse(string value)
        {
            if (value == null)
            {
                return(null);
            }
            var formula = ObjPool <TexFormula> .Get();

            var position = 0;

            while (position < value.Length)
            {
                char ch = value[position];
                if (ch == '\r' || ch == '\0' || ch == '\x200c')
                {
                    position++; // Skip chars that have zero width length
                }
                else if (IsWhiteSpace(ch))
                {
                    formula.Add(AttachScripts(formula, value, ref position, SpaceAtom.Get()));
                    position++;
                }
                else if (ch == escapeChar)
                {
                    ProcessEscapeSequence(formula, value, ref position);
                }
                else if (ch == leftGroupChar)
                {
                    formula.Add(AttachScripts(formula, value, ref position, Parse(ReadGroup(value,
                                                                                            ref position, leftGroupChar, rightGroupChar)).ExtractRoot()));
                }
                else if (ch == rightGroupChar)
                {
                    position++;
                }
                else if (ch == superScriptChar || ch == subScriptChar)
                {
                    formula.Add(AttachScripts(formula, value, ref position, SpaceAtom.Get(0, TexUtility.spaceHeight, 0)));
                }
                else
                {
                    var scriptsAtom = AttachScripts(formula, value, ref position,
                                                    ConvertCharacter(value, ref position, ch));
                    formula.Add(scriptsAtom);
                }
            }

            if (formula.RootAtom == null && formula.AttachedMetaRenderer == null)
            {
                formula.Add(SpaceAtom.Get()); // a blank paragraph
            }
            return(formula);
        }
Beispiel #7
0
        public static AccentedAtom Get(Atom baseAtom, Atom accent)
        {
            var atom = ObjPool <AccentedAtom> .Get();

            var rootSymbol = accent;

            atom.AccentAtom = (SymbolAtom)rootSymbol;
            atom.BaseAtom   = baseAtom;
            if (atom.BaseAtom == null)
            {
                atom.BaseAtom = SpaceAtom.Get(0, 0, 0);
            }
            return(atom);
        }
        public override Box CreateBox(TexStyle style)
        {
            // Create box for base atom.
            var baseBox = BaseAtom == null ? StrutBox.Empty : BaseAtom.CreateBox(style);

            // Create boxes for over and under atoms.
            Box overBox = null, underBox = null;
            var maxWidth = baseBox.width;

            if (OverAtom != null)
            {
                overBox  = OverAtom.CreateBox(OverScriptSmaller ? TexUtility.GetSuperscriptStyle(style) : style);
                maxWidth = Mathf.Max(maxWidth, overBox.width);
            }

            if (UnderAtom != null)
            {
                underBox = UnderAtom.CreateBox(UnderScriptSmaller ? TexUtility.GetSubscriptStyle(style) : style);
                maxWidth = Mathf.Max(maxWidth, underBox.width);
            }

            // Create result box.
            var resultBox = VerticalBox.Get();

            // Create and add box for over atom.
            if (OverAtom != null)
            {
                resultBox.Add(ChangeWidth(overBox, maxWidth));
                resultBox.Add(TexUtility.GetBox(SpaceAtom.Get(0, OverSpace, 0), style));
            }

            // Add box for base atom.
            resultBox.Add(ChangeWidth(baseBox, maxWidth));

            float totalHeight = resultBox.height + resultBox.depth - baseBox.depth;

            // Create and add box for under atom.
            if (UnderAtom != null)
            {
                resultBox.Add(TexUtility.GetBox(SpaceAtom.Get(0, UnderSpace, 0), style));
                resultBox.Add(ChangeWidth(underBox, maxWidth));
            }

            resultBox.depth  = resultBox.height + resultBox.depth - totalHeight;
            resultBox.height = totalHeight;

            return(resultBox);
        }
        Atom Table(string value, ref int position, int align, int h, int v, bool vertical)
        {
            List <List <Atom> > childs     = new List <List <Atom> >();
            MatrixAtom          matrixAtom = ObjPool <MatrixAtom> .Get();

            matrixAtom.horizontalAlign = align;
            matrixAtom.horizontalLine  = h;
            matrixAtom.verticalLine    = v;

            Atom parsedChild = (Parse(ReadGroup(
                                          value, ref position, leftGroupChar, rightGroupChar)).ExtractRoot());

            childs.Add(ListPool <Atom> .Get());
            if (parsedChild == null)
            {
                MatrixAtom.Last(childs).Add(SpaceAtom.Get());
            }
            if (parsedChild is RowAtom)
            {
                List <Atom> el = ((RowAtom)parsedChild).Elements;
                if (!vertical)
                {
                    MatrixAtom.ParseMatrix(el, childs);
                }
                else
                {
                    MatrixAtom.ParseMatrixVertical(el, childs);
                }
                el.Clear();
                ObjPool <RowAtom> .Release((RowAtom)parsedChild);
            }
            else
            {
                MatrixAtom.Last(childs).Add(parsedChild);
            }
            matrixAtom.Elements = childs;
            return(matrixAtom);
        }
Beispiel #10
0
        private Atom ProcessCommand(TexFormula formula, string value, ref int position, string command)
        {
            SkipWhiteSpace(value, ref position);
            if (position == value.Length)
            {
                return(null);
            }

            switch (command)
            {
            case "meta":
                // Command is meta
                var metaRule = formula.AttachedMetaRenderer;
                if (metaRule == null)
                {
                    metaRule = formula.AttachedMetaRenderer = ObjPool <TexMetaRenderer> .Get();
                }
                else
                {
                    metaRule.Reset();
                }

                string metaPar = null;
                if (value[position] == leftBracketChar)
                {
                    metaPar = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                    metaRule.ParseString(metaPar);
                }

                return(null);

            case "root":
            case "sqrt":
                // Command is radical.

                TexFormula degreeFormula = null;
                if (value[position] == leftBracketChar)
                {
                    degreeFormula = Parse(ReadGroup(value, ref position, leftBracketChar, rightBracketChar));
                    SkipWhiteSpace(value, ref position);
                }
                return(Radical.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))
                                   .GetRoot, degreeFormula == null ? null : degreeFormula.GetRoot));

            case "vmatrix":
            case "matrix":
                //Command is Matrix
                MatrixAtom          matrixAtom = MatrixAtom.Get();
                List <List <Atom> > childs     = matrixAtom.Elements;

                Atom parsedChild = (Parse(ReadGroup(
                                              value, ref position, leftGroupChar, rightGroupChar)).GetRoot);
                childs.Add(ListPool <Atom> .Get());
                if (parsedChild == null)
                {
                    MatrixAtom.Last(childs).Add(SpaceAtom.Get());
                }
                if (parsedChild is RowAtom)
                {
                    List <Atom> el = ((RowAtom)parsedChild).Elements;
                    if (command == "matrix")
                    {
                        MatrixAtom.ParseMatrix(el, childs);
                    }
                    else
                    {
                        MatrixAtom.ParseMatrixVertical(el, childs);
                    }
                    el.Clear();
                    ObjPool <RowAtom> .Release((RowAtom)parsedChild);
                }
                else
                {
                    MatrixAtom.Last(childs).Add(parsedChild);
                }
                matrixAtom.Elements = childs;
                return(matrixAtom);

            case "math":
            case "text":
                var idx   = TexUtility.RawRenderFont < 0 ? TEXConfiguration.main.Typeface_Text : -2;
                var style = TexUtility.RenderFontStyle;
                if (value[position] == leftBracketChar)
                {
                    var str = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    if (!int.TryParse(str, out idx))
                    {
                        idx   = TexUtility.RawRenderFont < 0 ? TEXConfiguration.main.Typeface_Text : -2;
                        style = ParseFontStyle(str);
                    }
                    SkipWhiteSpace(value, ref position);
                }
                else if (command == "math")
                {
                    idx = -1;
                }

                var oldType  = TexUtility.RenderFont;
                var oldStyle = TexUtility.RenderFontStyle;

                TexUtility.RenderFont      = idx;
                TexUtility.RenderFontStyle = style;
                var parsed = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot;
                TexUtility.RenderFont      = oldType;
                TexUtility.RenderFontStyle = oldStyle;
                return(parsed);

            case "clr":
            case "mclr":
            case "color":
                // Command is color
                string clr = null;
                if (value[position] == leftBracketChar)
                {
                    clr = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }

                if (position == value.Length)
                {
                    return(null);
                }
                AttrColorAtom endColor;
                var           startColor = AttrColorAtom.Get(clr, command == "color" ? 1 : (command == "clr" ? 0 : 2), out endColor);
                return(InsertAttribute(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot, startColor, endColor));

            case "bg":
            case "vbg":
                if (value[position] == leftBracketChar)
                {
                    clr = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }
                else
                {
                    clr = null;
                }
                return(AttrBgAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))
                                      .GetRoot, clr, command == "bg"));

            case "size":
                // Command is size
                string sz = null;
                if (value[position] == leftBracketChar)
                {
                    sz = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }

                if (position == value.Length)
                {
                    return(null);
                }

                return(AttrSizeAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))
                                        .GetRoot, sz));

            case "link":
            case "ulink":
                // Command is Link
                string meta = null;
                if (value[position] == leftBracketChar)
                {
                    meta = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }

                if (position == value.Length)
                {
                    return(null);
                }

                string groupBrack = ReadGroup(value, ref position, leftGroupChar, rightGroupChar);
                if (meta == null)
                {
                    meta = groupBrack;
                }
                return(AttrLinkAtom.Get(Parse(groupBrack).GetRoot, meta, command == "ulink"));

            case "under":
                command = "anot";
                break;

            case "over":
                command = "bnot";
                break;
            }
            if (command.Length > 2 && command.Substring(command.Length - 3) == "not")
            {
                int    NotMode   = 0;
                bool   UseMargin = true;
                string prefix    = command.Substring(0, command.Length - 3);
                if (prefix.Length > 0)
                {
                    switch (prefix[0])
                    {
                    case 'n':
                        NotMode = 1;
                        break;

                    case 'h':
                        NotMode = 2;
                        break;

                    case 'd':
                        NotMode = 3;
                        break;

                    case 'u':
                        NotMode = 4;
                        break;

                    case 'o':
                        NotMode = 5;
                        break;

                    case 'v':
                        if (prefix.Length > 1 && prefix[1] == 'n')
                        {
                            NotMode = 7;
                        }
                        else
                        {
                            NotMode = 6;
                        }
                        break;

                    case 'a':
                        NotMode   = 4;
                        UseMargin = false;
                        break;

                    case 'b':
                        NotMode   = 5;
                        UseMargin = false;
                        break;
                    }
                }
                if (position == value.Length)
                {
                    return(null);
                }

                string sz = null;
                if (value[position] == leftBracketChar)
                {
                    sz = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }
                return(NegateAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))
                                      .GetRoot, NotMode, sz, UseMargin));
            }
            if (command.Length > 2 && command.Substring(command.Length - 3) == "trs")
            {
                int    PivotMode = 0;
                string prefix    = command.Substring(0, command.Length - 3);
                if (prefix.Length > 0)
                {
                    switch (prefix[0])
                    {
                    case 'm':
                        PivotMode = 1;
                        break;

                    case 'l':
                        PivotMode = 2;
                        break;
                    }
                }
                if (position == value.Length)
                {
                    return(null);
                }

                string trs = null;
                if (value[position] == leftBracketChar)
                {
                    trs = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    SkipWhiteSpace(value, ref position);
                }

                AttrTransformationAtom endTRS;
                var startTRS = AttrTransformationAtom.Get(trs, PivotMode, out endTRS);
                return(InsertAttribute(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot, startTRS, endTRS));
            }
            if (command.Length > 3 && command.Substring(command.Length - 4) == "frac")
            {
                int    FracAlignT = 0, FracAlignB = 0;
                bool   FracAlignN = true;
                string prefix     = command.Substring(0, command.Length - 4);
                if (prefix.Length > 0)
                {
                    if (prefix[0] == 'n')
                    {
                        FracAlignN = false;
                        prefix     = prefix.Substring(1);
                    }
                    if (prefix.Length == 1)
                    {
                        FracAlignT = fracP(prefix[0]);
                        FracAlignB = FracAlignT;
                    }
                    else if (prefix.Length == 2)
                    {
                        FracAlignT = fracP(prefix[0]);
                        FracAlignB = fracP(prefix[1]);
                    }
                }
                if (position == value.Length)
                {
                    return(null);
                }
                Atom numeratorFormula = null, denominatorFormula = null;
                numeratorFormula = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot;
                SkipWhiteSpace(value, ref position);
                if (position != value.Length)
                {
                    denominatorFormula = Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar)).GetRoot;
                }

                return(FractionAtom.Get(numeratorFormula, denominatorFormula, FracAlignN,
                                        (TexAlignment)FracAlignT, (TexAlignment)FracAlignB));
            }
            if (command.Length > 3 && command.Substring(command.Length - 4) == "hold")
            {
                TexAlignment align      = TexAlignment.Center;
                bool         isVertical = false;
                string       prefix     = command.Substring(0, command.Length - 3);
                if (prefix.Length > 0)
                {
                    switch (prefix[0])
                    {
                    case 'v':
                        isVertical = true;
                        break;

                    case 'l':
                        align = TexAlignment.Left;
                        break;

                    case 'r':
                        align = TexAlignment.Right;
                        break;

                    case 'b':
                        align = TexAlignment.Bottom;
                        goto case 'v';

                    case 't':
                        align = TexAlignment.Top;
                        goto case 'v';
                    }
                }

                Vector2 sz = Vector2.zero;
                if (position < value.Length && value[position] == leftBracketChar)
                {
                    var frag = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    int idx  = frag.IndexOf(',');
                    if (idx >= 0)
                    {
                        var fragL = frag.Substring(0, idx);
                        var fragR = frag.Substring(idx + 1);
                        float.TryParse(fragL, out sz.x);
                        float.TryParse(fragR, out sz.y);
                    }
                    else
                    {
                        if (isVertical)
                        {
                            float.TryParse(frag, out sz.y);
                        }
                        else
                        {
                            float.TryParse(frag, out sz.x);
                        }
                    }
                    SkipWhiteSpace(value, ref position);
                }
                if (position < value.Length && value[position] == leftGroupChar)
                {
                    return(HolderAtom.Get(Parse(ReadGroup(value, ref position, leftGroupChar, rightGroupChar))
                                          .GetRoot, sz.x, sz.y, align));
                }
                else
                {
                    return(HolderAtom.Get(null, sz.x, sz.y, align));
                }
            }
            if (command.Length > 4 && command.Substring(command.Length - 5) == "table")
            {
                bool   vertical = false;
                int    align    = 1 + 8 + 64;
                string prefix   = command.Substring(0, command.Length - 5);
                if (prefix.Length > 0)
                {
                    if (prefix[0] == 'v')
                    {
                        vertical = true;
                        prefix   = prefix.Substring(1);
                    }
                    if (prefix.Length == 1)
                    {
                        var pref = fracP(prefix[0]);
                        align = Math.Max(1, pref * 2) + Math.Max(8, pref * 16) + Math.Max(64, pref * 128);
                    }
                    else if (prefix.Length == 3)
                    {
                        var pref0 = fracP(prefix[0]);
                        var pref1 = fracP(prefix[1]);
                        var pref2 = fracP(prefix[2]);
                        align = Math.Max(1, pref0 * 2) + Math.Max(8, pref1 * 16) + Math.Max(64, pref2 * 128);
                    }
                }

                int lineStyleH = 0, lineStyleV = 0;
                if (value[position] == leftBracketChar)
                {
                    string lineOpt;
                    int    lineP = 0;
                    lineOpt = ReadGroup(value, ref position, leftBracketChar, rightBracketChar);
                    for (int i = 0; i < lineOpt.Length; i++)
                    {
                        if (!int.TryParse(lineOpt[i].ToString(), out lineP))
                        {
                            continue;
                        }
                        if (i >= 6)
                        {
                            break;
                        }
                        switch (i)
                        {
                        case 0:
                            lineStyleH += lineP >= 2 ? 17 : lineP;
                            break;

                        case 1:
                            lineStyleH += lineP >= 2 ? 10 : (lineP == 1 ? 2 : 0);
                            break;

                        case 2:
                            lineStyleH += lineP >= 1 ? 4 : 0;
                            break;

                        case 3:
                            lineStyleV += lineP >= 2 ? 17 : lineP;
                            break;

                        case 4:
                            lineStyleV += lineP >= 2 ? 10 : (lineP == 1 ? 2 : 0);
                            break;

                        case 5:
                            lineStyleV += lineP >= 1 ? 4 : 0;
                            break;
                        }
                    }
                    SkipWhiteSpace(value, ref position);
                }
                else
                {
                    lineStyleH = 7;
                    lineStyleV = 7;
                }


                List <List <Atom> > childs     = new List <List <Atom> >();
                MatrixAtom          matrixAtom = ObjPool <MatrixAtom> .Get();

                matrixAtom.horizontalAlign = align;
                matrixAtom.horizontalLine  = lineStyleH;
                matrixAtom.verticalLine    = lineStyleV;

                Atom parsedChild = (Parse(ReadGroup(
                                              value, ref position, leftGroupChar, rightGroupChar)).GetRoot);
                childs.Add(ListPool <Atom> .Get());
                if (parsedChild == null)
                {
                    MatrixAtom.Last(childs).Add(SpaceAtom.Get());
                }
                if (parsedChild is RowAtom)
                {
                    List <Atom> el = ((RowAtom)parsedChild).Elements;
                    if (!vertical)
                    {
                        MatrixAtom.ParseMatrix(el, childs);
                    }
                    else
                    {
                        MatrixAtom.ParseMatrixVertical(el, childs);
                    }
                    el.Clear();
                    ObjPool <RowAtom> .Release((RowAtom)parsedChild);
                }
                else
                {
                    MatrixAtom.Last(childs).Add(parsedChild);
                }
                matrixAtom.Elements = childs;
                return(matrixAtom);
            }
            throw new TexParseException("Invalid command.");
        }