/// <summary> /// Create a XmlElement. This is typically called by the base class when creating a DOM tree /// </summary> /// <param name="prefix"></param> /// <param name="localname"></param> /// <param name="nsURI"></param> /// <returns></returns> public override XmlElement CreateElement(string prefix, string localname, string nsURI) { XmlElement result = null; switch (localname) { case "math": result = new MathMLMathElement(prefix, localname, nsURI, this); break; case "mi": case "mn": case "mtext": result = new MathMLPresentationToken(prefix, localname, nsURI, this); break; case "mo": result = new MathMLOperatorElement(prefix, localname, nsURI, this); break; case "mspace": result = new MathMLSpaceElement(prefix, localname, nsURI, this); break; case "ms": result = new MathMLStringLitElement(prefix, localname, nsURI, this); break; case "mglyph": result = new MathMLGlyphElement(prefix, localname, nsURI, this); break; case "mrow": case "merror": case "mphantom": result = new MathMLPresentationContainer(prefix, localname, nsURI, this); break; case "mfrac": result = new MathMLFractionElement(prefix, localname, nsURI, this); break; case "msqrt": case "mroot": result = new MathMLRadicalElement(prefix, localname, nsURI, this); break; case "mstyle": result = new MathMLStyleElement(prefix, localname, nsURI, this); break; case "mpadded": result = new MathMLPaddedElement(prefix, localname, nsURI, this); break; case "mfenced": result = new MathMLFencedElement(prefix, localname, nsURI, this); break; case "menclose": result = new MathMLEncloseElement(prefix, localname, nsURI, this); break; case "msub": case "msup": case "msubsup": result = new MathMLScriptElement(prefix, localname, nsURI, this); break; case "munder": case "mover": case "munderover": result = new MathMLUnderOverElement(prefix, localname, nsURI, this); break; case "mmultiscripts": result = new MathMLMultiScriptsElement(prefix, localname, nsURI, this); break; case "mtable": result = new MathMLTableElement(prefix, localname, nsURI, this); break; case "mlabeledtr": result = new MathMLLabeledRowElement(prefix, localname, nsURI, this); break; case "mtr": result = new MathMLTableRowElement(prefix, localname, nsURI, this); break; case "mtd": result = new MathMLTableCellElement(prefix, localname, nsURI, this); break; case "maligngroup": result = new MathMLAlignGroupElement(prefix, localname, nsURI, this); break; case "malignmark": result = new MathMLAlignMarkElement(prefix, localname, nsURI, this); break; case "maction": result = new MathMLActionElement(prefix, localname, nsURI, this); break; case "cn": result = new MathMLCnElement(prefix, localname, nsURI, this); break; case "ci": result = new MathMLCiElement(prefix, localname, nsURI, this); break; case "csymbol": result = new MathMLCsymbolElement(prefix, localname, nsURI, this); break; case "apply": result = new MathMLApplyElement(prefix, localname, nsURI, this); break; case "fn": result = new MathMLFnElement(prefix, localname, nsURI, this); break; case "interval": result = new MathMLIntervalElement(prefix, localname, nsURI, this); break; case "inverse": case "compose": case "ident": case "domain": case "codomain": case "image": case "quotient": case "exp": case "factorial": case "divide": case "max": case "min": case "minus": case "plus": case "power": case "rem": case "times": case "root": case "gcd": case "and": case "or": case "xor": case "not": case "implies": case "forall": case "exists": case "abs": case "conjugate": case "arg": case "real": case "imaginary": case "lcm": case "floor": case "ceiling": case "eq": case "neq": case "gt": case "lt": case "geq": case "leq": case "equivalent": case "approx": case "factorof": case "int": case "diff": case "partialdiff": case "divergence": case "grad": case "curl": case "laplacian": case "union": case "intersect": case "in": case "notin": case "subset": case "prsubset": case "notsubset": case "notprsubset": case "setdiff": case "card": case "cartesianproduct": case "sum": case "product": case "limit": case "tendsto": case "ln": case "log": case "sin": case "cos": case "tan": case "sec": case "csc": case "cot": case "sinh": case "cosh": case "tanh": case "sech": case "csch": case "coth": case "arcsin": case "arccos": case "arctan": case "arccosh": case "arccot": case "arccoth": case "arccsc": case "arccsch": case "arcsec": case "arcsech": case "arcsinh": case "arctanh": case "mean": case "sdev": case "variance": case "median": case "mode": case "moment": case "determinant": case "transpose": case "selector": case "vectorproduct": case "scalarproduct": case "outerproduct": case "integers": case "reals": case "rationals": case "naturalnumbers": case "complexes": case "primes": case "exponentiale": case "imaginaryi": case "notanumber": case "true": case "false": case "emptyset": case "pi": case "eulergamma": case "infinity": result = new MathMLPredefinedSymbol(prefix, localname, nsURI, this); break; case "condition": result = new MathMLConditionElement(prefix, localname, nsURI, this); break; case "declare": result = new MathMLDeclareElement(prefix, localname, nsURI, this); break; case "lambda": result = new MathMLLambdaElement(prefix, localname, nsURI, this); break; case "piecewise": result = new MathMLPiecewiseElement(prefix, localname, nsURI, this); break; case "piecev": result = new MathMLCaseElement(prefix, localname, nsURI, this); break; case "reln": case "domainofapplication": case "otherwise": case "lowlimit": case "uplimit": case "degree": case "momentabout": case "logbase": // TODO is this correct, 'logbase' not specified in mathml docs???? result = new MathMLContentContainer(prefix, localname, nsURI, this); break; case "bvar": result = new MathMLBvarElement(prefix, localname, nsURI, this); break; case "set": result = new MathMLSetElement(prefix, localname, nsURI, this); break; case "list": result = new MathMLListElement(prefix, localname, nsURI, this); break; case "vector": result = new MathMLVectorElement(prefix, localname, nsURI, this); break; case "matrix": result = new MathMLMatrixElement(prefix, localname, nsURI, this); break; case "matrixrow": result = new MathMLMatrixRowElement(prefix, localname, nsURI, this); break; case "annotation": result = new MathMLAnnotationElement(prefix, localname, nsURI, this); break; case "semantics": result = new MathMLSemanticsElement(prefix, localname, nsURI, this); break; case "annotation-xml": result = new MathMLXMLAnnotationElement(prefix, localname, nsURI, this); break; case "sep": result = new MathMLSeparator(prefix, localname, nsURI, this); break; case "placeholder": result = new MathMLPlaceholderElement(prefix, localname, nsURI, this); break; default: result = base.CreateElement(prefix, localname, nsURI); break; } return(result); }
/// <summary> /// set the foreground and background colors for an area derived from a /// token area. This takes a formatted area tree, and if a color exists /// for a token, this color is set to the area subtree, same for background /// color. /// </summary> private static Area Colorize(MathMLPresentationToken e, Area a) { Color color = e.MathColor; Color backColor = e.MathBackground; // make sure we only colorize outermost area if(!color.IsEmpty && !backColor.IsEmpty) { a = AreaFactory.Color(color, a); a = AreaFactory.Background(backColor, a); } else if(!color.IsEmpty) { a = AreaFactory.Color(color, a); } else if(!backColor.IsEmpty) { a = AreaFactory.Background(backColor, a); } return a; }
/// <summary> /// Create a XmlElement. This is typically called by the base class when creating a DOM tree /// </summary> /// <param name="prefix"></param> /// <param name="localname"></param> /// <param name="nsURI"></param> /// <returns></returns> public override XmlElement CreateElement(string prefix, string localname, string nsURI) { XmlElement result = null; switch(localname) { case "math": result = new MathMLMathElement(prefix, localname, nsURI, this); break; case "mi": case "mn": case "mtext": result = new MathMLPresentationToken(prefix, localname, nsURI, this); break; case "mo": result = new MathMLOperatorElement(prefix, localname, nsURI, this); break; case "mspace": result = new MathMLSpaceElement(prefix, localname, nsURI, this); break; case "ms": result = new MathMLStringLitElement(prefix, localname, nsURI, this); break; case "mglyph": result = new MathMLGlyphElement(prefix, localname, nsURI, this); break; case "mrow": case "merror": case "mphantom": result = new MathMLPresentationContainer(prefix, localname, nsURI, this); break; case "mfrac": result = new MathMLFractionElement(prefix, localname, nsURI, this); break; case "msqrt": case "mroot": result = new MathMLRadicalElement(prefix, localname, nsURI, this); break; case "mstyle": result = new MathMLStyleElement(prefix, localname, nsURI, this); break; case "mpadded": result = new MathMLPaddedElement(prefix, localname, nsURI, this); break; case "mfenced": result = new MathMLFencedElement(prefix, localname, nsURI, this); break; case "menclose": result = new MathMLEncloseElement(prefix, localname, nsURI, this); break; case "msub": case "msup": case "msubsup": result = new MathMLScriptElement(prefix, localname, nsURI, this); break; case "munder": case "mover": case "munderover": result = new MathMLUnderOverElement(prefix, localname, nsURI, this); break; case "mmultiscripts": result = new MathMLMultiScriptsElement(prefix, localname, nsURI, this); break; case "mtable": result = new MathMLTableElement(prefix, localname, nsURI, this); break; case "mlabeledtr": result = new MathMLLabeledRowElement(prefix, localname, nsURI, this); break; case "mtr": result = new MathMLTableRowElement(prefix, localname, nsURI, this); break; case "mtd": result = new MathMLTableCellElement(prefix, localname, nsURI, this); break; case "maligngroup": result = new MathMLAlignGroupElement(prefix, localname, nsURI, this); break; case "malignmark": result = new MathMLAlignMarkElement(prefix, localname, nsURI, this); break; case "maction": result = new MathMLActionElement(prefix, localname, nsURI, this); break; case "cn": result = new MathMLCnElement(prefix, localname, nsURI, this); break; case "ci": result = new MathMLCiElement(prefix, localname, nsURI, this); break; case "csymbol": result = new MathMLCsymbolElement(prefix, localname, nsURI, this); break; case "apply": result = new MathMLApplyElement(prefix, localname, nsURI, this); break; case "fn": result = new MathMLFnElement(prefix, localname, nsURI, this); break; case "interval": result = new MathMLIntervalElement(prefix, localname, nsURI, this); break; case "inverse": case "compose": case "ident": case "domain": case "codomain": case "image": case "quotient": case "exp": case "factorial": case "divide": case "max": case "min": case "minus": case "plus": case "power": case "rem": case "times": case "root": case "gcd": case "and": case "or": case "xor": case "not": case "implies": case "forall": case "exists": case "abs": case "conjugate": case "arg": case "real": case "imaginary": case "lcm": case "floor": case "ceiling": case "eq": case "neq": case "gt": case "lt": case "geq": case "leq": case "equivalent": case "approx": case "factorof": case "int": case "diff": case "partialdiff": case "divergence": case "grad": case "curl": case "laplacian": case "union": case "intersect": case "in": case "notin": case "subset": case "prsubset": case "notsubset": case "notprsubset": case "setdiff": case "card": case "cartesianproduct": case "sum": case "product": case "limit": case "tendsto": case "ln": case "log": case "sin": case "cos": case "tan": case "sec": case "csc": case "cot": case "sinh": case "cosh": case "tanh": case "sech": case "csch": case "coth": case "arcsin": case "arccos": case "arctan": case "arccosh": case "arccot": case "arccoth": case "arccsc": case "arccsch": case "arcsec": case "arcsech": case "arcsinh": case "arctanh": case "mean": case "sdev": case "variance": case "median": case "mode": case "moment": case "determinant": case "transpose": case "selector": case "vectorproduct": case "scalarproduct": case "outerproduct": case "integers": case "reals": case "rationals": case "naturalnumbers": case "complexes": case "primes": case "exponentiale": case "imaginaryi": case "notanumber": case "true": case "false": case "emptyset": case "pi": case "eulergamma": case "infinity": result = new MathMLPredefinedSymbol(prefix, localname, nsURI, this); break; case "condition": result = new MathMLConditionElement(prefix, localname, nsURI, this); break; case "declare": result = new MathMLDeclareElement(prefix, localname, nsURI, this); break; case "lambda": result = new MathMLLambdaElement(prefix, localname, nsURI, this); break; case "piecewise": result = new MathMLPiecewiseElement(prefix, localname, nsURI, this); break; case "piecev": result = new MathMLCaseElement(prefix, localname, nsURI, this); break; case "reln": case "domainofapplication": case "otherwise": case "lowlimit": case "uplimit": case "degree": case "momentabout": case "logbase": // TODO is this correct, 'logbase' not specified in mathml docs???? result = new MathMLContentContainer(prefix, localname, nsURI, this); break; case "bvar": result = new MathMLBvarElement(prefix, localname, nsURI, this); break; case "set": result = new MathMLSetElement(prefix, localname, nsURI, this); break; case "list": result = new MathMLListElement(prefix, localname, nsURI, this); break; case "vector": result = new MathMLVectorElement(prefix, localname, nsURI, this); break; case "matrix": result = new MathMLMatrixElement(prefix, localname, nsURI, this); break; case "matrixrow": result = new MathMLMatrixRowElement(prefix, localname, nsURI, this); break; case "annotation": result = new MathMLAnnotationElement(prefix, localname, nsURI, this); break; case "semantics": result = new MathMLSemanticsElement(prefix, localname, nsURI, this); break; case "annotation-xml": result = new MathMLXMLAnnotationElement(prefix, localname, nsURI, this); break; case "sep": result = new MathMLSeparator(prefix, localname, nsURI, this); break; case "placeholder": result = new MathMLPlaceholderElement(prefix, localname, nsURI, this); break; default: result = base.CreateElement(prefix, localname, nsURI); break; } return result; }
/// <summary> /// process a presentation token. This can be either a "mi", /// "mn", or "mtext" element. These nodes can only have content /// of text or glyph nodes. This method process all of the child /// nodes of the element, verifies that they are indeed text nodes, /// or glyph elements, and depending on the content, creates either /// an array of glyphs in a horizontal array if the content is text /// nodes interspersed with glyph elements, or a string element /// if the content is a single text node /// </summary> public object Visit(MathMLPresentationToken e, object args) { Area cache = Area.GetArea(e); if(cache != null) return cache; Area area = null; // make an updated context IFormattingContext context = ((IFormattingContext)args).Clone(); XmlNode node = null; MathMLElement element = null; MathMLNodeList contents = e.Contents; // update the font size, pres-tokens can specify font size context.Size = context.Evaluate(e.MathSize); MathVariant variant = e.MathVariant; if(variant != MathVariant.Unknown) { context.MathVariant = variant; } if(contents.Count == 1) // create a single string area { if((node = e.FirstChild) != null && node.NodeType == XmlNodeType.Text) { area = AreaFactory.String(context, node.Value); } else if((element = e.FirstChild as MathMLElement) != null) { // sets area to a new glyph area area = (Area)element.Accept(this, context); } else { // TODO this is bad, need error handler } } else // create a sequence of areas { Area[] areas = new Area[contents.Count]; int i = 0; foreach(XmlNode n in contents) { if(n.NodeType == XmlNodeType.Text) { area = AreaFactory.String(context, n.Value); } else if((element = n as MathMLElement) != null) { area = (Area)element.Accept(this, context); } areas[i++] = area; } area = AreaFactory.Horizontal(areas); } return CompleteArea((IFormattingContext)args, e, Colorize(e, area)); }