/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
/// The border widths are calculated like in Netscape: /// Outer border: BORDER + CELLSPACING + CELLPADDING /// Inner border: CELLSPACING + CELLPADDING /// However, we respect the border widths in SW if bSwBorders is set, /// so that we don't wrap wrongly. /// We also need to respect the distance to the content. Even if /// only the opposite side has a border.
sal_uInt16 SwHTMLTableLayout::GetLeftCellSpace( sal_uInt16 nCol, sal_uInt16 nColSpan, bool bSwBorders ) const
{
sal_uInt16 nSpace = m_nCellSpacing + m_nCellPadding;
if( nCol == 0 )
{
nSpace = nSpace + m_nBorder;
if( bSwBorders && nSpace < m_nLeftBorderWidth )
nSpace = m_nLeftBorderWidth;
} elseif( bSwBorders )
{ if( GetColumn(nCol)->HasLeftBorder() )
{ if( nSpace < m_nBorderWidth )
nSpace = m_nBorderWidth;
} elseif( nCol+nColSpan == m_nCols && m_nRightBorderWidth &&
nSpace < MIN_BORDER_DIST )
{
OSL_ENSURE( !m_nCellPadding, "GetLeftCellSpace: CELLPADDING!=0" ); // If the opposite side has a border we need to respect at // least the minimum distance to the content. // Additionally, we could also use nCellPadding for this.
nSpace = MIN_BORDER_DIST;
}
}
if( nCol+nColSpan == m_nCols )
{
nSpace += m_nBorder + m_nCellSpacing; if( bSwBorders && nSpace < m_nRightBorderWidth )
nSpace = m_nRightBorderWidth;
} elseif( bSwBorders && GetColumn(nCol)->HasLeftBorder() &&
nSpace < MIN_BORDER_DIST )
{
OSL_ENSURE( !m_nCellPadding, "GetRightCellSpace: CELLPADDING!=0" ); // If the opposite side has a border we need to respect at // least the minimum distance to the content. // Additionally, we could also use nCellPadding for this.
nSpace = MIN_BORDER_DIST;
}
sal_uInt16 SwHTMLTableLayout::GetBrowseWidth( const SwDoc& rDoc )
{ // If we have a layout, we can get the width from there. const SwRootFrame *pRootFrame = rDoc.getIDocumentLayoutAccess().GetCurrentLayout(); if( pRootFrame )
{ const SwFrame *pPageFrame = pRootFrame->GetLower(); if( pPageFrame ) return o3tl::narrowing<sal_uInt16>(pPageFrame->getFramePrintArea().Width());
}
// #i91658# // Assertion removed which state that no browse width is available. // Investigation reveals that all calls can handle the case that no browse // width is provided. return GetBrowseWidthByVisArea( rDoc );
}
// The maximal width for a <PRE> paragraph is the minimal width const SwFormatColl *pColl = &pTextNd->GetAnyFormatColl(); while( pColl && !pColl->IsDefault() &&
(USER_FMT & pColl->GetPoolFormatId()) )
{
pColl = static_cast<const SwFormatColl *>(pColl->DerivedFrom());
}
// <NOBR> in the whole cell apply to text but not to tables. // Netscape only considers this for graphics. if( (pColl && RES_POOLCOLL_HTML_PRE==pColl->GetPoolFormatId()) || bNoBreak )
{
rMinNoAlignCnts = rMaxNoAlignCnts;
rAbsMinNoAlignCnts = rMaxNoAlignCnts;
}
}
for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i );
pColumn->ClearPass1Info( !HasColTags() );
sal_uInt16 nMinColSpan = USHRT_MAX; // Column count to which the calculated width refers to
sal_uInt16 nColSkip = USHRT_MAX; // How many columns need to be skipped
// We need to examine all rows in order to // get the column that should be calculated next.
sal_uInt16 nColSpan = pCell->GetColSpan(); if( nColSpan < nColSkip )
nColSkip = nColSpan;
if( !pCnts || !pCnts->IsPass1Done(m_nPass1Done) )
{ // The cell is empty or it's content was not edited if( nColSpan < nMinColSpan )
nMinColSpan = nColSpan;
// A fixed table width is taken over as minimum and // maximum at the same time if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
{
sal_uLong nTabWidth = pChild->m_nWidthOption; if( nTabWidth >= nAbsMinTableCnts )
{
nMaxTableCnts = nTabWidth;
nAbsMinTableCnts = nTabWidth;
} else
{
nMaxTableCnts = nAbsMinTableCnts;
}
}
// A fixed table width is taken over as minimum and // maximum at the same time if( !pChild->m_bPercentWidthOption && pChild->m_nWidthOption )
{
sal_uLong nTabWidth = pChild->m_nWidthOption; if( nTabWidth >= nAbsMinTableCnts )
{
nMaxTableCnts = nTabWidth;
nAbsMinTableCnts = nTabWidth;
} else
{
nMaxTableCnts = nAbsMinTableCnts;
}
}
// This code previously came after AddBorderWidth // If a table's width is wider in a cell than what we've calculated // for the other content we need to use the table's width. if( nMaxTableCell > nMaxNoAlignCell )
nMaxNoAlignCell = nMaxTableCell; if( nAbsMinTableCell > nAbsMinNoAlignCell )
{
nAbsMinNoAlignCell = nAbsMinTableCell; if( nMinNoAlignCell < nAbsMinNoAlignCell )
nMinNoAlignCell = nAbsMinNoAlignCell; if( nMaxNoAlignCell < nMinNoAlignCell )
nMaxNoAlignCell = nMinNoAlignCell;
} // This code previously came after AddBorderWidth
// Respect the border and distance to the content
AddBorderWidth( nMinNoAlignCell, nMaxNoAlignCell,
nAbsMinNoAlignCell, i, nColSpan );
if( 1==nColSpan )
{ // take over the values directly
pColumn->MergeMinMaxNoAlign( nMinNoAlignCell,
nMaxNoAlignCell,
nAbsMinNoAlignCell );
// the widest WIDTH wins if( !HasColTags() )
pColumn->MergeCellWidthOption( nWidth, bRelWidth );
} else
{ // Process the data line by line from left to right at the end
// When which values is taken over will be explained further down. if( !HasColTags() && nWidth && !bRelWidth )
{
sal_uLong nAbsWidth = nWidth, nDummy = 0, nDummy2 = 0;
AddBorderWidth( nAbsWidth, nDummy, nDummy2,
i, nColSpan, false );
SwHTMLTableLayoutConstraints *pConstr = new SwHTMLTableLayoutConstraints( nMinNoAlignCell,
nMaxNoAlignCell, j, i, nColSpan ); if (xConstraints)
{
SwHTMLTableLayoutConstraints* pConstraints = xConstraints->InsertNext(pConstr); // coverity[leaked_storage] - ownership transferred to pConstraints chain
xConstraints.release();
xConstraints.reset(pConstraints);
} else
xConstraints.reset(pConstr);
}
}
}
OSL_ENSURE( nMinColSpan>0 && nColSkip>0 && nColSkip <= nMinColSpan, "Layout pass 1: Columns are being forgotten!" );
OSL_ENSURE( nMinColSpan!=USHRT_MAX, "Layout pass 1: unnecessary pass through the loop or a bug" );
if( 1==nMinColSpan )
{ // There are cells with COLSPAN 1 and therefore also useful // values in pColumn
// Take over values according to the following table (Netscape 4.0 pv 3):
// WIDTH: no COLS COLS
// none min = min min = absmin // max = max max = max
// >= min min = min min = width // max = width max = width
// >= absmin min = width(*) min = width // max = width max = width
// < absmin min = absmin min = absmin // max = absmin max = absmin
// (*) Netscape uses the minimum width without a break before // the last graphic here. We don't have that (yet?), // so we leave it set to width.
if( pColumn->GetWidthOption() && !pColumn->IsRelWidthOption() )
{ // Take over absolute widths as minimal and maximal widths.
sal_uLong nAbsWidth = pColumn->GetWidthOption();
sal_uLong nDummy = 0, nDummy2 = 0;
AddBorderWidth( nAbsWidth, nDummy, nDummy2, i, 1, false );
if( nAbsWidth >= pColumn->GetMinNoAlign() )
{
pColumn->SetMinMax( HasColsOption() ? nAbsWidth
: pColumn->GetMinNoAlign(),
nAbsWidth );
} elseif( nAbsWidth >= pColumn->GetAbsMinNoAlign() )
{
pColumn->SetMinMax( nAbsWidth, nAbsWidth );
} else
{
pColumn->SetMinMax( pColumn->GetAbsMinNoAlign(),
pColumn->GetAbsMinNoAlign() );
}
} else
{
pColumn->SetMinMax( HasColsOption() ? pColumn->GetAbsMinNoAlign()
: pColumn->GetMinNoAlign(),
pColumn->GetMaxNoAlign() );
}
} elseif( USHRT_MAX!=nMinColSpan )
{ // Can be anything != 0, because it is altered by the constraints.
pColumn->SetMinMax( MINLAY, MINLAY );
// the next columns need not to be processed
i += (nColSkip-1);
}
// Now process the constraints
SwHTMLTableLayoutConstraints *pConstr = xConstraints.get(); while( pConstr )
{ // At first we need to process the width in the same way // as the column widths
sal_uInt16 nCol = pConstr->GetColumn();
sal_uInt16 nColSpan = pConstr->GetColSpan();
sal_uLong nConstrMin = pConstr->GetMinNoAlign();
sal_uLong nConstrMax = pConstr->GetMaxNoAlign();
// We get the hitherto width of the spanned columns
sal_uLong nColsMin = 0;
sal_uLong nColsMax = 0; for( sal_uInt16 j=nCol; j<nCol+nColSpan; j++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( j );
nColsMin += pColumn->GetMin();
nColsMax += pColumn->GetMax();
}
if( nColsMin<nConstrMin )
{ // Proportionately distribute the minimum value to the columns
sal_uLong nMinD = nConstrMin-nColsMin;
if( nConstrMin > nColsMax )
{ // Proportional according to the minimum widths
sal_uInt16 nEndCol = nCol+nColSpan;
sal_uLong nDiff = nMinD; for( sal_uInt16 ic=nCol; ic<nEndCol; ic++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
pColumn->SetMinMax( nColMin, nColMax );
}
} else
{ // Proportional according to the difference of max and min for( sal_uInt16 ic=nCol; ic<nCol+nColSpan; ic++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( ic );
if( HasColTags() )
{ // To adapt the relative widths, in a first step we multiply the // minimum width of all affected cells with the relative width // of the column. // Thus, the width ratio among the columns is correct.
// Furthermore, a factor is calculated that says by how much the // cell has gotten wider than the minimum width.
// In the second step the calculated widths are divided by this // factor. Thereby a cell's width is preserved and serves as a // basis for the other cells. // We only change the maximum widths here!
sal_uLong nAbsMin = 0; // absolute minimum width of all widths with relative width
sal_uLong nRel = 0; // sum of all relative widths of all columns for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
{
nAbsMin += pColumn->GetMin();
nRel += pColumn->GetWidthOption();
}
}
sal_uLong nQuot = ULONG_MAX; for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() )
{
m_nMax -= pColumn->GetMax(); if( pColumn->GetWidthOption() && pColumn->GetMin() )
{
pColumn->SetMax( nAbsMin * pColumn->GetWidthOption() );
sal_uLong nColQuot = pColumn->GetMax() / pColumn->GetMin(); if( nColQuot<nQuot )
nQuot = nColQuot;
}
}
}
OSL_ENSURE( 0==nRel || nQuot!=ULONG_MAX, "Where did the relative columns go?" ); for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() )
{ if( pColumn->GetWidthOption() )
pColumn->SetMax( pColumn->GetMax() / nQuot ); else
pColumn->SetMax( pColumn->GetMin() );
OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(), "Maximum column width is lower than the minimum column width" );
m_nMax += pColumn->GetMax();
}
}
} else
{
sal_uInt16 nRel = 0; // sum of the relative widths of all columns
sal_uInt16 nRelCols = 0; // count of the columns with a relative setting
sal_uLong nRelMax = 0; // fraction of the maximum of this column for( i=0; i<m_nCols; i++ )
{
OSL_ENSURE( nRel<=100, "relative width of all columns > 100%" );
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
{ // Make sure that the relative widths don't go above 100%
sal_uInt16 nColWidth = pColumn->GetWidthOption(); if( nRel+nColWidth > 100 )
{
nColWidth = 100 - nRel;
pColumn->SetWidthOption( nColWidth );
}
nRelMax += pColumn->GetMax();
nRel = nRel + nColWidth;
nRelCols++;
} elseif( !pColumn->GetMin() )
{ // The column is empty (so it was solely created by // COLSPAN) and therefore must not be assigned a % width.
nRelCols++;
}
}
// If there are percentages left we distribute them to the columns // that don't have a width setting. Like in Netscape we distribute // the remaining percentages according to the ratio of the maximum // width of the affected columns. // For the maximum widths we also take the fixed-width columns // into account. Is that correct?
sal_uLong nFixMax = 0; if( nRel < 100 && nRelCols < m_nCols )
{
nFixMax = m_nMax - nRelMax;
SAL_WARN_IF(!nFixMax, "sw.core", "bad fixed width max");
} if (nFixMax)
{
sal_uInt16 nRelLeft = 100 - nRel; for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( !pColumn->IsRelWidthOption() &&
!pColumn->GetWidthOption() &&
pColumn->GetMin() )
{ // the next column gets the rest
sal_uInt16 nColWidth =
o3tl::narrowing<sal_uInt16>((pColumn->GetMax() * nRelLeft) / nFixMax);
pColumn->SetWidthOption( nColWidth );
}
}
}
// adjust the maximum widths now accordingly
sal_uLong nQuotMax = ULONG_MAX;
sal_uLong nOldMax = m_nMax;
m_nMax = 0; for( i=0; i<m_nCols; i++ )
{ // Columns with a % setting are adapted accordingly. // Columns, that // - do not have a % setting and are located within a tables // with COLS and WIDTH, or // - their width is 0% // get set to the minimum width.
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() )
{
sal_uLong nNewMax;
sal_uLong nColQuotMax; if( !m_nWidthOption )
{
nNewMax = nOldMax * pColumn->GetWidthOption();
nColQuotMax = nNewMax / pColumn->GetMax();
} else
{
nNewMax = m_nMin * pColumn->GetWidthOption();
nColQuotMax = nNewMax / pColumn->GetMin();
}
pColumn->SetMax( nNewMax ); if( nColQuotMax < nQuotMax )
nQuotMax = nColQuotMax;
} elseif( HasColsOption() || m_nWidthOption ||
(pColumn->IsRelWidthOption() &&
!pColumn->GetWidthOption()) )
pColumn->SetMax( pColumn->GetMin() );
} // and divide by the quotient
SAL_WARN_IF(!nQuotMax, "sw.core", "Where did the relative columns go?"); for (i = 0; i < m_nCols; ++i)
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if (pColumn->IsRelWidthOption() && pColumn->GetWidthOption() && nQuotMax)
{
pColumn->SetMax( pColumn->GetMax() / nQuotMax );
OSL_ENSURE( pColumn->GetMax() >= pColumn->GetMin(), "Minimum width is one column bigger than maximum" ); if( pColumn->GetMax() < pColumn->GetMin() )
pColumn->SetMax( pColumn->GetMin() );
}
m_nMax += pColumn->GetMax();
}
}
}
//TODO: provide documentation /**
@param nAbsAvail available space in TWIPS. @param nRelAvail available space related to USHRT_MAX or 0 @param nAbsSpace fraction of nAbsAvail, which is reserved by the surrounding cell for the border and the distance to the paragraph.
*/ void SwHTMLTableLayout::AutoLayoutPass2( sal_uInt16 nAbsAvail, sal_uInt16 nRelAvail,
sal_uInt16 nAbsLeftSpace,
sal_uInt16 nAbsRightSpace,
sal_uInt16 nParentInhAbsSpace )
{ // For a start we do a lot of plausibility tests
// An absolute width always has to be passed
OSL_ENSURE( nAbsAvail, "AutoLayout pass 2: No absolute width given" );
// A relative width must only be passed for tables within tables (?)
OSL_ENSURE( IsTopTable() == (nRelAvail==0), "AutoLayout pass 2: Relative width at table in table or the other way around" );
// The table's minimum width must not be bigger than its maximum width
OSL_ENSURE( m_nMin<=m_nMax, "AutoLayout pass 2: nMin > nMax" );
// Remember the available width for which the table was calculated. // This is a good place as we pass by here for the initial calculation // of the table in the parser and for each Resize_ call.
m_nLastResizeAbsAvail = nAbsAvail;
// Step 1: The available space is readjusted for the left/right border, // possibly existing filler cells and distances.
// Left and right distance if( m_nLeftMargin || m_nRightMargin )
{ if( IsTopTable() )
{ // For the top table we always respect the borders, because we // never go below the table's minimum width.
nAbsAvail -= (m_nLeftMargin + m_nRightMargin);
} elseif( GetMin() + m_nLeftMargin + m_nRightMargin <= nAbsAvail )
{ // Else, we only respect the borders if there's space available // for them (nMin has already been calculated!)
nAbsLeftFill = nAbsLeftFill + m_nLeftMargin;
nAbsRightFill = nAbsRightFill + m_nRightMargin;
}
}
// Read just the available space
m_nRelLeftFill = 0;
m_nRelRightFill = 0; if( !IsTopTable() && (nAbsLeftFill>0 || nAbsRightFill) )
{
sal_uLong nAbsLeftFillL = nAbsLeftFill, nAbsRightFillL = nAbsRightFill;
// The absolute width is equal to the given percentage of // the available width. // Top tables only get a relative width if the available space // is *strictly larger* than the minimum width.
// CAUTION: We need the "strictly larger" because changing from a // relative width to an absolute width by resizing would lead // to an infinite loop.
// Because we do not call resize for tables in frames if the // frame has a non-relative width, we cannot play such games.
// Let's play such games now anyway. We had a graphic in a 1% wide // table and it didn't fit in of course.
nAbsTabWidth = o3tl::narrowing<sal_uInt16>( (static_cast<sal_uLong>(nAbsAvail) * m_nWidthOption) / 100 ); if( IsTopTable() &&
( /*MayBeInFlyFrame() ||*/ static_cast<sal_uLong>(nAbsTabWidth) > m_nMin ) )
{
nRelAvail = USHRT_MAX;
m_bUseRelWidth = true;
}
} else
{
nAbsTabWidth = m_nWidthOption; if( nAbsTabWidth > MAX_TABWIDTH )
nAbsTabWidth = MAX_TABWIDTH;
// Tables within tables must never get wider than the available // space. if( !IsTopTable() && nAbsTabWidth > nAbsAvail )
nAbsTabWidth = nAbsAvail;
}
}
OSL_ENSURE( IsTopTable() || nAbsTabWidth<=nAbsAvail, "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for table in table" );
OSL_ENSURE( !nRelAvail || nAbsTabWidth<=nAbsAvail, "AutoLayout pass 2: nAbsTabWidth > nAbsAvail for relative width" );
// Catch for the two asserts above (we never know!) if( (!IsTopTable() || nRelAvail>0) && nAbsTabWidth>nAbsAvail )
nAbsTabWidth = nAbsAvail;
// Step 3: Identify the column width and, if applicable, the absolute // and relative table widths. if( (!IsTopTable() && m_nMin > static_cast<sal_uLong>(nAbsAvail)) ||
m_nMin > MAX_TABWIDTH )
{ // If // - an inner table's minimum is larger than the available space, or // - a top table's minimum is larger than USHORT_MAX the table // has to be adapted to the available space or USHORT_MAX. // We preserve the widths' ratio amongst themselves, however.
nAbs = nAbs + pColumn->GetAbsColWidth();
nRel = nRel + pColumn->GetRelColWidth();
}
pColumn = GetColumn( m_nCols-1 );
pColumn->SetAbsColWidth( nAbsTabWidth - nAbs );
pColumn->SetRelColWidth( m_nRelTabWidth - nRel );
}
} elseif( m_nMax <= static_cast<sal_uLong>(nAbsTabWidth ? nAbsTabWidth : nAbsAvail) )
{ // If // - the table has a fixed width and the table's maximum is // smaller, or //- the maximum is smaller than the available space, // we can take over the maximum as it is. Respectively // the table can only be adapted to the fixed width by // respecting the maximum.
// No fixed width, use the maximum. if( !nAbsTabWidth )
nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMax);
// A top table may also get wider then the available space. if( nAbsTabWidth > nAbsAvail )
{
OSL_ENSURE( IsTopTable(), "Table in table should get wider than the surrounding cell." );
nAbsAvail = nAbsTabWidth;
}
// Only use the relative widths' fraction, that is used for the // absolute width.
sal_uLong nAbsTabWidthL = nAbsTabWidth; if (nRelAvail)
{ if (nAbsAvail == 0) throw o3tl::divide_by_zero();
m_nRelTabWidth = o3tl::narrowing<sal_uInt16>((nAbsTabWidthL * nRelAvail) / nAbsAvail);
} else
m_nRelTabWidth = nAbsTabWidth;
// Are there columns width a percentage setting and some without one?
sal_uLong nFixMax = m_nMax; for( sal_uInt16 i=0; i<m_nCols; i++ )
{ const SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption()>0 )
nFixMax -= pColumn->GetMax();
}
if( nFixMax > 0 && nFixMax < m_nMax )
{ // Yes, distribute the to-be-distributed space only to the // columns with a percentage setting.
// In this case (and in this case only) there are columns // that exactly keep their maximum width, that is they neither // get smaller nor wider. When calculating the absolute width // from the relative width we can get rounding errors. // To correct this, we first make the fixed widths compensate for // this error. We then fix the relative widths the same way.
// The to-be-distributed percentage of the maximum, the // relative and absolute widths. Here, nFixMax corresponds // to nAbs, so that we could've called it nAbs. // The code is, however, more readable like that.
OSL_ENSURE( nFixMax == nAbs, "Two loops, two sums?" );
sal_uLong nDistMax = m_nMax - nFixMax;
sal_uInt16 nDistAbsTabWidth = nAbsTabWidth - nAbs;
sal_uInt16 nDistRelTabWidth = m_nRelTabWidth - nRel;
for( i=0; i<m_nCols; i++ )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( i ); if( pColumn->IsRelWidthOption() && pColumn->GetWidthOption() > 0 )
{ // The column gets proportionately wider.
nFixedCols++; if( nFixedCols == m_nCols )
{
pColumn->SetAbsColWidth( nAbsTabWidth-nAbs );
pColumn->SetRelColWidth( m_nRelTabWidth-nRel );
} else
{
sal_uLong nColMax = pColumn->GetMax();
pColumn->SetAbsColWidth(
o3tl::narrowing<sal_uInt16>((nColMax * nDistAbsTabWidth) / nDistMax) );
pColumn->SetRelColWidth(
o3tl::narrowing<sal_uInt16>((nColMax * nDistRelTabWidth) / nDistMax) );
}
nAbs = nAbs + pColumn->GetAbsColWidth();
nRel = nRel + pColumn->GetRelColWidth();
}
}
OSL_ENSURE( m_nCols==nFixedCols, "Missed a column!" );
} elseif (m_nCols > 0)
{ if (m_nMax == 0) throw o3tl::divide_by_zero(); // No. So distribute the space regularly among all columns. for (sal_uInt16 i=0; i < m_nCols; ++i)
{
sal_uLong nColMax = GetColumn( i )->GetMax();
GetColumn( i )->SetAbsColWidth(
o3tl::narrowing<sal_uInt16>((nColMax * nAbsTabWidth) / m_nMax) );
GetColumn( i )->SetRelColWidth(
o3tl::narrowing<sal_uInt16>((nColMax * m_nRelTabWidth) / m_nMax) );
}
}
} else
{ // Proportionately distribute the space that extends over the minimum // width among the columns. if( !nAbsTabWidth )
nAbsTabWidth = nAbsAvail; if( nAbsTabWidth < m_nMin )
nAbsTabWidth = o3tl::narrowing<sal_uInt16>(m_nMin);
if( nAbsTabWidth > nAbsAvail )
{
OSL_ENSURE( IsTopTable(), "A nested table should become wider than the available space." );
nAbsAvail = nAbsTabWidth;
}
// Step 4: For nested tables we can have balancing cells on the // left or right. Here we calculate their width.
m_nInhAbsLeftSpace = 0;
m_nInhAbsRightSpace = 0; if( IsTopTable() ||
!(m_nRelLeftFill>0 || m_nRelRightFill>0 || nAbsTabWidth<nAbsAvail) ) return;
// Calculate the width of additional cells we use for // aligning inner tables.
sal_uInt16 nAbsDist = o3tl::narrowing<sal_uInt16>(nAbsAvail-nAbsTabWidth);
sal_uInt16 nRelDist = o3tl::narrowing<sal_uInt16>(nRelAvail-m_nRelTabWidth);
sal_uInt16 nParentInhAbsLeftSpace = 0, nParentInhAbsRightSpace = 0;
// Filler widths are added to the outer columns, if there are no boxes // for them after the first pass (nWidth>0) or their width would become // too small or if there are COL tags and the filler width corresponds // to the border width. // In the last case we probably exported the table ourselves. if( m_nRelLeftFill &&
( m_nWidthSet>0 || nAbsLeftFill<MINLAY+m_nInhLeftBorderWidth ||
(HasColTags() && nAbsLeftFill < nAbsLeftSpace+nParentInhAbsLeftSpace+20) ) )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( 0 );
pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsLeftFill );
pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelLeftFill );
m_nRelLeftFill = 0;
m_nInhAbsLeftSpace = nAbsLeftSpace + nParentInhAbsLeftSpace;
} if( m_nRelRightFill &&
( m_nWidthSet>0 || nAbsRightFill<MINLAY+m_nInhRightBorderWidth ||
(HasColTags() && nAbsRightFill < nAbsRightSpace+nParentInhAbsRightSpace+20) ) )
{
SwHTMLTableLayoutColumn *pColumn = GetColumn( m_nCols-1 );
pColumn->SetAbsColWidth( pColumn->GetAbsColWidth()+nAbsRightFill );
pColumn->SetRelColWidth( pColumn->GetRelColWidth()+m_nRelRightFill );
m_nRelRightFill = 0;
m_nInhAbsRightSpace = nAbsRightSpace + nParentInhAbsRightSpace;
}
}
SAL_WARN_IF( nOldWidth && std::abs(*pWidth-nOldWidth) >= COLFUZZY, "sw.core", "A box's rows have all a different length" );
}
void SwHTMLTableLayout::SetWidths( bool bCallPass2, sal_uInt16 nAbsAvail,
sal_uInt16 nRelAvail, sal_uInt16 nAbsLeftSpace,
sal_uInt16 nAbsRightSpace,
sal_uInt16 nParentInhAbsSpace )
{ // SetWidth must have been passed through once more for every cell in the // end.
m_nWidthSet++;
// Step 0: If necessary, we call the layout algorithm of Pass2. if( bCallPass2 )
AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, nAbsRightSpace,
nParentInhAbsSpace );
// Step 1: Set the new width in all content boxes. // Because the boxes don't know anything about the HTML table structure, // we iterate over the HTML table structure. // For tables in tables in tables we call SetWidth recursively. for( sal_uInt16 i=0; i<m_nRows; i++ )
{ for( sal_uInt16 j=0; j<m_nCols; j++ )
{
SwHTMLTableLayoutCell *pCell = GetCell( i, j );
// Step 2: If we have a top table, we adapt the formats of the // non-content-boxes. Because they are not known in the HTML table // due to garbage collection there, we need the iterate over the // whole table. // We also adapt the table frame format. For nested tables we set the // filler cell's width instead. if( !IsTopTable() ) return;
SwTwips nCalcTabWidth = 0; for( const SwTableLine *pLine : m_pSwTable->GetTabLines() )
lcl_ResizeLine( pLine, &nCalcTabWidth );
SAL_WARN_IF( std::abs( m_nRelTabWidth-nCalcTabWidth ) >= COLFUZZY, "sw.core", "Table width is not equal to the row width" );
// Lock the table format when altering it, or else the box formats // are altered again. // Also, we need to preserve a percent setting if it exists.
SwFrameFormat *pFrameFormat = m_pSwTable->GetFrameFormat(); const_cast<SwTable *>(m_pSwTable)->LockModify();
SwFormatFrameSize aFrameSize( pFrameFormat->GetFrameSize() );
aFrameSize.SetWidth( m_nRelTabWidth ); bool bRel = m_bUseRelWidth &&
text::HoriOrientation::FULL!=pFrameFormat->GetHoriOrient().GetHoriOrient();
aFrameSize.SetWidthPercent( static_cast<sal_uInt8>(bRel ? m_nWidthOption : 0) );
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.