Added support for repeat table header and footer on every page break.

Added support for repeat table header and footer on every page break.
This commit is contained in:
Prakash V 2016-07-19 15:16:00 +05:30
Родитель 5a229f9c7c
Коммит 5df4e28040
12 изменённых файлов: 159 добавлений и 13 удалений

Просмотреть файл

@ -437,6 +437,9 @@ public:
void setScrollPinningBehavior(ScrollPinningBehavior);
//Enable or disable repeated thead/tfoot.
bool repeatTableHeader;
bool repeatTableFooter;
protected:
virtual bool scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
virtual void scrollContentsSlowPath(const IntRect& updateRect);

Просмотреть файл

@ -81,10 +81,9 @@ public:
// The height of the graphics context should be
// (pageSizeInPixels.height() + 1) * number-of-pages - 1
static void spoolAllPagesWithBoundaries(Frame*, GraphicsContext&, const FloatSize& pageSizeInPixels);
Vector<IntRect> m_pageRects;
protected:
Frame* m_frame;
Vector<IntRect> m_pageRects;
private:
void computePageRectsWithPageSizeInternal(const FloatSize& pageSizeInPixels, bool allowHorizontalTiling);

Просмотреть файл

@ -431,7 +431,8 @@ void RenderTable::layout()
oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
bool collapsing = collapseBorders();
int headHeight = 0;
int footHeight = 0;
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isTableSection()) {
RenderTableSection* section = toRenderTableSection(child);
@ -439,6 +440,14 @@ void RenderTable::layout()
section->setChildNeedsLayout(true, MarkOnlyThis);
section->layoutIfNeeded();
totalSectionLogicalHeight += section->calcRowLogicalHeight();
int rowHeight = section->calcRowLogicalHeight();
if (child == m_head && view()->repeatTableHeader) {
headHeight = rowHeight;
}
else if (child == m_foot && view()->repeatTableFooter) {
footHeight = rowHeight;
}
totalSectionLogicalHeight += rowHeight;
if (collapsing)
section->recalcOuterBorder();
ASSERT(!section->needsLayout());
@ -496,7 +505,12 @@ void RenderTable::layout()
distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
section->layoutRows();
{
LayoutUnit height = computedLogicalHeight - totalSectionLogicalHeight;
LayoutUnit First = 0;
height = max(First, height);
section->layoutRows(section == m_firstBody ? height : 0, headHeight, footHeight);
}
if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
// Completely empty tables (with no sections or anything) should at least honor specified height
@ -655,6 +669,10 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
PaintInfo info(paintInfo);
info.phase = paintPhase;
info.updateSubtreePaintRootForChildren(this);
bool repaintedHead = false;
IntPoint repaintedHeadPoint;
bool repaintedFoot = false;
IntPoint repaintedFootPoint;
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
@ -662,7 +680,64 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
child->paint(info, childPoint);
}
}
if (view()->pageLogicalHeight()) {
// re-paint header/footer if table is split over multiple pages
if (m_head && view()->repeatTableHeader) {
LayoutPoint childPoint = flipForWritingModeForChild(m_head, paintOffset);
if (!info.rect.contains(childPoint.x() + m_head->x(), childPoint.y() + m_head->y())) {
repaintedHeadPoint = IntPoint(childPoint.x(), info.rect.y() - m_head->y());
repaintedHead = true;
dynamic_cast<RenderObject*>(m_head)->paint(info, repaintedHeadPoint);
}
}
if (m_foot && view()->repeatTableFooter) {
LayoutPoint childPoint = flipForWritingModeForChild(m_foot, paintOffset);
if (!info.rect.contains(childPoint.x() + m_foot->x(), childPoint.y() + m_foot->y())) {
// find actual end of table on current page
int dy = 0;
const int max_dy = info.rect.y() + info.rect.height();
const int vspace = vBorderSpacing();
for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
if (section->isTableSection()) {
if (toRenderBox(section)->y() > max_dy) {
continue;
}
int i = 0;
for (RenderObject* row = section->firstChild(); row; row = row->nextSibling()) {
if (!row->isTableRow()) {
continue;
}
// get actual bottom-y position of this row - pretty complicated, how could this be simplified?
// note how we have to take the rowPoint and section's y-offset into account, see e.g.
// RenderTableSection::paint where this is also done...
LayoutPoint rowPoint = flipForWritingModeForChild(toRenderBox(row), paintOffset);
int row_dy = rowPoint.y() + toRenderBox(row)->y() + toRenderBox(row)->logicalHeight() + toRenderBox(section)->y();
if (row_dy < max_dy && row_dy > dy) {
dy = row_dy;
}
else if (row_dy > max_dy) {
break;
}
i++;
}
}
}
repaintedFoot = true;
repaintedFootPoint = IntPoint(childPoint.x(), dy - m_foot->y());
dynamic_cast<RenderObject*>(m_foot)->paint(info, repaintedFootPoint);
}
}
}
if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
recalcCollapsedBorders();
// Using our cached sorted styles, we then do individual passes,
@ -673,6 +748,15 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
m_currentBorder = &m_collapsedBorders[i];
for (RenderTableSection* section = bottomSection(); section; section = sectionAbove(section)) {
LayoutPoint childPoint = flipForWritingModeForChild(section, paintOffset);
// also repaint borders of header/footer if required
if (section == m_head && repaintedHead) {
childPoint = repaintedHeadPoint;
}
else if (section == m_foot && repaintedFoot) {
childPoint = repaintedFootPoint;
}
section->paint(info, childPoint);
}
}

Просмотреть файл

@ -503,7 +503,7 @@ int RenderTableSection::distributeExtraLogicalHeightToRows(int extraLogicalHeigh
return extraLogicalHeight - remainingExtraLogicalHeight;
}
void RenderTableSection::layoutRows()
int RenderTableSection::layoutRows(int toAdd, int headHeight, int footHeight)
{
#ifndef NDEBUG
SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
@ -522,12 +522,41 @@ void RenderTableSection::layoutRows()
LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || style()->isFlippedBlocksWritingMode());
WTF::Vector<int> logicalHeightsForPrinting;
// make sure that rows do not overlap a page break
if (view()->layoutState()->pageLogicalHeight()) {
logicalHeightsForPrinting.resize(totalRows);
int pageOffset = 0;
for (int r = 0; r < totalRows; ++r) {
const int childLogicalHeight = m_rowPos[r + 1] - m_rowPos[r] - (m_grid[r].rowRenderer ? vspacing : 0);
logicalHeightsForPrinting[r] = childLogicalHeight;
LayoutState* layoutState = view()->layoutState();
const int pageLogicalHeight = layoutState->m_pageLogicalHeight;
if (childLogicalHeight < pageLogicalHeight - footHeight) {
const LayoutSize delta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
const int logicalOffset = m_rowPos[r] + pageOffset;
const int offset = isHorizontalWritingMode() ? delta.height() : delta.width();
const int remainingLogicalHeight = (pageLogicalHeight - (offset + logicalOffset) % pageLogicalHeight) % pageLogicalHeight;
if (remainingLogicalHeight - footHeight< childLogicalHeight) {
pageOffset += remainingLogicalHeight + headHeight;
}
}
m_rowPos[r] += pageOffset;
}
m_rowPos[totalRows] += pageOffset;
}
for (unsigned r = 0; r < totalRows; r++) {
// Set the row's x/y position and width/height.
if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
rowRenderer->setLogicalWidth(logicalWidth());
if (view()->layoutState()->pageLogicalHeight()) {
rowRenderer->setLogicalHeight(logicalHeightsForPrinting[r]);
}
else {
rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
}
rowRenderer->updateLayerTransform();
}
@ -541,8 +570,13 @@ void RenderTableSection::layoutRows()
continue;
int rowIndex = cell->rowIndex();
int rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing;
int rHeight;
if (view()->layoutState()->pageLogicalHeight() && cell->rowSpan() == 1) {
rHeight = logicalHeightsForPrinting[rowIndex];
}
else {
rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing;
}
// Force percent height children to lay themselves out again.
// This will cause these children to grow to fill the cell.
// FIXME: There is still more work to do here to fully match WinIE (should
@ -656,6 +690,7 @@ void RenderTableSection::layoutRows()
computeOverflowFromCells(totalRows, nEffCols);
statePusher.pop();
return height();
}
void RenderTableSection::computeOverflowFromCells()

Просмотреть файл

@ -78,7 +78,7 @@ public:
void addCell(RenderTableCell*, RenderTableRow* row);
int calcRowLogicalHeight();
void layoutRows();
int layoutRows(int, int, int);
void computeOverflowFromCells();
RenderTable* table() const { return toRenderTable(parent()); }

Просмотреть файл

@ -136,6 +136,8 @@ bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
void RenderView::layoutContent(const LayoutState& state)
{
repeatTableHeader = m_frameView->repeatTableHeader;
repeatTableFooter = m_frameView->repeatTableFooter;
UNUSED_PARAM(state);
ASSERT(needsLayout());

Просмотреть файл

@ -230,6 +230,9 @@ public:
IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); }
//Enable or disable repeated thead/tfoot.
bool repeatTableHeader;
bool repeatTableFooter;
protected:
virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;

Просмотреть файл

@ -981,6 +981,8 @@ void QWebFrameAdapter::setViewportSize(const QSize& size)
ASSERT(view);
view->resize(size);
view->adjustViewSize();
view->repeatTableHeader = repeatTableHeader;
view->repeatTableFooter = repeatTableFooter;
PrintContext printer(frame);
printer.setViewportToPdf(size);

Просмотреть файл

@ -226,6 +226,9 @@ public:
QWebPageAdapter* pageAdapter;
bool repeatTableHeader;
bool repeatTableFooter;
// protected:
bool allowsScrolling;
int marginWidth;

Просмотреть файл

@ -47,19 +47,24 @@ QtPrintContext::QtPrintContext(QPainter* painter, const QRect& pageRect, QWebFra
{
m_printContext->setElementToDraw(element);
renderElement = element;
totalPageLayoutSize = m_printContext->begin(pageRect.width(), pageRect.height());
float pageHeight = 0;
m_printContext->computePageRects(IntRect(pageRect), /* headerHeight 26*/ 0, /* footerHeight 26*/ 0, /* userScaleFactor */ 1.0, pageHeight);
IntRect tempRect = m_printContext->m_pageRects[0];
totalPageLayoutSize = m_printContext->begin(tempRect.width(), tempRect.height());
m_printContext->computePageRects(IntRect(pageRect), /* headerHeight 26*/ 0, /* footerHeight 26*/ 0, /* userScaleFactor */ 1.0, pageHeight);
printStatus = true;
float pageHeight = 0;
m_printContext->computePageRects(IntRect(pageRect), /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
}
QtPrintContext::QtPrintContext(QPainter* painter, const QRect& pageRect, QWebFrameAdapter* frameAdapter, bool status)
: m_graphicsContext(new GraphicsContext(painter))
, m_printContext(new PrintContext(frameAdapter->frame))
{
totalPageLayoutSize = m_printContext->begin(pageRect.width(), pageRect.height());
printStatus = status;
float pageHeight = 0;
m_printContext->computePageRects(IntRect(pageRect), /* headerHeight */ 0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
IntRect tempRect = m_printContext->m_pageRects[0];
totalPageLayoutSize = m_printContext->begin(tempRect.width(), tempRect.height());
printStatus = status;
m_printContext->computePageRects(IntRect(pageRect), /* headerHeight */0, /* footerHeight */ 0, /* userScaleFactor */ 1.0, pageHeight);
}
QtPrintContext::QtPrintContext(QPainter* painter, QWebFrameAdapter* frameAdapter)
{

Просмотреть файл

@ -1996,6 +1996,15 @@ QSize QWebPage::viewportSize() const
\sa QWebFrame::render(), preferredContentsSize
*/
void QWebPage::EnableRepeatedHeaderFooter(bool header,bool footer)
{
QWebFrameAdapter* mainFrame = d->mainFrameAdapter();
if (!mainFrame->hasView())
return;
mainFrame->repeatTableHeader = header;
mainFrame->repeatTableFooter = footer;
}
void QWebPage::setViewportSize(const QSize &size) const
{
d->m_viewportSize = size;

Просмотреть файл

@ -306,6 +306,7 @@ public:
QSize viewportSize() const;
void setViewportSize(const QSize &size) const;
void EnableRepeatedHeaderFooter(bool,bool);
ViewportAttributes viewportAttributesForSize(const QSize& availableSize) const;
QSize preferredContentsSize() const;