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

Generated by: LCOV version 1.11