/** * calculate the required space to fit all the columns */ private static Column[] CreateColumns(IFormattingContext ctx, MathMLMeasurer measurer, MathMLTableCellElement[][] cells, BoundingBox[][] minCellSizes, int columnCount, Length[] columnWidths, Length[] spaceWidths, Length frameSpacing) { Column[] columns = null; int c = 0; int colWidth = 0; int spaceWidth = 0; // new column array: max column count + spacing columns + border spacing // = (max column count) + (max column count - 1) + 2 // = (max column count) + (max column count) + 1 columns = new Column[columnCount + columnCount + 1]; // set the frame spacing columns columns[c++] = new Column(ctx, frameSpacing, 0, true); // outer loop: columns for (int i = 0; i < columnCount; i++) { BoundingBox[] columnCells = new BoundingBox[cells.Length]; // inner loop: rows for (int j = 0; j < cells.Length; j++) { columnCells[j] = i < cells[j].Length ? minCellSizes[j][i] : BoundingBox.New(); } // set the column columns[c++] = new Column(ctx, columnWidths[colWidth++], GetRequiredWidth(columnCells), false); // set the space column if (i < columnCount - 1) { columns[c++] = new Column(ctx, spaceWidths[spaceWidth++], 0, true); } } // set the right spacing column columns[c++] = new Column(ctx, frameSpacing, 0, true); // sanity check Debug.Assert(c == columns.Length, "error, maxColumnCount and processed column count do not match"); return(columns); }
/** * 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); } }
/** * calculate the required space to fit all the columns */ private static Column[] CreateColumns(IFormattingContext ctx, MathMLMeasurer measurer, MathMLTableCellElement[][] cells, BoundingBox[][] minCellSizes, int columnCount, Length[] columnWidths, Length[] spaceWidths, Length frameSpacing) { Column[] columns = null; int c = 0; int colWidth = 0; int spaceWidth = 0; // new column array: max column count + spacing columns + border spacing // = (max column count) + (max column count - 1) + 2 // = (max column count) + (max column count) + 1 columns = new Column[columnCount + columnCount + 1]; // set the frame spacing columns columns[c++] = new Column(ctx, frameSpacing, 0, true); // outer loop: columns for(int i = 0; i < columnCount; i++) { BoundingBox[] columnCells = new BoundingBox[cells.Length]; // inner loop: rows for(int j = 0; j < cells.Length; j++) { columnCells[j] = i < cells[j].Length ? minCellSizes[j][i] : BoundingBox.New(); } // set the column columns[c++] = new Column(ctx, columnWidths[colWidth++], GetRequiredWidth(columnCells), false); // set the space column if(i < columnCount - 1) { columns[c++] = new Column(ctx, spaceWidths[spaceWidth++], 0, true); } } // set the right spacing column columns[c++] = new Column(ctx, frameSpacing, 0, true); // sanity check Debug.Assert(c == columns.Length, "error, maxColumnCount and processed column count do not match"); return columns; }
/** * 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); } }
// cache of layout areas // this is a map of MathMLElements to layout areas. // every time a node is changed or updated, it and it's parent // hierarchy are removed from this cache. // if a document is re-loaded this cache is cleared. // private Hashtable cachedAreas = new Hashtable(); public MathMLFormatter() { measurer = new MathMLMeasurer(this); }