object MathML.MathMLVisitor.Visit(MathMLUnderOverElement e, object args) { MathMLElement c = (MathMLElement)args; switch (selection) { case SelectionType.Prev: { if (c == e.UnderScript || c == e.OverScript) { selection = SelectionType.End; return(e.Base.Accept(this, e)); } else { MathMLElement p = e.ParentNode as MathMLElement; return(p != null?p.Accept(this, e) : null); } } case SelectionType.Next: { if (c == e.Base) { MathMLElement next = e.OverScript != null ? e.OverScript : e.UnderScript; selection = SelectionType.Start; return(next != null?next.Accept(this, null) : null); } else { MathMLElement p = e.ParentNode as MathMLElement; return(p != null?p.Accept(this, e) : null); } } case SelectionType.End: { MathMLElement end = e.OverScript != null ? e.OverScript : (e.UnderScript != null ? e.UnderScript : e.Base); return(end.Accept(this, null)); } case SelectionType.Start: { return(e.Base.Accept(this, null)); } default: { return(null); } } }
object MathML.MathMLVisitor.Visit(MathMLUnderOverElement e, object args) { return ((Area)formatter.Visit(e, args)).BoundingBox; }
/// <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; }
object MathML.MathMLVisitor.Visit(MathMLUnderOverElement e, object args) { return(((Area)formatter.Visit(e, args)).BoundingBox); }
public object Visit(MathMLUnderOverElement e, object args) { Area cache = Area.GetArea(e); if(cache != null) return cache; IFormattingContext ctx = (IFormattingContext)args; IFormattingContext baseCtx = ctx.Clone(); IFormattingContext overCtx = ctx.Clone(); IFormattingContext underCtx = ctx.Clone(); MathMLElement baseElement = e.Base; MathMLElement overElement = e.OverScript; MathMLElement underElement = e.UnderScript; Area overArea = null; Area underArea = null; Area result = null; BoundingBox baseBox = BoundingBox.New(); BoundingBox underBox = BoundingBox.New(); BoundingBox overBox = BoundingBox.New(); BoundingBox extent = BoundingBox.New(); float ex = baseCtx.Evaluate(new Length(LengthType.Ex, 1.0f)); float overSpace = e.Accent ? ex / 8.0f : ex / 4.0f; float underSpace = e.AccentUnder ? ex / 8.0f : ex / 4.0f; // first get the initial un-stretched areas to compute the // stretch extent baseCtx.Stretch = BoundingBox.New(); Area baseArea = (Area)baseElement.Accept(this, baseCtx); baseBox = baseArea.BoundingBox; extent.Overlap(baseBox); if(overElement != null) { overCtx.cacheArea = false; overCtx.Stretch = BoundingBox.New(); overCtx.DisplayStyle = Display.Block; if(e.Accent == false) overCtx.ScriptLevel++; overArea = (Area)overElement.Accept(this, overCtx); overBox = overArea.BoundingBox; extent.Overlap(overBox); } if(underElement != null) { underCtx.cacheArea = false; underCtx.Stretch = BoundingBox.New(); underCtx.DisplayStyle = Display.Block; if(e.AccentUnder == false) underCtx.ScriptLevel++; underArea = (Area)underElement.Accept(this, underCtx); underBox = underArea.BoundingBox; extent.Overlap(underBox); } // now that we have the stretch extent, re-format the areas with // the correct stretch distance. baseCtx.Stretch = BoundingBox.New(extent.Width, baseBox.Height, baseBox.Depth); baseArea = (Area)baseElement.Accept(this, baseCtx); if(overElement != null) { overCtx.cacheArea = ctx.cacheArea; overCtx.Stretch = BoundingBox.New(extent.Width, overBox.Height, overBox.Depth); overArea = (Area)overElement.Accept(this, overCtx); } if(underElement != null) { underCtx.cacheArea = ctx.cacheArea; underCtx.Stretch = BoundingBox.New(extent.Width, underBox.Height, underBox.Depth); underArea = (Area)underElement.Accept(this, underCtx); } if(overArea != null && underArea != null) { Area[] areas = new Area[5]; areas[0] = AreaFactory.HorizontalCenter(underArea); areas[1] = AreaFactory.VerticalSpace(underSpace, underSpace); areas[2] = AreaFactory.HorizontalCenter(baseArea); areas[3] = AreaFactory.VerticalSpace(overSpace, overSpace); areas[4] = AreaFactory.HorizontalCenter(overArea); result = AreaFactory.Vertical(areas, 2); } else if(overArea != null) { Area[] areas = new Area[3]; areas[0] = AreaFactory.HorizontalCenter(baseArea); areas[1] = AreaFactory.VerticalSpace(overSpace, overSpace); areas[2] = AreaFactory.HorizontalCenter(overArea); result = AreaFactory.Vertical(areas, 0); } else if(underArea != null) { Area[] areas = new Area[3]; areas[0] = AreaFactory.HorizontalCenter(underArea); areas[1] = AreaFactory.VerticalSpace(underSpace, underSpace); areas[2] = AreaFactory.HorizontalCenter(baseArea); result = AreaFactory.Vertical(areas, 2); } else { // strange, but could happen, no under or over areas result = baseArea; } return CompleteArea(ctx, e, result); }