LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/filter/writer - wrtswtbl.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 219 389 56.3 %
Date: 2013-07-09 Functions: 19 26 73.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <hintids.hxx>
      21             : #include <editeng/boxitem.hxx>
      22             : #include <editeng/brushitem.hxx>
      23             : #include <tools/fract.hxx>
      24             : #include <wrtswtbl.hxx>
      25             : #include <swtable.hxx>
      26             : #include <frmfmt.hxx>
      27             : #include <fmtfsize.hxx>
      28             : #include <fmtornt.hxx>
      29             : #include <frmatr.hxx>
      30             : #include <htmltbl.hxx>
      31             : 
      32             : using ::editeng::SvxBorderLine;
      33             : using namespace ::com::sun::star;
      34             : 
      35         307 : sal_Int16 SwWriteTableCell::GetVertOri() const
      36             : {
      37         307 :     sal_Int16 eCellVertOri = text::VertOrientation::TOP;
      38         307 :     if( pBox->GetSttNd() )
      39             :     {
      40         307 :         const SfxItemSet& rItemSet = pBox->GetFrmFmt()->GetAttrSet();
      41             :         const SfxPoolItem *pItem;
      42         307 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_VERT_ORIENT, sal_False, &pItem ) )
      43             :         {
      44             :             sal_Int16 eBoxVertOri =
      45           0 :                 ((const SwFmtVertOrient *)pItem)->GetVertOrient();
      46           0 :             if( text::VertOrientation::CENTER==eBoxVertOri || text::VertOrientation::BOTTOM==eBoxVertOri)
      47           0 :                 eCellVertOri = eBoxVertOri;
      48             :         }
      49             :     }
      50             : 
      51         307 :     return eCellVertOri;
      52             : }
      53             : 
      54         140 : SwWriteTableRow::SwWriteTableRow( long nPosition, bool bUseLayoutHeights )
      55             :     : pBackground(0), nPos(nPosition), mbUseLayoutHeights(bUseLayoutHeights),
      56             :     nTopBorder(USHRT_MAX), nBottomBorder(USHRT_MAX), bTopBorder(true),
      57         140 :     bBottomBorder(true)
      58             : {
      59         140 : }
      60             : 
      61         309 : SwWriteTableCell *SwWriteTableRow::AddCell( const SwTableBox *pBox,
      62             :                                 sal_uInt16 nRow, sal_uInt16 nCol,
      63             :                                 sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
      64             :                                 long nHeight,
      65             :                                 const SvxBrushItem *pBackgroundBrush )
      66             : {
      67             :     SwWriteTableCell *pCell =
      68             :         new SwWriteTableCell( pBox, nRow, nCol, nRowSpan, nColSpan,
      69         309 :                                 nHeight, pBackgroundBrush );
      70         309 :     aCells.push_back( pCell );
      71             : 
      72         309 :     return pCell;
      73             : }
      74             : 
      75         559 : SwWriteTableCol::SwWriteTableCol(sal_uInt32 nPosition)
      76             :     : nPos(nPosition), nWidthOpt(0), bRelWidthOpt(false), bOutWidth(true),
      77         559 :     bLeftBorder(true), bRightBorder(true)
      78             : {
      79         559 : }
      80             : 
      81         478 : sal_uInt32 SwWriteTable::GetBoxWidth( const SwTableBox *pBox )
      82             : {
      83         478 :     const SwFrmFmt *pFmt = pBox->GetFrmFmt();
      84             :     const SwFmtFrmSize& aFrmSize=
      85         478 :         (const SwFmtFrmSize&)pFmt->GetFmtAttr( RES_FRM_SIZE );
      86             : 
      87         478 :     return sal::static_int_cast<sal_uInt32>(aFrmSize.GetSize().Width());
      88             : }
      89             : 
      90         140 : long SwWriteTable::GetLineHeight( const SwTableLine *pLine )
      91             : {
      92             : #ifdef DBG_UTIL
      93             :     bool bOldGetLineHeightCalled = m_bGetLineHeightCalled;
      94             :     m_bGetLineHeightCalled = true;
      95             : #endif
      96             : 
      97         140 :     long nHeight = 0;
      98         140 :     if( bUseLayoutHeights )
      99             :     {
     100             :         // At first we try to get the height of the layout.
     101          62 :         bool bLayoutAvailable = false;
     102          62 :         nHeight = pLine->GetTableLineHeight(bLayoutAvailable);
     103          62 :         if( nHeight > 0 )
     104          38 :             return nHeight;
     105             : 
     106             :         // If no layout is found, we assume that the heights are fixed.
     107             :         // #i60390# - in some cases we still want to continue
     108             :         // to use the layout heights even if one of the rows has a height of 0
     109             :         // ('hidden' rows)
     110          24 :         bUseLayoutHeights = bLayoutAvailable;
     111             : 
     112             : #ifdef DBG_UTIL
     113             :         SAL_WARN_IF( !bLayoutAvailable && bOldGetLineHeightCalled, "sw", "Layout invalid?" );
     114             : #endif
     115             :     }
     116             : 
     117         102 :     const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     118         102 :     sal_uInt16 nBoxes = rBoxes.size();
     119             : 
     120         612 :     for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     121             :     {
     122         510 :         const SwTableBox* pBox = rBoxes[nBox];
     123         510 :         if( pBox->GetSttNd() )
     124             :         {
     125         510 :             if( nHeight < ROW_DFLT_HEIGHT )
     126         102 :                 nHeight = ROW_DFLT_HEIGHT;
     127             :         }
     128             :         else
     129             :         {
     130           0 :             long nTmp = 0;
     131           0 :             const SwTableLines &rLines = pBox->GetTabLines();
     132           0 :             for( sal_uInt16 nLine=0; nLine<rLines.size(); nLine++ )
     133             :             {
     134           0 :                 nTmp += GetLineHeight( rLines[nLine] );
     135             :             }
     136           0 :             if( nHeight < nTmp )
     137           0 :                 nHeight = nTmp;
     138             :         }
     139             :     }
     140             : 
     141         102 :     return nHeight;
     142             : }
     143             : 
     144           0 : long SwWriteTable::GetLineHeight( const SwTableBox *pBox ) const
     145             : {
     146           0 :     const SwTableLine *pLine = pBox->GetUpper();
     147             : 
     148           0 :     if( !pLine )
     149           0 :         return 0;
     150             : 
     151           0 :     const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     152             :     const SfxPoolItem* pItem;
     153           0 :     const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     154             : 
     155           0 :     long nHeight = 0;
     156           0 :     if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
     157           0 :         nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
     158             : 
     159           0 :     return nHeight;
     160             : }
     161             : 
     162           0 : const SvxBrushItem *SwWriteTable::GetLineBrush( const SwTableBox *pBox,
     163             :                                                   SwWriteTableRow *pRow )
     164             : {
     165           0 :     const SwTableLine *pLine = pBox->GetUpper();
     166             : 
     167           0 :     while( pLine )
     168             :     {
     169           0 :         const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     170             :         const SfxPoolItem* pItem;
     171           0 :         const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     172             : 
     173           0 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
     174           0 :                                                    &pItem ) )
     175             :         {
     176           0 :             if( !pLine->GetUpper() )
     177             :             {
     178           0 :                 if( !pRow->GetBackground() )
     179           0 :                     pRow->SetBackground( (const SvxBrushItem *)pItem );
     180           0 :                 pItem = 0;
     181             :             }
     182             : 
     183           0 :             return (const SvxBrushItem *)pItem;
     184             :         }
     185             : 
     186           0 :         pBox = pLine->GetUpper();
     187           0 :         pLine = pBox ? pBox->GetUpper() : 0;
     188             :     }
     189             : 
     190           0 :     return 0;
     191             : }
     192             : 
     193             : 
     194        1228 : void SwWriteTable::MergeBorders( const SvxBorderLine* pBorderLine,
     195             :                                    bool bTable )
     196             : {
     197        1228 :     if( (sal_uInt32)-1 == nBorderColor )
     198             :     {
     199          11 :         Color aGrayColor( COL_GRAY );
     200          11 :         if( !pBorderLine->GetColor().IsRGBEqual( aGrayColor ) )
     201          11 :             nBorderColor = pBorderLine->GetColor().GetColor();
     202             :     }
     203             : 
     204        1228 :     if( !bCollectBorderWidth )
     205        1228 :         return;
     206             : 
     207        1228 :     sal_uInt16 nOutWidth = pBorderLine->GetOutWidth();
     208        1228 :     if( bTable )
     209             :     {
     210         198 :         if( nOutWidth && (!nBorder || nOutWidth < nBorder) )
     211          11 :             nBorder = nOutWidth;
     212             :     }
     213             :     else
     214             :     {
     215        1030 :         if( nOutWidth && (!nInnerBorder || nOutWidth < nInnerBorder) )
     216           9 :             nInnerBorder = nOutWidth;
     217             :     }
     218             : 
     219        1228 :     sal_uInt16 nDist = pBorderLine->GetInWidth() ? pBorderLine->GetDistance()
     220        1228 :                                                 : 0;
     221        1228 :     if( nDist && (!nCellSpacing || nDist < nCellSpacing) )
     222           0 :         nCellSpacing = nDist;
     223             : }
     224             : 
     225             : 
     226         309 : sal_uInt16 SwWriteTable::MergeBoxBorders( const SwTableBox *pBox,
     227             :                                         size_t const nRow, size_t const nCol,
     228             :                                         sal_uInt16 nRowSpan, sal_uInt16 nColSpan,
     229             :                                         sal_uInt16& rTopBorder,
     230             :                                         sal_uInt16 &rBottomBorder )
     231             : {
     232         309 :     sal_uInt16 nBorderMask = 0;
     233             : 
     234         309 :     const SwFrmFmt *pFrmFmt = pBox->GetFrmFmt();
     235         309 :     const SvxBoxItem& rBoxItem = (const SvxBoxItem&)pFrmFmt->GetFmtAttr( RES_BOX );
     236             : 
     237         309 :     if( rBoxItem.GetTop() )
     238             :     {
     239         307 :         nBorderMask |= 1;
     240         307 :         MergeBorders( rBoxItem.GetTop(), nRow==0 );
     241         307 :         rTopBorder = rBoxItem.GetTop()->GetOutWidth();
     242             :     }
     243             : 
     244         309 :     if( rBoxItem.GetLeft() )
     245             :     {
     246         307 :         nBorderMask |= 4;
     247         307 :         MergeBorders( rBoxItem.GetLeft(), nCol==0 );
     248             :     }
     249             : 
     250         309 :     if( rBoxItem.GetBottom() )
     251             :     {
     252         307 :         nBorderMask |= 2;
     253         307 :         MergeBorders( rBoxItem.GetBottom(), nRow+nRowSpan==aRows.size() );
     254         307 :         rBottomBorder = rBoxItem.GetBottom()->GetOutWidth();
     255             :     }
     256             : 
     257         309 :     if( rBoxItem.GetRight() )
     258             :     {
     259         307 :         nBorderMask |= 8;
     260         307 :         MergeBorders( rBoxItem.GetRight(), nCol+nColSpan==aCols.size() );
     261             :     }
     262             : 
     263             :     // If any distance is set, the smallest one is used. This holds for
     264             :     // the four distance of a box as well as for the distances of different
     265             :     // boxes.
     266         309 :     if( bCollectBorderWidth )
     267             :     {
     268         309 :         sal_uInt16 nDist = rBoxItem.GetDistance( BOX_LINE_TOP );
     269         309 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     270           1 :             nCellPadding = nDist;
     271         309 :         nDist = rBoxItem.GetDistance( BOX_LINE_BOTTOM );
     272         309 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     273           0 :             nCellPadding = nDist;
     274         309 :         nDist = rBoxItem.GetDistance( BOX_LINE_LEFT );
     275         309 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     276           9 :             nCellPadding = nDist;
     277         309 :         nDist = rBoxItem.GetDistance( BOX_LINE_RIGHT );
     278         309 :         if( nDist && (!nCellPadding || nDist < nCellPadding) )
     279           3 :             nCellPadding = nDist;
     280             :     }
     281             : 
     282         309 :     return nBorderMask;
     283             : }
     284             : 
     285             : 
     286         265 : sal_uInt32  SwWriteTable::GetRawWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     287             : {
     288         265 :     sal_uInt32 nWidth = aCols[nCol+nColSpan-1]->GetPos();
     289         265 :     if( nCol > 0 )
     290         212 :         nWidth = nWidth - aCols[nCol-1]->GetPos();
     291             : 
     292         265 :     return nWidth;
     293             : }
     294             : 
     295           0 : sal_uInt16 SwWriteTable::GetLeftSpace( sal_uInt16 nCol ) const
     296             : {
     297           0 :     sal_uInt16 nSpace = nCellPadding + nCellSpacing;
     298             : 
     299             :     // Additional subtract the line thickness in the first column.
     300           0 :     if( nCol==0 )
     301             :     {
     302           0 :         nSpace = nSpace + nLeftSub;
     303             : 
     304           0 :         const SwWriteTableCol *pCol = aCols[nCol];
     305           0 :         if( pCol->HasLeftBorder() )
     306           0 :             nSpace = nSpace + nBorder;
     307             :     }
     308             : 
     309           0 :     return nSpace;
     310             : }
     311             : 
     312             : sal_uInt16
     313           0 : SwWriteTable::GetRightSpace(size_t const nCol, sal_uInt16 nColSpan) const
     314             : {
     315           0 :     sal_uInt16 nSpace = nCellPadding;
     316             : 
     317             :     // Additional subtract in the last column CELLSPACING and
     318             :     // line thickness once again.
     319           0 :     if( nCol+nColSpan==aCols.size() )
     320             :     {
     321           0 :         nSpace += (nCellSpacing + nRightSub);
     322             : 
     323           0 :         const SwWriteTableCol *pCol = aCols[nCol+nColSpan-1];
     324           0 :         if( pCol->HasRightBorder() )
     325           0 :             nSpace = nSpace + nBorder;
     326             :     }
     327             : 
     328           0 :     return nSpace;
     329             : }
     330             : 
     331           0 : sal_uInt16 SwWriteTable::GetAbsWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     332             : {
     333           0 :     sal_uInt32 nWidth = GetRawWidth( nCol, nColSpan );
     334           0 :     if( nBaseWidth != nTabWidth )
     335             :     {
     336           0 :         nWidth *= nTabWidth;
     337           0 :         nWidth /= nBaseWidth;
     338             :     }
     339             : 
     340           0 :     nWidth -= GetLeftSpace( nCol ) + GetRightSpace( nCol, nColSpan );
     341             : 
     342             :     OSL_ENSURE( nWidth > 0, "Column Width <= 0. OK?" );
     343           0 :     return nWidth > 0 ? (sal_uInt16)nWidth : 0;
     344             : }
     345             : 
     346           5 : sal_uInt16 SwWriteTable::GetRelWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     347             : {
     348           5 :     long nWidth = GetRawWidth( nCol, nColSpan );
     349             : 
     350           5 :     return (sal_uInt16)(long)Fraction( nWidth*256 + GetBaseWidth()/2,
     351          10 :                                    GetBaseWidth() );
     352             : }
     353             : 
     354         260 : sal_uInt16 SwWriteTable::GetPrcWidth( sal_uInt16 nCol, sal_uInt16 nColSpan ) const
     355             : {
     356         260 :     long nWidth = GetRawWidth( nCol, nColSpan );
     357             : 
     358             :     // Looks funny, but is nothing more than
     359             :     // [(100 * nWidth) + .5] without rounding errors
     360         260 :     return (sal_uInt16)(long)Fraction( nWidth*100 + GetBaseWidth()/2,
     361         520 :                                    GetBaseWidth() );
     362             : }
     363             : 
     364           0 : long SwWriteTable::GetAbsHeight(long nRawHeight, size_t const nRow,
     365             :                                    sal_uInt16 nRowSpan ) const
     366             : {
     367           0 :     nRawHeight -= (2*nCellPadding + nCellSpacing);
     368             : 
     369             :     // Additional subtract in the first column CELLSPACING and
     370             :     // line thickness once again.
     371           0 :     const SwWriteTableRow *pRow = 0;
     372           0 :     if( nRow==0 )
     373             :     {
     374           0 :         nRawHeight -= nCellSpacing;
     375           0 :         pRow = aRows[nRow];
     376           0 :         if( pRow->HasTopBorder() )
     377           0 :             nRawHeight -= nBorder;
     378             :     }
     379             : 
     380             :     // Subtract the line thickness in the last column
     381           0 :     if( nRow+nRowSpan==aRows.size() )
     382             :     {
     383           0 :         if( !pRow || nRowSpan > 1 )
     384           0 :             pRow = aRows[nRow+nRowSpan-1];
     385           0 :         if( pRow->HasBottomBorder() )
     386           0 :             nRawHeight -= nBorder;
     387             :     }
     388             : 
     389             :     OSL_ENSURE( nRawHeight > 0, "Row Height <= 0. OK?" );
     390           0 :     return nRawHeight > 0 ? nRawHeight : 0;
     391             : }
     392             : 
     393         618 : sal_Bool SwWriteTable::ShouldExpandSub(const SwTableBox *pBox, sal_Bool /*bExpandedBefore*/,
     394             :     sal_uInt16 nDepth) const
     395             : {
     396         618 :     return !pBox->GetSttNd() && nDepth > 0;
     397             : }
     398             : 
     399             : // FIXME: the degree of coupling between this method and
     400             : // FillTableRowsCols which is called immediately afterwards
     401             : // is -extremely- unpleasant and potentially problematic.
     402             : 
     403          11 : void SwWriteTable::CollectTableRowsCols( long nStartRPos,
     404             :                                            sal_uInt32 nStartCPos,
     405             :                                            long nParentLineHeight,
     406             :                                            sal_uInt32 nParentLineWidth,
     407             :                                            const SwTableLines& rLines,
     408             :                                            sal_uInt16 nDepth )
     409             : {
     410          11 :     sal_Bool bSubExpanded = sal_False;
     411          11 :     sal_uInt16 nLines = rLines.size();
     412             : 
     413             : #if OSL_DEBUG_LEVEL > 0
     414             :     sal_uInt32 nEndCPos = 0;
     415             : #endif
     416             : 
     417          11 :     long nRPos = nStartRPos;
     418          81 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     419             :     {
     420          70 :         /*const*/ SwTableLine *pLine = rLines[nLine];
     421             : 
     422          70 :         long nOldRPos = nRPos;
     423             : 
     424          70 :         if( nLine < nLines-1 || nParentLineHeight==0  )
     425             :         {
     426          70 :             long nLineHeight = GetLineHeight( pLine );
     427          70 :             nRPos += nLineHeight;
     428          70 :             if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
     429             :             {
     430             :                 /* If you have corrupt line height information, e.g. breaking rows in complex table
     431             :                 layout, you may run into this robust code.
     432             :                 It's not allowed that subrows leaves their parentrow. If this would happen the line
     433             :                 height of subrow is reduced to a part of the remaining height */
     434             :                 OSL_FAIL( "Corrupt line height I" );
     435           0 :                 nRPos -= nLineHeight;
     436           0 :                 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
     437           0 :                 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
     438           0 :                 nRPos += nLineHeight;
     439             :             }
     440          70 :             SwWriteTableRow *pRow = new SwWriteTableRow( nRPos, bUseLayoutHeights);
     441          70 :             if( !aRows.insert( pRow ).second )
     442           0 :                 delete pRow;
     443             :         }
     444             :         else
     445             :         {
     446             : #if OSL_DEBUG_LEVEL > 0
     447             :             long nCheckPos = nRPos + GetLineHeight( pLine );
     448             : #endif
     449           0 :             nRPos = nStartRPos + nParentLineHeight;
     450             : #if OSL_DEBUG_LEVEL > 0
     451             :             SwWriteTableRow aSrchRow( nRPos, bUseLayoutHeights );
     452             :             OSL_ENSURE( aRows.find( &aSrchRow ) != aRows.end(), "Parent-Row not found" );
     453             :             SwWriteTableRow aRowCheckPos(nCheckPos,bUseLayoutHeights);
     454             :             SwWriteTableRow aRowRPos(nRPos,bUseLayoutHeights);
     455             :             OSL_ENSURE( !bUseLayoutHeights ||
     456             :                     aRowCheckPos == aRowRPos,
     457             :                     "Height of the rows does not correspond with the parent" );
     458             : #endif
     459             :         }
     460             : 
     461             :         // If necessary insert a column for all boxes of the row
     462          70 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     463          70 :         sal_uInt16 nBoxes = rBoxes.size();
     464             : 
     465          70 :         sal_uInt32 nCPos = nStartCPos;
     466         379 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     467             :         {
     468         309 :             const SwTableBox *pBox = rBoxes[nBox];
     469             : 
     470         309 :             sal_uInt32 nOldCPos = nCPos;
     471             : 
     472         309 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0)  )
     473             :             {
     474         239 :                 nCPos = nCPos + GetBoxWidth( pBox );
     475         239 :                 SwWriteTableCol *pCol = new SwWriteTableCol( nCPos );
     476             : 
     477         239 :                 if( !aCols.insert( pCol ).second )
     478         221 :                     delete pCol;
     479             : 
     480         239 :                 if( nBox==nBoxes-1 )
     481             :                 {
     482             :                     OSL_ENSURE( nLine==0 && nParentLineWidth==0,
     483             :                             "Now the parent width will be flattened!" );
     484           0 :                     nParentLineWidth = nCPos-nStartCPos;
     485         239 :                 }
     486             :             }
     487             :             else
     488             :             {
     489             : #if OSL_DEBUG_LEVEL > 0
     490             :                 sal_uInt32 nCheckPos = nCPos + GetBoxWidth( pBox );
     491             :                 if( !nEndCPos )
     492             :                 {
     493             :                     nEndCPos = nCheckPos;
     494             :                 }
     495             :                 else
     496             :                 {
     497             :                     OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
     498             :                                                 SwWriteTableCol(nEndCPos),
     499             :                     "Cell includes rows of different widths" );
     500             :                 }
     501             : #endif
     502          70 :                 nCPos = nStartCPos + nParentLineWidth;
     503             : 
     504             : #if OSL_DEBUG_LEVEL > 0
     505             :                 SwWriteTableCol aSrchCol( nCPos );
     506             :                 OSL_ENSURE( aCols.find( &aSrchCol ) != aCols.end(),
     507             :                         "Parent-Cell not found" );
     508             :                 OSL_ENSURE( SwWriteTableCol(nCheckPos) ==
     509             :                                             SwWriteTableCol(nCPos),
     510             :                         "Width of the cells does not correspond with the parent" );
     511             : #endif
     512             :             }
     513             : 
     514         309 :             if( ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     515             :             {
     516             :                 CollectTableRowsCols( nOldRPos, nOldCPos,
     517             :                                         nRPos - nOldRPos,
     518             :                                         nCPos - nOldCPos,
     519           0 :                                         pBox->GetTabLines(),
     520           0 :                                         nDepth-1 );
     521           0 :                 bSubExpanded = sal_True;
     522             :             }
     523             :         }
     524             :     }
     525          11 : }
     526             : 
     527             : 
     528          11 : void SwWriteTable::FillTableRowsCols( long nStartRPos, sal_uInt16 nStartRow,
     529             :                                         sal_uInt32 nStartCPos, sal_uInt16 nStartCol,
     530             :                                         long nParentLineHeight,
     531             :                                         sal_uInt32 nParentLineWidth,
     532             :                                         const SwTableLines& rLines,
     533             :                                         const SvxBrushItem* pParentBrush,
     534             :                                         sal_uInt16 nDepth,
     535             :                                         sal_uInt16 nNumOfHeaderRows )
     536             : {
     537          11 :     sal_uInt16 nLines = rLines.size();
     538          11 :     sal_Bool bSubExpanded = sal_False;
     539             : 
     540             :     // Specifying the border
     541          11 :     long nRPos = nStartRPos;
     542          11 :     sal_uInt16 nRow = nStartRow;
     543             : 
     544          81 :     for( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
     545             :     {
     546          70 :         const SwTableLine *pLine = rLines[nLine];
     547             : 
     548             :         // Determine the position of the last covered row
     549          70 :         long nOldRPos = nRPos;
     550          70 :         if( nLine < nLines-1 || nParentLineHeight==0 )
     551             :         {
     552          70 :             long nLineHeight = GetLineHeight( pLine );
     553          70 :             nRPos += nLineHeight;
     554          70 :             if( nParentLineHeight && nStartRPos + nParentLineHeight <= nRPos )
     555             :             {
     556             :                 /* See comment in CollectTableRowCols */
     557             :                 OSL_FAIL( "Corrupt line height II" );
     558           0 :                 nRPos -= nLineHeight;
     559           0 :                 nLineHeight = nStartRPos + nParentLineHeight - nRPos; // remaining parent height
     560           0 :                 nLineHeight /= nLines - nLine; // divided through the number of remaining sub rows
     561           0 :                 nRPos += nLineHeight;
     562          70 :             }
     563             :         }
     564             :         else
     565           0 :             nRPos = nStartRPos + nParentLineHeight;
     566             : 
     567             :         // And their index
     568          70 :         sal_uInt16 nOldRow = nRow;
     569          70 :         SwWriteTableRow aSrchRow( nRPos,bUseLayoutHeights );
     570          70 :         SwWriteTableRows::const_iterator it2 = aRows.find( &aSrchRow );
     571             : 
     572             :         // coupled methods out of sync ...
     573             :         assert( it2 != aRows.end() );
     574          70 :         nRow = it2 - aRows.begin();
     575             : 
     576             :         OSL_ENSURE( nOldRow <= nRow, "Don't look back!" );
     577          70 :         if( nOldRow > nRow )
     578             :         {
     579           0 :             nOldRow = nRow;
     580           0 :             if( nOldRow )
     581           0 :                 --nOldRow;
     582             :         }
     583             : 
     584             : 
     585          70 :         SwWriteTableRow *pRow = aRows[nOldRow];
     586          70 :         SwWriteTableRow *pEndRow = aRows[nRow];
     587          70 :         if( nLine+1==nNumOfHeaderRows && nParentLineHeight==0 )
     588           0 :             nHeadEndRow = nRow;
     589             : 
     590          70 :         const SwTableBoxes& rBoxes = pLine->GetTabBoxes();
     591             : 
     592          70 :         const SwFrmFmt *pLineFrmFmt = pLine->GetFrmFmt();
     593             :         const SfxPoolItem* pItem;
     594          70 :         const SfxItemSet& rItemSet = pLineFrmFmt->GetAttrSet();
     595             : 
     596          70 :         long nHeight = 0;
     597          70 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_FRM_SIZE, sal_True, &pItem ))
     598           3 :             nHeight = ((SwFmtFrmSize*)pItem)->GetHeight();
     599             : 
     600             : 
     601          70 :         const SvxBrushItem *pBrushItem, *pLineBrush = pParentBrush;
     602          70 :         if( SFX_ITEM_SET == rItemSet.GetItemState( RES_BACKGROUND, sal_False,
     603          70 :                                                    &pItem ) )
     604             :         {
     605           0 :             pLineBrush = (const SvxBrushItem *)pItem;
     606             : 
     607             :             // If the row spans the entire table, we can
     608             :             // print out the background to the row. Otherwise
     609             :             // we have to print out into the cell.
     610           0 :             sal_Bool bOutAtRow = !nParentLineWidth;
     611           0 :             if( !bOutAtRow && nStartCPos==0 )
     612             :             {
     613           0 :                 SwWriteTableCol aCol( nParentLineWidth );
     614           0 :                 bOutAtRow = aCols.find( &aCol ) == (aCols.end() - 1);
     615             :             }
     616           0 :             if( bOutAtRow )
     617             :             {
     618           0 :                 pRow->SetBackground( pLineBrush );
     619           0 :                 pBrushItem = 0;
     620             :             }
     621             :             else
     622           0 :                 pBrushItem = pLineBrush;
     623             :         }
     624             :         else
     625             :         {
     626          70 :             pRow->SetBackground( pLineBrush );
     627          70 :             pBrushItem = 0;
     628             :         }
     629             : 
     630          70 :         sal_uInt16 nBoxes = rBoxes.size();
     631          70 :         sal_uInt32 nCPos = nStartCPos;
     632          70 :         sal_uInt16 nCol = nStartCol;
     633             : 
     634         379 :         for( sal_uInt16 nBox=0; nBox<nBoxes; nBox++ )
     635             :         {
     636         309 :             const SwTableBox *pBox = rBoxes[nBox];
     637             : 
     638             :             // Determine the position of the last covered column
     639         309 :             sal_uInt32 nOldCPos = nCPos;
     640         309 :             if( nBox < nBoxes-1 || (nParentLineWidth==0 && nLine==0) )
     641             :             {
     642         239 :                 nCPos = nCPos + GetBoxWidth( pBox );
     643         478 :                 if( nBox==nBoxes-1 )
     644           0 :                     nParentLineWidth = nCPos - nStartCPos;
     645             :             }
     646             :             else
     647          70 :                 nCPos = nStartCPos + nParentLineWidth;
     648             : 
     649             :             // And their index
     650         309 :             sal_uInt16 nOldCol = nCol;
     651         309 :             SwWriteTableCol aSrchCol( nCPos );
     652         309 :             SwWriteTableCols::const_iterator it = aCols.find( &aSrchCol );
     653             :             OSL_ENSURE( it != aCols.end(), "missing column" );
     654         309 :             nCol = it - aCols.begin();
     655             : 
     656         309 :             if( !ShouldExpandSub( pBox, bSubExpanded, nDepth ) )
     657             :             {
     658         309 :                 sal_uInt16 nRowSpan = nRow - nOldRow + 1;
     659             : 
     660             :                 // The new table model may have true row span attributes
     661         309 :                 const long nAttrRowSpan = pBox->getRowSpan();
     662         309 :                 if ( 1 < nAttrRowSpan )
     663           0 :                     nRowSpan = (sal_uInt16)nAttrRowSpan;
     664         309 :                 else if ( nAttrRowSpan < 1 )
     665           0 :                     nRowSpan = 0;
     666             : 
     667         309 :                 sal_uInt16 nColSpan = nCol - nOldCol + 1;
     668             :                 pRow->AddCell( pBox, nOldRow, nOldCol,
     669             :                                nRowSpan, nColSpan, nHeight,
     670         309 :                                pBrushItem );
     671         309 :                 nHeight = 0; // The height requires only to be written once
     672             : 
     673         309 :                 if( pBox->GetSttNd() )
     674             :                 {
     675         309 :                     sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     676             :                     sal_uInt16 nBorderMask = MergeBoxBorders(pBox, nOldRow, nOldCol,
     677         309 :                         nRowSpan, nColSpan, nTopBorder, nBottomBorder);
     678             : 
     679             :                     // #i30094# add a sanity check here to ensure that
     680             :                     // we don't access an invalid aCols[] as &nCol
     681             :                     // above can be changed.
     682         309 :                     if (!(nBorderMask & 4) && nOldCol < aCols.size())
     683             :                     {
     684           2 :                         SwWriteTableCol *pCol = aCols[nOldCol];
     685             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     686           2 :                         if (pCol)
     687           2 :                             pCol->bLeftBorder = false;
     688             :                     }
     689             : 
     690         309 :                     if (!(nBorderMask & 8))
     691             :                     {
     692           2 :                         SwWriteTableCol *pCol = aCols[nCol];
     693             :                         OSL_ENSURE(pCol, "No TableCol found, panic!");
     694           2 :                         if (pCol)
     695           2 :                             pCol->bRightBorder = false;
     696             :                     }
     697             : 
     698         309 :                     if (!(nBorderMask & 1))
     699           2 :                         pRow->bTopBorder = false;
     700         307 :                     else if (!pRow->nTopBorder || nTopBorder < pRow->nTopBorder)
     701          70 :                         pRow->nTopBorder = nTopBorder;
     702             : 
     703         309 :                     if (!(nBorderMask & 2))
     704           2 :                         pEndRow->bBottomBorder = false;
     705         307 :                     else if (
     706         614 :                                 !pEndRow->nBottomBorder ||
     707         307 :                                 nBottomBorder < pEndRow->nBottomBorder
     708             :                             )
     709             :                     {
     710          70 :                         pEndRow->nBottomBorder = nBottomBorder;
     711             :                     }
     712             :                 }
     713             :             }
     714             :             else
     715             :             {
     716             :                 FillTableRowsCols( nOldRPos, nOldRow, nOldCPos, nOldCol,
     717             :                                     nRPos-nOldRPos, nCPos-nOldCPos,
     718           0 :                                     pBox->GetTabLines(),
     719             :                                     pLineBrush, nDepth-1,
     720           0 :                                     nNumOfHeaderRows );
     721           0 :                 bSubExpanded = sal_True;
     722             :             }
     723             : 
     724         309 :             nCol++; // The next cell begins in the next column
     725             :         }
     726             : 
     727          70 :         nRow++;
     728          70 :     }
     729          11 : }
     730             : 
     731          11 : SwWriteTable::SwWriteTable(const SwTableLines& rLines, long nWidth,
     732             :     sal_uInt32 nBWidth, bool bRel, sal_uInt16 nMaxDepth, sal_uInt16 nLSub, sal_uInt16 nRSub, sal_uInt32 nNumOfRowsToRepeat)
     733             :     : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
     734             :     nInnerBorder(0), nBaseWidth(nBWidth), nHeadEndRow(USHRT_MAX),
     735             :      nLeftSub(nLSub), nRightSub(nRSub), nTabWidth(nWidth), bRelWidths(bRel),
     736             :     bUseLayoutHeights(true),
     737             : #ifdef DBG_UTIL
     738             :     m_bGetLineHeightCalled(false),
     739             : #endif
     740             :     bColsOption(false), bColTags(true), bLayoutExport(false),
     741          11 :     bCollectBorderWidth(true)
     742             : {
     743          11 :     sal_uInt32 nParentWidth = nBaseWidth + nLeftSub + nRightSub;
     744             : 
     745             :     // First the table structure set. Behind the table is in each
     746             :     // case the end of a column
     747          11 :     SwWriteTableCol *pCol = new SwWriteTableCol( nParentWidth );
     748          11 :     aCols.insert( pCol );
     749          11 :     bUseLayoutHeights = true;
     750          11 :     CollectTableRowsCols( 0, 0, 0, nParentWidth, rLines, nMaxDepth - 1 );
     751             : 
     752             :     // FIXME: awfully GetLineHeight writes to this in its first call
     753             :     // and proceeds to return a rather odd number fdo#62336, we have to
     754             :     // behave identically since the code in FillTableRowsCols duplicates
     755             :     // and is highly coupled to CollectTableRowsCols - sadly.
     756          11 :     bUseLayoutHeights = true;
     757             :     // And now fill with life
     758          11 :     FillTableRowsCols( 0, 0, 0, 0, 0, nParentWidth, rLines, 0, nMaxDepth - 1, static_cast< sal_uInt16 >(nNumOfRowsToRepeat) );
     759             : 
     760             :     // Adjust some Twip values to pixel boundaries
     761          11 :     if( !nBorder )
     762           0 :         nBorder = nInnerBorder;
     763          11 : }
     764             : 
     765           0 : SwWriteTable::SwWriteTable( const SwHTMLTableLayout *pLayoutInfo )
     766             :     : nBorderColor((sal_uInt32)-1), nCellSpacing(0), nCellPadding(0), nBorder(0),
     767           0 :     nInnerBorder(0), nBaseWidth(pLayoutInfo->GetWidthOption()), nHeadEndRow(0),
     768           0 :     nLeftSub(0), nRightSub(0), nTabWidth(pLayoutInfo->GetWidthOption()),
     769           0 :     bRelWidths(pLayoutInfo->HasPrcWidthOption()), bUseLayoutHeights(false),
     770             : #ifdef DBG_UTIL
     771             :     m_bGetLineHeightCalled(false),
     772             : #endif
     773           0 :     bColsOption(pLayoutInfo->HasColsOption()),
     774           0 :     bColTags(pLayoutInfo->HasColTags()), bLayoutExport(true),
     775           0 :     bCollectBorderWidth(pLayoutInfo->HaveBordersChanged())
     776             : {
     777           0 :     if( !bCollectBorderWidth )
     778             :     {
     779           0 :         nBorder = pLayoutInfo->GetBorder();
     780           0 :         nCellPadding = pLayoutInfo->GetCellPadding();
     781           0 :         nCellSpacing = pLayoutInfo->GetCellSpacing();
     782             :     }
     783             : 
     784             :     sal_uInt16 nRow, nCol;
     785           0 :     sal_uInt16 nCols = pLayoutInfo->GetColCount();
     786           0 :     sal_uInt16 nRows = pLayoutInfo->GetRowCount();
     787             : 
     788             :     // First set the table structure.
     789           0 :     for( nCol=0; nCol<nCols; nCol++ )
     790             :     {
     791             :         SwWriteTableCol *pCol =
     792           0 :             new SwWriteTableCol( (nCol+1)*COL_DFLT_WIDTH );
     793             : 
     794           0 :         if( bColTags )
     795             :         {
     796             :             const SwHTMLTableLayoutColumn *pLayoutCol =
     797           0 :                 pLayoutInfo->GetColumn( nCol );
     798           0 :             pCol->SetWidthOpt( pLayoutCol->GetWidthOption(),
     799           0 :                                pLayoutCol->IsRelWidthOption() );
     800             :         }
     801             : 
     802           0 :         aCols.insert( pCol );
     803             :     }
     804             : 
     805           0 :     for( nRow=0; nRow<nRows; nRow++ )
     806             :     {
     807             :         SwWriteTableRow *pRow =
     808           0 :             new SwWriteTableRow( (nRow+1)*ROW_DFLT_HEIGHT, bUseLayoutHeights );
     809           0 :         pRow->nTopBorder = 0;
     810           0 :         pRow->nBottomBorder = 0;
     811           0 :         aRows.insert( pRow );
     812             :     }
     813             : 
     814             :     // And now fill with life
     815           0 :     for( nRow=0; nRow<nRows; nRow++ )
     816             :     {
     817           0 :         SwWriteTableRow *pRow = aRows[nRow];
     818             : 
     819           0 :         sal_Bool bHeightExported = sal_False;
     820           0 :         for( nCol=0; nCol<nCols; nCol++ )
     821             :         {
     822             :             const SwHTMLTableLayoutCell *pLayoutCell =
     823           0 :                 pLayoutInfo->GetCell( nRow, nCol );
     824             : 
     825             :             const SwHTMLTableLayoutCnts *pLayoutCnts =
     826           0 :                 pLayoutCell->GetContents();
     827             : 
     828             :             // The cell begins actually a row above or further forward?
     829           0 :             if( ( nRow>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow-1,nCol)
     830           0 :                                                       ->GetContents() ) ||
     831           0 :                 ( nCol>0 && pLayoutCnts == pLayoutInfo->GetCell(nRow,nCol-1)
     832           0 :                                                       ->GetContents() ) )
     833             :             {
     834           0 :                 continue;
     835             :             }
     836             : 
     837           0 :             sal_uInt16 nRowSpan = pLayoutCell->GetRowSpan();
     838           0 :             sal_uInt16 nColSpan = pLayoutCell->GetColSpan();
     839           0 :             const SwTableBox *pBox = pLayoutCnts->GetTableBox();
     840             :             OSL_ENSURE( pBox,
     841             :                     "Table in Table can not be exported over layout" );
     842             : 
     843           0 :             long nHeight = bHeightExported ? 0 : GetLineHeight( pBox );
     844           0 :             const SvxBrushItem *pBrushItem = GetLineBrush( pBox, pRow );
     845             : 
     846             :             SwWriteTableCell *pCell =
     847             :                 pRow->AddCell( pBox, nRow, nCol, nRowSpan, nColSpan,
     848           0 :                                nHeight, pBrushItem );
     849           0 :             pCell->SetWidthOpt( pLayoutCell->GetWidthOption(),
     850           0 :                                 pLayoutCell->IsPrcWidthOption() );
     851             : 
     852           0 :             sal_uInt16 nTopBorder = USHRT_MAX, nBottomBorder = USHRT_MAX;
     853             :             sal_uInt16 nBorderMask =
     854             :             MergeBoxBorders( pBox, nRow, nCol, nRowSpan, nColSpan,
     855           0 :                                 nTopBorder, nBottomBorder );
     856             : 
     857           0 :             SwWriteTableCol *pCol = aCols[nCol];
     858           0 :             if( !(nBorderMask & 4) )
     859           0 :                 pCol->bLeftBorder = false;
     860             : 
     861           0 :             pCol = aCols[nCol+nColSpan-1];
     862           0 :             if( !(nBorderMask & 8) )
     863           0 :                 pCol->bRightBorder = false;
     864             : 
     865           0 :             if( !(nBorderMask & 1) )
     866           0 :                 pRow->bTopBorder = false;
     867             : 
     868           0 :             SwWriteTableRow *pEndRow = aRows[nRow+nRowSpan-1];
     869           0 :             if( !(nBorderMask & 2) )
     870           0 :                 pEndRow->bBottomBorder = false;
     871             : 
     872             :             // The height requires only to be written once
     873           0 :             if( nHeight )
     874           0 :                 bHeightExported = sal_True;
     875             :         }
     876             :     }
     877             : 
     878             :     // Adjust some Twip values to pixel boundaries
     879           0 :     if( bCollectBorderWidth && !nBorder )
     880           0 :         nBorder = nInnerBorder;
     881           0 : }
     882             : 
     883          21 : SwWriteTable::~SwWriteTable()
     884             : {
     885         120 : }
     886             : 
     887             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10