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:
Родитель
5a229f9c7c
Коммит
5df4e28040
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче