Beispiel #1
0
        public static XElement DrawImage(MathNode node)
        {
            //Top-level draw function: prepare the canvas, then call the draw method of the root node
            double baseline = 0;
            if (node.AlignToAxis)
                baseline = node.Axis();

            double height = Math.Max(node.Height, node.Ascender);
            double depth = Math.Max(node.Depth, node.Descender);
            double vsize = height + depth;

            Dictionary<string, string> attrs = new Dictionary<string, string>(){
                {"width", string.Format("{0:F6}pt", node.Width)},
                {"height", string.Format("{0:F6}pt", vsize)},
                {"viewBox", string.Format("0 {0:F6} {1:F6} {2:F6}", (-(height+baseline)), node.Width, vsize)}
            };
            

            XElement nodeElement = creatElement("svg", attrs);
            nodeElement.SetAttributeValue(XNamespace.Xmlns + "svg", SvgNs.NamespaceName);
            nodeElement.SetAttributeValue(XNamespace.Xmlns + "svgmath", SvgMathNs.NamespaceName);

            XElement metadataElement = creatElement("metadata", null, false);
            XElement metricElement = creatElement("metrics", new Dictionary<string, string>(){
                {"baseline", string.Format("{0}", depth - baseline)},
                {"axis", string.Format("{0}", depth - baseline + node.Axis())},
                {"top", string.Format("{0}", depth + node.Height)},
                {"bottom", string.Format("{0}", depth - node.Depth)}
            }, true);
            metadataElement.Add(metricElement);
            nodeElement.Add(metadataElement);
            DrawTranslatedNode(node, nodeElement, 0, -baseline);
            return nodeElement;
        }
Beispiel #2
0
		public static void DefaultContext(MathNode node)
		{
			if (node.Parent != null)
			{
				node.MathSize = node.Parent.MathSize;
				node.FontSize = node.Parent.FontSize;
				node.MetricList = node.Parent.MetricList;
				node.ScriptLevel = node.Parent.ScriptLevel;
				node.TightSpaces = node.Parent.TightSpaces;
				node.DisplayStyle = node.Parent.DisplayStyle;
				node.Color = node.Parent.Color;
				node.FontFamilies = node.Parent.FontFamilies;
				node.FontWeight = node.Parent.FontWeight;
				node.FontStyle = node.Parent.FontStyle;
				node.NodeDefaults = node.Parent.NodeDefaults;
				node.Parent.MakeChildContext(node);
			}
			else
			{
				node.MathSize = node.ParseLength(node.NodeDefaults["mathsize"]);
				node.FontSize = node.MathSize;
				node.MetricList = null;
				node.ScriptLevel = int.Parse(node.NodeDefaults["scriptlevel"]);
				node.TightSpaces = false;
				node.DisplayStyle = (node.NodeDefaults["displaystyle"] == "true");
				node.Color = node.NodeDefaults["mathcolor"];

				if (!node.Config.Variants.ContainsKey(node.NodeDefaults["mathvariant"]))
					throw new InvalidOperationException("Default mathvariant not defined in configuration file: configuration is unusable");

				MathVariant defaultVariant = node.Config.Variants[node.NodeDefaults["mathvariant"]];
				node.FontWeight = defaultVariant.Weight;
				node.FontStyle = defaultVariant.Style;
				node.FontFamilies = defaultVariant.Families;
			}

			node.ProcessFontAttributes();
			node.Width = 0;
			node.Height = 0;
			node.Depth = 0;
			node.Ascender = 0;
			node.Descender = 0;
			node.LeftSpace = 0;
			node.RightSpace = 0;
			node.AlignToAxis = false;
			node.Base = node;
			node.Core = node;
			node.Stretchy = false;
			node.Accent = false;
			node.MoveLimits = false;
			node.TextShift = 0;
			node.TextStretch = 1;
			node.LeftBearing = 0;
			node.RightBearing = 0;
			node.IsSpace = false;
			//Reset metrics list to None(so far, we used metrics from the parent)
			node.MetricList = null;
			node.NominalMetric = null;
		}
Beispiel #3
0
		public XElement MakeSvg()
		{
			m_mathConfig = new MathConfig(m_configFileName);
			MathNode currentNode = new MathNode(
				m_mathDocument.Root.Name.LocalName,
				m_mathDocument.Root.Attributes().ToDictionary(kvp => kvp.Name.ToString(), kvp => kvp.Value),
				m_mathConfig,
				null);
			ParseMML(m_mathDocument.Root, currentNode, 0);
			return currentNode.MakeImage();
		}
Beispiel #4
0
		public RowDescriptor(MathNode node, List<MathNode> childCells, string rowalign, List<string> columnaligns, List<int> busycells)
		{
			AlignToAxis = (rowalign == "axis");
			Height = 0;
			Depth = 0;
			SpaceAfter = 0;
			Cells = new List<CellDescriptor>();
			
			foreach (MathNode c in childCells)
			{
				// Find first free cell
				while (busycells.Count > Cells.Count && busycells[Cells.Count] > 0)
				{
					Cells.Add(null);
				}

				string halign = Measurer.GetByIndexOrLast(columnaligns, Cells.Count);
				string valign = rowalign;
				int colspan = 1;
				int rowspan = 1;

				if (c.ElementName == "mtd")
				{
					if (c.Attributes.ContainsKey("columnalign"))
						halign = c.Attributes["columnalign"];
					
					if (c.Attributes.ContainsKey("rowalign"))
						valign = c.Attributes["rowalign"];

					colspan = int.Parse(c.Attributes.ContainsKey("colspan") ? c.Attributes["colspan"] : "1");
					rowspan = int.Parse(c.Attributes.ContainsKey("rowspan") ? c.Attributes["rowspan"] : "1");
				}

				while (Cells.Count >= node.Columns.Count)
					node.Columns.Add(new ColumnDescriptor());

				Cells.Add(new CellDescriptor(c, halign, valign, colspan, rowspan));

				for (int i = 1; i< colspan; i++)
				{
					Cells.Add(null);
				}

				while (Cells.Count > node.Columns.Count)
					node.Columns.Add(new ColumnDescriptor());

			}

		}
Beispiel #5
0
        public static void MakeLimitContext(MathNode node, MathNode child, string accentProperty)
        {
            child.DisplayStyle = false;
            child.TightSpaces  = true;
            string accentValue = node.GetProperty(accentProperty);

            if (accentValue == null)
            {
                accentValue = GetAccentValue(child);
            }

            child.Accent = (accentValue == "true");
            if (!child.Accent)
            {
                child.ScriptLevel += 1;
            }
        }
Beispiel #6
0
        public static void GMSqrt(MathNode node, XElement output)
        {
            DrawBox(node, output);
            DrawTranslatedNode(node.Base, output, node.Width - node.Base.Width - node.Gap, 0);
            // Basic contour
            double x1 = node.Width - node.Base.Width - node.RootWidth - 2 * node.Gap;
            double y1 = (node.RootDepth - node.RootHeight) / 2;
            double x2 = x1 + node.RootWidth * 0.2;
            double y2 = y1;
            double x3 = x1 + node.RootWidth * 0.6;
            double y3 = node.RootDepth;
            double x4 = x1 + node.RootWidth;
            double y4 = (-node.RootHeight) + node.LineWidth / 2;
            double x5 = node.Width;
            double y5 = y4;
            // Thickening
            double slopeA = (x2 - x3) / (y2 - y3);
            double slopeB = (x3 - x4) / (y3 - y4);
            double x2a    = x2 + (node.ThickLineWidth - node.LineWidth);
            double y2a    = y2;
            double x2c    = x2 + node.LineWidth * slopeA / 2;
            double y2c    = y2 + node.LineWidth * 0.9;
            double x2b    = x2c + (node.ThickLineWidth - node.LineWidth) / 2;
            double y2b    = y2c;
            double ytmp   = y3 - node.LineWidth / 2;
            double xtmp   = x3 - node.LineWidth * (slopeA + slopeB) / 4;
            double y3a    = (y2a * slopeA - ytmp * slopeB + xtmp - x2a) / (slopeA - slopeB);
            double x3a    = xtmp + (y3a - ytmp) * slopeB;
            double y3b    = (y2b * slopeA - ytmp * slopeB + xtmp - x2b) / (slopeA - slopeB);
            double x3b    = xtmp + (y3b - ytmp) * slopeB;

            // Lean the left protrusion down
            y1 += (x2 - x1) * slopeA;
            Dictionary <string, string> attrs = new Dictionary <string, string>()
            {
                { "stroke", node.Color },
                { "fill", "none" },
                { "stroke-width", string.Format(CultureInfo.InvariantCulture, "{0:F6}", node.LineWidth) },
                { "stroke-linecap", "butt" },
                { "stroke-linejoin", "miter" },
                { "stroke-miterlimit", "10" },
                { "d", string.Format(CultureInfo.InvariantCulture, "M {0:F6} {1:F6} L {2:F6} {3:F6} L {4:F6} {5:F6} L {6:F6} {7:F6} L {8:F6} {9:F6} L {10:F6} {11:F6} L {12:F6} {13:F6} L {14:F6} {15:F6} L {16:F6} {17:F6}", x1, y1, x2a, y2a, x3a, y3a, x3b, y3b, x2b, y2b, x2c, y2c, x3, y3, x4, y4, x5, y5) }
            };

            output.Add(creatElement("path", attrs));
        }
Beispiel #7
0
        public void MakeChildContext(MathNode child)
        {
            switch (ElementName)
            {
            case "mfrac":
                MathContext.ChildCMFrac(this, child);
                break;

            case "mroot":
                MathContext.ChildCMRoot(this, child);
                break;

            case "msub":
                MathContext.ChildCMSub(this, child);
                break;

            case "msup":
                MathContext.ChildCMSup(this, child);
                break;

            case "msubsup":
                MathContext.ChildCMSubSup(this, child);
                break;

            case "mmultiscripts":
                MathContext.ChildCMMultiScripts(this, child);
                break;

            case "munder":
                MathContext.ChildCMUnder(this, child);
                break;

            case "mover":
                MathContext.ChildCMOver(this, child);
                break;

            case "munderover":
                MathContext.ChildCMUnderOver(this, child);
                break;

            default:
                MathContext.DefaultChildContext(this, child);
                break;
            }
        }
Beispiel #8
0
		public static void ParseMML(XElement root, MathNode parentNode, MathConfig mc, int depth)
		{
			int recDepth = depth + 1;
			foreach (XElement element in root.Elements())
			{
				//ToDo: implement namespaces
				Console.WriteLine("{0} {1}", new String(' ', recDepth), element.Name);
				MathNode mn = new MathNode(
                    element.Name.LocalName,
                    element.Attributes().ToDictionary(kvp => kvp.Name.ToString(), kvp => kvp.Value),
                    mc, parentNode);
                element.Nodes()
                    .Where(x => x.NodeType == System.Xml.XmlNodeType.Text || x.NodeType == System.Xml.XmlNodeType.Whitespace)
                    .ToList()
                    .ForEach(x => mn.Text = mn.Text + string.Join(" ", ((XText)x).Value.Split(null)));
				ParseMML(element, mn, mc, recDepth);
			}
		}
Beispiel #9
0
        public XElement MakeSvg()
        {
            // need to enforce point as decimal seperator, otherwise it will fail.
            CultureInfo customCulture = CultureInfo.CurrentCulture.Clone() as CultureInfo;

            customCulture.NumberFormat.NumberDecimalSeparator = ".";
            CultureInfo.CurrentCulture = customCulture;

            m_mathConfig = new MathConfig(m_configFileName);
            MathNode currentNode = new MathNode(
                m_mathDocument.Root.Name.LocalName,
                m_mathDocument.Root.Attributes().ToDictionary(kvp => kvp.Name.ToString(), kvp => kvp.Value),
                m_mathConfig,
                null);

            ParseMML(m_mathDocument.Root, currentNode, 0);
            return(currentNode.MakeImage());
        }
Beispiel #10
0
        public static void CMStyle(MathNode node)
        {
            DefaultContext(node);
            // Avoid redefinition of mathsize - it is inherited anyway.
            // This serves to preserve values of 'big', 'small', and 'normal'
            // throughout the MathML instance.
            if (node.Attributes != null && node.Attributes.ContainsKey("mathsize"))
            {
                node.Attributes.Remove("mathsize");
            }

            if (node.Attributes != null)
            {
                Dictionary <string, string> newDefaults = new Dictionary <string, string>(node.NodeDefaults);
                newDefaults.AddRange(node.Attributes);
                node.NodeDefaults = newDefaults;
            }
        }
Beispiel #11
0
        public static void DrawTranslatedNode(MathNode node, XElement output, double dx, double dy)
        {
            if (dx != 0 || dy != 0)
            {
                XElement svge = creatElement("g", new Dictionary <string, string>()
                {
                    { "transform", string.Format(CultureInfo.InvariantCulture, "translate({0}, {1})", dx, dy) }
                });
                node.Draw(svge);
                output.Add(svge);
            }
            else
            {
                node.Draw(output);
            }

            //ToDo:Check implementation
        }
Beispiel #12
0
        public static void GMRow(MathNode node, XElement output)
        {
            DrawBox(node, output);
            if (node.Children.Count == 0)
                return;

            double offset = -node.Children.First().LeftSpace;
            foreach (MathNode ch in node.Children)
            {
                offset += ch.LeftSpace;
                double baseline = 0;
                if (ch.AlignToAxis && !node.AlignToAxis) //ToDo: might not behave the same as Python since aligntoaxis might be none
                    baseline = -node.Axis();

                DrawTranslatedNode(ch, output, offset, baseline);
                offset += ch.Width + ch.RightSpace;
            }
        }
Beispiel #13
0
		void ParseMML(XElement root, MathNode parentNode, int depth)
		{
			int recDepth = depth + 1;
			foreach (XElement element in root.Elements())
			{
				MathNode mn = new MathNode(
					element.Name.LocalName,
					element.Attributes().ToDictionary(kvp => kvp.Name.ToString(), kvp => kvp.Value),
					m_mathConfig, parentNode);

				element.Nodes()
					.Where(x => x.NodeType == System.Xml.XmlNodeType.Text || x.NodeType == System.Xml.XmlNodeType.Whitespace)
					.ToList()
					.ForEach(x => mn.Text = mn.Text + string.Join(" ", ((XText)x).Value.Split(null)));

				ParseMML(element, mn, recDepth);
			}
		}
Beispiel #14
0
        public static void DrawSVGText(MathNode node, XElement output)
        {
            DrawBox(node, output);
            List <string> fontFamilies = node.FontPool().Where(x => x.Used == true).Select(x => x.Family).ToList();

            if (fontFamilies.Count == 0)
            {
                fontFamilies = node.FontFamilies;
            }

            Dictionary <string, string> attrs = new Dictionary <string, string>()
            {
                { "fill", node.Color },
                { "font-family", string.Join(", ", fontFamilies) },
                { "font-size", string.Format(CultureInfo.InvariantCulture, "{0}", node.FontSize) },
                { "text-anchor", "middle" },
                { "x", string.Format(CultureInfo.InvariantCulture, "{0}", (node.Width + node.LeftBearing - node.RightBearing) / 2 / node.TextStretch) },
                { "y", string.Format(CultureInfo.InvariantCulture, "{0}", -node.TextShift) }
            };

            if (node.FontWeight != "normal")
            {
                attrs["font-weight"] = node.FontWeight;
            }
            if (node.FontStyle != "normal")
            {
                attrs["font-style"] = node.FontStyle;
            }
            if (node.TextStretch != 1)
            {
                attrs["transform"] = string.Format(CultureInfo.InvariantCulture, "scale({0}, 1)", node.TextStretch);
            }

            foreach (KeyValuePair <int, char> ch in MathDefaults.SpecialChars)
            {
                node.Text = node.Text.Replace((char)ch.Key, ch.Value); //ToDo: validate
            }

            XElement nxe   = creatElement("text", attrs);
            XText    chars = new XText(node.Text);

            nxe.Add(chars);
            output.Add(nxe);
        }
Beispiel #15
0
        private void ParseMML(XElement root, MathNode parentNode, int depth)
        {
            int recDepth = depth + 1;

            foreach (XElement element in root.Elements())
            {
                MathNode mn = new MathNode(
                    element.Name.LocalName,
                    element.Attributes().ToDictionary(kvp => kvp.Name.ToString(), kvp => kvp.Value),
                    m_mathConfig, parentNode);

                element.Nodes()
                .Where(x => x.NodeType == System.Xml.XmlNodeType.Text || x.NodeType == System.Xml.XmlNodeType.Whitespace)
                .ToList()
                .ForEach(x => mn.Text = mn.Text + string.Join(" ", ((XText)x).Value.Split(null)));

                ParseMML(element, mn, recDepth);
            }
        }
Beispiel #16
0
        public static void DrawCircleEnclosure(MathNode node, XElement output)
        {
            string background = GetBackGround(node);
            double r          = (node.Width - node.BorderWidth) / 2;
            double cx         = node.Width / 2;
            double cy         = (node.Depth - node.Height) / 2;

            Dictionary <string, string> attrs = new Dictionary <string, string>()
            {
                { "fill", background },
                { "stroke", node.Color },
                { "stroke-width", string.Format(CultureInfo.InvariantCulture, "{0}", node.BorderWidth) },
                { "cx", string.Format(CultureInfo.InvariantCulture, "{0}", cx) },
                { "cy", string.Format(CultureInfo.InvariantCulture, "{0}", cy) },
                { "r", string.Format(CultureInfo.InvariantCulture, "{0}", r) }
            };

            output.Add(creatElement("circle", attrs));
            DrawTranslatedNode(node.Base, output, (node.Width - node.Base.Width) / 2, 0);
        }
Beispiel #17
0
        public static XElement DrawImage(MathNode node)
        {
            //Top-level draw function: prepare the canvas, then call the draw method of the root node
            double baseline = 0;

            if (node.AlignToAxis)
            {
                baseline = node.Axis();
            }

            double height = Math.Max(node.Height, node.Ascender);
            double depth  = Math.Max(node.Depth, node.Descender);
            double vsize  = height + depth;

            Dictionary <string, string> attrs = new Dictionary <string, string>()
            {
                { "width", string.Format(CultureInfo.InvariantCulture, "{0:F6}pt", node.Width) },
                { "height", string.Format(CultureInfo.InvariantCulture, "{0:F6}pt", vsize) },
                { "viewBox", string.Format(CultureInfo.InvariantCulture, "0 {0:F6} {1:F6} {2:F6}", (-(height + baseline)), node.Width, vsize) }
            };


            XElement nodeElement = creatElement("svg", attrs);

            nodeElement.SetAttributeValue(XNamespace.Xmlns + "svg", SvgNs.NamespaceName);
            nodeElement.SetAttributeValue(XNamespace.Xmlns + "svgmath", SvgMathNs.NamespaceName);

            XElement metadataElement = creatElement("metadata", null, false);
            XElement metricElement   = creatElement("metrics", new Dictionary <string, string>()
            {
                { "baseline", string.Format(CultureInfo.InvariantCulture, "{0}", depth - baseline) },
                { "axis", string.Format(CultureInfo.InvariantCulture, "{0}", depth - baseline + node.Axis()) },
                { "top", string.Format(CultureInfo.InvariantCulture, "{0}", depth + node.Height) },
                { "bottom", string.Format(CultureInfo.InvariantCulture, "{0}", depth - node.Depth) }
            }, true);

            metadataElement.Add(metricElement);
            nodeElement.Add(metadataElement);
            DrawTranslatedNode(node, nodeElement, 0, -baseline);
            return(nodeElement);
        }
Beispiel #18
0
 public static string GetAccentValue(MathNode node)
 {
     if (node.ElementName == "mo")
     {
         if (node.OpDefaults != null)
         {
             return(node.OpDefaults.Dict()["accent"]);
         }
         else
         {
             return("false");
         }
     }
     else if (MathDefaults.Embellishments.Any(x => x == node.ElementName) && node.Children.Count > 0)
     {
         return(GetAccentValue(node.Children[0]));
     }
     else
     {
         return("false");
     }
 }
Beispiel #19
0
		public static void CMath(MathNode node)
		{
			DefaultContext(node);
			// Display style: set differently on 'math'
			string attr = null;
			if (node.Attributes.ContainsKey("display"))
            { 
				attr = node.Attributes["display"];
				node.DisplayStyle = (node.Attributes["display"] == "block");
			}
			else
			{
                if (node.Attributes.ContainsKey("mode"))
                {
                    attr = node.Attributes["mode"];
                    node.DisplayStyle = (attr == "display");
                }
                else
                {
                    node.DisplayStyle = false;
                }
			}
		}
Beispiel #20
0
        public static void GMRow(MathNode node, XElement output)
        {
            DrawBox(node, output);
            if (node.Children.Count == 0)
            {
                return;
            }

            double offset = -node.Children.First().LeftSpace;

            foreach (MathNode ch in node.Children)
            {
                offset += ch.LeftSpace;
                double baseline = 0;
                if (ch.AlignToAxis && !node.AlignToAxis) //ToDo: might not behave the same as Python since aligntoaxis might be none
                {
                    baseline = -node.Axis();
                }

                DrawTranslatedNode(ch, output, offset, baseline);
                offset += ch.Width + ch.RightSpace;
            }
        }
Beispiel #21
0
        public static void DrawBox(MathNode node, XElement output, double?borderWidth = null, string borderColor = null, double borderRadius = 0)
        {
            string background = GetBackGround(node);

            if (background == "none" && (borderWidth == null || borderWidth == 0))
            {
                return;
            }
            if (borderColor == null)
            {
                borderColor = node.Color;
            }

            Dictionary <string, string> attrs = new Dictionary <string, string>
            {
                { "fill", background },
                { "stroke", "none" },
                { "x", string.Format(CultureInfo.InvariantCulture, "{0}", (double)borderWidth / 2) },
                { "y", string.Format(CultureInfo.InvariantCulture, "{0}", (double)borderWidth / 2 - node.Height) },
                { "width", string.Format(CultureInfo.InvariantCulture, "{0}", node.Width - (double)borderWidth) },
                { "height", string.Format(CultureInfo.InvariantCulture, "{0}", node.Height + node.Depth - (double)borderWidth) }
            };

            if (borderWidth != null && borderColor != null)
            {
                attrs["stroke"]       = borderColor;
                attrs["stroke-width"] = string.Format(CultureInfo.InvariantCulture, "{0}", borderWidth);
                if (borderRadius != 0)
                {
                    attrs.Add("rx", string.Format(CultureInfo.InvariantCulture, "{0}", borderRadius));
                    attrs.Add("ry", string.Format(CultureInfo.InvariantCulture, "{0}", borderRadius));
                }
            }
            XElement rect = creatElement("rect", attrs);

            output.Add(rect);
        }
Beispiel #22
0
 public MathNode(string elementName, Dictionary <string, string> attributes, MathConfig config, MathNode parent)
 {
     ElementName   = elementName;
     Config        = config;
     Text          = "";
     Children      = new List <MathNode>();
     Attributes    = attributes;
     Parent        = parent;
     MetricList    = null;
     FontFamilies  = new List <string>();
     NominalMetric = null;
     if (parent != null)
     {
         NodeIndex    = parent.Children == null ? 0 : parent.Children.Count;
         NodeDefaults = parent.NodeDefaults;
         Parent.Children.Add(this);
     }
     else
     {
         NodeDefaults = MathDefaults.globalDefaults;
         Config.Defaults.Keys.ToList().ForEach(x => NodeDefaults[x] = Config.Defaults[x]);
         NodeIndex = 0;
     }
 }
Beispiel #23
0
		public void MakeChildContext(MathNode child)
		{
			switch (ElementName)
			{
				case "mfrac":
					MathContext.ChildCMFrac(this, child);
					break;
				case "mroot":
					MathContext.ChildCMRoot(this, child);
					break;
				case "msub":
					MathContext.ChildCMSub(this, child);
					break;
				case "msup":
					MathContext.ChildCMSup(this, child);
					break;
				case "msubsup":
					MathContext.ChildCMSubSup(this, child);
					break;
				case "mmultiscripts":
					MathContext.ChildCMMultiScripts(this, child);
					break;
				case "munder":
					MathContext.ChildCMUnder(this, child);
					break;
				case "mover":
					MathContext.ChildCMOver(this, child);
					break;
				case "munderover":
					MathContext.ChildCMUnderOver(this, child);
					break;
				default:
					MathContext.DefaultChildContext(this, child);
					break;
			}
		}
Beispiel #24
0
        public MathNode(string elementName, Dictionary<string, string> attributes, MathConfig config, MathNode parent)
        {
            ElementName = elementName;
            Config = config;
            Text = "";
            Children = new List<MathNode>();
            Attributes = attributes;
            Parent = parent;
            MetricList = null;
			FontFamilies = new List<string>();
            NominalMetric = null;
            if (parent != null)
            {
                NodeIndex = parent.Children == null ? 0 : parent.Children.Count;
                NodeDefaults = parent.NodeDefaults;
                Parent.Children.Add(this);
            }
            else
            {
                NodeDefaults = MathDefaults.globalDefaults;
                Config.Defaults.Keys.ToList().ForEach(x => NodeDefaults[x] = Config.Defaults[x]);
                NodeIndex = 0;
            }
        }
Beispiel #25
0
        public static void CMath(MathNode node)
        {
            DefaultContext(node);
            // Display style: set differently on 'math'
            string attr = null;

            if (node.Attributes.ContainsKey("display"))
            {
                attr = node.Attributes["display"];
                node.DisplayStyle = (node.Attributes["display"] == "block");
            }
            else
            {
                if (node.Attributes.ContainsKey("mode"))
                {
                    attr = node.Attributes["mode"];
                    node.DisplayStyle = (attr == "display");
                }
                else
                {
                    node.DisplayStyle = false;
                }
            }
        }
Beispiel #26
0
        public static void DrawBordersEnclosure(MathNode node, XElement output)
        {
            DrawBox(node, output);
            double x1 = node.BorderWidth / 2;
            double y1 = node.BorderWidth / 2 - node.Height;
            double x2 = node.Width - node.BorderWidth / 2;
            double y2 = node.Depth - node.BorderWidth / 2;
            // Left
            if (node.DecorationData[0])
                DrawBorder(node, output, x1, y1, x1, y2);
            // Right
            if (node.DecorationData[1])
                DrawBorder(node, output, x2, y1, x2, y2);
            // top
            if (node.DecorationData[2])
                DrawBorder(node, output, x1, y1, x2, y1);
            // bottom
            if (node.DecorationData[3])
                DrawBorder(node, output, x1, y2, x2, y2);

            double offset;
            //Left
            if (node.DecorationData[0])
            {
                offset = node.Width - node.Base.Width;
                //Right
                if (node.DecorationData[1])
                    offset /= 2;
            }
            else
            {
                offset = 0;
            }
            DrawTranslatedNode(node.Base, output, offset, 0);
        }
Beispiel #27
0
 public static void GMAction(MathNode node, XElement output)
 {
     if (node.Base != null)
         node.Base.Draw(output);
 }
Beispiel #28
0
        public static void DrawTranslatedNode(MathNode node, XElement output, double dx, double dy)
        {
            if (dx != 0 || dy != 0)
            {
                XElement svge = creatElement("g", new Dictionary<string, string>() { { "transform", string.Format("translate({0}, {1})", dx, dy) } });
                node.Draw(svge);
                output.Add(svge);
            }
            else
            {
                node.Draw(output);
            }

            //ToDo:Check implementation
        }
Beispiel #29
0
 public static void DefaultDraw(MathNode node, XElement output)
 {
     //Matching Python
     //Pass
 }
Beispiel #30
0
 public static void GMSpace(MathNode node, XElement output)
 {
     DrawSVGText(node, output);
 }
Beispiel #31
0
 public static void GMError(MathNode node, XElement output)
 {
     DrawBox(node, output, node.BorderWidth, "red");
     DrawTranslatedNode(node.Base, output, node.BorderWidth, 0);
 }
Beispiel #32
0
        public static void DefaultContext(MathNode node)
        {
            if (node.Parent != null)
            {
                node.MathSize     = node.Parent.MathSize;
                node.FontSize     = node.Parent.FontSize;
                node.MetricList   = node.Parent.MetricList;
                node.ScriptLevel  = node.Parent.ScriptLevel;
                node.TightSpaces  = node.Parent.TightSpaces;
                node.DisplayStyle = node.Parent.DisplayStyle;
                node.Color        = node.Parent.Color;
                node.FontFamilies = node.Parent.FontFamilies;
                node.FontWeight   = node.Parent.FontWeight;
                node.FontStyle    = node.Parent.FontStyle;
                node.NodeDefaults = node.Parent.NodeDefaults;
                node.Parent.MakeChildContext(node);
            }
            else
            {
                node.MathSize     = node.ParseLength(node.NodeDefaults["mathsize"]);
                node.FontSize     = node.MathSize;
                node.MetricList   = null;
                node.ScriptLevel  = int.Parse(node.NodeDefaults["scriptlevel"]);
                node.TightSpaces  = false;
                node.DisplayStyle = (node.NodeDefaults["displaystyle"] == "true");
                node.Color        = node.NodeDefaults["mathcolor"];

                if (!node.Config.Variants.ContainsKey(node.NodeDefaults["mathvariant"]))
                {
                    throw new InvalidOperationException("Default mathvariant not defined in configuration file: configuration is unusable");
                }

                MathVariant defaultVariant = node.Config.Variants[node.NodeDefaults["mathvariant"]];
                node.FontWeight   = defaultVariant.Weight;
                node.FontStyle    = defaultVariant.Style;
                node.FontFamilies = defaultVariant.Families;
            }

            node.ProcessFontAttributes();
            node.Width        = 0;
            node.Height       = 0;
            node.Depth        = 0;
            node.Ascender     = 0;
            node.Descender    = 0;
            node.LeftSpace    = 0;
            node.RightSpace   = 0;
            node.AlignToAxis  = false;
            node.Base         = node;
            node.Core         = node;
            node.Stretchy     = false;
            node.Accent       = false;
            node.MoveLimits   = false;
            node.TextShift    = 0;
            node.TextStretch  = 1;
            node.LeftBearing  = 0;
            node.RightBearing = 0;
            node.IsSpace      = false;
            //Reset metrics list to None(so far, we used metrics from the parent)
            node.MetricList    = null;
            node.NominalMetric = null;
        }
Beispiel #33
0
 public static void GMError(MathNode node, XElement output)
 {
     DrawBox(node, output, node.BorderWidth, "red");
     DrawTranslatedNode(node.Base, output, node.BorderWidth, 0);
 }
Beispiel #34
0
 public static void GMFenced(MathNode node, XElement output)
 {
     GMRow(node, output);
 }
Beispiel #35
0
 public static void GMPhantom(MathNode node, XElement output)
 {
     //Pass
 }
Beispiel #36
0
        public static void DrawScripts(MathNode node, XElement output)
        {
            //ToDo: figger wat to match python
            //    if len(node.children) < 2:
            //      draw_mrow(node); return

            double subY = node.SubShift;
            double superY = -node.SuperShift;

            DrawBox(node, output);
            double offset = 0;
            foreach (var item in node.PreWidths.Select((value, i) => new { i, value }))
            {
                offset += node.PreWidths[item.i];
                if (item.i < node.PreSubScripts.Count)
                {
                    MathNode presubscript = node.PreSubScripts[item.i];
                    DrawTranslatedNode(presubscript, output, offset - presubscript.Width, subY - Adjustment(presubscript));
                }
                if (item.i < node.PreSuperScripts.Count)
                {
                    MathNode presuperscript = node.PreSuperScripts[item.i];
                    DrawTranslatedNode(presuperscript, output, offset - presuperscript.Width, superY - Adjustment(presuperscript));
                }
            }
            DrawTranslatedNode(node.Base, output, offset, 0);
            offset += node.Base.Width;

            foreach (var item in node.PostWidths.Select((value, i) => new { i, value }))
            {
                if (item.i < node.SubScripts.Count)
                {
                    MathNode subscript = node.SubScripts[item.i];
                    DrawTranslatedNode(subscript, output, offset, subY - Adjustment(subscript));
                }
                if (item.i < node.SuperScripts.Count)
                {
                    MathNode superscript = node.SuperScripts[item.i];
                    DrawTranslatedNode(superscript, output, offset, superY - Adjustment(superscript));
                }
                offset += node.PostWidths[item.i];
            }
        }
Beispiel #37
0
 public static void GMNone(MathNode node, XElement output)
 {
     //Pass
 }
Beispiel #38
0
        public static void DrawStrikesEnclosure(MathNode node, XElement output)
        {
            DrawBox(node, output);
            node.Base.Draw(output);

            double mid_x = node.Width / 2;
            double mid_y = (node.Depth - node.Height) / 2;
            // horizontal
            if (node.DecorationData[0])
                DrawStrike(node, output, 0, mid_y, node.Width, mid_y);
            // vert
            if (node.DecorationData[1])
                DrawStrike(node, output, mid_x, -node.Height, mid_x, node.Depth);
            // updiag
            if (node.DecorationData[2])
                DrawStrike(node, output, 0, node.Depth, node.Width, -node.Height);
            // downdiag
            if (node.DecorationData[3])
                DrawStrike(node, output, 0, -node.Height, node.Width, node.Depth);
        }
Beispiel #39
0
        public static void DrawSVGText(MathNode node, XElement output)
        {
            DrawBox(node, output);
            List<string> fontFamilies = node.FontPool().Where(x => x.Used == true).Select(x => x.Family).ToList();
            if (fontFamilies.Count == 0)
                fontFamilies = node.FontFamilies;

            Dictionary<string, string> attrs = new Dictionary<string, string>()
            {
                { "fill", node.Color },
                { "font-family", string.Join(", ",fontFamilies) },
                { "font-size", node.FontSize.ToString() },
                { "text-anchor", "middle" },
                { "x", string.Format("{0}",(node.Width + node.LeftBearing - node.RightBearing) / 2 / node.TextStretch)},
                { "y", (-node.TextShift).ToString()}
            };

            if (node.FontWeight != "normal")
                attrs["font-weight"] = node.FontWeight;
            if (node.FontStyle != "normal")
                attrs["font-style"] = node.FontStyle;
            if (node.TextStretch != 1)
                attrs["transform"] = string.Format("scale({0}, 1)", node.TextStretch);

            foreach (KeyValuePair<int, char> ch in MathDefaults.SpecialChars)
            {
                node.Text = node.Text.Replace((char)ch.Key, ch.Value); //ToDo: validate
            }

            XElement nxe = creatElement("text", attrs);
            XText chars = new XText(node.Text);
            nxe.Add(chars);
            output.Add(nxe);
        }
Beispiel #40
0
 public static double GetAlign(MathNode node, string attrName)
 {
     string attrValue = node.GetProperty(attrName, "center");
     if (alignKeywords.ContainsKey(attrValue))
     {
         return alignKeywords[attrValue];
     }
     else
     {
         return 0.5;
         //ToDO: node.error("Bad value %s for %s", attrValue, attrName)
     }
 }
Beispiel #41
0
 public static void GMPrescripts(MathNode node, XElement output)
 {
     //Pass
 }
Beispiel #42
0
 public static void DrawBoxEnclosure(MathNode node, XElement output, double roundRadius = 0)
 {
     DrawBox(node, output, node.BorderWidth, null, roundRadius);
     DrawTranslatedNode(node.Base, output, (node.Width - node.Base.Width) / 2, 0);
 }
Beispiel #43
0
 public static void GMPAdded(MathNode node, XElement output)
 {
     DrawBox(node, output);
     DrawTranslatedNode(node.Base, output, node.LeftPadding, 0);
 }
Beispiel #44
0
        public static void DrawCircleEnclosure(MathNode node, XElement output)
        {
            string background = GetBackGround(node);
            double r = (node.Width - node.BorderWidth) / 2;
            double cx = node.Width / 2;
            double cy = (node.Depth - node.Height) / 2;

            Dictionary<string, string> attrs = new Dictionary<string, string>()
            {
                { "fill", background},
                {"stroke", node.Color },
                { "stroke-width", node.BorderWidth.ToString() },
                { "cx", cx.ToString() },
                { "cy", cy.ToString() },
                { "r", r.ToString() }
            };
            output.Add(creatElement("circle", attrs));
            DrawTranslatedNode(node.Base, output, (node.Width - node.Base.Width) / 2, 0);
        }
Beispiel #45
0
        public static void GMTable(MathNode node, XElement output)
        {
            DrawBox(node, output);
            //Draw cells
            double vshift = -node.Height + node.FrameSpacings[1];
            double hshift;

            foreach (var rowItem in node.Rows.Select((value, r) => new { r, value }))
            {
                RowDescriptor row = rowItem.value;
                vshift += row.Height;
                hshift  = node.FrameSpacings[0];
                foreach (var cellItem in row.Cells.Select((value, c) => new { c, value }))
                {
                    ColumnDescriptor column = node.Columns[cellItem.c];
                    CellDescriptor   cell   = row.Cells[cellItem.c];
                    if (cell != null && cell.Content != null)
                    {
                        double cellWidth;
                        // Calculate horizontal alignment
                        if (cell.ColSpan > 1)
                        {
                            cellWidth  = node.Columns.Skip(cellItem.c).Take(cellItem.c + cell.ColSpan).Select(x => x.Width).Sum();          //ToDo: verify
                            cellWidth += node.Columns.Skip(cellItem.c).Take(cellItem.c + cell.ColSpan - 1).Select(x => x.SpaceAfter).Sum(); //ToDo: verify
                        }
                        else
                        {
                            cellWidth = column.Width;
                        }
                        double hadjust = (cellWidth - cell.Content.Width) * (alignKeywords.ContainsKey(cell.HAlign) ? alignKeywords[cell.HAlign] : 0.5);

                        // Calculate vertical alignment.
                        double cellHeight;
                        if (cell.RowSpan > 1)
                        {
                            cellHeight  = node.Rows.Skip(rowItem.r).Take(rowItem.r + cell.RowSpan).Select(x => x.Height + x.Depth).Sum(); //ToDo: Verify
                            cellHeight += node.Rows.Skip(rowItem.r).Take(rowItem.r + cell.RowSpan - 1).Select(x => x.SpaceAfter).Sum();   //ToDo: Verify
                        }
                        else
                        {
                            cellHeight = row.Height + row.Depth;
                        }

                        double vadjust;
                        if (cell.VAlign == "top")
                        {
                            vadjust = cell.Content.Height - row.Height;
                        }
                        else if (cell.VAlign == "bottom")
                        {
                            vadjust = cellHeight - row.Height - cell.Content.Depth;
                        }
                        else if ((cell.VAlign == "axis" || cell.VAlign == "baseline") && cell.RowSpan == 1)
                        {
                            vadjust = -cell.VShift; // calculated in the measurer
                        }
                        else
                        {
                            vadjust = (cell.Content.Height - cell.Content.Depth + cellHeight) / 2 - row.Height;
                        }
                        DrawTranslatedNode(cell.Content, output, hshift + hadjust, vshift + vadjust);
                    }
                    hshift += column.Width + column.SpaceAfter;
                }
                vshift += row.Depth + row.SpaceAfter;
            }

            //Draw frame
            double x1 = node.LineWidth / 2;
            double y1 = node.LineWidth / 2 - node.Height;
            double x2 = node.Width - node.LineWidth / 2;
            double y2 = node.Depth - node.LineWidth / 2;

            DrawBorder(node, output, x1, y1, x1, y2, node.FrameLines[0]);
            DrawBorder(node, output, x2, y1, x2, y2, node.FrameLines[0]);
            DrawBorder(node, output, x1, y1, x2, y1, node.FrameLines[1]);
            DrawBorder(node, output, x1, y2, x2, y2, node.FrameLines[1]);

            // Draw intermediate lines
            // First, let's make a grid
            hshift = node.FrameSpacings[0];
            List <double> hoffsets = new List <double>();

            foreach (var item in node.Columns.Select((value, c) => new { c, value }))
            {
                double spacing = item.value.SpaceAfter;
                hshift += item.value.Width;
                hoffsets.Add(hshift + spacing / 2);
                hshift += spacing;
            }
            hoffsets[hoffsets.Count - 1] = x2;

            vshift = -node.Height + node.FrameSpacings[1];
            List <double> voffsets = new List <double>();

            foreach (var item in node.Rows.Select((value, r) => new { r, value }))
            {
                double spacing = item.value.SpaceAfter;
                vshift += item.value.Height + item.value.Depth;
                voffsets.Add(vshift + spacing / 2);
                vshift += spacing;
            }
            voffsets[voffsets.Count - 1] = y2;

            List <double> vspans = Enumerable.Repeat <double>(0, node.Columns.Count).ToList();

            for (int r = 0; r < node.Rows.Count - 1; r++)
            {
                RowDescriptor row = node.Rows[r];
                if (row.LineAfter == null)
                {
                    continue;
                }

                foreach (var cellItem in row.Cells.Select((value, c) => new { c, value }))
                {
                    CellDescriptor cell = cellItem.value;
                    if (cell == null || cell.ColSpan == 0)
                    {
                        continue;
                    }
                    for (int i = cellItem.c; i < cellItem.c + cell.ColSpan; i++)
                    {
                        vspans[i] = cell.RowSpan;
                    }
                }
                vspans = vspans.Select(x => Math.Max(0, x - 1)).ToList();

                double lineY  = voffsets[r];
                double startX = x1;
                double endX   = x1;
                foreach (var cellItem in node.Columns.Select((value, c) => new { c, value }))
                {
                    if (vspans[cellItem.c] > 0)
                    {
                        DrawBorder(node, output, startX, lineY, endX, lineY, row.LineAfter);
                        startX = hoffsets[cellItem.c];
                    }
                    endX = hoffsets[cellItem.c];
                }
                DrawBorder(node, output, startX, lineY, endX, lineY, row.LineAfter);
            }

            List <double> hspans = Enumerable.Repeat <double>(0, node.Columns.Count).ToList();

            for (int c = 0; c < node.Columns.Count - 1; c++)
            {
                ColumnDescriptor column = node.Columns[c];
                if (column.LineAfter == null)
                {
                    continue;
                }

                foreach (var rowItem in node.Rows.Select((value, r) => new { r, value }))
                {
                    RowDescriptor row = rowItem.value;
                    if (row.Cells.Count <= c)
                    {
                        continue;
                    }
                    CellDescriptor cell = row.Cells[c];
                    if (cell == null || cell.Content == null)
                    {
                        continue;
                    }
                    for (int j = rowItem.r; j < rowItem.r + cell.RowSpan; j++)
                    {
                        hspans[j] = cell.ColSpan;
                    }
                }
                hspans = hspans.Select(x => Math.Max(0, x - 1)).ToList();
                double lineX  = hoffsets[c];
                double startY = y1;
                double endY   = y1;
                foreach (var item in node.Rows.Select((value, r) => new { r, value }))
                {
                    if (hspans[item.r] > 0)
                    {
                        DrawBorder(node, output, lineX, startY, lineX, endY, column.LineAfter);
                        startY = voffsets[item.r];
                    }
                    endY = voffsets[item.r];
                }
                DrawBorder(node, output, lineX, startY, lineX, endY, column.LineAfter);
            }
        }
Beispiel #46
0
        public static void DrawBorder(MathNode node, XElement output, double x1, double y1, double x2, double y2, string lineStyle)
        {
            if (lineStyle == null)
                return;

            if (x1 == x2 && y1 == y2)
                return;
            Dictionary<string, string> extraStyle = null;
            if (lineStyle == "dashed")
            {
                double linelength = Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
                double dashoffset = 5 - ((linelength / node.LineWidth + 3) % 10) / 2;
                extraStyle = new Dictionary<string, string>()
                {
                    { "stroke-dasharray", string.Format("{0:F6},{1:F6}", node.LineWidth * 7, node.LineWidth * 3)},
                    { "stroke-dashoffset", string.Format("{0:F6}", node.LineWidth * dashoffset) }
                };
            }
            DrawLine(output, node.Color, node.LineWidth, x1, y1, x2, y2, extraStyle);
        }
Beispiel #47
0
 public static void GMath(MathNode node, XElement output)
 {
     GMRow(node, output);
 }
Beispiel #48
0
 public static void DrawBorder(MathNode node, XElement output, double x1, double y1, double x2, double y2)
 {
     DrawLine(output, node.Color, node.BorderWidth, x1, y2, x2, y2);
 }
Beispiel #49
0
 public static double Adjustment(MathNode script)
 {
     if (script.AlignToAxis)
         return script.Axis();
     else
         return 0;
 }
Beispiel #50
0
        public static void DrawLimits(MathNode node, XElement output)
        {
            if (node.Core.MoveLimits)
            {
                DrawScripts(node, output);
                return;
            }

            DrawBox(node, output);
            DrawTranslatedNode(node.Base, output, (node.Width - node.Base.Width) / 2, 0);
            if (node.UnderScript != null)
                DrawTranslatedNode(node.UnderScript, output, (node.Width - node.UnderScript.Width) / 2, node.Depth - node.UnderScript.Depth);
            if (node.OverScript != null)
                DrawTranslatedNode(node.OverScript, output, (node.Width - node.OverScript.Width) / 2, node.OverScript.Height - node.Height);
        }
Beispiel #51
0
 public static void DrawBorder(MathNode node, XElement output, double x1, double y1, double x2, double y2)
 {
     DrawLine(output, node.Color, node.BorderWidth, x1, y2, x2, y2);
 }
Beispiel #52
0
 public static string GetBackGround(MathNode node)
 {
     foreach (string attr in m_backgroundAttributes)
     {
         if (node.Attributes != null && node.Attributes.ContainsKey(attr))
         {
             if (node.Attributes[attr] == "transparent")
                 return "none";
             else
                 return node.Attributes[attr];
         }
     }
     return "none";
 }
Beispiel #53
0
 public static void DrawBoxEnclosure(MathNode node, XElement output, double roundRadius = 0)
 {
     DrawBox(node, output, node.BorderWidth, null, roundRadius);
     DrawTranslatedNode(node.Base, output, (node.Width - node.Base.Width) / 2, 0);
 }
Beispiel #54
0
 public static void GMPrescripts(MathNode node, XElement output)
 {
     //Pass
 }
Beispiel #55
0
 public static void GMPhantom(MathNode node, XElement output)
 {
     //Pass
 }
Beispiel #56
0
 public static void GMStyle(MathNode node, XElement output)
 {
     GMRow(node, output);
 }