[Libreoffice-commits] libmspub.git: src/lib
David Tardon
dtardon at redhat.com
Sun Dec 28 11:45:44 PST 2014
src/lib/MSPUBCollector.cpp | 173 +++++++++++++++++++++++++++++++++------------
src/lib/MSPUBParser.cpp | 69 ++++++++++++++++-
src/lib/TableInfo.h | 23 +++++
3 files changed, 216 insertions(+), 49 deletions(-)
New commits:
commit 3b6efdb66e92c4d3d93daa56930ead86bf4fb96a
Author: David Tardon <dtardon at redhat.com>
Date: Sun Dec 28 20:22:34 2014 +0100
handle merged cells
Change-Id: I32c416d89e18d780d852a900f16a35d14531c209
diff --git a/src/lib/MSPUBCollector.cpp b/src/lib/MSPUBCollector.cpp
index 04f5b6c..7f8cc84 100644
--- a/src/lib/MSPUBCollector.cpp
+++ b/src/lib/MSPUBCollector.cpp
@@ -9,6 +9,8 @@
#include <math.h>
+#include <boost/multi_array.hpp>
+
#include <unicode/ucsdet.h>
#include "MSPUBCollector.h"
@@ -103,6 +105,79 @@ static void separateSpacesAndInsertText(librevenge::RVNGDrawingInterface *iface,
separateTabsAndInsertText(iface, tmpText);
}
+struct TableLayoutCell
+{
+ TableLayoutCell()
+ : m_rowSpan(0)
+ , m_colSpan(0)
+ {
+ }
+
+ unsigned m_rowSpan;
+ unsigned m_colSpan;
+};
+
+bool isCovered(const TableLayoutCell &cell)
+{
+ assert((cell.m_rowSpan == 0) == (cell.m_colSpan == 0));
+ return (cell.m_rowSpan == 0) && (cell.m_colSpan == 0);
+}
+
+typedef boost::multi_array<TableLayoutCell, 2> TableLayout;
+
+void createTableLayout(const std::vector<CellInfo> &cells, TableLayout &tableLayout)
+{
+ for (std::vector<CellInfo>::const_iterator it = cells.begin(); it != cells.end(); ++it)
+ {
+ if ((it->m_endRow >= tableLayout.shape()[0]) || (it->m_endColumn >= tableLayout.shape()[1]))
+ {
+ MSPUB_DEBUG_MSG((
+ "cell %u (rows %u to %u, columns %u to %u) overflows the table, ignoring\n",
+ unsigned(int(it - cells.begin())),
+ it->m_startRow, it->m_endRow,
+ it->m_startColumn, it->m_endColumn,
+ ));
+ continue;
+ }
+ if (it->m_startRow > it->m_endRow)
+ {
+ MSPUB_DEBUG_MSG((
+ "cell %u (rows %u to %u) has got negative row span, ignoring\n",
+ unsigned(int(it - cells.begin())),
+ it->m_startRow, it->m_endRow,
+ ));
+ continue;
+ }
+ if (it->m_startColumn > it->m_endColumn)
+ {
+ MSPUB_DEBUG_MSG((
+ "cell %u (columns %u to %u) has got negative column span, ignoring\n",
+ unsigned(int(it - cells.begin())),
+ it->m_startColumn, it->m_endColumn,
+ ));
+ continue;
+ }
+
+ const unsigned rowSpan = it->m_endRow - it->m_startRow + 1;
+ const unsigned colSpan = it->m_endColumn - it->m_startColumn + 1;
+
+ if ((rowSpan == 0) != (colSpan == 0))
+ {
+ MSPUB_DEBUG_MSG((
+ "cell %u (rows %u to %u, columns %u to %u) has got 0 span in one dimension, ignoring\n",
+ unsigned(int(it - cells.begin())),
+ it->m_startRow, it->m_endRow,
+ it->m_startColumn, it->m_endColumn,
+ ));
+ continue;
+ }
+
+ TableLayoutCell &layoutCell = tableLayout[it->m_startRow][it->m_startColumn];
+ layoutCell.m_rowSpan = rowSpan;
+ layoutCell.m_colSpan = colSpan;
+ }
+}
+
} // anonymous namespace
void MSPUBCollector::addEOTFont(const librevenge::RVNGString &name, const librevenge::RVNGBinaryData &data)
@@ -874,62 +949,72 @@ boost::function<void(void)> MSPUBCollector::paintShape(const ShapeInfo &info, co
std::vector<unsigned> tableCellTextEnds;
if (bool(info.m_tableCellTextEnds))
tableCellTextEnds = get(info.m_tableCellTextEnds);
- unsigned row = 0;
- unsigned column = 0;
+ TableLayout tableLayout(boost::extents[get(info.m_tableInfo).m_numRows][get(info.m_tableInfo).m_numColumns]);
+ createTableLayout(get(info.m_tableInfo).m_cells, tableLayout);
+
+ unsigned cell = 0;
unsigned para = 0;
unsigned offset = 1;
- for (unsigned cell = 0; cell != get(info.m_tableInfo).m_numColumns * get(info.m_tableInfo).m_numRows; ++cell)
+ for (unsigned row = 0; row != tableLayout.shape()[0]; ++row)
{
- assert(row < get(info.m_tableInfo).m_numRows);
- assert(column < get(info.m_tableInfo).m_numColumns);
-
- if (column == 0)
- m_painter->openTableRow(librevenge::RVNGPropertyList());
+ m_painter->openTableRow(librevenge::RVNGPropertyList());
- librevenge::RVNGPropertyList cellProps;
- cellProps.insert("librevenge:column", int(column));
- cellProps.insert("librevenge:row", int(row));
- m_painter->openTableCell(cellProps);
-
- if (cell < tableCellTextEnds.size())
+ for (unsigned col = 0; col != tableLayout.shape()[1]; ++col)
{
- const unsigned cellEnd = tableCellTextEnds[cell];
- while ((para < text.size()) && (offset < cellEnd))
+ librevenge::RVNGPropertyList cellProps;
+ cellProps.insert("librevenge:column", int(col));
+ cellProps.insert("librevenge:row", int(row));
+
+ if (isCovered(tableLayout[row][col]))
{
- librevenge::RVNGPropertyList paraProps = getParaStyleProps(text[para].style, text[para].style.m_defaultCharStyleIndex);
- m_painter->openParagraph(paraProps);
- for (unsigned i_spans = 0; (i_spans < text[para].spans.size()) && (offset < cellEnd); ++i_spans)
- {
- librevenge::RVNGString textString;
- appendCharacters(textString, text[para].spans[i_spans].chars,
- getCalculatedEncoding());
- offset += textString.len();
- // TODO: why do we not drop these during parse already?
- if ((i_spans == text[para].spans.size() - 1) && (textString == "\r"))
- continue;
- librevenge::RVNGPropertyList charProps = getCharStyleProps(text[para].spans[i_spans].style, text[para].style.m_defaultCharStyleIndex);
- m_painter->openSpan(charProps);
- separateSpacesAndInsertText(m_painter, textString);
- m_painter->closeSpan();
- }
+ m_painter->insertCoveredTableCell(cellProps);
+ }
+ else
+ {
+ if (tableLayout[row][col].m_colSpan > 1)
+ cellProps.insert("table:number-columns-spanned", int(tableLayout[row][col].m_colSpan));
+ if (tableLayout[row][col].m_rowSpan > 1)
+ cellProps.insert("table:number-rows-spanned", int(tableLayout[row][col].m_rowSpan));
+
+ m_painter->openTableCell(cellProps);
- if (offset > cellEnd)
+ if (cell < tableCellTextEnds.size())
{
- MSPUB_DEBUG_MSG(("cell text ends in the middle of a span!\n"));
+ const unsigned cellEnd = tableCellTextEnds[cell];
+ while ((para < text.size()) && (offset < cellEnd))
+ {
+ librevenge::RVNGPropertyList paraProps = getParaStyleProps(text[para].style, text[para].style.m_defaultCharStyleIndex);
+ m_painter->openParagraph(paraProps);
+ for (unsigned i_spans = 0; (i_spans < text[para].spans.size()) && (offset < cellEnd); ++i_spans)
+ {
+ librevenge::RVNGString textString;
+ appendCharacters(textString, text[para].spans[i_spans].chars,
+ getCalculatedEncoding());
+ offset += textString.len();
+ // TODO: why do we not drop these during parse already?
+ if ((i_spans == text[para].spans.size() - 1) && (textString == "\r"))
+ continue;
+ librevenge::RVNGPropertyList charProps = getCharStyleProps(text[para].spans[i_spans].style, text[para].style.m_defaultCharStyleIndex);
+ m_painter->openSpan(charProps);
+ separateSpacesAndInsertText(m_painter, textString);
+ m_painter->closeSpan();
+ }
+
+ if (offset > cellEnd)
+ {
+ MSPUB_DEBUG_MSG(("cell text ends in the middle of a span!\n"));
+ }
+ m_painter->closeParagraph();
+ ++para;
+ }
}
- m_painter->closeParagraph();
- ++para;
+
+ ++cell;
+ m_painter->closeTableCell();
}
}
- m_painter->closeTableCell();
- ++column;
- if (column == get(info.m_tableInfo).m_numColumns)
- {
- m_painter->closeTableRow();
- ++row;
- column = 0;
- }
+ m_painter->closeTableRow();
}
m_painter->endTableObject();
diff --git a/src/lib/MSPUBParser.cpp b/src/lib/MSPUBParser.cpp
index 9b56db8..d2f3baa 100644
--- a/src/lib/MSPUBParser.cpp
+++ b/src/lib/MSPUBParser.cpp
@@ -751,6 +751,11 @@ bool MSPUBParser::parseShape(librevenge::RVNGInputStream *input,
break;
}
}
+
+ TableInfo ti(nr, nc);
+ ti.m_rowOffsetsInEmu = rowOffsetsInEmu;
+ ti.m_columnOffsetsInEmu = columnOffsetsInEmu;
+
if (!index)
{
MSPUB_DEBUG_MSG(("WARNING: Couldn't find cells of seqnum %u corresponding to table of seqnum %u.\n",
@@ -759,11 +764,67 @@ bool MSPUBParser::parseShape(librevenge::RVNGInputStream *input,
}
else
{
- // Currently do nothing with the cells chunk.
+ const ContentChunkReference &cellsChunk = m_contentChunks[m_cellsChunkIndices[get(index)]];
+ input->seek(cellsChunk.offset, librevenge::RVNG_SEEK_SET);
+ const unsigned cellsLength = readU32(input);
+ boost::optional<unsigned> cellCount;
+ while (stillReading(input, cellsChunk.offset + cellsLength))
+ {
+ MSPUBBlockInfo info = parseBlock(input, true);
+ switch (info.id)
+ {
+ case 0x01:
+ cellCount = info.data;
+ break;
+ case 0x02:
+ {
+ input->seek(info.dataOffset + 4, librevenge::RVNG_SEEK_SET);
+ while (stillReading(input, info.dataOffset + info.dataLength))
+ {
+ const MSPUBBlockInfo itemInfo = parseBlock(input, true);
+ if (itemInfo.id == 0)
+ {
+ input->seek(itemInfo.dataOffset + 4, librevenge::RVNG_SEEK_SET);
+ CellInfo currentCell;
+ while (stillReading(input, itemInfo.dataOffset + itemInfo.dataLength))
+ {
+ const MSPUBBlockInfo subInfo = parseBlock(input, true);
+ switch (subInfo.id)
+ {
+ case 0x01:
+ currentCell.m_startRow = subInfo.data;
+ break;
+ case 0x02:
+ currentCell.m_endRow = subInfo.data;
+ break;
+ case 0x03:
+ currentCell.m_startColumn = subInfo.data;
+ break;
+ case 0x04:
+ currentCell.m_endColumn = subInfo.data;
+ break;
+ // TODO: 0x09 - 0x0e: width/height of content + margins?
+ default:
+ break;
+ }
+ }
+ ti.m_cells.push_back(currentCell);
+ }
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (bool(cellCount) && (get(cellCount) != ti.m_cells.size()))
+ {
+ MSPUB_DEBUG_MSG(("%u cell records expected, but read %u\n", get(cellCount), ti.m_cells.size()));
+ }
}
- TableInfo ti(nr, nc);
- ti.m_rowOffsetsInEmu = rowOffsetsInEmu;
- ti.m_columnOffsetsInEmu = columnOffsetsInEmu;
+
m_collector->setShapeTableInfo(chunk.seqNum, ti);
if (bool(textId))
m_collector->addTextShape(get(textId), chunk.seqNum);
diff --git a/src/lib/TableInfo.h b/src/lib/TableInfo.h
index f2e9688..7869c7c 100644
--- a/src/lib/TableInfo.h
+++ b/src/lib/TableInfo.h
@@ -10,16 +10,37 @@
#ifndef __TABLEINFO_H__
#define __TABLEINFO_H__
+#include <vector>
+
namespace libmspub
{
+
+struct CellInfo
+{
+ CellInfo()
+ : m_startRow()
+ , m_endRow()
+ , m_startColumn()
+ , m_endColumn()
+ {
+ }
+
+ unsigned m_startRow;
+ unsigned m_endRow;
+ unsigned m_startColumn;
+ unsigned m_endColumn;
+};
+
struct TableInfo
{
std::vector<unsigned> m_rowOffsetsInEmu;
std::vector<unsigned> m_columnOffsetsInEmu;
unsigned m_numRows;
unsigned m_numColumns;
+ std::vector<CellInfo> m_cells;
TableInfo(unsigned numRows, unsigned numColumns) : m_rowOffsetsInEmu(),
- m_columnOffsetsInEmu(), m_numRows(numRows), m_numColumns(numColumns)
+ m_columnOffsetsInEmu(), m_numRows(numRows), m_numColumns(numColumns),
+ m_cells()
{
}
};
More information about the Libreoffice-commits
mailing list