예제 #1
0
        public override Box CreateBox(TexEnvironment environment)
        {
            var texFont = environment.TexFont;
            var style   = environment.Style;

            // Create box for base atom.
            var baseBox = BaseAtom.CreateBox(environment);

            // Create result box.
            var resultBox = new HorizontalBox();
            var axis      = texFont.GetAxisHeight(style);
            var delta     = Math.Max(baseBox.Height - axis, baseBox.Depth + axis);
            var minHeight = Math.Max((delta / 500) * delimeterFactor, 2 * delta - delimeterShortfall);

            // Create and add box for left delimeter.
            if (LeftDelimeter != null)
            {
                var leftDelimeterBox = DelimiterFactory.CreateBox(LeftDelimeter.Name, minHeight, environment);
                CentreBox(leftDelimeterBox, axis);
                resultBox.Add(leftDelimeterBox);
            }

            // add glueElement between left delimeter and base Atom, unless base Atom is whitespace.
            if (!(BaseAtom is SpaceAtom))
            {
                resultBox.Add(Glue.CreateBox(TexAtomType.Opening, BaseAtom.GetLeftType(), environment));
            }

            // add box for base Atom.
            resultBox.Add(baseBox);

            // add glueElement between right delimeter and base Atom, unless base Atom is whitespace.
            if (!(BaseAtom is SpaceAtom))
            {
                resultBox.Add(Glue.CreateBox(BaseAtom.GetRightType(), TexAtomType.Closing, environment));
            }

            // Create and add box for right delimeter.
            if (RightDelimeter is null)
            {
                return(resultBox);
            }

            var rightDelimeterBox = DelimiterFactory.CreateBox(RightDelimeter.Name, minHeight, environment);

            CentreBox(rightDelimeterBox, axis);
            resultBox.Add(rightDelimeterBox);

            return(resultBox);
        }
예제 #2
0
        public override Box CreateBox(TexEnvironment environment)
        {
            var texFont = environment.TexFont;
            var style   = environment.Style;

            // Create box for base atom.
            var baseBox = (BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment));

            if (SubscriptAtom is null && SuperscriptAtom is null)
            {
                return(baseBox);
            }

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

            // Get last font used or default Mu font.
            var lastFontId = baseBox.GetLastFontId();

            if (lastFontId == TexFontUtilities.NoFontId)
            {
                lastFontId = texFont.GetMuFontId();
            }

            var subscriptStyle   = environment.GetSubscriptStyle();
            var superscriptStyle = environment.GetSuperscriptStyle();

            // Set delta value and preliminary shift-up and shift-down amounts depending on type of base atom.
            var    delta = 0d;
            double shiftUp, shiftDown;

            if (BaseAtom is AccentedAtom)
            {
                var accentedBox = ((AccentedAtom)BaseAtom).BaseAtom.CreateBox(environment.GetCrampedStyle());
                shiftUp   = accentedBox.Height - texFont.GetSupDrop(superscriptStyle.Style);
                shiftDown = accentedBox.Depth + texFont.GetSubDrop(subscriptStyle.Style);
            }
            else if (BaseAtom is SymbolAtom && BaseAtom.Type == TexAtomType.BigOperator)
            {
                var charInfo = texFont.GetCharInfo(((SymbolAtom)BaseAtom).Name, style);
                if (style < TexStyle.Text && texFont.HasNextLarger(charInfo))
                {
                    charInfo = texFont.GetNextLargerCharInfo(charInfo, style);
                }
                var charBox = new CharBox(environment, charInfo);

                charBox.Shift = -(charBox.Height + charBox.Depth) / 2 - environment.TexFont.GetAxisHeight(
                    environment.Style);
                resultBox = new HorizontalBox(charBox);

                delta = charInfo.Metrics.Italic;
                if (delta > TexUtilities.FloatPrecision && SubscriptAtom is null)
                {
                    resultBox.Add(new StrutBox(delta, 0, 0, 0));
                }

                shiftUp   = resultBox.Height - texFont.GetSupDrop(superscriptStyle.Style);
                shiftDown = resultBox.Depth + texFont.GetSubDrop(subscriptStyle.Style);
            }
            else if (BaseAtom is CharSymbol)
            {
                var charFont = ((CharSymbol)BaseAtom).GetCharFont(texFont);
                if (!((CharSymbol)BaseAtom).IsTextSymbol || !texFont.HasSpace(charFont.FontId))
                {
                    delta = texFont.GetCharInfo(charFont, style).Metrics.Italic;
                }
                if (delta > TexUtilities.FloatPrecision && SubscriptAtom is null)
                {
                    resultBox.Add(new StrutBox(delta, 0, 0, 0));
                    delta = 0;
                }

                shiftUp   = 0;
                shiftDown = 0;
            }
            else
            {
                shiftUp   = baseBox.Height - texFont.GetSupDrop(superscriptStyle.Style);
                shiftDown = baseBox.Depth + texFont.GetSubDrop(subscriptStyle.Style);
            }

            Box superscriptBox          = null;
            Box superscriptContainerBox = null;
            Box subscriptBox            = null;
            Box subscriptContainerBox   = null;

            if (SuperscriptAtom != null)
            {
                // Create box for superscript atom.
                superscriptBox          = SuperscriptAtom.CreateBox(superscriptStyle);
                superscriptContainerBox = new HorizontalBox(superscriptBox);

                // Add box for script space.
                superscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment));

                // Adjust shift-up amount.
                double p;
                if (style == TexStyle.Display)
                {
                    p = texFont.GetSup1(style);
                }
                else if (environment.GetCrampedStyle().Style == style)
                {
                    p = texFont.GetSup3(style);
                }
                else
                {
                    p = texFont.GetSup2(style);
                }
                shiftUp = Math.Max(Math.Max(shiftUp, p), superscriptBox.Depth + Math.Abs(texFont.GetXHeight(
                                                                                             style, lastFontId)) / 4);
            }

            if (SubscriptAtom != null)
            {
                // Create box for subscript atom.
                subscriptBox          = SubscriptAtom.CreateBox(subscriptStyle);
                subscriptContainerBox = new HorizontalBox(subscriptBox);

                // Add box for script space.
                subscriptContainerBox.Add(scriptSpaceAtom.CreateBox(environment));
            }

            // Check if only superscript is set.
            if (subscriptBox is null)
            {
                superscriptContainerBox.Shift = -shiftUp;
                resultBox.Add(superscriptContainerBox);
                return(resultBox);
            }

            // Check if only subscript is set.
            if (superscriptBox is null)
            {
                subscriptBox.Shift = Math.Max(Math.Max(shiftDown, texFont.GetSub1(style)), subscriptBox.Height - 4 *
                                              Math.Abs(texFont.GetXHeight(style, lastFontId)) / 5);
                resultBox.Add(subscriptContainerBox);
                return(resultBox);
            }

            // Adjust shift-down amount.
            shiftDown = Math.Max(shiftDown, texFont.GetSub2(style));

            // Reposition both subscript and superscript.
            var defaultLineThickness = texFont.GetDefaultLineThickness(style);
            // Space between subscript and superscript.
            var scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height;

            if (scriptsInterSpace < 4 * defaultLineThickness)
            {
                shiftUp += 4 * defaultLineThickness - scriptsInterSpace;

                // Position bottom of superscript at least 4/5 of X-height above baseline.
                var psi = 0.8 * Math.Abs(texFont.GetXHeight(style, lastFontId)) - (shiftUp - superscriptBox.Depth);
                if (psi > 0)
                {
                    shiftUp   += psi;
                    shiftDown -= psi;
                }
            }
            scriptsInterSpace = shiftUp - superscriptBox.Depth + shiftDown - subscriptBox.Height;

            // Create box containing both superscript and subscript.
            var scriptsBox = new VerticalBox();

            superscriptContainerBox.Shift = delta;
            scriptsBox.Add(superscriptContainerBox);
            scriptsBox.Add(new StrutBox(0, scriptsInterSpace, 0, 0));
            scriptsBox.Add(subscriptContainerBox);
            scriptsBox.Height = shiftUp + superscriptBox.Height;
            scriptsBox.Depth  = shiftDown + subscriptBox.Depth;
            resultBox.Add(scriptsBox);

            return(resultBox);
        }
예제 #3
0
        public override Box CreateBox(TexEnvironment environment)
        {
            var tex_font = environment.TexFont;
            var style    = environment.Style;

            // Calculate minimum clearance amount.
            var default_rule_thickness = tex_font.GetDefaultLineThickness(style);
            var clearance = style < TexStyle.Text ? tex_font.GetXHeight(style, tex_font.GetCharInfo(__SqrtSymbol, style).FontId) : default_rule_thickness;

            clearance = default_rule_thickness + Math.Abs(clearance) / 4;

            // Create box for base atom, in cramped style.
            var base_box = BaseAtom.CreateBox(environment.GetCrampedStyle());

            // Create box for radical sign.
            var total_height     = base_box.Height + base_box.Depth;
            var radical_sign_box = DelimiterFactory.CreateBox(__SqrtSymbol, total_height + clearance + default_rule_thickness,
                                                              environment);

            // Add half of excess height to clearance.
            var delta = radical_sign_box.Depth - (total_height + clearance);

            clearance += delta / 2;

            // Create box for square-root containing base box.
            radical_sign_box.Shift = -(base_box.Height + clearance);
            var over_bar = new OverBar(base_box, clearance, radical_sign_box.Height)
            {
                Shift = -(base_box.Height + clearance + default_rule_thickness)
            };
            var radical_container_box = new HorizontalBox(radical_sign_box);

            radical_container_box.Add(over_bar);

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

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

            // Create box for root atom.
            var root_box     = DegreeAtom.CreateBox(environment.GetRootStyle());
            var bottom_shift = __Scale * (radical_container_box.Height + radical_container_box.Depth);

            root_box.Shift = radical_container_box.Depth - root_box.Depth - bottom_shift;

            // Create result box.
            var result_box = new HorizontalBox();

            // Add box for negative kern.
            var negative_kern = new SpaceAtom(TexUnit.Mu, -10, 0, 0).CreateBox(environment);
            var x_pos         = root_box.Width + negative_kern.Width;

            if (x_pos < 0)
            {
                result_box.Add(new StrutBox(-x_pos, 0, 0, 0));
            }

            result_box.Add(root_box);
            result_box.Add(negative_kern);
            result_box.Add(radical_container_box);

            return(result_box);
        }
예제 #4
0
        public override Box CreateBox(TexEnvironment environment)
        {
            var texFont = environment.TexFont;
            var style   = environment.Style;

            // Create box for base atom.
            var baseBox = BaseAtom is null ? StrutBox.Empty : BaseAtom.CreateBox(environment.GetCrampedStyle());
            var skew    = 0d;

            if (BaseAtom is CharSymbol)
            {
                skew = texFont.GetSkew(((CharSymbol)BaseAtom).GetCharFont(texFont), style);
            }

            // Find character of best scale for accent symbol.
            var accentChar = texFont.GetCharInfo(AccentAtom.Name, style);

            while (texFont.HasNextLarger(accentChar))
            {
                var nextLargerChar = texFont.GetNextLargerCharInfo(accentChar, style);
                if (nextLargerChar.Metrics.Width > baseBox.Width)
                {
                    break;
                }
                accentChar = nextLargerChar;
            }

            var resultBox = new VerticalBox();

            // Create and add box for accent symbol.
            Box accentBox;
            var accentItalicWidth = accentChar.Metrics.Italic;

            if (accentItalicWidth > TexUtilities.FloatPrecision)
            {
                accentBox = new HorizontalBox(new CharBox(environment, accentChar));
                accentBox.Add(new StrutBox(accentItalicWidth, 0, 0, 0));
            }
            else
            {
                accentBox = new CharBox(environment, accentChar);
            }
            resultBox.Add(accentBox);

            var delta = Math.Min(baseBox.Height, texFont.GetXHeight(style, accentChar.FontId));

            resultBox.Add(new StrutBox(0, -delta, 0, 0));

            // Centre and add box for base atom. Centre base box and accent box with respect to each other.
            var boxWidthsDiff = (baseBox.Width - accentBox.Width) / 2;

            accentBox.Shift = skew + Math.Max(boxWidthsDiff, 0);
            if (boxWidthsDiff < 0)
            {
                baseBox = new HorizontalBox(baseBox, accentBox.Width, TexAlignment.Center);
            }
            resultBox.Add(baseBox);

            // Adjust height and depth of result box.
            var depth       = baseBox.Depth;
            var totalHeight = resultBox.Height + resultBox.Depth;

            resultBox.Depth  = depth;
            resultBox.Height = totalHeight - depth;

            return(resultBox);
        }
예제 #5
0
        public override Box CreateBox(TexEnvironment environment)
        {
            var texFont = environment.TexFont;
            var style   = environment.Style;

            if ((UseVerticalLimits.HasValue && !UseVerticalLimits.Value) ||
                (!UseVerticalLimits.HasValue && style >= TexStyle.Text))
            {
                // Attach atoms for limits as scripts.
                return(new ScriptsAtom(BaseAtom, LowerLimitAtom, UpperLimitAtom).CreateBox(environment));
            }

            // Create box for base atom.
            Box    baseBox;
            double delta;

            if ((BaseAtom as SymbolAtom)?.Type == TexAtomType.BigOperator)
            {
                // Find character of best scale for operator symbol.
                var opChar = texFont.GetCharInfo(((SymbolAtom)BaseAtom).Name, style);
                if (style < TexStyle.Text && texFont.HasNextLarger(opChar))
                {
                    opChar = texFont.GetNextLargerCharInfo(opChar, style);
                }
                var charBox = new CharBox(environment, opChar);
                charBox.Shift = -(charBox.Height + charBox.Depth) / 2 -
                                environment.TexFont.GetAxisHeight(environment.Style);
                baseBox = new HorizontalBox(charBox);

                delta = opChar.Metrics.Italic;
                if (delta > TexUtilities.FloatPrecision)
                {
                    baseBox.Add(new StrutBox(delta, 0, 0, 0));
                }
            }
            else
            {
                baseBox = new HorizontalBox(BaseAtom?.CreateBox(environment) ?? StrutBox.Empty);
                delta   = 0;
            }

            // Create boxes for upper and lower limits.
            var upperLimitBox = UpperLimitAtom?.CreateBox(environment.GetSuperscriptStyle());
            var lowerLimitBox = LowerLimitAtom?.CreateBox(environment.GetSubscriptStyle());

            // Make all component boxes equally wide.
            var maxWidth = Math.Max(Math.Max(baseBox.Width, upperLimitBox?.Width ?? 0),
                                    lowerLimitBox?.Width ?? 0);

            baseBox = ChangeWidth(baseBox, maxWidth);
            if (upperLimitBox != null)
            {
                upperLimitBox = ChangeWidth(upperLimitBox, maxWidth);
            }
            if (lowerLimitBox != null)
            {
                lowerLimitBox = ChangeWidth(lowerLimitBox, maxWidth);
            }

            var resultBox  = new VerticalBox();
            var opSpacing5 = texFont.GetBigOpSpacing5(style);
            var kern       = 0d;

            // Create and add box for upper limit.
            if (UpperLimitAtom != null)
            {
                resultBox.Add(new StrutBox(0, opSpacing5, 0, 0));
                Debug.Assert(upperLimitBox != null, "upperLimitBox != null");
                upperLimitBox.Shift = delta / 2;
                resultBox.Add(upperLimitBox);
                kern = Math.Max(texFont.GetBigOpSpacing1(style), texFont.GetBigOpSpacing3(style) -
                                upperLimitBox.Depth);
                resultBox.Add(new StrutBox(0, kern, 0, 0));
            }

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

            // Create and add box for lower limit.
            if (LowerLimitAtom != null)
            {
                Debug.Assert(lowerLimitBox != null, "lowerLimitBox != null");
                resultBox.Add(new StrutBox(0, Math.Max(texFont.GetBigOpSpacing2(style), texFont.GetBigOpSpacing4(style) -
                                                       lowerLimitBox.Height), 0, 0));
                lowerLimitBox.Shift = -delta / 2;
                resultBox.Add(lowerLimitBox);
                resultBox.Add(new StrutBox(0, opSpacing5, 0, 0));
            }

            // Adjust height and depth of result box.
            var baseBoxHeight = baseBox.Height;
            var totalHeight   = resultBox.Height + resultBox.Depth;

            if (upperLimitBox != null)
            {
                baseBoxHeight += opSpacing5 + kern + upperLimitBox.Height + upperLimitBox.Depth;
            }
            resultBox.Height = baseBoxHeight;
            resultBox.Depth  = totalHeight - baseBoxHeight;

            return(resultBox);
        }