object MathML.MathMLVisitor.Visit(MathMLPresentationToken e, object args) { 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(formatter, 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(formatter, context); } areas[i++] = area; } area = AreaFactory.Horizontal(areas); } return(area.BoundingBox); }
object MathML.MathMLVisitor.Visit(MathMLPresentationContainer e, object args) { IFormattingContext context = ((IFormattingContext)args).Clone(); MathMLNodeList arguments = e.Arguments; BoundingBox extent = BoundingBox.New(); int stretchCount = 0; // save the stretch size because stretch scope can not extend into another // level of nesting BoundingBox stretch = context.Stretch; context.Stretch = BoundingBox.New(); // process all nodes that are not stretchy operators, get thier total // extents for (int i = 0; i < arguments.Count; i++) { MathMLElement element = (MathMLElement)arguments[i]; MathMLOperatorElement op = element as MathMLOperatorElement; if (op == null || op.Stretchy == false) { //areas[i] = (Area)element.Accept(this, context); extent.Append((BoundingBox)element.Accept(this, context)); } if (op != null && op.Stretchy) { stretchCount++; } } // if we have any elements that can be stretched, stretch them if (stretchCount > 0) { if (!stretch.Defined) { // avail width is epsilon because stretchy glyphs were not counted in the // width calculation context.Stretch = BoundingBox.New(Single.Epsilon, extent.Height, extent.Depth); } else { // set the stretch size back to stretch the child elements context.Stretch = stretch; // calculate availible width context.StretchWidth = context.StretchWidth - extent.Width; if (context.Stretch.Width < 0) { context.StretchWidth = 0; } // size to stretch each width equally context.StretchWidth = context.Stretch.Width / (float)stretchCount; } // process all areas that need to be stretched for (int i = 0; i < arguments.Count; i++) { MathMLOperatorElement op = arguments[i] as MathMLOperatorElement; if (op != null && op.Stretchy) { //areas[i] = (Area)op.Accept(this, context); extent.Append((BoundingBox)op.Accept(this, context)); } } } return(extent); }
/** * grab all the cells from a table and return them in a 2 dimensional array * TODO optimize (cache) cell.attribute* calls */ public static MathMLTableCellElement[][] GetCells(MathMLTableElement table) { int i = 0; MathMLNodeList tableRows = table.Rows; MathMLTableCellElement[][] cells = new MathMLTableCellElement[tableRows.Count][]; int[] remainderCols = new int[0]; ArrayList rowCellsList = new ArrayList(); foreach (MathMLTableRowElement row in tableRows) { MathMLNodeList rowCells = row.Cells; rowCellsList.Clear(); foreach (MathMLTableCellElement cell in rowCells) { if (rowCellsList.Count < remainderCols.Length && remainderCols[rowCellsList.Count] > 0) { remainderCols[rowCellsList.Count] = remainderCols[rowCellsList.Count] - 1; rowCellsList.Add(null); } rowCellsList.Add(cell); for (int j = 1; j < cell.ColumnSpan; j++) { // deal with overlapping cells if (rowCellsList.Count < remainderCols.Length && remainderCols[rowCellsList.Count] > 0) { remainderCols[rowCellsList.Count] = remainderCols[rowCellsList.Count] - 1; } rowCellsList.Add(null); } } cells[i] = new MathMLTableCellElement[rowCellsList.Count]; for (int j = 0; j < rowCellsList.Count; j++) { cells[i][j] = (MathMLTableCellElement)rowCellsList[j]; } if (remainderCols.Length < cells[i].Length) { int[] tmp = new int[cells[i].Length]; for (int j = 0; j < remainderCols.Length; j++) { tmp[j] = remainderCols[j]; } for (int j = remainderCols.Length; j < tmp.Length; j++) { tmp[j] = 0; } remainderCols = tmp; } for (int j = 0; j < cells[i].Length; j++) { if (cells[i][j] != null) { Debug.Assert(remainderCols[j] == 0, "remainder columns value should be zero if we have a current cell"); remainderCols[j] = cells[i][j].RowSpan - 1; } } i++; // next row } return(cells); }