/** * construct a new sizer. All calculations are done here. */ public MathMLTableSizer(IFormattingContext ctx, MathMLMeasurer measurer, MathMLTableElement table) { try { // copy the context because we change the stretch size so not to // stretch tables ctx = ctx.Clone(); ctx.Stretch = BoundingBox.New(); ctx.cacheArea = false; //MathMLMeasurer measurer = new MathMLMeasurer(); equalColumns = table.EqualColumns; // get the cells from the table and store them in a multi dim array cells = GetCells(table); // min area sizes for the cells BoundingBox[][] minCellSizes = measurer.MeasureElements(ctx, cells); DebugWriteCellSizes(minCellSizes); // count of columns that are actual table cells int cellColumnCount = GetCellColumnCount(cells); // column widths attr from dom Length[] columnWidths = GetColumnWidths(table, cellColumnCount); // column space attr from dom Length[] columnSpacing = GetColumnSpacing(table, cellColumnCount - 1); // frame spaceing attr from dom Length[] frameSpacing = table.FrameSpacing; // row spacing attr from dom Length[] rowSpacing = GetRowSpacing(table, cells.Length - 1); // create a set of columns from the cells columns = CreateColumns(ctx, measurer, cells, minCellSizes, cellColumnCount, columnWidths, columnSpacing, frameSpacing[0]); // create a set of row measurments, this is both the cell rows and spacing rows Row[] rows = CreateRows(ctx, cells, minCellSizes, rowSpacing, frameSpacing[1]); // adjust rows and columns so there is enough space to fit spanning cells AdjustSpanningCells(cells, minCellSizes, rows, columns); Debug.WriteLine("retrieved " + columns.Length + "total columns, "); DebugWriteColumnWidths("Initial Column Widths: "); // get the minimum area for the columns float tableWidth = CalculateTableWidth(ctx, table, columns, equalColumns, cellColumnCount); Debug.WriteLine("Minimum Table Width: " + tableWidth); // find the space needed to fit the availible for the auto and fit columns float availSpace = CalculateColumnAvailSpace(columns, tableWidth); Debug.WriteLine("Availible Space For Columns: " + availSpace); // set the table widths DistributeSpace(columns, tableWidth, availSpace, cellColumnCount, equalColumns); DebugWriteColumnWidths("Column Widths After Formatting: "); // calcuate the shift float shift = 0; CalculateShiftAndSize(ctx, table, rows, columns, ref box, ref shift); // create the cell sizes and offsets CreateCellSizesAndShifts(cells, rows, columns, ref cellSizes, ref cellShifts); // create the lines for the frame and cell separators LineStyle frame = table.Frame; LineStyle[] columnLines = GetColumnLines(table, cellColumnCount); LineStyle[] rowLines = GetRowLines(table, cells.Length); CreateLines(cellSizes, cells, rows, columns, columnLines, rowLines, frame); // set the shift tableShift = GetTableShift(ctx, table, box); } catch(Exception ex) { throw new Exception("Error constructing table sizer: " + ex.Message); } }
/** * construct a new sizer. All calculations are done here. */ public MathMLTableSizer(IFormattingContext ctx, MathMLMeasurer measurer, MathMLTableElement table) { try { // copy the context because we change the stretch size so not to // stretch tables ctx = ctx.Clone(); ctx.Stretch = BoundingBox.New(); ctx.cacheArea = false; //MathMLMeasurer measurer = new MathMLMeasurer(); equalColumns = table.EqualColumns; // get the cells from the table and store them in a multi dim array cells = GetCells(table); // min area sizes for the cells BoundingBox[][] minCellSizes = measurer.MeasureElements(ctx, cells); DebugWriteCellSizes(minCellSizes); // count of columns that are actual table cells int cellColumnCount = GetCellColumnCount(cells); // column widths attr from dom Length[] columnWidths = GetColumnWidths(table, cellColumnCount); // column space attr from dom Length[] columnSpacing = GetColumnSpacing(table, cellColumnCount - 1); // frame spaceing attr from dom Length[] frameSpacing = table.FrameSpacing; // row spacing attr from dom Length[] rowSpacing = GetRowSpacing(table, cells.Length - 1); // create a set of columns from the cells columns = CreateColumns(ctx, measurer, cells, minCellSizes, cellColumnCount, columnWidths, columnSpacing, frameSpacing[0]); // create a set of row measurments, this is both the cell rows and spacing rows Row[] rows = CreateRows(ctx, cells, minCellSizes, rowSpacing, frameSpacing[1]); // adjust rows and columns so there is enough space to fit spanning cells AdjustSpanningCells(cells, minCellSizes, rows, columns); Debug.WriteLine("retrieved " + columns.Length + "total columns, "); DebugWriteColumnWidths("Initial Column Widths: "); // get the minimum area for the columns float tableWidth = CalculateTableWidth(ctx, table, columns, equalColumns, cellColumnCount); Debug.WriteLine("Minimum Table Width: " + tableWidth); // find the space needed to fit the availible for the auto and fit columns float availSpace = CalculateColumnAvailSpace(columns, tableWidth); Debug.WriteLine("Availible Space For Columns: " + availSpace); // set the table widths DistributeSpace(columns, tableWidth, availSpace, cellColumnCount, equalColumns); DebugWriteColumnWidths("Column Widths After Formatting: "); // calcuate the shift float shift = 0; CalculateShiftAndSize(ctx, table, rows, columns, ref box, ref shift); // create the cell sizes and offsets CreateCellSizesAndShifts(cells, rows, columns, ref cellSizes, ref cellShifts); // create the lines for the frame and cell separators LineStyle frame = table.Frame; LineStyle[] columnLines = GetColumnLines(table, cellColumnCount); LineStyle[] rowLines = GetRowLines(table, cells.Length); CreateLines(cellSizes, cells, rows, columns, columnLines, rowLines, frame); // set the shift tableShift = GetTableShift(ctx, table, box); } catch (Exception ex) { throw new Exception("Error constructing table sizer: " + ex.Message); } }
/// <summary> /// Format a row of elements. This can be either a presentation container or a mrow /// </summary> private Area FormatContainer(MathMLElement e, IFormattingContext ctx, ArrayList arguments) { IFormattingContext context = ctx.Clone(); BoundingBox extent = BoundingBox.New(); Area[] areas = new Area[arguments.Count]; 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(areas[i].BoundingBox); } 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.Stretch.Width - 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); } } } Area area = AreaFactory.Horizontal(areas); // hide the areas if it is a phantom if(e.Name == "mphantom") { area = AreaFactory.Hide(area); } else if(e.Name == "merror") { area = AreaFactory.Color(Color.Red, area); } // table cell areas elemetns area a special case, they get 'Completed' // in the MathMLTableCellElement method return area; }